From cbab226a74fbaaa43220dee80e8435555c6506ce Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Tue, 23 Jan 2024 12:58:00 +0100 Subject: Imported Upstream version 2.03.22 --- test/.gitignore | 4 + test/Makefile.in | 388 ++- test/api/Makefile.in | 60 - test/api/dbustest.sh | 42 + test/api/lvtest.c | 64 - test/api/lvtest.sh | 21 - test/api/pe_start.c | 47 - test/api/pe_start.sh | 21 - test/api/percent.c | 63 - test/api/percent.sh | 29 - test/api/test.c | 1107 --------- test/api/thin_percent.c | 68 - test/api/thin_percent.sh | 37 - test/api/vgtest.c | 164 -- test/api/vgtest.sh | 20 - test/dbus/lvm_error_inject.py | 348 +++ test/dbus/lvmdbustest.py | 2614 ++++++++++++++++++++ test/dbus/testlib.py | 331 +++ test/dbus/validatestate.py | 32 + test/lib/aux.sh | 2079 +++++++++++++--- test/lib/brick-shelltest.h | 1340 ++++++++++ test/lib/check.sh | 366 ++- test/lib/dmsecuretest.c | 86 + test/lib/flavour-ndev-cluster-lvmpolld.sh | 2 + test/lib/flavour-ndev-cluster.sh | 1 + test/lib/flavour-ndev-devicesfile.sh | 2 + test/lib/flavour-ndev-lvmpolld.sh | 2 + test/lib/flavour-ndev-vanilla.sh | 1 + test/lib/flavour-udev-cluster-lvmpolld.sh | 3 + test/lib/flavour-udev-cluster.sh | 2 + test/lib/flavour-udev-lvmlockd-dlm.sh | 6 + test/lib/flavour-udev-lvmlockd-idm.sh | 5 + test/lib/flavour-udev-lvmlockd-sanlock.sh | 5 + test/lib/flavour-udev-lvmlockd-test.sh | 8 + test/lib/flavour-udev-lvmpolld.sh | 3 + test/lib/flavour-udev-vanilla.sh | 2 + test/lib/get.sh | 96 +- test/lib/harness.c | 431 +++- test/lib/idm_inject_failure.c | 55 + test/lib/inittest.sh | 197 ++ test/lib/lvm-wrapper.sh | 47 +- test/lib/lvm_vdo_wrapper.sh | 364 +++ test/lib/mke2fs.conf | 45 + test/lib/not.c | 52 +- test/lib/runner.cpp | 46 + test/lib/test-corosync-conf | 28 + test/lib/test-dlm-conf | 4 + test/lib/test-sanlock-conf | 2 + test/lib/test.sh | 79 - test/lib/utils.sh | 233 +- test/shell/000-basic.sh | 37 +- test/shell/aa-lvmlockd-dlm-prepare.sh | 23 + test/shell/aa-lvmlockd-idm-prepare.sh | 22 + test/shell/aa-lvmlockd-sanlock-prepare.sh | 46 + test/shell/activate-minor.sh | 18 +- test/shell/activate-missing-segment.sh | 12 +- test/shell/activate-missing.sh | 24 +- test/shell/activate-partial.sh | 20 +- test/shell/activation-skip.sh | 38 + test/shell/allow-mixed-block-sizes.sh | 71 + test/shell/autoactivation-metadata.sh | 336 +++ test/shell/backup-read-only.sh | 84 + test/shell/cache-metadata2.sh | 100 + test/shell/cache-no-discard.sh | 45 + test/shell/cache-single-options.sh | 273 ++ test/shell/cache-single-split.sh | 423 ++++ test/shell/cache-single-thin.sh | 46 + test/shell/cache-single-types.sh | 88 + test/shell/cache-single-usage.sh | 146 ++ test/shell/cachevol-cachedevice.sh | 235 ++ test/shell/caching-snapshot.sh | 162 ++ test/shell/clvmd-restart.sh | 53 - test/shell/component-cache.sh | 92 + test/shell/component-mirror.sh | 70 + test/shell/component-raid.sh | 50 + test/shell/component-thin.sh | 43 + test/shell/covercmd.sh | 127 +- test/shell/creation-time.sh | 40 + test/shell/dev-aliases.sh | 53 + test/shell/devicesfile-basic.sh | 687 +++++ test/shell/devicesfile-devname.sh | 628 +++++ test/shell/devicesfile-edit.sh | 257 ++ test/shell/devicesfile-realdevs.sh | 612 +++++ test/shell/devicesfile-serial.sh | 890 +++++++ test/shell/devicesfile-vpd-ids.sh | 436 ++++ test/shell/discards-thin.sh | 64 +- test/shell/dmeventd-restart.sh | 43 +- test/shell/dmsecuretest.sh | 77 + test/shell/dmsetup-integrity-keys.sh | 58 + test/shell/dmsetup-keyring.sh | 75 + test/shell/dmstats-create.sh | 30 + test/shell/dmstats-report.sh | 30 + test/shell/dumpconfig.sh | 12 +- test/shell/duplicate-pvs-md0.sh | 308 +++ test/shell/duplicate-pvs-md1.sh | 21 + test/shell/duplicate-pvs-multipath.sh | 71 + test/shell/duplicate-vgid.sh | 52 + test/shell/duplicate-vgnames.sh | 624 +++++ test/shell/duplicate-vgrename.sh | 304 +++ test/shell/error-usage.sh | 47 + test/shell/exported.sh | 209 ++ test/shell/fsadm-crypt-fsresize.sh | 625 +++++ test/shell/fsadm-crypt.sh | 614 +++++ test/shell/fsadm-renamed.sh | 138 ++ test/shell/fsadm.sh | 122 +- test/shell/hints.sh | 480 ++++ test/shell/idm_fabric_failure.sh | 58 + test/shell/idm_fabric_failure_half_brain.sh | 78 + test/shell/idm_fabric_failure_timeout.sh | 74 + test/shell/idm_ilm_failure.sh | 80 + test/shell/inconsistent-metadata.sh | 99 +- test/shell/integrity-blocksize-2.sh | 98 + test/shell/integrity-blocksize-3.sh | 252 ++ test/shell/integrity-blocksize.sh | 298 +++ test/shell/integrity-caching.sh | 527 ++++ test/shell/integrity-dmeventd.sh | 263 ++ test/shell/integrity-large.sh | 177 ++ test/shell/integrity-misc.sh | 216 ++ test/shell/integrity-syncaction.sh | 159 ++ test/shell/integrity.sh | 771 ++++++ test/shell/large-physical-sector-size.sh | 43 + test/shell/listings.sh | 195 +- test/shell/lock-blocking.sh | 38 +- test/shell/lock-parallel.sh | 50 + test/shell/losetup-partscan.sh | 68 + test/shell/lv-ancestry.sh | 230 ++ test/shell/lvchange-cache-mode.sh | 90 + test/shell/lvchange-cache-old.sh | 43 + test/shell/lvchange-cache-syncaction-raid.sh | 44 + test/shell/lvchange-cache.sh | 97 + test/shell/lvchange-mirror.sh | 22 +- test/shell/lvchange-partial-raid10.sh | 34 + test/shell/lvchange-partial.sh | 20 +- test/shell/lvchange-raid-transient-failures.sh | 70 + test/shell/lvchange-raid.sh | 349 +++ test/shell/lvchange-raid1-writemostly.sh | 44 + test/shell/lvchange-raid10.sh | 21 + test/shell/lvchange-raid456.sh | 24 + test/shell/lvchange-rebuild-raid.sh | 144 ++ test/shell/lvchange-syncaction-raid.sh | 92 + test/shell/lvchange-thin.sh | 204 ++ test/shell/lvchange-vdo.sh | 170 ++ test/shell/lvconvert-cache-abort.sh | 89 + test/shell/lvconvert-cache-chunks.sh | 62 + test/shell/lvconvert-cache-raid.sh | 115 + test/shell/lvconvert-cache-smq.sh | 34 + test/shell/lvconvert-cache-snapshot.sh | 63 + test/shell/lvconvert-cache-thin.sh | 125 + test/shell/lvconvert-cache-vdo.sh | 71 + test/shell/lvconvert-cache.sh | 202 ++ test/shell/lvconvert-m-raid1-degraded.sh | 47 + test/shell/lvconvert-mirror-basic-0.sh | 8 +- test/shell/lvconvert-mirror-basic-1.sh | 8 +- test/shell/lvconvert-mirror-basic-2.sh | 8 +- test/shell/lvconvert-mirror-basic-3.sh | 8 +- test/shell/lvconvert-mirror-basic.sh | 57 +- test/shell/lvconvert-mirror-split.sh | 32 + test/shell/lvconvert-mirror-updown.sh | 42 + test/shell/lvconvert-mirror.sh | 323 ++- test/shell/lvconvert-raid-allocation.sh | 81 + test/shell/lvconvert-raid-regionsize.sh | 104 + ...ert-raid-reshape-linear_to_raid6-single-type.sh | 102 + ...t-raid-reshape-linear_to_striped-single-type.sh | 78 + .../lvconvert-raid-reshape-linear_to_striped.sh | 72 + test/shell/lvconvert-raid-reshape-load.sh | 75 + ...t-raid-reshape-striped_to_linear-single-type.sh | 86 + .../lvconvert-raid-reshape-striped_to_linear.sh | 115 + .../lvconvert-raid-reshape-stripes-load-fail.sh | 84 + .../lvconvert-raid-reshape-stripes-load-reload.sh | 103 + test/shell/lvconvert-raid-reshape-stripes-load.sh | 80 + test/shell/lvconvert-raid-reshape.sh | 242 ++ test/shell/lvconvert-raid-restripe-linear.sh | 74 + test/shell/lvconvert-raid-status-validation.sh | 172 ++ .../shell/lvconvert-raid-takeover-alloc-failure.sh | 104 + .../lvconvert-raid-takeover-linear_to_raid4.sh | 60 + .../lvconvert-raid-takeover-raid4_to_linear.sh | 71 + test/shell/lvconvert-raid-takeover-thin.sh | 73 + test/shell/lvconvert-raid-takeover.sh | 372 +++ test/shell/lvconvert-raid.sh | 263 +- test/shell/lvconvert-raid0-striped.sh | 25 + test/shell/lvconvert-raid0_to_raid10.sh | 30 + test/shell/lvconvert-raid1-split-trackchanges.sh | 41 + test/shell/lvconvert-raid10.sh | 31 +- test/shell/lvconvert-raid456.sh | 72 + test/shell/lvconvert-raid5_to_raid10.sh | 64 + test/shell/lvconvert-repair-cache.sh | 156 ++ test/shell/lvconvert-repair-dmeventd.sh | 17 +- test/shell/lvconvert-repair-mirror.sh | 78 + test/shell/lvconvert-repair-policy.sh | 64 +- test/shell/lvconvert-repair-raid-dmeventd.sh | 40 + test/shell/lvconvert-repair-raid.sh | 176 ++ test/shell/lvconvert-repair-replace.sh | 111 +- test/shell/lvconvert-repair-snapshot.sh | 19 +- test/shell/lvconvert-repair-thin-raid.sh | 69 + test/shell/lvconvert-repair-thin.sh | 105 + test/shell/lvconvert-repair-transient-dmeventd.sh | 26 +- test/shell/lvconvert-repair-transient.sh | 27 +- test/shell/lvconvert-repair.sh | 88 +- test/shell/lvconvert-snapshot-cache.sh | 78 + test/shell/lvconvert-snapshot-mirror.sh | 60 + test/shell/lvconvert-snapshot-raid.sh | 62 + test/shell/lvconvert-snapshot-thin.sh | 80 + test/shell/lvconvert-snapshot.sh | 73 + test/shell/lvconvert-striped-raid0.sh | 25 + test/shell/lvconvert-thin-external-cache.sh | 110 + test/shell/lvconvert-thin-external.sh | 180 ++ test/shell/lvconvert-thin-from-thick.sh | 93 + test/shell/lvconvert-thin-raid.sh | 61 + test/shell/lvconvert-thin.sh | 150 +- test/shell/lvconvert-twostep.sh | 20 +- test/shell/lvconvert-vdo-raid.sh | 70 + test/shell/lvconvert-vdo.sh | 78 + test/shell/lvcreate-cache-fail.sh | 42 + test/shell/lvcreate-cache-no-tools.sh | 119 + test/shell/lvcreate-cache-raid.sh | 36 + test/shell/lvcreate-cache-snapshot.sh | 63 + test/shell/lvcreate-cache.sh | 308 +++ test/shell/lvcreate-external-dmeventd.sh | 47 + test/shell/lvcreate-large-raid.sh | 106 +- test/shell/lvcreate-large-raid10.sh | 47 +- test/shell/lvcreate-large.sh | 31 +- test/shell/lvcreate-mirror.sh | 44 +- test/shell/lvcreate-missing.sh | 26 + test/shell/lvcreate-operation.sh | 38 +- test/shell/lvcreate-pvtags.sh | 31 +- test/shell/lvcreate-raid-nosync.sh | 101 + test/shell/lvcreate-raid-volume_list.sh | 42 + test/shell/lvcreate-raid.sh | 177 +- test/shell/lvcreate-raid1-read-error.sh | 33 + test/shell/lvcreate-raid10.sh | 79 +- test/shell/lvcreate-repair.sh | 19 +- test/shell/lvcreate-signature-wiping.sh | 125 + test/shell/lvcreate-small-snap.sh | 36 +- test/shell/lvcreate-striped-mirror.sh | 62 +- test/shell/lvcreate-thin-big.sh | 90 + test/shell/lvcreate-thin-cache.sh | 48 + test/shell/lvcreate-thin-external-size.sh | 94 + test/shell/lvcreate-thin-external.sh | 109 + test/shell/lvcreate-thin-limits.sh | 61 + test/shell/lvcreate-thin-power2.sh | 21 +- test/shell/lvcreate-thin-snap.sh | 79 +- test/shell/lvcreate-thin.sh | 193 +- test/shell/lvcreate-usage.sh | 227 +- test/shell/lvcreate-vdo-cache.sh | 58 + test/shell/lvcreate-vdo.sh | 91 + test/shell/lvdisplay-raid.sh | 80 + test/shell/lvextend-caches-on-thindata.sh | 178 ++ test/shell/lvextend-caches.sh | 154 ++ test/shell/lvextend-percent-extents.sh | 45 +- test/shell/lvextend-raid.sh | 89 + test/shell/lvextend-snapshot-dmeventd.sh | 27 +- test/shell/lvextend-snapshot-policy.sh | 20 +- test/shell/lvextend-thin-adddel.sh | 78 + test/shell/lvextend-thin-cache.sh | 43 + test/shell/lvextend-thin-data-dmeventd.sh | 68 + test/shell/lvextend-thin-full.sh | 68 + test/shell/lvextend-thin-metadata-dmeventd.sh | 207 ++ test/shell/lvextend-thin-raid.sh | 63 + test/shell/lvextend-thin.sh | 43 + test/shell/lvextend-vdo-dmeventd.sh | 68 + test/shell/lvextend-vdo.sh | 54 + test/shell/lvm-conf-error.sh | 62 + test/shell/lvm-init.sh | 10 +- test/shell/lvm-on-md.sh | 317 +++ test/shell/lvmcache-exercise.sh | 52 +- test/shell/lvmetad-disabled.sh | 26 - test/shell/lvmetad-dump.sh | 38 - test/shell/lvmetad-lvm1.sh | 22 - test/shell/lvmetad-pvs.sh | 19 - test/shell/lvmetad-pvscan-cache.sh | 23 - test/shell/lvmetad-restart.sh | 23 - test/shell/lvmetad-test.sh | 34 - test/shell/lvmetad-warning.sh | 27 - test/shell/lvmlockd-hello-world.sh | 27 + test/shell/lvmlockd-lv-types.sh | 192 ++ test/shell/lvmlockd_failure.sh | 38 + test/shell/lvremove-thindata-caches.sh | 71 + test/shell/lvrename-cache-thin.sh | 52 + test/shell/lvrename-vdo.sh | 88 + test/shell/lvresize-fs-crypt.sh | 163 ++ test/shell/lvresize-fs.sh | 627 +++++ test/shell/lvresize-full.sh | 78 + test/shell/lvresize-mirror.sh | 56 +- test/shell/lvresize-raid.sh | 87 +- test/shell/lvresize-raid10.sh | 29 +- test/shell/lvresize-rounding.sh | 50 +- test/shell/lvresize-thin-external-origin.sh | 60 + test/shell/lvresize-thin-metadata.sh | 49 + test/shell/lvresize-usage.sh | 49 +- test/shell/lvresize-vdo.sh | 50 + test/shell/lvresize-xfs.sh | 306 +++ test/shell/lvs-cache.sh | 93 + test/shell/mda-rollback.sh | 33 + test/shell/mdata-strings.sh | 27 +- test/shell/metadata-bad-mdaheader.sh | 78 + test/shell/metadata-bad-text.sh | 320 +++ test/shell/metadata-balance.sh | 127 +- test/shell/metadata-dirs.sh | 43 - test/shell/metadata-full.sh | 131 + test/shell/metadata-old.sh | 221 ++ test/shell/metadata-zero-space.sh | 88 + test/shell/metadata.sh | 56 +- test/shell/mirror-names.sh | 73 +- test/shell/mirror-vgreduce-removemissing.sh | 222 +- test/shell/missing-pv-unused.sh | 79 + test/shell/missing-pv.sh | 187 ++ test/shell/multi_hosts_lv_ex_timeout_hosta.sh | 87 + test/shell/multi_hosts_lv_ex_timeout_hostb.sh | 56 + test/shell/multi_hosts_lv_hosta.sh | 78 + test/shell/multi_hosts_lv_hostb.sh | 61 + test/shell/multi_hosts_lv_sh_timeout_hosta.sh | 87 + test/shell/multi_hosts_lv_sh_timeout_hostb.sh | 56 + test/shell/multi_hosts_vg_hosta.sh | 45 + test/shell/multi_hosts_vg_hostb.sh | 52 + test/shell/multipath-config.sh | 171 ++ test/shell/name-mangling.sh | 92 +- test/shell/nomda-missing.sh | 29 +- test/shell/nomda-restoremissing.sh | 48 + test/shell/open-file-limit.sh | 48 + test/shell/orphan-ondisk.sh | 19 + test/shell/outdated-pv.sh | 64 + test/shell/pe-align.sh | 142 ++ test/shell/pool-labels.sh | 21 +- test/shell/process-each-duplicate-pvs.sh | 528 ++++ test/shell/process-each-lv.sh | 659 +++++ test/shell/process-each-pv-nomda-all.sh | 63 + test/shell/process-each-pv-nomda.sh | 30 + test/shell/process-each-pv.sh | 1063 ++++++++ test/shell/process-each-pvresize.sh | 563 +++++ test/shell/process-each-vg.sh | 269 ++ test/shell/process-each-vgreduce.sh | 331 +++ test/shell/profiles-cache.sh | 153 ++ test/shell/profiles-thin.sh | 97 + test/shell/profiles-vdo.sh | 54 + test/shell/profiles.sh | 134 + test/shell/pv-check-dev-size.sh | 46 + test/shell/pv-corruption.sh | 56 + test/shell/pv-duplicate-uuid.sh | 49 + test/shell/pv-duplicate.sh | 25 - test/shell/pv-ext-flags.sh | 157 ++ test/shell/pv-ext-update.sh | 185 ++ test/shell/pv-min-size.sh | 10 +- test/shell/pv-range-overflow.sh | 13 +- test/shell/pvchange-usage.sh | 94 +- test/shell/pvck-dump.sh | 204 ++ test/shell/pvck-repair.sh | 421 ++++ test/shell/pvcreate-bootloaderarea.sh | 58 + test/shell/pvcreate-ff.sh | 23 + test/shell/pvcreate-md-fake-hdr.sh | 102 + test/shell/pvcreate-metadata0.sh | 16 +- test/shell/pvcreate-operation-md.sh | 169 +- test/shell/pvcreate-operation.sh | 99 +- test/shell/pvcreate-restore.sh | 45 + test/shell/pvcreate-usage.sh | 84 +- test/shell/pvmove-abort-all.sh | 85 + test/shell/pvmove-abort.sh | 73 + test/shell/pvmove-all-segtypes.sh | 111 + test/shell/pvmove-background.sh | 36 + test/shell/pvmove-basic.sh | 402 ++- test/shell/pvmove-cache-segtypes.sh | 177 ++ test/shell/pvmove-lvs.sh | 35 + test/shell/pvmove-raid-segtypes.sh | 96 + test/shell/pvmove-restart.sh | 103 + test/shell/pvmove-resume-1.sh | 244 ++ test/shell/pvmove-resume-2.sh | 197 ++ test/shell/pvmove-resume-multiseg.sh | 222 ++ test/shell/pvmove-thin-segtypes.sh | 77 + test/shell/pvremove-thin.sh | 35 + test/shell/pvremove-usage.sh | 32 +- test/shell/pvremove-warnings.sh | 26 + test/shell/pvresize-mdas.sh | 38 + test/shell/pvscan-autoactivate.sh | 240 ++ test/shell/pvscan-autoactivation-polling.sh | 74 + test/shell/pvscan-cache.sh | 80 + test/shell/pvscan-nomda-bg.sh | 43 + test/shell/read-ahead.sh | 22 +- test/shell/relative-sign-options.sh | 80 + test/shell/report-fields.sh | 91 + test/shell/report-format.sh | 77 + test/shell/report-hidden.sh | 33 + test/shell/scan-lvs.sh | 46 + test/shell/select-report.sh | 223 ++ test/shell/select-tools-thin.sh | 43 + test/shell/select-tools.sh | 280 +++ test/shell/snapshot-autoumount-dmeventd.sh | 44 +- test/shell/snapshot-cluster.sh | 28 + test/shell/snapshot-maxsize.sh | 35 + test/shell/snapshot-merge-stack.sh | 89 + test/shell/snapshot-merge-thin.sh | 78 + test/shell/snapshot-merge.sh | 74 +- test/shell/snapshot-raid.sh | 423 ++++ test/shell/snapshot-reactivate.sh | 60 + test/shell/snapshot-remove-dmsetup.sh | 93 + test/shell/snapshot-rename.sh | 28 + test/shell/snapshot-usage-exa.sh | 47 + test/shell/snapshot-usage.sh | 205 ++ test/shell/snapshots-of-mirrors.sh | 26 +- test/shell/stray-device-node.sh | 36 + test/shell/stress_multi_threads_1.sh | 113 + test/shell/stress_multi_threads_2.sh | 95 + test/shell/stress_single_thread.sh | 61 + test/shell/system_id.sh | 709 ++++++ test/shell/tags.sh | 31 +- test/shell/test-partition.sh | 14 +- test/shell/thin-16g.sh | 88 + test/shell/thin-autoumount-dmeventd.sh | 114 +- test/shell/thin-defaults.sh | 41 + test/shell/thin-dmeventd-warns.sh | 83 + test/shell/thin-errors.sh | 79 + test/shell/thin-flags.sh | 140 ++ test/shell/thin-foreign-dmeventd.sh | 108 + test/shell/thin-foreign-repair.sh | 80 + test/shell/thin-large.sh | 55 + test/shell/thin-many-dmeventd.sh | 69 + test/shell/thin-merge.sh | 142 ++ test/shell/thin-overprovisioning.sh | 79 + test/shell/thin-resize-match.sh | 84 + test/shell/thin-restore.sh | 40 + test/shell/thin-vglock.sh | 65 + test/shell/thin-volume-list.sh | 60 + test/shell/thin-zero-meta.sh | 68 + test/shell/topology-support.sh | 89 +- test/shell/udev-pvscan-vgchange.sh | 457 ++++ test/shell/unknown-segment.sh | 33 +- test/shell/unlost-pv.sh | 67 +- test/shell/vdo-autoumount-dmeventd.sh | 127 + test/shell/vdo-convert.sh | 230 ++ test/shell/vg-check-devs-used.sh | 39 + test/shell/vg-name-from-env.sh | 108 + test/shell/vg-raid-takeover-1.sh | 202 ++ test/shell/vg-raid-takeover-2.sh | 65 + test/shell/vg-raid-takeover-3.sh | 52 + test/shell/vg-raid-takeover-4.sh | 37 + test/shell/vgcfgbackup-lvm1.sh | 38 + test/shell/vgcfgbackup-usage.sh | 71 +- test/shell/vgchange-many.sh | 57 + test/shell/vgchange-maxlv.sh | 21 +- test/shell/vgchange-partial.sh | 15 +- test/shell/vgchange-pvs-online.sh | 232 ++ test/shell/vgchange-sysinit.sh | 27 +- test/shell/vgchange-usage.sh | 75 +- test/shell/vgck.sh | 34 + test/shell/vgcreate-many-pvs.sh | 64 + test/shell/vgcreate-usage.sh | 115 +- test/shell/vgextend-restoremissing.sh | 44 +- test/shell/vgextend-usage.sh | 42 +- test/shell/vgimportclone.sh | 134 +- test/shell/vgimportdevices.sh | 309 +++ test/shell/vgmerge-operation.sh | 75 +- test/shell/vgmerge-usage.sh | 13 +- test/shell/vgreduce-removemissing-snapshot.sh | 15 +- test/shell/vgreduce-usage.sh | 41 +- test/shell/vgremove-corrupt-vg.sh | 23 + test/shell/vgrename-usage.sh | 25 +- test/shell/vgsplit-cache.sh | 135 + test/shell/vgsplit-operation.sh | 132 +- test/shell/vgsplit-raid.sh | 61 + test/shell/vgsplit-stacked.sh | 24 +- test/shell/vgsplit-thin.sh | 67 + test/shell/vgsplit-usage.sh | 51 +- test/shell/vgsplit-vdo.sh | 56 + test/shell/writecache-cache-blocksize-2.sh | 242 ++ test/shell/writecache-cache-blocksize.sh | 251 ++ test/shell/writecache-large.sh | 181 ++ test/shell/writecache-misc.sh | 116 + test/shell/writecache-split.sh | 265 ++ test/shell/writecache.sh | 272 ++ test/shell/zero-usage.sh | 46 + test/shell/zz-lvmlockd-dlm-remove.sh | 30 + test/shell/zz-lvmlockd-idm-remove.sh | 29 + test/shell/zz-lvmlockd-sanlock-remove.sh | 45 + test/unit/Makefile | 65 + test/unit/Makefile.in | 33 - test/unit/bcache_t.c | 1036 ++++++++ test/unit/bcache_utils_t.c | 474 ++++ test/unit/bitset_t.c | 99 +- test/unit/config_t.c | 154 +- test/unit/dmlist_t.c | 49 + test/unit/dmstatus_t.c | 84 + test/unit/framework.c | 66 + test/unit/framework.h | 51 + test/unit/io_engine_t.c | 229 ++ test/unit/matcher_t.c | 122 +- test/unit/percent_t.c | 102 + test/unit/radix_tree_t.c | 852 +++++++ test/unit/rt_case1.c | 1669 +++++++++++++ test/unit/run.c | 335 ++- test/unit/string_t.c | 72 +- test/unit/unit-test.sh | 21 + test/unit/units.h | 55 + test/unit/vdo_t.c | 325 +++ 491 files changed, 60735 insertions(+), 5238 deletions(-) create mode 100644 test/.gitignore delete mode 100644 test/api/Makefile.in create mode 100644 test/api/dbustest.sh delete mode 100644 test/api/lvtest.c delete mode 100644 test/api/lvtest.sh delete mode 100644 test/api/pe_start.c delete mode 100644 test/api/pe_start.sh delete mode 100644 test/api/percent.c delete mode 100644 test/api/percent.sh delete mode 100644 test/api/test.c delete mode 100644 test/api/thin_percent.c delete mode 100644 test/api/thin_percent.sh delete mode 100644 test/api/vgtest.c delete mode 100644 test/api/vgtest.sh create mode 100755 test/dbus/lvm_error_inject.py create mode 100755 test/dbus/lvmdbustest.py create mode 100644 test/dbus/testlib.py create mode 100755 test/dbus/validatestate.py create mode 100644 test/lib/brick-shelltest.h create mode 100644 test/lib/dmsecuretest.c create mode 100644 test/lib/flavour-ndev-cluster-lvmpolld.sh create mode 100644 test/lib/flavour-ndev-cluster.sh create mode 100644 test/lib/flavour-ndev-devicesfile.sh create mode 100644 test/lib/flavour-ndev-lvmpolld.sh create mode 100644 test/lib/flavour-ndev-vanilla.sh create mode 100644 test/lib/flavour-udev-cluster-lvmpolld.sh create mode 100644 test/lib/flavour-udev-cluster.sh create mode 100644 test/lib/flavour-udev-lvmlockd-dlm.sh create mode 100644 test/lib/flavour-udev-lvmlockd-idm.sh create mode 100644 test/lib/flavour-udev-lvmlockd-sanlock.sh create mode 100644 test/lib/flavour-udev-lvmlockd-test.sh create mode 100644 test/lib/flavour-udev-lvmpolld.sh create mode 100644 test/lib/flavour-udev-vanilla.sh create mode 100644 test/lib/idm_inject_failure.c create mode 100644 test/lib/inittest.sh create mode 100755 test/lib/lvm_vdo_wrapper.sh create mode 100644 test/lib/mke2fs.conf create mode 100644 test/lib/runner.cpp create mode 100644 test/lib/test-corosync-conf create mode 100644 test/lib/test-dlm-conf create mode 100644 test/lib/test-sanlock-conf delete mode 100644 test/lib/test.sh create mode 100644 test/shell/aa-lvmlockd-dlm-prepare.sh create mode 100644 test/shell/aa-lvmlockd-idm-prepare.sh create mode 100644 test/shell/aa-lvmlockd-sanlock-prepare.sh create mode 100644 test/shell/activation-skip.sh create mode 100644 test/shell/allow-mixed-block-sizes.sh create mode 100644 test/shell/autoactivation-metadata.sh create mode 100644 test/shell/backup-read-only.sh create mode 100644 test/shell/cache-metadata2.sh create mode 100644 test/shell/cache-no-discard.sh create mode 100644 test/shell/cache-single-options.sh create mode 100644 test/shell/cache-single-split.sh create mode 100644 test/shell/cache-single-thin.sh create mode 100644 test/shell/cache-single-types.sh create mode 100644 test/shell/cache-single-usage.sh create mode 100644 test/shell/cachevol-cachedevice.sh create mode 100644 test/shell/caching-snapshot.sh delete mode 100644 test/shell/clvmd-restart.sh create mode 100644 test/shell/component-cache.sh create mode 100644 test/shell/component-mirror.sh create mode 100644 test/shell/component-raid.sh create mode 100644 test/shell/component-thin.sh create mode 100644 test/shell/creation-time.sh create mode 100644 test/shell/dev-aliases.sh create mode 100644 test/shell/devicesfile-basic.sh create mode 100644 test/shell/devicesfile-devname.sh create mode 100644 test/shell/devicesfile-edit.sh create mode 100644 test/shell/devicesfile-realdevs.sh create mode 100644 test/shell/devicesfile-serial.sh create mode 100644 test/shell/devicesfile-vpd-ids.sh create mode 100644 test/shell/dmsecuretest.sh create mode 100644 test/shell/dmsetup-integrity-keys.sh create mode 100644 test/shell/dmsetup-keyring.sh create mode 100644 test/shell/dmstats-create.sh create mode 100644 test/shell/dmstats-report.sh create mode 100644 test/shell/duplicate-pvs-md0.sh create mode 100644 test/shell/duplicate-pvs-md1.sh create mode 100644 test/shell/duplicate-pvs-multipath.sh create mode 100644 test/shell/duplicate-vgid.sh create mode 100644 test/shell/duplicate-vgnames.sh create mode 100644 test/shell/duplicate-vgrename.sh create mode 100644 test/shell/error-usage.sh create mode 100644 test/shell/exported.sh create mode 100644 test/shell/fsadm-crypt-fsresize.sh create mode 100644 test/shell/fsadm-crypt.sh create mode 100644 test/shell/fsadm-renamed.sh create mode 100644 test/shell/hints.sh create mode 100644 test/shell/idm_fabric_failure.sh create mode 100644 test/shell/idm_fabric_failure_half_brain.sh create mode 100644 test/shell/idm_fabric_failure_timeout.sh create mode 100644 test/shell/idm_ilm_failure.sh create mode 100644 test/shell/integrity-blocksize-2.sh create mode 100644 test/shell/integrity-blocksize-3.sh create mode 100644 test/shell/integrity-blocksize.sh create mode 100644 test/shell/integrity-caching.sh create mode 100644 test/shell/integrity-dmeventd.sh create mode 100644 test/shell/integrity-large.sh create mode 100644 test/shell/integrity-misc.sh create mode 100644 test/shell/integrity-syncaction.sh create mode 100644 test/shell/integrity.sh create mode 100644 test/shell/large-physical-sector-size.sh create mode 100644 test/shell/lock-parallel.sh create mode 100644 test/shell/losetup-partscan.sh create mode 100644 test/shell/lv-ancestry.sh create mode 100644 test/shell/lvchange-cache-mode.sh create mode 100644 test/shell/lvchange-cache-old.sh create mode 100644 test/shell/lvchange-cache-syncaction-raid.sh create mode 100644 test/shell/lvchange-cache.sh create mode 100644 test/shell/lvchange-partial-raid10.sh create mode 100644 test/shell/lvchange-raid-transient-failures.sh create mode 100644 test/shell/lvchange-raid.sh create mode 100644 test/shell/lvchange-raid1-writemostly.sh create mode 100644 test/shell/lvchange-raid10.sh create mode 100644 test/shell/lvchange-raid456.sh create mode 100644 test/shell/lvchange-rebuild-raid.sh create mode 100644 test/shell/lvchange-syncaction-raid.sh create mode 100644 test/shell/lvchange-thin.sh create mode 100644 test/shell/lvchange-vdo.sh create mode 100644 test/shell/lvconvert-cache-abort.sh create mode 100644 test/shell/lvconvert-cache-chunks.sh create mode 100644 test/shell/lvconvert-cache-raid.sh create mode 100644 test/shell/lvconvert-cache-smq.sh create mode 100644 test/shell/lvconvert-cache-snapshot.sh create mode 100644 test/shell/lvconvert-cache-thin.sh create mode 100644 test/shell/lvconvert-cache-vdo.sh create mode 100644 test/shell/lvconvert-cache.sh create mode 100644 test/shell/lvconvert-m-raid1-degraded.sh create mode 100644 test/shell/lvconvert-mirror-split.sh create mode 100644 test/shell/lvconvert-mirror-updown.sh create mode 100644 test/shell/lvconvert-raid-allocation.sh create mode 100644 test/shell/lvconvert-raid-regionsize.sh create mode 100644 test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh create mode 100644 test/shell/lvconvert-raid-reshape-linear_to_striped-single-type.sh create mode 100644 test/shell/lvconvert-raid-reshape-linear_to_striped.sh create mode 100644 test/shell/lvconvert-raid-reshape-load.sh create mode 100644 test/shell/lvconvert-raid-reshape-striped_to_linear-single-type.sh create mode 100644 test/shell/lvconvert-raid-reshape-striped_to_linear.sh create mode 100644 test/shell/lvconvert-raid-reshape-stripes-load-fail.sh create mode 100644 test/shell/lvconvert-raid-reshape-stripes-load-reload.sh create mode 100644 test/shell/lvconvert-raid-reshape-stripes-load.sh create mode 100644 test/shell/lvconvert-raid-reshape.sh create mode 100644 test/shell/lvconvert-raid-restripe-linear.sh create mode 100644 test/shell/lvconvert-raid-status-validation.sh create mode 100644 test/shell/lvconvert-raid-takeover-alloc-failure.sh create mode 100644 test/shell/lvconvert-raid-takeover-linear_to_raid4.sh create mode 100644 test/shell/lvconvert-raid-takeover-raid4_to_linear.sh create mode 100644 test/shell/lvconvert-raid-takeover-thin.sh create mode 100644 test/shell/lvconvert-raid-takeover.sh create mode 100644 test/shell/lvconvert-raid0-striped.sh create mode 100644 test/shell/lvconvert-raid0_to_raid10.sh create mode 100644 test/shell/lvconvert-raid1-split-trackchanges.sh create mode 100644 test/shell/lvconvert-raid456.sh create mode 100644 test/shell/lvconvert-raid5_to_raid10.sh create mode 100644 test/shell/lvconvert-repair-cache.sh create mode 100644 test/shell/lvconvert-repair-mirror.sh create mode 100644 test/shell/lvconvert-repair-raid-dmeventd.sh create mode 100644 test/shell/lvconvert-repair-raid.sh create mode 100644 test/shell/lvconvert-repair-thin-raid.sh create mode 100644 test/shell/lvconvert-repair-thin.sh create mode 100644 test/shell/lvconvert-snapshot-cache.sh create mode 100644 test/shell/lvconvert-snapshot-mirror.sh create mode 100644 test/shell/lvconvert-snapshot-raid.sh create mode 100644 test/shell/lvconvert-snapshot-thin.sh create mode 100644 test/shell/lvconvert-snapshot.sh create mode 100644 test/shell/lvconvert-striped-raid0.sh create mode 100644 test/shell/lvconvert-thin-external-cache.sh create mode 100644 test/shell/lvconvert-thin-external.sh create mode 100644 test/shell/lvconvert-thin-from-thick.sh create mode 100644 test/shell/lvconvert-thin-raid.sh create mode 100644 test/shell/lvconvert-vdo-raid.sh create mode 100644 test/shell/lvconvert-vdo.sh create mode 100644 test/shell/lvcreate-cache-fail.sh create mode 100644 test/shell/lvcreate-cache-no-tools.sh create mode 100644 test/shell/lvcreate-cache-raid.sh create mode 100644 test/shell/lvcreate-cache-snapshot.sh create mode 100644 test/shell/lvcreate-cache.sh create mode 100644 test/shell/lvcreate-external-dmeventd.sh create mode 100644 test/shell/lvcreate-missing.sh create mode 100644 test/shell/lvcreate-raid-nosync.sh create mode 100644 test/shell/lvcreate-raid-volume_list.sh create mode 100644 test/shell/lvcreate-raid1-read-error.sh create mode 100644 test/shell/lvcreate-signature-wiping.sh create mode 100644 test/shell/lvcreate-thin-big.sh create mode 100644 test/shell/lvcreate-thin-cache.sh create mode 100644 test/shell/lvcreate-thin-external-size.sh create mode 100644 test/shell/lvcreate-thin-external.sh create mode 100644 test/shell/lvcreate-thin-limits.sh create mode 100644 test/shell/lvcreate-vdo-cache.sh create mode 100644 test/shell/lvcreate-vdo.sh create mode 100644 test/shell/lvdisplay-raid.sh create mode 100644 test/shell/lvextend-caches-on-thindata.sh create mode 100644 test/shell/lvextend-caches.sh create mode 100644 test/shell/lvextend-raid.sh create mode 100644 test/shell/lvextend-thin-adddel.sh create mode 100644 test/shell/lvextend-thin-cache.sh create mode 100644 test/shell/lvextend-thin-data-dmeventd.sh create mode 100644 test/shell/lvextend-thin-full.sh create mode 100644 test/shell/lvextend-thin-metadata-dmeventd.sh create mode 100644 test/shell/lvextend-thin-raid.sh create mode 100644 test/shell/lvextend-thin.sh create mode 100644 test/shell/lvextend-vdo-dmeventd.sh create mode 100644 test/shell/lvextend-vdo.sh create mode 100644 test/shell/lvm-conf-error.sh create mode 100644 test/shell/lvm-on-md.sh delete mode 100644 test/shell/lvmetad-disabled.sh delete mode 100644 test/shell/lvmetad-dump.sh delete mode 100644 test/shell/lvmetad-lvm1.sh delete mode 100644 test/shell/lvmetad-pvs.sh delete mode 100644 test/shell/lvmetad-pvscan-cache.sh delete mode 100644 test/shell/lvmetad-restart.sh delete mode 100644 test/shell/lvmetad-test.sh delete mode 100644 test/shell/lvmetad-warning.sh create mode 100644 test/shell/lvmlockd-hello-world.sh create mode 100644 test/shell/lvmlockd-lv-types.sh create mode 100644 test/shell/lvmlockd_failure.sh create mode 100644 test/shell/lvremove-thindata-caches.sh create mode 100644 test/shell/lvrename-cache-thin.sh create mode 100644 test/shell/lvrename-vdo.sh create mode 100644 test/shell/lvresize-fs-crypt.sh create mode 100644 test/shell/lvresize-fs.sh create mode 100644 test/shell/lvresize-full.sh create mode 100644 test/shell/lvresize-thin-external-origin.sh create mode 100644 test/shell/lvresize-thin-metadata.sh create mode 100644 test/shell/lvresize-vdo.sh create mode 100644 test/shell/lvresize-xfs.sh create mode 100644 test/shell/lvs-cache.sh create mode 100644 test/shell/mda-rollback.sh create mode 100644 test/shell/metadata-bad-mdaheader.sh create mode 100644 test/shell/metadata-bad-text.sh delete mode 100644 test/shell/metadata-dirs.sh create mode 100644 test/shell/metadata-full.sh create mode 100644 test/shell/metadata-old.sh create mode 100644 test/shell/metadata-zero-space.sh create mode 100644 test/shell/missing-pv-unused.sh create mode 100644 test/shell/missing-pv.sh create mode 100644 test/shell/multi_hosts_lv_ex_timeout_hosta.sh create mode 100644 test/shell/multi_hosts_lv_ex_timeout_hostb.sh create mode 100644 test/shell/multi_hosts_lv_hosta.sh create mode 100644 test/shell/multi_hosts_lv_hostb.sh create mode 100644 test/shell/multi_hosts_lv_sh_timeout_hosta.sh create mode 100644 test/shell/multi_hosts_lv_sh_timeout_hostb.sh create mode 100644 test/shell/multi_hosts_vg_hosta.sh create mode 100644 test/shell/multi_hosts_vg_hostb.sh create mode 100644 test/shell/multipath-config.sh create mode 100644 test/shell/nomda-restoremissing.sh create mode 100644 test/shell/open-file-limit.sh create mode 100644 test/shell/orphan-ondisk.sh create mode 100644 test/shell/outdated-pv.sh create mode 100644 test/shell/pe-align.sh create mode 100644 test/shell/process-each-duplicate-pvs.sh create mode 100644 test/shell/process-each-lv.sh create mode 100644 test/shell/process-each-pv-nomda-all.sh create mode 100644 test/shell/process-each-pv-nomda.sh create mode 100644 test/shell/process-each-pv.sh create mode 100644 test/shell/process-each-pvresize.sh create mode 100644 test/shell/process-each-vg.sh create mode 100644 test/shell/process-each-vgreduce.sh create mode 100644 test/shell/profiles-cache.sh create mode 100644 test/shell/profiles-thin.sh create mode 100644 test/shell/profiles-vdo.sh create mode 100644 test/shell/profiles.sh create mode 100644 test/shell/pv-check-dev-size.sh create mode 100644 test/shell/pv-corruption.sh create mode 100644 test/shell/pv-duplicate-uuid.sh delete mode 100644 test/shell/pv-duplicate.sh create mode 100644 test/shell/pv-ext-flags.sh create mode 100644 test/shell/pv-ext-update.sh create mode 100644 test/shell/pvck-dump.sh create mode 100644 test/shell/pvck-repair.sh create mode 100644 test/shell/pvcreate-bootloaderarea.sh create mode 100644 test/shell/pvcreate-ff.sh create mode 100644 test/shell/pvcreate-md-fake-hdr.sh create mode 100644 test/shell/pvcreate-restore.sh create mode 100644 test/shell/pvmove-abort-all.sh create mode 100644 test/shell/pvmove-abort.sh create mode 100644 test/shell/pvmove-all-segtypes.sh create mode 100644 test/shell/pvmove-background.sh create mode 100644 test/shell/pvmove-cache-segtypes.sh create mode 100644 test/shell/pvmove-lvs.sh create mode 100644 test/shell/pvmove-raid-segtypes.sh create mode 100644 test/shell/pvmove-restart.sh create mode 100644 test/shell/pvmove-resume-1.sh create mode 100644 test/shell/pvmove-resume-2.sh create mode 100644 test/shell/pvmove-resume-multiseg.sh create mode 100644 test/shell/pvmove-thin-segtypes.sh create mode 100644 test/shell/pvremove-thin.sh create mode 100644 test/shell/pvremove-warnings.sh create mode 100644 test/shell/pvresize-mdas.sh create mode 100644 test/shell/pvscan-autoactivate.sh create mode 100644 test/shell/pvscan-autoactivation-polling.sh create mode 100644 test/shell/pvscan-cache.sh create mode 100644 test/shell/pvscan-nomda-bg.sh create mode 100644 test/shell/relative-sign-options.sh create mode 100644 test/shell/report-fields.sh create mode 100644 test/shell/report-format.sh create mode 100644 test/shell/report-hidden.sh create mode 100644 test/shell/scan-lvs.sh create mode 100644 test/shell/select-report.sh create mode 100644 test/shell/select-tools-thin.sh create mode 100644 test/shell/select-tools.sh create mode 100644 test/shell/snapshot-cluster.sh create mode 100644 test/shell/snapshot-maxsize.sh create mode 100644 test/shell/snapshot-merge-stack.sh create mode 100644 test/shell/snapshot-merge-thin.sh create mode 100644 test/shell/snapshot-raid.sh create mode 100644 test/shell/snapshot-reactivate.sh create mode 100644 test/shell/snapshot-remove-dmsetup.sh create mode 100644 test/shell/snapshot-rename.sh create mode 100644 test/shell/snapshot-usage-exa.sh create mode 100644 test/shell/snapshot-usage.sh create mode 100644 test/shell/stray-device-node.sh create mode 100644 test/shell/stress_multi_threads_1.sh create mode 100644 test/shell/stress_multi_threads_2.sh create mode 100644 test/shell/stress_single_thread.sh create mode 100644 test/shell/system_id.sh create mode 100644 test/shell/thin-16g.sh create mode 100644 test/shell/thin-defaults.sh create mode 100644 test/shell/thin-dmeventd-warns.sh create mode 100644 test/shell/thin-errors.sh create mode 100644 test/shell/thin-flags.sh create mode 100644 test/shell/thin-foreign-dmeventd.sh create mode 100644 test/shell/thin-foreign-repair.sh create mode 100644 test/shell/thin-large.sh create mode 100644 test/shell/thin-many-dmeventd.sh create mode 100644 test/shell/thin-merge.sh create mode 100644 test/shell/thin-overprovisioning.sh create mode 100644 test/shell/thin-resize-match.sh create mode 100644 test/shell/thin-restore.sh create mode 100644 test/shell/thin-vglock.sh create mode 100644 test/shell/thin-volume-list.sh create mode 100644 test/shell/thin-zero-meta.sh create mode 100644 test/shell/udev-pvscan-vgchange.sh create mode 100644 test/shell/vdo-autoumount-dmeventd.sh create mode 100644 test/shell/vdo-convert.sh create mode 100644 test/shell/vg-check-devs-used.sh create mode 100644 test/shell/vg-name-from-env.sh create mode 100644 test/shell/vg-raid-takeover-1.sh create mode 100644 test/shell/vg-raid-takeover-2.sh create mode 100644 test/shell/vg-raid-takeover-3.sh create mode 100644 test/shell/vg-raid-takeover-4.sh create mode 100644 test/shell/vgcfgbackup-lvm1.sh create mode 100644 test/shell/vgchange-many.sh create mode 100644 test/shell/vgchange-pvs-online.sh create mode 100644 test/shell/vgck.sh create mode 100644 test/shell/vgcreate-many-pvs.sh create mode 100644 test/shell/vgimportdevices.sh create mode 100644 test/shell/vgremove-corrupt-vg.sh create mode 100644 test/shell/vgsplit-cache.sh create mode 100644 test/shell/vgsplit-raid.sh create mode 100644 test/shell/vgsplit-thin.sh create mode 100644 test/shell/vgsplit-vdo.sh create mode 100644 test/shell/writecache-cache-blocksize-2.sh create mode 100644 test/shell/writecache-cache-blocksize.sh create mode 100644 test/shell/writecache-large.sh create mode 100644 test/shell/writecache-misc.sh create mode 100644 test/shell/writecache-split.sh create mode 100644 test/shell/writecache.sh create mode 100644 test/shell/zero-usage.sh create mode 100644 test/shell/zz-lvmlockd-dlm-remove.sh create mode 100644 test/shell/zz-lvmlockd-idm-remove.sh create mode 100644 test/shell/zz-lvmlockd-sanlock-remove.sh create mode 100644 test/unit/Makefile delete mode 100644 test/unit/Makefile.in create mode 100644 test/unit/bcache_t.c create mode 100644 test/unit/bcache_utils_t.c create mode 100644 test/unit/dmlist_t.c create mode 100644 test/unit/dmstatus_t.c create mode 100644 test/unit/framework.c create mode 100644 test/unit/framework.h create mode 100644 test/unit/io_engine_t.c create mode 100644 test/unit/percent_t.c create mode 100644 test/unit/radix_tree_t.c create mode 100644 test/unit/rt_case1.c create mode 100644 test/unit/unit-test.sh create mode 100644 test/unit/units.h create mode 100644 test/unit/vdo_t.c (limited to 'test') diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..5b377c7 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,4 @@ +.bin-dir-stamp +bin +init.sh +results/ diff --git a/test/Makefile.in b/test/Makefile.in index 5bbd1d6..20e97eb 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2007-2012 Red Hat, Inc. All rights reserved. +# Copyright (C) 2007-2015 Red Hat, Inc. All rights reserved. # # This file is part of LVM2. # @@ -8,7 +8,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #TEST_OPTS=--verbose --debug SHELL_PATH ?= $(SHELL) @@ -19,121 +19,351 @@ 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@" +abs_srcdir = @abs_srcdir@ +abs_builddir = @abs_builddir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +datarootdir = @datarootdir@ -SUBDIRS = api unit -SOURCES = lib/not.c lib/harness.c +LVM_TEST_RESULTS ?= results + +# FIXME: resolve testing of: unit +SOURCES := lib/not.c lib/harness.c lib/dmsecuretest.c +CXXSOURCES := lib/runner.cpp +CXXFLAGS += $(EXTRA_EXEC_CFLAGS) + +CLEAN_DIRS += dbus/__pycache__ $(LVM_TEST_RESULTS) +ifneq (.,$(firstword $(srcdir))) +CLEAN_TARGETS += $(RUN_BASE) $(addprefix lib/,$(LIB_LVMLOCKD_CONF) $(LIB_MKE2FS_CONF)) +endif +CLEAN_TARGETS += $(shell find -H lib -type l) \ + $(CXXSOURCES:%.cpp=%.o) $(CXXSOURCES:%.cpp=%.d) $(CXXSOURCES:%.cpp=%.gcno) $(CXXSOURCES:%.cpp=%.gcda) + +CLEAN_TARGETS += .lib-dir-stamp .tests-stamp $(LIB) $(addprefix lib/,\ + clvmd harness dmeventd dmsetup dmstats lvmpolld \ + $(LVM_PROFILES) $(LVM_SCRIPTS) \ + paths-installed paths-installed-t paths-common paths-common-t) include $(top_builddir)/make.tmpl T ?= . S ?= @ # never match anything by default VERBOSE ?= 0 -ALL = $(shell find $(srcdir) \( -path \*/shell/\*.sh -or -path \*/api/\*.sh \) | sort) -RUN = $(shell find $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/api/\*.sh \) -and -regex "$(srcdir)/.*($(T)).*" -and -not -regex "$(srcdir)/.*($(S)).*" | sort) +comma = , +RUN := $(shell find -L $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/api/\*.sh -or -path \*/unit/\*.sh \) -and -regex "$(srcdir)/.*($(subst $(comma),|,$(T))).*" -and -not -regex "$(srcdir)/.*($(subst $(comma),|,$(S))).*" | $(SORT)) RUN_BASE = $(subst $(srcdir)/,,$(RUN)) +ifeq ("@BUILD_DMEVENTD@", "yes") +DMEVENTD_TOOLS :=\ + daemons/dmeventd/dmeventd +endif + +ifeq ("@BUILD_LVMPOLLD@", "yes") +LVMPOLLD_RUN_BASE = $(RUN_BASE) +LVMPOLLD_NDEV_FLAVOUR = ,ndev-lvmpolld +LVMPOLLD_UDEV_FLAVOUR = ,udev-lvmpolld +LVMPOLLD_TOOLS :=\ + daemons/lvmpolld/lvmpolld +endif + +ifeq ("@BUILD_LVMLOCKD@", "yes") +LVMLOCKD_RUN_BASE = $(RUN_BASE) +LVMLOCKD_UDEV_FLAVOUR = ,udev-lvmlockd-test +LVMLOCKD_TOOLS :=\ + daemons/lvmlockd/lvmlockd\ + daemons/lvmlockd/lvmlockctl +endif + # Shell quote; -SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) +SHELL_PATH_SQ := $(subst ','\'',$(SHELL_PATH)) ifeq ("@UDEV_SYNC@", "yes") -dm_udev_synchronisation = 1 +dm_udev_synchronization = 1 endif -all: check +all: .tests-stamp help: @echo -e "\nAvailable targets:" @echo " all Default target, run check." @echo " check Run all tests." - @echo " check_local Run tests without clvmd and lvmetad." - @echo " check_cluster Run tests with cluster daemon." - @echo " check_lvmetad Run tests with lvmetad daemon." + @echo " check_system Run all tests using udev." + @echo " check_local Run tests." + @echo " check_lvmpolld Run tests with lvmpolld daemon." + @echo " check_devicesfile Run tests using a devices file." + @echo " check_all_lvmpolld Run all tests with lvmpolld daemon." + @echo " check_lvmlockd_sanlock Run tests with lvmlockd and sanlock." + @echo " check_lvmlockd_dlm Run tests with lvmlockd and dlm." + @echo " check_lvmlockd_idm Run tests with lvmlockd and idm." + @echo " check_lvmlockd_test Run tests with lvmlockd --test." + @echo " run-unit-test Run only unit tests (root not needed)." @echo " clean Clean dir." @echo " help Display callable targets." @echo -e "\nSupported variables:" + @echo " LVM_TEST_AUX_TRACE Set for verbose messages for aux scripts []." + @echo " LVM_TEST_BACKING_DEVICE Set device used for testing (see also LVM_TEST_DIR)." + @echo " LVM_TEST_MULTI_HOST Set multiple hosts used for testing." + @echo " LVM_TEST_CAN_CLOBBER_DMESG Allow to clobber dmesg buffer without /dev/kmsg. (1)" @echo " LVM_TEST_DEVDIR Set to '/dev' to run on real /dev." - @echo " LVM_TEST_DIR Where to create test files [TMPDIR]." + @echo " LVM_TEST_PREFER_BRD Prefer using brd (ramdisk) over loop for testing [1]." + @echo " LVM_TEST_DIR Where to create test files [$(LVM_TEST_DIR)]." @echo " LVM_TEST_LOCKING Normal (1), Cluster (3)." - @echo " LVM_TEST_LVMETAD Start lvmetad (1)." + @echo " LVM_TEST_LVMPOLLD Start lvmpolld" @echo " LVM_TEST_NODEBUG Do not debug lvm commands." @echo " LVM_TEST_PARALLEL May skip agresive wipe of LVMTEST resources." + @echo " LVM_TEST_RESULTS Where to create result files [results]." + @echo " LVM_TEST_THIN_CHECK_CMD Command for thin_check [$(LVM_TEST_THIN_CHECK_CMD)]." + @echo " LVM_TEST_THIN_DUMP_CMD Command for thin_dump [$(LVM_TEST_THIN_DUMP_CMD)]." + @echo " LVM_TEST_THIN_REPAIR_CMD Command for thin_repair [$(LVM_TEST_THIN_REPAIR_CMD)]." + @echo " LVM_TEST_THIN_RESTORE_CMD Command for thin_restore [$(LVM_TEST_THIN_RESTORE_CMD)]." + @echo " LVM_TEST_CACHE_CHECK_CMD Command for cache_check [$(LVM_TEST_CACHE_CHECK_CMD)]." + @echo " LVM_TEST_CACHE_DUMP_CMD Command for cache_dump [$(LVM_TEST_CACHE_DUMP_CMD)]." + @echo " LVM_TEST_CACHE_REPAIR_CMD Command for cache_repair [$(LVM_TEST_CACHE_REPAIR_CMD)]." + @echo " LVM_TEST_CACHE_RESTORE_CMD Command for cache_restore [$(LVM_TEST_CACHE_RESTORE_CMD)]." + @echo " LVM_TEST_UNLIMITED Set to get unlimited test log (>32MB)" + @echo " LVM_TEST_DEVICE_LIST File path listing real devs that tests can use." + @echo " LVM_VALGRIND Enable valgrind testing, execs $$"VALGRIND. + @echo " LVM_VALGRIND_DMEVENTD Enable valgrind testing of dmeventd (1)." + @echo " LVM_VALGRIND_LVMPOLLD Enable valgrind testing of lvmpolld (1)." + @echo " LVM_STRACE Enable strace logging." + @echo " LVM_DEBUG_LEVEL Sets debuging level for valgrind/strace (use > 0)." + @echo " LVM_DEBUG_LVMDBUS Run lvmdbus with --debug option." @echo " LVM_VERIFY_UDEV Default verify state for lvm.conf." - @echo " S Skip given test (regex)." - @echo " T Run given test (regex)." + @echo " LVM_LOG_FILE_MAX_LINES Maximum number of logged lines for lvm2 command [1000000]." + @echo " S Skip given test(s) (regex)." + @echo " T Run given test(s) (regex)." @echo " VERBOSE Verbose output (1), timing (2)." -check: check_local check_cluster check_lvmetad +check: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours ndev-vanilla$(LVMPOLLD_NDEV_FLAVOUR) --only $(T) --skip $(S) -check_cluster: .tests-stamp - @echo Testing with locking_type 3 - VERBOSE=$(VERBOSE) LVM_TEST_LOCKING=3 ./lib/harness $(RUN_BASE) +check_system: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours udev-vanilla$(LVMPOLLD_UDEV_FLAVOUR)$(LVMLOCKD_UDEV_FLAVOUR) --only $(T) --skip $(S) check_local: .tests-stamp - @echo Testing with locking_type 1 - VERBOSE=$(VERBOSE) LVM_TEST_LOCKING=1 ./lib/harness $(RUN_BASE) + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours ndev-vanilla --only $(T) --skip $(S) + +ifeq ("@BUILD_LVMPOLLD@", "yes") +check_lvmpolld: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours ndev-lvmpolld --only $(T) --skip $(S) + +check_all_lvmpolld: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours ndev-lvmpolld --only $(T) --skip $(S) +endif + +check_devicesfile: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours ndev-devicesfile --only $(T) --skip $(S) + +ifeq ("@BUILD_LVMLOCKD@", "yes") +check_lvmlockd_sanlock: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours udev-lvmlockd-sanlock --only shell/aa-lvmlockd-sanlock-prepare.sh,$(T),shell/zz-lvmlockd-sanlock-remove.sh --skip $(S) + +check_lvmlockd_dlm: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours udev-lvmlockd-dlm --only shell/aa-lvmlockd-dlm-prepare.sh,$(T),shell/zz-lvmlockd-dlm-remove.sh --skip $(S) + +check_lvmlockd_idm: .tests-stamp lib/idm_inject_failure + $(INSTALL_PROGRAM) lib/idm_inject_failure $(EXECDIR) + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours udev-lvmlockd-idm --only shell/aa-lvmlockd-idm-prepare.sh,$(T),shell/zz-lvmlockd-idm-remove.sh --skip $(S) + +check_lvmlockd_test: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir $(LVM_TEST_RESULTS) \ + --flavours udev-lvmlockd-test --only $(T) --skip $(S) +endif + +run-unit-test unit-test unit/unit-test: + @echo " [MAKE] $(@F)" + $(Q) $(MAKE) -C $(top_builddir) $(@F) + +DATADIR := $(datadir)/lvm2-testsuite +EXECDIR := $(libexecdir)/lvm2-testsuite + +LIB_FLAVOURS :=\ + flavour-ndev-lvmpolld\ + flavour-ndev-vanilla\ + flavour-ndev-devicesfile\ + flavour-udev-lvmpolld\ + flavour-udev-lvmlockd-sanlock\ + flavour-udev-lvmlockd-dlm\ + flavour-udev-lvmlockd-idm\ + flavour-udev-lvmlockd-test\ + flavour-udev-vanilla -check_lvmetad: .tests-stamp - @echo Testing with lvmetad on - VERBOSE=$(VERBOSE) LVM_TEST_LVMETAD=1 ./lib/harness $(RUN_BASE) +LIB_LVMLOCKD_CONF :=\ + test-corosync-conf \ + test-dlm-conf \ + test-sanlock-conf -lib/should: lib/not - ln -sf not lib/should +LIB_MKE2FS_CONF := mke2fs.conf + +LVM_TOOLS := \ + $(LVMPOLLD_TOOLS)\ + $(LVMLOCKD_TOOLS)\ + $(DMEVENTD_TOOLS)\ + libdm/dm-tools/dmsetup + +LVM_PROFILES := $(addsuffix .profile,\ + cache-mq\ + cache-smq\ + lvmdbusd\ + thin-performance) + +LIB_LINK_NOT := invalid fail should +LIB_LOCAL := paths runner +LIB_NOT := not +LIB_SHARED := check aux inittest utils get lvm-wrapper lvm_vdo_wrapper +LIB_CONF := $(LIB_LVMLOCKD_CONF) $(LIB_MKE2FS_CONF) +LIB_DATA := $(LIB_FLAVOURS) dm-version-expected version-expected +LIB_EXEC := $(LIB_NOT) dmsecuretest securetest +LVM_SCRIPTS := fsadm lvm_import_vdo + +install: .tests-stamp lib/paths-installed + $(SHOW) " [INSTALL] tests" + $(Q) $(INSTALL_DIR) $(DATADIR)/{shell,api,unit,lib,dbus} $(EXECDIR) + $(Q) $(INSTALL_DATA) shell/*.sh $(DATADIR)/shell + $(Q) $(INSTALL_DATA) api/*.sh $(DATADIR)/api + $(Q) $(INSTALL_DATA) unit/*.sh $(DATADIR)/unit + $(Q)- $(INSTALL_PROGRAM) unit/unit-test $(DATADIR)/unit + $(Q)- $(INSTALL_PROGRAM) dbus/*.py $(DATADIR)/dbus/ + $(Q) $(INSTALL_DATA) lib/paths-installed $(DATADIR)/lib/paths + $(Q) cd lib &&\ + $(INSTALL_DATA) $(LIB_DATA) $(LIB_CONF) $(DATADIR)/lib + $(Q) cd lib &&\ + $(INSTALL_SCRIPT) $(LIB_SHARED) $(DATADIR)/lib + $(Q) cd lib &&\ + $(INSTALL_PROGRAM) -D $(LIB_EXEC) $(EXECDIR) + $(Q) cd $(abs_top_srcdir)/conf &&\ + $(INSTALL_DATA) $(LVM_PROFILES) $(DATADIR)/lib + $(Q) cd $(DATADIR)/lib &&\ + $(foreach FILE, $(CMDS), $(LN_S) -f lvm-wrapper $(FILE) $(newline)) + $(Q) cd $(EXECDIR) &&\ + $(foreach FILE, $(LIB_LINK_NOT), $(LN_S) -f $(LIB_NOT) $(FILE) $(newline)) + $(Q) $(INSTALL_PROGRAM) -D lib/runner $(bindir)/lvm2-testsuite + +lib/should lib/invalid lib/fail: lib/not + $(SHOW) " [LN] $@" + $(Q) $(LN_S) -f $(> $@-t - echo 'abs_top_builddir=$(abs_top_builddir)' >> $@-t - echo 'abs_top_srcdir=$(abs_top_srcdir)' >> $@-t - echo 'abs_srcdir=$(abs_srcdir)' >> $@-t - echo 'abs_builddir=$(abs_builddir)' >> $@-t - echo 'export DM_UDEV_SYNCHRONISATION=$(dm_udev_synchronisation)' >> $@-t - echo 'export THIN=@THIN@' >> $@-t - echo 'export LVMETAD_PIDFILE=@LVMETAD_PIDFILE@' >> $@-t - mv $@-t $@ - -LIB = lib/not lib/should lib/harness \ - lib/check lib/aux lib/test lib/utils lib/get lib/lvm-wrapper \ - lib/paths - -CMDS = lvm $(shell cat $(top_builddir)/tools/.commands) - -.tests-stamp: $(ALL) $(LIB) $(SUBDIRS) - @if test "$(srcdir)" != . ; then \ - echo "Linking tests to builddir."; \ - $(MKDIR_P) shell; \ - for f in $(subst $(srcdir)/,,$(ALL)); do \ - ln -sf $(abs_top_srcdir)/test/$$f $$f; \ - done; \ - fi - touch $@ - -.lib-dir-stamp: - $(MKDIR_P) lib - for i in $(CMDS); do ln -fs lvm-wrapper lib/$$i; done - ln -fs $(abs_top_builddir)/tools/dmsetup lib/dmsetup - ln -fs $(abs_top_builddir)/daemons/clvmd/clvmd lib/clvmd - ln -fs $(abs_top_builddir)/daemons/dmeventd/dmeventd lib/dmeventd - ln -fs $(abs_top_builddir)/daemons/lvmetad/lvmetad lib/lvmetad - ln -fs $(abs_top_srcdir)/scripts/vgimportclone.sh lib/vgimportclone - ln -fs $(abs_top_srcdir)/scripts/fsadm.sh lib/fsadm - touch $@ - -clean: - test "$(srcdir)" = . || $(RM) $(RUN_BASE) - -CLEAN_TARGETS += .lib-dir-stamp .tests-stamp $(LIB) $(addprefix lib/,$(CMDS)) \ - lib/clvmd lib/dmeventd lib/dmsetup lib/lvmetad lib/fsadm lib/vgimportclone + $(SHOW) " [CP] $@" + $(Q) cp $< $@ + $(Q) $(CHMOD) +x $@ + +lib/%: $(top_srcdir)/scripts/%.sh .lib-dir-stamp + $(SHOW) " [CP] $@" + $(Q) cp $< $@ + $(Q) $(CHMOD) +x $@ + +lib/flavour-%: $(srcdir)/lib/flavour-%.sh .lib-dir-stamp + $(SHOW) " [FLAVOUR] $<" + $(Q) cp $< $@ + +lib/paths-common: $(srcdir)/Makefile.in Makefile .lib-dir-stamp + $(SHOW) " [PATHS] $@" + $(Q) echo 'DM_UDEV_SYNCHRONIZATION=$(dm_udev_synchronization)' >> $@-t + $(Q) echo 'LVMPOLLD_PIDFILE="@LVMPOLLD_PIDFILE@"' >> $@-t + $(Q) echo 'DMEVENTD_PIDFILE="@DMEVENTD_PIDFILE@"' >> $@-t + $(Q) echo 'LVM_TEST_THIN_CHECK_CMD=$${LVM_TEST_THIN_CHECK_CMD-@THIN_CHECK_CMD@}' >> $@-t + $(Q) echo 'LVM_TEST_THIN_DUMP_CMD=$${LVM_TEST_THIN_DUMP_CMD-@THIN_DUMP_CMD@}' >> $@-t + $(Q) echo 'LVM_TEST_THIN_REPAIR_CMD=$${LVM_TEST_THIN_REPAIR_CMD-@THIN_REPAIR_CMD@}' >> $@-t + $(Q) echo 'LVM_TEST_THIN_RESTORE_CMD=$${LVM_TEST_THIN_RESTORE_CMD-@THIN_RESTORE_CMD@}' >> $@-t + $(Q) echo 'LVM_TEST_CACHE_CHECK_CMD=$${LVM_TEST_CACHE_CHECK_CMD-@CACHE_CHECK_CMD@}' >> $@-t + $(Q) echo 'LVM_TEST_CACHE_DUMP_CMD=$${LVM_TEST_CACHE_DUMP_CMD-@CACHE_DUMP_CMD@}' >> $@-t + $(Q) echo 'LVM_TEST_CACHE_REPAIR_CMD=$${LVM_TEST_CACHE_REPAIR_CMD-@CACHE_REPAIR_CMD@}' >> $@-t + $(Q) echo 'LVM_TEST_CACHE_RESTORE_CMD=$${LVM_TEST_CACHE_RESTORE_CMD-@CACHE_RESTORE_CMD@}' >> $@-t + $(Q) echo 'export DM_UDEV_SYNCHRONIZATION THIN RAID CACHE\' >> $@-t + $(Q) echo ' LVM_TEST_THIN_CHECK_CMD LVM_TEST_THIN_DUMP_CMD LVM_TEST_THIN_REPAIR_CMD LVM_TEST_THIN_RESTORE_CMD\' >> $@-t + $(Q) echo ' LVM_TEST_CACHE_CHECK_CMD LVM_TEST_CACHE_DUMP_CMD LVM_TEST_CACHE_REPAIR_CMD LVM_TEST_CACHE_RESTORE_CMD' >> $@-t + $(Q) mv $@-t $@ + +lib/paths-installed: lib/paths-common + $(SHOW) " [PATHS] $@" + $(Q) $(RM) $@-t + $(Q) cat lib/paths-common > $@-t + $(Q) echo 'installed_testsuite=1' >> $@-t + $(Q) echo 'export PATH=@libexecdir@/lvm2-testsuite:@datadir@/lvm2-testsuite/lib:@datadir@/lvm2-testsuite/api:$$PATH' >> $@-t + $(Q) mv $@-t $@ + +lib/paths: lib/paths-common + $(SHOW) " [PATHS] $@" + $(Q) $(RM) $@-t + $(Q) cat lib/paths-common > $@-t + $(Q) echo 'top_srcdir="$(top_srcdir)"' >> $@-t + $(Q) echo 'abs_top_builddir="$(abs_top_builddir)"' >> $@-t + $(Q) echo 'abs_top_srcdir="$(abs_top_srcdir)"' >> $@-t + $(Q) echo 'abs_srcdir="$(abs_srcdir)"' >> $@-t + $(Q) echo 'abs_builddir="$(abs_builddir)"' >> $@-t + $(Q) mv $@-t $@ + +lib/version-expected: $(top_srcdir)/VERSION .lib-dir-stamp + $(Q) cut -f 1 -d ' ' <$< >$@ + +lib/dm-version-expected: $(top_srcdir)/VERSION_DM .lib-dir-stamp + $(Q) cut -f 1 -d ' ' <$< >$@ + +CMDS := lvm $(shell cat $(abs_top_builddir)/tools/.commands 2>/dev/null) +LIB := $(addprefix lib/, $(LVM_SCRIPTS) $(LIB_SHARED) $(LIB_LOCAL) $(LIB_EXEC) $(LIB_LINK_NOT) $(LIB_DATA)) + +.tests-stamp: .lib-dir-stamp $(LIB) $(SUBDIRS) + $(SHOW) " [TESTS-STAMP]" +ifneq (.,$(firstword $(srcdir))) + $(SHOW) " Linking tests to builddir." + $(Q) $(LN_S) -f $(srcdir)/shell +endif + $(Q) $(MKDIR_P) -m a=rwx $(LVM_TEST_RESULTS) + $(Q) touch $@ + +.lib-dir-stamp: unit/unit-test + $(SHOW) " [LIB-DIR-STAMP]" + $(Q) $(MKDIR_P) api lib unit + $(Q) $(RM) lib/clvmd + $(Q) $(LN_S) -f dmsetup lib/dmstats + $(Q) $(foreach FILE, $(CMDS), $(LN_S) -f lvm-wrapper lib/$(FILE) $(newline)) + $(Q) $(foreach FILE, $(LVM_TOOLS), $(LN_S) -f $(abs_top_builddir)/$(FILE) lib/ $(newline)) + $(Q) $(LN_S) -f $(addprefix $(abs_top_srcdir)/conf/, $(LVM_PROFILES)) lib/ +ifneq (.,$(firstword $(srcdir))) + $(Q) $(LN_S) -f $(addprefix $(abs_top_srcdir)/test/lib/,\ + $(LIB_LVMLOCKD_CONF) $(LIB_MKE2FS_CONF)) lib/ +endif + $(Q) touch $@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ diff --git a/test/api/Makefile.in b/test/api/Makefile.in deleted file mode 100644 index 7ad6743..0000000 --- a/test/api/Makefile.in +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright (C) 2009-2012 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@ - -TARGETS = -ifeq ("@APPLIB@", "yes") -TARGETS += test -SOURCES = test.c - -TARGETS += \ - lvtest.t \ - percent.t \ - pe_start.t \ - thin_percent.t \ - vgtest.t - -SOURCES2 = \ - lvtest.c \ - percent.c \ - pe_start.c \ - thin_percent.c \ - vgtest.c - -endif - -include $(top_builddir)/make.tmpl - -DEFS += -D_REENTRANT -DEPLIBS += $(top_builddir)/liblvm/liblvm2app.so $(top_builddir)/libdm/libdevmapper.so -LDFLAGS += -L$(top_builddir)/liblvm -LVMLIBS = @LVM2APP_LIB@ -ldevmapper - -ifeq ("@DMEVENTD@", "yes") - LVMLIBS += -ldevmapper-event - LDFLAGS += -L$(top_builddir)/daemons/dmeventd -endif - -LVMLIBS += $(LIBS) - -%.t: %.o $(DEPLIBS) - $(CC) -o $@ $(<) $(LDFLAGS) $(LVMLIBS) - -test: $(OBJECTS) $(DEPLIBS) - $(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(READLINE_LIBS) - -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) && $(SHELL) ./config.status test/api/Makefile diff --git a/test/api/dbustest.sh b/test/api/dbustest.sh new file mode 100644 index 0000000..d69c0e8 --- /dev/null +++ b/test/api/dbustest.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_CLVMD=1 + +. lib/inittest + +# Unsupported with valgrid testing +test "${LVM_VALGRIND:-0}" -eq 0 || skip "Unsupported with valgrind" + +# NOTE: Some tests, namely anything with vdo, and +# api/dbus_test_lv_interface_cache_lv.sh, require larger PVs +aux prepare_pvs 6 6400 + +# Required by test_nesting: +aux extend_filter_LVMTEST + +# We need the lvmdbusd.profile for the daemon to utilize JSON +# output +aux prepare_profiles "lvmdbusd" + +# Keep generating test file within test dir +export TMPDIR=$PWD +aux prepare_lvmdbusd + +# Example for testing individual test: +#"$TESTOLDPWD/dbus/lvmdbustest.py" -v TestDbusService.test_lv_interface_cache_lv +#"$TESTOLDPWD/dbus/lvmdbustest.py" -v TestDbusService.test_pv_symlinks + +"$TESTOLDPWD/dbus/lvmdbustest.py" -v diff --git a/test/api/lvtest.c b/test/api/lvtest.c deleted file mode 100644 index c0fee65..0000000 --- a/test/api/lvtest.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 - */ - -#undef NDEBUG - -#include "lvm2app.h" -#include "assert.h" - -#define err(args...) \ - do { fprintf(stderr, args); goto bad; } while (0) - -int main(int argc, char *argv[]) -{ - lvm_t handle; - vg_t vg; - lv_t lv; - int r = -1; - - if (!(handle = lvm_init(NULL))) - return -1; - - if (!(vg = lvm_vg_open(handle, argv[1], "w", 0))) - err("VG open %s failed.\n", argv[1]); - - if (!(lv = lvm_lv_from_name(vg, "test"))) - err("LV test not found.\n"); - - if (lvm_lv_deactivate(lv)) - err("LV test deactivation failed.\n"); - - if (lvm_lv_activate(lv)) - err("LV test activation failed.\n"); - - if (lvm_lv_activate(lv)) - err("LV test repeated activation failed.\n"); - - if (lvm_lv_rename(lv, "test1")) - err("LV test rename to test1 failed.\n"); - - if (lvm_lv_rename(lv, "test2")) - err("LV test1 rename to test2 failed.\n"); - - if (lvm_lv_rename(lv, "test")) - err("LV test2 rename to test failed.\n"); - - if (lvm_vg_close(vg)) - err("VG close failed.\n"); - - r = 0; -bad: - lvm_quit(handle); - return r; -} diff --git a/test/api/lvtest.sh b/test/api/lvtest.sh deleted file mode 100644 index 0b7684a..0000000 --- a/test/api/lvtest.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# Copyright (C) 2011 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 - -. lib/test - -aux prepare_vg 1 - -lvcreate -n test -l 5 $vg -aux apitest lvtest $vg - -check lv_field $vg/test lv_name test diff --git a/test/api/pe_start.c b/test/api/pe_start.c deleted file mode 100644 index 129f8a2..0000000 --- a/test/api/pe_start.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 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 - */ - -#undef NDEBUG - -#include "lvm2app.h" -#include "assert.h" - -int main(int argc, char *argv[]) -{ - lvm_t handle; - vg_t vg = NULL; - pv_t pv; - struct lvm_property_value v; - - handle = lvm_init(NULL); - assert(handle); - - vg = lvm_vg_create(handle, argv[1]); - assert(vg); - - if (lvm_vg_extend(vg, argv[2])) - abort(); - - pv = lvm_pv_from_name(vg, argv[2]); - assert(pv); - - v = lvm_pv_get_property(pv, "pe_start"); - assert(v.is_valid); - fprintf(stderr, "pe_start = %d\n", (int)v.value.integer); - assert(v.value.integer == 2048 * 512); - - lvm_vg_close(vg); - lvm_quit(handle); - return 0; -} diff --git a/test/api/pe_start.sh b/test/api/pe_start.sh deleted file mode 100644 index 20ba8ec..0000000 --- a/test/api/pe_start.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# Copyright (C) 2011 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 - -. lib/test - -aux prepare_devs 2 - -aux apitest pe_start test_vg $dev1 - -not vgs test_vg -not pvs $dev1 diff --git a/test/api/percent.c b/test/api/percent.c deleted file mode 100644 index c5fa434..0000000 --- a/test/api/percent.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 - */ - -#undef NDEBUG - -#include "lvm2app.h" -#include "assert.h" - -int main(int argc, char *argv[]) -{ - lvm_t handle; - vg_t vg = NULL; - lv_t lv; - struct lvm_property_value v; - struct lvm_property_value d; - - 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); - - d = lvm_lv_get_property(lv, "data_percent"); - assert(d.is_valid); - assert(d.value.integer == v.value.integer); - - lvm_vg_close(vg); - - lvm_quit(handle); - return 0; -} diff --git a/test/api/percent.sh b/test/api/percent.sh deleted file mode 100644 index 07b8bc6..0000000 --- a/test/api/percent.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -# 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 - -. lib/test - -kernel_at_least 2 6 33 || skip - -aux prepare_devs 2 - -vgcreate -c n -s 4k $vg $(cat DEVICES) -lvcreate -l 5 -n foo $vg -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 $vg -aux apitest percent $vg - -vgremove -ff $vg diff --git a/test/api/test.c b/test/api/test.c deleted file mode 100644 index b27aed1..0000000 --- a/test/api/test.c +++ /dev/null @@ -1,1107 +0,0 @@ -/* - * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2011 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 -#include -#include -#include - -#include "configure.h" -#include "lvm2app.h" - -#ifdef READLINE_SUPPORT -#include - -#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); - v = lvm_lvseg_get_property(lvl->lvseg, "devices"); - _print_property_value("devices", v); - v = lvm_lvseg_get_property(lvl->lvseg, "seg_pe_ranges"); - _print_property_value("seg_pe_ranges", 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; -} -#else /* !READLINE_SUPPORT */ -static int lvmapi_test_shell(lvm_t libh) -{ - printf("Build without readline library, no interactive testing.\n"); - return 1; -} -#endif - -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/thin_percent.c b/test/api/thin_percent.c deleted file mode 100644 index 2c8b19b..0000000 --- a/test/api/thin_percent.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2012 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 - */ - -#undef NDEBUG - -#include "lvm2app.h" -#include "assert.h" - -int main(int argc, char *argv[]) -{ - lvm_t handle; - vg_t vg; - 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, "pool"); - assert(lv); - - v = lvm_lv_get_property(lv, "data_percent"); - assert(v.is_valid); - assert(v.value.integer == 25 * PERCENT_1); - - - lv = lvm_lv_from_name(vg, "thin"); - assert(lv); - - v = lvm_lv_get_property(lv, "data_percent"); - assert(v.is_valid); - assert(v.value.integer == 50 * PERCENT_1); - - - lv = lvm_lv_from_name(vg, "snap"); - assert(lv); - - v = lvm_lv_get_property(lv, "data_percent"); - assert(v.is_valid); - assert(v.value.integer == 75 * PERCENT_1); - - v = lvm_lv_get_property(lv, "snap_percent"); - assert(v.is_valid); - assert(v.value.integer == PERCENT_INVALID); - - v = lvm_lv_get_property(lv, "origin"); - assert(v.is_valid); - assert(strcmp(v.value.string, "thin") == 0); - - lvm_vg_close(vg); - lvm_quit(handle); - - return 0; -} diff --git a/test/api/thin_percent.sh b/test/api/thin_percent.sh deleted file mode 100644 index 9287cf3..0000000 --- a/test/api/thin_percent.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test - -aux have_thin 1 0 0 || skip - -# disable thin_check if not present in system -which thin_check || aux lvmconf 'global/thin_check_executable = ""' - -aux prepare_devs 2 - -vgcreate -s 64k $vg $(cat DEVICES) - -lvcreate -L5M -T $vg/pool - -lvcreate -V1M -T $vg/pool -n thin -dd if=/dev/urandom of="$DM_DEV_DIR/$vg/thin" count=2 bs=256K - -lvcreate -s $vg/thin -n snap -dd if=/dev/urandom of="$DM_DEV_DIR/$vg/snap" count=3 bs=256K - -lvs $vg - -aux apitest thin_percent $vg - -vgremove -ff $vg diff --git a/test/api/vgtest.c b/test/api/vgtest.c deleted file mode 100644 index cb35da3..0000000 --- a/test/api/vgtest.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 -#include -#include - -#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 [... ]", - argv[0]); - return -1; - } - vg_name = argv[1]; - for(i=2; i 0: + if remaining: + to_send = len(q) + else: + to_send = random.randint(1, len(q)) + + for _ in range(0, to_send): + c = q.popleft() + if binary: + stream.write(bytes(c, "utf-8")) + else: + stream.write(c) + stream.flush() + + +def del_random_key(src_dict): + keys = list(src_dict.keys()) + pick = random.randint(0, len(keys) - 1) + debug("%s will be deleted" % keys[pick]) + del src_dict[keys[pick]] + + +def inject_key_error(output_json): + debug("Deleting a key") + for r in output_json['report']: + if 'lv' in r: + for i in r['lv']: + debug("deleting a lv key") + del_random_key(i) + return + if 'vg' in r: + for i in r["vg"]: + debug("deleting a vg key") + del_random_key(i) + return + elif 'pv' in r: + for i in r["pv"]: + debug("deleting a pv key") + del_random_key(i) + return + + +def inject_exit_error(output_json, val): + if 'log' in output_json and len(output_json['log']) > 0: + debug("Returning bad exit code") + # Change the exit code to failure + output_json['log'][-1:][0]['log_ret_code'] = "%d" % val + else: + # We are in fork & exec mode, just exit. + if val == 0: + sys.exit(1) + sys.exit(val) + + +def inject_error(output_str, output_json=None): + try: + if random.randint(0, 9) == 1: + error_case = random.randint(0, 3) + if error_case == 0: + debug("Truncating JSON") + # Create bad JSON by truncating it + str_rep = output_str[:-len(output_str) // 2] + rc = str_rep + else: + if output_json is None: + output_json = json.loads(output_str) + if error_case == 1: + inject_key_error(output_json) + elif error_case == 2: + debug("Returning bad exit code") + inject_exit_error(output_json, 0) + else: + debug("Returning exit code 5") + inject_exit_error(output_json, 5) + + rc = json.dumps(output_json) + "\n" + else: + rc = output_str + except Exception as e: + debug("Exception %s occurred: JSON = \n%s\n" % (str(e), output_str)) + sys.exit(100) + + return rc + + +def run_one(cmd): + debug("run_one(%s)" % str(cmd)) + result = subprocess.run(cmd, capture_output=True, text=True) + + if "fullreport" in cmd: + sys.stdout.write(inject_error(result.stdout)) + else: + sys.stdout.write(result.stdout) + sys.stdout.flush() + sys.stderr.write(result.stderr) + sys.stderr.flush() + return result.returncode + + +class LvmShellHandler: + + def __init__(self, cmd): + debug(os.environ) + + self.d_stdout = deque() + self.d_stderr = deque() + self.d_report = deque() + + tmp_dir = tempfile.mkdtemp(prefix="pipeinmiddle_") + self.tmp_file = "%s/middle_man_report" % tmp_dir + + # Let's create a fifo for the report output + os.mkfifo(self.tmp_file, 0o600) + + self.child_report_fd = os.open(self.tmp_file, os.O_NONBLOCK) + self.child_report_stream = os.fdopen(self.child_report_fd, 'rb', 0) + passed_report_fd = os.open(self.tmp_file, os.O_WRONLY) + + debug("passed_report_fd = %d" % passed_report_fd) + + # The report FD from who executed us. + self.daemon_report_fd = int(os.environ["LVM_REPORT_FD"]) + self.daemon_report_stream = os.fdopen(self.daemon_report_fd, "wb", 0) + + env = copy.deepcopy(os.environ) + env["LVM_REPORT_FD"] = "%s" % str(passed_report_fd) + env["LC_ALL"] = "C" + env["LVM_COMMAND_PROFILE"] = "lvmdbusd" + + self.parent_stdin_fd, child_stdin_fd = pty.openpty() + self.parent_stdout_fd, child_stdout_fd = pty.openpty() + self.parent_stderr_fd, child_stderr_fd = pty.openpty() + self.parent_stdin = os.fdopen(self.parent_stdin_fd, "w") + self.parent_stdout = os.fdopen(self.parent_stdout_fd, "r") + self.parent_stderr = os.fdopen(self.parent_stderr_fd, "r") + + debug("exec'ing %s" % cmd) + self.process = Popen(cmd, + stdin=child_stdin_fd, + stdout=child_stdout_fd, + stderr=child_stderr_fd, + close_fds=True, + env=env, + pass_fds=[passed_report_fd, ], + shell=False) + + os.close(passed_report_fd) + os.close(child_stdin_fd) + os.close(child_stdout_fd) + os.close(child_stderr_fd) + + make_non_block(self.parent_stdout_fd) + make_non_block(self.parent_stderr_fd) + make_non_block(sys.stdin) + + self.report_text_in_progress = "" + self.last_request = "" + + os.unlink(self.tmp_file) + os.rmdir(tmp_dir) + + def _complete_response(self): + try: + _complete_json = json.loads(self.report_text_in_progress) + return _complete_json + except ValueError: + return None + + def _write_all(self): + write_some(self.d_stderr, sys.stderr, remaining=True) + write_some(self.d_report, self.daemon_report_stream, remaining=True, binary=True) + write_some(self.d_stdout, sys.stdout, remaining=True) + + def _handle_report(self): + # Read from child report stream, write to parent report stream + report_text = read_decoded(self.child_report_stream) + self.report_text_in_progress += report_text + report_json = self._complete_response() + + # Always wait until we have a full response before we do anything with the output + if report_json is not None: + # Only add data to d_report after we have the entire JSON and have injected + # an error into it if we so wish, usually only for 'fullreport' + if "fullreport" in self.last_request: + self.d_report.extend(inject_error(self.report_text_in_progress, report_json)) + else: + debug("Not the cmd we are looking for ...") + self.d_report.extend(self.report_text_in_progress) + + self.report_text_in_progress = "" + + def _handle_command(self): + global run + stdin_text = sys.stdin.readline() + self.last_request = stdin_text + + debug("stdin: %s..." % stdin_text[:min(10, len(stdin_text) - 1)]) + + if "exit\n" in stdin_text: + debug("asking to exit ...") + run.value = 0 + + self.parent_stdin.writelines(stdin_text) + self.parent_stdin.flush() + + @staticmethod + def _empty_stream_to_queue(stream, queue): + read_text = stream.readlines() + for line in read_text: + queue.extend(line) + + def run(self): + global run + select_tmo = 0.2 + while run.value == 1: + try: + rd_fd = [sys.stdin.fileno(), self.parent_stdout_fd, self.parent_stderr_fd, self.child_report_fd] + ready = select.select(rd_fd, [], [], select_tmo) + + if len(ready[0]) == 0: + write_some(self.d_stderr, sys.stderr) + write_some(self.d_report, self.daemon_report_stream, binary=True) + + for r in ready[0]: + if r == self.parent_stdout_fd: + LvmShellHandler._empty_stream_to_queue(self.parent_stdout, self.d_stdout) + elif r == self.parent_stderr_fd: + LvmShellHandler._empty_stream_to_queue(self.parent_stderr, self.d_stderr) + elif r == self.child_report_fd: + self._handle_report() + elif r == sys.stdin.fileno(): + # Read from parent stdin write to child stdin, this is a command getting issued. + self._handle_command() + else: + debug("FD %d not handled!" % r) + sys.exit(10) + + # We have handled all the FDs that were ready, write some output + if len(self.d_stdout) > 0: + self._write_all() + else: + write_some(self.d_stderr, sys.stderr) + write_some(self.d_report, self.daemon_report_stream, binary=True) + + # Check to see if child process has terminated, None when running + if self.process.poll() is not None: + self._write_all() + debug("child process %s exited %d" % (cmd, self.process.returncode)) + break + except IOError as ioe: + debug("run_cmd:" + str(ioe)) + + if self.process.poll() is not None: + debug("exiting %d " % self.process.returncode) + else: + debug("lvm process still running, be we are exiting ...") + return self.process.returncode + + +if __name__ == "__main__": + try: + args = sys.argv[1:] + + exe = os.getenv("LVM_MAN_IN_MIDDLE", "/usr/sbin/lvm") + cmdline = [exe, ] + if args: + cmdline.extend(args) + ec = run_one(cmdline) + else: + if "LVM_REPORT_FD" in os.environ: + SH = LvmShellHandler(cmdline) + ec = SH.run() + else: + debug('running as lvm shell requires: LVM_REPORT_FD to be set') + ec = 1 + sys.exit(ec) + except Exception: + traceback.print_exc(file=d_out) + sys.exit(1) diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py new file mode 100755 index 0000000..475f328 --- /dev/null +++ b/test/dbus/lvmdbustest.py @@ -0,0 +1,2614 @@ +#!/usr/bin/python3 + +# Copyright (C) 2015-2016 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, see . +import os +import signal +# noinspection PyUnresolvedReferences +import subprocess +import unittest +import tempfile +from glob import glob +from subprocess import Popen, PIPE + +import dbus +import pyudev +# noinspection PyUnresolvedReferences +from dbus.mainloop.glib import DBusGMainLoop + +import testlib +from testlib import * + +g_tmo = 0 + +g_lvm_shell = False + +# Approx. min size +VDO_MIN_SIZE = mib(8192) + +VG_TEST_SUFFIX = "_vg_LvMdBuS_TEST" + +EXE_NAME = "/lvmdbusd" + +# Prefix on created objects to enable easier clean-up +g_prefix = os.getenv('PREFIX', '') + +# Check dev dir prefix for test suite (LVM_TEST_DEVDIR +dm_dev_dir = os.getenv('DM_DEV_DIR', '/dev') + +# Use the session bus instead of the system bus +use_session = os.getenv('LVM_DBUSD_USE_SESSION', False) + +# Only use the devices listed in the ENV variable +pv_device_list = os.getenv('LVM_DBUSD_PV_DEVICE_LIST', None) + +# Default is to test all modes +# 0 == Only test fork & exec mode +# 1 == Only test lvm shell mode +# 2 == Test both fork & exec & lvm shell mode (default) +# Other == Test just lvm shell mode +test_shell = os.getenv('LVM_DBUSD_TEST_MODE', 2) + +# LVM binary to use +LVM_EXECUTABLE = os.getenv('LVM_BINARY', '/usr/sbin/lvm') + +# Empty options dictionary (EOD) +EOD = dbus.Dictionary({}, signature=dbus.Signature('sv')) +# Base interfaces on LV objects +LV_BASE_INT = (LV_COMMON_INT, LV_INT) + +if use_session: + bus = dbus.SessionBus(mainloop=DBusGMainLoop()) +else: + bus = dbus.SystemBus(mainloop=DBusGMainLoop()) + +# If we have multiple clients we will globally disable introspection +# validation to limit the massive amount of introspection calls we make as +# that method prevents things from executing concurrently +if pv_device_list: + testlib.validate_introspection = False + + +def vg_n(prefix=None): + name = rs(8, VG_TEST_SUFFIX) + if prefix: + name = prefix + name + return g_prefix + name + + +def lv_n(suffix=None): + if not suffix: + s = '_lv' + else: + s = suffix + return rs(8, s) + + +def _is_testsuite_pv(pv_name): + return g_prefix != "" and pv_name[-1].isdigit() and \ + pv_name[:-1].endswith(g_prefix + "pv") + + +def is_nested_pv(pv_name): + return pv_name.count('/') == 3 and not _is_testsuite_pv(pv_name) + + +def _root_pv_name(res, pv_name): + if not is_nested_pv(pv_name): + return pv_name + vg_name = pv_name.split('/')[2] + for v in res[VG_INT]: + if v.Vg.Name == vg_name: + for pv in res[PV_INT]: + if pv.object_path in v.Vg.Pvs: + return _root_pv_name(res, pv.Pv.Name) + return None + + +def _prune_lvs(res, interface, vg_object_path): + lvs = [lv for lv in res[interface] if lv.LvCommon.Vg == vg_object_path] + res[interface] = lvs + + +def _prune(res, pv_filter): + if pv_filter: + pv_lookup = {} + + pv_list = [] + for p in res[PV_INT]: + if _root_pv_name(res, p.Pv.Name) in pv_filter: + pv_list.append(p) + pv_lookup[p.object_path] = p + + res[PV_INT] = pv_list + + vg_list = [] + for v in res[VG_INT]: + if v.Vg.Pvs[0] in pv_lookup: + vg_list.append(v) + + for interface in \ + [LV_INT, THINPOOL_INT, LV_COMMON_INT, + CACHE_POOL_INT, CACHE_LV_INT, VDOPOOL_INT]: + _prune_lvs(res, interface, v.object_path) + + res[VG_INT] = vg_list + + return res + + +def get_objects(): + rc = { + MANAGER_INT: [], PV_INT: [], VG_INT: [], LV_INT: [], + THINPOOL_INT: [], JOB_INT: [], SNAPSHOT_INT: [], LV_COMMON_INT: [], + CACHE_POOL_INT: [], CACHE_LV_INT: [], VG_VDO_INT: [], VDOPOOL_INT: []} + + object_manager_object = bus.get_object( + BUS_NAME, "/com/redhat/lvmdbus1", introspect=False) + + manager_interface = dbus.Interface( + object_manager_object, "org.freedesktop.DBus.ObjectManager") + + objects = manager_interface.GetManagedObjects() + + for object_path, v in objects.items(): + proxy = ClientProxy(bus, object_path, v) + for interface in v.keys(): + rc[interface].append(proxy) + + # At this point we have a full population of everything, we now need to + # prune the objects if we are filtering PVs with a sub selection. + return _prune(rc, pv_device_list), bus + + +def set_exec_mode(lvmshell): + lvm_manager = dbus.Interface(bus.get_object( + BUS_NAME, "/com/redhat/lvmdbus1/Manager", introspect=False), + "com.redhat.lvmdbus1.Manager") + return lvm_manager.UseLvmShell(lvmshell) + + +def set_execution(lvmshell, test_result): + global g_lvm_shell + if lvmshell: + m = 'lvm shell (non-fork)' + else: + m = "forking & exec'ing" + + rc = set_exec_mode(lvmshell) + + if rc: + g_lvm_shell = lvmshell + std_err_print('Successfully changed execution mode to "%s"' % m) + else: + std_err_print('ERROR: Failed to change execution mode to "%s"' % m) + test_result.register_fail() + return rc + + +def call_lvm(command): + """ + Call lvm executable and return a tuple of exitcode, stdout, stderr + :param command: Command to execute + :type command: list + :returns (exitcode, stdout, stderr) + :rtype (int, str, str) + """ + + # Prepend the full lvm executable so that we can run different versions + # in different locations on the same box + command.insert(0, LVM_EXECUTABLE) + + process = Popen( + command, stdout=PIPE, stderr=PIPE, close_fds=True, env=os.environ) + out = process.communicate() + + stdout_text = bytes(out[0]).decode("utf-8") + stderr_text = bytes(out[1]).decode("utf-8") + return process.returncode, stdout_text, stderr_text + + +def supports_vdo(): + cmd = ['segtypes'] + modprobe = Popen(["modprobe", "kvdo"], stdout=PIPE, stderr=PIPE, close_fds=True, env=os.environ) + modprobe.communicate() + if modprobe.returncode != 0: + return False + rc, out, err = call_lvm(cmd) + if rc != 0 or "vdo" not in out: + return False + return True + + +def process_exists(name): + # Walk the process table looking for executable 'name' + for p in [pid for pid in os.listdir('/proc') if pid.isdigit()]: + try: + cmdline_args = read_file_split_nuls("/proc/%s/cmdline" % p) + except OSError: + continue + for arg in cmdline_args: + if name in arg: + return int(p) + return None + + +def read_file_split_nuls(fn): + with open(fn, "rb") as fh: + return [p.decode("utf-8") for p in fh.read().split(b'\x00') if len(p) > 0] + + +def read_file_build_hash(fn): + rc = dict() + lines = read_file_split_nuls(fn) + for line in lines: + if line.count("=") == 1: + k, v = line.split("=") + rc[k] = v + return rc + + +def remove_lvm_debug(): + # If we are running the lvmdbusd daemon and collecting lvm debug data, check and + # clean-up after the tests. + tmpdir = tempfile.gettempdir() + fp = os.path.join(tmpdir, "lvmdbusd.lvm.debug.*.log") + for f in glob(fp): + os.unlink(f) + + +class DaemonInfo(object): + def __init__(self, pid): + # The daemon is running, we have a pid, lets see how it's being run. + # When running under systemd, fd 0 -> /dev/null, fd 1&2 -> socket + # when ran manually it may have output re-directed to a file etc. + # we need the following + # command line arguments + # cwd + # where the output is going (in case it's directed to a file) + # Which lvm binary is being used (check LVM_BINARY env. variable) + # PYTHONPATH + base = "/proc/%d" % pid + self.cwd = os.readlink("%s/cwd" % base) + self.cmdline = read_file_split_nuls("%s/cmdline" % (base))[1:] + self.env = read_file_build_hash("%s/environ" % base) + self.stdin = os.readlink("%s/fd/0" % base) + self.stdout = os.readlink("%s/fd/1" % base) + self.stderr = os.readlink("%s/fd/2" % base) + + if self.cwd == "/" and self.stdin == "/dev/null": + self.systemd = True + else: + self.systemd = False + + self.process = None + + @classmethod + def get(cls): + pid = process_exists(EXE_NAME) + if pid: + return cls(pid) + return None + + def start(self, expect_fail=False): + if self.systemd: + subprocess.run(["/usr/bin/systemctl", "start", "lvm2-lvmdbusd"], check=True) + else: + stdin_stream = None + stdout_stream = None + stderr_stream = None + try: + stdout_stream = open(self.stdout, "ab") + stdin_stream = open(self.stdin, "rb") + stderr_stream = open(self.stderr, "ab") + + self.process = Popen(self.cmdline, cwd=self.cwd, stdin=stdin_stream, + stdout=stdout_stream, stderr=stderr_stream, env=self.env) + + if expect_fail: + # Let's wait a bit to see if this process dies as expected and return the exit code + try: + self.process.wait(10) + return self.process.returncode + except subprocess.TimeoutExpired as e: + # Process did not fail as expected, lets kill it + os.kill(self.process.pid, signal.SIGKILL) + self.process.wait(20) + raise e + else: + # This is a hack to set the returncode. When the Popen object goes out of scope during the unit test + # the __del__ method gets called. As we leave the daemon running the process.returncode + # hasn't been set, so it incorrectly raises an exception that the process is still running + # which in our case is correct and expected. + self.process.returncode = 0 + finally: + # Close these in the parent + if stdin_stream: + stdin_stream.close() + if stderr_stream: + stderr_stream.close() + if stdout_stream: + stdout_stream.close() + + # Make sure daemon is responding to dbus events before returning + DaemonInfo._ensure_daemon("Daemon is not responding on dbus within 20 seconds of starting!") + + # During local testing it usually takes ~0.25 seconds for daemon to be ready + return None + + @staticmethod + def _ensure_no_daemon(): + start = time.time() + pid = process_exists(EXE_NAME) + while pid is not None and (time.time() - start) <= 20: + time.sleep(0.3) + pid = process_exists(EXE_NAME) + + if pid: + raise Exception( + "lsmd daemon did not exit within 20 seconds, pid = %s" % pid) + + @staticmethod + def _ensure_daemon(msg): + start = time.time() + running = False + while True and (time.time() - start) < 20: + try: + get_objects() + running = True + break + except dbus.exceptions.DBusException: + time.sleep(0.2) + pass + if not running: + raise RuntimeError(msg) + + def term_signal(self, sig_number): + # Used for signals that we expect with terminate the daemon, eg. SIGINT, SIGKILL + if self.process: + os.kill(self.process.pid, sig_number) + # Note: The following should work, but doesn't! + # self.process.send_signal(sig_number) + try: + self.process.wait(10) + except subprocess.TimeoutExpired: + std_err_print("Daemon hasn't exited within 10 seconds") + if self.process.poll() is None: + std_err_print("Daemon still running...") + else: + self.process = None + else: + pid = process_exists(EXE_NAME) + os.kill(pid, sig_number) + + # Make sure there is no daemon present before we return for things to be "good" + DaemonInfo._ensure_no_daemon() + + def non_term_signal(self, sig_number): + if sig_number not in [signal.SIGUSR1, signal.SIGUSR2]: + raise ValueError("Incorrect signal number! %d" % sig_number) + if self.process: + os.kill(self.process.pid, sig_number) + else: + pid = process_exists(EXE_NAME) + os.kill(pid, sig_number) + + +# noinspection PyUnresolvedReferences +class TestDbusService(unittest.TestCase): + def setUp(self): + self.pvs = [] + + # Because of the sensitive nature of running LVM tests we will only + # run if we have PVs and nothing else, so that we can be confident that + # we are not mucking with someone's data on their system + self.objs, self.bus = get_objects() + if len(self.objs[PV_INT]) == 0: + std_err_print('No PVs present exiting!') + sys.exit(1) + + for p in self.objs[PV_INT]: + self.pvs.append(p.Pv.Name) + + if len(self.objs[MANAGER_INT]) != 1: + std_err_print('Expecting a manager object!') + sys.exit(1) + + if len(self.objs[VG_INT]) != 0: + std_err_print('Expecting no VGs to exist!') + sys.exit(1) + + self.addCleanup(self.clean_up) + + self.vdo = supports_vdo() + remove_lvm_debug() + + def _recurse_vg_delete(self, vg_proxy, pv_proxy, nested_pv_hash): + vg_name = str(vg_proxy.Vg.Name) + + if not vg_name.endswith(VG_TEST_SUFFIX): + std_err_print("Refusing to remove VG: %s" % vg_name) + return + + for pv_device_name, t in nested_pv_hash.items(): + if vg_name in pv_device_name: + self._recurse_vg_delete(t[0], t[1], nested_pv_hash) + break + + vg_proxy.update() + + self.handle_return(vg_proxy.Vg.Remove(dbus.Int32(g_tmo), EOD)) + if is_nested_pv(pv_proxy.Pv.Name): + rc = self._pv_remove(pv_proxy) + self.assertTrue(rc == '/', "We expected a '/', but got %s when removing a PV" % str(rc)) + + def clean_up(self): + self.objs, self.bus = get_objects() + + # The self.objs[PV_INT] list only contains those which we should be + # mucking with, lets remove any embedded/nested PVs first, then proceed + # to walk the base PVs and remove the VGs + nested_pvs = {} + non_nested = [] + + for p in self.objs[PV_INT]: + if is_nested_pv(p.Pv.Name): + if p.Pv.Vg != '/': + v = ClientProxy(self.bus, p.Pv.Vg, interfaces=(VG_INT,)) + nested_pvs[p.Pv.Name] = (v, p) + else: + # Nested PV with no VG, so just simply remove it! + self._pv_remove(p) + else: + non_nested.append(p) + + for p in non_nested: + # When we remove a VG for a PV it could ripple across multiple + # PVs, so update each PV while removing each VG, to ensure + # the properties are current and correct. + p.update() + if p.Pv.Vg != '/': + v = ClientProxy(self.bus, p.Pv.Vg, interfaces=(VG_INT,)) + self._recurse_vg_delete(v, p, nested_pvs) + + # Check to make sure the PVs we had to start exist, else re-create + # them + self.objs, self.bus = get_objects() + if len(self.pvs) != len(self.objs[PV_INT]): + for p in self.pvs: + found = False + for pc in self.objs[PV_INT]: + if pc.Pv.Name == p: + found = True + break + + if not found: + # print('Re-creating PV=', p) + self._pv_create(p) + + remove_lvm_debug() + + def _check_consistency(self): + # Only do consistency checks if we aren't running the unit tests + # concurrently + if pv_device_list is None: + self.assertEqual(self._refresh(), 0) + + def handle_return(self, rc): + if isinstance(rc, (tuple, list)): + # We have a tuple returned + if rc[0] != '/': + return rc[0] + else: + return self._wait_for_job(rc[1]) + else: + if rc == '/': + return rc + else: + return self._wait_for_job(rc) + + def _pv_create(self, device): + + pv_path = self.handle_return( + self.objs[MANAGER_INT][0].Manager.PvCreate( + dbus.String(device), dbus.Int32(g_tmo), EOD) + ) + + self._validate_lookup(device, pv_path) + + self.assertTrue(pv_path is not None and len(pv_path) > 0, + "When creating a PV we expected the returned path to be valid") + return pv_path + + def _manager(self): + return self.objs[MANAGER_INT][0] + + def _refresh(self): + return self._manager().Manager.Refresh() + + def test_refresh(self): + self._check_consistency() + + def test_version(self): + rc = self.objs[MANAGER_INT][0].Manager.Version + self.assertTrue(rc is not None and len(rc) > 0, "Manager.Version is invalid") + self._check_consistency() + + def _vg_create(self, pv_paths=None, vg_prefix=None, options=None): + + if not pv_paths: + pv_paths = self._all_pv_object_paths() + + if options is None: + options = EOD + + vg_name = vg_n(prefix=vg_prefix) + + vg_path = self.handle_return( + self.objs[MANAGER_INT][0].Manager.VgCreate( + dbus.String(vg_name), + dbus.Array(pv_paths, signature=dbus.Signature('o')), + dbus.Int32(g_tmo), + options)) + + self._validate_lookup(vg_name, vg_path) + self.assertTrue(vg_path is not None and len(vg_path) > 0, "During VG creation, returned path is empty") + + intf = [VG_INT, ] + if self.vdo: + intf.append(VG_VDO_INT) + + return ClientProxy(self.bus, vg_path, interfaces=intf) + + def test_vg_create(self): + self._vg_create() + self._check_consistency() + + def test_vg_delete(self): + vg = self._vg_create().Vg + + self.handle_return( + vg.Remove(dbus.Int32(g_tmo), EOD)) + self._check_consistency() + + def _pv_remove(self, pv): + rc = self.handle_return( + pv.Pv.Remove(dbus.Int32(g_tmo), EOD)) + return rc + + def test_pv_remove_add(self): + target = self.objs[PV_INT][0] + + # Remove the PV + rc = self._pv_remove(target) + self.assertTrue(rc == '/') + self._check_consistency() + + # Add it back + rc = self._pv_create(target.Pv.Name)[0] + self.assertTrue(rc == '/') + self._check_consistency() + + def _create_raid5_thin_pool(self, vg=None): + + meta_name = "meta_r5" + data_name = "data_r5" + + if not vg: + vg = self._vg_create(self._all_pv_object_paths()).Vg + + lv_meta_path = self.handle_return( + vg.LvCreateRaid( + dbus.String(meta_name), + dbus.String("raid5"), + dbus.UInt64(mib(4)), + dbus.UInt32(0), + dbus.UInt32(0), + dbus.Int32(g_tmo), + EOD) + ) + self._validate_lookup("%s/%s" % (vg.Name, meta_name), lv_meta_path) + + lv_data_path = self.handle_return( + vg.LvCreateRaid( + dbus.String(data_name), + dbus.String("raid5"), + dbus.UInt64(mib(16)), + dbus.UInt32(0), + dbus.UInt32(0), + dbus.Int32(g_tmo), + EOD) + ) + + self._validate_lookup("%s/%s" % (vg.Name, data_name), lv_data_path) + + thin_pool_path = self.handle_return( + vg.CreateThinPool( + dbus.ObjectPath(lv_meta_path), + dbus.ObjectPath(lv_data_path), + dbus.Int32(g_tmo), EOD) + ) + + # Get thin pool client proxy + intf = (LV_COMMON_INT, LV_INT, THINPOOL_INT) + thin_pool = ClientProxy(self.bus, thin_pool_path, interfaces=intf) + + return vg, thin_pool + + def test_meta_lv_data_lv_props(self): + # Ensure that metadata lv and data lv for thin pools and cache pools + # point to a valid LV + (vg, thin_pool) = self._create_raid5_thin_pool() + + # Check properties on thin pool + self.assertTrue(thin_pool.ThinPool.DataLv != '/') + self.assertTrue(thin_pool.ThinPool.MetaDataLv != '/') + + (vg, cache_pool) = self._create_cache_pool(vg) + + self.assertTrue(cache_pool.CachePool.DataLv != '/') + self.assertTrue(cache_pool.CachePool.MetaDataLv != '/') + + # Cache the thin pool + cached_thin_pool_path = self.handle_return( + cache_pool.CachePool.CacheLv( + dbus.ObjectPath(thin_pool.object_path), + dbus.Int32(g_tmo), EOD) + ) + + # Get object proxy for cached thin pool + intf = (LV_COMMON_INT, LV_INT, THINPOOL_INT) + cached_thin_pool_object = ClientProxy( + self.bus, cached_thin_pool_path, interfaces=intf) + + # Check properties on cache pool + self.assertTrue(cached_thin_pool_object.ThinPool.DataLv != '/') + self.assertTrue(cached_thin_pool_object.ThinPool.MetaDataLv != '/') + + def _lookup(self, lvm_id): + return self.objs[MANAGER_INT][0].\ + Manager.LookUpByLvmId(dbus.String(lvm_id)) + + def _validate_lookup(self, lvm_name, object_path): + t = self._lookup(lvm_name) + self.assertTrue( + object_path == t, "%s != %s for %s" % (object_path, t, lvm_name)) + + def test_lookup_by_lvm_id(self): + # For the moment lets just lookup what we know about which is PVs + # When we start testing VGs and LVs we will test lookups for those + # during those unit tests + for p in self.objs[PV_INT]: + rc = self._lookup(p.Pv.Name) + self.assertTrue(rc is not None and rc != '/') + + # Search for something which doesn't exist + rc = self._lookup('/dev/null') + self.assertTrue(rc == '/') + + def test_vg_extend(self): + # Create a VG + self.assertTrue(len(self.objs[PV_INT]) >= 2) + + if len(self.objs[PV_INT]) >= 2: + pv_initial = self.objs[PV_INT][0] + pv_next = self.objs[PV_INT][1] + + vg = self._vg_create([pv_initial.object_path]).Vg + + path = self.handle_return( + vg.Extend( + dbus.Array([pv_next.object_path], signature="o"), + dbus.Int32(g_tmo), EOD) + ) + self.assertTrue(path == '/') + self._check_consistency() + + # noinspection PyUnresolvedReferences + def test_vg_reduce(self): + self.assertTrue(len(self.objs[PV_INT]) >= 2) + + if len(self.objs[PV_INT]) >= 2: + vg = self._vg_create( + [self.objs[PV_INT][0].object_path, + self.objs[PV_INT][1].object_path]).Vg + + path = self.handle_return( + vg.Reduce( + dbus.Boolean(False), dbus.Array([vg.Pvs[0]], signature='o'), + dbus.Int32(g_tmo), EOD) + ) + self.assertTrue(path == '/') + self._check_consistency() + + def _verify_lv_paths(self, vg, new_name): + """ + # Go through each LV and make sure it has the correct path back to the + # VG + :return: + """ + lv_paths = vg.Lvs + + for l in lv_paths: + lv_proxy = ClientProxy( + self.bus, l, interfaces=(LV_COMMON_INT,)).LvCommon + self.assertTrue( + lv_proxy.Vg == vg.object_path, "%s != %s" % + (lv_proxy.Vg, vg.object_path)) + full_name = "%s/%s" % (new_name, lv_proxy.Name) + lv_path = self._lookup(full_name) + self.assertTrue( + lv_path == lv_proxy.object_path, "%s != %s" % + (lv_path, lv_proxy.object_path)) + + # noinspection PyUnresolvedReferences + def test_vg_rename(self): + vg = self._vg_create().Vg + + # Do a vg lookup + path = self._lookup(vg.Name) + + vg_name_start = vg.Name + + prev_path = path + self.assertTrue(path != '/', "%s" % (path)) + + # Create some LVs in the VG + for i in range(0, 5): + lv_t = self._create_lv(size=mib(4), vg=vg) + full_name = "%s/%s" % (vg_name_start, lv_t.LvCommon.Name) + lv_path = self._lookup(full_name) + self.assertTrue(lv_path == lv_t.object_path) + + new_name = 'renamed_' + vg.Name + + path = self.handle_return( + vg.Rename(dbus.String(new_name), dbus.Int32(g_tmo), EOD)) + self.assertTrue(path == '/') + self._check_consistency() + + # Do a vg lookup + path = self._lookup(new_name) + self.assertTrue(path != '/', "%s" % (path)) + self.assertTrue(prev_path == path, "%s != %s" % (prev_path, path)) + + # Go through each LV and make sure it has the correct path back to the + # VG + vg.update() + + self.assertTrue(len(vg.Lvs) == 5) + self._verify_lv_paths(vg, new_name) + + def _verify_hidden_lookups(self, lv_common_object, vgname): + hidden_lv_paths = lv_common_object.HiddenLvs + + for h in hidden_lv_paths: + h_lv = ClientProxy( + self.bus, h, interfaces=(LV_COMMON_INT,)).LvCommon + + if len(h_lv.HiddenLvs) > 0: + self._verify_hidden_lookups(h_lv, vgname) + + full_name = "%s/%s" % (vgname, h_lv.Name) + # print("Hidden check %s" % (full_name)) + lookup_path = self._lookup(full_name) + self.assertTrue(lookup_path != '/') + self.assertTrue(lookup_path == h_lv.object_path) + + # Lets's strip off the '[ ]' and make sure we can find + full_name = "%s/%s" % (vgname, h_lv.Name[1:-1]) + # print("Hidden check %s" % (full_name)) + + lookup_path = self._lookup(full_name) + self.assertTrue(lookup_path != '/') + self.assertTrue(lookup_path == h_lv.object_path) + + def test_vg_rename_with_thin_pool(self): + + (vg, thin_pool) = self._create_raid5_thin_pool() + + vg_name_start = vg.Name + + # noinspection PyTypeChecker + self._verify_hidden_lookups(thin_pool.LvCommon, vg_name_start) + + for i in range(0, 5): + lv_name = lv_n() + + thin_lv_path = self.handle_return( + thin_pool.ThinPool.LvCreate( + dbus.String(lv_name), + dbus.UInt64(mib(16)), + dbus.Int32(g_tmo), + EOD)) + + self._validate_lookup( + "%s/%s" % (vg_name_start, lv_name), thin_lv_path) + + self.assertTrue(thin_lv_path != '/') + + full_name = "%s/%s" % (vg_name_start, lv_name) + + lookup_lv_path = self._lookup(full_name) + self.assertTrue( + thin_lv_path == lookup_lv_path, + "%s != %s" % (thin_lv_path, lookup_lv_path)) + + # Rename the VG + new_name = 'renamed_' + vg.Name + path = self.handle_return( + vg.Rename(dbus.String(new_name), dbus.Int32(g_tmo), EOD)) + + self.assertTrue(path == '/') + self._check_consistency() + + vg.update() + thin_pool.update() + self._verify_lv_paths(vg, new_name) + # noinspection PyTypeChecker + self._verify_hidden_lookups(thin_pool.LvCommon, new_name) + + def _test_lv_create(self, method, params, vg, proxy_interfaces=None): + lv = None + + path = self.handle_return(method(*params)) + self.assertTrue(vg) + + if path: + lv = ClientProxy(self.bus, path, interfaces=proxy_interfaces) + + # We are quick enough now that we can get VolumeType changes from + # 'I' to 'i' between the time it takes to create a RAID and it returns + # and when we refresh state here. Not sure how we can handle this as + # we cannot just sit and poll all the time for changes... + # self._check_consistency() + return lv + + def test_lv_create(self): + lv_name = lv_n() + vg = self._vg_create().Vg + lv = self._test_lv_create( + vg.LvCreate, + (dbus.String(lv_name), dbus.UInt64(mib(4)), + dbus.Array([], signature='(ott)'), dbus.Int32(g_tmo), + EOD), vg, LV_BASE_INT) + self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path) + + def test_prop_get(self): + lv_name = lv_n() + vg = self._vg_create().Vg + lv = self._test_lv_create( + vg.LvCreate, + (dbus.String(lv_name), dbus.UInt64(mib(4)), + dbus.Array([], signature='(ott)'), dbus.Int32(g_tmo), + EOD), vg, LV_BASE_INT) + ri = RemoteInterface(lv.dbus_object, interface=LV_COMMON_INT, introspect=False) + + ri.update() + for prop_name in ri.get_property_names(): + self.assertEqual(ri.get_property_value(prop_name), getattr(ri, prop_name)) + + def test_lv_create_job(self): + lv_name = lv_n() + vg = self._vg_create().Vg + (object_path, job_path) = vg.LvCreate( + dbus.String(lv_name), dbus.UInt64(mib(4)), + dbus.Array([], signature='(ott)'), dbus.Int32(0), + EOD) + + self.assertTrue(object_path == '/') + self.assertTrue(job_path != '/') + object_path = self._wait_for_job(job_path) + + self._validate_lookup("%s/%s" % (vg.Name, lv_name), object_path) + self.assertTrue(object_path != '/') + + def test_lv_create_linear(self): + + lv_name = lv_n() + vg = self._vg_create().Vg + lv = self._test_lv_create( + vg.LvCreateLinear, + (dbus.String(lv_name), dbus.UInt64(mib(4)), dbus.Boolean(False), + dbus.Int32(g_tmo), EOD), vg, LV_BASE_INT) + self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path) + + def _all_pv_object_paths(self): + return [pp.object_path for pp in self.objs[PV_INT]] + + def test_lv_create_striped(self): + lv_name = lv_n() + vg = self._vg_create(self._all_pv_object_paths()).Vg + lv = self._test_lv_create( + vg.LvCreateStriped, + (dbus.String(lv_name), dbus.UInt64(mib(4)), + dbus.UInt32(2), dbus.UInt32(8), dbus.Boolean(False), + dbus.Int32(g_tmo), EOD), vg, LV_BASE_INT) + self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path) + + def test_lv_create_mirror(self): + lv_name = lv_n() + vg = self._vg_create(self._all_pv_object_paths()).Vg + lv = self._test_lv_create( + vg.LvCreateMirror, + (dbus.String(lv_name), dbus.UInt64(mib(4)), dbus.UInt32(2), + dbus.Int32(g_tmo), EOD), vg, LV_BASE_INT) + self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path) + + def test_lv_create_raid(self): + lv_name = lv_n() + vg = self._vg_create(self._all_pv_object_paths()).Vg + lv = self._test_lv_create( + vg.LvCreateRaid, + (dbus.String(lv_name), dbus.String('raid5'), dbus.UInt64(mib(16)), + dbus.UInt32(2), dbus.UInt32(8), dbus.Int32(g_tmo), EOD), + vg, LV_BASE_INT) + self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path) + + def _create_lv(self, thinpool=False, size=None, vg=None, suffix=None): + + lv_name = lv_n(suffix=suffix) + interfaces = list(LV_BASE_INT) + + if thinpool: + interfaces.append(THINPOOL_INT) + + if not vg: + vg = self._vg_create(self._all_pv_object_paths()).Vg + + if size is None: + size = mib(8) + + lv = self._test_lv_create( + vg.LvCreateLinear, + (dbus.String(lv_name), dbus.UInt64(size), + dbus.Boolean(thinpool), dbus.Int32(g_tmo), EOD), + vg, interfaces) + + self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path) + return lv + + def _create_thin_pool_lv(self): + return self._create_lv(True) + + def test_lv_create_rounding(self): + self._create_lv(size=(mib(2) + 13)) + + def test_lv_create_thin_pool(self): + self._create_thin_pool_lv() + + def _rename_lv_test(self, lv): + path = self._lookup(lv.LvCommon.Name) + prev_path = path + + new_name = 'renamed_' + lv.LvCommon.Name + + self.handle_return( + lv.Lv.Rename(dbus.String(new_name), dbus.Int32(g_tmo), EOD)) + + path = self._lookup(new_name) + + self._check_consistency() + self.assertTrue(prev_path == path, "%s != %s" % (prev_path, path)) + + lv.update() + self.assertTrue( + lv.LvCommon.Name == new_name, + "%s != %s" % (lv.LvCommon.Name, new_name)) + + def test_lv_rename(self): + # Rename a regular LV + lv = self._create_lv() + self._rename_lv_test(lv) + + def test_lv_thinpool_rename(self): + # Rename a thin pool + tp = self._create_lv(True) + self.assertTrue( + THINPOOL_LV_PATH in tp.object_path, + "%s" % (tp.object_path)) + + new_name = 'renamed_' + tp.LvCommon.Name + self.handle_return(tp.Lv.Rename( + dbus.String(new_name), dbus.Int32(g_tmo), EOD)) + tp.update() + self._check_consistency() + self.assertEqual(new_name, tp.LvCommon.Name) + + def _create_thin_lv(self): + vg = self._vg_create().Vg + tp = self._create_lv(thinpool=True, vg=vg) + + lv_name = lv_n('_thin_lv') + + thin_path = self.handle_return( + tp.ThinPool.LvCreate( + dbus.String(lv_name), + dbus.UInt64(mib(10)), + dbus.Int32(g_tmo), + EOD) + ) + self._validate_lookup("%s/%s" % (vg.Name, lv_name), thin_path) + + lv = ClientProxy( + self.bus, thin_path, interfaces=(LV_COMMON_INT, LV_INT)) + return vg, thin_path, lv + + # noinspection PyUnresolvedReferences + def test_lv_on_thin_pool_rename(self): + # Rename a LV on a thin Pool + vg, thin_path, lv = self._create_thin_lv() + re_named = 'rename_test' + lv.LvCommon.Name + rc = self.handle_return( + lv.Lv.Rename( + dbus.String(re_named), + dbus.Int32(g_tmo), + EOD) + ) + + self._validate_lookup("%s/%s" % (vg.Name, re_named), thin_path) + self.assertTrue(rc == '/') + self._check_consistency() + + def _lv_remove(self, lv): + rc = self.handle_return( + lv.Lv.Remove( + dbus.Int32(g_tmo), + EOD)) + self.assertTrue(rc == '/') + self._check_consistency() + + def test_lv_remove(self): + lv = self._create_lv() + self._lv_remove(lv) + + def _take_lv_snapshot(self, lv_p): + ss_name = 'ss_' + lv_p.LvCommon.Name + + ss_obj_path = self.handle_return(lv_p.Lv.Snapshot( + dbus.String(ss_name), + dbus.UInt64(0), + dbus.Int32(g_tmo), + EOD)) + + self.assertTrue(ss_obj_path != '/') + return ClientProxy( + self.bus, ss_obj_path, interfaces=(LV_COMMON_INT, LV_INT)) + + def test_lv_snapshot(self): + lv_p = self._create_lv() + self._take_lv_snapshot(lv_p) + + # noinspection PyUnresolvedReferences,PyUnusedLocal + def _wait_for_job(self, j_path): + rc = None + j = ClientProxy(self.bus, j_path, interfaces=(JOB_INT, )).Job + + while True: + j.update() + if j.Complete: + (ec, error_msg) = j.GetError + self.assertTrue(ec == 0, "%d :%s" % (ec, error_msg)) + + if ec == 0: + self.assertTrue(j.Percent == 100, "P= %f" % j.Percent) + + rc = j.Result + j.Remove() + + break + + if j.Wait(1): + self.assertTrue(j.Wait(0)) + j.update() + self.assertTrue(j.Complete) + + return rc + + def test_lv_create_pv_specific(self): + vg = self._vg_create().Vg + lv_name = lv_n() + pv = vg.Pvs + pvp = ClientProxy(self.bus, pv[0], interfaces=(PV_INT,)) + + lv = self._test_lv_create( + vg.LvCreate, ( + dbus.String(lv_name), + dbus.UInt64(mib(4)), + dbus.Array( + [[pvp.object_path, 0, (pvp.Pv.PeCount - 1)]], + signature='(ott)'), + dbus.Int32(g_tmo), EOD), vg, LV_BASE_INT) + self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path) + + def _test_lv_resize(self, lv): + # Can't resize cache or thin pool volumes or vdo pool lv + if lv.LvCommon.Attr[0] == 'C' or lv.LvCommon.Attr[0] == 't' or \ + lv.LvCommon.Attr[0] == 'd': + return + + vg = ClientProxy(self.bus, lv.LvCommon.Vg, interfaces=(VG_INT,)).Vg + + start_size = lv.LvCommon.SizeBytes + + # Vdo are fairly big and need large re-size amounts. + if start_size > mib(4) * 3: + delta = mib(4) + else: + delta = 16384 + + for size in [start_size + delta, start_size - delta]: + + pv_in_use = [i[0] for i in lv.LvCommon.Devices] + # Select a PV in the VG that isn't in use + pv_empty = [p for p in vg.Pvs if p not in pv_in_use] + + prev = lv.LvCommon.SizeBytes + + if len(pv_empty): + p = ClientProxy(self.bus, pv_empty[0], interfaces=(PV_INT,)) + + rc = self.handle_return( + lv.Lv.Resize( + dbus.UInt64(size), + dbus.Array( + [[p.object_path, 0, p.Pv.PeCount - 1]], '(oii)'), + dbus.Int32(g_tmo), EOD)) + else: + rc = self.handle_return( + lv.Lv.Resize( + dbus.UInt64(size), + dbus.Array([], '(oii)'), + dbus.Int32(g_tmo), EOD)) + + self.assertEqual(rc, '/') + self._check_consistency() + + lv.update() + + if prev < size: + self.assertTrue(lv.LvCommon.SizeBytes > prev) + else: + # We are testing re-sizing to same size too... + self.assertTrue(lv.LvCommon.SizeBytes <= prev) + + def test_lv_resize(self): + + pv_paths = [ + self.objs[PV_INT][0].object_path, self.objs[PV_INT][1].object_path] + + vg = self._vg_create(pv_paths).Vg + lv = self._create_lv(vg=vg, size=mib(16)) + + self._test_lv_resize(lv) + + def test_lv_resize_same(self): + vg = self._vg_create(self._all_pv_object_paths()).Vg + lv = self._create_lv(vg=vg) + + with self.assertRaises(dbus.exceptions.DBusException): + lv.Lv.Resize( + dbus.UInt64(lv.LvCommon.SizeBytes), + dbus.Array([], '(oii)'), + dbus.Int32(-1), EOD) + + def test_lv_move(self): + lv = self._create_lv() + + pv_path_move = str(lv.LvCommon.Devices[0][0]) + + # Test moving a specific LV + rc = self.handle_return( + lv.Lv.Move( + dbus.ObjectPath(pv_path_move), + dbus.Struct((0, 0), signature='(tt)'), + dbus.Array([], '(ott)'), dbus.Int32(g_tmo), + EOD)) + self.assertTrue(rc == '/') + self._check_consistency() + + lv.update() + new_pv = str(lv.LvCommon.Devices[0][0]) + self.assertTrue( + pv_path_move != new_pv, "%s == %s" % (pv_path_move, new_pv)) + + def _test_activate_deactivate(self, lv_p): + self.handle_return(lv_p.Lv.Deactivate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) + lv_p.update() + self.assertFalse(lv_p.LvCommon.Active) + self._check_consistency() + + self.handle_return(lv_p.Lv.Activate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) + + lv_p.update() + self.assertTrue(lv_p.LvCommon.Active) + + # Vdo property "IndexState" when getting activated goes from + # "opening" -> "online" after we have returned from the activate call + # thus when we try to check the consistency we fail as the property + # is changing on it's own and not because the lvmdbusd failed to + # refresh it's own state. One solution is to not expose IndexState as + # a property. + # TODO Expose method to determine if Lv is partaking in VDO. + vg = ClientProxy(self.bus, lv_p.LvCommon.Vg, interfaces=(VG_INT,)) + if "vdo" not in vg.Vg.Name: + self._check_consistency() + + # Try control flags + for i in range(0, 6): + + self.handle_return(lv_p.Lv.Activate( + dbus.UInt64(1 << i), + dbus.Int32(g_tmo), + EOD)) + + self.assertTrue(lv_p.LvCommon.Active) + self._check_consistency() + + def test_lv_activate_deactivate(self): + lv_p = self._create_lv() + self._test_activate_deactivate(lv_p) + + def test_move(self): + lv = self._create_lv() + + # Test moving without being LV specific + vg = ClientProxy(self.bus, lv.LvCommon.Vg, interfaces=(VG_INT, )).Vg + pv_to_move = str(lv.LvCommon.Devices[0][0]) + + rc = self.handle_return( + vg.Move( + dbus.ObjectPath(pv_to_move), + dbus.Struct((0, 0), signature='tt'), + dbus.Array([], '(ott)'), + dbus.Int32(0), + EOD)) + self.assertEqual(rc, '/') + self._check_consistency() + + vg.update() + lv.update() + + location = lv.LvCommon.Devices[0][0] + + dst = None + for p in vg.Pvs: + if p != location: + dst = p + + # Fetch the destination + pv = ClientProxy(self.bus, dst, interfaces=(PV_INT, )).Pv + + # Test range, move it to the middle of the new destination + job = self.handle_return( + vg.Move( + dbus.ObjectPath(location), + dbus.Struct((0, 0), signature='tt'), + dbus.Array([(dst, pv.PeCount // 2, 0), ], '(ott)'), + dbus.Int32(g_tmo), + EOD)) + self.assertEqual(job, '/') + self._check_consistency() + + def test_job_handling(self): + pv_paths = self._all_pv_object_paths() + vg_name = vg_n() + + # Test getting a job right away + vg_path, vg_job = self.objs[MANAGER_INT][0].Manager.VgCreate( + dbus.String(vg_name), + dbus.Array(pv_paths, 'o'), + dbus.Int32(0), + EOD) + + self.assertTrue(vg_path == '/') + self.assertTrue(vg_job and len(vg_job) > 0) + + vg_path = self._wait_for_job(vg_job) + self._validate_lookup(vg_name, vg_path) + + def _create_num_lvs(self, num_lvs, no_wait=False): + vg_proxy = self._vg_create(self._all_pv_object_paths()) + if no_wait: + tmo = 0 + else: + tmo = g_tmo + + for i in range(0, num_lvs): + lv_name = lv_n() + vg_proxy.update() + if vg_proxy.Vg.FreeCount > 0: + create_result = vg_proxy.Vg.LvCreateLinear( + dbus.String(lv_name), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(tmo), + EOD) + + if not no_wait: + lv_path = self.handle_return(create_result) + self.assertTrue(lv_path != '/') + self._validate_lookup("%s/%s" % (vg_proxy.Vg.Name, lv_name), lv_path) + else: + # We ran out of space, test(s) may fail + break + return vg_proxy + + def _test_expired_timer(self, num_lvs): + rc = False + + # In small configurations lvm is pretty snappy, so let's create a VG + # add a number of LVs and then remove the VG and all the contained + # LVs which appears to consistently run a little slow. + + vg_proxy = self._create_num_lvs(num_lvs) + + # Make sure that we are honoring the timeout + start = time.time() + + remove_job = vg_proxy.Vg.Remove(dbus.Int32(1), EOD) + + end = time.time() + + tt_remove = float(end) - float(start) + + self.assertTrue(tt_remove < 2.0, "remove time %s" % (str(tt_remove))) + + # Depending on how long it took we could finish either way + if remove_job != '/': + # We got a job + result = self._wait_for_job(remove_job) + self.assertTrue(result == '/') + rc = True + else: + # It completed before timer popped + pass + + return rc + + # noinspection PyUnusedLocal + def test_job_handling_timer(self): + + yes = False + + for pp in self.objs[PV_INT]: + if '/dev/sd' not in pp.Pv.Name: + std_err_print("Skipping test_job_handling_timer on loopback") + return + + # This may not pass + for i in [128, 256]: + yes = self._test_expired_timer(i) + if yes: + break + std_err_print('Attempt (%d) failed, trying again...' % (i)) + + self.assertTrue(yes) + + def test_pv_tags(self): + pvs = [] + vg = self._vg_create(self._all_pv_object_paths()).Vg + + # Get the PVs + for p in vg.Pvs: + pvs.append(ClientProxy(self.bus, p, interfaces=(PV_INT, )).Pv) + + for tags_value in [['hello'], ['foo', 'bar']]: + + rc = self.handle_return( + vg.PvTagsAdd( + dbus.Array(vg.Pvs, 'o'), + dbus.Array(tags_value, 's'), + dbus.Int32(g_tmo), + EOD)) + self.assertTrue(rc == '/') + + for p in pvs: + p.update() + self.assertTrue(sorted(tags_value) == p.Tags) + + rc = self.handle_return( + vg.PvTagsDel( + dbus.Array(vg.Pvs, 'o'), + dbus.Array(tags_value, 's'), + dbus.Int32(g_tmo), + EOD)) + self.assertEqual(rc, '/') + + for p in pvs: + p.update() + self.assertTrue([] == p.Tags) + + def test_vg_tags(self): + vg = self._vg_create().Vg + + t = ['Testing', 'tags'] + + self.handle_return( + vg.TagsAdd( + dbus.Array(t, 's'), + dbus.Int32(g_tmo), + EOD)) + + vg.update() + self.assertTrue(t == vg.Tags) + + self.handle_return( + vg.TagsDel( + dbus.Array(t, 's'), + dbus.Int32(g_tmo), + EOD)) + vg.update() + self.assertTrue([] == vg.Tags) + + def _test_lv_tags(self, lv): + t = ['Testing', 'tags'] + + self.handle_return( + lv.Lv.TagsAdd( + dbus.Array(t, 's'), dbus.Int32(g_tmo), EOD)) + self._check_consistency() + lv.update() + self.assertTrue(t == lv.LvCommon.Tags) + + self.handle_return( + lv.Lv.TagsDel( + dbus.Array(t, 's'), + dbus.Int32(g_tmo), + EOD)) + self._check_consistency() + lv.update() + self.assertTrue([] == lv.LvCommon.Tags) + + def test_lv_tags(self): + vg = self._vg_create().Vg + lv = self._create_lv(vg=vg) + self._test_lv_tags(lv) + + def test_vg_allocation_policy_set(self): + vg = self._vg_create().Vg + + for p in ['anywhere', 'contiguous', 'cling', 'normal']: + rc = self.handle_return( + vg.AllocationPolicySet( + dbus.String(p), dbus.Int32(g_tmo), EOD)) + + self.assertEqual(rc, '/') + vg.update() + + prop = getattr(vg, 'Alloc' + p.title()) + self.assertTrue(prop) + + def test_vg_max_pv(self): + vg = self._vg_create([self.objs[PV_INT][0].object_path]).Vg + for p in [0, 1, 10, 100, 100, 1024, 2 ** 32 - 1]: + rc = self.handle_return( + vg.MaxPvSet( + dbus.UInt64(p), dbus.Int32(g_tmo), EOD)) + self.assertEqual(rc, '/') + vg.update() + self.assertTrue( + vg.MaxPv == p, + "Expected %s != Actual %s" % (str(p), str(vg.MaxPv))) + + def test_vg_max_lv(self): + vg = self._vg_create().Vg + for p in [0, 1, 10, 100, 100, 1024, 2 ** 32 - 1]: + rc = self.handle_return( + vg.MaxLvSet( + dbus.UInt64(p), dbus.Int32(g_tmo), EOD)) + self.assertEqual(rc, '/') + vg.update() + self.assertTrue( + vg.MaxLv == p, + "Expected %s != Actual %s" % (str(p), str(vg.MaxLv))) + + def test_vg_uuid_gen(self): + vg = self._vg_create().Vg + prev_uuid = vg.Uuid + rc = self.handle_return( + vg.UuidGenerate( + dbus.Int32(g_tmo), + EOD)) + self.assertEqual(rc, '/') + vg.update() + self.assertTrue( + vg.Uuid != prev_uuid, + "Expected %s != Actual %s" % (vg.Uuid, prev_uuid)) + + def test_vg_activate_deactivate(self): + vg = self._vg_create().Vg + self._create_lv(vg=vg) + vg.update() + + rc = self.handle_return( + vg.Deactivate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) + self.assertEqual(rc, '/') + self._check_consistency() + + rc = self.handle_return( + vg.Activate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) + + self.assertEqual(rc, '/') + self._check_consistency() + + # Try control flags + for i in range(0, 5): + self.handle_return( + vg.Activate( + dbus.UInt64(1 << i), + dbus.Int32(g_tmo), + EOD)) + + def test_pv_resize(self): + + self.assertTrue(len(self.objs[PV_INT]) > 0) + + if len(self.objs[PV_INT]) > 0: + pv = ClientProxy( + self.bus, self.objs[PV_INT][0].object_path, + interfaces=(PV_INT, )).Pv + + original_size = pv.SizeBytes + + new_size = original_size // 2 + + self.handle_return( + pv.ReSize( + dbus.UInt64(new_size), + dbus.Int32(g_tmo), + EOD)) + + self._check_consistency() + pv.update() + + self.assertTrue(pv.SizeBytes != original_size) + self.handle_return( + pv.ReSize( + dbus.UInt64(0), + dbus.Int32(g_tmo), + EOD)) + self._check_consistency() + pv.update() + self.assertTrue(pv.SizeBytes == original_size) + + def test_pv_allocation(self): + vg = self._vg_create(self._all_pv_object_paths()).Vg + + pv = ClientProxy(self.bus, vg.Pvs[0], interfaces=(PV_INT, )).Pv + + self.handle_return( + pv.AllocationEnabled( + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) + + pv.update() + self.assertFalse(pv.Allocatable) + + self.handle_return( + pv.AllocationEnabled( + dbus.Boolean(True), + dbus.Int32(g_tmo), + EOD)) + + self.handle_return( + pv.AllocationEnabled( + dbus.Boolean(True), + dbus.Int32(g_tmo), + EOD)) + pv.update() + self.assertTrue(pv.Allocatable) + + self._check_consistency() + + @staticmethod + def _get_devices(): + context = pyudev.Context() + bd = context.list_devices(subsystem='block') + # Handle block extended major too (259) + return [b for b in bd if b.properties.get('MAJOR') == '8' or + b.properties.get('MAJOR') == '259'] + + def _pv_scan(self, activate, cache, device_paths, major_minors): + mgr = self._manager().Manager + return self.handle_return( + mgr.PvScan( + dbus.Boolean(activate), + dbus.Boolean(cache), + dbus.Array(device_paths, 's'), + dbus.Array(major_minors, '(ii)'), + dbus.Int32(g_tmo), + EOD)) + + def test_pv_scan(self): + + def major_minor(d): + return (int(d.properties.get('MAJOR')), int(d.properties.get('MINOR'))) + + devices = TestDbusService._get_devices() + + self.assertEqual(self._pv_scan(False, True, [], []), '/') + self._check_consistency() + self.assertEqual(self._pv_scan(False, False, [], []), '/') + self._check_consistency() + + block_path = [d.properties.get('DEVNAME') for d in devices] + self.assertEqual(self._pv_scan(False, True, block_path, []), '/') + self._check_consistency() + + mm = [major_minor(d) for d in devices] + + self.assertEqual(self._pv_scan(False, True, block_path, mm), '/') + self._check_consistency() + + self.assertEqual(self._pv_scan(False, True, [], mm), '/') + self._check_consistency() + + @staticmethod + def _write_some_data(device_path, size): + blocks = int(size // 512) + block = bytearray(512) + for i in range(0, 512): + block[i] = i % 255 + + with open(device_path, mode='wb') as lv: + for i in range(0, blocks): + lv.write(block) + + def test_snapshot_merge(self): + # Create a non-thin LV and merge it + ss_size = mib(8) + + lv_p = self._create_lv(size=mib(16)) + ss_name = lv_p.LvCommon.Name + '_snap' + + snapshot_path = self.handle_return( + lv_p.Lv.Snapshot( + dbus.String(ss_name), + dbus.UInt64(ss_size), + dbus.Int32(g_tmo), + EOD)) + + intf = (LV_COMMON_INT, LV_INT, SNAPSHOT_INT, ) + ss = ClientProxy(self.bus, snapshot_path, interfaces=intf) + + # Write some data to snapshot so merge takes some time + TestDbusService._write_some_data(ss.LvCommon.Path, ss_size // 2) + + job_path = self.handle_return( + ss.Snapshot.Merge( + dbus.Int32(g_tmo), + EOD)) + self.assertEqual(job_path, '/') + + def test_snapshot_merge_thin(self): + # Create a thin LV, snapshot it and merge it + _vg, _thin_path, lv_p = self._create_thin_lv() + + ss_name = lv_p.LvCommon.Name + '_snap' + snapshot_path = self.handle_return( + lv_p.Lv.Snapshot( + dbus.String(ss_name), + dbus.UInt64(0), + dbus.Int32(g_tmo), + EOD)) + + intf = (LV_INT, LV_COMMON_INT, SNAPSHOT_INT) + ss = ClientProxy(self.bus, snapshot_path, interfaces=intf) + + job_path = self.handle_return( + ss.Snapshot.Merge( + dbus.Int32(g_tmo), EOD) + ) + self.assertTrue(job_path == '/') + + def _create_cache_pool(self, vg=None): + + if not vg: + vg = self._vg_create().Vg + + md = self._create_lv(size=(mib(8)), vg=vg) + data = self._create_lv(size=(mib(8)), vg=vg) + + cache_pool_path = self.handle_return( + vg.CreateCachePool( + dbus.ObjectPath(md.object_path), + dbus.ObjectPath(data.object_path), + dbus.Int32(g_tmo), + EOD)) + + intf = (CACHE_POOL_INT, ) + cp = ClientProxy(self.bus, cache_pool_path, interfaces=intf) + + return vg, cp + + def test_cache_pool_create(self): + + vg, cache_pool = self._create_cache_pool() + + self.assertTrue( + '/com/redhat/lvmdbus1/CachePool' in cache_pool.object_path) + + def _create_cache_lv(self, return_all=False): + vg, cache_pool = self._create_cache_pool() + + lv_to_cache = self._create_lv(size=mib(32), vg=vg) + + c_lv_path = self.handle_return( + cache_pool.CachePool.CacheLv( + dbus.ObjectPath(lv_to_cache.object_path), + dbus.Int32(g_tmo), + EOD)) + + intf = (LV_COMMON_INT, LV_INT, CACHE_LV_INT) + cached_lv = ClientProxy(self.bus, c_lv_path, interfaces=intf) + + if return_all: + return vg, cache_pool, cached_lv + return cached_lv + + def test_cache_lv_create(self): + + for destroy_cache in [True, False]: + vg, _, cached_lv = self._create_cache_lv(True) + uncached_lv_path = self.handle_return( + cached_lv.CachedLv.DetachCachePool( + dbus.Boolean(destroy_cache), + dbus.Int32(g_tmo), + EOD)) + + self.assertTrue( + '/com/redhat/lvmdbus1/Lv' in uncached_lv_path) + + rc = self.handle_return( + vg.Remove(dbus.Int32(g_tmo), EOD)) + self.assertTrue(rc == '/') + + def test_cache_lv_rename(self): + """ + Make sure that if we rename a cache lv that we correctly handle the + internal state update. + :return: + """ + def verify_cache_lv_count(): + cur_objs, _ = get_objects() + self.assertEqual(len(cur_objs[CACHE_LV_INT]), 2) + self._check_consistency() + + cached_lv = self._create_cache_lv() + + verify_cache_lv_count() + new_name = 'renamed_' + cached_lv.LvCommon.Name + self.handle_return( + cached_lv.Lv.Rename(dbus.String(new_name), dbus.Int32(g_tmo), EOD)) + verify_cache_lv_count() + + def test_writecache_lv(self): + vg = self._vg_create().Vg + data_lv = self._create_lv(size=mib(16), vg=vg) + cache_lv = self._create_lv(size=mib(16), vg=vg) + + # both LVs need to be inactive + self.handle_return(data_lv.Lv.Deactivate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) + data_lv.update() + self.handle_return(cache_lv.Lv.Deactivate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) + cache_lv.update() + + cached_lv_path = self.handle_return( + cache_lv.Lv.WriteCacheLv( + dbus.ObjectPath(data_lv.object_path), + dbus.Int32(g_tmo), + EOD)) + + intf = (LV_COMMON_INT, LV_INT, CACHE_LV_INT) + cached_lv = ClientProxy(self.bus, cached_lv_path, interfaces=intf) + self.assertEqual(cached_lv.LvCommon.SegType, ["writecache"]) + + uncached_lv_path = self.handle_return( + cached_lv.CachedLv.DetachCachePool( + dbus.Boolean(True), + dbus.Int32(g_tmo), + EOD)) + self.assertTrue('/com/redhat/lvmdbus1/Lv' in uncached_lv_path) + + def test_vg_change(self): + vg_proxy = self._vg_create() + + result = self.handle_return(vg_proxy.Vg.Change( + dbus.Int32(g_tmo), + dbus.Dictionary({'-a': 'ay'}, 'sv'))) + self.assertTrue(result == '/') + + result = self.handle_return( + vg_proxy.Vg.Change( + dbus.Int32(g_tmo), + dbus.Dictionary({'-a': 'n'}, 'sv'))) + self.assertTrue(result == '/') + + @staticmethod + def _invalid_vg_lv_name_characters(): + bad_vg_lv_set = set(string.printable) - \ + set(string.ascii_letters + string.digits + '.-_+') + return ''.join(bad_vg_lv_set) + + def test_invalid_names(self): + mgr = self.objs[MANAGER_INT][0].Manager + + # Pv device path + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + mgr.PvCreate( + dbus.String("/dev/space in name"), + dbus.Int32(g_tmo), + EOD)) + + # VG Name testing... + # Go through all bad characters + pv_paths = [self.objs[PV_INT][0].object_path] + bad_chars = TestDbusService._invalid_vg_lv_name_characters() + for c in bad_chars: + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + mgr.VgCreate( + dbus.String("name%s" % (c)), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) + + # Bad names + for bad in [".", ".."]: + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + mgr.VgCreate( + dbus.String(bad), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) + + # Exceed name length + for i in [128, 1024, 4096]: + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + mgr.VgCreate( + dbus.String('T' * i), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) + + # Create a VG and try to create LVs with different bad names + vg_name = vg_n() + vg_path = self.handle_return( + mgr.VgCreate( + dbus.String(vg_name), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) + self._validate_lookup(vg_name, vg_path) + + vg_proxy = ClientProxy(self.bus, vg_path, interfaces=(VG_INT, )) + + for c in bad_chars: + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + vg_proxy.Vg.LvCreateLinear( + dbus.String(lv_n() + c), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) + + for reserved in ( + "_cdata", "_cmeta", "_corig", "_mimage", "_mlog", + "_pmspare", "_rimage", "_rmeta", "_tdata", "_tmeta", + "_vorigin", "_vdata"): + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + vg_proxy.Vg.LvCreateLinear( + dbus.String(lv_n() + reserved), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) + + for reserved in ("snapshot", "pvmove"): + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + vg_proxy.Vg.LvCreateLinear( + dbus.String(reserved + lv_n()), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) + + _ALLOWABLE_TAG_CH = string.ascii_letters + string.digits + "._-+/=!:&#" + + def _invalid_tag_characters(self): + bad_tag_ch_set = set(string.printable) - set(self._ALLOWABLE_TAG_CH) + return ''.join(bad_tag_ch_set) + + def test_invalid_tags(self): + vg_proxy = self._vg_create() + + for c in self._invalid_tag_characters(): + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + vg_proxy.Vg.TagsAdd( + dbus.Array([c], 's'), + dbus.Int32(g_tmo), + EOD)) + + for c in self._invalid_tag_characters(): + with self.assertRaises(dbus.exceptions.DBusException): + self.handle_return( + vg_proxy.Vg.TagsAdd( + dbus.Array(["a%sb" % (c)], 's'), + dbus.Int32(g_tmo), + EOD)) + + def _tag_add_common(self, vg_proxy, tag): + tmp = self.handle_return( + vg_proxy.Vg.TagsAdd( + dbus.Array([tag], 's'), + dbus.Int32(g_tmo), + EOD)) + self.assertTrue(tmp == '/') + vg_proxy.update() + + self.assertTrue( + tag in vg_proxy.Vg.Tags, + "%s not in %s" % (tag, str(vg_proxy.Vg.Tags))) + + def test_tag_names(self): + vg_proxy = self._vg_create() + + for i in range(1, 64): + tag = rs(i, "", self._ALLOWABLE_TAG_CH) + self._tag_add_common(vg_proxy, tag) + + self.assertEqual( + i, len(vg_proxy.Vg.Tags), + "%d != %d" % (i, len(vg_proxy.Vg.Tags))) + + def test_tag_regression(self): + vg_proxy = self._vg_create() + tag = '--h/K.6g0A4FOEatf3+k_nI/Yp&L_u2oy-=j649x:+dUcYWPEo6.IWT0c' + self._tag_add_common(vg_proxy, tag) + + def _verify_existence(self, cmd, operation, resource_name): + ec, stdout, stderr = call_lvm(cmd) + if ec == 0: + path = self._lookup(resource_name) + self.assertTrue(path != '/') + else: + std_err_print( + "%s failed with stdout= %s, stderr= %s" % + (operation, stdout, stderr)) + self.assertTrue(ec == 0, "%s exit code = %d" % (operation, ec)) + + def test_external_vg_create(self): + # We need to ensure that if a user creates something outside lvm + # dbus service that things are sequenced correctly so that if a dbus + # user calls into the service they will find the same information. + vg_name = vg_n() + + # Get all the PV device paths + pv_device_paths = [p.Pv.Name for p in self.objs[PV_INT]] + + cmd = ['vgcreate', vg_name] + cmd.extend(pv_device_paths) + self._verify_existence(cmd, cmd[0], vg_name) + + def test_external_lv_create(self): + # Let's create a LV outside of service and see if we correctly handle + # its inclusion + vg = self._vg_create().Vg + lv_name = lv_n() + full_name = "%s/%s" % (vg.Name, lv_name) + + cmd = ['lvcreate', '-L4M', '-n', lv_name, vg.Name] + self._verify_existence(cmd, cmd[0], full_name) + + def test_external_pv_create(self): + # Let's create a PV outside of service and see if we correctly handle + # its inclusion + target = self.objs[PV_INT][0] + + # Remove the PV + rc = self._pv_remove(target) + self.assertTrue(rc == '/') + self._check_consistency() + + # Make sure the PV we removed no longer exists + self.assertTrue(self._lookup(target.Pv.Name) == '/') + + # Add it back with external command line + cmd = ['pvcreate', target.Pv.Name] + self._verify_existence(cmd, cmd[0], target.Pv.Name) + + def _create_nested(self, pv_object_path, vg_suffix): + vg = self._vg_create([pv_object_path], vg_suffix) + pv = ClientProxy(self.bus, pv_object_path, interfaces=(PV_INT,)) + + self.assertEqual(pv.Pv.Vg, vg.object_path) + self.assertIn( + pv_object_path, vg.Vg.Pvs, "Expecting PV object path in Vg.Pvs") + + lv = self._create_lv( + vg=vg.Vg, size=vg.Vg.FreeBytes, suffix="_pv0") + device_path = '/dev/%s/%s' % (vg.Vg.Name, lv.LvCommon.Name) + dev_info = os.stat(device_path) + major = os.major(dev_info.st_rdev) + minor = os.minor(dev_info.st_rdev) + sysfs = "/sys/dev/block/%d:%d" % (major, minor) + self.assertTrue(os.path.exists(sysfs)) + new_pv_object_path = self._pv_create(device_path) + vg.update() + + self.assertEqual(lv.LvCommon.Vg, vg.object_path) + self.assertIn( + lv.object_path, vg.Vg.Lvs, "Expecting LV object path in Vg.Lvs") + + new_pv_proxy = ClientProxy( + self.bus, new_pv_object_path, interfaces=(PV_INT, )) + self.assertEqual(new_pv_proxy.Pv.Name, device_path) + + return new_pv_object_path + + @staticmethod + def _scan_lvs_enabled(): + cmd = ['lvmconfig', '--typeconfig', 'full', 'devices/scan_lvs'] + config = Popen(cmd, stdout=PIPE, stderr=PIPE, close_fds=True, env=os.environ) + out = config.communicate() + if config.returncode != 0: + return False + if "scan_lvs=1" == out[0].decode("utf-8").strip(): + return True + return False + + def test_nesting(self): + # check to see if we handle an LV becoming a PV which has it's own + # LV + # + # NOTE: This needs an equivalent of aux extend_filter_LVMTEST + # when run from lvm2 testsuite. See dbustest.sh. + # Also, if developing locally with actual devices one can achieve this + # by editing lvm.conf with "devices/scan_lvs = 1" As testing + # typically utilizes loopback, this test is skipped in + # those environments. + + if dm_dev_dir != '/dev': + raise unittest.SkipTest('test not running in real /dev') + if not TestDbusService._scan_lvs_enabled(): + raise unittest.SkipTest('scan_lvs=0 in config, unit test requires scan_lvs=1') + pv_object_path = self.objs[PV_INT][0].object_path + if not self.objs[PV_INT][0].Pv.Name.startswith("/dev"): + raise unittest.SkipTest('test not running in /dev') + + for i in range(0, 5): + pv_object_path = self._create_nested(pv_object_path, "nest_%d_" % i) + + def test_pv_symlinks(self): + # Let's take one of our test PVs, pvremove it, find a symlink to it + # and re-create using the symlink to ensure we return an object + # path to it. Additionally, we will take the symlink and do a lookup + # (Manager.LookUpByLvmId) using it and the original device path to + # ensure that we can find the PV. + symlink = None + + pv = self.objs[PV_INT][0] + pv_device_path = pv.Pv.Name + + if dm_dev_dir != '/dev': + raise unittest.SkipTest('test not running in real /dev') + + if not pv_device_path.startswith("/dev"): + raise unittest.SkipTest('test not running in /dev') + + self._pv_remove(pv) + + # Make sure we no longer find the pv + rc = self._lookup(pv_device_path) + self.assertEqual(rc, '/') + + # Let's locate a symlink for it + devices = glob('/dev/disk/*/*') + rp_pv_device_path = os.path.realpath(pv_device_path) + for d in devices: + if rp_pv_device_path == os.path.realpath(d): + symlink = d + break + + self.assertIsNotNone(symlink, "We expected to find at least 1 symlink!") + + # Make sure symlink look up fails too + rc = self._lookup(symlink) + self.assertEqual(rc, '/') + + ### pv_object_path = self._pv_create(symlink) + ### Test is limited by filter rules and must use /dev/mapper/LVMTEST path + pv_object_path = self._pv_create(pv_device_path) + + self.assertNotEqual(pv_object_path, '/') + + pv_proxy = ClientProxy(self.bus, pv_object_path, interfaces=(PV_INT, )) + self.assertEqual(pv_proxy.Pv.Name, pv_device_path) + + # Lets check symlink lookup + self.assertEqual(pv_object_path, self._lookup(pv_device_path)) + + def _create_vdo_pool_and_lv(self, vg_prefix="vdo_"): + pool_name = lv_n("_vdo_pool") + lv_name = lv_n() + + vg_proxy = self._vg_create(vg_prefix=vg_prefix) + vdo_pool_object_path = self.handle_return( + vg_proxy.VgVdo.CreateVdoPoolandLv( + pool_name, lv_name, + dbus.UInt64(VDO_MIN_SIZE), + dbus.UInt64(VDO_MIN_SIZE * 2), + dbus.Int32(g_tmo), + EOD)) + + self.assertNotEqual(vdo_pool_object_path, "/") + self.assertEqual( + vdo_pool_object_path, + self._lookup("%s/%s" % (vg_proxy.Vg.Name, pool_name))) + + vdo_pool_path = self._lookup("%s/%s" % (vg_proxy.Vg.Name, pool_name)) + self.assertNotEqual(vdo_pool_path, "/") + intf = [LV_COMMON_INT, LV_INT] + vdo_lv_obj_path = self._lookup("%s/%s" % (vg_proxy.Vg.Name, lv_name)) + vdo_lv = ClientProxy(self.bus, vdo_lv_obj_path, interfaces=intf) + intf.append(VDOPOOL_INT) + vdo_pool_lv = ClientProxy(self.bus, vdo_pool_path, interfaces=intf) + return vg_proxy, vdo_pool_lv, vdo_lv + + def _create_vdo_lv(self): + return self._create_vdo_pool_and_lv()[2] + + def _vdo_pool_lv(self): + return self._create_vdo_pool_and_lv()[1] + + def test_vdo_pool_create(self): + # Basic vdo sanity testing + if not self.vdo: + raise unittest.SkipTest('vdo not supported') + + # Do this twice to ensure we are providing the correct flags to force + # the operation when it finds an existing vdo signature, which likely + # shouldn't exist. + for _ in range(0, 2): + vg, _, _ = self._create_vdo_pool_and_lv() + self.handle_return(vg.Vg.Remove(dbus.Int32(g_tmo), EOD)) + + def _create_vdo_pool(self): + pool_name = lv_n('_vdo_pool') + lv_name = lv_n('_vdo_data') + vg_proxy = self._vg_create(vg_prefix="vdo_conv_") + lv = self._test_lv_create( + vg_proxy.Vg.LvCreate, + (dbus.String(pool_name), dbus.UInt64(VDO_MIN_SIZE), + dbus.Array([], signature='(ott)'), dbus.Int32(g_tmo), + EOD), vg_proxy.Vg, LV_BASE_INT) + lv_obj_path = self._lookup("%s/%s" % (vg_proxy.Vg.Name, pool_name)) + self.assertNotEqual(lv_obj_path, "/") + + vdo_pool_path = self.handle_return( + vg_proxy.VgVdo.CreateVdoPool( + dbus.ObjectPath(lv.object_path), lv_name, + dbus.UInt64(VDO_MIN_SIZE), + dbus.Int32(g_tmo), + EOD)) + + self.assertNotEqual(vdo_pool_path, "/") + self.assertEqual( + vdo_pool_path, + self._lookup("%s/%s" % (vg_proxy.Vg.Name, pool_name))) + intf = [LV_COMMON_INT, LV_INT] + vdo_lv_obj_path = self._lookup("%s/%s" % (vg_proxy.Vg.Name, lv_name)) + vdo_lv = ClientProxy(self.bus, vdo_lv_obj_path, interfaces=intf) + intf.append(VDOPOOL_INT) + vdo_pool_lv = ClientProxy(self.bus, vdo_pool_path, interfaces=intf) + return vg_proxy, vdo_pool_lv, vdo_lv + + def test_vdo_pool_convert(self): + # Basic vdo sanity testing + if not self.vdo: + raise unittest.SkipTest('vdo not supported') + + vg, _pool, _lv = self._create_vdo_pool() + self.handle_return(vg.Vg.Remove(dbus.Int32(g_tmo), EOD)) + + def test_vdo_pool_compression_deduplication(self): + if not self.vdo: + raise unittest.SkipTest('vdo not supported') + + vg, pool, _lv = self._create_vdo_pool_and_lv(vg_prefix="vdo2_") + + # compression and deduplication should be enabled by default + self.assertEqual(pool.VdoPool.Compression, "enabled") + self.assertEqual(pool.VdoPool.Deduplication, "enabled") + + self.handle_return( + pool.VdoPool.DisableCompression(dbus.Int32(g_tmo), EOD)) + self.handle_return( + pool.VdoPool.DisableDeduplication(dbus.Int32(g_tmo), EOD)) + pool.update() + self.assertEqual(pool.VdoPool.Compression, "") + self.assertEqual(pool.VdoPool.Deduplication, "") + + self.handle_return( + pool.VdoPool.EnableCompression(dbus.Int32(g_tmo), EOD)) + self.handle_return( + pool.VdoPool.EnableDeduplication(dbus.Int32(g_tmo), EOD)) + pool.update() + self.assertEqual(pool.VdoPool.Compression, "enabled") + self.assertEqual(pool.VdoPool.Deduplication, "enabled") + + self.handle_return(vg.Vg.Remove(dbus.Int32(g_tmo), EOD)) + + def _test_lv_method_interface(self, lv): + self._rename_lv_test(lv) + self._test_activate_deactivate(lv) + self._test_lv_tags(lv) + self._test_lv_resize(lv) + + def _test_lv_method_interface_sequence( + self, lv, test_ss=True, remove_lv=True): + self._test_lv_method_interface(lv) + + # We can't take a snapshot of a pool lv (not yet). + if test_ss: + ss_lv = self._take_lv_snapshot(lv) + self._test_lv_method_interface(ss_lv) + self._lv_remove(ss_lv) + + if remove_lv: + self._lv_remove(lv) + + def test_lv_interface_plain_lv(self): + self._test_lv_method_interface_sequence(self._create_lv()) + + def test_lv_interface_vdo_lv(self): + if not self.vdo: + raise unittest.SkipTest('vdo not supported') + self._test_lv_method_interface_sequence(self._create_vdo_lv()) + + def test_lv_interface_cache_lv(self): + self._test_lv_method_interface_sequence( + self._create_cache_lv(), remove_lv=False) + + def test_lv_interface_thin_pool_lv(self): + self._test_lv_method_interface_sequence( + self._create_thin_pool_lv(), test_ss=False) + + def test_lv_interface_vdo_pool_lv(self): + if not self.vdo: + raise unittest.SkipTest('vdo not supported') + self._test_lv_method_interface_sequence( + self._vdo_pool_lv(), test_ss=False) + + def _log_file_option(self): + fn = os.path.join(tempfile.gettempdir(), rs(8, "_lvm.log")) + try: + options = dbus.Dictionary({}, signature=dbus.Signature('sv')) + option_str = "log { level=7 file=%s syslog=0 }" % fn + options["config"] = dbus.String(option_str) + self._vg_create(None, None, options) + self.assertTrue(os.path.exists(fn), + "We passed the following options %s to lvm while creating a VG and the " + "log file we expected to exist (%s) was not found" % (option_str, fn)) + finally: + if os.path.exists(fn): + os.unlink(fn) + + def test_log_file_option(self): + self._log_file_option() + + def test_external_event(self): + # Call into the service to register an external event, so that we can test sending the path + # where we don't send notifications on the command line in addition to the logging + lvm_manager = dbus.Interface(bus.get_object( + BUS_NAME, "/com/redhat/lvmdbus1/Manager", introspect=False), + "com.redhat.lvmdbus1.Manager") + rc = lvm_manager.ExternalEvent("unit_test") + self.assertTrue(rc == 0) + self._log_file_option() + + def test_delete_non_complete_job(self): + # Let's create a vg with a number of lvs and then delete it all + # to hopefully create a long-running job. + vg_proxy = self._create_num_lvs(64) + job_path = vg_proxy.Vg.Remove(dbus.Int32(0), EOD) + self.assertNotEqual(job_path, "/") + + # Try to delete the job expecting an exception + job_proxy = ClientProxy(self.bus, job_path, interfaces=(JOB_INT,)).Job + with self.assertRaises(dbus.exceptions.DBusException): + try: + job_proxy.Remove() + except dbus.exceptions.DBusException as e: + # Verify we got the expected text in exception + self.assertTrue('Job is not complete!' in str(e)) + raise e + + def test_z_sigint(self): + # Issue SIGINT while daemon is processing work to ensure we shut down. + if bool(int(os.getenv("LVM_DBUSD_TEST_SKIP_SIGNAL", "0"))): + raise unittest.SkipTest("Skipping as env. LVM_DBUSD_TEST_SKIP_SIGNAL is '1'") + + di = DaemonInfo.get() + self.assertTrue(di is not None) + if di: + # Find out how long it takes to create a VG and a number of LVs + # we will then issue the creation of the LVs async., wait, then issue a signal + # and repeat stepping through the entire time range. + start = time.time() + vg_proxy = self._create_num_lvs(20) + end = time.time() + + self.handle_return(vg_proxy.Vg.Remove(dbus.Int32(g_tmo), EOD)) + total = end - start + + for i in range(5): + sleep_amt = i * (total/5.0) + self._create_num_lvs(20, True) + time.sleep(sleep_amt) + + exited = False + try: + di.term_signal(signal.SIGINT) + exited = True + except Exception: + std_err_print("Failed to exit on SIGINT, sending SIGKILL...") + di.term_signal(signal.SIGKILL) + finally: + di.start() + self.clean_up() + + self.assertTrue(exited, + "Failed to exit after sending signal %f seconds after " + "queuing up work for signal %d" % (sleep_amt, signal.SIGINT)) + set_exec_mode(g_lvm_shell) + + def test_z_singleton_daemon(self): + # Ensure we can only have 1 daemon running at a time, daemon should exit with 114 if already running + di = DaemonInfo.get() + self.assertTrue(di is not None) + if di.systemd: + raise unittest.SkipTest('existing dameon running via systemd') + if di: + ec = di.start(True) + self.assertEqual(ec, 114) + + def test_z_switching(self): + # Ensure we can switch from forking to shell repeatedly + try: + t_mode = True + for _ in range(50): + t_mode = not t_mode + set_exec_mode(t_mode) + finally: + set_exec_mode(g_lvm_shell) + + @staticmethod + def _wipe_it(block_device): + cmd = ["/usr/sbin/wipefs", '-a', block_device] + config = Popen(cmd, stdout=PIPE, stderr=PIPE, close_fds=True, env=os.environ) + config.communicate() + if config.returncode != 0: + return False + return True + + def _block_present_absent(self, block_device, present=False): + start = time.time() + keep_looping = True + max_wait = 10 + while keep_looping and time.time() < start + max_wait: + if present: + if (self._lookup(block_device) != "/"): + keep_looping = False + else: + if (self._lookup(block_device) == "/"): + keep_looping = False + + if keep_looping: + print("Daemon failed to update within %d seconds!" % max_wait) + else: + print("Note: Time for udev update = %f" % (time.time() - start)) + if present: + rc = self._lookup(block_device) + self.assertNotEqual(rc, '/', "Daemon failed to update, missing udev change event?") + return True + else: + rc = self._lookup(block_device) + self.assertEqual(rc, '/', "Daemon failed to update, missing udev change event?") + return True + + def test_wipefs(self): + # Ensure we update the status of the daemon if an external process clears a PV + pv = self.objs[PV_INT][0] + pv_device_path = pv.Pv.Name + + wipe_result = TestDbusService._wipe_it(pv_device_path) + self.assertTrue(wipe_result) + + if wipe_result: + # Need to wait a bit before the daemon will reflect the change + self._block_present_absent(pv_device_path, False) + + # Put it back + pv_object_path = self._pv_create(pv_device_path) + self.assertNotEqual(pv_object_path, '/') + + @staticmethod + def _write_signature(device, data=None): + fd = os.open(device, os.O_RDWR|os.O_EXCL|os.O_NONBLOCK) + existing = os.read(fd, 1024) + os.lseek(fd, 0, os.SEEK_SET) + + if data is None: + data_copy = bytearray(existing) + # Clear lvm signature + data_copy[536:536+9] = bytearray(8) + os.write(fd, data_copy) + else: + os.write(fd, data) + os.sync() + os.close(fd) + return existing + + def test_copy_signature(self): + # Ensure we update the state of the daemon if an external process copies + # a pv signature onto a block device + pv = self.objs[PV_INT][0] + pv_device_path = pv.Pv.Name + + try: + existing = TestDbusService._write_signature(pv_device_path, None) + if self._block_present_absent(pv_device_path, False): + TestDbusService._write_signature(pv_device_path, existing) + self._block_present_absent(pv_device_path, True) + finally: + # Ensure we put the PV back for sure. + rc = self._lookup(pv_device_path) + if rc == "/": + self._pv_create(pv_device_path) + + def test_stderr_collection(self): + lv_name = lv_n() + vg = self._vg_create().Vg + (object_path, job_path) = vg.LvCreate( + dbus.String(lv_name), dbus.UInt64(vg.SizeBytes * 2), + dbus.Array([], signature='(ott)'), dbus.Int32(0), + EOD) + + self.assertTrue(object_path == '/') + self.assertTrue(job_path != '/') + + j = ClientProxy(self.bus, job_path, interfaces=(JOB_INT,)).Job + while True: + j.update() + if j.Complete: + (ec, error_msg) = j.GetError + self.assertTrue("insufficient free space" in error_msg, + "We're expecting 'insufficient free space' in \n\"%s\"\n, stderr missing?" % error_msg) + break + else: + time.sleep(0.1) + + @staticmethod + def _is_vg_devices_supported(): + rc, stdout_txt, stderr_txt = call_lvm(["vgcreate", "--help"]) + if rc == 0: + for line in stdout_txt.split("\n"): + if "--devices " in line: + return True + return False + + @staticmethod + def _vg_create_specify_devices(name, device): + cmd = [LVM_EXECUTABLE, "vgcreate", "--devices", device, name, device] + outcome = Popen(cmd, stdout=PIPE, stderr=PIPE, close_fds=True, env=os.environ) + outcome.communicate() + if outcome.returncode == 0: + return True + else: + print("Failed to create vg %s, stdout= %s, stderr= %s" % (name, outcome.stdout, outcome.stderr)) + return False + + def test_duplicate_vg_name(self): + # LVM allows duplicate VG names, test handling renames for now + if not TestDbusService._is_vg_devices_supported(): + raise unittest.SkipTest("lvm does not support vgcreate with --device syntax") + + if len(self.objs[PV_INT]) < 2: + raise unittest.SkipTest("we need at least 2 PVs to run test") + + vg_name = vg_n() + if TestDbusService._vg_create_specify_devices(vg_name, self.objs[PV_INT][0].Pv.Name) and \ + TestDbusService._vg_create_specify_devices(vg_name, self.objs[PV_INT][1].Pv.Name): + objects, _ = get_objects() + self.assertEqual(len(objects[VG_INT]), 2) + + if len(objects[VG_INT]) == 2: + for vg in objects[VG_INT]: + new_name = vg_n() + vg.Vg.Rename(dbus.String(new_name), dbus.Int32(g_tmo), EOD) + # Ensure we find the renamed VG + self.assertNotEqual("/", self._lookup(new_name), "Expecting to find VG='%s'" % new_name) + else: + self.assertFalse(True, "We failed to create 2 VGs with same name!") + + +class AggregateResults(object): + + def __init__(self): + self.no_errors = True + + def register_result(self, result): + if not result.result.wasSuccessful(): + self.no_errors = False + + def register_fail(self): + self.no_errors = False + + def exit_run(self): + if self.no_errors: + sys.exit(0) + sys.exit(1) + + +if __name__ == '__main__': + + r = AggregateResults() + mode = int(test_shell) + + # To test with error injection, simply set the env. variable LVM_BINARY to the error inject script + # and the LVM_MAN_IN_MIDDLE variable to the lvm binary to test which defaults to "/usr/sbin/lvm" + # An example + # export LVM_BINARY=/home/tasleson/projects/lvm2/test/dbus/lvm_error_inject.py + # export LVM_MAN_IN_MIDDLE=/home/tasleson/projects/lvm2/tools/lvm + + if mode == 0: + std_err_print('\n*** Testing only lvm fork & exec test mode ***\n') + elif mode == 1: + std_err_print('\n*** Testing only lvm shell mode ***\n') + elif mode == 2: + std_err_print('\n*** Testing fork & exec & lvm shell mode ***\n') + else: + std_err_print("Unsupported \"LVM_DBUSD_TEST_MODE\"=%d, [0-2] valid" % mode) + sys.exit(1) + + for g_tmo in [0, 15]: + std_err_print('Testing TMO=%d\n' % g_tmo) + if mode == 0: + if set_execution(False, r): + r.register_result(unittest.main(exit=False)) + elif mode == 1: + if set_execution(True, r): + r.register_result(unittest.main(exit=False)) + else: + if set_execution(False, r): + r.register_result(unittest.main(exit=False)) + # Test lvm shell + if set_execution(True, r): + r.register_result(unittest.main(exit=False)) + + if not r.no_errors: + break + + r.exit_run() diff --git a/test/dbus/testlib.py b/test/dbus/testlib.py new file mode 100644 index 0000000..b793b67 --- /dev/null +++ b/test/dbus/testlib.py @@ -0,0 +1,331 @@ +#!/usr/bin/python3 + +# Copyright (C) 2015-2016 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, see . +import string +import random +import functools +import xml.etree.ElementTree as Et +from collections import OrderedDict +import dbus +import os +import sys +import time + +BUS_NAME = os.getenv('LVM_DBUS_NAME', 'com.redhat.lvmdbus1') +BASE_INTERFACE = 'com.redhat.lvmdbus1' +MANAGER_INT = BASE_INTERFACE + '.Manager' +MANAGER_OBJ = '/' + BASE_INTERFACE.replace('.', '/') + '/Manager' +PV_INT = BASE_INTERFACE + ".Pv" +VG_INT = BASE_INTERFACE + ".Vg" +VG_VDO_INT = BASE_INTERFACE + ".VgVdo" +LV_INT = BASE_INTERFACE + ".Lv" +THINPOOL_INT = BASE_INTERFACE + ".ThinPool" +VDOPOOL_INT = BASE_INTERFACE + ".VdoPool" +SNAPSHOT_INT = BASE_INTERFACE + ".Snapshot" +LV_COMMON_INT = BASE_INTERFACE + ".LvCommon" +JOB_INT = BASE_INTERFACE + ".Job" +CACHE_POOL_INT = BASE_INTERFACE + ".CachePool" +CACHE_LV_INT = BASE_INTERFACE + ".CachedLv" +THINPOOL_LV_PATH = '/' + THINPOOL_INT.replace('.', '/') + + +validate_introspection = True + + +def rs(length, suffix, character_set=string.ascii_lowercase): + return ''.join(random.choice(character_set) for _ in range(length)) + suffix + + +def mib(s): + return 1024 * 1024 * s + + +def std_err_print(*args): + sys.stderr.write(' '.join(map(str, args)) + '\n') + sys.stderr.flush() + + +class DbusIntrospection(object): + @staticmethod + def introspect(xml_representation): + interfaces = {} + + root = Et.fromstring(xml_representation) + + for c in root: + if c.tag == "interface": + in_f = c.attrib['name'] + interfaces[in_f] = dict(methods=OrderedDict(), properties={}) + for nested in c: + if nested.tag == "method": + mn = nested.attrib['name'] + interfaces[in_f]['methods'][mn] = OrderedDict() + + for arg in nested: + if arg.tag == 'arg': + arg_dir = arg.attrib['direction'] + if arg_dir == 'in': + n = arg.attrib['name'] + else: + n = 'RETURN_VALUE' + + arg_type = arg.attrib['type'] + + if n: + v = dict( + name=mn, + a_dir=arg_dir, + a_type=arg_type + ) + interfaces[in_f]['methods'][mn][n] = v + + elif nested.tag == 'property': + pn = nested.attrib['name'] + p_access = nested.attrib['access'] + p_type = nested.attrib['type'] + + interfaces[in_f]['properties'][pn] = \ + dict(p_access=p_access, p_type=p_type) + else: + pass + + # print('Interfaces...') + # for k, v in list(interfaces.items()): + # print('Interface %s' % k) + # if v['methods']: + # for m, args in list(v['methods'].items()): + # print(' method: %s' % m) + # for a, aa in args.items(): + # print(' method arg: %s type %s' % + # (a, aa['a_type'])) + # if v['properties']: + # for p, d in list(v['properties'].items()): + # print(' Property: %s type= %s' % (p, d['p_type'])) + # print('End interfaces') + + return interfaces + + +def btsr(value): + t = type(value) + if t == dbus.Boolean: + return 'b' + elif t == dbus.ObjectPath: + return 'o' + elif t == dbus.String: + return 's' + elif t == dbus.Byte: + return 'y' + elif t == dbus.Int16: + return 'n' + elif t == dbus.Int32: + return 'i' + elif t == dbus.Int64: + return 'x' + elif t == dbus.UInt16: + return 'q' + elif t == dbus.UInt32: + return 'u' + elif t == dbus.UInt64: + return 't' + elif t == dbus.Double: + return 'd' + elif t == dbus.Struct: + rc = '(' + for vt in value: + rc += btsr(vt) + rc += ')' + return rc + elif t == dbus.Array: + rc = "a" + if hasattr(value, "signature"): + return rc + value.signature + for i in value: + rc += btsr(i) + break + return rc + else: + raise RuntimeError("Unhandled type %s" % str(t)) + + +def verify_type(value, dbus_str_rep): + actual_str_rep = btsr(value) + + if dbus_str_rep != actual_str_rep: + raise RuntimeError( + "Incorrect type, expected= %s actual = %s object= %s" % + (dbus_str_rep, actual_str_rep, str(type(value)))) + + +class RemoteInterface(object): + def _set_props(self, props=None): + if not props: + for _ in range(0, 3): + try: + prop_interface = dbus.Interface( + self.dbus_object, 'org.freedesktop.DBus.Properties') + props = prop_interface.GetAll(self.interface) + break + except dbus.exceptions.DBusException as dbe: + if "GetAll" not in str(dbe): + raise dbe + if props: + for kl, vl in list(props.items()): + # Verify type is correct! + if self.introspect: + verify_type( + vl, self.introspect[self.interface] + ['properties'][kl]['p_type']) + self.p_name[kl] = True + setattr(self, kl, vl) + + @property + def object_path(self): + return self.dbus_object.object_path + + def __init__( + self, dbus_object, interface, + introspect, properties=None, timelimit=-1): + self.dbus_object = dbus_object + self.interface = interface + self.introspect = introspect + self.tmo = 0 + self.p_name = {} + + if timelimit >= 0: + self.tmo = float(timelimit) + self.tmo *= 1.10 + + self.dbus_interface = dbus.Interface(self.dbus_object, self.interface) + self._set_props(properties) + + # noinspection PyTypeChecker + def __getattr__(self, item): + if hasattr(self.dbus_interface, item): + return functools.partial(self._wrapper, item) + else: + return functools.partial(self, item) + + def _wrapper(self, _method_name, *args, **kwargs): + + # Let's see how long a method takes to execute, in call cases we should + # return something when the time limit has been reached. + start = time.time() + result = getattr(self.dbus_interface, _method_name)(*args, **kwargs) + end = time.time() + + diff = end - start + + if self.tmo > 0.0: + if diff > self.tmo: + std_err_print( + "\n Time exceeded: %f > %f %s" % + (diff, self.tmo, _method_name)) + + if self.introspect: + if 'RETURN_VALUE' in self.introspect[ + self.interface]['methods'][_method_name]: + r_type = self.introspect[ + self.interface]['methods'][ + _method_name]['RETURN_VALUE']['a_type'] + + verify_type(result, r_type) + + return result + + def update(self): + self._set_props() + + def get_property_names(self): + return self.p_name.keys() + + def get_property_value(self, name): + prop_interface = dbus.Interface( + self.dbus_object, 'org.freedesktop.DBus.Properties') + return prop_interface.Get(self.interface, name) + + +class ClientProxy(object): + + @staticmethod + def _intf_short_name(nm): + return nm.split('.')[-1:][0] + + def get_introspect(self): + i = dbus.Interface( + self.dbus_object, + 'org.freedesktop.DBus.Introspectable') + + return DbusIntrospection.introspect(i.Introspect()) + + def _common(self, interface, introspect, properties): + short_name = ClientProxy._intf_short_name(interface) + self.short_interface_names.append(short_name) + ro = RemoteInterface( + self.dbus_object, interface, introspect, properties, + timelimit=self.tmo) + setattr(self, short_name, ro) + + def __init__( + self, bus, object_path, interface_prop_hash=None, + interfaces=None, timelimit=-1): + # Instance variables which may or may not get assigned during class + # construction dynamically. Assigned here so code inspection tools + # have knowledge of their existence. + self.Manager = None + self.Pv = None + self.Vg = None + self.Lv = None + self.VgVdo = None + self.ThinPool = None + self.VdoPool = None + self.SnapShot = None + self.LvCommon = None + self.Job = None + self.CachePool = None + self.CachedLv = None + + self.object_path = object_path + self.short_interface_names = [] + self.tmo = timelimit + self.dbus_object = bus.get_object( + BUS_NAME, self.object_path, introspect=False) + + if interface_prop_hash: + assert interfaces is None + if interfaces: + assert interface_prop_hash is None + + if interface_prop_hash and not validate_introspection: + # We have everything including the values of the properties + for i, props in interface_prop_hash.items(): + self._common(i, None, props) + elif interfaces and not validate_introspection: + # We are retrieving the values of the properties + for i in interfaces: + self._common(i, None, None) + else: + # We need to query the interfaces and gather all the properties + # for each interface, as we have the introspection data we + # will also utilize it to verify what we get back verifies + introspect = self.get_introspect() + + if interface_prop_hash: + introspect_interfaces = list(introspect.keys()) + for object_manager_key in interface_prop_hash.keys(): + assert object_manager_key in introspect_interfaces + + for i in list(introspect.keys()): + self._common(i, introspect, None) + + def update(self): + # Go through all interfaces and update them + for sn in self.short_interface_names: + getattr(self, sn).update() diff --git a/test/dbus/validatestate.py b/test/dbus/validatestate.py new file mode 100755 index 0000000..1af303f --- /dev/null +++ b/test/dbus/validatestate.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +# Copyright (C) 2015-2016 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, see . +# +# Simply connects to the dbus service and calls Refresh and ensures that the +# value returned is zero + +import testlib +import dbus +from dbus.mainloop.glib import DBusGMainLoop +import sys +import os + + +if __name__ == "__main__": + + use_session = os.getenv('LVMD_BUSD_USE_SESSION', False) + + if use_session: + bus = dbus.SessionBus(mainloop=DBusGMainLoop()) + else: + bus = dbus.SystemBus(mainloop=DBusGMainLoop()) + + mgr_proxy = testlib.ClientProxy(bus, testlib.MANAGER_OBJ) + sys.exit(mgr_proxy.Manager.Refresh()) diff --git a/test/lib/aux.sh b/test/lib/aux.sh index 7c0c189..3f66e92 100644 --- a/test/lib/aux.sh +++ b/test/lib/aux.sh @@ -1,5 +1,5 @@ -#!/bin/bash -# Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash +# Copyright (C) 2011-2017 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 @@ -7,188 +7,575 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . lib/utils +test -n "$BASH" && set -euE -o pipefail + run_valgrind() { # Execute script which may use $TESTNAME for creating individual # log files for each execute command - exec "${VALGRIND:-valg}" "$@" + exec "${VALGRIND:-valgrind}" "$@" } expect_failure() { echo "TEST EXPECT FAILURE" } +check_daemon_in_builddir() { + # skip if we don't have our own deamon... + if test -z "${installed_testsuite+varset}"; then + (which "$1" 2>/dev/null | grep "$abs_builddir" >/dev/null ) || skip "$1 is not in executed path." + fi + rm -f debug.log strace.log +} + +create_corosync_conf() { + local COROSYNC_CONF="/etc/corosync/corosync.conf" + local COROSYNC_NODE=$(hostname) + + if test -a "$COROSYNC_CONF"; then + if ! grep "created by lvm test suite" "$COROSYNC_CONF"; then + rm "$COROSYNC_CONF" + else + mv "$COROSYNC_CONF" "$COROSYNC_CONF.prelvmtest" + fi + fi + + sed -e "s/@LOCAL_NODE@/$COROSYNC_NODE/" lib/test-corosync-conf > "$COROSYNC_CONF" + echo "created new $COROSYNC_CONF" +} + +create_dlm_conf() { + local DLM_CONF="/etc/dlm/dlm.conf" + + if test -a "$DLM_CONF"; then + if ! grep "created by lvm test suite" "$DLM_CONF"; then + rm "$DLM_CONF" + else + mv "$DLM_CONF" "$DLM_CONF.prelvmtest" + fi + fi + mkdir -p "$(dirname "$DLM_CONF")" + cp lib/test-dlm-conf "$DLM_CONF" + echo "created new $DLM_CONF" +} + +prepare_dlm() { + pgrep dlm_controld && skip "Cannot run while existing dlm_controld process exists." + pgrep corosync && skip "Cannot run while existing corosync process exists." + + create_corosync_conf + create_dlm_conf + + systemctl start corosync + sleep 1 + if ! pgrep corosync; then + echo "Failed to start corosync." + exit 1 + fi + + systemctl start dlm + sleep 1 + if ! pgrep dlm_controld; then + echo "Failed to start dlm." + exit 1 + fi +} + +create_sanlock_conf() { + local SANLOCK_CONF="/etc/sanlock/sanlock.conf" + + if test -a "$SANLOCK_CONF"; then + if ! grep "created by lvm test suite" "$SANLOCK_CONF"; then + rm "$SANLOCK_CONF" + else + mv "$SANLOCK_CONF" "$SANLOCK_CONF.prelvmtest" + fi + fi + + mkdir -p "$(dirname "$SANLOCK_CONF")" + cp lib/test-sanlock-conf "$SANLOCK_CONF" + echo "created new $SANLOCK_CONF" +} + +prepare_sanlock() { + pgrep sanlock && skip "Cannot run while existing sanlock process exists" + + create_sanlock_conf + + systemctl start sanlock + if ! pgrep sanlock; then + echo "Failed to start sanlock" + exit 1 + fi +} + +prepare_idm() { + pgrep seagate_ilm && skip "Cannot run while existing seagate_ilm process exists" + + seagate_ilm -D 0 -l 0 -L 7 -E 7 -S 7 + + if ! pgrep seagate_ilm; then + echo "Failed to start seagate_ilm" + exit 1 + fi +} + +prepare_lvmlockd() { + pgrep lvmlockd && skip "Cannot run while existing lvmlockd process exists" + + if test -n "$LVM_TEST_LOCK_TYPE_SANLOCK"; then + # make check_lvmlockd_sanlock + echo "starting lvmlockd for sanlock" + lvmlockd -o 2 + + elif test -n "$LVM_TEST_LOCK_TYPE_DLM"; then + # make check_lvmlockd_dlm + echo "starting lvmlockd for dlm" + lvmlockd + + elif test -n "$LVM_TEST_LOCK_TYPE_IDM"; then + # make check_lvmlockd_idm + echo "starting lvmlockd for idm" + lvmlockd -g idm + + elif test -n "$LVM_TEST_LVMLOCKD_TEST_DLM"; then + # make check_lvmlockd_test + echo "starting lvmlockd --test (dlm)" + lvmlockd --test -g dlm + + elif test -n "$LVM_TEST_LVMLOCKD_TEST_SANLOCK"; then + # FIXME: add option for this combination of --test and sanlock + echo "starting lvmlockd --test (sanlock)" + lvmlockd --test -g sanlock -o 2 + + elif test -n "$LVM_TEST_LVMLOCKD_TEST_IDM"; then + # make check_lvmlockd_test + echo "starting lvmlockd --test (idm)" + lvmlockd --test -g idm + + else + echo "not starting lvmlockd" + exit 0 + fi + + sleep 1 + if ! pgrep lvmlockd >LOCAL_LVMLOCKD; then + echo "Failed to start lvmlockd" + exit 1 + fi +} + prepare_clvmd() { test "${LVM_TEST_LOCKING:-0}" -ne 3 && return # not needed if pgrep clvmd ; then - echo "Cannot use fake cluster locking with real clvmd ($(pgrep clvmd)) running." - skip + skip "Cannot use fake cluster locking with real clvmd ($(pgrep clvmd)) running." fi - # skip if we don't have our own clvmd... - (which clvmd 2>/dev/null | grep "$abs_builddir") || skip + check_daemon_in_builddir clvmd - # skip if we singlenode is not compiled in - (clvmd --help 2>&1 | grep "Available cluster managers" | grep "singlenode") || skip + test -e "$DM_DEV_DIR/control" || dmsetup table >/dev/null # create control node + # skip if singlenode is not compiled in + (clvmd --help 2>&1 | grep "Available cluster managers" | grep "singlenode" >/dev/null) || \ + skip "Compiled clvmd does not support singlenode for testing." # lvmconf "activation/monitoring = 1" - local run_valgrind= - test -z "$LVM_VALGRIND_CLVMD" || run_valgrind="run_valgrind" - $run_valgrind lib/clvmd -Isinglenode -d 1 -f & - local local_clvmd=$! - sleep .3 - # extra sleep for slow valgrind - test -z "$LVM_VALGRIND_CLVMD" || sleep 7 - # check that it is really running now - ps $local_clvmd || die - echo $local_clvmd > LOCAL_CLVMD + local run_valgrind="" + test "${LVM_VALGRIND_CLVMD:-0}" -eq 0 || run_valgrind="run_valgrind" + rm -f "$CLVMD_PIDFILE" + echo "<======== Starting CLVMD ========>" + echo -n "## preparing clvmd..." + # lvs is executed from clvmd - use our version + LVM_LOG_FILE_EPOCH=CLVMD LVM_LOG_FILE_MAX_LINES=1000000 $run_valgrind clvmd -Isinglenode -d 1 -f & + echo $! > LOCAL_CLVMD + + for i in {200..0} ; do + test "$i" -eq 0 && die "Startup of clvmd is too slow." + test -e "$CLVMD_PIDFILE" && test -e "${CLVMD_PIDFILE%/*}/lvm/clvmd.sock" && break + echo -n . + sleep .1 + done + echo ok } prepare_dmeventd() { if pgrep dmeventd ; then - echo "Cannot test dmeventd with real dmeventd ($(pgrep dmeventd)) running." - skip + skip "Cannot test dmeventd with real dmeventd ($(pgrep dmeventd)) running." fi - # skip if we don't have our own dmeventd... - (which dmeventd 2>/dev/null | grep "$abs_builddir") || skip - + check_daemon_in_builddir dmeventd lvmconf "activation/monitoring = 1" - dmeventd -f "$@" & + local run_valgrind="" + test "${LVM_VALGRIND_DMEVENTD:-0}" -eq 0 || run_valgrind="run_valgrind" + echo -n "## preparing dmeventd..." +# LVM_LOG_FILE_EPOCH=DMEVENTD $run_valgrind dmeventd -fddddl "$@" 2>&1 & + LVM_LOG_FILE_EPOCH=DMEVENTD $run_valgrind dmeventd -fddddl "$@" >debug.log_DMEVENTD_out 2>&1 & echo $! > LOCAL_DMEVENTD # FIXME wait for pipe in /var/run instead - sleep .3 + for i in {200..0} ; do + test "$i" -eq 0 && die "Startup of dmeventd is too slow." + test -e "${DMEVENTD_PIDFILE}" && break + echo -n . + sleep .1 + done + echo ok } -prepare_lvmetad() { - # skip if we don't have our own lvmetad... - (which lvmetad 2>/dev/null | grep "$abs_builddir") || skip +prepare_lvmpolld() { + test -e LOCAL_LVMPOLLD || lvmconf "global/use_lvmpolld = 1" - lvmconf "global/use_lvmetad = 1" - lvmconf "devices/md_component_detection = 0" + local run_valgrind="" + test "${LVM_VALGRIND_LVMPOLLD:-0}" -eq 0 || run_valgrind="run_valgrind" - local run_valgrind= - test -z "$LVM_VALGRIND_LVMETAD" || run_valgrind="run_valgrind" + kill_sleep_kill_ LOCAL_LVMPOLLD "${LVM_VALGRIND_LVMPOLLD:-0}" - echo "preparing lvmetad..." - $run_valgrind lvmetad -f "$@" -s "$TESTDIR/lvmetad.socket" -l wire,debug & - echo $! > LOCAL_LVMETAD - while ! test -e "$TESTDIR/lvmetad.socket"; do echo -n .; sleep .1; done # wait for the socket + echo -n "## preparing lvmpolld..." + $run_valgrind lvmpolld -f "$@" -s "$TESTDIR/lvmpolld.socket" -B "$TESTDIR/lib/lvm" -l all & + echo $! > LOCAL_LVMPOLLD + for i in {200..0} ; do + test -e "$TESTDIR/lvmpolld.socket" && break + echo -n .; + sleep .1; + done # wait for the socket + test "$i" -gt 0 || die "Startup of lvmpolld is too slow." echo ok } -notify_lvmetad() { - if test -e LOCAL_LVMETAD; then - pvscan --cache "$@" || true +lvmpolld_talk() { + local use=nc + if type -p socat >& /dev/null; then + use=socat + elif echo | not nc -U "$TESTDIR/lvmpolld.socket" ; then + echo "WARNING: Neither socat nor nc -U seems to be available." 1>&2 + echo "## failed to contact lvmpolld." + return 1 + fi + + if test "$use" = nc ; then + nc -U "$TESTDIR/lvmpolld.socket" + else + socat "unix-connect:$TESTDIR/lvmpolld.socket" - + fi | tee -a lvmpolld-talk.txt +} + +lvmpolld_dump() { + (echo 'request="dump"'; echo '##') | lvmpolld_talk "$@" +} + +prepare_lvmdbusd() { + local lvmdbusdebug= + local daemon + rm -f debug.log_LVMDBUSD_out + + kill_sleep_kill_ LOCAL_LVMDBUSD 0 + + # FIXME: This is not correct! Daemon is auto started. + echo -n "## checking lvmdbusd is NOT running..." + if pgrep -f -l lvmdbusd | grep python3 || pgrep -x -l lvmdbusd ; then + skip "Cannot run lvmdbusd while existing lvmdbusd process exists" + fi + echo ok + + # skip if we don't have our own lvmdbusd... + echo -n "## find lvmdbusd to use..." + if test -z "${installed_testsuite+varset}"; then + # NOTE: this is always present - additional checks are needed: + daemon="$abs_top_builddir/daemons/lvmdbusd/lvmdbusd" + if test -x "$daemon" || chmod ugo+x "$daemon"; then + echo "$daemon" + else + echo "Failed to make '$daemon' executable">&2 + return 1 + fi + # Setup the python path so we can run + export PYTHONPATH="$abs_top_builddir/daemons" + else + daemon=$(which lvmdbusd || :) + echo "$daemon" + fi + test -x "$daemon" || skip "The lvmdbusd daemon is missing" + which python3 >/dev/null || skip "Missing python3" + + python3 -c "import pyudev, dbus, gi.repository" || skip "Missing python modules" + python3 -c "from json.decoder import JSONDecodeError" || skip "Python json module is missing JSONDecodeError" + + # Copy the needed file to run on the system bus if it doesn't + # already exist + if [ ! -f /etc/dbus-1/system.d/com.redhat.lvmdbus1.conf ]; then + install -m 644 "$abs_top_builddir/scripts/com.redhat.lvmdbus1.conf" /etc/dbus-1/system.d/ + fi + + echo "## preparing lvmdbusd..." + lvmconf "global/notify_dbus = 1" + + test "${LVM_DEBUG_LVMDBUS:-0}" != "0" && lvmdbusdebug="--debug" + "$daemon" $lvmdbusdebug > debug.log_LVMDBUSD_out 2>&1 & + local pid=$! + + sleep 1 + echo -n "## checking lvmdbusd IS running..." + comm= + # TODO: Is there a better check than wait 1 second and check pid? + if ! comm=$(ps -p $pid -o comm=) >/dev/null || [[ $comm != lvmdbusd ]]; then + echo "Failed to start lvmdbusd daemon" + return 1 fi + echo "$pid" > LOCAL_LVMDBUSD + echo ok +} + +# +# Temporary solution to create some occupied thin metadata +# This heavily depends on thin metadata output format to stay as is. +# Currently it expects 2MB thin metadata and 200MB data volume size +# Argument specifies how many devices should be created. +# +prepare_thin_metadata() { + local devices=$1 + local transaction_id=${2:-0} + local data_block_size=${3:-128} + local nr_data_blocks=${4:-3200} + local i + + echo '' + for i in $(seq 1 "$devices") + do + echo ' ' + echo ' ' + echo ' ' + done + echo "" } teardown_devs_prefixed() { local prefix=$1 local stray=${2:-0} local IFS=$IFS_NL + local once=1 local dm + rm -rf "${TESTDIR:?}/dev/$prefix*" + + # Send idle message to frozen raids (with hope to unfreeze them) + for dm in $(dm_status | grep -E "$prefix.*raid.*frozen"); do + echo "## unfreezing: dmsetup message \"${dm%:*}\"" + dmsetup message "${dm%:*}" 0 "idle" & + done + # Resume suspended devices first - for dm in $(dm_info suspended,name | grep "^Suspended:.*$prefix"); do - echo "dmsetup resume \"${dm#Suspended:}\"" - dmsetup resume "${dm#Suspended:}" || true + for dm in $(dm_info name -S "name=~$PREFIX&&suspended=Suspended"); do + test "$dm" != "No devices found" || break + echo "## resuming: dmsetup resume \"$dm\"" + dmsetup clear "$dm" + dmsetup resume "$dm" & done - local mounts=( $(grep "$prefix" /proc/mounts | cut -d' ' -f1) ) + wait + + local mounts + mounts=( $(grep "$prefix" /proc/mounts | cut -d' ' -f1) ) || true if test ${#mounts[@]} -gt 0; then - test "$stray" -eq 0 || echo "Removing stray mounted devices containing $prefix: ${mounts[@]}" + test "$stray" -eq 0 || echo "## removing stray mounted devices containing $prefix:" "${mounts[@]}" if umount -fl "${mounts[@]}"; then udev_wait fi fi # Remove devices, start with closed (sorted by open count) - local remfail=no - local need_udev_wait=0 - init_udev_transaction - for dm in $(dm_info name --sort open | grep "$prefix"); do - dmsetup remove "$dm" &>/dev/null || remfail=yes - need_udev_wait=1 - done - finish_udev_transaction - test $need_udev_wait -eq 0 || udev_wait - - if test $remfail = yes; then - local num_devs - local num_remaining_devs=999 - while num_devs=$(dm_table | grep "$prefix" | wc -l) && \ - test $num_devs -lt $num_remaining_devs -a $num_devs -ne 0; do - test "$stray" -eq 0 || echo "Removing $num_devs stray mapped devices with names beginning with $prefix: " - for dm in $(dm_info name --sort open | grep "$prefix") ; do - dmsetup remove -f "$dm" || true + # Run 'dmsetup remove' in parallel + rm -f REMOVE_FAILED + #local listdevs=( $(dm_info name,open --sort open,name | grep "$prefix.*:0") ) + #dmsetup remove --deferred ${listdevs[@]%%:0} || touch REMOVE_FAILED + + # 2nd. loop is trying --force removal which can possibly 'unstuck' some bloked operations + for i in 0 1; do + test "$i" = 1 && test "$stray" = 0 && break # no stray device removal + + while :; do + local sortby="name" + local progress=0 + + # HACK: sort also by minors - so we try to close 'possibly later' created device first + test "$i" = 0 || sortby="-minor" + + for dm in $(dm_info name,open --separator ';' --nameprefixes --unquoted --sort open,"$sortby" -S "name=~$prefix" --mangle none || true) ; do + test "$dm" != "No devices found" || break 2 + eval "$dm" + local force="-f" + if test "$i" = 0; then + if test "$once" = 1 ; then + once=0 + echo "## removing stray mapped devices with names beginning with $prefix: " + fi + test "$DM_OPEN" = 0 || break # stop loop with 1st. opened device + force="" + fi + + # Succesfull 'remove' signals progress + dmsetup remove $force "$DM_NAME" --mangle none && progress=1 done - num_remaining_devs=$num_devs - done - fi + + test "$i" = 0 || break + + test "$progress" = 1 || break + + udev_wait + wait + done # looping till there are some removed devices + done } teardown_devs() { # Delete any remaining dm/udev semaphores teardown_udev_cookies - - test -z "$PREFIX" || { - rm -rf "$TESTDIR/dev/$PREFIX"* - teardown_devs_prefixed "$PREFIX" - } + restore_dm_mirror + + test ! -f MD_DEV || cleanup_md_dev + test ! -f DEVICES || teardown_devs_prefixed "$PREFIX" + if test -f RAMDISK ; then + for i in 1 2 ; do + modprobe -r brd && break + sleep .1 + udev_wait + done + fi # 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 test -f SCSI_DEBUG_DEV; then - test ${LVM_TEST_PARALLEL:-0} -eq 1 || modprobe -r scsi_debug + udev_wait + test "${LVM_TEST_PARALLEL:-0}" -eq 1 || { + for i in 1 2 ; do + modprobe -r scsi_debug && break + sleep .1 + udev_wait + done + } else - test ! -f LOOP || losetup -d $(cat LOOP) || true - test ! -f LOOPFILE || rm -f $(cat LOOPFILE) + test ! -f LOOP || losetup -d "$(< LOOP)" || true + test ! -f LOOPFILE || rm -f "$(< LOOPFILE)" fi - rm -f DEVICES # devs is set in prepare_devs() - rm -f LOOP + + not diff LOOP BACKING_DEV >/dev/null 2>&1 || rm -f BACKING_DEV + rm -f DEVICES LOOP RAMDISK # Attempt to remove any loop devices that failed to get torn down if earlier tests aborted - test ${LVM_TEST_PARALLEL:-0} -eq 1 -o -z "$COMMON_PREFIX" || { - teardown_devs_prefixed "$COMMON_PREFIX" 1 - local stray_loops=( $(losetup -a | grep "$COMMON_PREFIX" | cut -d: -f1) ) + test "${LVM_TEST_PARALLEL:-0}" -eq 1 || test -z "$COMMON_PREFIX" || { + local stray_loops + stray_loops=( $(losetup -a | grep "$COMMON_PREFIX" | cut -d: -f1) ) || true test ${#stray_loops[@]} -eq 0 || { - echo "Removing stray loop devices containing $COMMON_PREFIX: ${stray_loops[@]}" - losetup -d "${stray_loops[@]}" + teardown_devs_prefixed "$COMMON_PREFIX" 1 + echo "## removing stray loop devices containing $COMMON_PREFIX:" "${stray_loops[@]}" + for i in "${stray_loops[@]}" ; do test ! -b "$i" || losetup -d "$i" || true ; done + # Leave test when udev processed all removed devices + udev_wait } } } +kill_sleep_kill_() { + local pidfile=$1 + local slow=$2 + + if test -s "$pidfile" ; then + pid=$(< "$pidfile") + rm -f "$pidfile" + kill -TERM "$pid" 2>/dev/null || return 0 + for i in {0..10} ; do + ps "$pid" >/dev/null || return 0 + if test "$slow" -eq 0 ; then sleep .2 ; else sleep 1 ; fi + kill -KILL "$pid" 2>/dev/null || true + done + fi +} + +print_procs_by_tag_() { + (ps -o pid,args ehax | grep -we"LVM_TEST_TAG=${1:-kill_me_$PREFIX}") || true +} + +count_processes_with_tag() { + print_procs_by_tag_ | wc -l +} + +kill_tagged_processes() { + local pid + local wait + + # read uses all vars within pipe subshell + local pids=() + while read -r pid wait; do + if test -n "$pid" ; then + echo "## killing tagged process: $pid ${wait:0:120}..." + kill -TERM "$pid" 2>/dev/null || true + fi + pids+=( "$pid" ) + done < <(print_procs_by_tag_ "$@") + + test ${#pids[@]} -eq 0 && return + + # wait if process exited and eventually -KILL + wait=0 + for pid in "${pids[@]}" ; do + while ps "$pid" > /dev/null && test "$wait" -le 10; do + sleep .2 + wait=$(( wait + 1 )) + done + test "$wait" -le 10 || kill -KILL "$pid" 2>/dev/null || true + done +} + teardown() { + local TEST_LEAKED_DEVICES="" echo -n "## teardown..." - test ! -s LOCAL_LVMETAD || \ - (kill -TERM "$(cat LOCAL_LVMETAD)" && sleep 1 && - kill -KILL "$(cat LOCAL_LVMETAD)" 2> /dev/null) || true + unset LVM_LOG_FILE_EPOCH + + if test -f TESTNAME ; then + + if test ! -f SKIP_THIS_TEST ; then + # Evaluate left devices only for non-skipped tests + TEST_LEAKED_DEVICES=$(dmsetup table | grep "$PREFIX" | \ + grep -Ev "${PREFIX}(pv|[0-9])" | \ + grep -v "$(cat ERR_DEV_NAME 2>/dev/null)" | \ + grep -v "$(cat ZERO_DEV_NAME 2>/dev/null)") || true + fi + + kill_tagged_processes + + if test -n "$LVM_TEST_LVMLOCKD_TEST" ; then + echo "" + echo "## stopping lvmlockd in teardown" + kill_sleep_kill_ LOCAL_LVMLOCKD 0 + fi - dm_table | not egrep -q "$vg|$vg1|$vg2|$vg3|$vg4" || { + dm_table | not grep -E -q "$vg|$vg1|$vg2|$vg3|$vg4" || { # Avoid activation of dmeventd if there is no pid cfg=$(test -s LOCAL_DMEVENTD || echo "--config activation{monitoring=0}") - vgremove -ff $cfg \ - $vg $vg1 $vg2 $vg3 $vg4 &>/dev/null || rm -f debug.log + if dm_info suspended,name | grep "^Suspended:.*$PREFIX" >/dev/null ; then + echo "## skipping vgremove, suspended devices detected." + else + vgremove -ff "$cfg" \ + "$vg" "$vg1" "$vg2" "$vg3" "$vg4" &>/dev/null || rm -f debug.log strace.log + fi } - test -s LOCAL_CLVMD && { - kill -INT "$(cat LOCAL_CLVMD)" - test -z "$LVM_VALGRIND_CLVMD" || sleep 1 - sleep .1 - kill -9 "$(cat LOCAL_CLVMD)" &>/dev/null || true - } + kill_sleep_kill_ LOCAL_LVMDBUSD 0 + + echo -n . + + kill_sleep_kill_ LOCAL_LVMPOLLD "${LVM_VALGRIND_LVMPOLLD:-0}" + + echo -n . + + kill_sleep_kill_ LOCAL_CLVMD "${LVM_VALGRIND_CLVMD:-0}" echo -n . - pgrep dmeventd || true - test ! -s LOCAL_DMEVENTD || kill -9 "$(cat LOCAL_DMEVENTD)" || true + kill_sleep_kill_ LOCAL_DMEVENTD "${LVM_VALGRIND_DMEVENTD:-0}" echo -n . @@ -196,31 +583,48 @@ teardown() { echo -n . + fi + + test -z "$TEST_LEAKED_DEVICES" || { + echo "## unexpected devices left dm table:" + echo "$TEST_LEAKED_DEVICES" + return 1 + } + + if test "${LVM_TEST_PARALLEL:-0}" = 0 && test -z "$RUNNING_DMEVENTD"; then + not pgrep dmeventd &>/dev/null # printed in STACKTRACE + fi + + echo -n . + test -n "$TESTDIR" && { - cd "$TESTOLDPWD" - rm -rf "$TESTDIR" || echo BLA + cd "$TESTOLDPWD" || die "Failed to enter $TESTOLDPWD" + # after this delete no further write is possible + rm -rf "${TESTDIR:?}" || echo BLA } - echo "ok" + # Remove any dangling symlink in /dev/disk (our tests can confuse udev) + test -d /dev/disk && { + find /dev/disk -type l ! -exec /usr/bin/test -e {} \; -print0 | xargs -0 rm -f || true + } - test ${LVM_TEST_PARALLEL:-0} -eq 1 -o -n "$RUNNING_DMEVENTD" || not pgrep dmeventd #&>/dev/null -} + # Remove any metadata archives and backups from this test on system + rm -f /etc/lvm/archive/"${PREFIX}"* /etc/lvm/backup/"${PREFIX}"* -make_ioerror() { - echo 0 10000000 error | dmsetup create -u ${PREFIX}-ioerror ioerror - ln -s "$DM_DEV_DIR/mapper/ioerror" "$DM_DEV_DIR/ioerror" + echo "ok" } prepare_loop() { - local size=${1=32} + local size=$1 + shift # all other params are directly passed to all 'losetup' calls local i local slash - test -f LOOP && LOOP=$(cat LOOP) + test -f LOOP && LOOP=$(< LOOP) echo -n "## preparing loop device..." # skip if prepare_scsi_debug_dev() was used - if test -f SCSI_DEBUG_DEV -a -f LOOP ; then + if test -f SCSI_DEBUG_DEV && test -f LOOP ; then echo "(skipped)" return 0 fi @@ -235,10 +639,11 @@ prepare_loop() { echo -n . local LOOPFILE="$PWD/test.img" - dd if=/dev/zero of="$LOOPFILE" bs=$((1024*1024)) count=0 seek=$(($size-1)) 2> /dev/null - if LOOP=$(losetup -s -f "$LOOPFILE" 2>/dev/null); then + rm -f "$LOOPFILE" + dd if=/dev/zero of="$LOOPFILE" bs=$((1024*1024)) count=0 seek=$(( size + 1 )) 2> /dev/null + if LOOP=$(losetup "$@" -s -f "$LOOPFILE" 2>/dev/null); then : - elif LOOP=$(losetup -f) && losetup "$LOOP" "$LOOPFILE"; then + elif LOOP=$(losetup -f) && losetup "$@" "$LOOP" "$LOOPFILE"; then # no -s support : else @@ -249,7 +654,7 @@ prepare_loop() { local dev="$DM_DEV_DIR/loop$slash$i" ! losetup "$dev" >/dev/null 2>&1 || continue # got a free - losetup "$dev" "$LOOPFILE" + losetup "$@" "$dev" "$LOOPFILE" LOOP=$dev break done @@ -257,43 +662,81 @@ prepare_loop() { done fi test -n "$LOOP" # confirm or fail + touch NO_BLKDISCARD_Z # loop devices do not support WRITE_ZEROS + BACKING_DEV=$LOOP echo "$LOOP" > LOOP + echo "$LOOP" > BACKING_DEV echo "ok ($LOOP)" } +prepare_ramdisk() { + local size=$1 + + # if brd is unused, remove and use for test + modprobe -r brd || return 0 + + echo -n "## preparing ramdisk device..." + modprobe brd rd_size=$((size * 1024)) rd_nr=1 || return + + BACKING_DEV=/dev/ram0 + echo "ok ($BACKING_DEV)" + touch RAMDISK +} + +prepare_real_devs() { + aux lvmconf 'devices/scan = "/dev"' + + touch REAL_DEVICES + + if test -n "$LVM_TEST_DEVICE_LIST"; then + local count=0 + while read path; do + REAL_DEVICES[count]=$path + count=$(( count + 1 )) + aux extend_filter "a|$path|" + dd if=/dev/zero of="$path" bs=32k count=1 + wipefs -a "$path" 2>/dev/null || true + done < "$LVM_TEST_DEVICE_LIST" + fi + printf "%s\\n" "${REAL_DEVICES[@]}" > REAL_DEVICES +} + # 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 - local SCSI_DEBUG_PARAMS=${@:2} + shift # rest of params directly passed to modprobe + local DEBUG_DEV - test -f "SCSI_DEBUG_DEV" && return 0 - test -z "$LOOP" + rm -f debug.log strace.log + test ! -f "SCSI_DEBUG_DEV" || return 0 + test ! -f LOOP test -n "$DM_DEV_DIR" - # Skip test if awk isn't available (required for get_sd_devs_) - which awk || skip - # Skip test if scsi_debug module is unavailable or is already in use modprobe --dry-run scsi_debug || skip - lsmod | grep -q scsi_debug && skip + lsmod | not grep scsi_debug >/dev/null || skip # 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 || skip - sleep 2 # allow for async Linux SCSI device registration + touch SCSI_DEBUG_DEV + modprobe scsi_debug dev_size_mb="$(( DEV_SIZE + 2 ))" "$@" num_tgts=1 || skip - local DEBUG_DEV="/dev/$(grep -H scsi_debug /sys/block/*/device/model | cut -f4 -d /)" + for i in {1..20} ; do + sleep .1 # allow for async Linux SCSI device registration + DEBUG_DEV="/dev/$(grep -H scsi_debug /sys/block/sd*/device/model | cut -f4 -d /)" + test -b "$DEBUG_DEV" && break + done test -b "$DEBUG_DEV" || return 1 # should not happen # Create symlink to scsi_debug device in $DM_DEV_DIR - SCSI_DEBUG_DEV="$DM_DEV_DIR/$(basename $DEBUG_DEV)" + SCSI_DEBUG_DEV="$DM_DEV_DIR/$(basename "$DEBUG_DEV")" echo "$SCSI_DEBUG_DEV" > SCSI_DEBUG_DEV - echo "$SCSI_DEBUG_DEV" > LOOP + echo "$SCSI_DEBUG_DEV" > BACKING_DEV # Setting $LOOP provides means for prepare_devs() override - test "$LVM_TEST_DEVDIR" != "/dev" && ln -snf "$DEBUG_DEV" "$SCSI_DEBUG_DEV" + test "$DEBUG_DEV" = "$SCSI_DEBUG_DEV" || ln -snf "$DEBUG_DEV" "$SCSI_DEBUG_DEV" } cleanup_scsi_debug_dev() { @@ -301,201 +744,1071 @@ cleanup_scsi_debug_dev() { rm -f SCSI_DEBUG_DEV LOOP } -prepare_devs() { - local n=${1:-3} - local devsize=${2:-34} - local pvname=${3:-pv} - local loopsz +mdadm_create() { + local devid + local mddev - prepare_loop $(($n*$devsize)) - echo -n "## preparing $n devices..." + which mdadm >/dev/null || skip "mdadm tool is missing!" - if ! loopsz=$(blockdev --getsz "$LOOP" 2>/dev/null); then - loopsz=$(blockdev --getsize "$LOOP" 2>/dev/null) - fi + cleanup_md_dev + rm -f debug.log strace.log - local size=$(($loopsz/$n)) - devs= + # try to find free MD node + # using the old naming /dev/mdXXX + # if we need more MD arrays test suite more likely leaked them + for devid in {127..150} ; do + grep -q "md${devid}" /proc/mdstat || break + done + test "$devid" -lt "150" || skip "Cannot find free /dev/mdXXX node!" + mddev=/dev/md${devid} + + mdadm --create "$mddev" "$@" || { + # Some older 'mdadm' version managed to open and close devices internaly + # and reporting non-exclusive access on such device + # let's just skip the test if this happens. + # Note: It's pretty complex to get rid of consequences + # the following sequence avoid leaks on f19 + # TODO: maybe try here to recreate few times.... + mdadm --stop "$mddev" || true + udev_wait + while [ "$#" -ne 0 ] ; do + case "$1" in + *"$PREFIX"*) mdadm --zero-superblock "$1" || true ;; + esac + shift + done + udev_wait + skip "Test skipped, unreliable mdadm detected!" + } - init_udev_transaction - for i in $(seq 1 $n); do - local name="${PREFIX}$pvname$i" - local dev="$DM_DEV_DIR/mapper/$name" - devs="$devs $dev" - echo 0 $size linear "$LOOP" $((($i-1)*$size)) > "$name.table" - dmsetup create -u "TEST-$name" "$name" "$name.table" + for i in {10..0} ; do + test -e "$mddev" && break + echo "Waiting for $mddev." + sleep .5 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 + test -b "$mddev" || skip "mdadm has not created device!" + echo "$mddev" > MD_DEV - echo $devs > DEVICES - echo "ok" + # LVM/DM will see this device + case "$DM_DEV_DIR" in + "/dev") echo "$mddev" > MD_DEV_PV ;; + *) rm -f "$DM_DEV_DIR/md${devid}" + cp -LR "$mddev" "$DM_DEV_DIR" + echo "${DM_DEV_DIR}/md${devid}" > MD_DEV_PV ;; + esac + + rm -f MD_DEVICES + while [ "$#" -ne 0 ] ; do + case "$1" in + *"$PREFIX"*) echo "$1" >> MD_DEVICES ;; + esac + shift + done } -disable_dev() { - local dev +mdadm_assemble() { + STRACE= + [ "$DM_DEV_DIR" = "/dev" ] && mdadm -V 2>&1 | grep " v3.2" && { + # use this 'trick' to slow down mdadm which otherwise + # is racing with udev rule since mdadm internally + # opens and closes raid leg devices in RW mode and then + # tries to get exlusive access to the leg device during + # insertion to kernel and fails during assembly + # There can be some other affected version of mdadm. + STRACE="strace -f -o /dev/null" + } - init_udev_transaction - for dev in "$@"; do - maj=$(($(stat --printf=0x%t "$dev"))) - min=$(($(stat --printf=0x%T "$dev"))) - echo "Disabling device $dev ($maj:$min)" - dmsetup remove -f "$dev" || true - notify_lvmetad --major "$maj" --minor "$min" - done - finish_udev_transaction + $STRACE mdadm --assemble "$@" + udev_wait } -enable_dev() { +cleanup_md_dev() { + local IFS=$IFS_NL + local i local dev + local base + local mddev + + test -f MD_DEV || return 0 + mddev=$(< MD_DEV) + base=$(basename "$mddev") + + # try to find and remove any DM device on top of cleaned MD + # assume /dev/mdXXX is 9:MINOR + local minor=${mddev##/dev/md} + for i in $(dmsetup table | grep 9:"$minor" | cut -d: -f1) ; do + dmsetup remove "$i" || { + dmsetup --force remove "$i" || true + } + done - init_udev_transaction - for dev in "$@"; do - local name=$(echo "$dev" | sed -e 's,.*/,,') - dmsetup create -u "TEST-$name" "$name" "$name.table" || \ - dmsetup load "$name" "$name.table" - # using device name (since device path does not exists yes with udev) - dmsetup resume "$name" - notify_lvmetad "$dev" + for i in {0..10} ; do + grep -q "$base" /proc/mdstat || break + test "$i" = 0 || { + sleep .1 + echo "$mddev is still present, stopping again" + cat /proc/mdstat + } + mdadm --stop "$mddev" || true + udev_wait # wait till events are process, not zeroing to early done - finish_udev_transaction -} -backup_dev() { - local dev + test "$DM_DEV_DIR" = "/dev" || rm -f "$(< MD_DEV_PV)" - for dev in "$@"; do - dd if="$dev" of="$dev.backup" bs=1024 + for dev in $(< MD_DEVICES); do + mdadm --zero-superblock "$dev" 2>/dev/null || true done + udev_wait + rm -f MD_DEV MD_DEVICES MD_DEV_PV } -restore_dev() { - local dev +wipefs_a() { + local have_wipefs= + + if test -e HAVE_WIPEFS; then + have_wipefs=$(< HAVE_WIPEFS) + else + wipefs -V >HAVE_WIPEFS 2>/dev/null && have_wipefs=yes + fi + + udev_wait for dev in "$@"; do - test -e "$dev.backup" || \ - die "Internal error: $dev not backed up, can't restore!" - dd of="$dev" if="$dev.backup" bs=1024 + if test -n "$LVM_TEST_DEVICES_FILE"; then + lvmdevices --deldev "$dev" || true + fi + + if test -n "$have_wipefs"; then + wipefs -a "$dev" || { + echo "$dev: device in-use, retrying wipe again." + sleep .1 + udev_wait + wipefs -a "$dev" + } + else + dd if=/dev/zero of="$dev" bs=4096 count=8 oflag=direct >/dev/null || true + mdadm --zero-superblock "$dev" 2>/dev/null || true + fi + + if test -n "$LVM_TEST_DEVICES_FILE"; then + lvmdevices --adddev "$dev" || true + fi done + + udev_wait } -prepare_pvs() { - prepare_devs "$@" - pvcreate -ff $devs +cleanup_idm_context() { + local dev=$1 + + if [ -n "$LVM_TEST_LOCK_TYPE_IDM" ]; then + sg_dev=$(sg_map26 "${dev}") + echo "Cleanup IDM context for drive ${dev} ($sg_dev)" + sg_raw -v -r 512 -o idm_tmp_data.bin "$sg_dev" \ + 88 00 01 00 00 00 00 20 FF 01 00 00 00 01 00 00 + sg_raw -v -s 512 -i idm_tmp_data.bin "$sg_dev" \ + 8E 00 FF 00 00 00 00 00 00 00 00 00 00 01 00 00 + rm idm_tmp_data.bin + fi } -prepare_vg() { - teardown_devs - prepare_pvs "$@" - vgcreate -c n $vg $devs +# +# clear device either with blkdiscard -z or fallback to 'dd' +# $1 device_path +# TODO: add support for parametrized [OPTION] usage (Not usable ATM) +# TODO: -bs blocksize (defaults 512K) +# TODO: -count count/length (defaults to whole device, otherwise in BS units) +# TODO: -seek offset/seek (defaults 0, begining of zeroing area in BS unit) +clear_devs() { + local bs= + local count= + local seek= + + while [ "$#" -ne 0 ] ; do + case "$1" in + "") ;; + "--bs") bs=$2; shift ;; + "--count") count=$2; shift ;; + "--seek") seek=$2; shift ;; + *TEST*) # Protection: only test devices with TEST in its path name can be zeroed + test -e NO_BLKDISCARD_Z || { + if blkdiscard -f -z "$1" ; then + shift + continue + fi + echo "Info: can't use 'blkdiscard -z' switch to 'dd'." + touch NO_BLKDISCARD_Z + } + + dd if=/dev/zero of="$1" bs=512K oflag=direct $seek $count || true + ;; + esac + shift + done } -lvmconf() { - LVM_TEST_LOCKING=${LVM_TEST_LOCKING:-1} - if test "$DM_DEV_DIR" = "/dev"; then - LVM_VERIFY_UDEV=${LVM_VERIFY_UDEV:-0} - else - LVM_VERIFY_UDEV=${LVM_VERIFY_UDEV:-1} +# +# corrupt device content +# $1 file_path +# $2 string/pattern search for curruption +# $3 string/pattern replacing/corruptiong +corrupt_dev() { + local a + + # search for string on a file + # Note: returned string may possibly start with other ASCII chars + # a[0] is position in file, a[1] is the actual string + a=( $(strings -t d -n 64 "$1" | grep -m 1 "$2") ) || true + + test -n "${a[0]-}" || return 0 + + # Seek for the sequence and replace it with corruption pattern + echo -n "${a[1]/$2/$3}" | LANG=C dd of="$1" bs=1 seek="${a[0]}" conv=fdatasync +} + +prepare_backing_dev() { + local size=${1=32} + shift + + if test -n "$LVM_TEST_BACKING_DEVICE"; then + IFS=',' read -r -a BACKING_DEVICE_ARRAY <<< "$LVM_TEST_BACKING_DEVICE" + + for d in "${BACKING_DEVICE_ARRAY[@]}"; do + if test ! -b "$d"; then + echo "Device $d doesn't exist!" + return 1 + fi + done fi - test -f CONFIG_VALUES || { - cat > CONFIG_VALUES <<-EOF -devices/dir = "$DM_DEV_DIR" -devices/scan = "$DM_DEV_DIR" -devices/filter = [ "a|$DM_DEV_DIR/mirror|", "a|$DM_DEV_DIR/mapper/.*pv[0-9_]*$|", "r|.*|" ] -devices/cache_dir = "$TESTDIR/etc" -devices/sysfs_scan = 0 -devices/default_data_alignment = 1 -devices/md_component_detection = 0 -log/syslog = 0 -log/indent = 1 -log/level = 9 -log/file = "$TESTDIR/debug.log" -log/overwrite = 1 -log/activation = 1 -log/verbose = 0 + + if test -f BACKING_DEV; then + BACKING_DEV=$(< BACKING_DEV) + return 0 + elif test -n "$LVM_TEST_BACKING_DEVICE"; then + BACKING_DEV=${BACKING_DEVICE_ARRAY[0]} + echo "$BACKING_DEV" > BACKING_DEV + return 0 + elif test "${LVM_TEST_PREFER_BRD-1}" = "1" && \ + test ! -d /sys/block/ram0 && \ + kernel_at_least 4 16 0 && \ + test "$size" -lt 16384; then + # try to use ramdisk if possible, but for + # big allocs (>16G) do not try to use ramdisk + # Also we can't use BRD device prior kernel 4.16 + # since they were DAX based and lvm2 often relies + # in save table loading between exiting backend device + # and bio-based 'error' device. + # However with request based DAX brd device we get this: + # device-mapper: ioctl: can't change device type after initial table load. + prepare_ramdisk "$size" "$@" && return + echo "(failed)" + fi + + prepare_loop "$size" "$@" +} + +prepare_devs() { + local n=${1:-3} + local devsize=${2:-34} + local pvname=${3:-pv} + local header_shift=1 # shift header from begin & end of device by 1MiB + + # sanlock requires more space for the internal sanlock lv + # This could probably be lower, but what are the units? + if test -n "$LVM_TEST_LOCK_TYPE_SANLOCK" ; then + devsize=1024 + fi + + touch DEVICES + prepare_backing_dev $(( n * devsize + 2 * header_shift )) + blkdiscard "$BACKING_DEV" 2>/dev/null || true + echo -n "## preparing $n devices..." + + local size=$(( devsize * 2048 )) # sectors + local count=0 + rm -f CREATE_FAILED + init_udev_transaction + for i in $(seq 1 "$n"); do + local name="${PREFIX}$pvname$i" + local dev="$DM_DEV_DIR/mapper/$name" + DEVICES[count]=$dev + count=$(( count + 1 )) + # If the backing device number can meet the requirement for PV devices, + # then allocate a dedicated backing device for PV; otherwise, rollback + # to use single backing device for device-mapper. + if [ -n "$LVM_TEST_BACKING_DEVICE" ] && [ "$n" -le ${#BACKING_DEVICE_ARRAY[@]} ]; then + echo 0 $size linear "${BACKING_DEVICE_ARRAY[$(( count - 1 ))]}" $(( header_shift * 2048 )) > "$name.table" + else + echo 0 $size linear "$BACKING_DEV" $(( ( i - 1 ) * size + ( header_shift * 2048 ) )) > "$name.table" + fi + dmsetup create -u "TEST-$name" "$name" "$name.table" || touch CREATE_FAILED & + test -f CREATE_FAILED && break; + done + wait + finish_udev_transaction + + if test -f CREATE_FAILED ; then + if test -z "$LVM_TEST_BACKING_DEVICE"; then + echo "failed" + return 1 + fi + LVM_TEST_BACKING_DEVICE= + rm -f BACKING_DEV CREATE_FAILED + prepare_devs "$@" + return $? + fi + + if [ -n "$LVM_TEST_BACKING_DEVICE" ]; then + for d in "${BACKING_DEVICE_ARRAY[@]}"; do + cnt=$(( $(blockdev --getsize64 "$d") / 1024 / 1024 )) + cnt=$(( cnt < 1000 ? cnt : 1000 )) + dd if=/dev/zero of="$d" bs=1MB count=$cnt + wipefs -a "$d" 2>/dev/null || true + cleanup_idm_context "$d" + done + fi + + # non-ephemeral devices need to be cleared between tests + test -f LOOP -o -f RAMDISK || for d in "${DEVICES[@]}"; do + # ensure disk header is always zeroed + dd if=/dev/zero of="$d" bs=32k count=1 + wipefs -a "$d" 2>/dev/null || true + done + + if test -n "$LVM_TEST_DEVICES_FILE"; then + mkdir -p "$TESTDIR/etc/lvm/devices" || true + rm "$TESTDIR/etc/lvm/devices/system.devices" || true + touch "$TESTDIR/etc/lvm/devices/system.devices" + for d in "${DEVICES[@]}"; do + lvmdevices --adddev "$d" || true + done + fi + + #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 + + printf "%s\\n" "${DEVICES[@]}" > DEVICES +# ( IFS=$'\n'; echo "${DEVICES[*]}" ) >DEVICES + echo "ok" +} + +common_dev_() { + local tgtype=$1 + local dev=$2 + local name=${dev##*/} + shift 2 + local read_ms=${1-0} + local write_ms=${2-0} + + case "$tgtype" in + delay) + test "$read_ms" -eq 0 && test "$write_ms" -eq 0 && { + # zero delay is just equivalent to 'enable_dev' + enable_dev "$dev" + return + } + shift 2 + ;; + delayzero) + shift 2 + # zero delay is just equivalent to 'zero_dev' + test "$read_ms" -eq 0 && test "$write_ms" -eq 0 && tgtype="zero" + ;; + # error|zero target does not take read_ms & write_ms only offset list + esac + + local pos + local size + local type + local pvdev + local offset + + read -r pos size type pvdev offset < "$name.table" + + for fromlen in "${@-0:}"; do + from=${fromlen%%:*} + len=${fromlen##*:} + if test "$len" = "$fromlen"; then + # Missing the colon at the end: empty len + len= + fi + test -n "$len" || len=$(( size - from )) + diff=$(( from - pos )) + if test $diff -gt 0 ; then + echo "$pos $diff $type $pvdev $(( pos + offset ))" + pos=$(( pos + diff )) + elif test $diff -lt 0 ; then + die "Position error" + fi + + case "$tgtype" in + delay) + echo "$from $len delay $pvdev $(( pos + offset )) $read_ms $pvdev $(( pos + offset )) $write_ms" ;; + writeerror) + echo "$from $len delay $pvdev $(( pos + offset )) 0 $(cat ERR_DEV) 0 0" ;; + delayzero) + echo "$from $len delay $(cat ZERO_DEV) 0 $read_ms $(cat ZERO_DEV) 0 $write_ms" ;; + error|zero) + echo "$from $len $tgtype" ;; + esac + pos=$(( pos + len )) + done > "$name.devtable" + diff=$(( size - pos )) + test "$diff" -gt 0 && echo "$pos $diff $type $pvdev $(( pos + offset ))" >>"$name.devtable" + + restore_from_devtable "$dev" +} + +# Replace linear PV device with its 'delayed' version +# Could be used to more deterministicaly hit some problems. +# Parameters: {device path} [read delay ms] [write delay ms] [offset[:[size]]]... +# Original device is restored when both delay params are 0 (or missing). +# If the size is missing, the remaing portion of device is taken +# i.e. delay_dev "$dev1" 0 200 256: +delay_dev() { + if test ! -f HAVE_DM_DELAY ; then + target_at_least dm-delay 1 1 0 || return 0 + touch HAVE_DM_DELAY + fi + common_dev_ delay "$@" +} + +disable_dev() { + local dev + local silent="" + local error="" + local notify="" + + while test -n "$1"; do + if test "$1" = "--silent"; then + silent=1 + shift + elif test "$1" = "--error"; then + error=1 + shift + else + break + fi + done + + udev_wait + for dev in "$@"; do + maj=$(($(stat -L --printf=0x%t "$dev"))) + min=$(($(stat -L --printf=0x%T "$dev"))) + echo "Disabling device $dev ($maj:$min)" + notify="$notify $maj:$min" + if test -n "$error"; then + echo 0 10000000 error | dmsetup load "$dev" + dmsetup resume "$dev" + else + dmsetup remove -f "$dev" 2>/dev/null || true + fi + done +} + +enable_dev() { + local dev + local silent="" + + if test "$1" = "--silent"; then + silent=1 + shift + fi + + rm -f debug.log strace.log + init_udev_transaction + for dev in "$@"; do + local name=${dev##*/} + dmsetup create -u "TEST-$name" "$name" "$name.table" 2>/dev/null || \ + dmsetup load "$name" "$name.table" + # using device name (since device path does not exists yes with udev) + dmsetup resume "$name" + done + finish_udev_transaction +} + +# Try to remove list of DM device from table +remove_dm_devs() { + local remove=( "$@" ) + local held + local i + + for i in {1..50}; do + held=() + for d in "${remove[@]}" ; do + dmsetup remove "$d" 2>/dev/null || { + dmsetup info -c "$d" 2>/dev/null && { + held+=( "$d" ) + dmsetup status "$d" + } + } + done + test ${#held[@]} -eq 0 && { + rm -f debug.log* + return + } + remove=( "${held[@]}" ) + done + die "Can't remove device(s) ${held[*]}" +} + +# Throttle down performance of kcopyd when mirroring i.e. disk image +throttle_sys="/sys/module/dm_mirror/parameters/raid1_resync_throttle" +throttle_dm_mirror() { + # if the kernel config file is present, validate whether the kernel uses HZ_1000 + # and return failure for this 'throttling' when it does NOT as without this setting + # whole throttling is pointless on modern hardware + local kconfig + + kconfig="/boot/config-$(uname -r)" + if test -e "$kconfig" ; then + grep -q "CONFIG_HZ_1000=y" "$kconfig" 2>/dev/null || { + echo "WARNING: CONFIG_HZ_1000=y is NOT set in $kconfig -> throttling is unusable" + return 1 + } + fi + test -e "$throttle_sys" || return + test -f THROTTLE || cat "$throttle_sys" > THROTTLE + echo "${1-1}" > "$throttle_sys" +} + +# Restore original kcopyd throttle value and have mirroring fast again +restore_dm_mirror() { + test ! -f THROTTLE || { + cat THROTTLE > "$throttle_sys" + rm -f THROTTLE + } +} + + +# Once there is $name.devtable +# this is a quick way to restore to this table entry +restore_from_devtable() { + local dev + local silent="" + + if test "$1" = "--silent"; then + silent=1 + shift + fi + + rm -f debug.log strace.log + init_udev_transaction + for dev in "$@"; do + local name=${dev##*/} + dmsetup load "$name" "$name.devtable" + if not dmsetup resume "$name" ; then + dmsetup clear "$name" + dmsetup resume "$name" + finish_udev_transaction + echo "Device $name has unusable table \"$(cat "$name.devtable")\"" + return 1 + fi + done + finish_udev_transaction +} + +# +# Convert device to device with errors +# Takes the list of pairs of error segment from:len +# Combination with zero or delay is unsupported +# Original device table is replaced with multiple lines +# i.e. error_dev "$dev1" 8:32 96:8 +error_dev() { + common_dev_ error "$@" +} + +# +# Convert device to device with write errors but normal reads. +# For this 'delay' dev is used and reroutes 'reads' back to original device +# and for writes it will use extra new TEST-errordev (huge error target) +# i.e. writeerror_dev "$dev1" 8:32 +writeerror_dev() { + local name=${PREFIX}-errordev + + if test ! -e ERR_DEV; then + # delay target is used for error mapping + if test ! -f HAVE_DM_DELAY ; then + target_at_least dm-delay 1 1 0 || return 0 + touch HAVE_DM_DELAY + fi + dmsetup create -u "TEST-$name" "$name" --table "0 4611686018427387904 error" + # Take major:minor of our error device + echo "$name" > ERR_DEV_NAME + dmsetup info -c --noheadings -o major,minor "$name" > ERR_DEV + fi + + common_dev_ writeerror "$@" +} + +# +# Convert device to device with sections of delayed zero read and writes. +# For this 'delay' dev will use extra new TEST-zerodev (huge zero target) +# and reroutes reads and writes +# i.e. delayzero_dev "$dev1" 8:32 +delayzero_dev() { + local name=${PREFIX}-zerodev + + if test ! -e ZERO_DEV; then + # delay target is used for error mapping + if test ! -f HAVE_DM_DELAY ; then + target_at_least dm-delay 1 1 0 || return 0 + touch HAVE_DM_DELAY + fi + dmsetup create -u "TEST-$name" "$name" --table "0 4611686018427387904 zero" + # Take major:minor of our error device + echo "$name" > ZERO_DEV_NAME + dmsetup info -c --noheadings -o major,minor "$name" > ZERO_DEV + fi + + common_dev_ delayzero "$@" +} + +# +# Convert existing device to a device with zero segments +# Takes the list of pairs of zero segment from:len +# Combination with error or delay is unsupported +# Original device table is replaced with multiple lines +# i.e. zero_dev "$dev1" 8:32 96:8 +zero_dev() { + common_dev_ zero "$@" +} + +backup_dev() { + local dev + + for dev in "$@"; do + dd if="$dev" of="${dev##*/}.backup" bs=16K conv=fdatasync || \ + die "Cannot backup device: \"$dev\" with size $(blockdev --getsize64 "$dev" || true) bytes." + done +} + +restore_dev() { + local dev + + for dev in "$@"; do + test -e "${dev##*/}.backup" || \ + die "Internal error: $dev not backed up, can't restore!" + dd of="$dev" if="${dev##*/}.backup" bs=16K + done +} + +prepare_pvs() { + prepare_devs "$@" + pvcreate -ff "${DEVICES[@]}" +} + +prepare_vg() { + teardown_devs + + prepare_devs "$@" + vgcreate $SHARED -s 512K "$vg" "${DEVICES[@]}" +} + +extend_devices() { + test -z "$LVM_TEST_DEVICES_FILE" && return + + for dev in "$@"; do + lvmdevices --adddev "$dev" + done +} + +extend_filter() { + local filter + + test -n "$LVM_TEST_DEVICES_FILE" && return + + filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1) + for rx in "$@"; do + filter=$(echo "$filter" | sed -e "s:\\[:[ \"$rx\", :") + done + lvmconf "$filter" "devices/scan_lvs = 1" +} + +extend_filter_md() { + local filter + + test -n "$LVM_TEST_DEVICES_FILE" && return + + filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1) + for rx in "$@"; do + filter=$(echo "$filter" | sed -e "s:\\[:[ \"$rx\", :") + done + lvmconf "$filter" + lvmconf "devices/scan = [ \"$DM_DEV_DIR\", \"/dev\" ]" +} + +extend_filter_LVMTEST() { + extend_filter "a|$DM_DEV_DIR/$PREFIX|" "$@" +} + +hide_dev() { + local filter + + if test -n "$LVM_TEST_DEVICES_FILE"; then + for dev in "$@"; do + lvmdevices --deldev "$dev" + done + else + filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1) + for dev in "$@"; do + filter=$(echo "$filter" | sed -e "s:\\[:[ \"r|$dev|\", :") + done + lvmconf "$filter" + fi +} + +unhide_dev() { + local filter + + if test -n "$LVM_TEST_DEVICES_FILE"; then + for dev in "$@"; do + lvmdevices -y --adddev "$dev" + done + else + filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1) + for dev in "$@"; do + filter=$(echo "$filter" | sed -e "s:\"r|$dev|\", ::") + done + lvmconf "$filter" + fi +} + +mkdev_md5sum() { + rm -f debug.log strace.log + mkfs.ext2 "$DM_DEV_DIR/$1/$2" || return 1 + md5sum "$DM_DEV_DIR/$1/$2" > "md5.$1-$2" +} + +generate_config() { + if test -n "$profile_name"; then + config_values="PROFILE_VALUES_$profile_name" + config="PROFILE_$profile_name" + touch "$config_values" + else + config_values=CONFIG_VALUES + config=CONFIG + fi + + LVM_TEST_LOCKING=${LVM_TEST_LOCKING:-1} + LVM_TEST_LVMPOLLD=${LVM_TEST_LVMPOLLD:-0} + LVM_TEST_LVMLOCKD=${LVM_TEST_LVMLOCKD:-0} + LVM_TEST_DEVICES_FILE=${LVM_TEST_DEVICES_FILE:-0} + # FIXME:dct: This is harmful! Variables are unused here and are tested not being empty elsewhere: + #LVM_TEST_LOCK_TYPE_SANLOCK=${LVM_TEST_LOCK_TYPE_SANLOCK:-0} + #LVM_TEST_LOCK_TYPE_DLM=${LVM_TEST_LOCK_TYPE_DLM:-0} + if test "$DM_DEV_DIR" = "/dev"; then + LVM_VERIFY_UDEV=${LVM_VERIFY_UDEV:-0} + else + LVM_VERIFY_UDEV=${LVM_VERIFY_UDEV:-1} + fi + test -f "$config_values" || { + cat > "$config_values" <<-EOF +activation/checks = 1 +activation/monitoring = 0 +activation/polling_interval = 1 activation/retry_deactivation = 1 -backup/backup = 0 +activation/snapshot_autoextend_percent = 50 +activation/snapshot_autoextend_threshold = 50 +activation/verify_udev_operations = $LVM_VERIFY_UDEV +activation/raid_region_size = 512 +allocation/wipe_signatures_when_zeroing_new_lvs = 0 +allocation/vdo_slab_size_mb = 128 +allocation/zero_metadata = 0 backup/archive = 0 +backup/backup = 0 +devices/cache_dir = "$LVM_SYSTEM_DIR" +devices/default_data_alignment = 1 +devices/dir = "$DM_DEV_DIR" +devices/md_component_detection = 0 +devices/scan = "$DM_DEV_DIR" +devices/sysfs_scan = 1 +devices/write_cache_state = 0 +devices/use_devicesfile = $LVM_TEST_DEVICES_FILE +devices/filter = "a|.*|" +devices/global_filter = [ "a|$DM_DEV_DIR/mapper/${PREFIX}.*pv[0-9_]*$|", "r|.*|" ] global/abort_on_internal_errors = 1 +global/cache_check_executable = "$LVM_TEST_CACHE_CHECK_CMD" +global/cache_dump_executable = "$LVM_TEST_CACHE_DUMP_CMD" +global/cache_repair_executable = "$LVM_TEST_CACHE_REPAIR_CMD" +global/cache_restore_executable = "$LVM_TEST_CACHE_RESTORE_CMD" global/detect_internal_vg_cache_corruption = 1 -global/library_dir = "$TESTDIR/lib" -global/locking_dir = "$TESTDIR/var/lock/lvm" +global/fallback_to_local_locking = 0 +global/etc = "$LVM_SYSTEM_DIR" global/locking_type=$LVM_TEST_LOCKING +global/notify_dbus = 0 global/si_unit_consistency = 1 -global/fallback_to_local_locking = 0 -activation/checks = 1 -activation/udev_sync = 1 +global/thin_check_executable = "$LVM_TEST_THIN_CHECK_CMD" +global/thin_dump_executable = "$LVM_TEST_THIN_DUMP_CMD" +global/thin_repair_executable = "$LVM_TEST_THIN_REPAIR_CMD" +global/thin_restore_executable = "$LVM_TEST_THIN_RESTORE_CMD" +global/use_lvmpolld = $LVM_TEST_LVMPOLLD +global/use_lvmlockd = $LVM_TEST_LVMLOCKD +log/activation = 1 +log/file = "$TESTDIR/debug.log" +log/indent = 1 +log/level = 9 +log/overwrite = 1 +log/syslog = 0 +log/verbose = 0 +EOF + # For 'rpm' builds use system installed binaries + # and libraries and locking dir and some more built-in + # defaults + # For test suite run use binaries from builddir. + test -z "${abs_top_builddir+varset}" || { + cat >> "$config_values" <<-EOF +dmeventd/executable = "$abs_top_builddir/test/lib/dmeventd" activation/udev_rules = 1 -activation/verify_udev_operations = $LVM_VERIFY_UDEV -activation/polling_interval = 0 -activation/snapshot_autoextend_percent = 50 -activation/snapshot_autoextend_threshold = 50 -activation/monitoring = 0 +activation/udev_sync = 1 +global/fsadm_executable = "$abs_top_builddir/test/lib/fsadm" +global/library_dir = "$TESTDIR/lib" +global/locking_dir = "$TESTDIR/var/lock/lvm" EOF + } } + # append all parameters (avoid adding empty \n) local v - for v in "$@"; do - echo "$v" >> CONFIG_VALUES - done + test $# -gt 0 && printf "%s\\n" "$@" >> "$config_values" + + declare -A CONF 2>/dev/null || { + # Associative arrays is not available + local s + for s in $(cut -f1 -d/ "$config_values" | sort | uniq); do + echo "$s {" + local k + for k in $(grep ^"$s"/ "$config_values" | cut -f1 -d= | sed -e 's, *$,,' | sort | uniq); do + grep "^${k}[ \t=]" "$config_values" | tail -n 1 | sed -e "s,^$s/, ," || true + done + echo "}" + echo + done | tee "$config" | sed -e "s,^,## LVMCONF: ," + return 0 + } + + local sec + local last_sec="" + + # read sequential list and put into associative array + while IFS= read -r v; do + CONF["${v%%[={ ]*}"]=${v#*/} + done < "$config_values" + + # sort by section and iterate through them + printf "%s\\n" "${!CONF[@]}" | sort | while read -r v ; do + sec=${v%%/*} # split on section'/'param_name + test "$sec" = "$last_sec" || { + test -z "$last_sec" || echo "}" + echo "$sec {" + last_sec=$sec + } + echo " ${CONF[$v]}" + done > "$config" + echo "}" >> "$config" + + sed -e "s,^,## LVMCONF: ," "$config" +} - rm -f CONFIG - local s - for s in $(cat CONFIG_VALUES | cut -f1 -d/ | sort | uniq); do - echo "$s {" >> CONFIG - local k - for k in $(grep ^"$s"/ CONFIG_VALUES | cut -f1 -d= | sed -e 's, *$,,' | sort | uniq); do - grep "^$k" CONFIG_VALUES | tail -n 1 | sed -e "s,^$s/, ," >> CONFIG +lvmconf() { + local profile_name="" + test $# -eq 0 || { + # Compare if passed args aren't already all in generated lvm.conf + local needed=0 + for i in "$@"; do + val=$(grep "${i%%[={ ]*}" CONFIG_VALUES 2>/dev/null | tail -1) || { needed=1; break; } + test "$val" = "$i" || { needed=1; break; } done - echo "}" >> CONFIG - echo >> CONFIG - done - mv -f CONFIG etc/lvm.conf + test "$needed" -eq 0 && { + echo "## Skipping reconfiguring for: (" "$@" ")" + return 0 # not needed + } + } + generate_config "$@" + mv -f CONFIG "$LVM_SYSTEM_DIR/lvm.conf" } -apitest() { - local t=$1 +profileconf() { + local pdir="$LVM_SYSTEM_DIR/profile" + local profile_name=$1 shift - test -x "$abs_top_builddir/test/api/$t.t" || skip - "$abs_top_builddir/test/api/$t.t" "$@" && rm -f debug.log + generate_config "$@" + mkdir -p "$pdir" + mv -f "PROFILE_$profile_name" "$pdir/$profile_name.profile" +} + +prepare_profiles() { + local pdir="$LVM_SYSTEM_DIR/profile" + local profile_name + mkdir -p "$pdir" + for profile_name in "$@"; do + test -L "lib/$profile_name.profile" || skip + cp "lib/$profile_name.profile" "$pdir/$profile_name.profile" + done } -api() { - test -x "$abs_top_builddir/test/api/wrapper" || skip - "$abs_top_builddir/test/api/wrapper" "$@" && rm -f debug.log +unittest() { + test -x "$TESTOLDPWD/unit/unit-test" || skip + "$TESTOLDPWD/unit/unit-test" "${@}" +} + +mirror_recovery_works() { + case "$(uname -r)" in + 3.3.4-5.fc17.i686|3.3.4-5.fc17.x86_64) return 1 ;; + esac +} + +raid456_replace_works() { +# The way kmem_cache aliasing is done in the kernel is broken. +# It causes RAID 4/5/6 tests to fail. +# +# The problem with kmem_cache* is this: +# *) Assume CONFIG_SLUB is set +# 1) kmem_cache_create(name="foo-a") +# - creates new kmem_cache structure +# 2) kmem_cache_create(name="foo-b") +# - If identical cache characteristics, it will be merged with the previously +# created cache associated with "foo-a". The cache's refcount will be +# incremented and an alias will be created via sysfs_slab_alias(). +# 3) kmem_cache_destroy() +# - Attempting to destroy cache associated with "foo-a", but instead the +# refcount is simply decremented. I don't even think the sysfs aliases are +# ever removed... +# 4) kmem_cache_create(name="foo-a") +# - This FAILS because kmem_cache_sanity_check colides with the existing +# name ("foo-a") associated with the non-removed cache. +# +# This is a problem for RAID (specifically dm-raid) because the name used +# for the kmem_cache_create is ("raid%d-%p", level, mddev). If the cache +# persists for long enough, the memory address of an old mddev will be +# reused for a new mddev - causing an identical formulation of the cache +# name. Even though kmem_cache_destory had long ago been used to delete +# the old cache, the merging of caches has cause the name and cache of that +# old instance to be preserved and causes a colision (and thus failure) in +# kmem_cache_create(). I see this regularly in testing the following +# kernels: +# +# This seems to be finaly resolved with this patch: +# http://www.redhat.com/archives/dm-devel/2014-March/msg00008.html +# so we need to put here exlusion for kernes which do trace SLUB +# + case "$(uname -r)" in + 3.6.*.fc18.i686*|3.6.*.fc18.x86_64) return 1 ;; + 3.9.*.fc19.i686*|3.9.*.fc19.x86_64) return 1 ;; + 3.1[0123].*.fc18.i686*|3.1[0123].*.fc18.x86_64) return 1 ;; + 3.1[01234].*.fc19.i686*|3.1[01234].*.fc19.x86_64) return 1 ;; + 3.1[123].*.fc20.i686*|3.1[123].*.fc20.x86_64) return 1 ;; + 3.14.*.fc21.i686*|3.14.*.fc21.x86_64) return 1 ;; + 3.15.*rc6*.fc21.i686*|3.15.*rc6*.fc21.x86_64) return 1 ;; + 3.16.*rc4*.fc21.i686*|3.16.*rc4*.fc21.x86_64) return 1 ;; + esac +} + +# +# Some 32bit kernel cannot pass some erroring magic which forces +# thin-pool to be falling into Error state. +# +# Skip test on such kernels (see: https://bugzilla.redhat.com/1310661) +# +thin_pool_error_works_32() { + case "$(uname -r)" in + 2.6.32-618.*.i686) return 1 ;; + 2.6.32-623.*.i686) return 1 ;; + 2.6.32-573.1[28].1.el6.i686) return 1 ;; + esac +} + +thin_restore_needs_more_volumes() { + case $("$LVM_TEST_THIN_RESTORE_CMD" -V) in + # With older version of thin-tool we got slightly more compact metadata + 0.[0-6]*|0.7.0*) return 0 ;; + 0.8.5-2.el7) return 0 ;; + esac + return 1 } udev_wait() { pgrep udev >/dev/null || return 0 - which udevadm >/dev/null || return 0 - if test -n "$1" ; then - udevadm settle --exit-if-exists="$1" || true + which udevadm &>/dev/null || return 0 + if test -n "${1-}" ; then + udevadm settle --exit-if-exists="$1" 2>/dev/null || true else - udevadm settle --timeout=15 || true + udevadm settle --timeout=15 2>/dev/null || true fi } # wait_for_sync wait_for_sync() { local i - for i in {1..500} ; do - check in_sync $1 $2 && return + for i in {1..100} ; do + check in_sync "$@" && return sleep .2 done echo "Sync is taking too long - assume stuck" + echo t >/proc/sysrq-trigger 2>/dev/null + return 1 +} + +wait_recalc() { + local checklv=$1 + + for i in {1..100} ; do + sync=$(get lv_field "$checklv" sync_percent | cut -d. -f1) + echo "sync_percent is $sync" + + test "$sync" = "100" && return + + sleep .1 + done + + # TODO: There is some strange bug, first leg of RAID with integrity + # enabled never gets in sync. I saw this in BB, but not when executing + # the commands manually +# if test -z "$sync"; then +# echo "TEST\ WARNING: Resync of dm-integrity device '$checklv' failed" +# dmsetup status "$DM_DEV_DIR/mapper/${checklv/\//-}" +# exit +# fi + echo "Timeout waiting for recalc" + dmsetup status "$DM_DEV_DIR/mapper/${checklv/\//-}" return 1 } +# Check if tests are running on 64bit architecture +can_use_16T() { + test "$(getconf LONG_BIT)" -eq 64 +} + +# Check if major.minor.revision' string is 'at_least' +version_at_least() { + local major + local minor + local revision + IFS=".-" read -r major minor revision <<< "$1" + shift + + test -n "${1:-}" || return 0 + test -n "$major" || return 1 + test "$major" -gt "$1" && return 0 + test "$major" -eq "$1" || return 1 + + test -n "${2:-}" || return 0 + test -n "$minor" || return 1 + test "$minor" -gt "$2" && return 0 + test "$minor" -eq "$2" || return 1 + + test -n "${3:-}" || return 0 + test "$revision" -ge "$3" 2>/dev/null || return 1 +} # # Check wheter kernel [dm module] target exist # at least in expected version @@ -503,49 +1816,255 @@ wait_for_sync() { # [dm-]target-name major minor revision # # i.e. dm_target_at_least dm-thin-pool 1 0 -target_at_least() -{ +target_at_least() { + rm -f debug.log strace.log case "$1" in + dm-vdo) modprobe "kvdo" || true ;; dm-*) modprobe "$1" || true ;; esac - local version=$(dmsetup targets 2>/dev/null | grep "${1##dm-} " 2>/dev/null) - version=${version##* v} - shift + if test "$1" = dm-raid; then + case "$(uname -r)" in + 3.12.0*) return 1 ;; + esac + fi - local major=$(echo "$version" | cut -d. -f1) - test -z "$1" && return 0 - test -n "$major" || return 1 - test "$major" -gt "$1" && return 0 - test "$major" -eq "$1" || return 1 + local version + version=$(dmsetup targets 2>/dev/null | grep "^${1##dm-} " 2>/dev/null) + version=${version##* v} - test -z "$2" && return 0 - local minor=$(echo "$version" | cut -d. -f2) - test -n "$minor" || return 1 - test "$minor" -gt "$2" && return 0 - test "$minor" -eq "$2" || return 1 + version_at_least "$version" "${@:2}" || { + echo "Found $1 version $version, but requested ${*:2}." >&2 + return 1 + } +} - test -z "$3" && return 0 - local revision=$(echo "$version" | cut -d. -f3) - test "$revision" -ge "$3" 2>/dev/null || return 1 +# Check whether the kernel driver version is greater or equal +# to the specified version. This can be used to skip tests on +# kernels where they are known to not be supported. +# +# e.g. driver_at_least 4 33 +# +driver_at_least() { + local version + version=$(dmsetup version | tail -1 2>/dev/null) + version=${version##*:} + version_at_least "$version" "$@" || { + echo "Found driver version $version, but requested" "$@" "." >&2 + return 1 + } } -have_thin() -{ - target_at_least dm-thin-pool "$@" || exit 1 - test "$THIN" = shared || test "$THIN" = internal || exit 1 +have_thin() { + lvm segtypes 2>/dev/null | grep thin$ >/dev/null || { + echo "Thin is not built-in." >&2 + return 1 + } + target_at_least dm-thin-pool "$@" + declare -a CONF=() # disable thin_check if not present in system - which thin_check || lvmconf 'global/thin_check_executable = ""' + if test -n "$LVM_TEST_THIN_CHECK_CMD" && test ! -x "$LVM_TEST_THIN_CHECK_CMD"; then + CONF[0]="global/thin_check_executable = \"\"" + fi + if test -n "$LVM_TEST_THIN_DUMP_CMD" && test ! -x "$LVM_TEST_THIN_DUMP_CMD"; then + CONF[1]="global/thin_dump_executable = \"\"" + fi + if test -n "$LVM_TEST_THIN_REPAIR_CMD" && test ! -x "$LVM_TEST_THIN_REPAIR_CMD"; then + CONF[2]="global/thin_repair_executable = \"\"" + fi + if test ${#CONF[@]} -ne 0 ; then + echo "TEST WARNING: Reconfiguring" "${CONF[@]}" + lvmconf "${CONF[@]}" + fi +} + +have_vdo() { + lvm segtypes 2>/dev/null | grep 'vdo$' >/dev/null || { + echo "VDO is not built-in." >&2 + return 1 + } + target_at_least dm-vdo "$@" +} + +have_writecache() { + lvm segtypes 2>/dev/null | grep 'writecache$' >/dev/null || { + echo "writecache is not built-in." >&2 + return 1 + } + target_at_least dm-writecache "$@" +} + +have_integrity() { + lvm segtypes 2>/dev/null | grep 'integrity$' >/dev/null || { + echo "integrity is not built-in." >&2 + return 1 + } + target_at_least dm-integrity "$@" +} + +have_raid() { + target_at_least dm-raid "$@" + + # some kernels have broken mdraid bitmaps, don't use them! + # may oops kernel, we know for sure all FC24 are currently broken + # in general any 4.1, 4.2 is likely useless unless patched + case "$(uname -r)" in + 4.[12].*fc24*) return 1 ;; + esac +} + +have_raid4 () { + local r=0 + + have_raid 1 8 0 && r=1 + have_raid 1 9 1 && r=0 + + return $r +} + +have_cache() { + lvm segtypes 2>/dev/null | grep ' cache-pool$' >/dev/null || { + echo "Cache is not built-in." >&2 + return 1 + } + target_at_least dm-cache "$@" + + declare -a CONF=() + # disable cache_check if not present in system + if test -n "$LVM_TEST_CACHE_CHECK_CMD" && test ! -x "$LVM_TEST_CACHE_CHECK_CMD" ; then + CONF[0]="global/cache_check_executable = \"\"" + fi + if test -n "$LVM_TEST_CACHE_DUMP_CMD" && test ! -x "$LVM_TEST_CACHE_DUMP_CMD" ; then + CONF[1]="global/cache_dump_executable = \"\"" + fi + if test -n "$LVM_TEST_CACHE_REPAIR_CMD" && test ! -x "$LVM_TEST_CACHE_REPAIR_CMD" ; then + CONF[2]="global/cache_repair_executable = \"\"" + fi + if test ${#CONF[@]} -ne 0 ; then + echo "TEST WARNING: Reconfiguring" "${CONF[@]}" + lvmconf "${CONF[@]}" + fi +} + +have_tool_at_least() { + local version + version=$("$1" -V 2>/dev/null) + version=${version%%-*} + version=${version##* } + shift + + version_at_least "$version" "$@" } # check if lvm shell is build-in (needs readline) -have_readline() -{ +have_readline() { echo version | lvm &>/dev/null } -test -f DEVICES && devs=$(cat DEVICES) +have_multi_core() { + which nproc &>/dev/null || return 0 + [ "$(nproc)" -ne 1 ] +} + +dmsetup_wrapped() { + udev_wait + dmsetup "$@" +} + +awk_parse_init_count_in_lvmpolld_dump() { + printf '%s' \ + \ + $'BEGINFILE { x=0; answ=0 }' \ + $'{' \ + $'if (/.*{$/) { x++ }' \ + $'else if (/.*}$/) { x-- }' \ + $'else if ( x == 2 && $1 ~ "[[:space:]]*"vkey) { value=substr($2, 2); value=substr(value, 1, length(value) - 1); }' \ + $'if ( x == 2 && value == vvalue && $1 ~ /[[:space:]]*init_requests_count/) { answ=$2 }' \ + $'if (answ > 0) { exit 0 }' \ + $'}' \ + $'END { printf "%d", answ }' +} + +check_lvmpolld_init_rq_count() { + local ret + ret=$(awk -v vvalue="$2" -v vkey="${3:-lvname}" -F= "$(awk_parse_init_count_in_lvmpolld_dump)" lvmpolld_dump.txt) + test "$ret" -eq "$1" || { + die "check_lvmpolld_init_rq_count failed. Expected $1, got $ret" + } +} + +wait_pvmove_lv_ready() { + # given sleep .1 this is about 20 secs of waiting + local lvid=() + local all + + for i in {100..0}; do + if [ -e LOCAL_LVMPOLLD ]; then + if test "${#lvid[@]}" -eq "$#" ; then + lvmpolld_dump > lvmpolld_dump.txt + all=1 + for l in "${lvid[@]}" ; do + check_lvmpolld_init_rq_count 1 "${l##LVM-}" lvid || all=0 + done + test "$all" = 1 && return + else + # wait till wanted LV really appears + lvid=( $(dmsetup info --noheadings -c -o uuid "$@" 2>/dev/null) ) || true + fi + else + dmsetup info -c --noheadings -o tables_loaded "$@" >out 2>/dev/null || true + test "$(grep -c Live out)" = "$#" && return + fi + sleep .1 + done + + test -e LOCAL_LVMPOLLD && die "Waiting for lvmpolld timed out" + die "Waiting for pvmove LV to get activated has timed out" +} + +# Holds device open with sleep which automatically expires after given timeout +# Prints PID of running holding sleep process in background +hold_device_open() { + local vgname=$1 + local lvname=$2 + local sec=${3-20} # default 20sec + + sleep "$sec" < "$DM_DEV_DIR/$vgname/$lvname" >/dev/null 2>&1 & + SLEEP_PID=$! + # wait till device is openned + for i in $(seq 1 50) ; do + if test "$(dmsetup info --noheadings -c -o open "$vgname"-"$lvname")" -ne 0 ; then + echo "$SLEEP_PID" + return + fi + sleep .1 + done + + die "$vgname-$lvname expected to be openned, but it's not!" +} + +# return total memory size in kB units +total_mem() { + local a + local b + + while IFS=":" read -r a b ; do + case "$a" in MemTotal*) echo "${b%% kB}" ; break ;; esac + done < /proc/meminfo +} + +kernel_at_least() { + version_at_least "$(uname -r)" "$@" +} + +test "${LVM_TEST_AUX_TRACE-0}" = "0" || set -x + +test -f DEVICES && devs=$(< DEVICES) -#unset LVM_VALGRIND -"$@" +if test "$1" = "dmsetup" ; then + shift + dmsetup_wrapped "$@" +else + "$@" +fi diff --git a/test/lib/brick-shelltest.h b/test/lib/brick-shelltest.h new file mode 100644 index 0000000..af28105 --- /dev/null +++ b/test/lib/brick-shelltest.h @@ -0,0 +1,1340 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- + +/* + * This brick allows you to build a test runner for shell-based functional + * tests. It comes with fairly elaborate features (although most are only + * available on posix systems), geared toward difficult-to-test software. + * + * It provides a full-featured "main" function (brick::shelltest::run) that you + * can use as a drop-in shell test runner. + * + * Features include: + * - interactive and batch-mode execution + * - collects test results and test logs in a simple text-based format + * - measures resource use of individual tests + * - rugged: suited for running in monitored virtual machines + * - supports test flavouring + */ + +/* + * (c) 2014 Petr Rockai + * (c) 2014 Red Hat, Inc. + */ + +/* Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __unix +#include +#include /* rusage */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +/* Timeout for the whole test suite in hours */ +static const time_t TEST_SUITE_TIMEOUT = 4; + +#ifndef BRICK_SHELLTEST_H +#define BRICK_SHELLTEST_H + +namespace brick { +namespace shelltest { + +/* TODO: remove this section in favour of brick-filesystem.h */ + +inline std::runtime_error syserr( std::string msg, std::string ctx = "" ) { + return std::runtime_error( std::string( strerror( errno ) ) + " " + msg + " " + ctx ); +} + +struct dir { + DIR *d; + dir( std::string p ) { + d = opendir( p.c_str() ); + if ( !d ) + throw syserr( "error opening directory", p ); + } + ~dir() { (void) closedir( d ); } +}; + +typedef std::vector< std::string > Listing; + +inline void fsync_name( std::string n ) +{ + int fd = open( n.c_str(), O_WRONLY ); + if ( fd >= 0 ) { + (void) fsync( fd ); + (void) close( fd ); + } +} + +inline Listing listdir( std::string p, bool recurse = false, std::string prefix = "" ) +{ + Listing r; + + dir d( p ); +#if !defined(__GLIBC__) || (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 23)) + /* readdir_r is deprecated with newer GLIBC */ + struct dirent entry, *iter = 0; + while ( (errno = readdir_r( d.d, &entry, &iter )) == 0 && iter ) { + std::string ename( entry.d_name ); +#else + struct dirent *entry; + errno = 0; + while ( (entry = readdir( d.d )) ) { + std::string ename( entry->d_name ); +#endif + + if ( ename == "." || ename == ".." ) + continue; + + if ( recurse ) { + struct stat64 stat; + std::string s = p + "/" + ename; + if ( ::stat64( s.c_str(), &stat ) == -1 ) { + errno = 0; + continue; + } + if ( S_ISDIR(stat.st_mode) ) { + Listing sl = listdir( s, true, prefix + ename + "/" ); + for ( Listing::iterator i = sl.begin(); i != sl.end(); ++i ) + r.push_back( prefix + *i ); + } else + r.push_back( prefix + ename ); + } else + r.push_back( ename ); + }; + + if ( errno != 0 ) + throw syserr( "error reading directory", p ); + + return r; +} + +/* END remove this section */ + +struct Journal { + enum R { + STARTED, + RETRIED, + UNKNOWN, + FAILED, + INTERRUPTED, + KNOWNFAIL, + PASSED, + SKIPPED, + TIMEOUT, + WARNED, + }; + + friend std::ostream &operator<<( std::ostream &o, R r ) { + switch ( r ) { + case STARTED: return o << "started"; + case RETRIED: return o << "retried"; + case FAILED: return o << "failed"; + case INTERRUPTED: return o << "interrupted"; + case PASSED: return o << "passed"; + case SKIPPED: return o << "skipped"; + case TIMEOUT: return o << "timeout"; + case WARNED: return o << "warnings"; + default: return o << "unknown"; + } + } + + friend std::istream &operator>>( std::istream &i, R &r ) { + std::string x; + i >> x; + + r = UNKNOWN; + if ( x == "started" ) r = STARTED; + if ( x == "retried" ) r = RETRIED; + if ( x == "failed" ) r = FAILED; + if ( x == "interrupted" ) r = INTERRUPTED; + if ( x == "passed" ) r = PASSED; + if ( x == "skipped" ) r = SKIPPED; + if ( x == "timeout" ) r = TIMEOUT; + if ( x == "warnings" ) r = WARNED; + return i; + } + + template< typename S, typename T > + friend std::istream &operator>>( std::istream &i, std::pair< S, T > &r ) { + return i >> r.first >> r.second; + } + + typedef std::map< std::string, R > Status; + Status status, written; + + std::string location, list; + int timeouts; + + void append( std::string path ) { + std::ofstream of( path.c_str(), std::fstream::app ); + Status::iterator writ; + for ( Status::iterator i = status.begin(); i != status.end(); ++i ) { + writ = written.find( i->first ); + if ( writ == written.end() || writ->second != i->second ) + of << i->first << " " << i->second << std::endl; + } + written = status; + of.close(); + } + + void write( std::string path ) { + std::ofstream of( path.c_str() ); + for ( Status::iterator i = status.begin(); i != status.end(); ++i ) + of << i->first << " " << i->second << std::endl; + of.close(); + } + + void sync() { + append( location ); + fsync_name( location ); + write ( list ); + fsync_name( list ); + } + + void started( std::string n ) { + if ( status.count( n ) && status[ n ] == STARTED ) + status[ n ] = RETRIED; + else + status[ n ] = STARTED; + sync(); + } + + void done( std::string n, R r ) { + status[ n ] = r; + if ( r == TIMEOUT ) + ++ timeouts; + else + timeouts = 0; + sync(); + } + + bool done( std::string n ) { + if ( !status.count( n ) ) + return false; + return status[ n ] != STARTED && status[ n ] != INTERRUPTED; + } + + int count( R r ) { + int c = 0; + for ( Status::iterator i = status.begin(); i != status.end(); ++i ) + if ( i->second == r ) + ++ c; + return c; + } + + void banner() { + std::cout << std::endl << "### " << status.size() << " tests: " + << count( PASSED ) << " passed, " + << count( SKIPPED ) << " skipped, " + << count( TIMEOUT ) << " timed out, " << count( WARNED ) << " warned, " + << count( FAILED ) << " failed" << std::endl; + } + + void details() { + for ( Status::iterator i = status.begin(); i != status.end(); ++i ) + if ( i->second != PASSED ) + std::cout << i->second << ": " << i->first << std::endl; + } + + void read( std::string n ) { + std::ifstream ifs( n.c_str() ); + typedef std::istream_iterator< std::pair< std::string, R > > It; + for ( It i( ifs ); i != It(); ++i ) + status[ i->first ] = i->second; + } + + void read() { read( location ); } + + Journal( std::string dir ) + : location( dir + "/journal" ), + list( dir + "/list" ), + timeouts( 0 ) + {} +}; + +struct TimedBuffer { + typedef std::pair< time_t, std::string > Line; + + std::deque< Line > data; + Line incomplete; + bool stamp; + + Line shift( bool force = false ) { + Line result = std::make_pair( 0, "" ); + if ( force && data.empty() ) + std::swap( result, incomplete ); + else { + result = data.front(); + data.pop_front(); + } + return result; + } + + void push( std::string buf ) { + time_t now = stamp ? time( 0 ) : 0; + std::string::iterator b = buf.begin(), e = buf.begin(); + + while ( e != buf.end() ) + { + e = std::find( b, buf.end(), '\n' ); + incomplete.second += std::string( b, e ); + + if ( !incomplete.first ) + incomplete.first = now; + + if ( e != buf.end() ) { + incomplete.second += "\n"; + data.push_back( incomplete ); + if (incomplete.second[0] == '#') { + /* Disable timing between '## 0 STACKTRACE' & '## teardown' keywords */ + if (incomplete.second.find("# 0 STACKTRACE", 1) != std::string::npos || + incomplete.second.find("# timing off", 1) != std::string::npos) { + stamp = false; + now = 0; + } else if (incomplete.second.find("# teardown", 1) != std::string::npos || + incomplete.second.find("# timing on", 1) != std::string::npos) { + stamp = true; + now = time( 0 ); + } + } + incomplete = std::make_pair( now, "" ); + } + b = (e == buf.end() ? e : e + 1); + } + } + + bool empty( bool force = false ) { + if ( force && !incomplete.second.empty() ) + return false; + return data.empty(); + } + + TimedBuffer() : stamp(true) {} +}; + +struct Sink { + virtual void outline( bool ) {} + virtual void push( std::string x ) = 0; + virtual void sync( bool ) {} + virtual ~Sink() {} +}; + +struct Substitute { + typedef std::map< std::string, std::string > Map; + std::string testdir; // replace testdir first + std::string prefix; + + std::string map( std::string line ) { + return line; + } +}; + +struct Format { + time_t start; + Substitute subst; + + std::string format( TimedBuffer::Line l ) { + std::stringstream result; + if ( l.first >= start ) { + time_t rel = l.first - start; + result << "[" << std::setw( 2 ) << std::setfill( ' ' ) << rel / 60 + << ":" << std::setw( 2 ) << std::setfill( '0' ) << rel % 60 << "] "; + } + result << subst.map( l.second ); + return result.str(); + } + + Format() : start( time( 0 ) ) {} +}; + +struct BufSink : Sink { + TimedBuffer data; + Format fmt; + + virtual void push( std::string x ) { + data.push( x ); + } + + void dump( std::ostream &o ) { + o << std::endl; + while ( !data.empty( true ) ) + o << "| " << fmt.format( data.shift( true ) ); + } +}; + +struct FdSink : Sink { + int fd; + + TimedBuffer stream; + Format fmt; + bool killed; + + virtual void outline( bool force ) + { + TimedBuffer::Line line = stream.shift( force ); + std::string out = fmt.format( line ); + if ( write( fd, out.c_str(), out.length() ) < (int)out.length() ) + perror( "short write" ); + } + + virtual void sync( bool force ) { + if ( killed ) + return; + while ( !stream.empty( force ) ) + outline( force ); + } + + virtual void push( std::string x ) { + if ( !killed ) + stream.push( x ); + } + + FdSink( int _fd ) : fd( _fd ), killed( false ) {} +}; + +struct FileSink : FdSink { + std::string file; + FileSink( std::string n ) : FdSink( -1 ), file( n ) {} + + void sync( bool force ) { + if ( fd < 0 && !killed ) { +#ifdef O_CLOEXEC + fd = open( file.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644 ); +#else + fd = open( file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644 ); + if ( fcntl( fd, F_SETFD, FD_CLOEXEC ) < 0 ) + perror("failed to set FD_CLOEXEC on file"); +#endif + if ( fd < 0 ) + killed = true; + } + FdSink::sync( force ); + } + + ~FileSink() { + if ( fd >= 0 ) { + (void) fsync( fd ); + (void) close( fd ); + } + } +}; + +#define BRICK_SYSLOG_ACTION_READ 2 +#define BRICK_SYSLOG_ACTION_READ_ALL 3 +#define BRICK_SYSLOG_ACTION_READ_CLEAR 4 +#define BRICK_SYSLOG_ACTION_CLEAR 5 +#define BRICK_SYSLOG_ACTION_SIZE_UNREAD 9 +#define BRICK_SYSLOG_ACTION_SIZE_BUFFER 10 + +struct Source { + int fd; + + virtual void sync( Sink *sink ) { + ssize_t sz; + /* coverity[stack_use_local_overflow] */ + char buf[ 128 * 1024 ]; + if ( (sz = read(fd, buf, sizeof(buf) - 1)) > 0 ) + sink->push( std::string( buf, sz ) ); + + /* + * On RHEL5 box this code busy-loops here, while + * parent process no longer writes anything. + * + * Unclear why 'select()' is anouncing available + * data, while we read 0 bytes with errno == 0. + * + * Temporarily resolved with usleep() instead of loop. + */ + if (!sz && (!errno || errno == EINTR)) + usleep(50000); + + if ( sz < 0 && errno != EAGAIN ) + throw syserr( "reading pipe" ); + } + + virtual void reset() {} + + virtual int fd_set_( fd_set *set ) { + if ( fd >= 0 ) { + FD_SET( fd, set ); + return fd; + } else + return -1; + } + + Source( int _fd = -1 ) : fd( _fd ) {} + virtual ~Source() { + if ( fd >= 0 ) + (void) ::close( fd ); + } +}; + +struct FileSource : Source { + std::string file; + FileSource( std::string n ) : Source( -1 ), file( n ) {} + + int fd_set_( ::fd_set * ) { return -1; } /* reading a file is always non-blocking */ + void sync( Sink *s ) { + if ( fd < 0 ) { +#ifdef O_CLOEXEC + fd = open( file.c_str(), O_RDONLY | O_CLOEXEC | O_NONBLOCK ); +#else + fd = open( file.c_str(), O_RDONLY | O_NONBLOCK ); + if ( fcntl( fd, F_SETFD, FD_CLOEXEC ) < 0 ) + perror("failed to set FD_CLOEXEC on file"); +#endif + if ( fd >= 0 ) + lseek( fd, 0, SEEK_END ); + } + if ( fd >= 0 ) + try { + Source::sync( s ); + } catch (...) { + perror("failed to sync"); + } + } +}; + +struct KMsg : Source { + bool can_clear; + ssize_t buffer_size; + + KMsg() : can_clear( strcmp(getenv("LVM_TEST_CAN_CLOBBER_DMESG") ? : "0", "0") ), + buffer_size(128 * 1024) + { +#ifdef __unix + struct utsname uts; + unsigned kmaj, kmin, krel; + const char *read_msg = "/dev/kmsg"; + + // Can't use kmsg on kernels pre 3.5, read /var/log/messages + if ( ( ::uname(&uts) == 0 ) && + ( ::sscanf( uts.release, "%u.%u.%u", &kmaj, &kmin, &krel ) == 3 ) && + ( ( kmaj < 3 ) || ( ( kmaj == 3 ) && ( kmin < 5 ) ) ) ) + can_clear = false, read_msg = "/var/log/messages"; + + if ( ( fd = open(read_msg, O_RDONLY | O_NONBLOCK)) < 0 ) { + if ( errno != ENOENT ) /* Older kernels (<3.5) do not support /dev/kmsg */ + fprintf( stderr, "open log %s %s\n", read_msg, strerror( errno ) ); + if ( can_clear && ( klogctl( BRICK_SYSLOG_ACTION_CLEAR, 0, 0 ) < 0 ) ) + can_clear = false; + } else if ( lseek( fd, 0L, SEEK_END ) == (off_t) -1 ) { + fprintf( stderr, "lseek log %s %s\n", read_msg, strerror( errno ) ); + (void) close(fd); + fd = -1; + } +#endif + } + + bool dev_kmsg() { + return fd >= 0; + } + + void sync( Sink *s ) { +#ifdef __unix + ssize_t sz; + char buf[ buffer_size ]; + + if ( dev_kmsg() ) { + while ( (sz = ::read(fd, buf, buffer_size)) > 0 ) + s->push( std::string( buf, sz ) ); + } else if ( can_clear ) { + while ( ( sz = klogctl( BRICK_SYSLOG_ACTION_READ_CLEAR, buf, + ( int) buffer_size ) ) > 0 ) + s->push( std::string( buf, sz ) ); + if ( sz < 0 && errno == EPERM ) + can_clear = false; + } +#endif + } +}; + +struct Observer : Sink { + TimedBuffer stream; + + bool warnings; + Observer() : warnings( false ) {} + + void push( std::string s ) { + stream.push( s ); + } + + void sync( bool force ) { + while ( !stream.empty( force ) ) { + TimedBuffer::Line line = stream.shift( force ); + if ( line.second.find( "TEST WARNING" ) != std::string::npos ) + warnings = true; + } + } +}; + +struct IO : Sink { + typedef std::vector< Sink* > Sinks; + typedef std::vector< Source* > Sources; + + mutable Sinks sinks; + mutable Sources sources; + + Observer *_observer; + + virtual void push( std::string x ) { + for ( Sinks::iterator i = sinks.begin(); i != sinks.end(); ++i ) + (*i)->push( x ); + } + + void sync( bool force ) { + for ( Sources::iterator i = sources.begin(); i != sources.end(); ++i ) + (*i)->sync( this ); + + for ( Sinks::iterator i = sinks.begin(); i != sinks.end(); ++i ) + (*i)->sync( force ); + } + + void close() { + for ( Sources::iterator i = sources.begin(); i != sources.end(); ++i ) + delete *i; + sources.clear(); + } + + int fd_set_( fd_set *set ) { + int max = -1; + + for ( Sources::iterator i = sources.begin(); i != sources.end(); ++i ) + max = std::max( (*i)->fd_set_( set ), max ); + return max + 1; + } + + Observer &observer() { return *_observer; } + + IO() { + clear(); + } + + /* a stealing copy constructor */ + IO( const IO &io ) : sinks( io.sinks ), sources( io.sources ), _observer( io._observer ) + { + io.sinks.clear(); + io.sources.clear(); + } + + IO &operator= ( const IO &io ) { + this->~IO(); + return *new (this) IO( io ); + } + + void clear( int to_push = 1 ) { + for ( Sinks::iterator i = sinks.begin(); i != sinks.end(); ++i ) + delete *i; + sinks.clear(); + if ( to_push ) + sinks.push_back( _observer = new Observer ); + } + + ~IO() { close(); clear(0); } + +}; + +namespace { +pid_t kill_pid = 0; +bool fatal_signal = false; +bool interrupt = false; +} + +struct Options { + bool verbose, batch, interactive, cont, fatal_timeouts, kmsg; + std::string testdir, outdir, workdir, heartbeat; + std::vector< std::string > flavours, filter, skip, watch; + std::string flavour_envvar; + int timeout; + Options() : verbose( false ), batch( false ), interactive( false ), + cont( false ), fatal_timeouts( false ), kmsg( true ), + timeout( 180 ) {} +}; + +struct TestProcess +{ + std::string filename; + bool interactive; + int fd; + + void exec() __attribute__ ((noreturn)) { + assert( fd >= 0 ); + if ( !interactive ) { + int devnull = ::open( "/dev/null", O_RDONLY ); + if ( devnull >= 0 ) { /* gcc really doesn't like to not have stdin */ + (void) dup2( devnull, STDIN_FILENO ); + (void) close( devnull ); + } else + (void) close( STDIN_FILENO ); + (void) dup2( fd, STDOUT_FILENO ); + (void) dup2( fd, STDERR_FILENO ); + (void) close( fd ); + } + + setpgid( 0, 0 ); + + execlp( "bash", "bash", "-noprofile", "-norc", filename.c_str(), NULL ); + perror( "execlp" ); + _exit( 202 ); + } + + TestProcess( std::string file ) + : filename( file ), interactive( false ), fd( -1 ) + {} +}; + +struct TestCase { + TestProcess child; + std::string name, flavour; + IO io; + BufSink *iobuf; + + struct rusage usage; + int status; + bool timeout; + pid_t pid; + + time_t start, end, silent_start, last_update, last_heartbeat; + Options options; + + Journal *journal; + + std::string pretty() { + if ( options.batch ) + return flavour + ": " + name; + return "[" + flavour + "] " + name; + } + + std::string id() { + return flavour + ":" + name; + } + + void pipe() { + int fds[2] = { 0 }; + + if (socketpair( PF_UNIX, SOCK_STREAM, 0, fds )) { + perror("socketpair"); + exit(201); + } + +#if 0 + if (fcntl( fds[0], F_SETFL, O_NONBLOCK ) == -1) { + perror("fcntl on socket"); + exit(202); + } +#endif + + io.sources.push_back( new Source( fds[0] ) ); + child.fd = fds[1]; + child.interactive = options.interactive; + } + + bool monitor() { + end = time( 0 ); + + /* heartbeat */ + if ( end - last_heartbeat >= 20 && !options.heartbeat.empty() ) { + std::ofstream hb( options.heartbeat.c_str(), std::fstream::app ); + hb << "."; + hb.close(); + fsync_name( options.heartbeat ); + last_heartbeat = end; + } + + if ( wait4(pid, &status, WNOHANG, &usage) != 0 ) { + io.sync( true ); + return false; + } + + /* kill off tests after a timeout silence */ + if ( !options.interactive ) + if ( end - silent_start > options.timeout ) { + kill( pid, SIGINT ); + sleep( 5 ); /* wait a bit for a reaction */ + if ( waitpid( pid, &status, WNOHANG ) == 0 ) { + system( "echo t > /proc/sysrq-trigger 2> /dev/null" ); + kill( -pid, SIGKILL ); + (void) waitpid( pid, &status, 0 ); + } + timeout = true; + io.sync( true ); + return false; + } + + struct timeval wait; + fd_set set; + + FD_ZERO( &set ); + int nfds = io.fd_set_( &set ); + wait.tv_sec = 0; + wait.tv_usec = 500000; /* timeout 0.5s */ + + if ( !options.verbose && !options.interactive && !options.batch ) { + if ( end - last_update >= 1 ) { + progress( Update ) << tag( "running" ) << pretty() << " " + << end - start << std::flush; + last_update = end; + } + } + if ( select( nfds, &set, NULL, NULL, &wait ) > 0 ) { + silent_start = end; /* something happened */ + io.sync( false ); + } + + return true; + } + + std::string timefmt( time_t t ) { + std::stringstream ss; + ss << t / 60 << ":" << std::setw( 2 ) << std::setfill( '0' ) << t % 60; + return ss.str(); + } + + std::string rusage() + { + std::stringstream ss; + time_t wall = end - start, user = usage.ru_utime.tv_sec, + system = usage.ru_stime.tv_sec; + size_t rss = usage.ru_maxrss / 1024, + inb = usage.ru_inblock / 100, + outb = usage.ru_oublock / 100; + + size_t inb_10 = inb % 10, outb_10 = outb % 10; + inb /= 10; outb /= 10; + + ss << timefmt( wall ) << " wall " << timefmt( user ) << " user " + << timefmt( system ) << " sys " << std::setw( 3 ) << rss << "M RSS | " + << "IOPS: " << std::setw( 5 ) << inb << "." << inb_10 << "K in " + << std::setw( 5 ) << outb << "." << outb_10 << "K out"; + return ss.str(); + } + + std::string tag( std::string n ) { + if ( options.batch ) + return "## "; + size_t pad = n.length(); + pad = (pad < 12) ? 12 - pad : 0; + return "### " + std::string( pad, ' ' ) + n + ": "; + } + + std::string tag( Journal::R r ) { + std::stringstream s; + s << r; + return tag( s.str() ); + } + + enum P { First, Update, Last }; + + std::ostream &progress( P p = Last ) + { + static struct : std::streambuf {} buf; + static std::ostream null(&buf); + + if ( options.batch && p == First ) + return std::cout; + + if ( isatty( STDOUT_FILENO ) && !options.batch ) { + if ( p != First ) + return std::cout << "\r"; + return std::cout; + } + + if ( p == Last ) + return std::cout; + + return null; + } + + void parent() + { + (void) ::close( child.fd ); + setupIO(); + + journal->started( id() ); + silent_start = start = time( 0 ); + + progress( First ) << tag( "running" ) << pretty() << std::flush; + if ( options.verbose || options.interactive ) + progress() << std::endl; + + while ( monitor() ) + /* empty */ ; + + Journal::R r = Journal::UNKNOWN; + + if ( timeout ) { + r = Journal::TIMEOUT; + } else if ( WIFEXITED( status ) ) { + if ( WEXITSTATUS( status ) == 0 ) + r = Journal::PASSED; + else if ( WEXITSTATUS( status ) == 200 ) + r = Journal::SKIPPED; + else + r = Journal::FAILED; + } else if ( interrupt && WIFSIGNALED( status ) && WTERMSIG( status ) == SIGINT ) + r = Journal::INTERRUPTED; + else + r = Journal::FAILED; + + if ( r == Journal::PASSED && io.observer().warnings ) + r = Journal::WARNED; + + io.close(); + + if ( iobuf && ( r == Journal::FAILED || r == Journal::TIMEOUT ) ) + iobuf->dump( std::cout ); + + journal->done( id(), r ); + + if ( options.batch ) { + int spaces = std::max( 64 - int(pretty().length()), 0 ); + progress( Last ) << " " << std::string( spaces, '.' ) << " " + << std::left << std::setw( 9 ) << std::setfill( ' ' ) << r; + if ( r != Journal::SKIPPED ) + progress( First ) << " " << rusage(); + progress( Last ) << std::endl; + } else + progress( Last ) << tag( r ) << pretty() << std::endl; + + io.clear(); + } + + void run() { + pipe(); + pid = kill_pid = fork(); + if (pid < 0) { + perror("Fork failed."); + exit(201); + } else if (pid == 0) { + io.close(); + (void) chdir( options.workdir.c_str() ); + if ( !options.flavour_envvar.empty() ) + (void) setenv( options.flavour_envvar.c_str(), flavour.c_str(), 1 ); + child.exec(); + } else { + parent(); + } + } + + void setupIO() { + iobuf = 0; + if ( options.verbose || options.interactive ) + io.sinks.push_back( new FdSink( 1 ) ); + else if ( !options.batch ) + io.sinks.push_back( iobuf = new BufSink() ); + + std::string n = id(); + std::replace( n.begin(), n.end(), '/', '_' ); + std::string fn = options.outdir + "/" + n + ".txt"; + io.sinks.push_back( new FileSink( fn ) ); + + for ( std::vector< std::string >::iterator i = options.watch.begin(); + i != options.watch.end(); ++i ) + io.sources.push_back( new FileSource( *i ) ); + if ( options.kmsg ) + io.sources.push_back( new KMsg ); + } + + TestCase( Journal &j, Options opt, std::string path, std::string _name, std::string _flavour ) + : child( path ), name( _name ), flavour( _flavour ), + iobuf( NULL ), usage( (struct rusage) { { 0 } } ), status( 0 ), timeout( false ), + pid( 0 ), start( 0 ), end( 0 ), silent_start( 0 ), + last_update( 0 ), last_heartbeat( 0 ), options( opt ), journal( &j ) + { + } +}; + +struct Main { + bool die; + time_t start; + + typedef std::vector< TestCase > Cases; + typedef std::vector< std::string > Flavours; + + Journal journal; + Options options; + Cases cases; + + void setup() { + bool filter; + Listing l = listdir( options.testdir, true ); + std::sort( l.begin(), l.end() ); + + for ( Flavours::iterator flav = options.flavours.begin(); + flav != options.flavours.end(); ++flav ) { + + for ( Listing::iterator i = l.begin(); i != l.end(); ++i ) { + if ( ( i->length() < 3 ) || ( i->substr( i->length() - 3, i->length() ) != ".sh" ) ) + continue; + if ( i->substr( 0, 4 ) == "lib/" ) + continue; + + if (!options.filter.empty()) { + filter = true; + for ( std::vector< std::string >::iterator filt = options.filter.begin(); + filt != options.filter.end(); ++filt ) { + if ( i->find( *filt ) != std::string::npos ) { + filter = false; + break; + } + } + if ( filter ) + continue; + } + + if (!options.skip.empty()) { + filter = false; + for ( std::vector< std::string >::iterator filt = options.skip.begin(); + filt != options.skip.end(); ++filt ) { + if ( i->find( *filt ) != std::string::npos ) { + filter = true; + break; + } + } + if ( filter ) + continue; + } + + cases.push_back( TestCase( journal, options, options.testdir + *i, *i, *flav ) ); + cases.back().options = options; + } + } + + if ( options.cont ) + journal.read(); + else + (void) ::unlink( journal.location.c_str() ); + } + + int run() { + setup(); + start = time( 0 ); + std::cerr << "running " << cases.size() << " tests" << std::endl; + + for ( Cases::iterator i = cases.begin(); i != cases.end(); ++i ) { + + if ( options.cont && journal.done( i->id() ) ) + continue; + + i->run(); + + if ( options.fatal_timeouts && journal.timeouts >= 2 ) { + journal.started( i->id() ); // retry the test on --continue + std::cerr << "E: Hit 2 timeouts in a row with --fatal-timeouts" << std::endl; + std::cerr << "Suspending (please restart the VM)." << std::endl; + sleep( 3600 ); + die = 1; + } + + if ( time(0) - start > (TEST_SUITE_TIMEOUT * 3600) ) { + std::cerr << TEST_SUITE_TIMEOUT << " hours passed, giving up..." << std::endl; + die = 1; + } + + if ( die || fatal_signal ) + break; + } + + journal.banner(); + if ( die || fatal_signal ) + return 1; + + return journal.count( Journal::FAILED ) || journal.count( Journal::TIMEOUT ) ? 1 : 0; + } + + Main( Options o ) : die( false ), start( 0 ), journal( o.outdir ), options( o ) {} +}; + +namespace { + +void handler( int sig ) { + signal( sig, SIG_DFL ); /* die right away next time */ + if ( kill_pid > 0 ) + kill( -kill_pid, sig ); + fatal_signal = true; + if ( sig == SIGINT ) + interrupt = true; +} + +void setup_handlers() { + /* set up signal handlers */ + for ( int i = 0; i <= 32; ++i ) + switch (i) { + case SIGCHLD: case SIGWINCH: case SIGURG: + case SIGKILL: case SIGSTOP: break; + default: signal(i, handler); + } +} + +} + +/* TODO remove in favour of brick-commandline.h */ +struct Args { + typedef std::vector< std::string > V; + V args; + + Args( int argc, const char **argv ) { + for ( int i = 1; i < argc; ++ i ) + args.push_back( argv[ i ] ); + } + + bool has( std::string fl ) { + return std::find( args.begin(), args.end(), fl ) != args.end(); + } + + // TODO: This does not handle `--option=VALUE`: + std::string opt( std::string fl ) { + V::iterator i = std::find( args.begin(), args.end(), fl ); + if ( i == args.end() || i + 1 == args.end() ) + return ""; + return *(i + 1); + } +}; + +namespace { + +bool hasenv( const char *name ) { + const char *v = getenv( name ); + if ( !v ) + return false; + if ( strlen( v ) == 0 || !strcmp( v, "0" ) ) + return false; + return true; +} + +template< typename C > +void split( std::string s, C &c ) { + std::stringstream ss( s ); + std::string item; + while ( std::getline( ss, item, ',' ) ) + c.push_back( item ); +} + +} + +const char *DEF_FLAVOURS="ndev-vanilla"; + +std::string resolve_path(std::string a_path, const char *default_path=".") +{ + char temp[PATH_MAX]; + const char *p; + p = a_path.empty() ? default_path : a_path.c_str(); + if ( !realpath( p, temp ) ) + throw syserr( "Failed to resolve path", p ); + return temp; +} + +static int run( int argc, const char **argv, std::string fl_envvar = "TEST_FLAVOUR" ) +{ + Args args( argc, argv ); + Options opt; + + if ( args.has( "--help" ) ) { + std::cout << + " lvm2-testsuite - Run a lvm2 testsuite.\n\n" + "lvm2-testsuite" + "\n\t" + " [--flavours FLAVOURS]" + " [--only TESTS]" + "\n\t" + " [--outdir OUTDIR]" + " [--testdir TESTDIR]" + " [--workdir WORKDIR]" + "\n\t" + " [--batch|--verbose|--interactive]" + "\n\t" + " [--fatal-timeouts]" + " [--continue]" + " [--heartbeat]" + " [--watch WATCH]" + " [--timeout TIMEOUT]" + " [--nokmsg]\n\n" + /* TODO: list of flavours: + "lvm2-testsuite" + "\n\t" + " --list-flavours [--testdir TESTDIR]" + */ + "\n\n" + "OPTIONS:\n\n" + // TODO: looks like this could be worth a man page... + "Filters:\n" + " --flavours FLAVOURS\n\t\t- comma separated list of flavours to run.\n\t\t For the list of flavours see `$TESTDIR/lib/flavour-*`.\n\t\t Default: \"" << DEF_FLAVOURS << "\".\n" + " --only TESTS\t- comma separated list of tests to run. Default: All tests.\n" + "\n" + "Directories:\n" + " --testdir TESTDIR\n\t\t- directory where tests reside. Default: \"" TESTSUITE_DATA "\".\n" + " --workdir WORKDIR\n\t\t- directory to change to when running tests.\n\t\t This is directory containing testing libs. Default: TESTDIR.\n" + " --outdir OUTDIR\n\t\t- directory where all the output files should go. Default: \".\".\n" + "\n" + "Formatting:\n" + " --batch\t- Brief format for automated runs.\n" + " --verbose\t- More verbose format for automated runs displaying progress on stdout.\n" + " --interactive\t- Verbose format for interactive runs.\n" + "\n" + "Other:\n" + " --fatal-timeouts\n\t\t- exit after encountering 2 timeouts in a row.\n" + " --continue\t- If set append to journal. Otherwise it will be overwritten.\n" + " --heartbeat HEARTBEAT\n\t\t- Name of file to update periodicaly while running.\n" + " --watch WATCH\t- Comma separated list of files to watch and print.\n" + " --timeout TIMEOUT\n\t\t- Period of silence in seconds considered a timeout. Default: 180.\n" + " --nokmsg\t- Do not try to read kernel messages.\n" + "\n\n" + "ENV.VARIABLES:\n\n" + " T\t\t- see --only\n" + " INTERACTIVE\t- see --interactive\n" + " VERBOSE\t- see --verbose\n" + " BATCH\t\t- see --batch\n" + " LVM_TEST_CAN_CLOBBER_DMESG\n\t\t- when set and non-empty tests are allowed to flush\n\t\t kmsg in an attempt to read it." + "\n\n" + "FORMATS:\n\n" + "When multiple formats are specified interactive overrides verbose\n" + "which overrides batch. Command line options override environment\n" + "variables.\n\n" + ; + return 0; + } + + opt.flavour_envvar = fl_envvar; + + if ( args.has( "--continue" ) ) + opt.cont = true; + + if ( args.has( "--only" ) ) + split( args.opt( "--only" ), opt.filter ); + else if ( hasenv( "T" ) ) + split( getenv( "T" ), opt.filter ); + + if ( args.has( "--skip" ) ) + split( args.opt( "--skip" ), opt.skip ); + else if ( hasenv( "S" ) ) + split( getenv( "S" ), opt.skip ); + + if ( args.has( "--fatal-timeouts" ) ) + opt.fatal_timeouts = true; + + if ( args.has( "--heartbeat" ) ) + opt.heartbeat = args.opt( "--heartbeat" ); + + if ( args.has( "--batch" ) || args.has( "--verbose" ) || args.has( "--interactive" ) ) { + if ( args.has( "--batch" ) ) { + opt.verbose = false; + opt.batch = true; + } + + if ( args.has( "--verbose" ) ) { + opt.batch = false; + opt.verbose = true; + } + + if ( args.has( "--interactive" ) ) { + opt.verbose = false; + opt.batch = false; + opt.interactive = true; + } + } else { + if ( hasenv( "BATCH" ) ) { + opt.verbose = false; + opt.batch = true; + } + + if ( hasenv( "VERBOSE" ) ) { + opt.batch = false; + opt.verbose = true; + } + + if ( hasenv( "INTERACTIVE" ) ) { + opt.verbose = false; + opt.batch = false; + opt.interactive = true; + } + } + + if ( args.has( "--flavours" ) ) + split( args.opt( "--flavours" ), opt.flavours ); + else + split( DEF_FLAVOURS, opt.flavours ); + + if ( args.has( "--watch" ) ) + split( args.opt( "--watch" ), opt.watch ); + + if ( args.has( "--timeout" ) ) + opt.timeout = atoi( args.opt( "--timeout" ).c_str() ); + + if ( args.has( "--nokmsg" ) ) + opt.kmsg = false; + + opt.testdir = resolve_path( args.opt( "--testdir" ), TESTSUITE_DATA ) + "/"; + opt.workdir = resolve_path( args.opt( "--workdir" ), opt.testdir.c_str() ); + opt.outdir = resolve_path( args.opt( "--outdir" ), "." ); + + setup_handlers(); + + Main main( opt ); + return main.run(); +} + +} +} + +#endif + +#ifdef BRICK_DEMO + +int main( int argc, const char **argv ) { + return brick::shelltest::run( argc, argv ); +} + +#endif + +// vim: syntax=cpp tabstop=4 shiftwidth=4 expandtab diff --git a/test/lib/check.sh b/test/lib/check.sh index 6b7849f..1f26194 100644 --- a/test/lib/check.sh +++ b/test/lib/check.sh @@ -1,5 +1,5 @@ -#!/bin/bash -# Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash +# Copyright (C) 2010-2013 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 @@ -7,7 +7,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # check.sh: assert various things about volumes @@ -25,7 +25,8 @@ test -z "$BASH" || set -e -o pipefail die() { - echo "$@" >&2 + rm -f debug.log + echo -e "$@" >&2 return 1 } @@ -39,36 +40,71 @@ lvdevices() { mirror_images_redundant() { local vg=$1 - local lv=$vg/$2 - lvs -a $vg -o+devices - for i in $(lvdevices $lv); do + local lv="$vg/$2" + for i in $(lvdevices "$lv"); do echo "# $i:" - lvdevices $vg/$i | sort | uniq + 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 || \ + test "$(wc -l < check.tmp)" -eq 0 || \ die "mirror images of $lv expected redundant, but are not:" \ - $(cat check.tmp.all) + "$(cat check.tmp.all)" } +lv_err_list_() { + (echo "$2" | not grep -m 1 -q "$1") || \ + echo "$3 on [ $(echo "$2" | grep "$1" | cut -b3- | tr '\n' ' ')] " +} + +lv_on_diff_() { + declare -a xdevs=("${!1}") # pass in shell array + local expect=( "${@:4}" ) # make an array starting from 4th args... + local diff_e + + # Find diff between 2 shell arrays, print them as stdin files + printf "%s\\n" "${expect[@]}" | sort | uniq >_lv_on_diff1 + printf "%s\\n" "${xdevs[@]}" >_lv_on_diff2 + diff_e=$(diff _lv_on_diff1 _lv_on_diff2) || + die "LV $2/$3 $(lv_err_list_ "^>" "${diff_e}" found)$(lv_err_list_ "^<" "${diff_e}" "not found")." +} + +# list devices for given LV lv_on() { - local lv=$1/$2 - (lvdevices $lv | grep -F "$3") || \ - die "LV $lv expected on $3 but is not:" \ - $(lvdevices $lv) - test $(lvdevices $lv | grep -vF "$3" | wc -l) -eq 0 || \ - die "LV $lv contains unexpected devices:" \ - $(lvdevices $lv) + local devs + + devs=( $(lvdevices "$1/$2" | sort | uniq ) ) + + lv_on_diff_ devs[@] "$@" } +# list devices for given LV and all its subdevices +lv_tree_on() { + local devs + + # Get sorted list of devices + devs=( $(get lv_tree_devices "$1" "$2") ) + + lv_on_diff_ devs[@] "$@" +} + +# Test if all mimage_X LV legs are sitting on given ordered list of PVs +# When LV is composed of imagetmp, such leg is decomposed so only +# real _mimage LVs are always checked mirror_images_on() { local vg=$1 local lv=$2 shift 2 - for i in $(lvdevices $lv); do - lv_on $vg $lv $1 + local mimages=() + local line + + while IFS= read -r line ; do + mimages+=( "$line" ) + done < <( get lv_field_lv_ "$vg" lv_name -a | grep "${lv}_mimage_" ) + + for i in "${mimages[@]}"; do + lv_on "$vg" "$i" "$1" shift done } @@ -78,170 +114,263 @@ mirror_log_on() { local lv=$2 local where=$3 if test "$where" = "core"; then - get lv_field $vg/$lv mirror_log | not grep mlog + get lv_field "$vg/$lv" mirror_log | not grep mlog else - lv_on $vg ${lv}_mlog "$where" + lv_on "$vg" "${lv}_mlog" "$where" fi } lv_is_contiguous() { - local lv=$1/$2 - test $(lvl --segments $lv | wc -l) -eq 1 || \ + local lv="$1/$2" + test "$(lvl --segments "$lv" | wc -l)" -eq 1 || \ die "LV $lv expected to be contiguous, but is not:" \ - $(lvl --segments $lv) + "$(lvl --segments "$lv")" } lv_is_clung() { - local lv=$1/$2 - test $(lvdevices $lv | sort | uniq | wc -l) -eq 1 || \ + local lv="$1/$2" + test "$(lvdevices "$lv" | sort | uniq | wc -l)" -eq 1 || \ die "LV $lv expected to be clung, but is not:" \ - $(lvdevices $lv | sort | uniq) + "$(lvdevices "$lv" | sort | uniq)" } mirror_images_contiguous() { - for i in $(lvdevices $1/$2); do - lv_is_contiguous $1 $i + 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 + for i in $(lvdevices "$1/$2"); do + lv_is_clung "$1" "$i" done } mirror() { mirror_nonredundant "$@" - mirror_images_redundant $1 $2 + mirror_images_redundant "$1" "$2" } mirror_nonredundant() { - local lv=$1/$2 - local attr=$(get lv_field $lv attr) - (echo "$attr" | grep "^m........$" >/dev/null) || { - if (echo "$attr" | grep "^o........$" >/dev/null) && - lvs -a | fgrep "[${2}_mimage" >/dev/null; then + local lv="$1/$2" + local attr + attr=$(get lv_field "$lv" attr) + (echo "$attr" | grep "^......m...$" >/dev/null) || { + if (echo "$attr" | grep "^o.........$" >/dev/null) && + lvs -a "$1" | grep -F "[${2}_mimage" >/dev/null; then echo "TEST WARNING: $lv is a snapshot origin and looks like a mirror," echo "assuming it is actually a mirror" else die "$lv expected a mirror, but is not:" \ - $(lvs $lv) + "$(lvs "$lv")" fi } - test -z "$3" || mirror_log_on $1 $2 "$3" + test -z "$3" || mirror_log_on "$1" "$2" "$3" } mirror_legs() { - local expect=$3 - test "$expect" -eq $(lvdevices $1/$2 | wc -w) + local expect_legs=$3 + test "$expect_legs" -eq "$(lvdevices "$1/$2" | wc -w)" } mirror_no_temporaries() { local vg=$1 local lv=$2 - (lvl -o name $vg | grep $lv | not grep "tmp") || \ + (lvl -o name "$vg" | grep "$lv" | not grep "tmp") || \ die "$lv has temporary mirror images unexpectedly:" \ - $(lvl $vg | grep $lv) + "$(lvl "$vg" | grep "$lv")" } linear() { - local lv=$1/$2 - test $(get lv_field $lv stripes -a) -eq 1 || \ + local lv="$1/$2" + test "$(get lv_field "$lv" stripes -a)" -eq 1 || \ die "$lv expected linear, but is not:" \ - $(lvl $lv -o+devices) + "$(lvl "$lv" -o+devices)" } -# in_sync +# in_sync # Works for "mirror" and "raid*" in_sync() { local a local b + local c local idx local type + local snap="" local lvm_name="$1/$2" - local dm_name=$(echo $lvm_name | sed s:-:--: | sed s:/:-:) + local ignore_a=${3:-0} + local dm_name="$1-$2" - if ! a=(`dmsetup status $dm_name`); then + a=( $(dmsetup status "$dm_name") ) || \ die "Unable to get sync status of $1" - elif [ ${a[2]} = "snapshot-origin" ]; then - if ! a=(`dmsetup status ${dm_name}-real`); then + + if [ "${a[2]}" = "snapshot-origin" ]; then + a=( $(dmsetup status "${dm_name}-real") ) || \ die "Unable to get sync status of $1" - fi + snap=": under snapshot" fi - if [ ${a[2]} = "raid" ]; then - # Last argument is the sync ratio for RAID - idx=$((${#a[@]} - 1)) + case "${a[2]}" in + "raid") + # 6th argument is the sync ratio for RAID + idx=6 type=${a[3]} - elif [ ${a[2]} = "mirror" ]; then + if [ "${a[$(( idx + 1 ))]}" != "idle" ]; then + echo "$lvm_name ($type$snap) is not in-sync " "${a[@]}" + return 1 + fi + ;; + "mirror") # 4th Arg tells us how far to the sync ratio - idx=$((${a[3]} + 4)) + idx=$(( a[3] + 4 )) type=${a[2]} - else + ;; + *) die "Unable to get sync ratio for target type '${a[2]}'" - fi + ;; + esac - b=( $(echo ${a[$idx]} | sed s:/:' ':) ) + b=${a[$idx]%%/*} # split ratio x/y + c=${a[$idx]##*/} - if [ ${b[0]} != ${b[1]} ]; then - echo "$lvm_name ($type) is not in-sync" + if [ "$b" -eq 0 ] || [ "$b" != "$c" ]; then + echo "$lvm_name ($type$snap) is not in-sync " "${a[@]}" return 1 fi - if [[ ${a[$(($idx - 1))]} =~ a ]]; then - die "$lvm_name in-sync, but 'a' characters in health status" + if [[ ${a[$(( idx - 1 ))]} =~ a ]] ; then + [ "$ignore_a" = 0 ] && \ + die "$lvm_name ($type$snap) in-sync, but 'a' characters in health status" + echo "$lvm_name ($type$snap) is not in-sync " "${a[@]}" + [ "$ignore_a" = 1 ] && return 0 + return 1 fi - echo "$lvm_name ($type) is in-sync" - return 0 + echo "$lvm_name ($type$snap) is in-sync " "${a[@]}" } active() { - local lv=$1/$2 - (get lv_field $lv attr | grep "^....a....$" >/dev/null) || \ + local lv="$1/$2" + (get lv_field "$lv" attr | grep "^....a.....$" >/dev/null) || \ die "$lv expected active, but lvs says it's not:" \ - $(lvl $lv -o+devices) - dmsetup info $1-$2 >/dev/null || + "$(lvl "$lv" -o+devices)" + dmsetup info "$1-$2" >/dev/null || die "$lv expected active, lvs thinks it is but there are no mappings!" } inactive() { - local lv=$1/$2 - (get lv_field $lv attr | grep "^....[-isd]....$" >/dev/null) || \ + local lv="$1/$2" + (get lv_field "$lv" attr | grep "^....[-isd].....$" >/dev/null) || \ die "$lv expected inactive, but lvs says it's not:" \ - $(lvl $lv -o+devices) - not dmsetup info $1-$2 2>/dev/null || \ - die "$lv expected inactive, lvs thinks it is but there are mappings!" + "$(lvl "$lv" -o+devices)" + not dmsetup info "$1-$2" 2>/dev/null || \ + die "$lv expected inactive, lvs thinks it is but there are mappings!" } # Check for list of LVs from given VG lv_exists() { local vg=$1 - local lv= + declare -a list=() while [ $# -gt 1 ]; do shift - lv="$lv $vg/$1" + list+=( "$vg/$1" ) done - lvl $lv &>/dev/null || \ - die "$lv expected to exist but does not" + test "${#list[@]}" -gt 0 || list=( "$vg" ) + lvl "${list[@]}" &>/dev/null || \ + die "${list[@]}" "expected to exist, but does not!" +} + +lv_not_exists() { + local vg=$1 + if test $# -le 1 ; then + if lvl "$vg" &>/dev/null ; then + die "$vg expected to not exist but it does!" + fi + else + while [ $# -gt 1 ]; do + shift + not lvl "$vg/$1" &>/dev/null || die "$vg/$1 expected to not exist but it does!" + done + fi + rm -f debug.log } pv_field() { - local actual=$(get pv_field "$1" "$2" "${@:4}") + local actual + actual=$(get pv_field "$1" "$2" "${@:4}") test "$actual" = "$3" || \ die "pv_field: PV=\"$1\", field=\"$2\", actual=\"$actual\", expected=\"$3\"" } vg_field() { - local actual=$(get vg_field $1 "$2" "${@:4}") + local actual + actual=$(get vg_field "$1" "$2" "${@:4}") test "$actual" = "$3" || \ die "vg_field: vg=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\"" } +vg_attr_bit() { + local actual + local offset=$1 + actual=$(get vg_field "$2" vg_attr "${@:4}") + case "$offset" in + perm*) offset=0 ;; + resiz*) offset=1 ;; + export*) offset=2 ;; + partial) offset=3 ;; + alloc*) offset=4 ;; + cluster*) offset=5 ;; + esac + test "${actual:$offset:1}" = "$3" || \ + die "vg_attr_bit: vg=$2, ${offset} bit of \"$actual\" is \"${actual:$offset:1}\", but expected \"$3\"" +} + lv_field() { - local actual=$(get lv_field $1 "$2" "${@:4}") + local actual + actual=$(get lv_field "$1" "$2" "${@:4}") test "$actual" = "$3" || \ - die "lv_field: lv=$lv, field=\"$2\", actual=\"$actual\", expected=\"$3\"" + die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\"" +} + +lv_first_seg_field() { + local actual + actual=$(get lv_first_seg_field "$1" "$2" "${@:4}") + test "$actual" = "$3" || \ + die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\"" +} + +lvh_field() { + local actual + actual=$(get lvh_field "$1" "$2" "${@:4}") + test "$actual" = "$3" || \ + die "lvh_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\"" +} + +lva_field() { + local actual + actual=$(get lva_field "$1" "$2" "${@:4}") + test "$actual" = "$3" || \ + die "lva_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\"" +} + +lv_attr_bit() { + local actual + local offset=$1 + actual=$(get lv_field "$2" lv_attr "${@:4}") + case "$offset" in + type) offset=0 ;; + perm*) offset=1 ;; + alloc*) offset=2 ;; + fixed*) offset=3 ;; + state) offset=4 ;; + open) offset=5 ;; + target) offset=6 ;; + zero) offset=7 ;; + health) offset=8 ;; + skip) offset=9 ;; + esac + test "${actual:$offset:1}" = "$3" || \ + die "lv_attr_bit: lv=$2, ${offset} bit of \"$actual\" is \"${actual:$offset:1}\", but expected \"$3\"" } compare_fields() { @@ -251,8 +380,10 @@ compare_fields() { local cmd2=$4 local obj2=$5 local field2=$6 - local val1=$($cmd1 --noheadings -o "$field1" "$obj1") - local val2=$($cmd2 --noheadings -o "$field2" "$obj2") + local val1 + local val2 + val1=$("$cmd1" --noheadings -o "$field1" "$obj1") + val2=$("$cmd2" --noheadings -o "$field2" "$obj2") test "$val1" = "$val2" || \ die "compare_fields $obj1($field1): $val1 $obj2($field2): $val2" } @@ -261,8 +392,10 @@ compare_vg_field() { local vg1=$1 local vg2=$2 local field=$3 - local val1=$(vgs --noheadings -o "$field" $vg1) - local val2=$(vgs --noheadings -o "$field" $vg2) + local val1 + local val2 + val1=$(vgs --noheadings -o "$field" "$vg1") + val2=$(vgs --noheadings -o "$field" "$vg2") test "$val1" = "$val2" || \ die "compare_vg_field: $vg1: $val1, $vg2: $val2" } @@ -272,11 +405,62 @@ pvlv_counts() { local num_pvs=$2 local num_lvs=$3 local num_snaps=$4 - lvs -o+devices $local_vg - vg_field $local_vg pv_count $num_pvs - vg_field $local_vg lv_count $num_lvs - vg_field $local_vg snap_count $num_snaps + lvs -o+devices "$local_vg" + vg_field "$local_vg" pv_count "$num_pvs" + vg_field "$local_vg" lv_count "$num_lvs" + vg_field "$local_vg" snap_count "$num_snaps" +} + +# Compare md5 check generated from get dev_md5sum +dev_md5sum() { + md5sum -c "md5.$1-$2" || \ + (get lv_field "$1/$2" "name,size,seg_pe_ranges" + die "LV $1/$2 has different MD5 check sum!") +} + +sysfs() { + # read maj min and also convert hex to decimal + local maj + local min + local P + local val + maj=$(($(stat -L --printf=0x%t "$1"))) + min=$(($(stat -L --printf=0x%T "$1"))) + P="/sys/dev/block/$maj:$min/$2" + val=$(< "$P") || return 0 # no sysfs ? + test "$val" -eq "$3" || \ + die "$1: $P = $val differs from expected value $3!" +} + +# check raid_leg_status $vg $lv "Aaaaa" +raid_leg_status() { + local st + local val + + # Ignore inconsisten raid status 0/xxxxx idle + for i in {100..0} ; do + st=( $(dmsetup status "$1-$2") ) || die "Unable to get status of $vg/$lv1" + b=( $(echo "${st[6]}" | sed s:/:' ':) ) + [ "${b[0]}" = "0" ] || { + test "${st[5]}" = "$3" || break + return 0 + } + sleep .1 + done + + die "$1-$2 status ${st[5]} != $3 (${st[*]})" +} + +grep_dmsetup() { + dmsetup "$1" "$2" | tee out + grep -q "${@:3}" out || die "Expected output \"" "${@:3}" "\" from dmsetup $1 not found!" +} + +grep_lvmlockd_dump() { + lvmlockctl --dump | tee out + grep -q "${@:1}" out || die "Expected output \"" "${@:1}" "\" from lvmlockctl --dump not found!" } +#set -x unset LVM_VALGRIND "$@" diff --git a/test/lib/dmsecuretest.c b/test/lib/dmsecuretest.c new file mode 100644 index 0000000..19265bf --- /dev/null +++ b/test/lib/dmsecuretest.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Test sample code to check for leftovers from secure table loading in + * userspace memory (initial sample provided by Milan Broz). + * + * Compile with: gcc -O2 -g -o tst dmcrypt.c -ldevmapper + * + * Search for string in coredump (needs 'raise', or using 'gcore' tool) + * + * grep "434e0cbab02ca68ffba9268222c3789d703fe62427b78b308518b3228f6a2122" core + * + */ + +#include "device_mapper/all.h" + +#include +#include + +/* Comment out this define to get coredump instead of sleeping */ +#define SLEEP 1 + +static void rot13(char *s) +{ + unsigned i; + + for (i = 0; s[i]; i++) + if (s[i] >= 'a' && s[i] <= 'm') + s[i] += 13; + else if (s[i] >= 'n' && s[i] <= 'z') + s[i] -= 13; +} + +int main (int argc, char *argv[]) +{ + const unsigned sz = 8192; + /* rot13: 434e0cbab02ca68ffba9268222c3789d703fe62427b78b308518b3228f6a2122 */ + char aes[] = "434r0pono02pn68sson9268222p3789q703sr62427o78o308518o3228s6n2122"; + const char *device = (argc > 1) ? argv[1] : "/dev/loop0"; /* device for use */ + const char *devname = (argc > 2) ? argv[2] : "test-secure"; /* name of dm device */ + const char *cipher = (argc > 3) ? argv[3] : "aes-xts-plain64"; /* name of dm device */ + uint32_t cookie = 0; + char table[300]; + struct dm_task *dmt; + + if (geteuid() != 0) { + fprintf(stderr, "Needs root UID for execution!\n"); + exit(1); + } + + printf("Going to create %s dm device using backend device: %s\n", devname, device); + + if ((dmt = dm_task_create(DM_DEVICE_CREATE))) { + (void) dm_task_set_name(dmt, devname); + (void) dm_task_secure_data(dmt); + rot13(aes); + snprintf(table, sizeof(table), "%s %s 0 %s %u", cipher, aes, device, sz); + memset(aes, 0, sizeof(aes)); + (void) dm_task_add_target(dmt, 0, sz, "crypt", table); + memset(table, 0, sizeof(table)); + asm volatile ("" ::: "memory");/* Compiler barrier. */ + (void) dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK); + (void) dm_task_run(dmt); + (void) dm_task_destroy(dmt); + (void) dm_udev_wait(cookie); /* Finish udev processing */ + } + + /* At this point there should be no memory trace from a secure table line */ + +#ifdef SLEEP + sleep(4); /* Give time to other process to capture 'gcore pid' */ +#else + raise(SIGABRT); /* Generate core for search of any forgotten traces of key */ +#endif + return 0; +} diff --git a/test/lib/flavour-ndev-cluster-lvmpolld.sh b/test/lib/flavour-ndev-cluster-lvmpolld.sh new file mode 100644 index 0000000..fe31bb4 --- /dev/null +++ b/test/lib/flavour-ndev-cluster-lvmpolld.sh @@ -0,0 +1,2 @@ +export LVM_TEST_LOCKING=3 +export LVM_TEST_LVMPOLLD=1 diff --git a/test/lib/flavour-ndev-cluster.sh b/test/lib/flavour-ndev-cluster.sh new file mode 100644 index 0000000..3629069 --- /dev/null +++ b/test/lib/flavour-ndev-cluster.sh @@ -0,0 +1 @@ +export LVM_TEST_LOCKING=3 diff --git a/test/lib/flavour-ndev-devicesfile.sh b/test/lib/flavour-ndev-devicesfile.sh new file mode 100644 index 0000000..21168fd --- /dev/null +++ b/test/lib/flavour-ndev-devicesfile.sh @@ -0,0 +1,2 @@ +export LVM_TEST_LOCKING=1 +export LVM_TEST_DEVICES_FILE=1 diff --git a/test/lib/flavour-ndev-lvmpolld.sh b/test/lib/flavour-ndev-lvmpolld.sh new file mode 100644 index 0000000..0a70703 --- /dev/null +++ b/test/lib/flavour-ndev-lvmpolld.sh @@ -0,0 +1,2 @@ +export LVM_TEST_LOCKING=1 +export LVM_TEST_LVMPOLLD=1 diff --git a/test/lib/flavour-ndev-vanilla.sh b/test/lib/flavour-ndev-vanilla.sh new file mode 100644 index 0000000..1899c94 --- /dev/null +++ b/test/lib/flavour-ndev-vanilla.sh @@ -0,0 +1 @@ +export LVM_TEST_LOCKING=1 diff --git a/test/lib/flavour-udev-cluster-lvmpolld.sh b/test/lib/flavour-udev-cluster-lvmpolld.sh new file mode 100644 index 0000000..abf76e9 --- /dev/null +++ b/test/lib/flavour-udev-cluster-lvmpolld.sh @@ -0,0 +1,3 @@ +export LVM_TEST_LOCKING=3 +export LVM_TEST_LVMPOLLD=1 +export LVM_TEST_DEVDIR=/dev diff --git a/test/lib/flavour-udev-cluster.sh b/test/lib/flavour-udev-cluster.sh new file mode 100644 index 0000000..a9025a6 --- /dev/null +++ b/test/lib/flavour-udev-cluster.sh @@ -0,0 +1,2 @@ +export LVM_TEST_LOCKING=3 +export LVM_TEST_DEVDIR=/dev diff --git a/test/lib/flavour-udev-lvmlockd-dlm.sh b/test/lib/flavour-udev-lvmlockd-dlm.sh new file mode 100644 index 0000000..93d7877 --- /dev/null +++ b/test/lib/flavour-udev-lvmlockd-dlm.sh @@ -0,0 +1,6 @@ +export LVM_TEST_LOCKING=1 +export LVM_TEST_LVMPOLLD=1 +export LVM_TEST_LVMLOCKD=1 +export LVM_TEST_LVMLOCKD_TEST=1 +export LVM_TEST_LOCK_TYPE_DLM=1 +export LVM_TEST_DEVDIR=/dev diff --git a/test/lib/flavour-udev-lvmlockd-idm.sh b/test/lib/flavour-udev-lvmlockd-idm.sh new file mode 100644 index 0000000..e9f8908 --- /dev/null +++ b/test/lib/flavour-udev-lvmlockd-idm.sh @@ -0,0 +1,5 @@ +export LVM_TEST_LOCKING=1 +export LVM_TEST_LVMPOLLD=1 +export LVM_TEST_LVMLOCKD=1 +export LVM_TEST_LOCK_TYPE_IDM=1 +export LVM_TEST_DEVDIR=/dev diff --git a/test/lib/flavour-udev-lvmlockd-sanlock.sh b/test/lib/flavour-udev-lvmlockd-sanlock.sh new file mode 100644 index 0000000..52f3cea --- /dev/null +++ b/test/lib/flavour-udev-lvmlockd-sanlock.sh @@ -0,0 +1,5 @@ +export LVM_TEST_LOCKING=1 +export LVM_TEST_LVMPOLLD=1 +export LVM_TEST_LVMLOCKD=1 +export LVM_TEST_LOCK_TYPE_SANLOCK=1 +export LVM_TEST_DEVDIR=/dev diff --git a/test/lib/flavour-udev-lvmlockd-test.sh b/test/lib/flavour-udev-lvmlockd-test.sh new file mode 100644 index 0000000..f9cd527 --- /dev/null +++ b/test/lib/flavour-udev-lvmlockd-test.sh @@ -0,0 +1,8 @@ +export LVM_TEST_LOCKING=1 +export LVM_TEST_LVMPOLLD=1 +export LVM_TEST_LVMLOCKD=1 +export LVM_TEST_LVMLOCKD_TEST=1 +export LVM_TEST_DEVDIR=/dev + +# FIXME:dct: add option to allow --test with sanlock +export LVM_TEST_LVMLOCKD_TEST_DLM=1 diff --git a/test/lib/flavour-udev-lvmpolld.sh b/test/lib/flavour-udev-lvmpolld.sh new file mode 100644 index 0000000..c7f40b5 --- /dev/null +++ b/test/lib/flavour-udev-lvmpolld.sh @@ -0,0 +1,3 @@ +export LVM_TEST_LOCKING=1 +export LVM_TEST_LVMPOLLD=1 +export LVM_TEST_DEVDIR=/dev diff --git a/test/lib/flavour-udev-vanilla.sh b/test/lib/flavour-udev-vanilla.sh new file mode 100644 index 0000000..ca778a6 --- /dev/null +++ b/test/lib/flavour-udev-vanilla.sh @@ -0,0 +1,2 @@ +export LVM_TEST_LOCKING=1 +export LVM_TEST_DEVDIR=/dev diff --git a/test/lib/get.sh b/test/lib/get.sh index 4197f47..3b0d1f2 100644 --- a/test/lib/get.sh +++ b/test/lib/get.sh @@ -1,5 +1,5 @@ -#!/bin/sh -# Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash +# Copyright (C) 2011-2017 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 @@ -7,7 +7,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # get.sh: get various values from volumes # @@ -18,28 +18,104 @@ # # get lv_devices LV [lvs params] +test -z "$BASH" || set -e -o pipefail -# trims only leading prefix, we should not need trim trailing spaces +# trims only leading prefix and suffix trim_() { - #local var=${var%"${var##*[! ]}"} # remove trailing space characters - echo ${1#"${1%%[! ]*}"} # remove leading space characters + rm -f debug.log # drop log, command was ok + local var=${1%"${1##*[! ]}"} # remove trailing space characters + echo "${var#"${var%%[! ]*}"}" # remove leading space characters } pv_field() { - trim_ "$(pvs --noheadings -o $2 ${@:3} $1)" + local r + r=$(pvs --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1") + trim_ "$r" } vg_field() { - trim_ "$(vgs --noheadings -o $2 ${@:3} $1)" + local r + r=$(vgs --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1") + trim_ "$r" } lv_field() { - trim_ "$(lvs --noheadings -o $2 ${@:3} $1)" + local r + r=$(lvs --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1") + trim_ "$r" +} + +lv_first_seg_field() { + local r + r=$(head -1 < <(lvs --config 'log{prefix=""}' --unbuffered --noheadings -o "$2" "${@:3}" "$1")) + trim_ "$r" +} + +lvh_field() { + local r + r=$(lvs -H --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1") + trim_ "$r" +} + +lva_field() { + local r + r=$(lvs -a --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1") + trim_ "$r" } lv_devices() { - lv_field $1 devices -a "${@:2}" | sed 's/([^)]*)//g; s/,/ /g' + lv_field "$1" devices -a "${@:2}" | sed 's/([^)]*)//g; s/,/\n/g' +} + +lv_field_lv_() { + lv_field "$1" "$2" -a --unbuffered | tr -d '[]' +} + +lv_tree_devices_() { + local lv="$1/$2" + local type + type=$(lv_first_seg_field "$lv" segtype -a) + #local orig + #orig=$(lv_field_lv_ "$lv" origin) + # FIXME: should we count in also origins ? + #test -z "$orig" || lv_tree_devices_ $1 $orig + case "$type" in + linear|striped) + lv_devices "$lv" + ;; + mirror|raid*) + local log + log=$(lv_field_lv_ "$lv" mirror_log) + test -z "$log" || lv_tree_devices_ "$1" "$log" + for i in $(lv_devices "$lv") + do lv_tree_devices_ "$1" "$i"; done + ;; + thin) + lv_tree_devices_ "$1" "$(lv_field_lv_ "$lv" pool_lv)" + ;; + thin-pool) + lv_tree_devices_ "$1" "$(lv_field_lv_ "$lv" data_lv)" + lv_tree_devices_ "$1" "$(lv_field_lv_ "$lv" metadata_lv)" + ;; + cache) + lv_tree_devices_ "$1" "$(lv_devices "$lv")" + ;; + cache-pool) + lv_tree_devices_ "$1" "$(lv_field_lv_ "$lv" data_lv)" + lv_tree_devices_ "$1" "$(lv_field_lv_ "$lv" metadata_lv)" + ;; + esac +} + +lv_tree_devices() { + lv_tree_devices_ "$@" | sort | uniq +} + +first_extent_sector() { + pv_field "$@" pe_start --units s --nosuffix } +#set -x unset LVM_VALGRIND +unset LVM_LOG_FILE_EPOCH "$@" diff --git a/test/lib/harness.c b/test/lib/harness.c index 929bfc8..a97f5db 100644 --- a/test/lib/harness.c +++ b/test/lib/harness.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2013 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -9,24 +9,33 @@ * * 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 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define _GNU_SOURCE +#include #include -#include +#include #include +#include +#include +#include +#include /* rusage */ +#include #include +#include +#include +#include #include -#include -#include #include -#include +#include +#include static pid_t pid; static int fds[2]; #define MAX 1024 +#define MAX_LOG_SIZE (32*1024*1024) /* Default max size of test log */ +#define WRITE_TIMEOUT (180 * 2) /* 3 minutes */ struct stats { int nfailed; @@ -34,17 +43,28 @@ struct stats { int npassed; int nknownfail; int nwarned; + int ninterrupted; int status[MAX]; }; static struct stats s; static char *readbuf = NULL; -static int readbuf_sz = 0, readbuf_used = 0; +static size_t readbuf_sz = 0, readbuf_used = 0; static int die = 0; static int verbose = 0; /* >1 with timestamps */ static int interactive = 0; /* disable all redirections */ +static int quiet = 0; +static const char *results; +static unsigned fullbuffer = 0; +static int unlimited = 0; +static int write_timeout = WRITE_TIMEOUT; + +static time_t harness_start; + +static FILE *outfile = NULL; +char testdirdebug[PATH_MAX]; struct subst { const char *key; @@ -53,19 +73,24 @@ struct subst { static struct subst subst[2]; -#define PASSED 0 -#define SKIPPED 1 -#define FAILED 2 -#define WARNED 3 -#define KNOWNFAIL 4 +enum { + UNKNOWN, + FAILED, + INTERRUPTED, + KNOWNFAIL, + PASSED, + SKIPPED, + TIMEOUT, + WARNED, +}; static void handler( int sig ) { signal( sig, SIG_DFL ); - kill( pid, sig ); + kill( -pid, sig ); die = sig; } -static int outline(char *buf, int start, int force) { +static int outline(FILE *out, char *buf, int start, int force) { char *from = buf + start; char *next = strchr(buf + start, '\n'); @@ -79,9 +104,12 @@ static int outline(char *buf, int start, int force) { if (!strncmp(from, "@TESTDIR=", 9)) { subst[0].key = "@TESTDIR@"; + free(subst[0].value); subst[0].value = strndup(from + 9, next - from - 9 - 1); + snprintf(testdirdebug, sizeof(testdirdebug), "%s/debug.log", subst[0].value); } else if (!strncmp(from, "@PREFIX=", 8)) { subst[1].key = "@PREFIX@"; + free(subst[1].value); subst[1].value = strndup(from + 8, next - from - 8 - 1); } else { char *line = strndup(from, next - from); @@ -100,11 +128,11 @@ static int outline(char *buf, int start, int force) { } } } - fwrite(a, 1, b - a, stdout); + fwrite(a, 1, b - a, out); a = b; if ( idx >= 0 ) { - fprintf(stdout, "%s", subst[idx].key); + fprintf(out, "%s", subst[idx].key); a += strlen(subst[idx].value); } } while (b < line + strlen(line)); @@ -117,27 +145,26 @@ static int outline(char *buf, int start, int force) { static void dump(void) { int counter_last = -1, counter = 0; - while ( counter < readbuf_used && counter != counter_last ) { + while ((counter < (int) readbuf_used) && (counter != counter_last)) { counter_last = counter; - counter = outline( readbuf, counter, 1 ); + counter = outline( stdout, readbuf, counter, 1 ); } } -static void trickle(void) { - static int counter_last = -1, counter = 0; - - if (counter_last > readbuf_used) { - counter_last = -1; - counter = 0; +static void trickle(FILE *out, int *last, int *counter) { + if (*last > (int) readbuf_used) { + *last = -1; + *counter = 0; } - while ( counter < readbuf_used && counter != counter_last ) { - counter_last = counter; - counter = outline( readbuf, counter, 1 ); + while ((*counter < (int) readbuf_used) && (*counter != *last)) { + *last = *counter; + *counter = outline( out, readbuf, *counter, 1 ); } } static void clear(void) { readbuf_used = 0; + fullbuffer = 0; } static int64_t _get_time_us(void) @@ -151,7 +178,12 @@ static int64_t _get_time_us(void) static void _append_buf(const char *buf, size_t len) { if ((readbuf_used + len) >= readbuf_sz) { - readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 4096; + if ((readbuf_sz >= MAX_LOG_SIZE) && !unlimited) { + if (fullbuffer++ == 0) + kill(-pid, SIGINT); + return; + } + readbuf_sz = 2 * (readbuf_used + len + readbuf_sz); readbuf = realloc(readbuf, readbuf_sz); } @@ -197,16 +229,19 @@ static const char *_append_with_stamp(const char *buf, int stamp) return bb; } -static void drain(void) { - char buf[4096]; +static int drain(int fd) +{ + char buf[2 * 1024 * 1024 + 1]; /* try to capture large sysrq trace */ const char *bp; int stamp = 0; int sz; - while ((sz = read(fds[1], buf, sizeof(buf) - 1)) > 0) { + static int stdout_last = -1, stdout_counter = 0; + static int outfile_last = -1, outfile_counter = 0; + + if ((sz = read(fd, buf, sizeof(buf) - 1)) > 0) { buf[sz] = '\0'; bp = (verbose < 2) ? buf : _append_with_stamp(buf, stamp); - if (sz > (bp - buf)) { _append_buf(bp, sz - (bp - buf)); stamp = -1; /* unfinished line */ @@ -216,32 +251,91 @@ static void drain(void) { readbuf[readbuf_used] = 0; if (verbose) - trickle(); + trickle(stdout, &stdout_last, &stdout_counter); + if (outfile) + trickle(outfile, &outfile_last, &outfile_counter); } + + return sz; } -static const char *duration(time_t start) +static int drain_fds(int fd1, int fd2, long timeout) { - static char buf[16]; + return -1; +} + +#define SYSLOG_ACTION_READ_CLEAR 4 +#define SYSLOG_ACTION_CLEAR 5 + +static void clear_dmesg(void) +{ + klogctl(SYSLOG_ACTION_CLEAR, 0, 0); +} + +static void drain_dmesg(void) +{ + char buf[1024 * 1024 + 1]; + int sz = klogctl(SYSLOG_ACTION_READ_CLEAR, buf, sizeof(buf) - 1); + if (sz > 0) { + buf[sz] = 0; + _append_buf(buf, sz); + } +} + +static const char *duration(time_t start, const struct rusage *usage) +{ + static char buf[100]; int t = (int)(time(NULL) - start); - sprintf(buf, "%2d:%02d", t / 60, t % 60); + int p = sprintf(buf, "%2d:%02d", t / 60, t % 60); + + if (usage) + sprintf(buf + p, " %2ld:%02ld.%03ld/%ld:%02ld.%03ld%5ld%8ld/%ld", + usage->ru_utime.tv_sec / 60, usage->ru_utime.tv_sec % 60, + usage->ru_utime.tv_usec / 1000, + usage->ru_stime.tv_sec / 60, usage->ru_stime.tv_sec % 60, + usage->ru_stime.tv_usec / 1000, + usage->ru_maxrss / 1024, + usage->ru_inblock, usage->ru_oublock); + return buf; } -static void passed(int i, char *f, time_t t) { +static void passed(int i, char *f, time_t t, const struct rusage *usage) { if (readbuf && strstr(readbuf, "TEST EXPECT FAIL")) { ++ s.npassed; s.status[i] = PASSED; - printf("passed (UNEXPECTED). %s\n", duration(t)); + printf("passed (UNEXPECTED). %s\n", duration(t, usage)); } else if (readbuf && strstr(readbuf, "TEST WARNING")) { ++s.nwarned; s.status[i] = WARNED; - printf("warnings %s\n", duration(t)); + printf("warnings %s\n", duration(t, usage)); } else { ++ s.npassed; s.status[i] = PASSED; - printf("passed. %s\n", duration(t)); + printf("passed. %s\n", duration(t, usage)); + } +} + +static void interrupted(int i, char *f) { + ++ s.ninterrupted; + s.status[i] = INTERRUPTED; + printf("\ninterrupted.\n"); + if (!quiet && !verbose && fullbuffer) { + printf("-- Interrupted %s ------------------------------------\n", f); + dump(); + printf("\n-- Interrupted %s (end) ------------------------------\n", f); + } +} + +static void timeout(int i, char *f) { + ++ s.ninterrupted; + s.status[i] = TIMEOUT; + printf("timeout.\n"); + if (!quiet && !verbose && readbuf) { + printf("-- Timed out %s ------------------------------------\n", f); + dump(); + printf("\n-- Timed out %s (end) ------------------------------\n", f); } } @@ -261,12 +355,8 @@ static void failed(int i, char *f, int st) { ++ s.nfailed; s.status[i] = FAILED; - if(die == 2) { - printf("interrupted.\n"); - return; - } - printf("FAILED.\n"); - if (!verbose) { + printf("FAILED (status %d).\n", WEXITSTATUS(st)); + if (!quiet && !verbose && readbuf) { printf("-- FAILED %s ------------------------------------\n", f); dump(); printf("-- FAILED %s (end) ------------------------------\n", f); @@ -274,59 +364,181 @@ static void failed(int i, char *f, int st) { } static void run(int i, char *f) { + struct rusage usage; + char flavour[512], script[512]; + pid = fork(); if (pid < 0) { perror("Fork failed."); exit(201); } else if (pid == 0) { if (!interactive) { - close(0); - dup2(fds[0], 1); - dup2(fds[0], 2); - close(fds[0]); + close(STDIN_FILENO); + dup2(fds[1], STDOUT_FILENO); + dup2(fds[1], STDERR_FILENO); close(fds[1]); } - execlp("bash", "bash", f, NULL); + close(fds[0]); + if (strchr(f, ':')) { + strcpy(flavour, f); + *strchr(flavour, ':') = 0; + setenv("LVM_TEST_FLAVOUR", flavour, 1); + strcpy(script, strchr(f, ':') + 1); + } else { + strcpy(script, f); + } + setpgid(0, 0); + execlp("bash", "bash", "-noprofile", "-norc", script, NULL); perror("execlp"); fflush(stderr); _exit(202); } else { - int st, w; + int st = -1, w; time_t start = time(NULL); char buf[128]; - snprintf(buf, 128, "%s ...", f); - buf[127] = 0; - printf("Running %-50s ", buf); + char outpath[PATH_MAX]; + char *c = outpath + strlen(results) + 1; + struct stat statbuf; + int runaway = 0; + int no_write = 0; + int clobber_dmesg = 0; + int collect_debug = 0; + int fd_debuglog = -1; + int fd_kmsg; + fd_set set; + int ret; + + //close(fds[1]); + testdirdebug[0] = '\0'; /* Capture RUNTESTDIR */ + snprintf(buf, sizeof(buf), "%s ...", f); + printf("Running %-60s%c", buf, verbose ? '\n' : ' '); fflush(stdout); - while ((w = waitpid(pid, &st, WNOHANG)) == 0) { - drain(); - usleep(20000); + snprintf(outpath, sizeof(outpath), "%s/%s.txt", results, f); + while ((c = strchr(c, '/'))) + *c = '_'; + if (!(outfile = fopen(outpath, "w"))) + perror("fopen"); + + /* Mix-in kernel log message */ + if ((fd_kmsg = open("/dev/kmsg", O_RDONLY | O_NONBLOCK)) < 0) { + if (errno != ENOENT) /* Older kernels (<3.5) do not support /dev/kmsg */ + perror("open /dev/kmsg"); + } else if (lseek(fd_kmsg, 0L, SEEK_END) == (off_t) -1) + perror("lseek /dev/kmsg"); + + if ((fd_kmsg < 0) && + (clobber_dmesg = strcmp(getenv("LVM_TEST_CAN_CLOBBER_DMESG") ? : "0", "0"))) + clear_dmesg(); + + while ((w = wait4(pid, &st, WNOHANG, &usage)) == 0) { + struct timeval selectwait = { .tv_usec = 500000 }; /* 0.5s */ + + if ((fullbuffer && fullbuffer++ == 8000) || + (write_timeout > 0 && no_write > write_timeout)) + { + timeout: + kill(pid, SIGINT); + sleep(5); /* wait a bit for a reaction */ + if ((w = waitpid(pid, &st, WNOHANG)) == 0) { + if (write_timeout > 0 && no_write > write_timeout) + /* + * Kernel traces needed, when stuck for + * too long in userspace without producing + * any output, in other case it should be + * user space problem + */ + system("echo t > /proc/sysrq-trigger"); + collect_debug = 1; + kill(-pid, SIGKILL); + w = pid; // waitpid(pid, &st, NULL); + } + runaway = 1; + break; + } + + if (clobber_dmesg) + drain_dmesg(); + + FD_ZERO(&set); + FD_SET(fds[0], &set); + if (fd_kmsg >= 0) + FD_SET(fd_kmsg, &set); + + if ((ret = select(fd_kmsg > fds[0] ? fd_kmsg + 1 : fds[0] + 1, &set, NULL, NULL, &selectwait)) <= 0) { + /* Still checking debug log size if it's not growing too much */ + if (!unlimited && testdirdebug[0] && + (stat(testdirdebug, &statbuf) == 0) && + statbuf.st_size > 32 * 1024 * 1024) { /* 32MB command log size */ + printf("Killing test since debug.log has gone wild (size %ld)\n", + statbuf.st_size); + goto timeout; + } + no_write++; + continue; + } + + if (FD_ISSET(fds[0], &set) && drain(fds[0]) > 0) + no_write = 0; + else if (fd_kmsg >= 0 && FD_ISSET(fd_kmsg, &set) && (drain(fd_kmsg) < 0)) { + close(fd_kmsg); + fd_kmsg = -1; /* Likely /dev/kmsg is not readable */ + if ((clobber_dmesg = strcmp(getenv("LVM_TEST_CAN_CLOBBER_DMESG") ? : "0", "0"))) + clear_dmesg(); + } } if (w != pid) { perror("waitpid"); exit(206); } - drain(); - if (WIFEXITED(st)) { - if (WEXITSTATUS(st) == 0) { - passed(i, f, start); - } else if (WEXITSTATUS(st) == 200) { + + while (!fullbuffer && (drain_fds(fds[0], fd_kmsg, 0) > 0)) + /* read out what was left */; + + if (die == 2) + interrupted(i, f); + else if (runaway) { + if (collect_debug && + (fd_debuglog = open(testdirdebug, O_RDONLY)) != -1) { + runaway = unlimited ? INT32_MAX : 4 * 1024 * 1024; + while (!fullbuffer && runaway > 0 && (ret = drain(fd_debuglog)) > 0) + runaway -= ret; + close(fd_debuglog); + } + timeout(i, f); + } else if (WIFEXITED(st)) { + if (WEXITSTATUS(st) == 0) + passed(i, f, start, &usage); + else if (WEXITSTATUS(st) == 200) skipped(i, f); - } else { + else failed(i, f, st); - } - } else { + } else failed(i, f, st); - } + + if (fd_kmsg >= 0) + close(fd_kmsg); + else if (clobber_dmesg) + drain_dmesg(); + if (outfile) + fclose(outfile); + if (fullbuffer) + printf("\nTest was interrupted, output has got too large (>%u) (loop:%u)\n" + "Set LVM_TEST_UNLIMITED=1 for unlimited log.\n", + (unsigned) readbuf_sz, fullbuffer); clear(); } } int main(int argc, char **argv) { + char results_list[PATH_MAX]; + const char *result; const char *be_verbose = getenv("VERBOSE"), - *be_interactive = getenv("INTERACTIVE"); + *be_interactive = getenv("INTERACTIVE"), + *be_quiet = getenv("QUIET"), + *be_write_timeout = getenv("WRITE_TIMEOUT"); time_t start = time(NULL); int i; + FILE *list; if (argc >= MAX) { fprintf(stderr, "Sorry, my head exploded. Please increase MAX.\n"); @@ -339,55 +551,102 @@ int main(int argc, char **argv) { if (be_interactive) interactive = atoi(be_interactive); + if (be_quiet) + quiet = atoi(be_quiet); + + if (be_write_timeout) + write_timeout = atoi(be_write_timeout) * 2; + + results = getenv("LVM_TEST_RESULTS") ? : "results"; + unlimited = getenv("LVM_TEST_UNLIMITED") ? 1 : 0; + (void) snprintf(results_list, sizeof(results_list), "%s/list", results); + + //if (pipe(fds)) { if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds)) { perror("socketpair"); return 201; } - if ( fcntl( fds[1], F_SETFL, O_NONBLOCK ) == -1 ) { + if (fcntl(fds[0], 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); - } + for (i = 0; i <= 32; ++i) + switch (i) { + case SIGCHLD: case SIGWINCH: case SIGURG: + case SIGKILL: case SIGSTOP: break; + default: signal(i, handler); + } + harness_start = time(NULL); /* run the tests */ - for (i = 1; i < argc; ++ i) { + for (i = 1; !die && i < argc; ++i) { run(i, argv[i]); - if (die) - break; + if ( time(NULL) - harness_start > 48 * 360 ) { /* 04:48 */ + printf("Nearly 5 hours passed, giving up...\n"); + die = 1; + } } - printf("\n## %d tests %s : %d OK, %d warnings, %d failures, %d known failures; %d skipped\n", - s.nwarned + s.npassed + s.nfailed + s.nskipped, - duration(start), - s.npassed, s.nwarned, s.nfailed, s.nknownfail, s.nskipped); + free(subst[0].value); + free(subst[1].value); + free(readbuf); + + printf("\n## %d tests %s : %d OK, %d warnings, %d failures (%d interrupted), %d known failures; " + "%d skipped\n", + s.nwarned + s.npassed + s.nfailed + s.nskipped + s.ninterrupted, + duration(start, NULL), + s.npassed, s.nwarned, s.nfailed + s.ninterrupted, s.ninterrupted, + s.nknownfail, s.nskipped); + + /* dump a list to results */ + if ((list = fopen(results_list, "w"))) { + for (i = 1; i < argc; ++ i) { + switch (s.status[i]) { + case FAILED: result = "failed"; break; + case INTERRUPTED: result = "interrupted"; break; + case PASSED: result = "passed"; break; + case SKIPPED: result = "skipped"; break; + case TIMEOUT: result = "timeout"; break; + case WARNED: result = "warnings"; break; + default: result = "unknown"; break; + } + fprintf(list, "%s %s\n", argv[i], result); + } + fclose(list); + } else + perror("fopen result"); /* print out a summary */ - if (s.nfailed || s.nskipped || s.nknownfail) { + if (s.nfailed || s.nskipped || s.nknownfail || s.ninterrupted || s.nwarned) { for (i = 1; i < argc; ++ i) { switch (s.status[i]) { case FAILED: printf("FAILED: %s\n", argv[i]); break; + case INTERRUPTED: + printf("INTERRUPTED: %s\n", argv[i]); + break; case KNOWNFAIL: printf("FAILED (expected): %s\n", argv[i]); break; case SKIPPED: printf("skipped: %s\n", argv[i]); break; + case TIMEOUT: + printf("TIMEOUT: %s\n", argv[i]); + break; + case WARNED: + printf("WARNED: %s\n", argv[i]); + break; + default: /* do nothing */ ; } } printf("\n"); - return s.nfailed > 0 || die; + return (s.nfailed > 0) || (s.ninterrupted > 0) || die; } - free(readbuf); - return die; } diff --git a/test/lib/idm_inject_failure.c b/test/lib/idm_inject_failure.c new file mode 100644 index 0000000..4998b58 --- /dev/null +++ b/test/lib/idm_inject_failure.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020-2021 Seagate Ltd. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + int pecent = atoi(argv[1]); + int ret, s; + + ret = ilm_connect(&s); + if (ret == 0) { + printf("ilm_connect: SUCCESS\n"); + } else { + printf("ilm_connect: FAIL\n"); + exit(-1); + } + + ret = ilm_inject_fault(s, pecent); + if (ret == 0) { + printf("ilm_inject_fault (100): SUCCESS\n"); + } else { + printf("ilm_inject_fault (100): FAIL\n"); + exit(-1); + } + + ret = ilm_disconnect(s); + if (ret == 0) { + printf("ilm_disconnect: SUCCESS\n"); + } else { + printf("ilm_disconnect: FAIL\n"); + exit(-1); + } + + return 0; +} diff --git a/test/lib/inittest.sh b/test/lib/inittest.sh new file mode 100644 index 0000000..40ea98f --- /dev/null +++ b/test/lib/inittest.sh @@ -0,0 +1,197 @@ +#!/usr/bin/env bash +# Copyright (C) 2011-2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +initskip() { + test $# -eq 0 || echo "TEST SKIPPED:" "$@" + exit 200 +} + +# sanitize the environment +LANG=C +LC_ALL=C +TZ=UTC + +# Put script name into variable, so it can used in external scripts +TESTNAME=${0##*/} +# Nice debug message +PS4='#${BASH_SOURCE[0]##*/}:${LINENO}+ ' +export TESTNAME PS4 + +LVM_TEST_FLAVOUR=${LVM_TEST_FLAVOUR-ndev-vanilla} + +LVM_TEST_BACKING_DEVICE=${LVM_TEST_BACKING_DEVICE-} +LVM_TEST_DEVDIR=${LVM_TEST_DEVDIR-} +LVM_TEST_NODEBUG=${LVM_TEST_NODEBUG-} +LVM_TEST_LVM1=${LVM_TEST_LVM1-} +LVM_TEST_FAILURE=${LVM_TEST_FAILURE-} +LVM_TEST_MULTI_HOST=${LVM_TEST_MULTI_HOST-} +# TODO: LVM_TEST_SHARED +SHARED=${SHARED-} + +LVM_TEST_LVMLOCKD=${LVM_TEST_LVMLOCKD-} +LVM_TEST_LVMLOCKD_TEST=${LVM_TEST_LVMLOCKD_TEST-} +LVM_TEST_LVMPOLLD=${LVM_TEST_LVMPOLLD-} +LVM_TEST_DEVICES_FILE=${LVM_TEST_DEVICES_FILE-} +LVM_TEST_LOCK_TYPE_DLM=${LVM_TEST_LOCK_TYPE_DLM-} +LVM_TEST_LOCK_TYPE_SANLOCK=${LVM_TEST_LOCK_TYPE_SANLOCK-} +LVM_TEST_LOCK_TYPE_IDM=${LVM_TEST_LOCK_TYPE_IDM-} + +SKIP_WITHOUT_CLVMD=${SKIP_WITHOUT_CLVMD-} +SKIP_WITH_CLVMD=${SKIP_WITH_CLVMD-} + +SKIP_WITH_LVMPOLLD=${SKIP_WITH_LVMPOLLD-} +SKIP_WITH_LVMLOCKD=${SKIP_WITH_LVMLOCKD-} +SKIP_ROOT_DM_CHECK=${SKIP_ROOT_DM_CHECK-} +SKIP_WITH_LOW_SPACE=${SKIP_WITH_LOW_SPACE-50} + +test -n "$LVM_TEST_FLAVOUR" || { echo "NOTE: Empty flavour">&2; initskip; } +test -f "lib/flavour-$LVM_TEST_FLAVOUR" || { echo "NOTE: Flavour '$LVM_TEST_FLAVOUR' does not exist">&2; initskip; } +. "lib/flavour-$LVM_TEST_FLAVOUR" + +test -n "$SKIP_WITHOUT_CLVMD" && test "$LVM_TEST_LOCKING" -ne 3 && initskip +test -n "$SKIP_WITH_CLVMD" && test "$LVM_TEST_LOCKING" = 3 && initskip + +test -n "$SKIP_WITH_LVMPOLLD" && test -n "$LVM_TEST_LVMPOLLD" && test -z "$LVM_TEST_LVMLOCKD" && initskip + +test -n "$SKIP_WITH_LVMLOCKD" && test -n "$LVM_TEST_LVMLOCKD" && initskip + +test -n "$SKIP_WITH_DEVICES_FILE" && test -n "$LVM_TEST_DEVICES_FILE" && initskip + +unset CDPATH + +export LVM_TEST_BACKING_DEVICE LVM_TEST_DEVDIR LVM_TEST_NODEBUG LVM_TEST_FAILURE +export LVM_TEST_MULTI_HOST +export LVM_TEST_LVMLOCKD LVM_TEST_LVMLOCKD_TEST +export LVM_TEST_LVMPOLLD LVM_TEST_LOCK_TYPE_DLM LVM_TEST_LOCK_TYPE_SANLOCK LVM_TEST_LOCK_TYPE_IDM +export LVM_TEST_DEVICES_FILE +# grab some common utilities +. lib/utils + +TESTOLDPWD=$(pwd) +COMMON_PREFIX="LVMTEST" +PREFIX="${COMMON_PREFIX}$$" + +# Check we are not conflickting with some exiting setup +if test -z "$SKIP_ROOT_DM_CHECK" ; then + dmsetup table | not grep "${PREFIX}[^0-9]" || die "DM table already has devices with prefix $PREFIX!" +fi + +test -n "$LVM_TEST_DIR" || LVM_TEST_DIR=${TMPDIR:-/tmp} +test "$LVM_TEST_DIR" = "/dev" && die "Setting LVM_TEST_DIR=/dev is not supported!" + +TESTDIR=$(mkdtemp "$LVM_TEST_DIR" "$PREFIX.XXXXXXXXXX") || \ + die "failed to create temporary directory in \"$LVM_TEST_DIR\"" +RUNNING_DMEVENTD=$(pgrep dmeventd || true) + +export TESTOLDPWD TESTDIR COMMON_PREFIX PREFIX RUNNING_DMEVENTD +LVM_LOG_FILE_EPOCH=DEBUG +LVM_LOG_FILE_MAX_LINES=${LVM_LOG_FILE_MAX_LINES-1000000} +LVM_EXPECTED_EXIT_STATUS=1 +export LVM_LOG_FILE_EPOCH LVM_LOG_FILE_MAX_LINES LVM_EXPECTED_EXIT_STATUS + +if test -z "$SKIP_ROOT_DM_CHECK" ; then + # Teardown only with root + test -n "$BASH" && trap 'set +vx; STACKTRACE; set -vx' ERR + trap 'aux teardown' EXIT # don't forget to clean up +else + trap 'cd $TESTOLDPWD; rm -rf "${TESTDIR:?}"' EXIT +fi + +cd "$TESTDIR" +mkdir lib tmp + +# Setting up symlink from $i to $TESTDIR/lib +# library libdevmapper-event-lvm2.so.2.03 is needed with name +test -n "${abs_top_builddir+varset}" && \ + find "$abs_top_builddir/daemons/dmeventd/plugins/" -name '*.so*' \ + -exec ln -s -t lib "{}" + +find "$TESTOLDPWD/lib" ! \( -name '*.sh' -o -name '*.[cdo]' \ + -o -name '*~' \) -exec ln -s -t lib "{}" + +LD_LIBRARY_PATH="$TESTDIR/lib:$LD_LIBRARY_PATH" + +DM_DEFAULT_NAME_MANGLING_MODE=none +DM_DEV_DIR="$TESTDIR/dev" +LVM_SYSTEM_DIR="$TESTDIR/etc" +TMPDIR="$TESTDIR/tmp" +# abort on the internal dm errors in the tests (allowing test user override) +DM_ABORT_ON_INTERNAL_ERRORS=${DM_ABORT_ON_INTERNAL_ERRORS:-1} +DM_DEBUG_WITH_LINE_NUMBERS=${DM_DEBUG_WITH_LINE_NUMBERS:-1} + +export DM_DEFAULT_NAME_MANGLING_MODE DM_DEV_DIR LVM_SYSTEM_DIR DM_ABORT_ON_INTERNAL_ERRORS +mkdir "$LVM_SYSTEM_DIR" "$DM_DEV_DIR" +MACHINEID=$(uuidgen 2>/dev/null || echo "abcdefabcdefabcdefabcdefabcdefab") +echo "${MACHINEID//-/}" > "$LVM_SYSTEM_DIR/machine-id" # remove all '-' +if test -n "$LVM_TEST_DEVDIR" ; then + test -d "$LVM_TEST_DEVDIR" || die "Test device directory LVM_TEST_DEVDIR=\"$LVM_TEST_DEVDIR\" is not valid." + DM_DEV_DIR=$LVM_TEST_DEVDIR +elif test -z "$SKIP_ROOT_DM_CHECK" ; then + mknod "$DM_DEV_DIR/testnull" c 1 3 || die "mknod failed" + echo >"$DM_DEV_DIR/testnull" || \ + die "Filesystem does support devices in $DM_DEV_DIR (mounted with nodev?)" + # dmsetup makes here needed control entry if still missing + dmsetup version || \ + die "Dmsetup in $DM_DEV_DIR can't report version?" +fi + +echo "$TESTNAME" >TESTNAME +# Require 50M of free space in testdir +test "$(df -k -P . | awk '/\// {print $4}')" -gt $(( SKIP_WITH_LOW_SPACE * 1024 )) || \ + skip "Testing requires more then ${SKIP_WITH_LOW_SPACE}M of free space in directory $TESTDIR!\\n$(df -H | sed -e 's,^,## DF: ,')" + +echo "Kernel is $(uname -a)" +# Report SELinux mode +echo "Selinux mode is $(getenforce 2>/dev/null || echo not installed)." +free -m || true + +df -h || true + +# Set vars from utils now that we have TESTDIR/PREFIX/... +prepare_test_vars + +# Set strict shell mode +# see: http://redsymbol.net/articles/unofficial-bash-strict-mode +test -n "$BASH" && set -euE -o pipefail + +# Vars for harness +echo "@TESTDIR=$TESTDIR" +echo "@PREFIX=$PREFIX" + +if test -z "$SKIP_ROOT_DM_CHECK" ; then + aux lvmconf +fi + +test -n "$LVM_TEST_LVMPOLLD" && { + export LVM_LVMPOLLD_SOCKET="$TESTDIR/lvmpolld.socket" + export LVM_LVMPOLLD_PIDFILE="$TESTDIR/lvmpolld.pid" + aux prepare_lvmpolld +} + +export SHARED="" + +if test -n "$LVM_TEST_LVMLOCKD" ; then + if test -n "$LVM_TEST_LOCK_TYPE_SANLOCK" ; then + aux lvmconf 'local/host_id = 1' + fi + + export SHARED="--shared" +fi + +# for check_lvmlockd_test, lvmlockd is restarted for each shell test. +# for check_lvmlockd_{sanlock,dlm}, lvmlockd is started once by +# aa-lvmlockd-{sanlock,dlm}-prepare.sh and left running for all shell tests. + +if test -n "$LVM_TEST_LVMLOCKD_TEST" ; then + aux prepare_lvmlockd +fi + +echo "<======== Processing test: \"$TESTNAME\" ========>" + +set -vx diff --git a/test/lib/lvm-wrapper.sh b/test/lib/lvm-wrapper.sh index d3a2a36..469154a 100644 --- a/test/lib/lvm-wrapper.sh +++ b/test/lib/lvm-wrapper.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (C) 2011-2012 Red Hat, Inc. +# Copyright (C) 2011-2017 Red Hat, Inc. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions @@ -7,26 +7,47 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . lib/paths CMD=${0##*/} test "$CMD" != lvm || unset CMD +# When needed to trace command from test suite use env var before program +# and run program directly via shell in test dir i.e.: +# sh shell/activate-mirror.sh +# 'LVM_GDB=1 lvcreate -l1 $vg' +# > run +test -z "$LVM_GDB" || exec gdb --readnow --args "$abs_top_builddir/tools/lvm" $CMD "$@" + # Multiple level of LVM_VALGRIND support # the higher level the more commands are traced if test -n "$LVM_VALGRIND"; then - RUN_VALGRIND="aux run_valgrind"; - case "$CMD" in - lvs|pvs|vgs|vgck|vgscan) - test "$LVM_VALGRIND" -gt 2 || unset RUN_VALGRIND ;; - pvcreate|pvremove|lvremove|vgcreate|vgremove) - test "$LVM_VALGRIND" -gt 1 || unset RUN_VALGRIND ;; - *) - test "$LVM_VALGRIND" -gt 0 || unset RUN_VALGRIND ;; - esac + RUN_DBG="${VALGRIND:-valgrind}"; +fi + +if test -n "$LVM_STRACE"; then + RUN_DBG="strace $LVM_STRACE -o strace.log" fi -$RUN_VALGRIND "$abs_top_builddir/tools/lvm" $CMD "$@" && \ - rm -f debug.log # Remove log for successful command +case "$CMD" in + lvs|pvs|vgs|vgck|vgscan) + test "${LVM_DEBUG_LEVEL:-0}" -lt 2 && RUN_DBG="" ;; + pvcreate|pvremove|lvremove|vgcreate|vgremove) + test "${LVM_DEBUG_LEVEL:-0}" -lt 1 && RUN_DBG="" ;; +esac + +# Capture parallel users of debug.log file +#test -z "$(fuser debug.log 2>/dev/null)" || { +# echo "TEST WARNING: \"debug.log\" is still in use while running $CMD $@" >&2 +# fuser -v debug.log >&2 +#} + +# the exec is important, because otherwise fatal signals inside "not" go unnoticed +if test -n "$abs_top_builddir"; then + exec $RUN_DBG "$abs_top_builddir/tools/lvm" $CMD "$@" +else # we are testing the lvm on $PATH + PATH=$(echo "$PATH" | sed -e 's,[^:]*lvm2-testsuite[^:]*:,,g') + exec $RUN_DBG lvm $CMD "$@" +fi diff --git a/test/lib/lvm_vdo_wrapper.sh b/test/lib/lvm_vdo_wrapper.sh new file mode 100755 index 0000000..8333256 --- /dev/null +++ b/test/lib/lvm_vdo_wrapper.sh @@ -0,0 +1,364 @@ +#!/bin/bash +# +# Wrapper script for 'naive' emulation of vdo manager tool for systems +# that no longer have this tool present +# + +set -euE -o pipefail + +# tool for formatting 'old' VDO metadata format +LVM_VDO_FORMAT=${LVM_VDO_FORMAT-"oldvdoformat"} +# tool for shifting VDO metadata header by 2MiB +LVM_VDO_PREPARE=${LVM_VDO_PREPARE-"oldvdoprepareforlvm"} +# default vdo conf file +LVM_VDO_DEFAULT_CONF=${LVM_VDO_DEFAULT_CONF-"${TMPDIR:-/tmp}/vdoconf.yml"} + +vdo_die_() { + echo -e "$@" >&2 + return 1 +} + +vdo_verbose_() { + test -z "$vdo_verbose" || echo "$0:" "$@" +} + +vdo_dry_() { + if test -n "$vdo_dry"; then + vdo_verbose_ "Dry execution" "$@" + return 0 + fi + vdo_verbose_ "Executing" "$@" + "$@" +} + +vdo_get_kb_size_with_unit_() { + local sz=${2-1} # 2nd. arg as unit - default 'k' + + case "$sz" in + [mM]) sz=1024 ;; + esac + + case "$1" in + *[kK]) sz=1 ;; + *[mM]) sz=1024 ;; + *[gG]) sz=$(( 1024 * 1024 )) ;; + *[tT]) sz=$(( 1024 * 1024 * 1024 )) ;; + *[pP]) sz=$(( 1024 * 1024 * 1024 * 1024 )) ;; + esac + + echo $(( sz * ${1%[kKmMgGtTpP]} )) +} + +# +# Emulate functionality of deprecated 'vdo create' +# +vdo_create_() { +local cachesize= +local devsize= +local emulate512=disabled +local logicalsize= +local maxdiscardsize= +local slabbits=0 # 4k +local slabsize= +local sparse= +local table= +local vdo_compression_msg= +local vdo_dry= +local vdo_index_msg= +local vdo_logicalBlockSize= +local vdo_verbose= + +local vdo_ackThreads=${vdo_ackThreads-1} +local vdo_bioRotationInterval=${vdo_bioRotationInterval-64} +local vdo_bioThreads=${vdo_bioThreads-4} +local vdo_blockMapCacheSize=${vdo_blockMapCacheSize-128M} +local vdo_blockMapPeriod=${vdo_blockMapPeriod-16380} +local vdo_compression=${vdo_compression-enabled} +local vdo_confFile=$LVM_VDO_DEFAULT_CONF # place some file in /tmp +local vdo_cpuThreads=${vdo_cpuThreads-2} +local vdo_deduplication=${vdo_deduplication-enabled} +local vdo_hashZoneThreads=${vdo_hashZoneThreads-1} +local vdo_indexCfreq=${vdo_indexCfreq-0} +local vdo_indexMemory=${vdo_indexMemory-0.25} +local vdo_indexSparse=${vdo_indexSparse-disabled} +local vdo_indexThreads=${vdo_indexThreads-0} +local vdo_logicalSize=${vdo_logicalSize-0} +local vdo_logicalThreads=${vdo_logicalThreads-1} +local vdo_maxDiscardSize=${vdo_maxDiscardSize-4K} +local vdo_name=${vdo_name-VDONAME} +local vdo_physicalThreads=${vdo_physicalThreads-1} +local vdo_slabSize=${vdo_slabSize-2G} +local vdo_writePolicy=${vdo_writePolicy-auto} +local vdo_uuid + +vdo_uuid="VDO-$(uuidgen || echo \"f7a3ecdc-40a0-4e43-814c-4a7039a75de4\")" + +while [ "$#" -ne 0 ] +do + case "$1" in + "--blockMapCacheSize") shift; vdo_blockMapCacheSize=$1 ;; + "--blockMapPeriod") shift; vdo_blockMapPeriod=$1 ;; + "--compression") shift; vdo_compression=$1 ;; + "--confFile"|"-f") shift; vdo_confFile=$1 ;; + "--deduplication") shift; vdo_deduplication=$1 ;; + "--device") shift; vdo_device=$1 ;; + "--emulate512") shift; emulate512=$1 ;; + "--indexMem") shift; vdo_indexMemory=$1 ;; + "--maxDiscardSize") shift; vdo_maxDiscardSize=$1 ;; + "--name"|"-n") shift; vdo_name=$1 ;; + "--sparseIndex") shift; vdo_indexSparse=$1 ;; + "--uuid") shift ;; # ignored + "--vdoAckThreads") shift; vdo_ackThreads=$1 ;; + "--vdoBioRotationInterval") shift; vdo_bioRotationInterval=$1 ;; + "--vdoBioThreads") shift; vdo_bioThreads=$1 ;; + "--vdoCpuThreads") shift; vdo_cpuThreads=$1 ;; + "--vdoHashZoneThreads") shift; vdo_hashZoneThreads=$1 ;; + "--vdoLogicalSize") shift; vdo_logicalSize=$1 ;; + "--vdoLogicalThreads") shift; vdo_logicalThreads=$1 ;; + "--vdoLogLevel") shift ;; # ignored + "--vdoPhysicalThreads") shift; vdo_physicalThreads=$1 ;; + "--vdoSlabSize") shift; vdo_slabSize=$1 ;; + "--verbose"|"-d"|"--debug") vdo_verbose="-v" ;; + "--writePolicy") shift; vdo_writePolicy=$1 ;; + esac + shift +done + +# Convert when set +case "$emulate512" in + "enabled") vdo_logicalBlockSize=512 ;; + "disabled") vdo_logicalBlockSize=4096 ;; + *) vdo_die_ "Invalid emulate512 setting." +esac + +case "$vdo_deduplication" in + "enabled") vdo_index_msg="index-enable" ;; + "disabled") vdo_index_msg="index-disable";; + *) vdo_die_ "Invalid deduplication setting." +esac + +case "$vdo_compression" in + "enabled") vdo_compression_msg="compression on" ;; + "disabled") vdo_compression_msg="compression off";; + *) vdo_die_ "Invalid compression setting." +esac + +test -n "${vdo_device-}" || vdo_die_ "VDO device is missing" + +blkid -c /dev/null -s UUID -o value "${vdo_device}" || true + +devsize=$(blockdev --getsize64 "$vdo_device") +devsize=$(( devsize / 4096 )) # convert to 4KiB units + +logicalsize=$(vdo_get_kb_size_with_unit_ "$vdo_logicalSize" M) +logicalsize=$(( logicalsize * 2 )) # 512B units + +cachesize=$(vdo_get_kb_size_with_unit_ "$vdo_blockMapCacheSize" M) +cachesize=$(( cachesize / 4 )) # 4KiB units + +maxdiscardsize=$(vdo_get_kb_size_with_unit_ "$vdo_maxDiscardSize" M) +maxdiscardsize=$(( maxdiscardsize / 4 )) # 4KiB units + +test -e "$vdo_confFile" || { + cat > "$vdo_confFile" <> "$vdo_confFile" </dev/null || return 0 +vdo_dry_ dmsetup remove $vdo_force "$vdo_name" || true +} + +# +# vdo remove +# +vdo_remove_() { +local vdo_confFile=$LVM_VDO_DEFAULT_CONF +local vdo_name= + +vdo_stop_ "$@" +while [ "$#" -ne 0 ] +do + case "$1" in + "--confFile"|"-f") shift; vdo_confFile=$1 ;; + "--name"|"-n") shift; vdo_name=$1 ;; + esac + shift +done + +# remove entry from conf file +awk -v vdovolname="$vdo_name" 'BEGIN { have=0 } + $0 ~ "!VDOService" { have=0 } + $0 ~ vdovolname":" { have=1 } + { if (have==0) { print } ;} + ' "$vdo_confFile" >"${vdo_confFile}.new" + +mv "${vdo_confFile}.new" "$vdo_confFile" +grep "!VDOService" "$vdo_confFile" || rm -f "$vdo_confFile" +} + + +# +# print_config_file +# +vdo_print_config_file_() { +local vdo_confFile=$LVM_VDO_DEFAULT_CONF + +while [ "$#" -ne 0 ] +do + case "$1" in + "--confFile"|"-f") shift; vdo_confFile=$1 ;; + "--verbose"|"-d"|"--debug") ;; + "--logfile") shift ;; # ignore + esac + shift +done + +cat "$vdo_confFile" +} + +# +# vdo convert +# +vdo_convert_() { +local vdo_confFile=$LVM_VDO_DEFAULT_CONF +local vdo_dry= +local vdo_force= +local vdo_name= +local vdo_verbose= +local vdo_device= +local vdo_dry_run= +local vdo_check= +local vdo_version= +local vdo_help= + +while [ "$#" -ne 0 ] +do + case "$1" in + "--confFile"|"-f") shift; vdo_confFile=$1 ;; + "--name"|"-n") shift; vdo_name=$1 ;; + "--verbose"|"-d"|"--debug") vdo_verbose="-v" ;; + "--force") vdo_force="--force" ;; + "--dry-run") vdo_dry_run="--dry-run" ;; + "--check") vdo_check="--check" ;; + "--version") vdo_version="--version" ;; + "--help") vdo_help="--help" ;; + esac + shift +done + +vdo_device=$(awk -v vdovolname="$vdo_name" 'BEGIN { have=0 } + $0 ~ "!VDOService" { have=0 } + $0 ~ vdovolname":" { have=1 } + { if (have==1 && $0 ~ "device:" ) { print $2 } ;}'\ + "$vdo_confFile") + +#dmsetup status --target vdo "$vdo_name" || true +vdo_dry_ "$LVM_VDO_PREPARE" $vdo_dry_run $vdo_check $vdo_version $vdo_help "$vdo_device" +vdo_dry_ vdo_remove_ -f "$vdo_confFile" -n "$vdo_name" || true +} + +# +# MAIN +# +case "${1-}" in + "create") shift; vdo_create_ "$@" ;; + "remove") shift; vdo_remove_ "$@" ;; + "stop") shift; vdo_stop_ "$@" ;; + "convert") shift; vdo_convert_ "$@" ;; + "printConfigFile") shift; vdo_print_config_file_ "$@" ;; +esac diff --git a/test/lib/mke2fs.conf b/test/lib/mke2fs.conf new file mode 100644 index 0000000..81bed21 --- /dev/null +++ b/test/lib/mke2fs.conf @@ -0,0 +1,45 @@ +[defaults] + base_features = sparse_super,filetype,resize_inode,dir_index,ext_attr + enable_periodic_fsck = 1 + blocksize = 4096 + inode_size = 256 + inode_ratio = 16384 + +[fs_types] + ext3 = { + features = has_journal + } + ext4 = { + features = has_journal,extent,huge_file,flex_bg,dir_nlink,extra_isize + inode_size = 256 + } + ext4dev = { + features = has_journal,extent,huge_file,flex_bg,dir_nlink,extra_isize + inode_size = 256 + options = test_fs=1 + } + small = { + blocksize = 1024 + inode_size = 128 + inode_ratio = 4096 + } + floppy = { + blocksize = 1024 + inode_size = 128 + inode_ratio = 8192 + } + news = { + inode_ratio = 4096 + } + largefile = { + inode_ratio = 1048576 + blocksize = -1 + } + largefile4 = { + inode_ratio = 4194304 + blocksize = -1 + } + hurd = { + blocksize = 4096 + inode_size = 128 + } diff --git a/test/lib/not.c b/test/lib/not.c index 9f6b988..751c95b 100644 --- a/test/lib/not.c +++ b/test/lib/not.c @@ -9,28 +9,55 @@ * * 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 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include +#include #include #include #include #include -static int finished(const char *cmd, int status) { +static int _finished(const char *cmd, int status, int pid) { + int ret; if (!strcmp(cmd, "not")) return !status; if (!strcmp(cmd, "should")) { - if (status) + if (status) { fprintf(stderr, "TEST WARNING: Ignoring command failure.\n"); + /* TODO: avoid using shell here */ + /* Show log for failing command which should be passing */ + ret = system("ls debug.log*${LVM_LOG_FILE_EPOCH}* 2>/dev/null"); + if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) { + printf("## timing off\n<======== Debug log ========>\n"); /* timing off */ + fflush(stdout); + if (system("sed -e 's,^,## DEBUG: ,' debug.log*${LVM_LOG_FILE_EPOCH}* 2>/dev/null")) { + /* Ignore result code */; + } + printf("## timing on\n"); /* timing on */ + if (system("rm -f debug.log*${LVM_LOG_FILE_EPOCH}*")) { + /* Ignore result code */; + } + fflush(stdout); + } + } return 0; + } else if (!strcmp(cmd, "invalid")) { + if (status == 3) + return 0; + fprintf(stderr, "Test expected exit code 3 (invalid), but got %d.\n", status); + } else if (!strcmp(cmd, "fail")) { + if (status == 5) + return 0; + fprintf(stderr, "Test expected exit code 5 (fail), but got %d.\n", status); } return 6; } int main(int args, char **argv) { + const char *val = NULL; pid_t pid; int status; int FAILURE = 6; @@ -45,11 +72,26 @@ int main(int args, char **argv) { fprintf(stderr, "Could not fork\n"); return FAILURE; } else if (pid == 0) { /* child */ + if (!strcmp(argv[0], "not")) + val = ">1"; + else if (!strcmp(argv[0], "invalid")) + val = "3"; + else if (!strcmp(argv[0], "fail")) + val = "5"; + + if (val) + (void) setenv("LVM_EXPECTED_EXIT_STATUS", val, 1); + + /* coverity[os_cmd_sink] intentionally passing argv + 1 */ execvp(argv[1], &argv[1]); /* should not be accessible */ return FAILURE; } else { /* parent */ - waitpid(pid, &status, 0); + if (waitpid(pid, &status, 0) < 0) { + fprintf(stderr, "Process %d failed on waitpid.\n", pid); + return FAILURE; + } + if (!WIFEXITED(status)) { if (WIFSIGNALED(status)) fprintf(stderr, @@ -59,7 +101,7 @@ int main(int args, char **argv) { return FAILURE; } - return finished(argv[0], WEXITSTATUS(status)); + return _finished(argv[0], WEXITSTATUS(status), pid); } /* not accessible */ return FAILURE; diff --git a/test/lib/runner.cpp b/test/lib/runner.cpp new file mode 100644 index 0000000..d522228 --- /dev/null +++ b/test/lib/runner.cpp @@ -0,0 +1,46 @@ +/* -*- C++ -*- copyright (c) 2014 Red Hat, Inc. + * + * This file is part of LVM2. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "brick-shelltest.h" + +int main(int argc, const char **argv) +{ + + if (getuid() != 0) { + std::cout << "Skipping tests, root is required, current UID: " << getuid() << "\n"; + return 0; + } + + try { + return brick::shelltest::run( argc, argv, "LVM_TEST_FLAVOUR" ); + } catch (std::exception const& e) { + std::cout << "Exception: " << e.what() << "\n"; + } + + return 1; +} + diff --git a/test/lib/test-corosync-conf b/test/lib/test-corosync-conf new file mode 100644 index 0000000..e04be73 --- /dev/null +++ b/test/lib/test-corosync-conf @@ -0,0 +1,28 @@ +# created by lvm test suite +totem { + version: 2 + secauth: off + cluster_name: test + interface { + ingnumber: 0 + bindnetaddr: 127.0.0.1 + mcastaddr: 239.255.255.100 + mcastport: 5405 + ttl: 1 + } +} +nodelist { + node { + ring0_addr: @LOCAL_NODE@ + nodeid: 1 + } +} +quorum { + provider: corosync_votequorum + expected_votes: 1 + two_node: 0 +} +logging { + to_syslog: yes +} + diff --git a/test/lib/test-dlm-conf b/test/lib/test-dlm-conf new file mode 100644 index 0000000..a93c93f --- /dev/null +++ b/test/lib/test-dlm-conf @@ -0,0 +1,4 @@ +# created by lvm test suite +log_debug=1 +enable_fencing=0 + diff --git a/test/lib/test-sanlock-conf b/test/lib/test-sanlock-conf new file mode 100644 index 0000000..6285d63 --- /dev/null +++ b/test/lib/test-sanlock-conf @@ -0,0 +1,2 @@ +# created by lvm test suite +use_watchdog=0 diff --git a/test/lib/test.sh b/test/lib/test.sh deleted file mode 100644 index 3729749..0000000 --- a/test/lib/test.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash -# Copyright (C) 2011-2012 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 - -# sanitize the environment -LANG=C -LC_ALL=C -TZ=UTC - -# Put script name into variable, so it can used in external scripts -TESTNAME=${0##*/} -# Nice debug message -PS4='#${BASH_SOURCE[0]##*/}:${LINENO}+ ' -export TESTNAME PS4 - -unset CDPATH - -# grab some common utilities -. lib/utils - -TESTOLDPWD=$(pwd) -COMMON_PREFIX="LVMTEST" -PREFIX="${COMMON_PREFIX}$$" - -TESTDIR=$(mkdtemp "${LVM_TEST_DIR:-$TESTOLDPWD}" "$PREFIX.XXXXXXXXXX") || \ - die "failed to create temporary directory in ${LVM_TEST_DIR:-$TESTOLDPWD}" -RUNNING_DMEVENTD=$(pgrep dmeventd) || true - -export TESTOLDPWD TESTDIR COMMON_PREFIX PREFIX RUNNING_DMEVENTD - -test -n "$BASH" && trap 'set +vx; STACKTRACE; set -vx' ERR -trap 'aux teardown' EXIT # don't forget to clean up - -DM_DEV_DIR="$TESTDIR/dev" -LVM_SYSTEM_DIR="$TESTDIR/etc" -mkdir "$LVM_SYSTEM_DIR" "$TESTDIR/lib" "$DM_DEV_DIR" -if test -n "$LVM_TEST_DEVDIR" ; then - DM_DEV_DIR=$LVM_TEST_DEVDIR -else - mknod "$DM_DEV_DIR/testnull" c 1 3 || die "mknod failed"; - echo >"$DM_DEV_DIR/testnull" || \ - die "Filesystem does support devices in $DM_DEV_DIR (mounted with nodev?)" - mkdir "$DM_DEV_DIR/mapper" -fi - -export DM_DEV_DIR LVM_SYSTEM_DIR - -cd "$TESTDIR" - -echo "$TESTNAME" >TESTNAME - -# Setting up symlink from $i to $TESTDIR/lib -find "$abs_top_builddir/daemons/dmeventd/plugins/" -name '*.so' \ - -exec ln -s -t lib "{}" + -find "$abs_top_builddir/test/lib" ! \( -name '*.sh' -o -name '*.[cdo]' \ - -o -name '*~' \) -exec ln -s -t lib "{}" + - -# Set vars from utils now that we have TESTDIR/PREFIX/... -prepare_test_vars - -test -n "$BASH" && set -eE -o pipefail - -aux lvmconf -aux prepare_clvmd -test -n "$LVM_TEST_LVMETAD" && { - aux prepare_lvmetad - export LVM_LVMETAD_SOCKET="$TESTDIR/lvmetad.socket" -} -echo "@TESTDIR=$TESTDIR" -echo "@PREFIX=$PREFIX" - -set -vx diff --git a/test/lib/utils.sh b/test/lib/utils.sh index 70d9f66..24b7f89 100644 --- a/test/lib/utils.sh +++ b/test/lib/utils.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +7,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA set -e MAX_TRIES=4 @@ -15,7 +15,8 @@ IFS_NL=' ' die() { - echo "$@" >&2 + rm -f debug.log* + echo -e "$@" >&2 return 1 } @@ -34,16 +35,16 @@ rand_bytes() { 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) + n_plus_50=$(( 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; + len=${#data} # number of chars in $data + 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 \ + echo "$data" | dd bs=1 skip=50 count="$n" 2>/dev/null \ | tr -c "$chars" "01234567$chars$chars$chars" } @@ -56,6 +57,8 @@ mkdtemp() { destdir=$1 template=$2 + test -d "$destdir" || die "DIR ('$destdir') does not exist." + case "$template" in *XXXX) ;; *) die "Invalid template: $template (must have a suffix of at least 4 X's)";; @@ -84,7 +87,7 @@ mkdtemp() { base_template=$(echo "$template" | sed 's/XX*$//') # Calculate how many X's we've just removed. - nx=$(expr length "$template" - length "$base_template") + nx=$(( ${#template} - ${#base_template} )) err= i=1 @@ -94,62 +97,136 @@ mkdtemp() { err=$(mkdir -m 0700 "$candidate_dir" 2>&1) && \ { echo "$candidate_dir"; return; } test $MAX_TRIES -le $i && break; - i=$(expr $i + 1) + i=$(( i + 1 )) done die "$err" } +# Like grep, just always print 1st. line +grep1_() { + awk -v pattern="${1}" 'NR==1 || $0~pattern' "${@:2}" +} + +stacktrace() { + trap - ERR + # i=1 - ignoring innermost frame - it is always stacktrace function + local i=1 n=${#BASH_LINENO[*]} + # n-=1 - ignoring last frame as well - it is not interesting + n=$(( n - 1 )) + + echo "## - $0:${BASH_LINENO[$((n-1))]}" + while [[ $i -lt $n ]]; do + echo "## $i ${FUNCNAME[$i]}() called from ${BASH_SOURCE[$((i+1))]}:${BASH_LINENO[$i]}" + i=$(( i + 1 )) + done +} + STACKTRACE() { trap - ERR - local i=0 + local i - echo "## - $0:${BASH_LINENO[0]}" - while FUNC=${FUNCNAME[$i]}; test "$FUNC" != "main"; do - echo "## $i ${FUNC}() called from ${BASH_SOURCE[$i]}:${BASH_LINENO[$i]}" - i=$(($i + 1)) - done + stacktrace - test ${LVM_TEST_PARALLEL:-0} -eq 1 -o -n "$RUNNING_DMEVENTD" -o -f LOCAL_DMEVENTD || { - pgrep dmeventd &>/dev/null && \ - die "** During test dmeventd has been started!" - } + test "${LVM_TEST_PARALLEL:-0}" -eq 0 && test -z "$RUNNING_DMEVENTD" && \ + test ! -f LOCAL_DMEVENTD && pgrep dmeventd >DPID 2>/dev/null && { + echo "## ERROR: The test started dmeventd ($(< DPID)) unexpectedly." + kill "$(< DPID)" + } # 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 + # Check for all cores newer then TESTNAME file + # Assume users keep prefix 'core' + # TODO: possibly better integrate with coredumpctl & systemd + while IFS= read -r i; do + bin=$(gdb -batch -c "$i" 2>&1 | grep "generated by" | \ + sed -e "s,.*generated by \`\([^ ']*\).*,\1,") || continue + { + echo bt full + echo l + echo quit + } > gdb_commands.txt || rm -f gdb_commands.txt + + if test ! -s gdb_commands.txt ; then + echo "Out of disk space, can't check coredump $i generated by $bin." + continue + fi + + echo "## Checking coredump: $i generated by $bin." + gdb -batch -c "$i" -x gdb_commands.txt "$(which "$bin")" 2>/dev/null | \ + sed -e "s,^,## GDB: ," || continue + done < <(find . "$(dirname "$(sysctl -n kernel.core_pattern)")" \ + "/var/lib/systemd/coredump/" -name 'core*' -newer TESTNAME 2>/dev/null || true) fi - test -z "$LVM_TEST_NODEBUG" -a -f debug.log && { - sed -e "s,^,## DEBUG: ,;s,$top_srcdir/\?,," < debug.log - } - test -f SKIP_THIS_TEST && exit 200 + + test -z "$LVM_TEST_NODEBUG" && test -f TESTNAME && { + local name + local idx=0 + for i in debug.log* ; do + test -f "$i" || break # nothing is found (expands to debug.log*) + name=${i##debug.log_} + name=${name%%_*} + test "$name" = "DEBUG" && { name="$name$idx" ; idx=$(( idx + 1 )) ; } + echo "<======== Debug log $i ========>" + sed -e "s,^,## $name: ," "$i" + mv -f "$i" "debug_${i#debug.}" + done + if test -e strace.log ; then + echo "<======== Strace debug log ========>" + sed -e "s,^,## STRACE: ," strace.log + fi + if dmsetup info -c | grep -q "$PREFIX" ; then + echo "<======== Info ========>" + dmsetup info -c | grep1_ "$PREFIX"| sed -e "s,^,## DMINFO: ," + echo "<======== Active table ========>" + dmsetup table | grep "$PREFIX" | sed -e "s,^,## DMTABLE: ," + echo "<======== Inactive table ========>" + dmsetup table --inactive | grep "$PREFIX" | sed -e "s,^,## DMITABLE: ," + echo "<======== Status ========>" + dmsetup status --noflush | grep "$PREFIX" | sed -e "s,^,## DMSTATUS: ," + echo "<======== Tree ========>" + dmsetup ls --tree | sed -e "s,^,## DMTREE: ," + echo "<======== Recursive list of $DM_DEV_DIR ========>" + ls -lR -I bsg -I bus -I char -Idma_heap -I dri \ + -I hugepages -I input -I mqueue \ + -I net -I pts -I shm -I snd \ + -I tty?* -I usb -I vfio -I vcs?* \ + -I virtio-ports \ + "$DM_DEV_DIR" | sed -e "s,^,## LS_LR: ," + echo "<======== Udev DB content ========>" + for i in /sys/block/dm-* /sys/block/loop* ; do + udevadm info --query=all --path "$i" 2>/dev/null || true + done | sed -e "s,^,## UDEV: ," + fi + echo "<======== Free space ========>" + df -h | sed -e "s,^,## DF_H: ," + echo "<======== Script file \"$(< TESTNAME)\" ========>" + local script=$0 + test -f "$script" || script="$TESTOLDPWD/$0" + awk '{print "## Line:", NR, "\t", $0}' "$script" + } } init_udev_transaction() { - if test "$DM_UDEV_SYNCHRONISATION" = 1; then - local cookie=$(dmsetup udevcreatecookie) + if test "$DM_UDEV_SYNCHRONIZATION" = 1; then + local cookie + cookie=$(dmsetup udevcreatecookie) # Cookie is not generated if udev is not running! test -z "$cookie" || export DM_UDEV_COOKIE=$cookie fi } finish_udev_transaction() { - if test "$DM_UDEV_SYNCHRONISATION" = 1 -a -n "$DM_UDEV_COOKIE"; then - dmsetup udevreleasecookie + if test "$DM_UDEV_SYNCHRONIZATION" = 1 && test -n "${DM_UDEV_COOKIE-}" ; then + dmsetup udevreleasecookie || true unset DM_UDEV_COOKIE fi } teardown_udev_cookies() { - if test "$DM_UDEV_SYNCHRONISATION" = 1; then + if test "$DM_UDEV_SYNCHRONIZATION" = 1; then # Delete any cookies created more than 10 minutes ago # and not used in the last 10 minutes. # Log only non-zero semaphores count @@ -161,55 +238,73 @@ dm_info() { should dmsetup info --noheadings -c -o "$@" } +dm_status() { + should dmsetup status --noheadings "$@" +} + dm_table() { should dmsetup table "$@" } skip() { + set +vx # debug off + if test "$#" -eq 0; then + stacktrace + else + echo -e "TEST SKIPPED:" "$@" + fi touch SKIP_THIS_TEST exit 200 } -kernel_at_least() { - local major=$(uname -r | cut -d. -f1) - local minor=$(uname -r | cut -d. -f2 | cut -d- -f1) - - test "$major" -gt "$1" && return 0 - test "$major" -eq "$1" || return 1 - test "$minor" -gt "$2" && return 0 - test "$minor" -eq "$2" || return 1 - test -z "$3" && return 0 +get_real_devs() { + REAL_DEVICES=( $(/dev/null || return 1 +get_devs() { + local IFS=$IFS_NL + DEVICES=( $( expected +. lib/inittest + +lvm version -lvm pvmove --version|sed -n "1s/.*: *\([0-9][^ ]*\) .*/\1/p" > actual +lvm pvmove --version|sed -n "1s/.*: *\([0-9][^ ]*\) .*/\1/p" | tee version # ensure they are the same -diff -u actual expected +diff -u version lib/version-expected + +dmstats version |sed -n "1s/.*: *\([0-9][^ ]*\) .*/\1/p" | tee dmstats-version + +# ensure dmstats version matches build +diff -u dmstats-version lib/dm-version-expected # ensure we can create devices (uses dmsetup, etc) aux prepare_devs 5 +get_devs # ensure we do not crash on a bug in config file aux lvmconf 'log/prefix = 1""' -not lvs $(cat DEVICES) +not lvs "${DEVICES[@]}" + +# validate testing machine with its services is in expected state and will not interfere with tests +if systemctl -a >out 2>/dev/null ; then + for i in dm-event lvm2-lvmpolld lvm2-monitor ; do + grep $i out > mout || continue + grep -v masked mout || continue + should not echo "Present unmasked $i service/socket may randomize testing results!" + echo "+++++ Stop & Mask with systemctl +++++" + touch show_out + done + test ! -e show_out || cat out +fi diff --git a/test/shell/aa-lvmlockd-dlm-prepare.sh b/test/shell/aa-lvmlockd-dlm-prepare.sh new file mode 100644 index 0000000..c261c1d --- /dev/null +++ b/test/shell/aa-lvmlockd-dlm-prepare.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Set up things to run tests with dlm' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_DLM" ] && skip; + +aux prepare_dlm +aux prepare_lvmlockd + diff --git a/test/shell/aa-lvmlockd-idm-prepare.sh b/test/shell/aa-lvmlockd-idm-prepare.sh new file mode 100644 index 0000000..fc9d75b --- /dev/null +++ b/test/shell/aa-lvmlockd-idm-prepare.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate. 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Set up things to run tests with idm' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip; + +aux prepare_idm +aux prepare_lvmlockd diff --git a/test/shell/aa-lvmlockd-sanlock-prepare.sh b/test/shell/aa-lvmlockd-sanlock-prepare.sh new file mode 100644 index 0000000..6db14fe --- /dev/null +++ b/test/shell/aa-lvmlockd-sanlock-prepare.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Set up things to run tests with sanlock' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_SANLOCK" ] && skip; + +# Create a device and a VG that are both outside the scope of +# the standard lvm test suite so that they will not be removed +# and will remain in place while all the tests are run. +# +# Use this VG to hold the sanlock global lock which will be used +# by lvmlockd during other tests. +# +# This script will be run before any standard tests are run. +# After all the tests are run, another script will be run +# to remove this VG and device. + +GL_DEV="/dev/mapper/GL_DEV" +GL_FILE="$PWD/gl_file.img" +dmsetup remove GL_DEV || true +rm -f "$GL_FILE" +dd if=/dev/zero of="$GL_FILE" bs=$((1024*1024)) count=1024 2> /dev/null +GL_LOOP=$(losetup -f "$GL_FILE" --show) +echo "0 $(blockdev --getsize $GL_LOOP linear $GL_LOOP 0)" | dmsetup create GL_DEV + +aux prepare_sanlock +aux prepare_lvmlockd + +vgcreate --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' --lock-type sanlock glvg $GL_DEV + +vgs --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' -o+locktype,lockargs glvg + diff --git a/test/shell/activate-minor.sh b/test/shell/activate-minor.sh index 5433f01..1b1ea8b 100644 --- a/test/shell/activate-minor.sh +++ b/test/shell/activate-minor.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash + # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,13 +8,22 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest + +# Just skip this test if minor is already in use... +dmsetup info | tee info +grep -E "^Major, minor: *[0-9]+, 123" info && skip aux prepare_vg 2 lvcreate -a n --zero n -l 1 -n foo $vg lvchange $vg/foo -My --major=255 --minor=123 lvchange $vg/foo -a y dmsetup info $vg-foo | tee info -egrep "^Major, minor: *[0-9]+, 123" info +grep -E "^Major, minor: *[0-9]+, 123" info + +vgremove -ff $vg diff --git a/test/shell/activate-missing-segment.sh b/test/shell/activate-missing-segment.sh index 55ec7ec..f066e58 100644 --- a/test/shell/activate-missing-segment.sh +++ b/test/shell/activate-missing-segment.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Test activation behaviour with devices missing. # - snapshots and their origins are only activated together; if one fails, both @@ -16,7 +17,10 @@ # instead lvconvert --repair them?) # - linear LVs with bits missing are not activated -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_vg 2 @@ -27,3 +31,5 @@ aux disable_dev "$dev1" not vgchange -a y $vg vgchange -a y --partial $vg check active $vg span + +vgremove -ff $vg diff --git a/test/shell/activate-missing.sh b/test/shell/activate-missing.sh index 4676ee1..c1c02d8 100644 --- a/test/shell/activate-missing.sh +++ b/test/shell/activate-missing.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Test activation behaviour with devices missing. # - snapshots and their origins are only activated together; if one fails, both @@ -16,7 +17,10 @@ # instead lvconvert --repair them?) # - linear LVs with bits missing are not activated -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_vg 4 @@ -24,11 +28,11 @@ 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 -aey -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" +lvcreate -aey -l1 --type mirror -m1 -n mirror12 --mirrorlog core $vg "$dev1" "$dev2" +lvcreate -aey -l1 --type mirror -m1 -n mirror123 $vg "$dev1" "$dev2" "$dev3" vgchange -a n $vg aux disable_dev "$dev1" @@ -46,7 +50,7 @@ check inactive $vg mirror123 vgchange -a n $vg aux enable_dev "$dev1" aux disable_dev "$dev2" -not vgchange -a y $vg +not vgchange -aey $vg not vgck $vg check active $vg linear1 @@ -60,7 +64,7 @@ check inactive $vg mirror123 vgchange -a n $vg aux enable_dev "$dev2" aux disable_dev "$dev3" -not vgchange -a y $vg +not vgchange -aey $vg not vgck $vg check active $vg origin1 @@ -74,7 +78,7 @@ check active $vg mirror12 vgchange -a n $vg aux enable_dev "$dev3" aux disable_dev "$dev4" -vgchange -a y $vg +vgchange -aey $vg not vgck $vg check active $vg origin1 @@ -84,3 +88,5 @@ check active $vg linear2 check active $vg linear12 check active $vg mirror12 check active $vg mirror123 + +vgremove -ff $vg diff --git a/test/shell/activate-partial.sh b/test/shell/activate-partial.sh index 4a06fc1..70c50bc 100644 --- a/test/shell/activate-partial.sh +++ b/test/shell/activate-partial.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,25 +8,28 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_vg 3 -lvcreate -m 1 -l 1 -n mirror $vg +lvcreate -aey --type mirror -m 1 -l 1 --nosync -n mirror $vg lvchange -a n $vg/mirror aux disable_dev "$dev1" not vgreduce --removemissing $vg -not lvchange -v -a y $vg/mirror -lvchange -v --partial -a y $vg/mirror +not lvchange -v -aey $vg/mirror +lvchange -v --partial -aey $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 +vgchange -aey --partial $vg # check vgremove -vgremove -f $vg +vgremove -ff $vg diff --git a/test/shell/activation-skip.sh b/test/shell/activation-skip.sh new file mode 100644 index 0000000..b0b3206 --- /dev/null +++ b/test/shell/activation-skip.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Test skip activation flag -k|--setactivationskip + +aux prepare_vg + +lvcreate -an --zero n -l 1 -n $lv1 $vg +lvcreate -ky -K -l1 -n $lv2 $vg +get lv_field $vg/$lv2 lv_attr | grep -- "-wi-a----k" + +lvchange -ay -K $vg +check active $vg $lv1 +lvchange -an $vg + +lvchange -ay --setactivationskip y $vg/$lv1 +check inactive $vg $lv1 + +get lv_field $vg/$lv1 lv_attr | grep -- "-wi------k" + +lvchange -ay -K $vg +check active $vg $lv1 + +vgremove -ff $vg diff --git a/test/shell/allow-mixed-block-sizes.sh b/test/shell/allow-mixed-block-sizes.sh new file mode 100644 index 0000000..d6983cc --- /dev/null +++ b/test/shell/allow-mixed-block-sizes.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019-2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +losetup -h | grep sector-size || skip +which fallocate || skip + +fallocate -l 2M loopa +fallocate -l 2M loopb + +# Fight a weird occasional race in losetup usage: +# +# losetup: loopa: failed to set up loop device: Resource temporarily unavailable +# loop0: detected capacity change from 0 to 4096 +# loop_set_block_size: loop0 () has still dirty pages (nrpages=2) +for i in {1..5} ; do + LOOP1=$(losetup -f loopa --sector-size 4096 --show || true) + test -n "$LOOP1" && break +done +for i in {1..5} ; do + LOOP2=$(losetup -f loopb --show || true) + test -n "$LOOP2" && break +done + +# prepare devX mapping so it works for real & fake dev dir +d=1 +for i in "$LOOP1" "$LOOP2"; do + echo "$i" + m=${i##*loop} + test -e "$DM_DEV_DIR/loop$m" || mknod "$DM_DEV_DIR/loop$m" b 7 "$m" + eval "dev$d=\"$DM_DEV_DIR/loop$m\"" + d=$(( d + 1 )) +done + +aux extend_filter "a|$dev1|" "a|$dev2|" +aux extend_devices "$dev1" "$dev2" + +not vgcreate --config 'devices/allow_mixed_block_sizes=0' $vg "$dev1" "$dev2" +vgcreate --config 'devices/allow_mixed_block_sizes=1' $vg "$dev1" "$dev2" +vgs --config 'devices/allow_mixed_block_sizes=1' $vg + +for i in "$dev1" "$dev2" ; do + aux wipefs_a "$i" + # FIXME - we are not missing notification for hinting + # likely in more places - as the test should be able to work without + # system's udev working only on real /dev dir. + # aux notify_lvmetad "$i" +done + +vgcreate --config 'devices/allow_mixed_block_sizes=1' $vg "$dev1" +vgs --config 'devices/allow_mixed_block_sizes=1' $vg +not vgextend --config 'devices/allow_mixed_block_sizes=0' $vg "$dev2" +vgextend --config 'devices/allow_mixed_block_sizes=1' $vg "$dev2" + +losetup -d "$LOOP1" +losetup -d "$LOOP2" +rm loopa +rm loopb diff --git a/test/shell/autoactivation-metadata.sh b/test/shell/autoactivation-metadata.sh new file mode 100644 index 0000000..3cdb5b3 --- /dev/null +++ b/test/shell/autoactivation-metadata.sh @@ -0,0 +1,336 @@ + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* + rm -f "$PVS_LOOKUP_DIR"/* +} + +. lib/inittest + +aux prepare_devs 1 + +# +# test lvchange --setautoactivation +# + +# default +vgcreate $vg "$dev1" +lvcreate -n $lv1 -l1 -an $vg +check vg_field $vg autoactivation "enabled" +check lv_field $vg/$lv1 autoactivation "enabled" + +lvchange -aay $vg/$lv1 +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +lvchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +_clear_online_files + +# --aa=n +lvchange --setautoactivation n $vg/$lv1 +check vg_field $vg autoactivation "enabled" +check lv_field $vg/$lv1 autoactivation "" + +lvchange -aay $vg/$lv1 +check lv_field $vg/$lv1 lv_active "" +lvchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "" +_clear_online_files + +# --aa=y +lvchange --setautoactivation y $vg/$lv1 +check vg_field $vg autoactivation "enabled" +check lv_field $vg/$lv1 autoactivation "enabled" + +lvchange -aay $vg/$lv1 +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +lvchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +_clear_online_files + +vgremove -y $vg + +# +# test vgchange --setautoactivation +# + +# default +vgcreate $vg "$dev1" +lvcreate -n $lv1 -l1 -an $vg + +# --aa=n +vgchange --setautoactivation n $vg +check vg_field $vg autoactivation "" +check lv_field $vg/$lv1 autoactivation "enabled" + +lvchange -aay $vg/$lv1 +check lv_field $vg/$lv1 lv_active "" +lvchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "" +_clear_online_files + +# --aa=y +vgchange --setautoactivation y $vg +check vg_field $vg autoactivation "enabled" +check lv_field $vg/$lv1 autoactivation "enabled" + +lvchange -aay $vg/$lv1 +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +lvchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "active" +lvchange -an $vg/$lv1 +_clear_online_files + +vgremove -y $vg + +# +# test vgcreate --setautoactivation, lvcreate --setautoactivation +# + +vgcreate $vg "$dev1" +lvcreate -n $lv1 -l1 -an $vg +lvcreate -n $lv2 -l1 --setautoactivation y -an $vg +lvcreate -n $lv3 -l1 --setautoactivation n -an $vg +check vg_field $vg autoactivation "enabled" +check lv_field $vg/$lv1 autoactivation "enabled" +check lv_field $vg/$lv2 autoactivation "enabled" +check lv_field $vg/$lv3 autoactivation "" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "active" +check lv_field $vg/$lv3 lv_active "" +vgchange -an $vg +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +lvchange -aay $vg/$lv3 +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "active" +check lv_field $vg/$lv3 lv_active "" +vgchange -an $vg +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "active" +check lv_field $vg/$lv3 lv_active "" +vgchange -an $vg +vgremove -y $vg +_clear_online_files + +vgcreate --setautoactivation y $vg "$dev1" +lvcreate -n $lv1 -l1 -an $vg +lvcreate -n $lv2 -l1 --setautoactivation y -an $vg +lvcreate -n $lv3 -l1 --setautoactivation n -an $vg +check vg_field $vg autoactivation "enabled" +check lv_field $vg/$lv1 autoactivation "enabled" +check lv_field $vg/$lv2 autoactivation "enabled" +check lv_field $vg/$lv3 autoactivation "" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "active" +check lv_field $vg/$lv3 lv_active "" +vgchange -an $vg +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +lvchange -aay $vg/$lv3 +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "active" +check lv_field $vg/$lv3 lv_active "" +vgchange -an $vg +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "active" +check lv_field $vg/$lv3 lv_active "" +vgchange -an $vg +vgremove -y $vg +_clear_online_files + +vgcreate --setautoactivation n $vg "$dev1" +lvcreate -n $lv1 -l1 -an $vg +lvcreate -n $lv2 -l1 --setautoactivation y -an $vg +lvcreate -n $lv3 -l1 --setautoactivation n -an $vg +check vg_field $vg autoactivation "" +check lv_field $vg/$lv1 autoactivation "enabled" +check lv_field $vg/$lv2 autoactivation "enabled" +check lv_field $vg/$lv3 autoactivation "" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +check lv_field $vg/$lv3 lv_active "" +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +lvchange -aay $vg/$lv3 +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +check lv_field $vg/$lv3 lv_active "" +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +check lv_field $vg/$lv3 lv_active "" +vgremove -y $vg +_clear_online_files + + +# +# test combination of --aa and auto_activation_volume_list +# + +vgcreate $vg "$dev1" +lvcreate -n $lv1 -l1 -an $vg +lvcreate -n $lv2 -l1 --setautoactivation n -an $vg +check vg_field $vg autoactivation "enabled" +check lv_field $vg/$lv1 autoactivation "enabled" +check lv_field $vg/$lv2 autoactivation "" + +# list prevents all aa, metadata settings don't matter +aux lvmconf "activation/auto_activation_volume_list = [ ]" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +_clear_online_files + +# list allows all vg aa, metadata allows lv1 -> lv1 activated +aux lvmconf "activation/auto_activation_volume_list = [ \"$vg\" ]" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +_clear_online_files + +# list allows lv1, metadata allows lv1 -> lv1 activated +aux lvmconf "activation/auto_activation_volume_list = [ \"$vg/$lv1\" ]" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +_clear_online_files + +# list allows lv2, metadata allows lv1 -> nothing activated +aux lvmconf "activation/auto_activation_volume_list = [ \"$vg/$lv2\" ]" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +_clear_online_files + +vgremove -y $vg + +vgcreate --setautoactivation n $vg "$dev1" +lvcreate -n $lv1 -l1 -an $vg +lvcreate -n $lv2 -l1 --setautoactivation n -an $vg +check vg_field $vg autoactivation "" +check lv_field $vg/$lv1 autoactivation "enabled" +check lv_field $vg/$lv2 autoactivation "" + +# list prevents all aa, metadata settings don't matter +aux lvmconf "activation/auto_activation_volume_list = [ ]" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +_clear_online_files + +# list allows lv1, metadata disallows vg -> nothing activated +aux lvmconf "activation/auto_activation_volume_list = [ \"$vg/$lv1\" ]" +vgchange -aay $vg +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +lvchange -aay $vg/$lv1 +lvchange -aay $vg/$lv2 +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +pvscan --cache -aay "$dev1" +check lv_field $vg/$lv1 lv_active "" +check lv_field $vg/$lv2 lv_active "" +vgchange -an $vg +_clear_online_files + +vgremove -y $vg + diff --git a/test/shell/backup-read-only.sh b/test/shell/backup-read-only.sh new file mode 100644 index 0000000..331e846 --- /dev/null +++ b/test/shell/backup-read-only.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_CLVMD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext3 || skip + +aux prepare_vg 2 + +# Note: inittest.sh sets LVM_SYSTEM_DIR to 'just' etc +etc_lv="$DM_DEV_DIR/$vg/$lv1" + +cleanup_mounted_and_teardown() +{ + umount "$mount_dir" || true + aux teardown +} + +vgreduce $vg "$dev2" + +lvcreate -n $lv1 -l 20%FREE $vg +mkfs.ext3 -b4096 -j "$etc_lv" + +# +# check read-only archive dir +# +mount_dir="etc/archive" +trap 'cleanup_mounted_and_teardown' EXIT +mkdir -p "$mount_dir" +mount -n -r "$etc_lv" "$mount_dir" + +aux lvmconf "backup/archive = 1" "backup/backup = 1" + +# cannot archive to read-only - requires user to specify -An +not lvcreate -n $lv2 -l 10%FREE $vg +lvcreate -An -n $lv2 -l 10%FREE $vg + +not vgextend $vg "$dev2" +vgextend -An $vg "$dev2" + +umount "$mount_dir" || true + +vgreduce $vg "$dev2" + +# +# check read-only backup dir +# +mount_dir="etc/backup" +mount -n -r "$etc_lv" "$mount_dir" + +# Must not fail on making backup +vgscan + +lvcreate -An -n $lv3 -l 10%FREE $vg + +vgextend $vg "$dev2" + +# +# Now check both archive & backup read-only +# +rm -rf etc/archive +ln -s backup etc/archive + +# Must not fail on making backup +vgscan +lvcreate -An -n $lv4 -l 10%FREE $vg + +umount "$mount_dir" || true + +# TODO maybe also support --ignorelockingfailure ?? +vgremove -ff $vg diff --git a/test/shell/cache-metadata2.sh b/test/shell/cache-metadata2.sh new file mode 100644 index 0000000..0270f5d --- /dev/null +++ b/test/shell/cache-metadata2.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise usage of metadata2 cache metadata format + + +SKIP_WITH_LVMPOLLD=1 + +# Until new version of cache_check tools - no integrity validation +LVM_TEST_CACHE_CHECK_CMD="" + +. lib/inittest + +META2= +aux have_cache 1 10 0 || { + META2=not + aux have_cache 1 3 0 || skip +} + +aux prepare_vg 5 80 + +lvcreate -L2 -n $lv1 $vg + +lvcreate --type cache-pool -L1 $vg/cpool1 +# no parameter - no format is stored +check lv_field $vg/cpool1 cachemetadataformat "" + +lvcreate --type cache-pool -L1 --config 'allocation/cache_metadata_format=1' $vg/cpool +# format is in configuration - would be applied during actual caching +# so not stored in this moment +check lv_field $vg/cpool cachemetadataformat "" + + +lvcreate --type cache-pool -L1 --cachemetadataformat 1 $vg/cpool2 +# format was specified on cmdline - preserve it metadata +check lv_field $vg/cpool2 cachemetadataformat "1" + +lvconvert --yes -H --cachepool $vg/cpool --config 'allocation/cache_metadata_format=1' $vg/$lv1 +check lv_field $vg/cpool2 cachemetadataformat "1" + +lvs -a -o+cachemetadataformat $vg + +lvremove -f $vg + +lvcreate --type cache-pool --cachepolicy cleaner --cachemetadataformat 1 -L1 $vg/cpool +lvcreate -H -L10 -n $lv1 --cachepool $vg/cpool +check lv_field $vg/$lv1 cachemetadataformat "1" +lvremove -f $vg + +if [ -z "$META2" ]; then +# for these test we need kernel with metadata2 support + +lvcreate --type cache-pool -L1 $vg/cpool +lvcreate -H -L10 -n $lv1 --cachepool $vg/cpool +check lv_field $vg/$lv1 cachemetadataformat "2" +lvremove -f $vg + +lvcreate -L10 -n $lv1 $vg +lvcreate --type cache-pool -L1 $vg/cpool +lvconvert -y -H --cachepool $vg/cpool $vg/$lv1 +check lv_field $vg/$lv1 cachemetadataformat "2" +lvremove -f $vg + + +lvcreate -L10 -n $lv1 $vg +lvcreate --type cache-pool -L1 $vg/cpool +lvconvert --cachemetadataformat 1 -y -H --cachepool $vg/cpool $vg/$lv1 +check lv_field $vg/$lv1 cachemetadataformat "1" +lvremove -f $vg + +lvcreate -L10 -n $lv1 $vg +lvcreate --type cache-pool -L1 $vg/cpool +lvconvert --config 'allocation/cache_metadata_format=1' -y -H --cachepool $vg/cpool $vg/$lv1 +check lv_field $vg/$lv1 cachemetadataformat "1" +lvremove -f $vg + +lvcreate --type cache-pool --cachepolicy cleaner -L1 $vg/cpool +lvcreate -H -L10 -n $lv1 --cachepool $vg/cpool +check lv_field $vg/$lv1 cachemetadataformat "2" +lvremove -f $vg + +lvcreate --type cache-pool --cachepolicy mq --cachemetadataformat 1 -L1 $vg/cpool +check lv_field $vg/cpool cachemetadataformat "1" +lvcreate -H -L10 -n $lv1 --cachemetadataformat 2 --cachepool $vg/cpool +check lv_field $vg/$lv1 cachemetadataformat "2" +lvremove -f $vg + +fi +#lvs -a -o name,cachemetadataformat,kernelmetadataformat,chunksize,cachepolicy,cachemode $vg + +vgremove -f $vg diff --git a/test/shell/cache-no-discard.sh b/test/shell/cache-no-discard.sh new file mode 100644 index 0000000..4593622 --- /dev/null +++ b/test/shell/cache-no-discard.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check reporting of no_discard_passdown + +SKIP_WITH_LVMPOLLD=1 + +# Until new version of cache_check tools - no integrity validation +LVM_TEST_CACHE_CHECK_CMD="" + +. lib/inittest + +aux kernel_at_least 5 1 || skip + +aux have_cache 2 0 + +aux prepare_vg 1 + +# Create thinLV without discard +lvcreate --discards=ignore -T -V20 -L20 -n $lv $vg/pool + +aux extend_filter_LVMTEST + +# Use discard-less LV as PV for $vg1 +pvcreate "$DM_DEV_DIR/$vg/$lv" +vgcreate -s 128K $vg1 "$DM_DEV_DIR/$vg/$lv" + +# Create simple cache LV +lvcreate -aey -L2 -n $lv1 $vg1 +lvcreate -H -L2 $vg1/$lv1 + +#lvs -ao+kernel_discards $vg1 +check lv_field $vg1/$lv1 kernel_discards "nopassdown" + +vgremove -f $vg1 +vgremove -f $vg diff --git a/test/shell/cache-single-options.sh b/test/shell/cache-single-options.sh new file mode 100644 index 0000000..c736e52 --- /dev/null +++ b/test/shell/cache-single-options.sh @@ -0,0 +1,273 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test single lv cache options + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 10 0 || skip +which mkfs.xfs || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +# generate random data +dd if=/dev/urandom of=pattern1 bs=512K count=1 + +aux prepare_devs 5 310 + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" +lvcreate -n $lv3 -l 4 -an $vg "$dev3" +lvcreate -n $lv4 -l 4 -an $vg "$dev4" +lvcreate -n $lv5 -l 8 -an $vg "$dev5" + +mkfs_mount_umount() +{ + lvt=$1 + + lvchange -ay $vg/$lvt + + mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lvt" + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + cp pattern1 "$mount_dir/pattern1" + dd if=/dev/zero of="$mount_dir/zeros2M" bs=1M count=2 conv=fdatasync + umount "$mount_dir" + + lvchange -an $vg/$lvt +} + +mount_umount() +{ + lvt=$1 + + lvchange -ay $vg/$lvt + + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + diff pattern1 "$mount_dir/pattern1" + dd if="$mount_dir/zeros2M" of=/dev/null bs=1M count=2 + umount "$mount_dir" + + lvchange -an $vg/$lvt +} + +# +# Test --cachemetadataformat +# + +# 1 shouldn't be used any longer +not lvconvert --cachemetadataformat 1 -y --type cache --cachevol $lv2 $vg/$lv1 + +# 3 doesn't exist +not lvconvert --cachemetadataformat 3 -y --type cache --cachevol $lv2 $vg/$lv1 + +# 2 is used by default +lvconvert -y --type cache --cachevol $lv2 $vg/$lv1 + +check lv_field $vg/$lv1 cachemetadataformat "2" + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear + +# 2 can be set explicitly +lvconvert --cachemetadataformat 2 -y --type cache --cachevol $lv2 $vg/$lv1 + +check lv_field $vg/$lv1 cachemetadataformat "2" + +lvconvert --splitcache $vg/$lv1 + +# "auto" means 2 +lvconvert --cachemetadataformat auto -y --type cache --cachevol $lv2 $vg/$lv1 + +check lv_field $vg/$lv1 cachemetadataformat "2" + +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +mount_umount $lv1 + + +# +# Test --poolmetadatasize +# + +lvconvert -y --type cache --cachevol $lv2 --poolmetadatasize 4m $vg/$lv1 + +check lv_field $vg/$lv1 lv_metadata_size "4.00m" + +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +mount_umount $lv1 + + +# +# Test --chunksize +# + +lvconvert -y --type cache --cachevol $lv2 --chunksize 32k $vg/$lv1 + +check lv_field $vg/$lv1 chunksize "32.00k" + +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +mount_umount $lv1 + + +# +# Test --cachemode +# + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 + +check lv_field $vg/$lv1 cachemode "writethrough" + +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +mount_umount $lv1 + +# FIXME: kernel errors for other cache modes + +#lvconvert -y --type cache --cachevol $lv2 --cachemode passthrough $vg/$lv1 + +#check lv_field $vg/$lv1 cachemode "passthrough" + +#mkfs_mount_umount $lv1 + +#lvconvert --splitcache $vg/$lv1 +#check lv_field $vg/$lv1 segtype linear +#check lv_field $vg/$lv2 segtype linear +#mount_umount $lv1 + + +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 + +check lv_field $vg/$lv1 cachemode "writeback" + +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +mount_umount $lv1 + + +# +# Test --cachepolicy +# + +lvconvert -y --type cache --cachevol $lv2 --cachepolicy smq $vg/$lv1 + +check lv_field $vg/$lv1 cachepolicy "smq" + +mkfs_mount_umount $lv1 + +lvchange --cachepolicy cleaner $vg/$lv1 +lvchange -ay $vg/$lv1 +check lv_field $vg/$lv1 cachepolicy "cleaner" +lvchange -an $vg/$lv1 + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +mount_umount $lv1 + + +# +# Test --cachesettings +# (only for mq policy, no settings for smq) +# + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough --cachepolicy mq --cachesettings 'migration_threshold = 233 sequential_threshold=13 random_threshold =1' $vg/$lv1 + +check lv_field $vg/$lv1 cachemode "writethrough" +check lv_field $vg/$lv1 cachepolicy "mq" + +lvs -o cachesettings $vg/$lv1 > settings +grep "migration_threshold=233" settings +grep "sequential_threshold=13" settings +grep "random_threshold=1" settings + +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +mount_umount $lv1 + + +# +# Test lvchange of --cachemode, --cachepolicy, --cachesettings +# + +lvconvert -y --type cache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 + +lvchange -y --cachemode writeback $vg/$lv1 + +check lv_field $vg/$lv1 cachemode "writeback" + +lvchange --cachemode writethrough $vg/$lv1 + +check lv_field $vg/$lv1 cachemode "writethrough" + +lvchange --cachemode passthrough $vg/$lv1 + +check lv_field $vg/$lv1 cachemode "passthrough" + +lvchange -an $vg/$lv1 + +lvchange --cachepolicy mq --cachesettings 'migration_threshold=100' $vg/$lv1 + +check lv_field $vg/$lv1 cachepolicy "mq" +check lv_field $vg/$lv1 cachesettings "migration_threshold=100" + +lvconvert --splitcache $vg/$lv1 + + +# +# Test --poolmetadata +# + +# causes a cache-pool type LV to be created +lvconvert -y --type cache --cachepool $lv3 --poolmetadata $lv4 $vg/$lv5 + +lvs -a -o+segtype $vg + +check lv_field $vg/$lv5 segtype cache + +# check lv_field doesn't work for hidden lvs +lvs -a -o segtype $vg/${lv3}_cpool > segtype +grep cache-pool segtype + +lvconvert --splitcache $vg/$lv5 +check lv_field $vg/$lv5 segtype linear +check lv_field $vg/$lv3 segtype cache-pool + + +vgremove -ff $vg diff --git a/test/shell/cache-single-split.sh b/test/shell/cache-single-split.sh new file mode 100644 index 0000000..025a086 --- /dev/null +++ b/test/shell/cache-single-split.sh @@ -0,0 +1,423 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test single lv cache options + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +case "$(uname -r)" in +6.[0123]*|5.19*) skip "Skippen test that kills this kernel" ;; +esac + +mkfs_mount_umount() +{ + lvt=$1 + + lvchange -ay $vg/$lvt + + mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lvt" + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + cp pattern1 "$mount_dir/pattern1" + dd if=/dev/zero of="$mount_dir/zeros2M" bs=1M count=32 conv=fdatasync + umount "$mount_dir" + + lvchange -an $vg/$lvt +} + +mount_umount() +{ + lvt=$1 + + lvchange -ay $vg/$lvt + + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + diff pattern1 "$mount_dir/pattern1" + dd if="$mount_dir/zeros2M" of=/dev/null bs=1M count=32 + umount "$mount_dir" + + lvchange -an $vg/$lvt +} + +aux have_cache 1 10 0 || skip +which mkfs.xfs || skip + +case $(cache_check -V) in +# support for v2 starts with version 0.7 +0.[0-6]*) skip 'At least version 0.7 of cache_check tool is needed.' ;; +esac + +mount_dir="mnt" +mkdir -p "$mount_dir" + +# generate random data +dd if=/dev/urandom of=pattern1 bs=512K count=1 + +aux prepare_devs 4 310 + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +# +# split when no devs are missing +# while inactive +# both cachemodes work the same +# + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 + +check lv_field $vg/$lv1 segtype "cache" +check lv_field $vg/$lv1 cachemode "writethrough" + +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay $vg/$lv2 +cache_check "$DM_DEV_DIR/$vg/$lv2" +lvchange -an $vg/$lv2 + +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 + +check lv_field $vg/$lv1 segtype "cache" +check lv_field $vg/$lv1 cachemode "writeback" + +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay $vg/$lv2 +cache_check "$DM_DEV_DIR/$vg/$lv2" +lvchange -an $vg/$lv2 + +mount_umount $lv1 + + +# +# split when no devs are missing +# while active +# both cachemodes work the same +# + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 + +check lv_field $vg/$lv1 segtype "cache" +check lv_field $vg/$lv1 cachemode "writethrough" + +mkfs_mount_umount $lv1 + +lvchange -ay $vg/$lv1 + +lvconvert --splitcache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay $vg/$lv2 +cache_check "$DM_DEV_DIR/$vg/$lv2" +lvchange -an $vg/$lv2 + +mount_umount $lv1 + +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 + +check lv_field $vg/$lv1 segtype "cache" +check lv_field $vg/$lv1 cachemode "writeback" + +lvchange -an $vg/$lv1 + +mkfs_mount_umount $lv1 + +lvchange -ay $vg/$lv1 + +lvconvert --splitcache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay $vg/$lv2 +cache_check "$DM_DEV_DIR/$vg/$lv2" +lvchange -an $vg/$lv2 + +# +# split while cachevol is missing +# writethrough +# + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 + +check lv_field $vg/$lv1 segtype "cache" +check lv_field $vg/$lv1 cachemode "writethrough" + +lvchange -an $vg/$lv1 + +mkfs_mount_umount $lv1 + +lvchange -ay $vg/$lv1 + +aux disable_dev "$dev2" + +lvconvert --splitcache $vg/$lv1 + +lvs -o segtype $vg/$lv1 | grep linear + +aux enable_dev "$dev2" + +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay --activationmode partial $vg/$lv2 +cache_check "$DM_DEV_DIR/$vg/$lv2" +lvchange -an $vg/$lv2 + +vgck --updatemetadata $vg +lvs $vg +vgchange -an $vg +vgextend --restoremissing $vg "$dev2" + +mount_umount $lv1 + +# +# split while cachevol is missing +# writeback +# + +lvremove $vg/$lv2 +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 + +check lv_field $vg/$lv1 segtype "cache" +check lv_field $vg/$lv1 cachemode "writeback" + +mkfs_mount_umount $lv1 + +aux disable_dev "$dev2" + +not lvconvert --splitcache $vg/$lv1 +lvconvert --splitcache --force --yes $vg/$lv1 + +lvs -o segtype $vg/$lv1 | grep linear + +aux enable_dev "$dev2" + +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay --activationmode partial $vg/$lv2 +cache_check "$DM_DEV_DIR/$vg/$lv2" +lvchange -an $vg/$lv2 + +vgck --updatemetadata $vg +lvs $vg +vgchange -an $vg +vgextend --restoremissing $vg "$dev2" + +# +# split while cachevol has 1 of 2 PVs +# writethrough +# + +lvremove $vg/$lv2 +lvcreate -n $lv2 -l 14 -an $vg "$dev2:0-10" "$dev3" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 + +check lv_field $vg/$lv1 segtype "cache" +check lv_field $vg/$lv1 cachemode "writethrough" + +mkfs_mount_umount $lv1 + +aux disable_dev "$dev3" + +lvconvert --splitcache $vg/$lv1 + +lvs -o segtype $vg/$lv1 | grep linear + +aux enable_dev "$dev3" + +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay --activationmode partial $vg/$lv2 +cache_check "$DM_DEV_DIR/$vg/$lv2" +lvchange -an $vg/$lv2 + +vgck --updatemetadata $vg +lvs $vg +vgchange -an $vg +vgextend --restoremissing $vg "$dev3" + +mount_umount $lv1 + +# +# split while cachevol has 1 of 2 PVs +# writeback +# + +lvremove $vg/$lv2 +lvcreate -n $lv2 -l 14 -an $vg "$dev2:0-10" "$dev3" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 + +check lv_field $vg/$lv1 segtype "cache" +check lv_field $vg/$lv1 cachemode "writeback" + +mkfs_mount_umount $lv1 + +aux disable_dev "$dev3" + +not lvconvert --splitcache $vg/$lv1 +lvconvert --splitcache --force --yes $vg/$lv1 + +lvs -o segtype $vg/$lv1 | grep linear + +aux enable_dev "$dev3" + +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay --activationmode partial $vg/$lv2 +cache_check "$DM_DEV_DIR/$vg/$lv2" +lvchange -an $vg/$lv2 + +vgck --updatemetadata $vg +lvs $vg +vgchange -an $vg +vgextend --restoremissing $vg "$dev3" + +# +# uncache when no devs are missing +# while inactive +# both cachemodes work the same +# + +lvremove $vg/$lv1 +lvremove $vg/$lv2 + +lvcreate -n $lv1 -L 300 -an $vg "$dev1:0-10" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 + +mkfs_mount_umount $lv1 + +lvconvert --uncache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear + +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 + +mkfs_mount_umount $lv1 + +lvconvert --uncache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear + +mount_umount $lv1 + +# +# uncache when no devs are missing +# while active +# both cachemodes work the same +# + +lvremove $vg/$lv1 + +lvcreate -n $lv1 -L 300 -an $vg "$dev1:0-10" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 + +mkfs_mount_umount $lv1 + +lvchange -ay $vg/$lv1 + +lvconvert --uncache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear + +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 + +lvchange -an $vg/$lv1 + +mkfs_mount_umount $lv1 + +lvchange -ay $vg/$lv1 + +lvconvert --uncache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear + +mount_umount $lv1 + +# +# uncache while cachevol is missing +# writethrough +# + +lvremove $vg/$lv1 + +lvcreate -n $lv1 -L 300 -an $vg "$dev1:0-10" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 + +mkfs_mount_umount $lv1 + +aux disable_dev "$dev2" + +lvconvert --uncache $vg/$lv1 + +lvs -o segtype $vg/$lv1 | grep linear + +aux enable_dev "$dev2" + +not lvs -o segtype $vg/$lv2 + +vgck --updatemetadata $vg +lvs $vg + +vgchange -an $vg + +mount_umount $lv1 + +# +# uncache while cachevol is missing +# writeback +# + +lvremove $vg/$lv1 + +lvcreate -n $lv1 -L 300 -an $vg "$dev1:0-10" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 + +mkfs_mount_umount $lv1 + +aux disable_dev "$dev2" + +not lvconvert --uncache $vg/$lv1 +lvconvert --uncache --force --yes $vg/$lv1 + +lvs -o segtype $vg/$lv1 | grep linear + +aux enable_dev "$dev2" + +not lvs -o segtype $vg/$lv2 + +vgck --updatemetadata $vg +lvs $vg + +vgremove -ff $vg diff --git a/test/shell/cache-single-thin.sh b/test/shell/cache-single-thin.sh new file mode 100644 index 0000000..6b478fb --- /dev/null +++ b/test/shell/cache-single-thin.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test single lv cache + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 10 0 || skip +aux have_thin 1 0 0 || skip + +aux prepare_devs 5 80 + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + +# lv1 starts as a standard linear LV +# lv1 is then sped up by attaching fast device lv2 using dm-cache +# lv1 is then used as the data device in a thin pool + +lvcreate -L10 -an -n $lv1 $vg "$dev1" +lvcreate -L10 -an -n $lv2 $vg "$dev2" + +lvconvert -y --type cache --cachevol $lv2 $vg/$lv1 +lvconvert -y --type thin-pool $vg/$lv1 + +lvcreate --type thin -V10 -n lvthin --thinpool $vg/$lv1 + +lvchange -an $vg/lvthin +lvchange -an $vg/$lv1 + +# detach the cache (lv2) from lv1 + +lvconvert --splitcache $vg/$lv1 + +vgremove -ff $vg + diff --git a/test/shell/cache-single-types.sh b/test/shell/cache-single-types.sh new file mode 100644 index 0000000..1e67e7e --- /dev/null +++ b/test/shell/cache-single-types.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test single lv cache with non-linear lvs + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 10 0 || skip +aux have_raid 1 3 5 || skip +which mkfs.xfs || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +# generate random data +dd if=/dev/urandom of=pattern1 bs=512K count=1 + +aux prepare_devs 4 310 + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" + +lvcreate --type raid1 -m 1 -n $lv1 -L 300 --nosync $vg "$dev1" "$dev2" + +lvcreate --type raid1 -m 1 -n $lv2 -l 4 $vg "$dev3" "$dev4" + +# test1: create fs on LV before cache is attached + +mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1" + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +cp pattern1 "$mount_dir/pattern1" + +umount "$mount_dir" +lvchange -an $vg/$lv1 + +lvconvert -y --type cache --cachevol $lv2 $vg/$lv1 + +check lv_field $vg/$lv1 segtype cache + +lvs -a $vg/${lv2}_cvol --noheadings -o segtype >out +grep raid1 out + +lvchange -ay $vg/$lv1 + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +diff pattern1 "$mount_dir/pattern1" + +cp pattern1 "$mount_dir/pattern1b" + +ls -l "$mount_dir" + +umount "$mount_dir" + +lvchange -an $vg/$lv1 + +lvconvert --splitcache $vg/$lv1 + +check lv_field $vg/$lv1 segtype raid1 +check lv_field $vg/$lv2 segtype raid1 + +lvchange -ay $vg/$lv1 +lvchange -ay $vg/$lv2 + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +ls -l "$mount_dir" + +diff pattern1 "$mount_dir/pattern1" +diff pattern1 "$mount_dir/pattern1b" + +umount "$mount_dir" +lvchange -an $vg/$lv1 +lvchange -an $vg/$lv2 + +vgremove -ff $vg diff --git a/test/shell/cache-single-usage.sh b/test/shell/cache-single-usage.sh new file mode 100644 index 0000000..2c47d05 --- /dev/null +++ b/test/shell/cache-single-usage.sh @@ -0,0 +1,146 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test single lv cache + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +lvm segtypes 2>/dev/null | grep writecache$ >/dev/null || { + skip 'Writecache is not built-in.' +} +aux have_cache 1 10 0 || skip +which mkfs.xfs || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +# generate random data +dd if=/dev/urandom of=pattern1 bs=512K count=1 + +aux prepare_devs 2 310 + +vgcreate $SHARED $vg "$dev1" + +vgextend $vg "$dev2" + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" + +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +# test1: create fs on LV before cache is attached + +lvchange -ay $vg/$lv1 + +mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1" + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +cp pattern1 "$mount_dir/pattern1" + +umount "$mount_dir" +lvchange -an $vg/$lv1 + +lvconvert -y --type cache --cachevol $lv2 $vg/$lv1 + +check lv_field $vg/$lv1 segtype cache + +lvs -a $vg/${lv2}_cvol --noheadings -o segtype >out +grep linear out + +lvchange -ay $vg/$lv1 + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +diff pattern1 "$mount_dir/pattern1" + +cp pattern1 "$mount_dir/pattern1b" + +ls -l "$mount_dir" + +umount "$mount_dir" + +lvchange -an $vg/$lv1 + +lvconvert --splitcache $vg/$lv1 + +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear + +lvchange -ay $vg/$lv1 +lvchange -ay $vg/$lv2 + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +ls -l "$mount_dir" + +diff pattern1 "$mount_dir/pattern1" +diff pattern1 "$mount_dir/pattern1b" + +umount "$mount_dir" +lvchange -an $vg/$lv1 +lvchange -an $vg/$lv2 + +# test2: create fs on LV after cache is attached + +lvconvert -y --type cache --cachevol $lv2 $vg/$lv1 + +check lv_field $vg/$lv1 segtype cache + +lvs -a $vg/${lv2}_cvol --noheadings -o segtype >out +grep linear out + +lvchange -ay $vg/$lv1 + +mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1" + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +cp pattern1 "$mount_dir/pattern1" +ls -l "$mount_dir" + +umount "$mount_dir" +lvchange -an $vg/$lv1 + +lvconvert --splitcache $vg/$lv1 + +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear + +lvchange -ay $vg/$lv1 +lvchange -ay $vg/$lv2 + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +ls -l "$mount_dir" + +diff pattern1 "$mount_dir/pattern1" + +umount "$mount_dir" +lvchange -an $vg/$lv1 +lvchange -an $vg/$lv2 + +# misc tests + +lvremove $vg + +lvcreate -n $lv1 -l 2 -an $vg "$dev1" +lvcreate -n $lv2 -l 2 -an $vg "$dev1" +lvcreate -n $lv3 -l 2 -an $vg "$dev2" + +lvconvert -y --type writecache --cachevol $lv3 $vg/$lv1 +not lvconvert -y --type writecache --cachevol ${lv3}_cvol $vg/$lv2 +not lvconvert -y --type cache --cachevol ${lv3}_cvol $vg/$lv2 +not lvconvert -y --type cache --cachepool ${lv3}_cvol $vg/$lv2 + +vgremove -ff $vg diff --git a/test/shell/cachevol-cachedevice.sh b/test/shell/cachevol-cachedevice.sh new file mode 100644 index 0000000..2695c98 --- /dev/null +++ b/test/shell/cachevol-cachedevice.sh @@ -0,0 +1,235 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 10 0 || skip +aux have_writecache 1 0 0 || skip + +aux prepare_devs 4 64 + +vgcreate $SHARED $vg "$dev1" "$dev2" + +## cache + +# use existing cachevol +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvcreate --type cache -n $lv2 -L40M --cachevol $lv1 -y $vg "$dev2" +check lv_field $vg/$lv2 segtype cache +check lv_field $vg/${lv1}_cvol segtype linear -a +lvremove -y $vg/$lv2 + +# use entire cachedevice for cachevol +lvcreate --type cache -n $lv2 -L40M --cachedevice "$dev1" -y $vg "$dev2" +check lv_field $vg/$lv2 segtype cache +check lv_field $vg/${lv2}_cache_cvol segtype linear -a +lvremove -y $vg/$lv2 + +# use part of cachedevice for cachevol +lvcreate --type cache -n $lv2 -L20M --cachedevice "$dev1" --cachesize 16M -y $vg "$dev2" +check lv_field $vg/$lv2 segtype cache +check lv_field $vg/${lv2}_cache_cvol segtype linear -a +lvcreate --type cache -n $lv3 -L20M --cachedevice "$dev1" --cachesize 16M -y $vg "$dev2" +check lv_field $vg/$lv3 segtype cache +check lv_field $vg/${lv3}_cache_cvol segtype linear -a +lvremove -y $vg/$lv2 +lvremove -y $vg/$lv3 + +## writecache + +# use existing cachevol +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvcreate --type writecache -n $lv2 -L40M --cachevol $lv1 -y $vg "$dev2" +check lv_field $vg/$lv2 segtype writecache +check lv_field $vg/${lv1}_cvol segtype linear -a +lvremove -y $vg/$lv2 + +# use entire cachedevice for cachevol +lvcreate --type writecache -n $lv2 -L40M --cachedevice "$dev1" -y $vg "$dev2" +check lv_field $vg/$lv2 segtype writecache +check lv_field $vg/${lv2}_cache_cvol segtype linear -a +lvremove -y $vg/$lv2 + +# use part of cachedevice for cachevol +lvcreate --type writecache -n $lv2 -L20M --cachedevice "$dev1" --cachesize 16M -y $vg "$dev2" +check lv_field $vg/$lv2 segtype writecache +check lv_field $vg/${lv2}_cache_cvol segtype linear -a +lvcreate --type writecache -n $lv3 -L20M --cachedevice "$dev1" --cachesize 16M -y $vg "$dev2" +check lv_field $vg/$lv3 segtype writecache +check lv_field $vg/${lv3}_cache_cvol segtype linear -a +lvremove -y $vg/$lv2 +lvremove -y $vg/$lv3 + +## multiple cachedevs + +vgextend $vg "$dev3" "$dev4" + +lvcreate --type writecache -n $lv2 -L100M --cachedevice "$dev1" --cachedevice "$dev3" -y $vg "$dev2" "$dev4" +check lv_field $vg/${lv2}_cache_cvol lv_size "120.00m" +lvremove -y $vg/$lv2 + +lvcreate --type writecache -n $lv2 -L100M --cachedevice "$dev1" --cachedevice "$dev3" --cachesize 80M -y $vg "$dev2" "$dev4" +check lv_field $vg/${lv2}_cache_cvol lv_size "80.00m" +lvremove -y $vg/$lv2 + +pvchange --addtag slow "$dev2" +pvchange --addtag slow "$dev4" +pvchange --addtag fast "$dev1" +pvchange --addtag fast "$dev3" + +lvcreate --type writecache -n $lv2 -L100M --cachedevice @fast --cachesize 80M -y $vg @slow +check lv_field $vg/${lv2}_cache_cvol lv_size "80.00m" +lvremove -y $vg/$lv2 + +lvcreate --type cache -n $lv2 -L100M --cachedevice @fast --cachesize 80M -y $vg @slow +check lv_field $vg/${lv2}_cache_cvol lv_size "80.00m" +lvremove -y $vg/$lv2 + +## error cases + +# cachevol doesn't exist +not lvcreate --type cache -n $lv2 -l8 --cachevol asdf -y $vg "$dev2" +not lvs $vg/$lv1 +not lvs $vg/$lv2 + +# cachedevice doesn't exist +not lvcreate --type cache -n $lv2 -l8 --cachedevice asdf -y $vg "$dev2" +not lvs $vg/$lv1 +not lvs $vg/$lv2 + +# cachevol doesn't exist +not lvcreate --type writecache -n $lv2 -l8 --cachevol asdf -y $vg "$dev2" +not lvs $vg/$lv1 +not lvs $vg/$lv2 + +# cachedevice doesn't exist +not lvcreate --type writecache -n $lv2 -l8 --cachedevice asdf -y $vg "$dev2" +not lvs $vg/$lv1 +not lvs $vg/$lv2 + +# when cachedevice is already being used, cachesize is required to use a part of it +lvcreate -n asdf -l1 $vg "$dev1" +not lvcreate --type writecache -n $lv2 -l8 --cachedevice "$dev1" -y $vg "$dev2" +not lvcreate --type writecache -n $lv2 -l8 --cachedevice "$dev1" --cachedevice "$dev3" -y $vg "$dev2" +not lvs $vg/$lv1 +not lvs $vg/$lv2 +lvcreate --type writecache -n $lv2 -l8 --cachedevice "$dev1" --cachesize 8M -y $vg "$dev2" +lvs $vg/$lv2 +check lv_field $vg/${lv2}_cache_cvol lv_size "8.00m" +lvremove -y $vg/$lv2 + +vgremove -ff $vg + +# lvconvert single step cachevol creation and attachment +# . cache and writecache +# . one or two cachedevices +# . with or without --cachesize +# . using tags for devices + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" + +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvconvert -y --type cache --cachedevice "$dev2" $vg/$lv1 +check lv_field $vg/$lv1 segtype cache +check lv_field $vg/${lv1}_cache_cvol segtype linear -a +check lv_field $vg/${lv1}_cache_cvol lv_size "60.00m" +lvs -o chunksize $vg/$lv1 |tee out +grep 64.00k out +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvconvert -y --type cache --cachedevice "$dev2" --chunksize 128k $vg/$lv1 +check lv_field $vg/$lv1 segtype cache +check lv_field $vg/${lv1}_cache_cvol segtype linear -a +check lv_field $vg/${lv1}_cache_cvol lv_size "60.00m" +lvs -o chunksize $vg/$lv1 |tee out +grep 128.00k out +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvconvert -y --type cache --cachedevice "$dev2" --cachedevice "$dev3" $vg/$lv1 +check lv_field $vg/$lv1 segtype cache +check lv_field $vg/${lv1}_cache_cvol lv_size "120.00m" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvconvert -y --type cache --cachedevice "$dev2" --cachedevice "$dev3" --cachesize 8M $vg/$lv1 +check lv_field $vg/$lv1 segtype cache +check lv_field $vg/${lv1}_cache_cvol lv_size "8.00m" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvconvert -y --type writecache --cachedevice "$dev2" $vg/$lv1 +check lv_field $vg/$lv1 segtype writecache +check lv_field $vg/${lv1}_cache_cvol lv_size "60.00m" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvconvert -y --type writecache --cachedevice "$dev2" --cachedevice "$dev3" $vg/$lv1 +check lv_field $vg/$lv1 segtype writecache +check lv_field $vg/${lv1}_cache_cvol lv_size "120.00m" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +lvcreate -n $lv1 -l8 -an $vg "$dev1" +lvconvert -y --type writecache --cachedevice "$dev2" --cachedevice "$dev3" --cachesize 8M $vg/$lv1 +check lv_field $vg/$lv1 segtype writecache +check lv_field $vg/${lv1}_cache_cvol lv_size "8.00m" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +pvchange --addtag slow "$dev1" +pvchange --addtag fast "$dev2" +pvchange --addtag fast "$dev3" + +lvcreate -n $lv1 -l8 -an $vg @slow +lvconvert -y --type cache --cachedevice @fast --cachesize 8M $vg/$lv1 +check lv_field $vg/$lv1 segtype cache +check lv_field $vg/${lv1}_cache_cvol lv_size "8.00m" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +lvcreate -n $lv1 -l8 -an $vg @slow +lvconvert -y --type writecache --cachedevice @fast --cachesize 8M $vg/$lv1 +check lv_field $vg/$lv1 segtype writecache +check lv_field $vg/${lv1}_cache_cvol lv_size "8.00m" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# if the cache name is used generate a new name +lvcreate -n $lv1 -l8 -an $vg @slow +lvcreate -n ${lv1}_cache -l1 -an $vg @slow +lvconvert -y --type writecache --cachedevice @fast --cachesize 8M $vg/$lv1 +check lv_field $vg/$lv1 segtype writecache +check lv_field $vg/${lv1}_cache0_cvol lv_size "8.00m" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +vgremove -ff $vg + diff --git a/test/shell/caching-snapshot.sh b/test/shell/caching-snapshot.sh new file mode 100644 index 0000000..d73f4ad --- /dev/null +++ b/test/shell/caching-snapshot.sh @@ -0,0 +1,162 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test snapshot on cache|writecache + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +lvm segtypes 2>/dev/null | grep writecache$ >/dev/null || { + skip 'Writecache is not built-in.' +} +aux have_cache 1 10 0 || skip +which mkfs.ext4 || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +mount_dir_snap="mnt_snap" +mkdir -p "$mount_dir_snap" + +# generate random data +dd if=/dev/urandom of=pattern1 bs=512K count=1 + +aux prepare_devs 2 310 + +vgcreate $SHARED $vg "$dev1" "$dev2" + +# creating a snapshot on top of a cache|writecache + +test_snap_create() { + # cache | writecache + local convert_type=$1 + + # --cachepool | --cachevol + local convert_option=$2 + + lvcreate -n $lv1 -L 300 -an $vg "$dev1" + lvcreate -n fast -l 4 -an $vg "$dev2" + lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 + lvchange -ay $vg/$lv1 + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + cp pattern1 "$mount_dir/pattern1a" + lvcreate -s -L 32 -n snap $vg/$lv1 + cp pattern1 "$mount_dir/pattern1b" + mount "$DM_DEV_DIR/$vg/snap" "$mount_dir_snap" + not ls "$mount_dir_snap/pattern1b" + rm "$mount_dir/pattern1a" + diff pattern1 "$mount_dir_snap/pattern1a" + umount "$mount_dir_snap" + lvconvert --splitcache $vg/$lv1 + umount "$mount_dir" + lvchange -an $vg/$lv1 + lvchange -an $vg/fast + lvremove $vg/snap + lvremove $vg/$lv1 + lvremove $vg/fast +} + +test_snap_create cache --cachepool +test_snap_create cache --cachevol +test_snap_create writecache --cachevol + +# removing cache|writecache while snapshot exists + +test_snap_remove() { + # cache | writecache + local convert_type=$1 + + # --cachepool | --cachevol + local convert_option=$2 + + lvcreate -n $lv1 -L 300 -an $vg "$dev1" + lvcreate -n fast -l 4 -an $vg "$dev2" + lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 + lvchange -ay $vg/$lv1 + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + cp pattern1 "$mount_dir/pattern1a" + lvcreate -s -L 32 -n snap $vg/$lv1 + cp pattern1 "$mount_dir/pattern1b" + lvconvert --splitcache $vg/$lv1 + mount "$DM_DEV_DIR/$vg/snap" "$mount_dir_snap" + not ls "$mount_dir_snap/pattern1b" + rm "$mount_dir/pattern1a" + diff pattern1 "$mount_dir_snap/pattern1a" + umount "$mount_dir_snap" + umount "$mount_dir" + lvchange -an $vg/$lv1 + lvchange -an $vg/fast + lvremove $vg/snap + lvremove $vg/$lv1 + lvremove $vg/fast +} + +test_snap_remove cache --cachepool +test_snap_remove cache --cachevol +test_snap_remove writecache --cachevol + +# adding cache|writecache to an LV that has a snapshot + +test_caching_with_snap() { + # cache | writecache + local convert_type=$1 + + # --cachepool | --cachevol + local convert_option=$2 + + lvcreate -n $lv1 -L 300 -an $vg "$dev1" + lvcreate -n fast -l 4 -an $vg "$dev2" + lvchange -ay $vg/$lv1 + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + cp pattern1 "$mount_dir/pattern1a" + lvcreate -s -L 32 -n snap $vg/$lv1 + lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 + cp pattern1 "$mount_dir/pattern1b" + mount "$DM_DEV_DIR/$vg/snap" "$mount_dir_snap" + not ls "$mount_dir_snap/pattern1b" + mv "$mount_dir/pattern1a" "$mount_dir/pattern1c" + diff pattern1 "$mount_dir_snap/pattern1a" + lvconvert --splitcache $vg/$lv1 + diff pattern1 "$mount_dir/pattern1c" + diff pattern1 "$mount_dir_snap/pattern1a" + umount "$mount_dir_snap" + umount "$mount_dir" + lvchange -an $vg/$lv1 + lvchange -an $vg/fast + lvremove $vg/snap + lvremove $vg/$lv1 + lvremove $vg/fast +} + +test_caching_with_snap cache --cachepool +test_caching_with_snap cache --cachevol +test_caching_with_snap writecache --cachevol + +# adding cache|writecache to a snapshot is not allowed + +lvcreate -n $lv1 -L 300 $vg "$dev1" +lvcreate -n fast -l 4 $vg "$dev2" +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +lvcreate -s -L 32 -n snap $vg/$lv1 +not lvconvert -y --type writecache --cachevol fast $vg/snap +not lvconvert -y --type cache --cachevol fast $vg/snap +not lvconvert -y --type cache --cachepool fast $vg/snap +vgchange -an $vg +lvremove $vg/snap +lvremove $vg/$lv1 +lvremove $vg/fast + +vgremove -ff $vg diff --git a/test/shell/clvmd-restart.sh b/test/shell/clvmd-restart.sh deleted file mode 100644 index 2b341e5..0000000 --- a/test/shell/clvmd-restart.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh -# Copyright (C) 2011 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 before test's clvmd is started, so it's passed in environ -export LVM_CLVMD_BINARY=clvmd -export LVM_BINARY=lvm - -. lib/test - -# only clvmd based test, skip otherwise -test -e LOCAL_CLVMD || skip -read LOCAL_CLVMD < LOCAL_CLVMD - -aux prepare_pvs 1 - -vgcreate --clustered y $vg $(cat DEVICES) - -lvcreate -an --zero n -n $lv1 -l1 $vg -lvcreate -an --zero n -n $lv2 -l1 $vg -lvcreate -l1 $vg - -lvchange -aey $vg/$lv1 -lvchange -aey $vg/$lv2 - -"$LVM_CLVMD_BINARY" -S -sleep .2 -# restarted clvmd has the same PID (no fork, only execvp) -NEW_LOCAL_CLVMD=$(pgrep clvmd) -test "$LOCAL_CLVMD" -eq "$NEW_LOCAL_CLVMD" - -# try restart once more - -"$LVM_CLVMD_BINARY" -S -sleep .2 -# restarted clvmd has the same PID (no fork, only execvp) -NEW_LOCAL_CLVMD=$(pgrep clvmd) -test "$LOCAL_CLVMD" -eq "$NEW_LOCAL_CLVMD" - -# FIXME: Hmm - how could we test exclusivity is preserved in singlenode ? -lvchange -an $vg/$lv1 -lvchange -ay $vg/$lv1 - -"$LVM_CLVMD_BINARY" -R - -vgremove -ff $vg diff --git a/test/shell/component-cache.sh b/test/shell/component-cache.sh new file mode 100644 index 0000000..7234504 --- /dev/null +++ b/test/shell/component-cache.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise activation of cache component devices + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +aux prepare_vg 5 80 + +lvcreate --type cache-pool -L 2 -n cpool $vg +lvcreate -H -L 4 -n corigin --cachepool $vg/cpool +lvchange -an $vg + +for j in 1 2 +do + +# Activate supported components +for i in cpool_cpool_cmeta cpool_cpool_cdata corigin_corig +do + test ! -e "$DM_DEV_DIR/$vg/$i" + lvchange -ay -y $vg/$i + # check usable link is there + test -e "$DM_DEV_DIR/$vg/$i" + + # cannot take snapshot of any active component LV + test "$j" -eq 2 || not lvcreate -s -L1 $vg/$i +done + +# After 1st. phase deactivation works +# Volumes are left active for vgremove on 2nd.. pass +test "$j" -eq 2 || lvchange -an $vg + +done + +# Cannot active cached LV while any component LV is active +not lvchange -ay $vg/corigin |& tee err +grep "prohibited" err + +lvs -a $vg + +# Can split for writethrough|passthrough +# deactivates all components as well... +lvconvert --splitcache $vg/corigin +lvs -a $vg + +# Cannot cache LV while components are active +lvcreate -L 4 -n $lv2 $vg +lvchange -ay -y $vg/cpool_cmeta + +not lvconvert -y --cachepool $vg/cpool -H $lv2 + +lvremove -f $vg +lvs -a $vg + +if aux have_thin 1 0 0 ; then + +lvcreate --type cache-pool -L 2 -n cpool $vg +lvcreate -H -L 4 -n tpool --cachepool $vg/cpool +lvchange -an $vg +lvs -a $vg +# Cannot convert to thin-pool with component LV active +lvchange -ay -y $vg/cpool_cpool_cmeta + +# Conversion does not need to activate data device, so it can proceed ?? +lvconvert -y --thinpool $vg/tpool + +# Thin-pool cannot be activated +not lvchange -ay $vg/tpool |& tee err +grep "prohibited" err + +lvs -a $vg + +fi + +lvs -a $vg + +# And final removal works +vgremove -f $vg diff --git a/test/shell/component-mirror.sh b/test/shell/component-mirror.sh new file mode 100644 index 0000000..b565c98 --- /dev/null +++ b/test/shell/component-mirror.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise activation of mirror component devices + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +aux prepare_vg 5 80 + +lvcreate -aey --type mirror -L 2 -m 1 -n $lv1 $vg +lvchange -an $vg + +lvs -a + +lvchange -an $vg + +for k in 1 2 +do + +# Activate supported components +for i in ${lv1}_mimage_0 ${lv1}_mimage_1 ${lv1}_mlog +do + test ! -e "$DM_DEV_DIR/$vg/$i" + lvchange -ay -y $vg/$i + # check usable link is there + test -e "$DM_DEV_DIR/$vg/$i" +done + +# Deactivation works in 1st. pass +test $k -eq 2 || lvchange -an $vg + +done + +# Cannot be resized +not lvextend -L+20 $vg/$lv1 |& tee err +grep "Cannot resize" err + +not lvresize -L-20 $vg/$lv1 |& tee err +grep "Cannot resize" err + +# Cannot be converted +lvcreate -aey -L10 -n $lv2 $vg +not lvconvert -y -s $vg/$lv1 $lv2 |& tee err +grep "Cannot use" err + +# Cannot be splitted +not lvconvert --splitmirrors 1 -n split $vg/$lv1 |& tee err +grep "Cannot convert" err + +# Cannot add new leg +not lvconvert -m+1 $vg/$lv1 |& tee err +grep "Cannot convert" err + +lvs -a + +vgremove -f $vg diff --git a/test/shell/component-raid.sh b/test/shell/component-raid.sh new file mode 100644 index 0000000..bff56d4 --- /dev/null +++ b/test/shell/component-raid.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise activation of raid component devices + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 0 || skip + +aux prepare_vg 5 80 + +lvcreate --type raid1 -L 2 -m 1 -n $lv1 $vg +lvchange -an $vg + +lvs -a $vg + +for k in 1 2 +do + +# Activate supported components +for j in 0 1 +do +for i in ${lv1}_rimage_$j ${lv1}_rmeta_$j +do + test ! -e "$DM_DEV_DIR/$vg/$i" + lvchange -ay -y $vg/$i + # check usable link is there + test -e "$DM_DEV_DIR/$vg/$i" +done +done + +# Deactivation works in 1st. pass +test $k -eq 2 || lvchange -an $vg + +done + +# And final removal works +vgremove -f $vg diff --git a/test/shell/component-thin.sh b/test/shell/component-thin.sh new file mode 100644 index 0000000..ddadd0f --- /dev/null +++ b/test/shell/component-thin.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise activation of thin component devices + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_thin 1 0 0 || skip + +aux prepare_vg 5 80 + +lvcreate -T -L2 -V20 $vg/pool -n $lv1 + +lvs -a + +lvchange -an $vg + +for i in pool_tdata pool_tmeta +do + lvchange -ay -y $vg/$i + # check usable is there + test -e "$DM_DEV_DIR/$vg/$i" +done + +lvs -a + +# When component LVs are active, thin-pool cannot be actived +not lvcreate -V20 $vg/pool + +# Rremoval of thin volumes should not need to activate thin-pool. +vgremove -f $vg diff --git a/test/shell/covercmd.sh b/test/shell/covercmd.sh index b77d378..16b2e6c 100644 --- a/test/shell/covercmd.sh +++ b/test/shell/covercmd.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2014 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 @@ -7,96 +8,74 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # -# tests basic functionality of read-ahead and ra regressions +# tests functionality we don't have in other special test files yet +# to improve code coverage # -. lib/test -aux prepare_devs 5 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest -TEST_UUID="aaaaaa-aaaa-aaaa-aaaa-aaaa-aaaa-aaaaaa" +aux prepare_pvs 5 +get_devs -pvcreate "$dev1" pvcreate --metadatacopies 0 "$dev2" pvcreate --metadatacopies 0 "$dev3" -pvcreate "$dev4" -pvcreate --norestorefile -u $TEST_UUID --metadatacopies 0 "$dev5" -vgcreate -c n $vg $(cat DEVICES) -lvcreate -l 5 -i5 -I256 -n $lv $vg -if aux have_readline; then -# test *scan and *display tools -cat <backnew + +vgcfgrestore -f backnew $vg |& tee err + +# Check the time was spotted +grep Invalid err + +vgcfgbackup -f back $vg |& tee err + +# Check the time is not a problem anymore +not grep Invalid err + +vgremove -ff $vg diff --git a/test/shell/dev-aliases.sh b/test/shell/dev-aliases.sh new file mode 100644 index 0000000..c3e4c7c --- /dev/null +++ b/test/shell/dev-aliases.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 10 0 || skip + +aux prepare_vg 3 + +# +# This lvconvert command will deactivate LV1, then internally create a new +# lv, lvol0, as a poolmetadataspare, then activate lvol0 to zero it. +# lvol0 will get the same major:minor that LV1 had. When the code gets +# the struct dev for lvol0, the new path to lvol0 is added to the +# dev-cache with it's major:minor. That major:minor already exists in +# dev-cache and has the stale LV1 as an alias. So the path to lvol0 is +# added as an alias to the existing struct dev (with the correct +# major:minor), but that struct dev has the stale LV1 path on its aliases +# list. The code will now validate all the aliases before returning the +# dev for lvol0, and will find that the LV1 path is stale and remove it +# from the aliases. That will prevent the stale path from being used for +# the dev in place of the new path. +# +# The preferred_name is set to /dev/mapper so that if the stale path still +# exists, that stale path would be used as the name for the dev, and the +# wiping code would fail to open that stale name. +# + +lvcreate -n $lv1 -L32M $vg "$dev1" +lvcreate -n $lv2 -L16M $vg "$dev2" +lvconvert -y --type cache-pool --poolmetadata $lv2 --cachemode writeback $vg/$lv1 --config='devices { preferred_names=["/dev/mapper/"] }' +lvremove -y $vg/$lv1 + +lvcreate -n $lv1 -L32M $vg "$dev1" +lvcreate -n $lv2 -L16M $vg "$dev2" +lvconvert -y --type cache-pool --poolmetadata $lv2 $vg/$lv1 +lvremove -y $vg/$lv1 + +# TODO: add more validation of dev aliases being specified as command +# args in combination with various preferred_names settings. + +vgremove -ff $vg diff --git a/test/shell/devicesfile-basic.sh b/test/shell/devicesfile-basic.sh new file mode 100644 index 0000000..c96bab7 --- /dev/null +++ b/test/shell/devicesfile-basic.sh @@ -0,0 +1,687 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='devices file' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 7 + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* + rm -f "$PVS_LOOKUP_DIR"/* +} + +wipe_all() { + aux wipefs_a "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" +} + +# The tests run with system dir of "/etc" but lvm when running +# normally has cmd->system_dir set to "/etc/lvm". +DFDIR="$LVM_SYSTEM_DIR/devices" +mkdir -p "$DFDIR" || true +DF="$DFDIR/system.devices" + +# +# Test with use_devicesfile=0 (no devices file is being applied by default) +# + +aux lvmconf 'devices/use_devicesfile = 0' + +wipe_all +rm -f "$DF" +pvcreate "$dev1" +not ls "$DF" + +wipe_all +rm -f "$DF" +vgcreate $vg1 "$dev1" +not ls "$DF" + +wipe_all +rm -f "$DF" + +# create one VG in a non-system devices file +vgcreate --devicesfile test.devices $vg1 "$dev1" +vgextend --devicesfile test.devices $vg1 "$dev2" +cat "$DFDIR/test.devices" +grep "$dev1" "$DFDIR/test.devices" +grep "$dev2" "$DFDIR/test.devices" +not ls "$DFDIR/system.devices" + +# create two VGs outside the special devices file +vgcreate $vg2 "$dev3" "$dev4" +vgcreate $vg3 "$dev5" "$dev6" +not grep "$dev3" "$DFDIR/test.devices" +not grep "$dev5" "$DFDIR/test.devices" +not ls "$DFDIR/system.devices" + +PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID3=`pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID4=`pvs "$dev4" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID5=`pvs "$dev5" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID6=`pvs "$dev6" --noheading -o uuid | tr -d - | awk '{print $1}'` + +lvcreate -l4 -an -i2 -n $lv1 $vg1 +lvcreate -l4 -an -i2 -n $lv2 $vg2 +lvcreate -l4 -an -i2 -n $lv3 $vg3 + +cat "$DFDIR/test.devices" +grep "$PVID1" "$DFDIR/test.devices" +grep "$PVID2" "$DFDIR/test.devices" +not grep "$PVID3" "$DFDIR/test.devices" +not grep "$PVID4" "$DFDIR/test.devices" +not grep "$PVID5" "$DFDIR/test.devices" +not grep "$PVID6" "$DFDIR/test.devices" +not ls "$DFDIR/system.devices" + +# verify devices file is working +vgs --devicesfile test.devices $vg1 +not vgs --devicesfile test.devices $vg2 + +# misspelled override name fails +not vgs --devicesfile doesnotexist $vg1 +not vgs --devicesfile doesnotexist $vg2 +not vgs --devicesfile doesnotexist + +# devicesfile and devices cannot be used together +not vgs --devicesfile test.devices --devices "$dev1","$dev1" $vg1 + +# verify correct vgs are seen / not seen when devices are specified +vgs --devices "$dev1","$dev2" $vg1 +vgs --devices "$dev3","$dev4" $vg2 +vgs --devices "$dev5","$dev6" $vg3 +not vgs --devices "$dev1","$dev2" $vg2 +not vgs --devices "$dev1","$dev2" $vg3 +not vgs --devices "$dev1","$dev2" $vg2 +not vgs --devices "$dev5","$dev6" $vg2 +not vgs --devices "$dev1","$dev2" $vg3 +not vgs --devices "$dev3","$dev4" $vg3 + +vgs --devices "$dev1","$dev2" |tee out +grep $vg1 out +not grep $vg2 out +not grep $vg3 out +vgs --devices "$dev3","$dev4" |tee out +not grep $vg1 out +grep $vg2 out +not grep $vg3 out + +# verify correct pvs are seen / not seen when devices are specified +pvs --devices "$dev1","$dev2" "$dev1" "$dev2" +pvs --devices "$dev3","$dev4" "$dev3" "$dev4" +pvs --devices "$dev5","$dev6" "$dev5" "$dev6" +not pvs --devices "$dev1","$dev2" "$dev3" "$dev4" +not pvs --devices "$dev1","$dev2" "$dev5" "$dev6" +not pvs --devices "$dev3","$dev4" "$dev1" "$dev2" "$dev5" "$dev6" + +pvs --devices "$dev1","$dev2" |tee out +grep "$dev1" out +grep "$dev2" out +not grep "$dev3" out +not grep "$dev4" out +not grep "$dev5" out +not grep "$dev6" out +pvs --devices "$dev3","$dev4" |tee out +not grep "$dev1" out +not grep "$dev2" out +grep "$dev3" out +grep "$dev4" out +not grep "$dev5" out +not grep "$dev6" out + +# verify correct lvs are activated / not activated when devices are specified +vgchange --devices "$dev1","$dev2" -ay +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg2/$lv2 lv_active "" +check lv_field $vg3/$lv3 lv_active "" +vgchange --devices "$dev1","$dev2" -an +check lv_field $vg1/$lv1 lv_active "" + +vgchange --devices "$dev3","$dev4" -ay +check lv_field $vg1/$lv1 lv_active "" +check lv_field $vg2/$lv2 lv_active "active" +check lv_field $vg3/$lv3 lv_active "" +vgchange --devices "$dev3","$dev4" -an +check lv_field $vg2/$lv2 lv_active "" + +# verify devices covering multiple vgs +vgs --devices "$dev1","$dev2","$dev3","$dev4" $vg1 $vg2 |tee out +grep $vg1 out +grep $vg2 out +not grep $vg3 out +vgs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" $vg1 $vg2 $vg3 |tee out +grep $vg1 out +grep $vg2 out +grep $vg3 out + +# verify vgs seen when incomplete devices are specified +vgs --devices "$dev1" $vg1 +vgs --devices "$dev3" $vg2 +vgs --devices "$dev5" $vg3 + +# incomplete vg because of --devices is the same as vg incomplete because +# of missing device +not lvcreate --devices "$dev1" -l1 $vg1 +not lvchange --devices "$dev1" -ay $vg1/$lv1 +not lvextend --devices "$dev1" -l+1 $vg1/$lv1 +not vgremove --devices "$dev1" $vg1 +not lvcreate --devices "$dev3" -l1 $vg2 +not lvchange --devices "$dev3" -ay $vg2/$lv2 +not lvextend --devices "$dev3" -l+1 $vg2/$lv2 +not vgremove --devices "$dev3" $vg2 + +# verify various commands with --devices for vg in a devicesfile +not lvcreate --devices "$dev1","$dev2" -l1 -n $lv2 -an $vg1 "$dev7" +lvcreate --devices "$dev1","$dev2" -l1 -n $lv2 -an $vg1 +lvs --devices "$dev1","$dev2" $vg1/$lv2 +lvextend --devices "$dev1","$dev2" -l2 $vg1/$lv2 +lvchange --devices "$dev1","$dev2" -ay $vg1/$lv2 +lvchange --devices "$dev1","$dev2" -an $vg1/$lv2 +lvremove --devices "$dev1","$dev2" $vg1/$lv2 +vgchange --devices "$dev1","$dev2" -ay $vg1 +vgchange --devices "$dev1","$dev2" -an $vg1 +not vgextend --devices "$dev1","$dev2" $vg1 "$dev7" +vgextend --devices "$dev1","$dev2","$dev7" $vg1 "$dev7" +vgreduce --devices "$dev1","$dev2","$dev7" $vg1 "$dev7" +vgexport --devices "$dev1","$dev2" $vg1 +vgimport --devices "$dev1","$dev2" $vg1 +not pvremove --devices "$dev1","$dev2" "$dev7" +not pvcreate --devices "$dev1","$dev2" "$dev7" +not vgcreate --devices "$dev1","$dev2" $vg7 "$dev7" +pvremove --devices "$dev7" "$dev7" +pvcreate --devices "$dev7" "$dev7" +vgcreate --devices "$dev7" $vg7 "$dev7" +vgremove --devices "$dev7" $vg7 +pvremove --devices "$dev7" "$dev7" + +# verify various commands with --devices for vg not in a devicesfile +not lvcreate --devices "$dev3","$dev4" -l1 -n $lv4 -an $vg2 "$dev7" +lvcreate --devices "$dev3","$dev4" -l1 -n $lv4 -an $vg2 +lvs --devices "$dev3","$dev4" $vg2/$lv4 +lvextend --devices "$dev3","$dev4" -l2 $vg2/$lv4 +lvchange --devices "$dev3","$dev4" -ay $vg2/$lv4 +lvchange --devices "$dev3","$dev4" -an $vg2/$lv4 +lvremove --devices "$dev3","$dev4" $vg2/$lv4 +vgchange --devices "$dev3","$dev4" -ay $vg2 +vgchange --devices "$dev3","$dev4" -an $vg2 +not vgextend --devices "$dev3","$dev4" $vg2 "$dev7" +vgextend --devices "$dev3","$dev4","$dev7" $vg2 "$dev7" +vgreduce --devices "$dev3","$dev4","$dev7" $vg2 "$dev7" +vgexport --devices "$dev3","$dev4" $vg2 +vgimport --devices "$dev3","$dev4" $vg2 +not pvremove --devices "$dev3","$dev4" "$dev7" +not pvcreate --devices "$dev3","$dev4" "$dev7" +not vgcreate --devices "$dev3","$dev4" $vg7 "$dev7" +pvremove --devices "$dev7" "$dev7" +pvcreate --devices "$dev7" "$dev7" +vgcreate --devices "$dev7" $vg7 "$dev7" +vgremove --devices "$dev7" $vg7 +pvremove --devices "$dev7" "$dev7" + +# verify pvscan with devices file and devices list + +# arg not in devices file +_clear_online_files +pvscan --devicesfile test.devices --cache -aay "$dev3" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" +pvscan --devicesfile test.devices --cache -aay "$dev4" +not ls "$RUNDIR/lvm/pvs_online/$PVID4" +check lv_field $vg1/$lv1 lv_active "" +check lv_field $vg2/$lv2 lv_active "" + +# arg in devices file +_clear_online_files +pvscan --devicesfile test.devices --cache "$dev1" +pvscan --devicesfile test.devices --cache "$dev2" +ls "$RUNDIR/lvm/pvs_online/$PVID1" +ls "$RUNDIR/lvm/pvs_online/$PVID2" + +# autoactivate with devices file +_clear_online_files +pvscan --devicesfile test.devices --cache -aay "$dev1" +pvscan --devicesfile test.devices --cache -aay "$dev2" +check lv_field $vg1/$lv1 lv_active "active" +vgchange -an $vg1 + +# autoactivate with no devices file +_clear_online_files +pvscan --cache -aay "$dev3" +pvscan --cache -aay "$dev4" +check lv_field $vg2/$lv2 lv_active "active" +vgchange -an $vg2 + +# arg not in devices list +_clear_online_files +pvscan --devices "$dev1","$dev2" --cache "$dev3" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" +pvscan --devices "$dev4" --cache "$dev3" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" +pvscan --devices "$dev5" --cache "$dev3" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" + +# arg in devices list +_clear_online_files +pvscan --devices "$dev3" --cache -aay "$dev3" +pvscan --devices "$dev4","$dev3" --cache -aay "$dev4" +check lv_field $vg2/$lv2 lv_active "active" +vgchange -an $vg2 + +vgchange --devicesfile "" -an +vgremove --devicesfile "" -y $vg1 +vgremove --devicesfile "" -y $vg2 +vgremove --devicesfile "" -y $vg3 + +# +# Test with use_devicesfile=1 (system devices file is in use by default) +# + +aux lvmconf 'devices/use_devicesfile = 1' + +DF="$DFDIR/system.devices" +touch "$DF" + +# create one VG in a non-system devices file +vgcreate --devicesfile test.devices $vg1 "$dev1" "$dev2" + +# create one VG in the default system devices file +vgcreate $vg2 "$dev3" "$dev4" + +# create one VG in neither devices file +vgcreate --devicesfile "" $vg3 "$dev5" "$dev6" + +lvcreate --devicesfile test.devices -l4 -an -i2 -n $lv1 $vg1 +lvcreate -l4 -an -i2 -n $lv2 $vg2 +lvcreate --devicesfile "" -l4 -an -i2 -n $lv3 $vg3 + +# system.devices only sees vg2 +vgs |tee out +not grep $vg1 out +grep $vg2 out +not grep $vg3 out +not vgs $vg1 +vgs $vg2 +not vgs $vg3 +pvs |tee out +not grep "$dev1" out +not grep "$dev2" out +grep "$dev3" out +grep "$dev4" out +not grep "$dev5" out +not grep "$dev6" out + +# test.devices only sees vg1 +vgs --devicesfile test.devices |tee out +grep $vg1 out +not grep $vg2 out +not grep $vg3 out +pvs --devicesfile test.devices |tee out +grep "$dev1" out +grep "$dev2" out +not grep "$dev3" out +not grep "$dev4" out +not grep "$dev5" out +not grep "$dev6" out + +# no devices file sees all +vgs --devicesfile "" |tee out +grep $vg1 out +grep $vg2 out +grep $vg3 out +vgs --devicesfile "" $vg1 +vgs --devicesfile "" $vg2 +vgs --devicesfile "" $vg3 +pvs --devicesfile "" |tee out +grep "$dev1" out +grep "$dev2" out +grep "$dev3" out +grep "$dev4" out +grep "$dev5" out +grep "$dev6" out + +vgchange -ay +lvs --devicesfile test.devices -o active $vg1/$lv1 |tee out +not grep active out +lvs -o active $vg2/$lv2 |tee out +grep active out +lvs --devicesfile "" -o active $vg3/$lv3 |tee out +not grep active out +vgchange -an +lvs -o active $vg2/$lv2 |tee out +not grep active out + +vgchange --devicesfile test.devices -ay +lvs --devicesfile test.devices -o active $vg1/$lv1 |tee out +grep active out +lvs -o active $vg2/$lv2 |tee out +not grep active out +lvs --devicesfile "" -o active $vg3/$lv3 |tee out +not grep active out +vgchange --devicesfile test.devices -an +lvs --devicesfile test.devices -o active $vg1/$lv1 |tee out +not grep active out + +# --devices overrides all three cases: +# always gives access to the specified devices +# always denies access to unspecified devices + +vgs --devices "$dev1","$dev2" $vg1 +vgs --devices "$dev3","$dev4" $vg2 +vgs --devices "$dev5","$dev6" $vg3 + +pvs --devices "$dev1" "$dev1" +pvs --devices "$dev3" "$dev3" +pvs --devices "$dev5" "$dev5" + +not pvs --devices "$dev1" "$dev1" "$dev2" |tee out +grep "$dev1" out +not grep "$dev2" out + +not pvs --devices "$dev3" "$dev3" "$dev4" |tee out +grep "$dev3" out +not grep "$dev4" out + +not pvs --devices "$dev5" "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" |tee out +grep "$dev5" out +not grep "$dev1" out +not grep "$dev2" out +not grep "$dev3" out +not grep "$dev4" out +not grep "$dev6" out + +pvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5" "$dev5" |tee out +grep "$dev5" out +not grep "$dev1" out +not grep "$dev2" out +not grep "$dev3" out +not grep "$dev4" out +not grep "$dev6" out + +pvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5" "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" |tee out +grep "$dev1" out +grep "$dev2" out +grep "$dev3" out +grep "$dev4" out +grep "$dev5" out + +vgchange --devices "$dev1","$dev2" -ay +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | grep active |tee out +grep $lv1 out +not grep $lv2 out +not grep $lv3 out +vgchange --devices "$dev1","$dev2" -an +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | tee out +not grep active out + +vgchange --devices "$dev3","$dev4" -ay +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | grep active |tee out +not grep $lv1 out +grep $lv2 out +not grep $lv3 out +vgchange --devices "$dev3","$dev4" -an +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active |tee out +not grep active out + +vgchange --devices "$dev5","$dev6" -ay +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | grep active |tee out +not grep $lv1 out +not grep $lv2 out +grep $lv3 out +vgchange --devices "$dev5","$dev6" -an +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active |tee out +not grep active out + +lvcreate --devices "$dev1","$dev2" -l1 -an -n $lv4 $vg1 +lvremove --devices "$dev1","$dev2" $vg1/$lv4 +lvcreate --devices "$dev3","$dev4" -l1 -an -n $lv4 $vg2 +lvremove --devices "$dev3","$dev4" $vg2/$lv4 +lvcreate --devices "$dev5","$dev6" -l1 -an -n $lv4 $vg3 +lvremove --devices "$dev5","$dev6" $vg3/$lv4 + +not vgchange --devices "$dev1","$dev2" -ay $vg2 +not vgchange --devices "$dev1","$dev2" -ay $vg3 +not vgchange --devices "$dev3","$dev4" -ay $vg1 +not vgchange --devices "$dev3","$dev4" -ay $vg3 +not vgchange --devices "$dev5","$dev6" -ay $vg1 +not vgchange --devices "$dev5","$dev6" -ay $vg2 + +not lvcreate --devices "$dev1","$dev2" -an -l1 $vg2 +not lvcreate --devices "$dev1","$dev2" -an -l1 $vg3 +not lvcreate --devices "$dev3","$dev4" -an -l1 $vg1 +not lvcreate --devices "$dev3","$dev4" -an -l1 $vg3 +not lvcreate --devices "$dev5","$dev6" -an -l1 $vg1 +not lvcreate --devices "$dev5","$dev6" -an -l1 $vg2 + +# autoactivate devs in default devices file +_clear_online_files +pvscan --cache -aay "$dev3" +pvscan --cache -aay "$dev4" +check lv_field $vg2/$lv2 lv_active "active" +vgchange -an $vg2 +pvscan --cache -aay "$dev1" +not ls "$RUNDIR/lvm/pvs_online/$PVID1" +pvscan --cache -aay "$dev2" +not ls "$RUNDIR/lvm/pvs_online/$PVID2" +pvscan --cache -aay "$dev5" +not ls "$RUNDIR/lvm/pvs_online/$PVID5" +_clear_online_files +pvscan --devices "$dev3" --cache -aay "$dev3" +pvscan --devices "$dev3","$dev4" --cache -aay "$dev4" +lvs --devices "$dev3","$dev4" -o active $vg2/$lv2 | grep active +vgchange --devices "$dev3","$dev4" -an $vg2 + +not vgchange -ay $vg1 +vgchange --devicesfile test.devices -ay $vg1 +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | grep active |tee out +grep $lv1 out +not grep $lv2 out +not grep $lv3 out + +vgchange -ay $vg2 +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | grep active |tee out +grep $lv1 out +grep $lv2 out +not grep $lv3 out + +not vgchange -ay $vg3 +vgchange --devicesfile "" -ay $vg3 +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | grep active |tee out +grep $lv1 out +grep $lv2 out +grep $lv3 out + +vgchange -an +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | grep active |tee out +grep $lv1 out +not grep $lv2 out +grep $lv3 out + +vgchange -ay +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active | grep active |tee out +grep $lv1 out +grep $lv2 out +grep $lv3 out + +vgchange --devicesfile "" -an +lvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5","$dev6" -o name,active |tee out +not grep active out + +not vgremove $vg1 +not vgremove $vg3 +vgremove -y $vg2 +vgremove --devicesfile test.devices -y $vg1 +vgremove --devicesfile "" -y $vg3 + +# +# Test when system.devices is created by lvm +# + +# no pvs exist, pvcreate creates DF, e.g. system installation + +wipe_all +rm -f "$DF" +pvcreate "$dev1" +ls "$DF" +grep "$dev1" "$DF" + +# no pvs exist, vgcreate creates DF, e.g. system installation + +wipe_all +rm -f "$DF" +vgcreate $vg1 "$dev1" +ls "$DF" +grep "$dev1" "$DF" + +# no pvs exist, touch DF, pvcreate uses it + +wipe_all +rm -f "$DF" +touch "$DF" +pvcreate "$dev1" +grep "$dev1" "$DF" + +# no vgs exist, touch DF, vgcreate uses it + +wipe_all +rm -f "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" +grep "$dev1" "$DF" + +# vgs exist, pvcreate/vgcreate do not create DF + +wipe_all +rm -f "$DF" +vgcreate $vg1 "$dev1" +ls "$DF" +rm "$DF" +pvcreate "$dev2" +not ls "$DF" +vgcreate $vg3 "$dev3" +not ls "$DF" + +# vgs exist, pvcreate/vgcreate --devicesfile system.devices creates DF + +wipe_all +rm -f "$DF" +vgcreate $vg1 "$dev1" +ls "$DF" +rm "$DF" +pvcreate --devicesfile system.devices "$dev2" +ls "$DF" +grep "$dev2" "$DF" +rm "$DF" +vgcreate --devicesfile system.devices $vg3 "$dev3" +ls "$DF" +grep "$dev3" "$DF" + +# pvcreate/vgcreate always create non-system DF if it doesn't exist + +wipe_all +rm -f "$DF" +vgcreate $vg1 "$dev1" +rm "$DF" +rm "$DFDIR/test.devices" +pvcreate --devicesfile test.devices "$dev2" +grep "$dev2" "$DFDIR/test.devices" +rm "$DFDIR/test.devices" +vgcreate --devicesfile test.devices $vg3 "$dev3" +grep "$dev3" "$DFDIR/test.devices" + +# vgchange uuid handles stacked PVs on VGs + +wipe_all +rm -f "$DF" +vgcreate $vg1 "$dev1" +lvcreate -l8 -n $lv1 $vg1 +aux lvmconf 'devices/scan_lvs = 1' +pvcreate "$DM_DEV_DIR/$vg1/$lv1" +pvs "$DM_DEV_DIR/$vg1/$lv1" +grep "$DM_DEV_DIR/$vg1/$lv1" $DF +vgchange -an $vg1 +vgchange --uuid $vg1 +vgchange -ay $vg1 +pvs "$DM_DEV_DIR/$vg1/$lv1" +vgchange -an $vg1 +not pvs "$DM_DEV_DIR/$vg1/$lv1" +aux lvmconf 'devices/scan_lvs = 0' +vgremove -y $vg1 + +# +# verify --devicesfile and --devices are not affected by a filter +# This is last because it sets lvm.conf filter and +# I haven't found a way of removing the filter from +# the config after setting it. +# + +aux lvmconf 'devices/use_devicesfile = 0' +wipe_all +rm -f "$DF" +rm -f "$DFDIR/test.devices" + +vgcreate --devicesfile test.devices $vg1 "$dev1" "$dev2" +grep "$dev1" "$DFDIR/test.devices" +grep "$dev2" "$DFDIR/test.devices" +not ls "$DFDIR/system.devices" + +# create two VGs outside the special devices file +vgcreate $vg2 "$dev3" "$dev4" +vgcreate $vg3 "$dev5" "$dev6" +not grep "$dev3" "$DFDIR/test.devices" +not grep "$dev5" "$DFDIR/test.devices" +not ls "$DFDIR/system.devices" + +lvcreate -l4 -an -i2 -n $lv1 $vg1 +lvcreate -l4 -an -i2 -n $lv2 $vg2 +lvcreate -l4 -an -i2 -n $lv3 $vg3 + +aux lvmconf "devices/filter = [ \"r|$dev2|\" \"r|$dev4|\" ]" + +pvs --devicesfile test.devices "$dev1" +pvs --devicesfile test.devices "$dev2" +not pvs --devicesfile test.devices "$dev3" +not pvs --devicesfile test.devices "$dev4" +pvs --devices "$dev1" "$dev1" +pvs --devices "$dev2" "$dev2" +pvs --devices "$dev3" "$dev3" +pvs --devices "$dev4" "$dev4" +pvs --devices "$dev5" "$dev5" +pvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5" "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" | tee out +grep "$dev1" out +grep "$dev2" out +grep "$dev3" out +grep "$dev4" out +grep "$dev5" out +vgchange --devices "$dev1","$dev2" -ay $vg1 +check lv_field $vg1/$lv1 lv_active "active" +lvchange --devices "$dev1","$dev2" -an $vg1/$lv1 +vgchange --devices "$dev3","$dev4" -ay $vg2 +check lv_field $vg2/$lv2 lv_active "active" +lvchange --devices "$dev3","$dev4" -an $vg2/$lv2 + +vgchange -an --devicesfile test.devices $vg1 +vgremove -y --devicesfile test.devices $vg1 +vgremove -y $vg2 +vgremove -y $vg3 + diff --git a/test/shell/devicesfile-devname.sh b/test/shell/devicesfile-devname.sh new file mode 100644 index 0000000..1ff87c2 --- /dev/null +++ b/test/shell/devicesfile-devname.sh @@ -0,0 +1,628 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='devices file with devnames' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 7 + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* + rm -f "$PVS_LOOKUP_DIR"/* +} + +DFDIR="$LVM_SYSTEM_DIR/devices" +mkdir "$DFDIR" || true +DF="$DFDIR/system.devices" +ORIG="$DFDIR/orig.devices" + +aux lvmconf 'devices/use_devicesfile = 1' + +pvcreate "$dev1" +ls "$DF" +grep "$dev1" "$DF" + +pvcreate "$dev2" +grep "$dev2" "$DF" + +pvcreate "$dev3" +grep "$dev3" "$DF" + +vgcreate $vg1 "$dev1" "$dev2" + +# PVID with dashes for matching pvs -o+uuid output +OPVID1=`pvs "$dev1" --noheading -o uuid | awk '{print $1}'` +OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'` +OPVID3=`pvs "$dev3" --noheading -o uuid | awk '{print $1}'` + +# PVID without dashes for matching devices file fields +PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID3=`pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}'` + +lvmdevices --deldev "$dev3" + +not grep "$dev3" "$DF" +not grep "$PVID3" "$DF" +not pvs "$dev3" + +cp "$DF" "$ORIG" + +lvcreate -l4 -an -i2 -n $lv1 $vg1 + +# +# when wrong idname devname is outside DF it's corrected if search_for=1 +# by a general cmd, or by lvmdevices --addpvid +# +# when wrong idname devname is outside DF it's not found or corrected if +# search_for=0 by a general cmd, but will be by lvmdevices --addpvid +# +# when wrong idname devname is inside DF it's corrected if search_for=0|1 +# by a general cmd, or by lvmdevices --addpvid +# +# pvscan --cache -aay does not update DF when devname= is wrong +# +# pvscan --cache -aay when idname devname is wrong: +# every dev is read and then skipped if pvid is not in DF +# +# commands still work with incorrect devname= +# . and they automatically correct the devname= +# + + +# +# idname changes to become incorrect, devname remains unchanged and correct +# . change idname to something outside DF +# . change idname to match another DF entry +# . swap idname of two DF entries +# + +# edit DF idname, s/dev1/dev3/, where new dev is not in DF + +sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" "$ORIG" > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +not grep "$OPVID3" out +not grep "$dev3" out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +# pvs fixed the DF +not grep "$PVID3" "$DF" +not grep "$dev3" "$DF" +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +cat "$DF" + +sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" "$ORIG" > "$DF" +cat "$DF" +# lvcreate uses correct dev +lvcreate -l1 -n $lv2 -an $vg1 "$dev1" +# lvcreate fixed the DF +not grep "$PVID3" "$DF" +not grep "$dev3" "$DF" +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +# pvs reports correct dev +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +not grep "$OPVID3" out +not grep "$dev3" out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +lvremove $vg1/$lv2 +cat "$DF" + +sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" "$ORIG" > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +not grep "$PVID3" "$DF" +not grep "$dev3" "$DF" +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +cat "$DF" + +# edit DF idname, s/dev1/dev2/, creating two entries with same idname + +sed -e "s|IDNAME=$dev1|IDNAME=$dev2|" "$ORIG" > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +grep "$OPVID2" out |tee out2 +grep "$dev2" out2 +# pvs fixed the DF +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "IDNAME=$dev2" out +cat "$DF" + +sed -e "s|IDNAME=$dev1|IDNAME=$dev2|" "$ORIG" > "$DF" +cat "$DF" +# lvcreate uses correct dev +lvcreate -l1 -n $lv2 -an $vg1 "$dev1" +# lvcreate fixed the DF +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "IDNAME=$dev2" out +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +grep "$OPVID2" out |tee out2 +grep "$dev2" out2 +lvremove $vg1/$lv2 +cat "$DF" + +sed -e "s|IDNAME=$dev1|IDNAME=$dev2|" "$ORIG" > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "IDNAME=$dev2" out +cat "$DF" + +# edit DF idname, swap dev1 and dev2 + +sed -e "s|IDNAME=$dev1|IDNAME=tmpname|" "$ORIG" > tmp1.devices +sed -e "s|IDNAME=$dev2|IDNAME=$dev1|" tmp1.devices > tmp2.devices +sed -e "s|IDNAME=tmpname|IDNAME=$dev2|" tmp2.devices > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +grep "$OPVID2" out |tee out2 +grep "$dev2" out2 +# pvs fixed the DF +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "IDNAME=$dev2" out +cat "$DF" + +sed -e "s|IDNAME=$dev1|IDNAME=tmpname|" "$ORIG" > tmp1.devices +sed -e "s|IDNAME=$dev2|IDNAME=$dev1|" tmp1.devices > tmp2.devices +sed -e "s|IDNAME=tmpname|IDNAME=$dev2|" tmp2.devices > "$DF" +cat "$DF" +# lvcreate uses correct dev +lvcreate -l1 -n $lv2 -an $vg1 "$dev1" +# lvcreate fixed the DF +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "IDNAME=$dev2" out +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +grep "$OPVID2" out |tee out2 +grep "$dev2" out2 +lvremove $vg1/$lv2 +cat "$DF" + +sed -e "s|IDNAME=$dev1|IDNAME=tmpname|" "$ORIG" > tmp1.devices +sed -e "s|IDNAME=$dev2|IDNAME=$dev1|" tmp1.devices > tmp2.devices +sed -e "s|IDNAME=tmpname|IDNAME=$dev2|" tmp2.devices > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "IDNAME=$dev2" out +cat "$DF" + + +# +# idname remains correct, devname changes to become incorrect +# . change devname to something outside DF +# . change devname to match another DF entry +# . swap devname of two DF entries +# + +# edit DF devname, s/dev1/dev3/, where new dev is not in DF + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +not grep "$OPVID3" out +not grep "$dev3" out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +# pvs fixed the DF +not grep "$PVID3" "$DF" +not grep "$dev3" "$DF" +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +cat "$DF" + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +not grep "$PVID3" "$DF" +not grep "$dev3" "$DF" +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +cat "$DF" + +# edit DF devname, s/dev1/dev2/, creating two entries with same devname + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev2|" "$ORIG" > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +grep "$OPVID2" out |tee out2 +grep "$dev2" out2 +# pvs fixed the DF +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "DEVNAME=$dev2" out +cat "$DF" + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev2|" "$ORIG" > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "IDNAME=$dev2" out +cat "$DF" + +# edit DF devname, swap dev1 and dev2 + +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpname|" "$ORIG" > tmp1.devices +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1.devices > tmp2.devices +sed -e "s|DEVNAME=tmpname|DEVNAME=$dev2|" tmp2.devices > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +grep "$OPVID2" out |tee out2 +grep "$dev2" out2 +# pvs fixed the DF +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "DEVNAME=$dev2" out +cat "$DF" + +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpname|" "$ORIG" > tmp1.devices +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1.devices > tmp2.devices +sed -e "s|DEVNAME=tmpname|DEVNAME=$dev2|" tmp2.devices > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +grep "$PVID1" "$DF" |tee out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "IDNAME=$dev2" out +cat "$DF" + + +# +# idname and devname change, both become incorrect +# . change idname&devname to something outside DF +# . change idname&devname to match another DF entry +# . swap idname&devname of two DF entries +# + +# edit DF idname&devname, s/dev1/dev3/, where new dev is not in DF + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices +sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" tmp1.devices > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +not grep "$OPVID3" out +not grep "$dev3" out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +# pvs fixed the DF +not grep "$PVID3" "$DF" +not grep "$dev3" "$DF" +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "IDNAME=$dev1" out +cat "$DF" + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices +sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" tmp1.devices > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +not grep "$PVID3" "$DF" +not grep "$dev3" "$DF" +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "IDNAME=$dev1" out +cat "$DF" + +# edit DF idname&devname, s/dev1/dev2/, creating two entries with same devname + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev2|" tmp1.devices > "$DF" +sed -e "s|IDNAME=$dev1|IDNAME=$dev2|" tmp1.devices > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +grep "$OPVID2" out |tee out2 +grep "$dev2" out2 +# pvs fixed the DF +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "DEVNAME=$dev2" out +grep "IDNAME=$dev2" out +cat "$DF" + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev2|" tmp1.devices > "$DF" +sed -e "s|IDNAME=$dev1|IDNAME=$dev2|" tmp1.devices > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "DEVNAME=$dev2" out +grep "IDNAME=$dev2" out +cat "$DF" + +# edit DF devname, swap dev1 and dev2 + +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpname|" "$ORIG" > tmp1.devices +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1.devices > tmp2.devices +sed -e "s|DEVNAME=tmpname|DEVNAME=$dev2|" tmp2.devices > tmp3.devices +sed -e "s|IDNAME=$dev1|IDNAME=tmpname|" tmp3.devices > tmp4.devices +sed -e "s|IDNAME=$dev2|IDNAME=$dev1|" tmp4.devices > tmp5.devices +sed -e "s|IDNAME=tmpname|IDNAME=$dev2|" tmp5.devices > "$DF" +cat "$DF" +# pvs reports correct info +pvs -o+uuid | tee pvs.out +grep $vg1 pvs.out > out +grep "$OPVID1" out |tee out2 +grep "$dev1" out2 +grep "$OPVID2" out |tee out2 +grep "$dev2" out2 +# pvs fixed the DF +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "DEVNAME=$dev2" out +grep "IDNAME=$dev2" out +cat "$DF" + +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpname|" "$ORIG" > tmp1.devices +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1.devices > tmp2.devices +sed -e "s|DEVNAME=tmpname|DEVNAME=$dev2|" tmp2.devices > tmp3.devices +sed -e "s|IDNAME=$dev1|IDNAME=tmpname|" tmp3.devices > tmp4.devices +sed -e "s|IDNAME=$dev2|IDNAME=$dev1|" tmp4.devices > tmp5.devices +sed -e "s|IDNAME=tmpname|IDNAME=$dev2|" tmp5.devices > "$DF" +cat "$DF" +# lvmdevices fixes the DF +lvmdevices --update +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "IDNAME=$dev1" out +grep "$PVID2" "$DF" |tee out +grep "DEVNAME=$dev2" out +grep "IDNAME=$dev2" out +cat "$DF" + +# +# check that pvscan --cache -aay does the right thing: +# +# idname and devname change, both become incorrect +# . change idname&devname to something outside DF +# . swap idname&devname of two DF entries +# + +# edit DF idname&devname, s/dev1/dev3/, where new dev is not in DF + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices +sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" tmp1.devices > "$DF" +cat "$DF" +_clear_online_files +pvscan --cache -aay "$dev1" +pvscan --cache -aay "$dev2" +pvscan --cache -aay "$dev3" +cat "$DF" +# pvscan does not fix DF +grep "$dev3" "$DF" +not grep "$dev1" "$DF" +ls "$RUNDIR/lvm/pvs_online/$PVID1" +ls "$RUNDIR/lvm/pvs_online/$PVID2" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" +check lv_field $vg1/$lv1 lv_active "active" +# pvs updates the DF +pvs |tee out +grep "$dev1" out +grep "$dev2" out +not grep "$dev3" out +grep "$dev1" "$DF" +grep "$dev2" "$DF" +not grep "$dev3" "$DF" +vgchange -an $vg1 + +# edit DF idname&devname, swap dev1 and dev2 + +vgremove -y $vg1 +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +vgcreate $vg2 "$dev2" +lvcreate -n $lv2 -l1 -an $vg2 + +cat "$DF" +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpname|" "$ORIG" > tmp1.devices +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1.devices > tmp2.devices +sed -e "s|DEVNAME=tmpname|DEVNAME=$dev2|" tmp2.devices > tmp3.devices +sed -e "s|IDNAME=$dev1|IDNAME=tmpname|" tmp3.devices > tmp4.devices +sed -e "s|IDNAME=$dev2|IDNAME=$dev1|" tmp4.devices > tmp5.devices +sed -e "s|IDNAME=tmpname|IDNAME=$dev2|" tmp5.devices > "$DF" +cat "$DF" + +_clear_online_files + +# pvscan creates the correct online files and activates correct vg +pvscan --cache -aay "$dev1" +ls "$RUNDIR/lvm/pvs_online/$PVID1" +ls "$RUNDIR/lvm/vgs_online/$vg1" +not ls "$RUNDIR/lvm/pvs_online/$PVID2" +not ls "$RUNDIR/lvm/vgs_online/$vg2" +# don't use lvs because it would fix DF before we check it +dmsetup status $vg1-$lv1 +not dmsetup status $vg2-$lv2 + +pvscan --cache -aay "$dev2" +ls "$RUNDIR/lvm/pvs_online/$PVID2" +ls "$RUNDIR/lvm/vgs_online/$vg2" +dmsetup status $vg2-$lv2 + +pvscan --cache -aay "$dev3" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" + +# pvscan did not correct DF +cat "$DF" +grep "$PVID1" "$DF" |tee out +grep "$dev2" out +not grep "$dev1" out +grep "$PVID2" "$DF" |tee out +grep "$dev1" out +not grep "$dev2" out + +# pvs corrects DF +pvs +grep "$PVID1" "$DF" |tee out +grep "$dev1" out +not grep "$dev2" out +grep "$PVID2" "$DF" |tee out +grep "$dev2" out +not grep "$dev1" out + +vgchange -an $vg1 +vgchange -an $vg2 +vgremove -ff $vg1 +vgremove -ff $vg2 + +# bz 2119473 + +aux lvmconf "devices/search_for_devnames = \"none\"" +sed -e "s|DEVNAME=$dev1|DEVNAME=.|" "$ORIG" > tmp1.devices +sed -e "s|IDNAME=$dev1|IDNAME=.|" tmp1.devices > "$DF" +pvs +lvmdevices +pvcreate -ff --yes --uuid "$PVID1" --norestorefile $dev1 +grep "$PVID1" "$DF" |tee out +grep "DEVNAME=$dev1" out +grep "IDNAME=$dev1" out +aux lvmconf "devices/search_for_devnames = \"auto\"" + +# devnames change so the new devname now refers to a filtered device, +# e.g. an mpath or md component, which is not scanned + +wait_md_create() { + local md=$1 + + while :; do + if ! grep "$(basename $md)" /proc/mdstat; then + echo "$md not ready" + cat /proc/mdstat + sleep 2 + else + break + fi + done + echo "$md" > WAIT_MD_DEV +} + +aux wipefs_a "$dev1" "$dev2" "$dev3" "$dev4" + +rm "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" "$dev2" +cat "$DF" +cp "$DF" "$ORIG" + +# PVID with dashes for matching pvs -o+uuid output +OPVID1=`pvs "$dev1" --noheading -o uuid | awk '{print $1}'` +OPVID2=`pvs "$dev2" --noheading -o uuid | awk '{print $1}'` + +# PVID without dashes for matching devices file fields +PVID1=`pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID2=`pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}'` + +aux mdadm_create --metadata=1.0 --level 1 --raid-devices=2 "$dev3" "$dev4" +mddev=$(< MD_DEV) + +wait_md_create "$mddev" + +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev3|" "$ORIG" > tmp1.devices +sed -e "s|IDNAME=$dev1|IDNAME=$dev3|" tmp1.devices > "$DF" +cat "$DF" +pvs -o+uuid |tee out +grep "$dev1" out +grep "$dev2" out +grep "$OPVID1" out +grep "$OPVID2" out +not grep "$dev3" out +not grep "$dev4" out + +grep "$dev1" "$DF" +grep "$dev2" "$DF" +grep "$PVID1" "$DF" +grep "$PVID2" "$DF" +not grep "$dev3" "$DF" +not grep "$dev4" "$DF" + +mdadm --stop "$mddev" +aux udev_wait + +vgremove -ff $vg1 diff --git a/test/shell/devicesfile-edit.sh b/test/shell/devicesfile-edit.sh new file mode 100644 index 0000000..0ccafaf --- /dev/null +++ b/test/shell/devicesfile-edit.sh @@ -0,0 +1,257 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='devices file editing with lvmdevices' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux lvmconf 'devices/scan = "/dev"' + +aux prepare_devs 1 + +# The tests run with system dir of "/etc" but lvm when running +# normally has cmd->system_dir set to "/etc/lvm". +DFDIR="$LVM_SYSTEM_DIR/devices" +mkdir -p "$DFDIR" || true +DF="$DFDIR/system.devices" + +aux lvmconf 'devices/use_devicesfile = 1' + +losetup -h | grep sector-size || skip +which fallocate || skip + +fallocate -l 2M loopa +fallocate -l 2M loopb + +setup_loop_devs() { + for i in {1..5} ; do + LOOP1=$(losetup -f loopa --show || true) + test -n "$LOOP1" && break + done + for i in {1..5} ; do + LOOP2=$(losetup -f loopb --show || true) + test -n "$LOOP2" && break + done +} + +setup_loop_devs + +# Tests of devices without PV on them. + +# add/del with default idtype loop_file +lvmdevices --adddev "$LOOP1" +grep "$LOOP1" $DF +lvmdevices --adddev "$LOOP2" +grep "$LOOP2" $DF +grep "IDTYPE=loop_file" $DF +not grep "IDTYPE=devname" $DF +lvmdevices --deldev "$LOOP1" +not grep "$LOOP1" $DF +lvmdevices --deldev "$LOOP2" +not grep "$LOOP2" $DF + +# add/del with non-default idtype devname +lvmdevices --adddev "$LOOP1" --deviceidtype devname +grep "$LOOP1" $DF +lvmdevices --adddev "$LOOP2" --deviceidtype devname +grep "$LOOP2" $DF +grep "IDTYPE=devname" $DF +not grep "IDTYPE=loop_file" $DF +lvmdevices --deldev "$LOOP1" +not grep "$LOOP1" $DF +lvmdevices --deldev "$LOOP2" +not grep "$LOOP2" $DF + +# add/del when dev is missing, using default idtype +lvmdevices --adddev "$LOOP1" +grep "$LOOP1" $DF +lvmdevices --adddev "$LOOP2" +grep "$LOOP2" $DF +losetup -D +grep "$LOOP1" $DF +grep "$LOOP2" $DF +lvmdevices --deldev "$LOOP1" +not grep "$LOOP1" $DF +lvmdevices --deldev "$LOOP2" +not grep "$LOOP2" $DF +not lvmdevices --adddev "$LOOP1" +not lvmdevices --adddev "$LOOP2" +not grep "$LOOP1" $DF +not grep "$LOOP2" $DF +setup_loop_devs +rm $DF + +# add/del when dev is missing, using devname idtype +lvmdevices --adddev "$LOOP1" --deviceidtype devname +grep "$LOOP1" $DF +lvmdevices --adddev "$LOOP2" --deviceidtype devname +grep "$LOOP2" $DF +losetup -D +grep "$LOOP1" $DF +grep "$LOOP2" $DF +lvmdevices --deldev "$LOOP1" +not grep "$LOOP1" $DF +lvmdevices --deldev "$LOOP2" +not grep "$LOOP2" $DF +setup_loop_devs +rm $DF + +# Tests of devices with PV on them. + +touch $DF +pvcreate "$LOOP1" +pvcreate "$LOOP2" +# PVID without dashes for matching devices file fields +PVID1=`pvs "$LOOP1" --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID2=`pvs "$LOOP2" --noheading -o uuid | tr -d - | awk '{print $1}'` +# PVID with dashes for matching pvs -o+uuid output +OPVID1=`pvs "$LOOP1" --noheading -o uuid | awk '{print $1}'` +OPVID2=`pvs "$LOOP2" --noheading -o uuid | awk '{print $1}'` +grep "$LOOP1" $DF +grep "$LOOP2" $DF +grep "$PVID1" $DF +grep "$PVID2" $DF +rm $DF + +# add/deldev with default idtype loop_file +lvmdevices --adddev "$LOOP1" +grep "$LOOP1" $DF +grep "$PVID1" $DF +lvmdevices --adddev "$LOOP2" +grep "$LOOP2" $DF +grep "$PVID2" $DF +grep "IDTYPE=loop_file" $DF +not grep "IDTYPE=devname" $DF +lvmdevices --deldev "$LOOP1" +not grep "$LOOP1" $DF +lvmdevices --deldev "$LOOP2" +not grep "$LOOP2" $DF +rm $DF + +# deldev using idname +lvmdevices --adddev "$LOOP1" +lvmdevices --adddev "$LOOP2" +vgcreate $vg "$LOOP1" "$LOOP2" +IDNAME1=`pvs "$LOOP1" --noheading -o deviceid | awk '{print $1}'` +IDNAME2=`pvs "$LOOP2" --noheading -o deviceid | awk '{print $1}'` +lvmdevices --deldev "$IDNAME2" --deviceidtype loop_file +not grep "$IDNAME2" $DF +not grep "$LOOP2" $DF +lvmdevices --deldev "$IDNAME1" --deviceidtype loop_file +not grep "$IDNAME1" $DF +not grep "$LOOP1" $DF +lvmdevices --adddev "$LOOP1" +lvmdevices --adddev "$LOOP2" +vgremove $vg +rm $DF + +# add/delpvid with default idtype loop_file +lvmdevices --addpvid "$PVID1" +grep "$LOOP1" $DF +grep "$PVID1" $DF +lvmdevices --addpvid "$PVID2" +grep "$LOOP2" $DF +grep "$PVID2" $DF +grep "IDTYPE=loop_file" $DF +not grep "IDTYPE=devname" $DF +lvmdevices --delpvid "$PVID1" +not grep "$LOOP1" $DF +not grep "$PVID1" $DF +lvmdevices --delpvid "$PVID2" +not grep "$LOOP2" $DF +not grep "$PVID2" $DF +rm $DF + +# add/deldev with non-default idtype devname +lvmdevices --adddev "$LOOP1" --deviceidtype devname +grep "$LOOP1" $DF +grep "$PVID1" $DF +lvmdevices --adddev "$LOOP2" --deviceidtype devname +grep "$LOOP2" $DF +grep "$PVID2" $DF +grep "IDTYPE=devname" $DF +not grep "IDTYPE=loop_file" $DF +lvmdevices --deldev "$LOOP1" +not grep "$LOOP1" $DF +lvmdevices --deldev "$LOOP2" +not grep "$LOOP2" $DF +rm $DF + +# add/delpvid with non-default idtype devname +lvmdevices --addpvid "$PVID1" --deviceidtype devname +grep "$LOOP1" $DF +grep "$PVID1" $DF +lvmdevices --addpvid "$PVID2" --deviceidtype devname +grep "$LOOP2" $DF +grep "$PVID2" $DF +grep "IDTYPE=devname" $DF +not grep "IDTYPE=loop_file" $DF +lvmdevices --deldev "$LOOP1" +not grep "$LOOP1" $DF +lvmdevices --deldev "$LOOP2" +not grep "$LOOP2" $DF +rm $DF + +# add/deldev when dev is missing, using default idtype +lvmdevices --adddev "$LOOP1" +grep "$LOOP1" $DF +grep "$PVID1" $DF +lvmdevices --adddev "$LOOP2" +grep "$LOOP2" $DF +grep "$PVID2" $DF +losetup -D +grep "$LOOP1" $DF +grep "$LOOP2" $DF +lvmdevices --deldev "$LOOP1" +not grep "$LOOP1" $DF +not grep "$PVID1" $DF +lvmdevices --deldev "$LOOP2" +not grep "$LOOP2" $DF +not grep "$PVID2" $DF +setup_loop_devs +rm $DF + +# add/delpvid when dev is missing, using devname idtype +lvmdevices --addpvid "$PVID1" --deviceidtype devname +grep "$LOOP1" $DF +grep "$PVID1" $DF +lvmdevices --addpvid "$PVID2" --deviceidtype devname +grep "$LOOP2" $DF +grep "$PVID2" $DF +losetup -D +grep "$LOOP1" $DF +grep "$LOOP2" $DF +lvmdevices --delpvid "$PVID1" +not grep "$LOOP1" $DF +not grep "$PVID1" $DF +lvmdevices --delpvid "$PVID2" +not grep "$LOOP2" $DF +not grep "$PVID2" $DF +setup_loop_devs +rm $DF + +# test delnotfound +lvmdevices --addpvid "$PVID1" +echo "IDTYPE=sys_wwid IDNAME=naa.123 DEVNAME=/dev/sdx1 PVID=aaa PART=1" >> $DF +echo "IDTYPE=devname IDNAME=/dev/sdy DEVNAME=/dev/sdy PVID=bbb" >> $DF +lvmdevices +lvmdevices --update --delnotfound +not grep PVID=aaa $DF +not grep PVID=bbb $DF + + +# TODO: add/rem of partitions of same device + +losetup -D +rm loopa loopb diff --git a/test/shell/devicesfile-realdevs.sh b/test/shell/devicesfile-realdevs.sh new file mode 100644 index 0000000..0f62e9b --- /dev/null +++ b/test/shell/devicesfile-realdevs.sh @@ -0,0 +1,612 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='devices file with real devs' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# +# To use this test, add two or more devices with real device ids, +# e.g. wwids, to a file, e.g. +# $ cat /tmp/devs +# /dev/sdb +# /dev/sdc +# /dev/sdd +# +# Specify this file as LVM_TEST_DEVICE_LIST=/tmp/devs +# when running the test. +# +# This test will wipe these devices. +# + +if [ -z ${LVM_TEST_DEVICE_LIST+x} ]; then echo "LVM_TEST_DEVICE_LIST is unset" && skip; else echo "LVM_TEST_DEVICE_LIST is set to '$LVM_TEST_DEVICE_LIST'"; fi + +test -e "$LVM_TEST_DEVICE_LIST" || skip + +num_devs=$(cat $LVM_TEST_DEVICE_LIST | wc -l) + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* + rm -f "$PVS_LOOKUP_DIR"/* +} + +test -d "$PVS_ONLINE_DIR" || mkdir -p "$PVS_ONLINE_DIR" +test -d "$VGS_ONLINE_DIR" || mkdir -p "$VGS_ONLINE_DIR" +test -d "$PVS_LOOKUP_DIR" || mkdir -p "$PVS_LOOKUP_DIR" +_clear_online_files + +aux prepare_real_devs + +aux lvmconf 'devices/dir = "/dev"' +aux lvmconf 'devices/use_devicesfile = 1' +DFDIR="$LVM_SYSTEM_DIR/devices" +DF="$DFDIR/system.devices" +mkdir $DFDIR || true +not ls $DF + +get_real_devs + +wipe_all() { + for dev in "${REAL_DEVICES[@]}"; do + wipefs -a $dev + done +} + +wipe_all + +# check each dev is added correctly to df + +touch $DF +for dev in "${REAL_DEVICES[@]}"; do + pvcreate $dev + + pvs -o+uuid $dev + maj=$(get pv_field "$dev" major) + min=$(get pv_field "$dev" minor) + pvid=`pvs $dev --noheading -o uuid | tr -d - | awk '{print $1}'` + + sys_wwid_file="/sys/dev/block/$maj:$min/device/wwid" + sys_serial_file="/sys/dev/block/$maj:$min/device/serial" + sys_dm_uuid_file="/sys/dev/block/$maj:$min/dm/uuid" + sys_md_uuid_file="/sys/dev/block/$maj:$min/md/uuid" + sys_loop_file="/sys/dev/block/$maj:$min/loop/backing_file" + + if test -e $sys_wwid_file; then + sys_file=$sys_wwid_file + idtype="sys_wwid" + elif test -e $sys_serial_file; then + sys_file=$sys_serial_file + idtype="sys_serial" + elif test -e $sys_dm_uuid_file; then + sys_file=$sys_dm_uuid_file + idtype="mpath_uuid" + elif test -e $sys_md_uuid_file; then + sys_file=$sys_md_uuid_file + idtype="md_uuid" + elif test -e $sys_loop_file; then + sys_file=$sys_loop_file + idtype="loop_file" + else + echo "no id type for device" + skip + fi + + idname=$(< $sys_file) + + rm -f idline + grep IDNAME=$idname $DF | tee idline + grep IDTYPE=$idtype idline + grep DEVNAME=$dev idline + grep PVID=$pvid idline +done + +cp $DF df2 + +# vgcreate from existing pvs, already in df + +vgcreate $vg "${REAL_DEVICES[@]}" + +vgremove $vg +rm $DF + +# vgcreate from existing pvs, adding to df + +touch $DF +vgcreate $vg "${REAL_DEVICES[@]}" + +grep IDNAME $DF > df.ids +grep IDNAME df2 > df2.ids +diff df.ids df2.ids + +# check device id metadata fields + +for dev in "${REAL_DEVICES[@]}"; do + grep $dev $DF + deviceid=`pvs $dev --noheading -o deviceid | awk '{print $1}'` + deviceidtype=`pvs $dev --noheading -o deviceidtype | awk '{print $1}'` + grep $dev $DF | grep $deviceid + grep $dev $DF | grep $deviceidtype + lvcreate -l1 $vg $dev +done + +vgchange -an $vg +vgremove -y $vg + +# check pvremove leaves devs in df but without pvid + +for dev in "${REAL_DEVICES[@]}"; do + maj=$(get pv_field "$dev" major) + min=$(get pv_field "$dev" minor) + pvid=`pvs $dev --noheading -o uuid | tr -d - | awk '{print $1}'` + + pvremove $dev + grep $dev $DF + not grep $pvid $DF +done + +# Many of remaining tests require two or three devices +test $num_devs -gt 2 || skip + +# check vgextend adds new dev to df, vgreduce leaves dev in df + +rm $DF + +touch $DF +vgcreate $vg $dev1 +vgextend $vg $dev2 +grep $dev1 $DF +grep $dev2 $DF +id1=`pvs $dev1 --noheading -o deviceid | awk '{print $1}'` +id2=`pvs $dev2 --noheading -o deviceid | awk '{print $1}'` +grep $id1 $DF +grep $id2 $DF +vgreduce $vg $dev2 +grep $dev2 $DF +vgremove $vg + +# check devs are not visible to lvm until added to df + +rm $DF + +# df needs to exist otherwise devicesfile feature turned off +touch $DF + +not pvs $dev1 +not pvs $dev2 +pvs -a |tee all +not grep $dev1 all +not grep $dev2 all +not grep $dev1 $DF +not grep $dev2 $DF + +pvcreate $dev1 + +pvs $dev1 +not pvs $dev2 +pvs -a |tee all +grep $dev1 all +not grep $dev2 all +grep $dev1 $DF +not grep $dev2 $DF + +pvcreate $dev2 + +pvs $dev1 +pvs $dev2 +pvs -a |tee all +grep $dev1 all +grep $dev2 all +grep $dev1 $DF +grep $dev2 $DF + +vgcreate $vg $dev1 + +pvs $dev1 +pvs $dev2 +pvs -a |tee all +grep $dev1 all +grep $dev2 all +grep $dev1 $DF +grep $dev2 $DF + +vgextend $vg $dev2 + +pvs $dev1 +pvs $dev2 +pvs -a |tee all +grep $dev1 all +grep $dev2 all +grep $dev1 $DF +grep $dev2 $DF + +# check vgimportdevices VG + +rm $DF +wipe_all + +vgcreate $vg "${REAL_DEVICES[@]}" +rm $DF +touch $DF + +for dev in "${REAL_DEVICES[@]}"; do + not pvs $dev +done + +vgimportdevices $vg + +for dev in "${REAL_DEVICES[@]}"; do + pvs $dev +done + +# check vgimportdevices -a + +rm $DF +wipe_all + +vgcreate $vg1 $dev1 +vgcreate $vg2 $dev2 + +rm $DF + +vgimportdevices -a + +ls $DF + +vgs $vg1 +vgs $vg2 + +pvs $dev1 +pvs $dev2 + +# check vgimportclone --importdevices + +rm $DF +wipe_all + +vgcreate $vg1 $dev1 +vgimportdevices $vg1 + +dd if=$dev1 of=$dev2 bs=1M count=1 + +pvs $dev1 +not pvs $dev2 + +grep $dev1 $DF +not grep $dev2 $DF + +not vgimportclone $dev2 + +not grep $dev2 $DF + +vgimportclone --basevgname $vg2 --importdevices $dev2 + +pvid1=`pvs $dev1 --noheading -o uuid | tr -d - | awk '{print $1}'` +pvid2=`pvs $dev2 --noheading -o uuid | tr -d - | awk '{print $1}'` +test "$pvid1" != "$pvid2" || die "same uuid" + +id1=`pvs $dev1 --noheading -o deviceid | tr -d - | awk '{print $1}'` +id2=`pvs $dev2 --noheading -o deviceid | tr -d - | awk '{print $1}'` +test "$id1" != "$id2" || die "same device id" + +grep $dev1 $DF +grep $dev2 $DF +grep $pvid1 $DF +grep $pvid2 $DF +grep $id1 $DF +grep $id2 $DF + +vgs $vg1 +vgs $vg2 + +# +# check lvmdevices +# + +wipe_all +rm $DF + +# set up pvs and save pvids/deviceids +touch $DF +count=0 +for dev in "${REAL_DEVICES[@]}"; do + pvcreate $dev + vgcreate ${vg}_${count} $dev + pvid=`pvs $dev --noheading -o uuid | tr -d - | awk '{print $1}'` + did=`pvs $dev --noheading -o deviceid | awk '{print $1}'` + echo dev $dev pvid $pvid did $did + PVIDS[$count]=$pvid + DEVICEIDS[$count]=$did + count=$(( count + 1 )) +done + +rm $DF || true +not lvmdevices +touch $DF +lvmdevices + +# check lvmdevices --adddev +count=0 +for dev in "${REAL_DEVICES[@]}"; do + pvid=${PVIDS[$count]} + did=${DEVICEIDS[$count]} + echo $dev pvid: $pvid did: $did + not pvs $dev + lvmdevices --adddev $dev + lvmdevices |tee out + grep $dev out |tee idline + grep $pvid idline + grep $did idline + grep $dev $DF + pvs $dev + count=$(( count + 1 )) +done + +# check lvmdevices --deldev +count=0 +for dev in "${REAL_DEVICES[@]}"; do + pvid=${PVIDS[$count]} + did=${DEVICEIDS[$count]} + pvs $dev + lvmdevices --deldev $dev + lvmdevices |tee out + not grep $dev out + not grep $pvid out + not grep $did out + not grep $dev $DF + not pvs $dev + count=$(( count + 1 )) +done + +# check lvmdevices --addpvid +count=0 +for dev in "${REAL_DEVICES[@]}"; do + pvid=${PVIDS[$count]} + did=${DEVICEIDS[$count]} + not pvs $dev + lvmdevices --addpvid $pvid + lvmdevices |tee out + grep $dev out |tee idline + grep $pvid idline + grep $did idline + grep $dev $DF + pvs $dev + count=$(( count + 1 )) +done + +# check lvmdevices --delpvid +count=0 +for dev in "${REAL_DEVICES[@]}"; do + pvid=${PVIDS[$count]} + did=${DEVICEIDS[$count]} + pvs $dev + lvmdevices --delpvid $pvid + lvmdevices |tee out + not grep $dev out + not grep $pvid out + not grep $did out + not grep $dev $DF + not pvs $dev + count=$(( count + 1 )) +done + +# wrong pvid in df +rm $DF +pvid1=${PVIDS[0]} +pvid2=${PVIDS[1]} +did1=${DEVICEIDS[0]} +did2=${DEVICEIDS[1]} +lvmdevices --adddev $dev1 +lvmdevices --adddev $dev2 + +# test bad pvid +cp $DF $DF.orig +rm $DF +sed "s/$pvid1/badpvid/" "$DF.orig" |tee $DF +not grep $pvid1 $DF +grep $did1 $DF + +not lvmdevices --check 2>&1|tee out +grep $dev1 out +grep badpvid out +grep $pvid1 out +not grep $dev2 out + +lvmdevices |tee out +grep $dev1 out |tee out1 +grep badpvid out1 +not grep $pvid1 out1 +grep $dev2 out + +lvmdevices --update + +lvmdevices 2>&1|tee out +grep $dev1 out +grep $dev2 out +not grep badpvid +grep $pvid1 out +grep $did1 out +grep $pvid1 $DF +grep $did1 $DF + +# wrong deviceid in df +# the devicesfile logic and behavior is based on the idname being +# the primary identifier that we trust over everything else, i.e. +# we'll never assume that the deviceid is wrong and some other +# field is correct, and "fix" the deviceid. We always assume the +# deviceid correct and other values are wrong (since pvid and devname +# have known, common ways of becoming wrong, but the deviceid doesn't +# really have any known way of becoming wrong apart from random +# file corruption.) +# So, if the deviceid *is* corrupted, as we do here, then standard +# commands won't correct it. We need to use delpvid/addpvid explicitly +# to say that we are targetting the given pvid. + +rm $DF +sed "s/$did1/baddid/" "$DF.orig" |tee $DF + +lvmdevices --check 2>&1|tee out +grep $dev1 out +grep baddid out +not grep $dev2 out + +lvmdevices 2>&1|tee out +grep $pvid1 out +grep $pvid2 out +grep baddid out +grep $did2 out +grep $dev2 out + +lvmdevices --delpvid $pvid1 +lvmdevices --addpvid $pvid1 + +lvmdevices |tee out +grep $dev1 out +grep $dev2 out +not grep baddid +grep $pvid1 out +grep $did1 out +grep $pvid1 $DF +grep $did1 $DF + +# wrong devname in df, this is expected to become incorrect regularly +# given inconsistent dev names after reboot + +rm $DF +d1=$(basename $dev1) +d3=$(basename $dev3) +sed "s/$d1/$d3/" "$DF.orig" |tee $DF +not lvmdevices --check 2>&1 |tee out +grep $dev1 out + +lvmdevices --update + +lvmdevices |tee out +grep $dev1 out |tee out1 +grep $pvid1 out1 +grep $did1 out1 +grep $dev2 out |tee out2 +grep $pvid2 out2 +grep $did2 out2 + +# swap devnames for two existing entries + +rm $DF +d1=$(basename $dev1) +d2=$(basename $dev2) +sed "s/$d1/tmp/" "$DF.orig" |tee ${DF}_1 +sed "s/$d2/$d1/" "${DF}_1" |tee ${DF}_2 +sed "s/tmp/$d2/" "${DF}_2" |tee $DF +rm ${DF}_1 ${DF}_2 +not lvmdevices --check 2>&1 |tee out +grep $dev1 out +grep $dev2 out + +lvmdevices --update + +lvmdevices |tee out +grep $dev1 out |tee out1 +grep $pvid1 out1 +grep $did1 out1 +grep $dev2 out |tee out2 +grep $pvid2 out2 +grep $did2 out2 + +# ordinary command is not confused by wrong devname and fixes +# the wrong devname in df + +rm $DF +d1=$(basename $dev1) +d3=$(basename $dev3) +sed "s/$d1/$d3/" "$DF.orig" |tee $DF +not lvmdevices --check 2>&1 |tee out +grep $dev1 out + +pvs -o+uuid,deviceid | grep $vg |tee out +grep $dev1 out |tee out1 +grep $dev2 out |tee out2 +grep $did1 out1 +grep $did2 out2 +not grep $dev3 out + +# same dev info reported after df is fixed +pvs -o+uuid,deviceid | grep $vg |tee out3 +diff out out3 + +pvid=`pvs $dev1 --noheading -o uuid | tr -d - | awk '{print $1}'` +test "$pvid" == "$pvid1" || die "wrong uuid" +pvid=`pvs $dev2 --noheading -o uuid | tr -d - | awk '{print $1}'` +test "$pvid" == "$pvid2" || die "wrong uuid" + +lvmdevices |tee out +grep $dev1 out |tee out1 +grep $pvid1 out1 +grep $did1 out1 +grep $dev2 out |tee out2 +grep $pvid2 out2 +grep $did2 out2 + +# pvscan --cache doesn't fix wrong devname but still works correctly with +# the correct device + +wipe_all +rm $DF +touch $DF +vgcreate $vg $dev1 $dev2 +vgcreate $vg3 $dev3 +lvcreate -an -n $lv1 -l1 $vg $dev1 +lvcreate -an -n $lv2 -l1 $vg $dev2 +lvcreate -an -n $lv3 -l1 $vg3 $dev3 +PVID1=`pvs $dev1 --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID2=`pvs $dev2 --noheading -o uuid | tr -d - | awk '{print $1}'` +PVID3=`pvs $dev3 --noheading -o uuid | tr -d - | awk '{print $1}'` +rm $DF +lvmdevices --adddev $dev1 +lvmdevices --adddev $dev2 +cp $DF $DF.orig +d1=$(basename $dev1) +d3=$(basename $dev3) +sed "s/$d1/$d3/" "$DF.orig" |tee $DF +_clear_online_files +pvscan --cache -aay $dev1 +pvscan --cache -aay $dev2 +# pvscan should ignore dev3 since it's not in DF +pvscan --cache -aay $dev3 +# pvscan does not fix the devname field in DF +grep $dev3 $DF +ls "$RUNDIR/lvm/pvs_online/$PVID1" +ls "$RUNDIR/lvm/pvs_online/$PVID2" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" +check lv_field $vg/$lv1 lv_active "active" +check lv_field $vg/$lv2 lv_active "active" +# pvs updates the DF +pvs |tee out +grep $dev1 out +grep $dev2 out +not grep $dev3 out +grep $dev1 $DF +grep $dev2 $DF +not grep $dev3 $DF +not pvs $dev3 +vgchange -an $vg +wipe_all + diff --git a/test/shell/devicesfile-serial.sh b/test/shell/devicesfile-serial.sh new file mode 100644 index 0000000..3123e9e --- /dev/null +++ b/test/shell/devicesfile-serial.sh @@ -0,0 +1,890 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020-23 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='device id wwid from vpd_pg83' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +test -d /sys/block/ram0 && skip "Ramdisk already loaded" + +test "$DM_DEV_DIR" = "/dev" || skip "Only works with /dev access -> make check LVM_TEST_DEVDIR=/dev" + +# requires trailing / to match dm +SYS_DIR="$PWD/test/sys" +aux lvmconf "devices/use_devicesfile = 1" \ + "devices/device_id_sysfs_dir = \"$SYS_DIR/\"" + +# The string format of the serial numbers +# encoded in the pg80 files +SERIAL1="003dd33a331c183c2300e1d883604609" +SERIAL2="003dd33a441c183c2300e1d883604609" +SERIAL3="003dd33a551c183c2300e1d883604609" +SERIAL4="003dd33a661c183c2300e1d883604609" + +create_base() { + mkdir -p "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device" + mkdir -p "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device" + mkdir -p "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device" + mkdir -p "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device" + + # Create four different pg80 serial numbers that + # can be assigned to devs + + echo -n "0080 0020 3030 3364 6433 3361 3333 3163 \ + 3138 3363 3233 3030 6531 6438 3833 3630 3436 3039" | xxd -r -p > pg80_1 + + echo -n "0080 0020 3030 3364 6433 3361 3434 3163 \ + 3138 3363 3233 3030 6531 6438 3833 3630 3436 3039" | xxd -r -p > pg80_2 + + echo -n "0080 0020 3030 3364 6433 3361 3535 3163 \ + 3138 3363 3233 3030 6531 6438 3833 3630 3436 3039" | xxd -r -p > pg80_3 + + echo -n "0080 0020 3030 3364 6433 3361 3636 3163 \ + 3138 3363 3233 3030 6531 6438 3833 3630 3436 3039" | xxd -r -p > pg80_4 +} + +remove_base() { + rm -rf "$SYS_DIR" +} + +cleanup_and_teardown() +{ + remove_base + rmmod brd + + aux teardown +} + +trap 'cleanup_and_teardown' EXIT + +modprobe brd rd_nr=4 || skip +sleep 1 +remove_base + +dev1="/dev/ram0" +dev2="/dev/ram1" +dev3="/dev/ram2" +dev4="/dev/ram3" + +devs=( "$dev1" "$dev2" "$dev3" "$dev4" ) + +DFDIR="$LVM_SYSTEM_DIR/devices" +mkdir -p "$DFDIR" || true +DF="$DFDIR/system.devices" +ORIG="$DFDIR/orig.devices" +touch "$DF" + +aux wipefs_a "${devs[@]}" + +vgcreate $vg1 "$dev1" +eval "$(pvs --noheading --nameprefixes -o major,minor,uuid "$dev1")" +MAJOR1=$LVM2_PV_MAJOR +MINOR1=$LVM2_PV_MINOR +OPVID1=$LVM2_PV_UUID +PVID1=${OPVID1//-/} + +vgcreate $vg2 "$dev2" +eval "$(pvs --noheading --nameprefixes -o major,minor,uuid "$dev2")" +MAJOR2=$LVM2_PV_MAJOR +MINOR2=$LVM2_PV_MINOR +OPVID2=$LVM2_PV_UUID +PVID2=${OPVID2//-/} + +vgcreate $vg3 "$dev3" +eval "$(pvs --noheading --nameprefixes -o major,minor,uuid "$dev3")" +MAJOR3=$LVM2_PV_MAJOR +MINOR3=$LVM2_PV_MINOR +OPVID3=$LVM2_PV_UUID +PVID3=${OPVID3//-/} + +vgcreate $vg4 "$dev4" +eval "$(pvs --noheading --nameprefixes -o major,minor,uuid "$dev4")" +MAJOR4=$LVM2_PV_MAJOR +MINOR4=$LVM2_PV_MINOR +OPVID4=$LVM2_PV_UUID +PVID4=${OPVID4//-/} + +create_base + + +# get serial number from pg80 +cp pg80_1 "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/vpd_pg80" +cp pg80_2 "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/vpd_pg80" +cp pg80_3 "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/vpd_pg80" +cp pg80_4 "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/vpd_pg80" + +grep -r "" "$SYS_DIR/dev/block/" + +declare -A serials=( ["$dev1"]=$SERIAL1 ["$dev2"]=$SERIAL2 \ + ["$dev3"]=$SERIAL3 ["$dev4"]=$SERIAL4 ) + +rm -f "$DF" + +for i in "${devs[@]}" +do + lvmdevices --adddev "$i" + grep "${serials["$i"]}" "$DF" || { + cat "$DF" + die "Cannot find ${serials["$i"]}" + } +done +cat "$DF" +cp "$DF" "$ORIG" +pvs +# run command to update metadata so deviceids are written to metadata +vgchange --addtag x $vg1 +vgchange --addtag x $vg2 +vgchange --addtag x $vg3 +vgchange --addtag x $vg4 +pvs -o uuid,deviceidtype,deviceid "$dev1" |tee out +grep "$OPVID1" out +grep sys_serial out +grep "$SERIAL1" out +pvs -o uuid,deviceidtype,deviceid "$dev2" |tee out +grep "$OPVID2" out +grep sys_serial out +grep "$SERIAL2" out + +# get serial number from device/serial + +aux wipefs_a "${devs[@]}" + +rm "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/vpd_pg80" +rm "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/vpd_pg80" +rm "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/vpd_pg80" +rm "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/vpd_pg80" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL2" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL3" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "$SERIAL4" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +pvcreate "$dev1" +pvcreate "$dev2" +pvcreate "$dev3" +pvcreate "$dev4" +grep "$SERIAL1" "$DF" +grep "$SERIAL2" "$DF" +grep "$SERIAL3" "$DF" +grep "$SERIAL4" "$DF" + +# all pvs have the same serial number + +aux wipefs_a "${devs[@]}" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +vgcreate $vg3 "$dev3" +vgcreate $vg4 "$dev4" +cp "$DF" "$ORIG" +OPVID1=$(echo $(pvs --noheading -o uuid "$dev1") ) +OPVID2=$(echo $(pvs --noheading -o uuid "$dev2") ) +OPVID3=$(echo $(pvs --noheading -o uuid "$dev3") ) +OPVID4=$(echo $(pvs --noheading -o uuid "$dev4") ) +PVID1=${OPVID1//-/} +PVID2=${OPVID2//-/} +PVID3=${OPVID3//-/} +PVID4=${OPVID4//-/} + +grep "$PVID1" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev1" out +grep "$PVID2" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev2" out +grep "$PVID3" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev3" out +grep "$PVID4" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev4" out + +pvs -o+uuid,deviceidtype,deviceid "${devs[@]}" |tee out +grep "$dev1" out +grep "$dev2" out +grep "$dev3" out +grep "$dev4" out +grep "$OPVID1" out +grep "$OPVID2" out +grep "$OPVID3" out +grep "$OPVID4" out +grep $vg1 out +grep $vg2 out +grep $vg3 out +grep $vg4 out +grep sys_serial out +grep "$SERIAL1" out + +pvs -o+uuid,deviceid "$dev1" |tee out +grep "$OPVID1" out +grep "$SERIAL1" out +grep $vg1 out + +pvs -o+uuid,deviceid "$dev2" |tee out +grep "$OPVID2" out +grep "$SERIAL1" out +grep $vg2 out + +pvs -o+uuid,deviceid "$dev3" |tee out +grep "$OPVID3" out +grep "$SERIAL1" out +grep $vg3 out + +pvs -o+uuid,deviceid "$dev4" |tee out +grep "$OPVID4" out +grep "$SERIAL1" out +grep $vg4 out + + +# all pvs have the same serial number, df devnames are stale +# edit DF to make devnames stale + +cp "$ORIG" orig +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpnm|" orig > tmp1 +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1 > tmp2 +sed -e "s|DEVNAME=tmpnm|DEVNAME=$dev2|" tmp2 > tmp3 +sed -e "s|DEVNAME=$dev3|DEVNAME=tmpnm|" tmp3 > tmp4 +sed -e "s|DEVNAME=$dev4|DEVNAME=$dev3|" tmp4 > tmp5 +sed -e "s|DEVNAME=tmpnm|DEVNAME=$dev4|" tmp5 > "$DF" +cat "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" |tee out +grep "$dev1" out |tee out1 +grep "$dev2" out |tee out2 +grep "$dev3" out |tee out3 +grep "$dev4" out |tee out4 +grep "$OPVID1" out1 +grep "$OPVID2" out2 +grep "$OPVID3" out3 +grep "$OPVID4" out4 +grep "$SERIAL1" out1 +grep "$SERIAL1" out2 +grep "$SERIAL1" out3 +grep "$SERIAL1" out4 + +grep "$PVID1" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev1" out +grep "$PVID2" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev2" out +grep "$PVID3" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev3" out +grep "$PVID4" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev4" out + +pvs -o+uuid,deviceid "$dev1"|tee out1 +pvs -o+uuid,deviceid "$dev2"|tee out2 +pvs -o+uuid,deviceid "$dev3"|tee out3 +pvs -o+uuid,deviceid "$dev4"|tee out4 +grep "$OPVID1" out1 +grep "$OPVID2" out2 +grep "$OPVID3" out3 +grep "$OPVID4" out4 + +# all pvs have the same serial number, +# dev1 and dev2 have devnames swapped, +# dev3 has stale PVID in the DF. +# lvm fixes the stale devnames but does not fix the stale PVID +# because of the duplicate serial numbers, so dev3 is not found + +cp "$ORIG" orig +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpnm|" orig > tmp1 +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1 > tmp2 +sed -e "s|PVID=$PVID4|PVID=4SqT4onBxSiv4dot0GRDPtrWqOlrOPH1|" tmp2 > "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" > out || true +cat out +not grep "$dev4" out +not grep "$OPVID4" out +grep "$dev1" out |tee out1 +grep "$dev2" out |tee out2 +grep "$dev3" out |tee out3 +grep "$OPVID1" out1 +grep "$OPVID2" out2 +grep "$OPVID3" out3 + +not pvs "$dev4" + +# dev1&2 have same serial, dev3&4 have same serial + +aux wipefs_a "${devs[@]}" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL2" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "$SERIAL2" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +vgcreate $vg3 "$dev3" +vgcreate $vg4 "$dev4" +cp "$DF" "$ORIG" +OPVID1=$(echo $(pvs --noheading -o uuid "$dev1") ) +OPVID2=$(echo $(pvs --noheading -o uuid "$dev2") ) +OPVID3=$(echo $(pvs --noheading -o uuid "$dev3") ) +OPVID4=$(echo $(pvs --noheading -o uuid "$dev4") ) +PVID1=${OPVID1//-/} +PVID2=${OPVID2//-/} +PVID3=${OPVID3//-/} +PVID4=${OPVID4//-/} + +grep "$PVID1" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev1" out +grep "$PVID2" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev2" out +grep "$PVID3" "$DF" |tee out +grep "$SERIAL2" out +grep "$dev3" out +grep "$PVID4" "$DF" |tee out +grep "$SERIAL2" out +grep "$dev4" out + +pvs -o+uuid,deviceidtype,deviceid "${devs[@]}" |tee out +grep "$dev1" out +grep "$dev2" out +grep "$dev3" out +grep "$dev4" out +grep "$OPVID1" out +grep "$OPVID2" out +grep "$OPVID3" out +grep "$OPVID4" out +grep $vg1 out +grep $vg2 out +grep $vg3 out +grep $vg4 out +grep sys_serial out +grep "$SERIAL1" out +grep "$SERIAL2" out + +pvs -o+uuid,deviceid "$dev1" |tee out +grep "$OPVID1" out +grep "$SERIAL1" out +grep $vg1 out + +pvs -o+uuid,deviceid "$dev2" |tee out +grep "$OPVID2" out +grep "$SERIAL1" out +grep $vg2 out + +pvs -o+uuid,deviceid "$dev3" |tee out +grep "$OPVID3" out +grep "$SERIAL2" out +grep $vg3 out + +pvs -o+uuid,deviceid "$dev4" |tee out +grep "$OPVID4" out +grep "$SERIAL2" out +grep $vg4 out + +# dev1&2 have serial1 and dev3&4 have serial2, swap devnames +# edit DF to make devnames stale + +cp "$ORIG" orig +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpnm|" orig > tmp1 +sed -e "s|DEVNAME=$dev3|DEVNAME=$dev1|" tmp1 > tmp2 +sed -e "s|DEVNAME=tmpnm|DEVNAME=$dev3|" tmp2 > tmp3 +sed -e "s|DEVNAME=$dev2|DEVNAME=tmpnm|" tmp3 > tmp4 +sed -e "s|DEVNAME=$dev4|DEVNAME=$dev2|" tmp4 > tmp5 +sed -e "s|DEVNAME=tmpnm|DEVNAME=$dev4|" tmp5 > "$DF" +cat "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" |tee out +grep "$dev1" out |tee out1 +grep "$dev2" out |tee out2 +grep "$dev3" out |tee out3 +grep "$dev4" out |tee out4 +grep "$OPVID1" out1 +grep "$OPVID2" out2 +grep "$OPVID3" out3 +grep "$OPVID4" out4 +grep "$SERIAL1" out1 +grep "$SERIAL1" out2 +grep "$SERIAL2" out3 +grep "$SERIAL2" out4 + +grep "$PVID1" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev1" out +grep "$PVID2" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev2" out +grep "$PVID3" "$DF" |tee out +grep "$SERIAL2" out +grep "$dev3" out +grep "$PVID4" "$DF" |tee out +grep "$SERIAL2" out +grep "$dev4" out + +pvs -o+uuid,deviceid "$dev1"|tee out1 +pvs -o+uuid,deviceid "$dev2"|tee out2 +pvs -o+uuid,deviceid "$dev3"|tee out3 +pvs -o+uuid,deviceid "$dev4"|tee out4 +grep "$OPVID1" out1 +grep "$SERIAL1" out1 +grep "$OPVID2" out2 +grep "$SERIAL1" out2 +grep "$OPVID3" out3 +grep "$SERIAL2" out3 +grep "$OPVID4" out4 +grep "$SERIAL2" out4 + + +# all devs have same serial, dev1&4 are pvs, dev2&3 are not pvs + +aux wipefs_a "${devs[@]}" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" +vgcreate $vg4 "$dev4" +cp "$DF" "$ORIG" +OPVID1=$(echo $(pvs --noheading -o uuid "$dev1") ) +OPVID4=$(echo $(pvs --noheading -o uuid "$dev4") ) +PVID1=${OPVID1//-/} +PVID4=${OPVID4//-/} + +grep "$PVID1" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev1" out +grep "$PVID4" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev4" out + +pvs -o+uuid,deviceidtype,deviceid |tee out +grep "$dev1" out +grep "$dev4" out +grep "$OPVID1" out +grep "$OPVID4" out +grep $vg1 out +grep $vg4 out +grep sys_serial out +grep "$SERIAL1" out + +pvs -o+uuid,deviceid "$dev1" |tee out +grep "$OPVID1" out +grep "$SERIAL1" out +grep $vg1 out + +not pvs -o+uuid,deviceid "$dev2" +not pvs -o+uuid,deviceid "$dev3" + +pvs -o+uuid,deviceid "$dev4" |tee out +grep "$OPVID4" out +grep "$SERIAL1" out +grep $vg4 out + +# edit DF to make devnames stale + +cp "$ORIG" orig +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev2|" orig > tmp1 +sed -e "s|DEVNAME=$dev4|DEVNAME=$dev3|" tmp1 > "$DF" +cat "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" > out || true +cat out +grep "$dev1" out |tee out1 +grep "$dev4" out |tee out4 +grep "$OPVID1" out1 +grep "$OPVID4" out4 +grep "$SERIAL1" out1 +grep "$SERIAL1" out4 + +grep "$PVID1" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev1" out +grep "$PVID4" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev4" out + +pvs -o+uuid,deviceid "$dev1"|tee out1 +pvs -o+uuid,deviceid "$dev4"|tee out4 +grep "$OPVID1" out1 +grep "$SERIAL1" out1 +grep "$OPVID4" out4 +grep "$SERIAL1" out4 + +# one pv with serial, three other non-pvs with same serial + +aux wipefs_a "${devs[@]}" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg2 "$dev2" +cp "$DF" "$ORIG" +OPVID2=$(echo $(pvs --noheading -o uuid "$dev2") ) +PVID2=${OPVID2//-/} + +grep "$PVID2" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev2" out + +pvs -o+uuid,deviceidtype,deviceid |tee out +grep "$dev2" out +grep sys_serial out +grep "$SERIAL1" out +not grep "$dev1" out +not grep "$dev3" out +not grep "$dev4" out + +# edit DF to make devname stale + +cp "$ORIG" orig +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev3|" orig > "$DF" +cat "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" > out || true +cat out +grep "$dev2" out +grep "$OPVID2" out +grep "$SERIAL1" out +grep "$dev2" "$DF" + +# different serial numbers, stale pvid and devname in df, +# lvm corrects pvid in df because serial number is unique + +aux wipefs_a "${devs[@]}" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL2" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL3" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "$SERIAL4" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +vgcreate $vg3 "$dev3" +vgcreate $vg4 "$dev4" +cp "$DF" "$ORIG" +grep "$SERIAL1" "$DF" +grep "$SERIAL2" "$DF" +grep "$SERIAL3" "$DF" +grep "$SERIAL4" "$DF" +OPVID1=$(echo $(pvs --noheading -o uuid "$dev1") ) +OPVID2=$(echo $(pvs --noheading -o uuid "$dev2") ) +OPVID3=$(echo $(pvs --noheading -o uuid "$dev3") ) +OPVID4=$(echo $(pvs --noheading -o uuid "$dev4") ) +PVID1=${OPVID1//-/} +PVID2=${OPVID2//-/} +PVID3=${OPVID3//-/} +PVID4=${OPVID4//-/} +pvs -o+uuid,deviceid "${devs[@]}" + +cp "$ORIG" orig +sed -e "s|PVID=$PVID1|PVID=bad14onBxSiv4dot0GRDPtrWqOlr1bad|" orig > tmp1 +sed -e "s|PVID=$PVID3|PVID=bad24onBxSiv4dot0GRDPtrWqOlr2bad|" tmp1 > tmp2 +sed -e "s|DEVNAME=$dev1|DEVNAME=.|" tmp2 > "$DF" +cat "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" |tee out +grep "$dev1" out |tee out1 +grep "$dev2" out |tee out2 +grep "$dev3" out |tee out3 +grep "$dev4" out |tee out4 +grep "$OPVID1" out1 +grep "$OPVID2" out2 +grep "$OPVID3" out3 +grep "$OPVID4" out4 +grep $vg1 out1 +grep $vg2 out2 +grep $vg3 out3 +grep $vg4 out4 +grep "$SERIAL1" out1 +grep "$SERIAL2" out2 +grep "$SERIAL3" out3 +grep "$SERIAL4" out4 + +grep "$PVID1" "$DF" |tee out +grep "$SERIAL1" out +grep "$dev1" out +grep "$PVID2" "$DF" |tee out +grep "$SERIAL2" out +grep "$dev2" out +grep "$PVID3" "$DF" |tee out +grep "$SERIAL3" out +grep "$dev3" out +grep "$PVID4" "$DF" |tee out +grep "$SERIAL4" out +grep "$dev4" out + +# duplicate serial on two pvs, two pvs with devname type, all devnames stale + +aux wipefs_a "${devs[@]}" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +vgcreate $vg3 "$dev3" +vgcreate $vg4 "$dev4" +cp "$DF" "$ORIG" +OPVID1=$(echo $(pvs --noheading -o uuid "$dev1") ) +OPVID2=$(echo $(pvs --noheading -o uuid "$dev2") ) +OPVID3=$(echo $(pvs --noheading -o uuid "$dev3") ) +OPVID4=$(echo $(pvs --noheading -o uuid "$dev4") ) +PVID1=${OPVID1//-/} +PVID2=${OPVID2//-/} +PVID3=${OPVID3//-/} +PVID4=${OPVID4//-/} +cat "$DF" + +pvs -o+uuid,deviceid "${devs[@]}" + +cp "$ORIG" orig +sed -e "s|DEVNAME=$dev1|DEVNAME=tmpnm|" orig > tmp1 +sed -e "s|DEVNAME=$dev3|DEVNAME=$dev1|" tmp1 > tmp2 +sed -e "s|DEVNAME=tmpnm|DEVNAME=$dev3|" tmp2 > tmp3 +sed -e "s|DEVNAME=$dev2|DEVNAME=tmpnm|" tmp3 > tmp4 +sed -e "s|DEVNAME=$dev4|DEVNAME=$dev2|" tmp4 > tmp5 +sed -e "s|DEVNAME=tmpnm|DEVNAME=$dev4|" tmp5 > "$DF" +cat "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" |tee out +grep "$dev1" out |tee out1 +grep "$dev2" out |tee out2 +grep "$dev3" out |tee out3 +grep "$dev4" out |tee out4 +grep "$OPVID1" out1 +grep "$OPVID2" out2 +grep "$OPVID3" out3 +grep "$OPVID4" out4 +grep $vg1 out1 +grep $vg2 out2 +grep $vg3 out3 +grep $vg4 out4 +grep "$SERIAL1" out1 +grep "$SERIAL1" out2 + +cat "$DF" +grep "$PVID1" "$DF" |tee out1 +grep "$PVID2" "$DF" |tee out2 +grep "$PVID3" "$DF" |tee out3 +grep "$PVID4" "$DF" |tee out4 +grep "$dev1" out1 +grep "$SERIAL1" out1 +grep "$dev2" out2 +grep "$SERIAL1" out2 +grep "$dev3" out3 +grep "$dev4" out4 + +# two pvs with duplicate serial and stale devname, one pv with unique serial and stale pvid + +aux wipefs_a "${devs[@]}" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL3" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +vgcreate $vg3 "$dev3" +cp "$DF" "$ORIG" +OPVID1=$(echo $(pvs --noheading -o uuid "$dev1") ) +OPVID2=$(echo $(pvs --noheading -o uuid "$dev2") ) +OPVID3=$(echo $(pvs --noheading -o uuid "$dev3") ) +PVID1=${OPVID1//-/} +PVID2=${OPVID2//-/} +PVID3=${OPVID3//-/} +cat "$DF" + +pvs -o+uuid,deviceid "${devs[@]}" || true + +cp "$ORIG" orig +sed -e "s|DEVNAME=$dev1|DEVNAME=$dev4|" orig > tmp1 +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1 > tmp2 +sed -e "s|PVID=$dev3|PVID=bad14onBxSiv4dot0GRDPtrWqOlr1bad|" tmp2 > "$DF" +cat "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" > out || true +cat out +grep "$dev1" out |tee out1 +grep "$dev2" out |tee out2 +grep "$dev3" out |tee out3 +grep "$OPVID1" out1 +grep "$OPVID2" out2 +grep "$OPVID3" out3 +grep $vg1 out1 +grep $vg2 out2 +grep $vg3 out3 +grep "$SERIAL1" out1 +grep "$SERIAL1" out2 +grep "$SERIAL3" out3 + +cat "$DF" +grep "$PVID1" "$DF" |tee out1 +grep "$PVID2" "$DF" |tee out2 +grep "$PVID3" "$DF" |tee out3 +grep "$dev1" out1 +grep "$SERIAL1" out1 +grep "$dev2" out2 +grep "$SERIAL1" out2 +grep "$dev3" out3 +grep "$SERIAL3" out3 + +# non-PV devices + +aux wipefs_a "${devs[@]}" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL2" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL2" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" +echo "$SERIAL4" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg4 "$dev4" +lvmdevices --adddev "$dev1" +lvmdevices --adddev "$dev2" +lvmdevices --adddev "$dev3" +cat "$DF" + +grep "$dev1" "$DF" |tee out1 +grep "$dev2" "$DF" |tee out2 +grep "$dev3" "$DF" |tee out3 +grep "$dev4" "$DF" |tee out4 + +grep "$SERIAL1" out1 +grep "$SERIAL2" out2 +grep "$SERIAL2" out3 +grep "$SERIAL4" out4 + +pvs "${devs[@]}" > out || true +cat out +grep "$dev4" out +not grep "$dev1" out +not grep "$dev2" out +not grep "$dev3" out + +pvcreate "$dev1" +pvs "${devs[@]}" > out || true +cat out +grep "$dev1" out +grep "$dev4" out +not grep "$dev2" out +not grep "$dev3" out + +pvcreate "$dev2" +pvs "${devs[@]}" > out || true +cat out +grep "$dev1" out +grep "$dev4" out +grep "$dev2" out +not grep "$dev3" out + +pvcreate "$dev3" +pvs "${devs[@]}" |tee out +grep "$dev1" out +grep "$dev4" out +grep "$dev2" out +grep "$dev3" out + +OPVID1=$(echo $(pvs --noheading -o uuid "$dev1") ) +OPVID2=$(echo $(pvs --noheading -o uuid "$dev2") ) +OPVID3=$(echo $(pvs --noheading -o uuid "$dev3") ) +OPVID4=$(echo $(pvs --noheading -o uuid "$dev4") ) +PVID1=${OPVID1//-/} +PVID2=${OPVID2//-/} +PVID3=${OPVID3//-/} +PVID4=${OPVID4//-/} + +grep "$dev1" "$DF" |tee out1 +grep "$dev2" "$DF" |tee out2 +grep "$dev3" "$DF" |tee out3 +grep "$dev4" "$DF" |tee out4 + +grep "$PVID1" out1 +grep "$PVID2" out2 +grep "$PVID3" out3 +grep "$PVID4" out4 + +vgcreate $vg2 "$dev2" "$dev3" +vgs | grep $vg2 + +# 3 devs with duplicate serial, 2 pvs with stale devnames, 1 non-pv device + +aux wipefs_a "$dev1" "$dev2" "$dev3" + +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/device/serial" +echo "$SERIAL1" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/device/serial" + +rm "$DF" +touch "$DF" +vgcreate $vg1 "$dev1" "$dev2" +lvmdevices --adddev "$dev3" +cat "$DF" +cp "$DF" "$ORIG" + +OPVID1=$(echo $(pvs --noheading -o uuid "$dev1") ) +OPVID2=$(echo $(pvs --noheading -o uuid "$dev2") ) +PVID1=${OPVID1//-/} +PVID2=${OPVID2//-/} + +pvs -o+uuid,deviceid "${devs[@]}" || true + +sed -e "s|DEVNAME=$dev1|DEVNAME=tmp|" "$ORIG" > tmp1 +sed -e "s|DEVNAME=$dev2|DEVNAME=$dev1|" tmp1 > tmp2 +sed -e "s|DEVNAME=tmp|DEVNAME=$dev2|" tmp2 > "$DF" +cat "$DF" + +# pvs should report the correct info and fix the DF +pvs -o+uuid,deviceid "${devs[@]}" > out || true +cat out +grep "$dev1" out |tee out1 +grep "$dev2" out |tee out2 +grep "$OPVID1" out1 +grep "$OPVID2" out2 +grep "$SERIAL1" out1 +grep "$SERIAL1" out2 diff --git a/test/shell/devicesfile-vpd-ids.sh b/test/shell/devicesfile-vpd-ids.sh new file mode 100644 index 0000000..9a12f49 --- /dev/null +++ b/test/shell/devicesfile-vpd-ids.sh @@ -0,0 +1,436 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='device id wwid from vpd_pg83' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +test "$DM_DEV_DIR" = "/dev" || skip "Only works with /dev access -> make check LVM_TEST_DEVDIR=/dev" + +aux lvmconf 'devices/use_devicesfile = 1' +# requires trailing / to match dm +aux lvmconf 'devices/device_id_sysfs_dir = "/test/sys/"' +SYS_DIR="/test/sys" + +# These values match the values encoded in the binary blob +# written to dev1_vpd_pg83 +DEV1_NAA=naa.600a098038303877413f4e7049592e6e +DEV1_EUI=eui.3f4e7049592d6f0000a0973730387741 +DEV1_T10=t10.LVMTST_LUN_809wALVMTSTo +# dev has a second naa wwid +DEV1_NAA2=naa.600a098000000002ac18542400000dbd +# dev has a third naa wwid in the scsi name field +DEV1_NAA3=naa.553b13644430344b4e3f486d32647962 + +create_base() { + mkdir -p $SYS_DIR/dev/block + + echo -n "0083 009c 0201 0020 4c56 4d54 5354 2020 \ + 204c 554e 2038 3039 7741 4c56 4d54 5354 \ + 6f20 2020 2020 2020 0103 0010 600a 0980 \ + 3830 3877 413f 4e70 4959 2e6e 0102 0010 \ + 3f4e 7049 592d 6f00 00a0 9737 3038 7741 \ + 0113 0010 600a 0980 0000 0002 ac18 5424 \ + 0000 0dbd 0114 0004 0101 0005 0115 0004 \ + 0000 03ec 0328 0028 6e61 612e 3535 3342 \ + 3133 3634 3434 3330 3334 3442 3445 3346 \ + 3438 3644 3332 3634 3739 3632 0000 0000" | xxd -r -p > $SYS_DIR/dev1_vpd_pg83 +} + +remove_base() { + rm $SYS_DIR/dev1_vpd_pg83 + rmdir $SYS_DIR/dev/block + rmdir $SYS_DIR/dev + rmdir $SYS_DIR +} + +setup_sysfs() { + mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device + echo $1 > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + cp $SYS_DIR/dev1_vpd_pg83 $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/vpd_pg83 +} + +cleanup_sysfs() { + rm -f $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid + rm -f $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/vpd_pg83 + rmdir $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device || true + rmdir $SYS_DIR/dev/block/$MAJOR1:$MINOR1 || true +} + + +modprobe scsi_debug dev_size_mb=16 num_tgts=1 +sleep 2 +# Get scsi device name created by scsi_debug. +# SD = sdh +# DEV1 = /dev/sdh +SD=$(grep -H scsi_debug /sys/block/sd*/device/model | cut -f4 -d /); +echo $SD +DEV1=/dev/$SD +echo $DEV1 + +DFDIR="$LVM_SYSTEM_DIR/devices" +mkdir -p "$DFDIR" || true +DF="$DFDIR/system.devices" +DFTMP="$DFDIR/system.devices_tmp" +touch $DF + +pvcreate "$DEV1" +vgcreate $vg "$DEV1" +MAJOR1=`pvs "$DEV1" --noheading -o major | tr -d - | awk '{print $1}'` +MINOR1=`pvs "$DEV1" --noheading -o minor | tr -d - | awk '{print $1}'` +PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` + +create_base + +# No sys/wwid, lvm uses wwid from sys/vpd + +setup_sysfs $DEV1_NAA +# no sys/wwid is reported +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +rm $DF +lvmdevices --adddev "$DEV1" +cat $DF +pvs "$DEV1" +grep $DEV1_NAA $DF +cleanup_sysfs + +# Kernel changes the type printed from sys/wwid from t10 to naa +# after lvm has used sys_wwid with the t10 value. +# set sys/wwid to t10 value +# add dev to df, it uses t10 value +# change sys/wwid to naa value +# reporting pvs should still find the dev based on using vpd data +# and find the t10 value there + +setup_sysfs $DEV1_T10 +rm $DF +lvmdevices --adddev "$DEV1" +cat $DF +grep sys_wwid $DF +grep $DEV1_T10 $DF +pvs "$DEV1" +# kernel changes what it reports from sys/wwid +echo $DEV1_NAA > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +# lvm finds the original t10 id in vpd +pvs "$DEV1" +cleanup_sysfs + +# User chooses wwid type other than is printed from sys/wwid +# set sys/wwid to t10|naa|eui value +# lvmdevices --adddev using --deviceidtype different from sys/wwid +# df entry uses the specified type +# reporting pvs should show the pv + +setup_sysfs $DEV1_T10 +rm $DF +lvmdevices --adddev "$DEV1" --deviceidtype wwid_naa +cat $DF +grep wwid_naa $DF +grep $DEV1_NAA $DF +pvs "$DEV1" +lvmdevices --deldev "$DEV1" +lvmdevices --addpvid "$PVID1" --deviceidtype wwid_naa +cat $DF +grep $DEV1_NAA $DF +pvs "$DEV1" +lvmdevices --deldev "$DEV1" +lvmdevices --adddev "$DEV1" --deviceidtype wwid_eui +cat $DF +grep wwid_eui $DF +grep $DEV1_EUI $DF +pvs "$DEV1" +cleanup_sysfs + +# Any of the vpd wwids can be used in the devices file +# with type sys_wwid and the device will be matched to +# it by finding that wwid in the vpd data. + +setup_sysfs $DEV1_NAA +rm $DF +lvmdevices --adddev "$DEV1" +cat $DF +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +pvs "$DEV1" +cleanup_sysfs + +setup_sysfs $DEV1_NAA2 +rm $DF +lvmdevices --adddev "$DEV1" +cat $DF +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +pvs "$DEV1" +cleanup_sysfs + +setup_sysfs $DEV1_NAA3 +rm $DF +lvmdevices --adddev "$DEV1" +cat $DF +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +pvs "$DEV1" +cleanup_sysfs + +setup_sysfs $DEV1_EUI +rm $DF +lvmdevices --adddev "$DEV1" +cat $DF +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +pvs "$DEV1" +cleanup_sysfs + +setup_sysfs $DEV1_T10 +rm $DF +lvmdevices --adddev "$DEV1" +cat $DF +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +pvs "$DEV1" +cleanup_sysfs + +# Test nvme wwid that starts with "nvme" instead of naa/eui/t10 +rm $DF +aux wipefs_a "$DEV1" +mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/ +echo "nvme.111111111111111111122222222222333333333333333-44444444444444444445555555555556666666666666666662-00000001" > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid +lvmdevices --adddev "$DEV1" +cat $DF +vgcreate $vg "$DEV1" +lvcreate -l1 -an $vg +cat $DF +pvs -o+deviceidtype,deviceid "$DEV1" |tee out +grep sys_wwid out +grep nvme.111 out +grep sys_wwid $DF +grep nvme.111 $DF +lvmdevices --deldev "$DEV1" +not lvmdevices --adddev "$DEV1" --deviceidtype wwid_eui +lvmdevices --adddev "$DEV1" --deviceidtype sys_wwid +lvmdevices | grep nvme.111 +lvremove -y $vg +sleep 1 +lvs $vg +vgremove $vg +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/wwid +cleanup_sysfs + +# Test t10 wwid containing quote +rm $DF +aux wipefs_a "$DEV1" +mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device +echo "t10.ATA_2.5\"_SATA_SSD_1112-A___111111111111" > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +lvmdevices --adddev "$DEV1" +cat $DF +vgcreate $vg "$DEV1" +lvcreate -l1 -an $vg +cat $DF +# check wwid string in metadata output +pvs -o+deviceidtype,deviceid "$DEV1" |tee out +grep sys_wwid out +# the quote is removed after the 5 +grep 2.5_SATA_SSD out +# check wwid string in system.devices +grep sys_wwid $DF +# the quote is removed after the 5 +grep 2.5_SATA_SSD $DF +lvremove -y $vg +vgremove $vg +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cleanup_sysfs + +# Test t10 wwid with trailing space and line feed at the end +rm $DF +aux wipefs_a "$DEV1" +mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device +echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ +2048 4152 4444 4953 4b20 2020 2020 2020 \ +2020 2020 2020 2020 2020 2020 2020 2020 \ +2020 2020 5642 3963 3130 6433 3138 2d31 \ +3838 6439 6562 6320 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +lvmdevices --adddev "$DEV1" +cat $DF +vgcreate $vg "$DEV1" +lvcreate -l1 -an $vg +cat $DF +# check wwid string in metadata output +pvs -o+deviceidtype,deviceid "$DEV1" |tee out +grep sys_wwid out +# check wwid string in system.devices +grep sys_wwid $DF +lvremove -y $vg +vgremove $vg +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cleanup_sysfs + +# Test t10 wwid with trailing space at the end that was created by 9.0/9.1 +rm $DF +aux wipefs_a "$DEV1" +mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device +echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ +2048 4152 4444 4953 4b20 2020 2020 2020 \ +2020 2020 2020 2020 2020 2020 2020 2020 \ +2020 2020 5642 3963 3130 6433 3138 2d31 \ +3838 6439 6562 6320 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +lvmdevices --adddev "$DEV1" +cat $DF +vgcreate $vg "$DEV1" +PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` +T10_WWID_RHEL91="t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9ebc_" +lvcreate -l1 -an $vg +cat $DF +# check wwid string in metadata output +pvs -o+deviceidtype,deviceid "$DEV1" |tee out +grep sys_wwid out +# check wwid string in system.devices +grep sys_wwid $DF +# Replace IDNAME with the IDNAME that 9.0/9.1 created from this wwid +cat $DF | grep -v IDNAME > $DFTMP +cat $DFTMP +echo "IDTYPE=sys_wwid IDNAME=t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9ebc_ DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP +cp $DFTMP $DF +cat $DF +vgs +pvs +pvs -o+deviceidtype,deviceid "$DEV1" +# Removing the trailing _ which should then work +cat $DF | grep -v IDNAME > $DFTMP +cat $DFTMP +echo "IDTYPE=sys_wwid IDNAME=t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9ebc DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP +cp $DFTMP $DF +cat $DF +vgs +pvs +pvs -o+deviceidtype,deviceid "$DEV1" +lvremove -y $vg +vgremove $vg +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cleanup_sysfs + +# test a t10 wwid that has actual trailing underscore which +# is followed by a trailing space. +rm $DF +aux wipefs_a "$DEV1" +mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device +echo -n "7431 302e 4154 4120 2020 2020 5642 4f58 \ +2048 4152 4444 4953 4b20 2020 2020 2020 \ +2020 2020 2020 2020 2020 2020 2020 2020 \ +2020 2020 5642 3963 3130 6433 3138 2d31 \ +3838 6439 6562 5f20 0a" | xxd -r -p > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cat $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +# The wwid has an actual underscore char (5f) followed by a space char (20) +# 9.1 converts the trailing space to an underscore +T10_WWID_RHEL91="t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9eb__" +# 9.2 ignores the trailing space +T10_WWID_RHEL92="t10.ATA_____VBOX_HARDDISK___________________________VB9c10d318-188d9eb_" +lvmdevices --adddev "$DEV1" +cat $DF +vgcreate $vg "$DEV1" +PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` +lvcreate -l1 -an $vg +cat $DF +# check wwid string in metadata output +pvs -o+deviceidtype,deviceid "$DEV1" |tee out +grep sys_wwid out +# check wwid string in system.devices +grep sys_wwid $DF +# Replace IDNAME with the IDNAME that 9.0/9.1 created from this wwid +cat $DF | grep -v IDNAME > $DFTMP +cat $DFTMP +echo "IDTYPE=sys_wwid IDNAME=${T10_WWID_RHEL91} DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP +cp $DFTMP $DF +cat $DF +vgs +pvs +pvs -o+deviceidtype,deviceid "$DEV1" +lvremove -y $vg +vgremove $vg +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cleanup_sysfs + +# +# Test trailing/leading/center spaces in sys_wwid and sys_serial device +# ids, and that old system.devices files that have trailing/leading +# underscores are understood. +# + +rm $DF +aux wipefs_a "$DEV1" +mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device +echo -n " s123 456 " > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial +lvmdevices --adddev "$DEV1" +cat $DF +grep "IDNAME=s123__456 DEVNAME" $DF +vgcreate $vg "$DEV1" +PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` +cat $DF | grep -v IDNAME > $DFTMP +cat $DFTMP +echo "IDTYPE=sys_serial IDNAME=__s123__456__ DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP +cp $DFTMP $DF +cat $DF +vgs +pvs -o+deviceidtype,deviceid "$DEV1" +lvremove -y $vg +vgremove $vg +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/serial +cleanup_sysfs + +rm $DF +aux wipefs_a "$DEV1" +mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device +echo -n " t10.123 456 " > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +lvmdevices --adddev "$DEV1" +cat $DF +grep "IDNAME=t10.123_456 DEVNAME" $DF +vgcreate $vg "$DEV1" +PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` +cat $DF | grep -v IDNAME > $DFTMP +cat $DFTMP +echo "IDTYPE=sys_wwid IDNAME=__t10.123__456__ DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP +cp $DFTMP $DF +cat $DF +vgs +pvs -o+deviceidtype,deviceid "$DEV1" +lvremove -y $vg +vgremove $vg +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cleanup_sysfs + +rm $DF +aux wipefs_a "$DEV1" +mkdir -p $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device +echo -n " naa.123 456 " > $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +lvmdevices --adddev "$DEV1" +cat $DF +grep "IDNAME=naa.123__456 DEVNAME" $DF +vgcreate $vg "$DEV1" +PVID1=`pvs "$DEV1" --noheading -o uuid | tr -d - | awk '{print $1}'` +cat $DF | grep -v IDNAME > $DFTMP +cat $DFTMP +echo "IDTYPE=sys_wwid IDNAME=__naa.123__456__ DEVNAME=${DEV1} PVID=${PVID1}" >> $DFTMP +cp $DFTMP $DF +cat $DF +vgs +pvs -o+deviceidtype,deviceid "$DEV1" +lvremove -y $vg +vgremove $vg +rm $SYS_DIR/dev/block/$MAJOR1:$MINOR1/device/wwid +cleanup_sysfs + + + + +# TODO: lvmdevices --adddev --deviceidtype --deviceid +# This would let the user specify the second naa wwid. + +remove_base +rmmod scsi_debug || true diff --git a/test/shell/discards-thin.sh b/test/shell/discards-thin.sh index 84688b4..213f713 100644 --- a/test/shell/discards-thin.sh +++ b/test/shell/discards-thin.sh @@ -1,6 +1,6 @@ -#!/bin/sh +#!/usr/bin/env bash -# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +# Copyright (C) 2012-2013 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 @@ -8,43 +8,89 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # test support of thin discards # -. lib/test + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest # # Main # aux have_thin 1 1 0 || skip -aux prepare_pvs 2 64 +aux prepare_vg 2 64 +get_devs -vgcreate $vg -s 64K $(cat DEVICES) +aux extend_filter_LVMTEST # Create named pool only lvcreate -l1 --discards ignore -T $vg/pool check lv_field $vg/pool discards "ignore" +check lv_field $vg/pool kernel_discards "ignore" lvcreate -l1 --discards nopassdown -T $vg/pool1 check lv_field $vg/pool1 discards "nopassdown" +check lv_field $vg/pool1 kernel_discards "nopassdown" lvcreate -l1 --discards passdown -T $vg/pool2 check lv_field $vg/pool2 discards "passdown" +check lv_field $vg/pool2 discards "passdown" lvchange --discards nopassdown $vg/pool2 -# cannot convert active ignore -> passdown +lvcreate -V1M -n origin -T $vg/pool +lvcreate -s $vg/origin -n snap + +# Cannot convert active nopassdown -> ignore +not lvchange --discards nopassdown $vg/pool + +# Cannot convert active ignore -> passdown not lvchange --discards passdown $vg/pool -# cannot convert active nopassdown -> ignore +# Cannot convert active nopassdown -> ignore not lvchange --discards ignore $vg/pool1 -# deactivate +# Deactivate pool only lvchange -an $vg/pool $vg/pool1 + +# Cannot convert, since thin volumes are still active +not lvchange --discards passdown $vg/pool + +# Deactive thin volumes +lvchange -an $vg/origin $vg/snap + lvchange --discards passdown $vg/pool check lv_field $vg/pool discards "passdown" + lvchange --discards ignore $vg/pool1 check lv_field $vg/pool1 discards "ignore" vgremove -ff $vg + +# Create thin pool with discards set to "ignore". +# If we create a thin volume which we use for a PV +# which we use to create another thin pool on top +# with discards set to "passdown", the discards value +# in metadata is still "passdown", but because the +# device below does not support it, the kernel value +# of discards actually used will be "nopassdown". +# This is why we have "-o discards" and "-o kernel_discards". +vgcreate $SHARED -s 1m "${vg}_1" "${DEVICES[@]}" +lvcreate -l 10 -T ${vg}_1/pool --discards ignore +lvcreate -V 9m -T ${vg}_1/pool -n device_with_ignored_discards +vgcreate $SHARED -s 1m ${vg}_2 "$DM_DEV_DIR/${vg}_1/device_with_ignored_discards" +lvcreate -l 1 -T ${vg}_2/pool --discards passdown +lvcreate -V 1 -T ${vg}_2/pool +check lv_field ${vg}_1/pool discards "ignore" +check lv_field ${vg}_1/pool kernel_discards "ignore" +check lv_field ${vg}_2/pool discards "passdown" +check lv_field ${vg}_2/pool kernel_discards "nopassdown" + +vgremove -ff ${vg}_2 +vgremove -ff ${vg}_1 diff --git a/test/shell/dmeventd-restart.sh b/test/shell/dmeventd-restart.sh index fa9db46..0def8c1 100644 --- a/test/shell/dmeventd-restart.sh +++ b/test/shell/dmeventd-restart.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,45 +8,59 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_dmeventd aux prepare_vg 5 -lvcreate -m 3 --ig -L 1 -n 4way $vg +lvcreate -aey --type mirror -m 3 --nosync --ignoremonitoring -l1 -n 4way $vg lvchange --monitor y $vg/4way -lvcreate -m 2 --ig -L 1 -n 3way $vg +lvcreate -aey --type mirror -m 2 --nosync --ignoremonitoring -l1 -n 3way $vg lvchange --monitor y $vg/3way +lvcreate -aey -l1 -n $lv1 $vg +lvcreate -s -l1 -n $lv2 $vg/$lv1 + dmeventd -R -f & echo $! >LOCAL_DMEVENTD sleep 2 # wait a bit, so we talk to the new dmeventd later +check lv_field $vg/3way seg_monitor "monitored" +check lv_field $vg/4way seg_monitor "monitored" lvchange --monitor y --verbose $vg/3way 2>&1 | tee lvchange.out -grep 'already monitored' lvchange.out +# only non-cluster tests can check command result +test -e LOCAL_CLVMD || grep 'already monitored' lvchange.out lvchange --monitor y --verbose $vg/4way 2>&1 | tee lvchange.out -grep 'already monitored' lvchange.out +test -e LOCAL_CLVMD || grep 'already monitored' lvchange.out # now try what happens if no dmeventd is running -kill -9 $(cat LOCAL_DMEVENTD) -rm LOCAL_DMEVENTD +kill -9 "$(< LOCAL_DMEVENTD)" +rm LOCAL_DMEVENTD debug.log* dmeventd -R -f & echo $! >LOCAL_DMEVENTD # wait longer as tries to communicate with killed daemon -sleep 7 +sleep 9 # now dmeventd should not be running not pgrep dmeventd rm LOCAL_DMEVENTD -# set dmeventd path -aux lvmconf "dmeventd/executable=\"$abs_top_builddir/test/lib/dmeventd\"" +# First lvs restarts 'dmeventd' (initiate a socket connection to a daemon) +check lv_field $vg/3way seg_monitor "not monitored" +pgrep -o dmeventd >LOCAL_DMEVENTD +check lv_field $vg/4way seg_monitor "not monitored" + lvchange --monitor y --verbose $vg/3way 2>&1 | tee lvchange.out -pgrep dmeventd >LOCAL_DMEVENTD -not grep 'already monitored' lvchange.out +test -e LOCAL_CLVMD || not grep 'already monitored' lvchange.out + +lvchange --monitor y --verbose $vg/$lv2 2>&1 | tee lvchange.out +test -e LOCAL_CLVMD || not grep 'already monitored' lvchange.out vgremove -ff $vg diff --git a/test/shell/dmsecuretest.sh b/test/shell/dmsecuretest.sh new file mode 100644 index 0000000..609fc7c --- /dev/null +++ b/test/shell/dmsecuretest.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test secure table is not leaking data in user land + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +# AES key matching rot13 string from dmsecuretest.c */ +SECURE="434e0cbab02ca68ffba9268222c3789d703fe62427b78b308518b3228f6a2122" + +. lib/inittest + +DMTEST="${PREFIX}-test-secure" + +# Test needs installed gdb package with gcore app +which gcore || skip + +aux driver_at_least 4 6 || skip + +# ensure we can create devices (uses dmsetup, etc) +aux prepare_devs 1 + +# check both code versions - linked libdm and internal device_mapper version +# there should not be any difference +for i in securetest dmsecuretest ; do + +# 1st. try with empty table +# 2nd. retry with already exiting DM node - exercize error path also wipes +for j in empty existing ; do + +"$i" "$dev1" "$DMTEST" >cmdout 2>&1 & +PID=$! +sleep .5 + +# crypt device should be loaded +dmsetup status "$DMTEST" + +# generate core file for running&sleeping binary +gcore "$PID" | tee out || skip + +# check we capture core while dmsecuretest was already sleeping +grep "nanosleep" out || grep kernel_vsyscall out +kill "$PID" || true +wait + +cat cmdout + +# $SECURE string must NOT be present in core file +not grep "$SECURE" "core.$PID" || { + ## cp "core.$PID" /dev/shm/core + rm -f "core.$PID" + should dmsetup remove "$DMTEST" # go around weird bugs + die "!!! Secure string $SECURE found present in core.$PID !!!" +} +rm -f "core.$PID" + +if test "$j" = empty ; then + not grep "Device or resource busy" cmdout +else + # Device should be already present resulting into error message + grep "Device or resource busy" cmdout + dmsetup remove "$DMTEST" +fi + +done + +done diff --git a/test/shell/dmsetup-integrity-keys.sh b/test/shell/dmsetup-integrity-keys.sh new file mode 100644 index 0000000..cd98ead --- /dev/null +++ b/test/shell/dmsetup-integrity-keys.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# unrelated to lvm2 daemons +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +INTERNAL_HASH_CRYPT="hmac(sha256)" +INTERNAL_HASH_NOCRYPT=crc32 +JOURNAL_CRYPT="ctr(aes)" +HEXKEY_32=0102030405060708090a0102030405060102030405060708090a010203040506 +HEXKEY2_32=0102030405060708090a010203040b060102030405060708090a010203040506 +HIDENKEY_32=0000000000000000000000000000000000000000000000000000000000000000 + +aux target_at_least dm-integrity 1 0 0 || skip "missing dm-integrity target" +aux target_at_least dm-zero 1 0 0 || skip "missing dm-zero target" + +function _teardown() { + aux teardown_devs_prefixed "$PREFIX" +} + +trap '_teardown' EXIT + +dmsetup create "$PREFIX-zero" --table "0 10000 zero" +dmsetup create "$PREFIX-integrity" --table "0 7856 integrity $DM_DEV_DIR/mapper/$PREFIX-zero 0 32 J 7 journal_sectors:88 interleave_sectors:32768 buffer_sectors:128 journal_watermark:50 commit_time:10000 internal_hash:$INTERNAL_HASH_NOCRYPT journal_crypt:$JOURNAL_CRYPT:$HEXKEY_32" + +str=$(dmsetup table "$PREFIX-integrity" | cut -d ' ' -f 15) +test "$str" = "journal_crypt:$JOURNAL_CRYPT:$HIDENKEY_32" +str=$(dmsetup table --showkeys "$PREFIX-integrity" | cut -d ' ' -f 15) +test "$str" = "journal_crypt:$JOURNAL_CRYPT:$HEXKEY_32" +str=$(dmsetup table "$PREFIX-integrity" | cut -d ' ' -f 14) +test "$str" = "internal_hash:$INTERNAL_HASH_NOCRYPT" + +dmsetup remove "$PREFIX-integrity" +dmsetup create "$PREFIX-integrity" --table "0 7856 integrity $DM_DEV_DIR/mapper/$PREFIX-zero 0 32 J 7 journal_sectors:88 interleave_sectors:32768 buffer_sectors:128 journal_watermark:50 commit_time:10000 internal_hash:$INTERNAL_HASH_CRYPT:$HEXKEY2_32 journal_crypt:$JOURNAL_CRYPT:$HEXKEY_32" + +str=$(dmsetup table "$PREFIX-integrity" | cut -d ' ' -f 15) +test "$str" = "journal_crypt:$JOURNAL_CRYPT:$HIDENKEY_32" +str=$(dmsetup table --showkeys "$PREFIX-integrity" | cut -d ' ' -f 15) +test "$str" = "journal_crypt:$JOURNAL_CRYPT:$HEXKEY_32" +str=$(dmsetup table "$PREFIX-integrity" | cut -d ' ' -f 14) +test "$str" = "internal_hash:$INTERNAL_HASH_CRYPT:$HIDENKEY_32" +str=$(dmsetup table --showkeys "$PREFIX-integrity" | cut -d ' ' -f 14) +test "$str" = "internal_hash:$INTERNAL_HASH_CRYPT:$HEXKEY2_32" + +dmsetup remove "$PREFIX-integrity" +dmsetup remove "$PREFIX-zero" diff --git a/test/shell/dmsetup-keyring.sh b/test/shell/dmsetup-keyring.sh new file mode 100644 index 0000000..3c0b867 --- /dev/null +++ b/test/shell/dmsetup-keyring.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# unrelated to lvm2 daemons +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +CIPHER=aes-xts-plain64 +HEXKEY_32=0102030405060708090a0102030405060102030405060708090a010203040506 +HIDENKEY_32=0000000000000000000000000000000000000000000000000000000000000000 +KEY_NAME="$PREFIX:keydesc" + +function _teardown() { + keyctl unlink "%:$PREFIX-keyring" + aux teardown_devs_prefixed "$PREFIX" +} + +aux target_at_least dm-zero 1 0 0 || skip "missing dm-zero target" +aux target_at_least dm-crypt 1 15 0 || skip "dm-crypt doesn't support keys in kernel keyring service" +which keyctl || skip "test requires keyctl utility" + +keyctl new_session || true # fails with 'su', works with 'su -' +keyctl newring "$PREFIX-keyring" @s +keyctl timeout "%:$PREFIX-keyring" 60 + +trap '_teardown' EXIT + +keyctl add logon "$KEY_NAME" "${HEXKEY_32:0:32}" "%:$PREFIX-keyring" + +dmsetup create "$PREFIX-zero" --table "0 1 zero" +# put key in kernel keyring for active table +dmsetup create "$PREFIX-crypt" --table "0 1 crypt $CIPHER :32:logon:$KEY_NAME 0 $DM_DEV_DIR/mapper/$PREFIX-zero 0" +# put hexbyte key in dm-crypt directly in inactive table +dmsetup load "$PREFIX-crypt" --table "0 1 crypt $CIPHER $HEXKEY_32 0 $DM_DEV_DIR/mapper/$PREFIX-zero 0" + +# test dmsetup doesn't hide key descriptions... +str=$(dmsetup table "$PREFIX-crypt" | cut -d ' ' -f 5) +test "$str" = ":32:logon:$KEY_NAME" +str=$(dmsetup table --showkeys "$PREFIX-crypt" | cut -d ' ' -f 5) +test "$str" = ":32:logon:$KEY_NAME" + +# ...but it hides hexbyte representation of keys... +str=$(dmsetup table --inactive "$PREFIX-crypt" | cut -d ' ' -f 5) +test "$str" = "$HIDENKEY_32" +#...unless --showkeys explictly requested +str=$(dmsetup table --showkeys --inactive "$PREFIX-crypt" | cut -d ' ' -f 5) +test "$str" = "$HEXKEY_32" + +# let's swap the tables +dmsetup resume "$PREFIX-crypt" +dmsetup load "$PREFIX-crypt" --table "0 1 crypt $CIPHER :32:logon:$KEY_NAME 0 $DM_DEV_DIR/mapper/$PREFIX-zero 0" + +str=$(dmsetup table --inactive "$PREFIX-crypt" | cut -d ' ' -f 5) +test "$str" = ":32:logon:$KEY_NAME" +str=$(dmsetup table --showkeys --inactive "$PREFIX-crypt" | cut -d ' ' -f 5) +test "$str" = ":32:logon:$KEY_NAME" + +str=$(dmsetup table "$PREFIX-crypt" | cut -d ' ' -f 5) +test "$str" = "$HIDENKEY_32" +str=$(dmsetup table --showkeys "$PREFIX-crypt" | cut -d ' ' -f 5) +test "$str" = "$HEXKEY_32" + +dmsetup remove "$PREFIX-crypt" +dmsetup remove "$PREFIX-zero" diff --git a/test/shell/dmstats-create.sh b/test/shell/dmstats-create.sh new file mode 100644 index 0000000..03406ae --- /dev/null +++ b/test/shell/dmstats-create.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +# Don't attempt to test stats with driver < 4.33.00 +aux driver_at_least 4 33 || skip + +# ensure we can create devices (uses dmsetup, etc) +aux prepare_devs 1 + +# basic dmstats create commands + +dmstats create "$dev1" +dmstats create --start 0 --len 1 "$dev1" +dmstats create --segments "$dev1" +dmstats create --precise "$dev1" +dmstats create --bounds 10ms,20ms,30ms "$dev1" diff --git a/test/shell/dmstats-report.sh b/test/shell/dmstats-report.sh new file mode 100644 index 0000000..bd72f1a --- /dev/null +++ b/test/shell/dmstats-report.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +# Don't attempt to test stats with driver < 4.33.00 +aux driver_at_least 4 33 || skip + +# ensure we can create devices (uses dmsetup, etc) +aux prepare_devs 1 + +# prepare a stats region with a histogram +dmstats create --bounds 10ms,20ms,30ms "$dev1" + +# basic dmstats report commands +dmstats report +dmstats report --count 1 +dmstats report --histogram diff --git a/test/shell/dumpconfig.sh b/test/shell/dumpconfig.sh index a16f753..abd4b62 100644 --- a/test/shell/dumpconfig.sh +++ b/test/shell/dumpconfig.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,13 +8,16 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest flatten() { cat > flatten.config - for s in `egrep '^[a-z]+ {$' flatten.config | sed -e s,{$,,`; do + for s in $(grep -E '^[a-z]+ {$' flatten.config | sed -e 's,{$,,'); do sed -e "/^$s/,/^}/p;d" flatten.config | sed -e '1d;$d' | sed -e "s,^[ \t]*,$s/,"; done } diff --git a/test/shell/duplicate-pvs-md0.sh b/test/shell/duplicate-pvs-md0.sh new file mode 100644 index 0000000..ea800cf --- /dev/null +++ b/test/shell/duplicate-pvs-md0.sh @@ -0,0 +1,308 @@ +#!/usr/bin/env bash + +# Copyright (C) 2012-2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +HINTS="$RUNDIR/lvm/hints" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* "$VGS_ONLINE_DIR"/* +} + +. lib/inittest + +MD_LEVEL=${MD_LEVEL-0} + +aux prepare_devs 4 10 + +# Create an unused PV so that there is at least one PV in the hints +# when the MD dev is stopped. If there are no PVs, the hints are +# empty, and the code falls back to scanning all, and we do not end +# up testing the code with hints actively used. +pvcreate "$dev3" + +## Test variations: +# PV on md raid1|raid0, md_component_checks auto|start, mddev start|stopped, +# one raid dev disabled when mddev is stopped. + +# LVM will ask udev if a dev is an md component, but we don't +# want to rely on that ability in this test so stops lvm from +# asking udev if a dev is an md component. +aux lvmconf "devices/obtain_device_list_from_udev = 0" \ + "devices/md_component_detection = 1" \ + "devices/md_component_checks = \"auto\"" + +aux extend_filter_md "a|/dev/md|" + +# Run in 2 passes - 1st. with "auto" 2nd. with "start" component checks +for pass in "auto" "start" ; do + +########################################## +# PV on an md raidX device +# md_component_checks: auto|start (not start) +# mddev: started (not stopped) +# +aux mdadm_create --metadata=1.0 --level="$MD_LEVEL" --chunk=64 --raid-devices=2 "$dev1" "$dev2" +mddev=$(< MD_DEV) +lvmdevices --adddev $mddev || true + +pvcreate "$mddev" +PVIDMD=$(get pv_field "$mddev" uuid | tr -d - ) +vgcreate $vg "$mddev" +lvcreate -n $lv1 -l 2 -an $vg + +# pvs shows only the md dev as PV +pvs "$mddev" +not pvs "$dev1" +not pvs "$dev2" +pvs | tee out +grep "$mddev" out +not grep "$dev1" out +not grep "$dev2" out +# N.B. in this case hints are disabled for duplicate pvs seen by scan +# it would be preferrable if this didn't happen as in auto mode, but it's ok. +test "$pass" = "auto" && grep "$mddev" "$HINTS" +not grep "$dev1" "$HINTS" +not grep "$dev2" "$HINTS" + +# normal activation works +lvchange -ay $vg/$lv1 +check active $vg $lv1 +vgchange -an $vg + +# pvscan activation all works +_clear_online_files +pvscan --cache -aay +test -e "$RUNDIR/lvm/pvs_online/$PVIDMD" +test -e "$RUNDIR/lvm/vgs_online/$vg" +check active $vg $lv1 +vgchange -an $vg + +# pvscan activation from mddev works +_clear_online_files +pvscan --cache -aay "$mddev" +test -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test -f "$RUNDIR/lvm/vgs_online/$vg" +check active $vg $lv1 +vgchange -an $vg + +# pvscan activation from md components does nothing +_clear_online_files +pvscan --cache -aay "$dev1" +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +if [ "$pass" = "auto" ] ; then + pvscan --cache -aay "$dev2" + test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" + test ! -f "$RUNDIR/lvm/vgs_online/$vg" +fi +# N.B. with raid0 the component because the PV/size difference +# triggers and md component check, whereas with raid1 it doesn't. +check inactive $vg $lv1 + +vgchange -an $vg +vgremove -f $vg +lvmdevices --deldev $mddev || true +aux cleanup_md_dev + + +########################################## +# PV on an md raidX device +# md_component_checks: auto|start +# mddev: stopped (not started) +# + +aux mdadm_create --metadata=1.0 --level="$MD_LEVEL" --chunk=64 --raid-devices=2 "$dev1" "$dev2" +mddev=$(< MD_DEV) +lvmdevices --adddev $mddev || true + +pvcreate "$mddev" +PVIDMD=$(get pv_field "$mddev" uuid | tr -d - ) +vgcreate $vg "$mddev" +lvcreate -n $lv1 -l 2 -an $vg + +mdadm --stop "$mddev" +cat /proc/mdstat + +# pvs does not show the PV +not pvs "$mddev" +not pvs "$dev1" +not pvs "$dev2" +pvs | tee out +not grep "$mddev" out +# N.B. it would be preferrable if dev1 did not appear in hints but it's ok +# not grep "$dev1" $HINTS +not grep "$dev1" out +not grep "$dev2" out +pvscan --cache +not grep "$mddev" "$HINTS" +not grep "$dev1" "$HINTS" +not grep "$dev2" "$HINTS" + +# the vg is not seen, normal activation does nothing +not lvchange -ay $vg/$lv1 +not lvs $vg + +# pvscan activation all does nothing +_clear_online_files +pvscan --cache -aay +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +# pvscan activation from md components does nothing +_clear_online_files +pvscan --cache -aay "$dev1" +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" +pvscan --cache -aay "$dev2" +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +#lvs -o active $vg |tee out || true +#not grep "active" out + +aux wipefs_a "$dev1" "$dev2" + +########################################## +# PV on an md raidX device +# md_component_checks: auto|start +# mddev: stopped (not started) +# only one raid dev online +# + +aux mdadm_create --metadata=1.0 --level="$MD_LEVEL" --chunk=64 --raid-devices=2 "$dev1" "$dev2" +mddev=$(< MD_DEV) +lvmdevices --adddev $mddev || true + +pvcreate "$mddev" +PVIDMD=$(get pv_field "$mddev" uuid | tr -d - ) +vgcreate $vg "$mddev" +lvcreate -n $lv1 -l 2 -an $vg + +mdadm --stop "$mddev" +cat /proc/mdstat + +# disable one leg +aux disable_dev "$dev2" + +# pvs does not show the PV +not pvs "$mddev" +not pvs "$dev1" +not pvs "$dev2" +pvs | tee out +not grep "$mddev" out +not grep "$dev1" out +not grep "$dev2" out +pvscan --cache +not grep "$mddev" "$HINTS" +# N.B. would be preferrable for this md component to not be in hints +# grep "$dev1" $HINTS +not grep "$dev1" "$HINTS" +not grep "$dev2" "$HINTS" + +# the vg is not seen, normal activation does nothing +not lvchange -ay $vg/$lv1 +not lvs $vg + +# pvscan activation all does nothing +_clear_online_files +pvscan --cache -aay +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +# pvscan activation from md components does nothing +_clear_online_files +pvscan --cache -aay "$dev1" +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" +pvscan --cache -aay "$dev2" +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +aux enable_dev "$dev2" +lvmdevices --deldev $mddev || true +aux cleanup_md_dev + +aux wipefs_a "$dev1" "$dev2" + +if [ "$MD_LEVEL" = "1" ] ; then +########################################## +# PV on an md raid1 device, auto+stopped +# md_component_checks: auto|start +# mddev: stopped (not started) +# three raid images +# +aux mdadm_create --metadata=1.0 --level="$MD_LEVEL" --chunk=64 --raid-devices=3 "$dev1" "$dev2" "$dev4" +mddev=$(< MD_DEV) +lvmdevices --adddev $mddev || true + +pvcreate "$mddev" +PVIDMD=$(get pv_field "$mddev" uuid | tr -d - ) +vgcreate $vg "$mddev" +lvcreate -n $lv1 -l 2 -an $vg + +mdadm --stop "$mddev" +cat /proc/mdstat + +# pvs does not show the PV +not pvs "$mddev" +not pvs "$dev1" +not pvs "$dev2" +not pvs "$dev4" +pvs | tee out +not grep "$mddev" out +not grep "$dev1" out +not grep "$dev2" out +not grep "$dev4" out +pvscan --cache +not grep "$mddev" "$HINTS" +not grep "$dev1" "$HINTS" +not grep "$dev2" "$HINTS" +not grep "$dev4" "$HINTS" + +# the vg is not seen, normal activation does nothing +not lvchange -ay $vg/$lv1 +not lvs $vg + +# pvscan activation all does nothing +_clear_online_files +pvscan --cache -aay +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +# pvscan activation from md components does nothing +_clear_online_files +pvscan --cache -aay "$dev1" +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" +pvscan --cache -aay "$dev2" +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" +pvscan --cache -aay "$dev4" +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +aux wipefs_a "$dev1" "$dev2" "$dev4" +fi # MD_LEVEL == 1 + +# next loop with 'start' +test "$pass" != "auto" || aux lvmconf "devices/md_component_checks = \"start\"" + +done diff --git a/test/shell/duplicate-pvs-md1.sh b/test/shell/duplicate-pvs-md1.sh new file mode 100644 index 0000000..e896c10 --- /dev/null +++ b/test/shell/duplicate-pvs-md1.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Copyright (C) 2012-2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# . different PV/VG's that happen to have the same PVID +# . a single PV/VG cloned to another device +# . dm wrapper around a PV +# . a single PV/VG cloned plus a dm wrapper (two separate dups of a PV) + + +# Reuse same test just use raid level 1 +export MD_LEVEL=1 +. ./shell/duplicate-pvs-md0.sh diff --git a/test/shell/duplicate-pvs-multipath.sh b/test/shell/duplicate-pvs-multipath.sh new file mode 100644 index 0000000..bc98d2d --- /dev/null +++ b/test/shell/duplicate-pvs-multipath.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='duplicate pv detection of mpath components using wwid' + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +# FIXME: skip until mpath/scsi_debug cleanup works after a failure +skip + +modprobe --dry-run scsi_debug || skip +multipath -l || skip +multipath -l | grep scsi_debug && skip + +# FIXME: setting multipath_component_detection=0 now also disables +# the wwid-based mpath component detection, so this test will need +# to find another way to disable only the filter-mpath code (using +# sysfs and multipath/wwids) while keeping the code enabled that +# eliminates duplicates based on their matching wwids which this +# tries to test. + +# Prevent wwids from being used for filtering. +aux lvmconf 'devices/multipath_wwids_file = "/dev/null"' +# Need to use /dev/mapper/mpath +aux lvmconf 'devices/dir = "/dev"' +aux lvmconf 'devices/scan = "/dev"' +# Could set filter to $MP and the component /dev/sd devs +aux lvmconf "devices/filter = [ \"a|.*|\" ]" +aux lvmconf "devices/global_filter = [ \"a|.*|\" ]" + +modprobe scsi_debug dev_size_mb=100 num_tgts=1 vpd_use_hostno=0 add_host=4 delay=20 max_luns=2 no_lun_0=1 +sleep 2 + +multipath -r +sleep 2 + +MPB=$(multipath -l | grep scsi_debug | cut -f1 -d ' ') +echo $MPB +MP=/dev/mapper/$MPB +echo $MP + +pvcreate $MP +vgcreate $vg1 $MP +lvcreate -l1 $vg1 +vgchange -an $vg1 + +pvs |tee out +grep $MP out +for i in $(grep -H scsi_debug /sys/block/sd*/device/model | cut -f4 -d /); do + not grep /dev/$i out; +done + +vgchange -an $vg1 +vgremove -y $vg1 + +sleep 2 +multipath -f $MP +sleep 1 +rmmod scsi_debug diff --git a/test/shell/duplicate-vgid.sh b/test/shell/duplicate-vgid.sh new file mode 100644 index 0000000..12163c2 --- /dev/null +++ b/test/shell/duplicate-vgid.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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. + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 2 + +vgcreate $vg1 "$dev1" +vgchange --setautoactivation n $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +lvcreate -l1 -an -n $lv1 $vg1 +dd if="$dev1" of="$dev2" bs=1M count=1 +aux disable_dev "$dev1" +vgrename $vg1 $vg2 +pvchange -u "$dev2" +aux enable_dev "$dev1" + +vgs -o+uuid |tee out +grep $vg1 out | tee out1 +grep $UUID1 out1 +grep $vg2 out | tee out2 +grep $UUID1 out2 + +vgs $vg1 +vgs $vg2 +lvs $vg1/$lv1 +lvs $vg2/$lv1 + +lvremove $vg1/$lv1 +lvremove $vg2/$lv1 + +lvcreate -l1 -an -n $lv2 $vg1 +lvcreate -l1 -an -n $lv3 $vg2 + +vgchange -u $vg2 + +vgs -o uuid $vg1 |tee out +grep $UUID1 out + +vgs -o uuid $vg2 |tee out +not grep $UUID1 out + +vgremove -ff $vg1 +vgremove -ff $vg2 diff --git a/test/shell/duplicate-vgnames.sh b/test/shell/duplicate-vgnames.sh new file mode 100644 index 0000000..b3f2c43 --- /dev/null +++ b/test/shell/duplicate-vgnames.sh @@ -0,0 +1,624 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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. + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 7 + +# test setups: +# # local vgs named foo # foreign vg named foo +# a. 0 1 +# b. 0 2 +# c. 1 1 +# d. 1 2 +# e. 2 0 +# f. 2 1 +# g. 2 2 +# h. 3 3 +# +# commands to run for each test setup: +# +# vgs +# all cases show all local +# +# vgs --foreign +# all cases show all local and foreign +# +# vgs foo +# a. not found +# b. not found +# c. show 1 local +# d. show 1 local +# e-g. dup error +# +# vgs --foreign foo +# a. show 1 foreign +# b. dup error +# c. show 1 local +# d. show 1 local +# e-g. dup error +# +# vgchange -ay +# a. none +# b. none +# c. activate 1 local +# d. activate 1 local +# e-g. activate 2 local +# (if both local vgs have lvs with same name the second will fail to activate) +# +# vgchange -ay foo +# a. none +# b. none +# c. activate 1 local +# d. activate 1 local +# e-g. dup error +# +# lvcreate foo +# a. none +# b. none +# c. create 1 local +# d. create 1 local +# e-g. dup error +# +# vgremove foo +# a. none +# b. none +# c. remove 1 local +# d. remove 1 local +# e-g. dup error +# (in a couple cases test that vgremove -S vg_uuid=N works for local vg when local dups exist) + + +# a. 0 local, 1 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 + +vgs -o+uuid |tee out +not grep $vg1 out +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out + +not vgs -o+uuid $vg1 |tee out +not grep $vg1 out +vgs --foreign -o+uuid $vg1 |tee out +grep $vg1 out + +vgchange -ay +lvs --foreign -o vguuid,active |tee out +not grep active out +vgchange -an + +not vgchange -ay $vg1 +lvs --foreign -o vguuid,active |tee out +not grep active out +vgchange -an + +not lvcreate -l1 -an -n $lv2 $vg1 +lvs --foreign -o vguuid,name |tee out +grep $UUID1 out | not grep $lv2 + +not vgremove $vg1 +vgs --foreign -o+uuid |tee out +grep $UUID1 out +vgremove -y -S vg_uuid=$UUID1 +vgs --foreign -o+uuid |tee out +grep $UUID1 out + +aux wipefs_a "$dev1" "$dev2" + +# b. 0 local, 2 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n $lv1 -l1 -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other2" $vg1 +aux enable_dev "$dev1" + +vgs -o+uuid |tee out +not grep $vg1 out +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out + +not vgs -o+uuid $vg1 |tee out +not grep $vg1 out +not vgs --foreign -o+uuid $vg1 |tee out +not grep $vg1 out + +vgchange -ay +lvs --foreign -o vguuid,active |tee out +not grep active out +vgchange -an + +not vgchange -ay $vg1 +lvs --foreign -o vguuid,active |tee out +not grep active out +vgchange -an + +not lvcreate -l1 -an -n $lv2 $vg1 +lvs --foreign -o vguuid,name |tee out +grep $UUID1 out | not grep $lv2 +grep $UUID2 out | not grep $lv2 + +not vgremove $vg1 +vgs --foreign -o+uuid |tee out +grep $UUID1 out + +aux wipefs_a "$dev1" "$dev2" "$dev3" + +# c. 1 local, 1 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n $lv1 -l1 -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux enable_dev "$dev1" + +vgs -o+uuid |tee out +cat out +grep $vg1 out +grep $UUID1 out +not grep $UUID2 out +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out + +vgs -o+uuid $vg1 |tee out +grep $vg1 out +grep $UUID1 out +not grep $UUID2 out +vgs --foreign -o+uuid $vg1 |tee out +grep $vg1 out +grep $UUID1 out +not grep $UUID2 out + +vgchange -ay +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | grep active +grep $UUID2 out | not grep active +vgchange -an + +vgchange -ay $vg1 +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | grep active +grep $UUID2 out | not grep active +vgchange -an + +lvcreate -l1 -an -n $lv2 $vg1 +lvs --foreign -o vguuid,name |tee out +grep $UUID1 out | grep $lv2 +grep $UUID2 out | not grep $lv2 + +vgremove -y $vg1 +vgs -o+uuid |tee out +not grep $UUID1 out +vgs --foreign -o+uuid |tee out +grep $UUID2 out + +aux wipefs_a "$dev1" "$dev2" "$dev3" + +# d. 1 local, 2 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n $lv1 -l1 -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux disable_dev "$dev2" +vgcreate $vg1 "$dev3" +lvcreate -n $lv1 -l1 -an $vg1 +UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other2" $vg1 +aux enable_dev "$dev1" "$dev2" + +vgs -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +not grep $UUID2 out +not grep $UUID3 out +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out + +vgs -o+uuid $vg1 |tee out +grep $vg1 out +grep $UUID1 out +not grep $UUID2 out +not grep $UUID3 out +vgs --foreign -o+uuid $vg1 |tee out +grep $vg1 out +grep $UUID1 out +not grep $UUID2 out +not grep $UUID3 out + +vgchange -ay +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | grep active +grep $UUID2 out | not grep active +grep $UUID3 out | not grep active +vgchange -an + +vgchange -ay $vg1 +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | grep active +grep $UUID2 out | not grep active +grep $UUID3 out | not grep active +vgchange -an + +lvcreate -l1 -an -n $lv2 $vg1 +lvs --foreign -o vguuid,name |tee out +grep $UUID1 out | grep $lv2 +grep $UUID2 out | not grep $lv2 +grep $UUID3 out | not grep $lv2 + +vgremove -y $vg1 +vgs -o+uuid |tee out +not grep $UUID1 out +vgs --foreign -o+uuid |tee out +grep $UUID2 out +grep $UUID3 out + +aux wipefs_a "$dev1" "$dev2" "$dev3" "$dev4" + +# e. 2 local, 0 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +# diff lvname to prevent clash in vgchange -ay +lvcreate -n ${lv1}_b -l1 -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux enable_dev "$dev1" + +vgs -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out + +not vgs -o+uuid $vg1 |tee out +not grep $vg1 out +not vgs --foreign -o+uuid $vg1 |tee out +not grep $vg1 out + +vgchange -ay +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | grep active +grep $UUID2 out | grep active +vgchange -an + +not vgchange -ay $vg1 +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | not grep active +grep $UUID2 out | not grep active +vgchange -an + +not lvcreate -l1 -an -n $lv2 $vg1 +lvs --foreign -o vguuid,name |tee out +grep $UUID1 out | not grep $lv2 +grep $UUID2 out | not grep $lv2 + +not vgremove $vg1 +vgs -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +vgremove -y -S vg_uuid=$UUID1 +vgs -o+uuid |tee out +not grep $UUID1 out +grep $UUID2 out +vgremove -y -S vg_uuid=$UUID2 +vgs -o+uuid |tee out +not grep $UUID1 out +not grep $UUID2 out + +aux wipefs_a "$dev1" "$dev2" "$dev3" + +# f. 2 local, 1 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +# diff lvname to prevent clash in vgchange -ay +lvcreate -n ${lv1}_b -l1 -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev2" +vgcreate $vg1 "$dev3" +lvcreate -n $lv1 -l1 -an $vg1 +UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux enable_dev "$dev1" "$dev2" + +vgs -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +not group $UUID3 out +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out + +not vgs -o+uuid $vg1 |tee out +not grep $vg1 out +not vgs --foreign -o+uuid $vg1 |tee out +not grep $vg1 out + +vgchange -ay +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | grep active +grep $UUID2 out | grep active +grep $UUID3 out | not grep active +vgchange -an + +not vgchange -ay $vg1 +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | not grep active +grep $UUID2 out | not grep active +grep $UUID3 out | not grep active +vgchange -an + +not lvcreate -l1 -an -n $lv2 $vg1 +lvs --foreign -o vguuid,name |tee out +grep $UUID1 out | not grep $lv2 +grep $UUID2 out | not grep $lv2 +grep $UUID3 out | not grep $lv2 + +not vgremove $vg1 +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +vgremove -y -S vg_uuid=$UUID1 +vgs --foreign -o+uuid |tee out +not grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +vgremove -y -S vg_uuid=$UUID2 +vgs --foreign -o+uuid |tee out +not grep $UUID1 out +not grep $UUID2 out +grep $UUID3 out + +aux wipefs_a "$dev1" "$dev2" "$dev3" "$dev4" + +# g. 2 local, 2 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +# diff lvname to prevent clash in vgchange -ay +lvcreate -n ${lv1}_b -l1 -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev2" +vgcreate $vg1 "$dev3" +lvcreate -n $lv1 -l1 -an $vg1 +UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux disable_dev "$dev3" +vgcreate $vg1 "$dev4" +lvcreate -n $lv1 -l1 -an $vg1 +UUID4=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other2" $vg1 +aux enable_dev "$dev1" "$dev2" "$dev3" + +vgs -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +not group $UUID3 out +not group $UUID4 out +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +grep $UUID4 out + +not vgs -o+uuid $vg1 |tee out +not grep $vg1 out +not vgs --foreign -o+uuid $vg1 |tee out +not grep $vg1 out + +vgchange -ay +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | grep active +grep $UUID2 out | grep active +grep $UUID3 out | not grep active +grep $UUID4 out | not grep active +vgchange -an + +not vgchange -ay $vg1 +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | not grep active +grep $UUID2 out | not grep active +grep $UUID3 out | not grep active +grep $UUID4 out | not grep active +vgchange -an + +not lvcreate -l1 -an -n $lv2 $vg1 +lvs --foreign -o vguuid,name |tee out +grep $UUID1 out | not grep $lv2 +grep $UUID2 out | not grep $lv2 +grep $UUID3 out | not grep $lv2 +grep $UUID4 out | not grep $lv2 + +not vgremove $vg1 +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +grep $UUID4 out + +aux wipefs_a "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + +# h. 3 local, 3 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +# diff lvname to prevent clash in vgchange -ay +lvcreate -n ${lv1}_b -l1 -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev2" +vgcreate $vg1 "$dev3" +# diff lvname to prevent clash in vgchange -ay +lvcreate -n ${lv1}_bb -l1 -an $vg1 +UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev3" +vgcreate $vg1 "$dev4" +lvcreate -n $lv1 -l1 -an $vg1 +UUID4=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux disable_dev "$dev4" +vgcreate $vg1 "$dev5" +lvcreate -n $lv1 -l1 -an $vg1 +UUID5=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other2" $vg1 +aux disable_dev "$dev5" +vgcreate $vg1 "$dev6" +lvcreate -n $lv1 -l1 -an $vg1 +UUID6=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other3" $vg1 +aux enable_dev "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + +vgs -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +not group $UUID4 out +not group $UUID5 out +not group $UUID6 out +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +grep $UUID4 out +grep $UUID5 out +grep $UUID6 out + +not vgs -o+uuid $vg1 |tee out +not grep $vg1 out +not vgs --foreign -o+uuid $vg1 |tee out +not grep $vg1 out + +vgchange -ay +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | grep active +grep $UUID2 out | grep active +grep $UUID3 out | grep active +grep $UUID4 out | not grep active +grep $UUID5 out | not grep active +grep $UUID6 out | not grep active +vgchange -an + +not vgchange -ay $vg1 +lvs --foreign -o vguuid,active |tee out +grep $UUID1 out | not grep active +grep $UUID2 out | not grep active +grep $UUID3 out | not grep active +grep $UUID4 out | not grep active +grep $UUID5 out | not grep active +grep $UUID6 out | not grep active +vgchange -an + +not lvcreate -l1 -an -n $lv2 $vg1 +lvs --foreign -o vguuid,name |tee out +grep $UUID1 out | not grep $lv2 +grep $UUID2 out | not grep $lv2 +grep $UUID3 out | not grep $lv2 +grep $UUID4 out | not grep $lv2 +grep $UUID5 out | not grep $lv2 +grep $UUID6 out | not grep $lv2 + +not vgremove $vg1 +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +grep $UUID4 out +grep $UUID5 out +grep $UUID6 out + +aux wipefs_a "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" + +# vgreduce test with 1 local and 1 foreign vg. +# setup +vgcreate $vg1 "$dev1" "$dev7" +lvcreate -n $lv1 -l1 -an $vg1 "$dev1" +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +PV1UUID=$(pvs --noheading -o uuid "$dev1") +PV7UUID=$(pvs --noheading -o uuid "$dev7") +aux disable_dev "$dev1" "$dev7" +vgcreate $vg1 "$dev2" +PV2UUID=$(pvs --noheading -o uuid "$dev2") +lvcreate -n $lv1 -l1 -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux enable_dev "$dev1" "$dev7" + +vgs --foreign -o+uuid |tee out +grep $vg1 out +grep $UUID1 out +grep $UUID2 out +pvs --foreign -o+uuid |tee out +grep $PV1UUID out +grep $PV7UUID out +grep $PV2UUID out + +vgreduce $vg1 "$dev7" + +pvs --foreign -o+uuid |tee out +grep $PV1UUID out +grep $PV7UUID out +grep $PV2UUID out + +grep $PV7UUID out >out2 +not grep $vg1 out2 + +vgremove -ff $vg1 diff --git a/test/shell/duplicate-vgrename.sh b/test/shell/duplicate-vgrename.sh new file mode 100644 index 0000000..2d6f169 --- /dev/null +++ b/test/shell/duplicate-vgrename.sh @@ -0,0 +1,304 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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. + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 4 + +# a. 0 local, 1 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 + +not vgrename $vg1 $vg2 +vgs --foreign -o+uuid |tee out +grep $UUID1 out +not vgrename $UUID1 $vg2 +vgs --foreign -o+uuid |tee out +grep $UUID1 out + +lvs --foreign + +aux wipefs_a "$dev1" + +# b. 0 local, 2 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other2" $vg1 +aux enable_dev "$dev1" + +not vgrename $vg1 $vg2 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +not grep $vg2 out +grep $UUID1 out +grep $UUID2 out +not vgrename $UUID1 $vg2 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +not grep $vg2 out +grep $UUID1 out +grep $UUID2 out + +lvs --foreign + +aux wipefs_a "$dev1" "$dev2" + +# c. 1 local, 1 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux enable_dev "$dev1" + +vgrename $vg1 $vg2 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out +not vgrename $vg2 $vg1 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out + +lvs --foreign + +aux wipefs_a "$dev1" "$dev2" + +# d. 1 local, 2 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux disable_dev "$dev2" +vgcreate $vg1 "$dev3" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other2" $vg1 +aux enable_dev "$dev1" "$dev2" + +vgrename $vg1 $vg2 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +not vgrename $vg2 $vg1 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out + +lvs --foreign + +aux wipefs_a "$dev1" "$dev2" "$dev3" + +# e. 2 local, 0 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n ${lv1}_b -l1 -ky -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux enable_dev "$dev1" + +not vgrename $vg1 $vg2 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +not grep $vg2 out +grep $UUID1 out +grep $UUID2 out +vgrename $UUID1 $vg2 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out +not vgrename $UUID2 $vg2 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out + +lvs --foreign + +aux wipefs_a "$dev1" "$dev2" + +# f. 2 local, 1 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n ${lv1}_b -l1 -ky -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev2" +vgcreate $vg1 "$dev3" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs) +vgchange -y --systemid "other" $vg1 +aux enable_dev "$dev1" "$dev2" +lvs --foreign + +not vgrename $vg1 $vg2 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +not grep $vg2 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +vgrename $UUID1 $vg2 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +vgrename $vg1 $vg3 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $vg3 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +not vgrename $vg2 $vg1 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $vg3 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +not vgrename $vg2 $vg3 +vgs --foreign -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $vg3 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out + +lvs --foreign + +aux wipefs_a "$dev1" "$dev2" "$dev3" + +# g. 3 local, 0 foreign +# setup +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l1 -ky -an $vg1 +UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +lvcreate -n ${lv1}_b -l1 -ky -an $vg1 +UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux disable_dev "$dev2" +vgcreate $vg1 "$dev3" +lvcreate -n ${lv1}_c -l1 -ky -an $vg1 +UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs) +aux enable_dev "$dev1" "$dev2" + +not vgrename $vg1 $vg2 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +not grep $vg2 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +vgrename $UUID1 $vg2 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +not vgrename $vg1 $vg2 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +not vgrename $vg1 $vg3 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +not grep $vg3 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +not vgrename $UUID2 $vg2 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +not grep $vg3 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out +vgrename $UUID2 $vg3 +vgs -o+uuid |tee out +lvs --foreign +grep $vg1 out +grep $vg2 out +grep $vg3 out +grep $UUID1 out +grep $UUID2 out +grep $UUID3 out + +lvs --foreign diff --git a/test/shell/error-usage.sh b/test/shell/error-usage.sh new file mode 100644 index 0000000..bc9f30a --- /dev/null +++ b/test/shell/error-usage.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Basic usage of zero target + + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 1 + +lvcreate --type error -L1 -n $lv1 $vg +lvextend -L+1 $vg/$lv1 + +# has to match + +check lv_field $vg/$lv1 lv_modules "error" +check lv_field $vg/$lv1 segtype "error" +check lv_field $vg/$lv1 seg_count "1" +check lv_field $vg/$lv1 seg_size_pe "4" # 4 * 512 => 2M + +# FIXME should we print info we are ignoring stripping? +lvextend -L+1 -I64 -i2 $vg/$lv1 + +# We support mixing error with zero & linear targets +lvextend -L+1 --type zero $vg/$lv1 +lvextend -L+1 --type linear $vg/$lv1 +lvextend -L+1 --type striped $vg/$lv1 +lvextend -L+1 --type error $vg/$lv1 + +# 4 segments: error 3m, zero 1m, linear 2m, error 1m +lvs -o+segtype,seg_size $vg +check lv_field $vg/$lv1 seg_count "4" +check lv_field $vg/$lv1 size "7.00m" + +vgremove -ff $vg diff --git a/test/shell/exported.sh b/test/shell/exported.sh new file mode 100644 index 0000000..18a8646 --- /dev/null +++ b/test/shell/exported.sh @@ -0,0 +1,209 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Check what is and is not permitted on an exported VG/PV + +aux prepare_devs 3 +get_devs + +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" + +lvcreate -l1 -n $lv1 -an $vg1 +lvcreate -l1 -n $lv2 -an $vg2 + +vgchange --addtag aa $vg1 +lvchange --addtag bb $vg1/$lv1 + +# vgexport only when no lvs are active +lvchange -ay $vg1/$lv1 +not vgexport $vg1 +lvchange -an $vg1/$lv1 + +vgexport $vg1 + +lvm fullreport |tee out +grep $vg1 out + +lvm fullreport $vg1 |tee out +grep $vg1 out + +not lvchange -ay $vg1 +not lvchange -ay $vg1/$lv1 +not lvchange --addtag bar $vg1/$lv1 +not lvchange --monitor y $vg1/$lv1 + +not lvconvert --type mirror $vg1/$lv1 + +not lvcreate -l1 $vg1 + +not lvdisplay $vg1 + +lvdisplay 2>&1|tee out +not grep $vg1 out + +not lvextend -l+1 $vg1/$lv1 + +lvmdiskscan 2>&1|tee foo +grep "$dev1" foo + +not lvreduce -l-1 $vg1/$lv1 + +not lvremove $vg1 +not lvremove $vg1/$lv1 + +not lvrename $vg1 $lv1 $lv2 + +not lvresize --size 1M $vg1/$lv1 + +not lvs $vg1 + +lvs 2>&1|tee out +not grep $vg1 out + +lvscan 2>&1|tee out +not grep $vg1 out + +not pvchange --addtag cc "$dev1" +pvs -o+tags "$dev1" 2>&1|tee out +grep "$dev1" out +not grep cc out + +pvs -osize "$dev1" > before +not pvresize --setphysicalvolumesize 100M "$dev1" +pvs -osize "$dev1" > after +diff before after + +pvck "$dev1" +pvck --dump headers "$dev1" > out +grep "label_header at 512" out + +not pvcreate "$dev1" + +pvdisplay "$dev1" 2>&1|tee out +grep "$dev1" out + +not pvmove "$dev1" + +not pvremove "$dev1" + +pvs "$dev1" 2>&1|tee out +grep "$dev1" out + +pvscan 2>&1|tee out +grep "$dev1" out + +pvscan --cache 2>&1|tee out +grep "$dev1" out + +vgcfgbackup $vg1 + +vgcfgrestore $vg1 + +not vgchange -ay $vg1 +not vgchange --addtag asdf $vg1 +not vgchange --monitor y $vg1 + +not vgck $vg1 + +not vgcreate $vg1 "$dev3" + +vgdisplay $vg1 2>&1|tee out +grep $vg1 out + +not vgexport $vg1 + +vgexport $vg2 +not lvcreate -l1 -n $lv3 -an $vg2 +vgimport $vg2 +lvcreate -l1 -n $lv3 -an $vg2 +lvremove $vg2/$lv3 + +not vgextend $vg1 "$dev3" + +not vgmerge $vg1 $vg2 + +not vgmknodes $vg1 + +not vgreduce --removemissing $vg1 + +not vgremove $vg1 + +vgrename $vg1 $vg3 +vgrename $vg3 $vg1 + +vgs $vg1 2>&1|tee out +grep $vg1 out + +vgscan 2>&1|tee out +grep $vg1 out + +# pvscan --cache tracks online state of exported PVs, +# but autoactivation should not activate LVs. +pvscan --cache -aay "$dev1" +vgimport $vg1 +check inactive $vg1 $lv1 +vgexport $vg1 + +# using a tag does not give access to exported vg +lvchange -ay @foo +vgimport $vg1 +check inactive $vg1 $lv1 +vgexport $vg1 + +# using select does not give access to exported vg +lvchange -ay --select lvname=$lv1 +vgimport $vg1 +check inactive $vg1 $lv1 +vgexport $vg1 + +# tag or select do not work with vgremove on exported vg +vgremove @foo +vgs $vg1 +vgremove --select vgname=$vg1 +vgs $vg1 + +# exported vg is skipped without error when not named +vgchange -ay +vgimport $vg1 +check inactive $vg1 $lv1 +vgexport $vg1 + +# exported vg is skipped without error when not named +vgchange --addtag newtag +vgs -o tags $vg1 > out +not grep newtag out +vgchange --deltag aa +vgs -o tags $vg1 > out +grep aa out + +# exported vg is skipped without error when not named +vgchange --monitor y +vgchange --monitor n + +vgimport $vg1 +vgextend $vg1 "$dev3" +vgexport $vg1 + +not vgreduce $vg1 "$dev3" + +not vgsplit $vg1 "$vg3" "$dev3" + +# For vgimportclone see vgimportclone.sh + +vgimport $vg1 +vgremove -ff $vg1 +vgremove -ff $vg2 diff --git a/test/shell/fsadm-crypt-fsresize.sh b/test/shell/fsadm-crypt-fsresize.sh new file mode 100644 index 0000000..da56886 --- /dev/null +++ b/test/shell/fsadm-crypt-fsresize.sh @@ -0,0 +1,625 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Exercise fsadm filesystem resize on crypt devices' + +SKIP_WITH_LVMPOLLD=1 + +# FIXME: cannot use brd (ramdisk) - lsblk is NOT listing it +# so lsblk usage should be replaced +export LVM_TEST_PREFER_BRD=0 + +. lib/inittest + +aux prepare_vg 1 1100 + +# Tests require a libblkid version that shows FSLASTBLOCK +which mkfs.ext4 || skip + +lvcreate -n $lv1 -L 100 $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep FSLASTBLOCK || skip +lvchange -an $vg +lvremove $vg/$lv1 + +# set to "skip" to avoid testing given fs and test warning result +# i.e. check_reiserfs=skip +check_ext2= +check_ext3= +check_xfs= +check_reiserfs= +check_cryptsetup= +DROP_SYMLINK= + +CRYPT_NAME="$PREFIX-tcrypt" +CRYPT_DEV="$DM_DEV_DIR/mapper/$CRYPT_NAME" + +CRYPT_NAME2="$PREFIX-tcrypt2" +CRYPT_DEV2="$DM_DEV_DIR/mapper/$CRYPT_NAME2" + +CRYPT_NAME_PLAIN="$PREFIX-tcryptp" +CRYPT_DEV_PLAIN="$DM_DEV_DIR/mapper/$CRYPT_NAME_PLAIN" + +FORMAT_PARAMS="-i1" +PWD1="93R4P4pIqAH8" +PWD2="mymJeD8ivEhE" +PWD3="ocMakf3fAcQO" +SKIP_DETACHED= + +if which cryptsetup ; then + # use older format luks1 - otherwise the test would need to pass password everywhere... + case $(cryptsetup --version) in + "cryptsetup 2"*) FORMAT_PARAMS="$FORMAT_PARAMS --type luks1" ;; + esac +else + check_cryptsetup=${check_cryptsetup:-cryptsetup} +fi + +which mkfs.ext2 || check_ext2=${check_ext2:-mkfs.ext2} +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 || { + which xfs_repair || check_xfs=${check_xfs:-xfs_repair} +} +grep xfs /proc/filesystems || check_xfs=${check_xfs:-no_xfs} + +which mkfs.reiserfs || check_reiserfs=${check_reiserfs:-mkfs.reiserfs} +which reiserfsck || check_reiserfs=${check_reiserfs:-reiserfsck} +modprobe reiserfs || true +grep reiserfs /proc/filesystems || check_reiserfs=${check_reiserfs:-no_reiserfs} + +vg_lv=$vg/$lv1 +vg_lv2=$vg/${lv1}bar +vg_lv3=$vg/${lv1}plain +dev_vg_lv="$DM_DEV_DIR/$vg_lv" +dev_vg_lv2="$DM_DEV_DIR/$vg_lv2" +dev_vg_lv3="$DM_DEV_DIR/$vg_lv3" +mount_dir="mnt" + +test ! -d "$mount_dir" && mkdir "$mount_dir" + +crypt_close() { + aux udev_wait + cryptsetup remove "$1" + if [ "$?" -eq 0 ] && [ -n "$DROP_SYMLINK" ]; then + rm -f "$DM_DEV_DIR/mapper/$1" + fi +} + +cleanup_mounted_and_teardown() +{ + umount "$mount_dir" || true + crypt_close $CRYPT_NAME > /dev/null 2>&1 || true + crypt_close $CRYPT_NAME2 > /dev/null 2>&1 || true + crypt_close $CRYPT_NAME_PLAIN > /dev/null 2>&1 || true + aux teardown +} + +fscheck_ext3() +{ + fsck.ext3 -p -F -f "$1" +} + +fscheck_xfs() +{ + if which xfs_repair ; then + xfs_repair -n "$1" + else + xfs_check "$1" + fi +} + +fscheck_reiserfs() +{ + reiserfsck --check -p -f "$1" /dev/null || skip +check_missing cryptsetup || skip + +vgchange -s 128k +lvcreate -n $lv1 -L25M $vg +lvcreate -n ${lv1}bar -L335M $vg +lvcreate -n ${lv1}plain -L335M $vg +create_crypt_device +trap 'cleanup_mounted_and_teardown' EXIT + + +# $1 LVM backend (vg/lv name) +# $2 LVM backend device (/dev/vg/lv) +# $3 active dm-crypt device (/dev/mapper/some_name ) +test_ext2_resize() { + mkfs.ext2 -b4096 -j "$3" + + fsadm --lvresize resize $1 30M + # Fails - not enough space for 4M fs + not fsadm -y --lvresize resize "$2" 4M + lvresize -L+10M --fs resize $1 + lvreduce -L10M --fs resize $1 + + fscheck_ext3 "$3" + mount "$3" "$mount_dir" + not fsadm -y --lvresize resize $1 4M + echo n | not lvresize -L4M --fs resize -n $1 + lvresize -L+20M --fs resize -n $1 + umount "$mount_dir" + fscheck_ext3 "$3" +} + +test_ext2_small_shrink() { + mkfs.ext2 "$3" + + lvresize -L-1 --fs resize $1 + lvresize -L-1 --fs resize $1 + + fscheck_ext3 "$3" +} + +test_ext3_resize() { + mkfs.ext3 -b4096 -j "$3" + + fsadm --lvresize resize $1 30M + # Fails - not enough space for 4M fs + not fsadm -y --lvresize resize "$2" 4M + lvresize -L+10M --fs resize $1 + lvreduce -L10M --fs resize $1 + + fscheck_ext3 "$3" + mount "$3" "$mount_dir" + lvresize -L+10M --fs resize $1 + + not fsadm -y --lvresize resize $1 4M + echo n | not lvresize -L4M --fs resize -n $1 + lvresize -L+20M --fs resize -n $1 + lvresize -L-10M --fs resize -y $1 + umount "$mount_dir" +} + +test_ext3_small_shrink() { + mkfs.ext3 "$3" + + lvresize -L-1 --fs resize $1 + lvresize -L-1 --fs resize $1 + + fscheck_ext3 "$3" +} + +test_xfs_resize() { + mkfs.xfs -f "$3" + + fsadm --lvresize resize $1 330M + # Fails - not enough space for 4M fs + lvresize -L+10M -y --fs resize $1 + not lvreduce -L10M --fs resize $1 + + fscheck_xfs "$3" + mount "$3" "$mount_dir" + lvresize -L+10M -y --fs resize -n $1 + umount "$mount_dir" + fscheck_xfs "$3" +} + +test_xfs_small_shrink() { + mkfs.xfs -f "$3" + + not lvresize -L-1 --fs resize $1 + fscheck_xfs "$3" +} + +test_reiserfs_resize() { + mkfs.reiserfs -s 513 -f "$3" + + fsadm -y --lvresize resize $1 30M + # resize fs does not support resiserfs and requires resize_fsadm + not lvresize -L+10M --fs resize $1 + lvresize -L+10M --fs resize_fsadm $1 + fsadm --lvresize -y resize $1 10M + + fscheck_reiserfs "$3" + mount "$3" "$mount_dir" + + fsadm -y --lvresize resize $1 30M + umount "$mount_dir" + fscheck_reiserfs "$3" +} + +test_reiserfs_small_shrink() { + mkfs.reiserfs -s 513 -f "$3" + + not lvresize -y -L-1 --fs resize $1 + lvresize -y -L-1 --fs resize_fsadm $1 + lvresize -y -L-1 --fs resize_fsadm $1 + + fscheck_reiserfs "$3" +} + +# $1 LVM backend (vg/lv name) +# $2 LVM backend device (/dev/vg/lv) +# $3 active dm-crypt device (/dev/mapper/some_name ) +# $4 active dm-crypt name ( some_name ) +test_ext2_inactive() { + crypt_open "$2" $PWD2 "$4" + mkfs.ext2 -b4096 -j "$3" + crypt_close "$4" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + + crypt_open "$2" $PWD2 "$4" + fscheck_ext3 "$3" + crypt_close "$4" +} + +test_ext3_inactive() { + crypt_open "$2" $PWD2 "$4" + mkfs.ext3 -b4096 -j "$3" + crypt_close "$4" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + + crypt_open "$2" $PWD2 "$4" + fscheck_ext3 "$3" + crypt_close "$4" +} + +test_xfs_inactive() { + crypt_open "$2" $PWD2 "$4" + mkfs.xfs -f "$3" + crypt_close "$4" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + + crypt_open "$2" $PWD2 "$4" + fscheck_xfs "$3" + crypt_close "$4" +} + +test_reiserfs_inactive() { + crypt_open "$2" $PWD2 "$4" + mkfs.reiserfs -s 513 -f "$3" + crypt_close "$4" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + + crypt_open "$2" $PWD2 "$4" + fscheck_reiserfs "$3" + crypt_close "$4" +} + +# $1 LVM backend (vg/lv name) +# $2 LVM backend device (/dev/vg/lv) +# $3 active dm-crypt device (/dev/mapper/some_name ) +# $4 active dm-crypt name ( some_name ) +test_ext2_plain() { + mkfs.ext2 -b4096 -j "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + fscheck_ext3 "$3" + + fsadm --cryptresize resize $3 30M + fsadm --cryptresize resize $3 35M + fscheck_ext3 "$3" + + mount "$3" "$mount_dir" + not fsadm -y --cryptresize resize $3 4M + umount "$mount_dir" + fscheck_ext3 "$3" + + crypt_close "$4" + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + crypt_open_plain "$2" $PWD3 "$4" + fscheck_ext3 "$3" +} + +test_ext3_plain() { + mkfs.ext3 -b4096 -j "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + fscheck_ext3 "$3" + + fsadm --cryptresize resize $3 30M + fsadm --cryptresize resize $3 35M + fscheck_ext3 "$3" + + mount "$3" "$mount_dir" + not fsadm -y --cryptresize resize $3 4M + umount "$mount_dir" + fscheck_ext3 "$3" + + crypt_close "$4" + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + crypt_open_plain "$2" $PWD3 "$4" + fscheck_ext3 "$3" +} + +test_xfs_plain() { + mkfs.xfs -f "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + fscheck_xfs "$3" + + lvresize -f -L+10M $1 + fsadm --cryptresize resize $3 345M + # no shrink support in xfs + not fsadm --cryptresize resize $3 35M + fscheck_xfs "$3" + + crypt_close "$4" + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + crypt_open_plain "$2" $PWD3 "$4" + fscheck_xfs "$3" + + lvresize -f -L320M $1 +} + +test_reiserfs_plain() { + mkfs.reiserfs -s 513 -f "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L-10M --fs resize $1 + fscheck_reiserfs "$3" + + fsadm -y --cryptresize resize $3 30M + fsadm -y --cryptresize resize $3 35M + fscheck_reiserfs "$3" + + crypt_close "$4" + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + crypt_open_plain "$2" $PWD3 "$4" + fscheck_reiserfs "$3" +} + +# $1 LVM header backend (vg/lv name) +# $2 LVM hedaer backend device (/dev/vg/lv) +# $3 active dm-crypt device (/dev/mapper/some_name ) +# $4 active dm-crypt name ( some_name )a +test_ext2_detached() { + mkfs.ext2 -b4096 -j "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + fscheck_ext3 "$3" +} + +test_ext3_detached() { + mkfs.ext3 -b4096 -j "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + fscheck_ext3 "$3" +} + +test_xfs_detached() { + mkfs.xfs -f "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + + fscheck_xfs "$3" +} + +test_reiserfs_detached() { + mkfs.reiserfs -s 513 -f "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize $1 + not lvreduce -L10M --fs resize $1 + + fscheck_reiserfs "$3" +} + +if check_missing ext2; then + test_ext2_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + test_ext2_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + + crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN" + test_ext2_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN" + crypt_close "$CRYPT_NAME_PLAIN" + + lvresize --fs ignore -y -L100M $vg_lv + cryptsetup resize $CRYPT_NAME + test_ext2_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + if [ -z "$SKIP_DETACHED" ]; then + crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2" + test_ext2_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + crypt_close "$CRYPT_NAME2" + fi +fi + +if check_missing ext3; then + test_ext3_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + test_ext3_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + + crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN" + test_ext3_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN" + crypt_close "$CRYPT_NAME_PLAIN" + + lvresize --fs ignore -y -L100M $vg_lv + cryptsetup resize $CRYPT_NAME + test_ext3_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + if [ -z "$SKIP_DETACHED" ]; then + crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2" + test_ext3_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + crypt_close "$CRYPT_NAME2" + fi +fi + +if check_missing xfs; then + lvresize --fs ignore -y -L325M $vg_lv + cryptsetup resize $CRYPT_NAME + + test_xfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + + test_xfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + + crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN" + test_xfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN" + crypt_close "$CRYPT_NAME_PLAIN" + + lvresize --fs ignore -y -L310M $vg_lv + cryptsetup resize $CRYPT_NAME + test_xfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L325M $vg_lv + cryptsetup resize $CRYPT_NAME + + if [ -z "$SKIP_DETACHED" ]; then + crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2" + test_xfs_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + crypt_close "$CRYPT_NAME2" + fi +fi + +if check_missing reiserfs; then + test_reiserfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + test_reiserfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + + crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN" + test_reiserfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN" + crypt_close "$CRYPT_NAME_PLAIN" + + lvresize --fs ignore -y -L100M $vg_lv + cryptsetup resize $CRYPT_NAME + test_reiserfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + if [ -z "$SKIP_DETACHED" ]; then + crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2" + test_reiserfs_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + crypt_close "$CRYPT_NAME2" + fi +fi + +crypt_close "$CRYPT_NAME" + +vgremove -ff $vg diff --git a/test/shell/fsadm-crypt.sh b/test/shell/fsadm-crypt.sh new file mode 100644 index 0000000..4415cea --- /dev/null +++ b/test/shell/fsadm-crypt.sh @@ -0,0 +1,614 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Exercise fsadm filesystem resize on crypt devices' + +SKIP_WITH_LVMPOLLD=1 + +# FIXME: cannot use brd (ramdisk) - lsblk is NOT listing it +# so lsblk usage should be replaced +export LVM_TEST_PREFER_BRD=0 + +. lib/inittest + +aux prepare_vg 1 1300 + +# set to "skip" to avoid testing given fs and test warning result +# i.e. check_reiserfs=skip +check_ext2= +check_ext3= +check_xfs= +check_reiserfs= +check_cryptsetup= +DROP_SYMLINK= + +CRYPT_NAME="$PREFIX-tcrypt" +CRYPT_DEV="$DM_DEV_DIR/mapper/$CRYPT_NAME" + +CRYPT_NAME2="$PREFIX-tcrypt2" +CRYPT_DEV2="$DM_DEV_DIR/mapper/$CRYPT_NAME2" + +CRYPT_NAME_PLAIN="$PREFIX-tcryptp" +CRYPT_DEV_PLAIN="$DM_DEV_DIR/mapper/$CRYPT_NAME_PLAIN" + +FORMAT_PARAMS="-i1" +PWD1="93R4P4pIqAH8" +PWD2="mymJeD8ivEhE" +PWD3="ocMakf3fAcQO" +SKIP_DETACHED= + +if which cryptsetup ; then + # use older format luks1 - otherwise the test would need to pass password everywhere... + case $(cryptsetup --version) in + "cryptsetup 2"*) FORMAT_PARAMS="$FORMAT_PARAMS --type luks1" ;; + esac +else + check_cryptsetup=${check_cryptsetup:-cryptsetup} +fi + +which mkfs.ext2 || check_ext2=${check_ext2:-mkfs.ext2} +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 || { + which xfs_repair || check_xfs=${check_xfs:-xfs_repair} +} +grep xfs /proc/filesystems || check_xfs=${check_xfs:-no_xfs} + +which mkfs.reiserfs || check_reiserfs=${check_reiserfs:-mkfs.reiserfs} +which reiserfsck || check_reiserfs=${check_reiserfs:-reiserfsck} +modprobe reiserfs || true +grep reiserfs /proc/filesystems || check_reiserfs=${check_reiserfs:-no_reiserfs} + +vg_lv=$vg/$lv1 +vg_lv2=$vg/${lv1}bar +vg_lv3=$vg/${lv1}plain +dev_vg_lv="$DM_DEV_DIR/$vg_lv" +dev_vg_lv2="$DM_DEV_DIR/$vg_lv2" +dev_vg_lv3="$DM_DEV_DIR/$vg_lv3" +mount_dir="mnt" + +test ! -d "$mount_dir" && mkdir "$mount_dir" + +crypt_close() { + aux udev_wait + cryptsetup remove "$1" + if [ "$?" -eq 0 ] && [ -n "$DROP_SYMLINK" ]; then + rm -f "$DM_DEV_DIR/mapper/$1" + fi +} + +cleanup_mounted_and_teardown() +{ + umount "$mount_dir" || true + crypt_close $CRYPT_NAME > /dev/null 2>&1 || true + crypt_close $CRYPT_NAME2 > /dev/null 2>&1 || true + crypt_close $CRYPT_NAME_PLAIN > /dev/null 2>&1 || true + aux teardown +} + +fscheck_ext3() +{ + fsck.ext3 -p -F -f "$1" +} + +fscheck_xfs() +{ + if which xfs_repair ; then + xfs_repair -n "$1" + else + xfs_check "$1" + fi +} + +fscheck_reiserfs() +{ + reiserfsck --check -p -f "$1" /dev/null || skip +check_missing cryptsetup || skip + +vgchange -s 128k +lvcreate -n $lv1 -L25M $vg +lvcreate -n ${lv1}bar -L335M $vg +lvcreate -n ${lv1}plain -L335M $vg +create_crypt_device +trap 'cleanup_mounted_and_teardown' EXIT + + +# $1 LVM backend (vg/lv name) +# $2 LVM backend device (/dev/vg/lv) +# $3 active dm-crypt device (/dev/mapper/some_name ) +test_ext2_resize() { + mkfs.ext2 -b4096 -j "$3" + + fsadm --lvresize resize $1 30M + # Fails - not enough space for 4M fs + not fsadm -y --lvresize resize "$2" 4M + lvresize -L+10M --fs resize_fsadm $1 + lvreduce -L10M --fs resize_fsadm $1 + + fscheck_ext3 "$3" + mount "$3" "$mount_dir" + not fsadm -y --lvresize resize $1 4M + echo n | not lvresize -L4M --fs resize_fsadm -n $1 + lvresize -L+20M --fs resize_fsadm -n $1 + umount "$mount_dir" + fscheck_ext3 "$3" +} + +test_ext2_small_shrink() { + mkfs.ext2 "$3" + + lvresize -L-1 --fs resize_fsadm $1 + lvresize -L-1 --fs resize_fsadm $1 + + fscheck_ext3 "$3" +} + +test_ext3_resize() { + mkfs.ext3 -b4096 -j "$3" + + fsadm --lvresize resize $1 30M + # Fails - not enough space for 4M fs + not fsadm -y --lvresize resize "$2" 4M + lvresize -L+10M --fs resize_fsadm $1 + lvreduce -L10M --fs resize_fsadm $1 + + fscheck_ext3 "$3" + mount "$3" "$mount_dir" + lvresize -L+10M --fs resize_fsadm $1 + + not fsadm -y --lvresize resize $1 4M + echo n | not lvresize -L4M --fs resize_fsadm -n $1 + lvresize -L+20M --fs resize_fsadm -n $1 + lvresize -L-10M --fs resize_fsadm -y $1 + umount "$mount_dir" +} + +test_ext3_small_shrink() { + mkfs.ext3 "$3" + + lvresize -L-1 --fs resize_fsadm $1 + lvresize -L-1 --fs resize_fsadm $1 + + fscheck_ext3 "$3" +} + +test_xfs_resize() { + mkfs.xfs -f "$3" + + fsadm --lvresize resize $1 330M + # Fails - not enough space for 4M fs + lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + + fscheck_xfs "$3" + mount "$3" "$mount_dir" + lvresize -L+10M --fs resize_fsadm -n $1 + umount "$mount_dir" + fscheck_xfs "$3" +} + +test_xfs_small_shrink() { + mkfs.xfs -f "$3" + + not lvresize -L-1 --fs resize_fsadm $1 + fscheck_xfs "$3" +} + +test_reiserfs_resize() { + mkfs.reiserfs -s 513 -f "$3" + + fsadm --lvresize resize $1 30M + lvresize -L+10M --fs resize_fsadm $1 + fsadm --lvresize -y resize $1 10M + + fscheck_reiserfs "$3" + mount "$3" "$mount_dir" + + fsadm -y --lvresize resize $1 30M + umount "$mount_dir" + fscheck_reiserfs "$3" +} + +test_reiserfs_small_shrink() { + mkfs.reiserfs -s 513 -f "$3" + + lvresize -y -L-1 --fs resize_fsadm $1 + lvresize -y -L-1 --fs resize_fsadm $1 + + fscheck_reiserfs "$3" +} + +# $1 LVM backend (vg/lv name) +# $2 LVM backend device (/dev/vg/lv) +# $3 active dm-crypt device (/dev/mapper/some_name ) +# $4 active dm-crypt name ( some_name ) +test_ext2_inactive() { + crypt_open "$2" $PWD2 "$4" + mkfs.ext2 -b4096 -j "$3" + crypt_close "$4" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + + crypt_open "$2" $PWD2 "$4" + fscheck_ext3 "$3" + crypt_close "$4" +} + +test_ext3_inactive() { + crypt_open "$2" $PWD2 "$4" + mkfs.ext3 -b4096 -j "$3" + crypt_close "$4" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + + crypt_open "$2" $PWD2 "$4" + fscheck_ext3 "$3" + crypt_close "$4" +} + +test_xfs_inactive() { + crypt_open "$2" $PWD2 "$4" + mkfs.xfs -f "$3" + crypt_close "$4" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + + crypt_open "$2" $PWD2 "$4" + fscheck_xfs "$3" + crypt_close "$4" +} + +test_reiserfs_inactive() { + crypt_open "$2" $PWD2 "$4" + mkfs.reiserfs -s 513 -f "$3" + crypt_close "$4" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + + crypt_open "$2" $PWD2 "$4" + fscheck_reiserfs "$3" + crypt_close "$4" +} + +# $1 LVM backend (vg/lv name) +# $2 LVM backend device (/dev/vg/lv) +# $3 active dm-crypt device (/dev/mapper/some_name ) +# $4 active dm-crypt name ( some_name ) +test_ext2_plain() { + mkfs.ext2 -b4096 -j "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + fscheck_ext3 "$3" + + fsadm --cryptresize resize $3 30M + fsadm --cryptresize resize $3 35M + fscheck_ext3 "$3" + + mount "$3" "$mount_dir" + not fsadm -y --cryptresize resize $3 4M + umount "$mount_dir" + fscheck_ext3 "$3" + + crypt_close "$4" + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + crypt_open_plain "$2" $PWD3 "$4" + fscheck_ext3 "$3" +} + +test_ext3_plain() { + mkfs.ext3 -b4096 -j "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + fscheck_ext3 "$3" + + fsadm --cryptresize resize $3 30M + fsadm --cryptresize resize $3 35M + fscheck_ext3 "$3" + + mount "$3" "$mount_dir" + not fsadm -y --cryptresize resize $3 4M + umount "$mount_dir" + fscheck_ext3 "$3" + + crypt_close "$4" + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + crypt_open_plain "$2" $PWD3 "$4" + fscheck_ext3 "$3" +} + +test_xfs_plain() { + mkfs.xfs -f "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + fscheck_xfs "$3" + + lvresize -f -L+10M $1 + fsadm --cryptresize resize $3 345M + # no shrink support in xfs + not fsadm --cryptresize resize $3 35M + fscheck_xfs "$3" + + crypt_close "$4" + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + crypt_open_plain "$2" $PWD3 "$4" + fscheck_xfs "$3" + + lvresize -f -L320M $1 +} + +test_reiserfs_plain() { + mkfs.reiserfs -s 513 -f "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L-10M --fs resize_fsadm $1 + fscheck_reiserfs "$3" + + fsadm -y --cryptresize resize $3 30M + fsadm -y --cryptresize resize $3 35M + fscheck_reiserfs "$3" + + crypt_close "$4" + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + crypt_open_plain "$2" $PWD3 "$4" + fscheck_reiserfs "$3" +} + +# $1 LVM header backend (vg/lv name) +# $2 LVM hedaer backend device (/dev/vg/lv) +# $3 active dm-crypt device (/dev/mapper/some_name ) +# $4 active dm-crypt name ( some_name )a +test_ext2_detached() { + mkfs.ext2 -b4096 -j "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + fscheck_ext3 "$3" +} + +test_ext3_detached() { + mkfs.ext3 -b4096 -j "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + fscheck_ext3 "$3" +} + +test_xfs_detached() { + mkfs.xfs -f "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + + fscheck_xfs "$3" +} + +test_reiserfs_detached() { + mkfs.reiserfs -s 513 -f "$3" + + not fsadm --lvresize resize $1 30M + not lvresize -L+10M --fs resize_fsadm $1 + not lvreduce -L10M --fs resize_fsadm $1 + + fscheck_reiserfs "$3" +} + +if check_missing ext2; then + test_ext2_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + test_ext2_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + + crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN" + test_ext2_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN" + crypt_close "$CRYPT_NAME_PLAIN" + + lvresize --fs ignore -y -L100M $vg_lv + cryptsetup resize $CRYPT_NAME + test_ext2_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + if [ -z "$SKIP_DETACHED" ]; then + crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2" + test_ext2_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + crypt_close "$CRYPT_NAME2" + fi +fi + +if check_missing ext3; then + test_ext3_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + test_ext3_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + + crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN" + test_ext3_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN" + crypt_close "$CRYPT_NAME_PLAIN" + + lvresize --fs ignore -y -L100M $vg_lv + cryptsetup resize $CRYPT_NAME + test_ext3_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + if [ -z "$SKIP_DETACHED" ]; then + crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2" + test_ext3_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + crypt_close "$CRYPT_NAME2" + fi +fi + +if check_missing xfs; then + lvresize -f -L310M $vg_lv + cryptsetup resize $CRYPT_NAME + test_xfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L325M $vg_lv + cryptsetup resize $CRYPT_NAME + + test_xfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + + crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN" + test_xfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN" + crypt_close "$CRYPT_NAME_PLAIN" + + lvresize --fs ignore -y -L310M $vg_lv + cryptsetup resize $CRYPT_NAME + test_xfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + if [ -z "$SKIP_DETACHED" ]; then + crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2" + test_xfs_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + crypt_close "$CRYPT_NAME2" + fi +fi + +if check_missing reiserfs; then + test_reiserfs_resize "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + test_reiserfs_inactive "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + + crypt_open_plain "$dev_vg_lv3" $PWD3 "$CRYPT_NAME_PLAIN" + test_reiserfs_plain "$vg_lv3" "$dev_vg_lv3" "$CRYPT_DEV_PLAIN" "$CRYPT_NAME_PLAIN" + crypt_close "$CRYPT_NAME_PLAIN" + + lvresize --fs ignore -y -L100M $vg_lv + cryptsetup resize $CRYPT_NAME + test_reiserfs_small_shrink "$vg_lv" "$dev_vg_lv" "$CRYPT_DEV" + lvresize --fs ignore -y -L25M $vg_lv + cryptsetup resize $CRYPT_NAME + + if [ -z "$SKIP_DETACHED" ]; then + crypt_open_detached "$dev_vg_lv3" $PWD2 "$CRYPT_NAME2" "$dev_vg_lv2" + test_reiserfs_detached "$vg_lv2" "$dev_vg_lv2" "$CRYPT_DEV2" "$CRYPT_NAME2" + crypt_close "$CRYPT_NAME2" + fi +fi + +crypt_close "$CRYPT_NAME" + +vgremove -ff $vg diff --git a/test/shell/fsadm-renamed.sh b/test/shell/fsadm-renamed.sh new file mode 100644 index 0000000..698b143 --- /dev/null +++ b/test/shell/fsadm-renamed.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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 operation on renamed device' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 1 700 + +vg_lv=$vg/$lv1 +vg_lv_ren=${vg_lv}_renamed + +dev_vg_lv="$DM_DEV_DIR/$vg_lv" +dev_vg_lv_ren="$DM_DEV_DIR/$vg_lv_ren" + +mount_dir="mnt" +mount_space_dir="mnt space dir" +mount_dolar_dir="mnt \$SPACE dir" + +test ! -d "$mount_dir" && mkdir "$mount_dir" +test ! -d "$mount_space_dir" && mkdir "$mount_space_dir" +test ! -d "$mount_dolar_dir" && mkdir "$mount_dolar_dir" + +cleanup_mounted_and_teardown() +{ + umount "$mount_dir" || true + umount "$mount_space_dir" || true + umount "$mount_dolar_dir" || true + aux teardown +} + +check_mounted() +{ + mount | tee out + grep $vg out || { + # older versions of systemd sometimes umount volume by mistake + # skip further test when this case happens + systemctl --version | grep "systemd 222" && \ + skip "System is running old racy systemd version." + } +} + +# Test for block sizes != 1024 (rhbz #480022) +trap 'cleanup_mounted_and_teardown' EXIT + +# Iterate over supported filesystems +for i in mkfs.ext3 mkfs.xfs mkfs.reiserfs +do + +if not which "$i" ; then + echo "Skipping tests for missing $i" + continue +fi + +lvcreate -n $lv1 -L300M $vg + +case "$i" in +*ext3) MKFS_ARGS="-b1024 -j" ;; +*xfs) MKFS_ARGS="-l internal,size=64m -f" ;; +*reiserfs) MKFS_ARGS="-s 513 -f" ;; +esac + +echo "$i" +"$i" $MKFS_ARGS "$dev_vg_lv" + +# Adding couple udev wait ops as some older systemd +# might get confused and was 'randomly/racy' umounting +# devices just mounted. +# +# See for explanation: +# https://github.com/systemd/systemd/commit/628c89cc68ab96fce2de7ebba5933725d147aecc +# https://github.com/systemd/systemd/pull/2017 +aux udev_wait + +# mount /dev/test/lv1 on /mnt +mount "$dev_vg_lv" "$mount_dir" + +aux udev_wait + +# rename lv1 to lv1_renamed, now /dev/test/lv1_renamed is mounted on /mnt, +# but "df" and "mount" commands will still show /dev/test/lv1 mounted on /mnt. +lvrename $vg_lv $vg_lv_ren + +check_mounted + +# fails on renamed LV +# lvextend -r test/lv1_renamed succeeds in extending the LV (as lv1_renamed), +# but xfs_growfs /dev/test/lv1_renamed fails because it doesn't recognize +# that device is mounted, because the old lv name reported as being mounted. +fail lvresize -y -L+10M -r $vg_lv_ren + +# fails on unknown mountpoint (FIXME: umount) +not umount "$dev_vg_lv" + +# create a new LV with the previous name of the renamed lv +lvcreate -L300 -n $lv1 $vg +"$i" $MKFS_ARGS "$dev_vg_lv" + +aux udev_wait + +# mount the new lv on a dir with a similar name as the other +# now df will show +# /dev/mapper/test-lv1 ... /mnt +# /dev/mapper/test-lv1 ... /mnt $SPACE dir +mount "$dev_vg_lv" "$mount_dolar_dir" + +check_mounted + +# try to resize the LV that was renamed: lvextend -r test/lv1_renamed +# this succeeds in extending the LV (lv1_renamed), but xfs_growfs fails +# for the same reason as above, i.e. mount doesn't show the lv1_renamed +# device is mounted anywhere. +not lvresize -L+10M -r $vg_lv_ren + +umount "$mount_dir" + +lvresize -y -L+10M -r $vg_lv + +aux udev_wait + +umount "$mount_dolar_dir" + +lvremove -ff $vg + +done + +vgremove -ff $vg diff --git a/test/shell/fsadm.sh b/test/shell/fsadm.sh index 4e624db..7f155d7 100644 --- a/test/shell/fsadm.sh +++ b/test/shell/fsadm.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2014 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 @@ -7,26 +8,36 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA test_description='Exercise fsadm filesystem resize' -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest -aux prepare_vg 1 100 +aux prepare_vg 1 400 # set to "skip" to avoid testing given fs and test warning result # i.e. check_reiserfs=skip +check_ext2= check_ext3= check_xfs= check_reiserfs= +which mkfs.ext2 || check_ext2=${check_ext2:-mkfs.ext2} 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 xfs_check || { + which xfs_repair || check_xfs=${check_xfs:-xfs_repair} +} +grep xfs /proc/filesystems || check_xfs=${check_xfs:-no_xfs} + which mkfs.reiserfs || check_reiserfs=${check_reiserfs:-mkfs.reiserfs} which reiserfsck || check_reiserfs=${check_reiserfs:-reiserfsck} +modprobe reiserfs || true +grep reiserfs /proc/filesystems || check_reiserfs=${check_reiserfs:-no_reiserfs} vg_lv=$vg/$lv1 vg_lv2=$vg/${lv1}bar @@ -34,27 +45,30 @@ dev_vg_lv="$DM_DEV_DIR/$vg_lv" dev_vg_lv2="$DM_DEV_DIR/$vg_lv2" mount_dir="mnt" mount_space_dir="mnt space dir" -# for recursive call -export LVM_BINARY=$(which lvm) test ! -d "$mount_dir" && mkdir "$mount_dir" test ! -d "$mount_space_dir" && mkdir "$mount_space_dir" cleanup_mounted_and_teardown() { - umount "$mount_dir" || true - umount "$mount_space_dir" || true + umount "$mount_dir" 2>/dev/null || true + umount "$mount_space_dir" 2>/dev/null || true aux teardown } fscheck_ext3() { - fsck.ext3 -p -F -f "$dev_vg_lv" + # fsck with result code '1' is success + fsck.ext3 -p -F -f "$dev_vg_lv" || test "$?" -eq 1 } fscheck_xfs() { - xfs_check "$dev_vg_lv" + if which xfs_repair ; then + xfs_repair -n "$dev_vg_lv" + else + xfs_check "$dev_vg_lv" + fi } fscheck_reiserfs() @@ -64,11 +78,13 @@ fscheck_reiserfs() check_missing() { - eval local t=$\check_$1 + local t + eval "t=\$check_$1" test -z "$t" && return 0 test "$t" = skip && return 1 - # trick for warning test - echo "WARNING: fsadm test skipped $1 tests, $t tool is missing" + echo "WARNING: fsadm test skipped $1 tests, $t tool is missing." + # trick to get test listed with warning + # should false; return 1 } @@ -77,24 +93,62 @@ lvcreate -n $lv1 -L20M $vg lvcreate -n ${lv1}bar -L10M $vg trap 'cleanup_mounted_and_teardown' EXIT +# prints help +fsadm + +# check needs arg +not fsadm check + +# check needs arg +not fsadm resize "$dev_vg_lv" 30M |& tee out +grep "Cannot get FSTYPE" out + if check_missing ext2; then mkfs.ext2 -b4096 -j "$dev_vg_lv" + # Check 'check' works + fsadm check $vg_lv + # Check 'resize' without size parameter works + fsadm resize $vg_lv fsadm --lvresize resize $vg_lv 30M # Fails - not enough space for 4M fs not fsadm -y --lvresize resize "$dev_vg_lv" 4M - lvresize -L+10M -r $vg_lv - lvreduce -L10M -r $vg_lv + lvresize -L+10M --fs resize_fsadm $vg_lv + lvreduce -L10M --fs resize_fsadm $vg_lv fscheck_ext3 mount "$dev_vg_lv" "$mount_dir" not fsadm -y --lvresize resize $vg_lv 4M - echo n | not lvresize -L4M -r -n $vg_lv - lvresize -L+20M -r -n $vg_lv + echo n | not lvresize -L4M --fs resize_fsadm -n $vg_lv + lvresize -L+20M --fs resize_fsadm -n $vg_lv umount "$mount_dir" fscheck_ext3 - lvresize -f -L20M $vg_lv + lvresize --fs ignore -y -L20M $vg_lv + + if which debugfs ; then + mkfs.ext2 -b4096 -j "$dev_vg_lv" + mount "$dev_vg_lv" "$mount_dir" + touch "$mount_dir/file" + umount "$mount_dir" + # generate a 'repariable' corruption + # so fsck returns code 1 (fs repaired) + debugfs -R "clri file" -w "$dev_vg_lv" + + fsadm -v -f check "$dev_vg_lv" + + # corrupting again + mount "$dev_vg_lv" "$mount_dir" + touch "$mount_dir/file" + umount "$mount_dir" + debugfs -R "clri file" -w "$dev_vg_lv" + + mount "$dev_vg_lv" "$mount_dir" + fsadm -v -y --lvresize resize $vg_lv 10M + lvresize -L+10M -y --fs resize_fsadm -n $vg_lv + umount "$mount_dir" 2>/dev/null || true + fscheck_ext3 + fi fi if check_missing ext3; then @@ -104,47 +158,49 @@ if check_missing ext3; then fsadm --lvresize resize $vg_lv 30M # Fails - not enough space for 4M fs not fsadm -y --lvresize resize "$dev_vg_lv" 4M - lvresize -L+10M -r $vg_lv - lvreduce -L10M -r $vg_lv + lvresize -L+10M --fs resize_fsadm $vg_lv + lvreduce -L10M --fs resize_fsadm $vg_lv fscheck_ext3 mount "$dev_vg_lv" "$mount_dir" - lvresize -L+10M -r $vg_lv + lvresize -L+10M --fs resize_fsadm $vg_lv mount "$dev_vg_lv2" "$mount_space_dir" fsadm --lvresize -e -y resize $vg_lv2 25M not fsadm -y --lvresize resize $vg_lv 4M echo n | not lvresize -L4M -r -n $vg_lv - lvresize -L+20M -r -n $vg_lv + lvresize -L+20M --fs resize_fsadm -n $vg_lv + lvresize -L-10M --fs resize_fsadm -y $vg_lv umount "$mount_dir" umount "$mount_space_dir" fscheck_ext3 - lvresize -f -L20M $vg_lv + lvresize --fs ignore -y -L20M $vg_lv fi if check_missing xfs; then - mkfs.xfs -l internal,size=1000b -f "$dev_vg_lv" + lvresize -L 300M $vg_lv + mkfs.xfs -l internal -f "$dev_vg_lv" - fsadm --lvresize resize $vg_lv 30M + fsadm --lvresize resize $vg_lv 320M # Fails - not enough space for 4M fs - lvresize -L+10M -r $vg_lv - not lvreduce -L10M -r $vg_lv + lvresize -L+10M --fs resize_fsadm $vg_lv + not lvreduce -L10M --fs resize_fsadm $vg_lv fscheck_xfs mount "$dev_vg_lv" "$mount_dir" - lvresize -L+10M -r -n $vg_lv + lvresize -L+10M --fs resize_fsadm -n $vg_lv umount "$mount_dir" fscheck_xfs - lvresize -f -L20M $vg_lv + lvresize --fs ignore -y -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 + lvresize -L+10M --fs resize_fsadm $vg_lv fsadm --lvresize -y resize $vg_lv 10M fscheck_reiserfs @@ -154,7 +210,7 @@ if check_missing reiserfs; then umount "$mount_dir" fscheck_reiserfs - lvresize -f -L20M $vg_lv + lvresize --fs ignore -y -L20M $vg_lv fi vgremove -ff $vg diff --git a/test/shell/hints.sh b/test/shell/hints.sh new file mode 100644 index 0000000..e25c7e1 --- /dev/null +++ b/test/shell/hints.sh @@ -0,0 +1,480 @@ +#!/usr/bin/env bash + +# Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +# hints are currently disabled with lvmlockd +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +# Since this test is currenly using 'system's' hints, +# it cannot be running, while lvmdbusd operates in the system. +# FIXME: sometimes test suite itself 'leaks' lvmdbusd process. +pgrep lvmdbusd && skip "Can't run this test, while lvmdbusd is running" + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +HINTS="$RUNDIR/lvm/hints" +NOHINTS="$RUNDIR/lvm/nohints" +NEWHINTS="$RUNDIR/lvm/newhints" +PREV="$RUNDIR/lvm/prev-hints" + +# TODO: +# Test commands that ignore hints +# Test flock + + +aux lvmconf 'devices/scan_lvs = 0' + +aux prepare_devs 6 + +# no PVs yet so hints should have no devs +pvs +not grep scan: $HINTS + +# +# test --nohints option +# + +pvcreate "$dev1" +pvcreate "$dev2" +# pvs --nohints does not create hints +pvs --nohints |tee out +grep "$dev1" out +grep "$dev2" out +not grep "$dev1" $HINTS +not grep "$dev2" $HINTS +# pvs creates hints +pvs +grep "$dev1" $HINTS +grep "$dev2" $HINTS + +# save hints with dev1 and dev2 before dev3 is created +cp $HINTS $PREV +# pvcreate --nohints invalidates hints +pvcreate --nohints "$dev3" +ls $NEWHINTS +# pvs --nohints does not update hints +pvs --nohints |tee out +grep "$dev1" out +grep "$dev2" out +grep "$dev3" out +not grep "$dev3" $HINTS +# restore old hint file without dev3 +cp $PREV $HINTS +# pvs --nohints does not update hints +pvs --nohints |tee out +grep "$dev1" out +grep "$dev2" out +grep "$dev3" out +grep "$dev1" $HINTS +grep "$dev2" $HINTS +not grep "$dev3" $HINTS +# pvs updates hints +pvs |tee out +grep "$dev1" out +grep "$dev2" out +grep "$dev3" out +grep "$dev1" $HINTS +grep "$dev2" $HINTS +grep "$dev3" $HINTS + +aux wipefs_a "$dev1" "$dev2" "$dev3" + +# +# vg1 uses dev1,dev2 +# +# Test basics that PVs are in hints, not non-PV devs, +# and that only PVs are scanned when using hints. +# + +rm $HINTS + +vgcreate $vg1 "$dev1" "$dev2" +lvcreate -n $lv1 -l 4 $vg1 + +# test that only the two PVs are in hints +pvs +grep -v -E "$dev1|$dev2" $HINTS > tmptest +not grep scan: tmptest + +# test that 'pvs' submits only three reads, one for each PV in hints +# for initial scan, and one more in vg_read rescan check + +if which strace; then +strace -e io_submit pvs 2>&1|tee tmptest +test "$(grep -c io_submit tmptest)" -eq 3 + +# test that 'pvs -a' submits seven reads, one for each device, +# and one more in vg_read rescan check +strace -e io_submit pvs -a 2>&1|tee tmptest +test "$(grep -c io_submit tmptest)" -eq 7 +fi + +# +# vg2 uses dev3,dev4 +# +# Test common commands that cause hints to be refreshed: +# pvcreate/vgcreate/vgextend/vgreduce/vgremove/pvremove +# + +not pvs "$dev3" +not grep "$dev3" $HINTS +cp $HINTS $PREV +pvcreate "$dev3" +grep "# Created empty" $HINTS +cat $NEWHINTS +# next cmd recreates hints +pvs "$dev3" +grep "$dev3" $HINTS +not diff $HINTS $PREV +not cat $NEWHINTS + +not vgs $vg2 +cp $HINTS $PREV +vgcreate $vg2 "$dev3" +grep "# Created empty" $HINTS +cat $NEWHINTS +# next cmd recreates hints +vgs $vg2 +grep $vg2 $HINTS +not diff $HINTS $PREV +not cat $NEWHINTS + +cp $HINTS $PREV +vgextend $vg2 "$dev4" +grep "# Created empty" $HINTS +cat $NEWHINTS +# next cmd recreates hints +vgs $vg2 +grep "$dev4" $HINTS +not diff $HINTS $PREV +not cat $NEWHINTS + +cp $HINTS $PREV +vgreduce $vg2 "$dev4" +grep "# Created empty" $HINTS +cat $NEWHINTS +# next cmd recreates hints +vgs $vg2 +grep "$dev4" $HINTS +not diff $HINTS $PREV +not cat $NEWHINTS + +cp $HINTS $PREV +vgremove $vg2 +grep "# Created empty" $HINTS +cat $NEWHINTS +# next cmd recreates hints +not vgs $vg2 +not grep $vg2 $HINTS +not diff $HINTS $PREV +not cat $NEWHINTS + +cp $HINTS $PREV +pvremove "$dev3" "$dev4" +grep "# Created empty" $HINTS +cat $NEWHINTS +# next cmd recreates hints +not pvs "$dev3" +not pvs "$dev4" +not grep "$dev3" $HINTS +not grep "$dev4" $HINTS +not diff $HINTS $PREV +not cat $NEWHINTS + +# +# Test that adding a new device and removing a device +# causes hints to be recreated. +# +# with a devices file the appearance of a new device on +# the system does not disturb lvm, so this test doesn't +# apply +# + +if ! lvmdevices; then + +not pvs "$dev5" + +# create a new temp device that will cause hint hash to change +DEVNAME=${PREFIX}pv99 +echo "0 $(blockdev --getsize "$dev5") linear $dev5 0" | dmsetup create $DEVNAME +dmsetup status $DEVNAME + +cp $HINTS $PREV +# pvs ignores current hints because of different dev hash and refreshes new hints +pvs +# devs listed in hints before and after are the same +grep scan: $PREV > scan1 +grep scan: $HINTS > scan2 +diff scan1 scan2 +# hash listed before and after are different +cat $PREV +cat $HINTS +grep devs_hash $PREV > devs_hash1 +grep devs_hash $HINTS > devs_hash2 +not diff devs_hash1 devs_hash2 + +# hints are stable/unchanging +cp $HINTS $PREV +pvs +diff $HINTS $PREV + +# remove the temp device which will cause hint hash to change again +dmsetup remove $DEVNAME + +cp $HINTS $PREV +# pvs ignores current hints because of different dev hash and refreshes new hints +pvs +# devs listed in hints before and after are the same +grep scan: $PREV > scan1 +grep scan: $HINTS > scan2 +diff scan1 scan2 +# hash listed before and after are different +grep devs_hash $PREV > devs_hash1 +grep devs_hash $HINTS > devs_hash2 +not diff devs_hash1 devs_hash2 + +# end of new device test for non-devicesfile case +fi + +# +# Test that hints don't change from a bunch of commands +# that use hints and shouldn't change it. +# + +# first create some more metadata using vg2 +pvcreate "$dev3" "$dev4" +vgcreate $vg2 "$dev3" +lvcreate -n $lv1 -l1 $vg2 +lvcreate -n $lv2 -l1 $vg2 + +cp $HINTS $PREV +lvm fullreport +lvchange -ay $vg1 +lvchange -an $vg1 +lvcreate -l1 -n $lv2 $vg1 +lvcreate -l1 -an -n $lv3 $vg1 +lvchange -an $vg1 +lvremove $vg1/$lv3 +lvresize --fs ignore -l+1 $vg1/$lv2 +lvresize --fs ignore -l-1 $vg1/$lv2 +lvdisplay +pvdisplay +vgdisplay +lvs +pvs +vgs +vgchange -ay $vg2 +vgchange -an $vg2 +vgck $vg2 +lvrename $vg1 $lv2 $lv3 +# no change in hints after all that +diff $HINTS $PREV + +# +# Test that changing the filter will cause hint refresh +# + +rm $HINTS $PREV +vgs +cp $HINTS $PREV +# this changes the filter to exclude dev5 which is not a PV +aux hide_dev "$dev5" +# next cmd sees different filter, ignores hints, creates new hints +pvs +not diff $HINTS $PREV +# run cmds using new filter +pvs +cp $HINTS $PREV +vgs +# hints are stable once refreshed +diff $HINTS $PREV +# this changes the filter to include dev5 +aux unhide_dev "$dev5" +# next cmd sees different filter, ignores hints, creates new hints +pvs +not diff $HINTS $PREV +# hints are stable +cp $HINTS $PREV +vgs +diff $HINTS $PREV + +# +# Test that changing scan_lvs will cause hint refresh +# + +rm $HINTS $PREV +vgs +cp $HINTS $PREV +# change lvm.conf +aux lvmconf 'devices/scan_lvs = 1' +# next cmd sees new setting, ignores hints, creates new hints +pvs +not diff $HINTS $PREV +# run cmds using new filter +pvs +cp $HINTS $PREV +vgs +# hints are stable once refreshed +diff $HINTS $PREV +# change lvm.conf back +aux lvmconf 'devices/scan_lvs = 0' +# next cmd sees different scan_lvs, ignores hints, creates new hints +pvs +not diff $HINTS $PREV +# hints are stable once refreshed +cp $HINTS $PREV +pvs +diff $HINTS $PREV + +# +# Test pvscan --cache to force hints refresh +# + +# pvs (no change), pvscan (hints are new), pvs (no change) +rm $HINTS $PREV +pvs +cp $HINTS $PREV +# this next pvscan recreates the hints file +pvscan --cache +# the only diff will be "Created by pvscan ..." vs "Created by pvs ..." +not diff $HINTS $PREV +cp $HINTS $PREV +pvs +diff $HINTS $PREV +grep 'Created by pvscan' $HINTS +# dev4 is a PV not used by a VG, dev5 is not a PV +# using dd to copy skirts hint tracking so dev5 won't be seen +# (unless the dd triggers udev which triggers pvscan --cache $dev5, +# but I've not seen that happen in tests so far.) +dd if="$dev4" of="$dev5" bs=1M +# this pvs won't see dev5 +pvs > foo +cat foo +grep "$dev4" foo +not grep "$dev5" foo +# no hints have changed after dd and pvs since dd cannot be detected +diff $HINTS $PREV +# force hints refresh, will see duplicate now +pvscan --cache +not diff $HINTS $PREV +cat $HINTS +pvs -a > foo +# after force refresh, both devs (dups) appear in output +cat foo +grep "$dev4" foo +grep "$dev5" foo +# clear PV from dev5 +dd if=/dev/zero of="$dev5" bs=1M count=1 +# this pvs won't use hints because of duplicate PVs, +# and will create new hints +cp $HINTS $PREV +pvs > foo +not diff $HINTS $PREV +grep "$dev4" foo +not grep "$dev5" foo +grep "$dev4" $HINTS +not grep "$dev5" $HINTS + +# +# Test pvscan --cache forces refresh +# + +rm $HINTS $PREV +pvs +cp $HINTS $PREV +# this next pvscan creates newhints to trigger a refresh +pvscan --cache "$dev4" +cat $NEWHINTS +# this next pvs creates new hints +pvs +# the only diff will be "Created by..." +not diff $HINTS $PREV + + +# +# Test pvck --repair forces refresh +# + +rm $HINTS $PREV +pvs +cp $HINTS $PREV +pvck --repairtype label_header -y "$dev3" +cat $NEWHINTS +grep 'Created empty by pvck' $HINTS +# this next pvs creates new hints +pvs +# the only diff will be "Created by..." +not diff $HINTS $PREV + + +# +# Test incorrect dev-to-pvid info in hints is detected +# dev4 is a PV not in a VG +# + +pvs +cp $HINTS tmp-old +# this pvchange will invalidate current hints +pvchange -u "$dev4" +grep "# Created empty" $HINTS +cat $NEWHINTS +# this next pvs will create new hints with the new uuid +pvs +grep "$dev4" $HINTS > tmp-newuuid +cp $HINTS tmp-new +not diff tmp-old tmp-new +# hints are stable +pvs +diff $HINTS tmp-new +# replace the current hints with the old hints with the old uuid +cp tmp-old $HINTS +# this next pvs will see wrong dev-to-pvid mapping and invalidate hints +pvs +cat $HINTS +cat $NEWHINTS +# this next pvs will create new hints with the new uuid +pvs +cat $HINTS +grep -f tmp-newuuid $HINTS +rm tmp-old tmp-new tmp-newuuid + + +# +# Test incorrent pvid-to-vgname info in hints is detected +# + +# this vgcreate invalidates current hints +vgcreate $vg3 "$dev4" +# this pvs creates new hints +pvs +cp $HINTS tmp-old +# this vgrename will invalidate current hints +vgrename $vg3 $vg4 +# this pvs will create new hints with the new vg name +pvs +cp $HINTS tmp-new +not diff tmp-old tmp-new +# replace the current hints with the old hints with the old vg name +cp tmp-old $HINTS +# this pvs will see wrong pvid-to-vgname mapping and invalidate hints +pvs +cat $NEWHINTS +# this pvs will create new hints with the new vg name +pvs +grep $vg4 $HINTS + +vgremove -y $vg4 +vgremove -y $vg2 +vgremove -y $vg1 diff --git a/test/shell/idm_fabric_failure.sh b/test/shell/idm_fabric_failure.sh new file mode 100644 index 0000000..edca86b --- /dev/null +++ b/test/shell/idm_fabric_failure.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_FAILURE" ] && skip + +aux prepare_devs 3 +aux extend_filter_LVMTEST + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +# Create new logic volume +lvcreate -a ey --zero n -l 50%FREE -n $lv1 $vg + +DRIVE1=$(dmsetup deps -o devname "$dev1" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') +DRIVE2=$(dmsetup deps -o devname "$dev2" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') +DRIVE3=$(dmsetup deps -o devname "$dev3" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') + +HOST1=$(readlink "/sys/block/$DRIVE1" | awk -F'/' '{print $6}') +HOST2=$(readlink "/sys/block/$DRIVE2" | awk -F'/' '{print $6}') +HOST3=$(readlink "/sys/block/$DRIVE3" | awk -F'/' '{print $6}') + +# Emulate fabric failure +echo 1 > "/sys/block/$DRIVE1/device/delete" +[ -f "/sys/block/$DRIVE2/device/delete" ] && echo 1 > "/sys/block/$DRIVE2/device/delete" +[ -f "/sys/block/$DRIVE3/device/delete" ] && echo 1 > "/sys/block/$DRIVE3/device/delete" + +# Wait for 10s and will not lead to timeout +sleep 10 + +# Rescan drives so can probe the deleted drives and join back them +echo "- - -" > "/sys/class/scsi_host/${HOST1}/scan" +echo "- - -" > "/sys/class/scsi_host/${HOST2}/scan" +echo "- - -" > "/sys/class/scsi_host/${HOST3}/scan" + +not check grep_lvmlockd_dump "S lvm_$vg kill_vg" + +# The previous device-mapper are removed, but LVM still can directly +# access VGs from the specified physical drives. So enable drives +# for these drives. +aux extend_filter_LVMTEST "a|/dev/$DRIVE1*|" "a|/dev/$DRIVE2*|" "a|/dev/$DRIVE3*|" +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +lvcreate -a n --zero n -l 10 -n $lv2 $vg + +vgremove -ff $vg diff --git a/test/shell/idm_fabric_failure_half_brain.sh b/test/shell/idm_fabric_failure_half_brain.sh new file mode 100644 index 0000000..e649646 --- /dev/null +++ b/test/shell/idm_fabric_failure_half_brain.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip +[ -z "$LVM_TEST_FAILURE" ] && skip + +aux prepare_devs 2 +aux extend_filter_LVMTEST + +DRIVE1=$(dmsetup deps -o devname "$dev1" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') +DRIVE2=$(dmsetup deps -o devname "$dev2" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') + +[ "$(basename -- $DRIVE1)" = "$(basename -- $DRIVE2)" ] && die "Need to pass two different drives!?" + +# The previous device-mapper are removed, but LVM still can directly +# access VGs from the specified physical drives. So enable drives +# for these drives. +aux extend_filter_LVMTEST "a|/dev/$DRIVE1*|" "a|/dev/$DRIVE2*|" +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +vgcreate $SHARED $vg "$dev1" "$dev2" + +# Create new logic volume +lvcreate -a ey --zero n -l 100%FREE -n $lv1 $vg + +drive_list=($DRIVE1) + +# Find all drives with the same WWN and delete them from system, +# so that we can emulate the same drive with multiple paths are +# disconnected with system. +drive_wwn=$(udevadm info /dev/${DRIVE1} | awk -F= '/E: ID_WWN=/ {print $2}') +for dev in /dev/*; do + if [ -b "$dev" ] && [[ ! "$dev" =~ [0-9] ]]; then + wwn=$(udevadm info "${dev}" | awk -F= '/E: ID_WWN=/ {print $2}') + if [ "$wwn" = "$drive_wwn" ]; then + base_name="$(basename -- ${dev})" + drive_list+=("$base_name") + host_list+=( $(readlink "/sys/block/$base_name" | awk -F'/' '{print $6}') ) + fi + fi +done + +for d in "${drive_list[@]}"; do + [ -f "/sys/block/$d/device/delete" ] && echo 1 > "/sys/block/$d/device/delete" +done + +# Fail to create new logic volume +not lvcreate -a n --zero n -l 1 -n $lv2 $vg + +# Wait for lock time out caused by drive failure +sleep 70 + +not check grep_lvmlockd_dump "S lvm_$vg kill_vg" + +# Rescan drives so can probe the deleted drives and join back them +for h in "${host_list[@]}"; do + [ -f "/sys/class/scsi_host/${h}/scan" ] && echo "- - -" > "/sys/class/scsi_host/${h}/scan" +done + +# After the drive is reconnected, $vg should be visible again. +vgchange --lock-start +lvremove -f $vg/$lv1 +lvcreate -a ey --zero n -l 1 -n $lv2 $vg +vgremove -ff $vg diff --git a/test/shell/idm_fabric_failure_timeout.sh b/test/shell/idm_fabric_failure_timeout.sh new file mode 100644 index 0000000..2924d81 --- /dev/null +++ b/test/shell/idm_fabric_failure_timeout.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip +[ -z "$LVM_TEST_FAILURE" ] && skip + +aux prepare_devs 1 +aux extend_filter_LVMTEST + +DRIVE1=$(dmsetup deps -o devname "$dev1" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') + +# The previous device-mapper are removed, but LVM still can directly +# access VGs from the specified physical drives. So enable drives +# for these drives. +aux extend_filter_LVMTEST "a|/dev/$DRIVE1*|" +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +vgcreate $SHARED $vg "$dev1" + +# Create new logic volume +lvcreate -a ey --zero n -l 1 -n $lv1 $vg + +drive_list=( "$DRIVE1" ) + +# Find all drives with the same WWN and delete them from system, +# so that we can emulate the same drive with multiple paths are +# disconnected with system. +drive_wwn=$(udevadm info /dev/${DRIVE1} | awk -F= '/E: ID_WWN=/ {print $2}') +for dev in /dev/*; do + if [ -b "$dev" ] && [[ ! "$dev" =~ [0-9] ]]; then + wwn=$(udevadm info "${dev}" | awk -F= '/E: ID_WWN=/ {print $2}') + if [ "$wwn" = "$drive_wwn" ]; then + base_name="$(basename -- ${dev})" + drive_list+=("$base_name") + host_list+=( $(readlink "/sys/block/$base_name" | awk -F'/' '{print $6}') ) + fi + fi +done + +for d in "${drive_list[@]}"; do + [ -f "/sys/block/$d/device/delete" ] && echo 1 > "/sys/block/$d/device/delete" +done + +# Fail to create new logic volume +not lvcreate -a n --zero n -l 1 -n $lv2 $vg + +# Wait for lock time out caused by drive failure +sleep 70 + +check grep_lvmlockd_dump "S lvm_$vg kill_vg" +lvmlockctl --drop $vg + +# Rescan drives so can probe the deleted drives and join back them +for h in "${host_list[@]}"; do + [ -f "/sys/class/scsi_host/${h}/scan" ] && echo "- - -" > "/sys/class/scsi_host/${h}/scan" +done + +# After the drive is reconnected, $vg should be visible again. +vgchange --lock-start +vgremove -ff $vg diff --git a/test/shell/idm_ilm_failure.sh b/test/shell/idm_ilm_failure.sh new file mode 100644 index 0000000..6b8e591 --- /dev/null +++ b/test/shell/idm_ilm_failure.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 Seagate, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip +[ -z "$LVM_TEST_FAILURE" ] && skip + +aux prepare_devs 3 +aux extend_filter_LVMTEST + +DRIVE1=$(dmsetup deps -o devname "$dev1" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') +DRIVE2=$(dmsetup deps -o devname "$dev2" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') +DRIVE3=$(dmsetup deps -o devname "$dev3" | awk '{gsub(/[()]/,""); print $4;}' | sed 's/[0-9]*$//') + +if [ "$DRIVE1" = "$DRIVE2" ] || [ "$DRIVE1" = "$DRIVE3" ] || [ "$DRIVE2" = "$DRIVE3" ]; then + die "Need to pass three different drives!?" +fi + +# The previous device-mapper are removed, but LVM still can directly +# access VGs from the specified physical drives. So enable drives +# for these drives. +aux extend_filter_LVMTEST "a|/dev/$DRIVE1*|" "a|/dev/$DRIVE2*|" "a|/dev/$DRIVE3*|" +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +# Create new logic volume and deactivate it +lvcreate -a y --zero n -l 1 -n $lv1 $vg + +# Inject failure 40% so cannot send partially request to drives +idm_inject_failure 40 + +# Wait for 40s, but the lock will not be time out +sleep 40 + +# Inject failure with 0% so can access drives +idm_inject_failure 0 + +# Deactivate logic volume due to locking failure +lvchange $vg/$lv1 -a n + +# Inject failure 100% so cannot send request to drives +idm_inject_failure 100 + +# Wait for 70s but should have no any alive locks +sleep 70 + +# Inject failure with 0% so can access drives +idm_inject_failure 0 + +# Activate logic volume +lvchange $vg/$lv1 -a y + +# Inject failure so cannot send request to drives +idm_inject_failure 100 + +# Wait for 70s but will not time out +sleep 70 + +# Inject failure with 0% so can access drives +idm_inject_failure 0 + +check grep_lvmlockd_dump "S lvm_$vg kill_vg" +lvmlockctl --drop $vg + +vgchange --lock-start +vgremove -f $vg diff --git a/test/shell/inconsistent-metadata.sh b/test/shell/inconsistent-metadata.sh index 9f4ffd2..e5ccf0c 100644 --- a/test/shell/inconsistent-metadata.sh +++ b/test/shell/inconsistent-metadata.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,74 +8,64 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_vg 3 12 +get_devs -lvcreate -m 1 -l 1 -n mirror $vg +lvcreate -aye --type mirror -m 1 -l 1 -n mirror $vg lvcreate -l 1 -n resized $vg lvchange -a n $vg/mirror -aux backup_dev $(cat DEVICES) +aux backup_dev "${DEVICES[@]}" -init() { - aux restore_dev $(cat DEVICES) - lvs -o lv_name,lv_size --units k $vg | tee lvs.out - grep resized lvs.out | not grep 8192 +makeold() { + # reset metadata on all devs to starting condition + aux restore_dev "${DEVICES[@]}" + not check lv_field $vg/resized lv_size "8.00m" + # change the metadata on all devs lvresize -L 8192K $vg/resized + # reset metadata on just dev1 to the previous version aux restore_dev "$dev1" } -check() { - lvs -o lv_name,lv_size --units k $vg | tee lvs.out - grep resized lvs.out | grep 8192 -} +# create old metadata +makeold + +# reports old metadata +vgs $vg 2>&1 | tee cmd.out +grep "ignoring metadata" cmd.out +check lv_field $vg/resized lv_size "8.00m" + +# corrects old metadata +lvcreate -l1 -an $vg + +# no old report +vgs $vg 2>&1 | tee cmd.out +not grep "ignoring metadata" cmd.out +check lv_field $vg/resized lv_size "8.00m" + + +echo Check auto-repair of failed vgextend +echo - metadata written to original pv but not new pv -# vgscan fixes up metadata (needs --cache option for direct scan if lvmetad is used) -test -e LOCAL_LVMETAD && cache="--cache" -init -vgscan $cache 2>&1 | tee cmd.out -grep "Inconsistent metadata found for VG $vg" cmd.out -test -e LOCAL_LVMETAD && vgrename $vg foo && vgrename foo $vg # trigger a write -vgscan $cache 2>&1 | tee cmd.out -not grep "Inconsistent metadata found for VG $vg" cmd.out -check - -# only vgscan would have noticed metadata inconsistencies when lvmetad is active -if !test -e LOCAL_LVMETAD; then - # vgdisplay fixes - init - vgdisplay $vg 2>&1 | tee cmd.out - grep "Inconsistent metadata found for VG $vg" cmd.out - vgdisplay $vg 2>&1 | tee cmd.out - not grep "Inconsistent metadata found for VG $vg" cmd.out - check - - # lvs fixes up - init - lvs $vg 2>&1 | tee cmd.out - grep "Inconsistent metadata found for VG $vg" cmd.out - vgdisplay $vg 2>&1 | tee cmd.out - not grep "Inconsistent metadata found for VG $vg" cmd.out - check - - # vgs fixes up as well - init - vgs $vg 2>&1 | tee cmd.out - grep "Inconsistent metadata found for VG $vg" cmd.out - vgs $vg 2>&1 | tee cmd.out - not grep "Inconsistent metadata found for VG $vg" cmd.out - check -fi - -echo Check auto-repair of failed vgextend - metadata written to original pv but not new pv vgremove -f $vg -pvremove -ff $(cat DEVICES) -pvcreate $(cat DEVICES) +pvremove -ff "${DEVICES[@]}" +pvcreate "${DEVICES[@]}" + aux backup_dev "$dev2" -vgcreate $vg "$dev1" +vgcreate $SHARED $vg "$dev1" vgextend $vg "$dev2" aux restore_dev "$dev2" + +vgs -o+vg_mda_count $vg +pvs -o+vg_mda_count + should check compare_fields vgs $vg vg_mda_count pvs "$dev2" vg_mda_count + +vgremove -ff $vg diff --git a/test/shell/integrity-blocksize-2.sh b/test/shell/integrity-blocksize-2.sh new file mode 100644 index 0000000..14c3bb1 --- /dev/null +++ b/test/shell/integrity-blocksize-2.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_integrity 1 5 0 || skip +# Avoid 4K ramdisk devices on older kernels +aux kernel_at_least 5 10 || export LVM_TEST_PREFER_BRD=0 + +mnt="mnt" +mkdir -p $mnt + +# prepare_devs uses ramdisk backing which has 512 LBS and 4K PBS +# This should cause mkfs.xfs to use 4K sector size, +# and integrity to use 4K block size +aux prepare_devs 2 64 + +vgcreate $vg "$dev1" "$dev2" +blockdev --getss "$dev1" +blockdev --getpbsz "$dev1" +blockdev --getss "$dev2" +blockdev --getpbsz "$dev2" + +# add integrity while LV is inactive +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +umount $mnt +lvchange -an $vg +lvconvert --raidintegrity y $vg/$lv1 +lvchange -ay $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# add integrity while LV is active, fs unmounted +# lvconvert will use ribs 512 to avoid increasing LBS from 512 to 4k on active LV +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +umount $mnt +lvchange -an $vg +lvchange -ay $vg +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# add integrity while LV is active, fs mounted +# lvconvert will use ribs 512 to avoid increasing LBS from 512 to 4k on active LV +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/integrity-blocksize-3.sh b/test/shell/integrity-blocksize-3.sh new file mode 100644 index 0000000..f86d7f7 --- /dev/null +++ b/test/shell/integrity-blocksize-3.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_integrity 1 5 0 || skip + +mnt="mnt" +mkdir -p $mnt + +# scsi_debug devices with 512 LBS 512 PBS +aux prepare_scsi_debug_dev 256 +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "512" +check sysfs "$(< SCSI_DEBUG_DEV)" queue/physical_block_size "512" +aux prepare_devs 2 64 + +vgcreate $vg "$dev1" "$dev2" +blockdev --getss "$dev1" +blockdev --getpbsz "$dev1" +blockdev --getss "$dev2" +blockdev --getpbsz "$dev2" + +# add integrity while LV is inactive +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +umount $mnt +lvchange -an $vg +lvconvert --raidintegrity y $vg/$lv1 +lvchange -ay $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# add integrity while LV is active, fs unmounted +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +umount $mnt +lvchange -an $vg +lvchange -ay $vg +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# add integrity while LV is active, fs mounted +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +vgremove -ff $vg +aux cleanup_scsi_debug_dev +sleep 1 + +# scsi_debug devices with 4K LBS and 4K PBS +aux prepare_scsi_debug_dev 256 sector_size=4096 +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "4096" +check sysfs "$(< SCSI_DEBUG_DEV)" queue/physical_block_size "4096" +aux prepare_devs 2 64 + +vgcreate $vg "$dev1" "$dev2" +blockdev --getss "$dev1" +blockdev --getpbsz "$dev1" +blockdev --getss "$dev2" +blockdev --getpbsz "$dev2" + +# add integrity while LV is inactive +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +umount $mnt +lvchange -an $vg +lvconvert --raidintegrity y $vg/$lv1 +lvchange -ay $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# add integrity while LV is active, fs unmounted +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +umount $mnt +lvchange -an $vg +lvchange -ay $vg +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# add integrity while LV is active, fs mounted +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +vgremove -ff $vg +aux cleanup_scsi_debug_dev +sleep 1 + +# scsi_debug devices with 512 LBS and 4K PBS +aux prepare_scsi_debug_dev 256 sector_size=512 physblk_exp=3 +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "512" +check sysfs "$(< SCSI_DEBUG_DEV)" queue/physical_block_size "4096" +aux prepare_devs 2 64 + +vgcreate $vg "$dev1" "$dev2" +blockdev --getss "$dev1" +blockdev --getpbsz "$dev1" +blockdev --getss "$dev2" +blockdev --getpbsz "$dev2" + +# add integrity while LV is inactive +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +umount $mnt +lvchange -an $vg +lvconvert --raidintegrity y $vg/$lv1 +lvchange -ay $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# add integrity while LV is active, fs unmounted +# lvconvert will use ribs 512 to avoid increasing LBS from 512 to 4k on active LV +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +umount $mnt +lvchange -an $vg +lvchange -ay $vg +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# add integrity while LV is active, fs mounted +# lvconvert will use ribs 512 to avoid increasing LBS from 512 to 4k on active LV +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +echo "hello world" > $mnt/hello +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +cat $mnt/hello | grep "hello world" +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +vgremove -ff $vg +aux cleanup_scsi_debug_dev diff --git a/test/shell/integrity-blocksize.sh b/test/shell/integrity-blocksize.sh new file mode 100644 index 0000000..e5d2620 --- /dev/null +++ b/test/shell/integrity-blocksize.sh @@ -0,0 +1,298 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_integrity 1 5 0 || skip + +losetup -h | grep sector-size || skip + + +cleanup_mounted_and_teardown() +{ + umount "$mnt" || true + vgremove -ff $vg1 $vg2 || true + + test -n "${LOOP1-}" && { losetup -d "$LOOP1" || true ; } + test -n "${LOOP2-}" && { losetup -d "$LOOP2" || true ; } + test -n "${LOOP3-}" && { losetup -d "$LOOP3" || true ; } + test -n "${LOOP4-}" && { losetup -d "$LOOP4" || true ; } + + rm -f loop[abcd] + aux teardown +} + +mnt="mnt" +mkdir -p $mnt + +# Tests with fs block sizes require a libblkid version that shows BLOCK_SIZE +aux prepare_devs 1 +vgcreate $vg "$dev1" +lvcreate -n $lv1 -l8 $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip +lvchange -an $vg +vgremove -ff $vg + +trap 'cleanup_mounted_and_teardown' EXIT + +# Currently (5.9-rc5 hits 'blkdev_issue_discard()' kernel WARNING) +#truncate -s 64M loopa +#truncate -s 64M loopb +#truncate -s 64M loopc +#truncate -s 64M loopd + +dd if=/dev/zero of=loopa bs=1M count=64 conv=fdatasync +dd if=/dev/zero of=loopb bs=1M count=64 conv=fdatasync +dd if=/dev/zero of=loopc bs=1M count=64 conv=fdatasync +dd if=/dev/zero of=loopd bs=1M count=64 conv=fdatasync + +LOOP1=$(losetup -f loopa --show) || skip "Cannot find free loop device" +LOOP2=$(losetup -f loopb --show) || skip "Cannot find free loop device" +LOOP3=$(losetup -f loopc --sector-size 4096 --show) || skip "Loop cannot handle --sector-size 4096" +LOOP4=$(losetup -f loopd --sector-size 4096 --show) || skip "Loop cannot handle --sector-size 4096" + +echo "$LOOP1" +echo "$LOOP2" +echo "$LOOP3" +echo "$LOOP4" + +aux extend_filter "a|$LOOP1|" "a|$LOOP2|" "a|$LOOP3|" "a|$LOOP4|" +aux extend_devices "$LOOP1" "$LOOP2" "$LOOP3" "$LOOP4" + +aux lvmconf 'devices/scan = "/dev"' + +vgcreate $vg1 "$LOOP1" "$LOOP2" +vgcreate $vg2 "$LOOP3" "$LOOP4" + +# LOOP1/LOOP2 have LBS 512 and PBS 512 +# LOOP3/LOOP4 have LBS 4K and PBS 4K + +blockdev --getss "$LOOP1" +blockdev --getpbsz "$LOOP1" +blockdev --getss "$LOOP2" +blockdev --getpbsz "$LOOP2" +blockdev --getss "$LOOP3" +blockdev --getpbsz "$LOOP3" +blockdev --getss "$LOOP4" +blockdev --getpbsz "$LOOP4" + +# lvcreate on dev512, result 512 +lvcreate --type raid1 -m1 --raidintegrity y -l 8 -n $lv1 $vg1 +pvck --dump metadata "$LOOP1" | grep 'block_size = 512' +lvremove -y $vg1/$lv1 + +# lvcreate on dev4k, result 4k +lvcreate --type raid1 -m1 --raidintegrity y -l 8 -n $lv1 $vg2 +pvck --dump metadata "$LOOP3" | grep 'block_size = 4096' +lvremove -y $vg2/$lv1 + +# lvcreate --bs 512 on dev4k, result fail +not lvcreate --type raid1 -m1 --raidintegrity y --raidintegrityblocksize 512 -l 8 -n $lv1 $vg2 + +# lvcreate --bs 4096 on dev512, result 4k +lvcreate --type raid1 -m1 --raidintegrity y --raidintegrityblocksize 4096 -l 8 -n $lv1 $vg1 +lvs -o raidintegrityblocksize $vg1/$lv1 | grep 4096 +pvck --dump metadata "$LOOP1" | grep 'block_size = 4096' +lvremove -y $vg1/$lv1 + +# Test an unknown fs block size by simply not creating a fs on the lv. + +# lvconvert on dev512, fsunknown, result 512 +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +# clear any residual fs so that libblkid cannot find an fs block size +aux wipefs_a "$DM_DEV_DIR/$vg1/$lv1" +lvconvert --raidintegrity y $vg1/$lv1 +pvck --dump metadata "$LOOP1" | grep 'block_size = 512' +lvremove -y $vg1/$lv1 + +# lvconvert on dev4k, fsunknown, result 4k +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg2 +# clear any residual fs so that libblkid cannot find an fs block size +aux wipefs_a "$DM_DEV_DIR//$vg2/$lv1" +lvconvert --raidintegrity y $vg2/$lv1 +pvck --dump metadata $LOOP3 | grep 'block_size = 4096' +lvremove -y $vg2/$lv1 + +# lvconvert --bs 4k on dev512, fsunknown, result fail +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +# clear any residual fs so that libblkid cannot find an fs block size +aux wipefs_a "$DM_DEV_DIR//$vg1/$lv1" +not lvconvert --raidintegrity y --raidintegrityblocksize 4096 $vg1/$lv1 +lvremove -y $vg1/$lv1 + +# lvconvert --bs 512 on dev4k, fsunknown, result fail +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg2 +# clear any residual fs so that libblkid cannot find an fs block size +aux wipefs_a "$DM_DEV_DIR//$vg2/$lv1" +not lvconvert --raidintegrity y --raidintegrityblocksize 512 $vg2/$lv1 +lvremove -y $vg2/$lv1 + +# lvconvert on dev512, ext4 1024, result 1024 +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +aux wipefs_a "$DM_DEV_DIR//$vg1/$lv1" +mkfs.ext4 "$DM_DEV_DIR/$vg1/$lv1" +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | tee out +grep BLOCK_SIZE=\"1024\" out +lvconvert --raidintegrity y $vg1/$lv1 +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +mount "$DM_DEV_DIR/$vg1/$lv1" $mnt +umount $mnt +pvck --dump metadata "$LOOP1" | grep 'block_size = 512' +lvremove -y $vg1/$lv1 + +# lvconvert on dev4k, ext4 4096, result 4096 +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg2 +aux wipefs_a "$DM_DEV_DIR/$vg2/$lv1" +mkfs.ext4 "$DM_DEV_DIR/$vg2/$lv1" +blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\" +lvconvert --raidintegrity y $vg2/$lv1 +blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\" +mount "$DM_DEV_DIR/$vg2/$lv1" $mnt +umount $mnt +pvck --dump metadata $LOOP3 | grep 'block_size = 4096' +lvremove -y $vg2/$lv1 + +# lvconvert on dev512, ext4 1024, result 1024 (LV active when adding) +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +aux wipefs_a "$DM_DEV_DIR//$vg1/$lv1" +mkfs.ext4 -b 1024 "$DM_DEV_DIR/$vg1/$lv1" +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +lvconvert --raidintegrity y $vg1/$lv1 +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +mount "$DM_DEV_DIR/$vg1/$lv1" $mnt +umount $mnt +pvck --dump metadata "$LOOP1" | grep 'block_size = 512' +lvremove -y $vg1/$lv1 + +# lvconvert on dev512, ext4 1024, result 1024 (LV inactive when adding) +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +aux wipefs_a "$DM_DEV_DIR//$vg1/$lv1" +mkfs.ext4 -b 1024 "$DM_DEV_DIR/$vg1/$lv1" +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +lvchange -an $vg1/$lv1 +lvconvert --raidintegrity y $vg1/$lv1 +lvchange -ay $vg1/$lv1 +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +mount "$DM_DEV_DIR/$vg1/$lv1" $mnt +umount $mnt +pvck --dump metadata "$LOOP1" | grep 'block_size = 1024' +lvremove -y $vg1/$lv1 + +# lvconvert on dev4k, ext4 4096, result 4096 +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg2 +aux wipefs_a "$DM_DEV_DIR//$vg2/$lv1" +mkfs.ext4 "$DM_DEV_DIR/$vg2/$lv1" +blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\" +lvconvert --raidintegrity y $vg2/$lv1 +blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\" +mount "$DM_DEV_DIR/$vg2/$lv1" $mnt +umount $mnt +pvck --dump metadata "$LOOP3" | grep 'block_size = 4096' +lvremove -y $vg2/$lv1 + +# lvconvert --bs 512 on dev512, ext4 4096, result 512 +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +aux wipefs_a "$DM_DEV_DIR//$vg1/$lv1" +mkfs.ext4 -b 4096 "$DM_DEV_DIR/$vg1/$lv1" +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\" +lvconvert --raidintegrity y --raidintegrityblocksize 512 $vg1/$lv1 +lvs -o raidintegrityblocksize $vg1/$lv1 | grep 512 +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\" +mount "$DM_DEV_DIR/$vg1/$lv1" $mnt +umount $mnt +pvck --dump metadata "$LOOP1" | grep 'block_size = 512' +lvremove -y $vg1/$lv1 + +# lvconvert --bs 1024 on dev512, ext4 4096, result 1024 +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +aux wipefs_a "$DM_DEV_DIR//$vg1/$lv1" +mkfs.ext4 -b 4096 "$DM_DEV_DIR/$vg1/$lv1" +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\" +lvchange -an $vg1/$lv1 +# lv needs to be inactive to increase LBS from 512 +lvconvert --raidintegrity y --raidintegrityblocksize 1024 $vg1/$lv1 +lvs -o raidintegrityblocksize $vg1/$lv1 | grep 1024 +lvchange -ay $vg1/$lv1 +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"4096\" +mount "$DM_DEV_DIR/$vg1/$lv1" $mnt +umount $mnt +pvck --dump metadata "$LOOP1" | grep 'block_size = 1024' +lvremove -y $vg1/$lv1 + +# lvconvert --bs 512 on dev512, ext4 1024, result 512 +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +aux wipefs_a "$DM_DEV_DIR//$vg1/$lv1" +mkfs.ext4 -b 1024 "$DM_DEV_DIR/$vg1/$lv1" +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +lvconvert --raidintegrity y --raidintegrityblocksize 512 $vg1/$lv1 +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +mount "$DM_DEV_DIR/$vg1/$lv1" $mnt +umount $mnt +pvck --dump metadata "$LOOP1" | grep 'block_size = 512' +lvremove -y $vg1/$lv1 + +# lvconvert --bs 512 on dev4k, ext4 4096, result fail +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg2 +aux wipefs_a "$DM_DEV_DIR//$vg2/$lv1" +mkfs.ext4 "$DM_DEV_DIR/$vg2/$lv1" +not lvconvert --raidintegrity y --raidintegrityblocksize 512 $vg2/$lv1 +lvremove -y $vg2/$lv1 + +# TODO: need to use scsi_debug to create devs with LBS 512 PBS 4k +# TODO: lvconvert, fsunknown, LBS 512, PBS 4k: result 512 +# TODO: lvconvert --bs 512, fsunknown, LBS 512, PBS 4k: result 512 +# TODO: lvconvert --bs 4k, fsunknown, LBS 512, PBS 4k: result 4k + +# lvconvert on dev512, ext4 1024, result 1024, (detect fs with LV inactive) +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg1 +aux wipefs_a "$DM_DEV_DIR//$vg1/$lv1" +mkfs.ext4 "$DM_DEV_DIR/$vg1/$lv1" +mount "$DM_DEV_DIR/$vg1/$lv1" $mnt +echo "test" > $mnt/test +umount $mnt +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +lvchange -an $vg1/$lv1 +lvconvert --raidintegrity y $vg1/$lv1 +lvchange -ay $vg1/$lv1 +mount "$DM_DEV_DIR/$vg1/$lv1" $mnt +cat $mnt/test +umount $mnt +blkid -p "$DM_DEV_DIR/$vg1/$lv1" | grep BLOCK_SIZE=\"1024\" +pvck --dump metadata "$LOOP1" | tee out +grep 'block_size = 1024' out +lvchange -an $vg1/$lv1 +lvremove -y $vg1/$lv1 + +# lvconvert on dev4k, ext4 4096, result 4096 (detect fs with LV inactive) +lvcreate --type raid1 -m1 -l 8 -n $lv1 $vg2 +aux wipefs_a "$DM_DEV_DIR//$vg2/$lv1" +mkfs.ext4 "$DM_DEV_DIR/$vg2/$lv1" +mount "$DM_DEV_DIR/$vg2/$lv1" $mnt +echo "test" > $mnt/test +umount $mnt +blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\" +lvchange -an $vg2/$lv1 +lvconvert --raidintegrity y $vg2/$lv1 +lvchange -ay $vg2/$lv1 +mount "$DM_DEV_DIR/$vg2/$lv1" $mnt +cat $mnt/test +umount $mnt +blkid -p "$DM_DEV_DIR/$vg2/$lv1" | grep BLOCK_SIZE=\"4096\" +pvck --dump metadata "$LOOP3" | tee out +grep 'block_size = 4096' out +lvchange -an $vg2/$lv1 +lvremove -y $vg2/$lv1 + +# remove of $vg1, $vg2 and loops in cleanup_mounted_and_teardown() diff --git a/test/shell/integrity-caching.sh b/test/shell/integrity-caching.sh new file mode 100644 index 0000000..72fb4af --- /dev/null +++ b/test/shell/integrity-caching.sh @@ -0,0 +1,527 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +which resize2fs || skip +aux have_integrity 1 5 0 || skip +# Avoid 4K ramdisk devices on older kernels +aux kernel_at_least 5 10 || export LVM_TEST_PREFER_BRD=0 + +mnt="mnt" +mkdir -p $mnt + +aux prepare_devs 9 80 + +# Use awk instead of anoyingly long log out from printf +#printf "%0.sA" {1..16384} >> fileA +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 4096) printf "B" ; while (z++ < 16384) printf "b" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_prepare_vg() { + # zero devs so we are sure to find the correct file data + # on the underlying devs when corrupting it + aux clear_devs "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" + pvs +} + +_test_fs_with_read_repair() { + mkfs.ext4 -b 4096 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + cp randA $mnt + cp randB $mnt + cp randC $mnt + cp fileA $mnt + cp fileB $mnt + cp fileC $mnt + + # The files written above are in the writecache so reading + # them back later will come from the writecache and not from the + # corrupted dev. Write a bunch of new data to the fs to clear + # the original files from the writecache, so when they are read + # back the data will hopefully come from the underlying disk and + # trigger reading the corrupted data. + mkdir $mnt/new1 + cat randA > $mnt/new1/randA + cat randB > $mnt/new1/randB + cat randC > $mnt/new1/randC + sync + du -h $mnt/new1 + cp -r $mnt/new1 $mnt/new2 || true + cp -r $mnt/new1 $mnt/new3 || true + cp -r $mnt/new1 $mnt/new4 || true + sync + du -h $mnt + df -h + # hopefully fileA is no longer in the writecache. + + umount $mnt + lvchange -an $vg/$lv1 + for dev in "$@"; do + aux corrupt_dev "$dev" BBBBBBBBBBBBBBBBB BBBBBBBBCBBBBBBBB + done + + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + cmp -b $mnt/fileA fileA + cmp -b $mnt/fileB fileB + cmp -b $mnt/fileC fileC + umount $mnt +} + +_add_new_data_to_mnt() { + mkfs.ext4 -b 4096 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 +} + +_add_more_data_to_mnt() { + mkdir $mnt/more + cp fileA $mnt/more + cp fileB $mnt/more + cp fileC $mnt/more + cp randA $mnt/more + cp randB $mnt/more + cp randC $mnt/more +} + +_verify_data_on_mnt() { + cmp -b randA $mnt/randA + cmp -b randB $mnt/randB + cmp -b randC $mnt/randC + cmp -b fileA $mnt/1/fileA + cmp -b fileB $mnt/1/fileB + cmp -b fileC $mnt/1/fileC + cmp -b fileA $mnt/2/fileA + cmp -b fileB $mnt/2/fileB + cmp -b fileC $mnt/2/fileC +} + +_verify_data_on_lv() { + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + _verify_data_on_mnt + rm $mnt/randA + rm $mnt/randB + rm $mnt/randC + rm -rf $mnt/1 + rm -rf $mnt/2 + umount $mnt + lvchange -an $vg/$lv1 +} + +# lv1 is a raid+integrity LV +# three variations of caching on lv1: +# +# 1. lvcreate --type cache-pool -n fast -l 4 $vg $dev6 +# lvconvert --type cache --cachepool fast $vg/$lv1 +# +# 2. lvcreate --type linear -n fast -l 4 $vg $dev6 +# lvconvert --type cache --cachvol fast $vg/$lv1 +# +# 3. lvcreate --type linear -n fast -l 4 $vg $dev6 +# lvconvert --type writecache --cachvol fast $vg/$lv1 + +do_test() { + +# --cachepool | --cachevol +local create_type=$1 + +# cache | writecache +local convert_type=$2 + +# --type cache-pool | --type linear +local convert_option=$3 + +# corig | wcorig +local suffix=$4 + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +aux wait_recalc $vg/${lv1}_${suffix} +_test_fs_with_read_repair "$dev1" +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_0 |tee mismatch +not grep ' 0 ' mismatch +lvs -o integritymismatches $vg/${lv1}_${suffix} |tee mismatch +not grep ' 0 ' mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/${lv1}_${suffix} +lvs -a -o name,size,segtype,devices,sync_percent $vg +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid1 -m2 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3" +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_2 +aux wait_recalc $vg/${lv1}_${suffix} +_test_fs_with_read_repair "$dev1" "$dev2" +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_0 |tee mismatch +not grep ' 0 ' mismatch +lvs -o integritymismatches $vg/${lv1}_${suffix} |tee mismatch +not grep ' 0 ' mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/${lv1}_${suffix} +lvconvert --splitcache $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid5 --raidintegrity y -n $lv1 -I4 -l 8 $vg "$dev1" "$dev2" "$dev3" +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_2 +aux wait_recalc $vg/${lv1}_${suffix} +_test_fs_with_read_repair "$dev1" "$dev2" "$dev3" +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_0 +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_1 +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_2 +lvs -o integritymismatches $vg/${lv1}_${suffix} |tee mismatch +not grep ' 0 ' mismatch +lvconvert --splitcache $vg/$lv1 +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test removing integrity from an active LV + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +aux wait_recalc $vg/${lv1}_${suffix} +_add_new_data_to_mnt +lvconvert --raidintegrity n $vg/${lv1}_${suffix} +_add_more_data_to_mnt +lvconvert --splitcache $vg/$lv1 +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test adding integrity to an active LV + +_prepare_vg +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +aux wait_recalc $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_new_data_to_mnt +# Can only be enabled while raid is top level lv (for now.) +not lvconvert --raidintegrity y $vg/${lv1}_${suffix} +#aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +#aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test lvextend while inactive + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_new_data_to_mnt +umount $mnt +lvchange -an $vg/$lv1 +# use two new devs for raid extend to ensure redundancy +vgextend $vg "$dev7" "$dev8" +lvs -a -o name,segtype,devices $vg +lvextend -l 16 $vg/$lv1 "$dev7" "$dev8" +lvs -a -o name,segtype,devices $vg +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +resize2fs "$DM_DEV_DIR/$vg/$lv1" +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test lvextend while active + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +# use two new devs for raid extend to ensure redundancy +vgextend $vg "$dev7" "$dev8" +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_new_data_to_mnt +lvextend -l 16 $vg/$lv1 "$dev7" "$dev8" +lvs -a -o name,size,segtype,devices,sync_percent $vg +resize2fs "$DM_DEV_DIR/$vg/$lv1" +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid5 --raidintegrity y -n $lv1 -I4 -l 8 $vg "$dev1" "$dev2" "$dev3" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +vgextend $vg "$dev7" "$dev8" "$dev9" +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_new_data_to_mnt +lvextend -l 16 $vg/$lv1 "$dev7" "$dev8" "$dev9" +lvs -a -o name,size,segtype,devices,sync_percent $vg +resize2fs "$DM_DEV_DIR/$vg/$lv1" +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test adding image to raid1 + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_new_data_to_mnt +# currently only allowed while raid is top level lv +not lvconvert -y -m+1 $vg/${lv1}_${suffix} +#aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +#aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +#aux wait_recalc $vg/${lv1}_${suffix}_rimage_2 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test removing image from raid1 + +_prepare_vg +lvcreate --type raid1 -m2 --raidintegrity y -n $lv1 -l 8 $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_new_data_to_mnt +lvconvert -y -m-1 $vg/${lv1}_${suffix} +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test disallowed operations on raid+integrity + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_new_data_to_mnt +not lvconvert -y -m-1 $vg/$lv1 +not lvconvert -y -m-1 $vg/${lv1}_${suffix} +not lvconvert --splitmirrors 1 -n tmp -y $vg/$lv1 +not lvconvert --splitmirrors 1 -n tmp -y $vg/${lv1}_${suffix} +not lvconvert --splitmirrors 1 --trackchanges -y $vg/$lv1 +not lvconvert --splitmirrors 1 --trackchanges -y $vg/${lv1}_${suffix} +not lvchange --syncaction repair $vg/$lv1 +not lvchange --syncaction repair $vg/${lv1}_${suffix} +not lvreduce -L4M $vg/$lv1 +not lvreduce -L4M $vg/${lv1}_${suffix} +not lvcreate -s -n snap -L4M $vg/${lv1}_${suffix} +# plan to enable snap on top level raid+integrity, so then +# snap+writecache+raid+integrity should be allowed. +not lvcreate -s -n snap -L4M $vg/$lv1 +lvs -a -o name,size,segtype,devices +not pvmove -n $vg/$lv1 "$dev1" +not pvmove -n $vg/${lv1}_${suffix} "$dev1" +not pvmove "$dev1" +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Repeat many of the tests above using bitmap mode + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg "$dev1" "$dev2" +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +aux wait_recalc $vg/${lv1}_${suffix} +_test_fs_with_read_repair "$dev1" +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_0 |tee mismatch +not grep ' 0 ' mismatch +lvs -o integritymismatches $vg/${lv1}_${suffix} |tee mismatch +not grep ' 0 ' mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/${lv1}_${suffix} +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid6 --raidintegrity y --raidintegritymode bitmap -n $lv1 -I4 -l 8 $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_2 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_3 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_4 +aux wait_recalc $vg/${lv1}_${suffix} +_test_fs_with_read_repair "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_0 +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_1 +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_2 +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_3 +lvs -o integritymismatches $vg/${lv1}_${suffix}_rimage_4 +lvs -o integritymismatches $vg/${lv1}_${suffix} |tee mismatch +not grep ' 0 ' mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/${lv1}_${suffix} +lvremove $vg/$lv1 +vgremove -ff $vg + +# remove from active lv +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +_add_new_data_to_mnt +lvconvert --raidintegrity n $vg/${lv1}_${suffix} +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# add to active lv +_prepare_vg +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +_add_new_data_to_mnt +lvconvert --raidintegrity y --raidintegritymode bitmap $vg/$lv1 +lvcreate --type $create_type -n fast -l 4 -an $vg "$dev6" +lvconvert -y --type $convert_type $convert_option fast $vg/$lv1 +lvs -a -o name,size,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_${suffix}_rimage_0 +aux wait_recalc $vg/${lv1}_${suffix}_rimage_1 +aux wait_recalc $vg/${lv1}_${suffix} +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg +} + +do_test cache-pool cache --cachepool corig +do_test linear cache --cachevol corig +do_test linear writecache --cachevol wcorig + +# TODO: add do_test() variant that skips adding the cache to lv1. +# This would be equivalent to integrity.sh which could be dropped. diff --git a/test/shell/integrity-dmeventd.sh b/test/shell/integrity-dmeventd.sh new file mode 100644 index 0000000..f3bc122 --- /dev/null +++ b/test/shell/integrity-dmeventd.sh @@ -0,0 +1,263 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_integrity 1 5 0 || skip +# Avoid 4K ramdisk devices on older kernels +aux kernel_at_least 5 10 || export LVM_TEST_PREFER_BRD=0 + +mnt="mnt" +mkdir -p $mnt + +aux prepare_devs 6 64 + +# Use awk instead of anoyingly long log out from printf +#printf "%0.sA" {1..16384} >> fileA +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 16384) printf "B" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_prepare_vg() { + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" + pvs +} + +_add_new_data_to_mnt() { + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 +} + +_add_more_data_to_mnt() { + mkdir $mnt/more + cp fileA $mnt/more + cp fileB $mnt/more + cp fileC $mnt/more + cp randA $mnt/more + cp randB $mnt/more + cp randC $mnt/more +} + +_verify_data_on_mnt() { + diff randA $mnt/randA + diff randB $mnt/randB + diff randC $mnt/randC + diff fileA $mnt/1/fileA + diff fileB $mnt/1/fileB + diff fileC $mnt/1/fileC + diff fileA $mnt/2/fileA + diff fileB $mnt/2/fileB + diff fileC $mnt/2/fileC +} + +_verify_data_on_lv() { + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + _verify_data_on_mnt + rm $mnt/randA + rm $mnt/randB + rm $mnt/randC + rm -rf $mnt/1 + rm -rf $mnt/2 + umount $mnt + lvchange -an $vg/$lv1 +} + +aux lvmconf \ + 'activation/raid_fault_policy = "allocate"' + +aux prepare_dmeventd + +# raid1, one device fails, dmeventd calls repair + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" +lvcreate --type raid1 -m 2 --raidintegrity y --ignoremonitoring -l 8 -n $lv1 $vg "$dev1" "$dev2" "$dev3" +lvchange --monitor y $vg/$lv1 +lvs -a -o+devices $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_for_sync $vg $lv1 +_add_new_data_to_mnt + +aux disable_dev "$dev2" + +# wait for dmeventd to call lvconvert --repair which should +# replace dev2 with dev4 +sync +sleep 5 + +lvs -a -o+devices $vg | tee out +not grep "$dev2" out +grep "$dev4" out + +_add_more_data_to_mnt +_verify_data_on_mnt + +aux enable_dev "$dev2" + +lvs -a -o+devices $vg | tee out +not grep "$dev2" out +grep "$dev4" out +grep "$dev1" out +grep "$dev3" out + +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# raid1, two devices fail, dmeventd calls repair + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvcreate --type raid1 -m 2 --raidintegrity y --ignoremonitoring -l 8 -n $lv1 $vg "$dev1" "$dev2" "$dev3" +lvchange --monitor y $vg/$lv1 +lvs -a -o+devices $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_for_sync $vg $lv1 +_add_new_data_to_mnt + +aux disable_dev "$dev1" "$dev2" + +# wait for dmeventd to call lvconvert --repair which should +# replace dev1 and dev2 with dev4 and dev5 +sync +sleep 5 + +lvs -a -o+devices $vg | tee out +not grep "$dev1" out +not grep "$dev2" out +grep "$dev4" out +grep "$dev5" out +grep "$dev3" out + +_add_more_data_to_mnt +_verify_data_on_mnt + +aux enable_dev "$dev1" "$dev2" + +lvs -a -o+devices $vg | tee out +not grep "$dev1" out +not grep "$dev2" out +grep "$dev4" out +grep "$dev5" out +grep "$dev3" out + +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# raid6, one device fails, dmeventd calls repair + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" +lvcreate --type raid6 --raidintegrity y --ignoremonitoring -l 8 -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvchange --monitor y $vg/$lv1 +lvs -a -o+devices $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/${lv1}_rimage_3 +aux wait_recalc $vg/${lv1}_rimage_4 +aux wait_for_sync $vg $lv1 +_add_new_data_to_mnt + +aux disable_dev "$dev2" + +# wait for dmeventd to call lvconvert --repair which should +# replace dev2 with dev6 +sync +sleep 5 + +lvs -a -o+devices $vg | tee out +not grep "$dev2" out +grep "$dev6" out + +_add_more_data_to_mnt +_verify_data_on_mnt + +aux enable_dev "$dev2" + +lvs -a -o+devices $vg | tee out +not grep "$dev2" out +grep "$dev6" out + +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# raid10, one device fails, dmeventd calls repair + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvcreate --type raid10 --raidintegrity y --ignoremonitoring -l 8 -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev4" +lvchange --monitor y $vg/$lv1 +lvs -a -o+devices $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/${lv1}_rimage_3 +aux wait_for_sync $vg $lv1 +_add_new_data_to_mnt + +aux disable_dev "$dev1" + +# wait for dmeventd to call lvconvert --repair which should +# replace dev1 with dev5 +sync +sleep 5 + +lvs -a -o+devices $vg | tee out +not grep "$dev1" out +grep "$dev5" out + +_add_more_data_to_mnt +_verify_data_on_mnt + +aux enable_dev "$dev1" + +lvs -a -o+devices $vg | tee out +not grep "$dev1" out +grep "$dev5" out + +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg diff --git a/test/shell/integrity-large.sh b/test/shell/integrity-large.sh new file mode 100644 index 0000000..37823ab --- /dev/null +++ b/test/shell/integrity-large.sh @@ -0,0 +1,177 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test writecache usage + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LOW_SPACE=1100 + +. lib/inittest + +aux have_integrity 1 5 0 || skip +which mkfs.xfs || skip + +mnt="mnt" +mkdir -p $mnt + +# raid1 LV needs to be extended to 512MB to test imeta being exended +aux prepare_devs 4 632 + +# this test may consume lot of disk space - so make sure cleaning works +# also in failure case +cleanup_mounted_and_teardown() +{ + umount "$mnt" 2>/dev/null || true + # Comment out this 'vgremove' when there is any need to analyze + # content of the failed test dir, otherwise all is deleted. + vgremove -ff $vg || true + aux teardown +} + +trap 'cleanup_mounted_and_teardown' EXIT + +# Use awk instead of anoyingly long log out from printf +#printf "%0.sA" {1..16384} >> fileA +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 16384) printf "B" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_prepare_vg() { + vgcreate $SHARED $vg "$dev1" "$dev2" + pvs +} + +_add_data_to_lv() { + mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 + + umount $mnt +} + +_verify_data_on_lv() { + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + diff randA $mnt/randA + diff randB $mnt/randB + diff randC $mnt/randC + diff fileA $mnt/1/fileA + diff fileB $mnt/1/fileB + diff fileC $mnt/1/fileC + diff fileA $mnt/2/fileA + diff fileB $mnt/2/fileB + diff fileC $mnt/2/fileC + + umount $mnt +} + +# lvextend to 512MB is needed for the imeta LV to +# be extended from 4MB to 8MB. + +_prepare_vg +lvcreate --type raid1 -m1 -n $lv1 -L 300 $vg +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +_add_data_to_lv +# lv needs to be inactive when adding integrity to increase LBS from 512 and get a ribs of 4k +lvchange -an $vg/$lv1 +lvconvert --raidintegrity y $vg/$lv1 +lvchange -ay $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +_verify_data_on_lv +lvchange -an $vg/$lv1 +lvextend -L 512M $vg/$lv1 +lvs -a -o+devices $vg +lvchange -ay $vg/$lv1 +_verify_data_on_lv +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +check lv_field $vg/${lv1}_rimage_0_imeta size "12.00m" +check lv_field $vg/${lv1}_rimage_1_imeta size "12.00m" + +# provide space to extend the images onto new devs +vgextend $vg "$dev3" "$dev4" + +# extending the images is possible using dev3,dev4 +# but extending imeta on the existing dev1,dev2 fails +not lvextend -L +512M $vg/$lv1 + +# removing integrity will permit extending the images +# using dev3,dev4 since imeta limitation is gone +lvconvert --raidintegrity n $vg/$lv1 +lvextend -L +512M $vg/$lv1 +lvs -a -o+devices $vg + +# adding integrity again will allocate new 12MB imeta LVs +# on dev3,dev4 +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +check lv_field $vg/${lv1}_rimage_0_imeta size "20.00m" +check lv_field $vg/${lv1}_rimage_1_imeta size "20.00m" + +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 + +# As the test doesn't wait for full resync +# delay legs so not all data need to be written. +aux delay_dev "$dev1" 1000 0 "$(( $(get first_extent_sector "$dev1") + 16000 )):1200000" +aux delay_dev "$dev2" 0 10 "$(( $(get first_extent_sector "$dev2") + 16000 )):1200000" + + +# this succeeds because dev1,dev2 can hold rmeta+rimage +lvcreate --type raid1 -n $lv1 -L 592M -an $vg "$dev1" "$dev2" +lvs -a -o+devices $vg +lvremove $vg/$lv1 + +# this fails because dev1,dev2 can hold rmeta+rimage, but not imeta +# and we require imeta to be on same devs as rmeta/rimeta +not lvcreate --type raid1 --raidintegrity y -n $lv1 -L 624M -an $vg "$dev1" "$dev2" +lvs -a -o+devices $vg + +# this can allocate from more devs so there's enough space for imeta to +# be allocated in the vg, but lvcreate fails because rmeta+rimage are +# allocated from dev1,dev2, we restrict imeta to being allocated on the +# same devs as rmeta/rimage, and dev1,dev2 can't fit imeta. +not lvcreate --type raid1 --raidintegrity y -n $lv1 -L 624M -an $vg +lvs -a -o+devices $vg + +# counterintuitively, increasing the size will allow lvcreate to succeed +# because rmeta+rimage are pushed to being allocated on dev1,dev2,dev3,dev4 +# which means imeta is now free to be allocated from dev3,dev4 which have +# plenty of space +lvcreate --type raid1 --raidintegrity y -n $lv1 -L 640M -an $vg +lvs -a -o+devices $vg + +vgremove -ff $vg diff --git a/test/shell/integrity-misc.sh b/test/shell/integrity-misc.sh new file mode 100644 index 0000000..3ab0c2b --- /dev/null +++ b/test/shell/integrity-misc.sh @@ -0,0 +1,216 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_integrity 1 5 0 || skip +# Avoid 4K ramdisk devices on older kernels +aux kernel_at_least 5 10 || export LVM_TEST_PREFER_BRD=0 + +mnt="mnt" +mkdir -p $mnt + +aux prepare_devs 5 64 + +# Use awk instead of anoyingly long log out from printf +#printf "%0.sA" {1..16384} >> fileA +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 16384) printf "B" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_prepare_vg() { + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + pvs +} + +_add_new_data_to_mnt() { + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 +} + +_add_more_data_to_mnt() { + mkdir $mnt/more + cp fileA $mnt/more + cp fileB $mnt/more + cp fileC $mnt/more + cp randA $mnt/more + cp randB $mnt/more + cp randC $mnt/more +} + +_verify_data_on_mnt() { + diff randA $mnt/randA + diff randB $mnt/randB + diff randC $mnt/randC + diff fileA $mnt/1/fileA + diff fileB $mnt/1/fileB + diff fileC $mnt/1/fileC + diff fileA $mnt/2/fileA + diff fileB $mnt/2/fileB + diff fileC $mnt/2/fileC +} + +_verify_data_on_lv() { + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + _verify_data_on_mnt + rm $mnt/randA + rm $mnt/randB + rm $mnt/randC + rm -rf $mnt/1 + rm -rf $mnt/2 + umount $mnt + lvchange -an $vg/$lv1 +} + +# lvrename +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +umount $mnt +lvrename $vg/$lv1 $vg/$lv2 +mount "$DM_DEV_DIR/$vg/$lv2" $mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv2 +lvremove $vg/$lv2 +vgremove -ff $vg + +# lvconvert --replace +# an existing dev is replaced with another dev +# lv must be active +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvs -o raidintegritymode $vg/$lv1 | grep journal +_add_new_data_to_mnt +lvconvert --replace "$dev1" $vg/$lv1 "$dev3" +lvs -a -o+devices $vg > out +cat out +grep "$dev2" out +grep "$dev3" out +not grep "$dev1" out +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# lvconvert --replace +# same as prev but with bitmap mode +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvs -o raidintegritymode $vg/$lv1 | grep bitmap +_add_new_data_to_mnt +lvconvert --replace "$dev1" $vg/$lv1 "$dev3" +lvs -a -o+devices $vg > out +cat out +grep "$dev2" out +grep "$dev3" out +not grep "$dev1" out +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# lvconvert --repair +# while lv is active a device goes missing (with rimage,rmeta,imeta,orig). +# lvconvert --repair should replace the missing dev with another, +# (like lvconvert --replace does for a dev that's not missing). +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +aux disable_dev "$dev2" +lvs -a -o+devices $vg > out +cat out +grep unknown out +lvconvert -vvvv -y --repair $vg/$lv1 +lvs -a -o+devices $vg > out +cat out +not grep "$dev2" out +not grep unknown out +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 +aux enable_dev "$dev2" +vgremove -ff $vg + +# lvchange activationmode +# a device is missing (with rimage,rmeta,imeta,iorig), the lv +# is already inactive, and it cannot be activated, with +# activationmode degraded or partial, or in any way, +# until integrity is removed. + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +umount $mnt +lvchange -an $vg/$lv1 +aux disable_dev "$dev2" +lvs -a -o+devices $vg +not lvchange -ay $vg/$lv1 +not lvchange -ay --activationmode degraded $vg/$lv1 +not lvchange -ay --activationmode partial $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvchange -ay --activationmode degraded $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvremove $vg/$lv1 +aux enable_dev "$dev2" +vgremove -ff $vg + diff --git a/test/shell/integrity-syncaction.sh b/test/shell/integrity-syncaction.sh new file mode 100644 index 0000000..4bd4acc --- /dev/null +++ b/test/shell/integrity-syncaction.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_integrity 1 5 0 || skip +# Avoid 4K ramdisk devices on older kernels +aux kernel_at_least 5 10 || export LVM_TEST_PREFER_BRD=0 + +mnt="mnt" +mkdir -p $mnt + +aux prepare_devs 3 40 + +# Use awk instead of anoyingly long log out from printf +#printf "%0.sA" {1..16384} >> fileA +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 4096) printf "B" ; while (z++ < 16384) printf "b" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +_prepare_vg() { + # zero devs so we are sure to find the correct file data + # on the underlying devs when corrupting it + aux clear_devs "$dev1" "$dev2" "$dev3" + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + pvs +} + +_test1() { + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + cp fileA $mnt + cp fileB $mnt + cp fileC $mnt + + umount $mnt + lvchange -an $vg/$lv1 + + # Corrupting raid1 is simple - 1 leg needs to be modifed + # For raid5 corrupted block can be places on any of its leg. + for i in "$@" ; do + aux corrupt_dev "$i" BBBBBBBBBBBBBBBBB BBBBBBBBCBBBBBBBB |& tee out + grep -q "copied" out && break # leg found and corrupted + done + + lvchange -ay $vg/$lv1 + + # so without synchecking the array - integrity doesn't know yet about failure + check lv_field $vg/${lv1}_rimage_0 integritymismatches "0" + check lv_field $vg/${lv1}_rimage_1 integritymismatches "0" + [ $# -gt 2 ] && check lv_field $vg/${lv1}_rimage_2 integritymismatches "0" + + lvchange --syncaction check $vg/$lv1 + + aux wait_recalc $vg/$lv1 + + # after synaction check - integrity should recognize faulty devices + baddev=0 + for i in 0 1 2 ; do + [ "$i" -gt 1 ] && [ $# -lt 3 ] && continue # only raid5 has rimage_2 + [ "$(get lv_field $vg/${lv1}_rimage_${i} integritymismatches)" = "0" ] || baddev=$(( baddev + 1 )) + done + [ "$baddev" -eq 1 ] || die "Unexpected number of integritymismatched devices ($baddev)!" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + cmp -b $mnt/fileA fileA + cmp -b $mnt/fileB fileB + cmp -b $mnt/fileC fileC + umount $mnt +} + +_test2() { + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + cp fileA $mnt + cp fileB $mnt + cp fileC $mnt + + umount $mnt + lvchange -an $vg/$lv1 + + # corrupt fileB and fileC on dev1 + aux corrupt_dev "$dev1" BBBBBBBBBBBBBBBBB BBBBBBBBCBBBBBBBB + aux corrupt_dev "$dev1" CCCCCCCCCCCCCCCCC DDDDDDDDDDDDDDDDD + + # corrupt fileA on dev2 + aux corrupt_dev "$dev2" AAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAA + + lvchange -ay $vg/$lv1 + + check lv_field $vg/${lv1}_rimage_0 integritymismatches "0" + check lv_field $vg/${lv1}_rimage_1 integritymismatches "0" + + lvchange --syncaction check $vg/$lv1 + + aux wait_recalc $vg/$lv1 + + not check lv_field $vg/${lv1}_rimage_0 integritymismatches "0" + not check lv_field $vg/${lv1}_rimage_1 integritymismatches "0" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + cmp -b $mnt/fileA fileA + cmp -b $mnt/fileB fileB + cmp -b $mnt/fileC fileC + umount $mnt +} + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 6 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_test1 "$dev1" +not check $vg/$lv1 integritymismatches "0" +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 6 $vg "$dev1" "$dev2" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_test2 +not check $vg/$lv1 integritymismatches "0" +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid5 --raidintegrity y -n $lv1 -I 4K -l 6 $vg "$dev1" "$dev2" "$dev3" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +_test1 "$dev1" "$dev2" "$dev3" +not check $vg/$lv1 integritymismatches "0" +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg diff --git a/test/shell/integrity.sh b/test/shell/integrity.sh new file mode 100644 index 0000000..61229c8 --- /dev/null +++ b/test/shell/integrity.sh @@ -0,0 +1,771 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +which resize2fs || skip +aux have_integrity 1 5 0 || skip +# Avoid 4K ramdisk devices on older kernels +aux kernel_at_least 5 10 || export LVM_TEST_PREFER_BRD=0 + +mnt="mnt" +mkdir -p $mnt + +aux prepare_devs 5 64 + +# Use awk instead of anoyingly long log out from printf +#printf "%0.sA" {1..16384} >> fileA +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 4096) printf "B" ; while (z++ < 16384) printf "b" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_prepare_vg() { + # zero devs so we are sure to find the correct file data + # on the underlying devs when corrupting it + aux clear_devs "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + pvs +} + +_test_fs_with_read_repair() { + mkfs.ext4 -b 4096 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + cp randA $mnt + cp randB $mnt + cp randC $mnt + cp fileA $mnt + cp fileB $mnt + cp fileC $mnt + + umount $mnt + lvchange -an $vg/$lv1 + + for dev in "$@"; do + aux corrupt_dev "$dev" BBBBBBBBBBBBBBBBB BBBBBBBBCBBBBBBBB + done + + lvchange -ay $vg/$lv1 + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + cmp -b $mnt/fileA fileA + cmp -b $mnt/fileB fileB + cmp -b $mnt/fileC fileC + umount $mnt +} + +_add_new_data_to_mnt() { + mkfs.ext4 -b 4096 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 +} + +_add_more_data_to_mnt() { + mkdir $mnt/more + cp fileA $mnt/more + cp fileB $mnt/more + cp fileC $mnt/more + cp randA $mnt/more + cp randB $mnt/more + cp randC $mnt/more +} + +_verify_data_on_mnt() { + cmp -b randA $mnt/randA + cmp -b randB $mnt/randB + cmp -b randC $mnt/randC + cmp -b fileA $mnt/1/fileA + cmp -b fileB $mnt/1/fileB + cmp -b fileC $mnt/1/fileC + cmp -b fileA $mnt/2/fileA + cmp -b fileB $mnt/2/fileB + cmp -b fileC $mnt/2/fileC +} + +_verify_data_on_lv() { + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + _verify_data_on_mnt + rm $mnt/randA + rm $mnt/randB + rm $mnt/randC + rm -rf $mnt/1 + rm -rf $mnt/2 + umount $mnt + lvchange -an $vg/$lv1 +} + +# Test corrupting data on an image and verifying that +# it is detected by integrity and corrected by raid. + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_test_fs_with_read_repair "$dev1" +lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch +not grep 0 mismatch +lvs -o integritymismatches $vg/$lv1 |tee mismatch +not grep 0 mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid1 -m2 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +_test_fs_with_read_repair "$dev1" "$dev2" +lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch +not grep 0 mismatch +lvs -o integritymismatches $vg/$lv1 |tee mismatch +not grep 0 mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid4 --raidintegrity y -n $lv1 -I 4K -l 8 $vg "$dev1" "$dev2" "$dev3" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +_test_fs_with_read_repair "$dev1" "$dev2" "$dev3" +lvs -o integritymismatches $vg/${lv1}_rimage_0 +lvs -o integritymismatches $vg/${lv1}_rimage_1 +lvs -o integritymismatches $vg/${lv1}_rimage_2 +lvs -o integritymismatches $vg/$lv1 |tee mismatch +not grep 0 mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid5 --raidintegrity y -n $lv1 -I 4K -l 8 $vg "$dev1" "$dev2" "$dev3" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +_test_fs_with_read_repair "$dev1" "$dev2" "$dev3" +lvs -o integritymismatches $vg/${lv1}_rimage_0 +lvs -o integritymismatches $vg/${lv1}_rimage_1 +lvs -o integritymismatches $vg/${lv1}_rimage_2 +lvs -o integritymismatches $vg/$lv1 |tee mismatch +not grep 0 mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid6 --raidintegrity y -n $lv1 -I 4K -l 8 $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/${lv1}_rimage_3 +aux wait_recalc $vg/${lv1}_rimage_4 +aux wait_recalc $vg/$lv1 +_test_fs_with_read_repair "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvs -o integritymismatches $vg/${lv1}_rimage_0 +lvs -o integritymismatches $vg/${lv1}_rimage_1 +lvs -o integritymismatches $vg/${lv1}_rimage_2 +lvs -o integritymismatches $vg/${lv1}_rimage_3 +lvs -o integritymismatches $vg/${lv1}_rimage_4 +lvs -o integritymismatches $vg/$lv1 |tee mismatch +not grep 0 mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid10 --raidintegrity y -n $lv1 -l 8 $vg "$dev1" "$dev2" "$dev3" "$dev4" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/${lv1}_rimage_3 +aux wait_recalc $vg/$lv1 +_test_fs_with_read_repair "$dev1" "$dev3" +lvs -o integritymismatches $vg/${lv1}_rimage_0 +lvs -o integritymismatches $vg/${lv1}_rimage_1 +lvs -o integritymismatches $vg/${lv1}_rimage_2 +lvs -o integritymismatches $vg/${lv1}_rimage_3 +lvs -o integritymismatches $vg/$lv1 |tee mismatch +not grep 0 mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test removing integrity from an active LV + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity n $vg/$lv1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid4 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity n $vg/$lv1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid5 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity n $vg/$lv1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid6 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/${lv1}_rimage_3 +aux wait_recalc $vg/${lv1}_rimage_4 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity n $vg/$lv1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid10 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity n $vg/$lv1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test adding integrity to an active LV + +_prepare_vg +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid4 -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid5 -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid6 -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid10 -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test lvextend while inactive + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvextend -l 16 $vg/$lv1 +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +resize2fs "$DM_DEV_DIR/$vg/$lv1" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o name,segtype,devices,sync_percent $vg +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid6 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,sync_percent,devices $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/${lv1}_rimage_3 +aux wait_recalc $vg/${lv1}_rimage_4 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvextend -l 16 $vg/$lv1 +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +resize2fs "$DM_DEV_DIR/$vg/$lv1" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o name,segtype,devices,sync_percent $vg +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test lvextend while active + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvs -a -o+devices $vg +_add_new_data_to_mnt +lvextend -l 16 $vg/$lv1 +resize2fs "$DM_DEV_DIR/$vg/$lv1" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid5 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +lvs -a -o+devices $vg +_add_new_data_to_mnt +lvextend -l 16 $vg/$lv1 +resize2fs "$DM_DEV_DIR/$vg/$lv1" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid10 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvs -a -o+devices $vg +_add_new_data_to_mnt +lvextend -l 16 $vg/$lv1 +resize2fs "$DM_DEV_DIR/$vg/$lv1" +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +lvs -a -o+devices $vg +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test adding image to raid1 + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +lvs -a -o+devices $vg +_add_new_data_to_mnt +lvconvert -y -m+1 $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +lvs -a -o+devices $vg +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test removing image from raid1 + +_prepare_vg +lvcreate --type raid1 -m2 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +lvconvert -y -m-1 $vg/$lv1 +lvs -a -o+devices $vg +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test disallowed operations on raid+integrity + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_add_new_data_to_mnt +not lvconvert -y -m-1 $vg/$lv1 +not lvconvert --splitmirrors 1 -n tmp -y $vg/$lv1 +not lvconvert --splitmirrors 1 --trackchanges -y $vg/$lv1 +not lvchange --syncaction repair $vg/$lv1 +not lvreduce -L4M $vg/$lv1 +not pvmove -n $vg/$lv1 "$dev1" +not pvmove "$dev1" +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Repeat many of the tests above using bitmap mode + +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg "$dev1" "$dev2" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/$lv1 +_test_fs_with_read_repair "$dev1" +lvs -o integritymismatches $vg/${lv1}_rimage_0 |tee mismatch +not grep 0 mismatch +lvs -o integritymismatches $vg/$lv1 |tee mismatch +not grep 0 mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +_prepare_vg +lvcreate --type raid6 --raidintegrity y --raidintegritymode bitmap -n $lv1 -I 4K -l 8 $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +aux wait_recalc $vg/${lv1}_rimage_3 +aux wait_recalc $vg/${lv1}_rimage_4 +aux wait_recalc $vg/$lv1 +_test_fs_with_read_repair "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvs -o integritymismatches $vg/${lv1}_rimage_0 +lvs -o integritymismatches $vg/${lv1}_rimage_1 +lvs -o integritymismatches $vg/${lv1}_rimage_2 +lvs -o integritymismatches $vg/${lv1}_rimage_3 +lvs -o integritymismatches $vg/${lv1}_rimage_4 +lvs -o integritymismatches $vg/$lv1 |tee mismatch +not grep 0 mismatch +lvchange -an $vg/$lv1 +lvconvert --raidintegrity n $vg/$lv1 +lvremove $vg/$lv1 +vgremove -ff $vg + +# remove from active lv +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg "$dev1" "$dev2" +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_new_data_to_mnt +lvconvert --raidintegrity n $vg/$lv1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# add to active lv +_prepare_vg +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +_add_new_data_to_mnt +lvconvert --raidintegrity y --raidintegritymode bitmap $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# lvextend active +_prepare_vg +lvcreate --type raid1 --raidintegrity y --raidintegritymode bitmap -m1 -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_new_data_to_mnt +lvextend -l 16 $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +resize2fs "$DM_DEV_DIR/$vg/$lv1" +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# add image to raid1 +_prepare_vg +lvcreate --type raid1 -m1 --raidintegrity y --raidintegritymode bitmap -n $lv1 -l 8 $vg +lvs -a -o name,segtype,devices,sync_percent $vg +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +_add_new_data_to_mnt +lvconvert -y -m+1 $vg/$lv1 +aux wait_recalc $vg/${lv1}_rimage_0 +aux wait_recalc $vg/${lv1}_rimage_1 +aux wait_recalc $vg/${lv1}_rimage_2 +_add_more_data_to_mnt +_verify_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +vgremove -ff $vg + +# Test that raid+integrity cannot be a sublv +# part1: cannot add integrity to a raid LV that is already a sublv + +_prepare_vg + +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvconvert -y --type thin-pool $vg/$lv1 +not lvconvert --raidintegrity y $vg/$lv1 +not lvconvert --raidintegrity y $vg/${lv1}_tdata +not lvconvert --raidintegrity y $vg/${lv1}_tmeta +lvremove -y $vg/$lv1 + +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvconvert -y --type cache-pool $vg/$lv1 +not lvconvert --raidintegrity y $vg/$lv1 +not lvconvert --raidintegrity y $vg/${lv1}_cdata +not lvconvert --raidintegrity y $vg/${lv1}_cmeta +lvremove -y $vg/$lv1 + +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvcreate --type cache-pool -n cpool -l 8 $vg +lvconvert -y --type cache --cachepool cpool $vg/$lv1 +not lvconvert --raidintegrity y $vg/$lv1 +not lvconvert --raidintegrity y $vg/${lv1}_corig +lvremove -y $vg/$lv1 + +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvcreate --type raid1 -m1 -n cvol -l 8 $vg +lvconvert -y --type cache --cachevol cvol $vg/$lv1 +not lvconvert --raidintegrity y $vg/$lv1 +not lvconvert --raidintegrity y $vg/${lv1}_corig +not lvconvert --raidintegrity y $vg/cvol +lvremove -y $vg/$lv1 + +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvcreate -n cvol -l 8 $vg +lvchange -an $vg +lvconvert -y --type writecache --cachevol cvol $vg/$lv1 +not lvconvert --raidintegrity y $vg/$lv1 +not lvconvert --raidintegrity y $vg/${lv1}_wcorig +lvremove -y $vg/$lv1 + +# Test that raid+integrity cannot be a sublv +# part2: cannot convert an existing raid+integrity LV into a sublv + +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvconvert -y --type thin-pool $vg/$lv1 +not lvconvert --raidintegrity y $vg/${lv1}_tdata +lvremove -y $vg/$lv1 + +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvcreate --type raid1 -m1 -n $lv2 -l 8 $vg +lvconvert -y --type cache --cachevol $lv2 $vg/$lv1 +not lvconvert --raidintegrity y $vg/${lv1}_corig +not lvconvert --raidintegrity y $vg/${lv2}_cvol +lvremove -y $vg/$lv1 + +lvcreate --type raid1 -m1 -n $lv1 -l 8 $vg +lvcreate --type raid1 -m1 -n $lv2 -l 8 $vg +lvconvert -y --type cache --cachepool $lv2 $vg/$lv1 +not lvconvert --raidintegrity y $vg/${lv1}_corig +not lvconvert --raidintegrity y $vg/${lv2}_cpool_cdata +not lvconvert --raidintegrity y $vg/${lv2}_cpool_cmeta +lvremove -y $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/large-physical-sector-size.sh b/test/shell/large-physical-sector-size.sh new file mode 100644 index 0000000..b603418 --- /dev/null +++ b/test/shell/large-physical-sector-size.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +LOGICAL_BLOCK_SIZE=4096 + +# PHYSICAL_BLOCK_SIZE is set with physblk_exp which +# shifts the logical block size value. + +# 4096 << 9 = 2MB physical block size +PHYSICAL_BLOCK_SHIFT=9 + +aux prepare_scsi_debug_dev 256 sector_size=$LOGICAL_BLOCK_SIZE physblk_exp=$PHYSICAL_BLOCK_SHIFT || skip + +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "$LOGICAL_BLOCK_SIZE" + +aux prepare_pvs 1 256 + +get_devs + +vgcreate $SHARED $vg "$dev1" + +for i in $(seq 1 40); do lvcreate -an -l1 $vg; done; + +lvs $vg + +lvremove -y $vg + +vgremove $vg + +aux cleanup_scsi_debug_dev diff --git a/test/shell/listings.sh b/test/shell/listings.sh index b6e4dfa..0c614d0 100644 --- a/test/shell/listings.sh +++ b/test/shell/listings.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2014 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 @@ -7,35 +8,46 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # tests functionality of lvs, pvs, vgs, *display tools # -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_devs 5 +get_devs + +# Check there is no PV +pvscan | tee out +grep "No matching" out -pvcreate "$dev1" +pvcreate --uuid BADBEE-BAAD-BAAD-BAAD-BAAD-BAAD-BADBEE --norestorefile "$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 -test $(pvs --noheadings $(cat DEVICES) | wc -l) -eq 5 +pvs --noheadings "${DEVICES[@]}" +test "$(pvs --noheadings "${DEVICES[@]}" | wc -l)" -eq 5 +pvdisplay #COMM pvs with segment attributes works even for orphans -test $(pvs --noheadings -o seg_all,pv_all,lv_all,vg_all $(cat DEVICES) | wc -l) -eq 5 +test "$(pvs --noheadings -o seg_all,pv_all,lv_all,vg_all "${DEVICES[@]}" | wc -l)" -eq 5 -vgcreate -c n $vg $(cat DEVICES) +vgcreate $SHARED $vg "${DEVICES[@]}" + +check pv_field "$dev1" pv_uuid BADBEE-BAAD-BAAD-BAAD-BAAD-BAAD-BADBEE #COMM pvs and vgs report mda_count, mda_free (bz202886, bz247444) -pvs -o +pv_mda_count,pv_mda_free $(cat DEVICES) +pvs -o +pv_mda_count,pv_mda_free "${DEVICES[@]}" for I in "$dev2" "$dev3" "$dev5"; do - check pv_field $I pv_mda_count 0 - check pv_field $I pv_mda_free 0 + check pv_field "$I" pv_mda_count 0 + check pv_field "$I" pv_mda_free 0 done vgs -o +vg_mda_count,vg_mda_free $vg check vg_field $vg vg_mda_count 2 @@ -45,25 +57,166 @@ pvdisplay "$dev2"|grep "VG Name.*$vg" check pv_field "$dev2" vg_name $vg #COMM lvs displays snapshots (bz171215) -lvcreate -l4 -n $lv1 $vg +lvcreate -aey -l4 -n $lv1 $vg lvcreate -l4 -s -n $lv2 $vg/$lv1 -test $(lvs --noheadings $vg | wc -l) -eq 2 +test "$(lvs --noheadings $vg | wc -l)" -eq 2 # should lvs -a display cow && real devices? (it doesn't) -test $(lvs -a --noheadings $vg | wc -l) -eq 2 -dmsetup ls|grep $PREFIX|grep -v "LVMTEST.*pv." +test "$(lvs -a --noheadings $vg | wc -l)" -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 -test $(lvs --noheadings $vg | wc -l) -eq 2 -test $(lvs -a --noheadings $vg | wc -l) -eq 6 -dmsetup ls|grep $PREFIX|grep -v "LVMTEST.*pv." +lvcreate -aey -l2 --type mirror -m2 -n $lv3 $vg +test "$(lvs --noheadings $vg | wc -l)" -eq 2 +test "$(lvs -a --noheadings $vg | wc -l)" -eq 6 +dmsetup ls | grep "$PREFIX" | grep -v "LVMTEST.*pv." + +# Check we parse /dev/mapper/vg-lv +lvdisplay "$DM_DEV_DIR/mapper/$vg-$lv3" +# Check we parse /dev/vg/lv +lvdisplay "$DM_DEV_DIR/$vg/$lv3" + +lvcreate -l2 -s $vg/$lv3 +lvcreate -l1 -s -n inval $vg/$lv3 +lvcreate -l4 -I4 -i2 -n stripe $vg +# Invalidate snapshot +not dd if=/dev/zero of="$DM_DEV_DIR/$vg/inval" bs=4K +invalid lvscan "$dev1" +lvdisplay --maps +lvscan --all #COMM vgs with options from pvs still treats arguments as VGs (bz193543) vgs -o pv_name,vg_name $vg # would complain if not +vgs -o all $vg #COMM pvdisplay --maps feature (bz149814) -pvdisplay $(cat DEVICES) >out -pvdisplay --maps $(cat DEVICES) >out2 +pvdisplay "${DEVICES[@]}" >out +pvdisplay --maps "${DEVICES[@]}" >out2 not diff out out2 + +aux disable_dev "$dev1" +pvs -o +pv_uuid | grep BADBEE-BAAD-BAAD-BAAD-BAAD-BAAD-BADBEE +aux enable_dev "$dev1" + +pvscan --uuid +pvscan -e +pvscan -s +pvscan --novolumegroup +vgscan --mknodes +vgmknodes --refresh +lvscan +lvmdiskscan + +invalid pvscan "$dev1" +invalid pvscan -aay +invalid pvscan --major 254 +invalid pvscan --minor 0 +invalid pvscan --novolumegroup -e +invalid vgscan $vg +invalid lvscan $vg + +if aux have_readline; then +cat < lv2 --> lv3 --> lv4 --> lv5 +# \ +# --> lv6 --> lv7 + +lvcreate -V1 -T ${vg}/pool -n lv1 +lvcreate -s ${vg}/lv1 -n lv2 +lvcreate -s ${vg}/lv2 -n lv3 +lvcreate -s ${vg}/lv3 -n lv4 +lvcreate -s ${vg}/lv4 -n lv5 +lvcreate -s ${vg}/lv3 -n lv6 +lvcreate -s ${vg}/lv6 -n lv7 + +check lvh_field ${vg}/lv1 full_ancestors "" +check lvh_field ${vg}/lv1 full_descendants "lv2,lv3,lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/lv2 full_ancestors "lv1" +check lvh_field ${vg}/lv2 full_descendants "lv3,lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/lv3 full_ancestors "lv2,lv1" +check lvh_field ${vg}/lv3 full_descendants "lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/lv4 full_ancestors "lv3,lv2,lv1" +check lvh_field ${vg}/lv4 full_descendants "lv5" + +check lvh_field ${vg}/lv5 full_ancestors "lv4,lv3,lv2,lv1" +check lvh_field ${vg}/lv5 full_descendants "" + +check lvh_field ${vg}/lv6 full_ancestors "lv3,lv2,lv1" +check lvh_field ${vg}/lv6 full_descendants "lv7" + +check lvh_field ${vg}/lv7 full_ancestors "lv6,lv3,lv2,lv1" +check lvh_field ${vg}/lv7 full_descendants "" + + +# lv1 --> lv2 --> lv3 --> -lv4 --> lv5 +# \ +# --> lv6 --> lv7 +lvremove -ff ${vg}/lv4 + +check lvh_field ${vg}/lv1 full_ancestors "" +check lvh_field ${vg}/lv1 full_descendants "lv2,lv3,lv6,lv7,-lv4,lv5" + +check lvh_field ${vg}/lv2 full_ancestors "lv1" +check lvh_field ${vg}/lv2 full_descendants "lv3,lv6,lv7,-lv4,lv5" + +check lvh_field ${vg}/lv3 full_ancestors "lv2,lv1" +check lvh_field ${vg}/lv3 full_descendants "lv6,lv7,-lv4,lv5" + +check lvh_field ${vg}/-lv4 full_ancestors "lv3,lv2,lv1" +check lvh_field ${vg}/-lv4 full_descendants "lv5" + +check lvh_field ${vg}/lv5 full_ancestors "-lv4,lv3,lv2,lv1" +check lvh_field ${vg}/lv5 full_descendants "" + +check lvh_field ${vg}/lv6 full_ancestors "lv3,lv2,lv1" +check lvh_field ${vg}/lv6 full_descendants "lv7" + +check lvh_field ${vg}/lv7 full_ancestors "lv6,lv3,lv2,lv1" +check lvh_field ${vg}/lv7 full_descendants "" + + +# lv1 --> lv2 --> -lv3 --> -lv4 --> lv5 +# \ +# --> lv6 --> lv7 +lvremove -ff ${vg}/lv3 + +check lvh_field ${vg}/lv1 full_ancestors "" +check lvh_field ${vg}/lv1 full_descendants "lv2,-lv3,-lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/lv2 full_ancestors "lv1" +check lvh_field ${vg}/lv2 full_descendants "-lv3,-lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/-lv3 full_ancestors "lv2,lv1" +check lvh_field ${vg}/-lv3 full_descendants "-lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/-lv4 full_ancestors "-lv3,lv2,lv1" +check lvh_field ${vg}/-lv4 full_descendants "lv5" + +check lvh_field ${vg}/lv5 full_ancestors "-lv4,-lv3,lv2,lv1" +check lvh_field ${vg}/lv5 full_descendants "" + +check lvh_field ${vg}/lv6 full_ancestors "-lv3,lv2,lv1" +check lvh_field ${vg}/lv6 full_descendants "lv7" + +check lvh_field ${vg}/lv7 full_ancestors "lv6,-lv3,lv2,lv1" +check lvh_field ${vg}/lv7 full_descendants "" + +# lv1 --> -lv2 --> -lv3 --> -lv4 --> lv5 +# \ +# --> lv6 --> lv7 +lvremove -ff $vg/lv2 + +check lvh_field ${vg}/lv1 full_ancestors "" +check lvh_field ${vg}/lv1 full_descendants "-lv2,-lv3,-lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/-lv2 full_ancestors "lv1" +check lvh_field ${vg}/-lv2 full_descendants "-lv3,-lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/-lv3 full_ancestors "-lv2,lv1" +check lvh_field ${vg}/-lv3 full_descendants "-lv4,lv5,lv6,lv7" + +check lvh_field ${vg}/-lv4 full_ancestors "-lv3,-lv2,lv1" +check lvh_field ${vg}/-lv4 full_descendants "lv5" + +check lvh_field ${vg}/lv5 full_ancestors "-lv4,-lv3,-lv2,lv1" +check lvh_field ${vg}/lv5 full_descendants "" + +check lvh_field ${vg}/lv6 full_ancestors "-lv3,-lv2,lv1" +check lvh_field ${vg}/lv6 full_descendants "lv7" + +check lvh_field ${vg}/lv7 full_ancestors "lv6,-lv3,-lv2,lv1" +check lvh_field ${vg}/lv7 full_descendants "" + +# lv1 --> -lv2 --> -lv3 --> -lv4 --> lv5 +# \ +# --> -lv6 --> lv7 +lvremove -ff ${vg}/lv6 + +check lvh_field ${vg}/lv1 full_ancestors "" +check lvh_field ${vg}/lv1 full_descendants "-lv2,-lv3,-lv4,lv5,-lv6,lv7" + +check lvh_field ${vg}/-lv2 full_ancestors "lv1" +check lvh_field ${vg}/-lv2 full_descendants "-lv3,-lv4,lv5,-lv6,lv7" + +check lvh_field ${vg}/-lv3 full_ancestors "-lv2,lv1" +check lvh_field ${vg}/-lv3 full_descendants "-lv4,lv5,-lv6,lv7" + +check lvh_field ${vg}/-lv4 full_ancestors "-lv3,-lv2,lv1" +check lvh_field ${vg}/-lv4 full_descendants "lv5" + +check lvh_field ${vg}/lv5 full_ancestors "-lv4,-lv3,-lv2,lv1" +check lvh_field ${vg}/lv5 full_descendants "" + +check lvh_field ${vg}/-lv6 full_ancestors "-lv3,-lv2,lv1" +check lvh_field ${vg}/-lv6 full_descendants "lv7" + +check lvh_field ${vg}/lv7 full_ancestors "-lv6,-lv3,-lv2,lv1" +check lvh_field ${vg}/lv7 full_descendants "" + +# lv1 --> -lv2 -----------> -lv4 --> lv5 +# \ +# --> -lv6 --> lv7 +lvremove -ff ${vg}/-lv3 + +check lvh_field ${vg}/lv1 full_ancestors "" +check lvh_field ${vg}/lv1 full_descendants "-lv2,-lv4,lv5,-lv6,lv7" + +check lvh_field ${vg}/-lv2 full_ancestors "lv1" +check lvh_field ${vg}/-lv2 full_descendants "-lv4,lv5,-lv6,lv7" + +check lvh_field ${vg}/-lv4 full_ancestors "-lv2,lv1" +check lvh_field ${vg}/-lv4 full_descendants "lv5" + +check lvh_field ${vg}/lv5 full_ancestors "-lv4,-lv2,lv1" +check lvh_field ${vg}/lv5 full_descendants "" + +check lvh_field ${vg}/-lv6 full_ancestors "-lv2,lv1" +check lvh_field ${vg}/-lv6 full_descendants "lv7" + +check lvh_field ${vg}/lv7 full_ancestors "-lv6,-lv2,lv1" +check lvh_field ${vg}/lv7 full_descendants "" + +# -lv2 -----------> -lv4 --> lv5 +# \ +# --> -lv6 --> lv7 + +lvremove --nohistory -ff ${vg}/lv1 + +check lvh_field ${vg}/-lv2 full_ancestors "" +check lvh_field ${vg}/-lv2 full_descendants "-lv4,lv5,-lv6,lv7" + +check lvh_field ${vg}/-lv4 full_ancestors "-lv2" +check lvh_field ${vg}/-lv4 full_descendants "lv5" + +check lvh_field ${vg}/lv5 full_ancestors "-lv4,-lv2" +check lvh_field ${vg}/lv5 full_descendants "" + +check lvh_field ${vg}/-lv6 full_ancestors "-lv2" +check lvh_field ${vg}/-lv6 full_descendants "lv7" + +check lvh_field ${vg}/lv7 full_ancestors "-lv6,-lv2" +check lvh_field ${vg}/lv7 full_descendants "" + +# -lv2 -----------> -lv4 --> lv5 +# +# lv7 +lvremove --nohistory -ff ${vg}/-lv6 + +check lvh_field ${vg}/-lv2 full_ancestors "" +check lvh_field ${vg}/-lv2 full_descendants "-lv4,lv5" + +check lvh_field ${vg}/-lv4 full_ancestors "-lv2" +check lvh_field ${vg}/-lv4 full_descendants "lv5" + +check lvh_field ${vg}/lv5 full_ancestors "-lv4,-lv2" +check lvh_field ${vg}/lv5 full_descendants "" + +check lvh_field ${vg}/lv7 full_ancestors "" +check lvh_field ${vg}/lv7 full_descendants "" + +vgremove -ff $vg diff --git a/test/shell/lvchange-cache-mode.sh b/test/shell/lvchange-cache-mode.sh new file mode 100644 index 0000000..a50dfd4 --- /dev/null +++ b/test/shell/lvchange-cache-mode.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise changing of caching mode on both cache pool and cached LV. + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 5 0 || skip + +aux prepare_vg 2 + +lvcreate --type cache-pool -L18 -n cpool $vg "$dev1" +lvcreate -H -L14 -n $lv1 --cachemode writeback --cachesettings migration_threshold=204800 --cachepool $vg/cpool $vg "$dev2" + +#cat "$DM_DEV_DIR/$vg/$lv1" >/dev/null +#aux delay_dev "$dev2" 300 1000 $(get first_extent_sector "$dev2"): + +#dmsetup status $vg-$lv1 +#dmsetup table $vg-$lv1 + +for i in $(seq 1 10) ; do +echo 3 >/proc/sys/vm/drop_caches +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=64K count=20 oflag=direct || true +echo 3 >/proc/sys/vm/drop_caches +dd if="$DM_DEV_DIR/$vg/$lv1" of=/dev/null bs=64K count=20 oflag=direct || true +done + +lvs -o+cache_dirty_blocks,cache_read_hits,cache_read_misses,cache_write_hits,cache_write_misses $vg/$lv1 + + +# +# Drop later, code loading dm tables directly without lvm +# RHBZ 1337588 +# +#dmsetup table +#echo "STATUS before cleaner" +#dmsetup status +#dmsetup load --table "0 28672 cache 253:4 253:3 253:5 128 1 writethrough cleaner 0" $vg-$lv1 +#dmsetup resume $vg-$lv1 +#sleep 1 +#dmsetup table +#echo "STATUS after cleaner 1sec" +#dmsetup status --noflush +#dmsetup suspend --noflush $vg-$lv1 +#dmsetup resume $vg-$lv1 + +#dmsetup load --table "0 28672 cache 253:4 253:3 253:5 128 1 passthrough smq 2 migration_threshold 204800" $vg-$lv1 +#dmsetup status $vg-$lv1 +#dmsetup load --table "0 28672 cache 253:4 253:3 253:5 128 1 writethrough smq 2 migration_threshold 204800" $vg-$lv1 +#dmsetup resume $vg-$lv1 +#dmsetup status $vg-$lv1 +#dmsetup table $vg-$lv1 +#dmsetup ls --tree +#exit + +check lv_field $vg/$lv1 cache_mode "writeback" +lvchange --cachemode passthrough $vg/$lv1 +check lv_field $vg/$lv1 cache_mode "passthrough" +lvchange --cachemode writethrough $vg/$lv1 +check lv_field $vg/$lv1 cache_mode "writethrough" +lvchange --cachemode writeback $vg/$lv1 +check lv_field $vg/$lv1 cache_mode "writeback" + +lvconvert --splitcache $vg/$lv1 + +lvs -a $vg + +check lv_field $vg/cpool cache_mode "writeback" +lvchange --cachemode passthrough $vg/cpool +check lv_field $vg/cpool cache_mode "passthrough" +lvchange --cachemode writethrough $vg/cpool +check lv_field $vg/cpool cache_mode "writethrough" +lvchange --cachemode writeback $vg/cpool +check lv_field $vg/cpool cache_mode "writeback" + +lvs -a $vg + +vgremove -f $vg diff --git a/test/shell/lvchange-cache-old.sh b/test/shell/lvchange-cache-old.sh new file mode 100644 index 0000000..992249c --- /dev/null +++ b/test/shell/lvchange-cache-old.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise usage of older metadata which are missing some new settings + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +# FIXME: parallel cache metadata allocator is crashing when used value 8000! +aux prepare_vg 5 80 + + +lvcreate -l 10 --type cache-pool $vg/cpool +lvcreate -l 20 -H -n $lv1 --cachepool $vg/cpool $vg + +vgcfgbackup -f backup $vg + +# check metadata without cache policy +lvchange -an $vg +grep -v "policy =" backup >backup_1 +vgcfgrestore -f backup_1 $vg +lvchange -ay $vg + +# check metadata without cache mode +lvchange -an $vg +grep -v "cache_mode =" backup >backup_2 +vgcfgrestore -f backup_2 $vg +lvchange -ay $vg + +vgremove -ff $vg diff --git a/test/shell/lvchange-cache-syncaction-raid.sh b/test/shell/lvchange-cache-syncaction-raid.sh new file mode 100644 index 0000000..bd4500d --- /dev/null +++ b/test/shell/lvchange-cache-syncaction-raid.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test activation race for raid's --syncaction check + + +SKIP_WITH_LVMPOLLD=1 + + +# Current support for syncaction in cluster is broken +# might get fixed one day though +# meanwhile skipped +SKIP_WITH_CLVMD=1 + +. lib/inittest + +aux have_cache 1 5 0 || skip + +# Proper mismatch count 1.5.2+ upstream, 1.3.5 < x < 1.4.0 in RHEL6 +aux have_raid 1 3 5 && + ! aux have_raid 1 4 0 || + aux have_raid 1 5 2 || skip +aux prepare_vg 3 + + +# Bug 1169495 - RFE: allow raid scrubbing on cache origin raid volumes +# lvcreate RAID1 origin, lvcreate cache-pool, and lvconvert to cache +# then test that the origin can be scrubbed. +lvcreate --type raid1 -m 1 --nosync -l 2 -n $lv1 $vg +lvcreate --type cache-pool -l 1 -n ${lv1}_cachepool $vg +lvconvert --cache -Zy --cachepool $vg/${lv1}_cachepool $vg/$lv1 +lvchange --syncaction check $vg/${lv1}_corig +# Check may go too quickly to verify with check of syncaction + +vgremove -ff $vg diff --git a/test/shell/lvchange-cache.sh b/test/shell/lvchange-cache.sh new file mode 100644 index 0000000..93c8c3b --- /dev/null +++ b/test/shell/lvchange-cache.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip +aux prepare_vg 3 + +aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]' + +lvcreate --type cache-pool -an -v -L 2 -n cpool $vg +lvcreate -H -L 4 -n corigin --cachepool $vg/cpool +lvcreate -n noncache -l 1 $vg + +# cannot change major minor for pools +not lvchange --yes -M y --minor 235 --major 253 $vg/cpool +not lvchange -M n $vg/cpool + +not lvchange --cachepolicy mq $vg/noncache +not lvchange --cachesettings foo=bar $vg/noncache + +lvchange --cachepolicy cleaner $vg/corigin +check lv_field $vg/corigin kernel_cache_policy "cleaner" + +# Skip these test on older cache driver as it shows errors with these lvchanges +# device-mapper: space map common: index_check failed: blocknr 17179869216 != wanted 11 +if aux have_cache 1 5 0 ; then + +lvchange --cachepolicy mq --cachesettings migration_threshold=1333 $vg/corigin + +# TODO once mq->smq happens we will get here some 0 for mq settings +check lv_field $vg/corigin kernel_cache_policy "mq" +get lv_field $vg/corigin kernel_cache_settings | grep 'migration_threshold=1333' + +lvchange --refresh $vg/corigin +get lv_field $vg/corigin kernel_cache_settings | grep 'migration_threshold=1333' +lvchange -an $vg +lvchange -ay $vg +get lv_field $vg/corigin kernel_cache_settings | grep 'migration_threshold=1333' + +lvchange --cachesettings 'migration_threshold = 1233 sequential_threshold = 13' $vg/corigin +get lv_field $vg/corigin kernel_cache_settings | tee out +grep 'migration_threshold=1233' out + +if grep 'sequential_threshold=13' out ; then + +lvchange --cachesettings 'migration_threshold = 1117' $vg/corigin +get lv_field $vg/corigin kernel_cache_settings | tee out +grep 'migration_threshold=1117' out +grep 'sequential_threshold=13' out + +lvchange --cachesettings 'migration_threshold = default' $vg/corigin +get lv_field $vg/corigin kernel_cache_settings | tee out +grep 'migration_threshold=2048' out +grep 'sequential_threshold=13' out + +lvchange --cachesettings 'migration_threshold = 1233 sequential_threshold = 13 random_threshold = 1' $vg/corigin +lvchange --cachesettings 'random_threshold = default migration_threshold = default' $vg/corigin +get lv_field $vg/corigin kernel_cache_settings | tee out +grep 'migration_threshold=2048' out +grep 'sequential_threshold=13' out +grep 'random_threshold=4' out + +lvchange --cachesettings migration_threshold=1233 --cachesettings sequential_threshold=13 --cachesettings random_threshold=1 $vg/corigin +get lv_field $vg/corigin kernel_cache_settings | tee out +grep 'migration_threshold=1233' out +grep 'sequential_threshold=13' out +grep 'random_threshold=1' out + +lvchange --cachesettings random_threshold=default --cachesettings migration_threshold=default $vg/corigin +get lv_field $vg/corigin kernel_cache_settings | tee out +grep 'migration_threshold=2048' out +grep 'sequential_threshold=13' out +grep 'random_threshold=4' out + +else +# When MQ is emulated by SMQ policy it does not hold settings. +# So just skip testing of param changes when sequential_threshold=0 +# or some older kernel instancies show also value 512 +grep 'sequential_threshold=0' out || grep 'sequential_threshold=512' out +fi + +fi # have_cache 1 5 0 + +vgremove -f $vg diff --git a/test/shell/lvchange-mirror.sh b/test/shell/lvchange-mirror.sh index 26656d4..f21a0fa 100644 --- a/test/shell/lvchange-mirror.sh +++ b/test/shell/lvchange-mirror.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,24 +8,31 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# FIXME RESYNC doesn't work in cluster with exclusive activation +# seriously broken! + +SKIP_WITH_CLVMD=1 +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_dmeventd aux prepare_vg 3 # force resync 2-way active mirror -lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3":0-1 +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3":0-1 check mirror $vg $lv1 "$dev3" -echo y | lvchange --resync $vg/$lv1 +lvchange -y --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 +lvcreate -aey -l2 --type mirror -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 + +vgremove -ff $vg diff --git a/test/shell/lvchange-partial-raid10.sh b/test/shell/lvchange-partial-raid10.sh new file mode 100644 index 0000000..2c96108 --- /dev/null +++ b/test/shell/lvchange-partial-raid10.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 2 || skip + +aux prepare_vg 4 + +# rhbz 889358 +# Should be able to activate when RAID10 +# has failed devs in different mirror sets. +lvcreate --type raid10 -m 1 -i 2 -l 2 -n $lv1 $vg +aux wait_for_sync $vg $lv1 +lvchange -an $vg/$lv1 +aux disable_dev "$dev1" "$dev3" +lvchange -ay --partial $vg/$lv1 +lvchange -an $vg/$lv1 + +aux enable_dev "$dev1" + +vgremove -ff $vg diff --git a/test/shell/lvchange-partial.sh b/test/shell/lvchange-partial.sh index fe642d4..7913811 100644 --- a/test/shell/lvchange-partial.sh +++ b/test/shell/lvchange-partial.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash + # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,15 +8,19 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 -aux target_at_least dm-raid 1 1 0 || skip +. lib/inittest -aux prepare_vg 2 +aux prepare_vg 4 -lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg +TYPE=raid1 +aux have_raid 1 3 0 || TYPE=mirror + +lvcreate -aey --type $TYPE -m 1 -l 2 -n $lv1 $vg lvchange -an $vg/$lv1 aux disable_dev "$dev1" @@ -64,3 +69,6 @@ not lvchange --zero y $vg/$lv1 not lvchange --resync -ay $vg/$lv1 not lvchange --resync --addtag foo $vg/$lv1 +aux enable_dev "$dev1" + +vgremove -ff $vg diff --git a/test/shell/lvchange-raid-transient-failures.sh b/test/shell/lvchange-raid-transient-failures.sh new file mode 100644 index 0000000..35b4898 --- /dev/null +++ b/test/shell/lvchange-raid-transient-failures.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 10 1 || skip +aux prepare_vg 6 + +# +# FIXME: add multi-segment leg tests +# + +function _check_raid +{ + local vg=$1 + shift + local lv=$1 + shift + local fail=$1 + shift + local good=$1 + shift + local devs=( "$@" ) + + aux wait_for_sync $vg $lv + aux disable_dev --error --silent "${devs[@]}" + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" + fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv" + check raid_leg_status $vg $lv "$fail" + aux enable_dev --silent "${devs[@]}" + lvs -a -o +devices $vg | tee out + not grep unknown out + lvchange --refresh $vg/$lv + fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv" + aux wait_for_sync $vg $lv + fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv" + check raid_leg_status $vg $lv "$good" +} + +# raid1 with transiently failing devices +lv=4way +lvcreate -aey --type raid1 -m 3 --ignoremonitoring -L 1 -n $lv $vg +_check_raid $vg $lv "ADAD" "AAAA" "$dev2" "$dev4" +lvremove -y $vg/$lv + +# raid6 with transiently failing devices +lv=6way +lvcreate -aey --type raid6 -i 4 --ignoremonitoring -L 1 -n $lv $vg +_check_raid $vg $lv "ADADAA" "AAAAAA" "$dev2" "$dev4" +lvremove -y $vg/$lv + +# raid10 with transiently failing devices +lv=6way +lvcreate -aey --type raid10 -i 3 -m 1 --ignoremonitoring -L 1 -n $lv $vg +_check_raid $vg $lv "ADADDA" "AAAAAA" "$dev2" "$dev4" "$dev5" +lvremove -y $vg/$lv + +vgremove -f $vg diff --git a/test/shell/lvchange-raid.sh b/test/shell/lvchange-raid.sh new file mode 100644 index 0000000..3a9ed60 --- /dev/null +++ b/test/shell/lvchange-raid.sh @@ -0,0 +1,349 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Writemostly has been in every version since the begining +# Device refresh in 1.5.1 upstream and 1.3.4 < x < 1.4.0 in RHEL6 +# Sync action in 1.5.0 upstream and 1.3.3 < x < 1.4.0 in RHEL6 +# Proper mismatch count 1.5.2 upstream,1.3.5 < x < 1.4.0 in RHEL6 +# +# We will simplify and simple test for 1.5.2 and 1.3.5 < x < 1.4.0 +aux have_raid 1 3 5 && + ! aux have_raid 1 4 0 || + aux have_raid 1 5 2 || skip + +# DEVICE "$dev6" is reserved for non-RAID LVs that +# will not undergo failure +aux prepare_vg 6 + +# run_writemostly_check +run_writemostly_check() { + local vg=$1 + local lv=${2}${THIN_POSTFIX} + local segtype= + local d0 + local d1 + + segtype=$(get lv_field $vg/$lv segtype -a) + d0=$(get lv_devices $vg/${lv}_rimage_0) + d1=$(get lv_devices $vg/${lv}_rimage_1) + + printf "#\n#\n#\n# %s/%s (%s): run_writemostly_check\n#\n#\n#\n" \ + $vg $lv $segtype + + # I've seen this sync fail. when it does, it looks like sync + # thread has not been started... haven't repo'ed yet. + aux wait_for_sync $vg $lv + + # No writemostly flag should be there yet. + check lv_attr_bit health $vg/${lv}_rimage_0 "-" + check lv_attr_bit health $vg/${lv}_rimage_1 "-" + + if [ "$segtype" != "raid1" ]; then + not lvchange --writemostly $d0 $vg/$lv + return + fi + + # Set the flag + lvchange --writemostly $d0 $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "w" + + # Running again should leave it set (not toggle) + lvchange --writemostly $d0 $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "w" + + # Running again with ':y' should leave it set + lvchange --writemostly $d0:y $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "w" + + # ':n' should unset it + lvchange --writemostly $d0:n $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "-" + + # ':n' again should leave it unset + lvchange --writemostly $d0:n $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "-" + + # ':t' toggle to set + lvchange --writemostly $d0:t $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "w" + + # ':t' toggle to unset + lvchange --writemostly $d0:t $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "-" + + # ':y' to set + lvchange --writemostly $d0:y $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "w" + + # Toggle both at once + lvchange --writemostly $d0:t --writemostly $d1:t $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "-" + check lv_attr_bit health $vg/${lv}_rimage_1 "w" + + # Toggle both at once again + lvchange --writemostly $d0:t --writemostly $d1:t $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "w" + check lv_attr_bit health $vg/${lv}_rimage_1 "-" + + # Toggle one, unset the other + lvchange --writemostly $d0:n --writemostly $d1:t $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "-" + check lv_attr_bit health $vg/${lv}_rimage_1 "w" + + # Toggle one, set the other + lvchange --writemostly $d0:y --writemostly $d1:t $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "w" + check lv_attr_bit health $vg/${lv}_rimage_1 "-" + + # Partial flag supercedes writemostly flag + aux disable_dev $d0 + check lv_attr_bit health $vg/${lv}_rimage_0 "p" + + # It is possible for the kernel to detect the failed device before + # we re-enable it. If so, the field will be set to 'r'efresh since + # that also takes precedence over 'w'ritemostly. If this has happened, + # we refresh the LV and then check for 'w'. + aux enable_dev $d0 + check lv_attr_bit health $vg/${lv}_rimage_0 "r" && lvchange --refresh $vg/$lv + check lv_attr_bit health $vg/${lv}_rimage_0 "w" + + # Catch Bad writebehind values + invalid lvchange --writebehind "invalid" $vg/$lv + invalid lvchange --writebehind -256 $vg/$lv + + # Set writebehind + check lv_field $vg/$lv raid_write_behind "" + lvchange --writebehind 512 $vg/$lv + check lv_field $vg/$lv raid_write_behind "512" + + # Converting to linear should clear flags and writebehind + not lvconvert -m 0 $vg/$lv $d1 + lvconvert -y -m 0 $vg/$lv $d1 + lvconvert -y --type raid1 -m 1 $vg/$lv $d1 + check lv_field $vg/$lv raid_write_behind "" + check lv_attr_bit health $vg/${lv}_rimage_0 "-" + check lv_attr_bit health $vg/${lv}_rimage_1 "-" +} + + +# run_syncaction_check +run_syncaction_check() { + local device + local seek + local size + local tmp + local vg=$1 + local lv=${2}${THIN_POSTFIX} + + printf "#\n#\n#\n# %s/%s (%s): run_syncaction_check\n#\n#\n#\n" \ + $vg $lv "$(get lv_field "$vg/$lv" segtype -a)" + aux wait_for_sync $vg $lv + + device=$(get lv_devices $vg/${lv}_rimage_1) + + size=$(get lv_field $vg/${lv}_rimage_1 size -a --units 1k) + size=$(( ${size%\.00k} / 2 )) + + tmp=$(get pv_field "$device" mda_size --units 1k) + seek=${tmp%\.00k} # Jump over MDA + + tmp=$(get lv_field $vg/${lv}_rmeta_1 size -a --units 1k) + seek=$(( seek + ${tmp%\.00k} )) # Jump over RAID metadata image + + seek=$(( seek + size )) # Jump halfway through the RAID image + + check lv_attr_bit health $vg/$lv "-" + check lv_field $vg/$lv raid_mismatch_count "0" + + # Overwrite the last half of one of the PVs with crap + dd if=/dev/urandom of="$device" bs=1k count=$size seek=$seek + sync + + # Cycle the LV so we don't grab stripe cache buffers instead + # of reading disk. This can happen with RAID 4/5/6. You + # may think this is bad because those buffers could prevent + # us from seeing bad disk blocks, however, the stripe cache + # is not long lived. (RAID1/10 are immediately checked.) + lvchange -an $vg/$lv + lvchange -ay $vg/$lv + + # "check" should find discrepancies but not change them + # 'lvs' should show results + lvchange --syncaction check $vg/$lv + not lv_field $vg/$lv sync_percent "100.00" + aux wait_for_sync $vg $lv + check lv_attr_bit health $vg/$lv "m" + not check lv_field $vg/$lv raid_mismatch_count "0" + + # "repair" will fix discrepancies + lvchange --syncaction repair $vg/$lv + not lv_field $vg/$lv sync_percent "100.00" + aux wait_for_sync $vg $lv + + # Final "check" should show no mismatches + # 'lvs' should show results + lvchange --syncaction check $vg/$lv + not lv_field $vg/$lv sync_percent "100.00" + aux wait_for_sync $vg $lv + check lv_attr_bit health $vg/$lv "-" + check lv_field $vg/$lv raid_mismatch_count "0" +} + +# run_refresh_check +# Assumes "$dev2" is in the array +run_refresh_check() { + local size + local sizelv + local vg=$1 + local lv=${2}${THIN_POSTFIX} + + printf "#\n#\n#\n# %s/%s (%s): run_refresh_check\n#\n#\n#\n" \ + $vg $lv "$(get lv_field $vg/$lv segtype -a)" + + aux wait_for_sync $vg $lv + + sizelv=$vg/$lv + test -z "$THIN_POSTFIX" || sizelv=$vg/thinlv + size=$(get lv_field $sizelv size --units 1k) + size=${size%\.00k} + + # Disable dev2 and do some I/O to make the kernel notice + aux disable_dev "$dev2" + dd if=/dev/urandom of="$DM_DEV_DIR/$sizelv" bs=1k count=$size + sync + + # Check for 'p'artial flag + check lv_attr_bit health $vg/$lv "p" + dmsetup status + lvs -a -o name,attr,devices $vg + + aux enable_dev "$dev2" + + dmsetup status + lvs -a -o name,attr,devices $vg + + # Check for 'r'efresh flag + check lv_attr_bit health $vg/$lv "r" + + lvchange --refresh $vg/$lv + aux wait_for_sync $vg $lv + check lv_attr_bit health $vg/$lv "-" + + # Writing random data above should mean that the devices + # were out-of-sync. The refresh should have taken care + # of properly reintegrating the device. + lvchange --syncaction repair $vg/$lv + aux wait_for_sync $vg $lv + check lv_attr_bit health $vg/$lv "-" +} + +# run_recovery_rate_check +# Assumes "$dev2" is in the array +run_recovery_rate_check() { + local vg=$1 + local lv=${2}${THIN_POSTFIX} + + printf "#\n#\n#\n# %s/%s (%s): run_recovery_rate_check\n#\n#\n#\n" \ + $vg $lv "$(get lv_field $vg/$lv segtype -a)" + lvchange --minrecoveryrate 50 $vg/$lv + lvchange --maxrecoveryrate 100 $vg/$lv + + check lv_field $vg/$lv raid_min_recovery_rate "50" + check lv_field $vg/$lv raid_max_recovery_rate "100" +} + +# run_checks <"-"|snapshot_dev|"thinpool_data"|"thinpool_meta"> +run_checks() { + THIN_POSTFIX="" + + if [ -z "$3" ]; then + printf "#\n#\n# run_checks: Too few arguments\n#\n#\n" + return 1 + elif [ '-' = "$3" ]; then + printf "#\n#\n# run_checks: Simple check\n#\n#\n" + + run_writemostly_check $1 $2 + run_syncaction_check $1 $2 + run_refresh_check $1 $2 + run_recovery_rate_check $1 $2 + elif [ "thinpool_data" = "$3" ]; then + printf "#\n#\n# run_checks: RAID as thinpool data\n#\n#\n" + +# Hey, specifying devices for thin allocation doesn't work +# lvconvert -y --thinpool $1/$2 "$dev6" + lvcreate -aey -L 2M -n ${2}_meta $1 "$dev6" + lvconvert --thinpool $1/$2 --poolmetadata ${2}_meta + lvcreate -T $1/$2 -V 1 -n thinlv + THIN_POSTFIX="_tdata" + + run_writemostly_check $1 $2 + run_syncaction_check $1 $2 + run_refresh_check $1 $2 + run_recovery_rate_check $1 $2 + elif [ "thinpool_meta" = "$3" ]; then + printf "#\n#\n# run_checks: RAID as thinpool metadata\n#\n#\n" + + lvrename $1/$2 ${2}_meta + lvcreate -aey -L 2M -n $2 $1 "$dev6" + lvconvert -y --thinpool $1/$2 --poolmetadata ${2}_meta + lvcreate -T $1/$2 -V 1 -n thinlv + THIN_POSTFIX="_tmeta" + + run_writemostly_check $1 $2 + run_syncaction_check $1 $2 + run_refresh_check $1 $2 + run_recovery_rate_check $1 $2 + elif [ "snapshot" = "$3" ]; then + printf "#\n#\n# run_checks: RAID under snapshot\n#\n#\n" + lvcreate -aey -s $1/$2 -l 4 -n snap "$dev6" + + run_writemostly_check $1 $2 + run_syncaction_check $1 $2 + run_refresh_check $1 $2 + run_recovery_rate_check $1 $2 + + lvremove -ff $1/snap + else + printf "#\n#\n# run_checks: Invalid argument\n#\n#\n" + return 1 + fi +} + +run_types() { + for i in $TEST_TYPES ; do + lvcreate -n $lv1 $vg -L2M --type "$@" + run_checks $vg $lv1 $i + lvremove -ff $vg + done +} + +######################################################## +# MAIN +######################################################## + +TEST_TYPES="- snapshot" +# RAID works EX in cluster +# thinpool works EX in cluster +# but they don't work together in a cluster yet +# (nor does thinpool+mirror work in a cluster yet) +test ! -e LOCAL_CLVMD && aux have_thin 1 8 0 && TEST_TYPE="$TEST_TYPES thinpool_data thinpool_meta" + +# Implicit test for 'raid1' only +if test "${TEST_RAID:-raid1}" = raid1 ; then + run_types raid1 -m 1 "$dev1" "$dev2" + vgremove -ff $vg +fi diff --git a/test/shell/lvchange-raid1-writemostly.sh b/test/shell/lvchange-raid1-writemostly.sh new file mode 100644 index 0000000..039429a --- /dev/null +++ b/test/shell/lvchange-raid1-writemostly.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_raid 1 3 5 || skip + +aux prepare_vg 4 +get_devs + +for d in "$dev1" "$dev2" "$dev3" "$dev4" +do + aux delay_dev "$d" 0 20 "$(get first_extent_sector "$d")" +done + +# +# Test writemostly prohibited on resynchronizing raid1 +# + +# Create 4-way raid1 LV +lvcreate -aey --ty raid1 -m 3 -Zn -L16M -n $lv1 $vg +not lvchange -y --writemostly "$dev1" "$vg/$lv1" +check lv_field $vg/$lv1 segtype "raid1" +check lv_field $vg/$lv1 stripes 4 +check lv_attr_bit health $vg/${lv1}_rimage_0 "-" +aux enable_dev "${DEVICES[@]}" +aux wait_for_sync $vg $lv1 +lvchange -y --writemostly "$dev1" "$vg/$lv1" +check lv_attr_bit health $vg/${lv1}_rimage_0 "w" + +vgremove -ff $vg diff --git a/test/shell/lvchange-raid10.sh b/test/shell/lvchange-raid10.sh new file mode 100644 index 0000000..a29ade9 --- /dev/null +++ b/test/shell/lvchange-raid10.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +TEST_RAID=raid10 + +. shell/lvchange-raid.sh + +aux have_raid 1 5 2 || skip + +run_types raid10 -m 1 -i 2 "$dev1" "$dev2" "$dev3" "$dev4" + +vgremove -ff $vg diff --git a/test/shell/lvchange-raid456.sh b/test/shell/lvchange-raid456.sh new file mode 100644 index 0000000..ea4b4e2 --- /dev/null +++ b/test/shell/lvchange-raid456.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +TEST_RAID=raid456 + +. shell/lvchange-raid.sh + +aux raid456_replace_works || skip +aux have_raid 1 5 2 || skip + +aux have_raid4 && run_types raid4 -i 2 "$dev1" "$dev2" "$dev3" "$dev4" +run_types raid5 -i 2 "$dev1" "$dev2" "$dev3" "$dev4" +run_types raid6 -i 3 "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + +vgremove -ff $vg diff --git a/test/shell/lvchange-rebuild-raid.sh b/test/shell/lvchange-rebuild-raid.sh new file mode 100644 index 0000000..d2bb723 --- /dev/null +++ b/test/shell/lvchange-rebuild-raid.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 2 || skip +v1_9_0=0 +aux have_raid 1 9 0 && v1_9_0=1 + +aux prepare_vg 8 +get_devs + +_sync() { + aux enable_dev "${DEVICES[@]}" + + aux wait_for_sync $vg $lv1 + test "$#" -eq 0 || check raid_leg_status $vg $lv1 "$@" + + # restore to delay_dev tables for all devices + aux restore_from_devtable "${DEVICES[@]}" +} + +# Delay legs so that rebuilding status characters can be read +for d in "${DEVICES[@]}" +do + aux delay_dev "$d" 0 50 "$(get first_extent_sector "$d")" +done + +# rhbz 1064592 + +############################################## +# Create an 8-way striped raid10 with 4 mirror +# groups and rebuild selected PVs. +lvcreate --type raid10 -m 1 -i 4 -l 64 -n $lv1 $vg +_sync "AAAAAAAA" + +# Rebuild 1st and 2nd device would rebuild a +# whole mirror group and needs to be rejected. +not lvchange --yes --rebuild "$dev1" --rebuild "$dev2" $vg/$lv1 +not check raid_leg_status $vg $lv1 "aaAAAAA" +_sync "AAAAAAAA" + +# Rebuild 1st and 3rd device from different mirror groups is fine. +lvchange --yes --rebuild "$dev1" --rebuild "$dev3" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "aAaAAAAA" +_sync "AAAAAAAA" + +# Rebuild devices 1, 3, 6 from different mirror groups is fine. +lvchange --yes --rebuild "$dev1" --rebuild "$dev3" --rebuild "$dev6" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "aAaAAaAA" +_sync "AAAAAAAA" + +# Rebuild devices 1, 3, 5 and 6 with 5+6 being +# being a whole mirror group needs to be rejected. +not lvchange --yes --rebuild "$dev1" --rebuild "$dev3" --rebuild "$dev6" --rebuild "$dev5" $vg/$lv1 +not check raid_leg_status $vg $lv1 "aAaAaaAA" +_sync "AAAAAAAA" + +# Rebuild devices 1, 3, 5 and 7 from different mirror groups is fine. +lvchange --yes --rebuild "$dev1" --rebuild "$dev3" --rebuild "$dev5" --rebuild "$dev7" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "aAaAaAaA" +_sync + +# Rebuild devices 2, 4, 6 and 8 from different mirror groups is fine. +lvchange --yes --rebuild "$dev2" --rebuild "$dev4" --rebuild "$dev6" --rebuild "$dev8" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "AaAaAaAa" +_sync "AAAAAAAA" + +############################################## +# Create an 8-legged raid1 and rebuild selected PVs +lvremove --yes $vg/$lv1 +lvcreate --yes --type raid1 -m 7 -l 2 -n $lv1 $vg +_sync "AAAAAAAA" + +# Rebuilding all raid1 legs needs to be rejected. +not lvchange --yes --rebuild "$dev1" --rebuild "$dev2" --rebuild "$dev3" --rebuild "$dev4" \ + --rebuild "$dev5" --rebuild "$dev6" --rebuild "$dev7" --rebuild "$dev8" $vg/$lv1 +not check raid_leg_status $vg $lv1 "aaaaaaaa" +_sync "AAAAAAAA" + +# Rebuilding all but the raid1 master leg is fine. +lvchange --yes --rebuild "$dev2" --rebuild "$dev3" --rebuild "$dev4" \ + --rebuild "$dev5" --rebuild "$dev6" --rebuild "$dev7" --rebuild "$dev8" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "Aaaaaaaa" +_sync "AAAAAAAA" + +# Rebuilding the raid1 master leg is fine. +lvchange --yes --rebuild "$dev1" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "aAAAAAAA" +_sync "AAAAAAAA" + +# Rebuild legs on devices 2, 4, 6 and 8 is fine. +lvchange --yes --rebuild "$dev2" --rebuild "$dev4" --rebuild "$dev6" --rebuild "$dev8" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "AaAaAaAa" +_sync "AAAAAAAA" + +############################################## +# Create an 6-legged raid6 and rebuild selected PVs +lvremove --yes $vg/$lv1 +lvcreate --yes --type raid6 -i 4 -l 2 -n $lv1 $vg +_sync "AAAAAA" + +# Rebuilding all raid6 stripes needs to be rejected. +not lvchange --yes --rebuild "$dev1" --rebuild "$dev2" --rebuild "$dev3" \ + --rebuild "$dev4" --rebuild "$dev5" --rebuild "$dev6" $vg/$lv1 +not check raid_leg_status $vg $lv1 "aaaaaa" +_sync "AAAAAA" + +# Rebuilding more than 2 raid6 stripes needs to be rejected. +not lvchange --yes --rebuild "$dev2" --rebuild "$dev4" --rebuild "$dev6" $vg/$lv1 +not check raid_leg_status $vg $lv1 "AaAaAa" +_sync "AAAAAA" + +# Rebuilding any 1 raid6 stripe is fine. +lvchange --yes --rebuild "$dev2" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "AaAAAA" +_sync + +lvchange --yes --rebuild "$dev5" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "AAAAaA" +_sync "AAAAAA" + +# Rebuilding any 2 raid6 stripes is fine. +lvchange --yes --rebuild "$dev2" --rebuild "$dev4" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "AaAaAA" +_sync "AAAAAA" + +lvchange --yes --rebuild "$dev1" --rebuild "$dev5" $vg/$lv1 +[ $v1_9_0 -eq 1 ] && check raid_leg_status $vg $lv1 "aAAAaA" +_sync "AAAAAA" + +vgremove -ff $vg diff --git a/test/shell/lvchange-syncaction-raid.sh b/test/shell/lvchange-syncaction-raid.sh new file mode 100644 index 0000000..73270f0 --- /dev/null +++ b/test/shell/lvchange-syncaction-raid.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test activation race for raid's --syncaction check + + +SKIP_WITH_LVMPOLLD=1 + + +# Current support for syncaction in cluster is broken +# might get fixed one day though +# meanwhile skipped +SKIP_WITH_CLVMD=1 + +. lib/inittest + +# Proper mismatch count 1.5.2+ upstream, 1.3.5 < x < 1.4.0 in RHEL6 +aux have_raid 1 3 5 && + ! aux have_raid 1 4 0 || + aux have_raid 1 5 2 || skip +aux prepare_vg 3 + +lvcreate -n $lv1 $vg -l1 --type raid1 + +aux wait_for_sync $vg $lv1 + +START=$(get pv_field "$dev2" pe_start --units 1k) +METASIZE=$(get lv_field $vg/${lv1}_rmeta_1 size -a --units 1k) +SEEK=$((${START%\.00k} + ${METASIZE%\.00k})) +# Overwrite some portion of _rimage_1 + +#aux delay_dev "$dev2" 10 10 +dd if=/dev/urandom of="$dev2" bs=1K count=1 seek=$SEEK oflag=direct +# FIXME +# Some delay - there is currently race in upstream kernel +# test may occasionaly fail with: +# device-mapper: message ioctl on failed: Device or resource busy +# +# Heinz's kernel seems to fix this particular issue but +# has some other problem for now +aux udev_wait + +lvchange --syncaction check $vg/$lv1 + +# Wait till scrubbing is finished +aux wait_for_sync $vg $lv1 + +check lv_field $vg/$lv1 raid_mismatch_count "128" + +# Let's deactivate +lvchange -an $vg/$lv1 + +lvchange -ay $vg/$lv1 +# noone has it open and target is read & running +dmsetup info -c | grep $vg + +#sleep 10 < "$DM_DEV_DIR/$vg/$lv1" & +# "check" should find discrepancies but not change them +# 'lvs' should show results + +# FIXME +# this looks like some race with 'write' during activation +# and syncaction... +# For now it fails with: +# device-mapper: message ioctl on failed: Device or resource busy +# +# As solution for now - user needs to run --synaction on synchronous raid array +# +aux wait_for_sync $vg $lv1 + +# Check raid array doesn't know about error yet +check lv_field $vg/$lv1 raid_mismatch_count "0" + +# Start scrubbing +lvchange --syncaction check $vg/$lv1 + +# Wait till scrubbing is finished +aux wait_for_sync $vg $lv1 + +# Retest mistmatch exists +check lv_field $vg/$lv1 raid_mismatch_count "128" + +vgremove -ff $vg diff --git a/test/shell/lvchange-thin.sh b/test/shell/lvchange-thin.sh new file mode 100644 index 0000000..5c23103 --- /dev/null +++ b/test/shell/lvchange-thin.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip + +aux prepare_pvs 3 + +vgcreate $SHARED -s 128k $vg "$dev1" "$dev2" +vgcreate $SHARED -s 128k $vg2 "$dev3" + +lvcreate -L10M -T $vg/pool + +# When PV does not support discard +# tests for checking thin-pool discard passdown are skipped +pvmajor=$(get pv_field "$dev1" major) +pvminor=$(get pv_field "$dev1" minor) + +if test "$(< "/sys/dev/block/$pvmajor:$pvminor/queue/discard_granularity")" -eq 0 ; then + no_discard=1 +else + no_discard= +fi + +# +# Check change operations on a thin-pool without any thin LV +# +# discards_ARG (default is passdown) +test -n "$no_discard" || check grep_dmsetup status $vg-pool " discard_passdown" || { + # trace device layout + grep -r "" /sys/block/* + die "Device was expected to support passdown" +} + +lvchange --discards nopassdown $vg/pool +check grep_dmsetup table $vg-pool " no_discard_passdown" +test -n "$no_discard" || check grep_dmsetup status $vg-pool " no_discard_passdown" + +lvchange --discards passdown $vg/pool +check grep_dmsetup table $vg-pool -v "passdown" +test -n "$no_discard" || check grep_dmsetup status $vg-pool " discard_passdown" + +# zero_ARG (default is 'yes') +check grep_dmsetup table $vg-pool -v "zeroing" +lvchange --zero n $vg/pool +check grep_dmsetup table $vg-pool " skip_block_zeroing" +lvchange --zero y $vg/pool +check grep_dmsetup table $vg-pool -v "zeroing" + +# errorwhenfull_ARG (default is 'no') +check grep_dmsetup status $vg-pool "queue_if_no_space" +lvchange --errorwhenfull y $vg/pool +check grep_dmsetup status $vg-pool "error_if_no_space" +check grep_dmsetup table $vg-pool "error_if_no_space" +lvchange --errorwhenfull n $vg/pool +check grep_dmsetup status $vg-pool "queue_if_no_space" +check grep_dmsetup table $vg-pool -v "error_if_no_space" + + +# Attach thin volume +lvcreate -V10M -n $lv1 $vg/pool +lvcreate -L10M -n $lv2 $vg + +lvchange -an $vg/$lv1 + +# Test activation +lvchange -aly $vg/$lv1 +check active $vg $lv1 + +lvchange -aln $vg/$lv1 +check inactive $vg $lv1 + +# Test for allowable changes +# +# contiguous_ARG +lvchange -C y $vg/$lv1 +lvchange -C n $vg/$lv1 + +# permission_ARG +lvchange -p r $vg/$lv1 +lvchange -p rw $vg/$lv1 + +# FIXME +#should lvchange -p r $vg/pool +#should lvchange -p rw $vg/pool + +# readahead_ARG +lvchange -r none $vg/$lv1 +lvchange -r auto $vg/$lv1 +# FIXME +# Think about more support + +# minor_ARG +lvchange --yes -M y --minor 234 --major 253 $vg/$lv1 +lvchange -M n $vg/$lv1 + +# cannot change major minor for pools +not lvchange --yes -M y --minor 235 --major 253 $vg/pool +not lvchange -M n $vg/pool + +# addtag_ARG +lvchange --addtag foo $vg/$lv1 +lvchange --addtag foo $vg/pool + +# deltag_ARG +lvchange --deltag foo $vg/$lv1 +lvchange --deltag foo $vg/pool + +# discards_ARG +lvchange --discards nopassdown $vg/pool +check grep_dmsetup table $vg-pool-tpool " no_discard_passdown" +test -n "$no_discard" || check grep_dmsetup status $vg-pool-tpool " no_discard_passdown" +lvchange --discards passdown $vg/pool +check grep_dmsetup table $vg-pool-tpool -v "passdown" +test -n "$no_discard" || check grep_dmsetup status $vg-pool-tpool " discard_passdown" + +# zero_ARG +lvchange --zero n $vg/pool +check grep_dmsetup table $vg-pool-tpool " skip_block_zeroing" +lvchange --zero y $vg/pool +check grep_dmsetup table $vg-pool-tpool -v "zeroing" + + +lvchange --errorwhenfull y $vg/pool +check grep_dmsetup status $vg-pool-tpool "error_if_no_space" +check grep_dmsetup table $vg-pool-tpool "error_if_no_space" +lvchange --errorwhenfull n $vg/pool +check grep_dmsetup status $vg-pool-tpool "queue_if_no_space" +check grep_dmsetup table $vg-pool-tpool -v "error_if_no_space" + + +# +# Test for disallowed metadata changes +# +# resync_ARG +not lvchange --resync $vg/$lv1 + +# alloc_ARG +#not lvchange --alloc anywhere $vg/$lv1 + +# discards_ARG +not lvchange --discards ignore $vg/$lv1 + +# zero_ARG +not lvchange --zero y $vg/$lv1 + + +# +# Ensure that allowed args don't cause disallowed args to get through +# +not lvchange --resync -ay $vg/$lv1 +not lvchange --resync --addtag foo $vg/$lv1 + +# +# Play with tags and activation +# +TAG=$(uname -n) +aux lvmconf "activation/volume_list = [ \"$vg/$lv2\", \"@mytag\" ]" + +lvchange -ay $vg/$lv1 +check inactive $vg $lv1 + +lvchange --addtag mytag $vg/$lv1 + +lvchange -ay @mytag_fake +check inactive $vg $lv1 + +lvchange -ay $vg/$lv1 +# Volume has matching tag +check active $vg $lv1 +lvchange -an $vg/$lv1 + +lvchange -ay @mytag +check active $vg $lv1 + +# Fails here since it cannot clear device header +not lvcreate -Zy -L10 -n $lv3 $vg2 +# OK when zeroing is disabled +lvcreate -Zn -L10 -n $lv3 $vg2 +check inactive $vg2 $lv3 + +aux lvmconf "activation/volume_list = [ \"$vg2\" ]" +vgchange -an $vg +vgchange -ay $vg $vg2 +lvs -a -o+lv_active $vg $vg2 + +aux lvmconf "activation/volume_list = [ \"$vg\", \"$vg2\" ]" + +vgremove -ff $vg $vg2 diff --git a/test/shell/lvchange-vdo.sh b/test/shell/lvchange-vdo.sh new file mode 100644 index 0000000..b11edf3 --- /dev/null +++ b/test/shell/lvchange-vdo.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_vdo 6 2 0 || skip + +aux prepare_vg 2 6400 + +lvcreate --vdo -L5G -n $lv1 $vg/vdopool + +# deduplication_ARG (default is 'yes') +# compression_ARG (default is 'yes') + +# Wait till index gets openned +for i in {1..10} ; do + sleep .1 + check grep_dmsetup status $vg-vdopool-vpool " online online " || continue + break +done + + +# compression_ARG +lvchange --compression n $vg/vdopool +check grep_dmsetup status $vg-vdopool-vpool " online offline " +lvchange --compression y $vg/vdopool +check grep_dmsetup status $vg-vdopool-vpool " online online " + +# dedulication_ARG +lvchange --deduplication n $vg/vdopool +check grep_dmsetup status $vg-vdopool-vpool -E " offline|closed online " + +lvchange --deduplication y $vg/vdopool +check grep_dmsetup status $vg-vdopool-vpool -E " online|opening online " + + +lvchange --compression n --deduplication n $vg/vdopool +check grep_dmsetup status $vg-vdopool-vpool -E " offline|closed offline " + +# --vdosettings needs inactive LV +not lvchange --vdosettings 'ack_threads=8' $vg/vdopool + +lvchange -an $vg/$lv1 + +# With inactive vdo-pool changes are applied +# explicit option --compression has highest priority +lvchange --vdosettings 'ack_threads=5 compression=0' --compression y $vg/vdopool +check lv_field $vg/$lv1 vdo_ack_threads "5" +check lv_field $vg/$lv1 vdo_compression "enabled" + +# Test activation +lvchange -aly $vg/$lv1 +check active $vg $lv1 + +lvchange -aln $vg/$lv1 +check inactive $vg $lv1 + +# Test for allowable changes +# +# contiguous_ARG +lvchange -C y $vg/$lv1 +lvchange -C n $vg/$lv1 + +# permission_ARG +lvchange -p r $vg/$lv1 +lvchange -p rw $vg/$lv1 + +# FIXME +#should lvchange -p r $vg/vdopool +#should lvchange -p rw $vg/vdopool + +# readahead_ARG +lvchange -r none $vg/$lv1 +lvchange -r auto $vg/$lv1 +# FIXME +# Think about more support + +# minor_ARG +lvchange --yes -M y --minor 234 --major 253 $vg/$lv1 +lvchange -M n $vg/$lv1 + +# cannot change major minor for pools +not lvchange --yes -M y --minor 235 --major 253 $vg/vdopool +not lvchange -M n $vg/vdopool + +# addtag_ARG +lvchange --addtag foo $vg/$lv1 +lvchange --addtag foo $vg/vdopool + +# deltag_ARG +lvchange --deltag foo $vg/$lv1 +lvchange --deltag foo $vg/vdopool + + +# +# Test for disallowed metadata changes +# +# resync_ARG +not lvchange --resync $vg/$lv1 + +# alloc_ARG +#not lvchange --alloc anywhere $vg/$lv1 + +# discards_ARG +not lvchange --discards ignore $vg/$lv1 + +# zero_ARG +not lvchange --zero y $vg/$lv1 + + +# +# Ensure that allowed args don't cause disallowed args to get through +# +not lvchange --resync -ay $vg/$lv1 +not lvchange --resync --addtag foo $vg/$lv1 + +# Check activation of VDO alone works (like for thin-pools) +lvchange -an $vg + +lvchange -ay $vg/vdopool +check active $vg vdopool +check inactive $vg $lv1 + +lvchange -ay $vg/$lv1 +check active $vg $lv1 + +lvchange -an $vg/$lv1 +check active $vg vdopool +check inactive $vg $lv1 + +lvchange -ay $vg/$lv1 +lvchange -an $vg/vdopool +lvchange -an $vg/$lv1 +check inactive $vg vdopool + +# +# Play with tags and activation +# +TAG=$(uname -n) +aux lvmconf "activation/volume_list = [ \"$vg/$lv2\", \"@mytag\" ]" + +lvchange -ay $vg/$lv1 +check inactive $vg $lv1 + +lvchange --addtag mytag $vg/$lv1 + +lvchange -ay @mytag_fake +check inactive $vg $lv1 + +lvchange -ay $vg/$lv1 +# Volume has matching tag +check active $vg $lv1 +lvchange -an $vg/$lv1 + +lvchange -ay @mytag +check active $vg $lv1 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-cache-abort.sh b/test/shell/lvconvert-cache-abort.sh new file mode 100644 index 0000000..f0f9220 --- /dev/null +++ b/test/shell/lvconvert-cache-abort.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise cache flushing is abortable + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +aux prepare_vg + +SIZE_MB=200 + +# Use large zero device and later delayed metadata dev1 +lvcreate -L$((SIZE_MB * 2))M --type zero -n cpool $vg +lvconvert -y --type cache-pool --chunksize 32k $vg/cpool "$dev1" +lvcreate -L$((SIZE_MB * 2))M --type zero -n $lv1 $vg +lvconvert -y -H --chunksize 32k --cachemode writeback --cachepool $vg/cpool $vg/$lv1 + +# +# Ensure cache gets promoted blocks +# +for i in $(seq 1 2) ; do +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=$SIZE_MB oflag=direct || true +dd if="$DM_DEV_DIR/$vg/$lv1" of=/dev/null bs=1M count=$SIZE_MB iflag=direct || true +done + +aux delay_dev "$dev1" 0 200 "$(get first_extent_sector "$dev1"):" +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=$SIZE_MB + +lvdisplay --maps $vg +# Delay dev to ensure we have some time to 'capture' interrupt in flush + +# TODO, how to make writeback cache dirty +test "$(get lv_field $vg/$lv1 cache_dirty_blocks)" -gt 0 || { + lvdisplay --maps $vg + skip "Cannot make a dirty writeback cache LV." +} + +LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -vvvv --splitcache $vg/$lv1 >logconvert 2>&1 & +PID_CONVERT=$! +for i in {1..50}; do + out=$(dmsetup status --noflush "$vg-$lv1") + case "$out" in + *cleaner*) break;; + esac + echo "$i: Waiting for cleaner policy on $vg/$lv1" + sleep .01 +done +test "$i" -ge 49 && die "Waited for cleaner policy on $vg/$lv1 too long!" + +# While lvconvert updated table to 'cleaner' policy now it +# should be running in 'Flushing' loop and just 1 KILL should +# cause abortion of flushing +kill -INT $PID_CONVERT +aux enable_dev "$dev2" +wait +#cat logconvert || true + +# Problem of this test is, in older kernels, even the initial change to cleaner +# policy table line causes long suspend which in practice is cleaning all the +# dirty blocks - so the test can't really break the cache clearing. +# +# So the failure of test is reported only for recent kernels > 5.6 +# ans skipped otherwise - as those can't be fixed anyway +grep -E "Flushing.*aborted" logconvert || { + cat logconvert || true + vgremove -f $vg + aux kernel_at_least 5 6 || skip "Cache missed to abort flushing with older kernel" + die "Flushing of $vg/$lv1 not aborted ?" +} + +# check the table got restored +check grep_dmsetup table $vg-$lv1 "writeback" +lvdisplay --maps $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-cache-chunks.sh b/test/shell/lvconvert-cache-chunks.sh new file mode 100644 index 0000000..72a64de --- /dev/null +++ b/test/shell/lvconvert-cache-chunks.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016-2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise number of cache chunks in cache pool +# Skips creation of real cached device for older cache targets... + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +aux prepare_vg 2 1000000 + +# Really large cache pool data LV +lvcreate -L1T -n cpool $vg + +# Works and pick higher chunks size then default +lvconvert -y --type cache-pool $vg/cpool + +# Check chunk size in sectors is more then 512K +test "$(get lv_field "$vg/cpool" chunk_size --units s --nosuffix)" -gt 1000 + +lvcreate -L1M -n $lv1 $vg + +# Not let pass small chunks when caching origin +fail lvconvert -y -H --chunksize 128K --cachepool $vg/cpool $vg/$lv1 >out 2>&1 +cat out +grep "too small chunk size" out + +# Thought 2M is valid +if aux have_cache 1 8 0 ; then + # Without SMQ we run out of kernel memory easily + lvconvert -y -H --chunksize 2M --cachepool $vg/cpool $vg/$lv1 +fi + +lvremove -f $vg + +### + +# Really large cache pool data LV +lvcreate -L1T -n cpool $vg +# Not allowed to create more then 10e6 chunks +fail lvconvert -y --type cache-pool --chunksize 128K $vg/cpool + +if aux have_cache 1 8 0 ; then + # Let operation pass when max_chunk limit is raised + lvconvert -y --type cache-pool --chunksize 128K $vg/cpool \ + --config 'allocation/cache_pool_max_chunks=10000000' +fi + +vgremove -f $vg diff --git a/test/shell/lvconvert-cache-raid.sh b/test/shell/lvconvert-cache-raid.sh new file mode 100644 index 0000000..033376d --- /dev/null +++ b/test/shell/lvconvert-cache-raid.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise usage of stacked cache volume using raid volume + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip +aux have_raid 1 0 0 || skip + +aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]' + +aux prepare_vg 5 80 + +# Bug 1095843 +# lvcreate RAID1 origin, lvcreate cache-pool, and lvconvert to cache +lvcreate --type raid1 -m 1 --nosync -l 2 -n $lv1 $vg +lvcreate --type cache-pool -l 1 -n ${lv1}_cachepool $vg +lvconvert --cache -Zy --cachepool $vg/${lv1}_cachepool $vg/$lv1 +check lv_exists $vg/${lv1}_corig_rimage_0 # ensure images are properly renamed +dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel +lvremove -f $vg + + +# lvcreate RAID1 origin, lvcreate RAID1 cache-pool, and lvconvert to cache +lvcreate --type raid1 -m 1 --nosync -l 2 -n $lv1 $vg +lvcreate --type raid1 -m 1 --nosync -l 2 -n ${lv1}_cachepool $vg +#should lvs -a $vg/${lv1}_cdata_rimage_0 # ensure images are properly renamed +lvconvert --yes --type cache --cachemode writeback --cachepool $vg/${lv1}_cachepool $vg/$lv1 2>&1 | tee out +grep "WARNING: Data redundancy could be lost" out +check lv_exists $vg/${lv1}_corig_rimage_0 # ensure images are properly renamed +dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel +lvremove -f $vg + + +lvcreate -n corigin -m 1 --type raid1 --nosync -l 10 $vg +lvcreate -n cpool --type cache $vg/corigin --cachemode writeback -l 10 2>&1 | tee out +grep "WARNING: Data redundancy could be lost" out +not lvconvert --splitmirrors 1 --name split $vg/corigin "$dev1" +lvconvert --yes --splitmirrors 1 --name split $vg/corigin "$dev1" + +lvremove -f $vg + +lvcreate -n cpool_meta -m 1 --type raid1 -l 10 $vg +lvcreate -n cpool -m 1 --type raid1 -l 10 $vg +aux wait_for_sync $vg cpool_meta +aux wait_for_sync $vg cpool +lvs -a -o+seg_pe_ranges $vg +lvconvert --yes --type cache-pool --poolmetadata $vg/cpool_meta $vg/cpool +lvcreate -n corigin --type cache --cachepool $vg/cpool -l 10 + +lvchange --syncaction repair $vg/cpool_cpool_cmeta +aux wait_for_sync $vg cpool_cpool_cmeta + +lvchange --syncaction repair $vg/cpool_cpool_cdata +aux wait_for_sync $vg cpool_cpool_cdata + +lvconvert -y --repair $vg/cpool_cpool_cmeta +lvconvert -y --repair $vg/cpool_cpool_cdata + +# do not allow reserved names for *new* LVs +not lvconvert --splitmirrors 1 --name split_cmeta $vg/cpool_cpool_cmeta "$dev1" +not lvconvert --splitmirrors 1 --name split_cdata $vg/cpool_cpool_cdata "$dev1" + +# but allow manipulating existing LVs with reserved names +aux wait_for_sync $vg cpool_cpool_cmeta +aux wait_for_sync $vg cpool_cpool_cdata +lvconvert --yes --splitmirrors 1 --name split_meta $vg/cpool_cpool_cmeta "$dev1" +lvconvert --yes --splitmirrors 1 --name split_data $vg/cpool_cpool_cdata "$dev1" +not lvconvert --splitmirrors 1 --name split_data $vg/cpool_cpool_cdata "$dev1" + +lvremove -f $vg + + +# Test up/down raid conversion of cache pool data and metadata + +lvcreate -l 10 -n cp1 $vg +lvconvert -y --type cache-pool $vg/cp1 + +lvcreate -l 20 -n co1 $vg +lvconvert -y --type cache --cachepool cp1 $vg/co1 + +lvconvert -y -m +1 --type raid1 $vg/cp1_cpool_cmeta +check lv_field $vg/cp1_cpool_cmeta layout "raid,raid1" +check lv_field $vg/cp1_cpool_cmeta role "private,cache,pool,metadata" + +lvconvert -y -m +1 --type raid1 $vg/cp1_cpool_cdata +check lv_field $vg/cp1_cpool_cdata layout "raid,raid1" +check lv_field $vg/cp1_cpool_cdata role "private,cache,pool,data" + +sleep 5 + +lvs -a -o+devices $vg + +not lvconvert -m -1 $vg/cp1_cpool_cmeta + +lvconvert -y -m -1 $vg/cp1_cpool_cmeta +check lv_field $vg/cp1_cpool_cmeta layout "linear" +lvconvert -y -m -1 $vg/cp1_cpool_cdata +check lv_field $vg/cp1_cpool_cdata layout "linear" + +lvremove -f $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-cache-smq.sh b/test/shell/lvconvert-cache-smq.sh new file mode 100644 index 0000000..67710fa --- /dev/null +++ b/test/shell/lvconvert-cache-smq.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise conversion of cache and cache pool + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 8 0 || skip + +aux prepare_vg 5 80 + +lvcreate --type cache-pool -an -v -L 2 -n cpool $vg + +lvcreate -H --cachepolicy smq -L 4 -n corigin --cachepool $vg/cpool + +check lv_field $vg/corigin cache_policy "smq" + +lvconvert --splitcache $vg/corigin + +lvs -o+cache_policy -a $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-cache-snapshot.sh b/test/shell/lvconvert-cache-snapshot.sh new file mode 100644 index 0000000..ac9d3dd --- /dev/null +++ b/test/shell/lvconvert-cache-snapshot.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test various supported conversion of snapshot of cached volume + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +aux prepare_vg 1 + + +# Prepare cached LV +lvcreate -aey -L1 -n $lv1 $vg +lvcreate -H -L2 -n cpool $vg/$lv1 + +# Prepare snapshot 'cow' LV +lvcreate -L3 -n cow $vg + +# Can't use 'cached' cow volume +not lvconvert -s cow $vg/$lv1 + +# Use cached LV with 'striped' cow volume +lvconvert -y -s $vg/$lv1 cow +check lv_field $vg/cow segtype linear +check lv_field $vg/$lv1 segtype cache + +# Drop cache while being in-use origin +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear + +# Cache existing origin +lvconvert -y --cache $vg/$lv1 --cachepool $vg/cpool +check lv_field $vg/$lv1 segtype cache + +# Cannot split from 'origin' (being cached LV) +not lvconvert -y --splitsnapshot $vg/$lv1 + +lvchange --cachemode writeback $vg/$lv1 +check lv_field $vg/$lv1 cache_mode "writeback" +check grep_dmsetup status ${vg}-${lv1}-real "writeback" + +lvchange --cachemode writethrough $vg/$lv1 +check lv_field $vg/$lv1 cache_mode "writethrough" +check grep_dmsetup status ${vg}-${lv1}-real "writethrough" + +# Split 'cow' from cached origin +lvconvert -y --splitsnapshot $vg/cow +get lv_field $vg/cow attr | grep "^-wi" + +vgremove -f $vg diff --git a/test/shell/lvconvert-cache-thin.sh b/test/shell/lvconvert-cache-thin.sh new file mode 100644 index 0000000..3fdd258 --- /dev/null +++ b/test/shell/lvconvert-cache-thin.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise usage of stacked cache volume used in thin pool volumes + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip +aux have_thin 1 0 0 || skip + +aux prepare_vg 5 80 + +# +# Check caching of whole thin-pool +# +lvcreate -L10 -n cpool $vg +lvcreate -L10 -n tpool $vg +lvcreate -L10 -n $lv1 $vg + +lvconvert --yes --cache --cachepool cpool $vg/tpool + +lvconvert --yes --type thin-pool $vg/tpool + +lvcreate -V10 -T -n $lv2 $vg/tpool + +aux mkdev_md5sum $vg $lv2 + +lvconvert --splitcache $vg/tpool + +check dev_md5sum $vg $lv2 +lvchange -an $vg +lvchange -ay $vg +check dev_md5sum $vg $lv2 + +lvs -a $vg +lvconvert --yes --cache --cachepool cpool $vg/tpool + +lvconvert --yes -T --thinpool $vg/tpool $vg/$lv1 +check lv_field $vg/tpool segtype "thin-pool" +check lv_field $vg/$lv1 segtype "thin" +lvconvert --uncache $vg/tpool +lvs -a $vg + +lvremove -f $vg + + +# +# Check caching of single individual thin LV +# +lvcreate --type cache-pool -L10 -n cpool $vg +lvcreate -T -L10 -V10 -n $lv1 $vg/tpool + +lvconvert --yes -H --cachepool $vg/cpool $vg/$lv1 +check lv_field $vg/${lv1}_corig segtype "thin" -a +check lv_field $vg/$lv1 segtype "cache" + +# Other thins from the thin-pool can be created +lvcreate -V10 $vg/tpool + +# ATM there is no support to take snapshot of cache thin LV +not lvcreate -s $vg/$lv1 + +# Use can take thick snapshot +lvcreate -s -L10 -n $lv2 $vg/$lv1 +check lv_field $vg/$lv2 segtype "linear" + +lvchange -an $vg +lvchange -ay $vg + +lvconvert --uncache $vg/$lv1 + +lvremove -f $vg + + +# +# Check conversion of cached LV works as thin-pool +# +lvcreate -L10 -n $lv $vg +lvcreate -L10 -n $lv1 $vg +lvcreate -H -L10 $vg/$lv + +# Stack of cache over cache is unsupported ATM +fail lvconvert --yes --cachepool $vg/$lv + +# Thin-pool cannot use cached metaddata LV (meta should be on FAST device) +fail lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv + +# Thin-pool CAN use cached data LV +lvconvert --yes --thinpool $vg/$lv + +lvremove -f $vg + +# Check we can active snapshot of cached external origin (BZ: 1967744) +lvcreate -T -L10M $vg/pool "$dev1" + +lvcreate -L10M -n origin $vg "$dev1" +lvcreate -H -L4M -n CPOOL $vg/origin "$dev2" + +# Use cached origin as external origin +lvconvert -y -T --thinpool $vg/pool --originname extorig origin + +# Check we can easily create snapshot of such LV +lvcreate -y -kn -n snap -s $vg/origin + +# Deactivate everything and do a component activation of _cmeta volume +lvchange -an $vg +lvchange -ay -y $vg/CPOOL_cpool_cmeta + +# Now this must fail since component volume is active +not lvcreate -y -kn -n snap2 -s $vg/origin |& tee err +grep "cmeta is active" err + +vgremove -f $vg diff --git a/test/shell/lvconvert-cache-vdo.sh b/test/shell/lvconvert-cache-vdo.sh new file mode 100644 index 0000000..39caf5e --- /dev/null +++ b/test/shell/lvconvert-cache-vdo.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise usage of stacked cache volume used in thin pool volumes + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +percent_() { + get lv_field $vg/vpool data_percent | cut -d. -f1 +} + +aux have_vdo 6 2 0 || skip +aux have_cache 1 3 0 || skip + +aux prepare_vg 1 9000 + +lvcreate -L10 -n cpool $vg +lvcreate -L4G -n vpool $vg + +# Cache volume +lvconvert --yes --cache --cachepool cpool $vg/vpool + +# Stack cached LV as VDODataLV for VDOPoolLV +lvconvert --yes --type vdo-pool -V50M --name $lv1 $vg/vpool + +aux mkdev_md5sum $vg $lv1 + +lvconvert --splitcache $vg/vpool + +check dev_md5sum $vg $lv1 +lvchange -an $vg +lvchange -ay $vg +check dev_md5sum $vg $lv1 + +lvconvert --yes --cache --cachepool cpool $vg/vpool + +VDODATA="$(percent_)" +# Check resize of cached VDO pool +lvextend -L+1G $vg/vpool + +lvs -a $vg +# Check after resize usage is reduced +test "$(percent_)" -lt $VDODATA +lvconvert --splitcache $vg/vpool + +lvconvert --yes --cache --cachepool cpool $vg/$lv1 +check dev_md5sum $vg $lv1 +lvchange -an $vg +lvchange -ay $vg +check dev_md5sum $vg $lv1 + +lvs -a $vg +not lvconvert --splitcache $vg/vpool +lvconvert --splitcache $vg/$lv1 +lvs -a $vg + +# Also check, removal of cached VDO LV works +lvconvert --yes --cache --cachepool cpool $vg/$lv1 +vgremove -f $vg diff --git a/test/shell/lvconvert-cache.sh b/test/shell/lvconvert-cache.sh new file mode 100644 index 0000000..cfc8281 --- /dev/null +++ b/test/shell/lvconvert-cache.sh @@ -0,0 +1,202 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise conversion of cache and cache pool + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +aux prepare_vg 5 80 + +lvcreate --type cache-pool -an -v -L 2 -n cpool $vg +lvcreate -H -L 4 -n corigin --cachepool $vg/cpool + +fail lvcreate -s -L2 $vg/cpool +fail lvcreate -s -L2 $vg/cpool_cdata +fail lvcreate -s -L2 $vg/cpool_cmeta + +########################### +# Check regular converion # +########################### +# lvcreate origin, lvcreate cache-pool, and lvconvert to cache +lvcreate -an -Zn -L 2 -n $lv1 $vg +lvcreate -L 8 -n $lv2 $vg +lvcreate -an -Zn -L 8 -n $lv3 $vg +lvcreate -an -Zn -L 8 -n $lv4 $vg +lvcreate -an -Zn -L 16 -n $lv5 $vg + +# check validation of cachemode arg works +invalid lvconvert --yes --type cache-pool --cachemode writethroughX --cachepool $vg/$lv1 + +# by default no cache settings are attached to converted cache-pool +lvconvert --yes --type cache-pool --chunksize 256 $vg/$lv1 +check inactive $vg ${lv1}_cdata +check lv_field $vg/$lv1 cache_mode "" +check lv_field $vg/$lv1 cache_policy "" +check lv_field $vg/$lv1 cache_settings "" +check lv_field $vg/$lv1 chunk_size "256.00k" + +# but allow to set them when specified explicitely on command line +lvconvert --yes --type cache-pool --cachemode writeback --cachepolicy mq \ + --cachesettings sequential_threshold=1234 --cachesettings random_threshold=56 \ + --cachepool $vg/$lv2 +check inactive $vg ${lv2}_cdata +check lv_field $vg/$lv2 cache_mode "writeback" +check lv_field $vg/$lv2 cache_policy "mq" +check lv_field $vg/$lv2 cache_settings "random_threshold=56,sequential_threshold=1234" + +# Check swap of cache pool metadata +lvconvert --yes --type cache-pool --poolmetadata $lv4 $vg/$lv3 +UUID=$(get lv_field $vg/$lv5 uuid) +lvconvert --yes --cachepool $vg/$lv3 --poolmetadata $lv5 +check lv_field $vg/${lv3}_cmeta uuid "$UUID" + +# Check swap of cache pool metadata with --swapmetadata +# (should swap back to lv5) +lvconvert --yes --swapmetadata $vg/$lv3 --poolmetadata $lv5 +check lv_field $vg/$lv5 uuid "$UUID" + +#fail lvconvert --cachepool $vg/$lv1 --poolmetadata $vg/$lv2 +#lvconvert --yes --type cache-pool --poolmetadata $vg/$lv2 $vg/$lv1 +#lvconvert --yes --poolmetadata $vg/$lv2 --cachepool $vg/$lv1 + +lvremove -ff $vg + +lvcreate -L 2 -n $lv1 $vg +lvcreate --type cache-pool -l 1 -n ${lv1}_cachepool $vg +lvconvert --cache --cachepool $vg/${lv1}_cachepool --cachemode writeback -Zy $vg/$lv1 +check lv_field $vg/$lv1 cache_mode "writeback" +dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel + +#lvconvert --cachepool $vg/${lv1}_cachepool $vg/$lv1 +#lvconvert --cachepool $vg/${lv1}_cachepool --poolmetadatasize 20 "$dev3" + + +fail lvconvert --type cache --cachepool $vg/${lv1}_cachepool -Zy $vg/$lv1 + +# Test --splitcache leaves both cache origin and cache pool +lvconvert --splitcache $vg/$lv1 +check lv_exists $vg $lv1 ${lv1}_cachepool +lvremove -f $vg + + +lvcreate -L 2 -n $lv1 $vg +lvcreate --type cache-pool -l 1 -n ${lv1}_cachepool "$DM_DEV_DIR/$vg" +lvconvert --cache --cachepool "$DM_DEV_DIR/$vg/${lv1}_cachepool" --cachemode writeback -Zy "$DM_DEV_DIR/$vg/$lv1" +lvremove -f $vg + + +lvcreate -n corigin -l 10 $vg +lvcreate -n pool -l 10 $vg +lvs -a -o +devices +fail lvconvert --type cache --cachepool $vg/pool $vg/corigin +lvconvert --yes --cache --cachepool $vg/pool $vg/corigin +lvconvert --splitcache $vg/corigin +lvremove -ff $vg + +# Check we also support conversion that uses 'cleaner' cache policy +lvcreate -n corigin -l 10 $vg +lvcreate -n pool -l 10 $vg +lvconvert --yes --cache --cachepool $vg/pool $vg/corigin --cachepolicy cleaner +lvremove -ff $vg + +####################### +# Invalid conversions # +####################### +lvcreate -an -Zn -L 2 -n $lv1 $vg +lvcreate -an -Zn -L 8 -n $lv2 $vg +lvcreate -an -Zn -L 8 -n $lv3 $vg +lvcreate -an -Zn -L 8 -n $lv4 $vg + +# Undefined cachepool +invalid lvconvert --type cache --poolmetadata $vg/$lv2 $vg/$lv1 + +# Cannot mix with thins +invalid lvconvert --type cache --poolmetadata $vg/$lv2 --thinpool $vg/$lv1 +invalid lvconvert --type cache --thin --poolmetadata $vg/$lv2 $vg/$lv1 + +# Undefined cached volume +invalid lvconvert --type cache --cachepool $vg/$lv1 +invalid lvconvert --cache --cachepool $vg/$lv1 + +# FIXME: temporarily we return error code 5 +INVALID=not +# Single vg is required +$INVALID lvconvert --type cache --cachepool $vg/$lv1 --poolmetadata $vg1/$lv2 $vg/$lv3 +$INVALID lvconvert --type cache --cachepool "$DM_DEV_DIR/$vg/$lv1" --poolmetadata "$DM_DEV_DIR/$vg1/$lv2" $vg/$lv3 +$INVALID lvconvert --type cache --cachepool $vg/$lv1 --poolmetadata $lv2 $vg1/$lv3 +$INVALID lvconvert --type cache --cachepool $vg1/$lv1 --poolmetadata $vg2/$lv2 $vg/$lv3 +$INVALID lvconvert --type cache --cachepool $vg1/$lv1 --poolmetadata $vg2/$lv2 "$DM_DEV_DIR/$vg/$lv3" +$INVALID lvconvert --type cache-pool --poolmetadata $vg2/$lv2 $vg1/$lv1 + +$INVALID lvconvert --cachepool $vg1/$lv1 --poolmetadata $vg2/$lv2 + +# Invalid syntax, vg is unknown +$INVALID lvconvert --yes --cachepool $lv3 --poolmetadata $lv4 + +# Invalid chunk size is <32KiB >1GiB +$INVALID lvconvert --type cache-pool --chunksize 16 --poolmetadata $lv2 $vg/$lv1 +$INVALID lvconvert --type cache-pool --chunksize 2G --poolmetadata $lv2 $vg/$lv1 + +# Invalid chunk size is bigger then data size, needs to open VG +fail lvconvert --yes --type cache-pool --chunksize 16M --poolmetadata $lv2 $vg/$lv1 + +lvremove -f $vg + +######################## +# Repair of cache pool # +######################## +lvcreate --type cache-pool -an -v -L 2 -n cpool $vg +lvcreate -H -L 4 -n corigin --cachepool $vg/cpool + +# unsupported yet +fail lvconvert --repair $vg/cpool 2>&1 | tee out +#grep "Cannot convert internal LV" out + +lvremove -f $vg + +######################### +# Some testing variants # +######################### + +for i in error zero +do + lvcreate --type "$i" -L50G -n $lv1 $vg + lvcreate --type "$i" -L10G -n cpool $vg + lvconvert -y --cachepool $vg/cpool + lvconvert -y -H --cachepool $vg/cpool $vg/$lv1 + lvremove -f $vg +done + +########################## +# Prohibited conversions # +########################## +lvcreate --type cache-pool -L10 $vg/$lv1 +lvcreate --cache -L20 $vg/$lv1 +lvcreate -L10 -n $lv2 $vg + +fail lvconvert --yes --type cache $vg/$lv2 --cachepool $vg/$lv1 +fail lvconvert --yes --type cache $vg/$lv1 --cachepool $vg/$lv2 +fail lvconvert --yes --type cache-pool $vg/$lv1 +fail lvconvert --yes --type mirror -m1 $vg/$lv1 +not aux have_raid 1 0 0 || fail lvconvert --yes --type raid1 -m1 $vg/$lv1 +fail lvconvert --yes --type snapshot $vg/$lv1 $vg/$lv2 +fail lvconvert --yes --type snapshot $vg/$lv2 $vg/$lv1 +not aux have_thin 1 0 0 || fail lvconvert --yes -T --thinpool $vg/$lv2 $vg/$lv1 + +lvremove -f $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-m-raid1-degraded.sh b/test/shell/lvconvert-m-raid1-degraded.sh new file mode 100644 index 0000000..05c3e89 --- /dev/null +++ b/test/shell/lvconvert-m-raid1-degraded.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 0 || skip + +aux lvmconf 'activation/raid_fault_policy = "warn"' + +aux prepare_vg 3 32 +get_devs + +# Create 2-legged RAID1 and wait for it to complete initial resync +lvcreate --type raid1 -m 1 -l 4 -n $lv $vg "$dev1" "$dev2" +aux wait_for_sync $vg $lv + +# Disable first PV thus erroring first leg +aux disable_dev "$dev1" + +# Reduce VG by missing PV +vgreduce --force --removemissing $vg +check raid_leg_status $vg $lv "DA" + +# Conversion to 2 legs must fail on degraded 2-legged raid1 LV +not lvconvert -y -m1 $vg/$lv +check raid_leg_status $vg $lv "DA" + +# Repair has to succeed +lvconvert -y --repair $vg/$lv +aux wait_for_sync $vg $lv +check raid_leg_status $vg $lv "AA" + +lvremove -ff $vg/$lv + +vgremove -ff $vg diff --git a/test/shell/lvconvert-mirror-basic-0.sh b/test/shell/lvconvert-mirror-basic-0.sh index dc71bb8..02f32a9 100644 --- a/test/shell/lvconvert-mirror-basic-0.sh +++ b/test/shell/lvconvert-mirror-basic-0.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,10 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . ./shell/lvconvert-mirror-basic.sh + test_many 0 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-mirror-basic-1.sh b/test/shell/lvconvert-mirror-basic-1.sh index b7ebf9e..76d1315 100644 --- a/test/shell/lvconvert-mirror-basic-1.sh +++ b/test/shell/lvconvert-mirror-basic-1.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,10 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . ./shell/lvconvert-mirror-basic.sh + test_many 1 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-mirror-basic-2.sh b/test/shell/lvconvert-mirror-basic-2.sh index d47f77d..eb6de87 100644 --- a/test/shell/lvconvert-mirror-basic-2.sh +++ b/test/shell/lvconvert-mirror-basic-2.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,10 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . ./shell/lvconvert-mirror-basic.sh + test_many 2 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-mirror-basic-3.sh b/test/shell/lvconvert-mirror-basic-3.sh index 732fb2d..fa4b3cd 100644 --- a/test/shell/lvconvert-mirror-basic-3.sh +++ b/test/shell/lvconvert-mirror-basic-3.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,10 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . ./shell/lvconvert-mirror-basic.sh + test_many 3 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-mirror-basic.sh b/test/shell/lvconvert-mirror-basic.sh index a0f50f6..96d30d2 100644 --- a/test/shell/lvconvert-mirror-basic.sh +++ b/test/shell/lvconvert-mirror-basic.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,9 +8,13 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + +. lib/inittest -. lib/test +aux lvmconf "global/support_mirrored_mirror_log=1" log_name_to_count() { case "$1" in @@ -38,28 +43,27 @@ log_name_to_count() { test_lvconvert() { local start_count=$1 - local start_count_p1=$(($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_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 active="-aey" local i - test "$5" = "active" && active=false + test "$5" = "active" && active="-an" #test $finish_count -gt $start_count && up=true # Do we have enough devices for the mirror images? - test $start_count_p1 -gt ${#dev_array[@]} && \ + test $start_count_p1 -gt ${#DEVICES[@]} && \ die "Action requires too many devices" # Do we have enough devices for the mirror images? - test $finish_count_p1 -gt ${#dev_array[@]} && \ + test $finish_count_p1 -gt ${#DEVICES[@]} && \ die "Action requires too many devices" start_log_count=$(log_name_to_count $start_log_type) @@ -72,30 +76,37 @@ test_lvconvert() { 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 + if [ $(( start_count_p1 + start_log_count )) -gt ${#DEVICES[@]} ]; then alloc="--alloc anywhere" fi - lvcreate -l2 -m $start_count --mirrorlog $start_log_type \ + lvcreate "$active" -Zn -l2 --type mirror -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 + lvcreate "$active" -Zn -l2 -n $lv1 $vg fi lvs -a -o name,copy_percent,devices $vg - test $active || lvchange -an $vg/$lv1 # Are there extra devices for the log or do we overlap - if [ $(($finish_count_p1 + $finish_log_count)) -gt ${#dev_array[@]} ]; then + if [ $(( finish_count_p1 + finish_log_count )) -gt ${#DEVICES[@]} ]; then alloc="--alloc anywhere" fi - lvconvert -m $finish_count --mirrorlog $finish_log_type \ + # --mirrorlog is invalid with -m0 + if [ "$finish_count" -eq 0 ]; then + mirrorlog="" + finish_log_type="" + else + mirrorlog="--mirrorlog" + fi + + lvconvert --type mirror -m $finish_count $mirrorlog $finish_log_type \ $vg/$lv1 $alloc - test $active || lvchange -ay $vg/$lv1 + test "$active" = "-an" || lvchange "$active" $vg/$lv1 check mirror_no_temporaries $vg $lv1 if [ "$finish_count_p1" -eq 1 ]; then @@ -110,14 +121,18 @@ test_lvconvert() { fi } -aux prepare_pvs 5 5 -vgcreate -c n -s 128k $vg $(cat DEVICES) +aux prepare_vg 5 5 +get_devs + +MIRRORED="mirrored" +# FIXME: Cluster is not supporting exlusive activation of mirrored log +test -e LOCAL_CLVMD && MIRRORED= 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 + 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" diff --git a/test/shell/lvconvert-mirror-split.sh b/test/shell/lvconvert-mirror-split.sh new file mode 100644 index 0000000..00291ec --- /dev/null +++ b/test/shell/lvconvert-mirror-split.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check --splitmirrors for mirror segtype + +. lib/inittest + +aux prepare_vg 3 + +########################################### +# Mirror split tests +########################################### +# 3-way to 2-way/linear +lvcreate -aey --type mirror -m 2 -l 2 -n $lv1 $vg +aux wait_for_sync $vg $lv1 +lvconvert --splitmirrors 1 -n $lv2 -vvvv $vg/$lv1 + +check lv_exists $vg $lv1 +check linear $vg $lv2 +check active $vg $lv2 +# FIXME: ensure no residual devices + +vgremove -ff $vg diff --git a/test/shell/lvconvert-mirror-updown.sh b/test/shell/lvconvert-mirror-updown.sh new file mode 100644 index 0000000..4aea496 --- /dev/null +++ b/test/shell/lvconvert-mirror-updown.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Demonstrate problem when upconverting and cutting leg in clvmd + + + +. lib/inittest + +aux prepare_pvs 3 100 +get_devs + +vgcreate $SHARED -s 64k "$vg" "${DEVICES[@]}" + +# Use zero devices for big mirror legs +aux zero_dev "$dev2" "$(get first_extent_sector "$dev2"):" +aux zero_dev "$dev3" "$(get first_extent_sector "$dev3"):" + +lvcreate -aey -L90 --type mirror --corelog --regionsize 16k -m1 -n $lv1 $vg "$dev1" "$dev2" + +lvconvert -m+1 -b $vg/$lv1 "$dev3" + + +# We want here ongoing conversion + +lvs -a -o+seg_pe_ranges $vg + +# Now it should be able to drop 2nd. leg +lvconvert -m-1 $vg/$lv1 "$dev2" + +lvs -a $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-mirror.sh b/test/shell/lvconvert-mirror.sh index c09b8fd..17ed033 100644 --- a/test/shell/lvconvert-mirror.sh +++ b/test/shell/lvconvert-mirror.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2010 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2010-2018 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 @@ -7,116 +8,78 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -. lib/test -aux prepare_pvs 5 10 -# FIXME - test fails with extent size < 512k -vgcreate -c n -s 512k $vg $(cat DEVICES) -# convert from linear to 2-way mirror -lvcreate -l2 -n $lv1 $vg "$dev1" -lvconvert -i1 -m+1 $vg/$lv1 "$dev2" "$dev3:0-1" -check mirror $vg $lv1 "$dev3" +. lib/inittest + +aux lvmconf "global/support_mirrored_mirror_log=1" + +aux prepare_pvs 5 +get_devs + +# proper DEVRANGE needs to be set according to extent size +DEVRANGE="0-32" +vgcreate $SHARED -s 32k "$vg" "${DEVICES[@]}" + +# convert from linear to 2-way mirror ("mirror" default type) +lvcreate -aey -l2 -n $lv1 $vg "$dev1" +lvconvert -i1 -m+1 -R32k $vg/$lv1 "$dev2" "$dev3:0-1" \ + --config 'global { mirror_segtype_default = "mirror" }' +lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*m' +lvremove -ff $vg + +# convert from linear to 2-way mirror (override "raid1" default type) +lvcreate -aey -l2 -n $lv1 $vg "$dev1" +lvconvert -i1 --type mirror -m+1 $vg/$lv1 "$dev2" "$dev3:0-1" \ + --config 'global { mirror_segtype_default = "raid1" }' +lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*m' lvremove -ff $vg # convert from linear to 2-way mirror - with tags and volume_list (bz683270) -lvcreate -l2 -n $lv1 $vg --addtag hello -lvconvert -i1 -m+1 $vg/$lv1 \ +lvcreate -aey -l2 -n $lv1 $vg --addtag hello +lvconvert -i1 --type mirror -m+1 $vg/$lv1 \ --config 'activation { volume_list = [ "@hello" ] }' lvremove -ff $vg # convert from 2-way to 3-way mirror - with tags and volume_list (bz683270) -lvcreate -l2 -m1 -n $lv1 $vg --addtag hello +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg --addtag hello lvconvert -i1 -m+1 $vg/$lv1 \ --config 'activation { volume_list = [ "@hello" ] }' lvremove -ff $vg # convert from 2-way mirror to linear -lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0-1" +lvcreate -aey -l2 --type mirror -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" +lvcreate -aey -l2 --type mirror -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 -lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0-1" +lvcreate -aey -l2 --type mirror -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 -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 -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 -lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg "$dev1" "$dev2" -lvchange -an $vg/$lv1 +lvcreate -aey -l2 --type mirror -m1 --mirrorlog core -n $lv1 $vg "$dev1" "$dev2" 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 -lvcreate -l2 -n $lv1 $vg "$dev1" +lvcreate -aey -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... - -aux wait_for_sync $vg $lv1 -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" -lvremove -ff $vg - -# No parallel lvconverts on a single LV please - -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 -lvremove -ff $vg - # add 1 mirror to core log mirror, but # implicitly keep log as 'core' -lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg "$dev1" "$dev2" +lvcreate -aey -l2 --type mirror -m1 --mirrorlog core -n $lv1 $vg "$dev1" "$dev2" lvconvert -m +1 -i1 $vg/$lv1 check mirror $vg $lv1 core @@ -125,7 +88,7 @@ check mirror_legs $vg $lv1 3 lvremove -ff $vg # remove 1 mirror from corelog'ed mirror; should retain 'core' log type -lvcreate -l2 -m2 --corelog -n $lv1 $vg +lvcreate -aey -l2 --type mirror -m2 --corelog -n $lv1 $vg lvconvert -m -1 -i1 $vg/$lv1 check mirror $vg $lv1 core @@ -135,7 +98,7 @@ lvremove -ff $vg # add 1 mirror then add 1 more mirror during conversion # FIXME this has been explicitly forbidden? -#lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3":0 +#lvcreate -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3":0 #lvconvert -m+1 -b $vg/$lv1 "$dev4" #lvconvert -m+1 $vg/$lv1 "$dev5" # @@ -144,17 +107,11 @@ lvremove -ff $vg #check mirror_legs $vg $lv1 4 #lvremove -ff $vg -# Linear to mirror with mirrored log using --alloc anywhere -lvcreate -l2 -n $lv1 $vg "$dev1" -lvconvert -m +1 --mirrorlog mirrored --alloc anywhere $vg/$lv1 "$dev1" "$dev2" -should check mirror $vg $lv1 -lvremove -ff $vg - # convert inactive mirror and start polling -lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0" +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE" lvchange -an $vg/$lv1 lvconvert -m+1 $vg/$lv1 "$dev4" -lvchange -ay $vg/$lv1 +lvchange -aey $vg/$lv1 lvconvert $vg/$lv1 # wait check mirror $vg $lv1 "$dev3" check mirror_no_temporaries $vg $lv1 @@ -164,8 +121,8 @@ lvremove -ff $vg # removal during conversion # "remove newly added mirror" -lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0" -lvconvert -m+1 -b $vg/$lv1 "$dev4" +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE" +LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4" lvconvert -m-1 $vg/$lv1 "$dev4" lvconvert $vg/$lv1 # wait @@ -175,8 +132,8 @@ check mirror_legs $vg $lv1 2 lvremove -ff $vg # "remove one of newly added mirrors" -lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0" -lvconvert -m+2 -b $vg/$lv1 "$dev4" "$dev5" +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE" +LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+2 -b $vg/$lv1 "$dev4" "$dev5" lvconvert -m-1 $vg/$lv1 "$dev4" lvconvert $vg/$lv1 # wait @@ -186,8 +143,12 @@ check mirror_legs $vg $lv1 3 lvremove -ff $vg # "remove from original mirror (the original is still mirror)" -lvcreate -l2 -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev5" "$dev3:0" -lvconvert -m+1 -b $vg/$lv1 "$dev4" +lvcreate -aey -l2 --type mirror -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev5" "$dev3:$DEVRANGE" +LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4" +# FIXME: Extra wait here for mirror upconvert synchronization +# otherwise we may fail her on parallel upconvert and downconvert +# lvconvert-mirror-updown.sh tests this errornous case separately +lvconvert $vg/$lv1 lvconvert -m-1 $vg/$lv1 "$dev2" lvconvert $vg/$lv1 @@ -197,8 +158,12 @@ check mirror_legs $vg $lv1 3 lvremove -ff $vg # "remove from original mirror (the original becomes linear)" -lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0" -lvconvert -m+1 -b $vg/$lv1 "$dev4" +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE" +LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4" +# FIXME: Extra wait here for mirror upconvert synchronization +# otherwise we may fail her on parallel upconvert and downconvert +# lvconvert-mirror-updown.sh tests this errornous case separately +lvconvert $vg/$lv1 lvconvert -m-1 $vg/$lv1 "$dev2" lvconvert $vg/$lv1 @@ -207,34 +172,44 @@ check mirror_no_temporaries $vg $lv1 check mirror_legs $vg $lv1 2 lvremove -ff $vg -# --------------------------------------------------------------------- +# Check the same with new --startpool lvconvert command option +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE" +LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4" +# FIXME: Extra wait here for mirror upconvert synchronization +# otherwise we may fail her on parallel upconvert and downconvert +# lvconvert-mirror-updown.sh tests this errornous case separately +lvconvert $vg/$lv1 +lvconvert -m-1 $vg/$lv1 "$dev2" +lvconvert $vg/$lv1 -# "rhbz440405: lvconvert -m0 incorrectly fails if all PEs allocated" -lvcreate -l`pvs --noheadings -ope_count "$dev1"` -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0" -aux wait_for_sync $vg $lv1 -lvconvert -m0 $vg/$lv1 "$dev1" -check linear $vg $lv1 +check mirror $vg $lv1 "$dev3" +check mirror_no_temporaries $vg $lv1 +check mirror_legs $vg $lv1 2 lvremove -ff $vg -# "rhbz264241: lvm mirror doesn't lose it's "M" --nosync attribute after being down and the up converted" -lvcreate -l2 -m1 -n$lv1 --nosync $vg +# --------------------------------------------------------------------- + +# "rhbz264241: lvm mirror doesn't lose it's "M" --nosync attribute +# after being down and the up converted" +lvcreate -aey -l2 --type mirror -m1 -n $lv1 --nosync $vg lvconvert -m0 $vg/$lv1 -lvconvert -m1 $vg/$lv1 -lvs --noheadings -o attr $vg/$lv1 | grep '^ *m' +lvconvert --type mirror -m1 $vg/$lv1 +lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*m' lvremove -ff $vg # lvconvert from linear (on multiple PVs) to mirror -lvcreate -l 8 -n $lv1 $vg "$dev1:0-3" "$dev2:0-3" -lvconvert -m1 $vg/$lv1 +lvcreate -aey -l 8 -n $lv1 $vg "$dev1:0-3" "$dev2:0-3" +lvconvert --type mirror -m1 $vg/$lv1 -should check mirror $vg $lv1 +# FIXME: lvm should be able to make legs redundant +#should check mirror $vg $lv1 check mirror_legs $vg $lv1 2 lvremove -ff $vg # BZ 463272: disk log mirror convert option is lost if downconvert option is also given -lvcreate -l1 -m2 --corelog -n $lv1 $vg "$dev1" "$dev2" "$dev3" +lvcreate -aey -l1 --type mirror -m2 --corelog -n $lv1 $vg "$dev1" "$dev2" "$dev3" aux wait_for_sync $vg $lv1 -lvconvert -m1 --mirrorlog disk $vg/$lv1 +lvconvert --type mirror -m1 --mirrorlog disk $vg/$lv1 check mirror $vg $lv1 not check mirror $vg $lv1 core lvremove -ff $vg @@ -243,10 +218,10 @@ lvremove -ff $vg # add mirror and disk log # "add 1 mirror and disk log" -lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg "$dev1" "$dev2" +lvcreate -aey -l2 --type mirror -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" +lvconvert -m+1 --mirrorlog disk -i1 $vg/$lv1 "$dev4" "$dev3:$DEVRANGE" check mirror $vg $lv1 "$dev3" check mirror_no_temporaries $vg $lv1 @@ -254,27 +229,143 @@ check mirror_legs $vg $lv1 3 lvremove -ff $vg # simple mirrored stripe -lvcreate -i2 -l10 -n $lv1 $vg -lvconvert -m1 -i1 $vg/$lv1 +lvcreate -aey -i2 -l10 -n $lv1 $vg +# FIXME: ATM reduce LV still must be bigger then region size! +# LVM should do a better job here +lvconvert --type mirror -m1 -i1 --regionsize 16k $vg/$lv1 lvreduce -f -l1 $vg/$lv1 lvextend -f -l10 $vg/$lv1 lvremove -ff $vg/$lv1 # extents must be divisible -lvcreate -l15 -n $lv1 $vg -not lvconvert -m1 --corelog --stripes 2 $vg/$lv1 +lvcreate -aey -l15 -n $lv1 $vg +not lvconvert --type mirror -m1 --corelog --stripes 2 $vg/$lv1 +lvremove -ff $vg + + +# Linear to mirror with mirrored log using --alloc anywhere +lvcreate -aey -l2 -n $lv1 $vg "$dev1" +if test -e LOCAL_CLVMD; then +# This is not supposed to work in cluster +not lvconvert --type mirror -m +1 --mirrorlog mirrored --alloc anywhere $vg/$lv1 "$dev1" "$dev2" +else +lvconvert --type mirror -m +1 --mirrorlog mirrored --alloc anywhere $vg/$lv1 "$dev1" "$dev2" +check mirror $vg $lv1 +fi lvremove -ff $vg + +if test -e LOCAL_CLVMD; then +: # FIXME - cases which needs to be fixed to work in cluster +else # Should not be able to add images to --nosync mirror # but should be able to after 'lvchange --resync' -lvcreate -m 1 -l1 -n $lv1 $vg --nosync +lvcreate -aey --type mirror -m 1 -l1 -n $lv1 $vg --nosync not lvconvert -m +1 $vg/$lv1 -lvchange --resync -y $vg/$lv1 +lvchange -aey --resync -y $vg/$lv1 lvconvert -m +1 $vg/$lv1 lvremove -ff $vg -lvcreate -m 1 --corelog -l1 -n $lv1 $vg --nosync +lvcreate -aey --type mirror -m 1 --corelog -l1 -n $lv1 $vg --nosync not lvconvert -m +1 $vg/$lv1 -lvchange --resync -y $vg/$lv1 +lvchange -aey --resync -y $vg/$lv1 lvconvert -m +1 $vg/$lv1 lvremove -ff $vg + +# FIXME: Cluster exclusive activation does not work here +# unsure why lib/metadata/mirror.c +# has this code: +# +# } else if (vg_is_clustered(vg)) { +# log_error("Unable to convert the log of an inactive " +# "cluster mirror, %s", lv->name); +# return 0; +# disabling this in the code passes this test + +# bz192865: lvconvert log of an inactive mirror lv +# convert from disklog to corelog, inactive +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0-1" +lvchange -an $vg/$lv1 +lvconvert -y -f --mirrorlog core $vg/$lv1 +check mirror $vg $lv1 core +lvremove -ff $vg + +# convert from corelog to disklog, inactive +lvcreate -aey -l2 --type mirror -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 + +# bz1272175: check lvconvert reports progress while waiting for mirror +# to get synced +lvcreate -l2 -n $lv1 $vg +lvconvert --type mirror -i1 -m1 $vg/$lv1 | tee out +grep -e "$vg/$lv1: Converted:" out || die "Missing sync info in foreground mode" +lvremove -ff $vg +fi + + +######################################################################### +# Start w/ 3-way mirror +# Test that the correct devices remain in the mirror +# Make $dev2 & $dev4 zero backend device so large mirrors can be user +# without consuming any real space. Clearly such mirrors can't be read back +# but tests here are validating possibilies of those conversions +# +# Test pulling primary image before mirror in-sync (should fail) +# Test pulling primary image after mirror in-sync (should work) +# +aux zero_dev "$dev2" "$(get first_extent_sector "$dev2"):" +aux zero_dev "$dev4" "$(get first_extent_sector "$dev4"):" + +SHOULD= +aux throttle_dm_mirror || SHOULD=should + +# Use large enough mirror that takes time to sychronize with small regionsize +lvcreate -aey -L30 -Zn -Wn --type mirror --regionsize 16k -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev4" "$dev3:$DEVRANGE" +$SHOULD not lvconvert -m-1 $vg/$lv1 "$dev1" 2>&1 | tee out +aux restore_dm_mirror +grep "not in-sync" out + +lvconvert $vg/$lv1 # wait + +lvconvert -m-1 $vg/$lv1 "$dev1" +check mirror_images_on $vg $lv1 "$dev2" "$dev4" +lvconvert -m-1 $vg/$lv1 "$dev2" +check linear $vg $lv1 +check lv_on $vg $lv1 "$dev4" +lvremove -ff $vg + + +aux throttle_dm_mirror || : +# No parallel lvconverts on a single LV please +# Use big enough mirror size and small regionsize to run on all test machines succesfully +lvcreate -aey -Zn -Wn -L30 --type mirror --regionsize 16k -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:0-8" +check mirror $vg $lv1 +check mirror_legs $vg $lv1 2 + +LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4" +# ATM upconversion should be running + +# Next convert should fail b/c we can't have 2 at once +$SHOULD not lvconvert -m+1 $vg/$lv1 "$dev5" 2>&1 | tee out +aux restore_dm_mirror +grep "is already being converted" out + +lvconvert $vg/$lv1 # wait +check mirror $vg $lv1 "$dev3" +check mirror_no_temporaries $vg $lv1 +check mirror_legs $vg $lv1 3 +lvremove -ff $vg + + +# "rhbz440405: lvconvert -m0 incorrectly fails if all PEs allocated" +lvcreate -aey -l "$(get pv_field "$dev1" pe_count)" --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE" +lvs -a -o+seg_pe_ranges $vg +aux wait_for_sync $vg $lv1 +lvconvert -m0 $vg/$lv1 "$dev1" +check linear $vg $lv1 +lvremove -ff $vg + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-allocation.sh b/test/shell/lvconvert-raid-allocation.sh new file mode 100644 index 0000000..5420d58 --- /dev/null +++ b/test/shell/lvconvert-raid-allocation.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +# Copyright (C) 2011-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 0 || skip + +aux prepare_pvs 5 +get_devs + +vgcreate $SHARED -s 256k "$vg" "${DEVICES[@]}" + +# Start with linear on 2 PV and ensure that converting to +# RAID is not allowed to reuse PVs for different images. (Bug 1113180) +lvcreate -aey -l 4 -n $lv1 $vg "$dev1:0-1" "$dev2:0-1" +not lvconvert -y --type raid1 -m 1 $vg/$lv1 "$dev1" "$dev2" +not lvconvert -y --type raid1 -m 1 $vg/$lv1 "$dev1" "$dev3:0-2" +lvconvert -y --type raid1 -m 1 $vg/$lv1 "$dev3" +not lvconvert -m 0 $vg/$lv1 +lvconvert -y -m 0 $vg/$lv1 +# RAID conversions are not honoring allocation policy! +# lvconvert -y --type raid1 -m 1 --alloc anywhere $vg/$lv1 "$dev1" "$dev2" +lvremove -ff $vg + + +# Setup 2-way RAID1 LV, spread across 4 devices. +# For each image: +# - metadata LV + 1 image extent (2 total extents) on one PV +# - 2 image extents on the other PV +# Then attempt allocation of another image from 2 extents on +# a 5th PV and the remainder of the rest of already used PVs. +# +# This should fail because there is insufficient space on the +# non-parallel PV (i.e. there is not enough space for the image +# if it doesn't share a PV with another image). +lvcreate --type raid1 -m 1 -l 3 -n $lv1 $vg \ + "$dev1:0-1" "$dev2:0-1" "$dev3:0-1" "$dev4:0-1" +aux wait_for_sync $vg $lv1 +# Should not be enough non-overlapping space. +not lvconvert -m +1 $vg/$lv1 \ + "$dev5:0-1" "$dev1" "$dev2" "$dev3" "$dev4" +lvconvert -y -m +1 $vg/$lv1 "$dev5" +aux wait_for_sync $vg $lv1 +# Cannot pass without --yes +not lvconvert -m 0 $vg/$lv1 +lvconvert -y -m 0 $vg/$lv1 +# Should work due to '--alloc anywhere' +# RAID conversion not honoring allocation policy! +#lvconvert -y -m +1 --alloc anywhere $vg/$lv1 \ +# "$dev5:0-1" "$dev1" "$dev2" "$dev3" "$dev4" +lvremove -ff $vg + + +# Setup 2-way RAID1 LV, spread across 4 devices +# - metadata LV + 1 image extent (2 total extents) on one PV +# - 2 image extents on the other PV +# Kill one PV. There should be enough space on the remaining +# PV for that image to reallocate the entire image there and +# still maintain redundancy. +lvcreate --type raid1 -m 1 -l 3 -n $lv1 $vg \ + "$dev1:0-1" "$dev2:0-1" "$dev3:0-1" "$dev4:0-1" +aux wait_for_sync $vg $lv1 +aux disable_dev "$dev1" +lvconvert -y --repair $vg/$lv1 "$dev2" "$dev3" "$dev4" +#FIXME: ensure non-overlapping images (they should not share PVs) +aux enable_dev "$dev1" +lvremove -ff $vg + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-regionsize.sh b/test/shell/lvconvert-raid-regionsize.sh new file mode 100644 index 0000000..23d54d0 --- /dev/null +++ b/test/shell/lvconvert-raid-regionsize.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_raid 1 9 0 || skip + +aux prepare_vg 6 + +function _test_regionsize +{ + local type=$1 + local regionsize=$2 + local regionsize_str=$3 + local vg=$4 + local lv=$5 + + lvconvert --type "$type" --yes -R "$regionsize" "$vg/$lv" + check lv_field $vg/$lv regionsize "$regionsize_str" + + not lvconvert --regionsize "$regionsize" "$vg/$lv" 2>err + grep "is already" err + + fsck -fn "$DM_DEV_DIR/$vg/$lv" +} + +function _test_regionsizes +{ + # FIXME: have to provide raid type or region size ain't set until cli validation merged + local type=$1 + + # Test RAID regionsize changes + _test_regionsize "$type" 128K "128.00k" $vg $lv1 + _test_regionsize "$type" 256K "256.00k" $vg $lv1 + not _test_regionsize "$type" 1K "1.00k" $vg $lv1 + _test_regionsize "$type" 1m "1.00m" $vg $lv1 + not _test_regionsize "$type" 1G "1.00g" $vg $lv1 + not _test_regionsize "$type" 16K "16.00k" $vg $lv1 +} + +# Create 3-way raid1 +lvcreate --yes -aey --type raid1 -m 2 -R64K -L8M -n $lv1 $vg +check lv_field $vg/$lv1 segtype "raid1" +check lv_field $vg/$lv1 stripes 3 +check lv_field $vg/$lv1 regionsize "64.00k" +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +_test_regionsizes raid1 + +# Clean up +lvremove --yes $vg + +# Needs reshaping kernel for raid6 conversion +if aux have_raid 1 14 0; then +# Create 5-way raid6 +lvcreate --yes -aey --type raid6 -i 3 --stripesize 128K -R 256K -L8M -n $lv1 $vg +check lv_field $vg/$lv1 segtype "raid6" +check lv_field $vg/$lv1 stripes 5 +check lv_field $vg/$lv1 stripesize "128.00k" +check lv_field $vg/$lv1 regionsize "256.00k" +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +_test_regionsizes raid6 + +# Clean up +lvremove --yes $vg +else + echo "Skipping RAID6 tests" +fi + +if aux have_raid 1 12 0; then +# Create 6-way raid01 +lvcreate --yes -aey --type raid10 -i 3 -m 1 --stripesize 128K -R 256K -L8M -n $lv1 $vg +check lv_field $vg/$lv1 segtype "raid10" +check lv_field $vg/$lv1 stripes 6 +check lv_field $vg/$lv1 stripesize "128.00k" +check lv_field $vg/$lv1 regionsize "256.00k" +mkfs.ext4 -t ext4 "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +_test_regionsizes raid10 +else + echo "Skipping RAID10 tests" +fi + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh b/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh new file mode 100644 index 0000000..731f006 --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Ensure expected default region size +aux lvmconf 'activation/raid_region_size = 512' + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +aux prepare_vg 5 + +# +# Test multi step linear -> striped conversion +# + +# Create linear LV +lvcreate -aey -L 16M -n $lv $vg +check lv_field $vg/$lv segtype "linear" +check lv_field $vg/$lv stripes 1 +check lv_field $vg/$lv data_stripes 1 +wipefs -a "$DM_DEV_DIR/$vg/$lv" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv" +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert linear -> raid1 (takeover) +lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_field $vg/$lv segtype "raid1" +check lv_field $vg/$lv stripes 2 +check lv_field $vg/$lv data_stripes 2 +check lv_field $vg/$lv regionsize "128.00k" +aux wait_for_sync $vg $lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert raid1 -> raid5_ls (takeover) +lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_field $vg/$lv segtype "raid5_ls" +check lv_field $vg/$lv stripes 2 +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripesize "64.00k" +check lv_field $vg/$lv regionsize "128.00k" + +# Convert raid5_ls adding stripes (reshape) +lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_first_seg_field $vg/$lv segtype "raid5_ls" +check lv_first_seg_field $vg/$lv stripes 4 +check lv_first_seg_field $vg/$lv data_stripes 3 +check lv_first_seg_field $vg/$lv stripesize "64.00k" +check lv_first_seg_field $vg/$lv regionsize "128.00k" +check lv_first_seg_field $vg/$lv reshape_len_le 8 +aux wait_for_sync $vg $lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert raid5_ls -> raid6_ls_6 (takeover) +lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_first_seg_field $vg/$lv segtype "raid6_ls_6" +check lv_first_seg_field $vg/$lv stripes 5 +check lv_first_seg_field $vg/$lv data_stripes 3 +check lv_first_seg_field $vg/$lv stripesize "64.00k" +check lv_first_seg_field $vg/$lv regionsize "128.00k" +check lv_first_seg_field $vg/$lv reshape_len_le 0 +aux wait_for_sync $vg $lv + +# Convert raid6_ls_6 -> raid6(_zr) (reshape) +lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_first_seg_field $vg/$lv segtype "raid6" +check lv_first_seg_field $vg/$lv stripes 5 +check lv_first_seg_field $vg/$lv data_stripes 3 +check lv_first_seg_field $vg/$lv stripesize "64.00k" +check lv_first_seg_field $vg/$lv regionsize "128.00k" +check lv_first_seg_field $vg/$lv reshape_len_le 10 +aux wait_for_sync $vg $lv + +# Remove reshape space +lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_first_seg_field $vg/$lv segtype "raid6" +check lv_first_seg_field $vg/$lv stripes 5 +check lv_first_seg_field $vg/$lv data_stripes 3 +check lv_first_seg_field $vg/$lv stripesize "64.00k" +check lv_first_seg_field $vg/$lv regionsize "128.00k" +check lv_first_seg_field $vg/$lv reshape_len_le 0 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-linear_to_striped-single-type.sh b/test/shell/lvconvert-raid-reshape-linear_to_striped-single-type.sh new file mode 100644 index 0000000..09f90dc --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-linear_to_striped-single-type.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux lvmconf 'activation/raid_region_size = 512' + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +aux prepare_vg 5 + +# +# Test multi step linear -> striped conversion +# + +# Create linear LV +lvcreate -aey -L 16M -n $lv $vg +check lv_field $vg/$lv segtype "linear" +check lv_field $vg/$lv stripes 1 +check lv_field $vg/$lv data_stripes 1 +wipefs -a "$DM_DEV_DIR/$vg/$lv" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv" +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert linear -> raid1 +lvconvert -y --type striped --stripes 4 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_field $vg/$lv segtype "raid1" +check lv_field $vg/$lv stripes 2 +check lv_field $vg/$lv data_stripes 2 +check lv_field $vg/$lv regionsize "128.00k" +aux wait_for_sync $vg $lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert raid1 -> raid5_n +lvconvert -y --type striped --stripes 4 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_field $vg/$lv segtype "raid5_n" +check lv_field $vg/$lv stripes 2 +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripesize "64.00k" +check lv_field $vg/$lv regionsize "128.00k" + +# Convert raid5_n adding stripes +lvconvert -y --type striped --stripes 4 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_first_seg_field $vg/$lv segtype "raid5_n" +check lv_first_seg_field $vg/$lv data_stripes 4 +check lv_first_seg_field $vg/$lv stripes 5 +check lv_first_seg_field $vg/$lv data_stripes 4 +check lv_first_seg_field $vg/$lv stripesize "64.00k" +check lv_first_seg_field $vg/$lv regionsize "128.00k" +check lv_first_seg_field $vg/$lv reshape_len_le 10 +aux wait_for_sync $vg $lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert raid5_n -> striped +lvconvert -y --type striped --stripes 4 --stripesize 64K --regionsize 128K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_first_seg_field $vg/$lv segtype "striped" +check lv_first_seg_field $vg/$lv stripes 4 +check lv_first_seg_field $vg/$lv data_stripes 4 +check lv_first_seg_field $vg/$lv stripesize "64.00k" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-linear_to_striped.sh b/test/shell/lvconvert-raid-reshape-linear_to_striped.sh new file mode 100644 index 0000000..7df25f1 --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-linear_to_striped.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux lvmconf 'activation/raid_region_size = 512' + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +aux prepare_vg 5 + +# +# Test single step linear -> striped conversion +# + +# Create linear LV +lvcreate -aey -L 16M -n $lv1 $vg +check lv_field $vg/$lv1 segtype "linear" +check lv_field $vg/$lv1 stripes 1 +check lv_field $vg/$lv1 data_stripes 1 +wipefs -a "$DM_DEV_DIR/$vg/$lv1" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv1" +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert linear -> raid1 +lvconvert -y -m 1 $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_field $vg/$lv1 segtype "raid1" +check lv_field $vg/$lv1 stripes 2 +check lv_field $vg/$lv1 data_stripes 2 +check lv_field $vg/$lv1 regionsize "512.00k" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert raid1 -> raid5_n +lvconvert -y --ty raid5_n --stripesize 64K --regionsize 512K $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_field $vg/$lv1 segtype "raid5_n" +check lv_field $vg/$lv1 stripes 2 +check lv_field $vg/$lv1 data_stripes 1 +check lv_field $vg/$lv1 stripesize "64.00k" +check lv_field $vg/$lv1 regionsize "512.00k" + +# Convert raid5_n adding stripes +lvconvert -y --stripes 4 $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_first_seg_field $vg/$lv1 segtype "raid5_n" +check lv_first_seg_field $vg/$lv1 data_stripes 4 +check lv_first_seg_field $vg/$lv1 stripes 5 +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" +check lv_first_seg_field $vg/$lv1 regionsize "512.00k" +check lv_first_seg_field $vg/$lv1 reshape_len_le 10 +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert raid5_n -> striped +lvconvert -y --type striped $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-load.sh b/test/shell/lvconvert-raid-reshape-load.sh new file mode 100644 index 0000000..5b381ac --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-load.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +case "$(uname -r)" in +5.19*) skip "Skippen test that kills this kernel" ;; +esac + +# Test reshaping under io load + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +mount_dir="mnt" + +cleanup_mounted_and_teardown() +{ + umount "$mount_dir" || true + aux teardown +} + +aux prepare_pvs 16 32 + +get_devs + +vgcreate $SHARED -s 1M "$vg" "${DEVICES[@]}" + +trap 'cleanup_mounted_and_teardown' EXIT + +# Create 13-way striped raid5 (14 legs total) +lvcreate --yes --type raid5_ls --stripes 13 -L4 -n$lv1 $vg +check lv_first_seg_field $vg/$lv1 segtype "raid5_ls" +check lv_first_seg_field $vg/$lv1 data_stripes 13 +check lv_first_seg_field $vg/$lv1 stripes 14 +wipefs -a "$DM_DEV_DIR/$vg/$lv1" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 + +mkdir -p $mount_dir +mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir +mkdir -p $mount_dir/1 $mount_dir/2 + +aux delay_dev "$dev2" 0 100 + +echo 3 >/proc/sys/vm/drop_caches +cp -r /usr/bin $mount_dir/1 >/dev/null 2>/dev/null & +cp -r /usr/bin $mount_dir/2 >/dev/null 2>/dev/null & +sync & + +# Reshape it to 256K stripe size +lvconvert --yes --stripesize 256 $vg/$lv1 +aux delay_dev "$dev2" 0 0 +check lv_first_seg_field $vg/$lv1 stripesize "256.00k" + +kill -9 %% +wait + +umount $mount_dir + +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-striped_to_linear-single-type.sh b/test/shell/lvconvert-raid-reshape-striped_to_linear-single-type.sh new file mode 100644 index 0000000..d7d4715 --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-striped_to_linear-single-type.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux lvmconf 'activation/raid_region_size = 512' + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +aux prepare_vg 5 + +# +# Test multi step striped -> linear conversion +# + +# Create 4-way striped LV +lvcreate -aey --type striped -L 16M --stripes 4 --stripesize 64K -n $lv $vg +check lv_first_seg_field $vg/$lv segtype "striped" +check lv_first_seg_field $vg/$lv stripes 4 +check lv_first_seg_field $vg/$lv data_stripes 4 +check lv_first_seg_field $vg/$lv stripesize "64.00k" +wipefs -a "$DM_DEV_DIR/$vg/$lv" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv" +fsck -fn "$DM_DEV_DIR/$vg/$lv" +lvextend -y -L64M $vg/$lv + +# Convert striped -> raid5_n +lvconvert -y --type linear $vg/$lv +check lv_field $vg/$lv segtype "raid5_n" +check lv_field $vg/$lv data_stripes 4 +check lv_field $vg/$lv stripes 5 +check lv_field $vg/$lv data_stripes 4 +check lv_field $vg/$lv stripesize "64.00k" +check lv_field $vg/$lv regionsize "512.00k" +check lv_field $vg/$lv reshape_len_le 0 +aux wait_for_sync $vg $lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Restripe raid5_n LV to single data stripe +# +# Need --force in order to remove stripes thus shrinking LV size! +lvconvert -y --force --type linear $vg/$lv +aux wait_for_sync $vg $lv 1 +fsck -fn "$DM_DEV_DIR/$vg/$lv" +# Remove the now freed stripes +lvconvert -y --type linear $vg/$lv +check lv_field $vg/$lv segtype "raid5_n" +check lv_field $vg/$lv stripes 2 +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripesize "64.00k" +check lv_field $vg/$lv regionsize "512.00k" +check lv_field $vg/$lv reshape_len_le 4 + +# Convert raid5_n -> raid1 +lvconvert -y --type linear $vg/$lv +check lv_field $vg/$lv segtype "raid1" +check lv_field $vg/$lv stripes 2 +check lv_field $vg/$lv data_stripes 2 +check lv_field $vg/$lv stripesize 0 +check lv_field $vg/$lv regionsize "512.00k" +check lv_field $vg/$lv reshape_len_le "" +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert raid1 -> linear +lvconvert -y --type linear $vg/$lv +check lv_first_seg_field $vg/$lv segtype "linear" +check lv_first_seg_field $vg/$lv stripes 1 +check lv_first_seg_field $vg/$lv data_stripes 1 +check lv_first_seg_field $vg/$lv stripesize 0 +check lv_first_seg_field $vg/$lv regionsize 0 +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-striped_to_linear.sh b/test/shell/lvconvert-raid-reshape-striped_to_linear.sh new file mode 100644 index 0000000..ab075e1 --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-striped_to_linear.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux lvmconf 'activation/raid_region_size = 512' + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +aux prepare_vg 5 20 + +# +# Test single step linear -> striped conversion +# + +# Create 4-way striped LV +lvcreate -aey -i 4 -I 32k -L 16M -n $lv1 $vg +check lv_field $vg/$lv1 segtype "striped" +check lv_field $vg/$lv1 data_stripes 4 +check lv_field $vg/$lv1 stripes 4 +check lv_field $vg/$lv1 stripesize "32.00k" +check lv_field $vg/$lv1 reshape_len_le "" +wipefs -a "$DM_DEV_DIR/$vg/$lv1" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv1" +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert striped -> raid5(_n) +lvconvert -y --ty raid5 -R 128k $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_field $vg/$lv1 segtype "raid5_n" +check lv_field $vg/$lv1 data_stripes 4 +check lv_field $vg/$lv1 stripes 5 +check lv_field $vg/$lv1 stripesize "32.00k" +check lv_field $vg/$lv1 regionsize "128.00k" +check lv_field $vg/$lv1 reshape_len_le 0 +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Extend raid5_n LV by factor 4 to keep size once linear +lvresize -y -L 64M $vg/$lv1 +aux wait_for_sync $vg $lv1 + +check lv_field $vg/$lv1 segtype "raid5_n" +check lv_field $vg/$lv1 data_stripes 4 +check lv_field $vg/$lv1 stripes 5 +check lv_field $vg/$lv1 stripesize "32.00k" +check lv_field $vg/$lv1 regionsize "128.00k" +check lv_field $vg/$lv1 reshape_len_le "0" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert raid5_n LV to 1 stripe (2 legs total), +# 64k stripesize and 1024k regionsize +# FIXME: "--type" superfluous (cli fix needed) +lvconvert -y -f --ty raid5_n --stripes 1 -I 64k -R 1024k $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_first_seg_field $vg/$lv1 segtype "raid5_n" +check lv_first_seg_field $vg/$lv1 data_stripes 1 +check lv_first_seg_field $vg/$lv1 stripes 5 +check lv_first_seg_field $vg/$lv1 stripesize "32.00k" +check lv_first_seg_field $vg/$lv1 regionsize "1.00m" +check lv_first_seg_field $vg/$lv1 reshape_len_le 10 +# for slv in {0..4} +# do +# check lv_first_seg_field $vg/${lv1}_rimage_${slv} reshape_len_le 2 +# done +aux wait_for_sync $vg $lv1 1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Remove the now freed legs +lvconvert -y --stripes 1 $vg/$lv1 +check lv_first_seg_field $vg/$lv1 segtype "raid5_n" +check lv_first_seg_field $vg/$lv1 data_stripes 1 +check lv_first_seg_field $vg/$lv1 stripes 2 +check lv_first_seg_field $vg/$lv1 stripesize "32.00k" +check lv_first_seg_field $vg/$lv1 regionsize "1.00m" +check lv_first_seg_field $vg/$lv1 reshape_len_le 4 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert raid5_n to raid1 +lvconvert -y --type raid1 $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_first_seg_field $vg/$lv1 segtype "raid1" +check lv_first_seg_field $vg/$lv1 data_stripes 2 +check lv_first_seg_field $vg/$lv1 stripes 2 +check lv_first_seg_field $vg/$lv1 stripesize "0" +check lv_first_seg_field $vg/$lv1 regionsize "1.00m" +check lv_first_seg_field $vg/$lv1 reshape_len_le "" +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert raid1 -> linear +lvconvert -y --type linear $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_first_seg_field $vg/$lv1 segtype "linear" +check lv_first_seg_field $vg/$lv1 data_stripes 1 +check lv_first_seg_field $vg/$lv1 stripes 1 +check lv_first_seg_field $vg/$lv1 stripesize "0" +check lv_first_seg_field $vg/$lv1 regionsize "0" +check lv_first_seg_field $vg/$lv1 reshape_len_le "" +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-stripes-load-fail.sh b/test/shell/lvconvert-raid-reshape-stripes-load-fail.sh new file mode 100644 index 0000000..b35cd8d --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-stripes-load-fail.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Test reshaping under io load + +case "$(uname -r)" in + 3.10.0-862*) skip "Cannot run this test on unfixed kernel." ;; +esac + +which mkfs.ext4 || skip +aux have_raid 1 13 2 || skip + +mount_dir="mnt" + +cleanup_mounted_and_teardown() +{ + umount "$mount_dir" || true + aux teardown +} + +aux prepare_pvs 16 32 + +get_devs + +vgcreate $SHARED -s 1M "$vg" "${DEVICES[@]}" + +trap 'cleanup_mounted_and_teardown' EXIT + +# Create 10-way striped raid5 (11 legs total) +lvcreate --yes --type raid5_ls --stripesize 64K --stripes 10 -L4 -n$lv1 $vg +check lv_first_seg_field $vg/$lv1 segtype "raid5_ls" +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" +check lv_first_seg_field $vg/$lv1 data_stripes 10 +check lv_first_seg_field $vg/$lv1 stripes 11 +wipefs -a "$DM_DEV_DIR/$vg/$lv1" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv1" +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +mkdir -p "$mount_dir" +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" +mkdir -p "$mount_dir/1" "$mount_dir/2" + + +echo 3 >/proc/sys/vm/drop_caches +cp -r /usr/bin "$mount_dir/1" &>/dev/null & +cp -r /usr/bin "$mount_dir/2" &>/dev/null & +sync & + +aux wait_for_sync $vg $lv1 +aux delay_dev "$dev2" 0 100 + +# Reshape it to 15 data stripes +lvconvert --yes --stripes 15 $vg/$lv1 +aux disable_dev $dev1 +aux delay_dev "$dev2" 0 0 +check lv_first_seg_field $vg/$lv1 segtype "raid5_ls" +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" +check lv_first_seg_field $vg/$lv1 data_stripes 15 +check lv_first_seg_field $vg/$lv1 stripes 16 + +kill -9 %% +wait +rm -fr "$mount_dir/[12]" + +sync +umount "$mount_dir" + +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-stripes-load-reload.sh b/test/shell/lvconvert-raid-reshape-stripes-load-reload.sh new file mode 100644 index 0000000..fb4b3d1 --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-stripes-load-reload.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Test reshaping under io load + +which md5sum || skip +which mkfs.ext4 || skip +aux have_raid 1 14 || skip + +mount_dir="mnt" + +cleanup_mounted_and_teardown() +{ + umount "$mount_dir" || true + aux teardown +} + +checksum_() +{ + md5sum "$1" | cut -f1 -d' ' +} + +aux prepare_pvs 16 32 + +get_devs + +vgcreate $SHARED -s 1M "$vg" "${DEVICES[@]}" + +trap 'cleanup_mounted_and_teardown' EXIT + +# Create 10-way striped raid5 (11 legs total) +lvcreate --yes --type raid5_ls --stripesize 64K --stripes 10 -L4 -n$lv1 $vg +check lv_first_seg_field $vg/$lv1 segtype "raid5_ls" +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" +check lv_first_seg_field $vg/$lv1 data_stripes 10 +check lv_first_seg_field $vg/$lv1 stripes 11 +wipefs -a "$DM_DEV_DIR/$vg/$lv1" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv1" + +mkdir -p "$mount_dir" +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + +echo 3 >/proc/sys/vm/drop_caches +# FIXME: This is filling up ram disk. Use sane amount of data please! Rate limit the data written! +dd if=/dev/urandom of="$mount_dir/random" bs=1M count=4 conv=fdatasync +checksum_ "$mount_dir/random" >MD5 + +# FIXME: wait_for_sync - is this really testing anything under load? +aux wait_for_sync $vg $lv1 +aux delay_dev "$dev2" 0 200 + +# Reshape it to 15 data stripes +lvconvert --yes --stripes 15 $vg/$lv1 +check lv_first_seg_field $vg/$lv1 segtype "raid5_ls" +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" +check lv_first_seg_field $vg/$lv1 data_stripes 15 +check lv_first_seg_field $vg/$lv1 stripes 16 + +# Reload table during reshape to test for data corruption +case "$(uname -r)" in + 5.[89]*|5.1[012].*|3.10.0-862*|4.18.0-*.el8*) + should not echo "Skipping table reload test on on unfixed kernel!!!" ;; + *) +for i in {0..5} +do + dmsetup table $vg-$lv1|dmsetup load $vg-$lv1 + dmsetup suspend --noflush $vg-$lv1 + dmsetup resume $vg-$lv1 + sleep 0.3 +done + +esac + +aux delay_dev "$dev2" 0 + +kill -9 %% || true +wait + +checksum_ "$mount_dir/random" >MD5_new + +umount "$mount_dir" + +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Compare checksum is matching +cat MD5 MD5_new +diff MD5 MD5_new + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape-stripes-load.sh b/test/shell/lvconvert-raid-reshape-stripes-load.sh new file mode 100644 index 0000000..af15534 --- /dev/null +++ b/test/shell/lvconvert-raid-reshape-stripes-load.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +case "$(uname -r)" in + 3.10.0-862*) skip "Cannot run this test on unfixed kernel." ;; +esac + +# Test reshaping under io load + +which mkfs.ext4 || skip +aux have_raid 1 13 2 || skip + +mount_dir="mnt" + +cleanup_mounted_and_teardown() +{ + umount "$mount_dir" || true + aux teardown +} + +aux prepare_pvs 16 32 + +get_devs + +vgcreate $SHARED -s 1M "$vg" "${DEVICES[@]}" + +trap 'cleanup_mounted_and_teardown' EXIT + +# Create 10-way striped raid5 (11 legs total) +lvcreate --yes --type raid5_ls --stripesize 64K --stripes 10 -L4 -n$lv1 $vg +check lv_first_seg_field $vg/$lv1 segtype "raid5_ls" +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" +check lv_first_seg_field $vg/$lv1 data_stripes 10 +check lv_first_seg_field $vg/$lv1 stripes 11 +wipefs -a "$DM_DEV_DIR/$vg/$lv1" +mkfs -t ext4 "$DM_DEV_DIR//$vg/$lv1" + +mkdir -p $mount_dir +mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir +mkdir -p $mount_dir/1 $mount_dir/2 + + +echo 3 >/proc/sys/vm/drop_caches +cp -r /usr/bin $mount_dir/1 >/dev/null 2>/dev/null & +cp -r /usr/bin $mount_dir/2 >/dev/null 2>/dev/null & +sync & + +aux wait_for_sync $vg $lv1 +aux delay_dev "$dev2" 0 100 + +# Reshape it to 15 data stripes +lvconvert --yes --stripes 15 $vg/$lv1 +aux delay_dev "$dev2" 0 0 +check lv_first_seg_field $vg/$lv1 segtype "raid5_ls" +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" +check lv_first_seg_field $vg/$lv1 data_stripes 15 +check lv_first_seg_field $vg/$lv1 stripes 16 + +kill -9 %% +wait + +umount $mount_dir + +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-reshape.sh b/test/shell/lvconvert-raid-reshape.sh new file mode 100644 index 0000000..abea0ff --- /dev/null +++ b/test/shell/lvconvert-raid-reshape.sh @@ -0,0 +1,242 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +LVM_SKIP_LARGE_TESTS=0 + +. lib/inittest + +case "$(uname -r)" in +5.19*) skip "Skippen test that kills this kernel" ;; +esac + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +test "$(aux total_mem)" -gt 1048576 || skip "Not enough RAM for this test" + +if [ $LVM_SKIP_LARGE_TESTS -eq 0 ] +then + aux prepare_pvs 65 9 +else + aux prepare_pvs 20 9 +fi + +get_devs + +vgcreate $SHARED -s 1M "$vg" "${DEVICES[@]}" + +function _lvcreate +{ + local level=$1 + local req_stripes=$2 + local stripes=$3 + local size=$4 + local vg=$5 + local lv=$6 + + lvcreate -y -aey --type $level -i $req_stripes -L $size -n $lv $vg + check lv_first_seg_field $vg/$lv segtype "$level" + check lv_first_seg_field $vg/$lv datastripes $req_stripes + check lv_first_seg_field $vg/$lv stripes $stripes + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" + fsck -fn "$DM_DEV_DIR/$vg/$lv" +} + +function _lvconvert +{ + local req_level=$1 + local level=$2 + local data_stripes=$3 + local stripes=$4 + local vg=$5 + local lv=$6 + local region_size=${7-} + local wait_and_check=1 + local R="" + + [ -n "$region_size" ] && R="-R $region_size" + [ "${level:0:7}" = "striped" ] && wait_and_check=0 + [ "${level:0:5}" = "raid0" ] && wait_and_check=0 + + lvconvert -y --ty $req_level $R $vg/$lv || return $? + + check lv_first_seg_field $vg/$lv segtype "$level" + check lv_first_seg_field $vg/$lv data_stripes $data_stripes + check lv_first_seg_field $vg/$lv stripes $stripes + [ -n "$region_size" ] && check lv_field $vg/$lv regionsize $region_size + if [ "$wait_and_check" -eq 1 ] + then + fsck -fn "$DM_DEV_DIR/$vg/$lv" + aux wait_for_sync $vg $lv + fi + fsck -fn "$DM_DEV_DIR/$vg/$lv" +} + +function _reshape_layout +{ + local type=$1 + shift + local data_stripes=$1 + shift + local stripes=$1 + shift + local vg=$1 + shift + local lv=$1 + shift + local opts="$*" + local ignore_a_chars=0 + + [[ "$opts" =~ "--stripes" ]] && ignore_a_chars=1 + + lvconvert -y --ty $type $opts $vg/$lv + check lv_first_seg_field $vg/$lv segtype "$type" + check lv_first_seg_field $vg/$lv data_stripes $data_stripes + check lv_first_seg_field $vg/$lv stripes $stripes + aux wait_for_sync $vg $lv $ignore_a_chars + fsck -fn "$DM_DEV_DIR/$vg/$lv" +} + +# Delay leg so that rebuilding status characters +# can be read before resync finished too quick. +# aux delay_dev "$dev1" 1 + +# +# Start out with raid5(_ls) +# + +# Create 3-way striped raid5 (4 legs total) +# _lvcreate raid5_ls 3 4 16M $vg $lv1 +_lvcreate raid5_ls 3 4 16M $vg $lv1 +check lv_first_seg_field $vg/$lv1 segtype "raid5_ls" +aux wait_for_sync $vg $lv1 + +# Reshape it to 256K stripe size +_reshape_layout raid5_ls 3 4 $vg $lv1 --stripesize 256K +check lv_first_seg_field $vg/$lv1 stripesize "256.00k" + +# Convert raid5(_n) -> striped testing raid5_ls gets rejected +not _lvconvert striped striped 3 3 $vg $lv1 512k +_reshape_layout raid5_n 3 4 $vg $lv1 +_lvconvert striped striped 3 3 $vg $lv1 + +# Convert striped -> raid5_n +_lvconvert raid5_n raid5_n 3 4 $vg $lv1 "" 1 + +# Convert raid5_n -> raid5_ls +_reshape_layout raid5_ls 3 4 $vg $lv1 + +# Convert raid5_ls to 5 stripes +_reshape_layout raid5_ls 5 6 $vg $lv1 --stripes 5 + +# Convert raid5_ls back to 3 stripes +_reshape_layout raid5_ls 3 6 $vg $lv1 --stripes 3 --force +_reshape_layout raid5_ls 3 4 $vg $lv1 --stripes 3 + +# Convert raid5_ls to 7 stripes +_reshape_layout raid5_ls 7 8 $vg $lv1 --stripes 7 + +# Convert raid5_ls to 9 stripes +_reshape_layout raid5_ls 9 10 $vg $lv1 --stripes 9 + +# Convert raid5_ls to 14 stripes +_reshape_layout raid5_ls 14 15 $vg $lv1 --stripes 14 + +if [ $LVM_SKIP_LARGE_TESTS -eq 0 ] +then + # Convert raid5_ls to 63 stripes + _reshape_layout raid5_ls 63 64 $vg $lv1 --stripes 63 + + # Convert raid5_ls back to 27 stripes + _reshape_layout raid5_ls 27 64 $vg $lv1 --stripes 27 --force + _reshape_layout raid5_ls 27 28 $vg $lv1 --stripes 27 + + # Convert raid5_ls back to 4 stripes checking + # conversion to striped/raid* gets rejected + # with existing LVs to be removed afer reshape + _reshape_layout raid5_ls 4 28 $vg $lv1 --stripes 4 --force +else + # Convert raid5_ls back to 4 stripes checking + # conversion to striped/raid* gets rejected + # with existing LVs to be removed afer reshape + _reshape_layout raid5_ls 4 15 $vg $lv1 --stripes 4 --force +fi + +# No we got the data reshaped and the freed SubLVs still present +# -> check takeover request gets rejected +not lvconvert --yes --type striped $vg/$lv1 +not lvconvert --yes --type raid0 $vg/$lv1 +not lvconvert --yes --type "$DM_DEV_DIR/raid0_meta $vg/$lv1" +not lvconvert --yes --type "$DM_DEV_DIR/raid6 $vg/$lv1" +# Remove the freed SubLVs +_reshape_layout raid5_ls 4 5 $vg $lv1 --stripes 4 + +# Convert raid5_ls back to 3 stripes +_reshape_layout raid5_ls 3 5 $vg $lv1 --stripes 3 --force +_reshape_layout raid5_ls 3 4 $vg $lv1 --stripes 3 + +# Convert raid5_ls -> raid5_rs +_reshape_layout raid5_rs 3 4 $vg $lv1 + +# Convert raid5_rs -> raid5_la +_reshape_layout raid5_la 3 4 $vg $lv1 + +# Convert raid5_la -> raid5_ra +_reshape_layout raid5_ra 3 4 $vg $lv1 + +# Convert raid5_ra -> raid6_ra_6 +_lvconvert raid6_ra_6 raid6_ra_6 3 5 $vg $lv1 "4.00m" 1 + +# Convert raid5_la -> raid6(_zr) +_reshape_layout raid6 3 5 $vg $lv1 + +# Convert raid6(_zr) -> raid6_nc +_reshape_layout raid6_nc 3 5 $vg $lv1 + +# Convert raid6(_nc) -> raid6_nr +_reshape_layout raid6_nr 3 5 $vg $lv1 + +# Convert raid6_nr) -> raid6_rs_6 +_reshape_layout raid6_rs_6 3 5 $vg $lv1 + +# Convert raid6_rs_6 to 5 stripes +_reshape_layout raid6_rs_6 5 7 $vg $lv1 --stripes 5 + +# Convert raid6_rs_6 to 4 stripes +_reshape_layout raid6_rs_6 4 7 $vg $lv1 --stripes 4 --force +_reshape_layout raid6_rs_6 4 6 $vg $lv1 --stripes 4 +check lv_first_seg_field $vg/$lv1 stripesize "256.00k" + +# Convert raid6_rs_6 to raid6_n_6 +_reshape_layout raid6_n_6 4 6 $vg $lv1 + +# Convert raid6_n_6 -> striped +_lvconvert striped striped 4 4 $vg $lv1 +check lv_first_seg_field $vg/$lv1 stripesize "256.00k" + +# Convert striped -> raid10(_near) +_lvconvert raid10 raid10 4 8 $vg $lv1 + +# Convert raid10 to 10 stripes and 64K stripesize +# FIXME: change once we support odd numbers of raid10 stripes +not _reshape_layout raid10 4 9 $vg $lv1 --stripes 9 --stripesize 64K +_reshape_layout raid10 10 20 $vg $lv1 --stripes 10 --stripesize 64K +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" + +# Convert raid6_n_6 -> striped +_lvconvert striped striped 10 10 $vg $lv1 +check lv_first_seg_field $vg/$lv1 stripesize "64.00k" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-restripe-linear.sh b/test/shell/lvconvert-raid-restripe-linear.sh new file mode 100644 index 0000000..59b4d5d --- /dev/null +++ b/test/shell/lvconvert-raid-restripe-linear.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +aux prepare_vg 5 + +# +# Test single step linear -> striped conversion +# + +# Create linear LV +lvcreate -aey -L 16M -n $lv $vg +check lv_field $vg/$lv segtype "linear" +check lv_field $vg/$lv stripes 1 +check lv_field $vg/$lv data_stripes 1 +wipefs -a "$DM_DEV_DIR/$vg/$lv" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv" +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert linear -> raid1 +not lvconvert -y --stripes 4 $vg/$lv +not lvconvert -y --stripes 4 --stripesize 64K $vg/$lv +not lvconvert -y --stripes 4 --stripesize 64K --regionsize 512K $vg/$lv +lvconvert -y --type striped --stripes 4 --stripesize 64K --regionsize 512K $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +check lv_field $vg/$lv segtype "raid1" +check lv_field $vg/$lv stripes 2 +check lv_field $vg/$lv data_stripes 2 +check lv_field $vg/$lv regionsize "512.00k" +aux wait_for_sync $vg $lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert raid1 -> raid5_n +lvconvert -y --type striped --stripes 4 --stripesize 64K --regionsize 512K $vg/$lv +check lv_field $vg/$lv segtype "raid5_n" +check lv_field $vg/$lv stripes 2 +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripesize "64.00k" +check lv_field $vg/$lv regionsize "512.00k" +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Convert raid5_n adding stripes +lvconvert -y --type striped --stripes 4 --stripesize 64K --regionsize 512K $vg/$lv +check lv_first_seg_field $vg/$lv segtype "raid5_n" +check lv_first_seg_field $vg/$lv data_stripes 4 +check lv_first_seg_field $vg/$lv stripes 5 +check lv_first_seg_field $vg/$lv stripesize "64.00k" +check lv_first_seg_field $vg/$lv regionsize "512.00k" +check lv_first_seg_field $vg/$lv reshape_len_le 10 +aux wait_for_sync $vg $lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" +resize2fs "$DM_DEV_DIR/$vg/$lv" + +# Convert raid5_n -> striped +lvconvert -y --type striped $vg/$lv +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-status-validation.sh b/test/shell/lvconvert-raid-status-validation.sh new file mode 100644 index 0000000..d923bf5 --- /dev/null +++ b/test/shell/lvconvert-raid-status-validation.sh @@ -0,0 +1,172 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + +####################################################################### +# This series of tests is meant to validate the correctness of +# 'dmsetup status' for RAID LVs - especially during various sync action +# transitions, like: recover, resync, check, repair, idle, reshape, etc +####################################################################### + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# check for version 1.9.0 +# - it is the point at which linear->raid1 uses "recover" +# check for version 1.13.0 instead +# - it is the point at which a finishing "recover" doesn't print all 'a's +aux have_raid 1 13 0 || skip + + + +aux prepare_pvs 9 +get_devs + +vgcreate $SHARED -s 2m "$vg" "${DEVICES[@]}" + +########################################### +# Upconverted RAID1 should never have all 'a's in status output +########################################### +aux delay_dev "$dev2" 0 20 +lvcreate -aey -l 2 -n $lv1 $vg "$dev1" +lvconvert --type raid1 -y -m 1 $vg/$lv1 "$dev2" +for i in {100..0}; do + check in_sync $vg $lv1 && break + a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1" + b=( $(echo "${a[6]}" | sed s:/:' ':) ) + if [ "${b[0]}" -ne "${b[1]}" ]; then + # First, 'check in_sync' should only need to check the ratio + # If we are here, it is probably doing more than that. + # If not in-sync, then we should only ever see "Aa" + # Ignore until raid starts to report consistent data + [ "${b[0]}" = "0" ] || [ "${a[5]}" == "Aa" ] + else + [ "${a[5]}" != "aa" ] + should [ "${a[5]}" == "AA" ] # RHBZ 1507719 + fi + sleep .1 +done +aux enable_dev "$dev2" +lvremove -ff $vg +test "$i" -gt 0 || die "Unable to get in sync $vg/$lv1" + +########################################### +# Upconverted RAID1 should not be at 100% right after upconvert +########################################### +aux delay_dev "$dev2" 0 50 +lvcreate -aey -l 2 -n $lv1 $vg "$dev1" +lvconvert --type raid1 -y -m 1 $vg/$lv1 "$dev2" +a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1" +b=( $(echo "${a[6]}" | sed s:/:' ':) ) +should [ "${b[0]}" -ne "${b[1]}" ] # RHBZ 1507729 +aux enable_dev "$dev2" +lvremove -ff $vg + +########################################### +# Catch anything suspicious with linear -> RAID1 upconvert +########################################### +aux delay_dev "$dev2" 0 20 +lvcreate -aey -l 2 -n $lv1 $vg "$dev1" +lvconvert --type raid1 -y -m 1 $vg/$lv1 "$dev2" +for i in {100..0}; do + a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1" + b=( $(echo "${a[6]}" | sed s:/:' ':) ) + if [ "${b[0]}" -eq "0" ]; then + : # Ignore until raid starts to report consistent data + elif [ "${b[0]}" -ne "${b[1]}" ]; then + # If the sync operation ("recover" in this case) is not + # finished, then it better be as follows: + [ "${a[5]}" = "Aa" ] + + # Might be transitioning from "idle" to "recover". + # Kernel could check mddev->recovery for the intent to + # begin a "recover" and report that... probably would be + # better. RHBZ 1507719 + should [ "${a[7]}" = "recover" ] + else + # Tough to tell the INVALID case, + # Before starting sync thread: "Aa X/X recover" + # from the valid case, + # Just finished sync thread: "Aa X/X recover" + should [ "${a[5]}" = "AA" ] # RHBZ 1507719 + should [ "${a[7]}" = "idle" ] # RHBZ 1507719 + break + fi + sleep .1 +done +aux enable_dev "$dev2" +lvremove -ff $vg + +########################################### +# Catch anything suspicious with RAID1 2-way -> 3-way upconvert +########################################### +aux delay_dev "$dev3" 0 20 +lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg "$dev1" "$dev2" +aux wait_for_sync $vg $lv1 +lvconvert -y -m +1 $vg/$lv1 "$dev3" +for i in {100..0}; do + a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1" + b=( $(echo "${a[6]}" | sed s:/:' ':) ) + if [ "${b[0]}" -eq "0" ]; then + : # Ignore until raid starts to report consistent data + elif [ "${b[0]}" -ne "${b[1]}" ]; then + # If the sync operation ("recover" in this case) is not + # finished, then it better be as follows: + [ "${a[5]}" = "AAa" ] + [ "${a[7]}" = "recover" ] + else + # Tough to tell the INVALID case, + # Before starting sync thread: "AAa X/X recover" + # from the valid case, + # Just finished sync thread: "AAa X/X recover" + should [ "${a[5]}" = "AAA" ] # RHBZ 1507719 + should [ "${a[7]}" = "idle" ] # RHBZ 1507719 + break + fi + sleep .1 +done +aux enable_dev "$dev3" +lvremove -ff $vg +test "$i" -gt 0 || die "Unable to get in sync $vg/$lv1" + +########################################### +# Catch anything suspicious with RAID1 initial resync +########################################### +aux delay_dev "$dev2" 0 20 +lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg "$dev1" "$dev2" +for i in {100..0}; do + a=( $(dmsetup status $vg-$lv1) ) || die "Unable to get status of $vg/$lv1" + b=( $(echo "${a[6]}" | sed s:/:' ':) ) + if [ "${b[0]}" -eq "0" ]; then + : # Ignore until raid starts to report consistent data + elif [ "${b[0]}" -ne "${b[1]}" ]; then + # If the sync operation ("resync" in this case) is not + # finished, then it better be as follows: + [ "${a[5]}" = "aa" ] + + # Should be in "resync", but it is possible things are only + # just getting going - in which case, it could be "idle" + # with 0% sync ratio + [ "${a[7]}" = "resync" ] || \ + [[ "${a[7]}" = "idle" && "${b[0]}" -eq "0" ]] + else + should [ "${a[5]}" = "AA" ] # RHBZ 1507719 + should [ "${a[7]}" = "idle" ] # RHBZ 1507719 + break + fi + sleep .1 +done +aux enable_dev "$dev2" +lvremove -ff $vg +test "$i" -gt 0 || die "Unable to get in sync $vg/$lv1" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-takeover-alloc-failure.sh b/test/shell/lvconvert-raid-takeover-alloc-failure.sh new file mode 100644 index 0000000..21d0511 --- /dev/null +++ b/test/shell/lvconvert-raid-takeover-alloc-failure.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash + +# Copyright (C) 017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 9 1 || skip + +aux prepare_vg 6 + +function check_sub_lvs +{ + local vg=$1 + local lv=$2 + local end=$3 + + for s in $(seq 0 "$end") + do + check lv_exists $vg ${lv}_rmeta_$s + check lv_exists $vg ${lv}_rimage_$s + done +} + +function check_no_sub_lvs +{ + local vg=$1 + local lv=$2 + local start=$3 + local end=$4 + + for s in $(seq "$start" "$end") + do + check lv_not_exists $vg ${lv}_rmeta_$s + check lv_not_exists $vg ${lv}_rimage_$s + done +} + +# Check takover upconversion fails allocation errors nicely without leaving image pair remnants behind + +# 6-way striped: neither conversion to raid5 nor raid6 possible +lvcreate -aey --yes --stripes 6 --size 4M --name $lv1 $vg +not lvconvert --yes --type raid4 $vg/$lv1 +check lv_field $vg/$lv1 segtype "striped" +check_no_sub_lvs $vg $lv1 0 5 + +not lvconvert --yes --type raid5 $vg/$lv1 +check lv_field $vg/$lv1 segtype "striped" +check_no_sub_lvs $vg $lv1 0 5 + +not lvconvert --yes --type raid6 $vg/$lv1 +check lv_field $vg/$lv1 segtype "striped" +check_no_sub_lvs $vg $lv1 0 5 + +# raid0_meta conversion is possible +lvconvert --yes --type raid0_meta $vg/$lv1 +check lv_field $vg/$lv1 segtype "raid0_meta" +check_sub_lvs $vg $lv1 0 5 + +lvremove -y $vg + +# 5-way striped: conversion to raid5 possible but not to raid6 +lvcreate -aey --stripes 5 --size 4M --name $lv1 $vg +not lvconvert --yes --type raid6 $vg/$lv1 +check lv_field $vg/$lv1 segtype "striped" +check_no_sub_lvs $vg $lv1 0 5 + +lvconvert --yes --type raid5 $vg/$lv1 +check lv_field $vg/$lv1 segtype "raid5_n" +check lv_field $vg/$lv1 stripes 6 +check lv_field $vg/$lv1 datastripes 5 +check_sub_lvs $vg $lv1 0 5 + +lvremove -y $vg + +# 4-way striped: conversion to raid5 and raid6 possible +lvcreate -aey --stripes 4 --size 4M --name $lv1 $vg +lvconvert --yes --type raid5 $vg/$lv1 +check lv_field $vg/$lv1 segtype "raid5_n" +check lv_field $vg/$lv1 stripes 5 +check lv_field $vg/$lv1 datastripes 4 +check_sub_lvs $vg $lv1 0 4 +check_no_sub_lvs $vg $lv1 5 5 + +lvremove -y $vg + +lvcreate -aey --stripes 4 --size 4M --name $lv1 $vg +lvconvert --yes --type raid6 $vg/$lv1 +check lv_field $vg/$lv1 segtype "raid6_n_6" +check lv_field $vg/$lv1 stripes 6 +check lv_field $vg/$lv1 datastripes 4 +check_sub_lvs $vg $lv1 0 5 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-takeover-linear_to_raid4.sh b/test/shell/lvconvert-raid-takeover-linear_to_raid4.sh new file mode 100644 index 0000000..6b28cad --- /dev/null +++ b/test/shell/lvconvert-raid-takeover-linear_to_raid4.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +aux prepare_vg 4 32 + +# FIXME: lvconvert leaks 'error' devices +detect_error_leak_() +{ + dmsetup table -S "name=~^$vg-" | not grep "error" || \ + die "Device(s) with error target should not be here." +} + +# Create linear LV +lvcreate -y -L 9M -n $lv $vg +check lv_field $vg/$lv segtype "linear" +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripes 1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Step 1: convert linear -> raid4 (convert to 2-legged raid1) +lvconvert -y --stripes 3 --ty raid4 $vg/$lv +detect_error_leak_ +check lv_field $vg/$lv segtype "raid1" +check lv_field $vg/$lv data_stripes 2 +check lv_field $vg/$lv stripes 2 +aux wait_for_sync $vg $lv + +# Step 2: convert linear ->raid4 (convert to raid4) +lvconvert -y --stripes 3 --ty raid4 $vg/$lv +detect_error_leak_ +check lv_field $vg/$lv segtype "raid4" +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripes 2 + +# Step 3: convert linear ->raid4 (reshape to add stripes) +lvconvert -y --stripes 3 --ty raid4 $vg/$lv +detect_error_leak_ +check lv_field $vg/$lv segtype "raid4" +check lv_field $vg/$lv data_stripes 3 +check lv_field $vg/$lv stripes 4 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-takeover-raid4_to_linear.sh b/test/shell/lvconvert-raid-takeover-raid4_to_linear.sh new file mode 100644 index 0000000..6201af4 --- /dev/null +++ b/test/shell/lvconvert-raid-takeover-raid4_to_linear.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_raid 1 14 0 || skip + +aux prepare_vg 4 32 + +# FIXME: lvconvert leaks 'error' devices +detect_error_leak_() +{ + dmsetup table -S "name=~^$vg-" | not grep "error" || \ + die "Device(s) with error target should not be here." +} + +# Create 3-way striped raid4 (4 legs total) +lvcreate -y --ty raid4 --stripes 3 -L 9M -n $lv $vg +check lv_field $vg/$lv segtype "raid4" +check lv_field $vg/$lv data_stripes 3 +check lv_field $vg/$lv stripes 4 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +fsck -fn "$DM_DEV_DIR/$vg/$lv" + +# Step 1: grow before removing stripes +lvextend -y -L27M $vg/$lv +aux wait_for_sync $vg $lv + +# Step 2: convert raid4 -> linear (reshape to remove stripes) +lvconvert -y -f --ty linear $vg/$lv +detect_error_leak_ +check lv_field $vg/$lv segtype "raid4" +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripes 4 +aux wait_for_sync $vg $lv 1 + +# Step 2: convert raid4 -> linear (remove freed stripes) +lvconvert -y --ty linear $vg/$lv +detect_error_leak_ +check lv_field $vg/$lv segtype "raid4" +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripes 2 + +# Step 3: convert raid4 -> linear (convert to raid1) +lvconvert -y --ty linear $vg/$lv +detect_error_leak_ +check lv_field $vg/$lv segtype "raid1" +check lv_field $vg/$lv data_stripes 2 +check lv_field $vg/$lv stripes 2 + +# Step 4: convert raid4 -> linear (convert to linear) +lvconvert -y --ty linear $vg/$lv +detect_error_leak_ +check lv_field $vg/$lv segtype "linear" +check lv_field $vg/$lv data_stripes 1 +check lv_field $vg/$lv stripes 1 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-takeover-thin.sh b/test/shell/lvconvert-raid-takeover-thin.sh new file mode 100644 index 0000000..8bea244 --- /dev/null +++ b/test/shell/lvconvert-raid-takeover-thin.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + +# check we may convert thin-pool to raid1/raid10 and back +# RHBZ#1365286 + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_thin 1 0 0 || skip +aux have_raid 1 9 0 || skip + +aux prepare_vg 6 + +lvcreate -L4 -i3 -T $vg/pool -V10 + +for i in 1 2 ; do +lvconvert --type raid10 -y $vg/pool_tdata +check grep_dmsetup table $vg-pool_tdata "raid10" +aux wait_for_sync $vg pool_tdata + +lvconvert --type striped -y $vg/pool_tdata +check grep_dmsetup table $vg-pool_tdata "striped" +done + +lvremove -f $vg + +lvcreate -L4 -T $vg/pool -V10 -n $lv1 + +for j in data meta ; do + LV=pool_t${j} + for i in 1 2 ; do + lvconvert --type raid1 -m1 -y $vg/$LV + check grep_dmsetup table $vg-${LV} "raid1" + aux wait_for_sync $vg $LV + + lvconvert --type raid1 -m0 -y $vg/$LV + check grep_dmsetup table ${vg}-${LV} "linear" + done +done + + +# +# Now same test again, when lock holding LV is not a thin-poll +# but thinLV $lv1 +# +lvchange -an $vg +lvchange -ay $vg/$lv1 + +for j in data meta ; do + LV=pool_t${j} + for i in 1 2 ; do + lvconvert --type raid1 -m1 -y $vg/$LV + check grep_dmsetup table $vg-${LV} "raid1" + aux wait_for_sync $vg $LV + + lvconvert --type raid1 -m0 -y $vg/$LV + check grep_dmsetup table ${vg}-${LV} "linear" + done +done + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh new file mode 100644 index 0000000..0265d48 --- /dev/null +++ b/test/shell/lvconvert-raid-takeover.sh @@ -0,0 +1,372 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016,2017 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_raid 1 12 0 || skip + +correct_raid4_layout=0 +aux have_raid 1 9 1 && correct_raid4_layout=1 + +aux prepare_vg 8 + +# FIXME: lvconvert leaks 'error' devices +detect_error_leak_() +{ + dmsetup table -S "name=~^$vg-" | awk '{print $3}'| not grep error || \ + die "Device(s) with error target should not be here." +} + +function _lvcreate +{ + local level=$1 + local req_stripes=$2 + local stripes=$3 + local size=$4 + local vg=$5 + local lv=$6 + + lvcreate -y -aey --type $level -i $req_stripes -L $size -n $lv $vg + check lv_field $vg/$lv segtype "$level" + check lv_field $vg/$lv data_stripes $req_stripes + check lv_field $vg/$lv stripes $stripes + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" + fsck -fn "$DM_DEV_DIR/$vg/$lv" +} + +function _lvconvert +{ + local req_level=$1 + local level=$2 + local data_stripes=$3 + local stripes=$4 + local vg=$5 + local lv=$6 + local region_size=${7-} + local wait_and_check=1 + local R="" + + [ -n "$region_size" ] && R="-R $region_size" + [ "${level:0:7}" = "striped" ] && wait_and_check=0 + [ "${level:0:5}" = "raid0" ] && wait_and_check=0 + + lvconvert -y --ty $req_level $R $vg/$lv + detect_error_leak_ + + check lv_field $vg/$lv segtype "$level" + check lv_field $vg/$lv data_stripes $data_stripes + check lv_field $vg/$lv stripes $stripes + if [ "$wait_and_check" -eq 1 ] + then + fsck -fn "$DM_DEV_DIR/$vg/$lv" + aux wait_for_sync $vg $lv + fi + fsck -fn "$DM_DEV_DIR/$vg/$lv" +} + +function _invalid_raid5_conversions +{ + local vg=$1 + local lv=$2 + + not _lvconvert striped 4 4 $vg $lv1 + not _lvconvert raid0 raid0 4 4 $vg $lv1 + not _lvconvert raid0_meta raid0_meta 4 4 $vg $lv1 + not _lvconvert raid4 raid4 4 5 $vg $lv1 + not _lvconvert raid5_ls raid5_ls 4 5 $vg $lv1 + not _lvconvert raid5_rs raid5_rs 4 5 $vg $lv1 + not _lvconvert raid5_la raid5_la 4 5 $vg $lv1 + not _lvconvert raid5_ra raid5_ra 4 5 $vg $lv1 + not _lvconvert raid6_zr raid6_zr 4 6 $vg $lv1 + not _lvconvert raid6_nr raid6_nr 4 6 $vg $lv1 + not _lvconvert raid6_nc raid6_nc 4 6 $vg $lv1 + not _lvconvert raid6_n_6 raid6_n_6 4 6 $vg $lv1 + not _lvconvert raid6 raid6_n_6 4 6 $vg $lv1 +} + +# Check raid6 conversion constrainst for 2 stripes +for type in striped raid0 raid0_meta +do + _lvcreate $type 2 2 4m $vg $lv1 + not _lvconvert raid6 raid6_n_6 2 4 $vg $lv1 + _lvconvert raid6 raid5_n 2 3 $vg $lv1 + _lvconvert raid6 raid5_n 3 4 $vg $lv1 + _lvconvert raid6 raid6_n_6 3 5 $vg $lv1 + lvremove -y $vg +done + + +# Check raid6 conversion constrainst of minimum 3 stripes +_lvcreate raid0 3 3 4m $vg $lv1 +_lvconvert raid6 raid6_n_6 3 5 $vg $lv1 +lvremove -y $vg + +# Delay 1st leg so that rebuilding status characters +# can be read before resync finished too quick. +# aux delay_dev "$dev1" 1 + +# Create 3-way mirror +lvcreate --yes -aey --type mirror -R 64K -m 2 -L8M -n $lv1 $vg +check lv_field $vg/$lv1 segtype "mirror" +check lv_field $vg/$lv1 stripes 3 +check lv_field $vg/$lv1 regionsize "64.00k" +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert 3-way to 4-way mirror +lvconvert -y -m 3 $vg/$lv1 +detect_error_leak_ +check lv_field $vg/$lv1 segtype "mirror" +check lv_field $vg/$lv1 stripes 4 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Takeover 4-way mirror to raid1 +lvconvert --yes --type raid1 -R 64k $vg/$lv1 +detect_error_leak_ +check lv_field $vg/$lv1 segtype "raid1" +check lv_field $vg/$lv1 stripes 4 +check lv_field $vg/$lv1 regionsize "64.00k" +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +## Convert 4-way raid1 to 5-way +lvconvert -y -m 4 -R 128K $vg/$lv1 +detect_error_leak_ +check lv_field $vg/$lv1 segtype "raid1" +check lv_field $vg/$lv1 stripes 5 +check lv_field $vg/$lv1 regionsize "128.00k" +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# FIXME: enable once lvconvert rejects early +## Try converting 4-way raid1 to 9-way +#not lvconvert --yes -m 8 $vg/$lv1 +#check lv_field $vg/$lv1 segtype "raid1" +#check lv_field $vg/$lv1 stripes 4 + +# Convert 5-way raid1 to 2-way +lvconvert --yes -m 1 $vg/$lv1 +detect_error_leak_ +lvs $vg/$lv1 +dmsetup status $vg-$lv1 +dmsetup table $vg-$lv1 +check lv_field $vg/$lv1 segtype "raid1" +check lv_field $vg/$lv1 stripes 2 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert 2-way raid1 to mirror +lvconvert --yes --type mirror -R 32K $vg/$lv1 +detect_error_leak_ +check lv_field $vg/$lv1 segtype "mirror" +check lv_field $vg/$lv1 stripes 2 +check lv_field $vg/$lv1 regionsize "32.00k" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 + +# Clean up +lvremove --yes $vg/$lv1 + + +if [ $correct_raid4_layout -eq 1 ] +then + +# +# Start out with raid4 +# + +# Create 3-way striped raid4 (4 legs total) +_lvcreate raid4 3 4 8M $vg $lv1 +aux wait_for_sync $vg $lv1 + +# Convert raid4 -> striped +not _lvconvert striped striped 3 3 $vg $lv1 512k +_lvconvert striped striped 3 3 $vg $lv1 + +# Convert striped -> raid4 +_lvconvert raid4 raid4 3 4 $vg $lv1 64k +check lv_field $vg/$lv1 regionsize "64.00k" + +# Convert raid4 -> raid5_n +_lvconvert raid5 raid5_n 3 4 $vg $lv1 128k +check lv_field $vg/$lv1 regionsize "128.00k" + +# Convert raid5_n -> striped +_lvconvert striped striped 3 3 $vg $lv1 + +# Convert striped -> raid5_n +_lvconvert raid5_n raid5_n 3 4 $vg $lv1 + +# Convert raid5_n -> raid4 +_lvconvert raid4 raid4 3 4 $vg $lv1 + +# Convert raid4 -> raid0 +_lvconvert raid0 raid0 3 3 $vg $lv1 + +# Convert raid0 -> raid5_n +_lvconvert raid5_n raid5_n 3 4 $vg $lv1 + +# Convert raid5_n -> raid0_meta +_lvconvert raid0_meta raid0_meta 3 3 $vg $lv1 + +# Convert raid0_meta -> raid5_n +_lvconvert raid5 raid5_n 3 4 $vg $lv1 + +# Convert raid4 -> raid0_meta +not _lvconvert raid0_meta raid0_meta 3 3 $vg $lv1 256k +_lvconvert raid0_meta raid0_meta 3 3 $vg $lv1 + +# Convert raid0_meta -> raid4 +_lvconvert raid4 raid4 3 4 $vg $lv1 + +# Convert raid4 -> raid0 +_lvconvert raid0 raid0 3 3 $vg $lv1 + +# Convert raid0 -> raid4 +_lvconvert raid4 raid4 3 4 $vg $lv1 + +# Convert raid4 -> striped +_lvconvert striped striped 3 3 $vg $lv1 + +# Convert striped -> raid6_n_6 +_lvconvert raid6_n_6 raid6_n_6 3 5 $vg $lv1 + +# Convert raid6_n_6 -> striped +_lvconvert striped striped 3 3 $vg $lv1 + +# Convert striped -> raid6_n_6 +_lvconvert raid6 raid6_n_6 3 5 $vg $lv1 + +# Convert raid6_n_6 -> raid5_n +_lvconvert raid5_n raid5_n 3 4 $vg $lv1 + +# Convert raid5_n -> raid6_n_6 +_lvconvert raid6_n_6 raid6_n_6 3 5 $vg $lv1 + +# Convert raid6_n_6 -> raid4 +_lvconvert raid4 raid4 3 4 $vg $lv1 + +# Convert raid4 -> raid6_n_6 +_lvconvert raid6 raid6_n_6 3 5 $vg $lv1 + +# Convert raid6_n_6 -> raid0 +_lvconvert raid0 raid0 3 3 $vg $lv1 + +# Convert raid0 -> raid6_n_6 +_lvconvert raid6_n_6 raid6_n_6 3 5 $vg $lv1 + +# Convert raid6_n_6 -> raid0_meta +_lvconvert raid0_meta raid0_meta 3 3 $vg $lv1 + +# Convert raid0_meta -> raid6_n_6 +_lvconvert raid6 raid6_n_6 3 5 $vg $lv1 + +# Convert raid6_n_6 -> striped +not _lvconvert striped striped 3 3 $vg $lv1 128k +_lvconvert striped striped 3 3 $vg $lv1 + +# Convert striped -> raid10 +_lvconvert raid10 raid10 3 6 $vg $lv1 + +# Convert raid10 -> raid0 +not _lvconvert raid0 raid0 3 3 $vg $lv1 64k +_lvconvert raid0 raid0 3 3 $vg $lv1 + +# Convert raid0 -> raid10 +_lvconvert raid10 raid10 3 6 $vg $lv1 + +# Convert raid10 -> raid0_meta +_lvconvert raid0_meta raid0_meta 3 3 $vg $lv1 + +# Convert raid0_meta -> raid5 +_lvconvert raid5_n raid5_n 3 4 $vg $lv1 + +# Convert raid5_n -> raid0_meta +_lvconvert raid0_meta raid0_meta 3 3 $vg $lv1 + +# Convert raid0_meta -> raid10 +_lvconvert raid10 raid10 3 6 $vg $lv1 + +# Convert raid10 -> striped +not _lvconvert striped striped 3 3 $vg $lv1 256k +_lvconvert striped striped 3 3 $vg $lv1 + +# Clean up +lvremove -y $vg + +# Create + convert 4-way raid5 variations +_lvcreate raid5 4 5 8M $vg $lv1 +aux wait_for_sync $vg $lv1 +_invalid_raid5_conversions $vg $lv1 +not _lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1 +not _lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1 +not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1 +_lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1 +_lvconvert raid5_ls raid5_ls 4 5 $vg $lv1 +lvremove -y $vg + +_lvcreate raid5_ls 4 5 8M $vg $lv1 +aux wait_for_sync $vg $lv1 +_invalid_raid5_conversions $vg $lv1 +not _lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1 +not _lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1 +not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1 +_lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1 +_lvconvert raid5_ls raid5_ls 4 5 $vg $lv1 +lvremove -y $vg + +_lvcreate raid5_rs 4 5 8M $vg $lv1 +aux wait_for_sync $vg $lv1 +_invalid_raid5_conversions $vg $lv1 +not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1 +not _lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1 +not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1 +_lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1 +_lvconvert raid5_rs raid5_rs 4 5 $vg $lv1 +lvremove -y $vg + +_lvcreate raid5_la 4 5 8M $vg $lv1 +aux wait_for_sync $vg $lv1 +_invalid_raid5_conversions $vg $lv1 +not _lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1 +not _lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1 +not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1 +_lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1 +_lvconvert raid5_la raid5_la 4 5 $vg $lv1 +lvremove -y $vg + +_lvcreate raid5_ra 4 5 8M $vg $lv1 +aux wait_for_sync $vg $lv1 +_invalid_raid5_conversions $vg $lv1 +not _lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1 +not _lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1 +not _lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1 +_lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1 +_lvconvert raid5_ra raid5_ra 4 5 $vg $lv1 +lvremove -y $vg + +else + +not lvcreate -y -aey --type raid4 -i 3 -L8M -n $lv4 $vg +not lvconvert -y --ty raid4 $vg/$lv1 +not lvconvert -y --ty raid4 $vg/$lv2 + +fi + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid.sh b/test/shell/lvconvert-raid.sh index 4fa766d..aa50fbb 100644 --- a/test/shell/lvconvert-raid.sh +++ b/test/shell/lvconvert-raid.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2011-2017 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 @@ -7,34 +8,39 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# disable lvmetad logging as it bogs down test systems -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest get_image_pvs() { local d - local images + local images=() - images=`dmsetup ls | grep ${1}-${2}_.image_.* | cut -f1 | sed -e s:-:/:` - lvs --noheadings -a -o devices $images | sed s/\(.\)// + images=( $(dmsetup ls | grep "${1}-${2}_.image_.*" | cut -f1 | sed -e s:-:/:) ) + lvs --noheadings -a -o devices "${images[@]}" | sed s/\(.\)// } ######################################################## # MAIN ######################################################## -aux target_at_least dm-raid 1 1 0 || skip -aux kernel_at_least 3 2 0 || skip +aux have_raid 1 3 0 || skip + +aux prepare_pvs 9 +get_devs -# 9 PVs needed for RAID10 testing (3-stripes/2-mirror - replacing 3 devs) -aux prepare_pvs 9 80 -vgcreate -c n -s 256k $vg $(cat DEVICES) +# vgcreate -s 256k "$vg" "${DEVICES[@]}" +vgcreate $SHARED -s 2m "$vg" "${DEVICES[@]}" ########################################### # RAID1 convert tests ########################################### for under_snap in false true; do -for i in 1 2 3 4; do - for j in 1 2 3 4; do +for i in 1 2 3; do + for j in 1 2 3; do if [ $i -eq 1 ]; then from="linear" else @@ -56,17 +62,29 @@ for i in 1 2 3 4; do # Shouldn't be able to create with just 1 image not lvcreate --type raid1 -m 0 -l 2 -n $lv1 $vg - lvcreate -l 2 -n $lv1 $vg + lvcreate -aey -l 2 -n $lv1 $vg else - lvcreate --type raid1 -m $(($i - 1)) -l 2 -n $lv1 $vg + lvcreate --type raid1 -m $(( i - 1 )) -l 2 -n $lv1 $vg aux wait_for_sync $vg $lv1 fi if $under_snap; then - lvcreate -s $vg/$lv1 -n snap -l 2 + lvcreate -aey -s $vg/$lv1 -n snap -l 2 fi - lvconvert -m $((j - 1)) $vg/$lv1 + mirrors=$((j - 1)) + if [ $i -eq 1 ] + then + [ $mirrors -eq 0 ] && lvconvert -y -m $mirrors $vg/$lv1 + else + if [ $mirrors -eq 0 ] + then + not lvconvert -m $mirrors $vg/$lv1 + lvconvert -y -m $mirrors $vg/$lv1 + else + lvconvert -y -m $mirrors $vg/$lv1 + fi + fi # FIXME: ensure no residual devices @@ -87,13 +105,13 @@ lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg --nosync not lvconvert -m +1 $vg/$lv1 lvchange --resync -y $vg/$lv1 aux wait_for_sync $vg $lv1 -lvconvert -m +1 $vg/$lv1 +lvconvert -y -m +1 $vg/$lv1 lvremove -ff $vg # 3-way to 2-way convert while specifying devices -lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg $dev1 $dev2 $dev3 +lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg "$dev1" "$dev2" "$dev3" aux wait_for_sync $vg $lv1 -lvconvert -m1 $vg/$lv1 $dev2 +lvconvert -y -m 1 $vg/$lv1 "$dev2" lvremove -ff $vg # @@ -109,77 +127,201 @@ aux wait_for_sync $vg $lv1 lvconvert --splitmirrors 1 -n $lv2 $vg/$lv1 check lv_exists $vg $lv1 check linear $vg $lv2 +check active $vg $lv2 # FIXME: ensure no residual devices lvremove -ff $vg # 2-way to linear/linear lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg aux wait_for_sync $vg $lv1 -lvconvert --splitmirrors 1 -n $lv2 $vg/$lv1 +not lvconvert --splitmirrors 1 -n $lv2 $vg/$lv1 +lvconvert --yes --splitmirrors 1 -n $lv2 $vg/$lv1 check linear $vg $lv1 check linear $vg $lv2 +check active $vg $lv2 # FIXME: ensure no residual devices lvremove -ff $vg -# 3-way to linear/2-way -lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg +# 4-way +lvcreate --type raid1 -m 4 -l 2 -n $lv1 $vg aux wait_for_sync $vg $lv1 -# FIXME: Can't split off a RAID1 from a RAID1 yet -# 'should' results in "warnings" -should lvconvert --splitmirrors 2 -n $lv2 $vg/$lv1 -#check linear $vg $lv1 -#check lv_exists $vg $lv2 -# FIXME: ensure no residual devices +lvconvert --splitmirrors 1 --name $lv2 $vg/$lv1 "$dev2" lvremove -ff $vg ########################################### -# RAID1 split + trackchanges / merge +# RAID1 split + trackchanges / merge with content check ########################################### # 3-way to 2-way/linear -lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg +lvcreate --type raid1 -m 2 -l 1 -n $lv1 $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1" aux wait_for_sync $vg $lv1 +fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1" lvconvert --splitmirrors 1 --trackchanges $vg/$lv1 check lv_exists $vg $lv1 check linear $vg ${lv1}_rimage_2 +fsck.ext4 -fn "$DM_DEV_DIR/mapper/$vg-${lv1}_rimage_2" +dd of="$DM_DEV_DIR/$vg/$lv1" if=/dev/zero bs=512 oflag=direct count="$(blockdev --getsz "$DM_DEV_DIR/$vg/$lv1")" +not fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1" +fsck.ext4 -fn "$DM_DEV_DIR/mapper/$vg-${lv1}_rimage_2" +# FIXME: needed on tiny loop but not on real block backend ? +lvchange --refresh $vg/$lv1 lvconvert --merge $vg/${lv1}_rimage_2 +aux wait_for_sync $vg $lv1 +lvconvert --splitmirrors 1 --trackchanges $vg/$lv1 +not fsck.ext4 -fn "$DM_DEV_DIR/mapper/$vg-${lv1}_rimage_2" +# FIXME: ensure no residual devices +lvremove -ff $vg + +# Check split track changes gets rejected w/o -y on 2-legged raid1 +lvcreate --type raid1 -m 1 -l 1 -n $lv1 $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 +fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1" +not lvconvert --splitmirrors 1 --trackchanges $vg/$lv1 +lvconvert --yes --splitmirrors 1 --trackchanges $vg/$lv1 # FIXME: ensure no residual devices lvremove -ff $vg +########################################### +# Linear to RAID1 conversion ("raid1" default segtype) +########################################### +lvcreate -aey -l 2 -n $lv1 $vg +lvconvert -y -m 1 $vg/$lv1 \ + --config 'global { mirror_segtype_default = "raid1" }' +lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*r' +lvremove -ff $vg + +########################################### +# Linear to RAID1 conversion (override "mirror" default segtype) +########################################### +lvcreate -aey -l 2 -n $lv1 $vg +lvconvert --yes --type raid1 -m 1 $vg/$lv1 \ + --config 'global { mirror_segtype_default = "mirror" }' +lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*r' +lvremove -ff $vg + +########################################### +# Must not be able to convert non-EX LVs in a cluster +########################################### +if [ -e LOCAL_CLVMD ]; then + lvcreate -l 2 -n $lv1 $vg + not lvconvert -y --type raid1 -m 1 $vg/$lv1 \ + --config 'global { mirror_segtype_default = "mirror" }' + lvremove -ff $vg +fi + ########################################### # Mirror to RAID1 conversion ########################################### for i in 1 2 3 ; do - lvcreate --type mirror -m $i -l 2 -n $lv1 $vg + lvcreate -aey --type mirror -m $i -l 2 -n $lv1 $vg aux wait_for_sync $vg $lv1 - lvconvert --type raid1 $vg/$lv1 + lvconvert -y --type raid1 $vg/$lv1 lvremove -ff $vg done +########################################### +# Upconverted RAID1 should not allow loss of primary +# - don't allow removal of primary while syncing +# - DO allow removal of secondaries while syncing +########################################### +aux delay_dev "$dev2" 0 100 +lvcreate -aey -l 2 -n $lv1 $vg "$dev1" +lvconvert -y -m 1 $vg/$lv1 \ + --config 'global { mirror_segtype_default = "raid1" }' "$dev2" +lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*r' +not lvconvert --yes -m 0 $vg/$lv1 "$dev1" +lvconvert --yes -m 0 $vg/$lv1 "$dev2" +aux enable_dev "$dev2" +lvremove -ff $vg + +########################################### +# lvcreated RAID1 should allow all down-conversion +# - DO allow removal of primary while syncing +# - DO allow removal of secondaries while syncing +########################################### +aux delay_dev "$dev2" 0 100 +lvcreate --type raid1 -m 2 -aey -l 2 -n $lv1 $vg "$dev1" "$dev2" "$dev3" +case "$(uname -r)" in +4.8.14*) +echo "Skippen test that kills this kernel" +;; +*) +lvconvert --yes -m 1 $vg/$lv1 "$dev3" + +# FIXME: it is unclear what should happen - older kernel +# do use 'resync' for initial array building so then +# we are not able to recognize difference +# Should we check version target as react differentely ?? +# Otherwise we have problem with the above test case. +should lvconvert --yes -m 0 $vg/$lv1 "$dev1" +aux enable_dev "$dev2" +;; +esac +lvremove -ff $vg + +########################################### +# Converting from 2-way RAID1 to 3-way +# - DO allow removal of one of primary sources +# - Do not allow removal of all primary sources +########################################### +lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg "$dev1" "$dev2" +aux wait_for_sync $vg $lv1 +aux delay_dev "$dev3" 0 100 +lvconvert --yes -m +1 $vg/$lv1 "$dev3" +# should allow 1st primary to be removed +lvconvert --yes -m -1 $vg/$lv1 "$dev1" +# should NOT allow last primary to be removed +not lvconvert --yes -m -1 $vg/$lv1 "$dev2" +# should allow non-primary to be removed +lvconvert --yes -m 0 $vg/$lv1 "$dev3" +aux enable_dev "$dev3" +lvremove -ff $vg + +########################################### +# Converting from 2-way RAID1 to 3-way +# - Should allow removal of two devices, +# as long as they aren't both primary +########################################### +lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg "$dev1" "$dev2" +aux wait_for_sync $vg $lv1 +aux delay_dev "$dev3" 0 100 +lvconvert --yes -m +1 $vg/$lv1 "$dev3" +# should NOT allow both primaries to be removed +not lvconvert -m 0 $vg/$lv1 "$dev1" "$dev2" +# should allow primary + non-primary +lvconvert --yes -m 0 $vg/$lv1 "$dev1" "$dev3" +aux enable_dev "$dev3" +lvremove -ff $vg + ########################################### # Device Replacement Testing ########################################### # RAID1: Replace up to n-1 devices - trying different combinations # Test for 2-way to 4-way RAID1 LVs for i in {1..3}; do - lvcreate --type raid1 -m $i -l 2 -n $lv1 $vg + lvcreate --type raid1 -m "$i" -l 2 -n $lv1 $vg - for j in $(seq $(($i + 1))); do # The number of devs to replace at once + for j in $(seq $(( i + 1 ))); do # The number of devs to replace at once for o in $(seq 0 $i); do # The offset into the device list - replace="" + replace=() devices=( $(get_image_pvs $vg $lv1) ) - for k in $(seq $j); do - index=$((($k + $o) % ($i + 1))) - replace="$replace --replace ${devices[$index]}" + for k in $(seq "$j"); do + index=$(( ( k + o ) % ( i + 1 ) )) + replace+=( "--replace" ) + replace+=( "${devices[$index]}" ) done aux wait_for_sync $vg $lv1 - if [ $j -ge $((i + 1)) ]; then + if [ "$j" -ge $(( i + 1 )) ]; then # Can't replace all at once. - not lvconvert $replace $vg/$lv1 + not lvconvert "${replace[@]}" $vg/$lv1 else - lvconvert $replace $vg/$lv1 + lvconvert "${replace[@]}" $vg/$lv1 fi done done @@ -187,37 +329,4 @@ for i in {1..3}; do lvremove -ff $vg done -# RAID 4/5/6 (can replace up to 'parity' devices) -for i in 4 5 6; do - lvcreate --type raid$i -i 3 -l 3 -n $lv1 $vg - - if [ $i -eq 6 ]; then - dev_cnt=5 - limit=2 - else - dev_cnt=4 - limit=1 - fi - - for j in {1..3}; do - for o in $(seq 0 $i); do - replace="" - - devices=( $(get_image_pvs $vg $lv1) ) - - for k in $(seq $j); do - index=$((($k + $o) % $dev_cnt)) - replace="$replace --replace ${devices[$index]}" - done - aux wait_for_sync $vg $lv1 - - if [ $j -gt $limit ]; then - not lvconvert $replace $vg/$lv1 - else - lvconvert $replace $vg/$lv1 - fi - done - done - - lvremove -ff $vg -done +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid0-striped.sh b/test/shell/lvconvert-raid0-striped.sh new file mode 100644 index 0000000..4521b34 --- /dev/null +++ b/test/shell/lvconvert-raid0-striped.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 7 0 || skip + +aux prepare_vg 3 16 + +lvcreate -aey --type raid0 -i 3 -l3 -n $lv $vg +lvconvert -y --type striped $vg/$lv +check lv_field $vg/$lv segtype "striped" +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid0_to_raid10.sh b/test/shell/lvconvert-raid0_to_raid10.sh new file mode 100644 index 0000000..62c2c24 --- /dev/null +++ b/test/shell/lvconvert-raid0_to_raid10.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# rhbz1514500 + +aux have_raid 1 12 0 || skip + +# 8 PVs needed for RAID10 testing (4-stripes/2-mirror) +aux prepare_vg 8 64 + +lvcreate -y --type raid0 -R32k -i 4 -n $lv1 -L 64M $vg +lvcreate -y -i4 -l4 -n $lv2 $vg +lvextend -y -l +4 $vg/$lv1 +lvconvert -y -R512K --ty raid10 $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid1-split-trackchanges.sh b/test/shell/lvconvert-raid1-split-trackchanges.sh new file mode 100644 index 0000000..92b034c --- /dev/null +++ b/test/shell/lvconvert-raid1-split-trackchanges.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# rhbz1579072/rhbz1579438 + +aux have_raid 1 3 0 || skip + +# 8 PVs needed for RAID10 testing (4-stripes/2-mirror) +aux prepare_vg 4 2 + +lvcreate -y --ty raid1 -m 2 -n $lv1 -l 1 $vg +lvconvert -y --splitmirrors 1 --trackchanges $vg/$lv1 + +not lvconvert -y --ty linear $vg/$lv1 +not lvconvert -y --ty striped -i 3 $vg/$lv1 +not lvconvert -y --ty mirror $vg/$lv1 +not lvconvert -y --ty raid4 $vg/$lv1 +not lvconvert -y --ty raid5 $vg/$lv1 +not lvconvert -y --ty raid6 $vg/$lv1 +not lvconvert -y --ty raid10 $vg/$lv1 +not lvconvert -y --ty striped -m 1 $vg/${lv1}_rimage_2 +not lvconvert -y --ty raid1 -m 1 $vg/${lv1}_rimage_2 +not lvconvert -y --ty mirror -m 1 $vg/${lv1}_rimage_2 +not lvconvert -y --ty cache-pool $vg/${lv1}_rimage_2 +not lvconvert -y --ty thin-pool $vg/${lv1}_rimage_2 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid10.sh b/test/shell/lvconvert-raid10.sh index 2e4381d..04c912c 100644 --- a/test/shell/lvconvert-raid10.sh +++ b/test/shell/lvconvert-raid10.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,15 +8,18 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest get_image_pvs() { local d local images - images=`dmsetup ls | grep ${1}-${2}_.image_.* | cut -f1 | sed -e s:-:/:` + images=$(dmsetup ls | grep "${1}-${2}_.image_.*" | cut -f1 | sed -e s:-:/:) lvs --noheadings -a -o devices $images | sed s/\(.\)// } @@ -24,11 +28,10 @@ get_image_pvs() { ######################################################## # RAID10: Can replace 'copies - 1' devices from each stripe # Tests are run on 2-way mirror, 3-way stripe RAID10 -aux target_at_least dm-raid 1 3 1 || skip +aux have_raid 1 3 1 || skip # 9 PVs needed for RAID10 testing (3-stripes/2-mirror - replacing 3 devs) -aux prepare_pvs 9 80 -vgcreate -c n -s 256k $vg $(cat DEVICES) +aux prepare_vg 9 80 lvcreate --type raid10 -m 1 -i 3 -l 3 -n $lv1 $vg aux wait_for_sync $vg $lv1 @@ -41,16 +44,18 @@ done # Can't replace adjacent devices devices=( $(get_image_pvs $vg $lv1) ) -not lvconvert --replace ${devices[0]} --replace ${devices[1]} $vg/$lv1 -not lvconvert --replace ${devices[2]} --replace ${devices[3]} $vg/$lv1 -not lvconvert --replace ${devices[4]} --replace ${devices[5]} $vg/$lv1 +not lvconvert --replace "${devices[0]}" --replace "${devices[1]}" $vg/$lv1 +not lvconvert --replace "${devices[2]}" --replace "${devices[3]}" $vg/$lv1 +not lvconvert --replace "${devices[4]}" --replace "${devices[5]}" $vg/$lv1 # Can replace non-adjacent devices for i in 0 1; do lvconvert \ - --replace ${devices[$i]} \ - --replace ${devices[$(($i + 2))]} \ - --replace ${devices[$(($i + 4))]} \ + --replace "${devices[$i]}" \ + --replace "${devices[$(( i + 2 ))]}" \ + --replace "${devices[$(( i + 4 ))]}" \ $vg/$lv1 aux wait_for_sync $vg $lv1 done + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid456.sh b/test/shell/lvconvert-raid456.sh new file mode 100644 index 0000000..5198753 --- /dev/null +++ b/test/shell/lvconvert-raid456.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +get_image_pvs() { + local d + local images + + images=$(dmsetup ls | grep "${1}-${2}_.image_.*" | cut -f1 | sed -e s:-:/:) + lvs --noheadings -a -o devices $images | sed s/\(.\)// +} + +######################################################## +# MAIN +######################################################## +aux raid456_replace_works || skip +aux have_raid 1 3 0 || skip + +aux prepare_vg 7 # 7 devices for 2 dev replacement of 5-dev RAID6 + +levels="5 6" +aux have_raid4 && levels="4 5 6" + +# RAID 4/5/6 (can replace up to 'parity' devices) +for i in $levels; do + lvcreate --type raid$i -i 3 -l 3 -n $lv1 $vg + + if [ $i -eq 6 ]; then + dev_cnt=5 + limit=2 + else + dev_cnt=4 + limit=1 + fi + + for j in {1..3}; do + for o in $(seq 0 $i); do + replace="" + + devices=( $(get_image_pvs $vg $lv1) ) + + for k in $(seq $j); do + index=$(( ( k + o ) % dev_cnt )) + replace="$replace --replace ${devices[$index]}" + done + aux wait_for_sync $vg $lv1 + + if [ $j -gt $limit ]; then + not lvconvert $replace $vg/$lv1 + else + lvconvert $replace $vg/$lv1 + fi + done + done + + lvremove -ff $vg +done + +vgremove -ff $vg diff --git a/test/shell/lvconvert-raid5_to_raid10.sh b/test/shell/lvconvert-raid5_to_raid10.sh new file mode 100644 index 0000000..e7ecbc4 --- /dev/null +++ b/test/shell/lvconvert-raid5_to_raid10.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext4 || skip +aux have_raid 1 13 2 || skip + +aux prepare_vg 6 + +# +# Test multi step raid5 -> raid10 conversion +# + +# Create raid5(_ls) LV +lvcreate -y --type raid5 -i 3 -L 16M -R 256K -n $lv1 $vg +check lv_field $vg/$lv1 segtype "raid5" +check lv_field $vg/$lv1 stripes 4 +check lv_field $vg/$lv1 data_stripes 3 +check lv_field $vg/$lv1 region_size "256.00k" +wipefs -a "$DM_DEV_DIR/$vg/$lv1" +mkfs -t ext4 "$DM_DEV_DIR/$vg/$lv1" +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert raid5 -> raid10 (first step raid5 -> raid5_n) +lvconvert -y --ty raid10 $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_field $vg/$lv1 segtype "raid5_n" +check lv_field $vg/$lv1 stripes 4 +check lv_field $vg/$lv1 data_stripes 3 +check lv_field $vg/$lv1 region_size "256.00k" +aux wait_for_sync $vg $lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert raid5 -> raid10 (second step raid5_n -> raid0_meta) +lvconvert -y --ty raid10 $vg/$lv1 +check lv_field $vg/$lv1 segtype "raid0_meta" +check lv_field $vg/$lv1 stripes 3 +check lv_field $vg/$lv1 data_stripes 3 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" + +# Convert raid5 -> raid10 (third + last step raid0_meta -> raid10) +lvconvert -y --ty raid10 -R 256K $vg/$lv1 +fsck -fn "$DM_DEV_DIR/$vg/$lv1" +check lv_field $vg/$lv1 segtype "raid10" +check lv_field $vg/$lv1 stripes 6 +check lv_field $vg/$lv1 data_stripes 3 +check lv_field $vg/$lv1 region_size "256.00k" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-repair-cache.sh b/test/shell/lvconvert-repair-cache.sh new file mode 100644 index 0000000..a09007c --- /dev/null +++ b/test/shell/lvconvert-repair-cache.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test repairing of broken cached LV + +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +MKFS=mkfs.ext4 +FSCK=fsck + +which "$MKFS" || skip +which "$FSCK" || skip + +# +# Main +# +# older versions of cache target reported unreliably write failures +aux have_cache 1 7 0 || skip + +aux prepare_vg 4 + +#if [ 1 -eq 0 ] ; then +############################# +###### WRITETHROUGH ######### +############################# + +# Create cached LV +lvcreate --type cache-pool -L10 $vg/cpool "$dev1" +lvcreate -H -L20 --cachemode writethrough -n $lv1 $vg/cpool "$dev2" + +"$MKFS" "$DM_DEV_DIR/$vg/$lv1" +sync + +aux disable_dev "$dev1" + +#lvchange -an $vg + +# Check it is prompting for confirmation +not lvconvert --uncache $vg/$lv1 +# --yes to drop when Check its prompting +lvconvert --yes --uncache $vg/$lv1 +should not dmsetup remove ${vg}-cpool_cmeta-missing_0_0 +should not dmsetup remove ${vg}-cpool_cdata-missing_0_0 + +"$FSCK" -n "$DM_DEV_DIR/$vg/$lv1" + +aux enable_dev "$dev1" + +################## + +lvcreate --type cache-pool -L10 $vg/cpool "$dev1" +lvconvert -H --cachemode writethrough --cachepool $vg/cpool -Zy $lv1 + +# Check basic --repair of cachepool metadata +lvchange -an $vg/$lv1 +lvconvert --repair $vg/$lv1 + +lvs -a $vg +check lv_exists $vg cpool_cpool_meta0 + +eval "$(lvs -S 'name=~_pmspare' -a --config 'report/mark_hidden_devices=0' -o name --noheading --nameprefixes $vg)" +lvremove -f --yes "$vg/$LVM2_LV_NAME" + +# check --repair without creation of _pmspare device +lvconvert --repair --poolmetadataspare n $vg/$lv1 +check lv_exists $vg cpool_cpool_meta1 + +# check no _pmspare has been created in previous --repair +test "0" = "$(lvs -S 'name=~_pmspare' -a -o name --noheading --nameprefixes $vg | wc -l)" + + +aux disable_dev "$dev2" + +# Deactivate before remove +# FIXME: handle this while LV is alive +lvchange -an $vg/$lv1 + +# Check it is prompting for confirmation +not lvconvert --uncache $vg/$lv1 +# --yes to drop when Check its prompting +lvconvert --yes --uncache $vg/$lv1 + +aux enable_dev "$dev2" + +# vg was changed while dev was missing +vgextend --restoremissing $vg "$dev2" + +# FIXME: temporary workaround +lvcreate -L1 -n $lv5 $vg +lvremove -ff $vg + +########################## +###### WRITEBACK ######### +########################## +#fi + +# Create cached LV so metadata is on dev1 and data on dev2 +lvcreate -L5 -n meta $vg "$dev1" +lvcreate -L10 -n cpool $vg "$dev2" +lvconvert --yes --poolmetadata $vg/meta --cachepool $vg/cpool + +lvcreate -H -L20 --cachemode writeback -n $lv1 $vg/cpool "$dev3" + +lvs -a -o+seg_pe_ranges,cachemode $vg + +"$MKFS" "$DM_DEV_DIR/$vg/$lv1" +sync + +# Seriously damage cache metadata +aux error_dev "$dev1" 2054:2 + +# flushing status +dmsetup status $vg-$lv1 + +# On fixed kernel we get instant Fail here +get lv_field $vg/$lv1 lv_attr | tee out +grep "Cwi-a-C-F-" out || { + # while on older unfixed we just notice needs_check + grep "Cwi-c-C---" out + sleep .1 + # And now cache is finaly Failed + check lv_attr_bit health $vg/$lv1 "F" +} +check lv_field $vg/$lv1 lv_health_status "failed" + +aux disable_dev "$dev1" + +# Check it is prompting for confirmation +not lvconvert --uncache $vg/$lv1 +# Check --yes is not enought to drop writethrough caching +not lvconvert --yes --uncache $vg/$lv1 +# --force needs --yes to drop when Check its prompting +not lvconvert --force --uncache $vg/$lv1 + +lvconvert --force --yes --uncache $vg/$lv1 + +not "$FSCK" -n "$DM_DEV_DIR/$vg/$lv1" + +aux enable_dev "$dev1" + +vgremove -ff $vg + +# FIXME - device should not be here +should not dmsetup remove ${vg}-cpool_cmeta-missing_0_0 +should not dmsetup remove ${vg}-cpool_cdata-missing_0_0 diff --git a/test/shell/lvconvert-repair-dmeventd.sh b/test/shell/lvconvert-repair-dmeventd.sh index 66e4cc8..9e0dd8c 100644 --- a/test/shell/lvconvert-repair-dmeventd.sh +++ b/test/shell/lvconvert-repair-dmeventd.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,19 +8,23 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest which mkfs.ext2 || skip +aux mirror_recovery_works || skip -aux prepare_vg 5 aux prepare_dmeventd +aux prepare_vg 5 -lvcreate -m 3 --ig -L 1 -n 4way $vg +lvcreate -aey --type mirror -m 3 --ignoremonitoring -L 1 -n 4way $vg lvchange --monitor y $vg/4way aux disable_dev "$dev2" "$dev4" -mkfs.ext2 $DM_DEV_DIR/$vg/4way +mkfs.ext2 "$DM_DEV_DIR/$vg/4way" sleep 10 # FIXME: need a "poll" utility, akin to "check" aux enable_dev "$dev2" "$dev4" check mirror $vg 4way diff --git a/test/shell/lvconvert-repair-mirror.sh b/test/shell/lvconvert-repair-mirror.sh new file mode 100644 index 0000000..a37dec9 --- /dev/null +++ b/test/shell/lvconvert-repair-mirror.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +MOUNT_DIR=mnt +MKFS=$(which mkfs.ext3) || skip + +cleanup_mounted_and_teardown() +{ + umount "$MOUNT_DIR" || true + aux teardown +} + +aux lvmconf 'allocation/mirror_logs_require_separate_pvs = 1' + +aux prepare_vg 5 + +################### Check lost mirror leg ################# +# +# NOTE: using --regionsize 1M has major impact on my box +# on read performance while mirror is synchronized +# with the default 512K - my C2D T61 reads just couple MB/s! +# +lvcreate -aey --type mirror -L10 --regionsize 1M -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3" +"$MKFS" "$DM_DEV_DIR/$vg/$lv1" +mkdir "$MOUNT_DIR" + +aux delay_dev "$dev2" 0 500 "$(get first_extent_sector "$dev2"):" +aux delay_dev "$dev4" 0 500 "$(get first_extent_sector "$dev4"):" +# +# Enforce syncronization +# ATM requires unmounted/unused LV?? +# +lvchange --yes --resync $vg/$lv1 +trap 'cleanup_mounted_and_teardown' EXIT +mount "$DM_DEV_DIR/$vg/$lv1" "$MOUNT_DIR" + +# run 'dd' operation during failure of 'mlog/mimage' device + +dd if=/dev/zero of=mnt/zero bs=4K count=100 conv=fdatasync 2>err & + +PERCENT=$(get lv_field $vg/$lv1 copy_percent) +PERCENT=${PERCENT%%\.*} # cut decimal +# and check less than 50% mirror is in sync (could be unusable delay_dev ?) +test "$PERCENT" -lt 50 || skip +#lvs -a -o+devices $vg + +#aux disable_dev "$dev3" +aux disable_dev "$dev2" + +lvconvert --yes --repair $vg/$lv1 +lvs -a $vg + +aux enable_dev "$dev2" + +wait +# dd MAY NOT HAVE produced any error message +not grep error err + +lvs -a -o+devices $vg +umount "$MOUNT_DIR" +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +aux enable_dev "$dev4" +lvremove -ff $vg diff --git a/test/shell/lvconvert-repair-policy.sh b/test/shell/lvconvert-repair-policy.sh index e595d34..b69658e 100644 --- a/test/shell/lvconvert-repair-policy.sh +++ b/test/shell/lvconvert-repair-policy.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,85 +8,92 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test + +. lib/inittest aux prepare_vg 4 -aux lvmconf 'allocation/maximise_cling = 0' -aux lvmconf 'allocation/mirror_logs_require_separate_pvs = 1' +aux lvmconf 'allocation/maximise_cling = 0' \ + 'allocation/mirror_logs_require_separate_pvs = 1' # 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() { +cleanup_() { vgreduce --removemissing $vg for d in "$@"; do aux enable_dev "$d"; done + # clear the outdated metadata on enabled devs before we can reuse them + vgck --updatemetadata $vg 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 + lvcreate -aey --type mirror -m 1 --ignoremonitoring -l 2 -n mirror $vg "$dev1" "$dev2" "$dev3:0" } -repair() { +repair_() { lvconvert --repair --use-policies --config "$1" $vg/mirror } -lvcreate -m 1 -L 1 -n mirror $vg +lvcreate -aey --type mirror -m 1 --ignoremonitoring -l 2 -n mirror $vg "$dev1" "$dev2" "$dev3:0" 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" }' +lvchange --partial -aey $vg/mirror +repair_ 'activation { mirror_image_fault_policy = "remove" }' check linear $vg mirror -cleanup "$dev1" +cleanup_ "$dev1" # Fail a leg of a mirror. # Expected result: Mirror (leg replaced, should retain log) aux disable_dev "$dev1" -repair 'activation { mirror_image_fault_policy = "replace" mirror_log_fault_policy = "remove" }' +repair_ 'activation { mirror_image_fault_policy = "replace" mirror_log_fault_policy = "remove" }' check mirror $vg mirror check active $vg mirror_mlog -cleanup "$dev1" +cleanup_ "$dev1" # Fail a leg of a mirror. # Expected result: Mirror (leg replaced) aux disable_dev "$dev1" -repair 'activation { mirror_image_fault_policy = "replace" }' +repair_ 'activation { mirror_image_fault_policy = "replace" }' check mirror $vg mirror check active $vg mirror_mlog -cleanup "$dev1" +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_image_fault_policy = "replace" }' +repair_ 'activation { mirror_image_fault_policy = "replace" }' check mirror $vg mirror check active $vg mirror_mlog -cleanup "$dev1" +not pvdisplay $vg +cleanup_ "$dev1" # Fail a leg of a mirror w/ no available spare # Expected result: linear # (or 2-way with leg/log overlap if alloc anywhere) aux disable_dev "$dev2" "$dev4" -repair 'activation { mirror_image_fault_policy = "replace" }' +repair_ 'activation { mirror_image_fault_policy = "replace" }' check mirror $vg mirror -not check lv_exists $vg mirror_mlog -cleanup "$dev2" "$dev4" +check lv_not_exists $vg mirror_mlog +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 +repair_ 'activation { mirror_image_fault_policy = "replace" }' $vg/mirror check mirror $vg mirror -not check lv_exists $vg mirror_mlog -cleanup "$dev3" "$dev4" +check lv_not_exists $vg mirror_mlog +cleanup_ "$dev3" "$dev4" # Fail the log device with a remove policy # Expected result: mirror w/ corelog -lvchange -a y $vg/mirror +lvchange -aey $vg/mirror aux disable_dev "$dev3" "$dev4" -repair 'activation { mirror_log_fault_policy = "remove" }' +repair_ 'activation { mirror_log_fault_policy = "remove" }' check mirror $vg mirror core -not check lv_exists $vg mirror_mlog -cleanup "$dev3" "$dev4" +check lv_not_exists $vg mirror_mlog +cleanup_ "$dev3" "$dev4" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-repair-raid-dmeventd.sh b/test/shell/lvconvert-repair-raid-dmeventd.sh new file mode 100644 index 0000000..5519c4e --- /dev/null +++ b/test/shell/lvconvert-repair-raid-dmeventd.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext3 || skip +aux have_raid 1 3 0 || skip + +aux lvmconf \ + 'activation/raid_fault_policy = "allocate"' + +aux prepare_dmeventd +aux prepare_vg 5 + +lvcreate -aey --type raid1 -m 3 --ignoremonitoring -L 1 -n 4way $vg +lvchange --monitor y $vg/4way +lvs -a -o all,lv_modules $vg +lvdisplay --maps $vg +aux wait_for_sync $vg 4way +aux disable_dev "$dev2" "$dev4" +mkfs.ext3 "$DM_DEV_DIR/$vg/4way" +sleep 5 # FIXME: need a "poll" utility, akin to "check" +aux enable_dev "$dev2" "$dev4" + +dmsetup table +dmsetup status +dmsetup info -c +vgremove -vvvv -ff $vg diff --git a/test/shell/lvconvert-repair-raid.sh b/test/shell/lvconvert-repair-raid.sh new file mode 100644 index 0000000..de0c9ba --- /dev/null +++ b/test/shell/lvconvert-repair-raid.sh @@ -0,0 +1,176 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013-2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 0 || skip +aux raid456_replace_works || skip + +aux lvmconf 'allocation/maximise_cling = 0' \ + 'allocation/mirror_logs_require_separate_pvs = 1' \ + 'activation/raid_fault_policy = "allocate"' + +aux prepare_vg 8 80 +get_devs + +offset=$(get first_extent_sector "$dev1") + +function delay +{ + for d in "${DEVICES[@]}"; do + aux delay_dev "$d" 0 $1 "$offset" + done +} + +# It's possible small raid arrays do have problems with reporting in-sync. +# So try bigger size +RAID_SIZE=32 + +# Fast sync and repair afterwards +delay 0 + +# RAID1 transient failure check +lvcreate --type raid1 -m 1 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" +aux wait_for_sync $vg $lv1 +# enforce replacing live rimage leg with error target +dmsetup remove -f $vg-${lv1}_rimage_1 || true +# let it notice there is problem +echo a > "$DM_DEV_DIR/$vg/$lv1" +check grep_dmsetup status $vg-$lv1 AD +lvconvert -y --repair $vg/$lv1 "$dev3" +lvs -a -o+devices $vg +aux wait_for_sync $vg $lv1 +# Raid should have fixed device +check grep_dmsetup status $vg-$lv1 AA +check lv_on $vg ${lv1}_rimage_1 "$dev3" +lvremove -ff $vg/$lv1 + + +# RAID1 dual-leg single replace after initial sync +lvcreate --type raid1 -m 1 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" +aux wait_for_sync $vg $lv1 +aux disable_dev "$dev2" +lvconvert -y --repair $vg/$lv1 +vgreduce --removemissing $vg +aux enable_dev "$dev2" +vgck --updatemetadata $vg +vgextend $vg "$dev2" +lvremove -ff $vg/$lv1 + +# Delayed sync to allow for repair during rebuild +delay 50 + +# RAID1 triple-leg single replace during initial sync +lvcreate --type raid1 -m 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" +aux disable_dev "$dev2" "$dev3" +# FIXME 2016/11/04 AGK: Disabled next line as it fails to guarantee it is not already in sync. +#not lvconvert -y --repair $vg/$lv1 +aux wait_for_sync $vg $lv1 +lvconvert -y --repair $vg/$lv1 +vgreduce --removemissing $vg +aux enable_dev "$dev2" "$dev3" +vgck --updatemetadata $vg +vgextend $vg "$dev2" "$dev3" +lvremove -ff $vg/$lv1 + + +# Larger RAID size possible for striped RAID +RAID_SIZE=64 + +# Fast sync and repair afterwards +delay 0 +# RAID5 single replace after initial sync +lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" +aux wait_for_sync $vg $lv1 +aux disable_dev "$dev3" +vgreduce --removemissing -f $vg +lvconvert -y --repair $vg/$lv1 +aux enable_dev "$dev3" +vgck --updatemetadata $vg +pvcreate -yff "$dev3" +vgextend $vg "$dev3" +lvremove -ff $vg/$lv1 + +# Delayed sync to allow for repair during rebuild +delay 60 + +# RAID5 single replace during initial sync +lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" +aux disable_dev "$dev3" +# FIXME: there is quite big sleep on several 'status' read retries +# so over 3sec - it may actually finish full sync +# Use 'should' for this test result. +should not lvconvert -y --repair $vg/$lv1 +aux wait_for_sync $vg $lv1 +lvconvert -y --repair $vg/$lv1 +vgreduce --removemissing $vg +aux enable_dev "$dev3" +vgck --updatemetadata $vg +vgextend $vg "$dev3" +lvremove -ff $vg/$lv1 + +# Fast sync and repair afterwards +delay 0 + +# RAID6 double replace after initial sync +lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \ + "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +aux wait_for_sync $vg $lv1 +aux disable_dev "$dev4" "$dev5" +lvconvert -y --repair $vg/$lv1 +vgreduce --removemissing $vg +aux enable_dev "$dev4" "$dev5" +vgck --updatemetadata $vg +vgextend $vg "$dev4" "$dev5" +lvremove -ff $vg/$lv1 + +# Delayed sync to allow for repair during rebuild +delay 50 + +# RAID6 single replace after initial sync +lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \ + "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +aux disable_dev "$dev4" +not lvconvert -y --repair $vg/$lv1 +delay 0 # Fast sync and repair afterwards +aux disable_dev "$dev4" # Need to disable again after changing delay +aux wait_for_sync $vg $lv1 +lvconvert -y --repair $vg/$lv1 +vgreduce --removemissing $vg +aux enable_dev "$dev4" +vgck --updatemetadata $vg +vgextend $vg "$dev4" +lvremove -ff $vg/$lv1 + +# Delayed sync to allow for repair during rebuild +delay 50 + +# RAID10 single replace after initial sync +lvcreate --type raid10 -m 1 -i 2 -L $RAID_SIZE -n $lv1 $vg \ + "$dev1" "$dev2" "$dev3" "$dev4" +aux disable_dev "$dev4" +not lvconvert -y --repair $vg/$lv1 +delay 0 # Fast sync and repair afterwards +aux disable_dev "$dev4" # Need to disable again after changing delay +aux disable_dev "$dev1" +aux wait_for_sync $vg $lv1 +lvconvert -y --repair $vg/$lv1 +vgreduce --removemissing $vg +aux enable_dev "$dev4" +vgck --updatemetadata $vg +vgextend $vg "$dev4" +lvremove -ff $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/lvconvert-repair-replace.sh b/test/shell/lvconvert-repair-replace.sh index 974628a..0233e19 100644 --- a/test/shell/lvconvert-repair-replace.sh +++ b/test/shell/lvconvert-repair-replace.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008,2018 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 @@ -7,86 +8,96 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + -. lib/test +. lib/inittest aux prepare_vg 6 -aux lvmconf 'allocation/maximise_cling = 0' -aux lvmconf 'allocation/mirror_logs_require_separate_pvs = 1' + +aux lvmconf 'global/support_mirrored_mirror_log = 1' \ + 'allocation/maximise_cling = 0' \ + 'allocation/mirror_logs_require_separate_pvs = 1' # 3-way, disk log # multiple failures, full replace -lvcreate --mirrorlog disk -m 2 --ig -L 1 -n 3way $vg "$dev1" "$dev2" "$dev3" "$dev4":0-1 +lvcreate -aey --mirrorlog disk --type mirror -m 2 --ignoremonitoring --nosync -L 1 -n 3way $vg "$dev1" "$dev2" "$dev3" "$dev4":0-1 aux disable_dev "$dev1" "$dev2" -echo y | lvconvert --repair $vg/3way 2>&1 | tee 3way.out +lvconvert -y --repair $vg/3way 2>&1 | tee 3way.out lvs -a -o +devices $vg | not grep unknown not grep "WARNING: Failed" 3way.out vgreduce --removemissing $vg check mirror $vg 3way aux enable_dev "$dev1" "$dev2" - -vgremove -ff $vg; vgcreate -c n $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" - -# 2-way, mirrored log -# Double log failure, full replace -lvcreate --mirrorlog mirrored -m 1 --ig -L 1 -n 2way $vg \ - "$dev1" "$dev2" "$dev3":0 "$dev4":0 -aux disable_dev "$dev3" "$dev4" -echo y | lvconvert --repair $vg/2way 2>&1 | tee 2way.out -lvs -a -o +devices $vg | not grep unknown -not grep "WARNING: Failed" 2way.out -vgreduce --removemissing $vg -check mirror $vg 2way -aux enable_dev "$dev3" "$dev4" - -vgremove -ff $vg; vgcreate -c n $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" - -# 3-way, mirrored log -# Single log failure, replace -lvcreate --mirrorlog mirrored -m 2 --ig -L 1 -n 3way $vg \ - "$dev1" "$dev2" "$dev3" "$dev4":0 "$dev5":0 -aux disable_dev "$dev4" -echo y | lvconvert --repair $vg/3way 2>&1 | tee 3way.out -lvs -a -o +devices $vg | not grep unknown -not grep "WARNING: Failed" 3way.out -vgreduce --removemissing $vg -check mirror $vg 3way -aux enable_dev "$dev4" - -vgremove -ff $vg; vgcreate -c n $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +vgremove -ff $vg # 3-way, disk log # multiple failures, partial replace -lvcreate --mirrorlog disk -m 2 --ig -L 1 -n 3way $vg "$dev1" "$dev2" "$dev3" "$dev4" +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lvcreate -aey --mirrorlog disk --type mirror -m 2 --ignoremonitoring --nosync -L 1 -n 3way $vg "$dev1" "$dev2" "$dev3" "$dev4" aux disable_dev "$dev1" "$dev2" -echo y | lvconvert --repair $vg/3way 2>&1 | tee 3way.out +lvconvert -y --repair $vg/3way 2>&1 | tee 3way.out grep "WARNING: Failed" 3way.out lvs -a -o +devices $vg | not grep unknown vgreduce --removemissing $vg check mirror $vg 3way aux enable_dev "$dev1" "$dev2" -lvchange -a n $vg/3way - -vgremove -ff $vg; vgcreate -c n $vg "$dev1" "$dev2" "$dev3" +vgremove -ff $vg -lvcreate --mirrorlog disk -m 1 --ig -L 1 -n 2way $vg "$dev1" "$dev2" "$dev3" +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" +lvcreate -aey --mirrorlog disk --type mirror -m 1 --ignoremonitoring --nosync -l 1 -n 2way $vg "$dev1" "$dev2" "$dev3" aux disable_dev "$dev1" -echo y | lvconvert --repair $vg/2way 2>&1 | tee 2way.out +lvconvert -y --repair $vg/2way 2>&1 | tee 2way.out grep "WARNING: Failed" 2way.out lvs -a -o +devices $vg | not grep unknown vgreduce --removemissing $vg check mirror $vg 2way aux enable_dev "$dev1" "$dev2" -lvchange -a n $vg/2way +vgremove -ff $vg + +# FIXME - exclusive activation for mirrors should work here +# conversion of inactive cluster logs is also unsupported +test -e LOCAL_CLVMD && exit 0 -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 +# Replacement should fail, but convert should succeed (switch to corelog) +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" +lvcreate -aey --type mirror -m 2 --ignoremonitoring -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 +lvconvert -y --repair $vg/mirror2 check mirror $vg mirror2 vgs $vg +vgremove -ff $vg + +if aux kernel_at_least 3 0 0; then + # 2-way, mirrored log + # Double log failure, full replace + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" + lvcreate -aey --mirrorlog mirrored --type mirror -m 1 --ignoremonitoring --nosync -L 1 -n 2way $vg \ + "$dev1" "$dev2" "$dev3":0 "$dev4":0 + aux disable_dev "$dev3" "$dev4" + lvconvert -y --repair $vg/2way 2>&1 | tee 2way.out + lvs -a -o +devices $vg | not grep unknown + not grep "WARNING: Failed" 2way.out + vgreduce --removemissing $vg + check mirror $vg 2way + aux enable_dev "$dev3" "$dev4" + vgremove -ff $vg +fi + +# 3-way, mirrored log +# Single log failure, replace +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" +lvcreate -aey --mirrorlog mirrored --type mirror -m 2 --ignoremonitoring --nosync -L 1 -n 3way $vg \ + "$dev1" "$dev2" "$dev3" "$dev4":0 "$dev5":0 +aux disable_dev "$dev4" +lvconvert -y --repair $vg/3way 2>&1 | tee 3way.out +lvs -a -o +devices $vg | not grep unknown +not grep "WARNING: Failed" 3way.out +vgreduce --removemissing $vg +check mirror $vg 3way +aux enable_dev "$dev4" +vgremove -ff $vg diff --git a/test/shell/lvconvert-repair-snapshot.sh b/test/shell/lvconvert-repair-snapshot.sh index 786b950..0e9b2a3 100644 --- a/test/shell/lvconvert-repair-snapshot.sh +++ b/test/shell/lvconvert-repair-snapshot.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,15 +8,18 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_vg 5 -aux lvmconf 'allocation/maximise_cling = 0' -aux lvmconf 'allocation/mirror_logs_require_separate_pvs = 1' +aux lvmconf 'allocation/maximise_cling = 0' \ + 'allocation/mirror_logs_require_separate_pvs = 1' -lvcreate -m 3 --ig -L 2M -n 4way $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5":0 +lvcreate -aey --type mirror -m 3 --ignoremonitoring -L 2M -n 4way $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5":0 lvcreate -s $vg/4way -L 2M -n snap aux disable_dev "$dev2" "$dev4" @@ -25,3 +29,6 @@ vgreduce --removemissing $vg aux enable_dev "$dev2" "$dev4" lvs -a -o +devices $vg check mirror $vg 4way "$dev5" + +vgchange -an $vg +vgremove -ff $vg diff --git a/test/shell/lvconvert-repair-thin-raid.sh b/test/shell/lvconvert-repair-thin-raid.sh new file mode 100644 index 0000000..b97c5b4 --- /dev/null +++ b/test/shell/lvconvert-repair-thin-raid.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test repairing of broken thin pool on raid + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_thin 1 0 0 || skip +aux have_raid 1 4 0 || skip + +# +# To continue this test - we need real tools available +# When they are not present mark test as skipped, but still +# let proceed initial part which should work even without tools +# +aux have_tool_at_least "$LVM_TEST_THIN_CHECK_CMD" 0 3 1 || skip +aux have_tool_at_least "$LVM_TEST_THIN_DUMP_CMD" 0 3 1 || skip +aux have_tool_at_least "$LVM_TEST_THIN_REPAIR_CMD" 0 3 1 || skip + +# +# Main +# + +aux prepare_vg 4 + +lvcreate --type raid1 -L1 -n pool $vg +lvcreate --type raid1 -L2 -n meta $vg +# raid _tdata & _tmeta +lvconvert -y --thinpool $vg/pool --poolmetadata $vg/meta + +lvcreate -V1G $vg/pool + +# Pool has to be inactive (ATM) for repair +fail lvconvert -y --repair $vg/pool "$dev3" + +lvchange -an $vg + +check lv_field $vg/pool_tmeta lv_role "private,thin,pool,metadata" + +lvconvert -y --repair $vg/pool "$dev3" + +lvs -a -o+devices,seg_pe_ranges,role,layout $vg +check lv_field $vg/pool_meta0 lv_role "public" +check lv_field $vg/pool_meta0 lv_layout "raid,raid1" +check lv_field $vg/pool_tmeta lv_layout "linear" +check lv_on $vg pool_tmeta "$dev1" + +# Hmm name is generated in order +SPARE=$(lvs --noheadings -a --select "name=~_pmspare" -o name $vg) +SPARE=${SPARE##*[} +SPARE=${SPARE%%]*} + +check lv_on $vg $SPARE "$dev3" + +lvchange -ay $vg + +vgremove -ff $vg diff --git a/test/shell/lvconvert-repair-thin.sh b/test/shell/lvconvert-repair-thin.sh new file mode 100644 index 0000000..0fb0d76 --- /dev/null +++ b/test/shell/lvconvert-repair-thin.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test repairing of broken thin pool metadata + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext2 || skip + +# +# Main +# +aux have_thin 1 0 0 || skip + +aux prepare_vg 4 + +# Create LV +# TODO: investigate problem with --zero n and my repairable damage trick +#lvcreate -T -L20 -V10 -n $lv1 $vg/pool --discards ignore --zero n --chunksize 128 "$dev1" "$dev2" +lvcreate -T -L20 -V10 -n $lv1 $vg/pool --chunksize 128 --discards ignore "$dev1" "$dev2" +lvcreate -T -V10 -n $lv2 $vg/pool + +mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1" +mkfs.ext2 "$DM_DEV_DIR/$vg/$lv2" + +lvcreate -L20 -n repair $vg +lvcreate -L2 -n fixed $vg + +lvs -a -o+seg_pe_ranges $vg +#aux error_dev "$dev2" 2050:1 + +lvchange -an $vg/$lv2 $vg/$lv1 $vg/pool $vg/repair + +# Manual repair steps: +# Test swapping - swap out thin-pool's metadata with our repair volume +lvconvert -y -f --poolmetadata $vg/repair --thinpool $vg/pool + +lvchange -ay $vg/repair + +# +# To continue this test - we need real tools available +# When they are not present mark test as skipped, but still +# let proceed initial part which should work even without tools +# +aux have_tool_at_least "$LVM_TEST_THIN_CHECK_CMD" 0 3 1 || skip +aux have_tool_at_least "$LVM_TEST_THIN_DUMP_CMD" 0 3 1 || skip +aux have_tool_at_least "$LVM_TEST_THIN_REPAIR_CMD" 0 3 1 || skip + +# Make some 'repairable' damage?? +dd if=/dev/zero of="$DM_DEV_DIR/$vg/repair" bs=1 seek=40960 count=1 + +# Investige how to make such damage across different versions of thin-pool target. +should not "$LVM_TEST_THIN_CHECK_CMD" "$DM_DEV_DIR/$vg/repair" + +should not "$LVM_TEST_THIN_DUMP_CMD" "$DM_DEV_DIR/$vg/repair" | tee dump + +"$LVM_TEST_THIN_REPAIR_CMD" -i "$DM_DEV_DIR/$vg/repair" -o "$DM_DEV_DIR/$vg/fixed" + +"$LVM_TEST_THIN_DUMP_CMD" --repair "$DM_DEV_DIR/$vg/repair" | tee repaired_xml + +"$LVM_TEST_THIN_CHECK_CMD" "$DM_DEV_DIR/$vg/fixed" + +lvchange -an $vg + +# Swap repaired metadata back +lvconvert -y -f --poolmetadata $vg/fixed --thinpool $vg/pool + +# Check pool still preserves its original settings +check lv_field $vg/pool chunksize "128.00k" +check lv_field $vg/pool discards "ignore" +check lv_field $vg/pool zero "zero" + +# Activate pool - this should now work +vgchange -ay $vg + +vgchange -an $vg + +# Put back 'broken' metadata +lvconvert -y -f --poolmetadata $vg/repair --thinpool $vg/pool + +# Check --repair usage +lvconvert -v --repair $vg/pool + +# Check repaired pool could be activated +lvchange -ay $vg/pool + +vgchange -an $vg + +# Restore damaged metadata +lvconvert -y -f --poolmetadata $vg/pool_meta0 --thinpool $vg/pool + +# Check lvremove -ff works even with damaged pool +lvremove -ff $vg diff --git a/test/shell/lvconvert-repair-transient-dmeventd.sh b/test/shell/lvconvert-repair-transient-dmeventd.sh index ac687eb..6679dd6 100644 --- a/test/shell/lvconvert-repair-transient-dmeventd.sh +++ b/test/shell/lvconvert-repair-transient-dmeventd.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,23 +8,30 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -. lib/test -aux prepare_vg 5 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + aux prepare_dmeventd +aux mirror_recovery_works || skip +aux prepare_vg 5 -lvcreate -m 3 --ig -L 1 -n 4way $vg +lvcreate -aey --type mirror -m 3 --ignoremonitoring -L 1 -n 4way $vg lvchange --monitor y $vg/4way aux disable_dev "$dev2" "$dev4" -mkfs.ext3 $DM_DEV_DIR/$vg/4way +mkfs.ext3 "$DM_DEV_DIR/$vg/4way" aux enable_dev "$dev2" "$dev4" sleep 3 -lvs -a -o +devices $vg | not grep unknown +lvs -a -o +devices $vg | tee out +not grep unknown out check mirror $vg 4way check mirror_legs $vg 4way 2 -lvs -a -o +devices $vg | not grep mimage_1 -lvs -a -o +devices $vg | not grep mimage_3 +lvs -a -o +devices $vg | tee out +not grep mimage_1 out +lvs -a -o +devices $vg | tee out +not grep mimage_3 out vgremove -f $vg diff --git a/test/shell/lvconvert-repair-transient.sh b/test/shell/lvconvert-repair-transient.sh index beacf89..aa697f9 100644 --- a/test/shell/lvconvert-repair-transient.sh +++ b/test/shell/lvconvert-repair-transient.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,19 +8,29 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest +aux mirror_recovery_works || skip aux prepare_vg 5 -lvcreate -m 3 --ig -L 1 -n 4way $vg -aux disable_dev "$dev2" "$dev4" -mkfs.ext3 $DM_DEV_DIR/$vg/4way & +# ordinary mirrors + +lvcreate -aey --type mirror -m 3 --ignoremonitoring -L 1 -n 4way $vg +aux wait_for_sync $vg 4way +aux disable_dev --error --silent "$dev2" "$dev4" +mkfs.ext3 "$DM_DEV_DIR/$vg/4way" & sleep 1 -aux enable_dev "$dev2" "$dev4" +dmsetup status echo n | lvconvert --repair $vg/4way 2>&1 | tee 4way.out -lvs -a -o +devices | not grep unknown +aux enable_dev --silent "$dev2" "$dev4" + +lvs -a -o +devices $vg | tee out +not grep unknown out vgreduce --removemissing $vg check mirror $vg 4way lvchange -a n $vg/4way diff --git a/test/shell/lvconvert-repair.sh b/test/shell/lvconvert-repair.sh index 51bc9de..0d0231e 100644 --- a/test/shell/lvconvert-repair.sh +++ b/test/shell/lvconvert-repair.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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 @@ -7,24 +8,37 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +. lib/inittest -. lib/test +aux lvmconf "global/support_mirrored_mirror_log=1" recreate_vg_() { vgremove -ff $vg - vgcreate -c n $vg $(cat DEVICES) + vgcreate $SHARED "$vg" "$@" "${DEVICES[@]}" +} + +_check_mlog() +{ + lvs -a -o +devices $vg | tee out + not grep unknown out + not grep mlog out + dmsetup ls | grep $PREFIX | tee out + not grep mlog out } -aux lvmconf 'allocation/maximise_cling = 0' -aux lvmconf 'allocation/mirror_logs_require_separate_pvs = 1' +aux lvmconf "allocation/maximise_cling = 0" \ + "allocation/mirror_logs_require_separate_pvs = 1" # fail multiple devices # 4-way, disk log => 2-way, disk log aux prepare_vg 8 -lvcreate -m 3 --ig -L 1 -n 4way $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5":0 +get_devs + +lvcreate -aey --type mirror -m 3 --ignoremonitoring -L 1 -n 4way $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5":0 aux disable_dev "$dev2" "$dev4" echo n | lvconvert --repair $vg/4way 2>&1 | tee 4way.out lvs -a -o +devices $vg | not grep unknown @@ -34,13 +48,11 @@ check mirror $vg 4way "$dev5" # 3-way, disk log => linear recreate_vg_ -lvcreate -m 2 --ig -L 1 -n 3way $vg +lvcreate -aey --type mirror -m 2 --ignoremonitoring -L 1 -n 3way $vg aux disable_dev "$dev1" "$dev2" echo n | lvconvert --repair $vg/3way check linear $vg 3way -lvs -a -o +devices $vg | not grep unknown -lvs -a -o +devices $vg | not grep mlog -dmsetup ls | grep $PREFIX | not grep mlog +_check_mlog vgreduce --removemissing $vg aux enable_dev "$dev1" "$dev2" check linear $vg 3way @@ -49,37 +61,32 @@ check linear $vg 3way # 3-way, disk log => 3-way, core log recreate_vg_ -lvcreate -m 2 --ig -L 1 -n 3way $vg "$dev1" "$dev2" "$dev3" "$dev4":0 +lvcreate -aey --type mirror -m 2 --ignoremonitoring -L 1 -n 3way $vg "$dev1" "$dev2" "$dev3" "$dev4":0 aux disable_dev "$dev4" echo n | lvconvert --repair $vg/3way check mirror $vg 3way core -lvs -a -o +devices $vg | not grep unknown -lvs -a -o +devices $vg | not grep mlog -dmsetup ls | grep $PREFIX | not grep mlog +_check_mlog vgreduce --removemissing $vg aux enable_dev "$dev4" # 3-way, mirrored log => 3-way, core log recreate_vg_ -lvcreate -m 2 --mirrorlog mirrored --ig -L 1 -n 3way $vg \ +lvcreate -aey --type mirror -m 2 --mirrorlog mirrored --ignoremonitoring -L 1 -n 3way $vg \ "$dev1" "$dev2" "$dev3" "$dev4":0 "$dev5":0 aux disable_dev "$dev4" "$dev5" echo n | lvconvert --repair $vg/3way check mirror $vg 3way core -lvs -a -o +devices $vg | not grep unknown -lvs -a -o +devices $vg | not grep mlog -dmsetup ls | grep $PREFIX | not grep mlog +_check_mlog vgreduce --removemissing $vg aux enable_dev "$dev4" "$dev5" # 2-way, disk log => 2-way, core log recreate_vg_ -lvcreate -m 1 --ig -L 1 -n 2way $vg "$dev1" "$dev2" "$dev3":0 +lvcreate -aey --type mirror -m 1 --ignoremonitoring -L 1 -n 2way $vg "$dev1" "$dev2" "$dev3":0 aux disable_dev "$dev3" echo n | lvconvert --repair $vg/2way check mirror $vg 2way core -lvs -a -o +devices $vg | not grep unknown -lvs -a -o +devices $vg | not grep mlog +_check_mlog vgreduce --removemissing $vg aux enable_dev "$dev3" @@ -88,53 +95,34 @@ aux enable_dev "$dev3" recreate_vg_ vgreduce $vg "$dev4" -lvcreate -m 1 --ig -L 1 -n mirror $vg +lvcreate -aey --type mirror -m 1 --ignoremonitoring -L 1 -n mirror $vg lvchange -a n $vg/mirror vgextend $vg "$dev4" aux disable_dev "$dev1" -lvchange --partial -a y $vg/mirror +lvchange --partial -aey $vg/mirror not vgreduce -v --removemissing $vg lvconvert -y --repair $vg/mirror vgreduce --removemissing $vg aux enable_dev "$dev1" +# clear the outdated dev before we can reuse it +vgck --updatemetadata $vg vgextend $vg "$dev1" aux disable_dev "$dev2" lvconvert -y --repair $vg/mirror vgreduce --removemissing $vg aux enable_dev "$dev2" +# clear the outdated dev before we can reuse it +vgck --updatemetadata $vg vgextend $vg "$dev2" aux disable_dev "$dev3" lvconvert -y --repair $vg/mirror vgreduce --removemissing $vg aux enable_dev "$dev3" +# clear the outdated dev before we can reuse it +vgck --updatemetadata $vg vgextend $vg "$dev3" -lvremove -ff $vg - -if aux target_at_least dm-raid 1 1 0; then - # RAID5 single replace - lvcreate --type raid5 -i 2 -l 2 -n $lv1 $vg "$dev1" "$dev2" "$dev3" - aux wait_for_sync $vg $lv1 - aux disable_dev "$dev3" - lvconvert -y --repair $vg/$lv1 - vgreduce --removemissing $vg - aux enable_dev "$dev3" - vgextend $vg "$dev3" - lvremove -ff $vg - - # RAID6 double replace - lvcreate --type raid5 -i 3 -l 2 -n $lv1 $vg \ - "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" - aux wait_for_sync $vg $lv1 - aux disable_dev "$dev4" "$dev5" - lvconvert -y --repair $vg/$lv1 - vgreduce --removemissing $vg - aux enable_dev "$dev4" - aux enable_dev "$dev5" - vgextend $vg "$dev4" "$dev5" - lvremove -ff $vg -fi vgremove -ff $vg diff --git a/test/shell/lvconvert-snapshot-cache.sh b/test/shell/lvconvert-snapshot-cache.sh new file mode 100644 index 0000000..9cb383a --- /dev/null +++ b/test/shell/lvconvert-snapshot-cache.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test various supported conversion of snapshot with cache + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_cache 1 3 0 || skip + +aux prepare_vg 1 + +vgchange -s 16k $vg + +lvcreate -L1 -n cow $vg + +# Thin and snapshot conversion +lvcreate -aey -L1 -n ch $vg +lvcreate -H -L1 -n cpool $vg/ch + +# Cannot create snapshot of cpool +not lvcreate -s -L1 $vg/cpool_cpool 2>&1 | tee err +grep "not supported" err + +# Cannot create snapshot of cpool's meta +not lvcreate -s -L1 $vg/cpool_cpool_cmeta 2>&1 | tee err +grep "not supported" err + +# Cannot create snapshot of cpool's data +not lvcreate -s -L1 $vg/cpool_cpool_cdata 2>&1 | tee err +grep "not supported" err + +# Cannot use cache-type as COW +not lvconvert --yes --type snapshot $vg/cow $vg/ch 2>&1 | tee err +grep "not accept" err + +not lvconvert --yes --type snapshot $vg/cow $vg/cpool_cpool 2>&1 | tee err +grep "not accept" err + +not lvconvert --yes --type snapshot $vg/cow $vg/cpool_cpool_cdata 2>&1 | tee err +grep "lv_is_visible" err + +not lvconvert --yes --type snapshot $vg/cow $vg/cpool_cpool_cmeta 2>&1 | tee err +grep "lv_is_visible" err + +# Cannot use thin-pool, _tdata, _tmeta as origin +not lvconvert --yes --type snapshot $vg/cpool_cpool $vg/cow 2>&1 | tee err +grep "not supported" err + +not lvconvert --yes --type snapshot $vg/cpool_cpool_cdata $vg/cow 2>&1 | tee err +grep "not supported" err + +not lvconvert --yes --type snapshot $vg/cpool_cpool_cmeta $vg/cow 2>&1 | tee err +grep "not supported" err + +lvconvert --yes -s $vg/ch $vg/cow + +check lv_field $vg/ch segtype cache +check lv_field $vg/cow segtype linear +check lv_attr_bit type $vg/cow "s" +check lv_attr_bit type $vg/ch "o" + +lvs -a -o+lv_role,lv_layout $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-snapshot-mirror.sh b/test/shell/lvconvert-snapshot-mirror.sh new file mode 100644 index 0000000..22f40f7 --- /dev/null +++ b/test/shell/lvconvert-snapshot-mirror.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test various supported conversion of snapshot with mirrors + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 3 + +vgchange -s 16k $vg + +lvcreate -L1 -n cow $vg + +# Mirror and snapshot conversion +lvcreate -aye --type mirror -L1 -m1 -n mir $vg + +# Cannot create snapshot of mirror leg +not lvcreate -s -L1 $vg/mir_mimage_0 2>&1 | tee err +grep "not supported" err + +# cannot use 'mirror' as COW +not lvconvert --yes --type snapshot $vg/cow $vg/mir 2>&1 | tee err +grep "not accept" err + +not lvconvert --yes --type snapshot $vg/cow $vg/mir_mimage_0 2>&1 | tee err +grep "lv_is_visible" err + +not lvconvert --yes --type snapshot $vg/cow $vg/mir_mlog 2>&1 | tee err +grep "lv_is_visible" err + +# cannot use _mimage +not lvconvert --yes --type snapshot $vg/mir_mimage_0 $vg/cow 2>&1 | tee err +grep "not supported" err + +# cannot use _mlog +not lvconvert --yes --type snapshot $vg/mir_mlog $vg/cow 2>&1 | tee err +grep "not supported" err + +lvconvert --yes -s $vg/mir $vg/cow + +check lv_field $vg/mir segtype mirror +check lv_field $vg/cow segtype linear +check lv_attr_bit type $vg/cow "s" +check lv_attr_bit type $vg/mir "o" + +lvs -a -o+lv_role,lv_layout $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-snapshot-raid.sh b/test/shell/lvconvert-snapshot-raid.sh new file mode 100644 index 0000000..8deb60f --- /dev/null +++ b/test/shell/lvconvert-snapshot-raid.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test various supported conversion of snapshot with raid + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 0 || skip + +aux prepare_vg 3 + +vgchange -s 16k $vg + +lvcreate -L1 -n cow $vg + +# Raid and snapshot conversion +lvcreate --type raid1 -L1 -m1 -n rd $vg + +# Cannot create snapshot of raid leg +not lvcreate -s -L1 $vg/rd_rimage_0 2>&1 | tee err +grep "not supported" err + +# Cannot use raid-type as COW +not lvconvert --yes --type snapshot $vg/cow $vg/rd 2>&1 | tee err +grep "not accept" err + +not lvconvert --yes --type snapshot $vg/cow $vg/rd_rimage_0 2>&1 | tee err +grep "lv_is_visible" err + +not lvconvert --yes --type snapshot $vg/cow $vg/rd_rmeta_0 2>&1 | tee err +grep "lv_is_visible" err + +# Cannot use _rimage +not lvconvert --yes --type snapshot $vg/rd_rimage_0 $vg/cow 2>&1 | tee err +grep "not supported" err + +# Cannot use _rmeta +not lvconvert --yes --type snapshot $vg/rd_rmeta_0 $vg/cow 2>&1 | tee err +grep "not supported" err + +lvconvert --yes -s $vg/rd $vg/cow + +check lv_field $vg/rd segtype raid1 +check lv_field $vg/cow segtype linear +check lv_attr_bit type $vg/cow "s" +check lv_attr_bit type $vg/rd "o" + +lvs -a -o+lv_role,lv_layout $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-snapshot-thin.sh b/test/shell/lvconvert-snapshot-thin.sh new file mode 100644 index 0000000..cc4dade --- /dev/null +++ b/test/shell/lvconvert-snapshot-thin.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test various supported conversion of snapshot with raid + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip + +aux prepare_vg 1 + +vgchange -s 16k $vg + +lvcreate -L1 -n cow $vg + +# Thin and snapshot conversion +lvcreate -T -L1 -V10 -n th $vg/pool +eval "$(lvs -S 'name=~_pmspare' -a -o name --config 'report/mark_hidden_devices=0' --noheading --nameprefixes $vg)" + +# Cannot create snapshot of pool's meta +not lvcreate -s -L1 $vg/pool_tmeta 2>&1 | tee err +grep "not supported" err + +# Cannot create snapshot of pool's data +not lvcreate -s -L1 $vg/pool_tdata 2>&1 | tee err +grep "not supported" err + +# Cannot use thin-type as COW +not lvconvert --yes --type snapshot $vg/cow $vg/th 2>&1 | tee err +grep "not accept" err + +not lvconvert --yes --type snapshot $vg/cow $vg/pool 2>&1 | tee err +grep "not accept" err + +not lvconvert --yes --type snapshot $vg/cow $vg/$LVM2_LV_NAME 2>&1 | tee err +grep "lv_is_visible" err + +not lvconvert --yes --type snapshot $vg/cow $vg/pool_tdata 2>&1 | tee err +grep "lv_is_visible" err + +not lvconvert --yes --type snapshot $vg/cow $vg/pool_tmeta 2>&1 | tee err +grep "lv_is_visible" err + +# Cannot use thin-pool, _tdata, _tmeta as origin +not lvconvert --yes --type snapshot $vg/pool $vg/cow 2>&1 | tee err +grep "not supported" err + +not lvconvert --yes --type snapshot $vg/$LVM2_LV_NAME $vg/cow 2>&1 | tee err +grep "not supported" err + +not lvconvert --yes --type snapshot $vg/pool_tdata $vg/cow 2>&1 | tee err +grep "not supported" err + +not lvconvert --yes --type snapshot $vg/pool_tmeta $vg/cow 2>&1 | tee err +grep "not supported" err + +lvconvert --yes -s $vg/th $vg/cow + +check lv_field $vg/th segtype thin +check lv_field $vg/cow segtype linear +check lv_attr_bit type $vg/cow "s" +check lv_attr_bit type $vg/th "o" + +lvs -a -o+lv_role,lv_layout $vg + +vgremove -f $vg diff --git a/test/shell/lvconvert-snapshot.sh b/test/shell/lvconvert-snapshot.sh new file mode 100644 index 0000000..9a32776 --- /dev/null +++ b/test/shell/lvconvert-snapshot.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test various supported conversion of snapshot + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_pvs 2 +get_devs + +vgcreate -s 4k "$vg" "${DEVICES[@]}" + +lvcreate --type snapshot -V50 -L1 -n $lv1 -s $vg + +lvcreate -aey -L1 -n $lv2 $vg +lvcreate -L1 -s -n $lv3 $vg/$lv2 + +lvcreate -l1 -n $lv4 $vg +lvcreate -L1 -n $lv5 $vg +lvcreate -L1 -n $lv6 $vg + +not lvconvert -s $vg/$lv1 $vg/not_exist + +# Can't convert to snapshot of origin +not lvconvert -s $vg/$lv1 $vg/$lv2 +not lvconvert -s $vg/$lv2 $vg/$lv1 +not lvconvert -s $vg/$lv5 $vg/$lv1 + +not lvconvert -s $vg/$lv5 $vg/$lv2 +not lvconvert -s $vg/$lv5 $vg/$lv3 + +# Can't be itself +not lvconvert -s $vg/$lv1 $vg/$lv1 +not lvconvert -s $vg/$lv2 $vg/$lv2 + +# Can't convert snapshot to snapshot +not lvconvert -s $vg/$lv1 $vg/$lv3 +not lvconvert -s $vg/$lv2 $vg/$lv3 + +# Can't make a real LV snapshot of virtual 'zero' snapshot +not lvconvert -s $vg/$lv1 $vg/$lv4 + +# Check minimum size +not lvconvert -s $vg/$lv2 $vg/$lv4 2>&1 | tee err +grep "smaller" err + +# This should pass +lvconvert --yes -s $vg/$lv2 $vg/$lv5 +lvconvert --yes --type snapshot $vg/$lv2 $vg/$lv6 + +vgremove -f $vg + +# FIXME: older stripe target can't handle 1K chunks +vgcreate -s 4k "$vg" "${DEVICES[@]}" +lvcreate -aey -L1 -n $lv2 $vg +lvcreate -L1 -i2 -n $lv7 $vg + +# Striped LV is also supported +lvconvert --yes --snapshot $vg/$lv2 $vg/$lv7 + +vgremove -f $vg diff --git a/test/shell/lvconvert-striped-raid0.sh b/test/shell/lvconvert-striped-raid0.sh new file mode 100644 index 0000000..5cfb792 --- /dev/null +++ b/test/shell/lvconvert-striped-raid0.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 7 0 || skip + +aux prepare_vg 3 16 + +lvcreate -aey --type striped -i 3 -l3 -n $lv $vg +lvconvert -y --type raid0_meta $vg/$lv +check lv_field $vg/$lv segtype "raid0_meta" +vgremove -ff $vg diff --git a/test/shell/lvconvert-thin-external-cache.sh b/test/shell/lvconvert-thin-external-cache.sh new file mode 100644 index 0000000..a8b95b2 --- /dev/null +++ b/test/shell/lvconvert-thin-external-cache.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test conversion cached LV to thin with cached external origin + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +which mkfs.ext2 || skip +which fsck || skip + +# +# Main +# +aux have_thin 1 5 0 || skip +aux have_cache 1 7 0 || skip + +aux prepare_vg 2 64 + +# Test will use thin-pool +lvcreate -L10 -T $vg/tpool + +lvcreate -aey -L20 -n $lv1 $vg + + +mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1" +mkdir mnt +mount "$DM_DEV_DIR/$vg/$lv1" mnt +touch mnt/test + +# Prepared cached LV - first in 'writeback' mode +lvcreate -H --cachemode writeback -L10 -n cpool $vg/$lv1 + +# Can't convert 'writeback' cache +not lvconvert --thin --thinpool $vg/tpool $vg/$lv1 + +# Switch to 'writethrough' - this should be supported +lvchange --cachemode writethrough $vg/$lv1 + +# Check $lv1 remains mounted (so it's not been unmounted by systemd) +mountpoint "$PWD/mnt" + +lvconvert --thin $vg/$lv1 --originname extorg --thinpool $vg/tpool + +# check cache exist as extorg-real +check grep_dmsetup table ${vg}-extorg-real "cache" + + +# Split cache from external origin (while in-use) +lvconvert --splitcache $vg/extorg + +# check linear exist as extorg-real +check grep_dmsetup table ${vg}-extorg-real "linear" +check lv_field $vg/extorg segtype linear + +# Cache external origin in-use again +lvconvert -y -H $vg/extorg --cachepool $vg/cpool + +get lv_field $vg/extorg attr | grep "^ori" + +umount mnt + +# Is filesystem still ok ? +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +lvchange -an $vg +lvchange -ay $vg + +# Remove thin, external origin remains +lvremove -f $vg/$lv1 + +#lvchange -prw $vg/extorg +lvconvert --uncache $vg/extorg + +lvremove -f $vg + +# +# Check some more API variants +# + +lvcreate -L10 -n pool $vg + +lvcreate -aey -L2 -n $lv1 $vg +lvcreate -H -L2 $vg/$lv1 + +# Converts $vg/pool to thin-pool AND $vg/$lv1 to thin +lvconvert -y --type thin $vg/$lv1 --originname extorg --thinpool $vg/pool + +check lv_field $vg/$lv1 segtype thin +check lv_field $vg/pool segtype thin-pool +check lv_field $vg/extorg segtype cache + +lvconvert --uncache $vg/extorg + +check lv_field $vg/extorg segtype linear + +vgremove -ff $vg diff --git a/test/shell/lvconvert-thin-external.sh b/test/shell/lvconvert-thin-external.sh new file mode 100644 index 0000000..ee0463c --- /dev/null +++ b/test/shell/lvconvert-thin-external.sh @@ -0,0 +1,180 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test conversion to thin external origin + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +which mkfs.ext2 || skip +which fsck || skip + +# +# Main +# +aux have_thin 1 5 0 || skip + +aux prepare_pvs 2 64 +get_devs + +vgcreate "$vg" --metadatasize 128K -s 64K "${DEVICES[@]}" + +if test 0 -eq 1 ; then +# FIXME: needs patch to allow inactive old-snap creation +lvcreate -l10 -T $vg/pool +lvcreate -an -pr --zero n -l10 --name $lv1 $vg +lvcreate -s $vg/$lv1 --name $lv2 --thinpool $vg/pool +vgchange -an $vg +# oldstyle read-only inactive snapshot +lvcreate -an -s $vg/$lv2 -l10 -p r --name $lv3 + +lvcreate -s $vg/$lv3 --name $lv4 --thinpool $vg/pool +lvremove -ff $vg/$lv3 + +lvremove -ff $vg +fi + +#lvcreate -L20M --name orig $vg +#lvconvert -T --thinpool $vg/pool $vg/orig +#lvcreate -s -aey -L10M $vg/orig +#lvremove -f $vg +#exit 0 + +lvcreate -l10 -T $vg/pool +# Can't convert pool to external origin +lvcreate -l10 -T $vg/pool1 -c 192k +not lvconvert -T --thinpool $vg/pool1 $vg/pool --originname origin +# Create pool1 chunk_size unaligned LV and check failing conversion +lvcreate -l2 -n $lv1 $vg +# Newer thin-pool target (>= 1.13) supports unaligned external origin +aux lvmconf 'global/thin_disabled_features = [ "external_origin_extend" ]' +not lvconvert -T --thinpool $vg/pool1 $vg/$lv1 + +lvremove -f $vg/pool1 $vg/$lv1 + +# create plain LV (will be used for external origin) +lvcreate -L8M -n $lv1 $vg + +# Can't convert same LV to the thin pool and thin volume +not lvconvert --thinpool $vg/$lv1 -T $vg/$lv1 +check lv_field $vg/$lv1 segtype linear + +mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1" +mkdir mnt +mount "$DM_DEV_DIR/$vg/$lv1" mnt + +dd if=/dev/zero of=mnt/test1 bs=1M count=1 + +# convert plain LV into thin external snapshot volume +# during conversion dd above could be still flushed + +lvconvert -T --originname extorg --thinpool $vg/pool $vg/$lv1 + +check active $vg $lv1 +# FIXME handling attr is ... +get lv_field $vg/extorg attr | grep "^ori" +check inactive $vg extorg + +touch mnt/test +umount mnt + +# check fs is without errors +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +lvchange -aey $vg/extorg +lvchange -an $vg/$lv1 + +check active $vg extorg +check inactive $vg $lv1 + +# fsck in read-only mode +fsck -n "$DM_DEV_DIR/$vg/extorg" + +not lvresize -l+8 $vg/extorg +not lvresize -l-4 $vg/extorg +not lvchange -p rw $vg/extorg + +#lvresize -L+8M $vg/$lv1 +#lvresize -L-4M $vg/$lv1 +#lvchange -p r $vg/$lv1 +#lvchange -p rw $vg/$lv1 + +lvchange -aey $vg + +lvs -a -o+origin_size,seg_size $vg + +# Chain external origins +lvconvert --type thin --originname extorg1 --thinpool $vg/pool $vg/extorg +check inactive $vg extorg1 + +lvconvert --originname extorg2 --thinpool $vg/pool -T $vg/extorg1 +check inactive $vg extorg1 +check inactive $vg extorg2 + +lvchange -an $vg/extorg +lvchange -ay $vg/extorg1 + +lvcreate -l4 -s $vg/$lv1 -n $lv2 +lvcreate -l8 -s $vg/extorg -n $lv3 +lvcreate -l12 -s $vg/extorg1 -n $lv4 +lvcreate -l16 -s $vg/extorg2 -n $lv5 +#vgchange -aey $vg +#lvremove -f $vg/extorg2 +#exit 0 +# Converting old-snapshot into external origin is not supported +not lvconvert -T --thinpool $vg/pool --originname lv5origin $vg/$lv4 + +lvs -a -o +segtype $vg + +check lv_field $vg/$lv1 segtype thin +check lv_field $vg/$lv2 segtype linear +check lv_field $vg/$lv3 segtype linear +check lv_field $vg/$lv4 segtype linear +check lv_field $vg/$lv5 segtype linear +check lv_field $vg/extorg segtype thin +check lv_field $vg/extorg1 segtype thin +check lv_field $vg/extorg2 segtype linear + +vgchange -ay $vg + +lvs -a -o+origin_size,seg_size $vg + +lvchange -an $vg/extorg2 +check inactive $vg extorg2 + +# Remove all volumes dependent on external origin +lvs -a -o+origin_size,seg_size,segtype $vg +lvremove -f $vg/extorg2 +# Only pool is left +check vg_field $vg lv_count 1 +lvremove -ff $vg + +# Test conversion to the pool and thin external at the same time (rhbz #1003461) +lvcreate -l50 -n pool $vg +lvcreate -l100 -n thin $vg +lvconvert --yes --thin --thinpool $vg/pool $vg/thin --originname thin-origin +check lv_field $vg/thin segtype thin +check lv_field $vg/thin-origin segtype linear +lvremove -ff $vg + +# Test conversion with non-zeroing thin-pool, should not WARN about zeroing +lvcreate -l50 -n pool $vg +lvcreate -l100 -n thin $vg +lvconvert --yes --thin --thinpool $vg/pool $vg/thin --zero n --originname thin-origin 2>&1 | tee out +not grep "not zeroed" out +check lv_field $vg/pool zero "" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-thin-from-thick.sh b/test/shell/lvconvert-thin-from-thick.sh new file mode 100644 index 0000000..d0c7718 --- /dev/null +++ b/test/shell/lvconvert-thin-from-thick.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +# Copyright (C) 2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test conversion to thin volume from thick LVs + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +which mkfs.ext4 || skip +which fsck || skip +aux have_tool_at_least "$LVM_TEST_THIN_RESTORE_CMD" 0 3 1 || skip +aux have_thin 1 5 0 || skip + +_convert_to_thin() { + mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1" + lvconvert --yes --type thin $vg/$lv1 + fsck -n "$DM_DEV_DIR/$vg/$lv1" + check lv_field $vg/$lv1 segtype thin + lvs -ao+segtype $vg + lvremove -f $vg +} + + +# +# Main +# +aux prepare_vg 2 6000 + +# error -> thin +lvcreate --type error -Zn -L10 -n $lv1 $vg +lvconvert --yes --type thin $vg/$lv1 +not dd if="$DM_DEV_DIR/$vg/$lv1" of=/dev/null bs=512 count=1 +lvremove -f $vg + +# zero -> thin +lvcreate --type zero -L2T -n $lv1 $vg +lvconvert --yes --type thin $vg/$lv1 +lvremove -f $vg + +# zero -> thin --test +if [ ! -e LOCAL_LVMLOCKD ] ; then +# FIXME: missing support with lvmlockd +lvcreate --type zero -L2T -n $lv1 $vg +lvconvert --yes --type thin --test $vg/$lv1 +check lv_field $vg/$lv1 segtype zero +check vg_field $vg lv_count 1 +lvremove -f $vg +fi + +# linear -> thin +lvcreate -L10 -n $lv1 $vg +_convert_to_thin + +# raid1 -> thin +if aux have_raid 1 7 0 ; then + lvcreate --type raid1 -L10 -n $lv1 $vg + _convert_to_thin +fi + +# cache -> thin +if aux have_cache 1 3 0 ; then + lvcreate -L10 -n $lv1 $vg + lvcreate -H -L10 $vg/$lv1 + _convert_to_thin +fi + +# writecache -> thin +if aux have_writecache 1 0 0 ; then + lvcreate -L10 -n $lv1 $vg + lvcreate -an -L10 -n $lv2 $vg + lvconvert --yes --type writecache --cachevol $lv2 $vg/$lv1 + _convert_to_thin +fi + +# vdo -> thin +if aux have_vdo 6 2 0 ; then + lvcreate --type vdo -L4G -n $lv1 $vg/$lv2 + _convert_to_thin +fi + +vgremove -ff $vg diff --git a/test/shell/lvconvert-thin-raid.sh b/test/shell/lvconvert-thin-raid.sh new file mode 100644 index 0000000..c021e3b --- /dev/null +++ b/test/shell/lvconvert-thin-raid.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip +aux have_raid 1 4 0 || skip + +aux prepare_vg 4 + +# create RAID LVs for data and metadata volumes +lvcreate -aey -L10M --type raid1 -m3 -n $lv1 $vg +lvcreate -aey -L8M --type raid1 -m3 -n $lv2 $vg +aux wait_for_sync $vg $lv1 +aux wait_for_sync $vg $lv2 +lvchange -an $vg/$lv1 + +# FIXME: temporarily we return error code 5 +INVALID=not +# conversion fails for internal volumes +$INVALID lvconvert --thinpool $vg/${lv1}_rimage_0 +$INVALID lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/${lv2}_rimage_0 + +lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 + +lvchange -ay $vg + +lvconvert --splitmirrors 1 --name data2 $vg/${lv1}_tdata "$dev2" +lvconvert --splitmirrors 1 --name data3 $vg/${lv1}_tdata "$dev3" +# Check split and track gets rejected on 2-legged raid1 +not lvconvert --splitmirrors 1 --trackchanges $vg/${lv1}_tdata "$dev4" +lvconvert -y --splitmirrors 1 --trackchanges $vg/${lv1}_tdata "$dev4" + +lvconvert --splitmirrors 1 --name meta1 $vg/${lv1}_tmeta "$dev1" +lvconvert --splitmirrors 1 --name meta2 $vg/${lv1}_tmeta "$dev2" +# Check split and track gets rejected on 2-legged raid1 +not lvconvert --splitmirrors 1 --trackchanges $vg/${lv1}_tmeta "$dev4" +lvconvert -y --splitmirrors 1 --trackchanges $vg/${lv1}_tmeta "$dev4" + +lvremove -ff $vg/data2 $vg/data3 $vg/meta1 $vg/meta2 + +lvconvert --merge $vg/${lv1}_tdata_rimage_1 +lvconvert --merge $vg/${lv1}_tmeta_rimage_1 + +lvconvert -y -m +1 $vg/${lv1}_tdata "$dev2" +lvconvert -y -m +1 $vg/${lv1}_tmeta "$dev1" + +vgremove -ff $vg diff --git a/test/shell/lvconvert-thin.sh b/test/shell/lvconvert-thin.sh index 97ccc09..b1b11ab 100644 --- a/test/shell/lvconvert-thin.sh +++ b/test/shell/lvconvert-thin.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # @@ -8,9 +8,20 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -. lib/test +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +prepare_lvs() { + lvremove -f $vg + lvcreate -L10M -n $lv1 $vg + lvcreate -L8M -n $lv2 $vg +} # # Main @@ -18,26 +29,133 @@ aux have_thin 1 0 0 || skip aux prepare_pvs 4 64 +get_devs + +# build one large PV +vgcreate $vg1 "$dev1" "$dev2" "$dev3" + +# 32bit linux kernels are fragille with device size >= 16T +# maybe uname -m [ x86_64 | i686 ] +TSIZE=64T +aux can_use_16T || TSIZE=15T +lvcreate --type snapshot -l 100%FREE -n $lv $vg1 --virtualsize $TSIZE +aux extend_filter_LVMTEST + +pvcreate "$DM_DEV_DIR/$vg1/$lv" +vgcreate $vg -s 64K "$dev4" "$DM_DEV_DIR/$vg1/$lv" -vgcreate $vg -s 64K $(cat DEVICES) +lvcreate -L1T -n $lv1 $vg +lvconvert --yes -c 8M --type thin --poolmetadatasize 1G $vg/$lv1 + +# needs some --cachepool or --thinpool +invalid lvconvert --yes --poolmetadatasize 1G $vg/$lv1 +lvremove -f $vg # create mirrored LVs for data and metadata volumes -lvcreate -aey -l8 -m1 --mirrorlog core -n $lv1 $vg -lvcreate -aey -l4 -m1 --mirrorlog core -n $lv2 $vg +lvcreate -aey -L10M --type mirror -m1 --mirrorlog core -n $lv1 $vg +lvcreate -aey -L10M -n $lv2 $vg +lvchange -an $vg/$lv1 + +# conversion fails for mirror segment type +fail lvconvert --thinpool $vg/$lv1 + +# FIXME: temporarily we return error code 5 +INVALID=not +# cannot use same LV +$INVALID lvconvert --yes --thinpool $vg/$lv2 --poolmetadata $vg/$lv2 + +prepare_lvs + +# conversion fails for internal volumes +# can't use --readahead with --poolmetadata +invalid lvconvert --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 --readahead 512 +lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 + +prepare_lvs +lvconvert --yes -c 64 --stripes 2 --thinpool $vg/$lv1 --readahead 48 +lvremove -f $vg + + +# Swaping of metadata volume +lvcreate -L1T -n $lv1 $vg +lvcreate -L32 -n $lv2 $vg +lvconvert --yes -c 8M --type thin-pool $vg/$lv1 2>&1 | tee err +# Check there is a warning for large chunk size and zeroing enabled +grep "WARNING: Pool zeroing and" err +UUID=$(get lv_field $vg/$lv2 uuid) +# Fail is pool is active +# TODO maybe detect inactive pool and deactivate +fail lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $lv2 +lvchange -an $vg +lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $lv2 +check lv_field $vg/${lv1}_tmeta uuid "$UUID" + +# and swap again with new command --swapmetadata +lvconvert --yes --swapmetadata $vg/$lv1 --poolmetadata $lv2 +check lv_field $vg/$lv2 uuid "$UUID" +lvremove -f $vg + + +# test with bigger sizes +lvcreate -L1T -n $lv1 $vg +lvcreate -L8M -n $lv2 $vg +lvcreate -L1M -n $lv3 $vg + +# chunk size is bigger then size of thin pool data +fail lvconvert --yes -c 1G --thinpool $vg/$lv3 +# stripes can't be used with poolmetadata +invalid lvconvert --stripes 2 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 +# too small metadata (<2M) +fail lvconvert --yes -c 64 --thinpool $vg/$lv1 --poolmetadata $vg/$lv3 +# too small chunk size fails +$INVALID lvconvert -c 4 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 +# too big chunk size fails +$INVALID lvconvert -c 2G --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 +# negative chunk size fails +$INVALID lvconvert -c -256 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 +# non multiple of 64KiB fails +$INVALID lvconvert -c 88 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 + +# cannot use same LV for pool and convertion +$INVALID lvconvert --yes --thinpool $vg/$lv3 -T $vg/$lv3 + +# Warning about smaller then suggested +lvconvert --yes -c 256 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 2>&1 | tee err +grep "WARNING: Chunk size is smaller" err +lvremove -f $vg + + +lvcreate -L1T -n $lv1 $vg +lvcreate -L32G -n $lv2 $vg +# Warning about bigger then needed +lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 2>&1 | tee err +grep -i "maximum" err +lvremove -f $vg -lvconvert -c 64K --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 -lvcreate -V10M -T $vg/$lv1 --name $lv3 +if test "$TSIZE" = 64T; then +lvcreate -L24T -n $lv1 $vg +# Warning about bigger then needed (24T data and 16G -> 128K chunk) +fail lvconvert --yes -c 64 --thinpool $vg/$lv1 2>&1 | tee err +grep "WARNING: Chunk size is too small" err +lvremove -f $vg +fi -# check lvrename work properly -lvrename $vg/$lv1 $vg/pool -check lv_field $vg/pool name "pool" +#lvs -a -o+chunk_size,stripe_size,seg_pe_ranges -lvrename $vg/$lv3 $vg/$lv4 -check lv_field $vg/$lv4 name "$lv4" +#################################### +# Prohibites thin pool conversions # +#################################### +lvcreate -L32 -n $lv1 $vg +lvcreate -L16 -n $lv2 $vg +lvconvert --yes --thinpool $vg/$lv1 -# not yet supported conversions -not lvconvert -m 1 $vg/pool -not lvconvert -m 1 $vg/$lv3 +not aux have_cache 1 3 0 || fail lvconvert --yes --type cache-pool $vg/$lv1 +fail lvconvert --yes --type mirror -m1 $vg/$lv1 +not aux have_raid 1 0 0 || fail lvconvert --yes --type raid1 -m1 $vg/$lv1 +fail lvconvert --yes --type snapshot $vg/$lv1 $vg/$lv2 +fail lvconvert --yes --type snapshot $vg/$lv2 $vg/$lv1 +fail lvconvert --yes --type thin-pool $vg/$lv1 vgremove -ff $vg +vgremove -ff $vg1 diff --git a/test/shell/lvconvert-twostep.sh b/test/shell/lvconvert-twostep.sh index c45e7bc..dc072f0 100644 --- a/test/shell/lvconvert-twostep.sh +++ b/test/shell/lvconvert-twostep.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2010 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2010,2018 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 @@ -7,13 +8,17 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest + +aux lvmconf "global/support_mirrored_mirror_log=1" aux prepare_vg 4 -lvcreate -m 1 --mirrorlog disk --ig -L 1 -n mirror $vg +lvcreate -aey --type mirror -m 1 --mirrorlog disk --ignoremonitoring -L 1 -n mirror $vg not lvconvert -m 2 --mirrorlog core $vg/mirror "$dev3" 2>&1 | tee errs grep "two steps" errs @@ -22,5 +27,10 @@ lvconvert --mirrorlog core $vg/mirror not lvconvert -m 1 --mirrorlog disk $vg/mirror "$dev3" 2>&1 | tee errs grep "two steps" errs +if test ! -e LOCAL_CLVMD ; then +# FIXME mirrored unsupported in cluster not lvconvert -m 1 --mirrorlog mirrored $vg/mirror "$dev3" "$dev4" 2>&1 | tee errs grep "two steps" errs +fi + +vgremove -ff $vg diff --git a/test/shell/lvconvert-vdo-raid.sh b/test/shell/lvconvert-vdo-raid.sh new file mode 100644 index 0000000..1383145 --- /dev/null +++ b/test/shell/lvconvert-vdo-raid.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise vdo-pool's on raidLV + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# +# Main +# + +# +aux have_vdo 6 2 1 || skip +aux have_raid 1 3 0 || skip + + +aux prepare_vg 2 9000 + +lvcreate --yes --vdo -L4G $vg/vpool + +aux zero_dev "$dev1" "$(( $(get first_extent_sector "$dev1") + 8192 )):" +aux zero_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 8192 )):" + +# convert _vdata to raid +lvconvert --yes --type raid1 $vg/vpool_vdata +check lv_field $vg/vpool_vdata segtype raid1 -a + +lvconvert --yes -m 0 $vg/vpool_vdata "$dev2" +check lv_field $vg/vpool_vdata segtype linear -a + +# vpool should redirect to _vdata +lvconvert --yes --type raid1 $vg/vpool +check lv_field $vg/vpool_vdata segtype raid1 -a + +lvremove -f $vg + +aux enable_dev "$dev1" "$dev2" + + +lvcreate --type raid1 -L4G --nosync -n vpool1 $vg + +lvconvert --yes --vdopool $vg/vpool1 -V2G -n $lv1 + +mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1" + +not lvrename $vg/vpool1 + +lvchange -an $vg + +lvrename $vg/vpool1 $vg/vpool + +lvchange -ay $vg + +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +lvs -a $vg + +vgremove -ff $vg diff --git a/test/shell/lvconvert-vdo.sh b/test/shell/lvconvert-vdo.sh new file mode 100644 index 0000000..7c0bce5 --- /dev/null +++ b/test/shell/lvconvert-vdo.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# +# Main +# +aux prepare_vg 2 6400 + +# Conversion to vdo-pool +lvcreate -L5G -n $lv1 $vg + +if not aux have_vdo 6 2 0 ; then +# For unsupported VDO let's check lvconvert fails + not lvconvert --yes --type vdo-pool $vg/$lv1 |& tee out + vgremove -ff $vg + exit +fi + +# Check there is big prompting warning +not lvconvert --type vdo-pool $vg/$lv1 |& tee out +grep "WARNING" out + +# Check --vdosettings is also applied to converted vdo-pool +lvconvert -y --type vdo-pool --vdosettings 'ack_threads=5' $vg/$lv1 +check lv_field $vg/$lv1 vdo_ack_threads "5" +lvremove -f $vg + +# +lvcreate -L5G -n $lv1 $vg +lvconvert -y --vdopool $vg/$lv1 +lvremove -f $vg + + +lvcreate -L5G -n $lv1 $vg +lvconvert -y --vdopool $vg/$lv1 -n $lv2 +check lv_field $vg/$lv1 segtype vdo-pool +check lv_field $vg/${lv1}_vdata segtype linear -a +check lv_field $vg/$lv2 segtype vdo +lvremove -f $vg + + +lvcreate -L5G -n $lv1 $vg +lvconvert -y --type vdo-pool $vg/$lv1 -n $lv2 -V10G +lvremove -f $vg + + +lvcreate -L5G -n $lv1 $vg +lvconvert -y --vdopool $vg/$lv1 -n $lv2 -V10G --compression n --deduplication n +check lv_field $vg/$lv1 size "5.00g" +check lv_field $vg/${lv1}_vdata size "5.00g" -a +check lv_field $vg/$lv2 size "10.00g" +lvremove -f $vg + + +# Simple stacking works... +# Just be sure test do not try to synchronize 5G of mirror!! +lvcreate -L5G --type mirror --nosync -n $lv1 $vg +lvconvert -y --vdopool $vg/$lv1 -n $lv2 +lvs -a $vg +check lv_field $vg/${lv1}_vdata segtype mirror -a +lvremove -f $vg + + +vgremove -ff $vg diff --git a/test/shell/lvcreate-cache-fail.sh b/test/shell/lvcreate-cache-fail.sh new file mode 100644 index 0000000..39a8273 --- /dev/null +++ b/test/shell/lvcreate-cache-fail.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise creation of cache and cache pool volumes and failure path +# https://bugzilla.redhat.com/1355923 + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +#aux prepare_pvs 1 4707950 +#vgcreate $SHARED $vg "$dev1" +#lvcreate -L4T -n $lv1 $vg +#lvcreate -H -L500G -n cache $vg/$lv1 +#fail lvcreate -H -l 127999 -n cache $vg/$lv1 + +aux prepare_vg 1 20 +lvcreate -L10 -n $lv1 $vg +fail lvcreate -H -L2 -n cache $vg/$lv1 + +lvs -a $vg +vgs $vg +lvdisplay $vg + +#dmsetup table +#dmsetup status +#time dmsetup suspend ${vg}-${lv1} +#time dmsetup resume ${vg}-${lv1} + +vgremove -ff $vg diff --git a/test/shell/lvcreate-cache-no-tools.sh b/test/shell/lvcreate-cache-no-tools.sh new file mode 100644 index 0000000..2e4ee46 --- /dev/null +++ b/test/shell/lvcreate-cache-no-tools.sh @@ -0,0 +1,119 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise creation of cache without cache_check + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +if test -e LOCAL_CLVMD ; then +# In cluster, the error from activation is logged in clvmd +# so we can only check resulting state of activation + GREP="echo" +else + GREP="grep" +fi + +make_fake_() { + cat <<- EOF >fake-tool.sh +#!/bin/sh +echo "$1" +exit 1 +EOF + chmod +x fake-tool.sh +} + +check_change_() { + lvchange -an $vg |& tee out + "$GREP" "$1" out + + lvchange -ay $vg |& tee out + "$GREP" "$1" out +} + +# Integrity check fails, but deactivation is OK +check_change_failed_() { + lvchange -an $vg |& tee out + "$GREP" "failed" out + + # Activation must fail + fail lvchange -ay $vg |& tee out + "$GREP" "failed" out + + cat <<- EOF >fake-tool.sh +#!/bin/sh +exit +EOF + chmod +x fake-tool.sh + # Activate without any check + lvchange -ay $vg +} + + +aux have_cache 1 3 0 || skip + +# FIXME: parallel cache metadata allocator is crashing when used value 8000! +aux prepare_vg 5 80000 + +aux lvmconf 'global/cache_check_executable = "./fake-tool.sh"' +rm -f fake-tool.sh + +# On cache target that supports V2 +if aux have_cache 1 10 0 ; then + +lvcreate -aey -l1 -n $lv1 $vg +lvcreate -H -l2 $vg/$lv1 + +check_change_ "Check is skipped" + +# prepare fake version of cache_check tool that reports old version +make_fake_ "0.1.0" +check_change_ "upgrade" + +# prepare fake version of cache_check tool that reports garbage +make_fake_ "garbage" +check_change_ "parse" + +# prepare fake version of cache_check tool with high version +make_fake_ "99.0.0" +check_change_failed_ + +lvremove -f $vg + +fi + +# Enforce older cache target format V1 +aux lvmconf 'allocation/cache_metadata_format = 1' + +rm -f fake-tool.sh + +lvcreate -aey -l1 -n $lv1 $vg +lvcreate -H -l2 $vg/$lv1 + +check_change_ "Check is skipped" + +# prepare fake version of cache_check tool that reports old version +make_fake_ "0.1.0" +check_change_failed_ + +# prepare fake version of cache_check tool that reports garbage +make_fake_ "garbage" +check_change_failed_ + +# prepare fake version of cache_check tool with high version +make_fake_ "99.0.0" +check_change_failed_ + + +vgremove -ff $vg diff --git a/test/shell/lvcreate-cache-raid.sh b/test/shell/lvcreate-cache-raid.sh new file mode 100644 index 0000000..d1d1c19 --- /dev/null +++ b/test/shell/lvcreate-cache-raid.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise creation of cache and raids + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip +aux have_raid 1 0 0 || skip + +# FIXME: parallel cache metadata allocator is crashing when used value 8000! +aux prepare_vg 5 80000 + +aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]' + +# Bug 1110026 & Bug 1095843 +# Create RAID1 origin, then cache pool and cache +lvcreate -aey -l 2 --type raid1 -m1 -n $lv2 $vg +lvcreate --cache -l 1 $vg/$lv2 +check lv_exists $vg/${lv2}_corig_rimage_0 # ensure images are properly renamed +check active $vg ${lv2}_corig +dmsetup table ${vg}-$lv2 | grep cache # ensure it is loaded in kernel + +vgremove -ff $vg diff --git a/test/shell/lvcreate-cache-snapshot.sh b/test/shell/lvcreate-cache-snapshot.sh new file mode 100644 index 0000000..5d1c5a7 --- /dev/null +++ b/test/shell/lvcreate-cache-snapshot.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise creation of snapshot of cached LV + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext2 || skip +which fsck || skip + +aux have_cache 1 5 0 || skip + +aux prepare_vg 2 + +lvcreate --type cache-pool -L1 $vg/cpool +lvcreate -H -L4 -n $lv1 --cachepool $vg/cpool $vg + +lvcreate -s -L2 -n $lv2 $vg/$lv1 +check lv_field $vg/$lv1 segtype cache + + +# Make some 'fs' data in snapshot +mkfs.ext2 "$DM_DEV_DIR/$vg/$lv2" +mkdir mnt +mount "$DM_DEV_DIR/$vg/$lv2" mnt +touch mnt/test +umount mnt + +sync +aux udev_wait + +# Merge snap to origin +lvconvert --merge $vg/$lv2 + +# Check cached origin has no valid fs. +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +# Check deactivation +lvchange -an $vg + +# Check activation +lvchange -ay $vg + + +lvconvert --uncache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear + +# Uncached origin is fine as well +fsck -n "$DM_DEV_DIR/$vg/$lv1" + + +vgremove -ff $vg diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh new file mode 100644 index 0000000..38c915e --- /dev/null +++ b/test/shell/lvcreate-cache.sh @@ -0,0 +1,308 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise creation of cache and cache pool volumes + +# Full CLI uses --type +# Shorthand CLI uses -H | --cache + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +# FIXME: parallel cache metadata allocator is crashing when used value 8000! +aux prepare_vg 5 80000 + +aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]' + +####################### +# Cache_Pool creation # +####################### +# TODO: Unsupported yet creation of cache pool and cached volume at once +# TODO: Introduce --pooldatasize +# TODO: Policy to determine cache pool size and cache pool name +invalid lvcreate -H -l 1 $vg +invalid lvcreate -H -l 1 --name $lv1 $vg +invalid lvcreate -l 1 --cache $vg +# Only cached volume could be created +invalid lvcreate -l 1 --type cache $vg +# Striping is not supported with cache-pool creation +invalid lvcreate -l 1 -i 2 --type cache-pool $vg +# Fails as it needs to see VG content +fail lvcreate -l 1 --type cache --cachepool $vg/pool1 +fail lvcreate -l 1 --type cache --cachepool pool2 $vg +fail lvcreate -l 1 --cache $vg/pool3 +fail lvcreate -l 1 -H --cachepool pool4 $vg +fail lvcreate -l 1 -H --name $lv2 $vg/pool5 +fail lvcreate -l 1 -H --name $lv3 --cachepool $vg/pool6 +fail lvcreate -l 1 -H --name $vg/$lv4 --cachepool pool7 + +# Unlike in thin pool case - cache pool and cache volume both need size arg. +# So we require cache pool to exist and need to fail when it's missing. +# +# --cachepool gives implicit --cache +fail lvcreate -l 1 --cachepool pool8 $vg + +# no size specified +invalid lvcreate --cachepool pool $vg 2>&1 | tee err +#grep "specify either size or extents" err +grep "No command with matching syntax recognised" err + +# Check nothing has been created yet +check vg_field $vg lv_count 0 + +# Checks that argument passed with --cachepool is really a cache-pool +lvcreate -an -l 1 -n $lv1 $vg +# Hint: nice way to 'tee' only stderr.log so we can check it's log_error() +fail lvcreate -L10 --cachepool $vg/$lv1 2> >(tee -a stderr.log >&2) +grep "not a cache pool" stderr.log + +# With --type cache-pool we are clear which segtype has to be created +lvcreate -l 1 --type cache-pool $vg/pool1 +check lv_field $vg/pool1 segtype "cache-pool" +lvcreate -l 1 --type cache-pool --name $vg/pool2 $vg +check lv_field $vg/pool2 segtype "cache-pool" +lvcreate -l 1 --type cache-pool --cachepool $vg/pool3 $vg +check lv_field $vg/pool3 segtype "cache-pool" +lvcreate -l 1 --type cache-pool --cachepool $vg/pool4 +check lv_field $vg/pool4 segtype "cache-pool" +lvcreate -l 1 --type cache-pool --cachepool pool5 $vg +check lv_field $vg/pool5 segtype "cache-pool" +lvcreate -l 1 --type cache-pool --name pool6 $vg +check lv_field $vg/pool6 segtype "cache-pool" +lvcreate -l 1 --type cache-pool --name $vg/pool7 +check lv_field $vg/pool7 segtype "cache-pool" + +lvremove -f $vg + + +# Check the percentage values are reported for both cache and cache-pool +lvcreate --type cache-pool -L1 $vg/cpool +lvcreate -H -L4 -n $lv1 $vg/cpool + +check lv_field $vg/$lv1 origin "[${lv1}_corig]" +check lv_field $vg/$lv1 copy_percent "0.00" +# there should be something present (value differs per policy version) +test -n "$(get lv_field $vg/$lv1 data_percent)" +test -n "$(get lv_field $vg/$lv1 metadata_percent)" +check lv_field $vg/cpool_cpool copy_percent "0.00" +test -n "$(get lv_field $vg/cpool_cpool data_percent)" +test -n "$(get lv_field $vg/cpool_cpool metadata_percent)" +# check we also display percent value for segmented output (-o+devices) +lvs -a -o+devices $vg/cpool_cpool | tee out +grep "0.00" out +lvremove -f $vg + + +# Validate ambiguous pool name is detected +invalid lvcreate -l 1 --type cache-pool --cachepool pool1 $vg/pool2 +invalid lvcreate -l 1 --type cache-pool --name pool3 --cachepool pool4 $vg +invalid lvcreate -l 1 --type cache-pool --name pool6 --cachepool pool6 $vg/pool7 +invalid lvcreate -l 1 --type cache-pool --name pool8 $vg/pool9 + +# Unsupported with cache & cache pool +invalid lvcreate --type cache-pool --discards passdown -l1 $vg +invalid lvcreate -H --discards passdown -l1 $vg +invalid lvcreate --type cache-pool --virtualsize 1T -l1 $vg +invalid lvcreate -H --virtualsize 1T -l1 $vg + +check vg_field $vg lv_count 0 + + +for mode in "" "--cachemode writethrough" +do + +################ +# Cache creation +# Creating a cache is a two phase process +# - first, cache_pool (or origin) +# - then, the cache LV (lvcreate distinguishes supplied origin vs cache_pool) +################ + +lvcreate --type cache-pool -l 1 -n pool $vg $mode +# Select automatic name for cached LV +lvcreate --type cache -l1 $vg/pool + +lvcreate --type cache-pool -l 1 -n pool1 $vg $mode +lvcreate --cache -l1 -n $lv1 --cachepool $vg/pool1 +dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel + +lvcreate --type cache-pool -l 1 -n pool2 $vg $mode +lvcreate -H -l1 -n $lv2 --cachepool pool2 $vg + +# +# Now check removals +# + +# Removal of cached LV removes every related LV +check lv_field $vg/$lv1 segtype "cache" +lvremove -f $vg/$lv1 +check lv_not_exists $vg $lv1 pool1 pool1_cdata pool1_cmeta +# to preserve cachepool use lvconvert --splitcache $vg/$lv1 + +# Removal of cache pool leaves origin uncached +check lv_field $vg/$lv2 segtype "cache" +lvremove -f $vg/pool2_cpool +check lv_not_exists $vg pool2_cpool pool2_cpool_cdata pool2_cpool_cmeta +check lv_field $vg/$lv2 segtype "linear" + +lvremove -f $vg + +done + + +# Conversion through lvcreate case +# Bug 1110026 +# Create origin, then cache pool and cache the origin +lvcreate -aey -l 2 -n $lv1 $vg +lvcreate --type cache -l 1 $vg/$lv1 +dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel + +lvremove -f $vg + +# Check minimum cache pool metadata size +lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>&1 | tee out +grep -i "minimal" out + + +# FIXME: This test is failing in allocator with smaller VG sizes +lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>&1 | tee out +grep -i "maximum" out + +lvremove -f $vg +######################################## +# Cache conversion and r/w permissions # +######################################## + +# writeable origin and 'default' => writable cache + origin +lvcreate -an -l1 -n $vg/$lv1 +# do not allow stripping for cache-pool +fail lvcreate -H -i 2 -l1 -n cpool1 $vg/$lv1 +lvcreate -H -l1 -n cpool1 $vg/$lv1 +check lv_attr_bit perm $vg/cpool1_cpool "w" +check lv_attr_bit perm $vg/${lv1}_corig "w" +check lv_attr_bit perm $vg/$lv1 "w" + +# writeable origin and -pr => conversion is not supported +lvcreate -an -l1 -n $vg/$lv2 +fail lvcreate -H -l1 -pr -n cpool2 $vg/$lv2 + +# read-only origin and -pr => read-only cache + origin +lvcreate -an -pr -l1 -n $vg/$lv3 +lvcreate -an -H -l1 -pr -n cpool3 $vg/$lv3 +check lv_attr_bit perm $vg/cpool3_cpool "w" +check lv_attr_bit perm $vg/${lv3}_corig "r" +check lv_attr_bit perm $vg/$lv3 "r" +check inactive $vg $lv3 +check inactive $vg cpool3_cpool + +# read-only origin and 'default' => read-only cache + origin +lvcreate -an -pr -l1 -n $vg/$lv4 +lvcreate -H -l1 -n cpool4 $vg/$lv4 +check lv_attr_bit perm $vg/cpool4_cpool "w" +check lv_attr_bit perm $vg/${lv4}_corig "r" +check lv_attr_bit perm $vg/$lv4 "r" + +# read-only origin and -prw => conversion unsupported +lvcreate -an -pr -l1 -n $vg/$lv5 +fail lvcreate -H -l1 -prw -n cpool5 $vg/$lv5 + +# cached volume respects permissions +lvcreate --type cache-pool -l1 -n $vg/cpool +lvcreate -H -l1 -pr -n $lv6 $vg/cpool +check lv_attr_bit perm $vg/cpool_cpool "w" +check lv_attr_bit perm $vg/$lv6 "r" + +lvremove -f $vg + +######################################## +# Validate args are properly preserved # +######################################## +lvcreate --type cache-pool -L10 --chunksize 256 --cachemode writeback $vg/cpool1 +check lv_field $vg/cpool1 chunksize "256.00k" +check lv_field $vg/cpool1 cachemode "writeback" +# check striping is supported when creating a cached LV +lvcreate -H -L10 -i 2 -n $lv1 $vg/cpool1 +check lv_field $vg/${lv1}_corig stripes "2" -a +check lv_field $vg/$lv1 chunksize "256.00k" +check lv_field $vg/$lv1 cachemode "writeback" + +lvcreate --type cache-pool -L10 --chunksize 256 --cachemode writethrough $vg/cpool2 +lvcreate -H -L10 --chunksize 512 --cachemode writeback -n $lv2 $vg/cpool2 +check lv_field $vg/$lv2 chunksize "512.00k" +check lv_field $vg/$lv2 cachemode "writeback" + +# Chunk bigger then pool size +fail lvcreate --type cache-pool -l1 --chunksize 1G $vg/cpool3 + +lvcreate --type cache-pool -L10 $vg/cpool4 +fail lvcreate -H -L10 --chunksize 16M $vg/cpool4 + +lvdisplay --maps $vg + +lvremove -f $vg + +# migration_threshold is protected to not be smaller then 8*chunk_size +# so even when user sets migration threshold to lower value, +# activation will ensure the minimal size is preserved +lvcreate --type cache-pool -L10 $vg/cpool +lvcreate --type cache -l 1 --cachepool $vg/cpool -c 64k -n corigin $vg --cachesettings migration_threshold=233 +dmsetup status | grep $vg +dmsetup status | grep $vg-corigin | grep 'migration_threshold 1024' +lvchange -an $vg +lvchange -ay $vg +dmsetup status | grep $vg-corigin | grep 'migration_threshold 1024' + +lvremove -f $vg + +lvcreate --type cache-pool -L10 --cachepolicy mq --cachesettings migration_threshold=1233 $vg/cpool +lvcreate --type cache -l 1 --cachepool $vg/cpool -n corigin $vg +dmsetup status | grep $vg +dmsetup status | grep $vg-corigin | grep 'migration_threshold 1233' + +lvremove -f $vg + + +#################################################### +# S/MQ policy does not accept random string settings +#################################################### + +lvcreate -L1 -n $lv1 $vg +lvcreate -L1 -H $vg/$lv1 --cachesettings unknown=0 |& tee out + +grep "not support \"unknown=0\"" out + +# But still the caching should proceed and LV should be available +check lv_exists $vg/$lv1 + + +############################## +# Test things that should fail +############################## + +# Creation of read-only cache pool is not supported +invalid lvcreate -pr --type cache-pool -l1 -n $vg/cpool + +# Attempt to use bigger chunk size then cache pool data size +fail lvcreate -l 1 --type cache-pool --chunksize 16M $vg 2>out +grep "chunk size" out + +# Option testing +# --chunksize +# --cachepolicy +# --poolmetadatasize +# --poolmetadataspare + +vgremove -ff $vg diff --git a/test/shell/lvcreate-external-dmeventd.sh b/test/shell/lvcreate-external-dmeventd.sh new file mode 100644 index 0000000..20973da --- /dev/null +++ b/test/shell/lvcreate-external-dmeventd.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test check converted external origin remains monitored + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 3 0 || skip +aux have_raid 1 3 0 || skip + +aux prepare_dmeventd +aux prepare_vg 2 + +# Test validation for external origin being multiple of thin pool chunk size +lvcreate -L10M -T $vg/pool + +# Create raid LV (needs monitoring) for external origin. +lvcreate -m1 -L1 -n $lv1 $vg + +lvconvert -T --thinpool $vg/pool --originname $lv2 $vg/$lv1 + +# Check raid LV now as external origing with $lv2 name is still monitored +check lv_first_seg_field $vg/$lv2 seg_monitor "monitored" + +lvchange -an $vg + +lvchange -ay $vg/$lv1 +check lv_first_seg_field $vg/$lv2 seg_monitor "monitored" + +vgremove -ff $vg diff --git a/test/shell/lvcreate-large-raid.sh b/test/shell/lvcreate-large-raid.sh index 8768bb3..a7af9cb 100644 --- a/test/shell/lvcreate-large-raid.sh +++ b/test/shell/lvcreate-large-raid.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2012,2016 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 @@ -7,65 +8,114 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Exercise some lvcreate diagnostics' -. lib/test -aux target_at_least dm-raid 1 1 0 || skip +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# FIXME update test to make something useful on <16T +aux can_use_16T || skip -aux prepare_vg 5 +aux have_raid 1 3 0 || skip +v1_9_0=0 +aux have_raid 1 9 0 && v1_9_0=1 -lvcreate -s -l 20%FREE -n $lv1 $vg --virtualsize 256T -lvcreate -s -l 20%FREE -n $lv2 $vg --virtualsize 256T -lvcreate -s -l 20%FREE -n $lv3 $vg --virtualsize 256T -lvcreate -s -l 20%FREE -n $lv4 $vg --virtualsize 256T -lvcreate -s -l 20%FREE -n $lv5 $vg --virtualsize 256T +segtypes="raid5" +aux have_raid4 && segtypes="raid4 raid5" -#FIXME this should be 1024T -#check lv_field $vg/$lv size "128.00m" +# Prepare 5x ~1P sized devices +aux prepare_pvs 5 1000000000 +get_devs -aux lvmconf 'devices/filter = [ "a/dev\/mapper\/.*$/", "a/dev\/LVMTEST/", "r/.*/" ]' +vgcreate $SHARED "$vg1" "${DEVICES[@]}" -pvcreate $DM_DEV_DIR/$vg/$lv[12345] -vgcreate -c n $vg1 $DM_DEV_DIR/$vg/$lv[12345] +aux lvmconf 'devices/issue_discards = 1' + +# Delay PVs so that resynchronization doesn't fill too much space +for device in "${DEVICES[@]}" +do + aux zero_dev "$device" "$(( $(get first_extent_sector "$device") + 8192 )):" +done # bz837927 START # # Create large RAID LVs # -# We need '--nosync' or our virtual devices won't work + +# 200 TiB raid1 lvcreate --type raid1 -m 1 -L 200T -n $lv1 $vg1 --nosync check lv_field $vg1/$lv1 size "200.00t" +check raid_leg_status $vg1 $lv1 "AA" +lvremove -ff $vg1 + +# 1 PiB raid1 +lvcreate --type raid1 -m 1 -L 1P -n $lv1 $vg1 --nosync +check lv_field $vg1/$lv1 size "1.00p" +check raid_leg_status $vg1 $lv1 "AA" lvremove -ff $vg1 -for segtype in raid4 raid5 raid6; do +# 750 TiB raid4/5 +for segtype in $segtypes; do lvcreate --type $segtype -i 3 -L 750T -n $lv1 $vg1 --nosync check lv_field $vg1/$lv1 size "750.00t" + check raid_leg_status $vg1 $lv1 "AAAA" lvremove -ff $vg1 done # -# Convert large linear to RAID1 (belong in different test script?) +# Extending large 200 TiB RAID LV to 400 TiB (belong in different script?) # -lvcreate -L 200T -n $lv1 $vg1 -# Need to deactivate or the up-convert will start sync'ing -lvchange -an $vg1/$lv1 -lvconvert --type raid1 -m 1 $vg1/$lv1 +lvcreate --type raid1 -m 1 -L 200T -n $lv1 $vg1 --nosync check lv_field $vg1/$lv1 size "200.00t" +check raid_leg_status $vg1 $lv1 "AA" +lvextend -L +200T $vg1/$lv1 +check lv_field $vg1/$lv1 size "400.00t" +check raid_leg_status $vg1 $lv1 "AA" +lvremove -ff $vg1 + + +# Check --nosync is rejected for raid6 +if [ $v1_9_0 -eq 1 ] ; then + not lvcreate --type raid6 -i 3 -L 750T -n $lv1 $vg1 --nosync +fi + +# 750 TiB raid6 +lvcreate --type raid6 -i 3 -L 750T -n $lv1 $vg1 +check lv_field $vg1/$lv1 size "750.00t" +check raid_leg_status $vg1 $lv1 "aaaaa" +lvremove -ff $vg1 + +# 1 PiB raid6, then extend up to 2 PiB +lvcreate --type raid6 -i 3 -L 1P -n $lv1 $vg1 +check lv_field $vg1/$lv1 size "1.00p" +check raid_leg_status $vg1 $lv1 "aaaaa" +lvextend -L +1P $vg1/$lv1 +check lv_field $vg1/$lv1 size "2.00p" +check raid_leg_status $vg1 $lv1 "aaaaa" lvremove -ff $vg1 # -# Extending large RAID LV (belong in different script?) +# Convert large 200 TiB linear to RAID1 (belong in different test script?) # -lvcreate --type raid1 -m 1 -L 200T -n $lv1 $vg1 --nosync +lvcreate -aey -L 200T -n $lv1 $vg1 +lvconvert -y --type raid1 -m 1 $vg1/$lv1 check lv_field $vg1/$lv1 size "200.00t" -lvextend -L +200T $vg1/$lv1 -check lv_field $vg1/$lv1 size "400.00t" +if [ $v1_9_0 -eq 1 ] ; then + # The 1.9.0 version of dm-raid is capable of performing + # linear -> RAID1 upconverts as "recover" not "resync" + # The LVM code now checks the dm-raid version when + # upconverting and if 1.9.0+ is found, it uses "recover" + check raid_leg_status $vg1 $lv1 "Aa" +else + check raid_leg_status $vg1 $lv1 "aa" +fi lvremove -ff $vg1 # bz837927 END -lvremove -ff $vg +vgremove -ff $vg1 diff --git a/test/shell/lvcreate-large-raid10.sh b/test/shell/lvcreate-large-raid10.sh index c9d4a2a..89eb0a6 100644 --- a/test/shell/lvcreate-large-raid10.sh +++ b/test/shell/lvcreate-large-raid10.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2012,2016 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 @@ -7,34 +8,46 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Exercise some lvcreate diagnostics' -. lib/test +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest -aux target_at_least dm-raid 1 3 0 || skip +# FIXME update test to make something useful on <16T +aux can_use_16T || skip +aux have_raid 1 3 0 || skip aux prepare_vg 5 -lvcreate -s -l 20%FREE -n $lv1 $vg --virtualsize 256T -lvcreate -s -l 20%FREE -n $lv2 $vg --virtualsize 256T -lvcreate -s -l 20%FREE -n $lv3 $vg --virtualsize 256T -lvcreate -s -l 20%FREE -n $lv4 $vg --virtualsize 256T -lvcreate -s -l 20%FREE -n $lv5 $vg --virtualsize 256T +# Fake ~2.5PiB volume group $vg1 via snapshot LVs +for device in "$lv1" "$lv2" "$lv3" "$lv4" "$lv5" +do + lvcreate --type snapshot -s -l 20%FREE -n $device $vg --virtualsize 520T +done -aux lvmconf 'devices/filter = [ "a/dev\/mapper\/.*$/", "a/dev\/LVMTEST/", "r/.*/" ]' +aux extend_filter_LVMTEST + +pvcreate "$DM_DEV_DIR"/$vg/${lv}[12345] +vgcreate $vg1 "$DM_DEV_DIR"/$vg/${lv}[12345] -pvcreate $DM_DEV_DIR/$vg/$lv[12345] -vgcreate -c n $vg1 $DM_DEV_DIR/$vg/$lv[12345] # -# Create large RAID LVs +# Create and extend large RAID10 LV # # We need '--nosync' or our virtual devices won't work lvcreate --type raid10 -m 1 -i 2 -L 200T -n $lv1 $vg1 --nosync check lv_field $vg1/$lv1 size "200.00t" -lvremove -ff $vg1 - -lvremove -ff $vg +lvextend -L +200T $vg1/$lv1 +check lv_field $vg1/$lv1 size "400.00t" +lvextend -L +100T $vg1/$lv1 +check lv_field $vg1/$lv1 size "500.00t" +lvextend -L 1P $vg1/$lv1 +check lv_field $vg1/$lv1 size "1.00p" + +vgremove -ff $vg1 +vgremove -ff $vg diff --git a/test/shell/lvcreate-large.sh b/test/shell/lvcreate-large.sh index b61ccca..473b0ed 100644 --- a/test/shell/lvcreate-large.sh +++ b/test/shell/lvcreate-large.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,34 +8,42 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Exercise some lvcreate diagnostics' -. lib/test +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# FIXME update test to make something useful on <16T +aux can_use_16T || skip aux prepare_vg 4 -lvcreate -s -l 100%FREE -n $lv $vg --virtualsize 1024T +lvcreate --type snapshot -s -l 100%FREE -n $lv $vg --virtualsize 1024T #FIXME this should be 1024T #check lv_field $vg/$lv size "128.00m" -aux lvmconf 'devices/filter = [ "a/dev\/mapper\/.*$/", "a/dev\/LVMTEST/", "r/.*/" ]' +aux extend_filter_LVMTEST -pvcreate $DM_DEV_DIR/$vg/$lv -vgcreate -c n $vg1 $DM_DEV_DIR/$vg/$lv +pvcreate "$DM_DEV_DIR/$vg/$lv" +vgcreate $vg1 "$DM_DEV_DIR/$vg/$lv" lvcreate -l 100%FREE -n $lv1 $vg1 -check lv_field $vg1/$lv1 size "1024.00t" +check lv_field $vg1/$lv1 size "1024.00t" --units t lvresize -f -l 72%VG $vg1/$lv1 -check lv_field $vg1/$lv1 size "737.28t" +check lv_field $vg1/$lv1 size "737.28t" --units t lvremove -ff $vg1/$lv1 lvcreate -l 100%VG -n $lv1 $vg1 -check lv_field $vg1/$lv1 size "1024.00t" +check lv_field $vg1/$lv1 size "1024.00t" --units t lvresize -f -l 72%VG $vg1/$lv1 -check lv_field $vg1/$lv1 size "737.28t" +check lv_field $vg1/$lv1 size "737.28t" --units t lvremove -ff $vg1/$lv1 lvremove -ff $vg/$lv + +vgremove -ff $vg diff --git a/test/shell/lvcreate-mirror.sh b/test/shell/lvcreate-mirror.sh index 1f95387..1cec4c5 100644 --- a/test/shell/lvcreate-mirror.sh +++ b/test/shell/lvcreate-mirror.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,35 +8,36 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest -. lib/test aux prepare_vg 5 80 -aux lvmconf 'allocation/maximise_cling = 0' -aux lvmconf 'allocation/mirror_logs_require_separate_pvs = 1' +aux lvmconf 'allocation/maximise_cling = 0' \ + 'allocation/mirror_logs_require_separate_pvs = 1' # 2-way mirror with corelog, 2 PVs -lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg "$dev1" "$dev2" +lvcreate -aey -l2 --type mirror -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 +# lvcreate --nosync is in 100% sync after creation (bz429342) +lvcreate -aey -l2 --type mirror -m1 --nosync -n $lv2 $vg "$dev1" "$dev2" "$dev3":0-1 2>&1 | tee out +grep "New mirror won't be synchronized." out +check lv_field $vg/$lv2 copy_percent "100.00" +check mirror_images_redundant $vg $lv2 +check mirror_log_on $vg $lv2 "$dev3" # 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 +lvcreate -aey -l2 --type mirror -m2 --nosync --mirrorlog disk -n $lv3 $vg "$dev1" "$dev2" "$dev4" "$dev3":0-1 +check mirror_images_redundant $vg $lv3 +check mirror_log_on $vg $lv3 "$dev3" lvremove -ff $vg # creating 2-way mirror with disklog from 2 PVs fails -not lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" +not lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" + +vgremove -ff $vg diff --git a/test/shell/lvcreate-missing.sh b/test/shell/lvcreate-missing.sh new file mode 100644 index 0000000..18c979f --- /dev/null +++ b/test/shell/lvcreate-missing.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 2 + +aux disable_dev "$dev1" + +not lvcreate -n "foo" $vg -l 1 + +aux enable_dev "$dev1" + +vgremove -ff $vg diff --git a/test/shell/lvcreate-operation.sh b/test/shell/lvcreate-operation.sh index 0ef3138..568af36 100644 --- a/test/shell/lvcreate-operation.sh +++ b/test/shell/lvcreate-operation.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008,2018 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 @@ -7,11 +8,16 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Exercise some lvcreate diagnostics' -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux lvmconf "global/support_mirrored_mirror_log=1" cleanup_lvs() { lvremove -ff $vg @@ -20,22 +26,38 @@ cleanup_lvs() { } aux prepare_pvs 2 +get_devs + aux pvcreate --metadatacopies 0 "$dev1" -aux vgcreate -c n $vg $(cat DEVICES) +aux vgcreate $SHARED "$vg" "${DEVICES[@]}" # --- # Create snapshots of LVs on --metadatacopies 0 PV (bz450651) -lvcreate -n$lv1 -l4 $vg "$dev1" +lvcreate -aey -n$lv1 -l4 $vg "$dev1" lvcreate -n$lv2 -l4 -s $vg/$lv1 lvcreate -n$lv3 -l4 --permission r -s $vg/$lv1 cleanup_lvs +# Skip the rest for cluster +if test -e LOCAL_CLVMD; then + +# --- +# Create mirror on two devices with mirrored log using --alloc anywhere - should always fail in cluster +not lvcreate --type mirror -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere "$dev1" "$dev2" +cleanup_lvs + +else + # --- # Create mirror on two devices with mirrored log using --alloc anywhere -lvcreate -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere "$dev1" "$dev2" +lvcreate --type mirror -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" +not lvcreate --type mirror -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere "$dev1" cleanup_lvs + +fi + +vgremove -ff $vg diff --git a/test/shell/lvcreate-pvtags.sh b/test/shell/lvcreate-pvtags.sh index 806fff1..b794c45 100644 --- a/test/shell/lvcreate-pvtags.sh +++ b/test/shell/lvcreate-pvtags.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,19 +8,23 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_pvs 3 -aux lvmconf 'allocation/maximise_cling = 0' -aux lvmconf 'allocation/mirror_logs_require_separate_pvs = 1' +get_devs + +aux lvmconf 'allocation/maximise_cling = 0' \ + 'allocation/mirror_logs_require_separate_pvs = 1' # not required, just testing aux pvcreate --metadatacopies 0 "$dev1" -vgcreate -c n $vg $(cat DEVICES) -pvchange --addtag fast $(cat DEVICES) +vgcreate $SHARED "$vg" "${DEVICES[@]}" +pvchange --addtag fast "${DEVICES[@]}" # 3 stripes with 3 PVs (selected by tag, @fast) is fine lvcreate -l3 -i3 $vg @fast @@ -28,21 +33,21 @@ lvcreate -l3 -i3 $vg @fast 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 +not lvcreate -l2 -i2 $vg "$DM_DEV_DIR/mapper/pv1" # lvcreate mirror -lvcreate -l1 -m1 $vg @fast +lvcreate -aey -l1 --type mirror -m1 --nosync $vg @fast # lvcreate mirror w/corelog -lvcreate -l1 -m2 --corelog $vg @fast +lvcreate -aey -l1 --type mirror -m2 --corelog --nosync $vg @fast # lvcreate mirror w/no free PVs -not lvcreate -l1 -m2 $vg @fast +not lvcreate -aey -l1 --type mirror -m2 $vg @fast # lvcreate mirror (corelog, w/no free PVs) -not lvcreate -l1 -m3 --corelog $vg @fast +not lvcreate -aey -l1 --type mirror -m3 --corelog $vg @fast # lvcreate mirror with a single PV arg -not lvcreate -l1 -m1 --corelog $vg "$dev1" +not lvcreate -aey -l1 --type mirror -m1 --corelog $vg "$dev1" vgremove -ff $vg diff --git a/test/shell/lvcreate-raid-nosync.sh b/test/shell/lvcreate-raid-nosync.sh new file mode 100644 index 0000000..2818e94 --- /dev/null +++ b/test/shell/lvcreate-raid-nosync.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 7 0 || skip + +segtypes="raid5" +aux have_raid4 && segtypes="raid4 $segtypes" + +aux prepare_vg 6 + +_sync() { + aux enable_dev "$dev1" + + aux wait_for_sync $vg $lv1 + test -z "$1" || check raid_leg_status $vg $lv1 $1 + lvremove --yes $vg/$lv1 + + # restore to delay_dev tables for all devices + aux restore_from_devtable "$dev1" +} + +# Workaround for raid targets returning 'a' shortly after initialization +# TODO: maybe there is some workaround to be made on lvm side +_check_raid_in_loop() { + local vg=$1 + local lv=$2 + local health=$3 + for i in {1..10} ; do + check raid_leg_status $vg $lv ${health} && return 0 + sleep .05 + done + die "Cannot get $A status for $vg/$lv"; +} + +# Delay 1st leg so that rebuilding status characters +# can be read before resync finished too quick. +aux delay_dev "$dev1" 0 100 "$(get first_extent_sector "$dev1")" + +# raid0/raid0_meta don't support resynchronization +for r in raid0 raid0_meta +do + lvcreate --type $r -Zn -i 3 -l 1 -n $lv1 $vg + _check_raid_in_loop $vg $lv1 "AAA" + lvremove --yes $vg/$lv1 +done + +# raid1 supports resynchronization +lvcreate --type raid1 -m 2 -Zn -l 4 -n $lv1 $vg +should check raid_leg_status $vg $lv1 "aaa" +_sync "AAA" + +# raid1 supports --nosync +lvcreate --type raid1 --nosync -Zn -m 2 -l 1 -n $lv1 $vg +_check_raid_in_loop $vg $lv1 "AAA" +lvremove --yes $vg/$lv1 + +for r in $segtypes +do + # raid4/5 support resynchronization + lvcreate --type $r -Zn -i 3 -L10 -n $lv1 $vg + should check raid_leg_status $vg $lv1 "aaaa" + _sync "AAAA" + + # raid4/5 support --nosync + lvcreate --type $r -Zn --nosync -i 3 -l 1 -n $lv2 $vg + _check_raid_in_loop $vg $lv2 "AAAA" + lvremove --yes $vg +done + +# raid6 supports resynchronization +lvcreate --type raid6 -Zn -i 3 -l 4 -n $lv1 $vg +should check raid_leg_status $vg $lv1 "aaaaa" +_sync "AAAAA" + +# raid6 rejects --nosync; it has to initialize P- and Q-Syndromes +not lvcreate --type raid6 --nosync -Zn -i 3 -l 1 -n $lv1 $vg + +# raid10 supports resynchronization +lvcreate --type raid10 -m 1 -Zn -i 3 -L10 -n $lv1 $vg +should check raid_leg_status $vg $lv1 "aaaaaa" +_sync "AAAAAA" + +# raid10 supports --nosync +lvcreate --type raid10 --nosync -m 1 -Zn -i 3 -l 1 -n $lv1 $vg +_check_raid_in_loop $vg $lv1 "AAAAAA" + +vgremove -ff $vg diff --git a/test/shell/lvcreate-raid-volume_list.sh b/test/shell/lvcreate-raid-volume_list.sh new file mode 100644 index 0000000..052cf19 --- /dev/null +++ b/test/shell/lvcreate-raid-volume_list.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +# bz1161347 - When raid creation is aborted, left-over devices appear + +. lib/inittest + +######################################################## +# MAIN +######################################################## +aux have_raid 1 3 0 || skip + +aux prepare_pvs 2 # 2 devices for RAID1 +get_devs +vgcreate $SHARED -s 512k "$vg" "${DEVICES[@]}" + +aux lvmconf "activation/volume_list = [ \"vg_not_exist\" ]" + +########################################################## +# Create 2-way raid1 which fails due to $vg not listed on +# activation/volume_list. Check for any (Sub)LV remnants. +########################################################## +not lvcreate --yes --type raid1 -l 2 -n $lv $vg +check lv_not_exists $vg/${lv}_rmeta_0 +check lv_not_exists $vg/${lv}_rmeta_1 +check lv_not_exists $vg/${lv}_rimage_0 +check lv_not_exists $vg/${lv}_rimage_1 +check lv_not_exists $vg/$lv + +vgremove -ff $vg diff --git a/test/shell/lvcreate-raid.sh b/test/shell/lvcreate-raid.sh index 05c7428..b605443 100644 --- a/test/shell/lvcreate-raid.sh +++ b/test/shell/lvcreate-raid.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2011-2016 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 @@ -7,22 +8,33 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest + +lv_devices() { + test "$3" -eq "$(get lv_devices "$1/$2" | wc -w)" +} ######################################################## # MAIN ######################################################## -aux target_at_least dm-raid 1 1 0 || skip +aux have_raid 1 3 0 || skip + +RAID4="" +aux have_raid4 && RAID4=raid4 aux prepare_pvs 6 20 # 6 devices for RAID10 (2-mirror,3-stripe) test -vgcreate -c n -s 512k $vg $(cat DEVICES) +get_devs + +vgcreate $SHARED -s 512k "$vg" "${DEVICES[@]}" ########################################### # Create, wait for sync, remove tests ########################################### - # Create RAID1 (implicit 2-way) lvcreate --type raid1 -l 2 -n $lv1 $vg aux wait_for_sync $vg $lv1 @@ -38,8 +50,17 @@ lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg aux wait_for_sync $vg $lv1 lvremove -ff $vg +# Create RAID1 (explicit 3-way) - Set min/max recovery rate +lvcreate --type raid1 -m 2 -l 2 \ + --minrecoveryrate 50 --maxrecoveryrate 1M \ + -n $lv1 $vg +check lv_field $vg/$lv1 raid_min_recovery_rate 50 +check lv_field $vg/$lv1 raid_max_recovery_rate 1024 +aux wait_for_sync $vg $lv1 +lvremove -ff $vg + # Create RAID 4/5/6 (explicit 3-stripe + parity devs) -for i in raid4 \ +for i in $RAID4 \ raid5 raid5_ls raid5_la raid5_rs raid5_ra \ raid6 raid6_zr raid6_nr raid6_nc; do @@ -47,3 +68,143 @@ for i in raid4 \ aux wait_for_sync $vg $lv1 lvremove -ff $vg done + +# Create RAID 4/5/6 (explicit 3-stripe + parity devs) - Set min/max recovery +for i in $RAID4 \ + raid5 raid5_ls raid5_la raid5_rs raid5_ra \ + raid6 raid6_zr raid6_nr raid6_nc; do + + lvcreate --type $i -l 3 -i 3 \ + --minrecoveryrate 50 --maxrecoveryrate 1M \ + -n $lv1 $vg + check lv_field $vg/$lv1 raid_min_recovery_rate 50 + check lv_field $vg/$lv1 raid_max_recovery_rate 1024 + aux wait_for_sync $vg $lv1 + lvremove -ff $vg +done + +# Create RAID using 100%FREE +############################ +# 6 PVs with 19m in each PV. +# 1 metadata LV = 1 extent = .5m +# 1 image = 37+38+38 extents = 56.50m = lv_size +lvcreate --type raid1 -m 1 -l 100%FREE -an -Zn -n raid1 $vg +check lv_field $vg/raid1 size "56.50m" +lvremove -ff $vg + +# 1 metadata LV = 1 extent +# 1 image = 37 extents = 18.5m +# 5 images = 185 extents = 92.5m = lv_size +lvs -a $vg +lvcreate --type raid5 -i 5 -l 100%FREE -an -Zn -n raid5 $vg +check lv_field $vg/raid5 size "92.50m" +lvremove -ff $vg + +# 1 image = 37+38 extents +# 2 images = 150 extents = 75.00m = lv_size +lvcreate --type raid5 -i 2 -l 100%FREE -an -Zn -n raid5 $vg +check lv_field $vg/raid5 size "75.00m" +lvremove -ff $vg + +# 1 image = 37 extents +# 4 images = 148 extents = 74.00m = lv_size +lvcreate --type raid6 -i 4 -l 100%FREE -an -Zn -n raid6 $vg +check lv_field $vg/raid6 size "74.00m" +lvremove -ff $vg + +### +# For following tests eat 18 of 37 extents from dev1, leaving 19 +lvcreate -l 18 -an -Zn -n eat_space $vg "$dev1" +EAT_SIZE=$(get lv_field $vg/eat_space size) + +# Using 100% free should take the rest of dev1 and equal from dev2 +# 1 meta takes 1 extent +# 1 image = 19 extents = 9.50m = lv_size +lvcreate --type raid1 -m 1 -l 100%FREE -an -Zn -n raid1 $vg "$dev1" "$dev2" +check lv_field $vg/raid1 size "9.50m" +# Ensure image size is the same as the RAID1 size +check lv_field $vg/raid1 size "$(get lv_field $vg/raid1_rimage_0 size -a)" +# Amount remaining in dev2 should equal the amount taken by 'lv' in dev1 +check pv_field "$dev2" pv_free "$EAT_SIZE" +lvremove -ff $vg/raid1 + +# Using 100% free should take the rest of dev1 and equal amount from the rest +# 1 meta takes 1 extent +# 1 image = 19 extents = 9.50m +# 5 images = 95 extents = 47.50m = lv_size +lvcreate --type raid5 -i 5 -l 100%FREE -an -Zn -n raid5 $vg +check lv_field $vg/raid5 size "47.50m" +# Amount remaining in dev6 should equal the amount taken by 'lv' in dev1 +check pv_field "$dev6" pv_free "$EAT_SIZE" +lvremove -ff $vg/raid5 + +# Using 100% free should take the rest of dev1, an equal amount +# from 2 more devs, and all extents from 3 additional devs +# 1 meta takes 1 extent +# 1 image = 19+39 extents +# 2 images = 114 extents = 57.00m = lv_size +lvcreate --type raid5 -i 2 -l 100%FREE -an -Zn -n raid5 $vg +check lv_field $vg/raid5 size "57.00m" +lvremove -ff $vg/raid5 + +# Let's do some stripe tests too +# Using 100% free should take the rest of dev1 and an equal amount from rest +# 1 image = 20 extents +# 6 images = 120 extents = 60.00m = lv_size +lvcreate -i 6 -l 100%FREE -an -Zn -n stripe $vg +check lv_field $vg/stripe size "60.00m" +lvremove -ff $vg/stripe + +# Using 100% free should take the rest of dev1, an equal amount from +# one more dev, and all of the remaining 4 +# 1 image = 20+38+38 extents +# 2 images = 192 extents = 96.00m = lv_size +lvcreate -i 2 -l 100%FREE -an -Zn -n stripe $vg +check lv_field $vg/stripe size "96.00m" + +lvremove -ff $vg +# end of use of '$vg/eat_space' +### + +# Create RAID (implicit stripe count based on PV count) +####################################################### + +# Not enough drives +not lvcreate --type raid1 -l1 $vg "$dev1" +not lvcreate --type raid5 -l2 $vg "$dev1" "$dev2" +not lvcreate --type raid6 -l3 $vg "$dev1" "$dev2" "$dev3" "$dev4" + +# Implicit count comes from #PVs given (always 2 for mirror though) +lvcreate --type raid1 -l1 -an -Zn -n raid1 $vg "$dev1" "$dev2" +lv_devices $vg raid1 2 +lvcreate --type raid5 -l2 -an -Zn -n raid5 $vg "$dev1" "$dev2" "$dev3" +lv_devices $vg raid5 3 +lvcreate --type raid6 -l3 -an -Zn -n raid6 $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" +lv_devices $vg raid6 5 +lvremove -ff $vg + +# Implicit count comes from total #PVs in VG (always 2 for mirror though) +# Defaults -i2 even though more PVs listed +lvcreate --type raid1 -l1 -an -Zn -n raid1 $vg +lv_devices $vg raid1 2 +lvcreate --type raid5 -l2 -an -Zn -n raid5 $vg +lv_devices $vg raid5 3 +lvcreate --type raid6 -l3 -an -Zn -n raid6 $vg +lv_devices $vg raid6 5 +lvremove -ff $vg + + +######################################################## +# Try again with backward compatible old logic applied # +######################################################## +aux lvmconf 'allocation/raid_stripe_all_devices = 1' + +# Implicit count comes from total #PVs in VG (always 2 for mirror though) +lvcreate --type raid1 -l1 -an -Zn -n raid1 $vg +lv_devices $vg raid1 2 +lvcreate --type raid5 -l2 -an -Zn -n raid5 $vg +lv_devices $vg raid5 6 +lvcreate --type raid6 -l3 -an -Zn -n raid6 $vg +lv_devices $vg raid6 6 + +vgremove -ff $vg diff --git a/test/shell/lvcreate-raid1-read-error.sh b/test/shell/lvcreate-raid1-read-error.sh new file mode 100644 index 0000000..f9c6bb9 --- /dev/null +++ b/test/shell/lvcreate-raid1-read-error.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 0 || skip + +# Test for MD raid1 kernel bug causing read +# errors on failing first leg sectors. + +# Create VG with 2 PVs +aux prepare_vg 2 2 + +# Create 2-legged raid1 LV +lvcreate --yes --type raid1 --mirrors 1 --extents 1 --name $lv $vg +aux wait_for_sync $vg $lv + +aux error_dev "$dev1" 20:500 + +dd if="$DM_DEV_DIR/$vg/$lv" iflag=direct,fullblock of=/dev/zero bs=128K count=1 + +vgremove --force $vg diff --git a/test/shell/lvcreate-raid10.sh b/test/shell/lvcreate-raid10.sh index 63d086f..39069af 100644 --- a/test/shell/lvcreate-raid10.sh +++ b/test/shell/lvcreate-raid10.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2012-2016 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 @@ -7,36 +8,90 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest -. lib/test +lv_devices() { + test "$3" -eq "$(get lv_devices "$1/$2" | wc -w)" +} ######################################################## # MAIN ######################################################## -aux target_at_least dm-raid 1 3 0 || skip - -aux prepare_pvs 6 20 # 6 devices for RAID10 (2-mirror,3-stripe) test -vgcreate -c n -s 512k $vg $(cat DEVICES) +aux have_raid 1 3 0 || skip +aux prepare_vg 6 20 # 6 devices for RAID10 (2-mirror,3-stripe) test # # Create RAID10: # - # Should not allow more than 2-way mirror not lvcreate --type raid10 -m 2 -i 2 -l 2 -n $lv1 $vg # 2-way mirror, 2-stripes lvcreate --type raid10 -m 1 -i 2 -l 2 -n $lv1 $vg aux wait_for_sync $vg $lv1 -lvremove -ff $vg +lvremove -ff $vg/$lv1 -# 2-way mirror, 3-stripes -lvcreate --type raid10 -m 1 -i 3 -l 3 -n $lv1 $vg +# 2-way mirror, 2-stripes - Set min/max recovery rate +lvcreate --type raid10 -m 1 -i 2 -l 2 \ + --minrecoveryrate 50 --maxrecoveryrate 1M \ + -n $lv1 $vg +check lv_field $vg/$lv1 raid_min_recovery_rate 50 +check lv_field $vg/$lv1 raid_max_recovery_rate 1024 aux wait_for_sync $vg $lv1 + +# 2-way mirror, 3-stripes +lvcreate --type raid10 -m 1 -i 3 -l 3 -n $lv2 $vg +aux wait_for_sync $vg $lv2 + +lvremove -ff $vg + +# Test 100%FREE option +# 38 extents / device +# 1 image = 37 extents (1 for meta) +# 3 images = 111 extents = 55.50m +lvcreate --type raid10 -i 3 -l 100%FREE -an -Zn -n raid10 $vg +check lv_field $vg/raid10 size "55.50m" +lvremove -ff $vg + +# Create RAID (implicit stripe count based on PV count) +####################################################### + +# Not enough drives +not lvcreate --type raid10 -l2 $vg "$dev1" "$dev2" "$dev3" + +# Implicit count comes from #PVs given (always 2-way mirror) +# Defaults -i2, which works with 4 PVs listed +lvcreate --type raid10 -l2 -an -Zn -n raid10 $vg "$dev1" "$dev2" "$dev3" "$dev4" +lv_devices $vg raid10 4 + +# Defaults -i2 even though more PVs listed +lvcreate --type raid10 -l2 -an -Zn -n raid10_6 $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" +lv_devices $vg raid10_6 4 + lvremove -ff $vg # # FIXME: Add tests that specify particular PVs to use for creation # + + +######################################################## +# Try again with backward compatible old logic applied # +######################################################## +aux lvmconf 'allocation/raid_stripe_all_devices = 1' + +# Implicit count comes from #PVs given (always 2-way mirror) +lvcreate --type raid10 -l2 -an -Zn -n raid10 $vg "$dev1" "$dev2" "$dev3" "$dev4" +lv_devices $vg raid10 4 + +# Implicit count comes from total #PVs in VG (always 2 for mirror though) +lvcreate --type raid10 -l2 -an -Zn -n raid10_vg $vg +lv_devices $vg raid10_vg 6 + +vgremove -ff $vg diff --git a/test/shell/lvcreate-repair.sh b/test/shell/lvcreate-repair.sh index 8971536..07263a3 100644 --- a/test/shell/lvcreate-repair.sh +++ b/test/shell/lvcreate-repair.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,9 +8,11 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_vg 3 @@ -19,7 +22,7 @@ for i in "$dev1" "$dev2" "$dev3" ; do if test "$i" = "$j" ; then continue ; fi vgremove -ff $vg - vgcreate $vg "$dev1" "$dev2" "$dev3" + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" # exit 1 lvcreate -l1 -n $lv1 $vg "$dev1" @@ -29,7 +32,7 @@ for i in "$dev1" "$dev2" "$dev3" ; do vgreduce --removemissing --force $vg # check if reduced device was removed - test "$i" = "$dev1" && dm_table | not egrep "$vg-$lv1: *[^ ]+" + test "$i" = "$dev1" && dm_table | not grep -E "$vg-$lv1: *[^ ]+" lvcreate -l1 -n $lv2 $vg @@ -45,7 +48,7 @@ for i in "$dev1" "$dev2" "$dev3" ; do done vgremove -ff $vg -vgcreate $vg "$dev1" "$dev2" "$dev3" +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" # use tricky 'dd' for i in "$dev1" "$dev2" "$dev3" ; do @@ -85,7 +88,6 @@ dd if=backup_i of="$dev1" bs=256K count=1 # dirty game dd if=/dev/zero of="$dev3" bs=256K count=1 -aux notify_lvmetad "$dev3" # udev be watching you vgreduce --removemissing --force $vg @@ -97,3 +99,6 @@ vgreduce --removemissing --force $vg # Failed to activate new LV. should lvcreate -l1 $vg "$dev1" +should not dmsetup remove ${vg}-lvol0 + +vgremove -ff $vg diff --git a/test/shell/lvcreate-signature-wiping.sh b/test/shell/lvcreate-signature-wiping.sh new file mode 100644 index 0000000..4893d9a --- /dev/null +++ b/test/shell/lvcreate-signature-wiping.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# 'Exercise signature wiping during lvcreate' + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +init_lv_() { + mkswap "$DM_DEV_DIR/$vg/$lv1" +} + +test_blkid_() { + local type + type=$(blkid -s TYPE -o value -c /dev/null "$DM_DEV_DIR/$vg/$lv1") + test "$type" = "swap" +} + +test_msg_() { + grep "Wiping swap signature" out +} + +aux prepare_vg + +# lvcreate wipes signatures when found on newly created LV - test this on "swap". +# Test all combinatios with -Z{y|n} and -W{y|n} and related lvm.conf settings. + +lvcreate -l1 -n $lv1 $vg +init_lv_ +# This system has unusable blkid (does not recognize small swap, needs fix...) +test_blkid_ || skip +lvremove -f $vg/$lv1 + +# Zeroing stops the command when there is a failure (write error in this case) +aux error_dev "$dev1" "$(get first_extent_sector "$dev1"):8" +not lvcreate -l1 -n $lv1 $vg 2>&1 | tee out +grep "Failed to initialize" out +aux enable_dev "$dev1" + + +aux lvmconf "allocation/wipe_signatures_when_zeroing_new_lvs = 0" + +lvcreate -y -Zn -l1 -n $lv1 $vg 2>&1 | tee out +not test_msg_ +test_blkid_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zn -Wn -l1 -n $lv1 $vg 2>&1 | tee out +not test_msg_ +test_blkid_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zn -Wy -l1 -n $lv1 $vg 2>&1 | tee out +test_msg_ +not test_blkid_ +init_lv_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zy -l1 -n $lv1 $vg 2>&1 | tee out +not test_msg_ +not test_blkid_ +init_lv_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zy -Wn -l1 -n $lv1 $vg 2>&1 | tee out +not test_msg_ +not test_blkid_ +init_lv_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zy -Wy -l1 -n $lv1 $vg 2>&1 | tee out +test_msg_ +not test_blkid_ +init_lv_ +lvremove -f $vg/$lv1 + + +aux lvmconf "allocation/wipe_signatures_when_zeroing_new_lvs = 1" + +lvcreate -y -Zn -l1 -n $lv1 $vg 2>&1 | tee out +not test_msg_ +test_blkid_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zn -Wn -l1 -n $lv1 $vg 2>&1 | tee out +not test_msg_ +test_blkid_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zn -Wy -l1 -n $lv1 $vg 2>&1 | tee out +test_msg_ +not test_blkid_ +init_lv_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zy -l1 -n $lv1 $vg 2>&1 | tee out +test_msg_ +not test_blkid_ +init_lv_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zy -Wn -l1 -n $lv1 $vg 2>&1 | tee out +not test_msg_ +not test_blkid_ +init_lv_ +lvremove -f $vg/$lv1 + +lvcreate -y -Zy -Wy -l1 -n $lv1 $vg 2>&1 | tee out +test_msg_ +not test_blkid_ +init_lv_ +lvremove -f $vg/$lv1 + +vgremove -f $vg diff --git a/test/shell/lvcreate-small-snap.sh b/test/shell/lvcreate-small-snap.sh index 9b43868..09237ec 100644 --- a/test/shell/lvcreate-small-snap.sh +++ b/test/shell/lvcreate-small-snap.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2010 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2010-2014 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 @@ -7,24 +8,31 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 -aux prepare_pvs 3 +. lib/inittest -vgcreate -c n -s 1k $vg $(cat DEVICES) +aux prepare_pvs +get_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 +vgcreate $SHARED -s 4k "$vg" "${DEVICES[@]}" + +# 3 Chunks +lvcreate -aey -n one -l 10 $vg +lvcreate -s -l 3 -n snapA $vg/one +lvcreate -s -c 4k -l 3 -n snapX1 $vg/one +lvcreate -s -c 8k -l 6 -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 lvcreate -s -c 8k -l 2 -n snapX3 $vg/one 2>&1 | tee lvcreate.out not grep "suspend origin one" lvcreate.out -grep "Unable to create a snapshot" lvcreate.out +grep "smaller" lvcreate.out -not lvcreate -s -l 4 -n snapB $vg/one 2>&1 | tee lvcreate.out +not lvcreate -s -l 1 -n snapB $vg/one 2>&1 | tee lvcreate.out not grep "suspend origin one" lvcreate.out -grep "Unable to create a snapshot" lvcreate.out +grep "smaller" lvcreate.out + +vgremove -ff $vg diff --git a/test/shell/lvcreate-striped-mirror.sh b/test/shell/lvcreate-striped-mirror.sh index 9a55a97..b960522 100644 --- a/test/shell/lvcreate-striped-mirror.sh +++ b/test/shell/lvcreate-striped-mirror.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,59 +8,52 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest -. lib/test aux prepare_vg 9 -lvcreate -i2 -l2 -m1 --mirrorlog core -n $lv1 $vg 2>&1 | tee log +lvcreate -aey --nosync -i2 -l2 --type mirror -m1 --mirrorlog core -n $lv1 $vg 2>&1 | tee log not grep "Rounding" log check mirror_images_redundant $vg $lv1 -lvremove -ff $vg -lvcreate -i2 -l4 -m1 --mirrorlog core -n $lv1 $vg 2>&1 | tee log +lvcreate -aey --nosync -i2 -l4 --type mirror -m1 --mirrorlog core -n $lv2 $vg 2>&1 | tee log not grep "Rounding" log -check mirror_images_redundant $vg $lv1 -lvremove -ff $vg +check mirror_images_redundant $vg $lv2 -lvcreate -i3 -l3 -m1 --mirrorlog core -n $lv1 $vg 2>&1 | tee log +lvcreate -aey --nosync -i3 -l3 --type mirror -m1 --mirrorlog core -n $lv3 $vg 2>&1 | tee log not grep "Rounding" log -check mirror_images_redundant $vg $lv1 -lvremove -ff $vg +check mirror_images_redundant $vg $lv3 -lvcreate -i4 -l4 -m1 --mirrorlog core -n $lv1 $vg 2>&1 | tee log +lvcreate -aey --nosync -i4 -l4 --type mirror -m1 --mirrorlog core -n $lv4 $vg 2>&1 | tee log not grep "Rounding" log -check mirror_images_redundant $vg $lv1 -lvremove -ff $vg +check mirror_images_redundant $vg $lv4 - -lvcreate -i2 -l2 -m2 --mirrorlog core -n $lv1 $vg 2>&1 | tee log +lvcreate -aey --nosync -i2 -l2 --type mirror -m2 --mirrorlog core -n $lv5 $vg 2>&1 | tee log not grep "Rounding" log -check mirror_images_redundant $vg $lv1 -lvremove -ff $vg +check mirror_images_redundant $vg $lv5 -lvcreate -i3 -l3 -m2 --mirrorlog core -n $lv1 $vg 2>&1 | tee log +lvcreate -aey --nosync -i3 -l3 --type mirror -m2 --mirrorlog core -n $lv6 $vg 2>&1 | tee log not grep "Rounding" log -check mirror_images_redundant $vg $lv1 -lvremove -ff $vg +check mirror_images_redundant $vg $lv6 -lvcreate -i2 -l2 -m3 --mirrorlog core -n $lv1 $vg 2>&1 | tee log +lvcreate -aey --nosync -i2 -l2 --type mirror -m3 --mirrorlog core -n $lv7 $vg 2>&1 | tee log not grep "Rounding" log -check mirror_images_redundant $vg $lv1 -lvremove -ff $vg +check mirror_images_redundant $vg $lv7 -lvcreate -i3 -l2 -m2 --mirrorlog core -n $lv1 $vg 2>&1 | tee log -grep "Rounding size (2 extents) up to .* (3 extents)" log lvremove -ff $vg -lvcreate -i3 -l4 -m2 --mirrorlog core -n $lv1 $vg 2>&1 | tee log -grep "Rounding size (4 extents) up to .* (6 extents)" log -lvremove -ff $vg +lvcreate -aey --nosync -i3 -l4 --type mirror -m1 --mirrorlog core -n $lv1 $vg 2>&1 | tee log +grep "Rounding size .*(4 extents) up to .*(6 extents)" log -lvcreate -i3 -l4 -m1 --mirrorlog core -n $lv1 $vg 2>&1 | tee log -grep "Rounding size (4 extents) up to .* (6 extents)" log -lvremove -ff $vg +lvcreate -aey --nosync -i3 -l4 --type mirror -m2 --mirrorlog core -n $lv2 $vg 2>&1 | tee log +grep "Rounding size .*(4 extents) up to .*(6 extents)" log + +lvcreate -aey --nosync -i3 -l2 --type mirror -m2 --mirrorlog core -n $lv3 $vg 2>&1 | tee log +grep "Rounding size .*(2 extents) up to .*(3 extents)" log -lvcreate -i4 -l4 -m1 --mirrorlog core -n $lv1 $vg 2>&1 | tee log -not grep "Rounding" log lvremove -ff $vg diff --git a/test/shell/lvcreate-thin-big.sh b/test/shell/lvcreate-thin-big.sh new file mode 100644 index 0000000..bdb5942 --- /dev/null +++ b/test/shell/lvcreate-thin-big.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test currently needs to drop +# 'return NULL' in _lv_create_an_lv after log_error("Can't create %s without using " + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip + +# Test --poolmetadatasize range +# allocating large devices for testing +aux prepare_pvs 10 16500 +get_devs + +vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}" + +# Size 0 is not valid +invalid lvcreate -L4M --chunksize 128 --poolmetadatasize 0 -T $vg/pool1 2>out +lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 >out 2>&1 +grep -i "minimal" out +# FIXME: metadata allocation fails, if PV doesn't have at least 16GB +# i.e. pool metadata device cannot be multisegment +lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 >out 2>&1 +grep "maximum" out +check lv_field $vg/pool1_tmeta size "2.00m" +check lv_field $vg/pool2_tmeta size "<15.88g" + +# Check we do report correct percent values. +lvcreate --type zero -L3G $vg -n pool3 +lvconvert -y --thinpool $vg/pool3 +lvchange --errorwhenfull y $vg/pool3 +lvchange --zero n $vg/pool3 +lvcreate -V10G $vg/pool3 -n $lv1 +lvcreate -V2G $vg/pool3 -n $lv2 +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=512b count=1 conv=fdatasync +# ...excercise write speed to 'zero' device ;) +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv2" bs=64K count=32767 oflag=direct +lvs -a $vg +# Check the percentage is not shown as 0.00 +check lv_field $vg/$lv1 data_percent "0.01" +# Check the percentage is not shown as 100.00 +check lv_field $vg/$lv2 data_percent "99.99" + + +# Check can start and see thinpool with metadata size above kernel limit +lvcreate -L4M --poolmetadatasize 16G -T $vg/poolM +check lv_field $vg/poolM data_percent "0.00" + +lvremove -ff $vg + +# Test automatic calculation of pool metadata size +lvcreate -L160G -T $vg/pool +check lv_field $vg/pool lv_metadata_size "80.00m" +check lv_field $vg/pool chunksize "128.00k" +lvremove -ff $vg/pool + +lvcreate -L10G --chunksize 256 -T $vg/pool1 +lvcreate -L60G --chunksize 1024 -T $vg/pool2 +check lv_field $vg/pool1_tmeta size "2.50m" +check lv_field $vg/pool2_tmeta size "3.75m" +lvremove -ff $vg + +# Test chunk size is rounded to power-of-2 +lvcreate -L10G --poolmetadatasize 4M -T $vg/pool +check lv_field $vg/pool chunk_size "256.00k" + +# Old thinpool target required rounding to power of 2 +aux lvmconf "global/thin_disabled_features = [ \"block_size\" ]" +lvcreate -L10G --poolmetadatasize 4M -T $vg/pool_old +check lv_field $vg/pool_old chunk_size "256.00k" +lvremove -ff $vg +# reset +#aux lvmconf "global/thin_disabled_features = []" + +vgremove -ff $vg diff --git a/test/shell/lvcreate-thin-cache.sh b/test/shell/lvcreate-thin-cache.sh new file mode 100644 index 0000000..f87526a --- /dev/null +++ b/test/shell/lvcreate-thin-cache.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise caching thin-pool's data LV + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 0 0 || skip +aux have_cache 1 3 0 || skip + +which mkfs.ext4 || skip + +aux prepare_pvs 2 64 +get_devs + +vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}" + +lvcreate -L10M -V10M -T $vg/pool --name $lv1 + +lvcreate -H -L10 $vg/pool + +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + +lvconvert --uncache $vg/pool +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +lvcreate -H -L10 $vg/pool_tdata +fsck -n "$DM_DEV_DIR/$vg/$lv1" +lvconvert --uncache $vg/pool_tdata + +vgremove -ff $vg diff --git a/test/shell/lvcreate-thin-external-size.sh b/test/shell/lvcreate-thin-external-size.sh new file mode 100644 index 0000000..862dd15 --- /dev/null +++ b/test/shell/lvcreate-thin-external-size.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test unaligned size of external origin and thin pool chunk size + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +which cmp || skip + +# +# Main +# + +# Test needs thin-pool target with unaligned ext-orig size support +aux have_thin 1 13 0 || skip + +aux prepare_pvs 2 640 +get_devs + +# Use 8K extent size +vgcreate $SHARED -s 8K "$vg" "${DEVICES[@]}" + +# Prepare some numeric pattern with ~64K size +seq -s ' ' -w 0 10922 > 64K + +d1="$DM_DEV_DIR/$vg/$lv1" +d2="$DM_DEV_DIR/$vg/$lv2" + +# Prepare external origin LV with size not being a multiple of thin pool chunk size +lvcreate -l47 -n $lv1 $vg + +# Fill end with pattern +dd if=64K of="$d1" bs=8192 seek=45 count=2 conv=fdatasync + +# Switch to read-only volume +lvchange -an $vg/$lv1 +lvchange -pr $vg/$lv1 + +lvcreate -L2M -T $vg/pool -c 192K +lvcreate -s $vg/$lv1 --name $lv2 --thinpool $vg/pool + +# Check the tail of $lv2 matches $lv1 +dd if="$d2" of=16K bs=8192 skip=45 count=2 +cmp -n 16384 -l 64K 16K + +# Now extend and rewrite +lvextend -l+2 $vg/$lv2 + +dd if=64K of="$d2" bs=8192 seek=46 count=3 conv=fdatasync +dd if="$d2" of=24K bs=8192 skip=46 count=3 iflag=direct +cmp -n 24576 -l 64K 24K + +# Consumes 2 192K chunks -> 66.67% +check lv_field $vg/$lv2 data_percent "66.67" + +lvreduce -f -l-24 $vg/$lv2 + +dd if=64K of="$d2" bs=8192 seek=24 count=1 conv=fdatasync +dd if="$d2" of=8K bs=8192 skip=24 count=1 iflag=direct +cmp -n 8192 -l 64K 8K + +# Check extension still works +lvextend -l+2 $vg/$lv2 + +lvremove -f $vg/pool + +lvcreate -L256M -T $vg/pool -c 64M +lvcreate -s $vg/$lv1 --name $lv2 --thinpool $vg/pool +lvextend -l+2 $vg/$lv2 + +dd if=64K of="$d2" bs=8192 seek=45 count=4 conv=fdatasync +dd if="$d2" of=32K bs=8192 skip=45 count=4 iflag=direct +cmp -n 32768 -l 64K 32K + +lvextend -L+64M $vg/$lv2 + +# Consumes 64M chunk -> 50% +check lv_field $vg/$lv2 data_percent "50.00" + +vgremove -ff $vg diff --git a/test/shell/lvcreate-thin-external.sh b/test/shell/lvcreate-thin-external.sh new file mode 100644 index 0000000..20f0577 --- /dev/null +++ b/test/shell/lvcreate-thin-external.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test creation of thin snapshots using external origin + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +which mkfs.ext2 || skip +which fsck || skip + +# +# Main +# +aux have_thin 1 3 0 || skip + +aux prepare_pvs 2 64 +get_devs + +vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}" + +# Newer thin-pool target (>= 1.13) supports unaligned external origin +# But this test is written to test and expect older behavior +aux lvmconf 'global/thin_disabled_features = [ "external_origin_extend" ]' + +# Test validation for external origin being multiple of thin pool chunk size +lvcreate -L10M -T $vg/pool192 -c 192k +lvcreate -an -pr -Zn -l1 -n $lv1 $vg +not lvcreate -s $vg/$lv1 --thinpool $vg/pool192 + +lvcreate -an -pr -Zn -l5 -n $lv2 $vg +not lvcreate -s $vg/$lv2 --thinpool $vg/pool192 +lvremove -f $vg + +# Prepare pool and external origin with filesystem +lvcreate -L10M -V10M -T $vg/pool --name $lv1 +mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1" + +lvcreate -L4M -n $lv2 $vg +mkfs.ext2 "$DM_DEV_DIR/$vg/$lv2" + +# Fail to create external origin snapshot of rw LV +not lvcreate -s $vg/$lv2 --thinpool $vg/pool + +lvchange -p r $vg/$lv2 + +# Fail to create snapshot of active r LV +# FIXME: kernel update needed +not lvcreate -s $vg/$lv2 --thinpool $vg/pool + +# Deactivate LV we want to use as external origin +# once kernel will ensure read-only this condition may go away +lvchange -an $vg/$lv2 + +lvcreate -s $vg/$lv2 --thinpool $vg/pool + +# Fail with --thin and --snapshot +not lvcreate -s $vg/$lv5 --name $vg/$lv7 -T $vg/newpool + +# Cannot specify size and thin pool. +# TODO: maybe with --poolsize +invalid lvcreate -s $vg/$lv2 -L10 --thinpool $vg/pool +invalid lvcreate -s -K $vg/$lv2 --name $vg/$lv3 -L20 --chunksize 128 --thinpool $vg/newpool + +not lvcreate -s $vg/$lv2 --chunksize 64 --thinpool $vg/pool +not lvcreate -s $vg/$lv2 --zero y --thinpool $vg/pool +not lvcreate -s $vg/$lv2 --poolmetadata $vg/$lv1 --thinpool $vg/pool + +# Fail with nonexistent pool +not lvcreate -s $vg/$lv2 --thinpool $vg/newpool + +# Create pool and snap +lvcreate -T --name $vg/$lv3 -V10 -L20 --chunksize 128 --thinpool $vg/newpool +lvcreate -s -K $vg/$lv3 --name $vg/$lv4 +lvcreate -s -K $vg/$lv2 --name $vg/$lv5 --thinpool $vg/newpool +# Make normal thin snapshot +lvcreate -s -K $vg/$lv5 --name $vg/$lv6 +# We do not need to specify thinpool when doing thin snap, but it should work +lvcreate -s -K $vg/$lv5 --name $vg/$lv7 --thinpool $vg/newpool + +check inactive $vg $lv2 +lvchange -ay $vg/$lv2 +lvcreate -s -K $vg/$lv2 --name $vg/$lv8 --thinpool $vg/newpool + +lvs -o+chunksize $vg + +check active $vg $lv3 +check active $vg $lv4 +check active $vg $lv5 +check active $vg $lv6 +check active $vg $lv7 + +fsck -n "$DM_DEV_DIR/$vg/$lv1" +fsck -n "$DM_DEV_DIR/$vg/$lv7" + +vgremove -ff $vg diff --git a/test/shell/lvcreate-thin-limits.sh b/test/shell/lvcreate-thin-limits.sh new file mode 100644 index 0000000..5dcc160 --- /dev/null +++ b/test/shell/lvcreate-thin-limits.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test allocation of thin-pool on limiting extents number + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# FIXME update test to make something useful on <16T +aux can_use_16T || skip + +# +# Main +# +aux have_thin 1 0 0 || skip +which mkfs.ext4 || skip + +# 16T device +aux prepare_pvs 2 8388608 +get_devs + +# gives 16777215M device +vgcreate $SHARED -s 4M "$vg" "${DEVICES[@]}" + +# For 1st. pass only single PV +lvcreate -l100%PV --name $lv1 $vg "$dev2" + +for i in 1 0 +do + SIZE=$(get vg_field "$vg" vg_free --units m) + SIZE=${SIZE%%\.*} + + # ~16T - 2 * 5G + something -> should not fit + not lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 + 1 )) --poolmetadatasize 5G $vg/pool + + check vg_field "$vg" lv_count "$i" + + # Should fit data + metadata + pmspare + lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 )) --poolmetadatasize 5G $vg/pool + + check vg_field "$vg" vg_free "0" + + lvs -ao+seg_pe_ranges $vg + + # Remove everything for 2nd. pass + lvremove -ff $vg +done + +vgremove -ff $vg diff --git a/test/shell/lvcreate-thin-power2.sh b/test/shell/lvcreate-thin-power2.sh index 882b05c..ec9755a 100644 --- a/test/shell/lvcreate-thin-power2.sh +++ b/test/shell/lvcreate-thin-power2.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # @@ -8,12 +8,17 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # test support for non-power-of-2 thin chunk size # -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest # # Main @@ -21,17 +26,19 @@ aux have_thin 1 4 0 || skip aux prepare_pvs 2 64 +get_devs -vgcreate $vg -s 64K $(cat DEVICES) +vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}" # create non-power-of-2 pool lvcreate -l100 -c 192 -T $vg/pool -check lv_field $vg/pool discards "ignore" +check lv_field $vg/pool discards "passdown" # check we cannot change discards settings -not lvchange --discard passdown $vg/pool -not lvchange --discard nopassdown $vg/pool +not lvchange --discard ignore $vg/pool +lvchange --discard nopassdown $vg/pool +check lv_field $vg/pool discards "nopassdown" # must be multiple of 64KB not lvcreate -l100 -c 168 -T $vg/pool1 diff --git a/test/shell/lvcreate-thin-snap.sh b/test/shell/lvcreate-thin-snap.sh index 23f91f9..8f19879 100644 --- a/test/shell/lvcreate-thin-snap.sh +++ b/test/shell/lvcreate-thin-snap.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # @@ -8,17 +8,22 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest check_lv_field_modules_() { mod=$1 shift - for d in $*; do - check lv_field $vg/$d modules $mod + for d in "$@"; do + check lv_field "$vg/$d" modules "$mod" done } @@ -27,31 +32,67 @@ check_lv_field_modules_() # Main # aux have_thin 1 0 0 || skip +which mkfs.ext4 || skip aux prepare_pvs 2 64 +get_devs -vgcreate $vg -s 64K $(cat DEVICES) +vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}" lvcreate -L10M -V10M -T $vg/pool --name $lv1 -mkfs.ext4 $DM_DEV_DIR/$vg/$lv1 -# create thin snapshot of thin LV -lvcreate -s $vg/$lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +# create read-only thin snapshot of thin LV +lvcreate -K -s $vg/$lv1 -pr --name snap # check snapshot filesystem was properly frozen before snapping -fsck -p $DM_DEV_DIR/$vg/lvol0 -lvcreate -s $vg/$lv1 --name $lv2 -lvcreate -s $vg/$lv1 --name $vg/$lv3 -lvcreate --type snapshot $vg/$lv1 -lvcreate --type snapshot $vg/$lv1 --name $lv4 -lvcreate --type snapshot $vg/$lv1 --name $vg/$lv5 +fsck -n "$DM_DEV_DIR/$vg/snap" +lvcreate -K -s $vg/$lv1 --name $lv2 +lvcreate -K -s $vg/$lv1 --name $vg/$lv3 +# old-snapshot without known size is invalid +invalid lvcreate --type snapshot $vg/$lv1 +invalid lvcreate --type snapshot $vg/$lv1 --name $lv4 +invalid lvcreate --type snapshot $vg/$lv1 --name $vg/$lv5 +# some other ways how to take a thin snapshot +lvcreate -T $vg/$lv1 +lvcreate --thin $vg/$lv1 --name $lv4 +lvcreate --type thin $vg/$lv1 --name $vg/$lv5 +# virtual size needs thin pool +fail lvcreate --type thin $vg/$lv1 -V20 # create old-style snapshot lvcreate -s -L10M --name oldsnap1 $vg/$lv2 lvcreate -s -L10M --name oldsnap2 $vg/$lv2 # thin snap of snap of snap... -lvcreate -s --name sn1 $vg/$lv2 -lvcreate -s --name sn2 $vg/sn1 -lvcreate -s --name sn3 $vg/sn2 -lvcreate -s --name sn4 $vg/sn3 +lvcreate -K -s --name sn1 $vg/$lv2 +lvcreate -K -s --name sn2 $vg/sn1 +lvcreate -K -s --name sn3 $vg/sn2 +lvcreate -K -s --name sn4 $vg/sn3 + +lvremove -ff $vg + +lvcreate -L10M --zero n -T $vg/pool -V10M --name $lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +lvcreate -K -s $vg/$lv1 --name snap +fsck -n "$DM_DEV_DIR/$vg/snap" +vgchange -an $vg +lvremove -y $vg + +# One thin pool and one thin LV +lvcreate --type thin-pool -L 10M -n tp $vg +lvcreate --type thin -n thin1 -V 20M --thinpool tp $vg +# Different syntaxes for creating a thin snapshot +lvcreate --type thin -n snap1 $vg/thin1 +lvcreate --type thin --snapshot -n snap2 $vg/thin1 +lvcreate --type thin --thin -n snap3 $vg/thin1 +lvcreate --type thin --snapshot --thin -n snap4 $vg/thin1 +lvcreate --snapshot -n snap5 $vg/thin1 +lvcreate --thin -n snap6 $vg/thin1 +# The command defs allow --snapshot --thin, but the internal +# lvcreate option checks disallow it. It doesn't seem to make +# sense to disallow this from a syntax point of view, but it's +# possible that the lvcreate implementation would do the wrong +# thing (that should probably be fixed.) +not lvcreate --thin --snapshot -n snap7 $vg/thin1 +vgchange -an $vg vgremove -ff $vg diff --git a/test/shell/lvcreate-thin.sh b/test/shell/lvcreate-thin.sh index e651a81..c073eaf 100644 --- a/test/shell/lvcreate-thin.sh +++ b/test/shell/lvcreate-thin.sh @@ -1,6 +1,6 @@ -#!/bin/sh +#!/usr/bin/env bash -# Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. +# Copyright (C) 2011-2014 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 @@ -8,54 +8,88 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # test currently needs to drop # 'return NULL' in _lv_create_an_lv after log_error("Can't create %s without using " -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest check_lv_field_modules_() { mod=$1 shift - for d in $*; do + for d in "$@"; do check lv_field $vg/$d modules $mod done } - # # Main # aux have_thin 1 0 0 || skip +which mkfs.ext4 || skip aux prepare_pvs 2 64 +get_devs -vgcreate $vg -s 64K $(cat DEVICES) +vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}" # Create named pool only lvcreate -l1 -T $vg/pool1 lvcreate -l1 -T --thinpool $vg/pool2 lvcreate -l1 -T --thinpool pool3 $vg -lvcreate -l1 --type thin $vg/pool4 -lvcreate -l1 --type thin --thinpool $vg/pool5 -lvcreate -l1 --type thin --thinpool pool6 $vg +invalid lvcreate -l1 --type thin $vg/pool4 +invalid lvcreate -l1 --type thin --thinpool $vg/pool5 +invalid lvcreate -l1 --type thin --thinpool pool6 $vg lvcreate -l1 --type thin-pool $vg/pool7 lvcreate -l1 --type thin-pool --thinpool $vg/pool8 lvcreate -l1 --type thin-pool --thinpool pool9 $vg -lvremove -ff $vg/pool1 $vg/pool2 $vg/pool3 $vg/pool4 $vg/pool5 $vg/pool6 $vg/pool7 $vg/pool8 $vg/pool9 +lvremove -ff $vg/pool1 $vg/pool2 $vg/pool3 $vg/pool7 $vg/pool8 $vg/pool9 +check vg_field $vg lv_count 0 + + +# Let's pretend pool is like normal LV when using --type thin-pool support --name +# Reject ambiguous thin pool names +invalid lvcreate --type thin-pool -l1 --name pool1 $vg/pool2 +invalid lvcreate --type thin-pool -l1 --name pool3 --thinpool pool4 $vg +invalid lvcreate --type thin-pool -l1 --name pool5 --thinpool pool6 $vg/pool7 +invalid lvcreate --type thin-pool -l1 --name pool8 --thinpool pool8 $vg/pool9 + +# no size specified and no origin name give for snapshot +invalid lvcreate --thinpool pool $vg + check vg_field $vg lv_count 0 +lvcreate --type thin-pool -l1 --name pool1 $vg +lvcreate --type thin-pool -l1 --name $vg/pool2 +# If the thin pool name is unambiguous let it proceed +lvcreate --type thin-pool -l1 --name pool3 $vg/pool3 +lvcreate --type thin-pool -l1 --name pool4 --thinpool $vg/pool4 +lvcreate --type thin-pool -l1 --name pool5 --thinpool $vg/pool5 $vg/pool5 + +check lv_field $vg/pool1 segtype "thin-pool" +check lv_field $vg/pool2 segtype "thin-pool" +check lv_field $vg/pool3 segtype "thin-pool" +check lv_field $vg/pool4 segtype "thin-pool" +check lv_field $vg/pool5 segtype "thin-pool" + +lvremove -ff $vg + # Create default pool name lvcreate -l1 -T $vg -lvcreate -l1 --type thin $vg +invalid lvcreate -l1 --type thin $vg lvcreate -l1 --type thin-pool $vg -lvremove -ff $vg/lvol0 $vg/lvol1 $vg/lvol2 +lvremove -ff $vg check vg_field $vg lv_count 0 @@ -67,14 +101,14 @@ lvremove -ff $vg # Create named pool and default thin LV -lvcreate -L4M -V2G -T $vg/pool1 -lvcreate -L4M -V2G -T --thinpool $vg/pool2 -lvcreate -L4M -V2G -T --thinpool pool3 $vg -lvcreate -L4M -V2G --type thin $vg/pool4 -lvcreate -L4M -V2G --type thin --thinpool $vg/pool5 -lvcreate -L4M -V2G --type thin --thinpool pool6 $vg - -check lv_exists $vg lvol0 lvol1 lvol2 lvol3 lvol4 lvol5 +lvcreate -L4M -V2G --name lvo1 -T $vg/pool1 +lvcreate -L4M -V2G --name lvo2 -T --thinpool $vg/pool2 +lvcreate -L4M -V2G --name lvo3 -T --thinpool pool3 $vg +lvcreate -L4M -V2G --name lvo4 --type thin $vg/pool4 +lvcreate -L4M -V2G --name lvo5 --type thin --thinpool $vg/pool5 +lvcreate -L4M -V2G --name lvo6 --type thin --thinpool pool6 $vg + +check lv_exists $vg lvo1 lvo2 lvo3 lvremove -ff $vg @@ -103,14 +137,14 @@ lvremove -ff $vg # Create default thin LV in existing pool lvcreate -L4M -T $vg/pool -lvcreate -V2G -T $vg/pool -lvcreate -V2G -T --thinpool $vg/pool -lvcreate -V2G -T --thinpool pool $vg -lvcreate -V2G --type thin $vg/pool -lvcreate -V2G --type thin --thinpool $vg/pool -lvcreate -V2G --type thin --thinpool pool $vg +lvcreate -V2G --name lvo0 -T $vg/pool +lvcreate -V2G --name lvo1 -T --thinpool $vg/pool +lvcreate -V2G --name lvo2 -T --thinpool pool $vg +lvcreate -V2G --name lvo3 --type thin $vg/pool +lvcreate -V2G --name lvo4 --type thin --thinpool $vg/pool +lvcreate -V2G --name lvo5 --type thin --thinpool pool $vg -check lv_exists $vg lvol0 lvol1 lvol2 lvol3 lvol4 lvol5 +check lv_exists $vg lvo0 lvo1 lvo2 lvo3 lvo4 lvo5 # Create named thin LV in existing pool @@ -129,40 +163,52 @@ lvcreate -V2G --type thin --thinpool pool --name $vg/lv12 $vg check lv_exists $vg lv1 lv2 lv3 lv4 lv5 lv6 lv7 lv8 lv9 lv10 lv11 lv12 check vg_field $vg lv_count 19 +check lv_field $vg/lv1 thin_id 7 lvremove -ff $vg check vg_field $vg lv_count 0 # Create thin snapshot of thinLV -lvcreate -L10M -V10M -T $vg/pool --name lv1 -mkfs.ext4 $DM_DEV_DIR/$vg/lv1 -lvcreate -s $vg/lv1 -fsck -p $DM_DEV_DIR/$vg/lvol0 +lvcreate -L10M -I4 -i2 -V10M -T $vg/pool --name lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/lv1" +lvcreate -K -s $vg/lv1 --name snap_lv1 +fsck -n "$DM_DEV_DIR/$vg/snap_lv1" lvcreate -s $vg/lv1 --name lv2 lvcreate -s $vg/lv1 --name $vg/lv3 -lvcreate --type snapshot $vg/lv1 -lvcreate --type snapshot $vg/lv1 --name lv4 -lvcreate --type snapshot $vg/lv1 --name $vg/lv5 +invalid lvcreate --type snapshot $vg/lv1 --name lv6 +invalid lvcreate --type snapshot $vg/lv1 --name lv4 +invalid lvcreate --type snapshot $vg/lv1 --name $vg/lv5 + +lvdisplay --maps $vg +check_lv_field_modules_ thin,thin-pool lv1 snap_lv1 lv2 lv3 +check vg_field $vg lv_count 5 -check_lv_field_modules_ thin-pool lv1 lvol0 lv2 lv3 lvol1 lv4 lv5 -check vg_field $vg lv_count 8 lvremove -ff $vg # Normal Snapshots of thinLV lvcreate -L4M -V2G -T $vg/pool --name lv1 -lvcreate -s $vg/lv1 -l1 +lvcreate -s $vg/lv1 -l1 --name snap_lv1 lvcreate -s $vg/lv1 -l1 --name lv2 lvcreate -s $vg/lv1 -l1 --name $vg/lv3 lvcreate -s lv1 -L4M --name $vg/lv4 -check_lv_field_modules_ snapshot lvol0 lv2 lv3 lv4 +check_lv_field_modules_ snapshot snap_lv1 lv2 lv3 lv4 check vg_field $vg lv_count 6 lvremove -ff $vg check vg_field $vg lv_count 0 -lvdisplay $vg + +# Check how allocator works with 2PVs where one is nearly full +lvcreate -l99%PV $vg "$dev1" +lvs -a $vg +# Check when separate metadata is required, allocation needs to fail +fail lvcreate -L10 -T --poolmetadataspare n --config 'allocation/thin_pool_metadata_require_separate_pvs=1' $vg +# Check when data and metadata may share the same PV, it shall pass +lvcreate -L10 -T --poolmetadataspare n --config 'allocation/thin_pool_metadata_require_separate_pvs=0' $vg +lvremove -f $vg + # Fail cases # Too small pool size (1 extent 64KB) for given chunk size @@ -171,41 +217,56 @@ not lvcreate --chunksize 256 -l1 -T $vg/pool1 not lvcreate --chunksize 32 -l1 -T $vg/pool1 # Too large chunk size (max is 1GB) not lvcreate -L4M --chunksize 2G -T $vg/pool1 +# Cannot specify --minor with pool +fail lvcreate -L10M --minor 100 -T $vg/pool_minor + +# FIXME: Currently ambigous - is it for thin, thin-pool, both ? +fail lvcreate -L4M -Mn -m0 -T --readahead 32 -V20 -n $lv $vg/pool_normal + +# Check read-ahead setting will also pass with -Mn -m0 +lvcreate -L4M -Mn -m0 -T --readahead 64k $vg/pool_readahead +lvcreate -V20M -Mn -m0 -T --readahead 128k -n thin_readahead $vg/pool_readahead +check lv_field $vg/pool_readahead lv_read_ahead "64.00k" +check lv_field $vg/thin_readahead lv_read_ahead "128.00k" + +if test ! -d /sys/block/dm-2345; then +# Check some unused minor and support for --minor with thins + lvcreate --minor 2345 -T -V20M -n thin_minor $vg/pool_readahead + check lv_field $vg/thin_minor lv_minor "2345" +fi + +# Test creation of inactive pool +lvcreate -an -L4M -T $vg/pool1 +lvcreate -V2G --name lv1 -T $vg/pool1 +# Check we are able remove spare volume if we want to +lvremove -f $vg/lvol0_pmspare -lvcreate -L4M -V2G --name lv1 -T $vg/pool1 # Origin name is not accepted not lvcreate -s $vg/lv1 -L4M -V2G --name $vg/lv4 -# Check we cannot create mirror and thin or thinpool together +# Check we cannot create mirror/raid1 and thin or thinpool together not lvcreate -T mirpool -L4M --alloc anywhere -m1 $vg not lvcreate --thinpool mirpool -L4M --alloc anywhere -m1 $vg -vgremove -ff $vg -# Test --poolmetadatasize range -# allocating large devices for testing -aux teardown_devs -aux prepare_pvs 10 16500 -vgcreate $vg -s 64K $(cat DEVICES) - -lvcreate -L4M --chunksize 128 --poolmetadatasize 0 -T $vg/pool1 2>out -grep "WARNING: Minimum" out -# FIXME: metadata allocation fails, if PV doesn't have at least 16GB -# i.e. pool metadata device cannot be multisegment -lvcreate -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>out -grep "WARNING: Maximum" out -check lv_field $vg/pool1_tmeta size "2.00m" -check lv_field $vg/pool2_tmeta size "16.00g" +# Check pool metadata volume is zeroed, when zero_metadata is enabled. +# 1st. ensure 8megs of both PVs will have some non-0 data +lvcreate -L8m -n $lv1 $vg "$dev1" +lvextend -L+8m $vg/$lv1 "$dev2" +dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=16 oflag=direct conv=fdatasync +lvremove -ff $vg/$lv1 + +lvcreate -l1 --poolmetadatasize 4m --conf 'allocation/zero_metadata=1' -vvvv -T $vg/pool +lvchange -an $vg +# component activation to check device was zeroed +lvchange -y -ay $vg/pool_tmeta +dd if="$DM_DEV_DIR/$vg/pool_tmeta" of=file bs=1M count=3 skip=1 iflag=direct conv=fdatasync + +md5sum -b file | tee out +# md5sum of 3M of zeros +grep d1dd210d6b1312cb342b56d02bd5e651 out +lvchange -an $vg lvremove -ff $vg -# Test automatic calculation of pool metadata size -lvcreate -L160G -T $vg/pool -check lv_field $vg/pool lv_metadata_size "80.00m" -check lv_field $vg/pool chunksize "128.00k" -lvremove -ff $vg/pool -lvcreate -L10G --chunksize 256 -T $vg/pool1 -lvcreate -L60G --chunksize 1024 -T $vg/pool2 -check lv_field $vg/pool1_tmeta size "2.50m" -check lv_field $vg/pool2_tmeta size "3.75m" vgremove -ff $vg diff --git a/test/shell/lvcreate-usage.sh b/test/shell/lvcreate-usage.sh index ddde401..6d46939 100644 --- a/test/shell/lvcreate-usage.sh +++ b/test/shell/lvcreate-usage.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008-2011 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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 @@ -7,89 +8,112 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Exercise some lvcreate diagnostics' -. lib/test +. lib/inittest aux prepare_pvs 4 -aux pvcreate --metadatacopies 0 "$dev1" -vgcreate -cn $vg $(cat DEVICES) +get_devs -# "lvcreate rejects repeated invocation (run 2 times) (bz178216)" -lvcreate -n $lv -l 4 $vg +aux pvcreate --metadatacopies 0 "$dev1" +aux vgcreate $SHARED "$vg" "${DEVICES[@]}" + +invalid lvcreate --type free -l1 -n $lv1 $vg 2>err +grep "Invalid argument for --type" err +invalid lvcreate --type $RANDOM -l1 -n $lv1 $vg +invalid lvcreate --type unknown -l1 -n $lv1 $vg + +invalid lvcreate -L10000000000000000000 -n $lv $vg 2>&1 | tee err +grep "Size is too big" err +invalid lvcreate -L+-10 -n $lv $vg 2>&1 | tee err +grep "Multiple sign" err +invalid lvcreate -L-.1 -n $lv $vg 2>&1 | tee err +grep "Size may not be negative" err +invalid lvcreate -L..1 -n $lv $vg 2>&1 | tee err +grep "Can't parse size" err + +lvcreate --type linear -aey -m0 -l1 -n $lv1 $vg +lvcreate --type snapshot -l1 -n $lv2 $vg/$lv1 +# Supporting decimal point with size +lvcreate -L.1 -n $lv3 $vg + +# Reject 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) +# 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 +# Reject a negative stripe_size +invalid lvcreate -L 64m -n $lv -i2 --stripesize -4 $vg 2>err; +grep "may not be negative" err -# 'lvcreate rejects a too-large stripesize' -not lvcreate -L 64m -n $lv -i2 --stripesize 4294967291 $vg 2>err +# Reject a too-large stripesize +invalid 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' +# 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 +lvdisplay $vg lvremove -ff $vg -# 'lvcreate w/default (64KB) stripe size succeeds with diagnostics to stdout' +# 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 +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 +# Reject an invalid number of stripes +invalid 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 +# Reject an invalid stripe size +invalid lvcreate -L 64m -n $lv -i2 --stripesize 3 $vg 2>err grep "Invalid stripe size" err +# Verify that the LV was not created via lvdisplay empty output test -z "$(lvdisplay $vg)" # Setting max_lv works. (bz490298) -lvremove -ff $vg +check vg_field $vg max_lv "0" vgchange -l 3 $vg -lvcreate -l1 -n $lv1 $vg +check vg_field $vg max_lv "3" +lvcreate -aey -l1 -n $lv1 $vg lvcreate -l1 -s -n $lv2 $vg/$lv1 lvcreate -l1 -n $lv3 $vg -not lvcreate -l1 -n $lv4 $vg - +fail lvcreate -l1 -n $lv4 $vg lvremove -ff $vg/$lv3 + +# Check snapshot of inactive origin +lvchange -an $vg/$lv1 lvcreate -l1 -s -n $lv3 $vg/$lv1 -not lvcreate -l1 -n $lv4 $vg -not lvcreate -l1 -m1 -n $lv4 $vg +fail lvcreate -l1 -n $lv4 $vg +fail lvcreate -l1 --type mirror -m1 -n $lv4 $vg lvremove -ff $vg/$lv3 -lvcreate -l1 -m1 -n $lv3 $vg -vgs -o +max_lv $vg +lvcreate -aey -l1 --type mirror -m1 -n $lv3 $vg not lvcreate -l1 -n $lv4 $vg -not lvcreate -l1 -m1 -n $lv4 $vg +not lvcreate -l1 --type mirror -m1 -n $lv4 $vg lvconvert -m0 $vg/$lv3 -lvconvert -m2 -i 1 $vg/$lv3 +lvconvert -m2 --type mirror -i 1 $vg/$lv3 lvconvert -m1 $vg/$lv3 -not vgchange -l 2 +fail vgchange -l 2 +check vg_field $vg max_lv "3" vgchange -l 4 -vgs $vg +check vg_field $vg max_lv "4" lvremove -ff $vg vgchange -l 0 $vg +check vg_field $vg max_lv "0" -# lvcreate rejects invalid chunksize, accepts between 4K and 512K -# validate origin_size -vgremove -ff $vg -vgcreate -cn $vg $(cat DEVICES) -lvcreate -L 32m -n $lv1 $vg +# Rejects invalid chunksize, accepts between 4K and 512K +# and validate origin_size +lvcreate -aey -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 @@ -98,53 +122,110 @@ 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 +lvremove -f $vg -# regionsize must be +# Mirror 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 +invalid lvcreate --type mirror -m 1 -L 32m -n $lv -R 0 $vg 2>err +grep "may not be zero" err +invalid lvcreate --type mirror -m 1 -L 32m -n $lv -R 11k $vg +invalid lvcreate --type mirror -m 1 -L 32m -n $lv -R 1k $vg +lvcreate -aey -L 32m -n $lv --regionsize 128m --type mirror -m 1 $vg check lv_field $vg/$lv regionsize "32.00m" -lvremove -ff $vg -lvcreate -L 32m -n $lv --regionsize 4m -m 1 $vg +lvremove -f $vg +lvcreate -aey -L 32m -n $lv --regionsize 4m --type mirror -m 1 $vg check lv_field $vg/$lv regionsize "4.00m" + +# -m0 is creating non-mirrored segment and give info about redundant option +lvcreate -m 0 -l1 -n $lv1 $vg 2>&1 | tee err +grep "Redundant" err +check lv_field $vg/$lv1 segtype "linear" lvremove -ff $vg -# snapshot with virtual origin works +if test -n "$LVM_TEST_LVMLOCKD"; then +echo "skip snapshot without origin" +else + +# Old --type snapshot works with -s +lvcreate --type snapshot -s -V64 -L32 -n $lv1 $vg +check lv_field $vg/$lv1 segtype "linear" +lvcreate --type snapshot -V64 -L32 -n $lv2 $vg +check lv_field $vg/$lv2 segtype "linear" +lvremove -ff $vg + +# --virtualoriginsize always makes old snapshot lvcreate -s --virtualoriginsize 64m -L 32m -n $lv1 $vg +check lv_field $vg/$lv1 segtype "linear" lvrename $vg/$lv1 $vg/$lv2 lvcreate -s --virtualoriginsize 64m -L 32m -n $lv1 $vg lvchange -a n $vg/$lv1 lvremove -ff $vg/$lv1 lvremove -ff $vg +fi + # 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" -check lv_field $vg/$lv lv_kernel_read_ahead "0" -lvremove -ff $vg -lvcreate -L 32m -n $lv --readahead 8k $vg -check lv_field $vg/$lv lv_read_ahead "8.00k" -check lv_field $vg/$lv lv_kernel_read_ahead "8.00k" -lvremove -ff $vg -lvcreate -L 32m -n $lv --readahead auto $vg -check lv_field $vg/$lv lv_read_ahead "auto" -check lv_field $vg/$lv lv_kernel_read_ahead "128.00k" -lvremove -ff $vg -lvcreate -L 32m -n $lv -i2 --stripesize 16k --readahead auto $vg -check lv_field $vg/$lv lv_read_ahead "auto" -check lv_field $vg/$lv lv_kernel_read_ahead "128.00k" -lvremove -ff $vg -lvcreate -L 32m -n $lv -i2 --stripesize 128k --readahead auto $vg -check lv_field $vg/$lv lv_read_ahead "auto" -check lv_field $vg/$lv lv_kernel_read_ahead "512.00k" +lvcreate -L 8 -n $lv1 $vg +check lv_field $vg/$lv1 lv_read_ahead "auto" +lvcreate -L 8 -n $lv2 --readahead none $vg +check lv_field $vg/$lv2 lv_read_ahead "0" +check lv_field $vg/$lv2 lv_kernel_read_ahead "0" +lvcreate -L 8 -n $lv3 --readahead 8k $vg +check lv_field $vg/$lv3 lv_read_ahead "8.00k" +check lv_field $vg/$lv3 lv_kernel_read_ahead "8.00k" +lvcreate -L 8 -n $lv4 --readahead auto $vg "$dev1" +check lv_field $vg/$lv4 lv_read_ahead "auto" +# figure RA value of a PV origin device +DEVICE=$(dmsetup deps -o blkdevname "$dev1" | sed -e "s,.*:\ (\(.*\)),/dev/\1,") +RASZ=$(( $(blockdev --getra "$DEVICE" ) / 2 )) +test "$RASZ" -ge 128 || RASZ="128" +check lv_field $vg/$lv4 lv_kernel_read_ahead "${RASZ}.00k" --units k +lvcreate -vvvvv -L 8 -n $lv5 -i2 --stripesize 16k --readahead auto $vg +check lv_field $vg/$lv5 lv_read_ahead "auto" +# For 16k stripe we set '128k' as the is the minimum size we get when creating DM device +check lv_field $vg/$lv5 lv_kernel_read_ahead "128.00k" --units k +lvcreate -L 8 -n $lv6 -i2 --stripesize 128k --readahead auto $vg +check lv_field $vg/$lv6 lv_read_ahead "auto" +# For striped device we set double of strip size unrelated to underlaying dev RA size +check lv_field $vg/$lv6 lv_kernel_read_ahead "512.00k" --units k lvremove -ff $vg + +# +# Validate --major --minor, we need to know VG, thus failing +# +fail lvcreate -My --major 234 -l1 $vg +# cannot specify --major or --minor with -Mn +fail lvcreate -Mn --major 234 -l1 $vg +fail lvcreate --persistent n --minor 234 -l1 $vg +# out-of-range minor value +fail lvcreate --minor 9999999 -l1 $vg +if aux kernel_at_least 2 4 0; then +# On >2.4 we ignore --major +lvcreate --major 234 -l1 $vg 2>&1 | tee err; +grep "Ignoring" err +# Try some bigger possibly unused minor +if test ! -d /sys/block/dm-2345; then + lvcreate --minor 2345 -l1 -n $lv1 $vg + check lv_field $vg/$lv1 lv_kernel_minor "2345" +fi +if test ! -d /sys/block/dm-23456; then + lvcreate -My --minor 23456 -j 122 -l1 -n $lv2 $vg + check lv_field $vg/$lv2 lv_kernel_minor "23456" +fi +fi # 2.4 +lvremove -f $vg + +# prohibited names +for i in pvmove snapshot ; do + invalid lvcreate -l1 -n ${i}1 $vg +done +for i in _cdata _cmeta _cpool _cvol _mimage _mlog _pmspare _tdata _tmeta _vorigin ; do + invalid lvcreate -l1 -n s_${i}_1 $vg +done + +# Check invalid error for pool-only options +invalid lvcreate --poolmetadataspare y -l1 $vg +invalid lvcreate --poolmetadatasize 10 -l1 $vg +invalid lvcreate --discards passdown -l1 $vg diff --git a/test/shell/lvcreate-vdo-cache.sh b/test/shell/lvcreate-vdo-cache.sh new file mode 100644 index 0000000..6cf8437 --- /dev/null +++ b/test/shell/lvcreate-vdo-cache.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise caching vdo and vdo-pool's data LV + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# +# Main +# + +# +# FIXME: tempororarily disable this test until fixed VDO driver is relased +# should really be 6.2.2 - currently goes with vdo-6.2.2.18 +aux have_vdo 6 2 1 || skip +aux have_cache 1 3 0 || skip + +which mkfs.ext4 || skip +export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf" + +aux prepare_vg 1 9000 + +lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool +# Test caching VDOPoolLV +lvcreate -H -L10 $vg/vpool + +mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1" + +lvconvert --uncache $vg/vpool +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +lvcreate -H -L10 $vg/vpool_vdata +fsck -n "$DM_DEV_DIR/$vg/$lv1" +lvs -a $vg +lvconvert --uncache $vg/vpool_vdata + + +# Test caching VDOLV +lvcreate -H -L10 $vg/$lv1 + +lvconvert --uncache $vg/$lv1 +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +lvs -a $vg + +vgremove -ff $vg diff --git a/test/shell/lvcreate-vdo.sh b/test/shell/lvcreate-vdo.sh new file mode 100644 index 0000000..3e807ac --- /dev/null +++ b/test/shell/lvcreate-vdo.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + + +. lib/inittest + +# +# Main +# +aux have_vdo 6 2 0 || skip +which mkfs.ext4 || skip + +aux prepare_pvs 2 6400 +get_devs + +#aux lvmconf 'allocation/vdo_use_read_cache = 1' 'allocation/vdo_read_cache_size_mb = 64' + +#aux lvmconf 'allocation/vdo_use_compression = 0' 'allocation/vdo_use_deduplication = 0' + +#aux lvmconf 'allocation/vdo_hash_zone_threads = 0' \ +# 'allocation/vdo_logical_threads = 0' \ +# 'allocation/vdo_physical_threads = 0' \ +# 'allocation/vdo_cpu_threads = 1' + +vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}" + +# Create VDO device (vdo-pool is ATM internal volume type) +lvcreate --type vdo -L4G -n $lv1 $vg/$lv2 >out 2>&1 +# new vdoformat prints some more info +if grep "data slabs" out ; then + # check we have match vdo_slab_size_mb == 128MB (aux.sh) + grep "each 128 MB" out +fi + +check lv_field $vg/$lv1 size "<1.24g" +check lv_field $vg/${lv2} size "4.00g" +check lv_field $vg/${lv2}_vdata size "4.00g" +check lv_field $vg/${lv1} data_percent "0.00" +lvremove -ff $vg + + +lvcreate --vdo -L4G -V8G -n $lv1 $vg/$lv2 +check lv_field $vg/$lv1 size "8.00g" +check lv_field $vg/${lv2} size "4.00g" +check lv_field $vg/${lv2}_vdata size "4.00g" +lvs -a $vg + +dmsetup table | grep $vg +dmsetup status | grep $vg + +# Resize not yet supported +not lvresize -y $vg/$lv1 +not lvresize -y $vg/${lv2} +not lvresize -y $vg/${lv2}_vdata + +# Discard is very slow with VDO ATM so try to avoid it +#time blkdiscard "$DM_DEV_DIR/$vg/$lv1" +time mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1" +#time mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +fsck -n "$DM_DEV_DIR/$vg/$lv1" + +# vpool itself is NOT usable filesystem +not fsck -n "$DM_DEV_DIR/mapper/$vg-${lv2}" +# not usable even when there is no linear mapping on top of it +dmsetup remove ${vg}-$lv1 +not fsck -n "$DM_DEV_DIR/mapper/$vg-${lv2}" + +lvremove -ff $vg + +# Unknown settings does not pass +# TODO: try to catch this in parser and 'fail' +not lvcreate --type vdo --vdosettings 'ack_Xthreads=4' -L10G -V1T -ky -n $lv1 $vg + +lvcreate --type vdo --vdosettings 'ack_threads=4' -L10G -V1T -ky -n $lv1 $vg +check lv_field $vg/$lv1 vdo_ack_threads "4" +lvs -a $vg +lvremove -ff $vg + +vgremove -ff $vg diff --git a/test/shell/lvdisplay-raid.sh b/test/shell/lvdisplay-raid.sh new file mode 100644 index 0000000..32c3f34 --- /dev/null +++ b/test/shell/lvdisplay-raid.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# +# tests functionality lvdisplay tool for RAID +# + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 7 0 || skip + +aux prepare_vg 6 + +# raid0 loosing a leg +lvcreate -aey --type raid0 -i5 -l5 -n $lv $vg +lvdisplay $vg/$lv|grep "LV Status *available" +aux disable_dev "$dev1" +lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)" +aux enable_dev "$dev1" +lvremove -y $vg/$lv + +# raid1 loosing a leg/all legs +lvcreate -aey --type raid1 -m1 -l5 -n $lv $vg "$dev1" "$dev2" +lvdisplay $vg/$lv|grep "LV Status *available" +aux disable_dev "$dev1" +lvdisplay $vg/$lv|grep "LV Status *available (partial)" +aux disable_dev "$dev2" +lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)" +aux enable_dev "$dev1" "$dev2" +lvremove -y $vg/$lv + +# raid5 loosing a leg/2 legs +lvcreate -aey --type raid5 -i3 -l5 -n $lv $vg +lvdisplay $vg/$lv|grep "LV Status *available" +aux disable_dev "$dev1" +lvdisplay $vg/$lv|grep "LV Status *available (partial)" +aux disable_dev "$dev2" +lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)" +aux enable_dev "$dev1" "$dev2" +lvremove -y $vg/$lv + +# raid6 loosing a leg/2 legs/3 legs +lvcreate -aey --type raid6 -i3 -l5 -n $lv $vg +lvdisplay $vg/$lv|grep "LV Status *available" +aux disable_dev "$dev1" +lvdisplay $vg/$lv|grep "LV Status *available (partial)" +aux disable_dev "$dev2" +lvdisplay $vg/$lv|grep "LV Status *available (partial)" +aux disable_dev "$dev3" +lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)" +aux enable_dev "$dev1" "$dev2" "$dev3" +lvremove -y $vg/$lv + +# raid10 loosing a leg per mirror group / a complete mirror group +lvcreate -aey --type raid10 -i3 -l3 -n $lv $vg +lvdisplay $vg/$lv|grep "LV Status *available" +aux disable_dev "$dev1" +lvdisplay $vg/$lv|grep "LV Status *available (partial)" +aux disable_dev "$dev3" +lvdisplay $vg/$lv|grep "LV Status *available (partial)" +aux disable_dev "$dev6" +lvdisplay $vg/$lv|grep "LV Status *available (partial)" +aux enable_dev "$dev1" "$dev3" "$dev6" +lvdisplay $vg/$lv|grep "LV Status *available" +aux disable_dev "$dev1" "$dev2" +lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)" +aux enable_dev "$dev1" "$dev2" + +vgremove -y -f $vg diff --git a/test/shell/lvextend-caches-on-thindata.sh b/test/shell/lvextend-caches-on-thindata.sh new file mode 100644 index 0000000..2000c00 --- /dev/null +++ b/test/shell/lvextend-caches-on-thindata.sh @@ -0,0 +1,178 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017-2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +# lvextend thin pool data that has cache|writecache attached + +. lib/inittest + +do_test() +{ + local tp=$1 + local lvt=$2 + + # create some initial data + lvchange -ay $vg/$lvt + mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lvt" + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + cp pattern "$mount_dir/pattern1" + dd if=/dev/urandom of="$mount_dir/rand100M" bs=1M count=100 conv=fdatasync + cp pattern "$mount_dir/pattern2" + + # extend while mounted + lvextend -L+64M $vg/${tp}_tdata "$dev4" + lvs -a $vg -o+devices + + # verify initial data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + + # add more data + cp pattern "$mount_dir/pattern3" + dd if=/dev/urandom of="$mount_dir/rand8M" bs=1M count=8 conv=fdatasync + + # restart the LV + umount "$mount_dir" + lvchange -an $vg/$lvt + lvchange -an $vg/$tp + lvchange -ay $vg/$lvt + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + + # verify all data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + diff pattern "$mount_dir/pattern3" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + dd of=/dev/null if="$mount_dir/rand8M" bs=1M count=8 + + # extend again while inactive + umount "$mount_dir" + lvchange -an $vg/$lvt + lvchange -an $vg/$tp + lvextend -L+64M $vg/${tp}_tdata "$dev5" + lvs -a $vg -o+devices + lvchange -ay $vg/$lvt + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + + # verify all data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + diff pattern "$mount_dir/pattern3" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + dd of=/dev/null if="$mount_dir/rand8M" bs=1M count=8 + + # add more data + cp pattern "$mount_dir/pattern4" + + # remove the cache + lvconvert --splitcache $vg/${tp}_tdata + + # verify all data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + diff pattern "$mount_dir/pattern3" + diff pattern "$mount_dir/pattern4" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + dd of=/dev/null if="$mount_dir/rand8M" bs=1M count=8 + + umount "$mount_dir" + lvchange -an $vg/$lvt + lvchange -an $vg/$tp + lvchange -ay $vg/$lvt + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + + # verify all data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + diff pattern "$mount_dir/pattern3" + diff pattern "$mount_dir/pattern4" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + dd of=/dev/null if="$mount_dir/rand8M" bs=1M count=8 + + umount "$mount_dir" + lvchange -an $vg/$lvt + lvchange -an $vg/$tp + lvremove $vg/$lvt + lvremove $vg/$tp + lvremove -y $vg +} + + +aux have_cache 1 10 0 || skip +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +aux prepare_devs 6 400 # want 400M of usable space from each dev + +# Tests with fs block sizes require a libblkid version that shows BLOCK_SIZE +vgcreate $vg "$dev1" +lvcreate -n $lv1 -L300 $vg +mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" +blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip +lvchange -an $vg +vgremove -ff $vg + +# generate random data +dd if=/dev/urandom of=pattern bs=512K count=1 + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" + +# test extending cache|writecache on thin pool data +# test type cache|writecache +# cache with cachepool|cachevol +# cache with writeback|writethrough + +# lv1 is thinpool LV: 128M +# lv2 is fast LV: 64M +# lv3 is thin LV: 1G + +# attach writecache to thinpool data +lvcreate --type thin-pool -n $lv1 -L228M --poolmetadataspare n $vg "$dev1" "$dev2" +lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 +lvs -a $vg -o+devices +do_test $lv1 $lv3 + +# attach cache/writeback (cachevol) to thinpool data +lvcreate --type thin-pool -n $lv1 -L228M --poolmetadataspare n $vg "$dev1" "$dev2" +lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 +lvs -a $vg -o+devices +do_test $lv1 $lv3 + +# attach cache/writethrough (cachevol) to thinpool data +lvcreate --type thin-pool -n $lv1 -L228M --poolmetadataspare n $vg "$dev1" "$dev2" +lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 +lvs -a $vg -o+devices +do_test $lv1 $lv3 + +# attach cache (cachepool) to thinpool data +lvcreate --type thin-pool -n $lv1 -L228M --poolmetadataspare n $vg "$dev1" "$dev2" +lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg +lvcreate -y --type cache-pool -n $lv2 -L64M --poolmetadataspare n $vg "$dev3" "$dev6" +lvconvert -y --type cache --cachepool $lv2 --poolmetadataspare n $vg/$lv1 +lvs -a $vg -o+devices +do_test $lv1 $lv3 + +# FIXME: test these thin pool data extensions done by dmeventd + +vgremove -f $vg + diff --git a/test/shell/lvextend-caches.sh b/test/shell/lvextend-caches.sh new file mode 100644 index 0000000..4228a61 --- /dev/null +++ b/test/shell/lvextend-caches.sh @@ -0,0 +1,154 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017-2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +# lvextend LV with cache|writecache + +. lib/inittest + +case "$(uname -r)" in +6.[0123]*|5.19*) skip "Skippen test that kills this kernel" ;; +esac + +do_test() +{ + # create some initial data + lvchange -ay $vg/$lv1 + mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv1" + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + cp pattern "$mount_dir/pattern1" + dd if=/dev/urandom of="$mount_dir/rand100M" bs=1M count=100 conv=fdatasync + cp pattern "$mount_dir/pattern2" + + # extend while mounted + lvextend -L+64M $vg/$lv1 "$dev4" + lvs -a $vg -o+devices + + # verify initial data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + + # add more data + cp pattern "$mount_dir/pattern3" + dd if=/dev/urandom of="$mount_dir/rand8M" bs=1M count=8 conv=fdatasync + + # restart the LV + umount "$mount_dir" + lvchange -an $vg/$lv1 + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + + # verify all data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + diff pattern "$mount_dir/pattern3" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + dd of=/dev/null if="$mount_dir/rand8M" bs=1M count=8 + + # extend again while inactive + umount "$mount_dir" + lvchange -an $vg/$lv1 + lvextend -L+64M $vg/$lv1 "$dev5" + lvs -a $vg -o+devices + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + + # verify all data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + diff pattern "$mount_dir/pattern3" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + dd of=/dev/null if="$mount_dir/rand8M" bs=1M count=8 + + # add more data + cp pattern "$mount_dir/pattern4" + + # remove the cache + lvconvert --splitcache $vg/$lv1 + + # verify all data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + diff pattern "$mount_dir/pattern3" + diff pattern "$mount_dir/pattern4" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + dd of=/dev/null if="$mount_dir/rand8M" bs=1M count=8 + + umount "$mount_dir" + lvchange -an $vg/$lv1 + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + + # verify all data + diff pattern "$mount_dir/pattern1" + diff pattern "$mount_dir/pattern2" + diff pattern "$mount_dir/pattern3" + diff pattern "$mount_dir/pattern4" + dd of=/dev/null if="$mount_dir/rand100M" bs=1M count=100 + dd of=/dev/null if="$mount_dir/rand8M" bs=1M count=8 + + umount "$mount_dir" + lvchange -an $vg/$lv1 + lvremove $vg/$lv1 + lvremove -y $vg +} + + +aux have_cache 1 10 0 || skip +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +aux prepare_devs 6 200 # want 200M of usable space from each dev + +# generate random data +dd if=/dev/urandom of=pattern bs=512K count=1 + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" + +# test type cache|writecache +# cache with cachepool|cachevol +# cache with writeback|writethrough + +# lv1 is main LV: 300M +# lv2 is fast LV: 64M + +lvcreate -n $lv1 -L300M -an $vg "$dev1" "$dev2" +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 +lvs -a $vg -o+devices +do_test + +lvcreate -n $lv1 -L300M -an $vg "$dev1" "$dev2" +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 +lvs -a $vg -o+devices +do_test + +lvcreate -n $lv1 -L300M -an $vg "$dev1" "$dev2" +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 +lvs -a $vg -o+devices +do_test + +lvcreate -n $lv1 -L300M -an $vg "$dev1" "$dev2" +lvcreate -y --type cache-pool -n $lv2 -L64M --poolmetadataspare n $vg "$dev3" "$dev6" +lvconvert -y --type cache --cachepool $lv2 --poolmetadataspare n $vg/$lv1 +lvs -a $vg -o+devices +do_test + +vgremove -f $vg + diff --git a/test/shell/lvextend-percent-extents.sh b/test/shell/lvextend-percent-extents.sh index 1d59082..5d4946d 100644 --- a/test/shell/lvextend-percent-extents.sh +++ b/test/shell/lvextend-percent-extents.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008-2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,15 +8,21 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Check extents percentage arguments' -. lib/test -aux prepare_vg 2 128 +SKIP_WITH_LVMPOLLD=1 -lvcreate -L 64m -n $lv $vg +. lib/inittest + +aux prepare_pvs 2 128 +get_devs + +aux vgcreate $SHARED "$vg" "${DEVICES[@]}" + +lvcreate -L64 -n $lv $vg # 'lvextend rejects both size and extents without PVs' not lvextend -l 10 -L 64m $vg/$lv 2>err @@ -26,8 +33,8 @@ 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 +lvextend $vg/$lv "$dev1" | tee out +grep "Logical volume $vg/$lv successfully resized" out check pv_field "$dev1" pv_free "0" lvremove -f $vg/$lv @@ -35,7 +42,7 @@ lvremove -f $vg/$lv # 'lvextend computes necessary free space correctly - bz213552' vgsize=$(get vg_field $vg vg_extent_count) lvcreate -l $vgsize -n $lv $vg -lvreduce -f -l $(( $vgsize / 2 )) $vg/$lv +lvreduce -f -l $(( vgsize / 2 )) $vg/$lv lvextend -l $vgsize $vg/$lv # 'Reset LV to original size' @@ -43,8 +50,8 @@ 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 +lvextend -l +100%PVS $vg/$lv "$dev1" "$dev2" | tee out +grep "Logical volume $vg/$lv successfully resized" out check pv_field "$dev1" pv_free "0" check pv_field "$dev2" pv_free "0" @@ -69,15 +76,15 @@ check pv_field "$dev2" pv_free "0" # 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) +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 +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 | tee out +grep "Logical volume $vg/$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 @@ -86,17 +93,17 @@ check lv_field $vg/$lv lv_size "72.00m" # FIXME: test other segment fields such as seg_size, pvseg_start, pvseg_size lvremove -f $vg/$lv pe_count=$(get pv_field "$dev1" pv_pe_count) -pe1=$(( $pe_count / 2 )) +pe1=$(( pe_count / 2 )) lvcreate -l $pe1 -n $lv $vg pesize=$(get lv_field $vg/$lv vg_extent_size --units b --nosuffix) -segsize=$(( $pe1 * $pesize / 1024 / 1024 ))m +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 +lvextend -l +$(( pe_count * 1 )) $vg/$lv check lv_field $vg/$lv seg_count "2" -lvreduce -f -l -$(( $pe_count * 1 )) $vg/$lv +lvreduce -f -l -$(( pe_count * 1 )) $vg/$lv check lv_field $vg/$lv seg_count "1" # do not reduce to 0 extents @@ -104,3 +111,5 @@ lvremove -f $vg/$lv lvcreate -i2 -I 64k -l10 -n $lv $vg lvreduce -f -l1 $vg/$lv check lv_field $vg/$lv lv_size "8.00m" + +vgremove -ff $vg diff --git a/test/shell/lvextend-raid.sh b/test/shell/lvextend-raid.sh new file mode 100644 index 0000000..04ba554 --- /dev/null +++ b/test/shell/lvextend-raid.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 0 || skip +PROGRESS=0 +aux have_raid 1 15 0 && PROGRESS=1 + +# Use smallest regionsize to save VG space +regionsize=$(getconf PAGESIZE) # in bytes +pageregions=$(( regionsize * 8 )) # number of regions per MD bitmap page + +# in KiB +regionsize=$(( regionsize / 1024 )) + +# in MiB +lvsz=$(( pageregions * regionsize / 1024 )) +lvext=$(( lvsz / 8 )) + +aux prepare_pvs 2 $(( lvsz + 3 * lvext )) +get_devs +vgcreate -s 4k $vg ${DEVICES[@]} + +# Keep $dev1 & $dev2 always open via small active LVs. +# This trick avoids race on system with scanning udev service +# when device is 'in-use' and we cleared _rimage & _rmeta. +lvcreate -l1 $vg "$dev1" +lvcreate -l1 $vg "$dev2" + +sector=$(( $(get first_extent_sector "$dev2") + 2048 )) +aux zero_dev "$dev1" "${sector}:" +aux delayzero_dev "$dev2" 0 10 "${sector}:" + +# Create raid1 LV consuming 1 MD bitmap page +lvcreate --yes --type raid1 --regionsize ${regionsize}K -L$(( lvsz - lvext ))M -n $lv1 $vg + +lvs -a $vg + +not check lv_field $vg/$lv1 sync_percent "100.00" +check lv_field $vg/$lv1 size "$(( lvsz - lvext )).00m" $vg/$lv1 +aux wait_for_sync $vg $lv1 +check lv_field $vg/$lv1 sync_percent "100.00" +check lv_field $vg/$lv1 region_size "4.00k" + +# to slow down extension - slowdown readings +aux delayzero_dev "$dev1" 50 0 "${sector}:" +aux delayzero_dev "$dev2" 0 50 "${sector}:" + +# Extend so that full MD bitmap page is consumed +lvextend -y -L+${lvext}M $vg/$lv1 +if [ $PROGRESS -eq 1 ] +then +# Even with delayed devices wre are catching races here. +should not check lv_field $vg/$lv1 sync_percent "100.00" +check lv_field $vg/$lv1 size "$lvsz.00m" $vg/$lv1 +fi +aux wait_for_sync $vg $lv1 +check lv_field $vg/$lv1 sync_percent "100.00" + +# Extend so that another MD bitmap page is allocated +lvextend -y -L+${lvext}M $vg/$lv1 +if [ $PROGRESS -eq 1 ] +then + # Even with delayed devices wre are catching races here. + should not check lv_field $vg/$lv1 sync_percent "100.00" +else + check lv_field $vg/$lv1 sync_percent "100.00" +fi + +aux enable_dev "$dev1" "$dev2" + +aux wait_for_sync $vg $lv1 +check lv_field $vg/$lv1 sync_percent "100.00" +check lv_field $vg/$lv1 size "$(( lvsz + lvext )).00m" $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/lvextend-snapshot-dmeventd.sh b/test/shell/lvextend-snapshot-dmeventd.sh index 98bec19..e7040d3 100644 --- a/test/shell/lvextend-snapshot-dmeventd.sh +++ b/test/shell/lvextend-snapshot-dmeventd.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,16 +8,18 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest extend() { lvextend --use-policies --config "activation { snapshot_autoextend_threshold = $1 }" $vg/snap } write_() { - dd if=/dev/zero of="$DM_DEV_DIR/$vg/snap" bs=1k count=$2 seek=$1 + dd if=/dev/zero of="$DM_DEV_DIR/$vg/snap" bs=1k count=$2 seek=$1 conv=fdatasync } percent_() { @@ -25,7 +28,7 @@ percent_() { wait_for_change_() { # dmeventd only checks every 10 seconds :( - for i in $(seq 1 15) ; do + for i in $(seq 1 25) ; do test "$(percent_)" != "$1" && return sleep 1 done @@ -36,18 +39,22 @@ wait_for_change_() { aux prepare_dmeventd aux prepare_vg 2 -lvcreate -L16M -n base $vg +lvcreate -aey -L16M -n base $vg lvcreate -s -L4M -n snap $vg/base write_ 0 1000 -test 24 -eq $(percent_) +test 24 -eq "$(percent_)" lvchange --monitor y $vg/snap write_ 1000 1700 pre=$(percent_) +# Normally the usage should be ~66% here, however on slower systems +# dmeventd could be actually 'fast' enough to have COW already resized now +# so mark test skipped if we are below 50% by now +test "$pre" -gt 50 || skip wait_for_change_ $pre -test $pre -gt $(percent_) +test "$pre" -gt "$(percent_)" # check that a second extension happens; we used to fail to extend when the # utilisation ended up between THRESH and (THRESH + 10)... see RHBZ 754198 @@ -55,7 +62,9 @@ test $pre -gt $(percent_) write_ 2700 2000 pre=$(percent_) +# Mark test as skipped if already resized... +test "$pre" -gt 70 || skip wait_for_change_ $pre -test $pre -gt $(percent_) +test "$pre" -gt "$(percent_)" vgremove -f $vg diff --git a/test/shell/lvextend-snapshot-policy.sh b/test/shell/lvextend-snapshot-policy.sh index 2f5d84b..c49cbb3 100644 --- a/test/shell/lvextend-snapshot-policy.sh +++ b/test/shell/lvextend-snapshot-policy.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,9 +8,12 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest which mkfs.ext2 || skip @@ -27,23 +31,23 @@ percent() { get lv_field $vg/snap snap_percent | cut -d. -f1 } -aux prepare_dmeventd +# no dmeventd running in this test, testing --use-policies aux prepare_vg 2 -lvcreate -l 8 -n base $vg +lvcreate -aey -L24 -n base $vg mkfs.ext2 "$DM_DEV_DIR/$vg/base" -lvcreate -s -l 4 -n snap $vg/base +lvcreate -s -L16 -n snap $vg/base mkdir mnt write 1 4096 pre=$(percent) extend 50 -test $pre -eq $(percent) +test "$pre" -eq "$(percent)" write 2 4096 pre=$(percent) extend 50 -test $pre -gt $(percent) +test "$pre" -gt "$(percent)" vgremove -f $vg diff --git a/test/shell/lvextend-thin-adddel.sh b/test/shell/lvextend-thin-adddel.sh new file mode 100644 index 0000000..59b1bfa --- /dev/null +++ b/test/shell/lvextend-thin-adddel.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2022 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# +# Play with thin-pool and thin removal and creation in corner cases +# + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip + +test -n "$LVM_TEST_THIN_RESTORE_CMD" || LVM_TEST_THIN_RESTORE_CMD=$(which thin_restore) || skip +"$LVM_TEST_THIN_RESTORE_CMD" -V || skip + +aux have_thin 1 10 0 || skip + +aux prepare_vg 2 + +lvcreate -V10 -n $lv1 -L10 -T $vg/pool +lvcreate -V10 -n $lv2 $vg/pool + +# Forcibly 'error' _tmeta thin-pool metadata device +not dmsetup remove -f $vg-pool_tmeta + +# Now try to schedule removal of thin volume id 1 +# that will fail with errored meta device +not lvremove -y $vg/$lv1 + +# Check we have queued 'message' +vgcfgbackup -f out0 $vg +grep "message1" out0 + +vgchange -an $vg || true + +not dmsetup table ${vg}-pool-tpool + +# Reactivate thin-pool +vgchange -ay $vg + +# Check message is still queued there +vgcfgbackup -f out1 $vg +grep "message1" out1 + +lvchange -an $vg + +lvextend -L+10 $vg/pool + +# Messages should be now processed and gone +vgcfgbackup -f out2 $vg +not grep "message1" out2 + +lvchange -an $vg + +lvchange -y -ay $vg/pool_tmeta + +# Kernel metadata must not see dev_id 1 either +thin_dump $DM_DEV_DIR/$vg/pool_tmeta | tee meta +not grep 'dev_id="1"' meta + +lvremove -ff $vg + +lvs -a $vg + +vgremove -ff $vg diff --git a/test/shell/lvextend-thin-cache.sh b/test/shell/lvextend-thin-cache.sh new file mode 100644 index 0000000..40c213b --- /dev/null +++ b/test/shell/lvextend-thin-cache.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017-2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise resize of cached thin pool data volumes + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip +aux have_cache 1 3 0 || skip + +aux prepare_vg 2 20000 + +lvcreate -l1 -T $vg/pool +# Caching of thin-pool's dataLV +lvcreate -H -L10 $vg/pool + +lvextend -l+2 $vg/pool + +check lv_first_seg_field $vg/pool seg_size_pe "3" + +lvextend -L10G $vg/pool + +# Check data are resized and its metadata are matching data size +check lv_field $vg/pool size "10.00g" +check lv_field $vg/pool_tdata size "10.00g" +check lv_field $vg/pool_tdata_corig size "10.00g" +check lv_field $vg/pool_tmeta size "10.00m" + +vgremove -ff $vg diff --git a/test/shell/lvextend-thin-data-dmeventd.sh b/test/shell/lvextend-thin-data-dmeventd.sh new file mode 100644 index 0000000..7d37f16 --- /dev/null +++ b/test/shell/lvextend-thin-data-dmeventd.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test autoextension of thin data volume + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# As we check for 'instant' reaction +# retry only few times +test_equal_() { + for i in $(seq 1 4) ; do + test "$(get lv_field $vg/pool data_percent)" = "$1" || return + sleep 1 + done +} + +aux have_thin 1 10 0 || skip + +# set reserved stack size above dmeventd 300KiB stack +# ATM such value should be simply ignored +aux lvmconf "activation/thin_pool_autoextend_percent = 10" \ + "activation/thin_pool_autoextend_threshold = 75" \ + "activation/reserved_stack = 512" + +aux prepare_dmeventd + +aux prepare_pvs 3 256 +get_devs + +vgcreate $SHARED -s 256K "$vg" "${DEVICES[@]}" + +lvcreate -L1M -c 64k -T $vg/pool +lvcreate -V1M $vg/pool -n $lv1 + +# Fill exactly 75% +dd if=/dev/zero of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=786432c count=1 conv=fdatasync + +# when everything calcs correctly thin-pool should be exactly 75% full now +# and the size should not have changed +pre="75.00" +test_equal_ $pre || die "Data percentage has changed!" + + +# Now triger allocation of 1 extra pool chunk +dd if=/dev/zero of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=1c count=1 seek=786433 conv=fdatasync + +lvs -a -o+chunksize $vg +dmsetup table +dmsetup status + +# If the watermark works well - dmeventd should have already resized data LV +test_equal_ $pre && die "Data percentage has NOT changed!" + +vgremove -f $vg diff --git a/test/shell/lvextend-thin-full.sh b/test/shell/lvextend-thin-full.sh new file mode 100644 index 0000000..d67591d --- /dev/null +++ b/test/shell/lvextend-thin-full.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# +# play with thin-pool resize in corner cases +# + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip + +test -n "$LVM_TEST_THIN_RESTORE_CMD" || LVM_TEST_THIN_RESTORE_CMD=$(which thin_restore) || skip +"$LVM_TEST_THIN_RESTORE_CMD" -V || skip + +aux have_thin 1 10 0 || skip + +aux prepare_vg 3 4096 + +aux lvmconf 'activation/thin_pool_autoextend_percent = 30' \ + 'activation/thin_pool_autoextend_threshold = 70' + +aux prepare_thin_metadata 400 0 | tee data +lvcreate -L200 -V10 -n $lv2 -T $vg/pool +lvchange -an $vg + +# Prepare full metadata volume +lvcreate -L2M -n $lv1 $vg +"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1" +lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1 + +# active thin pool is needed to use policy +not lvextend --use-policies $vg/pool 2>&1 | tee err + +lvchange -ay $vg/$lv2 + +# Cannot resize if set to 0% +not lvextend --use-policies --config 'activation{thin_pool_autoextend_percent = 0}' $vg/pool 2>&1 | tee err +grep "0%" err + +# Creation of new LV is not allowed when thinpool is over threshold +not lvcreate -V10 $vg/pool + + +lvextend --use-policies $vg/pool "$dev2" "$dev3" +#should lvextend -l+100%FREE $vg/pool2 + +check lv_field $vg/pool_tmeta size "3.00m" + +lvextend -L+3G $vg/pool + +check lv_field $vg/pool_tmeta size "3.50m" + +lvs -a $vg + +vgremove -ff $vg diff --git a/test/shell/lvextend-thin-metadata-dmeventd.sh b/test/shell/lvextend-thin-metadata-dmeventd.sh new file mode 100644 index 0000000..732f670 --- /dev/null +++ b/test/shell/lvextend-thin-metadata-dmeventd.sh @@ -0,0 +1,207 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test autoextension of thin metadata volume + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + + +meta_percent_() { + get lv_field $vg/pool metadata_percent | cut -d. -f1 +} + +wait_for_change_() { + # dmeventd only checks every 10 seconds :( + for i in $(seq 1 12) ; do + test "$(meta_percent_)" -lt "$1" && return + sleep 1 + done + + return 1 # timeout +} + +# +# Temporary solution to create some occupied thin metadata +# This heavily depends on thin metadata output format to stay as is. +# Currently it expects 2MB thin metadata and 200MB data volume size +# Argument specifies how many devices should be created. +fake_metadata_() { + echo '' + echo ' ' + echo ' ' + echo ' ' + echo ' ' + for i in $(seq 10 $1) + do + echo ' ' + echo ' ' + echo ' ' + set +x + done + echo "" + set -x +} + +test -n "$LVM_TEST_THIN_RESTORE_CMD" || LVM_TEST_THIN_RESTORE_CMD=$(which thin_restore) || skip +"$LVM_TEST_THIN_RESTORE_CMD" -V || skip +aux have_thin 1 10 0 || skip + +BIG_DATA="" +aux thin_restore_needs_more_volumes && BIG_DATA="generate_more_metadata" + +aux prepare_dmeventd + +aux prepare_pvs 3 256 +get_devs + +vgcreate -s 1M "$vg" "${DEVICES[@]}" + +# Testing dmeventd does NOT autoresize when default threshold 100% is left +lvcreate -L200M -V50M -n thin -T $vg/pool +lvcreate -V2M -n thin2 $vg/pool +lvcreate -L2M -n $lv1 $vg +lvcreate -L32M -n $lv2 $vg +lvcreate -L32M -n $lv3 $vg +lvchange -an $vg/thin $vg/thin2 $vg/pool + +# Filling 2M metadata volume +# (Test for less than 25% free space in metadata) +fake_metadata_ 400 2 >data +"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1" + +# Swap volume with restored fake metadata +lvconvert -y --chunksize 64k --thinpool $vg/pool --poolmetadata $vg/$lv1 + +# Not alllowed when thin-pool metadata free space is <75% for 2M meta +fail lvcreate -V20 $vg/pool + + +lvchange -an $vg/pool + +# Consume more then (100% - 4MiB) out of 32MiB metadata volume (>87.5%) +# (Test for less than 4MiB free space in metadata, which is less than 25%) +DATA=7200 # Newer version of thin-pool have hidden reserve, so use lower value +test -z "$BIG_DATA" || DATA=7400 +fake_metadata_ "$DATA" 2 >data +"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv2" + +# Check tha restored metadata are OK for thin_check +"$LVM_TEST_THIN_CHECK_CMD" "$DM_DEV_DIR/mapper/$vg-$lv2" + +# Swap volume with restored fake metadata +lvconvert -y --chunksize 64k --thinpool $vg/pool --poolmetadata $vg/$lv2 +lvchange -ay $vg/pool +# Check generated metadata consume more then 88% +test "$(meta_percent_)" -gt "88" +lvchange -an $vg/pool + +# Creation of thin LV is prohibited when metadata are above this value +fail lvcreate -V20 $vg/pool 2>&1 | tee out +grep "free space" out +lvs -a $vg + + +# Check that even with 99% threshold policy - metadata will go below 88% +lvextend --use-policies --config "\ +activation/thin_pool_autoextend_percent=1 \ +activation/thin_pool_autoextend_threshold=99" $vg/pool +# Originaly wanted to test <88% - +# however some older kernels consume a bit more space, so be happy +# when it's <90% +test "$(meta_percent_)" -lt "90" + +# After such operatoin creation of thin LV has to pass +lvcreate -V20 $vg/pool + +# Let's revalidate pool metadata (thin_check upon deactivation/activation) +lvchange -an $vg +lvchange -ay $vg/pool + +lvremove -f $vg + + + +######################################################### +# Test automatic resize with help of dmeventd DOES work # +######################################################### + +aux lvmconf "activation/thin_pool_autoextend_percent = 10" \ + "activation/thin_pool_autoextend_threshold = 70" + +# Testing dmeventd autoresize +lvcreate -L200M -V500M -n thin -T $vg/pool 2>&1 | tee out +not grep "WARNING: Sum" out +lvcreate -V2M -n thin2 $vg/pool +lvcreate -L2M -n $lv1 $vg +lvchange -an $vg/thin $vg/thin2 $vg/pool + +# Prepare some fake metadata with unmatching id +# Transaction_id is lower by 1 and there are no messages -> ERROR +fake_metadata_ 10 0 >data +"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1" +lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1 +not vgchange -ay $vg 2>&1 | tee out +grep expected out + +check inactive $vg pool_tmeta + +# Transaction_id is higher by 1 +fake_metadata_ 10 3 >data +"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1" +lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1 +not vgchange -ay $vg 2>&1 | tee out +grep expected out + +check inactive $vg pool_tmeta + +# Prepare some fake metadata prefilled to ~81% (>70%) +fake_metadata_ 400 2 >data +"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1" + +# Swap volume with restored fake metadata +lvconvert -y --chunksize 64k --thinpool $vg/pool --poolmetadata $vg/$lv1 + +vgchange -ay $vg + +# Check dmeventd resizes metadata via timeout (nothing is written to pool) +pre=$(meta_percent_) +wait_for_change_ $pre + +lvchange -an $vg + +# +DATA=300 # Newer version of thin-pool have hidden reserve, so use lower value +test -z "$BIG_DATA" || DATA=350 +fake_metadata_ $DATA 2 >data +lvchange -ay $vg/$lv1 +"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1" + +lvconvert -y --chunksize 64k --thinpool $vg/pool --poolmetadata $vg/$lv1 +lvchange -ay $vg/pool $vg/$lv1 +lvs -a $vg + +lvcreate -s -Ky -n $lv2 $vg/thin +pre=$(meta_percent_) + +# go over thin metadata threshold +echo 2 >"$DM_DEV_DIR/mapper/$vg-$lv2" + +wait_for_change_ $pre + +lvs -a $vg + +vgremove -f $vg diff --git a/test/shell/lvextend-thin-raid.sh b/test/shell/lvextend-thin-raid.sh new file mode 100644 index 0000000..a706887 --- /dev/null +++ b/test/shell/lvextend-thin-raid.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip +aux have_raid 1 3 0 || skip + +aux prepare_vg 6 600 + +lvcreate --type raid1 -l2 --nosync -n pool $vg +lvconvert --yes --thinpool $vg/pool "$dev3" + +check lv_field $vg/pool seg_size_pe "2" +check lv_field $vg/pool_tdata seg_size_pe "2" -a + +lvextend -l+3 $vg/pool + +check lv_field $vg/pool seg_size_pe "5" +check lv_field $vg/pool_tdata seg_size_pe "5" -a + +lvremove -f $vg + +# check 'raid10' resize works for pool metadata resize +# https://bugzilla.redhat.com/1075644 +lvcreate --type raid10 -m1 -L5 -i3 --nosync -n pool $vg +lvcreate --type raid10 -m1 -L3 -i3 --nosync -n meta $vg +lvconvert --yes --thinpool $vg/pool --poolmetadata $vg/meta + +check lv_field $vg/pool_tdata lv_size "6.00m" -a +check lv_field $vg/pool_tmeta lv_size "3.00m" -a + +lvextend --poolmetadatasize +1 --size +1 $vg/pool + +check lv_field $vg/pool_tdata lv_size "7.50m" -a +check lv_field $vg/pool_tmeta lv_size "4.50m" -a + +lvremove -f $vg + +# check resize of pool and metadata being a different segtype +# https://bugzilla.redhat.com/1722666 +lvcreate -L4 -n pool $vg +lvcreate --type raid1 -m1 -L2 --nosync -n meta $vg +lvconvert --yes --thinpool $vg/pool --poolmetadata $vg/meta +# using big enough pool so resize of pool metadata is enforced +# (and it's using a differnt segtype) +lvextend -L3G $vg/pool + +vgremove -ff $vg diff --git a/test/shell/lvextend-thin.sh b/test/shell/lvextend-thin.sh new file mode 100644 index 0000000..d1efd47 --- /dev/null +++ b/test/shell/lvextend-thin.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip + +aux prepare_vg 3 +lvcreate -i2 -l2 -T $vg/pool2 +lvextend -l+2 $vg/pool2 "$dev2" "$dev3" +lvextend -l+100%FREE $vg/pool2 + +lvremove -f $vg + +lvcreate -L1 -n pool $vg +# Does work only with thin-pools +not lvextend --poolmetadatasize +1 $vg/pool +lvconvert -y --thinpool $vg/pool --poolmetadatasize 2 + +# _tdata cannot be used with --poolmetadata +not lvextend --poolmetadatasize +1 $vg/pool_tdata +lvextend --poolmetadatasize +1 $vg/pool_tmeta +lvextend --poolmetadatasize +1 --size +1 $vg/pool +check lv_field $vg/pool_tmeta size "4.00m" +check lv_field $vg/lvol0_pmspare size "4.00m" + +not lvresize --poolmetadatasize -1 $vg/pool + +vgremove -ff $vg diff --git a/test/shell/lvextend-vdo-dmeventd.sh b/test/shell/lvextend-vdo-dmeventd.sh new file mode 100644 index 0000000..6dbe4c4 --- /dev/null +++ b/test/shell/lvextend-vdo-dmeventd.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test autoextension of VDO pool volume + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +percent_() { + get lv_field $vg/vpool data_percent | cut -d. -f1 +} + +wait_for_change_() { + # dmeventd only checks every 10 seconds :( + for i in $(seq 1 25) ; do + test "$(percent_)" != "$1" && return + sleep 1 + done + + return 1 # timeout +} + +aux have_vdo 6 2 0 || skip + +aux prepare_dmeventd + +aux lvmconf "activation/vdo_pool_autoextend_percent = 20" \ + "activation/vdo_pool_autoextend_threshold = 70" \ + "allocation/vdo_slab_size_mb = 128" + +aux prepare_vg 1 9000 +lvcreate --vdo -V2G -L4G -n $lv1 $vg/vpool + +pre=$(percent_) +# Check out VDO pool is bellow 70% +test "$pre" -lt 70 + +# Fill space to be over 70% +dd if=/dev/urandom of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=1M count=80 conv=fdatasync + +# Should be now over 70% +pre=$(percent_) +test "$pre" -ge 70 + +wait_for_change_ $pre + +pre=$(percent_) +# Check out VDO pool gets again bellow 70% +test "$pre" -lt 70 || die "Data percentage has not changed bellow 70%!" + +# 4G * 1.2 (20%) -> 4.8G +check lv_field $vg/vpool size "4.80g" +check lv_field $vg/$lv1 size "2.00g" + +lvs -a $vg + +vgremove -f $vg diff --git a/test/shell/lvextend-vdo.sh b/test/shell/lvextend-vdo.sh new file mode 100644 index 0000000..2e9cee4 --- /dev/null +++ b/test/shell/lvextend-vdo.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_vdo 6 2 0 || skip + +aux lvmconf "activation/vdo_pool_autoextend_percent = 1" \ + "activation/vdo_pool_autoextend_threshold = 70" \ + "allocation/vdo_slab_size_mb = 128" + +aux prepare_vg 1 7000 +lvcreate --vdo -V3G -L4G -n $lv1 $vg/$lv2 + +# Resize data volume +lvextend -L+1G $vg/$lv2 +check lv_field $vg/$lv2 size "5.00g" +check lv_field $vg/${lv2}_vdata size "5.00g" + +# Resize virtual volume on top of VDO +lvextend -L+1G $vg/$lv1 +check lv_field $vg/$lv1 size "4.00g" + +lvremove -f $vg + + +# Resize by policy +lvcreate --vdo -V3G -L4G -n $lv1 $vg/$lv2 + +# Fill VDO LV to match configured threshold >= 70% +dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=60 oflag=direct +PERCENT=$(get lv_field $vg/$lv2 data_percent | cut -d. -f1) +test "$PERCENT" -ge "70" + +lvextend --use-policies "$vg/$lv2" + +# although autoextend is only 1%, it needs to extend at least by slab_size +# this is corner case where min growth requires 128M + 128k +check lv_field $vg/$lv2 size "<4.13g" + + +vgremove -ff $vg diff --git a/test/shell/lvm-conf-error.sh b/test/shell/lvm-conf-error.sh new file mode 100644 index 0000000..590834b --- /dev/null +++ b/test/shell/lvm-conf-error.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check what happens when reading of lvm.conf fails + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +MKFS=mkfs.ext3 +which $MKFS || skip +which filefrag || skip + +aux prepare_vg 1 + +mkdir mnt + +lvcreate -L5M -n $lv1 $vg + +$MKFS "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" mnt +cp etc/lvm.conf mnt + +# Figure where the file is placed in filesystem +filefrag -e mnt/lvm.conf | tee frags || rm -f frags +umount mnt + +test -s frags || skip + +# 1st. sector for filesystem +first_extent_sector=$(get first_extent_sector "$dev1") + +# find 1st. 1k block of file and trim '..' from printed number +file_block=$(awk '/0:/ { gsub(/\.\.$/, "", $4); print $4}' frags) + +# figure sector position on DM device +file_sector=$(( file_block * 2 + first_extent_sector )) + +aux error_dev "$dev1" $file_sector:2 + +mount "$DM_DEV_DIR/$vg/$lv1" mnt + +# force lvm to read lvm.conf from mnt path +LVM_SYSTEM_DIR=mnt lvs 2>&1 | tee out || true + +# shell give nice error message +grep "Failed to load config file mnt/lvm.conf" out + +aux enable_dev "$dev1" + +umount mnt + +vgremove -ff $vg diff --git a/test/shell/lvm-init.sh b/test/shell/lvm-init.sh index 8eb7814..7af3ef9 100644 --- a/test/shell/lvm-init.sh +++ b/test/shell/lvm-init.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,13 +8,16 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # tests lvm initialization, and especially negative tests of error paths # -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_devs 5 diff --git a/test/shell/lvm-on-md.sh b/test/shell/lvm-on-md.sh new file mode 100644 index 0000000..6c291b9 --- /dev/null +++ b/test/shell/lvm-on-md.sh @@ -0,0 +1,317 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018-2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +HINTS="$RUNDIR/lvm/hints" + +DFDIR="$LVM_SYSTEM_DIR/devices" +DF="$DFDIR/system.devices" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* "$VGS_ONLINE_DIR"/* +} + + +# This stops lvm from taking advantage of hints which +# will have already excluded md components. + +# This stops lvm from asking udev if a dev is an md component. +# LVM will ask udev if a dev is an md component, but we don't +# want to rely on that ability in this test. +aux lvmconf "devices/md_component_detection = 1" \ + "devices/hints = \"none\"" \ + "devices/obtain_device_list_from_udev = 0" \ + "devices/search_for_devnames = \"none\"" + +aux extend_filter_md "a|/dev/md|" + +aux prepare_devs 3 + +for level in 1 0 ; do + +# create 2 disk MD raid1 array +# by default using metadata format 1.0 with data at the end of device +# +# When a raid0 md array is stopped, the components will not look like +# duplicate PVs as they do with raid1. +# mdadm does not seem to like --chunk=64 with raid1 +case "$level" in +0) CHUNK="--chunk=64" ;; +*) CHUNK="" ;; +esac +aux mdadm_create --metadata=1.0 --level=$level $CHUNK --raid-devices=2 "$dev1" "$dev2" +mddev=$(< MD_DEV) + +vgcreate $vg "$mddev" + +lvmdevices || true +pvs -o+deviceidtype,deviceid + +PVIDMD=$(get pv_field "$mddev" uuid | tr -d - ) + +lvcreate -n $lv1 -l 2 $vg +lvcreate -n $lv2 -l 2 -an $vg + +lvchange -ay $vg/$lv2 +check lv_field $vg/$lv1 lv_active "active" + +# lvm does not show md components as PVs +pvs "$mddev" +not pvs "$dev1" +not pvs "$dev2" +pvs | tee out +not grep "$dev1" out +not grep "$dev2" out + +vgchange -an $vg + +# When the md device is started, lvm will see that and know to +# scan for md components, so stop the md device to remove this +# advantage so we will test the fallback detection. +mdadm --stop "$mddev" +aux udev_wait + +# The md components should still be detected and excluded. +not pvs "$dev1" +not pvs "$dev2" +pvs | tee out +not grep "$dev1" out +not grep "$dev2" out + +pvs 2>&1|tee out +not grep "Not using device" out + +# should not activate from the md legs +not vgchange -ay $vg + +# should not show an active lv +not dmsetup info $vg-$lv1 + +# should not allow updating vg +not lvcreate -l1 $vg + +# should not activate from the md legs +_clear_online_files +pvscan --cache -aay "$dev1" +pvscan --cache -aay "$dev2" + +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +# should not show an active lv +not dmsetup info $vg-$lv1 + +aux mdadm_assemble "$mddev" "$dev1" "$dev2" + +not pvs "$dev1" +not pvs "$dev2" +pvs | tee out +not grep "$dev1" out +not grep "$dev2" out + +lvs $vg +vgchange -an $vg + +# should not activate from the md legs +_clear_online_files +pvscan --cache -aay "$dev1" +pvscan --cache -aay "$dev2" + +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +# should not show an active lv +not dmsetup info $vg-$lv1 + +vgchange -ay $vg + +check lv_field $vg/$lv1 lv_active "active" + +vgchange -an $vg + +_clear_online_files +pvscan --cache -aay "$mddev" + +test -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test -f "$RUNDIR/lvm/vgs_online/$vg" + +check active $vg $lv1 + +vgchange -an $vg +vgremove -f $vg + +aux cleanup_md_dev +aux wipefs_a "$dev1" "$dev2" + +done + + +# Repeat tests using the default config settings + +aux lvmconf "devices/hints = \"all\"" \ + "devices/obtain_device_list_from_udev = 1" \ + "devices/search_for_devnames = \"none\"" + +rm $DF || true + +# create 2 disk MD raid0 array +# by default using metadata format 1.0 with data at the end of device +# When a raid0 md array is stopped, the components will not look like +# duplicate PVs as they do with raid1. + +aux mdadm_create --metadata=1.0 --level=0 --chunk=64 --raid-devices=2 "$dev1" "$dev2" +mddev=$(< MD_DEV) + +# Create an unused PV so that there is at least one PV in the hints +# when the MD dev is stopped. If there are no PVs, the hints are +# empty, and the code falls back to scanning all, and we do not end +# up testing the code with hints actively used. +pvcreate "$dev3" + +vgcreate $vg "$mddev" + +PVIDMD=$(get pv_field "$mddev" uuid | tr -d - ) + +lvcreate -n $lv1 -l 2 $vg +lvcreate -n $lv2 -l 2 -an $vg + +lvchange -ay $vg/$lv2 +check lv_field $vg/$lv1 lv_active "active" + +# lvm does not show md components as PVs +pvs "$mddev" +not pvs "$dev1" +not pvs "$dev2" +pvs > out +not grep "$dev1" out +not grep "$dev2" out + +grep "$mddev" "$HINTS" +grep "$dev3" "$HINTS" +not grep "$dev1" "$HINTS" +not grep "$dev2" "$HINTS" + +vgchange -an $vg + +# When the md device is started, lvm will see that and know to +# scan for md components, so stop the md device to remove this +# advantage so we will test the fallback detection. +mdadm --stop "$mddev" +aux udev_wait + +# A WARNING indicating duplicate PVs is printed by 'pvs' in this +# case. It's printed during the scan, but after the scan, the +# md component detection is run on the devs and they are dropped +# when we see they are md components. So, we ignore the warning +# containing the word duplicate, and look for the "Not using device" +# message, which shouldn't appear, as it would indicate that +# we didn't drop the md components. +# FIXME: we should avoid printing the premature warning indicating +# duplicate PVs which are eventually recognized as md components +# and dropped. +pvs 2>&1|tee out1 +grep -v -e WARNING -e "Devices file PVID" out1 > out2 +not grep "Not using device" out2 +not grep "$mddev" out2 +not grep "$dev1" out2 +not grep "$dev2" out2 +grep "$dev3" out2 +cat "$HINTS" + +pvs 2>&1|tee out1 +grep -v -e WARNING -e "Devices file PVID" out1 > out2 +not grep "Not using device" out2 +not grep "$mddev" out2 +not grep "$dev1" out2 +not grep "$dev2" out2 +grep "$dev3" out2 +cat "$HINTS" + +# The md components should still be detected and excluded. +not pvs "$dev1" +not pvs "$dev2" +pvs | tee out +not grep "$dev1" out +not grep "$dev2" out +grep "$dev3" out + +# should not activate from the md legs +not vgchange -ay $vg + +# should not show an active lv +not dmsetup info $vg-$lv1 + +# should not allow updating vg +not lvcreate -l1 $vg + +# should not activate from the md legs +_clear_online_files +pvscan --cache -aay "$dev1" +pvscan --cache -aay "$dev2" + +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +# should not show an active lv +not dmsetup info $vg-$lv1 + +# start the md dev +aux mdadm_assemble "$mddev" "$dev1" "$dev2" + +not pvs "$dev1" +not pvs "$dev2" +pvs | tee out +not grep "$dev1" out +not grep "$dev2" out + +lvs $vg +vgchange -an $vg + +# should not activate from the md legs +_clear_online_files +pvscan --cache -aay "$dev1" +pvscan --cache -aay "$dev2" + +test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test ! -f "$RUNDIR/lvm/vgs_online/$vg" + +# should not show an active lv +not dmsetup info $vg-$lv1 + +vgchange -ay $vg + +check lv_field $vg/$lv1 lv_active "active" + +vgchange -an $vg + +_clear_online_files +pvscan --cache -aay "$mddev" + +test -f "$RUNDIR/lvm/pvs_online/$PVIDMD" +test -f "$RUNDIR/lvm/vgs_online/$vg" + +check active $vg $lv1 + +vgchange -an $vg +vgremove -f $vg + +aux cleanup_md_dev diff --git a/test/shell/lvmcache-exercise.sh b/test/shell/lvmcache-exercise.sh index b1e2b92..8cfb7f1 100644 --- a/test/shell/lvmcache-exercise.sh +++ b/test/shell/lvmcache-exercise.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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 @@ -7,17 +8,56 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_pvs 5 +get_devs vgcreate $vg1 "$dev1" -vgcreate $vg2 "$dev3" +vgcreate $vg2 "$dev3" "$dev4" "$dev5" + +UUID1=$(get vg_field $vg1 uuid) aux disable_dev "$dev1" pvscan +# dev1 is missing +fail pvs "${DEVICES[@]}" + +# create a new vg1 on dev2, +# so dev1 and dev2 have different VGs with the same name vgcreate $vg1 "$dev2" + +UUID2=$(get vg_field $vg1 uuid) + +# Once dev1 is visible again, both VGs named "vg1" are visible. aux enable_dev "$dev1" -pvs + +pvs "$dev1" + +# reappearing device (rhbz 995440) +lvcreate -aey -m2 --type mirror -l4 --alloc anywhere --corelog -n $lv1 $vg2 + +aux disable_dev "$dev3" + +pvs 2>&1| tee out +grep "is missing PV" out + +lvconvert --yes --repair $vg2/$lv1 + +aux enable_dev "$dev3" + +lvs -a $vg2 -o+devices 2>&1 | tee out +not grep "is missing PV" out + +# This removes the first "vg1" using its uuid +vgremove -ff -S vg_uuid=$UUID1 + +# This removes the second "vg1" using its name, +# now that there is only one VG with that name. +vgremove -ff $vg1 $vg2 + diff --git a/test/shell/lvmetad-disabled.sh b/test/shell/lvmetad-disabled.sh deleted file mode 100644 index 41a3a19..0000000 --- a/test/shell/lvmetad-disabled.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test - -test -e LOCAL_LVMETAD || skip -kill $(cat LOCAL_LVMETAD) - -test -e $LVMETAD_PIDFILE && skip -lvmetad -test -e $LVMETAD_PIDFILE -cp $LVMETAD_PIDFILE LOCAL_LVMETAD -pvs 2>&1 | not grep "lvmetad is running" -aux lvmconf "global/use_lvmetad = 0" -pvs 2>&1 | grep "lvmetad is running" - -kill $(cat $LVMETAD_PIDFILE) -not ls $LVMETAD_PIDFILE diff --git a/test/shell/lvmetad-dump.sh b/test/shell/lvmetad-dump.sh deleted file mode 100644 index e49eb68..0000000 --- a/test/shell/lvmetad-dump.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test -test -e LOCAL_LVMETAD || skip - -aux prepare_pvs 2 -vgcreate $vg1 $dev1 $dev2 -lvcreate -n bar -l 1 $vg1 - -lvmetad_talk() { - if type -p socat >& /dev/null; then - socat "unix-connect:$1" - - elif echo | nc -U "$1"; then - nc -U "$1" - else - echo "WARNING: Neither socat nor nc -U seems to be available." 1>&2 - echo "# DUMP FAILED" - return 1 - fi -} - -lvmetad_dump() { - (echo 'request="dump"'; echo '##') | lvmetad_talk "$@" -} - -(echo | lvmetad_talk ./lvmetad.socket) || skip -lvmetad_dump ./lvmetad.socket | tee lvmetad.txt - -grep $vg1 lvmetad.txt diff --git a/test/shell/lvmetad-lvm1.sh b/test/shell/lvmetad-lvm1.sh deleted file mode 100644 index 528eec2..0000000 --- a/test/shell/lvmetad-lvm1.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test - -test -e LOCAL_LVMETAD || skip -aux prepare_devs 2 -pvcreate --metadatatype 1 $dev1 -vgscan --cache -pvs | grep $dev1 -vgcreate --metadatatype 1 $vg1 $dev1 -vgscan --cache -vgs | grep $vg1 -pvs | grep $dev1 diff --git a/test/shell/lvmetad-pvs.sh b/test/shell/lvmetad-pvs.sh deleted file mode 100644 index 80b421c..0000000 --- a/test/shell/lvmetad-pvs.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test - -aux prepare_pvs 1 20000 -pvs $(cat DEVICES) | grep "$dev1" - -# check for PV size overflows -pvs $(cat DEVICES) | grep 19.53g -pvs $(cat DEVICES) | not grep 16.00e diff --git a/test/shell/lvmetad-pvscan-cache.sh b/test/shell/lvmetad-pvscan-cache.sh deleted file mode 100644 index a27b6ad..0000000 --- a/test/shell/lvmetad-pvscan-cache.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test - -test -e LOCAL_LVMETAD || skip - -aux prepare_pvs 2 - -vgcreate $vg1 $dev1 $dev2 -vgs | grep $vg1 - -pvscan --cache - -vgs | grep $vg1 diff --git a/test/shell/lvmetad-restart.sh b/test/shell/lvmetad-restart.sh deleted file mode 100644 index 10268c2..0000000 --- a/test/shell/lvmetad-restart.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test - -test -e LOCAL_LVMETAD || skip -aux prepare_pvs 2 - -vgcreate $vg1 $dev1 $dev2 -vgs | grep $vg1 - -kill $(cat LOCAL_LVMETAD) -aux prepare_lvmetad - -vgs | grep $vg1 diff --git a/test/shell/lvmetad-test.sh b/test/shell/lvmetad-test.sh deleted file mode 100644 index 7e801f1..0000000 --- a/test/shell/lvmetad-test.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test - -aux prepare_pvs 2 - -vgcreate $vg1 $dev1 $dev2 --test -vgs | not grep $vg1 -vgcreate $vg1 $dev1 $dev2 -vgs | grep $vg1 - -lvcreate -n bar -l 1 $vg1 --test -lvs | not grep bar -lvcreate -n bar -l 1 $vg1 -lvs | grep bar - -lvremove $vg1/bar -f --test -lvs | grep bar -lvremove $vg1/bar -f -lvs | not grep bar - -vgremove $vg1 --test -vgs | grep $vg1 -vgremove $vg1 -vgs | not grep $vg1 diff --git a/test/shell/lvmetad-warning.sh b/test/shell/lvmetad-warning.sh deleted file mode 100644 index 3a97a1b..0000000 --- a/test/shell/lvmetad-warning.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh -# Copyright (C) 2012 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 - -. lib/test - -test -e LOCAL_LVMETAD || skip -aux prepare_pvs 2 - -vgcreate $vg1 $dev1 $dev2 -lvchange -ay $vg1 2>&1 | not grep "Failed to connect" -kill $(cat LOCAL_LVMETAD) -lvchange -ay $vg1 2>&1 | grep "Failed to connect" -lvchange -ay $vg1 --sysinit 2>&1 | not grep "Failed to connect" -aux lvmconf 'global/use_lvmetad = 0' -lvchange -ay $vg1 2>&1 | not grep "Failed to connect" -lvchange -ay $vg1 --sysinit 2>&1 | not grep "Failed to connect" -aux prepare_lvmetad -lvchange -ay $vg1 2>&1 | not grep "Failed to connect" -lvchange -ay $vg1 --sysinit 2>&1 | not grep "Failed to connect" diff --git a/test/shell/lvmlockd-hello-world.sh b/test/shell/lvmlockd-hello-world.sh new file mode 100644 index 0000000..2e1d329 --- /dev/null +++ b/test/shell/lvmlockd-hello-world.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Hello world for vgcreate $SHARED with lvmlockd and sanlock' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LVMLOCKD" ] && skip + +aux prepare_pvs 1 + +vgcreate $SHARED $vg "$dev1" + +vgs -o+locktype,lockargs $vg + +vgremove $vg diff --git a/test/shell/lvmlockd-lv-types.sh b/test/shell/lvmlockd-lv-types.sh new file mode 100644 index 0000000..398c964 --- /dev/null +++ b/test/shell/lvmlockd-lv-types.sh @@ -0,0 +1,192 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Check lvmlockd lock_args for different LV types' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LVMLOCKD" ] && skip; + +if test -n "$LVM_TEST_LOCK_TYPE_SANLOCK" ; then +LOCKARGS1="1.0.0:70254592" +LOCKARGS2="1.0.0:71303168" +LOCKARGS3="1.0.0:72351744" +fi + +if test -n "$LVM_TEST_LOCK_TYPE_DLM" ; then +LOCKARGS1="dlm" +LOCKARGS2="dlm" +LOCKARGS3="dlm" +fi + +if test -n "$LVM_TEST_LVMLOCKD_TEST" ; then +LOCKARGS1="dlm" +LOCKARGS2="dlm" +LOCKARGS3="dlm" +fi + +if test -n "$LVM_TEST_LOCK_TYPE_IDM" ; then +LOCKARGS1="idm" +LOCKARGS2="idm" +LOCKARGS3="idm" +fi + +aux prepare_devs 5 + +vgcreate --shared $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + +# +# pvscan autoactivation ignore shared PVs +# +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" + +PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}') +pvscan --cache -aay "$dev1" +not ls "$RUNDIR/lvm/pvs_online/$PVID1" +pvscan --cache -aay +not ls "$RUNDIR/lvm/pvs_online/$PVID1" +not ls "$RUNDIR/lvm/vgs_online/$vg" + + +# +# thin pool, thin lv, thin snap +# + +lvcreate -L 8M -n pool1 $vg +check lva_field $vg/pool1 lockargs $LOCKARGS1 + +lvcreate -L 8M -n pool1_meta $vg +check lva_field $vg/pool1_meta lockargs $LOCKARGS2 + +lvconvert -y --type thin-pool --poolmetadata $vg/pool1_meta $vg/pool1 +check lva_field $vg/pool1 lockargs $LOCKARGS3 +check lva_field $vg/pool1_tdata lockargs "" +check lva_field $vg/pool1_tmeta lockargs "" + +lvcreate -n thin1 -V 1G --thinpool $vg/pool1 +check lva_field $vg/thin1 lockargs "" + +lvcreate -s -n snap1 $vg/thin1 +check lva_field $vg/snap1 lockargs "" + +lvchange -ay -K $vg/snap1 + +lvchange -an $vg/snap1 +lvchange -an $vg/thin1 +lvchange -an $vg/pool1 +lvremove $vg/snap1 +lvremove $vg/thin1 +lvremove $vg/pool1 + +# the first sanlock lock should be found and reused +lvcreate -L 8M -n lv1 $vg +check lva_field $vg/lv1 lockargs $LOCKARGS1 + +lvchange -an $vg/lv1 +lvremove $vg/lv1 + + +# +# with automatic metadata lv +# + +lvcreate -L 8M -n pool2 $vg +check lva_field $vg/pool2 lockargs $LOCKARGS1 + +lvconvert -y --type thin-pool $vg/pool2 +check lva_field $vg/pool2 lockargs $LOCKARGS2 +check lva_field $vg/pool2_tdata lockargs "" +check lva_field $vg/pool2_tmeta lockargs "" + +lvcreate -n thin2 -V 1G --thinpool $vg/pool2 +check lva_field $vg/thin2 lockargs "" + +lvchange -an $vg/thin2 +lvchange -an $vg/pool2 +lvremove $vg/thin2 +lvremove $vg/pool2 + + +# +# cache pool, cache lv +# + +lvcreate -L 8M -n cache1 $vg +check lva_field $vg/cache1 lockargs $LOCKARGS1 + +lvcreate -L 8M -n cache1_meta $vg +check lva_field $vg/cache1_meta lockargs $LOCKARGS2 + +lvconvert -y --type cache-pool --poolmetadata $vg/cache1_meta $vg/cache1 +check lva_field $vg/cache1 lockargs "" +check lva_field $vg/cache1_cdata lockargs "" +check lva_field $vg/cache1_cmeta lockargs "" + +lvcreate -n lv1 -L 8M $vg +check lva_field $vg/lv1 lockargs $LOCKARGS1 + +lvconvert -y --type cache --cachepool $vg/cache1 $vg/lv1 +check lva_field $vg/lv1 lockargs $LOCKARGS1 +check lva_field $vg/cache1_cpool lockargs "" +check lva_field $vg/cache1_cpool_cdata lockargs "" +check lva_field $vg/cache1_cpool_cmeta lockargs "" + +lvconvert --splitcache $vg/lv1 +check lva_field $vg/lv1 lockargs $LOCKARGS1 +check lva_field $vg/cache1 lockargs "" +check lva_field $vg/cache1_cdata lockargs "" +check lva_field $vg/cache1_cmeta lockargs "" + +lvchange -an $vg/cache1 +lvchange -an $vg/lv1 +lvremove $vg/cache1 +lvremove $vg/lv1 + +# +# cow snap +# + +lvcreate -n lv2 -L 8M $vg +check lva_field $vg/lv2 lockargs $LOCKARGS1 + +lvcreate -s -n lv2snap -L 8M $vg/lv2 +check lva_field $vg/lv2 lockargs $LOCKARGS1 +check lva_field $vg/lv2snap lockargs "" + +lvchange -y -an $vg/lv2 +lvremove $vg/lv2snap +lvremove $vg/lv2 + +# +# mirror +# + +lvcreate --type mirror -m 1 -n lv3 -L 8M $vg +check lva_field $vg/lv3 lockargs $LOCKARGS1 + +lvchange -an $vg/lv3 +lvremove $vg/lv3 + +# +# raid1 +# + +lvcreate --type raid1 -m 1 -n lv4 -L 8M $vg +check lva_field $vg/lv4 lockargs $LOCKARGS1 + +lvchange -an $vg/lv4 +lvremove $vg/lv4 + +vgremove $vg diff --git a/test/shell/lvmlockd_failure.sh b/test/shell/lvmlockd_failure.sh new file mode 100644 index 0000000..2825462 --- /dev/null +++ b/test/shell/lvmlockd_failure.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020~2021 Seagate, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_FAILURE" ] && skip + +aux prepare_vg 3 + +# Create new logic volume +lvcreate -a ey --zero n -l 1 -n $lv1 $vg + +# FIXME - test shall NOT kill random processes in the system! +# Emulate lvmlockd abnormally exiting +killall -9 lvmlockd + +systemctl start lvm2-lvmlockd + +vgchange --lock-start $vg + +lvchange -a n $vg/$lv1 +lvchange -a sy $vg/$lv1 + +lvcreate -a ey --zero n -l 1 -n $lv2 $vg +lvchange -a n $vg/$lv2 + +vgremove -ff $vg diff --git a/test/shell/lvremove-thindata-caches.sh b/test/shell/lvremove-thindata-caches.sh new file mode 100644 index 0000000..ba099c3 --- /dev/null +++ b/test/shell/lvremove-thindata-caches.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017-2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 10 0 || skip +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +aux prepare_devs 6 70 # want 64M of usable space from each dev + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" + +# lv1 is thinpool LV: 128M +# lv2 is fast LV: 64M +# lv3 is thin LV: 1G + +# +# Test lvremove of a thinpool that uses cache|writecache on data +# + +# attach writecache to thinpool data +lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2" +lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 +lvchange -ay $vg/$lv1 +lvs -a $vg +mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3" +lvremove -y $vg/$lv1 + +# attach cache/writeback (cachevol) to thinpool data +lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2" +lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type cache --cachevol $lv2 --cachemode writeback $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3" +lvremove -y $vg/$lv1 + +# attach cache/writethrough (cachevol) to thinpool data +lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2" +lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg +lvcreate -n $lv2 -L64M -an $vg "$dev3" +lvconvert -y --type cache --cachevol $lv2 --cachemode writethrough $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3" +lvremove -y $vg/$lv1 + +# attach cache (cachepool) to thinpool data +lvcreate --type thin-pool -n $lv1 -L128M --poolmetadataspare n $vg "$dev1" "$dev2" +lvcreate --type thin -n $lv3 -V1G --thinpool $lv1 $vg +lvcreate -y --type cache-pool -n $lv2 -L64M --poolmetadataspare n $vg "$dev3" "$dev6" +lvconvert -y --type cache --cachepool $lv2 --poolmetadataspare n $vg/$lv1 +lvchange -ay $vg/$lv1 +mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lv3" +lvremove -y $vg/$lv1 + +vgremove -f $vg + diff --git a/test/shell/lvrename-cache-thin.sh b/test/shell/lvrename-cache-thin.sh new file mode 100644 index 0000000..a77a2c1 --- /dev/null +++ b/test/shell/lvrename-cache-thin.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check rename of stacked thin over cached LV + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip +aux have_thin 1 0 0 || skip + +aux prepare_vg 1 80 + +lvcreate -L10 -n cpool $vg +lvcreate -L10 -n tpool $vg +lvcreate -L10 -n $lv1 $vg + +lvconvert --yes --type cache-pool $vg/cpool + +lvconvert --yes --cache --cachepool cpool $vg/tpool + +# currently the only allowed stacking is cache thin data volume +lvconvert --yes --type thin-pool $vg/tpool + +lvcreate -V10 $vg/tpool + +# check cache pool remains same after thin-pool rename +lvrename $vg/tpool $vg/newpool + +check lv_exists $vg newpool cpool_cpool +check lv_not_exists $vg tpool + +# allowing rename of internal cache pool +lvrename $vg/cpool_cpool $vg/cachepool + +check lv_exists $vg cachepool +check lv_not_exists $vg cpool_cpool + +lvs -a $vg + +vgremove -f $vg diff --git a/test/shell/lvrename-vdo.sh b/test/shell/lvrename-vdo.sh new file mode 100644 index 0000000..1417d9f --- /dev/null +++ b/test/shell/lvrename-vdo.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check online renaming of VDO devices works + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# +# Main +# + +aux have_vdo 6 2 1 || skip +aux have_cache 1 3 0 || skip +aux have_raid 1 3 0 || skip + +aux prepare_vg 2 5000 + +lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1 +lvrename $vg/vpool1 vpool2 +check lv_exists $vg $lv1 vpool2 vpool2_vdata + +lvremove -ff $vg + +# With version >= 6.2.3 online rename should work +if aux have_vdo 6 2 3 ; then + +### CACHE #### +lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1 +lvcreate -H -L10 $vg/vpool1 +lvrename $vg/vpool1 $vg/vpool2 +check lv_exists $vg vpool2 vpool2_vdata +lvremove -ff $vg + +### RAID #### +lvcreate --type raid1 -L4G --nosync --name vpool1 $vg +lvconvert --yes --type vdo-pool $vg/vpool1 +lvrename $vg/vpool1 $vg/vpool2 +check lv_exists $vg vpool2 vpool2_vdata vpool2_vdata_rimage_0 +lvremove -ff $vg + +fi # >= 6.2.3 + +# Check when VDO target does not support online resize +aux lvmconf "global/vdo_disabled_features = [ \"online_rename\" ]" + + +### CACHE #### +lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1 +lvcreate -H -L10 $vg/vpool1 + +# VDO target driver cannot handle online rename +not lvrename $vg/vpool1 $vg/vpool2 2>&1 | tee out +grep "Cannot rename" out + +# Ofline should work +lvchange -an $vg +lvrename $vg/vpool1 $vg/vpool2 +lvchange -ay $vg +check lv_exists $vg $lv1 vpool2 vpool2_vdata +lvremove -ff $vg + + +### RAID #### +lvcreate --type raid1 -L4G --nosync --name vpool1 $vg +lvconvert --yes --type vdo-pool $vg/vpool1 +not lvrename $vg/vpool1 $vg/vpool2 2>&1 | tee out +grep "Cannot rename" out + +# Ofline should work +lvchange -an $vg +lvrename $vg/vpool1 $vg/vpool2 +lvchange -ay $vg +check lv_exists $vg vpool2 vpool2_vdata vpool2_vdata_rimage_0 +lvremove -ff $vg + +vgremove -ff $vg diff --git a/test/shell/lvresize-fs-crypt.sh b/test/shell/lvresize-fs-crypt.sh new file mode 100644 index 0000000..966870d --- /dev/null +++ b/test/shell/lvresize-fs-crypt.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env bash + +# Copyright (C) 2007-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 3 256 + +which mkfs.xfs || skip + +# Tests require a libblkid version that shows FSLASTBLOCK +lvcreate -n $lv1 -L 300 $vg +mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" +blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep FSLASTBLOCK || skip +lvremove -f $vg/$lv1 + +mount_dir="mnt_lvresize_cr" +mkdir -p "$mount_dir" + +# dm-crypt device on lv +cr="$PREFIX-$lv-cr" + +# lvextend ext4 on LUKS1 +lvcreate -n $lv -L 256M $vg +echo 93R4P4pIqAH8 | cryptsetup luksFormat -i1 --type luks1 "$DM_DEV_DIR/$vg/$lv" +echo 93R4P4pIqAH8 | cryptsetup luksOpen "$DM_DEV_DIR/$vg/$lv" $cr +mkfs.ext4 /dev/mapper/$cr +mount /dev/mapper/$cr "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +lvextend -L+200M --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "456.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +umount "$mount_dir" +cryptsetup close $cr +lvremove -f $vg/$lv + +# lvreduce ext4 on LUKS1 +lvcreate -n $lv -L 456M $vg +echo 93R4P4pIqAH8 | cryptsetup luksFormat -i1 --type luks1 "$DM_DEV_DIR/$vg/$lv" +echo 93R4P4pIqAH8 | cryptsetup luksOpen "$DM_DEV_DIR/$vg/$lv" $cr +mkfs.ext4 /dev/mapper/$cr +mount /dev/mapper/$cr "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +lvresize -L-100M --yes --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "356.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +umount "$mount_dir" +cryptsetup close $cr +lvremove -f $vg/$lv + +# lvextend xfs on LUKS1 +lvcreate -n $lv -L 320M $vg +echo 93R4P4pIqAH8 | cryptsetup luksFormat -i1 --type luks1 "$DM_DEV_DIR/$vg/$lv" +echo 93R4P4pIqAH8 | cryptsetup luksOpen "$DM_DEV_DIR/$vg/$lv" $cr +mkfs.xfs /dev/mapper/$cr +mount /dev/mapper/$cr "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +lvextend -L+136M --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "456.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +umount "$mount_dir" +cryptsetup close $cr +lvremove -f $vg/$lv + +# lvreduce xfs on LUKS1 +lvcreate -n $lv -L 456M $vg +echo 93R4P4pIqAH8 | cryptsetup luksFormat -i1 --type luks1 "$DM_DEV_DIR/$vg/$lv" +echo 93R4P4pIqAH8 | cryptsetup luksOpen "$DM_DEV_DIR/$vg/$lv" $cr +mkfs.xfs /dev/mapper/$cr +mount /dev/mapper/$cr "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +# xfs cannot be reduced +not lvresize -L-100M --yes --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "456.00m" +df --output=size "$mount_dir" |tee df2 +diff df1 df2 +umount "$mount_dir" +cryptsetup close $cr +lvremove -f $vg/$lv + +# lvextend ext4 on plain crypt (no header) +lvcreate -n $lv -L 256M $vg +echo 93R4P4pIqAH8 | cryptsetup create $cr "$DM_DEV_DIR/$vg/$lv" +mkfs.ext4 /dev/mapper/$cr +mount /dev/mapper/$cr "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +# fails when no fs is found for --fs resize +not lvextend -L+200M --yes --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "256.00m" +df --output=size "$mount_dir" |tee df2 +diff df1 df2 +umount "$mount_dir" +cryptsetup close $cr +lvremove -f $vg/$lv + +# lvreduce ext4 on plain crypt (no header) +lvcreate -n $lv -L 456M $vg +echo 93R4P4pIqAH8 | cryptsetup create $cr "$DM_DEV_DIR/$vg/$lv" +mkfs.ext4 /dev/mapper/$cr +mount /dev/mapper/$cr "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +# fails when no fs is found for --fs resize +not lvresize -L-100M --yes --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "456.00m" +df --output=size "$mount_dir" |tee df2 +diff df1 df2 +umount "$mount_dir" +cryptsetup close $cr +lvremove -f $vg/$lv + +# lvresize uses helper only for crypt dev resize +# because the fs was resized separately beforehand +lvcreate -n $lv -L 456M $vg +echo 93R4P4pIqAH8 | cryptsetup luksFormat -i1 --type luks1 "$DM_DEV_DIR/$vg/$lv" +echo 93R4P4pIqAH8 | cryptsetup luksOpen "$DM_DEV_DIR/$vg/$lv" $cr +mkfs.ext4 /dev/mapper/$cr +mount /dev/mapper/$cr "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct +df --output=size "$mount_dir" |tee df1 +# resize only the fs (to 256M), not the crypt dev or LV +umount "$mount_dir" +fsck -n /dev/mapper/$cr +resize2fs /dev/mapper/$cr 262144k +mount /dev/mapper/$cr "$mount_dir" +# this lvresize will not resize the fs (which is already reduced +# to smaller than the requested LV size), but lvresize will use +# the helper to resize the crypt dev before resizing the LV. +# Using --fs resize is required to allow lvresize to look above +# the lv at crypt&fs layers for potential resizing. Without +# --fs resize, lvresize fails because it sees that crypt resize +# is needed and --fs resize is needed to enable that. +not lvresize -L-100 $vg/$lv +lvresize -L-100M --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "356.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +umount "$mount_dir" +cryptsetup close $cr +lvremove -f $vg/$lv + +# test with LUKS2? + +vgremove -ff $vg diff --git a/test/shell/lvresize-fs.sh b/test/shell/lvresize-fs.sh new file mode 100644 index 0000000..d2c4ac7 --- /dev/null +++ b/test/shell/lvresize-fs.sh @@ -0,0 +1,627 @@ +#!/usr/bin/env bash + +# Copyright (C) 2007-2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 2 100 + +which mkfs.ext4 || skip +which resize2fs || skip + +# +# Workaroudn for kernel bug fixed with: +# a408f33e895e455f16cf964cb5cd4979b658db7b +# refreshing DM device - using fsfreeze with suspend +# +workaround_() { + blkid -p "$DM_DEV_DIR/$vg/$lv" >/dev/null || { + dmsetup suspend $vg-$lv + dmsetup resume $vg-$lv + } +} + +mount_dir="mnt_lvresize_fs" +mkdir -p "$mount_dir" + +mount_dir_space="other mnt dir" +mkdir -p "$mount_dir_space" + +mount_dir_2="mnt_lvresize_fs_2" +mkdir -p "$mount_dir_2" + +# Test combinations of the following: +# lvreduce / lvextend +# no fs / ext4 +# each --fs opt / no --fs opt / --resizefs +# active / inactive +# mounted / unmounted +# fs size less than, equal to or greater than reduced lv size + + +################### +# +# lvextend, no fs +# +################### + +# lvextend, no fs, active, no --fs +lvcreate -n $lv -L 10M $vg +lvextend -L+20M $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" + +# lvextend, no fs, active, --fs resize fails with no fs found +not lvextend -L+20M --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" + +lvchange -an $vg/$lv + +# lvextend, no fs, inactive, --fs resize error requires active lv +not lvextend -L+20M --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" + +# lvextend, no fs, inactive, no --fs +lvextend -L+30M $vg/$lv +check lv_field $vg/$lv lv_size "60.00m" + +lvremove -f $vg + + +################### +# +# lvreduce, no fs +# +################### + +# lvreduce, no fs, active, no --fs setting is same as --fs checksize +lvcreate -n $lv -L 50M $vg +lvreduce -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "40.00m" +lvchange -an $vg/$lv + +# lvreduce, no fs, inactive, no --fs setting is same as --fs checksize +not lvreduce -L-10M $vg/$lv +lvreduce --fs checksize -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" + +# lvreduce, no fs, inactive, --fs ignore +lvreduce -L-10M --fs ignore $vg/$lv +check lv_field $vg/$lv lv_size "20.00m" + +# lvreduce, no fs, active, --fs resize requires fs to be found +lvchange -ay $vg/$lv +not lvreduce -L-10M --fs resize $vg/$lv +check lv_field $vg/$lv lv_size "20.00m" + +lvremove -f $vg/$lv + + +################# +# +# lvextend, ext4 +# +################# + +# Use one instance of ext4 for series of lvextend tests: +lvcreate -n $lv -L 20M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" + +# --fs tests require a libblkid version that shows FSLASTBLOCK +# so exit 0 test here, if the feature is not present +blkid -p "$DM_DEV_DIR/$vg/$lv" | grep FSLASTBLOCK || exit 0 + + +# lvextend, ext4, active, mounted, no --fs setting is same as --fs ignore +df --output=size "$mount_dir" |tee df1 +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=8 oflag=direct +lvextend -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" +# with no --fs used, the fs size should be the same +df --output=size "$mount_dir" |tee df2 +diff df1 df2 +resize2fs "$DM_DEV_DIR/$vg/$lv" +df --output=size "$mount_dir" |tee df3 +not diff df2 df3 +dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=10 oflag=direct +# keep mounted fs + +# lvextend, ext4, active, mounted, --fs ignore +df --output=size "$mount_dir" |tee df1 +lvextend --fs ignore -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "40.00m" +df --output=size "$mount_dir" |tee df2 +diff df1 df2 +# keep mounted fs + +# lvextend, ext4, active, mounted, --fs resize +lvextend --fs resize -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "50.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +# keep mounted fs + +workaround_ + +# lvextend, ext4, active, mounted, --resizefs (same as --fs resize) +df --output=size "$mount_dir" |tee df1 +lvextend --resizefs -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "60.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +# keep mounted fs + +workaround_ + +# lvextend, ext4, active, mounted, --fs resize --fsmode manage (same as --fs resize) +df --output=size "$mount_dir" |tee df1 +lvextend --fs resize --fsmode manage -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "70.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +dd if=/dev/zero of="$mount_dir/zeros3" bs=1M count=10 oflag=direct +# keep mounted fs + +workaround_ + +# lvextend, ext4, active, mounted, --fs resize_fsadm +df --output=size "$mount_dir" |tee df1 +lvextend --fs resize_fsadm -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "80.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +# keep mounted fs + +workaround_ + +# lvextend, ext4, active, mounted, --fs resize --fsmode nochange +df --output=size "$mount_dir" |tee df1 +lvextend --fs resize --fsmode nochange -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "90.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +# keep mounted fs + +# lvextend|lvreduce, ext4, active, mounted, --fs resize, renamed LV +lvrename $vg/$lv $vg/$lv2 +not lvextend --fs resize -L+32M $vg/$lv2 +not lvreduce --fs resize -L-32M $vg/$lv2 +umount "$mount_dir" + +# lvextend|lvreduce, ext4, active, mounted, mount dir with space, --fs resize, renamed LV +mount "$DM_DEV_DIR/$vg/$lv2" "$mount_dir_space" +lvrename $vg/$lv2 $vg/$lv3 +not lvextend --fs resize -L+32M $vg/$lv3 +not lvreduce --fs resize -L-32M $vg/$lv3 +umount "$mount_dir_space" + +lvremove -f $vg/$lv3 + + +################################# +# +# lvextend, ext4, multiple mounts +# +################################# + +# Use one instance of ext4 for series of lvextend tests: +lvcreate -n $lv -L 32M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir_2" + +# lvextend, ext4, active, mounted twice, -r +lvextend -r -L+8M $vg/$lv +check lv_field $vg/$lv lv_size "40.00m" + +workaround_ + +lvrename $vg/$lv $vg/$lv2 +not lvextend -r -L+8M $vg/$lv2 +not lvreduce -r -L-8M $vg/$lv2 +umount "$mount_dir" +umount "$mount_dir_2" +lvextend -r -L+8M $vg/$lv2 + +mount "$DM_DEV_DIR/$vg/$lv2" "$mount_dir" +mount --bind "$mount_dir" "$mount_dir_2" +lvextend -r -L+8M $vg/$lv2 +check lv_field $vg/$lv2 lv_size "56.00m" +lvrename $vg/$lv2 $vg/$lv3 +not lvextend -r -L+8M $vg/$lv3 +not lvreduce -r -L-8M $vg/$lv3 +umount "$mount_dir" +umount "$mount_dir_2" +mount "$DM_DEV_DIR/$vg/$lv3" "$mount_dir" +lvextend -r -L+8M $vg/$lv3 +lvreduce -r -y -L-8M $vg/$lv3 +umount "$mount_dir" + +lvremove -f $vg/$lv3 + +##################################### +# +# Now let do some unmounted tests +# +##################################### + +# prepare new ext4 setup +lvcreate -n $lv -L 15M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" + +# lvextend, ext4, inactive, --fs ignore +lvchange -an $vg/$lv +lvextend --fs ignore -L+5M $vg/$lv +check lv_field $vg/$lv lv_size "20.00m" +lvchange -ay $vg/$lv + +# lvextend, ext4, active, mounted, --fs resize --fsmode offline +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df1 +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=8 oflag=direct +lvextend --fs resize --fsmode offline -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" +# fsmode offline leaves fs unmounted +df -a | tee dfa +not grep "$mount_dir" dfa +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=10 oflag=direct +umount "$mount_dir" + +# lvextend, ext4, active, unmounted, --fs resize --fsmode nochange +df --output=size "$mount_dir" |tee df1 +lvextend --fs resize --fsmode nochange -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "40.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +umount "$mount_dir" + +# lvextend, ext4, active, unmounted, --fs resize +lvextend --fs resize -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "50.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +umount "$mount_dir" + +# lvextend, ext4, active, unmounted, --fs resize_fsadm +lvextend --fs resize_fsadm -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "60.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 +umount "$mount_dir" + +lvremove -f $vg/$lv + + +#################################################################### +# +# lvreduce, ext4, no --fs setting and the equivalent --fs checksize +# i.e. fs is not resized +# +#################################################################### + +# lvreduce, ext4, active, mounted, no --fs setting is same as --fs checksize +# fs smaller than the reduced size +lvcreate -n $lv -L 20M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +lvextend -L+25M $vg/$lv +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct +df --output=size "$mount_dir" |tee df1 +# fs is 20M, reduced size is 27M, so no fs reduce is needed +# todo: check that resize2fs was not run? +lvreduce -L27M $vg/$lv +check lv_field $vg/$lv lv_size "27.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +# keep fs mounted + +# lvreduce, ext4, active, mounted, no --fs setting is same as --fs checksize +# fs equal to the reduced size +lvreduce -L20M $vg/$lv +check lv_field $vg/$lv lv_size "20.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +# keep fs mounted + +# lvreduce, ext4, active, mounted, no --fs setting is same as --fs checksize +# fs larger than the reduced size, fs not using reduced space +# lvreduce fails because fs needs to be reduced and checksize does not resize +not lvreduce -L-18M $vg/$lv +check lv_field $vg/$lv lv_size "20.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +# keep fs mounted + +# lvreduce, ext4, active, mounted, no --fs setting is same as --fs checksize +# fs larger than the reduced size, fs is using reduced space +not lvreduce -L-5M $vg/$lv +check lv_field $vg/$lv lv_size "20.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" + +lvremove -f $vg/$lv + + +############################################################ +# +# repeat lvreduce tests with unmounted instead of mounted fs +# +############################################################ + +# lvreduce, ext4, active, unmounted, no --fs setting is same as --fs checksize +# fs smaller than the reduced size +lvcreate -n $lv -L 20M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +lvextend -L+25M $vg/$lv +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct +df --output=size "$mount_dir" |tee df1 +umount "$mount_dir" +# fs is 20M, reduced size is 27M, so no fs reduce is needed +lvreduce -L27M $vg/$lv +check lv_field $vg/$lv lv_size "27.00m" + +# lvreduce, ext4, active, unmounted, no --fs setting is same as --fs checksize +# fs equal to the reduced size +# fs is 20M, reduced size is 20M, so no fs reduce is needed +lvreduce -L20M $vg/$lv +check lv_field $vg/$lv lv_size "20.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" + + +# lvreduce, ext4, active, unmounted, no --fs setting is same as --fs checksize +# fs larger than the reduced size, fs not using reduced space +# lvreduce fails because fs needs to be reduced and checksize does not resize +not lvreduce -L-5M $vg/$lv + +# lvreduce, ext4, active, unmounted, no --fs setting is same as --fs checksize +# fs larger than the reduced size, fs is using reduced space +# lvreduce fails because fs needs to be reduced and checksize does not resize +not lvreduce -L-10M $vg/$lv + +check lv_field $vg/$lv lv_size "20.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" + +lvremove -f $vg + + +######################################################################### +# +# repeat a couple prev lvreduce that had no --fs setting, +# now using --fs checksize to verify it's the same as using no --fs set +# +######################################################################### + +# lvreduce, ext4, active, mounted, --fs checksize (same as no --fs set) +# fs larger than the reduced size, fs not using reduced space +lvcreate -n $lv -L 100M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +# lvreduce fails because fs needs to be reduced and checksize does not resize +not lvreduce --fs checksize -L-50M $vg/$lv +check lv_field $vg/$lv lv_size "100.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" + +# lvreduce, ext4, active, unmounted, --fs checksize (same as no --fs set) +# fs smaller than the reduced size +lvextend -L+50M $vg/$lv +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df1 +umount "$mount_dir" + +# fs is 100M, reduced size is 120M, so no fs reduce is needed +lvreduce --fs checksize -L120M $vg/$lv +check lv_field $vg/$lv lv_size "120.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" +lvchange -an $vg/$lv + +# lvreduce with inactive and no --fs setting fails because +# default behavior is fs checksize which activates the LV +# and sees the fs + +# lvreduce, ext4, inactive, no --fs setting same as --fs checksize +# fs larger than the reduced size, fs not using reduced space +# lvreduce fails because default is --fs checksize which sees the fs +not lvreduce -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "120.00m" + +lvremove -f $vg/$lv + + +################################# +# +# lvreduce, ext4, --fs resize* +# +################################# + +# lvreduce, ext4, active, mounted, --fs resize +# fs larger than the reduced size, fs not using reduced space +lvcreate -n $lv -L 50M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct +df --output=size "$mount_dir" |tee df1 +# lvreduce runs resize2fs to shrink the fs +lvreduce --yes --fs resize -L-20M $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" +ls -l $mount_dir/zeros1 +df --output=size "$mount_dir" |tee df2 +# fs size is changed +not diff df1 df2 + +# lvreduce, ext4, active, mounted, --fs resize +# fs larger than the reduced size, fs is using reduced space +# lvreduce runs resize2fs to shrink the fs but resize2fs fails +# the fs is not remounted after resize2fs fails because the +# resize failure might leave the fs in an unknown state +not lvreduce --yes --fs resize -L-15M $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +ls -l $mount_dir/zeros1 +df --output=size "$mount_dir" |tee df3 +# fs size is unchanged +diff df2 df3 +umount "$mount_dir" + +lvremove -f $vg/$lv + + +############################################ +# +# repeat with unmounted instead of mounted +# +############################################ + +# lvreduce, ext4, active, unmounted, --fs resize +# fs larger than the reduced size, fs not using reduced space +lvcreate -n $lv -L 50M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct +df --output=size "$mount_dir" |tee df1 +umount "$mount_dir" +# lvreduce runs resize2fs to shrink the fs +lvreduce --fs resize -L-20M $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +ls -l $mount_dir/zeros1 +df --output=size "$mount_dir" |tee df2 +# fs size is changed +not diff df1 df2 +umount "$mount_dir" + +# lvreduce, ext4, active, unmounted, --fs resize +# fs larger than the reduced size, fs is using reduced space +# lvreduce runs resize2fs to shrink the fs but resize2fs fails +not lvreduce --yes --fs resize -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "30.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +ls -l $mount_dir/zeros1 +df --output=size "$mount_dir" |tee df3 +# fs size is unchanged +diff df2 df3 +umount "$mount_dir" +lvchange -an $vg/$lv +lvremove $vg/$lv + + +################################################################## +# +# repeat resizes that shrink the fs, replacing --fs resize with +# --fs resize --fsmode nochange|offline, --fs resize_fsadm. +# while mounted and unmounted +# +################################################################## + +# lvreduce, ext4, active, mounted, --fs resize --fsmode nochange +# fs larger than the reduced size, fs not using reduced space +lvcreate -n $lv -L 90M $vg +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct +df --output=size "$mount_dir" |tee df1 +# lvreduce needs to unmount to run resize2fs but fsmode nochange doesn't let it +not lvreduce --fs resize --fsmode nochange -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "90.00m" +df --output=size "$mount_dir" |tee df2 +# fs size is unchanged +diff df1 df2 +umount "$mount_dir" + +# lvreduce, ext4, active, unmounted, --fs resize --fsmode nochange +# fs larger than the reduced size, fs not using reduced space +# lvreduce runs resize2fs to shrink the fs +lvreduce --fs resize --fsmode nochange -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "80.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df3 +# fs size is changed +not diff df2 df3 +# keep fs mounted + +# lvreduce, ext4, active, mounted, --fs resize --fsmode offline +# fs larger than the reduced size, fs not using reduced space +# lvreduce runs resize2fs to shrink the fs +# fsmode offline leaves the fs unmounted +lvreduce --fs resize --fsmode offline -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "70.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df4 +# fs size is changed +not diff df3 df4 +umount "$mount_dir" + +# lvreduce, ext4, active, unmounted, --fs resize --fsmode offline +# fs larger than the reduced size, fs not using reduced space +# lvreduce runs resize2fs to shrink the fs +lvreduce --fs resize --fsmode offline -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "60.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df5 +# fs size is changed +not diff df4 df5 +# keep fs mounted + +# lvreduce, ext4, active, mounted, --fs resize_fsadm +# fs larger than the reduced size, fs not using reduced space +# lvreduce runs resize2fs to shrink the fs +lvreduce --yes --fs resize_fsadm -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "50.00m" +ls -l $mount_dir/zeros1 +df --output=size "$mount_dir" |tee df6 +# fs size is changed +not diff df5 df6 +umount "$mount_dir" + +# lvreduce, ext4, active, unmounted, --fs resize_fsadm +# fs larger than the reduced size, fs not using reduced space +# lvreduce runs resize2fs to shrink the fs +lvreduce --fs resize_fsadm -L-10M $vg/$lv +check lv_field $vg/$lv lv_size "40.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df7 +# fs size is changed +not diff df6 df7 +umount "$mount_dir" + + +vgremove -ff $vg diff --git a/test/shell/lvresize-full.sh b/test/shell/lvresize-full.sh new file mode 100644 index 0000000..fe39f45 --- /dev/null +++ b/test/shell/lvresize-full.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Excersize resize of filesystem when size of LV already matches +# https://bugzilla.redhat.com/1354396 + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +FSCK=${FSCK-fsck} +MKFS=${MKFS-mkfs.ext3} +RESIZEFS=${RESIZEFS-resize2fs} + +which $FSCK || skip +which $MKFS || skip +which $RESIZEFS || skip + +aux prepare_vg 2 20 + +lvcreate -l100%FREE -n $lv1 $vg + +lvdev="$DM_DEV_DIR/$vg/$lv1" + +lvs -a $vg + +"$MKFS" "$lvdev" + +# this should resolve to resize to same actual size +not lvreduce -l-100%FREE $vg/$lv1 +not lvreduce -r -f -l-100%FREE $vg/$lv1 +"$FSCK" -n "$lvdev" + +# size should remain the same +# lvresize fails with same result with or without -r +not lvextend -l+100%FREE $vg/$lv1 +not lvextend -r -f -l+100%FREE $vg/$lv1 +"$FSCK" -n "$lvdev" + +#lvchange -an $vg/$lv1 +not lvresize -l+100%FREE $vg/$lv1 +not lvresize -r -f -l+100%FREE $vg/$lv1 +"$FSCK" -n "$lvdev" + +# Check there is really file system resize happening +# even when LV itself has still the same size +"$RESIZEFS" -f "$lvdev" 20000 +"$FSCK" -n "$lvdev" | tee out +grep "20000 blocks" out + +SIZE=$(get lv_field $vg/$lv1 size) +not lvresize -l-100%FREE $vg/$lv1 +not lvresize -r -f -l-100%FREE $vg/$lv1 +test "$SIZE" = "$(get lv_field $vg/$lv1 size)" + +"$FSCK" -n "$lvdev" | tee out +grep -v "20000 blocks" out + + +# Also check it fails when the user 'resize' volume without +# resizing fs and then retries with '-r'. +# The first lvreduce intentionally ignores the fs and intentionally +# corrupts the fs so that the second lvresize will fail when it runs +# fsck. +lvreduce -f --fs ignore -l50%VG $vg/$lv1 +fail lvresize -r -f -l20%VG $vg/$lv1 + +lvremove -ff $vg diff --git a/test/shell/lvresize-mirror.sh b/test/shell/lvresize-mirror.sh index a10f7cd..ee23f7f 100644 --- a/test/shell/lvresize-mirror.sh +++ b/test/shell/lvresize-mirror.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,33 +8,42 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest -aux prepare_vg 5 80 +aux prepare_vg 5 + +for deactivate in true false; do # 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 + lvcreate -aye -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3":0-1 + + test $deactivate && lvchange -an $vg/$lv1 + + lvextend -l+2 $vg/$lv1 + check mirror $vg $lv1 "$dev3" + check mirror_images_contiguous $vg $lv1 # 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 + lvreduce -f --fs ignore -l-2 $vg/$lv1 + check mirror $vg $lv1 "$dev3" # 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 + lvcreate -aye -l2 --type mirror -m1 -n $lv2 $vg "$dev1" "$dev2" "$dev3":0-1 + lvcreate -l1 -n $lv3 $vg "$dev1" + lvcreate -l1 -n $lv4 $vg "$dev2" + + test $deactivate && lvchange -an $vg/$lv2 + + lvextend -l+2 $vg/$lv2 + check mirror $vg $lv2 "$dev3" + check mirror_images_clung $vg $lv2 + + lvremove -ff $vg +done + +vgremove -ff $vg diff --git a/test/shell/lvresize-raid.sh b/test/shell/lvresize-raid.sh index f999a31..4260de8 100644 --- a/test/shell/lvresize-raid.sh +++ b/test/shell/lvresize-raid.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2012,2017 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 @@ -7,74 +8,68 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -. lib/test -aux target_at_least dm-raid 1 1 0 || skip +SKIP_WITH_LVMPOLLD=1 -aux prepare_vg 5 80 +. lib/inittest -# Extend a 2-way RAID1 -for deactivate in true false; do - lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg +aux have_raid 1 3 0 || skip - if $deactivate; then - lvchange -an $vg/$lv1 - fi +levels="5 6 10" +aux have_raid4 && levels="4 $levels" +aux have_raid 1 7 0 && levels="0 0_meta $levels" - lvresize -l +2 $vg/$lv1 +aux prepare_pvs 6 +get_devs - #check raid_images_contiguous $vg $lv1 +vgcreate $SHARED -s 256K "$vg" "${DEVICES[@]}" - lvremove -ff $vg -done - -# Reduce 2-way RAID1 for deactivate in true false; do - lvcreate --type raid1 -m 1 -l 4 -n $lv1 $vg - if $deactivate; then +# Extend and reduce a 2-way RAID1 + lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg + + test $deactivate && { + aux wait_for_sync $vg $lv1 lvchange -an $vg/$lv1 - fi + } + + lvresize -l +2 $vg/$lv1 should lvresize -y -l -2 $vg/$lv1 #check raid_images_contiguous $vg $lv1 - lvremove -ff $vg -done - -# Extend 3-striped RAID 4/5/6 -for i in 4 5 6 ; do - for deactivate in true false; do - lvcreate --type raid$i -i 3 -l 3 -n $lv1 $vg +# Extend and reduce 3-striped RAID 4/5/6/10 + for i in $levels ; do + lvcreate --type raid$i -i 3 -l 3 -n $lv2 $vg + check lv_field $vg/$lv2 "seg_size" "768.00k" - if $deactivate; then - lvchange -an $vg/$lv1 - fi + test $deactivate && { + aux wait_for_sync $vg $lv2 + lvchange -an $vg/$lv2 + } - lvresize -l +3 $vg/$lv1 + lvresize -l +3 $vg/$lv2 + check lv_field $vg/$lv2 "seg_size" "1.50m" #check raid_images_contiguous $vg $lv1 - lvremove -ff $vg - done -done - -# Reduce 3-striped RAID 4/5/6 -for i in 4 5 6 ; do - for deactivate in true false; do - lvcreate --type raid$i -i 3 -l 6 -n $lv1 $vg - - if $deactivate; then - lvchange -an $vg/$lv1 - fi - - should lvresize -y -l -3 $vg/$lv1 + should lvresize -y -l -3 $vg/$lv2 + should check lv_field $vg/$lv2 "seg_size" "768.00k" #check raid_images_contiguous $vg $lv1 lvremove -ff $vg done done + +# Bug 1005434 +# Ensure extend is contiguous +lvcreate --type raid5 -l 2 -i 2 -n $lv1 $vg "$dev4" "$dev5" "$dev6" +lvextend -l +2 --alloc contiguous $vg/$lv1 +check lv_tree_on $vg $lv1 "$dev4" "$dev5" "$dev6" + +vgremove -f $vg diff --git a/test/shell/lvresize-raid10.sh b/test/shell/lvresize-raid10.sh index 9b71708..e28b684 100644 --- a/test/shell/lvresize-raid10.sh +++ b/test/shell/lvresize-raid10.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,36 +8,28 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -. lib/test -aux target_at_least dm-raid 1 3 0 || skip +SKIP_WITH_LVMPOLLD=1 -aux prepare_vg 5 80 +. lib/inittest + +aux have_raid 1 3 0 || skip + +aux prepare_vg 5 -# Extend RAID10 (2-stripes, 2-mirror) for deactivate in true false; do +# Extend RAID10 (2-stripes, 2-mirror) lvcreate --type raid10 -m 1 -i 2 -l 2 -n $lv1 $vg - if $deactivate; then - lvchange -an $vg/$lv1 - fi + test $deactivate && lvchange -an $vg/$lv1 lvresize -l +2 $vg/$lv1 #check raid_images_contiguous $vg $lv1 - lvremove -ff $vg -done - # Reduce RAID10 (2-stripes, 2-mirror) -for deactivate in true false; do - lvcreate --type raid10 -m 1 -i 2 -l 4 -n $lv1 $vg - - if $deactivate; then - lvchange -an $vg/$lv1 - fi should lvresize -y -l -2 $vg/$lv1 diff --git a/test/shell/lvresize-rounding.sh b/test/shell/lvresize-rounding.sh index ad8d9c0..52bedb4 100644 --- a/test/shell/lvresize-rounding.sh +++ b/test/shell/lvresize-rounding.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2007-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,59 +8,60 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_pvs 3 22 +get_devs -vgcreate -s 32K $vg "$dev1" "$dev2" "$dev3" +vgcreate $SHARED -s 32K "$vg" "${DEVICES[@]}" -lvcreate -l4 -i3 -I64 $vg +lvcreate -an -Zn -l4 -i3 -I64 $vg -lvcreate -l8 -i2 -I64 $vg +lvcreate -an -Zn -l8 -i2 -I64 $vg -lvcreate -l16 $vg +lvcreate -an -Zn -l16 $vg -lvcreate -l32 -i3 -I64 -n $lv1 $vg +lvcreate -an -Zn -l32 -i3 -I64 -n $lv1 $vg lvresize -l+64 -i3 -I64 $vg/$lv1 lvresize -l+64 -i3 -I128 $vg/$lv1 #lvcreate -l100%FREE -i3 -I64 --alloc anywhere $vg - -dmsetup table - -vgcfgbackup -f /tmp/vg $vg vgremove -f $vg # 15 extents +export LVM_TEST_AUX_TRACE=yes aux prepare_vg 3 22 +unset LVM_TEST_AUX_TRACE # Block some extents -lvcreate -l4 -i3 $vg -lvcreate -l1 $vg +lvcreate -an -Zn -l4 -i3 $vg +lvcreate -an -Zn -l1 $vg -lvcreate -l100%FREE -n $lv1 -i3 $vg +lvcreate -an -Zn -l100%FREE -n $lv1 -i3 $vg check vg_field $vg vg_free_count 2 lvremove -f $vg/$lv1 -lvcreate -l1 -n $lv1 -i3 $vg +lvcreate -an -Zn -l1 -n $lv1 -i3 $vg lvextend -l+100%FREE -i3 $vg/$lv1 check vg_field $vg vg_free_count 2 -lvreduce -f -l50%LV $vg/$lv1 +lvreduce -f --fs ignore -l50%LV $vg/$lv1 vgremove -f $vg - -vgcreate -s 4M $vg "$dev1" "$dev2" "$dev3" +vgcreate $SHARED -s 4M $vg "$dev1" "$dev2" "$dev3" # Expect to play with 15 extents check vg_field $vg vg_free_count 15 # Should be rounded to 12 extents -lvcreate -l10 -n lv -i3 $vg +lvcreate -an -Zn -l10 -n lv -i3 $vg check vg_field $vg vg_free_count 3 # Should want 16 extents @@ -70,21 +72,21 @@ lvextend -l+100%FREE $vg/lv check vg_field $vg vg_free_count 0 # Rounds up and should reduce just by 3 extents -lvreduce -f -l-4 $vg/lv +lvreduce -f --fs ignore -l-4 $vg/lv check vg_field $vg vg_free_count 3 # Should round up to 15 extents lvextend -f -l+1 $vg/lv check vg_field $vg vg_free_count 0 -lvreduce -f -l-4 $vg/lv +lvreduce -f --fs ignore -l-4 $vg/lv check vg_field $vg vg_free_count 3 lvextend -l90%VG $vg/lv check vg_field $vg vg_free_count 0 -not lvreduce -f -l-10%LV $vg/lv +not lvreduce -f --fs ignore -l-10%LV $vg/lv check vg_field $vg vg_free_count 0 -lvreduce -f -l-20%LV $vg/lv +lvreduce -f --fs ignore -l-20%LV $vg/lv check vg_field $vg vg_free_count 3 diff --git a/test/shell/lvresize-thin-external-origin.sh b/test/shell/lvresize-thin-external-origin.sh new file mode 100644 index 0000000..6dbfe4a --- /dev/null +++ b/test/shell/lvresize-thin-external-origin.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test resize of thin volume with external origin + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 2 0 || skip + +# Pretend we miss the external_origin_extend feature +aux lvmconf 'global/thin_disabled_features = [ "external_origin_extend" ]' + +aux prepare_vg 2 + +lvcreate -L10 -n $lv1 $vg + +# Prepare thin pool +lvcreate -L20 -T $vg/pool + +# Convert $lv1 into thin LV with external origin +lvconvert -T $vg/$lv1 --thinpool $vg/pool --originname ext + +lvs -a $vg + +# Bigger size is not supported without feature external_origin_extend +not lvresize -L+10 $vg/$lv1 + +# But reduction works +lvresize -L-5 -f $vg/$lv1 +check lv_field $vg/$lv1 lv_size "5.00" --units m --nosuffix + +# Inactive LV cannot be resized as well +lvchange -an $vg +not lvresize -L+15 -y $vg/$lv1 +check lv_field $vg/$lv1 lv_size "5.00" --units m --nosuffix +lvchange -ay $vg/$lv1 + +not lvresize -L+15 -y $vg/$lv1 +check lv_field $vg/$lv1 lv_size "5.00" --units m --nosuffix + + +# Try to resize again back up to the size of external origin +lvresize -L+5 -f $vg/$lv1 +check lv_field $vg/$lv1 lv_size "10.00" --units m --nosuffix + +vgremove -ff $vg diff --git a/test/shell/lvresize-thin-metadata.sh b/test/shell/lvresize-thin-metadata.sh new file mode 100644 index 0000000..f27934b --- /dev/null +++ b/test/shell/lvresize-thin-metadata.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 10 0 || skip + +aux prepare_vg 3 1256 + +for deactivate in true false; do +# Create some thin volumes + lvcreate -L20 -V30 -n $lv1 -T $vg/pool + lvcreate -s $vg/$lv1 +# Confirm we have basic 2M metadata + check lv_field $vg/pool_tmeta size "2.00m" + + test $deactivate && lvchange -an $vg + + lvresize --poolmetadatasize +2M $vg/pool +# Test it's been resized to 4M + check lv_field $vg/pool_tmeta size "4.00m" + + lvresize --poolmetadatasize +256M $vg/pool + check lv_field $vg/pool_tmeta size "260.00m" + + lvresize --poolmetadatasize +3G $vg/pool + check lv_field $vg/pool_tmeta size "3.25g" + + vgchange -an $vg + vgchange -ay $vg + +# TODO: Add more tests + + lvremove -ff $vg +done diff --git a/test/shell/lvresize-usage.sh b/test/shell/lvresize-usage.sh index 51ef221..a7e1544 100644 --- a/test/shell/lvresize-usage.sh +++ b/test/shell/lvresize-usage.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2007-2016 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 @@ -7,15 +8,53 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 -aux prepare_vg 2 +. lib/inittest + +aux prepare_vg 2 80 lvcreate -L 10M -n lv -i2 $vg lvresize -l +4 $vg/lv +not lvextend -L+0 $vg/lv +not lvextend -l+0 $vg/lv lvremove -ff $vg lvcreate -L 64M -n $lv -i2 $vg not lvresize -v -l +4 xxx/$lv + +# Check stripe size is reduced to extent size when it's bigger +ESIZE=$(get vg_field $vg vg_extent_size --units b) +lvextend -L+64m -i 2 -I$(( ${ESIZE%%B} * 2 ))B $vg/$lv 2>&1 | tee err +grep "Reducing stripe size" err + +lvremove -ff $vg + +lvcreate -L 10M -n lv $vg "$dev1" +lvextend -L +10M $vg/lv "$dev2" +lvextend --type striped -m0 -L +10M $vg/lv "$dev2" + +# Attempt to reduce with lvextend and vice versa: +not lvextend -L 16M $vg/lv +not lvreduce -L 32M $vg/lv + +lvremove -ff $vg + +lvcreate --type mirror -aey -L 4 -n $lv1 $vg +# Incorrent name for resized LV +not lvextend --type mirror -L 10 -n $lv1 $vg +# Same size +not lvextend --type mirror -L 4 $vg/$lv1 +# Cannot use any '-' or '+' sign for --mirror arg +not lvextend --type mirror -L+2 -m-1 $vg/$lv1 +not lvextend --type mirror -L+2 -m+1 $vg/$lv1 + +lvextend --type mirror -L+4 -m1 $vg/$lv1 + +lvs -a $vg +check lv_field $vg/$lv1 size "8.00m" + +lvremove -ff $vg diff --git a/test/shell/lvresize-vdo.sh b/test/shell/lvresize-vdo.sh new file mode 100644 index 0000000..cbe8ce9 --- /dev/null +++ b/test/shell/lvresize-vdo.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test resize of VDO volumes + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_vdo 6 2 0 || skip + +aux lvmconf 'allocation/vdo_slab_size_mb = 128' + +aux prepare_vg 1 7000 +lvcreate --vdo -V3G -L4G -n $lv1 $vg/$lv2 + +# Resize data volume +lvresize -L6G $vg/$lv2 +check lv_field $vg/$lv2 size "6.00g" +check lv_field $vg/${lv2}_vdata size "6.00g" + +# Resize virtual volume on top of VDO +lvresize -L6G $vg/$lv1 +check lv_field $vg/$lv1 size "6.00g" + +# Check too large size +not lvresize -L4P $vg/$lv1 2>err +grep "Volume too large" err + +# Can't resize inactive VDO +lvchange -an $vg +not lvresize -L10G $vg/$lv1 2>err +grep "Cannot resize inactive" err + +not lvresize -L10G $vg/$lv2 2>err +grep "Cannot resize inactive" err + +not lvresize -L10G $vg/${lv2}_vdata 2>err +grep "Cannot resize inactive" err + +vgremove -ff $vg diff --git a/test/shell/lvresize-xfs.sh b/test/shell/lvresize-xfs.sh new file mode 100644 index 0000000..7f31939 --- /dev/null +++ b/test/shell/lvresize-xfs.sh @@ -0,0 +1,306 @@ +#!/usr/bin/env bash + +# Copyright (C) 2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 1 500 + +which mkfs.xfs || skip +which xfs_growfs || skip + +mount_dir="mnt_lvresize_fs" +mkdir -p "$mount_dir" + +mount_dir_space="other mnt dir" +mkdir -p "$mount_dir_space" + + +# Test combinations of the following: +# lvreduce / lvextend +# xfs +# each --fs opt / no --fs opt / --resizefs +# active / inactive +# mounted / unmounted +# fs size less than, equal to or greater than reduced lv size + +################# +# +# lvextend, xfs +# +################# + +# lvextend, xfs, active, mounted, no --fs setting is same as --fs ignore +lvcreate -n $lv -L 300M $vg +mkfs.xfs "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" + +# --fs tests require a libblkid version that shows FSLASTBLOCK +# so exit 0 test here, if the feature is not present +blkid -p "$DM_DEV_DIR/$vg/$lv" | grep FSLASTBLOCK || skip + +df --output=size "$mount_dir" |tee df1 +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=10 oflag=direct +lvextend -L+20M $vg/$lv +check lv_field $vg/$lv lv_size "320.00m" +# with no --fs used, the fs size should be the same +df --output=size "$mount_dir" |tee df2 +diff df1 df2 +xfs_growfs "$DM_DEV_DIR/$vg/$lv" +df --output=size "$mount_dir" |tee df3 +not diff df2 df3 +dd if=/dev/zero of="$mount_dir/zeros2" bs=1M count=20 oflag=direct +# keep it mounted + +# lvextend, xfs, active, mounted, --fs ignore +df --output=size "$mount_dir" |tee df1 +lvextend --fs ignore -L+20 $vg/$lv +check lv_field $vg/$lv lv_size "340.00m" +df --output=size "$mount_dir" |tee df2 +diff df1 df2 + +# lvextend, xfs, active, mounted, --fs resize +lvextend --fs resize -L+20M $vg/$lv +check lv_field $vg/$lv lv_size "360.00m" +df --output=size "$mount_dir" |tee df3 +not diff df2 df3 + +# lvextend, xfs, active, mounted, --resizefs (same as --fs resize) +lvextend --resizefs -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "370.00m" +df --output=size "$mount_dir" |tee df4 +not diff df3 df4 + +# lvextend, xfs, active, mounted, --fs resize --fsmode manage (same as --fs resize) +lvextend --fs resize --fsmode manage -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "380.00m" +df --output=size "$mount_dir" |tee df2 +not diff df1 df2 + +umount "$mount_dir" +lvchange -an $vg/$lv + +# lvextend, xfs, inactive, --fs ignore +lvextend --fs ignore -L+20M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" + +lvremove -f $vg/$lv + +#################### +# start with new fs +#################### + +# lvextend, xfs, active, mounted, --fs resize --fsmode offline +lvcreate -n $lv -L 300M $vg +mkfs.xfs "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir_space" +df --output=size "$mount_dir_space" |tee df1 +dd if=/dev/zero of="$mount_dir_space/zeros1" bs=1M count=20 oflag=direct +# xfs_growfs requires the fs to be mounted, so extending the lv is +# succeeds, then the xfs extend fails because it cannot be done unmounted +not lvextend --fs resize --fsmode offline -L+20M $vg/$lv +check lv_field $vg/$lv lv_size "320.00m" +df -a | tee dfa +grep "$mount_dir_space" dfa +df --output=size "$mount_dir_space" |tee df2 +# fs not extended so fs size not changed +diff df1 df2 + +# lvextend, xfs, active, mounted, --fs resize --fsmode nochange +lvextend --fs resize --fsmode nochange -L+20M $vg/$lv +check lv_field $vg/$lv lv_size "340.00m" +df --output=size "$mount_dir_space" |tee df2 +not diff df1 df2 + +# lvextend, xfs, active, mounted, --fs resize_fsadm +lvextend --fs resize_fsadm -L+20M $vg/$lv +check lv_field $vg/$lv lv_size "360.00m" +df --output=size "$mount_dir_space" |tee df3 +not diff df2 df3 +umount "$mount_dir_space" + +# lvextend, xfs, active, unmounted, --fs resize --fsmode nochange +# xfs_growfs requires the fs to be mounted to grow, so --fsmode nochange +# with an unmounted fs fails +not lvextend --fs resize --fsmode nochange -L+20M $vg/$lv +check lv_field $vg/$lv lv_size "380.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir_space" +df --output=size "$mount_dir_space" |tee df4 +# fs not extended so fs size not changed +diff df3 df4 +umount "$mount_dir_space" + +# lvextend, xfs, active, unmounted, --fs resize +# --yes needed because mount changes are required and plain "resize" +# fsopt did not specify if the user wants to change mount state +lvextend --yes --fs resize -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "390.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir_space" +df --output=size "$mount_dir_space" |tee df5 +not diff df4 df5 +umount "$mount_dir_space" + +# lvextend, xfs, active, unmounted, --fs resize_fsadm +lvextend --fs resize_fsadm -L+10M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir_space" +df --output=size "$mount_dir_space" |tee df6 +not diff df5 df6 +umount "$mount_dir_space" +lvremove -f $vg/$lv + + +################################################# +# +# lvreduce, xfs (xfs does not support shrinking) +# +################################################## + +# lvreduce, xfs, active, mounted, no --fs setting is same as --fs checksize +# fs smaller than the reduced size +lvcreate -n $lv -L 300M $vg +mkfs.xfs "$DM_DEV_DIR/$vg/$lv" +lvextend -L+100M $vg/$lv +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +# fs is 300M, reduced size is 326M, so no fs reduce is needed +lvreduce -L326M $vg/$lv +check lv_field $vg/$lv lv_size "326.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" +lvchange -an $vg/$lv + +# lvreduce, xfs, inactive, no fs setting is same as --fs checksize +# fs smaller than the reduced size +# fs is 200M, reduced size is 216M, so no fs reduce is needed +lvreduce --fs checksize -L316M $vg/$lv +check lv_field $vg/$lv lv_size "316.00m" +lvchange -ay $vg/$lv +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 + +# lvreduce, xfs, active, mounted, no --fs setting is same as --fs checksize +# fs equal to the reduced size +# fs is 300M, reduced size is 300M, so no fs reduce is needed +lvreduce -L300M $vg/$lv +check lv_field $vg/$lv lv_size "300.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 + +# lvreduce, xfs, active, unmounted, no --fs setting is same as --fs checksize +# fs smaller than the reduced size +lvextend -L+100M $vg/$lv +umount "$mount_dir" +# fs is 300M, reduced size is 316M, so no fs reduce is needed +lvreduce -L356M $vg/$lv +check lv_field $vg/$lv lv_size "356.00m" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 + +# lvreduce, xfs, active, mounted, --fs resize +# fs smaller than the reduced size +# fs is 300M, reduced size is 316M, so no fs reduce is needed +lvreduce -L316M $vg/$lv +check lv_field $vg/$lv lv_size "316.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" +lvchange -an $vg/$lv + + +# lvreduce, xfs, inactive, no --fs setting is same as --fs checksize +# fs equal to the reduced size +# fs is 300M, reduced size is 300M, so no fs reduce is needed +lvreduce --fs checksize -L300M $vg/$lv +check lv_field $vg/$lv lv_size "300.00m" +lvchange -ay $vg/$lv +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" + +lvremove -f $vg/$lv + + +########################################################## +# +# lvreduce bigger xfs size (xfs does not support shrinking) +# +########################################################## + +# lvreduce, xfs, active, mounted, no --fs setting is same as --fs checksize +# fs larger than the reduced size, fs not using reduced space +lvcreate -n $lv -L 400M $vg +mkfs.xfs "$DM_DEV_DIR/$vg/$lv" +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=20 oflag=direct +df --output=size "$mount_dir" |tee df1 +# lvreduce fails because fs needs to be reduced +not lvreduce -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +# keep fs mounted + +# lvreduce, xfs, active, mounted, --fs resize +# fs larger than the reduced size, fs not using reduced space +# lvreduce fails because xfs cannot shrink +not lvreduce --yes --fs resize -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" + +# lvreduce, xfs, active, unmounted, --fs resize* +# fs larger than the reduced size, fs not using reduced space +# lvreduce fails because xfs cannot shrink +not lvreduce --yes --fs resize -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" +not lvreduce --yes --fs resize --fsmode manage -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" +not lvreduce --yes --fs resize --fsmode nochange -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" +not lvreduce --yes --fs resize --fsmode offline -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" +not lvreduce --yes --fs resize_fsadm -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" +not lvreduce --yes --resizefs -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" + +mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir" +df --output=size "$mount_dir" |tee df2 +# fs size unchanged +diff df1 df2 +umount "$mount_dir" +lvchange -an $vg/$lv + +# lvreduce, xfs, inactive, no --fs setting is same as --fs checksize +# fs larger than the reduced size +# lvreduce fails because fs needs to be reduced +not lvreduce -L-100M $vg/$lv +check lv_field $vg/$lv lv_size "400.00m" + +vgremove -f $vg diff --git a/test/shell/lvs-cache.sh b/test/shell/lvs-cache.sh new file mode 100644 index 0000000..62d45ac --- /dev/null +++ b/test/shell/lvs-cache.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise creation of cache and cache pool volumes + +# Full CLI uses --type +# Shorthand CLI uses -H | --cache + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip +aux prepare_vg 5 8000 + +# Use 10M origin size +lvcreate -aey -L10 -n $lv1 $vg +lvcreate -H -L5 $vg/$lv1 + +# replace 10M size with 5M size of cache device +NEWCLINE=$(dmsetup table $vg-$lv1 | sed 's/20480/10240/') +dmsetup reload $vg-$lv1 --table "$NEWCLINE" +dmsetup resume $vg-$lv1 + +# Check that mismatching cache target is shown by lvs +lvs -a $vg 2>&1 | grep "WARNING" +check lv_attr_bit state $vg/$lv1 "X" + +lvs -o+lv_active $vg + +lvremove -f $vg + + + +lvcreate --type cache-pool -L10 $vg/cpool +lvcreate --type cache -l 1 --cachepool $vg/cpool -n corigin $vg +lvs -o lv_name,cache_policy +lvs -o lv_name,cache_settings + +lvremove -f $vg + +lvcreate --type cache-pool -L10 $vg/cpool +lvcreate --type cache -l 1 --cachepool $vg/cpool -n corigin $vg --cachepolicy mq \ + --cachesettings migration_threshold=233 +lvs -o lv_name,cache_policy | grep mq +lvs -o lv_name,cache_settings | grep migration_threshold=233 + +lvremove -f $vg + +lvcreate --type cache-pool -L10 --cachepolicy mq --cachesettings migration_threshold=233 $vg/cpool +lvcreate --type cache -l 1 --cachepool $vg/cpool -n corigin $vg +lvs -o lv_name,cache_policy | grep mq +lvs -o lv_name,cache_settings | grep migration_threshold=233 + +lvremove -f $vg + +lvcreate --type cache-pool -L10 --cachepolicy mq --cachesettings migration_threshold=233 --cachesettings sequential_threshold=13 $vg/cpool +lvcreate --type cache -l 1 --cachepool $vg/cpool -n corigin $vg +lvs -o lv_name,cache_policy | grep mq +lvs -a -o lv_name,cache_policy -S 'cache_policy=mq' | grep corigin +lvs -o lv_name,cache_settings | grep migration_threshold=233 +lvs -o lv_name,cache_settings | grep sequential_threshold=13 + +lvcreate -n foo -l 1 $vg +lvs -S 'cache_policy=mq' | grep corigin +lvs -S 'cache_policy=mq' | not grep foo +lvs -S 'cache_policy=undefined' | not grep corigin +lvs -S 'cache_policy=undefined' | grep foo +lvs -o +cache_policy -S 'cache_policy=mq' | grep corigin +lvs -o +cache_policy -S 'cache_policy=mq' | not grep foo +lvs -o +cache_policy -S 'cache_policy=undefined' | not grep corigin +lvs -o +cache_policy -S 'cache_policy=undefined' | grep foo +lvs -o +cache_policy -O cache_policy +lvs -o +cache_settings -S 'cache_settings={migration_threshold=233}' | grep corigin +lvs -o +cache_settings -S 'cache_settings!={migration_threshold=233}' | grep foo +lvs -o +cache_policy -O cache_settings + +lvremove -f $vg + +lvcreate -n foo -l 1 $vg +lvs -a -S 'cache_policy=undefined' | grep foo + +vgremove -ff $vg diff --git a/test/shell/mda-rollback.sh b/test/shell/mda-rollback.sh new file mode 100644 index 0000000..adfc110 --- /dev/null +++ b/test/shell/mda-rollback.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 3 + +vgcreate $SHARED --metadatasize 128k $vg1 "$dev1" "$dev2" "$dev3" + +vgreduce $vg1 "$dev1" +dd if="$dev1" of=badmda bs=256K count=1 +vgextend $vg1 "$dev1" + +dd if=badmda of="$dev1" bs=256K count=1 + +# the vg_read in vgck (and other commands) will repair the metadata +vgck $vg1 + +# dev1 is part of vg1 (as witnessed by metadata on dev2 and dev3), but its mda +# was corrupt (written over by a backup from time dev1 was an orphan) +check pv_field "$dev1" vg_name $vg1 diff --git a/test/shell/mdata-strings.sh b/test/shell/mdata-strings.sh index 16e9360..c87cd75 100644 --- a/test/shell/mdata-strings.sh +++ b/test/shell/mdata-strings.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008-2011 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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 @@ -7,16 +8,23 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Test for proper escaping of strings in metadata (bz431474)' -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# For udev impossible to create +test "$LVM_TEST_DEVDIR" = "/dev" && skip aux prepare_devs 2 -aux lvmconf 'devices/global_filter = [ "a|.*LVMTEST.*dev/mapper/.*pv[0-9_]*$|", "r|.*|" ]' +aux extend_filter_LVMTEST + +# Setup mangling to 'none' globaly for all libdm users +export DM_DEFAULT_NAME_MANGLING_MODE=none -# for udev impossible to create pv_ugly="__\"!@#\$%^&*,()|@||'\\\"__pv1" # 'set up temp files, loopback devices' @@ -30,9 +38,12 @@ dm_table | grep -F "$pv_ugly" created="$dev1" # when used with real udev without fallback, it will fail here pvcreate "$dev1" || created="$dev2" -pvdisplay | should grep -F "$pv_ugly" +pvdisplay 2>&1 | tee err +should grep -F "$pv_ugly" err should check pv_field "$dev1" pv_name "$dev1" -vgcreate $vg "$created" +vgcreate $SHARED $vg "$created" # 'no parse errors and VG really exists' vgs $vg 2>err not grep "Parse error" err + +dmsetup remove "${PREFIX}${pv_ugly}" diff --git a/test/shell/metadata-bad-mdaheader.sh b/test/shell/metadata-bad-mdaheader.sh new file mode 100644 index 0000000..ad2bcc4 --- /dev/null +++ b/test/shell/metadata-bad-mdaheader.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +xxd -v || skip + +aux prepare_devs 3 +get_devs + +# +# Test corrupted mda_header.version field, which also +# causes the mda_header checksum to be bad. +# +# FIXME: if a VG has only a single PV, this repair +# doesn't work since there's no good PV to get +# metadata from. A more advanced repair capability +# is needed. +# + +dd if=/dev/zero of="$dev1" bs=1M count=1 oflag=direct +dd if=/dev/zero of="$dev2" bs=1M count=1 oflag=direct +dd if=/dev/zero of="$dev3" bs=1M count=1 oflag=direct + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +pvs + +# read mda_header which is 4k from start of disk +dd if="$dev1" of=meta1 bs=4k count=1 skip=1 + +# convert binary to text +xxd meta1 > meta1.txt + +# Corrupt mda_header by changing the version field from 0100 to 0200 +sed 's/0000010:\ 304e\ 2a3e\ 0100\ 0000\ 0010\ 0000\ 0000\ 0000/0000010:\ 304e\ 2a3e\ 0200\ 0000\ 0010\ 0000\ 0000\ 0000/' meta1.txt > meta1-bad.txt + +# convert text to binary +xxd -r meta1-bad.txt > meta1-bad + +# write bad mda_header back to disk +dd if=meta1-bad of="$dev1" bs=4k seek=1 + +# pvs reports bad metadata header +pvs 2>&1 | tee out +grep "bad metadata header" out + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +# bad metadata in one mda doesn't prevent using +# the VG since other mdas are fine and usable +lvcreate -l1 $vg + + +vgck --updatemetadata $vg + +pvs 2>&1 | tee out +not grep "bad metadata header" out + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +vgchange -an $vg +vgremove -ff $vg diff --git a/test/shell/metadata-bad-text.sh b/test/shell/metadata-bad-text.sh new file mode 100644 index 0000000..e512688 --- /dev/null +++ b/test/shell/metadata-bad-text.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* +} + +. lib/inittest + +aux prepare_devs 3 +get_devs + +aux clear_devs "$dev1" "$dev2" "$dev3" + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +pvs + +dd if="$dev1" of=meta1 bs=4k count=2 + +sed 's/flags =/flagx =/' meta1 > meta1.bad + +dd if=meta1.bad of="$dev1" + +pvs 2>&1 | tee out +grep "Checksum error" out + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +# bad metadata in one mda doesn't prevent using +# the VG since other mdas are fine and usable +lvcreate -l1 $vg + + +vgck --updatemetadata $vg + +pvs 2>&1 | tee out +not grep "Checksum error" out + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +vgchange -an $vg +vgremove -ff $vg + + +# +# Same test as above, but corrupt metadata text +# on two of the three PVs, leaving one good +# copy of the metadata. +# + +aux clear_devs "$dev1" "$dev2" "$dev3" + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +pvs + +dd if="$dev1" of=meta1 bs=4k count=2 +dd if="$dev2" of=meta2 bs=4k count=2 + +sed 's/READ/RRRR/' meta1 > meta1.bad +sed 's/seqno =/sss =/' meta2 > meta2.bad + +dd if=meta1.bad of="$dev1" +dd if=meta2.bad of="$dev2" + +pvs 2>&1 | tee out +# FIXME: find a better test than looking for a specific message +grep "Checksum error" out > out2 +grep "$dev1" out2 +grep "$dev2" out2 + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +# bad metadata in one mda doesn't prevent using +# the VG since other mdas are fine +lvcreate -l1 $vg + + +vgck --updatemetadata $vg + +pvs 2>&1 | tee out +not grep "Checksum error" out + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +vgchange -an $vg +vgremove -ff $vg + +# +# Three PVs where two have one mda, and the third +# has two mdas. The first mda is corrupted on all +# thee PVs, but the second mda on the third PV +# makes the VG usable. +# + +aux clear_devs "$dev1" "$dev2" "$dev3" + +pvcreate "$dev1" +pvcreate "$dev2" +pvcreate --pvmetadatacopies 2 "$dev3" + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +pvs + +dd if="$dev1" of=meta1 bs=4k count=2 +dd if="$dev2" of=meta2 bs=4k count=2 +dd if="$dev3" of=meta3 bs=4k count=2 + +sed 's/READ/RRRR/' meta1 > meta1.bad +sed 's/seqno =/sss =/' meta2 > meta2.bad +sed 's/id =/id/' meta3 > meta3.bad + +dd if=meta1.bad of="$dev1" +dd if=meta2.bad of="$dev2" +dd if=meta3.bad of="$dev3" + +pvs 2>&1 | tee out +grep "Checksum error" out > out2 +grep "$dev1" out2 +grep "$dev2" out2 +grep "$dev3" out2 + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +# bad metadata in some mdas doesn't prevent using +# the VG if there's a good mda found +lvcreate -l1 $vg + + +vgck --updatemetadata $vg + +pvs 2>&1 | tee out +not grep "Checksum error" out + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +vgchange -an $vg +vgremove -ff $vg + +# +# Test that vgck --updatemetadata will update old metadata +# and repair bad metadata text at the same time from different +# devices. +# + +aux clear_devs "$dev1" "$dev2" "$dev3" + +pvcreate "$dev1" +pvcreate "$dev2" +pvcreate --pvmetadatacopies 2 "$dev3" + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +# Put bad metadata onto dev1 +dd if="$dev1" of=meta1 bs=4k count=2 +sed 's/READ/RRRR/' meta1 > meta1.bad +dd if=meta1.bad of="$dev1" + +pvs 2>&1 | tee out +grep "Checksum error" out > out2 +grep "$dev1" out2 + +# We can still use the VG with other available +# mdas, skipping the bad mda. + +lvcreate -n $lv1 -l1 -an $vg "$dev1" +lvcreate -n $lv2 -l1 -an $vg "$dev1" + +# Put old metadata onto dev2 by updating +# the VG while dev2 is disabled. +aux disable_dev "$dev2" + +pvs +pvs "$dev1" +not pvs "$dev2" +pvs "$dev3" +lvs $vg/$lv1 +lvs $vg/$lv2 + +lvremove $vg/$lv2 + +aux enable_dev "$dev2" + +# Both old and bad metadata are reported. +pvs 2>&1 | tee out +grep "ignoring metadata seqno" out +grep "Checksum error" out +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +lvs $vg/$lv1 +not lvs $vg/$lv2 + +# fixes the bad metadata on dev1, and +# fixes the old metadata on dev2. +vgck --updatemetadata $vg + +pvs 2>&1 | tee out +not grep "ignoring metadata seqno" out +not grep "Checksum error" out +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +lvs $vg/$lv1 + +vgchange -an $vg +vgremove -ff $vg + +# +# Test pvscan activation with bad PVs +# + +# autoactivation not done on shared VGs +if test -n "$LVM_TEST_LVMLOCKD"; then +exit 0 +fi + +aux clear_devs "$dev1" "$dev2" "$dev3" + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}') +echo $PVID1 +PVID2=$(pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}') +echo $PVID2 +PVID3=$(pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}') +echo $PVID3 + +pvs + +dd if="$dev1" of=meta1 bs=4k count=2 +dd if="$dev2" of=meta2 bs=4k count=2 + +sed 's/READ/RRRR/' meta1 > meta1.bad +sed 's/seqno =/sss =/' meta2 > meta2.bad + +dd if=meta1.bad of="$dev1" +dd if=meta2.bad of="$dev2" + +pvs 2>&1 | tee out +grep "Checksum error" out > out2 +grep "$dev1" out2 +grep "$dev2" out2 + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +# bad metadata in one mda doesn't prevent using +# the VG since other mdas are fine +lvcreate -l1 -n $lv1 $vg + +vgchange -an $vg + +_clear_online_files + +# pvscan of one dev with bad metadata will result +# in the pvid online file being created but the +# VG will not be known. +pvscan --cache -aay "$dev1" +ls "$RUNDIR/lvm/pvs_online/$PVID1" +not ls "$RUNDIR/lvm/pvs_online/$PVID2" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" +not ls "$RUNDIR/lvm/vgs_online/$vg" + +_clear_online_files + +# scan the one pv with good metadata, does not scan any others +pvscan --cache -aay "$dev3" +not ls "$RUNDIR/lvm/pvs_online/$PVID1" +not ls "$RUNDIR/lvm/pvs_online/$PVID2" +ls "$RUNDIR/lvm/pvs_online/$PVID3" +not ls "$RUNDIR/lvm/vgs_online/$vg" + +vgck --updatemetadata $vg + +pvs 2>&1 | tee out +not grep "Checksum error" out + +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +vgchange -an $vg +vgremove -ff $vg diff --git a/test/shell/metadata-balance.sh b/test/shell/metadata-balance.sh index 88ac114..5f856a1 100644 --- a/test/shell/metadata-balance.sh +++ b/test/shell/metadata-balance.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,9 +8,11 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_devs 6 @@ -19,7 +22,7 @@ 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" + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" fi pvchange --metadataignore y "$dev1" check pv_field "$dev1" pv_mda_count $mdacp @@ -27,7 +30,7 @@ for mdacp in 1 2; do 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_count $(( mdacp * 2 )) check vg_field $vg vg_mda_used_count $mdacp check vg_field $vg vg_mda_copies unmanaged fi @@ -35,8 +38,8 @@ for mdacp in 1 2; do 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_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 @@ -60,7 +63,7 @@ pvunignore_ () { fi } -echo Test of vgmetadatacopies with vgcreate and vgchange +echo Test of vgmetadatacopies with vgcreate $SHARED and vgchange for mdacp in 1 2; do pvcreate --metadatacopies $mdacp "$dev1" "$dev2" "$dev4" "$dev5" check pv_field "$dev1" pv_mda_used_count $mdacp @@ -68,55 +71,55 @@ for mdacp in 1 2; do 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" + vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" check vg_field $vg vg_mda_copies unmanaged echo ensure both --vgmetadatacopies and --metadatacopies accepted - vgchange --metadatacopies $(($mdacp * 1)) $vg + 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)) + 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)) + 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 + echo vgcreate $SHARED 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" + vgcreate $SHARED $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)) + echo vgcreate $SHARED succeeds with a specific number of metadata copies + vgcreate $SHARED --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)) + vgcreate $SHARED --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)) + echo vgcreate $SHARED succeeds with a larger value than total metadatacopies + vgcreate $SHARED --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" + echo vgcreate $SHARED succeeds with --vgmetadatacopies unmanaged + vgcreate $SHARED --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" + echo vgcreate $SHARED succeds with small value of --metadatacopies, ignores mdas + vgcreate $SHARED --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_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 @@ -124,14 +127,14 @@ for mdacp in 1 2; do 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_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 + check vg_field $vg vg_mda_used_count $(( mdacp * 4 )) + echo --vgmetadatacopies 0 should be unmanaged for vgchange and vgcreate $SHARED 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" + vgcreate $SHARED --vgmetadatacopies 0 $vg "$dev1" "$dev2" "$dev4" "$dev5" check vg_field $vg vg_mda_copies unmanaged vgremove -f $vg done @@ -141,8 +144,8 @@ 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)) + vgcreate $SHARED --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" @@ -152,8 +155,8 @@ for mdacp in 1 2; do 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)) + vgcreate $SHARED --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" @@ -168,65 +171,71 @@ for mdacp in 1 2; do 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)) + 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 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 +if test -n "$LVM_TEST_LVMLOCKD"; then +echo skip vgsplit and vgmerge with lvmlockd +else + 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" + vgcreate $SHARED --vgmetadatacopies 2 $vg1 "$dev1" "$dev2" "$dev3" + vgcreate $SHARED --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)) + check vg_field $vg2 vg_mda_copies $(( mdacp * 1 )) vgsplit $vg1 $vg2 "$dev1" - check vg_field $vg2 vg_mda_copies $(($mdacp * 1)) + 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)) + 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)) + 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 $vg2 done +fi + 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)) + vgcreate $SHARED --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)) + 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)) + 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)) + 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)) + 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)) + check vg_field $vg1 vg_mda_used_count $(( mdacp * 2 )) vgremove -f $vg1 done diff --git a/test/shell/metadata-dirs.sh b/test/shell/metadata-dirs.sh deleted file mode 100644 index 852ce35..0000000 --- a/test/shell/metadata-dirs.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -# Copyright (C) 2011 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 - -. lib/test - -aux prepare_devs 3 - -pvcreate --metadatacopies 0 $(cat DEVICES) -not vgcreate $vg $(cat DEVICES) - -aux lvmconf "metadata/dirs = [ \"$TESTDIR/mda\" ]" - -vgcreate $vg "$dev1" -check vg_field $vg vg_mda_count 1 -vgremove -ff $vg - -vgcreate $vg $(cat DEVICES) -check vg_field $vg vg_mda_count 1 -vgremove -ff $vg - -pvcreate --metadatacopies 1 --metadataignore y "$dev1" -vgcreate $vg $(cat DEVICES) -check vg_field $vg vg_mda_count 2 -vgremove -ff $vg - -pvcreate --metadatacopies 1 --metadataignore n "$dev1" -vgcreate $vg $(cat DEVICES) -check vg_field $vg vg_mda_count 2 -vgremove -ff $vg - -pvcreate --metadatacopies 0 "$dev1" -aux lvmconf "metadata/dirs = [ \"$TESTDIR/mda\", \"$TESTDIR/mda2\" ]" -vgcreate $vg $(cat DEVICES) -check vg_field $vg vg_mda_count 2 -vgremove -ff $vg diff --git a/test/shell/metadata-full.sh b/test/shell/metadata-full.sh new file mode 100644 index 0000000..a1b7d02 --- /dev/null +++ b/test/shell/metadata-full.sh @@ -0,0 +1,131 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test full metadata' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# this test needs lot of memory +test "$(aux total_mem)" -gt 524288 || skip + +LVM_TEST_PVS=${LVM_TEST_PVS:-64} + +# aux prepare_vg $LVM_TEST_PVS + +unset LVM_LOG_FILE_MAX_LINES + +aux prepare_devs 64 1000 +get_devs + +vgcreate $SHARED -s 512K --metadatacopies 8 $vg "${DEVICES[@]}" + + +# Create a large metadata set, that getting close to 1/2MiB in size +# +# uses long tags to increase the size of the metadata +# more quickly +# +# the specific number of LVs in these loops isn't great +# because it doesn't depend specified behavior, but it's +# based on how much metadata it produces at the time this +# is written. + +vgcfgbackup -f data $vg +TEST_DEVS=925 +# Generate a lot of LV devices (size of 1 extent) +awk -v TEST_DEVS=$TEST_DEVS '/^\t\}/ { + printf("\t}\n\tlogical_volumes {\n"); + cnt=0; + for (i = 0; i < TEST_DEVS; i++) { + printf("\t\tlvol%d {\n", i); + printf("\t\t\tid = \"%06d-1111-2222-3333-2222-1111-%06d\"\n", i, i); + print "\t\t\tstatus = [\"READ\", \"WRITE\", \"VISIBLE\"]"; + print "\t\t\ttags = [\"A123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\"]"; + print "\t\t\tsegment_count = 1"; + print "\t\t\tsegment1 {"; + print "\t\t\t\tstart_extent = 0"; + print "\t\t\t\textent_count = 1"; + print "\t\t\t\ttype = \"striped\""; + print "\t\t\t\tstripe_count = 1"; + print "\t\t\t\tstripes = ["; + print "\t\t\t\t\t\"pv0\", " cnt++; + printf("\t\t\t\t]\n\t\t\t}\n\t\t}\n"); + } + } + {print} +' data >data_new +# Restoring big data set of LVs +vgcfgrestore -f data_new $vg + + +# should show non-zero +vgs -o+pv_mda_free + +# these addtag's will fail at some point when metadata space is full + +for i in $(seq 1 "$TEST_DEVS"); do + lvchange --addtag B123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 $vg/lvol$i || break; +done + +# test we hit 'out-of-metadata-space' +test "$i" -gt 2 +test "$i" -lt "$TEST_DEVS" + +# should show 0 +vgs -o+pv_mda_free +check vg_field $vg vg_mda_free 0 + +# remove some of the tags to check that we can reduce the size of the +# metadata, and continue using the vg + +for j in $(seq 1 "$i"); do + lvchange --deltag B123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 $vg/lvol$j; +done + +# should show non-zero +vgs -o+pv_mda_free + +# these will fail at some point when metadata space is full again + +for i in $(seq 1 50); do + lvcreate -l1 -an --addtag C123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 $vg || break; +done + +# should show 0 +vgs -o+pv_mda_free +check vg_field $vg vg_mda_free 0 + +# as long as we have a lot of LVs around, try to activate them all +# (filters are already set up that exclude the activated LVs from +# being scanned) + +time vgs + +# Avoid activation of large set of volumes - this is tested in vgchange-many.sh +#vgchange -ay $vg +#vgchange -an $vg + +# see if we can remove LVs to make more metadata space, +# and then create more LVs + +for i in $(seq 1 30); do lvremove -y $vg/lvol$i; done + +for i in $(seq 1 10); do lvcreate -l1 $vg; done + +# should show non-zero +vgs -o+pv_mda_free + +# FIXME: +# takes extreme amount of time, despite the fact, there are only few LVs active. +vgremove -ff $vg diff --git a/test/shell/metadata-old.sh b/test/shell/metadata-old.sh new file mode 100644 index 0000000..9a0351c --- /dev/null +++ b/test/shell/metadata-old.sh @@ -0,0 +1,221 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 3 +get_devs + +# +# Test "old metadata" repair which occurs when the VG is written +# and one of the PVs in the VG does not get written to, and then +# the PV reappears with the old metadata. This can happen if +# a command is killed or crashes after writing new metadata to +# only some of the PVs in the VG, or if a PV is temporarily +# inaccessible while a VG is written. +# + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +# +# Test that vgck --updatemetadata will update old metadata. +# + +lvcreate -n $lv1 -l1 -an $vg "$dev1" +lvcreate -n $lv2 -l1 -an $vg "$dev1" + +aux disable_dev "$dev2" + +pvs +pvs "$dev1" +not pvs "$dev2" +pvs "$dev3" +lvs $vg/$lv1 +lvs $vg/$lv2 + +lvremove $vg/$lv2 + +aux enable_dev "$dev2" + +pvs 2>&1 | tee out +grep "ignoring metadata seqno" out +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +lvs $vg/$lv1 +not lvs $vg/$lv2 + +# fixes the old metadata on dev1 +vgck --updatemetadata $vg + +pvs 2>&1 | tee out +not grep "ignoring metadata seqno" out +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +lvs $vg/$lv1 +not lvs $vg/$lv2 + +# +# Test that any writing command will also update the +# old metadata. +# + +lvcreate -n $lv2 -l1 -an $vg "$dev1" + +aux disable_dev "$dev2" + +pvs +pvs "$dev1" +not pvs "$dev2" +pvs "$dev3" +lvs $vg/$lv1 +lvs $vg/$lv2 + +lvremove $vg/$lv2 + +aux enable_dev "$dev2" + +pvs 2>&1 | tee out +grep "ignoring metadata seqno" out +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +lvs $vg/$lv1 +not lvs $vg/$lv2 + +# fixes the old metadata on dev1 +lvcreate -n $lv3 -l1 -an $vg + +pvs 2>&1 | tee out +not grep "ignoring metadata seqno" out +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +lvs $vg/$lv1 +not lvs $vg/$lv2 + +vgremove -ff $vg + +# +# First two PVs with one mda, where both have old metadata. +# Third PV with two mdas, where the first mda has old +# metadata, and the second mda has current metadata. +# + +aux clear_devs "$dev1" "$dev2" "$dev3" + +pvcreate "$dev1" +pvcreate "$dev2" +pvcreate --pvmetadatacopies 2 "$dev3" + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +lvcreate -n $lv1 -l1 -an $vg "$dev3" +lvcreate -n $lv2 -l1 -an $vg "$dev3" + +# Save the metadata at this point... +dd if="$dev1" of=meta1 bs=4k count=4 +dd if="$dev2" of=meta2 bs=4k count=4 +dd if="$dev3" of=meta3 bs=4k count=4 + +# and now change metadata so the saved copies are old +lvcreate -n $lv3 -l1 -an $vg "$dev3" + +# Copy the saved metadata back to the three +# devs first mda, leaving the second mda on +# dev3 as the only latest copy of the metadata. + +dd if=meta1 of="$dev1" +dd if=meta2 of="$dev2" +dd if=meta3 of="$dev3" + +pvs 2>&1 | tee out +grep "ignoring metadata seqno" out +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +# We still see the three LVs since we are using +# the latest copy of metadata from dev3:mda2 + +lvs $vg/$lv1 +lvs $vg/$lv2 +lvs $vg/$lv3 + +# This command which writes the VG should update +# all of the old copies. +lvcreate -n $lv4 -l1 -an $vg + +pvs 2>&1 | tee out +not grep "ignoring metadata seqno" out +pvs "$dev1" +pvs "$dev2" +pvs "$dev3" + +lvs $vg/$lv1 +lvs $vg/$lv2 +lvs $vg/$lv3 +lvs $vg/$lv4 + +vgchange -an $vg +vgremove -ff $vg + +# Test when the metadata on two PVs have the same seqno +# but different checksums. + +aux clear_devs "$dev1" "$dev2" + +pvcreate "$dev1" +pvcreate "$dev2" + +vgcreate $SHARED $vg "$dev1" "$dev2" + +lvcreate -n $lv1 -l1 -an $vg + +pvck --dump metadata -f meta "$dev2" + +# change an unimportant character so the metadata is effectively +# the same in content but will have a different checksum +sed 's/Linux/linux/' meta > meta2 + +# write out the changed metadata +pvck --repair -y -f meta2 "$dev2" + +# the vg can still be used but will produce warnings +# the mda on one pv is updated, but not the other, +# which changes the error from a checksum inconsistency +# into a seqno inconsistency. +lvs $vg 2>&1 | tee out +grep WARNING out +grep $lv1 out +lvcreate -n $lv2 -l1 -an $vg 2>&1 |tee out +grep WARNING out +lvs $vg 2>&1 | tee out +grep WARNING out +grep $lv1 out +grep $lv2 out + +# correct the senqo inconsistency +vgck --updatemetadata $vg +lvs $vg 2>&1 | tee out +not grep WARNING out +grep $lv1 out +grep $lv2 out + +vgremove -ff $vg diff --git a/test/shell/metadata-zero-space.sh b/test/shell/metadata-zero-space.sh new file mode 100644 index 0000000..54fbd8f --- /dev/null +++ b/test/shell/metadata-zero-space.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +xxd -v || skip + +aux prepare_devs 1 256 +get_devs + +# Fill with random data so if the space between metadata +# copies are not zeroed the grep for zeros will fail. +dd if=/dev/urandom of="$dev1" bs=1M count=1 || true +dd if=/dev/urandom of="$dev1" bs=1M skip=15 count=1 || true + +pvcreate --pvmetadatacopies 2 "$dev1" + +vgcreate $SHARED "$vg" "$dev1" + +for i in $(seq 1 50); do lvcreate -l1 -an $vg; done + +# Check metadata copies are separated by zeroes in the first mda + +dd if="$dev1" of=meta.raw bs=1M count=1 + +xxd meta.raw > meta.txt + +# to help debug if the next grep fails +ls -l meta.txt +head -n 100 meta.txt +grep -A4 -B4 '01200:' meta.txt + +_vg="$vg " +_vg="${_vg:0:16}" +grep -B1 "$_vg" meta.txt > meta.vg + +cat meta.vg + +grep -v "$_vg" meta.vg > meta.zeros + +cat meta.zeros + +grep '0000 0000 0000 0000 0000 0000 0000 0000' meta.zeros > meta.count + +# wc will often equal 51, but some natural variability in +# metadata locations/content mean that some lines do not +# require a full line of zero padding, and will not match +# the grep for a full row of zeros. So, check that more +# than 20 lines match the full row of zeros (this is a +# random choice, and this isn't a perfect way to test for +# zero padding.) + +test "$(wc -l < meta.count)" -gt 20 + +rm meta.raw meta.txt meta.vg meta.zeros meta.count + +# +# Check metadata copies are separated by zeroes in the second mda +# + +dd if="$dev1" of=meta.raw bs=1M seek=15 count=1 + +xxd meta.raw > meta.txt + +grep -B1 "$_vg" meta.txt > meta.vg + +cat meta.vg + +grep -v "$_vg" meta.vg > meta.zeros + +cat meta.zeros + +grep '0000 0000 0000 0000 0000 0000 0000 0000' meta.zeros > meta.count + +test "$(wc -l < meta.count)" -gt 20 + +vgremove -ff $vg diff --git a/test/shell/metadata.sh b/test/shell/metadata.sh index a9f8640..f5d6483 100644 --- a/test/shell/metadata.sh +++ b/test/shell/metadata.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,11 +8,14 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_devs 5 +get_devs pvcreate "$dev1" pvcreate --metadatacopies 0 "$dev2" @@ -19,9 +23,13 @@ pvcreate --metadatacopies 0 "$dev3" pvcreate "$dev4" pvcreate --metadatacopies 0 "$dev5" -vgcreate -c n $vg $(cat DEVICES) +vgcreate $SHARED "$vg" "${DEVICES[@]}" lvcreate -n $lv -l 1 -i5 -I256 $vg +pvck --dump metadata "$dev1" > meta1 +grep "description = " meta1 > desc1 +grep "Write from lvcreate" desc1 + pvchange -x n "$dev1" pvchange -x y "$dev1" vgchange -a n $vg @@ -31,46 +39,14 @@ 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 $(cat DEVICES) + pvcreate --metadatacopies "$mdacp" "${DEVICES[@]}" pvcreate "$dev1" - vgcreate -c n $vg $(cat DEVICES) + vgcreate $SHARED "$vg" "${DEVICES[@]}" lvcreate -n $lv1 -l 2 -i5 -I256 $vg - lvcreate -n $lv2 -m2 -l 2 $vg + lvcreate -aey -n $lv2 --type mirror -m2 -l 2 $vg lvchange -an $vg/$lv1 $vg/$lv2 - vgchange -ay $vg + vgchange -aey $vg lvchange -an $vg/$lv1 $vg/$lv2 vgremove -f $vg done not grep "Cached VG .* incorrect PV list" out0 - -# some M1 metadata tests -pvcreate -M1 "$dev1" "$dev2" "$dev3" -pv3_uuid=$(get pv_field "$dev3" pv_uuid) -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 $(cat DEVICES) - -# 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 $(cat DEVICES) - -# 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/shell/mirror-names.sh b/test/shell/mirror-names.sh index d6c67ee..8d525ca 100644 --- a/test/shell/mirror-names.sh +++ b/test/shell/mirror-names.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2007-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2007-2017 Red Hat, Inc. All rights reserved. # Copyright (C) 2007-2008 NEC Corporation # # This copyrighted material is made available to anyone wishing to use, @@ -8,36 +9,46 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA test_description="check namings of mirrored LV" -. lib/test + + +. lib/inittest # --------------------------------------------------------------------- # Utilities lv_devices_() { local d + local i local lv=$1 shift - local devices=$@ - local devs=$(get lv_field $lv devices -a | sed 's/([0-9]*)//g; s/ //g; s/,/ /g') + local devices=( "$@" ) + local devs + + devs=$(get lv_devices "$lv") for d in $devs; do - (echo $devices | grep $d) || return 1 - devices=$(echo $devices | sed "s/$d//") + (echo "${devices[@]}" | grep "$d") || return 1 + for i in "${!devices[@]}"; do + if [ "${devices[i]}" = "$d" ] ; then + unset "devices[i]" + fi + done done - test -z "$(echo $devices | sed 's/ //g')" + test "${#devices[@]}" -eq 0 || + die "Left devices " "${devices[@]}" } lv_mirror_log_() { - test $(get lv_field $1 mirror_log) = $2 + get lv_field "$1" mirror_log | tr -d '[]' } lv_convert_lv_() { - get lv_field $1 convert_lv + get lv_field "$1" convert_lv | tr -d '[]' } # --------------------------------------------------------------------- @@ -63,18 +74,18 @@ check_and_cleanup_lvs_ #COMM "init: lvcreate" #COMM "mirror images are ${lv1}_mimage_x" -lvcreate -l2 -m1 -n $lv1 $vg +lvcreate -an -Zn -l2 --type mirror -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 +test "$(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 +lvcreate -an -Zn --type mirror -m1 -l2 -n $name $vg lvs $vg/$name check_and_cleanup_lvs_ @@ -84,7 +95,7 @@ check_and_cleanup_lvs_ #COMM "init: lvrename" #COMM "renamed mirror names: $lv1 to $lv2" -lvcreate -l2 -m1 -n $lv1 $vg +lvcreate -an -Zn -l2 --type mirror -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 @@ -98,28 +109,48 @@ check_and_cleanup_lvs_ #COMM "init: lvconvert" #COMM "converting mirror names is ${lv1}_mimagetmp_2" -lvcreate -l2 -m1 -n $lv1 $vg -lvconvert -m+1 -i+40 -b $vg/$lv1 +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg +# Use large enough polling interval so mirror is keeping mimagetmp +LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -i+40 -b $vg/$lv1 + +# +# TODO: lvmpolld is not 'preserving' -i interval setting from +# lvconvert initiating command - so there is not much to test +# if the lvconvert is already finished at this point +# and lvmpolld cleaned metadata and refreshed DM table +# +# It' unclear if this is undocumented feature of bug. +# +if test ! -f LOCAL_LVMPOLLD ; then + +for i in $(seq 1 10) ; do + # check if background process already started + # this is recognized by presence of LV1_mimage_2 + check lvl $vg/${lv1}_mimage_2 && break + sleep .1 +done convlv=$(lv_convert_lv_ $vg/$lv1) -test $convlv = ${lv1}_mimagetmp_2 +test "$convlv" = "${lv1}_mimagetmp_2" lv_devices_ $vg/$lv1 $convlv ${lv1}_mimage_2 lv_devices_ $vg/$convlv ${lv1}_mimage_0 ${lv1}_mimage_1 lv_mirror_log_ $vg/$convlv ${lv1}_mlog +check lv_exists $vg ${lv1}_mimagetmp_2 -#COMM "mirror log name after re-adding is ${lv1}_mlog" \ -lvconvert --mirrorlog core $vg/$lv1 +#COMM "mirror log name after re-adding is ${lv1}_mlog" +lvconvert -f --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 lv_mirror_log_ $vg/$convlv ${lv1}_mlog -#COMM "renamed converting mirror names: $lv1 to $lv2" \ +#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 lv_mirror_log_ $vg/$convlv ${lv2}_mlog +fi # ! -f LOCAL_LVMPOLLD #COMM "cleanup" check_and_cleanup_lvs_ diff --git a/test/shell/mirror-vgreduce-removemissing.sh b/test/shell/mirror-vgreduce-removemissing.sh index 232c2be..ff7eea5 100644 --- a/test/shell/mirror-vgreduce-removemissing.sh +++ b/test/shell/mirror-vgreduce-removemissing.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2017 Red Hat, Inc. All rights reserved. # Copyright (C) 2007 NEC Corporation # # This copyrighted material is made available to anyone wishing to use, @@ -8,24 +9,28 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA test_description="ensure that 'vgreduce --removemissing' works on mirrored LV" -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +list_pvs=() lv_is_on_ () { local lv=$vg/$1 shift - local pvs=$@ + local list_pvs=( "$@" ) - echo "Check if $lv is exactly on PVs $pvs" + echo "Check if $lv is exactly on PVs" "${list_pvs[@]}" rm -f out1 out2 - echo $pvs | sed 's/ /\n/g' | sort | uniq > out1 + printf "%s\n" "${list_pvs[@]}" | sort | uniq > out1 lvs -a -o+devices $lv - get lv_devices $lv | sed 's/ /\n/g' | sort | uniq > out2 || true + get lv_devices "$lv" | sort | uniq > out2 diff --ignore-blank-lines out1 out2 } @@ -34,23 +39,23 @@ mimages_are_on_ () { local lv=$1 shift - local pvs=$@ - local mimages + local list_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 - lvs --noheadings -a -o lv_name $vg > lvs_log - mimages=$(grep "${lv}_mimage_" lvs_log | \ - sed 's/\[//g; s/\]//g' || true) - - for i in $mimages; do - echo "Checking $vg/$i" - lvs -a -o+devices $vg/$i - lvs -a -odevices --noheadings $vg/$i > lvs_log - sed 's/([^)]*)//g; s/ //g; s/,/ /g' lvs_log | sort | uniq >> out2 || true - done + echo "Check if mirror images of $lv are on PVs" "${list_pvs[@]}" + printf "%s\n" "${list_pvs[@]}" | sort | uniq | tee out1 + + get lv_field_lv_ "$vg" lv_name -a | grep "${lv}_mimage_" | tee lvs_log + test -s lvs_log || return 1 + + while IFS= read -r i ; do + mimages+=( "$i" ) + done < lvs_log + + for i in "${mimages[@]}"; do + get lv_devices "$vg/$i" + done | sort | uniq | tee out2 diff --ignore-blank-lines out1 out2 } @@ -65,29 +70,35 @@ mirrorlog_is_on_() lv_is_linear_() { echo "Check if $1 is linear LV (i.e. not a mirror)" - get lv_field $vg/$1 "stripes,attr" | grep "^1 -" >/dev/null + get lv_field $vg/$1 "stripes,attr" | tee out + grep "^1 -" out >/dev/null } rest_pvs_() { local index=$1 local num=$2 - local rem= + local rem=() local n + local dev - for n in $(seq 1 $(($index - 1))) $(seq $(($index + 1)) $num); do - eval local dev=$\dev$n - rem="$rem $dev" + for n in $(seq 1 $(( index - 1 )) ) $(seq $(( index + 1 )) $num); do + eval "dev=\$dev$n" + rem+=( "$dev" ) done - echo "$rem" + printf "%s\n" "${rem[@]}" } # --------------------------------------------------------------------- # Initialize PVs and VGs -aux prepare_vg 5 +aux prepare_pvs 5 80 +get_devs +vgcreate $SHARED -s 64k "$vg" "${DEVICES[@]}" +BLOCKS=0-7 +BLOCKS1=8-15 # --------------------------------------------------------------------- # Common environment setup/cleanup for each sub testcases @@ -100,15 +111,23 @@ prepare_lvs_() check_and_cleanup_lvs_() { - lvs -a -o+devices $vg + lvs -a -o+lv_uuid,devices $vg prepare_lvs_ } recover_vg_() { aux enable_dev "$@" + + # clear outdated metadata on PVs so they can be used again + vgck --updatemetadata $vg + + pvscan --cache + pvcreate -ff "$@" + # wipefs -a "$@" vgextend $vg "$@" + check_and_cleanup_lvs_ } @@ -121,10 +140,9 @@ check_and_cleanup_lvs_ #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 -mimages_are_on_ $lv1 $dev1 $dev2 -mirrorlog_is_on_ $lv1 $dev3 +lvcreate -an -Zn -l2 --type mirror -m1 --nosync -n $lv1 $vg "$dev1" "$dev2" "$dev3":$BLOCKS +mimages_are_on_ $lv1 "$dev1" "$dev2" +mirrorlog_is_on_ $lv1 "$dev3" aux disable_dev "$dev2" vgreduce --removemissing --force $vg lv_is_linear_ $lv1 @@ -142,14 +160,17 @@ test_3way_mirror_fail_1_() { local index=$1 - lvcreate -l2 -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev4":0 - lvchange -an $vg/$lv1 + lvcreate -an -Zn -l2 --type mirror -m2 --nosync -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev4":$BLOCKS mimages_are_on_ $lv1 "$dev1" "$dev2" "$dev3" mirrorlog_is_on_ $lv1 "$dev4" - eval aux disable_dev \$dev$index + eval aux disable_dev "\$dev$index" vgreduce --removemissing --force $vg - lvs -a -o+devices $vg - mimages_are_on_ $lv1 $(rest_pvs_ $index 3) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$index" 3 ) + + mimages_are_on_ "$lv1" "${list_pvs[@]}" mirrorlog_is_on_ $lv1 "$dev4" } @@ -157,7 +178,7 @@ 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 + eval recover_vg_ "\$dev$n" done # --------------------------------------------------------------------- @@ -169,23 +190,30 @@ test_3way_mirror_fail_2_() { local index=$1 - lvcreate -l2 -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev4":0 - lvchange -an $vg/$lv1 + lvcreate -an -Zn -l2 --type mirror -m2 --nosync -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev4":$BLOCKS mimages_are_on_ $lv1 "$dev1" "$dev2" "$dev3" mirrorlog_is_on_ $lv1 "$dev4" - rest_pvs_ $index 3 - aux disable_dev $(rest_pvs_ $index 3) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$index" 3 ) + + aux disable_dev "${list_pvs[@]}" vgreduce --force --removemissing $vg - lvs -a -o+devices $vg lv_is_linear_ $lv1 - eval lv_is_on_ $lv1 \$dev$n + 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) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$n" 3 ) + + recover_vg_ "${list_pvs[@]}" done # --------------------------------------------------------------------- @@ -197,16 +225,18 @@ 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 + lvcreate -an -Zn -l2 --type mirror -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev5":$BLOCKS lvconvert -m+1 $vg/$lv1 "$dev4" check mirror_images_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4" check mirror_log_on $vg $lv1 "$dev5" eval aux disable_dev \$dev$index - lvs -a -o +devices vgreduce --removemissing --force $vg - lvs -a -o+devices # $vg - check mirror_images_on $vg $lv1 "$dev5" # $(rest_pvs_ $index 4) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$index" 4 ) + + check mirror_images_on $vg $lv1 "${list_pvs[@]}" check mirror_log_on $vg $lv1 "$dev5" } @@ -225,26 +255,35 @@ done test_3way_mirror_plus_1_fail_3_() { local index=$1 + local dev - lvcreate -l2 -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev5":0 - lvchange -an $vg/$lv1 + lvcreate -an -Zn -l2 --type mirror -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev3" "$dev5":$BLOCKS lvconvert -m+1 $vg/$lv1 "$dev4" check mirror_images_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4" check mirror_log_on $vg $lv1 "$dev5" - lvs -a -o+devices $vg - aux disable_dev $(rest_pvs_ $index 4) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$index" 4 ) + + aux disable_dev "${list_pvs[@]}" vgreduce --removemissing --force $vg lvs -a -o+devices $vg - eval local dev=\$dev$n + eval dev=\$dev$n check linear $vg $lv1 - check lv_on $vg $lv1 $dev + check lv_on $vg $lv1 "$dev" } 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) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$n" 4 ) + + recover_vg_ "${list_pvs[@]}" done # --------------------------------------------------------------------- @@ -256,15 +295,18 @@ test_2way_mirror_plus_2_fail_1_() { local index=$1 - lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev5":0 - lvchange -an $vg/$lv1 + lvcreate -an -Zn -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS lvconvert -m+2 $vg/$lv1 "$dev3" "$dev4" mimages_are_on_ $lv1 "$dev1" "$dev2" "$dev3" "$dev4" mirrorlog_is_on_ $lv1 "$dev5" eval aux disable_dev \$dev$n vgreduce --removemissing --force $vg - lvs -a -o+devices $vg - mimages_are_on_ $lv1 $(rest_pvs_ $index 4) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$index" 4 ) + + mimages_are_on_ "$lv1" "${list_pvs[@]}" mirrorlog_is_on_ $lv1 "$dev5" } @@ -272,7 +314,7 @@ 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 + eval recover_vg_ "\$dev$n" done # --------------------------------------------------------------------- @@ -283,17 +325,23 @@ done test_2way_mirror_plus_2_fail_3_() { local index=$1 + local dev - lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev5":0 - lvchange -an $vg/$lv1 + lvcreate -an -Zn -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS lvconvert -m+2 $vg/$lv1 "$dev3" "$dev4" mimages_are_on_ $lv1 "$dev1" "$dev2" "$dev3" "$dev4" mirrorlog_is_on_ $lv1 "$dev5" - aux disable_dev $(rest_pvs_ $index 4) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$index" 4 ) + + aux disable_dev "${list_pvs[@]}" vgreduce --removemissing --force $vg lvs -a -o+devices $vg - eval local dev=\$dev$n - mimages_are_on_ $lv1 $dev || lv_is_on_ $lv1 $dev + eval dev=\$dev$n + not mimages_are_on_ $lv1 "$dev" + lv_is_on_ $lv1 "$dev" not mirrorlog_is_on_ $lv1 "$dev5" } @@ -301,7 +349,12 @@ 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) + + list_pvs=(); while IFS= read -r line ; do + list_pvs+=( "$line" ) + done < <( rest_pvs_ "$n" 4 ) + + recover_vg_ "${list_pvs[@]}" done # --------------------------------------------------------------------- @@ -309,8 +362,7 @@ done #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 +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS mimages_are_on_ $lv1 "$dev1" "$dev2" mirrorlog_is_on_ $lv1 "$dev5" aux disable_dev "$dev5" @@ -321,8 +373,7 @@ 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 +lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS lvconvert -m+1 $vg/$lv1 "$dev3" mimages_are_on_ $lv1 "$dev1" "$dev2" "$dev3" mirrorlog_is_on_ $lv1 "$dev5" @@ -337,8 +388,7 @@ recover_vg_ "$dev5" #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 +lvcreate -an -Zn -l2 --type mirror -m1 --nosync -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS mimages_are_on_ $lv1 "$dev1" "$dev2" mirrorlog_is_on_ $lv1 "$dev5" aux disable_dev "$dev1" "$dev2" @@ -348,8 +398,7 @@ 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 +lvcreate -an -Zn -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS lvconvert -m+1 $vg/$lv1 "$dev3" mimages_are_on_ $lv1 "$dev1" "$dev2" "$dev3" mirrorlog_is_on_ $lv1 "$dev5" @@ -363,10 +412,8 @@ recover_vg_ "$dev1" "$dev2" "$dev3" #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 +lvcreate -an -Zn -l2 --type mirror -m1 --nosync -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS +lvcreate -an -Zn -l2 --type mirror -m1 --nosync -n $lv2 $vg "$dev3" "$dev4" "$dev5":$BLOCKS1 mimages_are_on_ $lv1 "$dev1" "$dev2" mimages_are_on_ $lv2 "$dev3" "$dev4" mirrorlog_is_on_ $lv1 "$dev5" @@ -381,10 +428,8 @@ 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 +lvcreate -an -Zn -l2 --type mirror -m1 --nosync -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS +lvcreate -an -Zn -l2 --type mirror -m1 --nosync -n $lv2 $vg "$dev3" "$dev4" "$dev5":$BLOCKS1 mimages_are_on_ $lv1 "$dev1" "$dev2" mimages_are_on_ $lv2 "$dev3" "$dev4" mirrorlog_is_on_ $lv1 "$dev5" @@ -403,8 +448,7 @@ recover_vg_ "$dev2" "$dev4" #COMM "no failures" prepare_lvs_ -lvcreate -l2 -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev5":0 -lvchange -an $vg/$lv1 +lvcreate -an -Zn -l2 --type mirror -m1 --nosync -n $lv1 $vg "$dev1" "$dev2" "$dev5":$BLOCKS mimages_are_on_ $lv1 "$dev1" "$dev2" mirrorlog_is_on_ $lv1 "$dev5" vgreduce --removemissing --force $vg diff --git a/test/shell/missing-pv-unused.sh b/test/shell/missing-pv-unused.sh new file mode 100644 index 0000000..d74365f --- /dev/null +++ b/test/shell/missing-pv-unused.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 3 + +lvcreate -n $lv1 -L8M $vg "$dev2" +lvcreate -n $lv2 -L8M $vg "$dev3" +lvcreate -n $lv3 -L8M $vg "$dev2" +lvcreate -n $lv4 -L8M $vg "$dev3" + +vgchange -an $vg + +# Fail device that is not used by any LVs. +aux disable_dev "$dev1" + +pvs +vgs +lvs -a -o+devices + +# Cannot do normal activation of LVs not using failed PV. +lvchange -ay $vg/$lv1 +lvchange -ay $vg/$lv2 + +vgchange -an $vg + +# Check that MISSING flag is not set in ondisk metadata. +pvck --dump metadata "$dev2" > meta +not grep MISSING meta +rm meta + +pvs +vgs +lvs -a -o+devices + +# lvremove is one of the few commands that is allowed to run +# when PVs are missing. The vg_write from this command sets +# the MISSING flag on the PV in the ondisk metadata. +# (this could be changed, the MISSING flag wouldn't need +# to be set in the first place since the PV isn't used.) +lvremove $vg/$lv1 + +# Check that MISSING flag is set in ondisk metadata. +pvck --dump metadata "$dev2" > meta +grep MISSING meta +rm meta + +# with MISSING flag in metadata, restrictions apply +not lvcreate -l1 $vg + +aux enable_dev "$dev1" + +# No LVs are using the PV with MISSING flag, so no restrictions +# are applied, and the vg_write here clears the MISSING flag on disk. +lvcreate -l1 $vg + +# Check that MISSING flag is not set in ondisk metadata. +pvck --dump metadata "$dev2" > meta +not grep MISSING meta +rm meta + + +pvs +vgs +lvs -a -o+devices + +vgremove -ff $vg diff --git a/test/shell/missing-pv.sh b/test/shell/missing-pv.sh new file mode 100644 index 0000000..e1ff659 --- /dev/null +++ b/test/shell/missing-pv.sh @@ -0,0 +1,187 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 3 + +lvcreate -n $lv1 -L8M --type mirror -m 1 $vg +lvcreate -n $lv2 -L8M --type mirror -m 1 $vg + +vgchange -an $vg + +pvs +vgs +lvs -a -o+devices + +# Fail one leg of each mirror LV. +aux disable_dev "$dev1" + +pvs -o+missing |tee out +grep missing out |tee out2 +grep unknown out2 +vgs -o+partial,missing_pv_count +check vg_field $vg vg_partial "partial" +check vg_field $vg vg_missing_pv_count 1 +lvs -a -o+devices + +# Cannot do normal activate of either LV with a failed leg. +not lvchange -ay $vg/$lv1 +not lvchange -ay $vg/$lv2 + +# Can activate with partial option. +lvchange -ay --activationmode partial $vg/$lv1 +lvchange -ay --activationmode partial $vg/$lv2 + +pvs -o+missing |tee out +grep missing out |tee out2 +grep unknown out2 +vgs -o+partial,missing_pv_count +check vg_field $vg vg_partial "partial" +check vg_field $vg vg_missing_pv_count 1 +lvs -a -o+devices + +# Repair lv1 so it no longer uses failed dev. +lvconvert --repair --yes $vg/$lv1 + +# Check that MISSING flag is set in ondisk metadata, +# it should have been written by the lvconvert since the +# missing PV is still used by lv2. +pvck --dump metadata "$dev2" > meta +grep MISSING meta +rm meta + +pvs -o+missing |tee out +grep missing out |tee out2 +grep unknown out2 +vgs -o+partial,missing_pv_count +check vg_field $vg vg_partial "partial" +check vg_field $vg vg_missing_pv_count 1 +lvs -a -o+devices + +# Verify normal activation is possible of lv1 since it's +# not using any failed devs, and partial activation is +# required for lv2 since it's still using the failed dev. +vgchange -an $vg +lvchange -ay $vg/$lv1 +not lvchange -ay $vg/$lv2 +vgchange -an $vg + +aux enable_dev "$dev1" + +pvs -o+missing |tee out +grep missing out |tee out2 +grep "$dev1" out2 +vgs -o+partial,missing_pv_count +check vg_field $vg vg_partial "partial" +check vg_field $vg vg_missing_pv_count 1 +lvs -a -o+devices + +# TODO: check that lv2 has partial flag, lv1 does not +# (there's no partial reporting option, only attr p.) + +# Check that MISSING flag is still set in ondisk +# metadata since the previously missing dev is still +# used by lv2. +pvck --dump metadata "$dev2" > meta +grep MISSING meta +rm meta + +# The missing pv restrictions still apply even after +# the dev has reappeared since it has the MISSING flag. +not lvchange -ay $vg/$lv2 +not lvcreate -l1 $vg + +# Update old metadata on the previously missing PV. +# This should not clear the MISSING flag because the +# previously missing PV is still used by lv2. +# This would be done by any command that writes +# metadata, e.g. lvcreate, but since we are in a +# state with a missing pv, most commands that write +# metadata are restricted, so use a command that +# explicitly writes/fixes metadata. +vgck --updatemetadata $vg + +pvs -o+missing |tee out +grep missing out |tee out2 +grep "$dev1" out2 +vgs -o+partial,missing_pv_count +check vg_field $vg vg_partial "partial" +check vg_field $vg vg_missing_pv_count 1 +lvs -a -o+devices + +# Check that MISSING flag is still set in ondisk metadata since the +# previously missing dev is still used by lv2. +pvck --dump metadata "$dev2" > meta +grep MISSING meta +rm meta + +# The missing pv restrictions still apply since it has the MISSING flag. +not lvchange -ay $vg/$lv2 +not lvcreate -l1 $vg + +lvchange -ay --activationmode partial $vg/$lv2 + +# Replace the missing leg of LV2 so no LV will be using the dev that was +# missing. The MISSING_PV flag will not have been cleared from the +# metadata yet; that will take another metadata update. +lvconvert --repair --yes $vg/$lv2 + +lvs -a -o+devices | tee out +not grep "$dev1" out + +# The MISSING_PV flag hasn't been cleared from the metadata yet, but now +# that the PV is not used by any more LVs, that flag will be cleared from +# the metadata in the next update. +pvck --dump metadata "$dev2" > meta +grep MISSING meta +rm meta + +# Reporting commands run vg_read which sees MISSING_PV in the metadata, +# but vg_read then sees the dev is no longer used by any LV, so vg_read +# clears the MISSING_PV flag in the vg struct (not in the metadata) before +# returning the vg struct to the caller. It's cleared in the vg struct so +# that the limitations of having a missing PV are not applied to the +# command. The caller sees/uses/reports the VG as having no missing PV, +# even though the metadata still contains MISSING_PV. The MISSING_PV flag +# is no longer needed in the metadata, but there has simply not been a +# metadata update yet to clear it. +# The message that's printed in this case is: +# WARNING: VG %s has unused reappeared PV %s %s +pvs -o+missing |tee out +not grep missing out +vgs -o+partial,missing_pv_count +check vg_field $vg vg_partial "" +check vg_field $vg vg_missing_pv_count 0 + +# Run any command that updates the metadata, and the MISSING_PV flag will +# be cleared. Here just use lvcreate -l1, or we could use +# vgck --updatemetadata. +lvcreate -l1 $vg + +# Now the MISSING flag is removed from the ondisk metadata. +pvck --dump metadata "$dev2" > meta +not grep MISSING meta +rm meta + +# and commands continue to report no missing PV +pvs -o+missing |tee out +not grep missing out +vgs -o+partial,missing_pv_count +check vg_field $vg vg_partial "" +check vg_field $vg vg_missing_pv_count 0 + +vgchange -an $vg + +vgremove -ff $vg diff --git a/test/shell/multi_hosts_lv_ex_timeout_hosta.sh b/test/shell/multi_hosts_lv_ex_timeout_hosta.sh new file mode 100644 index 0000000..d78b6d9 --- /dev/null +++ b/test/shell/multi_hosts_lv_ex_timeout_hosta.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This testing script is for multi-hosts testing. +# +# On the host A: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_ex_timeout_hosta.sh +# On the host B: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_ex_timeout_hostb.sh + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_MULTI_HOST" ] && skip; + +IFS=',' read -r -a BLKDEVS <<< "$LVM_TEST_BACKING_DEVICE" + +for d in "${BLKDEVS[@]}"; do + aux extend_filter_LVMTEST "a|$d|" +done + +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +for d in "${BLKDEVS[@]}"; do + dd if=/dev/zero of="$d" bs=32k count=1 + wipefs -a "$d" 2>/dev/null || true + + sg_dev=$(sg_map26 "$d") + if [ -n "$LVM_TEST_LOCK_TYPE_IDM" ]; then + echo "Cleanup IDM context for drive ${d} ($sg_dev)" + sg_raw -v -r 512 -o idm_tmp_data.bin "$sg_dev" \ + 88 00 01 00 00 00 00 20 FF 01 00 00 00 01 00 00 + sg_raw -v -s 512 -i idm_tmp_data.bin "$sg_dev" \ + 8E 00 FF 00 00 00 00 00 00 00 00 00 00 01 00 00 + rm idm_tmp_data.bin + fi +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + vgcreate $SHARED TESTVG$i ${BLKDEVS[$(( i - 1 ))]} + lvcreate -a n --zero n -l 1 -n foo TESTVG$i + lvchange -a ey TESTVG$i/foo +done + +for d in "${BLKDEVS[@]}"; do + drive_wwn=$(udevadm info "$d" | awk -F= '/E: ID_WWN=/ {print $2}') + for dev in /dev/*; do + if [ -b "$dev" ] && [[ ! "$dev" =~ [0-9] ]]; then + wwn=$(udevadm info "$dev" | awk -F= '/E: ID_WWN=/ {print $2}') + if [ "$wwn" = "$drive_wwn" ]; then + base_name="$(basename -- ${dev})" + drive_list+=("$base_name") + host_list+=( $(readlink "/sys/block/$base_name" | awk -F'/' '{print $6}') ) + fi + fi + done +done + +for d in "${drive_list[@]}"; do + [ -f /sys/block/$d/device/delete ] && echo 1 > /sys/block/$d/device/delete +done + +sleep 100 + +for i in $(seq 1 ${#BLKDEVS[@]}); do + check grep_lvmlockd_dump "S lvm_TESTVG$i kill_vg" + lvmlockctl --drop TESTVG$i +done + +# Rescan drives so can probe the deleted drives and join back them +for h in "${host_list[@]}"; do + [ -f /sys/class/scsi_host/${h}/scan ] && echo "- - -" > /sys/class/scsi_host/${h}/scan +done diff --git a/test/shell/multi_hosts_lv_ex_timeout_hostb.sh b/test/shell/multi_hosts_lv_ex_timeout_hostb.sh new file mode 100644 index 0000000..f0273fa --- /dev/null +++ b/test/shell/multi_hosts_lv_ex_timeout_hostb.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This testing script is for multi-hosts testing. +# +# On the host A: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_ex_timeout_hosta.sh +# On the host B: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_ex_timeout_hostb.sh + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_MULTI_HOST" ] && skip; + +IFS=',' read -r -a BLKDEVS <<< "$LVM_TEST_BACKING_DEVICE" + +for d in "${BLKDEVS[@]}"; do + aux extend_filter_LVMTEST "a|$d|" +done + +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +vgchange --lock-start + +vgdisplay + +for i in $(seq 1 ${#BLKDEVS[@]}); do + not lvchange -a ey TESTVG$i/foo +done + +# Sleep for 70 seconds so the previous lease is expired +sleep 70 + +for i in $(seq 1 ${#BLKDEVS[@]}); do + lvchange -a ey TESTVG$i/foo + lvchange -a n TESTVG$i/foo +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + vgremove -f TESTVG$i +done diff --git a/test/shell/multi_hosts_lv_hosta.sh b/test/shell/multi_hosts_lv_hosta.sh new file mode 100644 index 0000000..2ae2989 --- /dev/null +++ b/test/shell/multi_hosts_lv_hosta.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This testing script is for multi-hosts testing, the paired scripts +# are: multi_hosts_lv_hosta.sh / multi_hosts_lv_hostb.sh +# +# On the host A: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_hosta.sh +# On the host B: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_hostb.sh + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_MULTI_HOST" ] && skip; + +IFS=',' read -r -a BLKDEVS <<< "$LVM_TEST_BACKING_DEVICE" + +for d in "${BLKDEVS[@]}"; do + aux extend_filter_LVMTEST "a|$d|" +done + +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +BLKDEVS_NUM=${#BLKDEVS[@]} + +for d in "${BLKDEVS[@]}"; do + dd if=/dev/zero of="$d" bs=32k count=1 + wipefs -a "$d" 2>/dev/null || true + + sg_dev=$(sg_map26 "$d") + if [ -n "$LVM_TEST_LOCK_TYPE_IDM" ]; then + echo "Cleanup IDM context for drive ${d} ($sg_dev)" + sg_raw -v -r 512 -o idm_tmp_data.bin "$sg_dev" \ + 88 00 01 00 00 00 00 20 FF 01 00 00 00 01 00 00 + sg_raw -v -s 512 -i idm_tmp_data.bin "$sg_dev" \ + 8E 00 FF 00 00 00 00 00 00 00 00 00 00 01 00 00 + rm idm_tmp_data.bin + fi +done + +#aux prepare_pvs $BLKDEVS_NUM 6400 + +for i in $(seq 1 ${#BLKDEVS[@]}); do + echo $i + d="dev$i" + vgcreate $SHARED TESTVG$i ${BLKDEVS[$(( i - 1 ))]} + + for j in {1..20}; do + lvcreate -a n --zero n -l 1 -n foo$j TESTVG$i + done +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + for j in {1..20}; do + lvchange -a ey TESTVG$i/foo$j + done +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + for j in {1..20}; do + lvchange -a n TESTVG$i/foo$j + done +done diff --git a/test/shell/multi_hosts_lv_hostb.sh b/test/shell/multi_hosts_lv_hostb.sh new file mode 100644 index 0000000..13efd1a --- /dev/null +++ b/test/shell/multi_hosts_lv_hostb.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This testing script is for multi-hosts testing, the paired scripts +# are: multi_hosts_lv_hosta.sh / multi_hosts_lv_hostb.sh +# +# On the host A: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_hosta.sh +# On the host B: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_hostb.sh + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_MULTI_HOST" ] && skip; + +IFS=',' read -r -a BLKDEVS <<< "$LVM_TEST_BACKING_DEVICE" + +for d in "${BLKDEVS[@]}"; do + aux extend_filter_LVMTEST "a|$d|" +done + +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +vgchange --lock-start + +for i in $(seq 1 ${#BLKDEVS[@]}); do + for j in {1..20}; do + lvchange -a sy TESTVG$i/foo$j + done +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + for j in {1..20}; do + lvchange -a ey TESTVG$i/foo$j + done +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + for j in {1..20}; do + lvchange -a n TESTVG$i/foo$j + done +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + vgremove -f TESTVG$i +done diff --git a/test/shell/multi_hosts_lv_sh_timeout_hosta.sh b/test/shell/multi_hosts_lv_sh_timeout_hosta.sh new file mode 100644 index 0000000..798f051 --- /dev/null +++ b/test/shell/multi_hosts_lv_sh_timeout_hosta.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This testing script is for multi-hosts testing. +# +# On the host A: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_sh_timeout_hosta.sh +# On the host B: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_sh_timeout_hostb.sh + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_MULTI_HOST" ] && skip; + +IFS=',' read -r -a BLKDEVS <<< "$LVM_TEST_BACKING_DEVICE" + +for d in "${BLKDEVS[@]}"; do + aux extend_filter_LVMTEST "a|$d|" +done + +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +for d in "${BLKDEVS[@]}"; do + dd if=/dev/zero of="$d" bs=32k count=1 + wipefs -a "$d" 2>/dev/null || true + + sg_dev=$(sg_map26 "$d") + if [ -n "$LVM_TEST_LOCK_TYPE_IDM" ]; then + echo "Cleanup IDM context for drive ${d} ($sg_dev)" + sg_raw -v -r 512 -o idm_tmp_data.bin "$sg_dev" \ + 88 00 01 00 00 00 00 20 FF 01 00 00 00 01 00 00 + sg_raw -v -s 512 -i idm_tmp_data.bin "$sg_dev" \ + 8E 00 FF 00 00 00 00 00 00 00 00 00 00 01 00 00 + rm idm_tmp_data.bin + fi +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + vgcreate $SHARED TESTVG$i ${BLKDEVS[$(( i - 1 ))]} + lvcreate -a n --zero n -l 1 -n foo TESTVG$i + lvchange -a sy TESTVG$i/foo +done + +for d in "${BLKDEVS[@]}"; do + drive_wwn=$(udevadm info "$d" | awk -F= '/E: ID_WWN=/ {print $2}') + for dev in /dev/*; do + if [ -b "$dev" ] && [[ ! "$dev" =~ [0-9] ]]; then + wwn=$(udevadm info "$dev" | awk -F= '/E: ID_WWN=/ {print $2}') + if [ "$wwn" = "$drive_wwn" ]; then + base_name="$(basename -- ${dev})" + drive_list+=("$base_name") + host_list+=( $(readlink "/sys/block/$base_name" | awk -F'/' '{print $6}') ) + fi + fi + done +done + +for d in "${drive_list[@]}"; do + [ -f "/sys/block/$d/device/delete" ] && echo 1 > "/sys/block/$d/device/delete" +done + +sleep 100 + +for i in $(seq 1 ${#BLKDEVS[@]}); do + check grep_lvmlockd_dump "S lvm_TESTVG$i kill_vg" + lvmlockctl --drop TESTVG$i +done + +# Rescan drives so can probe the deleted drives and join back them +for h in "${host_list[@]}"; do + [ -f "/sys/class/scsi_host/$h/scan" ] && echo "- - -" > "/sys/class/scsi_host/$h/scan" +done diff --git a/test/shell/multi_hosts_lv_sh_timeout_hostb.sh b/test/shell/multi_hosts_lv_sh_timeout_hostb.sh new file mode 100644 index 0000000..7aea223 --- /dev/null +++ b/test/shell/multi_hosts_lv_sh_timeout_hostb.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This testing script is for multi-hosts testing. +# +# On the host A: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_ex_timeout_hosta.sh +# On the host B: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_ex_timeout_hostb.sh + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_MULTI_HOST" ] && skip; + +IFS=',' read -r -a BLKDEVS <<< "$LVM_TEST_BACKING_DEVICE" + +for d in "${BLKDEVS[@]}"; do + aux extend_filter_LVMTEST "a|$d|" +done + +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +vgchange --lock-start + +vgdisplay + +for i in $(seq 1 ${#BLKDEVS[@]}); do + lvchange -a sy TESTVG$i/foo +done + +# Sleep for 70 seconds so the previous lease is expired +sleep 70 + +for i in $(seq 1 ${#BLKDEVS[@]}); do + lvchange -a ey TESTVG$i/foo + lvchange -a n TESTVG$i/foo +done + +for i in $(seq 1 ${#BLKDEVS[@]}); do + vgremove -f TESTVG$i +done diff --git a/test/shell/multi_hosts_vg_hosta.sh b/test/shell/multi_hosts_vg_hosta.sh new file mode 100644 index 0000000..1534749 --- /dev/null +++ b/test/shell/multi_hosts_vg_hosta.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This testing script is for multi-hosts testing, the paired scripts +# are: multi_hosts_vg_hosta.sh / multi_hosts_vg_hostb.sh +# +# On the host A: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_vg_hosta.sh +# On the host B: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_vg_hostb.sh + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_MULTI_HOST" ] && skip; + +IFS=',' read -r -a BLKDEVS <<< "$LVM_TEST_BACKING_DEVICE" + +for d in "${BLKDEVS[@]}"; do + aux extend_filter_LVMTEST "a|$d|" +done + +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +i=0 +for d in "${BLKDEVS[@]}"; do + echo $i + i=$((i+1)) + vgcreate $SHARED TESTVG$i $d + vgchange -a n TESTVG$i +done diff --git a/test/shell/multi_hosts_vg_hostb.sh b/test/shell/multi_hosts_vg_hostb.sh new file mode 100644 index 0000000..bab65b6 --- /dev/null +++ b/test/shell/multi_hosts_vg_hostb.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This testing script is for multi-hosts testing, the paired scripts +# are: multi_hosts_vg_hosta.sh / multi_hosts_vg_hostb.sh +# +# On the host A: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_vg_hosta.sh +# On the host B: +# make check_lvmlockd_idm \ +# LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \ +# LVM_TEST_MULTI_HOST=1 T=multi_hosts_vg_hostb.sh + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_MULTI_HOST" ] && skip; + +IFS=',' read -r -a BLKDEVS <<< "$LVM_TEST_BACKING_DEVICE" + +for d in "${BLKDEVS[@]}"; do + aux extend_filter_LVMTEST "a|$d|" +done + +aux lvmconf "devices/allow_changes_with_duplicate_pvs = 1" + +vgchange --lock-start + +i=0 +for d in "${BLKDEVS[@]}"; do + i=$((i+1)) + check vg_field TESTVG$i lv_count 0 +done + +i=0 +for d in "${BLKDEVS[@]}"; do + i=$((i+1)) + vgchange -a ey TESTVG$i + vgremove -ff TESTVG$i +done diff --git a/test/shell/multipath-config.sh b/test/shell/multipath-config.sh new file mode 100644 index 0000000..ffb7d63 --- /dev/null +++ b/test/shell/multipath-config.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='using multipath blacklist' + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +# FIXME: don't run this test by default because it destroys the +# local multipath config, the timing of multipath/dm/lvm interactions +# is fragile, and there's insufficient cleanup after a test fails. +skip + +systemctl stop multipathd +multipath -F || true +rm /etc/multipath/wwids || true +rmmod scsi_debug || true +rm /etc/multipath/conf.d/lvmtest.conf || true + +modprobe --dry-run scsi_debug || skip +multipath -l || skip +multipath -l | grep scsi_debug && skip +ls /etc/multipath/wwids && skip + +# Need to use /dev/mapper/mpath +aux lvmconf 'devices/dir = "/dev"' +aux lvmconf 'devices/scan = "/dev"' +# Could set filter to $MP and the component /dev/sd devs +aux lvmconf "devices/filter = [ \"a|.*|\" ]" +aux lvmconf "devices/global_filter = [ \"a|.*|\" ]" + +modprobe scsi_debug dev_size_mb=16 num_tgts=1 +sleep 2 + +# Get scsi device name created by scsi_debug. +# SD = sdh +# SD_DEV = /dev/sdh + +SD=$(grep -H scsi_debug /sys/block/sd*/device/model | cut -f4 -d /); +echo $SD +SD_DEV=/dev/$SD +echo $SD_DEV + +# if multipath claimed SD, then io will fail +#dd if=$SD_DEV of=/dev/null bs=4k count=1 iflag=direct +#dd if=/dev/zero of=$SD_DEV bs=4k count=1 oflag=direct + +# check if multipathd claimed the scsi dev when it appears and create mp dm device +sleep 2 +multipath -l +# create the mp dm device +multipath $SD_DEV + +# Get mpath device name created by multipath. +# MP = mpatha +# MP_DEV = /dev/maper/mpatha + +MP=$(multipath -l | grep scsi_debug | cut -f1 -d ' ') +echo $MP +MP_DEV=/dev/mapper/$MP +echo $MP_DEV + +dd if=$MP_DEV of=/dev/null bs=4k count=1 iflag=direct +dd if=/dev/zero of=$MP_DEV bs=4k count=1 oflag=direct + +# Get wwid for the mp and sd dev. +WWID=$(multipath -l $MP_DEV | head -1 | awk '{print $2}' | tr -d ')' | tr -d '(') +echo $WWID + +grep $WWID /etc/multipath/wwids + +pvcreate $MP_DEV +vgcreate $vg1 $MP_DEV + +not pvs $SD_DEV +pvs $MP_DEV + +# remove mpath dm device then check that SD_DEV is +# filtered based on /etc/multipath/wwids instead of +# based on sysfs holder +multipath -f $MP +sleep 2 +not pvs $SD_DEV +multipath $SD_DEV +sleep 2 +multipath -l | grep $SD + +# +# Add the wwid to the blacklist, then restart multipath +# so the sd dev should no longer be used by multipath, +# but the sd dev wwid is still in /etc/multipath/wwids. +# + +mkdir /etc/multipath/conf.d/ || true +rm -f /etc/multipath/conf.d/lvmtest.conf + +cat < "/etc/multipath/conf.d/lvmtest.conf" +blacklist { + wwid $WWID +} +EOF + +cat /etc/multipath/conf.d/lvmtest.conf + +multipath -r +sleep 2 + +grep $WWID /etc/multipath/wwids + +multipath -l |tee out +not grep $SD out +not grep $MP out +not grep $WWID out + +not pvs $MP_DEV +pvs $SD_DEV +vgs $vg1 + +# +# Add the wwid to the blacklist_exceptions, in addition +# to the blacklist, then restart multipath so the +# sd dev should again be used by multipath. +# + +rm -f /etc/multipath/conf.d/lvmtest.conf + +cat < "/etc/multipath/conf.d/lvmtest.conf" +blacklist { +wwid $WWID +} +blacklist_exceptions { +wwid $WWID +} +EOF + +cat /etc/multipath/conf.d/lvmtest.conf + +multipath -r +sleep 2 + +grep $WWID /etc/multipath/wwids + +multipath -l |tee out +grep $SD out +grep $MP out +grep $WWID out + +pvs $MP_DEV +not pvs $SD_DEV +vgs $vg1 +lvs $vg1 + +sleep 2 +vgremove -ff $vg1 +sleep 2 +multipath -f $MP +rm /etc/multipath/conf.d/lvmtest.conf +rm /etc/multipath/wwids +sleep 1 +rmmod scsi_debug diff --git a/test/shell/name-mangling.sh b/test/shell/name-mangling.sh index 5b92e60..4287939 100644 --- a/test/shell/name-mangling.sh +++ b/test/shell/name-mangling.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,17 +8,20 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This test is not using any lvm command +# so skip duplicate CLMVD and lvmetad test -. lib/test +SKIP_WITH_LVMPOLLD=1 -name_prefix=$RANDOM +. lib/inittest CHARACTER_WHITELIST="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#+-.:=@_" FAIL_MIXED_STR="contains mixed mangled and unmangled characters" FAIL_MULTI_STR="seems to be mangled more than once" FAIL_BLACK_STR="should be mangled but it contains blacklisted characters" -CORRECT_FORM_STR="name already in correct form" +CORRECT_FORM_STR="already in correct form" RENAMING_STR="renaming to" function create_dm_dev() @@ -34,7 +38,7 @@ function create_dm_dev() verify_udev="" fi - dmsetup create "${name_prefix}$name" $verify_udev --manglename $mode --table "0 1 zero" + aux dmsetup create "${PREFIX}$name" $verify_udev --manglename $mode --table "0 1 zero" } function remove_dm_dev() @@ -48,7 +52,7 @@ function remove_dm_dev() verify_udev="" fi - dmsetup remove $verify_udev --manglename $mode "${name_prefix}$name" + aux dmsetup remove $verify_udev --manglename $mode "${PREFIX}$name" } function check_create_and_remove() @@ -64,19 +68,19 @@ function check_create_and_remove() verify_udev="" fi - dmsetup create "${name_prefix}$input_name" $verify_udev --manglename $mode --table "0 1 zero" 2>err && \ - test -b "$DM_DEV_DIR/mapper/${name_prefix}$dm_name" && \ - dmsetup remove "${name_prefix}$input_name" $verify_udev --manglename $mode || r=1 + aux dmsetup create "${PREFIX}$input_name" $verify_udev --manglename $mode --table "0 1 zero" 2>err && \ + test -b "$DM_DEV_DIR/mapper/${PREFIX}$dm_name" && \ + aux dmsetup remove "${PREFIX}$input_name" $verify_udev --manglename $mode || r=1 - if [ $dm_name = "FAIL_MIXED" ]; then + if [ "$dm_name" = "FAIL_MIXED" ]; then r=0 - grep "$FAILED_MIXED_STR" err || r=1 - elif [ $dm_name = "FAIL_MULTI" ]; then + grep "$FAIL_MIXED_STR" err || r=1 + elif [ "$dm_name" = "FAIL_MULTI" ]; then r=0 - grep "$FAILED_MULTI_STR" err || r=1 - elif [ $dm_name = "FAIL_BLACK" ]; then + grep "$FAIL_MULTI_STR" err || r=1 + elif [ "$dm_name" = "FAIL_BLACK" ]; then r=0 - grep "$FAILED_BLACK_STR" err || r=1 + grep "$FAIL_BLACK_STR" err || r=1 fi return $r @@ -85,11 +89,11 @@ function check_create_and_remove() function check_dm_field() { local mode=$1 - local dm_name="$2" + local dm_name=$2 local field=$3 - local expected="$4" + local expected=$4 - value=$(dmsetup info --rows --noheadings --manglename $mode -c -o $field "${DM_DEV_DIR}/mapper/${name_prefix}$dm_name" 2> err || true) + value=$(dmsetup info --rows --noheadings --manglename $mode -c -o $field "${DM_DEV_DIR}/mapper/${PREFIX}$dm_name" 2> err || true) if [ "$expected" = "FAIL_MIXED" ]; then grep "$FAIL_MIXED_STR" err @@ -98,19 +102,19 @@ function check_dm_field() elif [ "$expected" = "FAIL_BLACK" ]; then grep "$FAIL_BLACK_STR" err else - test "$value" = "${name_prefix}$expected" + test "$value" = "${PREFIX}$expected" fi } function check_expected_names() { local mode=$1 - local dm_name="$2" + local dm_name=$2 local r=0 create_dm_dev none "$dm_name" - test -b "$DM_DEV_DIR/mapper/${name_prefix}$dm_name" && \ + test -b "$DM_DEV_DIR/mapper/${PREFIX}$dm_name" && \ check_dm_field none "$dm_name" name "$dm_name" && \ check_dm_field $mode "$dm_name" name "$3" && \ check_dm_field $mode "$dm_name" mangled_name "$4" && \ @@ -124,14 +128,14 @@ function check_expected_names() function check_mangle_cmd() { local mode=$1 - local dm_name="$2" - local expected="$3" + local dm_name=$2 + local expected=$3 local rename_expected=0 local r=0 create_dm_dev none "$dm_name" - dmsetup mangle --manglename $mode "${name_prefix}$dm_name" 1>out 2>err || true; + dmsetup mangle --manglename $mode --verifyudev "${PREFIX}$dm_name" 1>out 2>err || true; if [ "$expected" = "OK" ]; then grep "$CORRECT_FORM_STR" out || r=1 @@ -141,17 +145,40 @@ function check_mangle_cmd() grep "$FAIL_MULTI_STR" err || r=1 else rename_expected=1 - grep -F "$RENAMING_STR ${name_prefix}$expected" out || r=1 + if grep -F "$RENAMING_STR ${PREFIX}$expected" out; then + # Check the old node is really renamed. + test -b "$DM_DEV_DIR/mapper/${PREFIX}$dm_name" && r=1 + # FIXME: when renaming to mode=none with udev, udev will + # remove the old_node, but fails to properly rename + # to new_node. The libdevmapper code tries to call + # rename(old_node,new_node), but that won't do anything + # since the old node is already removed by udev. + # For example renaming 'a\x20b' to 'a b': + # - udev removes 'a\x20b' + # - udev creates 'a' and 'b' (since it considers the ' ' as a delimiter) + # - libdevmapper checks udev has done the rename properly + # - libdevmapper calls stat(new_node) and it does not see it + # - libdevmapper calls rename(old_node,new_node) + # - the rename is a NOP since the old_node does not exist anymore + # + # Remove this condition once the problem is fixed in libdevmapper. + # + if [ "$mode" != "none" ]; then + test -b "$DM_DEV_DIR/mapper/${PREFIX}$expected" || r=1 + fi + else + r=1 + fi fi - if [ $r = 0 -a $rename_expected = 1 ]; then + if [ "$r" = 0 ] && [ "$rename_expected" = 1 ]; then # successfuly renamed to expected name remove_dm_dev none "$expected" elif [ $r = 1 ]; then # failed to rename to expected or renamed when it should not - find the new name new_name=$(sed -e "s/.*: $RENAMING_STR //g" out) # try to remove any of the form - falling back to less probable error scenario - dmsetup remove --verifyudev --manglename none "$new_name" || \ + remove_dm_dev none "$new_name" || \ remove_dm_dev none "$dm_name" || remove_dm_dev none "$expected" else # successfuly done nothing @@ -164,11 +191,12 @@ function check_mangle_cmd() # check dmsetup can process path where the last component is not equal dm name (rhbz #797322) r=0 create_dm_dev auto "abc" -ln -s ${DM_DEV_DIR}/mapper/${name_prefix}abc ${DM_DEV_DIR}/${name_prefix}xyz -dmsetup status ${DM_DEV_DIR}/${name_prefix}xyz || r=1 +ln -s "$DM_DEV_DIR/mapper/${PREFIX}abc" "$DM_DEV_DIR/${PREFIX}xyz" +aux dmsetup status "$DM_DEV_DIR/${PREFIX}xyz" || r=1 +rm -f "$DM_DEV_DIR/${PREFIX}xyz" remove_dm_dev auto "abc" -if [ r = 1 ]; then - exit 1 +if [ "$r" = 1 ]; then + return "$r" fi ### ALL WHITELISTED CHARACTERS ### diff --git a/test/shell/nomda-missing.sh b/test/shell/nomda-missing.sh index 2cf759e..1899f03 100644 --- a/test/shell/nomda-missing.sh +++ b/test/shell/nomda-missing.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # @@ -8,28 +8,31 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_devs 4 pvcreate "$dev1" "$dev2" pvcreate --metadatacopies 0 "$dev3" "$dev4" -vgcreate -c n $vg "$dev1" "$dev2" "$dev3" "$dev4" +vgcreate $SHARED $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 -aey -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" +lvcreate -aey -l1 --type mirror -m1 -n mirror12 --mirrorlog core $vg "$dev1" "$dev2" +lvcreate -aey -l1 --type mirror -m1 -n mirror123 $vg "$dev1" "$dev2" "$dev3" vgchange -a n $vg aux disable_dev "$dev1" -not vgchange -a y $vg +not vgchange -aey $vg not vgck $vg check inactive $vg linear1 @@ -43,7 +46,7 @@ check inactive $vg mirror123 vgchange -a n $vg aux enable_dev "$dev1" aux disable_dev "$dev2" -not vgchange -a y $vg +not vgchange -aey $vg not vgck $vg check active $vg linear1 @@ -57,7 +60,7 @@ check inactive $vg mirror123 vgchange -a n $vg aux enable_dev "$dev2" aux disable_dev "$dev3" -not vgchange -a y $vg +not vgchange -aey $vg not vgck $vg check active $vg origin1 @@ -71,7 +74,9 @@ check active $vg mirror12 vgchange -a n $vg aux enable_dev "$dev3" aux disable_dev "$dev4" -vgchange -a y $vg +dmsetup table +dmsetup info -c +vgchange -aey $vg not vgck $vg check active $vg origin1 @@ -81,3 +86,5 @@ check active $vg linear2 check active $vg linear12 check active $vg mirror12 check active $vg mirror123 + +vgremove -ff $vg diff --git a/test/shell/nomda-restoremissing.sh b/test/shell/nomda-restoremissing.sh new file mode 100644 index 0000000..d9c544b --- /dev/null +++ b/test/shell/nomda-restoremissing.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 3 + +pvchange --metadataignore y "$dev1" + +lvcreate -aey --type mirror -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 +aux disable_dev "$dev1" +lvremove $vg/mirror +not vgck $vg 2>&1 | tee log +grep "missing 1 physical volume" log +not lvcreate -aey --type mirror -m 1 -l 1 -n mirror $vg # write operations fail +aux enable_dev "$dev1" +# Old versions would automatically clear MISSING_PV on a PV that had no mda, +# but this made no sense; the existence of an mda means nothing for the +# validity of the data on the device. I suspect that at some point in the +# past, the MISSING_PV flag was used to decide if metadata could be used +# from the device, so the flag could be cleared on a PV with no mda. +# These days lvm knows when to ignore outdated metadata. +# MISSING_PV probably has little to no value for determining valid data either, +# so it's likely that we'll begin to automatically clear MISSING_PV in the +# future (but it will have nothing to do with having mdas.) +not lvcreate -aey --type mirror -m 1 -l 1 -n mirror $vg +vgextend --restoremissing $vg "$dev1" +lvcreate -aey --type mirror -m 1 -l 1 -n mirror $vg +vgck $vg + +vgremove -ff $vg diff --git a/test/shell/open-file-limit.sh b/test/shell/open-file-limit.sh new file mode 100644 index 0000000..8e04705 --- /dev/null +++ b/test/shell/open-file-limit.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test scan_lvs config setting + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +prlimit -h || skip + +aux lvmconf 'devices/pv_min_size = 1024' + +aux prepare_devs 200 1 + +for i in $(seq 1 200); do + pvcreate "$DM_DEV_DIR/mapper/${PREFIX}pv$i" +done + +pvs > out +test "$(grep -c pv out)" -eq 200 + +# Set the soft limit to 100 fd's when 200 PVs need to be open. +# This requires lvm to increase its soft limit in order to +# process all the PVs. +# Test this with and without udev providing device lists. + +aux lvmconf 'devices/obtain_device_list_from_udev = 0' + +prlimit --nofile=100: pvs > out + +test "$(grep -c pv out)" -eq 200 + +aux lvmconf 'devices/obtain_device_list_from_udev = 1' + +prlimit --nofile=100: pvs > out + +test "$(grep -c pv out)" -eq 200 + diff --git a/test/shell/orphan-ondisk.sh b/test/shell/orphan-ondisk.sh new file mode 100644 index 0000000..507b482 --- /dev/null +++ b/test/shell/orphan-ondisk.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 2 +vgreduce $vg "$dev1" 2>&1 | not grep -i 'parse error' diff --git a/test/shell/outdated-pv.sh b/test/shell/outdated-pv.sh new file mode 100644 index 0000000..6a361d3 --- /dev/null +++ b/test/shell/outdated-pv.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 3 + +# +# Test handling of "outdated PV" which occurs when a PV goes missing +# from a VG, and while it's missing the PV is removed from the VG. +# Then the PV reappears with the old VG metadata that shows it is a +# member. That outdated metadata needs to be cleared. +# + +lvcreate -n $lv1 -l1 -an $vg "$dev1" +lvcreate -n $lv2 -l1 -an $vg "$dev1" + +aux disable_dev "$dev2" + +vgreduce --removemissing $vg + +pvs + +aux enable_dev "$dev2" + +pvs 2>&1 | tee out +grep "outdated" out + +not pvs "$dev2" + +# The VG can still be used with the outdated PV around +lvcreate -n $lv3 -l1 $vg +lvchange -ay $vg +lvs $vg +lvchange -an $vg + +# Clears the outdated PV +vgck --updatemetadata $vg + +pvs 2>&1 | tee out +not grep "outdated" out + +# The PV is no longer in the VG +pvs "$dev2" | tee out +not grep "$vg" out + +# The cleared PV can be added back to the VG +vgextend $vg "$dev2" + +pvs "$dev2" | tee out +grep "$vg" out + +vgremove -ff $vg diff --git a/test/shell/pe-align.sh b/test/shell/pe-align.sh new file mode 100644 index 0000000..7015108 --- /dev/null +++ b/test/shell/pe-align.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test pe alignment and metadata sizes' +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 1 + +# values depend on page size 4K + +# In order of strength: +# --dataalignmentoffset (modifies all below) +# --dataalignment (overrides all below) +# devices/data_alignment (overrides all below) +# devices/data_alignment_offset_detection (overrides all below) +# devices/md_chunk_alignment (overrides all below) +# devices/default_data_alignment + +pvcreate "$dev1" +check pv_field "$dev1" pe_start 1.00m +check pv_field "$dev1" mda_size 1020.00k +pvremove "$dev1" + +# default align at 1m is effective even with smaller requested metadata +pvcreate --metadatasize 100k "$dev1" +check pv_field "$dev1" pe_start 1.00m +check pv_field "$dev1" mda_size 1020.00k +pvremove "$dev1" + +# default first pe doesn't depend on on these two settings +pvcreate --config 'devices {default_data_alignment=0 data_alignment=0}' "$dev1" +check pv_field "$dev1" pe_start 1.00m +check pv_field "$dev1" mda_size 1020.00k +pvremove "$dev1" + +# same as previous +pvcreate --config 'devices {default_data_alignment=1 data_alignment=0}' "$dev1" +check pv_field "$dev1" pe_start 1.00m +check pv_field "$dev1" mda_size 1020.00k +pvremove "$dev1" + +# same as previous +pvcreate --config 'devices {default_data_alignment=0 data_alignment=1024}' "$dev1" +check pv_field "$dev1" pe_start 1.00m +check pv_field "$dev1" mda_size 1020.00k +pvremove "$dev1" + +# same as previous +pvcreate --config 'devices {default_data_alignment=1 data_alignment=1024}' "$dev1" +check pv_field "$dev1" pe_start 1.00m +check pv_field "$dev1" mda_size 1020.00k +pvremove "$dev1" + +# combine above +pvcreate --metadatasize 100k --config 'devices {default_data_alignment=0 data_alignment=0}' "$dev1" +check pv_field "$dev1" pe_start 1.00m +check pv_field "$dev1" mda_size 1020.00k +pvremove "$dev1" + +pvcreate --metadatasize 2048k "$dev1" +check pv_field "$dev1" pe_start 3072.00k --units k +check pv_field "$dev1" mda_size 3068.00k --units k +pvremove "$dev1" + +pvcreate --metadatasize 2044k "$dev1" +check pv_field "$dev1" pe_start 2048.00k --units k +check pv_field "$dev1" mda_size 2044.00k --units k +pvremove "$dev1" + +pvcreate --metadatasize 2048k --config 'devices {default_data_alignment=2}' "$dev1" +check pv_field "$dev1" pe_start 4.00m +check pv_field "$dev1" mda_size 4092.00k --units k +pvremove "$dev1" + +pvcreate --metadatasize 100k --config 'devices {default_data_alignment=2}' "$dev1" +check pv_field "$dev1" pe_start 2048.00k --units k +check pv_field "$dev1" mda_size 2044.00k --units k +pvremove "$dev1" + +pvcreate --metadatasize 2048k --dataalignment 128k "$dev1" +check pv_field "$dev1" pe_start 2176.00k --units k +check pv_field "$dev1" mda_size 2172.00k --units k +pvremove "$dev1" + +pvcreate --metadatasize 2048k --dataalignment 128k --dataalignmentoffset 2k "$dev1" +check pv_field "$dev1" pe_start 2178.00k --units k +check pv_field "$dev1" mda_size 2174.00k --units k +pvremove "$dev1" + +pvcreate --metadatasize 2048k --dataalignment 128k --config 'devices {default_data_alignment=0}' "$dev1" +check pv_field "$dev1" pe_start 2176.00k --units k +check pv_field "$dev1" mda_size 2172.00k --units k +pvremove "$dev1" + +pvcreate --metadatasize 2048k --dataalignment 128k --config 'devices {default_data_alignment=2}' "$dev1" +check pv_field "$dev1" pe_start 2176.00k --units k +check pv_field "$dev1" mda_size 2172.00k --units k +pvremove "$dev1" + +pvcreate --metadatasize 2048k --config 'devices {default_data_alignment=2 data_alignment=128}' "$dev1" +check pv_field "$dev1" pe_start 2176.00k --units k +check pv_field "$dev1" mda_size 2172.00k --units k +pvremove "$dev1" + +pvcreate --bootloaderareasize 256k "$dev1" +check pv_field "$dev1" mda_size 1020.00k --units k +check pv_field "$dev1" ba_start 1024.00k --units k +check pv_field "$dev1" ba_size 1024.00k --units k +check pv_field "$dev1" pe_start 2048.00k --units k +pvremove "$dev1" + +pvcreate --dataalignment 128k --bootloaderareasize 256k "$dev1" +check pv_field "$dev1" mda_size 1020.00k --units k +check pv_field "$dev1" ba_start 1024.00k --units k +check pv_field "$dev1" ba_size 256.00k --units k +check pv_field "$dev1" pe_start 1280.00k --units k +pvremove "$dev1" + +pvcreate --dataalignment 128k --metadatasize 256k "$dev1" +check pv_field "$dev1" mda_size 380.00k --units k +check pv_field "$dev1" ba_start 0k --units k +check pv_field "$dev1" ba_size 0k --units k +check pv_field "$dev1" pe_start 384.00k --units k +pvremove "$dev1" + +pvcreate --dataalignment 128k --metadatasize 256k --bootloaderareasize 256k "$dev1" +check pv_field "$dev1" mda_size 380.00k --units k +check pv_field "$dev1" ba_start 384.00k --units k +check pv_field "$dev1" ba_size 256.00k --units k +check pv_field "$dev1" pe_start 640.00k --units k +pvremove "$dev1" diff --git a/test/shell/pool-labels.sh b/test/shell/pool-labels.sh index 9d3fa03..88978e8 100644 --- a/test/shell/pool-labels.sh +++ b/test/shell/pool-labels.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2007 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,9 +8,11 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest env printf "" || skip # skip if printf is not available @@ -21,7 +24,6 @@ create_pool_label_() # 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 - aux notify_lvmetad "$2" } @@ -30,13 +32,10 @@ aux prepare_devs 2 create_pool_label_ 0 "$dev1" create_pool_label_ 1 "$dev2" +# verify that lvm will ignore and not use a gfs-pool device + +not pvs "$dev1" + # 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 }' -aux 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/shell/process-each-duplicate-pvs.sh b/test/shell/process-each-duplicate-pvs.sh new file mode 100644 index 0000000..f3063ab --- /dev/null +++ b/test/shell/process-each-duplicate-pvs.sh @@ -0,0 +1,528 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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. + +test_description='Test duplicate PVs' + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_CLVMD=1 + +# This test should work with real device ids (not devnames). +# When PVs are being overwritten by the test, the devices file is +# excluding them since with idtype=devname the devices file falls +# back to including devs based on PVIDs in the devices file, +# but the 'dd' is clobbering the PVIDs so those devs aren't included +# so the 'pvs' commands below don't report them. +# In general this is better behavior, but needs to be tested +# with proper device ids. +SKIP_WITH_DEVICES_FILE=1 + +. lib/inittest + +aux prepare_devs 6 16 + +# The LV-using-PV tests (DEV_USED_FOR_LV, where a PV is +# preferred if an active LV is using it) depend on sysfs +# info that is not available in RHEL5 kernels. +aux driver_at_least 4 15 || skip + +aux lvmconf 'devices/allow_changes_with_duplicate_pvs = 0' + +pvcreate "$dev1" +pvcreate "$dev2" +vgcreate $SHARED $vg1 "$dev1" +vgcreate $SHARED $vg2 "$dev2" +pvresize --setphysicalvolumesize 8m -y "$dev2" +lvcreate -an -l1 -n $lv1 $vg1 + +# Both devs are shown and used by the VG + +pvs 2>&1 | tee out + +grep "$dev1" out +grep "$dev2" out +grep "$dev1" out | grep $vg1 +grep "$dev2" out | grep $vg2 +check pv_field "$dev1" pv_allocatable "allocatable" +check pv_field "$dev2" pv_allocatable "allocatable" +not grep WARNING out + +UUID1=$(get pv_field "$dev1" uuid) +UUID2=$(get pv_field "$dev2" uuid) + +SIZE1=$(get pv_field "$dev1" dev_size) +SIZE2=$(get pv_field "$dev2" dev_size) + +MINOR1=$(get pv_field "$dev1" minor) +MINOR2=$(get pv_field "$dev2" minor) + +check pv_field "$dev1" dev_size "$SIZE1" +check pv_field "$dev2" dev_size "$SIZE2" + +# Copy dev1 over dev2. +dd if="$dev1" of="$dev2" bs=1M iflag=direct oflag=direct,sync +#pvscan --cache + +# The single preferred dev is shown from 'pvs'. +pvs -o+uuid,duplicate 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +# Don't know yet if dev1 or dev2 is preferred, so count just one is. +test "$(grep -c "$vg1" main)" -eq 1 +test "$(grep -c "$UUID1" main)" -eq 1 +not grep duplicate main +not grep $vg2 main +not grep $UUID2 main + +grep "Not using device" warn +grep "prefers device" warn + +# Find which is the preferred dev and which is the duplicate. +PV=$(pvs --noheadings -o name -S uuid="$UUID1" | xargs) +if [ "$PV" = "$dev1" ]; then + DUP=$dev2 +else + DUP=$dev1 +fi + +echo "PV is $PV" +echo "DUP is $DUP" + +grep "$PV" main +not grep "$DUP" main + +# Repeat above checking preferred/dup in output +pvs 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$PV" main +not grep "$DUP" main + +# The duplicate dev is included in 'pvs -a' +pvs -a -o+uuid,duplicate 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev1" main +grep "$dev2" main +grep $PV main +grep $DUP main +test "$(grep -c duplicate main)" -eq 1 +grep $DUP main | grep duplicate +not grep $vg2 main +not grep $UUID2 main +grep "$dev1" main | grep $vg1 +grep "$dev2" main | grep $vg1 +grep "$dev1" main | grep $UUID1 +grep "$dev2" main | grep $UUID1 + +grep "Not using device" warn +grep "prefers device" warn + +# +# Passing a dev name arg always includes that dev. +# + +pvs -o+uuid "$dev1" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev1" main +not grep "$dev2" main +grep "$UUID1" main +grep "$vg1" main +grep "Not using device" warn +grep "prefers device" warn + +pvs -o+uuid "$dev2" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev2" main +not grep "$dev1" main +grep "$UUID1" main +grep "$vg1" main +grep "Not using device" warn +grep "prefers device" warn + +pvs -o+uuid,duplicate "$dev1" "$dev2" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev1" main +grep "$dev2" main +grep "$dev1" main | grep $vg1 +grep "$dev2" main | grep $vg1 +grep "$dev1" main | grep $UUID1 +grep "$dev2" main | grep $UUID1 +test "$(grep -c duplicate main)" -eq 1 +grep $DUP main | grep duplicate + +# +# Test specific report fields for each dev. +# + +pvs --noheadings -o vg_name,vg_uuid "$dev1" 2>&1 | tee out1 +pvs --noheadings -o vg_name,vg_uuid "$dev2" 2>&1 | tee out2 + +grep -v WARNING out1 > main1 || true +grep -v WARNING out2 > main2 || true +diff main1 main2 +rm out1 out2 main1 main2 || true + +check pv_field "$dev1" pv_in_use "used" +check pv_field "$dev2" pv_in_use "used" + +check pv_field "$PV" pv_allocatable "allocatable" +check pv_field "$DUP" pv_allocatable "" + +check pv_field "$PV" pv_duplicate "" +check pv_field "$DUP" pv_duplicate "duplicate" + +pvs --noheadings -o name,pv_allocatable "$dev1" "$dev2" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$PV" main +grep "$DUP" main +grep "$dev1" main +grep "$dev2" main +test "$(grep -c allocatable main)" -eq 1 + +pvs --noheadings -o name,pv_duplicate "$dev1" "$dev2" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$PV" main +grep "$DUP" main +grep "$dev1" main +grep "$dev2" main +test "$(grep -c duplicate main)" -eq 1 + +# +# A filter can be used to show only one. +# + +pvs --config "devices { filter=[ \"a|$dev2|\", \"r|.*|\" ] }" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +not grep "$dev1" main +grep "$dev2" main + +not grep "Not using device" warn +not grep "prefers device" warn + + +pvs --config "devices { filter=[ \"a|$dev1|\", \"r|.*|\"] }" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev1" main +not grep "$dev2" main + +not grep "Not using device" warn +not grep "prefers device" warn + +# PV size and minor is still reported correctly for each. + +check pv_field "$dev1" dev_size "$SIZE1" +check pv_field "$dev2" dev_size "$SIZE2" + +check pv_field "$dev1" minor "$MINOR1" +check pv_field "$dev2" minor "$MINOR2" + +# With allow_changes_with_duplicate_pvs=0, a VG with duplicate devs +# cannot be modified or activated. + +not lvcreate -an -l1 -n $lv2 $vg1 +not lvremove $vg1/$lv1 +not lvchange -ay $vg1/$lv1 +not vgremove $vg1 + + +# With allow_changes_with_duplicate_pvs=1, changes above are permitted. + +aux lvmconf 'devices/allow_changes_with_duplicate_pvs = 1' + +lvcreate -an -l1 -n $lv2 $vg1 +lvremove $vg1/$lv1 +lvchange -ay $vg1/$lv2 +lvchange -an $vg1/$lv2 +lvremove $vg1/$lv2 +vgremove -f $vg1 +pvremove -ff -y "$dev1" +pvremove -ff -y "$dev2" + + +# dev3 and dev4 are copies, orphans + +pvcreate "$dev3" +pvcreate "$dev4" +pvresize --setphysicalvolumesize 8m -y "$dev4" + +UUID3=$(get pv_field "$dev3" uuid) +UUID4=$(get pv_field "$dev4" uuid) + +SIZE3=$(get pv_field "$dev3" dev_size) +SIZE4=$(get pv_field "$dev4" dev_size) + +check pv_field "$dev3" dev_size "$SIZE3" +check pv_field "$dev4" dev_size "$SIZE4" + +pvs 2>&1 | tee out + +grep "$dev3" out +grep "$dev4" out + +dd if="$dev3" of="$dev4" bs=1M iflag=direct oflag=direct,sync +#pvscan --cache + +# One appears with 'pvs' + +pvs -o+uuid 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +test "$(grep -c "$UUID3" main)" -eq 1 +not grep "$UUID4" main + +grep "Not using device" warn +grep "prefers device" warn + +# Both appear with 'pvs -a' + +pvs -a -o+uuid 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +test "$(grep -c "$UUID3" main)" -eq 2 + +grep "$dev3" main +grep "$dev4" main + +grep $UUID3 main +not grep $UUID4 main + +grep "Not using device" warn +grep "prefers device" warn + +# Show each dev individually and both together + +pvs -o+uuid "$dev3" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev3" main +not grep "$dev4" main + +grep "Not using device" warn +grep "prefers device" warn + +pvs -o+uuid "$dev4" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +not grep "$dev3" main +grep "$dev4" main + +grep "Not using device" warn +grep "prefers device" warn + +pvs -o+uuid "$dev3" "$dev4" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev3" main +grep "$dev4" main + +grep "Not using device" warn +grep "prefers device" warn + +# Same sizes shown. + +check pv_field "$dev3" dev_size "$SIZE3" +check pv_field "$dev4" dev_size "$SIZE4" + +# Verify that devs being used by an active LV are +# preferred over duplicates that are not used by an LV. + +aux clear_devs "$dev3" "$dev4" +#pvscan --cache + +# The previous steps prevent us from nicely cleaning up +# the vg lockspace in lvmlockd, so just restart it; +# what follows could also just be split into a separate test. +if test -n "$LVM_TEST_LVMLOCKD_TEST" ; then + killall -9 lvmlockd + sleep 2 + aux prepare_lvmlockd +fi + +vgcreate $SHARED "$vg2" "$dev3" "$dev4" +lvcreate -l1 -n $lv1 $vg2 "$dev3" +lvcreate -l1 -n $lv2 $vg2 "$dev4" + +dd if="$dev3" of="$dev5" bs=1M iflag=direct oflag=direct,sync +dd if="$dev4" of="$dev6" bs=1M iflag=direct oflag=direct,sync +# dev5/dev6 not pvs so dd'ing pv onto them causes invalid hints +# that won't be detected, so 5/6 won't be scanned unless we +# force hint recreation +pvscan --cache + +pvs -o+uuid,duplicate 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev3" main +grep "$dev4" main +not grep duplicate main +check pv_field "$dev3" pv_duplicate "" +check pv_field "$dev4" pv_duplicate "" +check pv_field "$dev5" pv_duplicate "duplicate" +check pv_field "$dev6" pv_duplicate "duplicate" + +grep "prefers device $dev3" warn +grep "prefers device $dev4" warn +not grep "prefers device $dev5" warn +not grep "prefers device $dev6" warn + +pvs -a -o+uuid,duplicate 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +test "$(grep -c duplicate main)" -eq 2 +grep "$dev3" main +grep "$dev4" main +grep "$dev5" main +grep "$dev6" main + +grep "prefers device $dev3" warn +grep "prefers device $dev4" warn +not grep "prefers device $dev5" warn +not grep "prefers device $dev6" warn + +pvs -o+uuid,duplicate "$dev3" "$dev4" "$dev5" "$dev6" 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +test "$(grep -c duplicate main)" -eq 2 +grep "$dev3" main +grep "$dev4" main +grep "$dev5" main +grep "$dev6" main + +grep "prefers device $dev3" warn +grep "prefers device $dev4" warn +not grep "prefers device $dev5" warn +not grep "prefers device $dev6" warn + + +dd if=/dev/zero of="$dev5" bs=1M oflag=direct,sync || true +dd if=/dev/zero of="$dev6" bs=1M oflag=direct,sync || true +#pvscan --cache + +lvremove -y $vg2/$lv1 +lvremove -y $vg2/$lv2 +vgremove $vg2 +pvremove -ff -y "$dev3" +pvremove -ff -y "$dev4" + +dd if=/dev/zero of="$dev3" bs=1M oflag=direct,sync || true +dd if=/dev/zero of="$dev4" bs=1M oflag=direct,sync || true +#pvscan --cache + +# Reverse devs in the previous in case dev3/dev4 would be +# preferred even without an active LV using them. + +vgcreate $SHARED $vg2 "$dev5" "$dev6" +lvcreate -l1 -n $lv1 $vg2 "$dev5" +lvcreate -l1 -n $lv2 $vg2 "$dev6" + +dd if="$dev5" of="$dev3" bs=1M iflag=direct oflag=direct,sync +dd if="$dev6" of="$dev4" bs=1M iflag=direct oflag=direct,sync +# dev3/dev4 are not pvs (zeroed above) so dd'ing pv onto them causes +# invalid hints that won't be detected, so 3/4 won't be scanned +# unless we force hint recreation +pvscan --cache + +pvs -o+uuid,duplicate 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +grep "$dev5" main +grep "$dev6" main +not grep duplicate main +check pv_field "$dev5" pv_duplicate "" +check pv_field "$dev6" pv_duplicate "" +check pv_field "$dev3" pv_duplicate "duplicate" +check pv_field "$dev4" pv_duplicate "duplicate" + +pvs -a -o+uuid,duplicate 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +test "$(grep -c duplicate main)" -eq 2 +grep "$dev3" main +grep "$dev4" main +grep "$dev5" main +grep "$dev6" main + +grep "prefers device $dev5" warn +grep "prefers device $dev6" warn +not grep "prefers device $dev3" warn +not grep "prefers device $dev4" warn + +dd if=/dev/zero of="$dev3" bs=1M oflag=direct,sync || true +dd if=/dev/zero of="$dev4" bs=1M oflag=direct,sync || true +#pvscan --cache + +lvremove -y $vg2/$lv1 +lvremove -y $vg2/$lv2 +vgremove $vg2 diff --git a/test/shell/process-each-lv.sh b/test/shell/process-each-lv.sh new file mode 100644 index 0000000..f28988c --- /dev/null +++ b/test/shell/process-each-lv.sh @@ -0,0 +1,659 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Exercise toollib process_each_lv' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + + +aux prepare_devs 10 + +# +# process_each_lv is used by a number of lv commands: +# lvconvert lv (none is error) +# lvchange vg|lv (none is error) +# lvremove vg|lv (none is error) +# lvdisplay [vg|lv] (none is all) +# vgmknodes [vg|lv] (none is all) +# lvs [vg|lv] (none is all) +# lvscan (none is all) +# +# (lv can also be a tag matching an lv tag, and +# vg can also be a tag matching a vg tag.) +# +# The logic in process_each_vl is mainly related to +# selecting which vgs/lvs to process. +# + +# +# test lvremove vg|lv names +# + +prepare_vgs_() { + # set up vgs/lvs that we will remove + vgcreate $SHARED $vg1 "$dev1" "$dev2" + vgcreate $SHARED $vg2 "$dev3" "$dev4" + vgcreate $SHARED $vg3 "$dev5" "$dev6" + vgcreate $SHARED $vg4 "$dev7" "$dev8" + vgcreate $SHARED $vg5 "$dev9" "$dev10" + lvcreate -Zn -an -l 2 -n $lv1 $vg1 + lvcreate -Zn -an -l 2 -n $lv1 $vg2 + lvcreate -Zn -an -l 2 -n $lv2 $vg2 + lvcreate -Zn -an -l 2 -n $lv1 $vg3 + lvcreate -Zn -an -l 2 -n $lv2 $vg3 + lvcreate -Zn -an -l 2 -n $lv3 $vg3 + lvcreate -Zn -an -l 2 -n $lv1 $vg5 + lvcreate -Zn -an -l 2 -n $lv2 $vg5 + lvcreate -Zn -an -l 2 -n $lv3 $vg5 + lvcreate -Zn -an -l 2 -n $lv4 $vg5 + lvcreate -Zn -an -l 2 -n $lv5 $vg5 +} + +# +# +# +prepare_vgs_ + +not lvremove +not lvremove garbage +not lvremove $vg1/garbage + +lvremove $vg1 +check lv_exists $vg1 +check lv_not_exists $vg1 $lv1 +vgremove $vg1 + +lvremove $vg2 +check lv_exists $vg2 +check lv_not_exists $vg2 $lv1 $lv2 +vgremove $vg2 + +lvremove $vg3/$lv1 +lvremove $vg3/$lv2 $vg3/$lv3 +check lv_exists $vg3 +check lv_not_exists $vg3 $lv1 $lv2 $lv3 +vgremove $vg3 + +lvremove $vg4 +check lv_exists $vg4 +vgremove $vg4 + +lvremove $vg5/$lv1 $vg5 $vg5/$lv3 +check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5 +vgremove $vg5 + + +# +# test lvremove vg|lv names from multiple vgs +# +prepare_vgs_ + +lvremove $vg2 $vg3/$lv3 $vg5/$lv1 +check lv_not_exists $vg2 $lv1 $lv2 +check lv_not_exists $vg3 $lv3 +check lv_not_exists $vg5 $lv1 + +lvremove $vg2 $vg1 +check lv_not_exists $vg1 $lv1 + +lvremove $vg3/$lv1 $vg3 $vg4 $vg5/$lv2 +check lv_not_exists $vg3 $lv1 $lv2 +check lv_not_exists $vg5 $lv2 + +lvremove $vg5 $vg1 $vg5/$lv3 +check lv_not_exists $vg5 $lv3 $lv4 $lv5 + +vgremove $vg1 $vg2 $vg3 $vg4 $vg5 + + +# +# test lvremove @lvtags +# +prepare_vgs_ + +lvchange --addtag V1L1 $vg1/$lv1 +lvchange --addtag V2L1 $vg2/$lv1 +lvchange --addtag V2L2 $vg2/$lv2 +lvchange --addtag V23 $vg2/$lv1 +lvchange --addtag V23 $vg2/$lv2 +lvchange --addtag V23 $vg3/$lv1 +lvchange --addtag V23 $vg3/$lv2 +lvchange --addtag V23 $vg3/$lv3 +lvchange --addtag V3L2 $vg3/$lv2 +lvchange --addtag V3L3A $vg3/$lv3 +lvchange --addtag V3L3B $vg3/$lv3 +lvchange --addtag V5L1 $vg5/$lv1 +lvchange --addtag V5L234 $vg5/$lv2 +lvchange --addtag V5L234 $vg5/$lv3 +lvchange --addtag V5L234 $vg5/$lv4 +lvchange --addtag V5L5 $vg5/$lv5 +vgchange -an $vg1 $vg2 $vg3 $vg4 $vg5 + +# verify all exist +check lv_exists $vg1 $lv1 +check lv_exists $vg2 $lv1 $lv2 +check lv_exists $vg3 $lv1 $lv2 $lv3 +check lv_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5 + +lvremove @garbage + +lvremove @V3L3A +check lv_not_exists $vg3 $lv3 +# verify unremoved still exist +check lv_exists $vg1 $lv1 +check lv_exists $vg2 $lv1 $lv2 +check lv_exists $vg3 $lv1 $lv2 +check lv_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5 + +lvremove @V5L234 +check lv_not_exists $vg5 $lv2 $lv3 $lv4 +# verify unremoved still exist +check lv_exists $vg1 $lv1 +check lv_exists $vg2 $lv1 $lv2 +check lv_exists $vg3 $lv1 $lv2 +check lv_exists $vg5 $lv1 $lv5 + +lvremove @V5L1 @V5L5 +check lv_not_exists $vg5 $lv1 $lv5 +# verify unremoved still exist +check lv_exists $vg1 $lv1 +check lv_exists $vg2 $lv1 $lv2 +check lv_exists $vg3 $lv1 $lv2 + +lvremove @V23 @V1L1 @V3L2 +check lv_not_exists $vg1 $lv1 +check lv_not_exists $vg2 $lv1 $lv2 +check lv_not_exists $vg3 $lv1 $lv2 + +vgremove $vg1 $vg2 $vg3 $vg4 $vg5 + + +# +# test lvremove @vgtags +# +prepare_vgs_ + +vgchange --addtag V1 $vg1 +vgchange --addtag V23 $vg2 +vgchange --addtag V23 $vg3 +vgchange --addtag V35 $vg3 +vgchange --addtag V4 $vg4 +vgchange --addtag V35 $vg5 +vgchange --addtag V5 $vg5 +vgchange -an $vg1 $vg2 $vg3 $vg4 $vg5 + +lvremove @V4 +# verify unremoved exist +check lv_exists $vg1 $lv1 +check lv_exists $vg2 $lv1 $lv2 +check lv_exists $vg3 $lv1 $lv2 $lv3 +check lv_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5 + +lvremove @V5 +check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5 +# verify unremoved exist +check lv_exists $vg1 $lv1 +check lv_exists $vg2 $lv1 $lv2 +check lv_exists $vg3 $lv1 $lv2 $lv3 + +lvremove @V1 @V23 +check lv_not_exists $vg1 $lv1 +check lv_not_exists $vg2 $lv1 $lv2 +check lv_not_exists $vg3 $lv1 $lv2 $lv3 + +vgremove $vg1 $vg2 $vg3 $vg4 $vg5 + +# +# +# +prepare_vgs_ + +vgchange --addtag V1 $vg1 +vgchange --addtag V23 $vg2 +vgchange --addtag V23 $vg3 +vgchange --addtag V35 $vg3 +vgchange --addtag V4 $vg4 +vgchange --addtag V35 $vg5 +vgchange --addtag V5 $vg5 + +lvremove @V35 @V5 +check lv_not_exists $vg3 $lv1 $lv2 /$lv3 +check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5 +# verify unremoved exist +check lv_exists $vg1 $lv1 +check lv_exists $vg2 $lv1 $lv2 + +lvremove @V1 @V23 +check lv_not_exists $vg1 $lv1 +check lv_not_exists $vg2 $lv1 $lv2 + +vgremove $vg1 $vg2 $vg3 $vg4 $vg5 + + +# +# test lvremove vg|lv names and @lvtags +# +prepare_vgs_ + +lvchange --addtag V1L1 $vg1/$lv1 +lvchange --addtag V2L1 $vg2/$lv1 +lvchange --addtag V2L2 $vg2/$lv2 +lvchange --addtag V23 $vg2/$lv1 +lvchange --addtag V23 $vg2/$lv2 +lvchange --addtag V23 $vg3/$lv1 +lvchange --addtag V23 $vg3/$lv2 +lvchange --addtag V23 $vg3/$lv3 +lvchange --addtag V3L2 $vg3/$lv2 +lvchange --addtag V3L3A $vg3/$lv3 +lvchange --addtag V3L3B $vg3/$lv3 +lvchange --addtag V5L1 $vg5/$lv1 +lvchange --addtag V5L234 $vg5/$lv2 +lvchange --addtag V5L234 $vg5/$lv3 +lvchange --addtag V5L234 $vg5/$lv4 +lvchange --addtag V5L5 $vg5/$lv5 +vgchange -an $vg1 $vg2 $vg3 $vg4 $vg5 + +lvremove $vg1/$lv1 @V3L2 @V5L234 +check lv_not_exists $vg1 $lv1 +check lv_not_exists $vg3 $lv2 +check lv_not_exists $vg5 $lv2 $lv3 $lv4 +# verify unremoved exist +check lv_exists $vg2 $lv1 $lv2 +check lv_exists $vg3 $lv1 $lv3 +check lv_exists $vg5 $lv1 $lv5 + +lvremove $vg2/$lv1 @V23 $vg5/$lv1 @V5L5 + +vgremove $vg1 $vg2 $vg3 $vg4 $vg5 + + +# +# test lvremove vg|lv names and @vgtags +# +prepare_vgs_ + +vgchange --addtag V1 $vg1 +vgchange --addtag V23 $vg2 +vgchange --addtag V23 $vg3 +vgchange --addtag V35 $vg3 +vgchange --addtag V4 $vg4 +vgchange --addtag V35 $vg5 +vgchange --addtag V5 $vg5 + +lvremove $vg1/$lv1 @V35 +check lv_not_exists $vg1 $lv1 +check lv_not_exists $vg3 $lv1 $lv2 $lv3 +check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5 +# verify unremoved exist +check lv_exists $vg2 $lv1 $lv2 + +lvremove $vg2/$lv1 @V23 $vg2/$lv2 + +vgremove $vg1 $vg2 $vg3 $vg4 $vg5 + + +# +# test lvremove @lvtags and @vgtags +# +prepare_vgs_ + +lvchange --addtag V1L1 $vg1/$lv1 +lvchange --addtag V2L1 $vg2/$lv1 +lvchange --addtag V2L2 $vg2/$lv2 +lvchange --addtag V23 $vg2/$lv1 +lvchange --addtag V23 $vg2/$lv2 +lvchange --addtag V23 $vg3/$lv1 +lvchange --addtag V23 $vg3/$lv2 +# to check that vg tag @V23 includes this +# lvchange --addtag V23 $vg3/$lv3 +lvchange --addtag V3L2 $vg3/$lv2 +lvchange --addtag V3L3A $vg3/$lv3 +lvchange --addtag V3L3B $vg3/$lv3 +lvchange --addtag V5L1 $vg5/$lv1 +lvchange --addtag V5L234 $vg5/$lv2 +lvchange --addtag V5L234 $vg5/$lv3 +lvchange --addtag V5L234 $vg5/$lv4 +lvchange --addtag V5L5 $vg5/$lv5 +vgchange --addtag V1 $vg1 +vgchange --addtag V23 $vg2 +vgchange --addtag V23 $vg3 +vgchange --addtag V35 $vg3 +vgchange --addtag V4 $vg4 +vgchange --addtag V35 $vg5 +vgchange --addtag V5 $vg5 + +lvremove @V23 @V35 +check lv_not_exists $vg2 $lv1 $lv2 +check lv_not_exists $vg3 $lv1 $lv2 $lv3 +check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 $lv5 +# verify unremoved exist +check lv_exists $vg1 $lv1 + +lvremove @V1 @V1L1 +check lv_not_exists $vg1 $lv1 + +vgremove $vg1 $vg2 $vg3 $vg4 $vg5 + + +# +# test lvremove vg|lv names and @lvtags and @vgtags +# +prepare_vgs_ + +lvchange --addtag V1L1 $vg1/$lv1 +lvchange --addtag V2L1 $vg2/$lv1 +lvchange --addtag V2L2 $vg2/$lv2 +lvchange --addtag V23 $vg2/$lv1 +lvchange --addtag V23 $vg2/$lv2 +lvchange --addtag V23 $vg3/$lv1 +lvchange --addtag V23 $vg3/$lv2 +# to check that vg tag @V23 includes this +# lvchange --addtag V23 $vg3/$lv3 +lvchange --addtag V3L2 $vg3/$lv2 +lvchange --addtag V3L3A $vg3/$lv3 +lvchange --addtag V3L3B $vg3/$lv3 +lvchange --addtag V5L1 $vg5/$lv1 +lvchange --addtag V5L234 $vg5/$lv2 +lvchange --addtag V5L234 $vg5/$lv3 +lvchange --addtag V5L234 $vg5/$lv4 +lvchange --addtag V5L5 $vg5/$lv5 +vgchange --addtag V1 $vg1 +vgchange --addtag V23 $vg2 +vgchange --addtag V23 $vg3 +vgchange --addtag V35 $vg3 +vgchange --addtag V4 $vg4 +vgchange --addtag V35 $vg5 +vgchange --addtag V5 $vg5 + +lvremove $vg1/$lv1 @V23 @V5L5 +check lv_not_exists $vg1 $lv1 +check lv_not_exists $vg2 $lv1 $lv2 +check lv_not_exists $vg3 $lv1 $lv2 $lv3 +check lv_not_exists $vg5 $lv5 +# verify unremoved exist +check lv_exists $vg5 $lv1 $lv2 $lv3 $lv4 + +lvremove $vg5/$lv2 @V5L234 @V5 +check lv_not_exists $vg5 $lv1 $lv2 $lv3 $lv4 + +vgremove $vg1 $vg2 $vg3 $vg4 $vg5 + + +# +# test lvs: empty, vg(s), lv(s), vgtag(s), lvtag(s), garbage, combinations +# +prepare_vgs_ + +lvchange --addtag V1L1 $vg1/$lv1 +lvchange --addtag V2L1 $vg2/$lv1 +lvchange --addtag V2L2 $vg2/$lv2 +lvchange --addtag V23 $vg2/$lv1 +lvchange --addtag V23 $vg2/$lv2 +lvchange --addtag V23 $vg3/$lv1 +lvchange --addtag V23 $vg3/$lv2 +lvchange --addtag V23 $vg3/$lv3 +lvchange --addtag V3L2 $vg3/$lv2 +lvchange --addtag V3L3A $vg3/$lv3 +lvchange --addtag V3L3B $vg3/$lv3 +lvchange --addtag V5L1 $vg5/$lv1 +lvchange --addtag V5L234 $vg5/$lv2 +lvchange --addtag V5L234 $vg5/$lv3 +lvchange --addtag V5L234 $vg5/$lv4 +lvchange --addtag V5L5 $vg5/$lv5 +vgchange --addtag V1 $vg1 +vgchange --addtag V23 $vg2 +vgchange --addtag V23 $vg3 +vgchange --addtag V35 $vg3 +vgchange --addtag V4 $vg4 +vgchange --addtag V35 $vg5 +vgchange --addtag V5 $vg5 + +# empty +lvs -o vg_name,lv_name --separator '-' >err +grep $vg1-$lv1 err +grep $vg2-$lv1 err +grep $vg2-$lv2 err +grep $vg3-$lv1 err +grep $vg3-$lv2 err +grep $vg3-$lv3 err +grep $vg5-$lv1 err +grep $vg5-$lv2 err +grep $vg5-$lv3 err +grep $vg5-$lv4 err +grep $vg5-$lv5 err + +# vg +lvs -o vg_name,lv_name --separator '-' $vg1 >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# vgs +lvs -o vg_name,lv_name --separator '-' $vg1 $vg2 >err +grep $vg1-$lv1 err +grep $vg2-$lv1 err +grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# lv +lvs -o vg_name,lv_name --separator '-' $vg1/$lv1 >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# lvs +lvs -o vg_name,lv_name --separator '-' $vg1/$lv1 $vg2/$lv1 $vg2/$lv2 >err +grep $vg1-$lv1 err +grep $vg2-$lv1 err +grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# vgtag +lvs -o vg_name,lv_name --separator '-' @V1 >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# vgtags +lvs -o vg_name,lv_name --separator '-' @V1 @V35 >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +grep $vg3-$lv1 err +grep $vg3-$lv2 err +grep $vg3-$lv3 err +grep $vg5-$lv1 err +grep $vg5-$lv2 err +grep $vg5-$lv3 err +grep $vg5-$lv4 err +grep $vg5-$lv5 err + +# lvtag +lvs -o vg_name,lv_name --separator '-' @V1L1 >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# lvtags +lvs -o vg_name,lv_name --separator '-' @V1L1 @V5L234 >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +grep $vg5-$lv2 err +grep $vg5-$lv3 err +grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# vg and lv and vgtag and lvtag +lvs -o vg_name,lv_name --separator '-' $vg2 $vg5/$lv5 @V1 @V5L234 >err +grep $vg1-$lv1 err +grep $vg2-$lv1 err +grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +grep $vg5-$lv2 err +grep $vg5-$lv3 err +grep $vg5-$lv4 err +grep $vg5-$lv5 err + +# garbage name gives an error if used without a tag + +not lvs -o vg_name,lv_name --separator '-' garbage >err +not grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +not lvs -o vg_name,lv_name --separator '-' $vg1/$lv1 garbage >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# garbage name does not give an error if used with a tag + +lvs -o vg_name,lv_name --separator '-' @V1 garbage >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +lvs -o vg_name,lv_name --separator '-' @garbage garbage >err +not grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +# garbage tag never gives an error + +lvs -o vg_name,lv_name --separator '-' @V1 @garbage >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +lvs -o vg_name,lv_name --separator '-' $vg1/$lv1 @garbage >err +grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +lvs -o vg_name,lv_name --separator '-' @garbage >err +not grep $vg1-$lv1 err +not grep $vg2-$lv1 err +not grep $vg2-$lv2 err +not grep $vg3-$lv1 err +not grep $vg3-$lv2 err +not grep $vg3-$lv3 err +not grep $vg5-$lv1 err +not grep $vg5-$lv2 err +not grep $vg5-$lv3 err +not grep $vg5-$lv4 err +not grep $vg5-$lv5 err + +vgremove -f $vg1 $vg2 $vg3 $vg4 $vg5 diff --git a/test/shell/process-each-pv-nomda-all.sh b/test/shell/process-each-pv-nomda-all.sh new file mode 100644 index 0000000..020f831 --- /dev/null +++ b/test/shell/process-each-pv-nomda-all.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test process_each_pv with zero mda' +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 14 + +# for vg1 +pvcreate "$dev10" + +# for vg2 +pvcreate "$dev2" --metadatacopies 0 +pvcreate "$dev3" +pvcreate "$dev4" +pvcreate "$dev5" + +# for vg3 +pvcreate "$dev6" --metadatacopies 0 +pvcreate "$dev7" --metadatacopies 0 +pvcreate "$dev8" --metadatacopies 0 +pvcreate "$dev9" + +# orphan with mda +pvcreate "$dev11" +# orphan without mda +pvcreate "$dev14" --metadatacopies 0 + +# non-pv devs +# dev12 +# dev13 + +vgcreate $SHARED $vg1 "$dev10" +vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5" +vgcreate $SHARED $vg3 "$dev6" "$dev7" "$dev8" "$dev9" + +pvs -a | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +grep "$dev12" err +grep "$dev13" err +grep "$dev14" err + +vgremove $vg1 $vg2 $vg3 diff --git a/test/shell/process-each-pv-nomda.sh b/test/shell/process-each-pv-nomda.sh new file mode 100644 index 0000000..2185ce4 --- /dev/null +++ b/test/shell/process-each-pv-nomda.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test process_each_pv with zero mda' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 2 + +pvcreate "$dev1" --metadatacopies 0 +pvcreate "$dev2" + +vgcreate $SHARED $vg1 "$dev1" "$dev2" + +pvdisplay -a -C | tee err +grep "$dev1" err +grep "$dev2" err + +vgremove $vg1 diff --git a/test/shell/process-each-pv.sh b/test/shell/process-each-pv.sh new file mode 100644 index 0000000..beb7a6c --- /dev/null +++ b/test/shell/process-each-pv.sh @@ -0,0 +1,1063 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Exercise toollib process_each_pv' +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 14 + +# +# process_each_pv is used by a number of pv commands: +# pvdisplay +# pvresize +# pvs +# +# process-each-pvresize.sh covers pvresize. +# process-each-vgreduce.sh covers vgreduce. +# + + +# +# set up +# +# use use dev10 instead of dev1 because simple grep for +# dev1 matchines dev10,dev11,etc +# + +vgcreate $SHARED $vg1 "$dev10" +vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5" +vgcreate $SHARED $vg3 "$dev6" "$dev7" "$dev8" "$dev9" + +pvchange --addtag V2D3 "$dev3" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" + +pvchange --addtag V3 "$dev6" "$dev7" "$dev8" "$dev9" +pvchange --addtag V3D9 "$dev9" + +# orphan +pvcreate "$dev11" + +# dev (a non-pv device) +pvcreate "$dev12" +pvremove "$dev12" + +# dev13 is intentionally untouched so we can +# test that it is handled appropriately as a non-pv + +# orphan +pvcreate "$dev14" + + +# +# test pvdisplay +# + +# pv in vg +pvdisplay -s "$dev10" | tee err +grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# pv not in vg (one orphan) +pvdisplay -s "$dev11" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# dev is not a pv +not pvdisplay -s "$dev12" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# two pvs in different vgs +pvdisplay -s "$dev10" "$dev2" | tee err +grep "$dev10" err +grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# -a is invalid when used alone +not pvdisplay -a | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# one pv and one orphan +pvdisplay -s "$dev10" "$dev11" | tee err +grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# one pv and one dev (dev refers to a non-pv device) +not pvdisplay -s "$dev10" "$dev12" | tee err +grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# one orphan and one dev +not pvdisplay -s "$dev11" "$dev12" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# all pvs (pvs in vgs and orphan pvs) +pvdisplay -s | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +grep "$dev14" err + +# all devs (pvs in vgs, orphan pvs, and devs) +pvdisplay -a -C | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +grep "$dev12" err +grep "$dev13" err +grep "$dev14" err + +# pv and orphan and dev +not pvdisplay -s "$dev9" "$dev11" "$dev12" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# -s option not allowed with -a -C +not pvdisplay -s -a -C | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# pv and all (all ignored) +pvdisplay -a -C "$dev9" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# orphan and all (all ignored) +pvdisplay -a -C "$dev11" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# one tag +pvdisplay -s @V2D3 | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# two tags +pvdisplay -s @V2D3 @V2D45 | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and pv +pvdisplay -s @V2D3 "$dev4" | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and orphan +pvdisplay -s @V2D3 "$dev11" | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and dev +not pvdisplay -s @V2D3 "$dev12" | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and all (all ignored) +pvdisplay @V2D3 -a -C | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and pv redundant +pvdisplay -s @V2D3 "$dev3" | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + + +# +# test pvs +# + +# pv in vg +pvs "$dev10" | tee err +grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# pv not in vg (one orphan) +pvs "$dev11" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# dev is not a pv +not pvs "$dev12" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# two pvs in different vgs +pvs "$dev10" "$dev2" | tee err +grep "$dev10" err +grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# one pv and one orphan +pvs "$dev10" "$dev11" | tee err +grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# one pv and one dev +not pvs "$dev10" "$dev12" | tee err +grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# one orphan and one dev +not pvs "$dev11" "$dev12" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# all pvs (pvs in vgs and orphan pvs) +pvs | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +grep "$dev14" err + +# all devs (pvs in vgs, orphan pvs, and devs) +pvs -a | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +grep "$dev12" err +grep "$dev13" err +grep "$dev14" err + +# pv and orphan and dev +not pvs "$dev9" "$dev11" "$dev12" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# pv and all (all ignored) +pvs -a "$dev9" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# orphan and all (all ignored) +pvs -a "$dev11" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# one tag +pvs @V2D3 | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# two tags +pvs @V2D3 @V2D45 | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and pv +pvs @V2D3 "$dev4" | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and orphan +pvs @V2D3 "$dev11" | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and dev +not pvs @V2D3 "$dev12" | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and all (all ignored) +pvs @V2D3 -a | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag and pv redundant +pvs @V2D3 "$dev3" | tee err +not grep "$dev10" err +not grep "$dev2" err +grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + + +# +# tests including pvs without mdas +# + +# remove old config +vgremove $vg1 +vgremove $vg2 +vgremove $vg3 +pvremove "$dev11" +pvremove "$dev14" + +# new config with some pvs that have zero mdas + +# for vg1 +pvcreate "$dev10" + +# for vg2 +pvcreate "$dev2" --metadatacopies 0 +pvcreate "$dev3" +pvcreate "$dev4" +pvcreate "$dev5" + +# for vg3 +pvcreate "$dev6" --metadatacopies 0 +pvcreate "$dev7" --metadatacopies 0 +pvcreate "$dev8" --metadatacopies 0 +pvcreate "$dev9" + +# orphan with mda +pvcreate "$dev11" +# orphan without mda +pvcreate "$dev14" --metadatacopies 0 + +# non-pv devs +# dev12 +# dev13 + +vgcreate $SHARED $vg1 "$dev10" +vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5" +vgcreate $SHARED $vg3 "$dev6" "$dev7" "$dev8" "$dev9" + +pvchange --addtag V2D3 "$dev3" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" + +pvchange --addtag V3 "$dev6" "$dev7" "$dev8" "$dev9" +pvchange --addtag V3D8 "$dev8" +pvchange --addtag V3D9 "$dev9" + + +# +# pvdisplay including pvs without mdas +# + +# pv with mda +pvdisplay -s "$dev10" | tee err +grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# pv without mda +pvdisplay -s "$dev2" | tee err +not grep "$dev10" err +grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# orphan with mda +pvdisplay -s "$dev11" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# orphan without mda +pvdisplay -s "$dev14" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +grep "$dev14" err + +# pv with mda, pv without mda, orphan with mda, orphan without mda +pvdisplay -s "$dev10" "$dev2" "$dev11" "$dev14" | tee err +grep "$dev10" err +grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +grep "$dev14" err + +# tag refering to pv with mda and pv without mda +pvdisplay -s @V3 | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag refering to one pv without mda +pvdisplay -s @V3D8 | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# all pvs (pvs in vgs and orphan pvs) +pvdisplay -s | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +grep "$dev14" err + +# all devs (pvs in vgs, orphan pvs, and devs) +pvdisplay -a -C | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +grep "$dev12" err +grep "$dev13" err +grep "$dev14" err + +# +# pvs including pvs without mdas +# + +# pv with mda +pvs "$dev10" | tee err +grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# pv without mda +pvs "$dev2" | tee err +not grep "$dev10" err +grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# orphan with mda +pvs "$dev11" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# orphan without mda +pvs "$dev14" | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +grep "$dev14" err + +# pv with mda, pv without mda, orphan with mda, orphan without mda +pvs "$dev10" "$dev2" "$dev11" "$dev14" | tee err +grep "$dev10" err +grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +not grep "$dev8" err +not grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +grep "$dev14" err + +# tag refering to pv with mda and pv without mda +pvs @V3 | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# tag refering to one pv without mda +pvs @V3D8 | tee err +not grep "$dev10" err +not grep "$dev2" err +not grep "$dev3" err +not grep "$dev4" err +not grep "$dev5" err +not grep "$dev6" err +not grep "$dev7" err +grep "$dev8" err +not grep "$dev9" err +not grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +not grep "$dev14" err + +# all pvs (pvs in vgs and orphan pvs) +pvs | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +not grep "$dev12" err +not grep "$dev13" err +grep "$dev14" err + +# all devs (pvs in vgs, orphan pvs, and devs) +pvs -a | tee err +grep "$dev10" err +grep "$dev2" err +grep "$dev3" err +grep "$dev4" err +grep "$dev5" err +grep "$dev6" err +grep "$dev7" err +grep "$dev8" err +grep "$dev9" err +grep "$dev11" err +grep "$dev12" err +grep "$dev13" err +grep "$dev14" err + +vgremove $vg1 $vg2 $vg3 diff --git a/test/shell/process-each-pvresize.sh b/test/shell/process-each-pvresize.sh new file mode 100644 index 0000000..b2287b4 --- /dev/null +++ b/test/shell/process-each-pvresize.sh @@ -0,0 +1,563 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Exercise toollib process_each_pv' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 14 + +# +# process_each_pv is used by a number of pv commands: +# pvdisplay +# pvresize +# pvs +# vgreduce +# + + +# +# set up +# +# use use dev10 instead of dev1 because simple grep for +# dev1 matchines dev10,dev11,etc +# + +vgcreate $SHARED $vg1 "$dev10" +vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5" +vgcreate $SHARED $vg3 "$dev6" "$dev7" "$dev8" "$dev9" + +pvchange --addtag V2D3 "$dev3" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" + +pvchange --addtag V3 "$dev6" "$dev7" "$dev8" "$dev9" +pvchange --addtag V3D9 "$dev9" + +# orphan +pvcreate "$dev11" + +# dev (a non-pv device) +pvcreate "$dev12" +pvremove "$dev12" + +# dev13 is intentionally untouched so we can +# test that it is handled appropriately as a non-pv + +# orphan +pvcreate "$dev14" + +# +# test pvresize without orphans and and without non-pv devs +# + +# For pvs in vgs, pvresize setphysicalvolumesize does not give us +# the size requested, but reduces the requested size by some the +# amount for alignment, metadata areas and pv headers. So, when we resize +# to 30M, the result is 28M, and when we resize to 20M, the result is 16M. +# For orphans, the resulting size is the same as requested. +# It suspect that these reduction amounts might be inconsistent, and +# depend on other changing factors, so it may be that we eventually +# want to give up checking the exact resulting size, but just check +# that the result is less than the original size. + +old_request="30.00m" +old_reduced="28.00m" +new_request="20.00m" +new_reduced="16.00m" + +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced + +# one pv +pvresize --setphysicalvolumesize $new_request -y "$dev10" +check pv_field "$dev10" pv_size $new_reduced +# unchanged +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + +# two pvs in separate vgs +pvresize --setphysicalvolumesize $new_request -y "$dev2" "$dev6" +check pv_field "$dev2" pv_size $new_reduced +check pv_field "$dev6" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + +# one tag on one pv +pvresize --setphysicalvolumesize $new_request -y @V2D4 +check pv_field "$dev4" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + +# one tag on all pvs in one vg +pvresize --setphysicalvolumesize $new_request -y @V3 +check pv_field "$dev6" pv_size $new_reduced +check pv_field "$dev7" pv_size $new_reduced +check pv_field "$dev8" pv_size $new_reduced +check pv_field "$dev9" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + +# one tag on some pvs in one vg +pvresize --setphysicalvolumesize $new_request -y @V2D45 +check pv_field "$dev4" pv_size $new_reduced +check pv_field "$dev5" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + +# one tag on multiple pvs in separate vgs +pvchange --addtag V12 "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" +pvresize --setphysicalvolumesize $new_request -y @V12 +check pv_field "$dev10" pv_size $new_reduced +check pv_field "$dev2" pv_size $new_reduced +check pv_field "$dev3" pv_size $new_reduced +check pv_field "$dev4" pv_size $new_reduced +check pv_field "$dev5" pv_size $new_reduced +# unchanged +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + +# one pv and one tag on different pv +pvresize --setphysicalvolumesize $new_request -y "$dev10" @V3D9 +check pv_field "$dev10" pv_size $new_reduced +check pv_field "$dev9" pv_size $new_reduced +# unchanged +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + +# redundant pv and tag +pvresize --setphysicalvolumesize $new_request -y "$dev9" @V3D9 +check pv_field "$dev9" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + +# two tags on pvs in separate vgs +pvresize --setphysicalvolumesize $new_request -y @V3D9 @V2D3 +check pv_field "$dev9" pv_size $new_reduced +check pv_field "$dev3" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" + + +# +# test pvresize with orphans +# + +old_request="30.00m" +old_reduced="28.00m" +old_orphan="30.00m" +new_request="20.00m" +new_reduced="16.00m" +new_orphan="20.00m" + +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +check pv_field "$dev14" pv_size $old_orphan + +# one orphan +pvresize --setphysicalvolumesize $new_request -y "$dev11" +check pv_field "$dev11" pv_size $new_orphan +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev14" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# two orphans +pvresize --setphysicalvolumesize $new_request -y "$dev11" "$dev14" +check pv_field "$dev11" pv_size $new_orphan +check pv_field "$dev14" pv_size $new_orphan +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one orphan, one tag +pvresize --setphysicalvolumesize $new_request -y @V3D9 "$dev14" +check pv_field "$dev9" pv_size $new_reduced +check pv_field "$dev14" pv_size $new_orphan +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one pv, one orphan, one tag +pvresize --setphysicalvolumesize $new_request -y @V3D9 "$dev14" "$dev10" +check pv_field "$dev9" pv_size $new_reduced +check pv_field "$dev10" pv_size $new_reduced +check pv_field "$dev14" pv_size $new_orphan +# unchanged +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + + +# +# test pvresize with non-pv devs +# + +# one dev (non-pv) +not pvresize --setphysicalvolumesize $new_request -y "$dev13" +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +check pv_field "$dev14" pv_size $old_orphan + +# one orphan and one dev (non-pv) +not pvresize --setphysicalvolumesize $new_request -y "$dev14" "$dev13" +check pv_field "$dev14" pv_size $new_orphan +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one pv and one dev (non-pv) +not pvresize --setphysicalvolumesize $new_request -y "$dev9" "$dev13" +check pv_field "$dev9" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +check pv_field "$dev14" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one tag and one dev (non-pv) +not pvresize --setphysicalvolumesize $new_request -y @V3D9 "$dev13" +check pv_field "$dev9" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +check pv_field "$dev14" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one pv, one orphan, one tag, one dev +not pvresize --setphysicalvolumesize $new_request -y @V3D9 "$dev13" "$dev14" "$dev10" +check pv_field "$dev9" pv_size $new_reduced +check pv_field "$dev10" pv_size $new_reduced +check pv_field "$dev14" pv_size $new_orphan +# unchanged +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + + +# +# pvresize including pvs without mdas +# + +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +check pv_field "$dev14" pv_size $old_orphan + +# one pv without mda +pvresize --setphysicalvolumesize $new_request -y "$dev2" +check pv_field "$dev2" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +check pv_field "$dev14" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# two pvs without mdas +pvresize --setphysicalvolumesize $new_request -y "$dev6" "$dev7" +check pv_field "$dev6" pv_size $new_reduced +check pv_field "$dev7" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +check pv_field "$dev14" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one pv with mda and one pv without mda +pvresize --setphysicalvolumesize $new_request -y "$dev8" "$dev9" +check pv_field "$dev8" pv_size $new_reduced +check pv_field "$dev9" pv_size $new_reduced +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +check pv_field "$dev14" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one orphan with mda +pvresize --setphysicalvolumesize $new_request -y "$dev11" +check pv_field "$dev11" pv_size $new_orphan +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev14" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one orphan without mda +pvresize --setphysicalvolumesize $new_request -y "$dev14" +check pv_field "$dev14" pv_size $new_orphan +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +check pv_field "$dev11" pv_size $old_orphan +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one orphan with mda and one orphan without mda +pvresize --setphysicalvolumesize $new_request -y "$dev14" "$dev11" +check pv_field "$dev11" pv_size $new_orphan +check pv_field "$dev14" pv_size $new_orphan +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +check pv_field "$dev8" pv_size $old_reduced +check pv_field "$dev9" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" + +# one pv with mda and one pv without mda, and +# one orphan with mda and one orphan without mda +pvresize --setphysicalvolumesize $new_request -y "$dev8" "$dev9" "$dev14" "$dev11" +check pv_field "$dev8" pv_size $new_reduced +check pv_field "$dev9" pv_size $new_reduced +check pv_field "$dev11" pv_size $new_orphan +check pv_field "$dev14" pv_size $new_orphan +# unchanged +check pv_field "$dev10" pv_size $old_reduced +check pv_field "$dev2" pv_size $old_reduced +check pv_field "$dev3" pv_size $old_reduced +check pv_field "$dev4" pv_size $old_reduced +check pv_field "$dev5" pv_size $old_reduced +check pv_field "$dev6" pv_size $old_reduced +check pv_field "$dev7" pv_size $old_reduced +# reset back to old size +pvresize --setphysicalvolumesize $old_request -y "$dev10" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" "$dev9" +pvresize --setphysicalvolumesize $old_request -y "$dev11" "$dev14" diff --git a/test/shell/process-each-vg.sh b/test/shell/process-each-vg.sh new file mode 100644 index 0000000..569cf08 --- /dev/null +++ b/test/shell/process-each-vg.sh @@ -0,0 +1,269 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Exercise toollib process_each_vg' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 6 + +# +# process_each_vg is used by a number of vg commands; +# use 'vgremove' and 'vgs' to test it. +# +# The logic in process_each_vg is mainly related to +# selecting which vg's to process. +# + +# +# set up four vgs that we will remove +# +vgcreate $SHARED $vg1 "$dev1" +vgcreate $SHARED $vg2 "$dev2" +vgcreate $SHARED $vg3 "$dev3" +vgcreate $SHARED $vg4 "$dev4" + +# these two vgs will not be removed +vgcreate $SHARED $vg5 "$dev5" +vgchange --addtag tagvg5 $vg5 +lvcreate -l 4 -n $lv1 $vg5 +vgcreate $SHARED $vg6 "$dev6" +lvcreate -l 4 -n $lv2 $vg6 + +# should fail without any arg +not vgremove + +# should succeed +vgremove $vg1 +vgremove $vg2 $vg3 $vg4 + +# these should fail because they are already removed +not vgremove $vg1 +not vgremove $vg2 +not vgremove $vg3 +not vgremove $vg4 + +# these should fail because they have lvs in them +not vgremove $vg5 +not vgremove $vg6 + +# check that the vgs we removed are gone +not vgs $vg1 +not vgs $vg2 +not vgs $vg3 +not vgs $vg4 + + +# +# set up four vgs that we will remove +# +vgcreate $SHARED --addtag tagfoo $vg1 "$dev1" +vgcreate $SHARED --addtag tagfoo $vg2 "$dev2" +vgcreate $SHARED --addtag tagfoo2 $vg3 "$dev3" +vgcreate $SHARED --addtag tagbar $vg4 "$dev4" +vgchange --addtag foo $vg4 + +# should do nothing and fail +not vgremove garbage + +# should find nothing to remove +vgremove @garbage + +# should find nothing to remove +vgremove @$vg1 + +# should succeed +vgremove $vg1 +not vgs $vg1 + +vgremove $vg2 $vg3 $vg4 +not vgs $vg2 +not vgs $vg3 +not vgs $vg4 + + +# +# set up four vgs that we will remove +# +vgcreate $SHARED --addtag tagfoo $vg1 "$dev1" +vgcreate $SHARED --addtag tagfoo $vg2 "$dev2" +vgcreate $SHARED --addtag tagfoo2 $vg3 "$dev3" +vgcreate $SHARED --addtag tagbar $vg4 "$dev4" +vgchange --addtag foo $vg4 + +vgremove @tagfoo +not vgs $vg1 +not vgs $vg2 + +vgremove @tagfoo2 @tagbar +not vgs $vg3 +not vgs $vg4 + + +# +# set up four vgs that we will remove +# +vgcreate $SHARED --addtag tagfoo $vg1 "$dev1" +vgcreate $SHARED --addtag tagfoo $vg2 "$dev2" +vgcreate $SHARED --addtag tagfoo2 $vg3 "$dev3" +vgcreate $SHARED --addtag tagbar $vg4 "$dev4" +vgchange --addtag foo $vg4 + +vgremove $vg1 @tagfoo2 +not vgs $vg1 +not vgs $vg3 + +vgremove @tagbar $vg2 +not vgs $vg2 +not vgs $vg4 + + +# +# set up four vgs that we will remove +# +vgcreate $SHARED --addtag tagfoo $vg1 "$dev1" +vgcreate $SHARED --addtag tagfoo $vg2 "$dev2" +vgcreate $SHARED --addtag tagfoo2 $vg3 "$dev3" +vgcreate $SHARED --addtag tagbar $vg4 "$dev4" +vgchange --addtag foo $vg4 + +vgremove @foo @tagfoo2 $vg1 $vg2 +not vgs $vg1 +not vgs $vg2 +not vgs $vg3 +not vgs $vg4 + + +# +# set up four vgs that we will remove +# +vgcreate $SHARED --addtag tagfoo $vg1 "$dev1" +vgcreate $SHARED --addtag tagfoo $vg2 "$dev2" +vgcreate $SHARED --addtag tagfoo2 $vg3 "$dev3" +vgcreate $SHARED --addtag tagbar $vg4 "$dev4" +vgchange --addtag foo $vg4 + +vgremove @tagfoo $vg1 @tagfoo @tagfoo2 $vg3 @tagbar +not vgs $vg1 +not vgs $vg2 +not vgs $vg3 +not vgs $vg4 + + +# +# set up four vgs that we will remove +# +vgcreate $SHARED --addtag tagfoo $vg1 "$dev1" +vgcreate $SHARED --addtag tagfoo $vg2 "$dev2" +vgcreate $SHARED --addtag tagfoo2 $vg3 "$dev3" +vgcreate $SHARED --addtag tagbar $vg4 "$dev4" +vgchange --addtag foo $vg4 + +not vgremove garbage $vg1 +not vgs $vg1 + +not vgremove $vg2 garbage +not vgs $vg2 + +vgremove $vg3 @garbage +not vgs $vg3 + +vgremove @garbage $vg4 +not vgs $vg4 + + +# +# end vgremove tests +# check that the two vgs we did not intend to remove +# are still there, and then remove them +# +vgs $vg5 +vgs $vg6 +vgremove -f $vg5 +vgremove -f $vg6 +not vgs $vg5 +not vgs $vg6 + + +# +# set up four vgs that we will report +# +vgcreate $SHARED --addtag tagfoo $vg1 "$dev1" +vgcreate $SHARED --addtag tagfoo $vg2 "$dev2" +vgcreate $SHARED --addtag tagfoo2 $vg3 "$dev3" +vgcreate $SHARED --addtag tagbar $vg4 "$dev4" +vgchange --addtag foo $vg4 + +vgs >err +grep $vg1 err +grep $vg2 err +grep $vg3 err +grep $vg4 err + +vgs $vg1 $vg2 >err +grep $vg1 err +grep $vg2 err +not grep $vg3 err +not grep $vg4 err + +vgs @tagfoo >err +grep $vg1 err +grep $vg2 err +not grep $vg3 err +not grep $vg4 err + +vgs @tagfoo2 >err +grep $vg3 err +not grep $vg1 err +not grep $vg2 err +not grep $vg4 err + +vgs @tagfoo2 @tagbar >err +grep $vg3 err +grep $vg4 err +not grep $vg1 err +not grep $vg2 err + +vgs $vg1 @tagbar >err +grep $vg1 err +grep $vg4 err +not grep $vg2 err +not grep $vg3 err + +vgs $vg1 @tagfoo >err +grep $vg1 err +grep $vg2 err +not grep $vg3 err +not grep $vg4 err + +not vgs garbage >err +not grep $vg1 err +not grep $vg2 err +not grep $vg3 err +not grep $vg4 err + +not vgs garbage $vg1 >err +grep $vg1 err +not grep $vg2 err +not grep $vg3 err +not grep $vg4 err + +vgs @garbage @foo >err +grep $vg4 err +not grep $vg1 err +not grep $vg2 err +not grep $vg3 err + +vgremove -f $vg1 $vg2 $vg3 $vg4 + diff --git a/test/shell/process-each-vgreduce.sh b/test/shell/process-each-vgreduce.sh new file mode 100644 index 0000000..23584bf --- /dev/null +++ b/test/shell/process-each-vgreduce.sh @@ -0,0 +1,331 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Exercise toollib process_each_pv with vgreduce' + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 14 + +# +# set up +# +# FIXME: some of the setup may not be used by the tests +# since this was split out from process-each-pv, where +# some of the setup was used by other tests that only +# remain in process-each-pv. +# +# use use dev10 instead of dev1 because simple grep for +# dev1 matchines dev10,dev11,etc +# + +vgcreate $SHARED $vg1 "$dev10" +vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5" +vgcreate $SHARED $vg3 "$dev6" "$dev7" "$dev8" "$dev9" + +pvchange --addtag V2D3 "$dev3" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" + +pvchange --addtag V3 "$dev6" "$dev7" "$dev8" "$dev9" +pvchange --addtag V3D9 "$dev9" + +# orphan +pvcreate "$dev11" + +# dev (a non-pv device) +pvcreate "$dev12" +pvremove "$dev12" + +# dev13 is intentionally untouched so we can +# test that it is handled appropriately as a non-pv + +# orphan +pvcreate "$dev14" + + +# fail without dev +not vgreduce $vg2 + + +# fail with dev and -a +not vgreduce $vg2 "$dev2" -a +check pv_field "$dev2" vg_name $vg2 +check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 + + +# remove one pv +vgreduce $vg2 "$dev2" +not check pv_field "$dev2" vg_name $vg2 +check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev2" + + +# remove two pvs +vgreduce $vg2 "$dev2" "$dev3" +not check pv_field "$dev2" vg_name $vg2 +not check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev2" "$dev3" +pvchange --addtag V2D3 "$dev3" + + +# remove one pv with tag +vgreduce $vg2 @V2D3 +check pv_field "$dev2" vg_name $vg2 +not check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev3" +pvchange --addtag V2D3 "$dev3" + + +# remove two pvs, each with different tag +vgreduce $vg2 @V2D3 @V2D4 +check pv_field "$dev2" vg_name $vg2 +not check pv_field "$dev3" vg_name $vg2 +not check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev3" "$dev4" +pvchange --addtag V2D3 "$dev3" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" + + +# remove two pvs, both with same tag +vgreduce $vg2 @V2D45 +check pv_field "$dev2" vg_name $vg2 +check pv_field "$dev3" vg_name $vg2 +not check pv_field "$dev4" vg_name $vg2 +not check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev4" "$dev5" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" + + +# remove two pvs, one by name, one by tag +vgreduce $vg2 "$dev2" @V2D3 +not check pv_field "$dev2" vg_name $vg2 +not check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev2" "$dev3" +pvchange --addtag V2D3 "$dev3" + + +# remove one pv by tag, where another vg has a pv with same tag +pvchange --addtag V2D5V3D9 "$dev5" +pvchange --addtag V2D5V3D9 "$dev9" +vgreduce $vg2 @V2D5V3D9 +check pv_field "$dev2" vg_name $vg2 +check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +not check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev5" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" + + +# fail to remove last pv (don't know which will be last) +not vgreduce -a $vg2 +# reset +vgremove $vg2 +vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5" +pvchange --addtag V2D3 "$dev3" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" + + +# lvcreate on one pv to make it used +# remove all unused pvs +lvcreate -n $lv1 -l 2 $vg2 "$dev2" +not vgreduce -a $vg2 +check pv_field "$dev2" vg_name $vg2 +not check pv_field "$dev3" vg_name $vg2 +not check pv_field "$dev4" vg_name $vg2 +not check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev3" "$dev4" "$dev5" +pvchange --addtag V2D3 "$dev3" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" +lvchange -an $vg2/$lv1 +lvremove $vg2/$lv1 + + +# +# tests including pvs without mdas +# + +# remove old config +vgremove $vg1 +vgremove $vg2 +vgremove $vg3 +pvremove "$dev11" +pvremove "$dev14" + +# new config with some pvs that have zero mdas + +# for vg1 +pvcreate "$dev10" + +# for vg2 +pvcreate "$dev2" --metadatacopies 0 +pvcreate "$dev3" +pvcreate "$dev4" +pvcreate "$dev5" + +# for vg3 +pvcreate "$dev6" --metadatacopies 0 +pvcreate "$dev7" --metadatacopies 0 +pvcreate "$dev8" --metadatacopies 0 +pvcreate "$dev9" + +# orphan with mda +pvcreate "$dev11" +# orphan without mda +pvcreate "$dev14" --metadatacopies 0 + +# non-pv devs +# dev12 +# dev13 + +vgcreate $SHARED $vg1 "$dev10" +vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5" +vgcreate $SHARED $vg3 "$dev6" "$dev7" "$dev8" "$dev9" + +pvchange --addtag V2D3 "$dev3" +pvchange --addtag V2D4 "$dev4" +pvchange --addtag V2D45 "$dev4" +pvchange --addtag V2D5 "$dev5" +pvchange --addtag V2D45 "$dev5" + +pvchange --addtag V3 "$dev6" "$dev7" "$dev8" "$dev9" +pvchange --addtag V3D8 "$dev8" +pvchange --addtag V3D9 "$dev9" + + +# +# vgreduce including pvs without mdas +# + +# remove pv without mda +vgreduce $vg2 "$dev2" +not check pv_field "$dev2" vg_name $vg2 +check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev2" + +# remove pv with mda and pv without mda +vgreduce $vg2 "$dev2" "$dev3" +not check pv_field "$dev2" vg_name $vg2 +not check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +# reset +vgextend $vg2 "$dev2" +vgextend $vg2 "$dev3" + +# fail to remove only pv with mda +not vgreduce $vg3 "$dev9" +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +check pv_field "$dev2" vg_name $vg2 +check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 + +# remove by tag a pv without mda +vgreduce $vg3 @V3D8 +check pv_field "$dev6" vg_name $vg3 +check pv_field "$dev7" vg_name $vg3 +not check pv_field "$dev8" vg_name $vg3 +check pv_field "$dev9" vg_name $vg3 +check pv_field "$dev2" vg_name $vg2 +check pv_field "$dev3" vg_name $vg2 +check pv_field "$dev4" vg_name $vg2 +check pv_field "$dev5" vg_name $vg2 +# reset +vgextend $vg3 "$dev8" + +vgremove $vg1 $vg2 $vg3 diff --git a/test/shell/profiles-cache.sh b/test/shell/profiles-cache.sh new file mode 100644 index 0000000..b408130 --- /dev/null +++ b/test/shell/profiles-cache.sh @@ -0,0 +1,153 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise obtaining cache parameter from various sources +# Either commmand line or metadata profile or implicit default... + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 8 0 || skip + +PDIR="$LVM_SYSTEM_DIR/profile" +PFILE="cache-test" + +aux prepare_profiles + +cat < "$PDIR/${PFILE}.profile" +allocation { + cache_pool_chunk_size = 128 + cache_mode = "writeback" + cache_policy = "mq" + cache_metadata_format = 1 + + cache_settings { + smq { + sequential_threshold = 300 + random_threshold = 500 + } + mq { + } + mq { + sequential_threshold = 100 + random_threshold = 200 + } + writecache { + high_watermark = 60 + } + } +} +EOF + +cat < "$PDIR/${PFILE}1.profile" +allocation { + cache_pool_chunk_size = 512 + cache_mode = "passthrough" + cache_policy = "smq" + cache_metadata_format = 1 +} +EOF + +aux prepare_vg 2 1000000 + +# Check writecache read data from profile +if aux have_writecache 1 0 0 ; then +lvcreate -n $lv1 -l 4 -an $vg "$dev1" +lvcreate -y --type writecache -l 4 --cachevol $lv1 -n $lv2 --metadataprofile $PFILE $vg "$dev2" +check lv_field $vg/$lv2 cachesettings "high_watermark=60" +lvremove -y $vg +fi + +# Check chunk_size is grabbed from configuration +lvcreate -L1G --config 'allocation/cache_pool_chunk_size=512' --type cache-pool $vg/cpool +check lv_field $vg/cpool chunksize "512.00k" + +# Check chunk_size can be overruled when caching LV. +lvcreate -H --chunksize 128K -L10 --cachepool $vg/cpool -n $lv1 +check lv_field $vg/$lv1 chunksize "128.00k" + +lvremove -f $vg + + +# Check chunk_size is grabbed from metadata profile +lvcreate -L1G --metadataprofile $PFILE --type cache-pool $vg/cpool +#lvcreate -L1G --commandprofile $PFILE --type cache-pool $vg/cpool + +# profile name is stored with cache-pool +check lv_field $vg/cpool profile "$PFILE" +# cache chunk size is selected and stored on creation time +check lv_field $vg/cpool chunksize "128.00k" +# cache metadata format is not stored with cache-pool +check lv_field $vg/cpool cachemetadataformat "" +# cache mode is not stored with cache-pool +check lv_field $vg/cpool cachemode "" +# cache policy is not stored with cache-pool +check lv_field $vg/cpool cachepolicy "" +# cache settings are not stored with cache-pool +check lv_field $vg/cpool cachesettings "" + + +lvcreate -L10 -n $lv1 $vg +lvconvert --metadataprofile "${PFILE}1" -y -H --cachepool $vg/cpool $vg/$lv1 +# chunk size 128k is replace with 512k from PFILE1 +check lv_field $vg/$lv1 chunksize "512.00k" +# cachemode is from PFILE1 +check lv_field $vg/$lv1 cachemode "passthrough" +lvremove -f $vg + +lvcreate -L1G --metadataprofile "$PFILE" --type cache-pool $vg/cpool +lvcreate -H -L10 -n $lv1 --cachepool $vg/cpool +# profile name is stored with cache +check lv_field $vg/$lv1 profile "$PFILE" +# cache chunk size is selected and stored on creation time +check lv_field $vg/$lv1 chunksize "128.00k" +# cache metadata format is stored with cache +check lv_field $vg/$lv1 cachemetadataformat "1" +# cache mode is stored with cache +check lv_field $vg/$lv1 cachemode "writeback" +# cache policy is stored with cache +check lv_field $vg/$lv1 cachepolicy "mq" +# cache settings are stored with cache +check lv_field $vg/$lv1 cachesettings "sequential_threshold=100,random_threshold=200" + +lvremove -f $vg + +##### + +lvcreate -L1G --metadataprofile "$PFILE" --type cache-pool $vg/cpool +lvcreate --cachesettings 'sequential_threshold=300' -H -L10 -n $lv1 --cachepool $vg/cpool +check lv_field $vg/$lv1 profile "$PFILE" +check lv_field $vg/$lv1 cachesettings "sequential_threshold=300" +lvremove -f $vg + +##### + +lvcreate -L1G --metadataprofile "$PFILE" --type cache-pool $vg/cpool +lvcreate --chunksize 256 -H -L10 -n $lv1 --cachepool $vg/cpool +check lv_field $vg/$lv1 cachemode "writeback" +check lv_field $vg/$lv1 chunksize "256.00k" +lvremove -f $vg + + +##### + +lvcreate -L1G --metadataprofile "$PFILE" --type cache-pool $vg/cpool +lvcreate --metadataprofile "${PFILE}1" -H -L10 -n $lv1 --cachepool $vg/cpool +check lv_field $vg/$lv1 chunksize "512.00k" +check lv_field $vg/$lv1 cachemode "passthrough" +lvremove -f $vg + +#lvs -a -o+chunksize,cachemode,cachemetadataformat,cachepolicy,cachesettings $vg + +vgremove -ff $vg diff --git a/test/shell/profiles-thin.sh b/test/shell/profiles-thin.sh new file mode 100644 index 0000000..c62a5f5 --- /dev/null +++ b/test/shell/profiles-thin.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# test thin profile functionality +# + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +DEV_SIZE=32 + +# check we have thinp support compiled in +aux have_thin 1 0 0 || skip + +aux prepare_profiles "thin-performance" + +# Create scsi debug dev with sector size of 4096B and 1MiB optimal_io_size +aux prepare_scsi_debug_dev $DEV_SIZE sector_size=4096 opt_blks=256 || skip +EXPECT=1048576 +check sysfs "$(< SCSI_DEBUG_DEV)" queue/optimal_io_size "$EXPECT" +aux prepare_pvs 1 "$DEV_SIZE" + +# Check we are not running on buggy kernel (broken lcm()) +# If so, turn chunk_size test into 'should' +SHOULD="" +check sysfs "$dev1" queue/optimal_io_size "$EXPECT" || SHOULD=should + +vgcreate $SHARED $vg "$dev1" + +# By default, "generic" policy is used to +# calculate chunk size which is 64KiB by default +# or minimum_io_size if it's higher. Also, zeroing is used +# under default operation. +lvcreate -L8m -T $vg/pool_generic +check lv_field $vg/pool_generic profile "" +check lv_field $vg/pool_generic chunk_size 64.00k +check lv_field $vg/pool_generic zero "zero" + +# If "thin-performance" profile is used, the "performance" +# policy is used to calculate chunk size which is 512KiB +# or optimal_io_suize if it's higher. Our test device has +# 1MiB, so that should be used. Also, zeroing is not used +# under "thin-perforance" profile. +lvcreate --profile thin-performance -L8m -T $vg/pool_performance +check lv_field $vg/pool_performance profile "thin-performance" +$SHOULD check lv_field $vg/pool_performance chunk_size 1.00m +check lv_field $vg/pool_performance zero "" + +lvremove -f $vg + +# +# Repeat same two creations via lvconvert +# +lvcreate -L8m --name pool_generic $vg +lvconvert --yes --type thin-pool $vg/pool_generic +check lv_field $vg/pool_generic chunk_size 64.00k +check lv_field $vg/pool_generic zero "zero" + + +lvcreate -L8m --name pool_performance $vg +lvconvert --yes --type thin-pool --errorwhenfull y --profile thin-performance $vg/pool_performance +check lv_field $vg/pool_performance profile "thin-performance" +$SHOULD check lv_field $vg/pool_performance chunk_size 1.00m +check lv_field $vg/pool_performance zero "" +check lv_field $vg/pool_performance lv_when_full "error" + +vgremove -ff $vg + +if test -d "$DM_DEV_DIR/$vg" ; then + should not echo "Udev has left \"$DM_DEV_DIR/$vg\"!" + rm -rf "${DM_DEV_DIR:?/dev}/$vg" +fi + +# The profile must be also applied if using the profile +# for the whole VG - any LVs inherit this profile then. +vgcreate $SHARED --profile thin-performance $vg "$dev1" +lvcreate -L8m -T $vg/pool_performance_inherited +# ...the LV does not have the profile attached, but VG does! +check vg_field $vg profile "thin-performance" +check lv_field $vg/pool_performance_inherited profile "" +$SHOULD check lv_field $vg/pool_performance_inherited chunk_size 1.00m +check lv_field $vg/pool_performance_inherited zero "" + +vgremove -ff $vg diff --git a/test/shell/profiles-vdo.sh b/test/shell/profiles-vdo.sh new file mode 100644 index 0000000..7b3c343 --- /dev/null +++ b/test/shell/profiles-vdo.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018-2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise obtaining vdo parameters from various sources +# Either commmand line or metadata profile or implicit default... + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_vdo 6 2 0 || skip + +PDIR="$LVM_SYSTEM_DIR/profile" +PFILE="vdo-test" + +aux prepare_profiles + +cat < "$PDIR/${PFILE}.profile" +allocation { + vdo_use_compression = 0 + vdo_use_deduplication = 0 + vdo_slab_size_mb = 128 +} +EOF + +aux prepare_vg 2 1000000 + +# Check chunk_size is grabbed from configuration +lvcreate --vdo -L5G --config 'allocation/vdo_use_compression=0' $vg/vdopool +lvdisplay -m $vg/vdopool | tee out +grep "Compression.*no" out +lvremove -f $vg + +# Without profile using 128MB slab it would NOT even pass +lvcreate --vdo -L4G --metadataprofile "$PFILE" $vg/vdopool +lvdisplay -m $vg/vdopool | tee out +grep "Compression.*no" out +lvremove -f $vg + +lvcreate -L4G --name vdopool $vg +lvconvert --yes --type vdo-pool --metadataprofile "$PFILE" $vg/vdopool +check lv_field $vg/vdopool vdo_compression "" + +vgremove -ff $vg diff --git a/test/shell/profiles.sh b/test/shell/profiles.sh new file mode 100644 index 0000000..be720c8 --- /dev/null +++ b/test/shell/profiles.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# test basic profile functionality +# + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +MSG_FAILED_TO_APPLY_CMD_PROFILE="Failed to apply command profile" +MSG_IGNORING_INVALID_CMD_PROFILE="Ignoring invalid command profile" +MSG_FAILED_TO_APPLY_MDA_PROFILE="Failed to apply metadata profile" +MSG_IGNORING_INVALID_MDA_PROFILE="Ignoring invalid metadata profile" +MSG_NOT_PROFILABLE="not customizable by a profile" +MSG_CMD_PROFILABLE_ONLY="customizable by command profile only, not metadata profile" +MSG_MDA_PROFILABLE_ONLY="customizable by metadata profile only, not command profile" + +# fail if the profile requested by --profile cmdline option is not present +not pvs --profile nonexistent 2>&1 | grep "$MSG_FAILED_TO_APPLY_CMD_PROFILE" + +# config/checks=1: warning message about setting not being profilable + +# summary error message about invalid profile +# config/checks=0: just summary error message about invalid profile +aux profileconf invalid 'log/prefix=" "' + +aux lvmconf 'config/checks = 0' +not pvs --profile invalid 2>msg +not grep "$MSG_NOT_PROFILABLE" msg +grep "$MSG_IGNORING_INVALID_CMD_PROFILE" msg +grep "$MSG_FAILED_TO_APPLY_CMD_PROFILE" msg + +aux lvmconf 'config/checks = 1' +not pvs --profile invalid 2>msg +grep "$MSG_NOT_PROFILABLE" msg +grep "$MSG_IGNORING_INVALID_CMD_PROFILE" msg +grep "$MSG_FAILED_TO_APPLY_CMD_PROFILE" msg + +aux lvmconf 'allocation/thin_pool_zero = 1' + +# all profilable items listed here - should pass +aux profileconf valid_cmd_profile 'global/units = "h"' \ + 'global/si_unit_consistency = 1' \ + 'global/suffix = 1' \ + 'global/lvdisplay_shows_full_device_path = 0' \ + 'report/aligned = 1' \ + 'report/buffered = 1' \ + 'report/headings = 1' \ + 'report/separator = " "' \ + 'report/prefixes = 0' \ + 'report/quoted = 1' \ + 'report/columns_as_rows = 0' \ + 'report/devtypes_sort = "devtype_name"' \ + 'report/devtypes_cols = "devtype_name,devtype_max_partitions,devtype_description"' \ + 'report/devtypes_cols_verbose = "devtype_name,devtype_max_partitions,devtype_description"' \ + 'report/lvs_sort = "vg_name,lv_name"' \ + 'report/lvs_cols = "lv_name,vg_name,lv_attr,lv_size,pool_lv,origin,data_percent,move_pv,mirror_log,copy_percent,convert_lv"' \ + 'report/lvs_cols_verbose = "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,pool_lv,origin,data_percent,metadata_percent,move_pv,copy_percent,mirror_log,convert_lv,lv_uuid,lv_profile"' \ + 'report/vgs_sort = "vg_name"' \ + 'report/vgs_cols = "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"' \ + 'report/vgs_cols_verbose = "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid,vg_profile"' \ + 'report/pvs_sort = "pv_name"' \ + 'report/pvs_cols = "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"' \ + 'report/pvs_cols_verbose = "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"' \ + 'report/segs_sort = "vg_name,lv_name,seg_start"' \ + 'report/segs_cols = "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"' \ + 'report/segs_cols_verbose = "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"' \ + 'report/pvsegs_sort = "pv_name,pvseg_start"' \ + 'report/pvsegs_cols = "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"' \ + 'report/pvsegs_cols_verbose = "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"' + +aux profileconf valid_mda_profile 'allocation/thin_pool_zero = 0' \ + 'allocation/thin_pool_discards = "passdown"' \ + 'allocation/thin_pool_chunk_size = 64' \ + 'activation/thin_pool_autoextend_threshold = 100' \ + 'activation/thin_pool_autoextend_percent = 20' + +aux profileconf extra_mda_profile 'allocation/thin_pool_chunk_size = 128' + +pvs --profile valid_cmd_profile 2>msg +not grep "$MSG_NOT_PROFILABLE" msg +not grep "$MSG_IGNORING_INVALID_CMD_PROFILE" msg +not grep "$MSG_IGNORING_INVALID_MDA_PROFILE" msg + +not pvs --profile valid_mda_profile 2>msg +grep "$MSG_MDA_PROFILABLE_ONLY" msg +grep "$MSG_IGNORING_INVALID_CMD_PROFILE" msg +not grep "$MSG_IGNORING_INVALID_MDA_PROFILE" msg + +# attaching/detaching profiles to VG/LV +aux prepare_pvs 1 8 +pvcreate "$dev1" +vgcreate $SHARED $vg1 "$dev1" +check vg_field $vg1 vg_profile "" +lvcreate -l 1 -n $lv1 $vg1 +check lv_field $vg1/$lv1 lv_profile "" +vgchange --profile valid_mda_profile $vg1 +check vg_field $vg1 vg_profile valid_mda_profile +check lv_field $vg1/$lv1 lv_profile "" +lvchange --profile extra_mda_profile $vg1/$lv1 +check vg_field $vg1 vg_profile valid_mda_profile +check lv_field $vg1/$lv1 lv_profile extra_mda_profile +vgchange --detachprofile $vg1 +check vg_field $vg1 vg_profile "" +check lv_field $vg1/$lv1 lv_profile extra_mda_profile +lvchange --detachprofile $vg1/$lv1 +check vg_field $vg1 vg_profile "" +check lv_field $vg1/$lv1 lv_profile "" + +# dumpconfig and merged lvm.conf + profile +aux lvmconf 'global/units="m"' +aux profileconf extra_cmd_profile 'global/units="h"' +lvm dumpconfig &>out +grep 'units="m"' out +lvm dumpconfig --profile extra_cmd_profile --mergedconfig >out +grep 'units="h"' out + +# dumpconfig --profilable output must be usable as a profile +lvm dumpconfig --type profilable-command --file etc/profile/generated.profile +pvs --profile generated &> msg +not grep "$MSG_NOT_PROFILABLE" msg +not grep "$MSG_IGNORING_INVALID_CMD_PROFILE" msg + +vgremove -ff $vg1 diff --git a/test/shell/pv-check-dev-size.sh b/test/shell/pv-check-dev-size.sh new file mode 100644 index 0000000..f9d31a1 --- /dev/null +++ b/test/shell/pv-check-dev-size.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_pvs 1 8 + +aux lvmconf 'metadata/check_pv_device_sizes = 1' + +CHECK_MSG="smaller than corresponding PV size" + +vgcreate $SHARED "$vg" "$dev1" 2>err +not grep "$CHECK_MSG" err +pvs 2>err +not grep "$CHECK_MSG" err +vgremove -ff $vg + +# set PV size to 2x dev size +pvcreate --yes --setphysicalvolumesize 16m "$dev1" +vgcreate $SHARED "$vg" "$dev1" 2>err +grep "$CHECK_MSG" err +pvs 2>err +grep "$CHECK_MSG" err +vgremove -ff $vg + +# should be quiet if requested +aux lvmconf 'metadata/check_pv_device_sizes = 0' +pvcreate --yes --setphysicalvolumesize 16m "$dev1" +vgcreate $SHARED "$vg" "$dev1" 2>err +not grep "$CHECK_MSG" err +pvs 2>err +not grep "$CHECK_MSG" err + +vgremove -ff $vg diff --git a/test/shell/pv-corruption.sh b/test/shell/pv-corruption.sh new file mode 100644 index 0000000..b3c5059 --- /dev/null +++ b/test/shell/pv-corruption.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# tests, write failer on PV1 is not reporting errors on PV2 or PV3... + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# skip test early if there is no 'delay' target available +aux target_at_least dm-delay 1 1 0 || skip "missing dm-delay target" +touch HAVE_DM_DELAY + +# +# Main +# +aux prepare_devs 3 20 + +pvcreate -y --setphysicalvolumesize 10m "$dev1" +pvcreate "$dev2" +pvcreate "$dev3" + +vgcreate $vg "$dev1" "$dev2" "$dev3" + +pvs -o +uuid + +# Keep device readable, but any write fails +aux writeerror_dev "$dev1" 0:100 + +# Suppose to fail, size PV1 is not writable +not pvresize "$dev1" 2>&1 | tee out + +# Output should not complain about any error on pv2 nor pv3 +not grep pv2 out +not grep pv3 out + +# Restore working PV1 back +aux enable_dev "$dev1" + +# FIXME: Takes a lot of time ATM.... +pvck "$dev2" + +pvs -o +uuid +vgdisplay + +vgremove $vg diff --git a/test/shell/pv-duplicate-uuid.sh b/test/shell/pv-duplicate-uuid.sh new file mode 100644 index 0000000..ac2b866 --- /dev/null +++ b/test/shell/pv-duplicate-uuid.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test 'Found duplicate' is shown + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 3 + +pvcreate "$dev1" +UUID1=$(get pv_field "$dev1" uuid) +pvcreate --devices "$dev2" -u "$UUID1" --norestorefile "$dev2" +pvcreate --devices "$dev3" -u "$UUID1" --norestorefile "$dev3" + +pvscan --cache 2>&1 | tee out + +pvs -o+uuid 2>&1 | tee out + +grep WARNING out > warn || true +grep -v WARNING out > main || true + +test "$(grep -c $UUID1 main)" -eq 1 + +COUNT=$(grep --count "Not using device" warn) +[ "$COUNT" -eq 2 ] + +pvs -o+uuid --devices $dev2 2>&1 | tee out + +rm warn main || true +grep WARNING out > warn || true +grep -v WARNING out > main || true + +not grep "$dev1" main +grep "$dev2" main +not grep "$dev3" main + +not grep "Not using device" warn + diff --git a/test/shell/pv-duplicate.sh b/test/shell/pv-duplicate.sh deleted file mode 100644 index 6a22cd1..0000000 --- a/test/shell/pv-duplicate.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -# Copyright (C) 2011 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 duplicate metadata diagnostics' - -. lib/test - -aux prepare_devs 3 - -vgcreate -c n --metadatasize 128k $vg1 "$dev1" - -# copy mda -dd if="$dev1" of="$dev2" bs=256K count=1 -dd if="$dev1" of="$dev3" bs=256K count=1 - -pvs "$dev1" -vgs $vg1 diff --git a/test/shell/pv-ext-flags.sh b/test/shell/pv-ext-flags.sh new file mode 100644 index 0000000..ae4d6b7 --- /dev/null +++ b/test/shell/pv-ext-flags.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 2 + +# PV_EXT_USED flag +MARKED_AS_USED_MSG="is used by a VG but its metadata is missing" + +###################################### +### CHECK PV WITH 0 METADATA AREAS ### +###################################### + +pvcreate -ff -y --metadatacopies 0 "$dev1" +pvcreate -ff -y --metadatacopies 1 "$dev2" + +# $dev1 and $dev2 not in any VG - pv_in_use field should be blank +check pv_field "$dev1" pv_in_use "" +check pv_field "$dev2" pv_in_use "" + +# $dev1 and $dev now in a VG - pv_in_use should display "used" +vgcreate $vg1 "$dev1" "$dev2" +check pv_field "$dev1" pv_in_use "used" +check pv_field "$dev2" pv_in_use "used" + +# disable $dev2 and dev1 with 0 MDAs remains, but still +# marked as used, so pvcreate/vgcreate/pvremove should fail +aux disable_dev "$dev2" + +check pv_field "$dev1" pv_in_use "used" +not pvcreate "$dev1" 2>err +cat err +grep "$MARKED_AS_USED_MSG" err +not pvchange -u "$dev1" 2>err +grep "$MARKED_AS_USED_MSG" err +not vgcreate $vg2 "$dev1" 2>err +grep "$MARKED_AS_USED_MSG" err +not pvremove "$dev1" 2>err +grep "$MARKED_AS_USED_MSG" err + +# save PV signature from dev1 for reuse later on in this +# test so we don't need to initialize all the VG stuff again +dd if="$dev1" of=dev1_backup bs=1M + +# pvcreate and pvremove can be forced even if the PV is marked as used +pvremove -ff -y "$dev1" +lvmdevices --deldev "$dev1" || true +dd if=dev1_backup of="$dev1" bs=1M +pvcreate -ff -y "$dev1" +dd if=dev1_backup of="$dev1" bs=1M +lvmdevices --adddev "$dev1" || true + +# prepare a VG with $dev1 and $dev both having 1 MDA +aux enable_dev "$dev2" +vgremove -ff $vg1 +pvremove -ff -y "$dev1" +pvcreate --metadatacopies 1 "$dev1" +vgcreate $vg1 "$dev1" "$dev2" + +# disable $dev1, then repair the VG - $dev1 is removed from VG +aux disable_dev "$dev1" +vgreduce --removemissing $vg1 + +# now, enable $dev1 and clear the old metadata from it +aux enable_dev "$dev1" +vgck --updatemetadata $vg1 + +vgck $vg1 + +# check $dev1 does not contain the PV_EXT_FLAG anymore +check pv_field "$dev1" pv_in_use "" + +############################################# +### CHECK PV WITH DISABLED METADATA AREAS ### +############################################# + +pvcreate -ff -y --metadatacopies 1 "$dev1" +pvcreate -ff -y --metadatacopies 1 "$dev2" + +# $dev1 and $dev2 not in any VG - pv_in_use field should be blank +check pv_field "$dev1" pv_in_use "" +check pv_field "$dev2" pv_in_use "" + +# $dev1 and $dev now in a VG - pv_in_use should display "used" +vgcreate $vg1 "$dev1" "$dev2" +check pv_field "$dev1" pv_in_use "used" +check pv_field "$dev2" pv_in_use "used" + +pvchange --metadataignore y "$dev1" +aux disable_dev "$dev2" + +check pv_field "$dev1" pv_in_use "used" +not pvcreate "$dev1" 2>err +grep "$MARKED_AS_USED_MSG" err +not pvchange -u "$dev1" 2>err +grep "$MARKED_AS_USED_MSG" err +not vgcreate $vg2 "$dev1" 2>err +grep "$MARKED_AS_USED_MSG" err +not pvremove "$dev1" 2>err +grep "$MARKED_AS_USED_MSG" err + +# save PV signature from dev1 for reuse later on in this +# test so we don't need to initialize all the VG stuff again +dd if="$dev1" of=dev1_backup bs=1M + +# pvcreate and pvremove can be forced even if the PV is marked as used +pvremove -ff -y "$dev1" +lvmdevices --deldev "$dev1" || true +dd if=dev1_backup of="$dev1" bs=1M +pvcreate -ff -y "$dev1" +dd if=dev1_backup of="$dev1" bs=1M +lvmdevices --adddev "$dev1" || true + +# prepare a VG with $dev1 and $dev both having 1 MDA +aux enable_dev "$dev2" +vgremove -ff $vg1 +pvremove -ff -y "$dev1" +pvcreate --metadatacopies 1 "$dev1" +vgcreate $vg1 "$dev1" "$dev2" + +# disable $dev1, then repair the VG - $dev1 is removed from VG +aux disable_dev "$dev1" +vgreduce --removemissing $vg1 + +# now, enable $dev1 and clear the old metadata from it +aux enable_dev "$dev1" +vgck --updatemetadata $vg1 + +vgck $vg1 + +# check $dev1 does not contain the PV_EXT_FLAG anymore +check pv_field "$dev1" pv_in_use "" + +########################### +# OTHER PV-RELATED CHECKS # +########################### + +# vgcfgrestore should also set PV_EXT_FLAG on PVs where VG is restored +vgcfgbackup -f vg_backup $vg1 +check pv_field "$dev2" pv_in_use "used" +vgremove -ff $vg1 +check pv_field "$dev2" pv_in_use "" +vgcfgrestore -f vg_backup $vg1 +check pv_field "$dev2" pv_in_use "used" diff --git a/test/shell/pv-ext-update.sh b/test/shell/pv-ext-update.sh new file mode 100644 index 0000000..bd66c02 --- /dev/null +++ b/test/shell/pv-ext-update.sh @@ -0,0 +1,185 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + + +. lib/inittest + +env printf "" || skip # skip if printf is not available + +# create the PV with PV ext vsn 1 and a vg +create_pv_with_ext_vsn1_and_vg() +{ + VG_NAME="LVMTEST12345pvextupdatevg" + LV_NAME="lvol0" + + # 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 + + # PV header with PV extension version 1 + env printf \ +"\x4c\x41\x42\x45\x4c\x4f\x4e\x45\x01\x00\x00\x00\x00\x00\x00\x00"\ +"\x78\x1c\x12\x43\x20\x00\x00\x00\x4c\x56\x4d\x32\x20\x30\x30\x31"\ +"\x64\x35\x56\x33\x38\x5a\x57\x49\x63\x7a\x64\x63\x34\x38\x37\x67"\ +"\x4d\x79\x46\x4b\x6c\x6d\x68\x39\x4e\x73\x34\x6f\x78\x61\x6b\x51"\ +"\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00"\ +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00"\ +"\x00\xf0\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ +"\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"\ +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | dd of="$1" bs=512 seek=1 conv=notrunc + + # MDA header + env printf \ +"\xd8\x36\x2c\xf6\x20\x4c\x56\x4d\x32\x20\x78\x5b\x35\x41\x25\x72"\ +"\x30\x4e\x2a\x3e\x01\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00"\ +"\x00\xf0\x0f\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00"\ +"\x06\x04\x00\x00\x00\x00\x00\x00\x07\x3d\x06\x28\x00\x00\x00\x00"\ +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | dd of="$1" bs=4096 seek=1 conv=notrunc + + # VG metadata + env printf \ +"\x4c\x56\x4d\x54\x45\x53\x54\x31\x32\x33\x34\x35\x70\x76\x65\x78"\ +"\x74\x75\x70\x64\x61\x74\x65\x76\x67\x20\x7b\x0a\x69\x64\x20\x3d"\ +"\x20\x22\x42\x72\x47\x6f\x34\x33\x2d\x36\x35\x62\x48\x2d\x41\x55"\ +"\x6d\x43\x2d\x77\x56\x74\x71\x2d\x51\x53\x63\x66\x2d\x6b\x5a\x51"\ +"\x45\x2d\x58\x51\x6e\x79\x31\x44\x22\x0a\x73\x65\x71\x6e\x6f\x20"\ +"\x3d\x20\x31\x0a\x66\x6f\x72\x6d\x61\x74\x20\x3d\x20\x22\x6c\x76"\ +"\x6d\x32\x22\x0a\x73\x74\x61\x74\x75\x73\x20\x3d\x20\x5b\x22\x52"\ +"\x45\x53\x49\x5a\x45\x41\x42\x4c\x45\x22\x2c\x20\x22\x52\x45\x41"\ +"\x44\x22\x2c\x20\x22\x57\x52\x49\x54\x45\x22\x5d\x0a\x66\x6c\x61"\ +"\x67\x73\x20\x3d\x20\x5b\x5d\x0a\x65\x78\x74\x65\x6e\x74\x5f\x73"\ +"\x69\x7a\x65\x20\x3d\x20\x38\x31\x39\x32\x0a\x6d\x61\x78\x5f\x6c"\ +"\x76\x20\x3d\x20\x30\x0a\x6d\x61\x78\x5f\x70\x76\x20\x3d\x20\x30"\ +"\x0a\x6d\x65\x74\x61\x64\x61\x74\x61\x5f\x63\x6f\x70\x69\x65\x73"\ +"\x20\x3d\x20\x30\x0a\x0a\x70\x68\x79\x73\x69\x63\x61\x6c\x5f\x76"\ +"\x6f\x6c\x75\x6d\x65\x73\x20\x7b\x0a\x0a\x70\x76\x30\x20\x7b\x0a"\ +"\x69\x64\x20\x3d\x20\x22\x64\x35\x56\x33\x38\x5a\x2d\x57\x49\x63"\ +"\x7a\x2d\x64\x63\x34\x38\x2d\x37\x67\x4d\x79\x2d\x46\x4b\x6c\x6d"\ +"\x2d\x68\x39\x4e\x73\x2d\x34\x6f\x78\x61\x6b\x51\x22\x0a\x64\x65"\ +"\x76\x69\x63\x65\x20\x3d\x20\x22\x2f\x64\x65\x76\x2f\x6c\x6f\x6f"\ +"\x70\x30\x22\x0a\x0a\x73\x74\x61\x74\x75\x73\x20\x3d\x20\x5b\x22"\ +"\x41\x4c\x4c\x4f\x43\x41\x54\x41\x42\x4c\x45\x22\x5d\x0a\x66\x6c"\ +"\x61\x67\x73\x20\x3d\x20\x5b\x5d\x0a\x64\x65\x76\x5f\x73\x69\x7a"\ +"\x65\x20\x3d\x20\x31\x36\x33\x38\x34\x0a\x70\x65\x5f\x73\x74\x61"\ +"\x72\x74\x20\x3d\x20\x32\x30\x34\x38\x0a\x70\x65\x5f\x63\x6f\x75"\ +"\x6e\x74\x20\x3d\x20\x31\x0a\x7d\x0a\x7d\x0a\x0a\x7d\x0a\x23\x20"\ +"\x47\x65\x6e\x65\x72\x61\x74\x65\x64\x20\x62\x79\x20\x4c\x56\x4d"\ +"\x32\x20\x76\x65\x72\x73\x69\x6f\x6e\x20\x32\x2e\x30\x32\x2e\x31"\ +"\x34\x32\x28\x32\x29\x2d\x67\x69\x74\x20\x28\x32\x30\x31\x36\x2d"\ +"\x30\x32\x2d\x31\x35\x29\x3a\x20\x57\x65\x64\x20\x4a\x75\x6c\x20"\ +"\x32\x37\x20\x31\x31\x3a\x32\x35\x3a\x30\x37\x20\x32\x30\x31\x36"\ +"\x0a\x0a\x63\x6f\x6e\x74\x65\x6e\x74\x73\x20\x3d\x20\x22\x54\x65"\ +"\x78\x74\x20\x46\x6f\x72\x6d\x61\x74\x20\x56\x6f\x6c\x75\x6d\x65"\ +"\x20\x47\x72\x6f\x75\x70\x22\x0a\x76\x65\x72\x73\x69\x6f\x6e\x20"\ +"\x3d\x20\x31\x0a\x0a\x64\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e"\ +"\x20\x3d\x20\x22\x22\x0a\x0a\x63\x72\x65\x61\x74\x69\x6f\x6e\x5f"\ +"\x68\x6f\x73\x74\x20\x3d\x20\x22\x66\x65\x64\x6f\x72\x61\x2e\x76"\ +"\x69\x72\x74\x22\x09\x23\x20\x4c\x69\x6e\x75\x78\x20\x66\x65\x64"\ +"\x6f\x72\x61\x2e\x76\x69\x72\x74\x20\x34\x2e\x36\x2e\x34\x2d\x33"\ +"\x30\x31\x2e\x66\x63\x32\x34\x2e\x78\x38\x36\x5f\x36\x34\x20\x23"\ +"\x31\x20\x53\x4d\x50\x20\x54\x75\x65\x20\x4a\x75\x6c\x20\x31\x32"\ +"\x20\x31\x31\x3a\x35\x30\x3a\x30\x30\x20\x55\x54\x43\x20\x32\x30"\ +"\x31\x36\x20\x78\x38\x36\x5f\x36\x34\x0a\x63\x72\x65\x61\x74\x69"\ +"\x6f\x6e\x5f\x74\x69\x6d\x65\x20\x3d\x20\x31\x34\x36\x39\x36\x31"\ +"\x31\x35\x30\x37\x09\x23\x20\x57\x65\x64\x20\x4a\x75\x6c\x20\x32"\ +"\x37\x20\x31\x31\x3a\x32\x35\x3a\x30\x37\x20\x32\x30\x31\x36\x0a"\ +"\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | dd of="$1" bs=4608 seek=1 conv=notrunc + + env printf \ +"\x4c\x56\x4d\x54\x45\x53\x54\x31\x32\x33\x34\x35\x70\x76\x65\x78"\ +"\x74\x75\x70\x64\x61\x74\x65\x76\x67\x20\x7b\x0a\x69\x64\x20\x3d"\ +"\x20\x22\x42\x72\x47\x6f\x34\x33\x2d\x36\x35\x62\x48\x2d\x41\x55"\ +"\x6d\x43\x2d\x77\x56\x74\x71\x2d\x51\x53\x63\x66\x2d\x6b\x5a\x51"\ +"\x45\x2d\x58\x51\x6e\x79\x31\x44\x22\x0a\x73\x65\x71\x6e\x6f\x20"\ +"\x3d\x20\x32\x0a\x66\x6f\x72\x6d\x61\x74\x20\x3d\x20\x22\x6c\x76"\ +"\x6d\x32\x22\x0a\x73\x74\x61\x74\x75\x73\x20\x3d\x20\x5b\x22\x52"\ +"\x45\x53\x49\x5a\x45\x41\x42\x4c\x45\x22\x2c\x20\x22\x52\x45\x41"\ +"\x44\x22\x2c\x20\x22\x57\x52\x49\x54\x45\x22\x5d\x0a\x66\x6c\x61"\ +"\x67\x73\x20\x3d\x20\x5b\x5d\x0a\x65\x78\x74\x65\x6e\x74\x5f\x73"\ +"\x69\x7a\x65\x20\x3d\x20\x38\x31\x39\x32\x0a\x6d\x61\x78\x5f\x6c"\ +"\x76\x20\x3d\x20\x30\x0a\x6d\x61\x78\x5f\x70\x76\x20\x3d\x20\x30"\ +"\x0a\x6d\x65\x74\x61\x64\x61\x74\x61\x5f\x63\x6f\x70\x69\x65\x73"\ +"\x20\x3d\x20\x30\x0a\x0a\x70\x68\x79\x73\x69\x63\x61\x6c\x5f\x76"\ +"\x6f\x6c\x75\x6d\x65\x73\x20\x7b\x0a\x0a\x70\x76\x30\x20\x7b\x0a"\ +"\x69\x64\x20\x3d\x20\x22\x64\x35\x56\x33\x38\x5a\x2d\x57\x49\x63"\ +"\x7a\x2d\x64\x63\x34\x38\x2d\x37\x67\x4d\x79\x2d\x46\x4b\x6c\x6d"\ +"\x2d\x68\x39\x4e\x73\x2d\x34\x6f\x78\x61\x6b\x51\x22\x0a\x64\x65"\ +"\x76\x69\x63\x65\x20\x3d\x20\x22\x2f\x64\x65\x76\x2f\x6c\x6f\x6f"\ +"\x70\x30\x22\x0a\x0a\x73\x74\x61\x74\x75\x73\x20\x3d\x20\x5b\x22"\ +"\x41\x4c\x4c\x4f\x43\x41\x54\x41\x42\x4c\x45\x22\x5d\x0a\x66\x6c"\ +"\x61\x67\x73\x20\x3d\x20\x5b\x5d\x0a\x64\x65\x76\x5f\x73\x69\x7a"\ +"\x65\x20\x3d\x20\x31\x36\x33\x38\x34\x0a\x70\x65\x5f\x73\x74\x61"\ +"\x72\x74\x20\x3d\x20\x32\x30\x34\x38\x0a\x70\x65\x5f\x63\x6f\x75"\ +"\x6e\x74\x20\x3d\x20\x31\x0a\x7d\x0a\x7d\x0a\x0a\x6c\x6f\x67\x69"\ +"\x63\x61\x6c\x5f\x76\x6f\x6c\x75\x6d\x65\x73\x20\x7b\x0a\x0a\x6c"\ +"\x76\x6f\x6c\x30\x20\x7b\x0a\x69\x64\x20\x3d\x20\x22\x46\x73\x36"\ +"\x6c\x6a\x6b\x2d\x4a\x65\x5a\x35\x2d\x55\x4e\x75\x37\x2d\x32\x41"\ +"\x33\x50\x2d\x76\x30\x41\x43\x2d\x64\x63\x64\x36\x2d\x32\x33\x38"\ +"\x39\x4d\x76\x22\x0a\x73\x74\x61\x74\x75\x73\x20\x3d\x20\x5b\x22"\ +"\x52\x45\x41\x44\x22\x2c\x20\x22\x57\x52\x49\x54\x45\x22\x2c\x20"\ +"\x22\x56\x49\x53\x49\x42\x4c\x45\x22\x5d\x0a\x66\x6c\x61\x67\x73"\ +"\x20\x3d\x20\x5b\x5d\x0a\x63\x72\x65\x61\x74\x69\x6f\x6e\x5f\x68"\ +"\x6f\x73\x74\x20\x3d\x20\x22\x66\x65\x64\x6f\x72\x61\x2e\x76\x69"\ +"\x72\x74\x22\x0a\x63\x72\x65\x61\x74\x69\x6f\x6e\x5f\x74\x69\x6d"\ +"\x65\x20\x3d\x20\x31\x34\x36\x39\x36\x31\x31\x35\x31\x30\x0a\x73"\ +"\x65\x67\x6d\x65\x6e\x74\x5f\x63\x6f\x75\x6e\x74\x20\x3d\x20\x31"\ +"\x0a\x0a\x73\x65\x67\x6d\x65\x6e\x74\x31\x20\x7b\x0a\x73\x74\x61"\ +"\x72\x74\x5f\x65\x78\x74\x65\x6e\x74\x20\x3d\x20\x30\x0a\x65\x78"\ +"\x74\x65\x6e\x74\x5f\x63\x6f\x75\x6e\x74\x20\x3d\x20\x31\x0a\x0a"\ +"\x74\x79\x70\x65\x20\x3d\x20\x22\x73\x74\x72\x69\x70\x65\x64\x22"\ +"\x0a\x73\x74\x72\x69\x70\x65\x5f\x63\x6f\x75\x6e\x74\x20\x3d\x20"\ +"\x31\x0a\x0a\x73\x74\x72\x69\x70\x65\x73\x20\x3d\x20\x5b\x0a\x22"\ +"\x70\x76\x30\x22\x2c\x20\x30\x0a\x5d\x0a\x7d\x0a\x7d\x0a\x7d\x0a"\ +"\x7d\x0a\x23\x20\x47\x65\x6e\x65\x72\x61\x74\x65\x64\x20\x62\x79"\ +"\x20\x4c\x56\x4d\x32\x20\x76\x65\x72\x73\x69\x6f\x6e\x20\x32\x2e"\ +"\x30\x32\x2e\x31\x34\x32\x28\x32\x29\x2d\x67\x69\x74\x20\x28\x32"\ +"\x30\x31\x36\x2d\x30\x32\x2d\x31\x35\x29\x3a\x20\x57\x65\x64\x20"\ +"\x4a\x75\x6c\x20\x32\x37\x20\x31\x31\x3a\x32\x35\x3a\x31\x30\x20"\ +"\x32\x30\x31\x36\x0a\x0a\x63\x6f\x6e\x74\x65\x6e\x74\x73\x20\x3d"\ +"\x20\x22\x54\x65\x78\x74\x20\x46\x6f\x72\x6d\x61\x74\x20\x56\x6f"\ +"\x6c\x75\x6d\x65\x20\x47\x72\x6f\x75\x70\x22\x0a\x76\x65\x72\x73"\ +"\x69\x6f\x6e\x20\x3d\x20\x31\x0a\x0a\x64\x65\x73\x63\x72\x69\x70"\ +"\x74\x69\x6f\x6e\x20\x3d\x20\x22\x22\x0a\x0a\x63\x72\x65\x61\x74"\ +"\x69\x6f\x6e\x5f\x68\x6f\x73\x74\x20\x3d\x20\x22\x66\x65\x64\x6f"\ +"\x72\x61\x2e\x76\x69\x72\x74\x22\x09\x23\x20\x4c\x69\x6e\x75\x78"\ +"\x20\x66\x65\x64\x6f\x72\x61\x2e\x76\x69\x72\x74\x20\x34\x2e\x36"\ +"\x2e\x34\x2d\x33\x30\x31\x2e\x66\x63\x32\x34\x2e\x78\x38\x36\x5f"\ +"\x36\x34\x20\x23\x31\x20\x53\x4d\x50\x20\x54\x75\x65\x20\x4a\x75"\ +"\x6c\x20\x31\x32\x20\x31\x31\x3a\x35\x30\x3a\x30\x30\x20\x55\x54"\ +"\x43\x20\x32\x30\x31\x36\x20\x78\x38\x36\x5f\x36\x34\x0a\x63\x72"\ +"\x65\x61\x74\x69\x6f\x6e\x5f\x74\x69\x6d\x65\x20\x3d\x20\x31\x34"\ +"\x36\x39\x36\x31\x31\x35\x31\x30\x09\x23\x20\x57\x65\x64\x20\x4a"\ +"\x75\x6c\x20\x32\x37\x20\x31\x31\x3a\x32\x35\x3a\x31\x30\x20\x32"\ +"\x30\x31\x36\x0a\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | dd of="$1" bs=5632 seek=1 conv=notrunc +} + +aux prepare_devs 1 8 + +create_pv_with_ext_vsn1_and_vg "$dev1" + +# pvs doesn't update PV header because it holds only VG read lock +check pv_field "$dev1" pv_ext_vsn 1 +check pv_field "$dev1" pv_in_use "used" +check pv_field "$dev1" vg_name "$VG_NAME" +lvs "$VG_NAME"/"$LV_NAME" + +# an LVM command taking VG write lock will also cause PV header update to recent version +vgchange --addtag test $VG_NAME +check pv_field "$dev1" pv_ext_vsn 2 +check pv_field "$dev1" pv_in_use "used" +check pv_field "$dev1" vg_name "$VG_NAME" +lvs "$VG_NAME"/"$LV_NAME" diff --git a/test/shell/pv-min-size.sh b/test/shell/pv-min-size.sh index 59250cf..574dce7 100644 --- a/test/shell/pv-min-size.sh +++ b/test/shell/pv-min-size.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,9 +8,12 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest # use small default size - 512KB aux lvmconf 'devices/pv_min_size = 512' diff --git a/test/shell/pv-range-overflow.sh b/test/shell/pv-range-overflow.sh index 0f353dd..ab845a9 100644 --- a/test/shell/pv-range-overflow.sh +++ b/test/shell/pv-range-overflow.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008-2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,15 +8,18 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Ensure that pvmove diagnoses PE-range values 2^32 and larger.' -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_vg 2 -lvcreate -L4 -n"$lv" $vg +lvcreate -L4 -n $lv $vg # Test for the bogus diagnostic reported in BZ 284771 # http://bugzilla.redhat.com/284771. @@ -30,3 +34,4 @@ grep "Logical volume bogus not found." err # 'run the offending pvmove command' not pvmove -v -n$lv "$dev1":4294967296 "$dev2" +vgremove -ff $vg diff --git a/test/shell/pvchange-usage.sh b/test/shell/pvchange-usage.sh index d5a2ebb..1f1348d 100644 --- a/test/shell/pvchange-usage.sh +++ b/test/shell/pvchange-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,20 +8,40 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Test pvchange option values' -. lib/test -aux prepare_devs 4 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +check_changed_uuid_() { + test "$1" != "$(get pv_field "$2" uuid)" || die "UUID has not changed!" +} + +aux prepare_pvs 4 + +# check 'allocatable' pv attribute +pvcreate "$dev1" +check pv_field "$dev1" pv_attr --- +vgcreate $SHARED $vg1 "$dev1" +check pv_field "$dev1" pv_attr a-- +pvchange --allocatable n "$dev1" +check pv_field "$dev1" pv_attr u-- +vgremove -ff $vg1 +not pvchange --allocatable y "$dev1" +pvremove -ff "$dev1" for mda in 0 1 2 do # "setup pv with metadatacopies = $mda" - pvcreate "$dev4" pvcreate --metadatacopies $mda "$dev1" - vgcreate $vg1 "$dev1" "$dev4" +# cannot change allocatability for orphan PVs + fail pvchange "$dev1" -x y + fail pvchange "$dev1" -x n + vgcreate $SHARED $vg1 "$dev4" "$dev1" # "pvchange adds/dels tag to pvs with metadatacopies = $mda " pvchange "$dev1" --addtag test$mda @@ -30,36 +51,73 @@ do # "vgchange disable/enable allocation for pvs with metadatacopies = $mda (bz452982)" pvchange "$dev1" -x n - check pv_field "$dev1" pv_attr --- + pvchange "$dev1" -x n # already disabled + check pv_field "$dev1" pv_attr u-- pvchange "$dev1" -x y + pvchange "$dev1" -x y # already enabled check pv_field "$dev1" pv_attr a-- +# check we are able to change number of managed metadata areas + if test $mda -gt 0 ; then + pvchange --force --metadataignore y "$dev1" + else + # already ignored + fail pvchange --metadataignore y "$dev1" + fi # 'remove pv' vgremove $vg1 - pvremove "$dev1" "$dev4" + pvremove "$dev1" done # "pvchange uuid" pvcreate --metadatacopies 0 "$dev1" pvcreate --metadatacopies 2 "$dev2" -vgcreate $vg1 "$dev1" "$dev2" +vgcreate $SHARED $vg1 "$dev1" "$dev2" + +# Checking for different UUID after pvchange +UUID1=$(get pv_field "$dev1" uuid) pvchange -u "$dev1" +check_changed_uuid_ "$UUID1" "$dev1" + +UUID2=$(get pv_field "$dev2" uuid) pvchange -u "$dev2" -check pvlv_counts $vg1 2 0 0 +check_changed_uuid_ "$UUID2" "$dev2" + +UUID1=$(get pv_field "$dev1" uuid) +UUID2=$(get pv_field "$dev2" uuid) pvchange -u --all +check_changed_uuid_ "$UUID1" "$dev1" +check_changed_uuid_ "$UUID2" "$dev2" check pvlv_counts $vg1 2 0 0 -# "pvchange rejects uuid change under an active lv" +# some args are needed +invalid pvchange +# some PV needed +invalid pvchange --addtag tag +invalid pvchange --deltag tag +# some --all & PV can go together +invalid pvchange -a "$dev1" --addtag tag +# '-a' needs more params +invalid pvchange -a +# '-a' is searching for devs, so specifying device is invalid +invalid pvchange -a "$dev1" +fail pvchange -u "$dev1-notfound" + +# pvchange rejects uuid change under an active lv lvcreate -l 16 -i 2 -n $lv --alloc anywhere $vg1 check pvlv_counts $vg1 2 1 0 not pvchange -u "$dev1" -lvchange -an $vg1/$lv -pvchange -u "$dev1" -# "cleanup" -lvremove -f $vg1/$lv -vgremove $vg1 +vgremove -f $vg1 + +# cannot change PV tag to PV that is not in VG" +fail pvchange "$dev1" --addtag test +fail pvchange "$dev1" --deltag test -# "pvchange reject --addtag to lvm1 pv" +if test -n "$LVM_TEST_LVM1" ; then +# cannot add PV tag to lvm1 format pvcreate -M1 "$dev1" -not pvchange "$dev1" --addtag test +vgcreate $SHARED -M1 $vg1 "$dev1" +fail pvchange "$dev1" --addtag test +fi + diff --git a/test/shell/pvck-dump.sh b/test/shell/pvck-dump.sh new file mode 100644 index 0000000..39632a4 --- /dev/null +++ b/test/shell/pvck-dump.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +SIZE_MB=80 +# 4 devs each $SIZE_MB +aux prepare_devs 4 $SIZE_MB +get_devs + +dd if=/dev/zero of="$dev1" bs=1M count=2 oflag=direct +dd if=/dev/zero of="$dev2" bs=1M count=2 oflag=direct +# clear entire dev to cover mda2 +dd if=/dev/zero of="$dev3" bs=1M count=$SIZE_MB oflag=direct +dd if=/dev/zero of="$dev4" bs=1M count=2 oflag=direct + +pvcreate "$dev1" +pvcreate "$dev2" +pvcreate --pvmetadatacopies 2 "$dev3" +pvcreate --pvmetadatacopies 0 "$dev4" + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" + +pvs + +pvck --dump headers "$dev1" > h1 +pvck --dump headers "$dev2" > h2 +pvck --dump headers "$dev3" > h3 +pvck --dump headers "$dev4" > h4 + +grep "label_header at 512" h1 +grep "label_header at 512" h2 +grep "label_header at 512" h3 +grep "label_header at 512" h4 + +grep "pv_header at 544" h1 +grep "pv_header at 544" h2 +grep "pv_header at 544" h3 +grep "pv_header at 544" h4 + +grep "pv_header.disk_locn\[0\].offset 1048576" h1 +grep "pv_header.disk_locn\[0\].offset 1048576" h2 +grep "pv_header.disk_locn\[0\].offset 1048576" h3 + +grep "pv_header.disk_locn\[2\].offset 4096" h1 +grep "pv_header.disk_locn\[2\].offset 4096" h2 +grep "pv_header.disk_locn\[2\].offset 4096" h3 + +grep "pv_header.disk_locn\[2\].size 1044480" h1 +grep "pv_header.disk_locn\[2\].size 1044480" h2 +grep "pv_header.disk_locn\[2\].size 1044480" h3 + +not grep "pv_header.disk_locn\[3\].size" h4 +not grep "pv_header.disk_locn\[4\].size" h4 +not grep "mda_header" h4 + +grep "mda_header_1 at 4096" h1 +grep "mda_header_1 at 4096" h2 +grep "mda_header_1 at 4096" h3 + +grep "mda_header_1.start 4096" h1 +grep "mda_header_1.start 4096" h2 +grep "mda_header_1.start 4096" h3 + +grep "mda_header_1.size 1044480" h1 +grep "mda_header_1.size 1044480" h2 +grep "mda_header_1.size 1044480" h3 + +grep "mda_header_2 at " h3 +grep "mda_header_2.start " h3 + +grep "metadata text at " h1 +grep "metadata text at " h2 +grep "metadata text at " h3 + +not grep CHECK h1 +not grep CHECK h2 +not grep CHECK h3 + +pvck --dump metadata "$dev1" > m1 +pvck --dump metadata "$dev2" > m2 +pvck --dump metadata "$dev3" > m3 +pvck --dump metadata "$dev4" > m4 +pvck --dump metadata --pvmetadatacopies 2 "$dev3" > m3b + +grep "zero metadata copies" m4 + +diff m1 m2 +diff m1 m3 + +not diff m1 m3b > out +grep "metadata text at" out + +lvcreate -an -l1 $vg + +pvck --dump metadata_all -f all1 "$dev1" > out1 +pvck --dump metadata_all -f all2 "$dev2" > out2 +pvck --dump metadata_all -f all3 "$dev3" > out3 +pvck --dump metadata_all --pvmetadatacopies 2 -f all3b "$dev3" > out3b + +diff out1 out2 +diff out1 out3 + +grep "seqno 1" out1 +grep "seqno 1" out3b +grep "seqno 2" out1 +grep "seqno 2" out3b + +diff all1 all2 +diff all1 all3 +diff all1 all3b + +grep "seqno = 1" all1 +grep "seqno = 2" all1 + + +pvck --dump metadata_area -f area1 "$dev1" +pvck --dump metadata_area -f area2 "$dev2" +pvck --dump metadata_area -f area3 "$dev3" +pvck --dump metadata_area -f area3b "$dev3" + +diff area1 area2 +diff area1 area3 +diff area1 area3b + +vgremove -ff $vg + + +# clear entire dev to cover mda2 +dd if=/dev/zero of="$dev1" bs=1M count=$SIZE_MB oflag=direct +dd if=/dev/zero of="$dev2" bs=1M count=32 oflag=direct +dd if=/dev/zero of="$dev3" bs=1M count=32 oflag=direct +dd if=/dev/zero of="$dev4" bs=1M count=32 oflag=direct + +pvcreate --pvmetadatacopies 2 --metadatasize 32M "$dev1" + +vgcreate $SHARED -s 64K --metadatasize 32M $vg "$dev1" "$dev2" "$dev3" "$dev4" + +for i in $(seq 1 500); do echo "lvcreate -an -Zn -n lv$i -l1 $vg"; done | lvm +rm -f debug.log* + +pvck --dump headers "$dev1" > h1 + +pvck --dump metadata_search "$dev1" > m1 +grep "seqno 500" m1 || { + cat m1 + die "Missing seqno 500" +} + +# When metadatasize is 32M, headers/rounding can mean that +# we need more than the first 32M of the dev to get all the +# metadata. +dd if="$dev1" of=dev1dd bs=1M count=34 + +# Clear the header so that we force metadata_search to use +# the settings instead of getting the mda_size/mda_offset +# from the headers. +dd if=/dev/zero of="$dev1" bs=4K count=1 oflag=direct + +# Warning: these checks are based on copying specific numbers +# seen when running these commands, but these numbers could +# change as side effects of other things. That makes this +# somewhat fragile, and we might want to remove some of the +# these checks if they are hard to keep working. + +# by experimentation, mda_size for mda1 is 34598912 +pvck --dump metadata_search --settings "mda_num=1 mda_size=34598912" "$dev1" > m1b +# by experimentation, metadata 484 is the last in the mda1 buffer +grep "seqno 484" m1b +# by experimentation, metadata 485 is the last in the mda1 buffer +grep "seqno 485" m1b +grep "seqno 500" m1b + +# same results when using file as on device +pvck --dump metadata_search --settings "mda_num=1 mda_size=34598912" dev1dd > m1c +# by experimentation, metadata 484 is the last in the mda1 buffer +grep "seqno 484" m1b +# by experimentation, metadata 485 is the last in the mda1 buffer +grep "seqno 485" m1b +grep "seqno 500" m1b + +# by experimentation, mda_size for mda2 is 33554432 +pvck --dump metadata_search --settings "mda_num=2 mda_size=33554432" "$dev1" > m2 +# by experimentation, metadata 477 is the last in the mda2 buffer +grep "seqno 477" m1b +# by experimentation, metadata 478 is the last in the mda2 buffer +grep "seqno 478" m1b +grep "seqno 500" m2 + +dd if=dev1dd of="$dev1" bs=4K count=1 oflag=direct + +vgremove -ff $vg diff --git a/test/shell/pvck-repair.sh b/test/shell/pvck-repair.sh new file mode 100644 index 0000000..ac26285 --- /dev/null +++ b/test/shell/pvck-repair.sh @@ -0,0 +1,421 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013,2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + + +. lib/inittest + +SIZE=34 + +_prepare_vg() { + rm -f meta debug.log_DEBUG* + for i in "$@" ; do + dd if=/dev/zero of="$i" bs=1M count=1 oflag=direct + done + vgcreate $vg "$@" +} + +_clear_devs() { + rm -f meta debug.log_DEBUG* + for i in "$@" ; do + dd if=/dev/zero of="$i" bs=1M count=$SIZE oflag=direct + done +} + +_prepare_vg_with_copy() { + _clear_devs "$@" + vgcreate --pvmetadatacopies 2 $vg "$@" +} + +aux prepare_devs 2 $SIZE +get_devs + +# One PV, one mda, pv_header zeroed +_prepare_vg "$dev1" +dd if=/dev/zero of="$dev1" bs=512 count=2 +pvck --dump headers "$dev1" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, one mda, mda_header zeroed +_prepare_vg "$dev1" +dd if=/dev/zero of="$dev1" bs=512 count=1 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, one mda, pv_header and mda_header zeroed +_prepare_vg "$dev1" +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=1 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, one mda, metadata zeroed, use backup +_prepare_vg "$dev1" +vgcfgbackup +dd if=/dev/zero of="$dev1" bs=512 count=2 seek=9 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata_search "$dev1" || true +pvck --repair -y -f etc/backup/$vg "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, one mda, mda_header and metadata zeroed, use backup +_prepare_vg "$dev1" +vgcfgbackup +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata_search "$dev1" || true +pvck --repair -y -f etc/backup/$vg "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, one mda, pv_header, mda_header and metadata zeroed, use backup +_prepare_vg "$dev1" +vgcfgbackup +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata_search "$dev1" || true +pvck --repair -y -f etc/backup/$vg "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, two mdas, pv_header zeroed +_prepare_vg_with_copy "$dev1" +dd if=/dev/zero of="$dev1" bs=512 count=2 +pvck --dump headers "$dev1" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, two mdas, mda_header1 zeroed +_prepare_vg_with_copy "$dev1" +pvck --dump headers "$dev1" || true +dd if=/dev/zero of="$dev1" bs=512 count=1 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump metadata_search --settings mda_num=1 "$dev1" || true +pvck --dump metadata_search --settings mda_num=2 "$dev1" || true +pvck --dump metadata --settings mda_num=1 "$dev1" || true +pvck --dump metadata --settings mda_num=2 "$dev1" || true +pvck --dump metadata --settings mda_num=2 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, two mdas, pv_header and mda_header1 zeroed +_prepare_vg_with_copy "$dev1" +pvck --dump headers "$dev1" || true +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=1 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata --settings mda_num=2 "$dev1" || true +pvck --dump metadata_search "$dev1" || true +pvck --dump metadata_search --settings mda_num=2 "$dev1" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, two mdas, metadata1 zeroed, use mda2 +_prepare_vg_with_copy "$dev1" +pvck --dump headers "$dev1" || true +dd if=/dev/zero of="$dev1" bs=512 count=2 seek=9 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata --settings mda_num=2 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, two mdas, mda_header1 and metadata1 zeroed, use mda2 +_prepare_vg_with_copy "$dev1" +pvck --dump headers "$dev1" || true +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata --settings mda_num=2 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, two mdas, pv_header, mda_header1 and metadata1 zeroed, use mda2 +_prepare_vg_with_copy "$dev1" +pvck --dump headers "$dev1" || true +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata --settings mda_num=2 "$dev1" || true +pvck --dump metadata_search "$dev1" || true +pvck --dump metadata_search --settings mda_num=2 "$dev1" || true +pvck --dump metadata_search --settings "mda_num=2 seqno=1" -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, two mdas, pv_header, both mda_header, and both metadata zeroed, use backup +# only writes mda1 since there's no evidence that mda2 existed +_prepare_vg_with_copy "$dev1" +pvck --dump headers "$dev1" || true +vgcfgbackup +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=67584 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata --settings mda_num=2 "$dev1" || true +pvck --dump metadata_search "$dev1" || true +pvck --dump metadata_search --settings mda_num=2 "$dev1" || true +pvck --repair -y -f etc/backup/$vg "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, two mdas, pv_header, both mda_header, and both metadata zeroed, use backup +# writes mda1 and also mda2 because of the mda2 settings passed to repair +_prepare_vg_with_copy "$dev1" +pvck --dump headers "$dev1" || true +vgcfgbackup +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=67584 +pvck --dump headers "$dev1" || true +pvck --dump metadata "$dev1" || true +pvck --dump metadata --settings mda_num=2 "$dev1" || true +pvck --dump metadata_search "$dev1" || true +pvck --dump metadata_search --settings mda_num=2 "$dev1" || true +pvck --repair --settings "mda2_offset=34603008 mda2_size=1048576" -y -f etc/backup/$vg "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda each, pv_header and mda_header zeroed on each +_prepare_vg "$dev1" "$dev2" +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev2" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=1 seek=8 +dd if=/dev/zero of="$dev2" bs=512 count=1 seek=8 +pvck --dump headers "$dev1" +pvck --dump headers "$dev2" +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --repair -y -f meta "$dev2" +pvck --dump headers "$dev1" +pvck --dump headers "$dev2" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda each, metadata zeroed on each, use backup +_prepare_vg "$dev1" "$dev2" +vgcfgbackup +dd if=/dev/zero of="$dev1" bs=512 count=2 seek=9 +dd if=/dev/zero of="$dev2" bs=512 count=2 seek=9 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --repair -y -f etc/backup/$vg "$dev1" +pvck --repair -y -f etc/backup/$vg "$dev2" +pvck --dump headers "$dev1" +pvck --dump headers "$dev2" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda each, pv_header, mda_header and metadata zeroed on each, use backup +_prepare_vg "$dev1" "$dev2" +vgcfgbackup +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev2" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +dd if=/dev/zero of="$dev2" bs=512 count=3 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --repair -y -f etc/backup/$vg "$dev1" +pvck --repair -y -f etc/backup/$vg "$dev2" +pvck --dump headers "$dev1" +pvck --dump headers "$dev2" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda each, pv_header and mda_header zeroed on first +_prepare_vg "$dev1" "$dev2" +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=1 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --dump metadata -f meta "$dev2" +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda each, metadata zeroed on first +_prepare_vg "$dev1" "$dev2" +dd if=/dev/zero of="$dev1" bs=512 count=2 seek=9 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --dump metadata -f meta "$dev2" +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda each, pv_header, mda_header and metadata zeroed on first +_prepare_vg "$dev1" "$dev2" +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --dump metadata -f meta "$dev2" +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda on first, no mda on second, zero header on first +_clear_devs "$dev1" "$dev2" +pvcreate "$dev1" +pvcreate --pvmetadatacopies 0 "$dev2" +vgcreate $vg "$dev1" "$dev2" +dd if=/dev/zero of="$dev1" bs=512 count=2 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --dump headers "$dev1" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda on first, no mda on second, zero headers on both +_clear_devs "$dev1" "$dev2" +pvcreate "$dev1" +pvcreate --pvmetadatacopies 0 "$dev2" +vgcreate $vg "$dev1" "$dev2" +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev2" bs=512 count=2 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +pvck --repair -y --settings "mda_offset=0 mda_size=0" -f meta "$dev2" +pvck --dump headers "$dev1" +pvck --dump headers "$dev2" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda on first, no mda on second, zero all on first +_clear_devs "$dev1" "$dev2" +pvcreate "$dev1" +pvcreate --pvmetadatacopies 0 "$dev2" +vgcreate $vg "$dev1" "$dev2" +vgcfgbackup +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=3 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --repair -y -f etc/backup/$vg "$dev1" +pvck --repair -y --settings "mda_offset=0 mda_size=0" -f etc/backup/$vg "$dev2" +pvck --dump headers "$dev1" +pvck --dump headers "$dev2" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, two mda on each, pv_header and mda_header1 zeroed on both +_clear_devs "$dev1" "$dev2" +pvcreate --pvmetadatacopies 2 "$dev1" +pvcreate --pvmetadatacopies 2 "$dev2" +vgcreate $vg "$dev1" "$dev2" +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev2" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=1 seek=8 +dd if=/dev/zero of="$dev2" bs=512 count=1 seek=8 +pvck --dump headers "$dev1" +pvck --dump headers "$dev2" +pvck --dump metadata_search --settings "mda_num=2 seqno=1" -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +rm meta +pvck --dump metadata_search --settings "mda_num=2 seqno=1" -f meta "$dev2" || true +pvck --repair -y -f meta "$dev2" +rm meta +pvck --dump headers "$dev1" +pvck --dump headers "$dev2" +vgs $vg +lvcreate -l1 -an $vg + +# Two PV, one mda each, pv_header and mda_header zeroed on each, +# non-standard data_offset/mda_size on first +_clear_devs "$dev1" "$dev2" +pvcreate --metadatasize 2048k --dataalignment 128k "$dev1" +pvcreate "$dev2" +vgcreate $vg "$dev1" "$dev2" +dd if=/dev/zero of="$dev1" bs=512 count=2 +dd if=/dev/zero of="$dev1" bs=512 count=1 seek=8 +dd if=/dev/zero of="$dev2" bs=512 count=2 +dd if=/dev/zero of="$dev2" bs=512 count=1 seek=8 +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +pvck --repair -y -f meta "$dev1" +rm meta +pvck --dump metadata_search --settings seqno=1 -f meta "$dev2" || true +pvck --repair -y -f meta "$dev2" +rm meta +pvck --dump headers "$dev1" || true +pvck --dump headers "$dev2" || true +vgs $vg +lvcreate -l1 -an $vg + +# One PV, one mda, pv_header zeroed, unmatching dev name requires specified uuid +_clear_devs "$dev1" "$dev2" +vgcreate $vg "$dev1" +pvck --dump headers "$dev1" || true +UUID1=$(pvck --dump headers "$dev1" | grep pv_header.pv_uuid | awk '{print $2}') +echo "$UUID1" +dd if=/dev/zero of="$dev1" bs=512 count=2 +pvck --dump headers "$dev1" || true +pvck --dump metadata_search --settings seqno=1 -f meta "$dev1" || true +sed 's/\/dev\/mapper\/LVMTEST/\/dev\/mapper\/BADTEST/' meta > meta.bad +grep device meta +grep device meta.bad +not pvck --repair -y -f meta.bad "$dev1" +pvck --repair -y -f meta.bad --settings pv_uuid=$UUID1 "$dev1" +pvck --dump headers "$dev1" || true +vgs $vg +lvcreate -l1 -an $vg + +vgremove -f $vg diff --git a/test/shell/pvcreate-bootloaderarea.sh b/test/shell/pvcreate-bootloaderarea.sh new file mode 100644 index 0000000..cc31812 --- /dev/null +++ b/test/shell/pvcreate-bootloaderarea.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test pvcreate bootloader area support' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 1 +aux lvmconf 'global/suffix=0' 'global/units="b"' + +#COMM 'pvcreate sets/aligns bootloader area correctly' +pvcreate --metadatasize 255s --dataalignment 262144b --bootloaderareasize 614400b "$dev1" +# ba_start must be aligned based on dataalignment +# pe_start starts at next dataalignment multiple +# ba_size is the whole space in between ba_start and pe_start +check pv_field "$dev1" ba_start "262144" +check pv_field "$dev1" ba_size "786432" +check pv_field "$dev1" pe_start "1048576" + +#COMM 'pvcreate with booloader area size - test corner cases' +dev_size=$(pvs -o pv_size --noheadings "$dev1") +pv_size=$(( dev_size - 1048576 )) # device size - 1m pe_start = area for data + +# try to use the whole data area for bootloader area, remaining data area is zero then (pe_start = pv_size) +pvcreate --metadatasize 255s --bootloaderareasize ${pv_size}b --dataalignment 1048576b "$dev1" +check pv_field "$dev1" pe_start $dev_size +check pv_field "$dev1" ba_start 1048576 +check pv_field "$dev1" ba_size $pv_size + +# try to use the whole data area for bootloader area only and add one more byte - this must error out +not pvcreate --bootloaderareasize $(( pv_size + 1 )) --dataalignment 1048576b "$dev1" 2>err +grep "Bootloader area with data-aligned start must not exceed device size" err + +# restoring the PV should also restore the bootloader area correctly +pvremove -ff "$dev1" +pvcreate --metadatasize 255s --dataalignment 256k --bootloaderareasize 600k "$dev1" +vgcreate $SHARED $vg "$dev1" +vgcfgbackup -f "$TESTDIR/vg_with_ba_backup" "$vg" +pv_uuid=$(get pv_field "$dev1" pv_uuid) +vgremove -ff $vg +pvremove -ff "$dev1" +pvcreate --metadatasize 255s --dataalignment 256k --restorefile "$TESTDIR/vg_with_ba_backup" --uuid "$pv_uuid" "$dev1" +check pv_field "$dev1" ba_start "262144" +check pv_field "$dev1" ba_size "786432" +check pv_field "$dev1" pe_start "1048576" + +pvremove -ff "$dev1" diff --git a/test/shell/pvcreate-ff.sh b/test/shell/pvcreate-ff.sh new file mode 100644 index 0000000..13b05fc --- /dev/null +++ b/test/shell/pvcreate-ff.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 2 +pvcreate "$dev1" +vgcreate foo "$dev1" +pvcreate -ff -y "$dev1" +vgs +vgcreate foo "$dev1" diff --git a/test/shell/pvcreate-md-fake-hdr.sh b/test/shell/pvcreate-md-fake-hdr.sh new file mode 100644 index 0000000..856b26c --- /dev/null +++ b/test/shell/pvcreate-md-fake-hdr.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018-2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +# TODO: once code get fixed, add matching 'check' calls + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +test -f /proc/mdstat && grep -q raid1 /proc/mdstat || \ + modprobe raid1 || skip + +aux lvmconf 'devices/md_component_detection = 1' +aux extend_filter_LVMTEST "a|/dev/md|" + +aux prepare_devs 4 + +pvcreate "$dev2" + +aux mdadm_create --metadata=1.0 --level=0 --chunk=64 --raid-devices=2 "$dev1" "$dev2" + +pvs | tee out +not grep pv2 out + +vgcreate $SHARED $vg "$dev3" "$dev4" + +# create 2 disk MD raid1 array +# by default using metadata format 1.0 with data at the end of device +# passing --chunk=64 makes mdadm non functional +aux mdadm_create --metadata=1.0 --level=1 --raid-devices=2 "$dev1" "$dev2" + +mddev=$(< MD_DEV) +pvdev=$(< MD_DEV_PV) +sleep 3 +mdadm --stop "$mddev" + +# copy fake PV/VG header PV3 -> PV2 (which is however md raid1 leg) +dd if="$dev3" of="$dev2" bs=64k count=1 conv=fdatasync + +# remove VG on PV3 & PV4 +vgremove -f $vg + +aux udev_wait +# too bad 'dd' wakes up md array reassembling +mdadm --detail "$mddev" || true +mdadm --stop "$mddev" || true +sleep 1 + +# print what blkid thinks about each PV +for i in "$dev1" "$dev2" "$dev3" "$dev4" +do + blkid -c /dev/null "$i" || echo "Unknown signature" +done + +# expect open count for each PV to be 0 +dmsetup info -c + +pvs "$dev2" "$dev3" || true + +# still expect open count for each PV to be 0 +dmsetup info -c + +pvs "$dev3" "$dev2" || true + +# and again we expect open count for each PV to be 0 +dmsetup info -c +dmsetup table + +# even after 3 second of possible hidden raid array assembling +sleep 3 +dmsetup info -c + +# if for any reason array went up - stop it again +if mdadm --detail "$mddev" ; then + mdadm --stop "$mddev" + aux udev_wait + should not mdadm --detail "$mddev" +fi + +# now reassemble array from PV1 & PV2 +aux mdadm_assemble --verbose "$mddev" "$dev1" "$dev2" + +sleep 1 + +# and let 'fake hdr' to be fixed from master/primary leg +# (when mdadm supports repair) +if mdadm --action=repair "$mddev" ; then + sleep 1 + pvscan -vvvv + # should be showing correctly PV3 & PV4 + pvs "$dev3" "$dev4" +fi diff --git a/test/shell/pvcreate-metadata0.sh b/test/shell/pvcreate-metadata0.sh index 9154e75..c732a2e 100644 --- a/test/shell/pvcreate-metadata0.sh +++ b/test/shell/pvcreate-metadata0.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # Testcase for bugzilla #450651 @@ -15,7 +16,10 @@ # # 'Test pvcreate without metadata on all pvs' -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_devs 2 128 @@ -24,9 +28,7 @@ pvcreate "$dev1" pvcreate --metadatacopies 0 "$dev2" # "check lv snapshot" -vgcreate -c n $vg "$dev1" "$dev2" -lvcreate -n $lv -l 60%FREE $vg +vgcreate $SHARED $vg "$dev1" "$dev2" +lvcreate -aey -n $lv -l 60%FREE $vg lvcreate -s -n $lv2 -l 10%FREE $vg/$lv -pvdisplay -lvdisplay vgremove -f $vg diff --git a/test/shell/pvcreate-operation-md.sh b/test/shell/pvcreate-operation-md.sh index 9bdc4a1..19f2145 100644 --- a/test/shell/pvcreate-operation-md.sh +++ b/test/shell/pvcreate-operation-md.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2009 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2009-2015 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 @@ -7,143 +8,129 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest # skip this test if mdadm or sfdisk (or others) aren't available -which mdadm || skip which sfdisk || skip -which perl || skip -which awk || skip -which cut || skip - -test -f /proc/mdstat && grep -q raid0 /proc/mdstat || \ - modprobe raid0 || skip aux lvmconf 'devices/md_component_detection = 1' -aux lvmconf 'devices/filter = [ "a|/dev/md.*|", "a/dev\/mapper\/.*$/", "r/.*/" ]' -aux prepare_devs 2 +aux extend_filter_md "a|/dev/md|" -# 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 - aux udev_wait - mdadm --stop "$mddev" || true - aux udev_wait - if [ -b "$mddev" ]; then - # mdadm doesn't always cleanup the device node - sleep 2 - rm -f "$mddev" - fi -} - -cleanup_md_and_teardown() { - cleanup_md - aux teardown -} +aux prepare_devs 2 # create 2 disk MD raid0 array (stripe_width=128K) -test -b "$mddev" && skip -mdadm --create --metadata=1.0 "$mddev" --auto=md --level 0 --raid-devices=2 --chunk 64 "$dev1" "$dev2" -trap 'cleanup_md_and_teardown' EXIT # cleanup this MD device at the end of the test -test -b "$mddev" || skip +aux mdadm_create --metadata=1.0 --level=0 --chunk=64 --raid-devices=2 "$dev1" "$dev2" +mddev=$(< MD_DEV) + +pvdev="$mddev" # 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 + "$pvdev" + +check pv_field "$pvdev" pe_start "1.00m" # 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 - + "$pvdev" +check pv_field "$pvdev" pe_start "1.00m" # Test newer topology-aware alignment detection # - first added to 2.6.31 but not "reliable" until 2.6.33 -if kernel_at_least 2 6 33 ; then - pv_align="1.00m" +if aux kernel_at_least 2 6 33 ; then # 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 + --config 'devices { md_chunk_alignment=0 }' "$pvdev" + check pv_field "$pvdev" pe_start "1.00m" + pvremove "$pvdev" fi # partition MD array directly, depends on blkext in Linux >= 2.6.28 -if kernel_at_least 2 6 28 ; then +if aux kernel_at_least 2 6 28 ; then # create one partition sfdisk "$mddev" < parent lookup via sysfs paths - not pvcreate --metadatasize 128k "$mddev" + not pvcreate --metadatasize 128k "$pvdev" # 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} - - # in case the system is running without devtmpfs /dev - # wait here for created device node on tmpfs - aux udev_wait "$mddev_p" - test -b "$mddev_p" || skip - # 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 ] && kernel_at_least 2 6 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" + if aux kernel_at_least 2 6 33 ; then + # in case the system is running without devtmpfs /dev + # wait here for created device node on tmpfs + # test "$DM_DEV_DIR" = "/dev" || cp -LR "${mddev}p1" "${pvdev%/*}" + + pvcreate --metadatasize 128k "${pvdev}p1" + + maj=$(($(stat -L --printf=0x%t "${mddev}p1"))) + min=$(($(stat -L --printf=0x%T "${mddev}p1"))) + + ls /sys/dev/block/$maj:$min/ + ls /sys/dev/block/$maj:$min/holders/ + cat /sys/dev/block/$maj:$min/dev + cat /sys/dev/block/$maj:$min/stat + cat /sys/dev/block/$maj:$min/size + + sysfs_alignment_offset="/sys/dev/block/$maj:$min/alignment_offset" + [ -f "$sysfs_alignment_offset" ] && \ + alignment_offset=$(< "$sysfs_alignment_offset") || \ + alignment_offset=0 + + # default alignment is 1M, add alignment_offset + pv_align=$(( 1048576 + alignment_offset )) + check pv_field "${pvdev}p1" pe_start $pv_align --units b --nosuffix + + pvremove "${pvdev}p1" + # test "$DM_DEV_DIR" = "/dev" || rm -f "${pvdev}p1" fi fi +aux cleanup_md_dev +aux wipefs_a "$dev1" "$dev2" + # Test newer topology-aware alignment detection w/ --dataalignment override -if kernel_at_least 2 6 33 ; then - cleanup_md - pvcreate -f "$dev1" - pvcreate -f "$dev2" +if aux kernel_at_least 2 6 33 ; then + + aux mdadm_create --metadata=1.0 --level 0 --chunk=1024 --raid-devices=2 "$dev1" "$dev2" + mddev=$(< MD_DEV) - # create 2 disk MD raid0 array (stripe_width=2M) - test -b "$mddev" && skip - mdadm --create --metadata=1.0 "$mddev" --auto=md --level 0 --raid-devices=2 --chunk 1024 "$dev1" "$dev2" - test -b "$mddev" || skip + pvdev="$mddev" # 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 + --config 'devices { md_chunk_alignment=0 }' "$pvdev" + + # to see the processing of scanning + pvs -vvvv + + check pv_field "$pvdev" pe_start "2.00m" # 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 + --config 'devices { md_chunk_alignment=0 }' "$pvdev" + check pv_field "$pvdev" pe_start "192.00k" + + aux cleanup_md_dev + aux wipefs_a "$dev1" "$dev2" fi diff --git a/test/shell/pvcreate-operation.sh b/test/shell/pvcreate-operation.sh index 55fff4e..5cf4fd6 100644 --- a/test/shell/pvcreate-operation.sh +++ b/test/shell/pvcreate-operation.sh @@ -1,4 +1,6 @@ -# Copyright (C) 2008 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2012 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 @@ -6,23 +8,35 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux lvmconf 'devices/md_component_detection = 1' aux prepare_devs 4 -for mdatype in 1 2 +if test -n "$LVM_TEST_LVM1" ; then +mdatypes='1 2' +else +mdatypes='2' +fi + +for mdatype in $mdatypes do # pvcreate (lvm$mdatype) refuses to overwrite an mounted filesystem (bz168330) test ! -d mnt && mkdir mnt if mke2fs "$dev1"; then mount "$dev1" mnt not pvcreate -M$mdatype "$dev1" 2>err - grep "Can't open "$dev1" exclusively. Mounted filesystem?" err + grep "Can't open $dev1 exclusively. Mounted filesystem?" err umount "$dev1" + # wipe the filesystem signature for next + # pvcreate to not issue any prompts + dd if=/dev/zero of="$dev1" bs=1K count=2 fi # pvcreate (lvm$mdatype) succeeds when run repeatedly (pv not in a vg) (bz178216) @@ -32,7 +46,7 @@ do # pvcreate (lvm$mdatype) fails when PV belongs to VG # pvcreate -M$mdatype "$dev1" - vgcreate -M$mdatype $vg1 "$dev1" + vgcreate $SHARED -M$mdatype $vg1 "$dev1" not pvcreate -M$mdatype "$dev1" vgremove -f $vg1 @@ -41,7 +55,7 @@ do # 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" + vgcreate $SHARED -M$mdatype $vg1 "$dev1" # pvcreate a second time on $dev2 and $dev1 not pvcreate -M$mdatype "$dev2" "$dev1" @@ -63,7 +77,7 @@ 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" +vgcreate $SHARED $vg1 "$dev1" "$dev2" not pvcreate "$dev1" vgremove -f $vg1 pvremove -f "$dev2" "$dev1" @@ -71,7 +85,7 @@ pvremove -f "$dev2" "$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" +vgcreate $SHARED $vg1 "$dev1" "$dev2" pvcreate -ff -y "$dev1" vgreduce --removemissing $vg1 vgremove -ff $vg1 @@ -88,7 +102,7 @@ done # pvcreate (lvm2) fails writing LVM label at sector 4 not pvcreate --labelsector 4 "$dev1" -backupfile=$PREFIX.mybackupfile +backupfile="$PREFIX.mybackupfile" uuid1=freddy-fred-fred-fred-fred-fred-freddy uuid2=freddy-fred-fred-fred-fred-fred-fredie bogusuuid=fred @@ -104,25 +118,70 @@ 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" +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" +vgcfgbackup -f "$backupfile" +not pvcreate --uuid $uuid2 --restorefile "$backupfile" "$dev2" # vgcfgrestore of a VG containing a PV with zero PEs (bz #820116) # (use case: one PV in a VG used solely to keep metadata) -size_mb=$(($(blockdev --getsz $dev1) / 2048)) -pvcreate --metadatasize $size_mb $dev1 -vgcreate $vg1 $dev1 -vgcfgbackup -f $backupfile -vgcfgrestore -f $backupfile $vg1 +size_mb=$(($(blockdev --getsz "$dev1") / 2048)) +pvcreate --metadatasize $size_mb "$dev1" +vgcreate $SHARED $vg1 "$dev1" +vgcfgbackup -f "$backupfile" +vgcfgrestore -f "$backupfile" "$vg1" vgremove -f $vg1 -pvremove -f $dev1 +pvremove -f "$dev1" + +# pvcreate --restorefile should handle --dataalignment and --dataalignmentoffset +# and check it's compatible with pe_start value being restored +# X * dataalignment + dataalignmentoffset == pe_start +pvcreate --norestorefile --uuid "$uuid1" --dataalignment 600k --dataalignmentoffset 32k "$dev1" +vgcreate $SHARED $vg1 "$dev1" +vgcfgbackup -f "$backupfile" "$vg1" +vgremove -ff $vg1 +pvremove -ff "$dev1" +# the dataalignment and dataalignmentoffset is ignored here since they're incompatible with pe_start +pvcreate --restorefile "$backupfile" --uuid "$uuid1" --dataalignment 500k --dataalignmentoffset 10k "$dev1" 2> err +grep "incompatible with restored pe_start value" err +# 300k is multiple of 600k so this should pass +pvcreate --restorefile "$backupfile" --uui "$uuid1" --dataalignment 300k --dataalignmentoffset 32k "$dev1" 2> err +not grep "incompatible with restored pe_start value" err + +# pvcreate rejects non-existent uuid given with restorefile +not pvcreate --uuid "$uuid2" --restorefile "$backupfile" "$dev1" 2> err +grep "Can't find uuid $uuid2 in backup file $backupfile" err + +# pvcreate rejects restorefile without uuid +not pvcreate --restorefile "$backupfile" "$dev1" 2>err +grep -- "--uuid is required with --restorefile" err + +# pvcreate rejects uuid restore with multiple volumes specified +not pvcreate --uuid "$uuid1" --restorefile "$backupfile" "$dev1" "$dev2" 2>err +grep "Can only set uuid on one volume at once" err + +# --bootloaderareasize not allowed with pvcreate --restorefile +not pvcreate --uuid "$uuid1" --restorefile "$backupfile" --bootloaderareasize 1m "$dev1" "$dev2" 2>err +grep -- "Command does not accept option combination: --bootloaderareasize with --restorefile" err + +rm -f "$backupfile" + +pvcreate --norestorefile --uuid $uuid1 "$dev1" +vgcreate $SHARED --physicalextentsize 1m $vg1 "$dev1" +vgcfgbackup -f "$backupfile" "$vg1" +vgremove -ff "$vg1" +pvremove -ff "$dev1" + +# when 2nd mda requested on pvcreate --restorefile and not enough space for it, pvcreate fails +not pvcreate --restorefile "$backupfile" --uuid $uuid1 --metadatacopies 2 "$dev1" 2>err +grep "Not enough space available for metadata area with index 1 on PV $dev1" err + +rm -f "$backupfile" # pvcreate wipes swap signature when forced -dd if=/dev/zero of="$dev1" bs=1024 count=64 +dd if=/dev/zero of="$dev1" bs=64k count=1 oflag=direct mkswap "$dev1" blkid -c /dev/null "$dev1" | grep "swap" pvcreate -f "$dev1" diff --git a/test/shell/pvcreate-restore.sh b/test/shell/pvcreate-restore.sh new file mode 100644 index 0000000..45c27bf --- /dev/null +++ b/test/shell/pvcreate-restore.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 4 + +lvcreate --type snapshot -s -L10 -n $lv1 $vg --virtualsize 2T +lvcreate --type snapshot -s -L10 -n $lv2 $vg --virtualsize 4T +lvcreate --type snapshot -s -L10 -n $lv3 $vg --virtualsize 4194300M + +aux extend_filter_LVMTEST +aux lvmconf "devices/scan_lvs = 1" +aux extend_devices "$DM_DEV_DIR/$vg/$lv1" +aux extend_devices "$DM_DEV_DIR/$vg/$lv2" +aux extend_devices "$DM_DEV_DIR/$vg/$lv3" + +vgcreate $vg1 "$DM_DEV_DIR/$vg/$lv2" + +vgcfgbackup -f vgback $vg1 + +UUID=$(get pv_field "$DM_DEV_DIR/$vg/$lv2" uuid) +pvremove -ff -y "$DM_DEV_DIR/$vg/$lv2" + +# too small to fit +fail pvcreate --restorefile vgback --uuid $UUID "$DM_DEV_DIR/$vg/$lv1" + +# still does not fit +fail pvcreate --restorefile vgback --uuid $UUID "$DM_DEV_DIR/$vg/$lv3" + +pvcreate --restorefile vgback --uuid $UUID "$DM_DEV_DIR/$vg/$lv2" + +vgremove -ff $vg diff --git a/test/shell/pvcreate-usage.sh b/test/shell/pvcreate-usage.sh index 148802f..a61a2c3 100644 --- a/test/shell/pvcreate-usage.sh +++ b/test/shell/pvcreate-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,12 +8,16 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA test_description='Test pvcreate option values' + +SKIP_WITH_LVMPOLLD=1 PAGESIZE=$(getconf PAGESIZE) +# MDA_SIZE_MIN defined in lib/format_text/layout.h +MDA_SIZE_MIN=$(( 8 * PAGESIZE )) -. lib/test +. lib/inittest aux prepare_devs 4 @@ -22,18 +27,18 @@ 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" +#COMM 'pvcreate rejects metadatasize that is less than minimum size' +not pvcreate --dataalignment $(( MDA_SIZE_MIN / 2 ))b --metadatasize $(( MDA_SIZE_MIN / 2 ))b "$dev1" 2>err +grep "Metadata area size too small" err + +#COMM 'pvcreate accepts metadatasize that is at least the minimum size' +pvcreate --dataalignment ${MDA_SIZE_MIN}b --metadatasize ${MDA_SIZE_MIN}b "$dev1" #Verify vg_mda_size is smaller pv_mda_size pvcreate --metadatasize 512k "$dev1" pvcreate --metadatasize 96k "$dev2" -vgcreate $vg "$dev1" "$dev2" +vgcreate $SHARED $vg "$dev1" "$dev2" +pvs -o +pv_mda_size check compare_fields vgs $vg vg_mda_size pvs "$dev2" pv_mda_size vgremove $vg @@ -81,7 +86,6 @@ not pvcreate --labelsector 1000000000000 "$dev1" #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' @@ -89,12 +93,12 @@ not pvcreate --dataalignment 1e "$dev1" # amuse shell experts #check pv_field "$dev1" pe_start $(($(getconf PAGESIZE)/1024))".00k" -#COMM 'pvcreate sets data offset directly' -pvcreate --dataalignment 512k "$dev1" +#COMM 'pvcreate sets data alignment directly' +pvcreate --dataalignment 512K --config 'metadata {pvmetadatasize=255}' "$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 }' +vgcreate $SHARED $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" @@ -110,6 +114,31 @@ case "$PAGESIZE" in *) pv_align="133.00k" ;; esac +# pe_start is a multiple of dataalignment, leaving enough +# space between mda_start and pe_end for the specified +# metadata size. +# +# With page size 4k, mda_start is rounded up start at 4k. +# The chosen multiple of data alignment (3.5k) is 38: +# 3.5k * 38 = 133k for pe_start +# Space available for metadata between mda_start and pe_end is: +# 133k - 4k = 129k mda size, which is large enough for the +# specified mda size of 128k. +# +# With page size 8k, mda_start is rouned up to start at 8k. +# The chosen multiple of data alignment (3.5k) is 39: +# 3.5k * 39 = 136.5k for pe_start +# Space available for metadata between mda_start and pe_end is: +# 136.5k - 8k = 128.5k mda size, which is large enough for the +# specified mda size of 128k. +# +# With page size 64k, mda_start is rouned up to start at 64k. +# The chosen multiple of data alignment (3.5k) is 55: +# 3.5k * 55 = 192.5k for pe_start +# Space available for metadata between mda_start and pe_end is: +# 192.5k - 64k = 128.5k mda size, which is large enough for the +# specified mda size of 128k. + pvcreate --metadatasize 128k --dataalignment 3.5k "$dev1" check pv_field "$dev1" pe_start $pv_align @@ -128,27 +157,12 @@ 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" +vgcreate $SHARED $vg "$dev1" "$dev2" vgcfgbackup -f backup.$$ $vg sed 's/pe_start = [0-9]*/pe_start = 0/' backup.$$ > backup.$$1 vgcfgrestore -f backup.$$1 $vg @@ -171,14 +185,14 @@ for ignore in y n; do 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" + echo "vgcreate $SHARED 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))" + vgcreate $SHARED $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))" + check vg_field $vg vg_mda_used_count "$(( mdacp * 2 ))" fi check vg_field $vg vg_mda_copies "unmanaged" vgremove $vg diff --git a/test/shell/pvmove-abort-all.sh b/test/shell/pvmove-abort-all.sh new file mode 100644 index 0000000..872db04 --- /dev/null +++ b/test/shell/pvmove-abort-all.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check pvmove --abort behaviour for all VGs and PVs + +SKIP_WITH_LVMLOCKD=1 + +# Ignore known failure when clvmd is processing sequences of commands for two VGs in parallel - 2015/07/17 agk +# CLVMD: ioctl/libdm-iface.c:1940 Internal error: Performing unsafe table load while 3 device(s) are known to be suspended: (253:19) +export DM_ABORT_ON_INTERNAL_ERRORS=0 + +. lib/inittest + +aux lvmconf 'activation/raid_region_size = 16' + +aux target_at_least dm-mirror 1 10 0 || skip +# Throttle mirroring +aux throttle_dm_mirror || skip + +aux prepare_pvs 6 60 + +vgcreate -s 512k $vg "$dev1" "$dev2" +pvcreate --metadatacopies 0 "$dev3" +vgextend $vg "$dev3" +vgcreate -s 512k $vg1 "$dev4" "$dev5" +pvcreate --metadatacopies 0 "$dev6" +vgextend $vg1 "$dev6" + +for mode in "--atomic" "" ; +do +for backgroundarg in "-b" "" ; +do + +# Create multisegment LV +lvcreate -an -Zn -l30 -n $lv1 $vg "$dev1" +lvcreate -an -Zn -l30 -n $lv2 $vg "$dev2" +lvcreate -an -Zn -l30 -n $lv1 $vg1 "$dev4" +lvextend -l+30 -n $vg1/$lv1 "$dev5" + +cmd1=(pvmove -i1 $backgroundarg $mode "$dev1" "$dev3") +cmd2=(pvmove -i1 $backgroundarg $mode "$dev2" "$dev3") +cmd3=(pvmove -i1 $backgroundarg $mode -n $vg1/$lv1 "$dev4" "$dev6") + + +if test -z "$backgroundarg" ; then + "${cmd1[@]}" & + aux wait_pvmove_lv_ready "$vg-pvmove0" + "${cmd2[@]}" & + "${cmd3[@]}" & + aux wait_pvmove_lv_ready "$vg-pvmove1" "$vg1-pvmove0" +else + LVM_TEST_TAG="kill_me_$PREFIX" "${cmd1[@]}" + LVM_TEST_TAG="kill_me_$PREFIX" "${cmd2[@]}" + LVM_TEST_TAG="kill_me_$PREFIX" "${cmd3[@]}" +fi + +# test removal of all pvmove LVs +pvmove --abort + +# check if proper pvmove was canceled +get lv_field $vg name -a | tee out +not grep "^\[pvmove" out +get lv_field $vg1 name -a | tee out +not grep "^\[pvmove" out + +lvremove -ff $vg $vg1 + +wait +aux kill_tagged_processes +done +done + +# Restore throttling +aux restore_dm_mirror + +vgremove -ff $vg $vg1 diff --git a/test/shell/pvmove-abort.sh b/test/shell/pvmove-abort.sh new file mode 100644 index 0000000..86f2417 --- /dev/null +++ b/test/shell/pvmove-abort.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check pvmove --abort behaviour when specific device is requested + +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +aux lvmconf 'activation/raid_region_size = 16' + +aux target_at_least dm-mirror 1 10 0 || skip +# Throttle mirroring +aux throttle_dm_mirror || skip + +aux prepare_pvs 3 90 + +vgcreate -s 512k $vg "$dev1" "$dev2" +pvcreate --metadatacopies 0 "$dev3" +vgextend $vg "$dev3" + +for mode in "--atomic" "" ; +do +for backgroundarg in "-b" "" ; +do + +# Create multisegment LV +lvcreate -an -Zn -l60 -n $lv1 $vg "$dev1" +lvcreate -an -Zn -l80 -n $lv2 $vg "$dev2" + +cmd1=(pvmove -i1 $backgroundarg $mode "$dev1" "$dev3") +cmd2=(pvmove -i1 $backgroundarg $mode "$dev2" "$dev3") + +if test -z "$backgroundarg" ; then + "${cmd1[@]}" & + aux wait_pvmove_lv_ready "$vg-pvmove0" + "${cmd2[@]}" & + aux wait_pvmove_lv_ready "$vg-pvmove1" +else + LVM_TEST_TAG="kill_me_$PREFIX" "${cmd1[@]}" + LVM_TEST_TAG="kill_me_$PREFIX" "${cmd2[@]}" +fi +# remove specific device +pvmove --abort "$dev1" + +# check if proper pvmove was canceled +get lv_field $vg name -a | tee out +not grep -E "^\[?pvmove0" out +grep -E "^\[?pvmove1" out + +# remove any remaining pvmoves in progress +pvmove --abort + +lvremove -ff $vg + +wait +aux kill_tagged_processes +done +done + +# Restore throttling +aux restore_dm_mirror + +vgremove -ff $vg diff --git a/test/shell/pvmove-all-segtypes.sh b/test/shell/pvmove-all-segtypes.sh new file mode 100644 index 0000000..38b5267 --- /dev/null +++ b/test/shell/pvmove-all-segtypes.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description="ensure pvmove works with all common segment types" + +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +which md5sum || skip + +aux prepare_vg 5 20 + +# Each of the following tests does: +# 1) Create two LVs - one linear and one other segment type +# The two LVs will share a PV. +# 2) Move both LVs together +# 3) Move only the second LV by name + +# Testing pvmove of linear LV +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey -l 2 -n $lv1 $vg "$dev1" +lvextend -l+2 $vg/${lv1}_foo "$dev1" +lvextend -l+2 $vg/${lv1} "$dev1" +lvextend -l+2 $vg/${lv1}_foo "$dev2" +lvextend -l+2 $vg/${lv1} "$dev3" +check lv_tree_on $vg ${lv1}_foo "$dev1" "$dev2" +check lv_tree_on $vg $lv1 "$dev1" "$dev3" +check lv_field $vg/${lv1}_foo seg_count 3 +check lv_field $vg/$lv1 seg_count 3 +aux mkdev_md5sum $vg $lv1 +dmsetup table +pvmove --atomic "$dev1" "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev2" "$dev5" +check lv_tree_on $vg $lv1 "$dev3" "$dev5" +# Also check 2 segments from $dev1 were merged on $dev5 +check lv_field $vg/${lv1}_foo seg_count 2 +check lv_field $vg/$lv1 seg_count 2 +check dev_md5sum $vg $lv1 +pvmove -n $lv1 "$dev5" "$dev4" +check lv_tree_on $vg $lv1 "$dev3" "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev2" "$dev5" +check dev_md5sum $vg $lv1 +lvremove -ff $vg + +# Testing pvmove of stripe LV +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey -l 4 -i 2 -n $lv1 $vg "$dev1" "$dev2" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" +aux mkdev_md5sum $vg $lv1 +pvmove "$dev1" "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check lv_tree_on $vg $lv1 "$dev2" "$dev5" +check dev_md5sum $vg $lv1 +pvmove -n $lv1 "$dev5" "$dev4" +check lv_tree_on $vg $lv1 "$dev2" "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check dev_md5sum $vg $lv1 +lvremove -ff $vg + +if test -e LOCAL_CLVMD ; then +#FIXME these tests currently fail end require cmirrord +echo "$(should false)FIXME!!! pvmove in clustered VG not fully supported!" +else + +# Testing pvmove of mirror LV +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey -l 2 --type mirror -m 1 -n $lv1 $vg "$dev1" "$dev2" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" +aux mkdev_md5sum $vg $lv1 +pvmove "$dev1" "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check lv_tree_on $vg $lv1 "$dev2" "$dev5" +check dev_md5sum $vg $lv1 +pvmove -n $lv1 "$dev5" "$dev4" +check lv_tree_on $vg $lv1 "$dev2" "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check dev_md5sum $vg $lv1 +lvremove -ff $vg + +# Dummy LV and snap share dev1, while origin is on dev2 +# Testing pvmove of snapshot LV +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey -l 2 -n $lv1 $vg "$dev2" +lvcreate -s $vg/$lv1 -l 2 -n snap "$dev1" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg snap "$dev1" +aux mkdev_md5sum $vg snap +pvmove "$dev1" "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check lv_tree_on $vg snap "$dev5" +check dev_md5sum $vg snap +pvmove -n snap "$dev5" "$dev4" +check lv_tree_on $vg snap "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check dev_md5sum $vg snap +lvremove -ff $vg +fi + +vgremove -ff $vg diff --git a/test/shell/pvmove-background.sh b/test/shell/pvmove-background.sh new file mode 100644 index 0000000..6a158e4 --- /dev/null +++ b/test/shell/pvmove-background.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check pvmove behavior when it's progress and machine is rebooted + +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +aux prepare_vg 3 + +for mode in "--atomic" "" +do +lvcreate -aey -l1 -n $lv1 $vg "$dev1" + +lvs -o +devices | tee out +grep "$dev1" out + +LVM_TEST_TAG="kill_me_$PREFIX" pvmove $mode -i 1 -b "$dev1" "$dev2" +sleep 5 # arbitrary... +lvs -o +devices | tee out +not grep "pvmove" out +lvs -o +devices | tee out +grep "$dev2" out + +lvremove -ff $vg +done diff --git a/test/shell/pvmove-basic.sh b/test/shell/pvmove-basic.sh index e95fc36..c02354d 100644 --- a/test/shell/pvmove-basic.sh +++ b/test/shell/pvmove-basic.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 Red Hat, Inc. All rights reserved. # Copyright (C) 2007 NEC Corporation # # This copyrighted material is made available to anyone wishing to use, @@ -8,94 +9,84 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA test_description="ensure that pvmove works with basic options" -. lib/test +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest -which mkfs.ext2 || skip which md5sum || skip # --------------------------------------------------------------------- # Utilities -lvdev_() { - echo "$DM_DEV_DIR/$1/$2" +create_vg_() { + vgcreate -s 128k "$vg" "${DEVICES[@]}" } -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 +# --------------------------------------------------------------------- +# Common environment setup/cleanup for each sub testcases +prepare_lvs_() { + lvcreate -aey -l2 -n $lv1 $vg "$dev1" + check lv_on $vg $lv1 "$dev1" + lvcreate -aey -l9 -i3 -n $lv2 $vg "$dev2" "$dev3" "$dev4" + check lv_on $vg $lv2 "$dev2" "$dev3" "$dev4" + lvextend -l+2 $vg/$lv1 "$dev2" + check lv_on $vg $lv1 "$dev1" "$dev2" + lvextend -l+2 $vg/$lv1 "$dev3" + lvextend -l+2 $vg/$lv1 "$dev1" + check lv_on $vg $lv1 "$dev1" "$dev2" "$dev3" + lvcreate -aey -l1 -n $lv3 $vg "$dev2" + check lv_on $vg $lv3 "$dev2" + aux mkdev_md5sum $vg $lv1 + aux mkdev_md5sum $vg $lv2 + aux mkdev_md5sum $vg $lv3 + get lv_devices "$vg/$lv1" > "${lv1}_devs" + get lv_devices "$vg/$lv2" > "${lv2}_devs" + get lv_devices "$vg/$lv3" > "${lv3}_devs" + lvs -a -o name,size,seg_pe_ranges $vg + vgcfgbackup -f bak-$$ $vg } -save_dev_sum_() { - mkfs.ext2 $1 > /dev/null && md5sum $1 > md5.$(basename $1) +# Restore metadata content, since data are pvmove-ed +# original content should be preserved +restore_lvs_() { + vgcfgrestore -f bak-$$ $vg + vgchange -aey $vg } -check_dev_sum_() { - md5sum -c md5.$(basename $1) +lvs_not_changed_() { + for i in "${@}"; do + get lv_devices "$vg/$i" | tee out + diff "${i}_devs" out || \ + (cat "${i}_devs"; die "Devices for LV $vg/$i differs!") + done } -create_vg_() { - vgcreate -c n -s 128k $vg $(cat DEVICES) +check_and_cleanup_lvs_() { + check dev_md5sum $vg $lv1 + check dev_md5sum $vg $lv2 + check dev_md5sum $vg $lv3 + get lv_field $vg name -a >out + not grep "^\[pvmove" out + vgchange -an $vg + lvremove -ff $vg + (dm_table | not grep $vg) || \ + die "ERROR: lvremove did leave some mappings in DM behind!" } + # --------------------------------------------------------------------- # Initialize PVs and VGs -#aux prepare_vg 5 30 aux prepare_pvs 5 5 -create_vg_ - -# --------------------------------------------------------------------- -# Common environment setup/cleanup for each sub testcases -FIRST="" +get_devs -prepare_lvs_() { - lvcreate -l2 -n $lv1 $vg "$dev1" - test -z "$FIRST" && lv_is_on_ $vg/$lv1 "$dev1" - lvcreate -l9 -i3 -n $lv2 $vg "$dev2" "$dev3" "$dev4" - test -z "$FIRST" && lv_is_on_ $vg/$lv2 "$dev2" "$dev3" "$dev4" - lvextend -l+2 $vg/$lv1 "$dev2" - test -z "$FIRST" && lv_is_on_ $vg/$lv1 "$dev1" "$dev2" - lvextend -l+2 $vg/$lv1 "$dev3" - test -z "$FIRST" && lv_is_on_ $vg/$lv1 "$dev1" "$dev2" "$dev3" - lvextend -l+2 $vg/$lv1 "$dev1" - test -z "$FIRST" && lv_is_on_ $vg/$lv1 "$dev1" "$dev2" "$dev3" "$dev1" - lvcreate -l1 -n $lv3 $vg "$dev2" - test -z "$FIRST" && lv_is_on_ $vg/$lv3 "$dev2" - save_dev_sum_ $(lvdev_ $vg $lv1) - save_dev_sum_ $(lvdev_ $vg $lv2) - save_dev_sum_ $(lvdev_ $vg $lv3) - if test -z "$FIRST" ; then - get lv_field $vg/$lv1 devices > ${lv1}_devs - get lv_field $vg/$lv2 devices > ${lv2}_devs - get lv_field $vg/$lv3 devices > ${lv3}_devs - fi - FIRST=done -} - -lv_not_changed_() { - get lv_field $1 devices > out - diff $(basename $1)_devs out -} +create_vg_ -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 - (dm_table | not grep $vg) || \ - die "ERROR: lvremove did leave some some mappings in DM behind!" -} +for mode in "--atomic" "" +do #COMM "check environment setup/cleanup" prepare_lvs_ @@ -108,276 +99,265 @@ check_and_cleanup_lvs_ # 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 +restore_lvs_ +pvmove $mode -i1 -n $vg/$lv1 "$dev2" "$dev5" +check lv_on $vg $lv1 "$dev1" "$dev5" "$dev3" +lvs_not_changed_ $lv2 $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 -i0 -n $vg/$lv1 "$dev1" "$dev4" -lv_is_on_ $vg/$lv1 "$dev4" "$dev2" "$dev3" "$dev4" -lv_not_changed_ $vg/$lv2 -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 -n $vg/$lv1 "$dev1" "$dev4" +check lv_on $vg $lv1 "$dev4" "$dev2" "$dev3" +lvs_not_changed_ $lv2 $lv3 check_and_cleanup_lvs_ #COMM "the 2nd seg of 3-segs LV is moved: from pv2 of lv1 to pv4" -prepare_lvs_ -pvmove -i0 -n $vg/$lv1 "$dev2" "$dev4" -lv_is_on_ $vg/$lv1 "$dev1" "$dev4" "$dev3" "$dev1" -lv_not_changed_ $vg/$lv2 -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 -n $vg/$lv1 "$dev2" "$dev4" +check lv_on $vg $lv1 "$dev1" "$dev4" "$dev3" +lvs_not_changed_ $lv2 $lv3 check_and_cleanup_lvs_ #COMM "the 3rd seg of 3-segs LV is moved: from pv3 of lv1 to pv4" -prepare_lvs_ -pvmove -i0 -n $vg/$lv1 "$dev3" "$dev4" -lv_is_on_ $vg/$lv1 "$dev1" "$dev2" "$dev4" "$dev1" -lv_not_changed_ $vg/$lv2 -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 -n $vg/$lv1 "$dev3" "$dev4" +check lv_on $vg $lv1 "$dev1" "$dev2" "$dev4" +lvs_not_changed_ $lv2 $lv3 check_and_cleanup_lvs_ # --- # multiple LVs matching #COMM "1 out of 3 LVs is moved: from pv4 to pv5" -prepare_lvs_ -pvmove -i0 "$dev4" "$dev5" -lv_not_changed_ $vg/$lv1 -lv_is_on_ $vg/$lv2 "$dev2" "$dev3" "$dev5" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 "$dev4" "$dev5" +check lv_on $vg $lv2 "$dev2" "$dev3" "$dev5" +lvs_not_changed_ $lv1 $lv3 check_and_cleanup_lvs_ #COMM "2 out of 3 LVs are moved: from pv3 to pv5" -prepare_lvs_ -pvmove -i0 "$dev3" "$dev5" -lv_is_on_ $vg/$lv1 "$dev1" "$dev2" "$dev5" "$dev1" -lv_is_on_ $vg/$lv2 "$dev2" "$dev5" "$dev4" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 "$dev3" "$dev5" +check lv_on $vg $lv1 "$dev1" "$dev2" "$dev5" +check lv_on $vg $lv2 "$dev2" "$dev5" "$dev4" +lvs_not_changed_ $lv3 check_and_cleanup_lvs_ #COMM "3 out of 3 LVs are moved: from pv2 to pv5" -prepare_lvs_ -pvmove -i0 "$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" +restore_lvs_ +pvmove $mode -i0 "$dev2" "$dev5" +check lv_on $vg $lv1 "$dev1" "$dev5" "$dev3" +check lv_on $vg $lv2 "$dev5" "$dev3" "$dev4" +check lv_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 -i0 -n $vg/$lv2 "$dev2" "$dev1" -lv_not_changed_ $vg/$lv1 -lv_is_on_ $vg/$lv2 "$dev1" "$dev3" "$dev4" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 -n $vg/$lv2 "$dev2" "$dev1" +check lv_on $vg $lv2 "$dev1" "$dev3" "$dev4" +lvs_not_changed_ $lv1 $lv3 check_and_cleanup_lvs_ #COMM "move the 2nd stripe: from pv3 of lv2 to pv1" -prepare_lvs_ -pvmove -i0 -n $vg/$lv2 "$dev3" "$dev1" -lv_not_changed_ $vg/$lv1 -lv_is_on_ $vg/$lv2 "$dev2" "$dev1" "$dev4" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 -n $vg/$lv2 "$dev3" "$dev1" +check lv_on $vg $lv2 "$dev2" "$dev1" "$dev4" +lvs_not_changed_ $lv1 $lv3 check_and_cleanup_lvs_ #COMM "move the 3rd stripe: from pv4 of lv2 to pv1" -prepare_lvs_ -pvmove -i0 -n $vg/$lv2 "$dev4" "$dev1" -lv_not_changed_ $vg/$lv1 -lv_is_on_ $vg/$lv2 "$dev2" "$dev3" "$dev1" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 -n $vg/$lv2 "$dev4" "$dev1" +check lv_on $vg $lv2 "$dev2" "$dev3" "$dev1" +lvs_not_changed_ $lv1 $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 -i0 "$dev2":0-0 "$dev5" -lv_not_changed_ $vg/$lv1 -lv_is_on_ $vg/$lv2 "$dev5" "$dev2" "$dev3" "$dev4" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 "$dev2":0-0 "$dev5" +check lv_on $vg $lv2 "$dev5" "$dev2" "$dev3" "$dev4" +lvs_not_changed_ $lv1 $lv3 check_and_cleanup_lvs_ - +#exit 0 #COMM "match to the middle of segment: from pv2:1-1 to pv5" -prepare_lvs_ -pvmove -i0 "$dev2":1-1 "$dev5" -lv_not_changed_ $vg/$lv1 -lv_is_on_ $vg/$lv2 "$dev2" "$dev5" "$dev2" "$dev3" "$dev4" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 "$dev2":1-1 "$dev5" +check lv_on $vg $lv2 "$dev2" "$dev3" "$dev4" "$dev5" +lvs_not_changed_ $lv1 $lv3 check_and_cleanup_lvs_ #COMM "match to the end of segment: from pv2:2-2 to pv5" -prepare_lvs_ -pvmove -i0 "$dev2":2-2 "$dev5" -lv_not_changed_ $vg/$lv1 -lv_is_on_ $vg/$lv2 "$dev2" "$dev5" "$dev3" "$dev4" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 "$dev2":2-2 "$dev5" +check lv_on $vg $lv2 "$dev2" "$dev5" "$dev3" "$dev4" +lvs_not_changed_ $lv1 $lv3 check_and_cleanup_lvs_ # --- # destination segment splitted #COMM "no destination split: from pv2:0-2 to pv5" -prepare_lvs_ -pvmove -i0 "$dev2":0-2 "$dev5" -lv_not_changed_ $vg/$lv1 -lv_is_on_ $vg/$lv2 "$dev5" "$dev3" "$dev4" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 "$dev2":0-2 "$dev5" +check lv_on $vg $lv2 "$dev5" "$dev3" "$dev4" +lvs_not_changed_ $lv1 $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 -i0 --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 +restore_lvs_ +pvmove $mode -i0 --alloc anywhere "$dev2":0-2 "$dev5":5-5 "$dev4":5-6 +check lv_on $vg $lv2 "$dev5" "$dev4" "$dev3" +lvs_not_changed_ $lv1 $lv3 check_and_cleanup_lvs_ #COMM "destination split into 3: from pv2:0-2 to {pv3,4,5}:5-5" -prepare_lvs_ -pvmove -i0 --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 +restore_lvs_ +pvmove $mode -i0 --alloc anywhere "$dev2":0-2 "$dev3":5-5 "$dev4":5-5 "$dev5":5-5 +check lv_on $vg $lv2 "$dev3" "$dev4" "$dev5" +lvs_not_changed_ $lv1 $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 -i0 "$dev3":0-2 "$dev3":5-7 +restore_lvs_ +not pvmove $mode -i0 "$dev3":0-2 "$dev3":5-7 # "(cleanup previous test)" -lv_not_changed_ $vg/$lv1 -lv_not_changed_ $vg/$lv2 -lv_not_changed_ $vg/$lv3 +lvs_not_changed_ $lv1 $lv2 $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 -i0 --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 +restore_lvs_ +pvmove $mode -i0 --alloc anywhere "$dev3":0-2 "$dev3":5-7 +check lv_on $vg $lv2 "$dev2" "$dev3" "$dev4" +lvs_not_changed_ $lv1 $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 -i0 --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 +restore_lvs_ +#lvs -a -o name,size,seg_pe_ranges $vg +#LV2 1.12m @TESTDIR@/dev/mapper/@PREFIX@pv2:0-2 @TESTDIR@/dev/mapper/@PREFIX@pv3:0-2 @TESTDIR@/dev/mapper/@PREFIX@pv4:0-2 + +pvmove $mode -i0 --alloc anywhere "$dev3":0-2 "$dev3":5-7 "$dev5":5-6 "$dev4":5-5 + +#lvs -a -o name,size,seg_pe_ranges $vg +# Hmm is this correct ? - why pv2 is split +#LV2 1.12m @TESTDIR@/dev/mapper/@PREFIX@pv2:0-1 @TESTDIR@/dev/mapper/@PREFIX@pv5:5-6 @TESTDIR@/dev/mapper/@PREFIX@pv4:0-1 +#LV2 1.12m @TESTDIR@/dev/mapper/@PREFIX@pv2:2-2 @TESTDIR@/dev/mapper/@PREFIX@pv3:5-5 @TESTDIR@/dev/mapper/@PREFIX@pv4:2-2 +check lv_on $vg $lv2 "$dev2" "$dev3" "$dev4" "$dev5" +lvs_not_changed_ $lv1 $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 -i0 --alloc contiguous "$dev2":0-2 "$dev5":5-5 "$dev4":5-6 +restore_lvs_ +not pvmove $mode -i0 --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 +lvs_not_changed_ $lv1 $lv2 $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 -i0 --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 +restore_lvs_ +pvmove $mode -i0 --alloc contiguous "$dev2":0-2 "$dev5":0-0 "$dev5":3-5 "$dev4":5-6 +check lv_on $vg $lv2 "$dev5" "$dev3" "$dev4" +lvs_not_changed_ $lv1 $lv3 check_and_cleanup_lvs_ # --- # multiple segments in a LV #COMM "multiple source LVs: from pv3 to pv5" -prepare_lvs_ -pvmove -i0 "$dev3" "$dev5" -lv_is_on_ $vg/$lv1 "$dev1" "$dev2" "$dev5" -lv_is_on_ $vg/$lv2 "$dev2" "$dev5" "$dev4" -lv_not_changed_ $vg/$lv3 +restore_lvs_ +pvmove $mode -i0 "$dev3" "$dev5" +check lv_on $vg $lv1 "$dev1" "$dev2" "$dev5" +check lv_on $vg $lv2 "$dev2" "$dev5" "$dev4" +lvs_not_changed_ $lv3 check_and_cleanup_lvs_ # --- # move inactive LV #COMM "move inactive LV: from pv2 to pv5" -prepare_lvs_ +restore_lvs_ lvchange -an $vg/$lv1 lvchange -an $vg/$lv3 -pvmove -i0 "$dev2" "$dev5" -lv_is_on_ $vg/$lv1 "$dev1" "$dev5" "$dev3" -lv_is_on_ $vg/$lv2 "$dev5" "$dev3" "$dev4" -lv_is_on_ $vg/$lv3 "$dev5" +pvmove $mode -i0 "$dev2" "$dev5" +check lv_on $vg $lv1 "$dev1" "$dev5" "$dev3" +check lv_on $vg $lv2 "$dev5" "$dev3" "$dev4" +check lv_on $vg $lv3 "$dev5" check_and_cleanup_lvs_ # --- # other failure cases #COMM "no PEs to move: from pv3 to pv1" -prepare_lvs_ -pvmove -i0 "$dev3" "$dev1" -not pvmove -i0 "$dev3" "$dev1" +restore_lvs_ +pvmove $mode -i0 "$dev3" "$dev1" +not pvmove $mode -i0 "$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 lv_on $vg $lv1 "$dev1" "$dev2" "$dev1" +check lv_on $vg $lv2 "$dev2" "$dev1" "$dev4" +lvs_not_changed_ $lv3 check_and_cleanup_lvs_ #COMM "no space available: from pv2:0-0 to pv1:0-0" -prepare_lvs_ -not pvmove -i0 "$dev2":0-0 "$dev1":0-0 +restore_lvs_ +not pvmove $mode -i0 "$dev2":0-0 "$dev1":0-0 # "(cleanup previous test)" -lv_not_changed_ $vg/$lv1 -lv_not_changed_ $vg/$lv2 -lv_not_changed_ $vg/$lv3 +lvs_not_changed_ $lv1 $lv2 $lv3 check_and_cleanup_lvs_ #COMM 'same source and destination: from pv1 to pv1' -prepare_lvs_ -not pvmove -i0 "$dev1" "$dev1" +restore_lvs_ +not pvmove $mode -i0 "$dev1" "$dev1" #"(cleanup previous test)" -lv_not_changed_ $vg/$lv1 -lv_not_changed_ $vg/$lv2 -lv_not_changed_ $vg/$lv3 +lvs_not_changed_ $lv1 $lv2 $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 +restore_lvs_ +not pvmove $mode --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 +lvs_not_changed_ $lv1 $lv2 $lv3 check_and_cleanup_lvs_ # --------------------------------------------------------------------- #COMM "pvmove abort" -prepare_lvs_ -pvmove -i100 -b "$dev1" "$dev3" +restore_lvs_ +LVM_TEST_TAG="kill_me_$PREFIX" pvmove $mode -i100 -b "$dev1" "$dev3" pvmove --abort check_and_cleanup_lvs_ #COMM "pvmove out of --metadatacopies 0 PV (bz252150)" vgremove -ff $vg -pvcreate $(cat DEVICES) +pvcreate "${DEVICES[@]}" pvcreate --metadatacopies 0 "$dev1" "$dev2" create_vg_ -lvcreate -l4 -n $lv1 $vg "$dev1" -pvmove "$dev1" +lvcreate -aey -l4 -n $lv1 $vg "$dev1" +pvmove $mode "$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 +not pvmove $mode -i 1 "$dev2" +dmsetup info --noheadings -c -o suspended $vg-$lv1 +test "$(dmsetup info --noheadings -c -o suspended "$vg-$lv1")" = "Active" +if dmsetup info $vg-pvmove0_mimage_0 > /dev/null; then + dmsetup remove $vg-pvmove0 $vg-pvmove0_mimage_0 $vg-pvmove0_mimage_1 +else + dmsetup remove $vg-pvmove0 +fi + +lvremove -ff $vg +done diff --git a/test/shell/pvmove-cache-segtypes.sh b/test/shell/pvmove-cache-segtypes.sh new file mode 100644 index 0000000..0cd3a16 --- /dev/null +++ b/test/shell/pvmove-cache-segtypes.sh @@ -0,0 +1,177 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description="ensure pvmove works with the cache segment types" +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +# pvmove fails when a RAID LV is the origin of a cache LV +# pvmoving cache types is currently disabled in tools/pvmove.c +# So, for now we set everything up and make sure pvmove /isn't/ allowed. +# This allows us to ensure that it is disallowed even when there are +# stacking complications to consider. + +which md5sum || skip + +aux have_cache 1 3 0 || skip +# for stacking +aux have_thin 1 8 0 || skip +aux have_raid 1 4 2 || skip + +aux prepare_vg 5 80 + +for mode in "--atomic" "" +do +# Each of the following tests does: +# 1) Create two LVs - one linear and one other segment type +# The two LVs will share a PV. +# 2) Move both LVs together +# 3) Move only the second LV by name + +# Testing pvmove of cache-pool LV (can't check contents though) +############################################################### +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate --type cache-pool -n ${lv1}_pool -l 4 $vg "$dev1" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg ${lv1}_pool "$dev1" + +pvmove $mode "$dev1" "$dev5" 2>&1 | tee out +lvs -a -o+devices $vg +check lv_tree_on $vg ${lv1}_pool "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev5" + +lvremove -ff $vg +dmsetup info -c | not grep $vg + +# Testing pvmove of origin LV +############################# +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate --type cache-pool -n ${lv1}_pool -l 4 $vg "$dev5" +lvcreate --type cache -n $lv1 -l 8 $vg/${lv1}_pool "$dev1" + +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg ${lv1}_pool_cpool "$dev5" +check lv_tree_on $vg ${lv1} "$dev1" + +aux mkdev_md5sum $vg $lv1 +pvmove $mode "$dev1" "$dev3" 2>&1 | tee out +check lv_tree_on $vg ${lv1}_foo "$dev3" +#check lv_tree_on $vg ${lv1}_pool "$dev5" +lvs -a -o name,attr,devices $vg +check lv_tree_on $vg ${lv1} "$dev3" +#check dev_md5sum $vg $lv1 + +#pvmove $mode -n $lv1 "$dev3" "$dev1" +#check lv_tree_on $vg ${lv1}_foo "$dev3" +#check lv_tree_on $vg ${lv1}_pool "$dev5" +#check lv_tree_on $vg ${lv1} "$dev1" +#check dev_md5sum $vg $lv1 +lvremove -ff $vg +dmsetup info -c | not grep $vg + +# Testing pvmove of a RAID origin LV +#################################### +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate --type raid1 -m 1 -l 8 -n $lv1 $vg "$dev1" "$dev2" +lvcreate --type cache -l 4 -n ${lv1}_pool $vg/$lv1 "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg ${lv1} "$dev1" "$dev2" +check lv_tree_on $vg ${lv1}_pool_cpool "$dev5" + +aux mkdev_md5sum $vg $lv1 +pvmove $mode "$dev1" "$dev3" 2>&1 | tee out +check lv_tree_on $vg ${lv1}_foo "$dev3" +lvs -a -o+devices $vg +not check lv_tree_on $vg ${lv1} "$dev1" +#check lv_tree_on $vg ${lv1}_pool "$dev5" +#check dev_md5sum $vg $lv1 -- THIS IS WHERE THINGS FAIL IF PVMOVE NOT DISALLOWED + +#pvmove $mode -n $lv1 "$dev3" "$dev1" +#check lv_tree_on $vg ${lv1}_foo "$dev3" +#check lv_tree_on $vg ${lv1} "$dev1" "$dev2" +#check lv_tree_on $vg ${lv1}_pool "$dev5" +#check dev_md5sum $vg $lv1 +lvremove -ff $vg +dmsetup info -c | not grep $vg + +# Testing pvmove of a RAID cachepool (metadata and data) +######################################################## +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate --type raid1 -L 6M -n meta $vg "$dev1" "$dev2" +lvcreate --type raid1 -L 4M -n ${lv1}_pool $vg "$dev1" "$dev2" +lvconvert --yes --type cache-pool $vg/${lv1}_pool --poolmetadata $vg/meta +lvcreate --type cache -n $lv1 -L 8M $vg/${lv1}_pool "$dev5" + +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg ${lv1}_pool_cpool "$dev1" "$dev2" +check lv_tree_on $vg ${lv1} "$dev5" + +aux mkdev_md5sum $vg $lv1 +# This will move ${lv1}_foo and the cache-pool data & meta +# LVs, both of which contain a RAID1 _rimage & _rmeta LV - 5 total LVs +pvmove $mode "$dev1" "$dev3" 2>&1 | tee out +check lv_tree_on $vg ${lv1}_foo "$dev3" +not check lv_tree_on $vg ${lv1}_pool_cpool "$dev1" +#check lv_tree_on $vg ${lv1} "$dev5" +#check dev_md5sum $vg $lv1 + +#pvmove $mode -n ${lv1}_pool "$dev3" "$dev1" +#check lv_tree_on $vg ${lv1}_foo "$dev3" +#check lv_tree_on $vg ${lv1}_pool "$dev1" "$dev2" +#check lv_tree_on $vg ${lv1} "$dev5" +#check dev_md5sum $vg $lv1 +lvremove -ff $vg +dmsetup info -c | not grep $vg + +# Testing pvmove of Thin-pool on cache LV on RAID +################################################# +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +# RAID for cachepool +lvcreate --type raid1 -m 1 -L 6M -n meta $vg "$dev1" "$dev2" +lvcreate --type raid1 -m 1 -L 4M -n cachepool $vg "$dev1" "$dev2" +lvconvert --yes --type cache-pool $vg/cachepool --poolmetadata $vg/meta +# RAID for thin pool data LV +lvcreate --type raid1 -m 1 -L 8 -n thinpool $vg "$dev3" "$dev4" +# Convert thin pool data to a cached LV +lvconvert --type cache -Zy $vg/thinpool --cachepool $vg/cachepool +# Create simple thin pool meta +lvcreate -aey -L 2M -n meta $vg "$dev1" +# Use thin pool data LV to build a thin pool +lvconvert --yes --thinpool $vg/thinpool --poolmetadata $vg/meta +# Create a thin lv for fun +lvcreate -T $vg/thinpool -V 20 -n thin_lv + +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg cachepool_cpool "$dev1" "$dev2" +check lv_tree_on $vg thinpool "$dev1" "$dev3" "$dev4" + +aux mkdev_md5sum $vg thin_lv +lvs -a -o name,attr,devices $vg +# Should move ${lv1}_foo and thinpool_tmeta from dev1 to dev5 +pvmove $mode "$dev1" "$dev5" 2>&1 | tee out +lvs -a -o name,attr,devices $vg +check lv_tree_on $vg ${lv1}_foo "$dev5" +not check lv_tree_on $vg cachepool_cpool "$dev1" +check lv_tree_on $vg thinpool "$dev3" "$dev4" "$dev5" # Move non-cache tmeta +#check dev_md5sum $vg/thin_lv + +#pvmove $mode -n $vg/cachepool "$dev5" "$dev1" +#check lv_tree_on $vg ${lv1}_foo "$dev5" +#check lv_tree_on $vg $vg/cachepool "$dev1" "$dev2" +#check lv_tree_on $vg $vg/thinpool "$dev3" "$dev4" +#check dev_md5sum $vg/thin_lv + +lvremove -ff $vg +dmsetup info -c | not grep $vg + +done diff --git a/test/shell/pvmove-lvs.sh b/test/shell/pvmove-lvs.sh new file mode 100644 index 0000000..754f86a --- /dev/null +++ b/test/shell/pvmove-lvs.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description="ensure pvmove works with lvs" +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +aux throttle_dm_mirror || skip + +aux prepare_vg 5 180 + +lvcreate -aey -L30 -n $lv1 $vg "$dev1" +lvextend -L+30 $vg/$lv1 "$dev2" +lvextend -L+30 $vg/$lv1 "$dev1" +lvextend -L+30 $vg/$lv1 "$dev2" +lvextend -L+30 $vg/$lv1 "$dev1" + +pvmove -b "$dev1" "$dev5" 2>&1 | tee out + +#lvchange -an $vg/$lv1 +lvs -a $vg + +pvmove --abort + +lvremove -ff $vg diff --git a/test/shell/pvmove-raid-segtypes.sh b/test/shell/pvmove-raid-segtypes.sh new file mode 100644 index 0000000..6584b74 --- /dev/null +++ b/test/shell/pvmove-raid-segtypes.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description="ensure pvmove works with raid segment types" +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +which md5sum || skip + +aux have_raid 1 3 5 || skip + +aux prepare_pvs 5 20 +get_devs + +vgcreate -s 128k "$vg" "${DEVICES[@]}" + +for mode in "--atomic" "" +do +# Each of the following tests does: +# 1) Create two LVs - one linear and one other segment type +# The two LVs will share a PV. +# 2) Move both LVs together +# 3) Move only the second LV by name + +# Testing pvmove of RAID1 LV +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey --regionsize 16K -l 2 --type raid1 -m 1 -n $lv1 $vg "$dev1" "$dev2" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" +aux mkdev_md5sum $vg $lv1 +pvmove $mode "$dev1" "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check lv_tree_on $vg $lv1 "$dev2" "$dev5" +check dev_md5sum $vg $lv1 +pvmove $mode -n $lv1 "$dev5" "$dev4" +check lv_tree_on $vg $lv1 "$dev2" "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check dev_md5sum $vg $lv1 +lvremove -ff $vg + +# Testing pvmove of RAID10 LV +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey -l 4 --type raid10 -i 2 -m 1 -n $lv1 $vg \ + "$dev1" "$dev2" "$dev3" "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4" +aux mkdev_md5sum $vg $lv1 + +# Check collocation of SubLVs is prohibited +not pvmove $mode -n ${lv1}_rimage_0 "$dev1" "$dev2" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4" +not pvmove $mode -n ${lv1}_rimage_1 "$dev2" "$dev1" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4" +not pvmove $mode -n ${lv1}_rmeta_0 "$dev1" "$dev3" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4" + +pvmove $mode "$dev1" "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check lv_tree_on $vg $lv1 "$dev2" "$dev3" "$dev4" "$dev5" +check dev_md5sum $vg $lv1 +pvmove $mode -n $lv1 "$dev5" "$dev1" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check dev_md5sum $vg $lv1 +lvremove -ff $vg + +# Testing pvmove of RAID5 LV +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey -l 4 --type raid5 -i 2 -n $lv1 $vg \ + "$dev1" "$dev2" "$dev3" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" +aux mkdev_md5sum $vg $lv1 +pvmove $mode "$dev1" "$dev5" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check lv_tree_on $vg $lv1 "$dev2" "$dev3" "$dev5" +check dev_md5sum $vg $lv1 +pvmove $mode -n $lv1 "$dev5" "$dev4" +check lv_tree_on $vg $lv1 "$dev2" "$dev3" "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check dev_md5sum $vg $lv1 + +lvremove -ff $vg +done + +vgremove -ff $vg diff --git a/test/shell/pvmove-restart.sh b/test/shell/pvmove-restart.sh new file mode 100644 index 0000000..1669187 --- /dev/null +++ b/test/shell/pvmove-restart.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check pvmove behavior when it's progress and machine is rebooted + +. lib/inittest + +aux prepare_pvs 3 60 + +vgcreate $SHARED -s 128k $vg "$dev1" "$dev2" +pvcreate --metadatacopies 0 "$dev3" +vgextend $vg "$dev3" + +# Slowdown writes +# (FIXME: generates interesting race when not used) +aux delay_dev "$dev3" 0 800 "$(get first_extent_sector "$dev3"):" +test -e HAVE_DM_DELAY || skip + +for mode in "--atomic" "" +do + +# Create multisegment LV +lvcreate -an -Zn -l5 -n $lv1 $vg "$dev1" +lvextend -l+10 $vg/$lv1 "$dev2" +lvextend -l+5 $vg/$lv1 "$dev1" +lvextend -l+10 $vg/$lv1 "$dev2" + +pvmove -i10 -n $vg/$lv1 "$dev1" "$dev3" $mode & +PVMOVE=$! +# Let's wait a bit till pvmove starts and kill it +aux wait_pvmove_lv_ready "$vg-pvmove0" +kill -9 $PVMOVE + +if test -e LOCAL_LVMPOLLD; then + aux prepare_lvmpolld +fi + +wait + +# Simulate reboot - forcibly remove related devices + +# First take down $lv1 then it's pvmove0 +j=0 +for i in $lv1 pvmove0 pvmove0_mimage_0 pvmove0_mimage_1 ; do + while dmsetup status "$vg-$i" ; do + dmsetup remove "$vg-$i" && break + j=$(( j + 1 )) + test $j -le 100 || die "Cannot take down devices." + sleep .1; + done +done +dmsetup table | grep $PREFIX + +# Check we really have pvmove volume +check lv_attr_bit type $vg/pvmove0 "p" + +if test -e LOCAL_CLVMD ; then + # giveup all clvmd locks (faster then restarting clvmd) + # no deactivation happen, nodes are already removed + #vgchange -an $vg + # FIXME: However above solution has one big problem + # as clvmd starts to abort on internal errors on various + # errors, based on the fact pvmove is killed -9 + # Restart clvmd + kill "$(< LOCAL_CLVMD)" + for i in $(seq 1 100) ; do + test $i -eq 100 && die "Shutdown of clvmd is too slow." + pgrep clvmd || break + sleep .1 + done # wait for the pid removal + aux prepare_clvmd +fi + +# Only PVs should be left in table... +dmsetup table + +# Restart pvmove +# use exclusive activation to have usable pvmove without cmirrord +LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey $vg +aux wait_pvmove_lv_ready "$vg-pvmove0" +dmsetup table + +pvmove --abort "$dev1" + +lvs -a -o+devices $vg + +lvremove -ff $vg +aux kill_tagged_processes +done + +# Restore delayed device back +aux delay_dev "$dev3" + +vgremove -ff $vg diff --git a/test/shell/pvmove-resume-1.sh b/test/shell/pvmove-resume-1.sh new file mode 100644 index 0000000..0068ab2 --- /dev/null +++ b/test/shell/pvmove-resume-1.sh @@ -0,0 +1,244 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check whether all available pvmove resume methods works as expected. +# lvchange is able to resume pvmoves in progress. + +# 2 pvmove LVs in 2 VGs (1 per VG) + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_CLVMD=1 + +. lib/inittest + +aux prepare_pvs 4 30 + +vgcreate -s 128k $vg "$dev1" +vgcreate -s 128k $vg1 "$dev2" +pvcreate --metadatacopies 0 "$dev3" +pvcreate --metadatacopies 0 "$dev4" +vgextend $vg "$dev3" +vgextend $vg1 "$dev4" + +# $1 resume fn +test_pvmove_resume() { + lvcreate -an -Zn -l30 -n $lv1 $vg + lvcreate -an -Zn -l30 -n $lv1 $vg1 + + aux delay_dev "$dev3" 0 30 "$(get first_extent_sector "$dev3"):" + test -e HAVE_DM_DELAY || { lvremove -f $vg $vg1; return 0; } + aux delay_dev "$dev4" 0 30 "$(get first_extent_sector "$dev4"):" + + pvmove -i5 "$dev1" & + PVMOVE=$! + aux wait_pvmove_lv_ready "$vg-pvmove0" + kill $PVMOVE + test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld + + pvmove -i5 "$dev2" & + PVMOVE=$! + aux wait_pvmove_lv_ready "$vg1-pvmove0" + kill $PVMOVE + test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld + wait + + aux remove_dm_devs "$vg-$lv1" "$vg1-$lv1" "$vg-pvmove0" "$vg1-pvmove0" + + check lv_attr_bit type $vg/pvmove0 "p" + check lv_attr_bit type $vg1/pvmove0 "p" + + if test -e LOCAL_CLVMD ; then + # giveup all clvmd locks (faster then restarting clvmd) + # no deactivation happen, nodes are already removed + #vgchange -an $vg + # FIXME: However above solution has one big problem + # as clvmd starts to abort on internal errors on various + # errors, based on the fact pvmove is killed -9 + # Restart clvmd + kill "$(< LOCAL_CLVMD)" + for i in $(seq 1 100) ; do + test $i -eq 100 && die "Shutdown of clvmd is too slow." + test -e "$CLVMD_PIDFILE" || break + sleep .1 + done # wait for the pid removal + aux prepare_clvmd + fi + + # call resume function (see below) + # with expected number of spawned + # bg polling as parameter + $1 2 + + aux enable_dev "$dev3" "$dev4" + + for i in {100..0} ; do + lvs -ao name $vg $vg1 | grep "\[pvmove" || break + sleep .1 + done + # wait for 10 secs at max + test $i -eq 0 && die "Pvmove is too slow or does not progress." + + aux kill_tagged_processes + + lvremove -ff $vg $vg1 +} + +lvchange_single() { + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg/$lv1 + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg1/$lv1 + + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 1 "$vg1/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq $1 + fi +} + +lvchange_all() { + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg/$lv1 $vg1/$lv1 + + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 1 "$vg1/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq $1 + fi +} + +vgchange_single() { + LVM_TEST_TAG="kill_me_$PREFIX" vgchange -aey $vg + LVM_TEST_TAG="kill_me_$PREFIX" vgchange -aey $vg1 + + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 1 "$vg1/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq "$1" + fi +} + +vgchange_all() { + LVM_TEST_TAG="kill_me_$PREFIX" vgchange -aey $vg $vg1 + + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 1 "$vg1/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq "$1" + fi +} + +pvmove_fg() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg $vg1 + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 0 "$vg1/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + get lv_field $vg1 name -a | grep -E "^\[?pvmove0" + + # disable delay device + # fg pvmove would take ages to complete otherwise + aux enable_dev "$dev3" "$dev4" + + pvmove +} + +pvmove_bg() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg $vg1 + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 0 "$vg1/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + get lv_field $vg1 name -a | grep -E "^\[?pvmove0" + + LVM_TEST_TAG="kill_me_$PREFIX" pvmove -b -i0 +} + +pvmove_fg_single() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 0 "$vg1/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + get lv_field $vg1 name -a | grep -E "^\[?pvmove0" + + # disable delay device + # fg pvmove would take ages to complete otherwise + aux enable_dev "$dev3" "$dev4" + + pvmove "$dev1" + pvmove "$dev2" +} + +pvmove_bg_single() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 0 "$vg1/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + get lv_field $vg1 name -a | grep -E "^\[?pvmove0" + + LVM_TEST_TAG="kill_me_$PREFIX" pvmove -b "$dev1" + LVM_TEST_TAG="kill_me_$PREFIX" pvmove -b "$dev2" +} + +test_pvmove_resume lvchange_single +test_pvmove_resume lvchange_all +test_pvmove_resume vgchange_single +test_pvmove_resume vgchange_all +test_pvmove_resume pvmove_fg +test_pvmove_resume pvmove_fg_single +test_pvmove_resume pvmove_bg +test_pvmove_resume pvmove_bg_single + +vgremove -ff $vg $vg1 diff --git a/test/shell/pvmove-resume-2.sh b/test/shell/pvmove-resume-2.sh new file mode 100644 index 0000000..3dea743 --- /dev/null +++ b/test/shell/pvmove-resume-2.sh @@ -0,0 +1,197 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check whether all available pvmove resume methods works as expected. +# lvchange is able to resume pvmoves in progress. + +# Moving 2 LVs in VG variant + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_CLVMD=1 + +. lib/inittest + +aux prepare_pvs 2 30 + +vgcreate -s 128k $vg "$dev1" +pvcreate --metadatacopies 0 "$dev2" +vgextend $vg "$dev2" + +test_pvmove_resume() { + # 2 LVs on same device + lvcreate -an -Zn -l15 -n $lv1 $vg "$dev1" + lvcreate -an -Zn -l15 -n $lv2 $vg "$dev1" + + aux delay_dev "$dev2" 0 30 "$(get first_extent_sector "$dev2"):" + + pvmove -i5 "$dev1" & + PVMOVE=$! + aux wait_pvmove_lv_ready "$vg-pvmove0" + kill $PVMOVE + + test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld + wait + aux remove_dm_devs "$vg-$lv1" "$vg-$lv2" "$vg-pvmove0" + + check lv_attr_bit type $vg/pvmove0 "p" + + if test -e LOCAL_CLVMD ; then + # giveup all clvmd locks (faster then restarting clvmd) + # no deactivation happen, nodes are already removed + #vgchange -an $vg + # FIXME: However above solution has one big problem + # as clvmd starts to abort on internal errors on various + # errors, based on the fact pvmove is killed -9 + # Restart clvmd + kill "$(< LOCAL_CLVMD)" + for i in {1..100} ; do + test $i -eq 100 && die "Shutdown of clvmd is too slow." + test -e "$CLVMD_PIDFILE" || break + sleep .1 + done # wait for the pid removal + aux prepare_clvmd + fi + + # call resume function (see below) + # with expected number of spawned + # bg polling as parameter + $1 1 + + aux enable_dev "$dev2" + + for i in {100..0} ; do # wait for 10 secs at max + get lv_field $vg name -a | grep -E "^\[?pvmove" || break + sleep .1 + done + test $i -gt 0 || die "Pvmove is too slow or does not progress." + + aux kill_tagged_processes + + lvremove -ff $vg +} + +lvchange_single() { + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg/$lv1 + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg/$lv2 +} + +lvchange_all() { + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg/$lv1 $vg/$lv2 + + # we don't want to spawn more than $1 background pollings + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove0" || should false + elif test -e HAVE_DM_DELAY; then + test "$(aux count_processes_with_tag)" -eq "$1" || { + # FIXME: currently lvm2 is spawning polling process for each LV + echo "Lvchange spawns pvmove per activated LV" + } + fi +} + +vgchange_single() { + LVM_TEST_TAG="kill_me_$PREFIX" vgchange -aey $vg + + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove0" + elif test -e HAVE_DM_DELAY; then + test "$(aux count_processes_with_tag)" -eq "$1" + fi +} + +pvmove_fg() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + + aux enable_dev "$dev2" + + pvmove +} + +pvmove_bg() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + + LVM_TEST_TAG="kill_me_$PREFIX" pvmove -b +} + +pvmove_fg_single() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + + aux enable_dev "$dev2" + + pvmove "$dev1" +} + +pvmove_bg_single() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + + LVM_TEST_TAG="kill_me_$PREFIX" pvmove -b "$dev1" +} + +test_pvmove_resume lvchange_single +test_pvmove_resume lvchange_all +test_pvmove_resume vgchange_single +test_pvmove_resume pvmove_fg +test_pvmove_resume pvmove_fg_single +test_pvmove_resume pvmove_bg +test_pvmove_resume pvmove_bg_single + +vgremove -ff $vg diff --git a/test/shell/pvmove-resume-multiseg.sh b/test/shell/pvmove-resume-multiseg.sh new file mode 100644 index 0000000..5cebd99 --- /dev/null +++ b/test/shell/pvmove-resume-multiseg.sh @@ -0,0 +1,222 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check whether all available pvmove resume methods works as expected. +# lvchange is able to resume pvmoves in progress. + +# Multisegment variant w/ 2 pvmoves LVs per VG + +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +aux prepare_pvs 5 40 + +vgcreate -s 128k $vg "$dev1" "$dev2" "$dev3" +pvcreate --metadatacopies 0 "$dev4" "$dev5" +vgextend $vg "$dev4" "$dev5" + +# $1 resume fn +test_pvmove_resume() { + # Create multisegment LV + lvcreate -an -Zn -l50 -n $lv1 $vg "$dev1" + lvextend -l+50 $vg/$lv1 "$dev2" + # next LV on same VG and differetnt PV (we want to test 2 pvmoves per VG) + lvcreate -an -Zn -l50 -n $lv2 $vg "$dev3" + + aux delay_dev "$dev4" 0 30 "$(get first_extent_sector "$dev4"):" + test -e HAVE_DM_DELAY || { lvremove -f $vg; return 0; } + aux delay_dev "$dev5" 0 30 "$(get first_extent_sector "$dev5"):" + + pvmove -i5 "$dev1" "$dev4" & + PVMOVE=$! + aux wait_pvmove_lv_ready "$vg-pvmove0" + kill $PVMOVE + + pvmove -i5 -n $vg/$lv2 "$dev3" "$dev5" & + PVMOVE=$! + aux wait_pvmove_lv_ready "$vg-pvmove1" + kill $PVMOVE + + test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld + wait + aux remove_dm_devs "$vg-$lv1" "$vg-$lv2" "$vg-pvmove0" "$vg-pvmove1" + + check lv_attr_bit type $vg/pvmove0 "p" + check lv_attr_bit type $vg/pvmove1 "p" + + if test -e LOCAL_CLVMD ; then + # giveup all clvmd locks (faster then restarting clvmd) + # no deactivation happen, nodes are already removed + #vgchange -an $vg + # FIXME: However above solution has one big problem + # as clvmd starts to abort on internal errors on various + # errors, based on the fact pvmove is killed -9 + # Restart clvmd + kill "$(< LOCAL_CLVMD)" + for i in $(seq 1 100) ; do + test $i -eq 100 && die "Shutdown of clvmd is too slow." + test -e "$CLVMD_PIDFILE" || break + sleep .1 + done # wait for the pid removal + aux prepare_clvmd + fi + + # call resume function (see below) + # with expected number of spawned + # bg polling as parameter + $1 2 + + aux enable_dev "$dev4" "$dev5" + + for i in {100..0} ; do # wait for 10 secs at max + get lv_field $vg name -a | grep -E "^\[?pvmove" || break + sleep .1 + done + test $i -gt 0 || die "Pvmove is too slow or does not progress." + + aux kill_tagged_processes + + lvremove -ff $vg + # drop debug logs from killed lvm2 commands + rm -f debug.log_DEBUG* +} + +lvchange_single() { + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg/$lv1 + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg/$lv2 +} + +lvchange_all() { + LVM_TEST_TAG="kill_me_$PREFIX" lvchange -aey $vg/$lv1 $vg/$lv2 + + # we don't want to spawn more than $1 background pollings + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove1" + else + test "$(aux count_processes_with_tag)" -eq $1 + fi +} + +vgchange_single() { + LVM_TEST_TAG="kill_me_$PREFIX" vgchange -aey $vg + + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 1 "$vg/pvmove1" + else + test "$(aux count_processes_with_tag)" -eq "$1" + fi +} + +pvmove_fg() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove1" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + get lv_field $vg name -a | grep -E "^\[?pvmove1" + + # disable delay device + # fg pvmove would take ages to complete otherwise + aux enable_dev "$dev4" "$dev5" + + LVM_TEST_TAG="kill_me_$PREFIX" pvmove +} + +pvmove_bg() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove1" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + get lv_field $vg name -a | grep -E "^\[?pvmove1" + + LVM_TEST_TAG="kill_me_$PREFIX" pvmove -b +} + +pvmove_fg_single() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove1" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + get lv_field $vg name -a | grep -E "^\[?pvmove1" + + # disable delay device + # fg pvmove would take ages to complete otherwise + aux enable_dev "$dev4" "$dev5" + + LVM_TEST_TAG="kill_me_$PREFIX" pvmove "$dev1" + LVM_TEST_TAG="kill_me_$PREFIX" pvmove "$dev3" +} + +pvmove_bg_single() { + # pvmove resume requires LVs active... + LVM_TEST_TAG="kill_me_$PREFIX" vgchange --config 'activation{polling_interval=10}' -aey --poll n $vg + + # ...also vgchange --poll n must not spawn any bg processes... + if test -e LOCAL_LVMPOLLD; then + aux lvmpolld_dump | tee lvmpolld_dump.txt + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove0" + aux check_lvmpolld_init_rq_count 0 "$vg/pvmove1" + else + test "$(aux count_processes_with_tag)" -eq 0 + fi + + # ...thus finish polling + get lv_field $vg name -a | grep -E "^\[?pvmove0" + get lv_field $vg name -a | grep -E "^\[?pvmove1" + + LVM_TEST_TAG="kill_me_$PREFIX" pvmove -b "$dev1" + LVM_TEST_TAG="kill_me_$PREFIX" pvmove -b "$dev3" +} + +test_pvmove_resume lvchange_single +test_pvmove_resume lvchange_all +test_pvmove_resume vgchange_single +test_pvmove_resume pvmove_fg +test_pvmove_resume pvmove_fg_single +test_pvmove_resume pvmove_bg +test_pvmove_resume pvmove_bg_single + +vgremove -ff $vg diff --git a/test/shell/pvmove-thin-segtypes.sh b/test/shell/pvmove-thin-segtypes.sh new file mode 100644 index 0000000..f8c65f5 --- /dev/null +++ b/test/shell/pvmove-thin-segtypes.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description="ensure pvmove works with thin segment types" +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +which md5sum || skip + +aux have_thin 1 8 0 || skip +# for stacking +aux have_raid 1 3 5 || skip + +aux prepare_pvs 5 20 +get_devs + +vgcreate -s 128k "$vg" "${DEVICES[@]}" + +for mode in "--atomic" "" +do + +# Each of the following tests does: +# 1) Create two LVs - one linear and one other segment type +# The two LVs will share a PV. +# 2) Move both LVs together +# 3) Move only the second LV by name + + +# Testing pvmove of thin LV +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey -T $vg/${lv1}_pool -l8 -V 8 -n $lv1 "$dev1" +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg $lv1 "$dev1" +aux mkdev_md5sum $vg $lv1 +pvmove "$dev1" "$dev5" $mode +check lv_tree_on $vg ${lv1}_foo "$dev5" +check lv_tree_on $vg $lv1 "$dev5" +check dev_md5sum $vg $lv1 +pvmove -n $lv1 "$dev5" "$dev4" $mode +check lv_tree_on $vg $lv1 "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check dev_md5sum $vg $lv1 +lvremove -ff $vg + +# Testing pvmove of thin LV on RAID +lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1" +lvcreate -aey --type raid1 -m 1 -l 8 -n ${lv1}_raid1_pool $vg "$dev1" "$dev2" +lvcreate -aey --type raid1 -m 1 -L 2 -n ${lv1}_raid1_meta $vg "$dev1" "$dev2" +lvconvert --yes --thinpool $vg/${lv1}_raid1_pool \ + --poolmetadata ${lv1}_raid1_meta +lvcreate -aey -T $vg/${lv1}_raid1_pool -V 8 -n $lv1 +check lv_tree_on $vg ${lv1}_foo "$dev1" +check lv_tree_on $vg $lv1 "$dev1" "$dev2" +aux mkdev_md5sum $vg $lv1 +pvmove "$dev1" "$dev5" $mode +check lv_tree_on $vg ${lv1}_foo "$dev5" +check lv_tree_on $vg $lv1 "$dev2" "$dev5" +check dev_md5sum $vg $lv1 +pvmove -n $lv1 "$dev5" "$dev4" $mode +check lv_tree_on $vg $lv1 "$dev2" "$dev4" +check lv_tree_on $vg ${lv1}_foo "$dev5" +check dev_md5sum $vg $lv1 +lvremove -ff $vg + +done + +vgremove -ff $vg diff --git a/test/shell/pvremove-thin.sh b/test/shell/pvremove-thin.sh new file mode 100644 index 0000000..4512557 --- /dev/null +++ b/test/shell/pvremove-thin.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Checks we are not reading our own devices +# https://bugzilla.redhat.com/show_bug.cgi?id=1064374 + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg + +aux have_thin 1 8 0 || skip + +aux extend_filter_LVMTEST + +lvcreate -L10 -V10 -n $lv1 -T $vg/pool1 + +aux extend_devices "$DM_DEV_DIR/$vg/$lv1" +aux lvmconf "devices/scan_lvs = 1" + +pvcreate "$DM_DEV_DIR/$vg/$lv1" +pvremove "$DM_DEV_DIR/$vg/$lv1" + +vgremove -ff $vg diff --git a/test/shell/pvremove-usage.sh b/test/shell/pvremove-usage.sh index c6d724b..17d90e6 100644 --- a/test/shell/pvremove-usage.sh +++ b/test/shell/pvremove-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,23 +8,33 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_devs 3 pvcreate "$dev1" pvcreate --metadatacopies 0 "$dev2" pvcreate --metadatacopies 2 "$dev3" + +# Fails without give argument +not pvremove 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" +pvs -a | grep "$dev2" +# bz1108394 no crash on nonPV label listing +pvs -a -o+devices + pvcreate --metadatacopies 0 "$dev2" # check pvremove refuses to remove pv in a vg -vgcreate -c n $vg "$dev1" "$dev2" +vgcreate $SHARED $vg "$dev1" "$dev2" not pvremove "$dev2" "$dev3" for mdacp in 0 1 2; do @@ -42,17 +53,20 @@ for mdacp in 0 1 2; do vgremove -ff $vg pvcreate --metadatacopies $mdacp "$dev1" pvcreate "$dev2" - vgcreate $vg "$dev1" "$dev2" + vgcreate $SHARED $vg "$dev1" "$dev2" # pvremove -f fails when pv in a vg (---metadatacopies $mdacp) - not pvremove -f "$dev1" + not pvremove -f "$dev1" 2>&1 | tee out + grep "is used" out pvs "$dev1" # pvremove -ff fails without confirmation when pv in a vg (---metadatacopies $mdacp) - echo n | not pvremove -ff "$dev1" + not pvremove -ff "$dev1" 2>&1 | tee out + grep "is used" out # pvremove -ff succeds with confirmation when pv in a vg (---metadatacopies $mdacp) - pvremove -ffy "$dev1" + pvremove -ffy "$dev1" 2>&1 | tee out + grep "is used" out not pvs "$dev1" vgreduce --removemissing $vg @@ -66,3 +80,5 @@ for mdacp in 0 1 2; do pvcreate --metadatacopies $mdacp "$dev1" vgextend $vg "$dev1" done + +vgremove -ff $vg diff --git a/test/shell/pvremove-warnings.sh b/test/shell/pvremove-warnings.sh new file mode 100644 index 0000000..dc3178d --- /dev/null +++ b/test/shell/pvremove-warnings.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 2 +pvcreate "$dev1" "$dev2" +pvremove "$dev1" "$dev2" 2>&1 | tee pvremove.txt +not grep "No physical" pvremove.txt + +pvcreate "$dev1" "$dev2" +vgcreate $SHARED bla "$dev1" "$dev2" +pvremove -ff -y "$dev1" "$dev2" 2>&1 | tee pvremove.txt +not grep "device missing" pvremove.txt diff --git a/test/shell/pvresize-mdas.sh b/test/shell/pvresize-mdas.sh new file mode 100644 index 0000000..240dfb2 --- /dev/null +++ b/test/shell/pvresize-mdas.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 1 8 + +pvcreate --setphysicalvolumesize 8m --metadatacopies 2 "$dev1" +check pv_field "$dev1" pv_size 8.00m +check pv_field "$dev1" pv_mda_count 2 +pvs "$dev1" + +pvresize --setphysicalvolumesize 4m -y "$dev1" +check pv_field "$dev1" pv_size 4.00m +check pv_field "$dev1" pv_mda_count 2 +pvs "$dev1" + +# Check physical size is checked agains metadatasize +pvcreate --metadatasize 2m --metadatacopies 1 -y "$dev1" +not pvresize --setphysicalvolumesize 2m -y "$dev1" |& tee out +grep "Size must exceed physical extent start of 6144 sectors on" out +# 3MiB shall pass with 1M default alignment +pvresize --setphysicalvolumesize 3m -y "$dev1" +check pv_field "$dev1" pv_size 3.00m +check pv_field "$dev1" pv_mda_count 1 +pvs "$dev1" diff --git a/test/shell/pvscan-autoactivate.sh b/test/shell/pvscan-autoactivate.sh new file mode 100644 index 0000000..f574731 --- /dev/null +++ b/test/shell/pvscan-autoactivate.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash + +# Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup" + +# FIXME: kills logic for running system +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* + rm -f "$PVS_LOOKUP_DIR"/* +} + +. lib/inittest + +aux prepare_devs 8 16 + +# Check 'pvscan' is ignored when event_activation is 0 +pvscan --cache -aay -v --config 'global/event_activation=0' 2>&1 | tee out +grep "Ignoring pvscan" out + +vgcreate $vg1 "$dev1" "$dev2" +lvcreate -n $lv1 -l 4 -a n $vg1 + +test -d "$PVS_ONLINE_DIR" || mkdir -p "$PVS_ONLINE_DIR" +test -d "$VGS_ONLINE_DIR" || mkdir -p "$VGS_ONLINE_DIR" +test -d "$PVS_LOOKUP_DIR" || mkdir -p "$PVS_LOOKUP_DIR" +_clear_online_files + +# check pvscan with no args scans and activates all +pvscan --cache -aay +check lv_field $vg1/$lv1 lv_active "active" +lvchange -an $vg1 + +_clear_online_files + +# first dev leaves vg incomplete and inactive, +# and second dev completes vg and activates +pvscan --cache -aay "$dev1" +check lv_field $vg1/$lv1 lv_active "" +pvscan --cache -aay "$dev2" +check lv_field $vg1/$lv1 lv_active "active" +lvchange -an $vg1 + +_clear_online_files + +# check that vg is activated when both devs +# are scanned together +pvscan --cache -aay "$dev1" "$dev2" +check lv_field $vg1/$lv1 lv_active "active" +lvchange -an $vg1 + +# check that a cache command without aay will +# just record online state, and that a following +# pvscan cache aay that does not record any new +# online files will activate the vg +_clear_online_files +pvscan --cache "$dev1" +check lv_field $vg1/$lv1 lv_active "" +pvscan --cache "$dev2" +check lv_field $vg1/$lv1 lv_active "" +pvscan --cache -aay +check lv_field $vg1/$lv1 lv_active "active" +lvchange -an $vg1 + +# Set up tests where one dev has no metadata + +vgchange -an $vg1 +vgremove -ff $vg1 +pvremove "$dev1" +pvremove "$dev2" +pvcreate --metadatacopies 0 "$dev1" +pvcreate --metadatacopies 1 "$dev2" +vgcreate $vg1 "$dev1" "$dev2" +lvcreate -n $lv1 -l 4 -a n $vg1 + + +_clear_online_files + +# test case where dev with metadata is scanned first +pvscan --cache -aay "$dev2" +check lv_field $vg1/$lv1 lv_active "" +pvscan --cache -aay "$dev1" +check lv_field $vg1/$lv1 lv_active "active" +lvchange -an $vg1 + +_clear_online_files +pvscan --cache -aay "$dev1" +check lv_field $vg1/$lv1 lv_active "" +pvscan --cache -aay "$dev2" +check lv_field $vg1/$lv1 lv_active "active" +lvchange -an $vg1 + +# use the --cache option to record a dev +# is online without the -aay option to +# activate until after they are online + +_clear_online_files + +pvscan --cache "$dev1" +check lv_field $vg1/$lv1 lv_active "" +pvscan --cache -aay "$dev2" +check lv_field $vg1/$lv1 lv_active "active" +lvchange -an $vg1 + +vgremove -f $vg1 + +# pvscan cache ignores pv that's not used + +pvcreate "$dev3" + +PVID3=$(pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}') +echo $PVID3 + +not ls "$RUNDIR/lvm/pvs_online/$PVID3" + +pvscan --cache -aay "$dev3" + +ls "$RUNDIR/lvm/pvs_online" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" + + +# pvscan cache ignores pv in a foreign vg + +if [ -e "/etc/machine-id" ]; then + +aux lvmconf "global/system_id_source = machineid" + +_clear_online_files + +vgcreate $vg2 "$dev3" +lvcreate -an -n $lv2 -l1 $vg2 +pvscan --cache -aay "$dev3" +ls "$RUNDIR/lvm/pvs_online/$PVID3" +check lv_field $vg2/$lv2 lv_active "active" +lvchange -an $vg2 +rm "$RUNDIR/lvm/pvs_online/$PVID3" + +# a vg without a system id is not foreign, not ignored +vgchange -y --systemid "" "$vg2" + +_clear_online_files +pvscan --cache -aay "$dev3" +ls "$RUNDIR/lvm/pvs_online/$PVID3" +check lv_field $vg2/$lv2 lv_active "active" +lvchange -an $vg2 +rm "$RUNDIR/lvm/pvs_online/$PVID3" + +# make the vg foreign by assigning a system id different from ours +vgchange -y --systemid "asdf" "$vg2" + +_clear_online_files + +pvscan --cache -aay "$dev3" +not ls "$RUNDIR/lvm/pvs_online/$PVID3" +lvs --foreign $vg2 > out +cat out +grep $lv2 out +check lv_field $vg2/$lv2 lv_active "" --foreign + +fi + + +# Test the case where pvscan --cache -aay (with no devs) +# gets the final PV to complete the VG, where that final PV +# does not hold VG metadata. In this case it needs to rely +# on VG metadata that has been saved from a previously +# scanned PV from the same VG. +# +# We can't control which order of devices pvscan will see, +# so create several PVs without metadata surrounding one +# PV with metadata, to make it likely that pvscan will +# get a final PV without metadata. + +pvcreate --metadatacopies 0 "$dev4" +pvcreate --metadatacopies 0 "$dev5" +pvcreate --metadatacopies 1 "$dev6" +pvcreate --metadatacopies 0 "$dev7" +pvcreate --metadatacopies 0 "$dev8" +vgcreate $vg3 "$dev4" "$dev5" "$dev6" "$dev7" "$dev8" +lvcreate -n $lv1 -l 4 -a n $vg3 + +_clear_online_files + +check lv_field $vg3/$lv1 lv_active "" +pvscan --cache "$dev4" +check lv_field $vg3/$lv1 lv_active "" +pvscan --cache "$dev5" +check lv_field $vg3/$lv1 lv_active "" +pvscan --cache "$dev6" +check lv_field $vg3/$lv1 lv_active "" +pvscan --cache "$dev7" +check lv_field $vg3/$lv1 lv_active "" +pvscan --cache "$dev8" +check lv_field $vg3/$lv1 lv_active "" +pvscan --cache -aay +check lv_field $vg3/$lv1 lv_active "active" +lvchange -an $vg3 + +# Test event activation when PV and dev size don't match + +vgremove -ff $vg3 + +pvremove "$dev8" +pvcreate -y --setphysicalvolumesize 8M "$dev8" + +PVID8=$(pvs "$dev8" --noheading -o uuid | tr -d - | awk '{print $1}') +echo $PVID8 + +vgcreate $vg3 "$dev8" +lvcreate -l1 -n $lv1 $vg3 +check lv_field $vg3/$lv1 lv_active "active" +vgchange -an $vg3 +check lv_field $vg3/$lv1 lv_active "" + +_clear_online_files + +pvscan --cache -aay "$dev8" +check lv_field $vg3/$lv1 lv_active "active" +ls "$RUNDIR/lvm/pvs_online/$PVID8" +ls "$RUNDIR/lvm/vgs_online/$vg3" +vgchange -an $vg3 + +vgremove -ff $vg3 diff --git a/test/shell/pvscan-autoactivation-polling.sh b/test/shell/pvscan-autoactivation-polling.sh new file mode 100644 index 0000000..53adf51 --- /dev/null +++ b/test/shell/pvscan-autoactivation-polling.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +# test if snapshot-merge target is available +aux target_at_least dm-snapshot-merge 1 0 0 || skip + +which mkfs.ext3 || skip + +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:-0} + local BASE_SNAP_LV_NAME + + BASE_SNAP_LV_NAME=$(snap_lv_name_ $LV_NAME) + + lvcreate -aey -n $LV_NAME -l 50%FREE $VG_NAME + lvs + 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%ORIGIN ${VG_NAME}/${LV_NAME} + done + fi +} + +aux prepare_pvs 1 50 + +vgcreate $vg1 "$dev1" +mkdir test_mnt + +setup_merge_ $vg1 $lv1 +mount "$(lvdev_ $vg1 $lv1)" test_mnt +lvconvert --merge "$vg1/$(snap_lv_name_ "$lv1")" +umount test_mnt +vgchange -an $vg1 + +# check snapshot get removed on autoactivation +pvscan --cache -aay "$dev1" + +check active $vg1 $lv1 +i=100 +while ! check lv_not_exists "$vg1/$(snap_lv_name_ "$lv1")"; do + test $i -lt 0 && fail "Background polling failed to remove merged snapshot LV" + sleep .1 + i=$((i-1)) +done + +# TODO: add similar simple tests for other interrupted/unfinished polling operation + +vgremove -ff $vg1 diff --git a/test/shell/pvscan-cache.sh b/test/shell/pvscan-cache.sh new file mode 100644 index 0000000..c351885 --- /dev/null +++ b/test/shell/pvscan-cache.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* +} + +. lib/inittest + +aux prepare_pvs 2 + +vgcreate $vg1 "$dev1" "$dev2" +vgs | grep $vg1 + +pvscan --cache + +vgs | grep $vg1 + +# Check that an LV cannot be activated by lvchange while VG is exported +lvcreate -n $lv1 -l 4 -a n $vg1 +check lv_exists $vg1 +vgexport $vg1 +fail lvs $vg1 +fail lvchange -ay $vg1/$lv1 +vgimport $vg1 +check lv_exists $vg1 +check lv_field $vg1/$lv1 lv_active "" + +# Check that an LV cannot be activated by pvscan while VG is exported +vgchange -an $vg1 +_clear_online_files +vgexport $vg1 +pvscan --cache -aay "$dev1" || true +pvscan --cache -aay "$dev2" || true +_clear_online_files +vgimport $vg1 +check lv_exists $vg1 +check lv_field $vg1/$lv1 lv_active "" +pvscan --cache -aay "$dev1" +pvscan --cache -aay "$dev2" +check lv_field $vg1/$lv1 lv_active "active" +lvchange -an -vvvv $vg1/$lv1 +dmsetup ls +lvremove $vg1/$lv1 + +# When MDA is ignored on PV, do not read any VG +# metadata from such PV as it may contain old +# metadata which hasn't been updated for some +# time and also since the MDA is marked as ignored, +# it should really be *ignored*! +_clear_online_files +pvchange --metadataignore y "$dev1" +aux disable_dev "$dev2" +pvscan --cache +check pv_field "$dev1" vg_name "[unknown]" +aux enable_dev "$dev2" +pvscan --cache +check pv_field "$dev1" vg_name "$vg1" + +vgremove -ff $vg1 diff --git a/test/shell/pvscan-nomda-bg.sh b/test/shell/pvscan-nomda-bg.sh new file mode 100644 index 0000000..42bd26f --- /dev/null +++ b/test/shell/pvscan-nomda-bg.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 2 + +pvcreate --metadatacopies 0 "$dev1" +pvcreate --metadatacopies 1 "$dev2" +vgcreate $vg1 "$dev1" "$dev2" +lvcreate -n foo -l 1 -an --zero n $vg1 + +check inactive $vg1 foo + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +# create a file in pvs_online to disable the pvscan init +# case which scans everything when the first dev appears. +mkdir -p "$RUNDIR/lvm/pvs_online" || true +touch "$RUNDIR/lvm/pvs_online/foo" + +pvscan --cache --background "$dev2" -aay + +check inactive $vg1 foo + +pvscan --cache --background "$dev1" -aay + +check active $vg1 foo + +rm "$RUNDIR/lvm/pvs_online/foo" +vgremove -ff $vg1 diff --git a/test/shell/read-ahead.sh b/test/shell/read-ahead.sh index 8c8f42c..2f061fa 100644 --- a/test/shell/read-ahead.sh +++ b/test/shell/read-ahead.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # tests basic functionality of read-ahead and ra regressions @@ -15,17 +16,18 @@ test_description='Test read-ahead functionality' -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_vg 5 #COMM "test various read ahead settings (bz450922)" -lvcreate -l 100%FREE -i5 -I256 -n $lv $vg +lvcreate -l 100%FREE -i5 -I512 -n $lv $vg ra=$(get lv_field $vg/$lv lv_kernel_read_ahead --units s --nosuffix) -test $(( ( $ra / 5 ) * 5 )) -eq $ra +test $(( ( ra / 5 ) * 5 )) -le $ra not lvchange -r auto $vg/$lv 2>&1 | grep auto check lv_field $vg/$lv lv_read_ahead auto -check lv_field $vg/$lv lv_kernel_read_ahead 5120 --units s --nosuffix lvchange -r 640 $vg/$lv check lv_field $vg/$lv lv_read_ahead 640 --units s --nosuffix lvremove -ff $vg @@ -33,8 +35,11 @@ lvremove -ff $vg #COMM "read ahead is properly inherited from underlying PV" blockdev --setra 768 "$dev1" vgscan +# is there something in the system changing readahead settings behind the scene... +RASZ=$(blockdev --getra "$dev1") +test "$RASZ" -ge 768 || RASZ=768 lvcreate -n $lv -L4m $vg "$dev1" -test $(blockdev --getra $DM_DEV_DIR/$vg/$lv) -eq 768 +test "$(blockdev --getra "$DM_DEV_DIR/$vg/$lv")" -eq "$RASZ" lvremove -ff $vg # Check default, active/inactive values for read_ahead / kernel_read_ahead @@ -46,4 +51,5 @@ 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 + +vgremove -ff $vg diff --git a/test/shell/relative-sign-options.sh b/test/shell/relative-sign-options.sh new file mode 100644 index 0000000..6be7525 --- /dev/null +++ b/test/shell/relative-sign-options.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Exercise toollib process_each_lv' +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 1 256 + +lvcreate -an -n $lv1 -l4 $vg +lvcreate -an -n $lv2 -L4 $vg +lvcreate -an -n $lv3 -l+4 $vg +lvcreate -an -n $lv4 -L+4 $vg +not lvcreate -n $lv5 -l-4 $vg +not lvcreate -n $lv5 -L-4 $vg + +lvremove $vg/$lv1 +lvremove $vg/$lv2 +lvremove $vg/$lv3 +lvremove $vg/$lv4 + +lvcreate -an -n $lv1 -l4 $vg +lvresize -y -l8 $vg/$lv1 +lvresize -y -L16 $vg/$lv1 +lvresize -y -l+1 $vg/$lv1 +lvresize -y -L+1 $vg/$lv1 +lvresize -y --fs ignore -l-1 $vg/$lv1 +lvresize -y --fs ignore -L-1 $vg/$lv1 + +lvcreate -an -n $lv2 -l4 $vg +lvextend -y -l8 $vg/$lv2 +lvextend -y -L16 $vg/$lv2 +lvextend -y -l+1 $vg/$lv2 +lvextend -y -L+1 $vg/$lv2 +not lvextend -y -l-1 $vg/$lv2 +not lvextend -y -L-1 $vg/$lv2 + +lvcreate -an -n $lv3 -l64 $vg +lvreduce -y --fs ignore -l32 $vg/$lv3 +lvreduce -y --fs ignore -L8 $vg/$lv3 +lvreduce -y --fs ignore -l-1 $vg/$lv3 +lvreduce -y --fs ignore -L-1 $vg/$lv3 +not lvreduce -y --fs ignore -l+1 $vg/$lv3 +not lvreduce -y --fs ignore -L+1 $vg/$lv3 + +# relative with percent extents + +lvcreate -an -n $lv6 -l+100%FREE $vg +lvremove $vg/$lv6 + +lvcreate -an -n $lv6 -l1 $vg +lvextend -y -l+100%FREE $vg/$lv6 +lvremove $vg/$lv6 + +lvcreate -an -n $lv6 -l1 $vg +lvresize -y -l+100%FREE $vg/$lv6 +lvremove $vg/$lv6 + +if aux have_thin 1 0 0 ; then +# relative poolmetadatasize +lvcreate --type thin-pool -L64 --poolmetadatasize 32 -n $lv7 $vg +lvresize --poolmetadatasize 64 $vg/$lv7 +lvresize --poolmetadatasize +8 $vg/$lv7 +not lvresize -y --poolmetadatasize -8 $vg/$lv7 + +lvextend --poolmetadatasize +4 $vg/$lv7 +not lvextend -y --poolmetadatasize -8 $vg/$lv7 +fi + +vgremove -y $vg diff --git a/test/shell/report-fields.sh b/test/shell/report-fields.sh new file mode 100644 index 0000000..eb81afc --- /dev/null +++ b/test/shell/report-fields.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Test only that there's correct set of fields displayed on output. + +aux prepare_pvs 1 + +OPTS="--nameprefixes --noheadings --rows" + +aux lvmconf 'report/pvs_cols="pv_name,pv_size"' +aux lvmconf 'report/compact_output=0' +aux lvmconf 'report/compact_output_cols=""' + +pvs $OPTS > out +grep LVM2_PV_NAME out +grep LVM2_PV_SIZE out + +pvs $OPTS -o pv_attr > out +grep LVM2_PV_ATTR out +not grep -v LVM2_PV_ATTR out + +pvs $OPTS -o+pv_attr > out +grep LVM2_PV_NAME out +grep LVM2_PV_SIZE out +grep LVM2_PV_ATTR out + +pvs $OPTS -o-pv_name > out +not grep LVM2_PV_NAME out +grep LVM2_PV_SIZE out + +pvs $OPTS -o+pv_attr -o-pv_attr > out +grep LVM2_PV_NAME out +grep LVM2_PV_SIZE out +not grep LVM2_PV_ATTR out + +pvs $OPTS -o-pv_attr -o+pv_attr > out +grep LVM2_PV_NAME out +grep LVM2_PV_SIZE out +grep LVM2_PV_ATTR out + +pvs $OPTS -o+pv_attr -o-pv_attr -o pv_attr > out +grep LVM2_PV_ATTR out +not grep -v LVM2_PV_ATTR out + +# -o-size is the same as -o-pv_size - the prefix is recognized +pvs $OPTS -o-size > out +not grep LVM2_PV_SIZE out + +# PV does not have tags nor is it exported if we haven't done that explicitly. +# Check compaction per field is done correctly. +pvs $OPTS -o pv_name,pv_exported,pv_tags -o#pv_tags > out +grep LVM2_PV_NAME out +grep LVM2_PV_EXPORTED out +not grep LVM2_PV_TAGS out + +aux lvmconf 'report/compact_output_cols="pv_tags"' + +pvs $OPTS -o pv_name,pv_exported,pv_tags > out +grep LVM2_PV_NAME out +grep LVM2_PV_EXPORTED out +not grep LVM2_PV_TAGS out + +pvs $OPTS -o pv_name,pv_exported,pv_tags -o#pv_exported > out +grep LVM2_PV_NAME out +not grep LVM2_PV_EXPORTED out +grep LVM2_PV_TAGS out + +aux lvmconf 'report/compact_output=1' +pvs $OPTS -o pv_name,pv_exported,pv_tags > out +grep LVM2_PV_NAME out +not grep LVM2_PV_EXPORTED out +not grep LVM2_PV_TAGS out + +pvs $OPTS -o pv_name,pv_exported,pv_tags -o#pv_exported > out +grep LVM2_PV_NAME out +not grep LVM2_PV_EXPORTED out +not grep LVM2_PV_TAGS out diff --git a/test/shell/report-format.sh b/test/shell/report-format.sh new file mode 100644 index 0000000..e02d61b --- /dev/null +++ b/test/shell/report-format.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +# Copyright (C) 2022 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_thin 1 0 0 || skip + +aux prepare_vg 1 + +OUT_LOG_FILE="out" + +lvcreate -l1 -T $vg/$lv1 +lvcreate -l1 -n $lv2 --addtag lv_tag1 -an $vg +lvcreate -l1 -n $lv3 --addtag lv_tag3 --addtag lv_tag1 --addtag lv_tag2 $vg + +aux lvmconf "report/output_format = basic" +lvs -o name,kernel_major,data_percent,tags | tee "$OUT_LOG_FILE" + +# +# LV KMaj Data% LV Tags +# lvol1 253 0.00 +# lvol2 -1 lv_tag1 +# lvol3 253 lv_tag1,lv_tag2,lv_tag3 +# +grep -E "^[[:space:]]*${lv1}[[:space:]]*[[:digit:]]+[[:space:]]*[[:digit:]]+.[[:digit:]]+[[:space:]]*\$" out +grep -E "^[[:space:]]*${lv2}[[:space:]]*-1[[:space:]]*lv_tag1[[:space:]]*\$" out +grep -E "^[[:space:]]*${lv3}[[:space:]]*[[:digit:]]+[[:space:]]*lv_tag1,lv_tag2,lv_tag3\$" out + + +aux lvmconf "report/output_format = json" +lvs -o name,kernel_major,data_percent,tags | tee "$OUT_LOG_FILE" +# { +# "report": [ +# { +# "lv": [ +# {"lv_name":"lvol1", "lv_kernel_major":"253", "data_percent":"0.00", "lv_tags":""}, +# {"lv_name":"lvol2", "lv_kernel_major":"-1", "data_percent":"", "lv_tags":"lv_tag1"}, +# {"lv_name":"lvol3", "lv_kernel_major":"253", "data_percent":"", "lv_tags":"lv_tag1,lv_tag2,lv_tag3"} +# ] +# } +# ] +# } +grep -E "^[[:space:]]*{\"lv_name\":\"$lv1\", \"lv_kernel_major\":\"[[:digit:]]+\", \"data_percent\":\"[[:digit:]]+.[[:digit:]]+\", \"lv_tags\":\"\"},\$" out +grep -E "^[[:space:]]*{\"lv_name\":\"$lv2\", \"lv_kernel_major\":\"-1\", \"data_percent\":\"\", \"lv_tags\":\"lv_tag1\"},\$" out +grep -E "^[[:space:]]*{\"lv_name\":\"$lv3\", \"lv_kernel_major\":\"[[:digit:]]+\", \"data_percent\":\"\", \"lv_tags\":\"lv_tag1,lv_tag2,lv_tag3\"}\$" out + +aux lvmconf "report/output_format = json_std" +lvs -o name,kernel_major,data_percent,tags | tee "$OUT_LOG_FILE" +# { +# "report": [ +# { +# "lv": [ +# {"lv_name":"lvol1", "lv_kernel_major":253, "data_percent":0.00, "lv_tags":[]}, +# {"lv_name":"lvol2", "lv_kernel_major":-1, "data_percent":null, "lv_tags":["lv_tag1"]}, +# {"lv_name":"lvol3", "lv_kernel_major":253, "data_percent":null, "lv_tags":["lv_tag1","lv_tag2","lv_tag3"]} +# ] +# } +# ] +# } +grep -E "^[[:space:]]*{\"lv_name\":\"$lv1\", \"lv_kernel_major\":[[:digit:]]+, \"data_percent\":[[:digit:]]+.[[:digit:]]+, \"lv_tags\":\[\]},\$" out +grep -E "^[[:space:]]*{\"lv_name\":\"$lv2\", \"lv_kernel_major\":-1, \"data_percent\":null, \"lv_tags\":\[\"lv_tag1\"\]},\$" out +grep -E "^[[:space:]]*{\"lv_name\":\"$lv3\", \"lv_kernel_major\":[[:digit:]]+, \"data_percent\":null, \"lv_tags\":\[\"lv_tag1\",\"lv_tag2\",\"lv_tag3\"\]}\$" out + +vgremove -ff $vg diff --git a/test/shell/report-hidden.sh b/test/shell/report-hidden.sh new file mode 100644 index 0000000..f38e048 --- /dev/null +++ b/test/shell/report-hidden.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 1 +lvcreate --type mirror -m1 -l1 --alloc anywhere -n $lv1 $vg + +aux lvmconf 'log/prefix=""' + +aux lvmconf "report/mark_hidden_devices = 0" +lvs --noheadings -a -o name $vg > out +grep "^${lv1}_mimage_0" out +not grep "^\[${lv1}_mimage_0\]" out + +aux lvmconf "report/mark_hidden_devices = 1" +lvs --noheadings -a -o name $vg > out +grep "^\[${lv1}_mimage_0\]" out +not grep "^${lv1}_mimage_0" out + +vgremove -ff $vg diff --git a/test/shell/scan-lvs.sh b/test/shell/scan-lvs.sh new file mode 100644 index 0000000..fe11201 --- /dev/null +++ b/test/shell/scan-lvs.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test scan_lvs config setting + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux extend_filter_LVMTEST +aux lvmconf "devices/scan_lvs = 1" + +aux prepare_pvs 1 + +vgcreate $SHARED $vg1 "$dev1" + +lvcreate -l1 -n $lv1 $vg1 + +aux extend_devices "$DM_DEV_DIR/$vg1/$lv1" +pvcreate "$DM_DEV_DIR/$vg1/$lv1" + +pvs "$DM_DEV_DIR/$vg1/$lv1" + +aux lvmconf 'devices/scan_lvs = 0' + +not pvs "$DM_DEV_DIR/$vg1/$lv1" + +pvs --config devices/scan_lvs=1 "$DM_DEV_DIR/$vg1/$lv1" + +not pvremove "$DM_DEV_DIR/$vg1/$lv1" + +pvremove --config devices/scan_lvs=1 "$DM_DEV_DIR/$vg1/$lv1" + +lvchange -an "$vg1/$lv1" + +lvremove "$vg1/$lv1" + +vgremove $vg1 diff --git a/test/shell/select-report.sh b/test/shell/select-report.sh new file mode 100644 index 0000000..f08c4ed --- /dev/null +++ b/test/shell/select-report.sh @@ -0,0 +1,223 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_pvs 6 16 + +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# MAKE SURE ALL PV, VG AND LV NAMES CREATED IN +# THIS TEST ARE UNIQUE - THIS SIMPLIFIES TESTING +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +# create $VGS with assorted tags +vgcreate $SHARED $vg1 --vgmetadatacopies 2 --addtag "vg_tag3" --addtag "vg_tag2" -s 4m "$dev1" "$dev2" "$dev3" +vgcreate $SHARED $vg2 --addtag "vg_tag2" -s 4m "$dev4" "$dev5" +vgcreate $SHARED $vg3 --addtag "vg_tag1" -s 4m "$dev6" + +# add PV assorted tags +pvchange --addtag "pv_tag3" --addtag "pv_tag1" --addtag "pv_tag2" "$dev1" +pvchange --addtag "pv_tag1" --addtag "pv_tag4" "$dev6" + +# create $LVS with assorted tags and various sizes +lvcreate --addtag 'lv_tag2.-+/=!:&#' --addtag "lv_tag1" -L8m -n "vol1" $vg1 +lvcreate --addtag "lv_tag1" -L4m -n "vol2" $vg1 +lvcreate --readahead 512 --addtag "lv_tag1" -L16m -n "abc" $vg2 +lvcreate --readahead 512 -My --minor 254 -L4m -n "xyz" $vg3 +lvcreate -L4m -aey -n "orig" $vg3 +lvcreate -L4m -s "$vg3/orig" -n "snap" + +OUT_LOG_FILE="out" +ERR_LOG_FILE="err" + +sel() { + local items_found + + ${1}s --noheadings -o ${1}_name --select "$2" 2>"$ERR_LOG_FILE" | tee "$OUT_LOG_FILE" + shift 2 + + test -f "$OUT_LOG_FILE" || { + echo " >>> Missing log file to check!" + return 1 + } + + # there shouldn't be any selection syntax error + grep "Selection syntax error at" "$ERR_LOG_FILE" >/dev/null && { + echo " >>> Selection syntax error hit!" + return 1 + } + + items_found=$(wc -l "$OUT_LOG_FILE" | cut -f 1 -d ' ') + + # the number of lines on output must match + test "$items_found" -eq $# || { + echo " >>> NUMBER OF ITEMS EXPECTED: $#" "$@" + echo " >>> NUMBER OF ITEMS FOUND: $items_found ($(< $OUT_LOG_FILE))" + return 1 + } + + # the names selected must be correct + # each pv, vg and lv name is unique so just check + # the presence of the names given as arg + for name in "$@" ; do + grep "$name" "$OUT_LOG_FILE" >/dev/null || { + echo " >>> $name not found in the output log" + return 1 + } + done + + rm -f "$OUT_LOG_FILE" "$ERR_LOG_FILE" +} + +########################## +# STRING FIELD SELECTION # +########################## +#$LVS 'lv_name="vol1"' && result vol1 +sel lv 'lv_name="vol1"' vol1 +#$LVS 'lv_name!="vol1"' && result vol2 abc xyz +sel lv 'lv_name!="vol1"' vol2 abc xyz orig snap +# check string values are accepted without quotes too +sel lv 'lv_name=vol1' vol1 +# check single quotes are also accepted instead of double quotes +sel lv "lv_name='vol1'" vol1 + +############################### +# STRING LIST FIELD SELECTION # +############################### +sel pv 'tags=["pv_tag1"]' +# for one item, no need to use [] +sel pv 'tags="pv_tag1"' "$dev1" "$dev6" +# no match +sel pv 'tags=["pv_tag1" && "pv_tag2"]' +sel pv 'tags=["pv_tag1" && "pv_tag2" && "pv_tag3"]' "$dev1" +# check the order has no effect on selection result +sel pv 'tags=["pv_tag3" && "pv_tag2" && "pv_tag1"]' "$dev1" +sel pv 'tags=["pv_tag4" || "pv_tag3"]' "$dev1" "$dev6" +sel pv 'tags!=["pv_tag1"]' "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" +# check mixture of && and || - this is not allowed +not sel pv 'tags=["pv_tag1" && "pv_tag2" || "pv_tag3"]' +# check selection with blank value +sel lv 'tags=""' xyz orig snap +sel lv 'tags={}' xyz orig snap +sel lv 'tags=[]' xyz orig snap +# check subset selection +sel pv 'tags={"pv_tag1"}' "$dev1" "$dev6" +sel pv 'tags={"pv_tag1" && "pv_tag2"}' "$dev1" + +########################## +# NUMBER FIELD SELECTION # +########################## +sel vg 'pv_count=3' $vg1 +sel vg 'pv_count!=3' $vg3 $vg2 +sel vg 'pv_count<2' $vg3 +sel vg 'pv_count<=2' $vg3 $vg2 +sel vg 'pv_count>2' $vg1 +sel vg 'pv_count>=2' $vg1 $vg2 + +######################## +# SIZE FIELD SELECTION # +######################## +# check size units are accepted as well as floating point numbers for sizes +sel lv 'size=8388608b' vol1 +sel lv 'size=8192k' vol1 +sel lv 'size=8m' vol1 +sel lv 'size=8.00m' vol1 +sel lv 'size=0.0078125g' vol1 +sel lv 'size=0.00000762939453125t' vol1 +sel lv 'size=0.000000007450580596923828125p' vol1 +sel lv 'size=0.0000000000072759576141834259033203125e' vol1 + +sel lv 'size>8m' abc +sel lv 'size>=8m' abc vol1 +sel lv 'size<8m' vol2 xyz orig snap +sel lv 'size<=8m' vol2 xyz vol1 orig snap + +########################### +# PERCENT FIELD SELECTION # +########################### +if aux target_at_least dm-snapshot 1 10 0; then + # Test zero percent only if snapshot can be zero. + # Before 1.10.0, the snap percent included metadata size. + sel lv 'snap_percent=0' snap +fi +dd if=/dev/zero of="$DM_DEV_DIR/$vg3/snap" bs=1M count=1 oflag=direct +sel lv 'snap_percent<50' snap +sel lv 'snap_percent>50' +# overflow snapshot -> invalidated, but still showing 100% +not dd if=/dev/zero of="$DM_DEV_DIR/$vg3/snap" bs=1M count=4 oflag=direct +sel lv 'snap_percent=100' snap +# % char is accepted as suffix for percent values +sel lv 'snap_percent=100%' snap +# percent values over 100% are not accepted +not sel lv 'snap_percent=101%' + +######################### +# REGEX FIELD SELECTION # +######################### +sel lv 'lv_name=~"^vol[12]"' vol1 vol2 +sel lv 'lv_name!~"^vol[12]"' abc xyz orig snap +# check regex is accepted without quotes too +sel lv 'lv_name=~^vol[12]' vol1 vol2 + +########### +# GENERIC # +########### +# check prefix works for selection too +sel lv 'lv_name="vol1"' vol1 +sel lv 'name="vol1"' vol1 + +# check reserved values are accepted for certain fields as well as usual values +sel vg 'vg_mda_copies=unmanaged' $vg2 $vg3 +sel vg 'vg_mda_copies=2' $vg1 +# also, we must match only vg1, not including vg2 and vg3 +# when comparing ranges - unamanged is mapped onto 2^64 - 1 internally, +# so we need to skip this internal value if it matches with selection criteria! +sel vg 'vg_mda_copies>=2' $vg1 +not sel vg 'vg_mda_copies=18446744073709551615' + +sel lv 'lv_read_ahead=auto' vol1 vol2 orig snap +sel lv 'lv_read_ahead=256k' abc xyz + +sel lv 'lv_minor=-1' vol1 vol2 abc orig snap +sel lv 'lv_minor=undefined' vol1 vol2 abc orig snap +sel lv 'lv_minor=undef' vol1 vol2 abc orig snap +sel lv 'lv_minor=unknown' vol1 vol2 abc orig snap +sel lv 'lv_minor=254' xyz +# also test synonym for string field type +sel lv 'seg_monitor=undefined' vol1 vol2 abc abc orig xyz + +# if size unit not spefied, the 'm' (MiB) unit is used by default +sel lv 'lv_size=8' vol1 + +# no need to use quotes for the whole selection string if it does not clash with shell +sel lv name=vol1 vol1 + +########################################## +# FORMING MORE COMPLEX SELECTION CLAUSES # +########################################## +# AND clause +sel lv 'lv_tags=lv_tag1 && lv_size=4m' vol2 +# OR clause +sel lv 'lv_name=vol1 || lv_name=vol2' vol1 vol2 +# grouping by using ( ) +sel lv '(lv_name=vol1 || lv_name=vol2) || vg_tags=vg_tag1' vol1 vol2 orig snap xyz +sel lv '(lv_name=vol1 && lv_size=100m) || vg_tags=vg_tag1' xyz orig snap +sel lv '(lv_name=vol1 || lv_name=vol2) && vg_tags=vg_tag1' +sel lv '(lv_name=vol1 || lv_name=vol2) && lv_size < 8m' vol2 +sel lv '(lv_name=vol1 && lv_size=8m) && vg_tags=vg_tag2' vol1 +# negation of clause grouped by ( ) +sel lv '!(lv_name=vol1 || lv_name=vol2)' abc xyz orig snap + +vgremove -ff $vg1 $vg2 $vg3 diff --git a/test/shell/select-tools-thin.sh b/test/shell/select-tools-thin.sh new file mode 100644 index 0000000..8fbe1b3 --- /dev/null +++ b/test/shell/select-tools-thin.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip + +aux prepare_pvs 1 16 + +######################### +# special cases to test # +######################### + +# if calling lvremove and an LV is removed that is related to other LV +# and we're doing selection based on this relation, check if we're +# selecting on initial state (here, thin origin LV thin_orig is removed +# first, but thin snap should be still selectable based on origin=thin_orig +# condition even though thin_orig has just been removed) +vgcreate $SHARED -s 4m $vg1 "$dev1" +lvcreate -l100%FREE -T $vg1/pool +lvcreate -V4m -T $vg1/pool -n thin_orig +lvcreate -s $vg1/thin_orig -n thin_snap +lvremove -ff -S 'lv_name=thin_orig || origin=thin_orig' > out +grep "Logical volume \"thin_orig\" successfully removed" out +grep "Logical volume \"thin_snap\" successfully removed" out +not lvs $vg1/thin_orig +not lvs $vg1/thin_snap + +vgremove -ff $vg1 diff --git a/test/shell/select-tools.sh b/test/shell/select-tools.sh new file mode 100644 index 0000000..0ca633c --- /dev/null +++ b/test/shell/select-tools.sh @@ -0,0 +1,280 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_pvs 4 12 + +vgcreate $SHARED -s 4m $vg1 "$dev1" "$dev2" +vgcreate $SHARED -s 4m $vg2 "$dev3" "$dev4" + +# vg1/lv1 mapped onto dev1 +lvcreate -l1 -n "lv1" $vg1 "$dev1" + +# vg1/lv2 mapped onto dev1 and dev2 (2 segments) +lvcreate -l3 -n "lv2" $vg1 "$dev1" "$dev2" + +# vg2/lv3 mapped onto dev3 +lvcreate -l1 -n "lv3" $vg2 "$dev3" + +# vg2/lv4 mapped onto dev3 +lvcreate -l1 -n "lv4" $vg2 "$dev3" "$dev4" + +# vg2/lv1 mapped onto "$dev4" (same LV name as vg1/lv1) +lvcreate -l1 -n "lv1" $vg2 "$dev4" + +########################################### +# exercise process_each_vg with selection # +########################################### + +# select contains VGS field +# direct vg name match +vgchange --addtag 101 -S "vg_name=$vg1" +check vg_field $vg1 vg_tags 101 +not check vg_field $vg2 vg_tags 101 +vgchange --deltag 101 + +# select contains LVS fiels +vgchange --addtag 102 -S "lv_name=lv2" +check vg_field $vg1 vg_tags 102 +not check vg_field $vg2 vg_tags 102 +vgchange --deltag 102 +vgchange --addtag 103 -S "lv_name=lv1" +check vg_field $vg1 vg_tags 103 +check vg_field $vg2 vg_tags 103 +vgchange --deltag 103 + +# select contains SEGS field +vgchange --addtag 104 -S 'seg_start=8m' +check vg_field $vg1 vg_tags 104 +not check vg_field $vg2 vg_tags 104 +vgchange --deltag 104 +vgchange --addtag 105 -S "seg_start=0m" +check vg_field $vg1 vg_tags 105 +check vg_field $vg2 vg_tags 105 +vgchange --deltag 105 + +# select contains PVS field +vgchange --addtag 106 -S pv_name="$dev1" +check vg_field $vg1 vg_tags 106 +not check vg_field $vg2 vg_tags 106 +vgchange --deltag 106 +vgchange --addtag 107 -S "pv_size>0m" +check vg_field $vg1 vg_tags 107 +check vg_field $vg2 vg_tags 107 +vgchange --deltag 107 + +# select contains PVSEGS field +vgchange --addtag 108 -S "pvseg_size=2" +check vg_field $vg1 vg_tags 108 +not check vg_field $vg2 vg_tags 108 +vgchange --deltag 108 +vgchange --addtag 109 -S "pvseg_size=1" +check vg_field $vg1 vg_tags 109 +check vg_field $vg2 vg_tags 109 +vgchange --deltag 109 + +# if VG name or tag is supplied together with the +# selection, the result is an intersection of both +vgchange --addtag 110 -S "vg_name=$vg1" $vg2 +not check vg_field $vg1 vg_tags 110 +not check vg_field $vg2 vg_tags 110 +vgchange --deltag 110 +vgchange --addtag 111 -S "vg_name=$vg1" $vg1 +check vg_field $vg1 vg_tags 111 +not check vg_field $vg2 vg_tags 111 +vgchange --deltag 111 +vgchange --addtag "tag" $vg1 +vgchange --addtag 112 -S "vg_name=$vg2" @tag +not check vg_field $vg1 vg_tags "tag,112" +not check vg_field $vg2 vg_tags "tag,112" +vgchange --deltag 112 +vgchange --addtag 113 -S "vg_name=$vg1" @tag +check vg_field $vg1 vg_tags "113,tag" +not check vg_field $vg2 vg_tags "113,tag" +vgchange --deltag 113 --deltag tag + +########################################### +# exercise process_each_lv with selection # +########################################### + +# select contains VGS field +lvchange --addtag 201 -S "vg_name=$vg1" +check lv_field $vg1/lv1 lv_tags 201 +check lv_field $vg1/lv2 lv_tags 201 +not check lv_field $vg2/lv3 lv_tags 201 +not check lv_field $vg2/lv4 lv_tags 201 +not check lv_field $vg2/lv1 lv_tags 201 +lvchange --deltag 201 $vg1 $vg2 + +# select contains LVS fiels +lvchange --addtag 202 -S "lv_name=lv2" +not check lv_field $vg1/lv1 lv_tags 202 +check lv_field $vg1/lv2 lv_tags 202 +not check lv_field $vg2/lv3 lv_tags 202 +not check lv_field $vg2/lv4 lv_tags 202 +not check lv_field $vg2/lv1 lv_tags 202 +lvchange --deltag 202 $vg1 $vg2 +lvchange --addtag 203 -S "lv_name=lv1" +check lv_field $vg1/lv1 lv_tags 203 +not check lv_field $vg1/lv2 lv_tags 203 +not check lv_field $vg2/lv3 lv_tags 203 +not check lv_field $vg2/lv4 lv_tags 203 +check lv_field $vg2/lv1 lv_tags 203 +lvchange --deltag 203 $vg1 $vg2 + +# select contains SEGS field +lvchange --addtag 204 -S "seg_start=8m" +not check lv_field $vg1/lv1 lv_tags 204 +check lv_field $vg1/lv2 lv_tags 204 +not check lv_field $vg2/lv3 lv_tags 204 +not check lv_field $vg2/lv4 lv_tags 204 +not check lv_field $vg2/lv1 lv_tags 204 +lvchange --deltag 204 $vg1 $vg2 + +# select contains PVS field - COMBINATION NOT ALLOWED! +lvchange --addtag 205 -S pv_name="$dev1" 2>err +grep "Can't report LV and PV fields at the same time" err +grep "Selection failed for LV" err +not check lv_field $vg1/lv1 lv_tags 205 +not check lv_field $vg1/lv2 lv_tags 205 +not check lv_field $vg2/lv3 lv_tags 205 +not check lv_field $vg2/lv4 lv_tags 205 +not check lv_field $vg2/lv1 lv_tags 205 + +# select contains PVSEGS field - COMBINATION NOT ALLOWED! +lvchange --addtag 206 -S "pvseg_start>=0" 2>err +grep "Can't report LV and PV fields at the same time" err +grep "Selection failed for LV" err +not check lv_field $vg1/lv1 lv_tags 206 +not check lv_field $vg1/lv2 lv_tags 206 +not check lv_field $vg2/lv3 lv_tags 206 +not check lv_field $vg2/lv4 lv_tags 206 +not check lv_field $vg2/lv1 lv_tags 206 + +# if LV name or tag is supplied together with the +# selection, the result is an intersection of both +lvchange --addtag 207 -S "lv_name=lv2" $vg1/lv1 +not check lv_field $vg1/lv1 lv_tags 207 +not check lv_field $vg1/lv2 lv_tags 207 +not check lv_field $vg2/lv3 lv_tags 207 +not check lv_field $vg2/lv4 lv_tags 207 +not check lv_field $vg2/lv1 lv_tags 207 +lvchange --deltag 207 $vg1 $vg2 +lvchange --addtag 208 -S "lv_name=lv2" $vg1/lv2 +not check lv_field $vg1/lv1 lv_tags 208 +check lv_field $vg1/lv2 lv_tags 208 +not check lv_field $vg2/lv3 lv_tags 208 +not check lv_field $vg2/lv4 lv_tags 208 +not check lv_field $vg2/lv1 lv_tags 208 +lvchange --deltag 208 $vg1 $vg2 +lvchange --addtag "tag" $vg1/lv2 +lvchange --addtag 209 -S "lv_name=lv3" @tag +not check lv_field $vg1/lv1 lv_tags "209,tag" +not check lv_field $vg1/lv2 lv_tags "209,tag" +not check lv_field $vg2/lv3 lv_tags "209,tag" +not check lv_field $vg2/lv4 lv_tags "209,tag" +not check lv_field $vg2/lv1 lv_tags "209,tag" +lvchange --deltag 209 $vg1 $vg2 +lvchange --addtag 210 -S "lv_name=lv2" @tag +not check lv_field $vg1/lv1 lv_tags "210,tag" +check lv_field $vg1/lv2 lv_tags "210,tag" +not check lv_field $vg2/lv3 lv_tags "210,tag" +not check lv_field $vg2/lv4 lv_tags "210,tag" +not check lv_field $vg2/lv1 lv_tags "210,tag" +lvchange --deltag 210 --deltag tag $vg1 $vg2 + +########################################### +# exercise process_each_pv with selection # +########################################### + +# select contains VGS field +pvchange --addtag 301 -S "vg_name=$vg1" +check pv_field "$dev1" pv_tags 301 +check pv_field "$dev2" pv_tags 301 +not check pv_field "$dev3" pv_tags 301 +not check pv_field "$dev4" pv_tags 301 +pvchange -a --deltag 301 + +# select contains LVS field +pvchange --addtag 302 -S "lv_name=lv2" +check pv_field "$dev1" pv_tags 302 +check pv_field "$dev2" pv_tags 302 +not check pv_field "$dev3" pv_tags 302 +not check pv_field "$dev4" pv_tags 302 +pvchange -a --deltag 302 + +# select contains SEGS field +pvchange --addtag 303 -S "seg_start=8m" +check pv_field "$dev1" pv_tags 303 +not check pv_field "$dev2" pv_tags 303 +not check pv_field "$dev3" pv_tags 303 +not check pv_field "$dev4" pv_tags 303 +pvchange -a --deltag 303 + +# select contains PVS field +pvchange --addtag 304 -S pv_name="$dev1" +check pv_field "$dev1" pv_tags 304 +not check pv_field "$dev2" pv_tags 304 +not check pv_field "$dev3" pv_tags 304 +not check pv_field "$dev4" pv_tags 304 +pvchange -a --deltag 304 + +# select contains PVSEGS field +pvchange --addtag 305 -S "pvseg_size=2" +not check pv_field "$dev1" pv_tags 305 +check pv_field "$dev2" pv_tags 305 +not check pv_field "$dev3" pv_tags 305 +not check pv_field "$dev4" pv_tags 305 +pvchange -a --deltag 305 + +# if PV name or tag is supplied together with the +# selection, the result is an intersection of both +pvchange --addtag 306 -S pv_name="$dev1" "$dev2" +not check pv_field "$dev1" pv_tags 306 +not check pv_field "$dev2" pv_tags 306 +not check pv_field "$dev3" pv_tags 306 +not check pv_field "$dev4" pv_tags 306 +pvchange -a --deltag 306 +pvchange --addtag 307 -S pv_name="$dev1" "$dev1" +check pv_field "$dev1" pv_tags 307 +not check pv_field "$dev2" pv_tags 307 +not check pv_field "$dev3" pv_tags 307 +not check pv_field "$dev4" pv_tags 307 +pvchange -a --deltag 307 +pvchange --addtag "tag" "$dev1" +pvchange --addtag 308 -S pv_name="$dev2" @tag +not check pv_field "$dev1" pv_tags "308,tag" +not check pv_field "$dev2" pv_tags "308,tag" +not check pv_field "$dev3" pv_tags "308,tag" +not check pv_field "$dev4" pv_tags "308,tag" +pvchange --deltag 308 "$dev1" +pvchange --addtag 309 -S pv_name="$dev1" @tag +check pv_field "$dev1" pv_tags "309,tag" +not check pv_field "$dev2" pv_tags "309,tag" +not check pv_field "$dev3" pv_tags "309,tag" +not check pv_field "$dev4" pv_tags "309,tag" +pvchange -a --deltag 309 --deltag tag + +######################### +# special cases to test # +######################### + +# if calling vgremove, make sure we're doing selection per-VG, not per-LV +# (vgremove calls process_each_vg with vgremove_single which itself +# iterates over LVs with process_each_lv_in_vg - so internally it actually +# operates per-LV, but we still need the selection to be done per-VG) +vgremove --yes -S 'lv_name=lv2' # should remove whole vg1, not just the lv2 +vgremove --yes $vg2 diff --git a/test/shell/snapshot-autoumount-dmeventd.sh b/test/shell/snapshot-autoumount-dmeventd.sh index 3b4b711..7967e86 100644 --- a/test/shell/snapshot-autoumount-dmeventd.sh +++ b/test/shell/snapshot-autoumount-dmeventd.sh @@ -1,5 +1,6 @@ -#!/bin/bash -# Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2010-2015 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 @@ -7,11 +8,14 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # no automatic extensions please -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest which mkfs.ext2 || skip @@ -22,24 +26,32 @@ aux prepare_dmeventd aux prepare_vg 2 mntdir="${PREFIX}mnt" -lvcreate -l 8 -n base $vg +lvcreate -aey -L8 -n base $vg mkfs.ext2 "$DM_DEV_DIR/$vg/base" -lvcreate -s -l 4 -n snap $vg/base +lvcreate -s -L4 -n snap $vg/base lvchange --monitor y $vg/snap mkdir "$mntdir" -mount "$DM_DEV_DIR/mapper/$vg-snap" "$mntdir" -mount -cat /proc/mounts | grep "$mntdir" -dd if=/dev/zero of="$mntdir/file$1" bs=1M count=16 -sync -#dmeventd only checks every 10 seconds :( -for i in {1..10}; do - cat /proc/mounts | grep "$mntdir" || break - sleep 1 +# Use remount-ro to avoid logging kernel WARNING +mount -o errors=remount-ro "$DM_DEV_DIR/mapper/$vg-snap" "$mntdir" + +test "$(dmsetup info -c --noheadings -o open $vg-snap)" -eq 1 + +grep "$mntdir" /proc/mounts + +# overfill 4M snapshot (with metadata) +not dd if=/dev/zero of="$mntdir/file" bs=1M count=4 conv=fdatasync + +# Should be nearly instant check of dmeventd for invalid snapshot. +# Wait here for umount and open_count drops to 0 as it may +# take a while to finalize umount operation (it might be already +# removed from /proc/mounts, but still opened). +for i in {1..100}; do + sleep .1 + test "$(dmsetup info -c --noheadings -o open $vg-snap)" -eq 0 && break done -cat /proc/mounts | not grep "$mntdir" +not grep "$mntdir" /proc/mounts vgremove -f $vg diff --git a/test/shell/snapshot-cluster.sh b/test/shell/snapshot-cluster.sh new file mode 100644 index 0000000..e6c9ab3 --- /dev/null +++ b/test/shell/snapshot-cluster.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Testing renaming snapshots in cluster +# https://bugzilla.redhat.com/show_bug.cgi?id=1136925 + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 1 + +lvcreate -aey -L1 -n $lv1 $vg +lvcreate -s -L1 -n $lv2 $vg/$lv1 +lvrename $vg/$lv2 $vg/$lv3 +lvremove -f $vg/$lv1 + +vgremove -f $vg diff --git a/test/shell/snapshot-maxsize.sh b/test/shell/snapshot-maxsize.sh new file mode 100644 index 0000000..43d4db1 --- /dev/null +++ b/test/shell/snapshot-maxsize.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Testing calculation of snapshot space +# https://bugzilla.redhat.com/show_bug.cgi?id=1035871 + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_pvs 1 +get_devs + +vgcreate $SHARED -s 4K "$vg" "${DEVICES[@]}" + +lvcreate -aey -L1 -n $lv1 $vg +# Snapshot should be large enough to handle any writes +lvcreate -L2 -s $vg/$lv1 -n $lv2 + +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv2" bs=1M count=1 oflag=direct + +# Snapshot must not be 'I'nvalid here +check lv_attr_bit state $vg/$lv2 "a" + +vgremove -f $vg diff --git a/test/shell/snapshot-merge-stack.sh b/test/shell/snapshot-merge-stack.sh new file mode 100644 index 0000000..b6763ca --- /dev/null +++ b/test/shell/snapshot-merge-stack.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise snapshot merge also when stacked + + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +which mkfs.ext3 || skip + +aux target_at_least dm-snapshot-merge 1 0 0 || skip + +aux prepare_vg 2 100 + +snap_and_merge() { + lvcreate -s -n $lv2 -L20 $vg/$lv1 "$dev2" + #dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=10 conv=fdatasync + aux udev_wait + mkfs.ext3 "$DM_DEV_DIR/$vg/$lv2" + sync + lvs -a $vg + + SLEEP_PID=$(aux hold_device_open $vg $lv1 20) + + # initiate background merge + lvconvert -b --merge $vg/$lv2 + + lvs -a -o+lv_merging,lv_merge_failed $vg + get lv_field $vg/$lv1 lv_attr | grep "Owi-ao" + get lv_field $vg/$lv2 lv_attr | grep "Swi-a-s---" + kill $SLEEP_PID + + aux delay_dev "$dev1" 0 200 "$(get first_extent_sector "$dev1"):" + lvchange --poll n --refresh $vg/$lv1 + dmsetup table + lvs -av -o+lv_merging,lv_merge_failed $vg + # Origin is closed and snapshot merge could run + get lv_field $vg/$lv1 lv_attr | grep "Owi-a-" + sleep 1 + check lv_attr_bit state $vg/$lv2 "a" + aux error_dev "$dev2" "$(get first_extent_sector "$dev2"):" + aux enable_dev "$dev1" + # delay to let snapshot merge 'discover' failing COW device + sleep 1 + sync + dmsetup status + lvs -a -o+lv_merging,lv_merge_failed $vg + check lv_attr_bit state $vg/$lv1 "m" + check lv_attr_bit state $vg/$lv2 "m" + + # device OK and running in full speed + aux enable_dev "$dev2" + + # reactivate so merge can finish + lvchange -an $vg + lvchange -ay $vg + sleep 1 + lvs -a -o+lv_merging,lv_merge_failed $vg + check lv_not_exists $vg $lv2 + fsck -n "$DM_DEV_DIR/$vg/$lv1" + + lvremove -f $vg +} + + +# First check merge on plain linear LV +lvcreate -aey -L50 -n $lv1 $vg "$dev1" +snap_and_merge + +# When available check merge of old snapshot with Thin LV being origin +if aux have_thin 1 0 0 ; then + lvcreate -T -L10 -V50 -n $lv1 $vg/pool "$dev1" + snap_and_merge +fi + +# TODO snapshot merge with Mirror, Raid, Cache... + +vgremove -f $vg diff --git a/test/shell/snapshot-merge-thin.sh b/test/shell/snapshot-merge-thin.sh new file mode 100644 index 0000000..a74567b --- /dev/null +++ b/test/shell/snapshot-merge-thin.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Exercise merge of old snapshots over thin + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux target_at_least dm-snapshot-merge 1 0 0 || skip +aux have_thin 1 0 0 || skip + +aux prepare_vg 2 + +lvcreate -T -L1 -V1 -n $lv1 $vg/pool "$dev1" +lvcreate -s -n $lv2 $vg/$lv1 + +# Take also thick snapshot of thin snapshot +lvcreate -s -L1 -n $lv3 $vg/$lv2 + +sleep 10 < "$DM_DEV_DIR/$vg/$lv1" >/dev/null 2>&1 & +PID_SLEEP=$! + +# initiated merge that cannot proceed, but there is no need to retry +lvconvert --config 'activation/retry_deactivation=0' --merge $vg/$lv2 + +kill $PID_SLEEP +wait + +# Remove everything +lvremove --yes $vg + +# No LV left in VG +check vg_field $vg lv_count "0" + + +# Create again pool with thin and thick snapshot +lvcreate -T -L1 -V1 -n $lv1 $vg/pool "$dev1" +lvcreate -s -n $lv2 -L2 $vg/$lv1 "$dev2" +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv2" bs=1M count=1 oflag=direct + +lvs -a -o+lv_merging,lv_merge_failed $vg +aux delay_dev "$dev1" 0 400 "$(get first_extent_sector "$dev1"):" + +# Initiate background merge +lvconvert -b --merge $vg/$lv2 + +# Query status of snapshot immediately after start +# - may hit race of checking already in-progress merge +#lvs -a -o+lv_merging,lv_merge_failed $vg +check lv_field $vg/$lv1 lv_merging "merging" + +lvm lvpoll -i 1 --polloperation merge $vg/$lv1 + +# Here should be everything already merged +#lvs -a -o+lv_merging,lv_merge_failed $vg +# check we see thin filled 100% (1MiB written to 1MiB LV) +check lv_field $vg/$lv1 data_percent "100.00" + +# -real must not exist for $vg/$lv1 +not dmsetup info ${vg}-${lv1}-real 2>&1 | tee out +grep "not exist" out + +not dmsetup info ${vg}-${lv2}-cow 2>&1 | tee out +grep "not exist" out + +check lv_not_exists $vg $lv2 + +vgremove -f $vg diff --git a/test/shell/snapshot-merge.sh b/test/shell/snapshot-merge.sh index a42b6f8..ff9de96 100644 --- a/test/shell/snapshot-merge.sh +++ b/test/shell/snapshot-merge.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2010-2017 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 @@ -7,9 +8,14 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + -. lib/test +. lib/inittest + +# test if snapshot-merge target is available +aux target_at_least dm-snapshot-merge 1 0 0 || skip which mkfs.ext3 || skip @@ -18,22 +24,24 @@ lvdev_() { } snap_lv_name_() { - echo ${1}_snap + echo "${1}_snap" } setup_merge_() { local VG_NAME=$1 local LV_NAME=$2 local NUM_EXTRA_SNAPS=${3:-0} - local BASE_SNAP_LV_NAME=$(snap_lv_name_ $LV_NAME) + local BASE_SNAP_LV_NAME + + BASE_SNAP_LV_NAME=$(snap_lv_name_ $LV_NAME) - lvcreate -n $LV_NAME -l 50%FREE $VG_NAME + lvcreate -aey -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} + for i in $(seq 1 $NUM_EXTRA_SNAPS); do + lvcreate -s -n ${BASE_SNAP_LV_NAME}_${i} -l 20%ORIGIN ${VG_NAME}/${LV_NAME} done fi } @@ -43,26 +51,37 @@ mkdir test_mnt # test full merge of a single LV setup_merge_ $vg $lv1 -# now that snapshot LV is created: test if snapshot-merge target is available -aux target_at_least snapshot-merge 1 0 0 || skip # make sure lvconvert --merge requires explicit LV listing -not lvconvert --merge 2>err -lvconvert --merge $vg/$(snap_lv_name_ $lv1) +not lvconvert --merge + +# check read-only origin is protected from being merge +lvchange -pr $vg/$lv1 +not lvconvert --merge "$vg/$(snap_lv_name_ "$lv1")" |& tee out +grep "read-only origin" out +lvchange -prw $vg/$lv1 + +# check exclusive lock is preserved after merge +check lv_field "$vg/$lv1" lv_active_exclusively "active exclusively" +lvconvert --merge "$vg/$(snap_lv_name_ "$lv1")" +check lv_field "$vg/$lv1" lv_active_exclusively "active exclusively" lvremove -f $vg/$lv1 +setup_merge_ $vg $lv1 +lvconvert --mergesnapshot "$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) +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 mount "$(lvdev_ $vg $lv1)" test_mnt -lvconvert --merge $vg/$(snap_lv_name_ $lv1) +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 @@ -78,13 +97,12 @@ dm_table $vg-$lv1 | grep " snapshot-merge " || dm_table $vg-$lv1 | grep " linear # 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 mount "$(lvdev_ $vg $lv1)" test_mnt -lvconvert --merge $vg/$(snap_lv_name_ $lv1) +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 @@ -95,19 +113,27 @@ lvremove -f $vg/$lv1 # test multiple snapshot merge; tests copy out that is driven by merge setup_merge_ $vg $lv1 1 -lvconvert --merge $vg/$(snap_lv_name_ $lv1) +lvconvert --merge "$vg/$(snap_lv_name_ "$lv1")" lvremove -f $vg/$lv1 +# test merging cannot start on already merging origin +setup_merge_ $vg $lv1 3 +lvchange -an $vg +lvs -a $vg +lvconvert --merge "$vg/$(snap_lv_name_ "$lv1")" +not lvconvert --merge "$vg/$(snap_lv_name_ "$lv1")_1" 2>&1 | tee err +grep "Cannot merge snapshot" err +lvremove -f $vg/$lv1 # test merging multiple snapshots that share the same tag setup_merge_ $vg $lv1 setup_merge_ $vg $lv2 -lvchange --addtag this_is_a_test $vg/$(snap_lv_name_ $lv1) -lvchange --addtag this_is_a_test $vg/$(snap_lv_name_ $lv2) +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 $vg >out -not grep $(snap_lv_name_ $lv1) out -not grep $(snap_lv_name_ $lv2) out +lvs $vg | tee out +not grep "$(snap_lv_name_ "$lv1")" out +not grep "$(snap_lv_name_ "$lv2")" out lvremove -f $vg/$lv1 $vg/$lv2 # FIXME following tests would need to poll merge progress, via periodic lvs? diff --git a/test/shell/snapshot-raid.sh b/test/shell/snapshot-raid.sh new file mode 100644 index 0000000..3dfe624 --- /dev/null +++ b/test/shell/snapshot-raid.sh @@ -0,0 +1,423 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test snapshots of raid + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 3 0 || skip +which mkfs.ext4 || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +snap_dir="mnt_snap" +mkdir -p "$snap_dir" + +# add and remove a snapshot + +test_add_del_snap() { + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" + mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + + touch "$mount_dir/B" + not ls "$snap_dir/B" + touch "$snap_dir/C" + not ls "$mount_dir/C" + ls "$mount_dir/A" + ls "$snap_dir/A" + + umount "$snap_dir" + lvremove -y $vg/snap + umount "$mount_dir" +} + +# add and remove snapshot while origin has a missing raid image + +test_snap_with_missing_image() { + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + aux disable_dev "$dev1" + lvs -a -o+devices $vg + + not lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" + + aux enable_dev "$dev1" + aux wait_for_sync $vg $lv1 + + lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" + + aux disable_dev "$dev1" + lvs -a -o+devices $vg + + lvremove -y $vg/snap + + aux enable_dev "$dev1" + vgextend --restoremissing $vg "$dev1" + lvs -a -o+devices $vg + aux wait_for_sync $vg $lv1 + + umount "$mount_dir" +} + +# raid image is lost and restored while a snapshot exists + +test_missing_image_with_snap() { + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" + mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + + aux disable_dev "$dev1" + lvs -a -o+devices $vg + + touch "$mount_dir/B" + not ls "$snap_dir/B" + touch "$snap_dir/C" + not ls "$mount_dir/C" + ls "$mount_dir/A" + ls "$snap_dir/A" + + aux enable_dev "$dev1" + aux wait_for_sync $vg $lv1 + + ls "$mount_dir/B" + ls "$snap_dir/C" + + umount "$snap_dir" + lvremove -y $vg/snap + umount "$mount_dir" +} + +# add and remove raid image while snapshot exists + +test_add_del_image_with_snap() { + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" + mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + + touch "$mount_dir/B" + touch "$snap_dir/C" + + lvconvert -y -m+1 $vg/$lv1 "$dev4" + aux wait_for_sync $vg $lv1 + + ls "$mount_dir/B" + ls "$snap_dir/C" + ls "$mount_dir/A" + ls "$snap_dir/A" + + touch "$mount_dir/B2" + touch "$snap_dir/C2" + + lvconvert -y -m-1 $vg/$lv1 "$dev4" + + ls "$mount_dir/B" + ls "$snap_dir/C" + ls "$mount_dir/A" + ls "$snap_dir/A" + ls "$mount_dir/B2" + ls "$snap_dir/C2" + umount "$snap_dir" + lvremove -y $vg/snap + + umount "$mount_dir" +} + +test_replace_image_with_snap() { + # add an image to replace + lvconvert -y -m+1 $vg/$lv1 "$dev4" + aux wait_for_sync $vg $lv1 + + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" + mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + + touch "$mount_dir/B" + touch "$snap_dir/C" + + lvconvert -y --replace "$dev4" $vg/$lv1 "$dev5" + aux wait_for_sync $vg $lv1 + + ls "$mount_dir/B" + ls "$snap_dir/C" + ls "$mount_dir/A" + ls "$snap_dir/A" + + touch "$mount_dir/B2" + touch "$snap_dir/C2" + + umount "$snap_dir" + lvremove -y $vg/snap + + # put lv1 back to original state with images on dev1 and dev2 + lvconvert -y -m-1 $vg/$lv1 "$dev5" + + umount "$mount_dir" +} + +test_repair_image_with_snap() { + # add an image to repair + lvconvert -y -m+1 $vg/$lv1 "$dev4" + aux wait_for_sync $vg $lv1 + + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" + mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + + touch "$mount_dir/B" + touch "$snap_dir/C" + + aux disable_dev "$dev4" + lvs -a -o+devices $vg + + lvconvert -y --repair $vg/$lv1 "$dev5" + aux wait_for_sync $vg $lv1 + + ls "$mount_dir/B" + ls "$snap_dir/C" + ls "$mount_dir/A" + ls "$snap_dir/A" + + touch "$mount_dir/B2" + touch "$snap_dir/C2" + + umount "$snap_dir" + lvremove -y $vg/snap + + aux enable_dev "$dev4" + lvs -a -o+devices $vg + vgck --updatemetadata $vg + + # put lv1 back to original state with images on dev1 and dev2 + lvconvert -y -m-1 $vg/$lv1 "$dev5" + + umount "$mount_dir" +} + +test_merge_snap() +{ + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" + mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + + touch "$mount_dir/B" + touch "$snap_dir/C" + + umount "$snap_dir" + + lvconvert --merge $vg/snap + + # the merge will begin once the origin is not in use + umount "$mount_dir" + + lvs -a $vg + lvchange -an $vg/$lv1 + lvchange -ay $vg/$lv1 + lvs -a $vg + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + ls "$mount_dir/A" + ls "$mount_dir/C" + not ls "$mount_dir/B" + + umount "$mount_dir" +} + +test_extend_snap() +{ + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + lvcreate -s -n snap -L8M $vg/$lv1 "$dev3" + mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + + touch "$mount_dir/B" + touch "$snap_dir/C" + + lvextend -L+8M $vg/snap + + umount "$mount_dir" + umount "$snap_dir" + lvremove -y $vg/snap +} + +test_fill_snap() +{ + mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + touch "$mount_dir/A" + + lvcreate -s -n snap -L4M $vg/$lv1 "$dev3" + + lvs -a $vg + get lv_field $vg/snap lv_attr | grep "swi-a-s---" + + dd if=/dev/zero of="$mount_dir/1" bs=1M count=1 oflag=direct + dd if=/dev/zero of="$mount_dir/2" bs=1M count=1 oflag=direct + dd if=/dev/zero of="$mount_dir/3" bs=1M count=1 oflag=direct + dd if=/dev/zero of="$mount_dir/4" bs=1M count=1 oflag=direct + dd if=/dev/zero of="$mount_dir/5" bs=1M count=1 oflag=direct + + lvs -a $vg + get lv_field $vg/snap lv_attr | grep "swi-I-s---" + check lv_field $vg/snap data_percent "100.00" + + umount "$mount_dir" + lvremove -y $vg/snap +} + +aux prepare_devs 5 200 + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" + +lvcreate --type raid1 -m1 -n $lv1 -L32M $vg "$dev1" "$dev2" +dmsetup table +aux wait_for_sync $vg $lv1 +test_add_del_snap +test_snap_with_missing_image +test_missing_image_with_snap +test_add_del_image_with_snap +test_replace_image_with_snap +test_repair_image_with_snap +test_merge_snap +test_extend_snap +test_fill_snap +lvremove -y $vg/$lv1 + +# INTEGRITY TESTS FOLLOWING: +if aux have_integrity 1 5 0; then + +lvcreate --type raid1 -m1 --raidintegrity y -n $lv1 -L32M $vg "$dev1" "$dev2" +aux wait_recalc $vg ${lv1}_rimage_0 +aux wait_recalc $vg ${lv1}_rimage_1 +aux wait_for_sync $vg $lv1 +test_add_del_snap +test_snap_with_missing_image +test_missing_image_with_snap +test_add_del_image_with_snap +test_replace_image_with_snap +test_repair_image_with_snap +test_merge_snap +test_extend_snap +test_fill_snap +lvremove -y $vg/$lv1 + +# Repeat above with cache|writecache on the raid image? + +# +# Add/remove integrity while a snapshot exists +# + +lvcreate --type raid1 -m1 -n $lv1 -L32M $vg "$dev1" "$dev2" +aux wait_for_sync $vg $lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" +touch "$mount_dir/A" + +lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" +mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + +touch "$mount_dir/B" +touch "$snap_dir/C" + +lvconvert --raidintegrity y $vg/$lv1 +aux wait_recalc $vg ${lv1}_rimage_0 +aux wait_recalc $vg ${lv1}_rimage_1 + +ls "$mount_dir/B" +ls "$snap_dir/C" +ls "$mount_dir/A" +ls "$snap_dir/A" + +touch "$mount_dir/B2" +touch "$snap_dir/C2" + +lvconvert --raidintegrity n $vg/$lv1 + +ls "$mount_dir/B" +ls "$snap_dir/C" +ls "$mount_dir/A" +ls "$snap_dir/A" +ls "$mount_dir/B2" +ls "$snap_dir/C2" +umount "$snap_dir" +umount "$mount_dir" +lvremove -y $vg/snap +lvremove -y $vg/$lv1 + +# +# Add integrity not allowed with missing image and snapshot exists +# + +lvcreate --type raid1 -m1 -n $lv1 -L32M $vg "$dev1" "$dev2" +aux wait_for_sync $vg $lv1 +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" +touch "$mount_dir/A" + +lvcreate -s -n snap -L12M $vg/$lv1 "$dev3" +mount "$DM_DEV_DIR/$vg/snap" "$snap_dir" + +touch "$mount_dir/B" +touch "$snap_dir/C" + +aux disable_dev "$dev1" +lvs -a $vg + +not lvconvert --raidintegrity y $vg/$lv1 + +aux enable_dev "$dev1" +lvs -a $vg + +umount "$snap_dir" +umount "$mount_dir" +lvremove -y $vg/snap +lvremove -y $vg/$lv1 + +fi # INTEGRITY TESTS SKIPPED + +vgremove -ff $vg diff --git a/test/shell/snapshot-reactivate.sh b/test/shell/snapshot-reactivate.sh new file mode 100644 index 0000000..4138e6e --- /dev/null +++ b/test/shell/snapshot-reactivate.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# +# Checking consistency of old-snapshot metadata after de/activation +# Validates recent snapshot target kernel updates and error +# is triggered by kernel 3.14-rc[1..5] +# http://www.redhat.com/archives/dm-devel/2014-March/msg00005.html +# + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Snapshot should remain unmodified +check_s_() { + check dev_md5sum $vg s + #diff data "$DM_DEV_DIR/$vg/s" +} + +which md5sum || skip + +aux prepare_vg + +# 8M file with some random data +dd if=/dev/urandom of=data bs=1M count=1 conv=fdatasync +dd if=data of=data bs=1M count=7 seek=1 conv=fdatasync +echo "$(md5sum data | cut -d' ' -f1) $DM_DEV_DIR/$vg/s" >md5.${vg}-s + +lvcreate -aey -L 8M -n o $vg +dd if=data of="$DM_DEV_DIR/$vg/o" bs=1M conv=fdatasync + +lvcreate -L 8M -s -n s $vg/o +check_s_ + +dd if=data of="$DM_DEV_DIR/$vg/o" bs=1234567 count=1 skip=1 conv=fdatasync +check_s_ +lvchange -an $vg + +lvchange -ay $vg +check_s_ + +dd if=data of="$DM_DEV_DIR/$vg/o" bs=1234567 count=2 skip=1 conv=fdatasync +check_s_ + +lvchange -an $vg +lvchange -ay $vg +check_s_ + +vgremove -f $vg diff --git a/test/shell/snapshot-remove-dmsetup.sh b/test/shell/snapshot-remove-dmsetup.sh new file mode 100644 index 0000000..ab5e2e9 --- /dev/null +++ b/test/shell/snapshot-remove-dmsetup.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# check if 'dmsetup --noflush' will work properly for mounted snapshot + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which mkfs.ext2 || skip + +aux prepare_vg 5 + +# Create stacked device +lvcreate --type snapshot -s -L10 -n $lv1 $vg --virtualsize 100M +aux lvmconf "devices/scan_lvs = 1" +aux extend_filter_LVMTEST +aux extend_devices "$DM_DEV_DIR"/$vg/$lv1 +vgcreate $vg1 "$DM_DEV_DIR"/$vg/$lv1 + +lvcreate -L20 -n $lv1 $vg1 +lvcreate -L10 -n snap -s $vg1/$lv1 + +mkfs.ext2 "$DM_DEV_DIR/$vg1/snap" +mkdir mnt +mount -o errors=remount-ro "$DM_DEV_DIR/$vg1/snap" mnt + +sync + +# intentionally suspend layer below +dmsetup suspend $vg-$lv1 + +# now this should pass without blocking +dmsetup suspend --noflush --nolockfs $vg1-snap & +DMPID=$! +#dmsetup suspend $vg1-snap & + +sleep .5 + +dmsetup info --noheadings -c -o suspended $vg1-snap | tee out +should grep -i suspend out + +# unlock device below +dmsetup resume $vg-$lv1 +# so this will pass without blocking on udev +# otherwise --noudevsync would be needed +dmsetup resume $vg1-snap + +# Expecting success from 'dmsetup' +wait $DMPID + + +# Try how force removal works (and wait till there is no user) +sync +sleep .5 +dmsetup suspend $vg-$lv1 +# needs to fail as device is still open +not dmsetup remove --force $vg1-snap & +DMPID=$! + +# on older snapshot target 'remove' will wait till $lv1 is resumed +if aux target_at_least dm-snapshot 1 6 0 ; then +sleep .5 + +dmsetup table $vg1-snap | tee out +should grep -i error out +fi + +dmsetup resume $vg-$lv1 + +# Expecting success from 'not dmsetup' +wait $DMPID + +# check it really is now 'error' target +dmsetup table $vg1-snap | tee out +grep error out + +umount mnt || true + +lvremove -f $vg1 + +vgremove -ff $vg1 +vgremove -ff $vg diff --git a/test/shell/snapshot-rename.sh b/test/shell/snapshot-rename.sh new file mode 100644 index 0000000..e8d77a3 --- /dev/null +++ b/test/shell/snapshot-rename.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Testing renaming snapshots (had problem in cluster) +# https://bugzilla.redhat.com/show_bug.cgi?id=1136925 + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 1 + +lvcreate -aey -L1 -n $lv1 $vg +lvcreate -s -L1 -n $lv2 $vg/$lv1 +lvrename $vg/$lv2 $vg/$lv3 +lvremove -f $vg/$lv1 + +vgremove -f $vg diff --git a/test/shell/snapshot-usage-exa.sh b/test/shell/snapshot-usage-exa.sh new file mode 100644 index 0000000..475960d --- /dev/null +++ b/test/shell/snapshot-usage-exa.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check very large device size (upto 15Exa bytes) +# this needs 64bit arch + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux can_use_16T || skip + +aux prepare_pvs 1 +get_devs + +# Prepare large enough backend device +vgcreate -s 4M "$vg" "${DEVICES[@]}" +lvcreate --type snapshot -s -l 100%FREE -n $lv $vg --virtualsize 15P + +aux lvmconf "devices/scan_lvs = 1" +aux extend_filter_LVMTEST +aux extend_devices "$DM_DEV_DIR/$vg/$lv" + +# Check usability with largest extent size +pvcreate "$DM_DEV_DIR/$vg/$lv" +vgcreate -s 4G $vg1 "$DM_DEV_DIR/$vg/$lv" + +lvcreate -an -Zn -l50%FREE -n $lv1 $vg1 +lvcreate -s -l100%FREE -n $lv2 $vg1/$lv1 +check lv_field $vg1/$lv2 size "7.50p" +lvremove -ff $vg1 + +lvcreate --type snapshot -V15E -l1 -n $lv1 -s $vg1 +check lv_field $vg1/$lv1 origin_size "15.00e" + +vgremove -ff $vg1 +vgremove -ff $vg diff --git a/test/shell/snapshot-usage.sh b/test/shell/snapshot-usage.sh new file mode 100644 index 0000000..0f14dd6 --- /dev/null +++ b/test/shell/snapshot-usage.sh @@ -0,0 +1,205 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# no automatic extensions please + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +MKFS=mkfs.ext2 +which $MKFS || skip + +fill() { + dd if=/dev/zero of="$DM_DEV_DIR/${2:-$vg1/lvol0}" bs=$1 count=1 oflag=direct || \ + die "Snapshot does not fit $1" +} + +cleanup_tail() +{ + test -z "${SLEEP_PID-}" || kill $SLEEP_PID || true + wait + vgremove -ff $vg1 || true + vgremove -ff $vg + aux teardown +} + +TSIZE=15P +aux can_use_16T || TSIZE=15T + +# With different snapshot target driver we may obtain different results. +# Older targets have metadata leak bug which needs extra compenstion. +# Ancient targets do not even provide separate info for metadata. +EXPECT1="16.00k" +EXPECT2="512.00k" +EXPECT3="32.00k" +EXPECT4="66.67" +if aux target_at_least dm-snapshot 1 10 0 ; then + # Extra metadata size + EXPECT4="0.00" + + if aux target_at_least dm-snapshot 1 12 0 ; then + # When fixed leak, expect smaller sizes + EXPECT1="12.00k" + EXPECT2="384.00k" + EXPECT3="28.00k" + fi +fi + +aux prepare_pvs 1 +get_devs + +vgcreate -s 4M "$vg" "${DEVICES[@]}" + +# Play with 1 extent +lvcreate -aey -l1 -n $lv $vg +# 100%LV is not supported for snapshot +fail lvcreate -s -l 100%LV -n snap $vg/$lv 2>&1 | tee out +grep 'Please express size as %FREE, %ORIGIN, %PVS or %VG' out +# 100%ORIGIN needs to have enough space for all data and needs to round-up +lvcreate -s -l 100%ORIGIN -n $lv1 $vg/$lv +# everything needs to fit +fill 4M $vg/$lv1 +lvremove -f $vg + + +# Automatically activates exclusively in cluster +lvcreate --type snapshot -s -l 100%FREE -n $lv $vg --virtualsize $TSIZE + +aux extend_filter_LVMTEST +aux extend_devices "$DM_DEV_DIR/$vg/$lv" +aux lvmconf "devices/scan_lvs = 1" +aux lvmconf "activation/snapshot_autoextend_percent = 20" \ + "activation/snapshot_autoextend_threshold = 50" + +# Check usability with smallest (1k) extent size ($lv has 15P) +pvcreate --yes --setphysicalvolumesize 4T "$DM_DEV_DIR/$vg/$lv" +trap 'cleanup_tail' EXIT +vgcreate -s 4K $vg1 "$DM_DEV_DIR/$vg/$lv" + +# Play with small 1k 128 extents +lvcreate -aey -L128K -n $lv $vg1 +# 100%ORIGIN needs to have enough space for all data +lvcreate -s -l 100%ORIGIN -n snap100 $vg1/$lv +# everything needs to fit +fill 128k $vg1/snap100 + +# 50%ORIGIN needs to have enough space for 50% of data +lvcreate -s -l 50%ORIGIN -n snap50 $vg1/$lv +fill 64k $vg1/snap50 + +lvcreate -s -l 25%ORIGIN -n snap25 $vg1/$lv +fill 32k $vg1/snap25 + +# Check we do not provide too much extra space +not fill 33k $vg1/snap25 + +lvs -a $vg1 +lvremove -f $vg1 + +# Test virtual snapshot over /dev/zero +lvcreate --type snapshot -V50 -L10 -n $lv1 -s $vg1 +CHECK_ACTIVE="active" +test ! -e LOCAL_CLVMD || CHECK_ACTIVE="local exclusive" +check lv_field $vg1/$lv1 lv_active "$CHECK_ACTIVE" +lvchange -an $vg1 + +# On cluster snapshot gets exclusive activation +lvchange -ay $vg1 +check lv_field $vg1/$lv1 lv_active "$CHECK_ACTIVE" + +# Test removal of opened (but unmounted) snapshot (device busy) for a while +SLEEP_PID=$(aux hold_device_open $vg1 $lv1 60) + +# Opened virtual snapshot device is not removable +# it should retry device removal for a few seconds +not lvremove -f $vg1/$lv1 + +kill $SLEEP_PID +SLEEP_PID= +# Wait for killed task, so there is no device holder +wait + +lvremove -f $vg1/$lv1 +check lv_not_exists $vg1 $lv1 + +# Check border size +lvcreate -aey -L4095G $vg1 +lvcreate -s -L100K $vg1/lvol0 +fill 4K +check lv_field $vg1/lvol1 data_percent "12.00" + +lvremove -ff $vg1 + +# Create 4KB snapshot, does not need to be active here +lvcreate -an -Zn -l1 -n $lv1 $vg1 +not lvcreate -s -l1 $vg1/$lv1 +# snapshot cannot be smaller then 3 chunks (12K) +not lvcreate -s -l2 $vg1/$lv1 +lvcreate -s -l30 -n $lv2 $vg1/$lv1 +check lv_field $vg1/$lv2 size "$EXPECT1" + +not lvcreate -s -c512 -l128 $vg1/$lv1 +lvcreate -s -c128 -l1700 -n $lv3 $vg1/$lv1 +# 3 * 128 +check lv_field $vg1/$lv3 size "$EXPECT2" +lvremove -ff $vg1 + +lvcreate -aey -l5 $vg1 +lvcreate -s -l3 $vg1/lvol0 + +# Fill 4KB -> 100% snapshot (1x 4KB chunk) +fill 4K +check lv_field $vg1/lvol1 data_percent "100.00" + +# Check it resizes 100% full valid snapshot to fit threshold +lvextend --use-policies $vg1/lvol1 +check lv_field $vg1/lvol1 data_percent "50.00" + +fill 4K +lvextend --use-policies $vg1/lvol1 +check lv_field $vg1/lvol1 size "24.00k" + +lvextend -l+8 $vg1/lvol1 +check lv_field $vg1/lvol1 size "$EXPECT3" + +fill 20K + +lvremove -f $vg1 + +# Check snapshot really deletes COW header for read-only snapshot +# Test needs special relation between chunk size and extent size +# This test expects extent size 1K +aux lvmconf "allocation/wipe_signatures_when_zeroing_new_lvs = 1" +lvcreate -aey -L4 -n $lv $vg1 +lvcreate -c 8 -s -L1 -n snap $vg1/$lv +# Populate snapshot +#dd if=/dev/urandom of="$DM_DEV_DIR/$vg1/$lv" bs=4096 count=10 +$MKFS "$DM_DEV_DIR/$vg1/$lv" +lvremove -f $vg1/snap + +# Undeleted header would trigger attempt to access +# beyond end of COW device +# Fails to create when chunk size is different +lvcreate -s -pr -l3 -n snap $vg1/$lv + +# When header is undelete, fails to read snapshot without read errors +#dd if="$DM_DEV_DIR/$vg1/snap" of=/dev/null bs=1M count=2 +fsck -n "$DM_DEV_DIR/$vg1/snap" + +# This test would trigger read of weird percentage for undeleted header +# And since older snapshot target counts with metadata sectors +# we have 2 valid results (unsure about correct version number) +check lv_field $vg1/snap data_percent "$EXPECT4" + +vgremove -ff $vg1 diff --git a/test/shell/snapshots-of-mirrors.sh b/test/shell/snapshots-of-mirrors.sh index 183d3ac..f2f2943 100644 --- a/test/shell/snapshots-of-mirrors.sh +++ b/test/shell/snapshots-of-mirrors.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2010 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2010,2018 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 @@ -7,25 +8,29 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + +. lib/inittest -. lib/test +aux lvmconf "global/support_mirrored_mirror_log=1" aux prepare_vg 4 -# Attempt to create snapshot of a mirror origin - should fail -lvcreate -m 1 -L 10M -n lv $vg +lvcreate -aey --type mirror -m 1 -L 10M --nosync -n lv $vg +# Create snapshot of a mirror origin 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 +lvconvert --type mirror -m2 $vg/lv # Down-convert (mirror -> mirror) -lvconvert -m1 $vg/lv +lvconvert -m 1 $vg/lv # Up-convert (mirror -> mirror) -- Not supported! not lvconvert -m2 $vg/lv @@ -34,7 +39,10 @@ not lvconvert -m2 $vg/lv lvconvert --mirrorlog core $vg/lv # Log conversion (core -> mirrored) -lvconvert --mirrorlog mirrored $vg/lv +# FIXME on cluster +SHOULD="" +test -e LOCAL_CLVMD && SHOULD=should +$SHOULD lvconvert --mirrorlog mirrored $vg/lv # Log conversion (mirrored -> core) lvconvert --mirrorlog core $vg/lv diff --git a/test/shell/stray-device-node.sh b/test/shell/stray-device-node.sh new file mode 100644 index 0000000..003afb7 --- /dev/null +++ b/test/shell/stray-device-node.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 3 +get_devs + +# Avoid manipulation with real /dev dir +test "$DM_DEV_DIR" = "/dev" && skip "Skipping stray test on real /dev dir" + +cp -r "$dev1" "$DM_DEV_DIR/stray" + +vgcreate $SHARED "$vg" "${DEVICES[@]}" +lvcreate -an -Zn --type mirror -m 1 -l 1 -n mirror $vg +aux disable_dev "$dev1" +# FIXME: +# for the .cache use case we need to run pvscan +# to keep clvmd in sync. +pvscan +vgreduce --removemissing --force $vg +aux enable_dev "$dev1" + +rm -f "$DM_DEV_DIR/stray" diff --git a/test/shell/stress_multi_threads_1.sh b/test/shell/stress_multi_threads_1.sh new file mode 100644 index 0000000..c5695eb --- /dev/null +++ b/test/shell/stress_multi_threads_1.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip; + +aux prepare_devs 6 +get_devs + +pvcreate -M2 "${DEVICES[@]}" + +vgcreate $SHARED -M2 "$vg1" "$dev1" "$dev2" "$dev3" +vgcreate $SHARED -M2 "$vg2" "$dev4" "$dev5" "$dev6" + +test_vg_thread1() +{ + for i in {1..1000} + do + # Create new logic volume and deactivate it + lvcreate -a n --zero n -l 1 -n foo $vg1 + + # Set minor number + lvchange $vg1/foo -My --major=255 --minor=123 + + # Activate logic volume + lvchange $vg1/foo -a y + + # Extend logic volume with 10% + lvextend -l+10 $vg1/foo + + # Deactivate logic volume + lvchange $vg1/foo -a n + + # Deactivate volume group + vgchange $vg1 -a n + + # Activate volume group with shareable mode + vgchange $vg1 -a sy + + # lvextend fails due to mismatched lock mode + not lvextend -l+10 $vg1/foo + + # Promote volume group to exclusive mode + vgchange $vg1 -a ey + + lvreduce -f -l-4 $vg1/foo + + lvchange -an $vg1/foo + lvremove $vg1/foo + done +} + +test_vg_thread2() +{ + for i in {1..1000} + do + # Create new logic volume and deactivate it + lvcreate -a n --zero n -l 1 -n foo $vg2 + + # Set minor number + lvchange $vg2/foo -My --major=255 --minor=124 + + # Activate logic volume + lvchange $vg2/foo -a y + + # Extend logic volume with 10% + lvextend -l+10 $vg2/foo + + # Deactivate logic volume + lvchange $vg2/foo -a n + + # Deactivate volume group + vgchange $vg2 -a n + + # Activate volume group with shareable mode + vgchange $vg2 -a sy + + # lvextend fails due to mismatched lock mode + not lvextend -l+10 $vg2/foo + + # Promote volume group to exclusive mode + vgchange $vg2 -a ey + + lvreduce -f -l-4 $vg2/foo + + lvchange -an $vg2/foo + lvremove $vg2/foo + done +} + +test_vg_thread1 & +WAITPID=$! + +test_vg_thread2 & +WAITPID="$WAITPID "$! + +wait $WAITPID + +vgremove -ff $vg1 +vgremove -ff $vg2 diff --git a/test/shell/stress_multi_threads_2.sh b/test/shell/stress_multi_threads_2.sh new file mode 100644 index 0000000..9b586a2 --- /dev/null +++ b/test/shell/stress_multi_threads_2.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip; + +aux prepare_devs 8 +get_devs + +pvcreate -M2 "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" + +test_vg_thread1() +{ + for i in {1..1000} + do + vgcreate $SHARED -M2 "$vg1" "$dev1" "$dev2" "$dev3" + vgremove -ff $vg1 + done +} + +test_vg_thread2() +{ + vgcreate $SHARED -M2 "$vg2" "$dev4" "$dev5" "$dev6" + + for i in {1..1000} + do + # Create new logic volume and deactivate it + lvcreate -a n --zero n -l 1 -n foo $vg2 + + # Set minor number + lvchange $vg2/foo -My --major=255 --minor=124 + + # Activate logic volume + lvchange $vg2/foo -a y + + # Extend logic volume with 10% + lvextend -l+10 $vg2/foo + + # Deactivate logic volume + lvchange $vg2/foo -a n + + # Deactivate volume group + vgchange $vg2 -a n + + # Activate volume group with shareable mode + vgchange $vg2 -a sy + + # lvextend fails due to mismatched lock mode + not lvextend -l+10 $vg2/foo + + # Promote volume group to exclusive mode + vgchange $vg2 -a ey + + lvreduce -f -l-4 $vg2/foo + + lvchange -an $vg2/foo + lvremove $vg2/foo + done + + vgremove -ff $vg2 +} + +test_vg_thread3() +{ + for i in {1..1000} + do + pvcreate -M2 "$dev7" "$dev8" + pvremove "$dev7" + pvremove "$dev8" + done +} + +test_vg_thread1 & +WAITPID=$! + +test_vg_thread2 & +WAITPID="$WAITPID "$! + +test_vg_thread3 & +WAITPID="$WAITPID "$! + +wait $WAITPID diff --git a/test/shell/stress_single_thread.sh b/test/shell/stress_single_thread.sh new file mode 100644 index 0000000..7982e9d --- /dev/null +++ b/test/shell/stress_single_thread.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate, 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip; + +aux prepare_vg 3 + +for i in {1..1000} +do + # Create new logic volume and deactivate it + lvcreate -a n --zero n -l 1 -n foo $vg + + # Set minor number + lvchange $vg/foo -My --major=255 --minor=123 + + # Activate logic volume + lvchange $vg/foo -a y + + # Check device mapper + dmsetup info $vg-foo | tee info + grep -E "^Major, minor: *[0-9]+, 123" info + + # Extend logic volume with 10% + lvextend -l+10 $vg/foo + + # Deactivate logic volume + lvchange $vg/foo -a n + + # Deactivate volume group + vgchange $vg -a n + + # Activate volume group with shareable mode + vgchange $vg -a sy + + # lvextend fails due to mismatched lock mode + not lvextend -l+10 $vg/foo + + # Promote volume group to exclusive mode + vgchange $vg -a ey + + lvreduce -f -l-4 $vg/foo + + lvchange -an $vg/foo + lvremove $vg/foo +done + +vgremove -ff $vg diff --git a/test/shell/system_id.sh b/test/shell/system_id.sh new file mode 100644 index 0000000..486fba1 --- /dev/null +++ b/test/shell/system_id.sh @@ -0,0 +1,709 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test system_id' + +# test does not apply to lvmlockd +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +print_lvmlocal() { + { echo "local {"; printf "%s\n" "$@"; echo "}"; } >"$LVMLOCAL" +} + +. lib/inittest + +aux prepare_devs 5 + +# get lvm.conf location in a form of: etc=path +eval "$(lvmconfig global/etc)" + +SIDFILE="$etc/lvm_test.conf" +LVMLOCAL="$etc/lvmlocal.conf" + +DFDIR="$etc/devices" +DF="$DFDIR/system.devices" + +# Avoid system id validation in the devices file +# which gets in the way of the test switching the +# local system id. +clear_df_systemid() { + if [[ -f $DF ]]; then + sed -e "s|SYSTEMID=.||" "$DF" > tmpdf + cp tmpdf $DF + fi +} + +# create vg with system_id using each source + +## none + +SID="" +aux lvmconf "global/system_id_source = none" +vgcreate $vg1 "$dev1" +check vg_field $vg1 systemid "$SID" +vgremove $vg1 + +## machineid +if [ -e "$etc/machine-id" ]; then +SID=$(cat "$etc/machine-id") +aux lvmconf "global/system_id_source = machineid" +vgcreate $vg1 "$dev1" +vgs -o+systemid $vg1 +check vg_field $vg1 systemid "$SID" +vgremove $vg1 +fi + +## appmachineid +lvm version > lvmver +if grep app-machineid lvmver; then +aux lvmconf "global/system_id_source = appmachineid" +lvm systemid | awk '{ print $3 }' > sid_lvm +vgcreate $vg1 "$dev1" +vgs -o systemid --noheadings $vg1 | awk '{print $1}' > sid_vg +diff sid_lvm sid_vg +vgremove $vg1 +fi + +## uname + +SID1=$(uname -n) +if [ -n "$SID1" ]; then +aux lvmconf "global/system_id_source = uname" +SID2=$(lvm systemid | awk '{ print $3 }') +vgcreate $vg1 "$dev1" +vgs -o+systemid $vg1 +check vg_field $vg1 systemid "$SID2" +vgremove $vg1 +fi + +## lvmlocal + +SID=sidfoolocal +print_lvmlocal " system_id = $SID" +aux lvmconf "global/system_id_source = lvmlocal" +vgcreate $vg1 "$dev1" +vgs -o+systemid $vg1 +check vg_field $vg1 systemid "$SID" +vgremove $vg1 +rm -f "$LVMLOCAL" + +## file + +SID=sidfoofile +echo "$SID" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +vgcreate $vg1 "$dev1" +vgs -o+systemid $vg1 +check vg_field $vg1 systemid "$SID" +vgremove $vg1 + +# override system_id to create a foreign vg, then fail to use the vg + +SID1=sidfoofile1 +SID2=sidfoofile2 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg, overriding the local system_id so the vg looks foreign +vgcreate --systemid "$SID2" "$vg1" "$dev1" +# normal vgs is not an error and does not see the vg +vgs >err +not grep $vg1 err +# vgs on the foreign vg is an error and not displayed +not vgs $vg1 >err +not grep $vg1 err +# fail to remove foreign vg +not vgremove $vg1 +# using --foreign we can see foreign vg +vgs --foreign >err +grep $vg1 err +vgs --foreign $vg1 >err +grep $vg1 err +# change the local system_id to the second value, making the vg not foreign +echo "$SID2" > "$SIDFILE" +clear_df_systemid +# we can now see and remove the vg +vgs $vg1 >err +grep $vg1 err +vgremove $vg1 + +# create a vg, then change the local system_id, making the vg foreign + +SID1=sidfoofile1 +SID2=sidfoofile2 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs >err +grep $vg1 err +# change the local system_id, making the vg foreign +echo "$SID2" > "$SIDFILE" +clear_df_systemid +# normal vgs doesn't see the vg +vgs >err +not grep $vg1 err +# using --foreign we can see the vg +vgs --foreign >err +grep $vg1 err +# change the local system_id back to the first value, making the vg not foreign +echo "$SID1" > "$SIDFILE" +clear_df_systemid +vgs >err +grep $vg1 err +vgremove $vg1 + +# create a vg, then change the vg's system_id, making it foreign + +SID1=sidfoofile1 +SID2=sidfoofile2 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs >err +grep $vg1 err +# change the vg's system_id, making the vg foreign +vgchange --yes --systemid "$SID2" $vg1 +# normal vgs doesn't see the vg +vgs >err +not grep $vg1 err +# using --foreign we can see the vg +vgs --foreign >err +grep $vg1 err +# change the local system_id to the second system_id so we can remove the vg +echo "$SID2" > "$SIDFILE" +clear_df_systemid +vgs >err +grep $vg1 err +vgremove $vg1 + +# create a vg, create active lvs in it, change our system_id, making +# the VG foreign, verify that we can still see the foreign VG, +# and can deactivate the LVs + +SID1=sidfoofile1 +SID2=sidfoofile2 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l 2 $vg1 +# normal vgs sees the vg and lv +vgs >err +grep $vg1 err +check lv_exists $vg1 $lv1 +# change our system_id, making the vg foreign, but accessible +echo "$SID2" > "$SIDFILE" +clear_df_systemid +vgs >err +grep $vg1 err +check lv_exists $vg1 $lv1 +# can deactivate the lv +lvchange -an $vg1/$lv1 +# now that the foreign vg has no active lvs, we can't access it +not lvremove $vg1/$lv1 +not vgremove $vg1 +# change our system_id back to match the vg so it's not foreign +echo "$SID1" > "$SIDFILE" +clear_df_systemid +vgs >err +grep $vg1 err +lvremove $vg1/$lv1 +vgremove $vg1 + +# local system has no system_id, so it can't access a vg with a system_id + +SID1=sidfoofile1 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +aux lvmconf "global/system_id_source = none" +vgs >err +not grep $vg1 err +not vgs $vg1 >err +not grep $vg1 err +aux lvmconf "global/system_id_source = file" +vgs >err +grep $vg1 err +vgremove $vg1 + +# local system has a system_id, and can use a vg without a system_id + +SID1=sidfoofile1 +rm -f "$SIDFILE" +clear_df_systemid +# create a vg with no system_id +aux lvmconf "global/system_id_source = none" +vgcreate $vg1 "$dev1" +check vg_field $vg1 systemid "" +# set a local system_id +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# check we can see and use the vg with no system_id +vgs >err +grep $vg1 err +vgs $vg1 >err +grep $vg1 err +vgremove $vg1 + +# vgexport clears system_id, vgimport sets system_id + +SID1=sidfoofile1 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs -o+systemid >err +grep $vg1 err +grep "$SID1" err +# after vgexport there is no systemid +vgexport $vg1 +vgs -o+systemid >err +grep $vg1 err +not grep "$SID1" err +# after vgimport there is a systemid +vgimport $vg1 +vgs -o+systemid >err +grep $vg1 err +grep "$SID1" err +vgremove $vg1 + +# Test max system_id length (128) and invalid system_id characters. +# The 128 length limit is imposed before invalid characters are omitted. + +# 120 numbers followed by 8 letters (max len) +SID1=012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789abcdefgh +# 120 numbers followed by 9 letters (too long by 1 character, the last is omitted) +SID2=012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789abcdefghi + +# max len system_id should appear normally +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs -o+systemid $vg1 >err +grep $vg1 err +grep "$SID1" err +vgremove $vg1 + +# max+1 len system_id should be missing the last character +echo "$SID2" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs -o+systemid $vg1 >err +grep $vg1 err +grep "$SID1" err +not grep "$SID2" err +vgremove $vg1 + +# max len system_id containing an invalid character should appear without +# the invalid character +# 120 numbers followed by invalid '%' character followed by 8 letters (too long by 1 character) +SID1=012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789%abcdefgh +# After the invalid character is omitted from SID1 +# The string is truncated to max length (128) before the invalid character is omitted +SID2=012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789abcdefg +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs -o+systemid $vg1 >err +grep $vg1 err +not grep $SID1 err +grep $SID2 err +vgremove $vg1 + +# contains a bunch of invalid characters +SID1="?%$&A.@1]" +# SID1 without the invalid characters +SID2=A.1 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs -o+systemid $vg1 >err +grep $vg1 err +not grep "$SID1" err +grep "$SID2" err +vgremove $vg1 + + +# pvs: pv in a foreign vg not reported +# pvs --foreign: pv in a foreign vg is reported + +SID1=sidfoofile1 +SID2=sidfoofile2 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal pvs sees the vg and pv +pvs >err +grep $vg1 err +grep "$dev1" err +# change the local system_id, making the vg foreign +echo "$SID2" > "$SIDFILE" +clear_df_systemid +# normal pvs does not see the vg or pv +pvs >err +not grep $vg1 err +not grep "$dev1" err +# pvs --foreign does see the vg and pv +pvs --foreign >err +grep $vg1 err +grep "$dev1" err +# change the local system_id back so the vg can be removed +echo "$SID1" > "$SIDFILE" +clear_df_systemid +vgremove $vg1 +rm -f "$SIDFILE" + +# lvs: lvs in a foreign vg not reported +# lvs --foreign: lvs in a foreign vg are reported + +SID1=sidfoofile1 +SID2=sidfoofile2 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +lvcreate -n $lv1 -l 2 $vg1 +lvchange -an $vg1/$lv1 +# normal lvs sees the vg and lv +lvs >err +grep $vg1 err +grep $lv1 err +# change the local system_id, making the vg foreign +echo "$SID2" > "$SIDFILE" +clear_df_systemid +# normal lvs does not see the vg or lv +lvs >err +not grep $vg1 err +not grep $lv1 err +# lvs --foreign does see the vg and lv +lvs --foreign >err +grep $vg1 err +grep $lv1 err +# change the local system_id back so the vg can be removed +echo "$SID1" > "$SIDFILE" +clear_df_systemid +lvremove $vg1/$lv1 +vgremove $vg1 +rm -f "$SIDFILE" + +# use extra_system_ids to read a foreign VG + +SID1=sidfoofile1 +SID2=sidfoofile2 +rm -f "$LVMLOCAL" +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs >err +grep $vg1 err +# change the local system_id, making the vg foreign +echo "$SID2" > "$SIDFILE" +clear_df_systemid +# normal vgs doesn't see the vg +vgs >err +not grep $vg1 err +# using --foreign we can see the vg +vgs --foreign >err +grep $vg1 err +# add the first system_id to extra_system_ids so we can see the vg +print_lvmlocal " extra_system_ids = [ $SID1 ] " +vgs >err +grep $vg1 err +vgremove $vg1 +rm -f "$LVMLOCAL" + +# vgcreate --systemid "" creates a vg without a system_id even if source is set +SID1=sidfoofile1 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate --systemid "" $vg1 "$dev1" +# normal vgs sees the vg +vgs >err +grep $vg1 err +# our system_id is not displayed for the vg +vgs -o+systemid >err +not grep "$SID1" err +vgremove $vg1 +rm -f "$SIDFILE" + +# vgchange --systemid "" clears the system_id on owned vg +SID1=sidfoofile1 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs >err +grep $vg1 err +# the vg has our system_id +vgs -o+systemid >err +grep $SID1 err +# clear the system_id +vgchange --yes --systemid "" $vg1 +# normal vgs sees the vg +vgs >err +grep $vg1 err +# the vg does not have our system_id +vgs -o+systemid >err +not grep "$SID1" err +vgremove $vg1 + +# vgchange --systemid does not set the system_id on foreign vg +SID1=sidfoofile1 +SID2=sidfoofile2 +rm -f "$LVMLOCAL" +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs >err +grep $vg1 err +# change the local system_id, making the vg foreign +echo "$SID2" > "$SIDFILE" +clear_df_systemid +# normal vgs doesn't see the vg +vgs >err +not grep $vg1 err +# using --foreign we can see the vg +vgs --foreign >err +grep $vg1 err +# cannot clear the system_id of the foreign vg +not vgchange --yes --systemid "" $vg1 +# cannot set the system_id of the foreign vg +not vgchange --yes --systemid foo $vg1 +# change our system_id back so we can remove the vg +echo "$SID1" > "$SIDFILE" +clear_df_systemid +vgremove $vg1 + +# vgchange --systemid --majoritypvs +SID1=sidfoofile1 +SID2=sidfoofile2 +rm -f "$LVMLOCAL" +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" "$dev2" "$dev3" +vgcreate $vg2 "$dev4" "$dev5" +# normal vgs sees the vg +# change the local system_id, making the vg foreign +echo "$SID2" > "$SIDFILE" +clear_df_systemid +# normal vgs doesn't see the vg +vgs >err +not grep $vg1 err +not grep $vg2 err +# using --foreign we can see the vg +vgs --foreign >err +grep $vg1 err +grep $vg2 err +# cannot clear the system_id of the foreign vg +not vgchange --yes --systemid "" $vg1 +not vgchange --yes --systemid "" $vg2 +# cannot set the system_id of the foreign vg +not vgchange --yes --systemid foo $vg1 +not vgchange --yes --systemid foo $vg2 +# we are local node SID2, foreign node is SID1 +# use extra_system_ids to take over the foreign vg, making it local +vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1 +vgs $vg1 +# make it foreign again +vgchange --yes --systemid sidfoofile1 $vg1 +not vgs $vg1 +# both vgs are foreign, drop dev1/dev4 so both vgs are missing a device +aux hide_dev "$dev1" +aux hide_dev "$dev4" +not pvs "$dev1" +not pvs "$dev4" +# neither VG can be changed because both are missing a dev +not vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1 +not vgchange --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2 +# using majoritypvs, vg1 can be changed because 2 of 3 PVs exist +vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg1 +vgs $vg1 +# using majoritypvs, vg2 cannot be changed because 1 of 2 PVs exist +not vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2 +not vgs $vg2 +vgs --foreign $vg2 +# dev1/dev4 return so we can take over vg2 now +# vg1 will complain about stale metadata on dev1 +aux unhide_dev "$dev1" +aux unhide_dev "$dev4" +vgs +pvs +vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID1}\"]" --systemid $SID2 $vg2 +vgs $vg2 +# update metadata on dev1 +vgck --updatemetadata $vg1 +vgs $vg1 +clear_df_systemid +vgremove $vg1 +vgremove $vg2 + + +# vgcfgbackup backs up foreign vg with --foreign +SID1=sidfoofile1 +SID2=sidfoofile2 +rm -f "$LVMLOCAL" +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +# create a vg +vgcreate $vg1 "$dev1" +# normal vgs sees the vg +vgs >err +grep $vg1 err +# change the local system_id, making the vg foreign +echo "$SID2" > "$SIDFILE" +clear_df_systemid +# normal vgs doesn't see the vg +vgs >err +not grep $vg1 err +# using --foreign we can back up the vg +not vgcfgbackup $vg1 +vgcfgbackup --foreign $vg1 +# change our system_id back so we can remove the vg +echo "$SID1" > "$SIDFILE" +clear_df_systemid +vgremove $vg1 +rm -f "$SIDFILE" + + +# Test handling of bad system_id source configurations +# The commands should proceed without a system_id. +# Look at the warning/error messages. + +# vgcreate with source machineid, where no $etc/machine-id file exists +if [ ! -e "$etc/machine-id" ]; then +SID="" +aux lvmconf "global/system_id_source = machineid" +vgcreate $vg1 "$dev1" 2>&1 | tee err +vgs -o+systemid $vg1 +check vg_field $vg1 systemid $SID +grep "No system ID found from system_id_source" err +vgremove $vg1 +fi + +# vgcreate with source uname, but uname is localhost +# TODO: don't want to change the hostname on the test machine... + +# vgcreate with source lvmlocal, but no lvmlocal.conf file +SID="" +rm -f $LVMLOCAL +aux lvmconf "global/system_id_source = lvmlocal" +vgcreate $vg1 "$dev1" 2>&1 | tee err +vgs -o+systemid $vg1 +check vg_field $vg1 systemid $SID +grep "No system ID found from system_id_source" err +vgremove $vg1 + +# vgcreate with source lvmlocal, but no system_id = "x" entry +SID="" +print_lvmlocal # " system_id = $SID" +aux lvmconf "global/system_id_source = lvmlocal" +vgcreate $vg1 "$dev1" 2>&1 | tee err +vgs -o+systemid $vg1 +check vg_field $vg1 systemid $SID +grep "No system ID found from system_id_source" err +vgremove $vg1 + +# vgcreate with source lvmlocal, and empty string system_id = "" +SID="" +print_lvmlocal " system_id = \"\"" +aux lvmconf "global/system_id_source = lvmlocal" +vgcreate $vg1 "$dev1" 2>&1 | tee err +vgs -o+systemid $vg1 +check vg_field $vg1 systemid "$SID" +grep "No system ID found from system_id_source" err +vgremove $vg1 +rm -f $LVMLOCAL + +# vgcreate with source file, but no system_id_file config +SID="" +rm -f "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" +vgcreate $vg1 "$dev1" 2>&1 | tee err +vgs -o+systemid $vg1 +check vg_field $vg1 systemid "$SID" +grep "No system ID found from system_id_source" err +vgremove $vg1 + +# vgcreate with source file, but system_id_file does not exist +SID="" +rm -f "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +vgcreate $vg1 "$dev1" 2>&1 | tee err +vgs -o+systemid $vg1 +check vg_field $vg1 systemid "$SID" +grep "No system ID found from system_id_source" err +vgremove $vg1 diff --git a/test/shell/tags.sh b/test/shell/tags.sh index 6c35fc3..5b636a8 100644 --- a/test/shell/tags.sh +++ b/test/shell/tags.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,22 +8,25 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_pvs 4 -# vgcreate with --addtag -vgcreate -c n --addtag firstvg $vg1 "$dev1" "$dev2" -vgcreate -c n --addtag secondvg $vg2 "$dev3" "$dev4" +# vgcreate $SHARED with --addtag +vgcreate $SHARED --addtag firstvg $vg1 "$dev1" "$dev2" +vgcreate $SHARED --addtag secondvg $vg2 "$dev3" "$dev4" check vg_field $vg1 tags "firstvg" check vg_field $vg2 tags "secondvg" vgremove -f $vg1 $vg2 # vgchange with --addtag and --deltag -vgcreate -c n $vg1 "$dev1" "$dev2" -vgcreate -c n $vg2 "$dev3" "$dev4" +vgcreate $SHARED $vg1 "$dev1" "$dev2" +vgcreate $SHARED $vg2 "$dev3" "$dev4" vgchange --addtag firstvgtag1 $vg1 # adding a tag multiple times is not an error vgchange --addtag firstvgtag2 $vg1 @@ -41,17 +45,22 @@ vgchange --deltag firstvgtag1 $vg2 vgremove -f $vg1 $vg2 # lvcreate with --addtag -vgcreate -c n $vg1 "$dev1" "$dev2" +vgcreate $SHARED $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" + +# LV is not zeroed when tag matches read only volume list +lvcreate -l1 $vg1 --addtag "RO" --config "activation/read_only_volume_list = [ \"@RO\" ]" 2>&1 | tee out +grep "not zeroed" out + vgremove -f $vg1 # lvchange with --addtag and --deltag -vgcreate -c n $vg1 "$dev1" "$dev2" +vgcreate $SHARED $vg1 "$dev1" "$dev2" lvcreate -l 4 -n $lv1 $vg1 lvcreate -l 4 -n $lv2 $vg1 lvchange --addtag firstlvtag1 $vg1/$lv1 @@ -71,3 +80,5 @@ 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" + +vgremove -ff $vg1 diff --git a/test/shell/test-partition.sh b/test/shell/test-partition.sh index f7e91b8..0e92f00 100644 --- a/test/shell/test-partition.sh +++ b/test/shell/test-partition.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,7 +8,7 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # Testcase for bugzilla #621173 @@ -15,9 +16,12 @@ # + +SKIP_WITH_LVMPOLLD=1 + LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]" -. lib/test +. lib/inittest which sfdisk || skip @@ -26,6 +30,6 @@ aux prepare_pvs 1 30 pvs "$dev1" # create small partition table -echo "1 2" | sfdisk "$dev1" +echo "1 2" | sfdisk --force "$dev1" -pvs "$dev1" +not pvs "$dev1" diff --git a/test/shell/thin-16g.sh b/test/shell/thin-16g.sh new file mode 100644 index 0000000..ee7e22e --- /dev/null +++ b/test/shell/thin-16g.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test usability of 16g thin pool metadata LV + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_thin 1 0 0 || skip + +aux prepare_vg 1 50000 + +lvcreate -T -L10 --poolmetadatasize 16g $vg/pool +check lv_field $vg/pool_tmeta size "<15.88g" +lvremove -f $vg + +# Cropped way +lvcreate -T -L10 --poolmetadatasize 16g --config 'allocation/thin_pool_crop_metadata=1' $vg/pool +check lv_field $vg/pool_tmeta size "15.81g" +lvremove -f $vg + +lvcreate -L16G -n meta $vg +lvcreate -L10 -n pool $vg +lvconvert --yes --thinpool $vg/pool --poolmetadata meta +# Uncropped size 33554432 sectors - 16GiB +dmsetup table ${vg}-pool_tmeta | grep 33554432 +lvremove -f $vg + +# Uses 20G metadata volume, but crops the size in DM table +lvcreate -L20G -n meta $vg +lvcreate -L10 -n pool $vg +lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1' +check lv_field $vg/lvol0_pmspare size "16.00g" +# Size should be cropped to 33161216 sectors ~15.81GiB +dmsetup table ${vg}-pool_tmeta | grep 33161216 + +# Also size remains unchanged with activation has no cropping, +# but metadata have no CROP_METADATA flag set +lvchange -an $vg +lvchange -ay $vg +# Size still stays cropped to 33161216 sectors ~15.81GiB +dmsetup table ${vg}-pool_tmeta | grep 33161216 +lvremove -f $vg + +# Minimal size is 2M +lvcreate -L1M -n meta $vg +lvcreate -L10 -n pool $vg +not lvconvert --yes --thinpool $vg/pool --poolmetadata meta +lvremove -f $vg + +# Uses 20G metadata volume, but crops the size in DM table +lvcreate -L1 --poolmetadatasize 10G -T $vg/pool +lvresize -L+10G $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1' +check lv_field $vg/lvol0_pmspare size "15.81g" +# Size should be cropped to 33161216 sectors ~15.81GiB +dmsetup table ${vg}-pool_tmeta | grep 33161216 + +# Without cropping we can grop to ~15.88GiB +lvresize -L+10G $vg/pool_tmeta +check lv_field $vg/lvol0_pmspare size "<15.88g" +lvremove -f $vg + +# User has already 'bigger' metadata and wants them uncropped +lvcreate -L16G -n meta $vg +lvcreate -L10 -n pool $vg +lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1' + +# No change with cropping +lvresize -l+1 $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1' +dmsetup table ${vg}-pool_tmeta | grep 33161216 + +# Resizes to 'uncropped' size 16GiB with ANY size +lvresize -l+1 $vg/pool_tmeta +dmsetup table ${vg}-pool_tmeta | grep 33554432 +check lv_field $vg/pool_tmeta size "16.00g" + +vgremove -ff $vg diff --git a/test/shell/thin-autoumount-dmeventd.sh b/test/shell/thin-autoumount-dmeventd.sh index bbffe8a..7244333 100644 --- a/test/shell/thin-autoumount-dmeventd.sh +++ b/test/shell/thin-autoumount-dmeventd.sh @@ -1,5 +1,6 @@ -#!/bin/bash -# Copyright (C) 2012 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2012-2016 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 @@ -7,64 +8,121 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # no automatic extensions, just umount -is_dir_mounted_() + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +mntdir="${PREFIX}mnt with space" +mntusedir="${PREFIX}mntuse" + +cleanup_mounted_and_teardown() { - cat /proc/mounts | sed 's:\\040: :g' | grep "$1" + umount "$mntdir" 2>/dev/null || true + umount "$mntusedir" 2>/dev/null || true + vgremove -ff $vg + aux teardown } -. lib/test +is_lv_opened_() +{ + test "$(get lv_field "$1" lv_device_open --binary)" = 1 +} # # Main # -which mkfs.ext2 || skip +which mkfs.ext4 || skip +export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf" aux have_thin 1 0 0 || skip -aux prepare_dmeventd +# Simple implementation of umount when lvextend fails +cat <<- EOF >testcmd.sh +#!/bin/sh + +echo "Data: \$DMEVENTD_THIN_POOL_DATA" +echo "Metadata: \$DMEVENTD_THIN_POOL_METADATA" + +"$TESTDIR/lib/lvextend" --use-policies \$1 || { + umount "$mntdir" || true + umount "$mntusedir" || true + return 0 +} +test "\$($TESTDIR/lib/lvs -o selected -S "data_percent>95||metadata_percent>95" --noheadings \$1)" -eq 0 || { + umount "$mntdir" || true + umount "$mntusedir" || true + return 0 +} +EOF +chmod +x testcmd.sh +# Show prepared script +cat testcmd.sh +# Use autoextend percent 0 - so extension fails and triggers umount... aux lvmconf "activation/thin_pool_autoextend_percent = 0" \ - "activation/thin_pool_autoextend_threshold = 70" + "activation/thin_pool_autoextend_threshold = 70" \ + "dmeventd/thin_command = \"/$PWD/testcmd.sh\"" -aux prepare_vg 2 +aux prepare_dmeventd -mntdir="${PREFIX}mnt with space" -mntusedir="${PREFIX}mntuse" +aux prepare_vg 2 lvcreate -L8M -V8M -n $lv1 -T $vg/pool lvcreate -V8M -n $lv2 -T $vg/pool -mkfs.ext2 "$DM_DEV_DIR/$vg/$lv1" -mkfs.ext2 "$DM_DEV_DIR/$vg/$lv2" +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv2" lvchange --monitor y $vg/pool mkdir "$mntdir" "$mntusedir" -mount "$DM_DEV_DIR/mapper/$vg-$lv1" "$mntdir" -mount "$DM_DEV_DIR/mapper/$vg-$lv2" "$mntusedir" +trap 'cleanup_mounted_and_teardown' EXIT +mount "$DM_DEV_DIR/$vg/$lv1" "$mntdir" +mount "$DM_DEV_DIR/$vg/$lv2" "$mntusedir" -is_dir_mounted_ "$mntdir" +# Check both LVs are opened (~mounted) +is_lv_opened_ "$vg/$lv1" +is_lv_opened_ "$vg/$lv2" -# fill above 70% -dd if=/dev/zero of="$mntdir/file$$" bs=1M count=6 touch "$mntusedir/file$$" -tail -f "$mntusedir/file$$" & -PID_TAIL=$! sync + +# Running 'keeper' process sleep holds the block device still in use +sleep 60 < "$mntusedir/file$$" >/dev/null 2>&1 & +PID_SLEEP=$! + lvs -a $vg -sleep 12 # dmeventd only checks every 10 seconds :( +# Fill pool above 95% (to cause 'forced lazy umount) +dd if=/dev/zero of="$mntdir/file$$" bs=256K count=20 conv=fdatasync lvs -a $vg -# both dirs should be unmounted -not is_dir_mounted "$mntdir" -not is_dir_mounted "$mntusedir" -# running tail keeps the block device still in use -kill $PID_TAIL +# Could loop here for a few secs so dmeventd can do some work +# In the worst case check only happens every 10 seconds :( +# With low water mark it quickly discovers overflow and umounts $vg/$lv1 +for i in $(seq 1 12) ; do + is_lv_opened_ "$vg/$lv1" || break + test $i -lt 12 || die "$mntdir should have been unmounted by dmeventd!" + sleep 1 +done + lvs -a $vg -vgremove -f $vg +is_lv_opened_ "$vg/$lv2" || \ + die "$mntusedir is not mounted here (sleep already expired??)" + +# Kill device holding process +kill $PID_SLEEP +wait + +not is_lv_opened_ "$vg/$lv2" || { + mount + die "$mntusedir should have been unmounted by dmeventd!" +} diff --git a/test/shell/thin-defaults.sh b/test/shell/thin-defaults.sh new file mode 100644 index 0000000..3f2db20 --- /dev/null +++ b/test/shell/thin-defaults.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test defaults entered through lvm.conf + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 0 0 || skip + +aux prepare_vg 2 + +lvcreate -T -L8M $vg/pool0 + +aux lvmconf "allocation/thin_pool_chunk_size = 128" \ + "allocation/thin_pool_discards = \"ignore\"" \ + "allocation/thin_pool_zero = 0" + +lvcreate -T -L8M $vg/pool1 + +check lv_field $vg/pool1 chunksize "128.00k" +check lv_field $vg/pool1 discards "ignore" +check lv_field $vg/pool1 zero "" + +vgremove -f $vg diff --git a/test/shell/thin-dmeventd-warns.sh b/test/shell/thin-dmeventd-warns.sh new file mode 100644 index 0000000..2eb8e41 --- /dev/null +++ b/test/shell/thin-dmeventd-warns.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test if dmeventd produces multiple warnings when pools runs above 80% + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which blkdiscard || skip + +percent_() { + get lv_field $vg/pool data_percent | cut -d. -f1 +} + +wait_warn_() { + + for i in $(seq 1 7) + do + test "$(grep -E -c "WARNING: Thin pool.*is now" debug.log_DMEVENTD_out)" -eq "$1" && return 0 + sleep 2 + done + + die "Waiting too log for dmeventd log warning" +} +# +# Main +# +aux have_thin 1 0 0 || skip + +aux prepare_dmeventd +aux prepare_vg + +lvcreate -L8 -V8 -T $vg/pool -n $lv1 + + +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=256K count=26 oflag=direct +test "$(percent_)" -gt 80 + +# Give it some time to dmeventd to log WARNING +wait_warn_ 1 + +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=256K count=30 oflag=direct +test "$(percent_)" -gt 90 + +# Give it some time to dmeventd to log WARNING +wait_warn_ 2 + +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=8 oflag=direct +test "$(percent_)" -eq 100 + +wait_warn_ 3 + +blkdiscard "$DM_DEV_DIR/$vg/$lv1" + +# FIXME: Enforce thin-pool metadata commit with flushing status +dmsetup status ${vg}-pool-tpool +# Wait for thin-pool monitoring to notice lower values +sleep 11 +# ATM dmeventd is not logging event for thin-pool getting +# below 'WARNED' threshold. + + +dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=256K count=30 oflag=direct +test "$(percent_)" -gt 90 + +lvs -a $vg +dmsetup status ${vg}-pool-tpool + +# Check pool again Warns +wait_warn_ 4 + +vgremove -f $vg diff --git a/test/shell/thin-errors.sh b/test/shell/thin-errors.sh new file mode 100644 index 0000000..7bdf268 --- /dev/null +++ b/test/shell/thin-errors.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test various error conditions user may hit with thin volumes + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 3 0 || skip +aux thin_pool_error_works_32 || skip + +aux prepare_vg 2 + +############################################### +# Testing failing thin-pool metadata device # +############################################### + +lvcreate -T -L1M --errorwhenfull y $vg/pool +lvcreate -V2 -n $lv1 $vg/pool +lvcreate -s -n $lv2 $vg/$lv1 + +# Prepare old metadata with transaction_id 2 +vgcfgbackup -f mda_tid_2 $vg + +lvcreate -s -n $lv3 $vg/$lv1 +lvcreate -s -n $lv4 $vg/$lv1 +lvcreate -s -n $lv5 $vg/$lv1 + +vgcfgbackup -f mda_tid_5 $vg + +# Restore mismatching old metadata with different transaction_id +vgcfgrestore -f mda_tid_2 --force --yes $vg + + +not lvcreate -s -n $lv5 $vg/$lv1 + +sed -e 's/transaction_id = 2/transaction_id = 5/g' mda_tid_2 > mda_tid_2_5 + +# Restore metadata with matching transaction_id, +# but already existing device in kernel, unknown to lvm2 +vgcfgrestore -f mda_tid_2_5 --force --yes $vg + +not lvcreate -s -n $lv5 $vg/$lv1 +# can be tried repeatedly +not lvcreate -s -n $lv5 $vg/$lv1 + + +# Restore matching metadata and check all works +# and no kernel thin device was lost +vgcfgrestore -f mda_tid_5 --force --yes $vg + +lvcreate -s -n $lv6 $vg/$lv1 + +lvchange -ay -K $vg + +check active $vg $lv1 +check active $vg $lv2 +check active $vg $lv3 +check active $vg $lv4 +check active $vg $lv5 +check active $vg $lv6 + +vgremove -ff $vg diff --git a/test/shell/thin-flags.sh b/test/shell/thin-flags.sh new file mode 100644 index 0000000..a3adee4 --- /dev/null +++ b/test/shell/thin-flags.sh @@ -0,0 +1,140 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test presence of various thin-pool/thin flags + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 3 0 || skip +aux thin_pool_error_works_32 || skip + +aux prepare_vg 2 256 + +############################################### +# Testing failing thin-pool metadata device # +############################################### + +lvcreate -T -L1M --errorwhenfull y $vg/pool +lvcreate -V2 -n $lv2 $vg/pool + +aux error_dev "$dev2" 2054:2 +# Check our 'lvs' is not flushing pool - should be still OK +check lv_attr_bit health $vg/pool "-" +# Enforce flush on thin pool device to notice error device. +dmsetup status $vg-pool-tpool +check lv_attr_bit health $vg/pool "F" +check lv_attr_bit health $vg/$lv2 "F" +aux enable_dev "$dev2" + +lvchange -an $vg + +# Overfill data area +lvchange -ay $vg +dd if=/dev/zero of="$DM_DEV_DIR/mapper/$vg-$lv2" bs=1M count=2 oflag=direct || true +check lv_attr_bit health $vg/pool "D" +# TODO use spaces ?? +check lv_field $vg/pool lv_health_status "out_of_data" + +lvremove -ff $vg + + +####################################################### +# Testing what happens on system without thin-check # +####################################################### + +lvcreate -L200M --errorwhenfull y -T $vg/pool +lvcreate -V2 -n $lv2 $vg/pool +lvchange -an $vg + +# Drop usage of thin_check +aux lvmconf 'global/thin_check_executable = ""' + +# Prepare some fake metadata prefilled to ~100% +lvcreate -L2 -n $lv1 $vg "$dev2" # tmp for metadata + +VOLS=490 +aux thin_restore_needs_more_volumes || VOLS=445 +aux prepare_thin_metadata $VOLS 1 | tee data + +# Note: we like want to test BOTH sizes (445 & 490) as ATM it gives +# different errors (5.9-rc5 kernel does not handle it as expected by this test) + +"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1" + +# Swap volume with restored fake metadata +lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1 + +lvchange -ay $vg + +lvchange -ay $vg/$lv2 +# Provisiong and last free bits in metadata +dd if=/dev/zero of="$DM_DEV_DIR/mapper/$vg-$lv2" bs=1M count=1 oflag=direct || true + +check lv_attr_bit health $vg/pool "M" || { + echo "TEST ""WARNING: Missing metadata corruption for this version of thin-pool." + exit 0 +} + +# TODO - use spaces ?? +check lv_field $vg/pool lv_health_status "metadata_read_only" +check lv_attr_bit health $vg/$lv2 "-" + +not lvcreate -s $vg/$lv2 +not lvcreate -V10 -n $lv3 $vg/pool + +lvs -ao+seg_pe_ranges $vg + +# needs_check needs newer version +THINMINVER="1 20 0" +aux kernel_at_least 4 18 && THINMINVER="1 19 0" # kernel >=4.18 already had changes from 1.20 + +if aux have_thin $THINMINVER ; then + check lv_attr_bit state $vg/pool "a" + + dmsetup suspend $vg-pool-tpool + + check lv_attr_bit state $vg/pool "s" + + dmsetup resume $vg-pool-tpool + + lvresize -L+2M $vg/pool_tmeta + + # Newer version recovers when metadata grow up + check lv_attr_bit state $vg/pool "a" + check lv_field $vg/pool lv_health_status "" + +elif aux have_thin 1 16 0 ; then + check lv_attr_bit state $vg/pool "c" + check lv_field $vg/pool lv_check_needed "check needed" + + dmsetup suspend $vg-pool-tpool + + # suspended thin-pool with Capital 'c' + check lv_attr_bit state $vg/pool "C" + + dmsetup resume $vg-pool-tpool + + lvresize -L+2M $vg/pool_tmeta + + # still require thin_check + check lv_attr_bit state $vg/pool "c" +fi + +vgremove -ff $vg diff --git a/test/shell/thin-foreign-dmeventd.sh b/test/shell/thin-foreign-dmeventd.sh new file mode 100644 index 0000000..76995a3 --- /dev/null +++ b/test/shell/thin-foreign-dmeventd.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test foreing user of thin-pool + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +MOUNT_DIR=mnt + +cleanup_mounted_and_teardown() +{ + umount "$MOUNT_DIR" || true + dmsetup remove $THIN + vgremove -ff $vg + aux teardown +} + +percent_() { + get lv_field $vg/pool data_percent | cut -d. -f1 +} + +# +# Main +# +aux have_thin 1 0 0 || skip +which mkfs.ext4 || skip + +# Use our mkfs config file to get approximately same results +# TODO: maybe use it for all test via some 'prepare' function +export MKE2FS_CONFIG="$TESTOLDPWD/lib/mke2fs.conf" + +aux prepare_dmeventd +aux prepare_vg 2 64 + +# Create named pool only +lvcreate --errorwhenfull y -L2 -T $vg/pool + +POOL="$vg-pool" +THIN="${PREFIX}_thin" + +# Foreing user is using own ioctl command to create thin devices +dmsetup message $POOL 0 "create_thin 0" +dmsetup message $POOL 0 "set_transaction_id 0 1" + +dmsetup status +# Once the transaction id has changed, lvm2 shall not be able to create thinLV +fail lvcreate -V10 $vg/pool + +trap 'cleanup_mounted_and_teardown' EXIT + +# 20M thin device +dmsetup create $THIN --table "0 40960 thin $DM_DEV_DIR/mapper/$POOL 0" + +dmsetup table +dmsetup info -c + +mkdir "$MOUNT_DIR" +# This mkfs should fill 2MB pool over 95% +# no autoresize is configured +mkfs.ext4 "$DM_DEV_DIR/mapper/$THIN" +# ensure all data from mkfs are written to disk +sync +test "$(percent_)" -gt 95 +mount "$DM_DEV_DIR/mapper/$THIN" "$MOUNT_DIR" + +pvchange -x n "$dev1" "$dev2" + +test "$(percent_)" -gt 95 +# Configure autoresize +aux lvmconf 'activation/thin_pool_autoextend_percent = 10' \ + 'activation/thin_pool_autoextend_threshold = 75' + +# Give it some time to left dmeventd do some (failing to resize) work +sleep 20 + +# And check foreign thin device is still mounted +mount | grep "$MOUNT_DIR" | grep "$THIN" +test "$(percent_)" -gt 95 + +pvchange -x y "$dev1" "$dev2" + +# FIXME: ATM tell dmeventd explicitely we've changed metadata +# however dmeventd shall be aware of any metadata change +# and automagically retry resize operation after that. +lvchange --refresh $vg/pool + +# Give it some time and let dmeventd do some work +for i in $(seq 1 15) ; do + test "$(percent_)" -ge 75 || break + sleep 1 +done + +test "$(percent_)" -lt 75 + +# And check foreign thin device is still mounted +mount | grep "$MOUNT_DIR" | grep "$THIN" diff --git a/test/shell/thin-foreign-repair.sh b/test/shell/thin-foreign-repair.sh new file mode 100644 index 0000000..55e9f62 --- /dev/null +++ b/test/shell/thin-foreign-repair.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test foreing user of thin-pool + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +clean_thin_() +{ + aux udev_wait + dmsetup remove "$THIN" || { sleep .5 ; dmsetup remove "$THIN" ; } +} + +cleanup_mounted_and_teardown() +{ + clean_thin_ || true + vgremove -ff $vg + aux teardown +} + +# +# Main +# +aux have_thin 1 0 0 || skip +which mkfs.ext4 || skip + +# Use our mkfs config file to get approximately same results +# TODO: maybe use it for all test via some 'prepare' function +export MKE2FS_CONFIG="$TESTOLDPWD/lib/mke2fs.conf" + +aux prepare_vg 2 64 + +# Create named pool only +lvcreate -L2 -T $vg/pool + +POOL="$vg-pool" +THIN="${PREFIX}_thin" + +# Foreing user is using own ioctl command to create thin devices +dmsetup message $POOL 0 "create_thin 0" +dmsetup message $POOL 0 "set_transaction_id 0 2" + +# Once the transaction id has changed, lvm2 shall not be able to create thinLV +fail lvcreate -V10 $vg/pool + +trap 'cleanup_mounted_and_teardown' EXIT + +# 20M thin device +dmsetup create "$THIN" --table "0 40960 thin $DM_DEV_DIR/mapper/$POOL 0" + +mkfs.ext4 "$DM_DEV_DIR/mapper/$THIN" + +clean_thin_ + +lvchange -an $vg/pool + +# Repair thin-pool used by 'foreing' apps (setting their own tid) +lvconvert --repair $vg/pool 2>&1 | tee out + +not grep "Transaction id" out + +lvchange -ay $vg/pool + +dmsetup create "$THIN" --table "0 40960 thin $DM_DEV_DIR/mapper/$POOL 0" + +fsck -n "$DM_DEV_DIR/mapper/$THIN" + +# exit calls cleanup_mounted_and_teardown diff --git a/test/shell/thin-large.sh b/test/shell/thin-large.sh new file mode 100644 index 0000000..714f91e --- /dev/null +++ b/test/shell/thin-large.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# 'Exercise logic around boundary sizes of thin-pool data and chunksize + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# FIXME update test to make something useful on <16T +aux can_use_16T || skip + +aux have_thin 1 0 0 || skip + +# Prepare ~1P sized devices +aux prepare_vg 1 1000000000 + +lvcreate -an -T -L250T $vg/pool250 + +lvcreate -an -T -L250T --poolmetadatasize 16G $vg/pool16 + +fail lvcreate -an -T -L250T --chunksize 64K --poolmetadatasize 16G $vg/pool64 + +# Creation of thin-pool with proper chunk-size but not enough metadata size +# which can grow later needs to pass +lvcreate -an -T -L250T --chunksize 1M --poolmetadatasize 4G $vg/pool1024 + +# Creation of chunk should fit +lvcreate -an -T -L12T --chunksize 64K --poolmetadatasize 16G $vg/pool64 + +check lv_field $vg/pool64 chunksize "64.00k" + +lvremove -ff $vg + + +### Check also lvconvert ### + +lvcreate -an -L250T -n pool $vg + +fail lvconvert -y --chunksize 64 --thinpool $vg/pool +lvconvert -y --chunksize 1M --thinpool $vg/pool + +check lv_field $vg/pool chunksize "1.00m" + +vgremove -ff $vg diff --git a/test/shell/thin-many-dmeventd.sh b/test/shell/thin-many-dmeventd.sh new file mode 100644 index 0000000..b93b0c6 --- /dev/null +++ b/test/shell/thin-many-dmeventd.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test activation of monitoring with more thin-pool + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 0 0 || skip + +aux prepare_dmeventd +aux prepare_vg 2 64 + +# Create couple pools to later cause race in dmeventd during activation. +# each pool may add 1sec. extra delay + +for i in $(seq 1 5) +do + lvcreate --errorwhenfull y -Zn -T -L4M -V4M $vg/pool_${i} -n $lv${i} + # Fill thin-pool to some capacity >50% + dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv${i}" bs=256K count=9 oflag=direct +done + +lvs -a $vg +vgchange -an $vg + + +# Try to now activate all existing pool - this will generate in about 10sec later +# storm of intial call of 'lvextend --use-policies' +vgchange -ay $vg + +# Every 10sec. ATM there is DM status monitoring made by dmeventd +sleep 9 + +# Here try to hit the race by creating several new thin-pools in sequence. +# Creation meets with dmeventd running 'lvextend' command and taking +# it's internal lvm2 library lock - this used to make impossible to proceed with +# new thin-pool registration. +for i in $(seq 11 15) +do + #/usr/bin/time -o TM -f %e lvcreate --errorwhenfull y -Zn -T -L4M -V4M $vg/pool_${i} -n $lv${i} + #read -r t < TM + #test ${t%%.*} -lt 8 || die "Creation of thin pool took more then 8 second! ($t seconds)" + START=$(date +%s) + lvcreate --errorwhenfull y -Zn -T -L4M -V4M $vg/pool_${i} -n $lv${i} + END=$(date +%s) + DIFF=$(( END - START )) + test "$DIFF" -lt 8 || die "Creation of thin pool took more then 8 second! ($DIFF seconds)" + # Fill thin-pool to some capacity >50% + dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv${i}" bs=256K count=9 oflag=direct +done + +vgremove -f $vg diff --git a/test/shell/thin-merge.sh b/test/shell/thin-merge.sh new file mode 100644 index 0000000..34f5c74 --- /dev/null +++ b/test/shell/thin-merge.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test merge of thin snapshot + + + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +MKFS=mkfs.ext2 +which $MKFS || skip +which fsck || skip + +MKFS="$MKFS -b4096" +# +# Main +# +aux have_thin 1 0 0 || skip + +aux prepare_vg 2 + +lvcreate -T -L8M $vg/pool -V10M -n $lv1 +lvcreate -s -K -n snap $vg/$lv1 +# check exclusive lock is preserved after merge +check lv_field "$vg/$lv1" lv_active_exclusively "active exclusively" +lvconvert --merge $vg/snap +check lv_field "$vg/$lv1" lv_active_exclusively "active exclusively" +lvremove -ff $vg + + +lvcreate -T -L8M $vg/pool -V10M -n $lv1 +lvchange --addtag tagL $vg/$lv1 + +mkdir mnt +$MKFS "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" mnt +touch mnt/test + +lvcreate -K -s -n snap --addtag tagS $vg/$lv1 +mkdir mntsnap +$MKFS "$DM_DEV_DIR/$vg/snap" +mount "$DM_DEV_DIR/$vg/snap" mntsnap +touch mntsnap/test_snap + +lvs -o+tags,thin_id $vg + +lvcreate -s -n snap1 $vg/$lv1 + +lvconvert --merge $vg/snap &>out +grep "Merging of thin snapshot $vg/snap will occur on next activation of $vg/${lv1}." out + +# Can't merge another snapshot while "snap" is still being 'merged'. +not lvconvert --merge $vg/snap1 &>out +grep "Cannot merge snapshot" out + +# Check lvdisplay is not crashing while merge needs to wait +lvdisplay -a $vg + +umount mnt + +# Merge cannot happen +lvchange --refresh $vg/$lv1 +check lv_field $vg/$lv1 thin_id "1" + +# Fails since it cannot deactivate both +not lvchange -an $vg/$lv1 + +# But test $lv1 is not active +check inactive $vg $lv1 + +# Also still cannot reactivate $lv1 +not lvchange -ay $vg/$lv1 + +umount mntsnap + +lvdisplay -a $vg | tee out +grep "merged with" out +grep "merging to" out + +# Check there is no support for manipulation with hidden 'snap' +not lvchange --refresh $vg/snap +not lvchange -an $vg/snap +not lvremove $vg/snap + + +# Finally deactivate 'snap' again via $lv1 +lvchange -an $vg/$lv1 + +# Still must not be activable +not lvchange -K -ay $vg/snap + +lvs -a -o +tags,thin_id $vg + +# Test if merge happens +lvchange -ay $vg/$lv1 +check lv_exists $vg $lv1 +check lv_field $vg/$lv1 thin_id "2" +check lv_field $vg/$lv1 tags "tagL" +check lv_not_exists $vg snap + +fsck -n "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" mnt +test -e mnt/test_snap +umount mnt + + +# test if thin snapshot has also 'old-snapshot' + +lvcreate -s -n snap $vg/$lv1 + +# Also add old snapshot to thin origin +lvcreate -s -L10 -n oldsnapof_${lv1} $vg/$lv1 +not lvconvert --merge $vg/snap +$MKFS "$DM_DEV_DIR/$vg/oldsnapof_${lv1}" +lvconvert --merge $vg/oldsnapof_${lv1} +fsck -n "$DM_DEV_DIR/$vg/$lv1" +check lv_not_exists $vg oldsnapof_${lv1} +# Add old snapshot to thin snapshot +lvcreate -s -L10 -n oldsnapof_snap $vg/snap +lvconvert --merge $vg/snap +lvremove -f $vg/oldsnapof_snap +check lv_field $vg/$lv1 thin_id "4" + +# Check --mergethin +lvcreate -s -n snap $vg/$lv1 +check lv_field $vg/snap thin_id "5" +lvconvert --mergethin $vg/snap &>out +grep "Volume $vg/snap replaced origin $vg/${lv1}." out +check lv_field $vg/$lv1 thin_id "5" + +vgremove -ff $vg diff --git a/test/shell/thin-overprovisioning.sh b/test/shell/thin-overprovisioning.sh new file mode 100644 index 0000000..d4ab63d --- /dev/null +++ b/test/shell/thin-overprovisioning.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test warns when thin pool is overprovisiong + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 3 0 || skip + +# 2PVs by 32M +aux prepare_vg 2 33 + +lvcreate -L32 -T $vg/pool +# check there is link node for UNUSED thin-pool +test -e "$DM_DEV_DIR/$vg/pool" + +# leave 12M free space +lvcreate -an -n $lv1 -L16 $vg 2>&1 | tee out +vgs $vg + +lvcreate -n thin1 -V30 $vg/pool 2>&1 | tee out +not grep "WARNING: Sum" out +# check again link node is now gone for a USED thin-pool +test ! -e "$DM_DEV_DIR/$vg/pool" + +# Pool gets overprovisioned +lvcreate -an -n thin2 -V4 $vg/pool 2>&1 | tee out +grep "WARNING: Sum" out +grep "amount of free space in volume group (12.00 MiB)" out + +# Eat all space in VG +lvcreate -an -n $lv2 -L12 $vg 2>&1 | tee out +grep "WARNING: Sum" out +grep "no free space in volume group" out + +lvcreate -an -n thin3 -V1G $vg/pool 2>&1 | tee out +grep "WARNING: Sum" out +grep "the size of whole volume group" out + +lvremove -ff $vg/thin2 $vg/thin3 $vg/$lv2 + +# Create 2nd thin pool in a VG + +lvcreate -L4 -T $vg/pool2 +lvcreate -V4 -n thin2 $vg/pool2 2>&1 | tee out +not grep "WARNING: Sum" out + +lvcreate -an -V4 -n thin3 $vg/pool2 2>&1 | tee out +grep "WARNING: Sum of all thin volume sizes (38.00 MiB)" out +grep "free space in volume group (6.00 MiB)" out + +lvcreate -an -L6 -n $lv3 $vg 2>&1 | tee out +grep "no free space in volume group" out + +lvremove -ff $vg/thin2 $vg/thin3 + +lvcreate -an -V4 -n thin2 $vg/pool2 2>&1 | tee out +not grep "WARNING: Sum" out + +# Check if resize notices problem +lvextend -L+8 $vg/thin2 + +vgs $vg + +vgremove -ff $vg diff --git a/test/shell/thin-resize-match.sh b/test/shell/thin-resize-match.sh new file mode 100644 index 0000000..dda5573 --- /dev/null +++ b/test/shell/thin-resize-match.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# ensure there is no data loss during thin-pool resize + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +which md5sum || skip + +aux have_thin 1 0 0 || skip + +aux prepare_vg 2 20 + +lvcreate -L1M -V2M -n $lv1 -T $vg/pool + +# just ensure we check what we need to check +check lv_field $vg/pool size "1.00m" +check lv_field $vg/$lv1 size "2.00m" + +# prepare 2097152 file content +seq 0 315465 > 2M +md5sum 2M | cut -f 1 -d ' ' | tee MD5 +dd if=2M of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=512K conv=fdatasync >log 2>&1 & +#dd if=2M of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=2M oflag=direct & + +# give it some time to fill thin-volume +# eventually loop to wait for 100% full pool... +sleep .1 +lvs -a $vg + +# this must not 'block & wait' on suspending flush +# if it waits on thin-pool's target timeout +# it will harm queued data +lvextend -L+512k $vg/pool +lvextend -L+512k $vg/pool + +# collect 'dd' result +wait +cat log + +lvs -a $vg + +dd if="$DM_DEV_DIR/mapper/$vg-$lv1" of=2M-2 iflag=direct +md5sum 2M-2 | cut -f 1 -d ' ' | tee MD5-2 + +# these 2 are supposed to match +diff MD5 MD5-2 + + +# Do not want to see Live & Inactive table entry +( dm_info attr,name | not grep "LI-.*${PREFIX}" ) || { + dmsetup table --inactive | grep ${PREFIX} + die "Found device with Inactive table" +} + +# Check wrapping active thin-pool linear mapping has matching size +POOLSZ=$(dmsetup table ${vg}-pool-tpool | cut -d ' ' -f 2) +WRAPSZ=$(dmsetup table ${vg}-pool | cut -d ' ' -f 2) + +# +# FIXME: currently requires to update 2 dependent targets in one 'preload' +# lvm2 cannot handle this and would need one extra --refresh pass. +# Once resolved - enabled this test. +# Maybe other solution without fake linear mapping could be found. +# Eventually strictly map just single sector as it has no real use? +# +#should test "${POOLSZ}" = "${WRAPSZ}" || \ +# die "Wrapping pool device size does not match real pool size" + +vgremove -f $vg diff --git a/test/shell/thin-restore.sh b/test/shell/thin-restore.sh new file mode 100644 index 0000000..d8bae3c --- /dev/null +++ b/test/shell/thin-restore.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +# Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test restore operation of thin pool metadata + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 0 0 || skip + +aux prepare_vg 2 + +lvcreate -T -L8M $vg/pool -V10M -n $lv1 + +vgcfgbackup -f backup $vg + +# use of --force is mandatory +not vgcfgrestore -f backup $vg + +vgcfgrestore -y -f backup --force $vg + +check lv_field $vg/pool transaction_id 1 + +vgremove -f $vg diff --git a/test/shell/thin-vglock.sh b/test/shell/thin-vglock.sh new file mode 100644 index 0000000..b48ef25 --- /dev/null +++ b/test/shell/thin-vglock.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test locking works and doesn't update metadata +# RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1063542 + + + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +MKFS=mkfs.ext2 +which $MKFS || skip + +aux have_thin 1 0 0 || skip +aux prepare_vg + +lvcreate -L10 -T -V5 -n $lv1 $vg/pool +lvcreate -an -V10 -T $vg/pool + +$MKFS "$DM_DEV_DIR/$vg/$lv1" +mkdir mnt +mount "$DM_DEV_DIR/$vg/$lv1" mnt + +lvcreate -s -n snap $vg/$lv1 +check lv_field $vg/snap thin_id "3" + +lvconvert --merge $vg/snap + +umount mnt + +check lv_field $vg/$lv1 thin_id "1" +check lv_field $vg/pool transaction_id "3" + +vgchange -an $vg + +# Check reboot case +vgchange -ay --sysinit $vg + +# Check correct thin_id is shown after activation +# even when metadata were not yet physically modified. +# Merge take its place during activation, +# but pool transaction_id still needs metadata update. +check lv_field $vg/$lv1 thin_id "3" +check lv_field $vg/pool transaction_id "3" + +# Check the metadata are updated after refresh +# +vgchange --refresh $vg +check lv_field $vg/$lv1 thin_id "3" +check lv_field $vg/pool transaction_id "4" + +#lvs -a -o+transaction_id,thin_id $vg + +vgremove -f $vg diff --git a/test/shell/thin-volume-list.sh b/test/shell/thin-volume-list.sh new file mode 100644 index 0000000..6caa720 --- /dev/null +++ b/test/shell/thin-volume-list.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# test pool behaviour when volume_list masks activation + + +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 0 0 || skip + +aux prepare_vg 2 + +lvcreate -T -L8M $vg/pool -V10M -n $lv1 + +# skip $vg from activation +aux lvmconf "activation/volume_list = [ \"$vg1\" ]" + +# We still could pass - since pool is still active +lvcreate -V10 -n $lv2 -T $vg/pool + +# but $lv2 is not active +check inactive $vg $lv2 + +vgchange -an $vg + +# Pool is not active - so it cannot create thin volume +not lvcreate -V10 -T $vg/pool + +# Cannot create even new pool +# check there are not left devices (RHBZ #1140128) +not lvcreate -L10 -T $vg/new_pool +check lv_not_exists $vg/new_pool + +aux lvmconf "activation/volume_list = [ \"$vg\" ]" + +lvcreate -V10 -T $vg/pool + +lvs -o +transaction_id,thin_id $vg + +lvremove -ff $vg + +check vg_field $vg lv_count "0" + +vgremove -ff $vg diff --git a/test/shell/thin-zero-meta.sh b/test/shell/thin-zero-meta.sh new file mode 100644 index 0000000..a466729 --- /dev/null +++ b/test/shell/thin-zero-meta.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test how zeroing of thin-pool metadata works + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +# +# Main +# +aux have_thin 1 3 0 || skip +aux have_cache 1 3 0 || skip + +aux prepare_vg 3 40000 + +# Create mostly-zero devs only front of it has some 'real' back-end +aux zero_dev "$dev1" "$(( $(get first_extent_sector "$dev1") + 8192 )):" +aux zero_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 8192 )):" +aux zero_dev "$dev3" "$(( $(get first_extent_sector "$dev3") + 8192 )):" + +# Prepare randomly filled 4M LV on dev2 +lvcreate -L16G -n $lv1 $vg "$dev2" +dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=4 oflag=direct || true +lvremove -f $vg + +for i in 0 1 +do + aux lvmconf "allocation/zero_metadata = $i" + + # Lvm2 should allocate metadata on dev2 + lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2" + lvchange -an $vg + + lvs -ao+seg_pe_ranges $vg + lvchange -ay $vg/pool_tmeta --yes + + # Skip past 1.2M which is 'created' by thin-pool initialization + hexdump -C -n 200 -s 2000000 "$DM_DEV_DIR/$vg/pool_tmeta" | tee out + + # When fully zeroed, it should be zero - so almost no output from hexdump + case "$i" in + 0) test "$(wc -l < out)" -ge 10 ;; # should not be zeroed + 1) test "$(wc -l < out)" -le 10 ;; # should be zeroed + esac + + lvremove -f $vg/pool +done + +# Check lvm2 spots error during full zeroing of metadata device +aux error_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 32 )):" +not lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2" |& tee err +grep "Failed to initialize logical volume" err + +vgremove -ff $vg diff --git a/test/shell/topology-support.sh b/test/shell/topology-support.sh index e952dc0..ffd637f 100644 --- a/test/shell/topology-support.sh +++ b/test/shell/topology-support.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2010 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2010-2015 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 @@ -7,42 +8,36 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -. lib/test -which mkfs.ext3 || skip +SKIP_WITH_LVMPOLLD=1 -check_logical_block_size() { - local DEV_=$(cat SCSI_DEBUG_DEV) - # 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 = $1 - fi -} +. lib/inittest + +which mkfs.ext3 || skip lvdev_() { echo "$DM_DEV_DIR/$1/$2" } test_snapshot_mount() { - lvcreate -L 16M -n $lv1 $vg "$dev1" - mkfs.ext3 $(lvdev_ $vg $lv1) + lvcreate -aey -L4M -n $lv1 $vg "$dev1" + mkfs.ext3 -b4096 "$(lvdev_ $vg $lv1)" mkdir test_mnt mount "$(lvdev_ $vg $lv1)" test_mnt - lvcreate -L 16M -n $lv2 -s $vg/$lv1 + lvcreate -L4M -n $lv2 -s $vg/$lv1 umount test_mnt + aux udev_wait # mount the origin mount "$(lvdev_ $vg $lv1)" test_mnt umount test_mnt + aux udev_wait # 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 } @@ -50,16 +45,7 @@ test_snapshot_mount() { NUM_DEVS=1 PER_DEV_SIZE=34 -DEV_SIZE=$(($NUM_DEVS*$PER_DEV_SIZE)) - -# Test that kernel supports topology -aux prepare_scsi_debug_dev $DEV_SIZE || skip - -if [ ! -e /sys/block/$(basename $(cat SCSI_DEBUG_DEV))/alignment_offset ] ; then - aux cleanup_scsi_debug_dev - skip -fi -aux cleanup_scsi_debug_dev +DEV_SIZE=$(( NUM_DEVS * PER_DEV_SIZE )) # --------------------------------------------- # Create "desktop-class" 4K drive @@ -67,10 +53,16 @@ aux cleanup_scsi_debug_dev LOGICAL_BLOCK_SIZE=512 aux prepare_scsi_debug_dev $DEV_SIZE \ sector_size=$LOGICAL_BLOCK_SIZE physblk_exp=3 -check_logical_block_size $LOGICAL_BLOCK_SIZE - +# Test that kernel supports topology +if [ ! -e "/sys/block/$(basename "$(< SCSI_DEBUG_DEV)")/alignment_offset" ] ; then + aux cleanup_scsi_debug_dev + skip +fi +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "$LOGICAL_BLOCK_SIZE" aux prepare_pvs $NUM_DEVS $PER_DEV_SIZE -vgcreate -c n $vg $(cat DEVICES) +get_devs + +vgcreate $SHARED $vg "${DEVICES[@]}" test_snapshot_mount vgremove $vg @@ -82,10 +74,10 @@ aux cleanup_scsi_debug_dev LOGICAL_BLOCK_SIZE=512 aux prepare_scsi_debug_dev $DEV_SIZE \ sector_size=$LOGICAL_BLOCK_SIZE physblk_exp=3 lowest_aligned=7 -check_logical_block_size $LOGICAL_BLOCK_SIZE +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size $LOGICAL_BLOCK_SIZE aux prepare_pvs $NUM_DEVS $PER_DEV_SIZE -vgcreate -c n $vg $(cat DEVICES) +vgcreate $SHARED $vg "${DEVICES[@]}" test_snapshot_mount vgremove $vg @@ -97,9 +89,36 @@ aux cleanup_scsi_debug_dev LOGICAL_BLOCK_SIZE=4096 aux prepare_scsi_debug_dev $DEV_SIZE \ sector_size=$LOGICAL_BLOCK_SIZE -check_logical_block_size $LOGICAL_BLOCK_SIZE +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size $LOGICAL_BLOCK_SIZE aux prepare_pvs $NUM_DEVS $PER_DEV_SIZE -vgcreate -c n $vg $(cat DEVICES) +vgcreate $SHARED $vg "${DEVICES[@]}" test_snapshot_mount vgremove $vg + +aux cleanup_scsi_debug_dev + +# scsi_debug option opt_blks appeared in Oct 2010 +aux kernel_at_least 2 6 37 || exit 0 + +# --------------------------------------------- +# Create "enterprise-class" 512 drive w/ HW raid stripe_size = 768K +# (logical_block_size=512, physical_block_size=512, alignment_offset=0): +# - tests case where optimal_io_size=768k < default PE alignment=1MB +LOGICAL_BLOCK_SIZE=512 +aux prepare_scsi_debug_dev $DEV_SIZE \ + sector_size=$LOGICAL_BLOCK_SIZE opt_blks=1536 + +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size $LOGICAL_BLOCK_SIZE +check sysfs "$(< SCSI_DEBUG_DEV)" queue/optimal_io_size 786432 + +aux prepare_devs 1 $PER_DEV_SIZE +pvcreate --metadatasize 255s "${DEVICES[@]}" + +# Kernel (3.19) could provide wrong results - in this case skip +# test with incorrect result - lvm2 can't figure out good values. +SHOULD="" +check sysfs "$dev1" queue/optimal_io_size 786432 || SHOULD=should +$SHOULD check pv_field "${DEVICES[@]}" pe_start 768.00k + +aux cleanup_scsi_debug_dev diff --git a/test/shell/udev-pvscan-vgchange.sh b/test/shell/udev-pvscan-vgchange.sh new file mode 100644 index 0000000..14dbe82 --- /dev/null +++ b/test/shell/udev-pvscan-vgchange.sh @@ -0,0 +1,457 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='udev rule and systemd unit run vgchange' + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +# FIXME: currently test relies on several system properties to be +# explcitely configure and directly modifies their state + +# +# $ cat /tmp/devs +# /dev/sdb +# /dev/sdc +# /dev/sdd +# +# Specify this file as LVM_TEST_DEVICE_LIST=/tmp/devs +# when running the test. +# +# This test will wipe these devices. +# + +if [ -z ${LVM_TEST_DEVICE_LIST+x} ]; then + skip "LVM_TEST_DEVICE_LIST is unset" +else + echo "LVM_TEST_DEVICE_LIST is set to '$LVM_TEST_DEVICE_LIST'" +fi + +test -e "$LVM_TEST_DEVICE_LIST" || skip + +num_devs=$(cat "$LVM_TEST_DEVICE_LIST" | wc -l) + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* + rm -f "$PVS_LOOKUP_DIR"/* +} + +test -d "$PVS_ONLINE_DIR" || mkdir -p "$PVS_ONLINE_DIR" +test -d "$VGS_ONLINE_DIR" || mkdir -p "$VGS_ONLINE_DIR" +test -d "$PVS_LOOKUP_DIR" || mkdir -p "$PVS_LOOKUP_DIR" +_clear_online_files + +aux prepare_real_devs + +aux lvmconf 'devices/dir = "/dev"' +aux lvmconf 'devices/use_devicesfile = 1' +DFDIR="$LVM_SYSTEM_DIR/devices" +DF="$DFDIR/system.devices" +mkdir "$DFDIR" || true +not ls "$DF" + +get_real_devs + +wipe_all() { + for dev in "${REAL_DEVICES[@]}"; do + wipefs -a "$dev" + done +} + +wait_lvm_activate() { + local vgw=$1 + local wait=0 + + while systemctl status lvm-activate-$vgw > /dev/null && test "$wait" -le 30; do + sleep .2 + wait=$(( wait + 1 )) + done +} + +# Test requires 3 devs +test "$num_devs" -gt 2 || skip +BDEV1=$(basename "$dev1") +BDEV2=$(basename "$dev2") +BDEV3=$(basename "$dev3") + +wipe_all +touch "$DF" +for dev in "${REAL_DEVICES[@]}"; do + pvcreate $dev +done + +# 1 dev, 1 vg, 1 lv + +vgcreate $vg1 "$dev1" +lvcreate -l1 -an -n $lv1 $vg1 "$dev1" + +PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}') + +_clear_online_files +udevadm trigger --settle -c add "/sys/block/$BDEV1" + +wait_lvm_activate $vg1 + +ls "$RUNDIR/lvm/pvs_online/$PVID1" || true +ls "$RUNDIR/lvm/vgs_online/$vg1" || true +journalctl -u lvm-activate-$vg1 | tee out || true +grep "now active" out +check lv_field $vg1/$lv1 lv_active "active" + +vgchange -an $vg1 +vgremove -y $vg1 + + +# 2 devs, 1 vg, 2 lvs + +vgcreate $vg2 "$dev1" "$dev2" +lvcreate -l1 -an -n $lv1 $vg2 "$dev1" +lvcreate -l1 -an -n $lv2 $vg2 "$dev2" + +PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}') +PVID2=$(pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}') + +_clear_online_files + +udevadm trigger --settle -c add "/sys/block/$BDEV1" +ls "$RUNDIR/lvm/pvs_online/$PVID1" +not ls "$RUNDIR/lvm/vgs_online/$vg2" +journalctl -u lvm-activate-$vg2 | tee out || true +not grep "now active" out +check lv_field $vg2/$lv1 lv_active "" +check lv_field $vg2/$lv2 lv_active "" + +udevadm trigger --settle -c add "/sys/block/$BDEV2" +ls "$RUNDIR/lvm/pvs_online/$PVID2" +ls "$RUNDIR/lvm/vgs_online/$vg2" + +wait_lvm_activate $vg2 + +journalctl -u lvm-activate-$vg2 | tee out || true +grep "now active" out +check lv_field $vg2/$lv1 lv_active "active" +check lv_field $vg2/$lv2 lv_active "active" + +vgchange -an $vg2 +vgremove -y $vg2 + + +# 3 devs, 1 vg, 4 lvs, concurrent pvscans +# (attempting to have the pvscans run concurrently and race +# to activate the VG) + +vgcreate $vg3 "$dev1" "$dev2" "$dev3" +lvcreate -l1 -an -n $lv1 $vg3 "$dev1" +lvcreate -l1 -an -n $lv2 $vg3 "$dev2" +lvcreate -l1 -an -n $lv3 $vg3 "$dev3" +lvcreate -l8 -an -n $lv4 -i 2 $vg3 "$dev1" "$dev2" + +PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}') +PVID2=$(pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}') +PVID3=$(pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}') + +_clear_online_files + +udevadm trigger -c add "/sys/block/$BDEV1" & +udevadm trigger -c add "/sys/block/$BDEV2" & +udevadm trigger -c add "/sys/block/$BDEV3" + +aux udev_wait +wait_lvm_activate $vg3 + +ls "$RUNDIR/lvm/pvs_online/$PVID1" +ls "$RUNDIR/lvm/pvs_online/$PVID2" +ls "$RUNDIR/lvm/pvs_online/$PVID3" +ls "$RUNDIR/lvm/vgs_online/$vg3" +journalctl -u lvm-activate-$vg3 | tee out || true +grep "now active" out +check lv_field $vg3/$lv1 lv_active "active" +check lv_field $vg3/$lv2 lv_active "active" +check lv_field $vg3/$lv3 lv_active "active" +check lv_field $vg3/$lv4 lv_active "active" + +vgchange -an $vg3 +vgremove -y $vg3 + + +# 3 devs, 1 vg, 4 lvs, concurrent pvscans, metadata on only 1 PV + +wipe_all +rm $DF +touch $DF +pvcreate --metadatacopies 0 "$dev1" +pvcreate --metadatacopies 0 "$dev2" +pvcreate "$dev3" + +vgcreate $vg4 "$dev1" "$dev2" "$dev3" +lvcreate -l1 -an -n $lv1 $vg4 "$dev1" +lvcreate -l1 -an -n $lv2 $vg4 "$dev2" +lvcreate -l1 -an -n $lv3 $vg4 "$dev3" +lvcreate -l8 -an -n $lv4 -i 2 $vg4 "$dev1" "$dev2" + +PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}') +PVID2=$(pvs "$dev2" --noheading -o uuid | tr -d - | awk '{print $1}') +PVID3=$(pvs "$dev3" --noheading -o uuid | tr -d - | awk '{print $1}') + +_clear_online_files + +udevadm trigger -c add "/sys/block/$BDEV1" & +udevadm trigger -c add "/sys/block/$BDEV2" & +udevadm trigger -c add "/sys/block/$BDEV3" + +aux udev_wait +wait_lvm_activate $vg4 + +ls "$RUNDIR/lvm/pvs_lookup/" +cat "$RUNDIR/lvm/pvs_lookup/$vg4" || true +ls "$RUNDIR/lvm/pvs_online/$PVID1" +ls "$RUNDIR/lvm/pvs_online/$PVID2" +ls "$RUNDIR/lvm/pvs_online/$PVID3" +ls "$RUNDIR/lvm/vgs_online/$vg4" +journalctl -u lvm-activate-$vg4 | tee out || true +grep "now active" out +check lv_field $vg4/$lv1 lv_active "active" +check lv_field $vg4/$lv2 lv_active "active" +check lv_field $vg4/$lv3 lv_active "active" +check lv_field $vg4/$lv4 lv_active "active" + +vgchange -an $vg4 +vgremove -y $vg4 + + +# 3 devs, 3 vgs, 2 lvs in each vg, concurrent pvscans + +wipe_all +rm "$DF" +touch "$DF" + +vgcreate $vg5 "$dev1" +vgcreate $vg6 "$dev2" +vgcreate $vg7 "$dev3" +lvcreate -l1 -an -n $lv1 $vg5 +lvcreate -l1 -an -n $lv2 $vg5 +lvcreate -l1 -an -n $lv1 $vg6 +lvcreate -l1 -an -n $lv2 $vg6 +lvcreate -l1 -an -n $lv1 $vg7 +lvcreate -l1 -an -n $lv2 $vg7 + +_clear_online_files + +udevadm trigger -c add "/sys/block/$BDEV1" & +udevadm trigger -c add "/sys/block/$BDEV2" & +udevadm trigger -c add "/sys/block/$BDEV3" + +aux udev_wait +wait_lvm_activate $vg5 +wait_lvm_activate $vg6 +wait_lvm_activate $vg7 + +ls "$RUNDIR/lvm/vgs_online/$vg5" +ls "$RUNDIR/lvm/vgs_online/$vg6" +ls "$RUNDIR/lvm/vgs_online/$vg7" +journalctl -u lvm-activate-$vg5 | tee out || true +grep "now active" out +journalctl -u lvm-activate-$vg6 | tee out || true +grep "now active" out +journalctl -u lvm-activate-$vg7 | tee out || true +grep "now active" out +check lv_field $vg5/$lv1 lv_active "active" +check lv_field $vg5/$lv2 lv_active "active" +check lv_field $vg6/$lv1 lv_active "active" +check lv_field $vg6/$lv2 lv_active "active" +check lv_field $vg7/$lv1 lv_active "active" +check lv_field $vg7/$lv2 lv_active "active" + +vgchange -an $vg5 +vgremove -y $vg5 +vgchange -an $vg6 +vgremove -y $vg6 +vgchange -an $vg7 +vgremove -y $vg7 + +# 3 devs, 1 vg, 1000 LVs + +wipe_all +rm "$DF" +touch "$DF" +pvcreate --metadatacopies 0 "$dev1" +pvcreate "$dev2" +pvcreate "$dev3" +vgcreate -s 128K $vg8 "$dev1" "$dev2" "$dev3" + +# Number of LVs to create +TEST_DEVS=1000 +# On low-memory boxes let's not stress too much +test "$(aux total_mem)" -gt 524288 || TEST_DEVS=256 + +vgcfgbackup -f data $vg8 + +# Generate a lot of devices (size of 1 extent) +awk -v TEST_DEVS=$TEST_DEVS '/^\t\}/ { + printf("\t}\n\tlogical_volumes {\n"); + cnt=0; + for (i = 0; i < TEST_DEVS; i++) { + printf("\t\tlvol%06d {\n", i); + printf("\t\t\tid = \"%06d-1111-2222-3333-2222-1111-%06d\"\n", i, i); + print "\t\t\tstatus = [\"READ\", \"WRITE\", \"VISIBLE\"]"; + print "\t\t\tsegment_count = 1"; + print "\t\t\tsegment1 {"; + print "\t\t\t\tstart_extent = 0"; + print "\t\t\t\textent_count = 1"; + print "\t\t\t\ttype = \"striped\""; + print "\t\t\t\tstripe_count = 1"; + print "\t\t\t\tstripes = ["; + print "\t\t\t\t\t\"pv0\", " cnt++; + printf("\t\t\t\t]\n\t\t\t}\n\t\t}\n"); + } + } + {print} +' data >data_new + +vgcfgrestore -f data_new $vg8 + +_clear_online_files + +udevadm trigger -c add "/sys/block/$BDEV1" & +udevadm trigger -c add "/sys/block/$BDEV2" & +udevadm trigger -c add "/sys/block/$BDEV3" + +aux udev_wait +wait_lvm_activate $vg8 + +ls "$RUNDIR/lvm/vgs_online/$vg8" +journalctl -u lvm-activate-$vg8 | tee out || true +grep "now active" out + +num_active=$(lvs $vg8 --noheading -o active | grep -c active) + +test "$num_active" -eq "$TEST_DEVS" + +vgchange -an $vg8 +vgremove -y $vg8 + +# 1 pv on an md dev, 1 vg + +wait_md_create() { + local md=$1 + + while :; do + if ! grep "$(basename $md)" /proc/mdstat; then + echo "$md not ready" + cat /proc/mdstat + sleep 2 + else + break + fi + done + echo "$md" > WAIT_MD_DEV +} + +test -f /proc/mdstat && grep -q raid1 /proc/mdstat || \ + modprobe raid1 || skip + +wipe_all +rm "$DF" +touch "$DF" + +aux mdadm_create --metadata=1.0 --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2" +mddev=$(< MD_DEV) + +wait_md_create "$mddev" +vgcreate $vg9 "$mddev" +lvmdevices --adddev "$mddev" || true + +PVIDMD=$(pvs "$mddev" --noheading -o uuid | tr -d - | awk '{print $1}') +BDEVMD=$(basename "$mddev") + +lvcreate -l1 -an -n $lv1 $vg9 +lvcreate -l1 -an -n $lv2 $vg9 + +mdadm --stop "$mddev" +_clear_online_files +aux mdadm_assemble "$mddev" "$dev1" "$dev2" + +# this trigger might be redundant because the mdadm --assemble +# probably triggers an add uevent +udevadm trigger --settle -c add /sys/block/$BDEVMD + +wait_lvm_activate $vg9 + +ls "$RUNDIR/lvm/vgs_online/$vg9" +journalctl -u lvm-activate-$vg9 | tee out || true +grep "now active" out +check lv_field $vg9/$lv1 lv_active "active" +check lv_field $vg9/$lv2 lv_active "active" + +vgchange -an $vg9 +vgremove -y $vg9 + +mdadm --stop "$mddev" +aux udev_wait +wipe_all + +# no devices file, filter with symlink of PV +# the pvscan needs to look at all dev names to +# match the symlink in the filter with the +# dev name (or major minor) passed to pvscan. +# This test doesn't really belong in this file +# because it's not testing lvm-activate. + +aux lvmconf 'devices/use_devicesfile = 0' +_clear_online_files +rm "$DF" +vgcreate $vg10 "$dev1" +lvcreate -l1 -an -n $lv1 $vg10 "$dev1" + +PVID1=$(pvs "$dev1" --noheading -o uuid | tr -d - | awk '{print $1}') +# PVID with dashes +OPVID1=$(pvs "$dev1" --noheading -o uuid | awk '{print $1}') + +udevadm trigger --settle -c add "/sys/block/$BDEV1" + +# uevent from the trigger should create this symlink +ls "/dev/disk/by-id/lvm-pv-uuid-$OPVID1" + +vgchange -an $vg10 +_clear_online_files + +aux lvmconf "devices/filter = [ \"a|/dev/disk/by-id/lvm-pv-uuid-$OPVID1|\", \"r|.*|\" ]" +aux lvmconf 'devices/global_filter = [ "a|.*|" ]' + +pvscan --cache -aay "$dev1" + +check lv_field $vg10/$lv1 lv_active "active" + +vgchange -an $vg10 +_clear_online_files + +aux lvmconf 'devices/filter = [ "a|lvm-pv-uuid|", "r|.*|" ]' +aux lvmconf 'devices/global_filter = [ "a|.*|" ]' + +pvscan --cache -aay "$dev1" + +check lv_field $vg10/$lv1 lv_active "active" + +vgchange -an $vg10 +vgremove -y $vg10 +wipe_all diff --git a/test/shell/unknown-segment.sh b/test/shell/unknown-segment.sh index d6071a1..ef66447 100644 --- a/test/shell/unknown-segment.sh +++ b/test/shell/unknown-segment.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2009 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,28 +8,40 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_vg 4 -lvcreate -l 1 -n $lv1 $vg -lvcreate -l 2 -m 1 -n $lv2 $vg +lvcreate -an -Zn -l 1 -n $lv1 $vg +lvcreate -an -Zn -l 2 --type mirror -m 1 -n $lv2 $vg +lvcreate -an -Zn --type zero -l 1 -n $lv3 $vg vgcfgbackup -f bak0 $vg -sed -e 's,striped,unstriped,;s,mirror,unmirror,' -i.orig bak0 +sed -e 's,striped,unstriped,;s,mirror,unmirror,;s,zero,zero+NEWFLAG,' -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 +not lvchange -aey $vg/$lv1 # check that activation is refused + +# try once more to catch invalid memory access with valgrind +# when clvmd flushes cmd mem pool +not lvchange -aey $vg/$lv2 # check that activation is refused + +not lvchange -aey $vg/$lv3 # check that activation is refused vgcfgbackup -f bak1 $vg cat bak1 -sed -e 's,unstriped,striped,;s,unmirror,mirror,' -i.orig bak1 +sed -e 's,unstriped,striped,;s,unmirror,mirror,;s,zero+NEWFLAG,zero,' -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 +grep -v -E 'description|seqno|creation_time|Generated' < bak0.orig > a +grep -v -E 'description|seqno|creation_time|Generated' < bak2 > b diff -u a b + +vgremove -ff $vg diff --git a/test/shell/unlost-pv.sh b/test/shell/unlost-pv.sh index 962fe22..50f8928 100644 --- a/test/shell/unlost-pv.sh +++ b/test/shell/unlost-pv.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,38 +8,66 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 -check_() { - # vgscan needs --cache option for direct scan if lvmetad is used - test -e LOCAL_LVMETAD && cache="--cache" - vgscan $cache 2>&1 | tee vgscan.out - $1 grep "Inconsistent metadata found for VG $vg" vgscan.out -} +. lib/inittest aux prepare_vg 3 -lvcreate -m 1 -l 1 -n mirror $vg -lvchange -a n $vg +lvcreate -an -Zn --type mirror -m 1 -l 1 -n mirror $vg # try orphaning a missing PV (bz45867) aux disable_dev "$dev1" vgreduce --removemissing --force $vg aux enable_dev "$dev1" -check_ -test -e LOCAL_LVMETAD && pvcreate -f "$dev1" -check_ not +vgscan 2>&1 | tee vgscan.out +grep "Inconsistent metadata found for VG $vg" vgscan.out + +# erase outdated dev1 +vgck --updatemetadata $vg + +vgscan 2>&1 | tee vgscan.out +not grep "Inconsistent metadata found for VG $vg" vgscan.out + -# 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" + lvcreate -l 1 -n boo -a n --zero n $vg + aux disable_dev "$dev1" + lvremove $vg/mirror + aux enable_dev "$dev1" -check_ -test -e LOCAL_LVMETAD && lvremove $vg/boo # FIXME trigger a write :-( -check_ not + +vgscan 2>&1 | tee vgscan.out +grep "Inconsistent metadata found for VG $vg" vgscan.out + +# write the vg to update the metadata on dev1 +vgck --updatemetadata $vg + +vgscan 2>&1 | tee vgscan.out +not grep "Inconsistent metadata found for VG $vg" vgscan.out + +aux disable_dev "$dev1" + +vgreduce --removemissing --force $vg + +aux enable_dev "$dev1" + +vgscan 2>&1 | tee out + +vgscan 2>&1 | tee vgscan.out +grep "Inconsistent metadata found for VG $vg" vgscan.out + +# erase outdated dev1 +vgck --updatemetadata $vg + +vgscan 2>&1 | tee vgscan.out +not grep "Inconsistent metadata found for VG $vg" vgscan.out + +vgremove -ff $vg diff --git a/test/shell/vdo-autoumount-dmeventd.sh b/test/shell/vdo-autoumount-dmeventd.sh new file mode 100644 index 0000000..e0449ff --- /dev/null +++ b/test/shell/vdo-autoumount-dmeventd.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# no automatic extensions, just umount + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +mntdir="${PREFIX}mnt with space" +PERCENT=70 + +cleanup_mounted_and_teardown() +{ + test -z "$PID_SLEEP" || { kill "$PID_SLEEP" || true ; } + umount "$mntdir" 2>/dev/null || true + vgremove -ff $vg + aux teardown +} + +is_lv_opened_() +{ + test "$(get lv_field "$1" lv_device_open --binary)" = 1 +} + +# +# Main +# +which mkfs.ext4 || skip +export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf" + +aux have_vdo 6 2 0 || skip + +# Simple implementation of umount when lvextend fails +# Script enforces failin exit, so dmeventd tries several times +# repeatedly to invoke this for given percentage +cat <<- EOF >testcmd.sh +#!/bin/sh + +echo "VDO Pool: \$DMEVENTD_VDO_POOL" + +"$TESTDIR/lib/lvextend" --use-policies \$1 || { + umount "$mntdir" && exit 0 + touch $PWD/TRIED_UMOUNT +} +test "\$($TESTDIR/lib/lvs -o selected -S "data_percent>=$PERCENT" --noheadings \$1)" -eq 0 || { + echo "Percentage still above $PERCENT" +} +exit 1 +EOF +chmod +x testcmd.sh +# Show prepared script +cat testcmd.sh + +# Use autoextend percent 0 - so extension fails and triggers umount... +aux lvmconf "activation/vdo_pool_autoextend_percent = 0" \ + "activation/vdo_pool_autoextend_threshold = $PERCENT" \ + "dmeventd/vdo_command = \"$PWD/testcmd.sh\"" \ + "allocation/vdo_slab_size_mb = 128" + +aux prepare_dmeventd + +aux prepare_vg 1 9000 + +lvcreate --vdo -L4G -V2G -n $lv1 $vg/vpool + +mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1" + +lvchange --monitor y $vg/vpool + +mkdir "$mntdir" +trap 'cleanup_mounted_and_teardown' EXIT +mount "$DM_DEV_DIR/$vg/$lv1" "$mntdir" + +# Check both LV is opened (~mounted) +is_lv_opened_ "$vg/$lv1" + +touch "$mntdir/file$$" +sync + +# Running 'keeper' process sleep holds the block device still in use +sleep 60 < "$mntdir/file$$" >/dev/null 2>&1 & +PID_SLEEP=$! + +lvs -a $vg +# Fill pool above 95% (to cause 'forced lazy umount) +dd if=/dev/urandom of="$mntdir/file$$" bs=256K count=200 oflag=direct + +lvs -a $vg + +# Could loop here for a few secs so dmeventd can do some work +# In the worst case check only happens every 10 seconds :( +for i in $(seq 1 12) ; do + is_lv_opened_ "$vg/$lv1" || break + test ! -f "TRIED_UMOUNT" || continue # finish loop quickly + sleep 1 +done + +rm -f "TRIED_UMOUNT" +test "$i" -eq 12 || die "$mntdir should NOT have been unmounted by dmeventd!" + +lvs -a $vg + +# Kill device holding process - umount should work now +kill "$PID_SLEEP" +PID_SLEEP= +wait + +# Could loop here for a few secs so dmeventd can do some work +# In the worst case check only happens every 10 seconds :( +for i in $(seq 1 12) ; do + is_lv_opened_ "$vg/$lv1" || break + test "$i" -lt 12 || die "$mntdir should have been unmounted by dmeventd!" + sleep 1 +done + +# vgremove is managed through cleanup_mounted_and_teardown() diff --git a/test/shell/vdo-convert.sh b/test/shell/vdo-convert.sh new file mode 100644 index 0000000..231939c --- /dev/null +++ b/test/shell/vdo-convert.sh @@ -0,0 +1,230 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test conversion of VDO volumes made by vdo manager into VDO LV. + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Use local for this test vdo configuratoin +VDO_CONFIG="vdotestconf.yml" +VDOCONF="-f $VDO_CONFIG" +#VDOCONF="" +export VDOCONF VDO_CONFIG +VDONAME="${PREFIX}-TESTVDO" +export DM_UUID_PREFIX=$PREFIX + +# VDO automatically starts dmeventd +aux prepare_dmeventd + +# +# Main +# +if not which vdo ; then + which lvm_vdo_wrapper || skip "Missing 'lvm_vdo_wrapper'." + which oldvdoformat || skip "Emulation of vdo manager 'oldvdoformat' missing." + which oldvdoprepareforlvm || skip "Emulation of vdo manager 'oldvdoprepareforlvm' missing." + # enable expansion of aliasis within script itself + shopt -s expand_aliases + alias vdo='lvm_vdo_wrapper' + export VDO_BINARY=lvm_vdo_wrapper + echo "Using 'lvm_vdo_wrapper' emulation of 'vdo' manager." +fi +which mkfs.ext4 || skip +export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf" + +aux have_vdo 6 2 0 || skip + +aux prepare_devs 2 20000 + +aux extend_filter_LVMTEST + +export TMPDIR=$PWD + + +# Conversion can be made with this version of vdo driver +aux have_vdo 6 2 5 || skip + +# +# Check conversion of VDO volume made on some LV +# +# In this case we do not need to move any VDO headers. +# +vgcreate $vg "$dev1" + +lvcreate -L5G -n $lv1 $vg + +# use some not so 'well' aligned virtual|logical size +vdo create $VDOCONF --name "$VDONAME" --device "$DM_DEV_DIR/$vg/$lv1" --vdoSlabSize 128M --vdoLogicalSize 10G + +mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME" +##XXXXX +# Different VG name fails +not lvm_import_vdo -y -v --name $vg1/$lv1 "$DM_DEV_DIR/$vg/$lv1" + +# Try just dry run and observe logging +lvm_import_vdo --dry-run -y -v --name $lv1 "$DM_DEV_DIR/$vg/$lv1" + +lvm_import_vdo -y --name $lv1 "$DM_DEV_DIR/$vg/$lv1" + +# ensure VDO device is not left in config file +vdo remove $VDOCONF --force --name "$VDONAME" 2>/dev/null || true + +lvremove -f $vg + + +# Test user can specify different VDO LV name (so the original LV is renamed) +lvcreate -y -L5G -n $lv1 $vg + +vdo create $VDOCONF --name "$VDONAME" --device "$DM_DEV_DIR/$vg/$lv1" --vdoSlabSize 128M --vdoLogicalSize 10G + +lvm_import_vdo -y --name $vg/$lv2 "$DM_DEV_DIR/$vg/$lv1" + +check lv_exists $vg $lv2 +check lv_not_exists $vg $lv1 + +vgremove -f $vg + +# ensure VDO device is not left in config file +vdo remove $VDOCONF --force --name "$VDONAME" 2>/dev/null || true + +aux wipefs_a "$dev1" + +# prepare 'unused' $vg2 +vgcreate $vg2 "$dev2" + +# +# Check conversion of VDO volume on non-LV device and with >2T size +# +vdo create $VDOCONF --name "$VDONAME" --device "$dev1" --vdoSlabSize 128M --vdoLogicalSize 3T + +# Fail with an already existing volume group $vg2 +not lvm_import_vdo --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err +grep "already existing volume group" err + +# User can also convert already stopped VDO volume +vdo stop $VDOCONF --name "$VDONAME" + +lvm_import_vdo -y -v --name $vg/$lv1 "$dev1" + +check lv_field $vg/$lv1 size "3.00t" + +vgremove -f $vg + + +# +# Try once again with different vgname/lvname and sizes +# +aux teardown_devs +aux prepare_devs 1 23456 + +vdo create $VDOCONF --name "$VDONAME" --device "$dev1" --vdoSlabSize 128M --vdoLogicalSize 23G + +mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME" + +lvm_import_vdo --vdo-config "$VDO_CONFIG" -y -v --name $vg1/$lv2 "$dev1" + +fsck -n "$DM_DEV_DIR/$vg1/$lv2" + +vgremove -f $vg1 + +aux wipefs_a "$dev1" + +# let's assume users with VDO target have 'new' enough version of stat too +# otherwise use more universal code from lvm_vdo_import +read major minor < <(stat -c '%Hr %Lr' $(readlink -e "$dev1")) +dmsetup create "$PREFIX-vdotest" --table "0 30280004 linear $major:$minor 32" + +TEST="$DM_DEV_DIR/mapper/$PREFIX-vdotest" + +aux wipefs_a "$TEST" +aux extend_filter "a|$TEST|" +aux extend_devices "$TEST" + +# +# Unfortunatelly generates this in syslog: +# +# vdo-start-by-dev@loop0.service: Main process exited, code=exited, status=1/FAILURE +# vdo-start-by-dev@loop0.service: Failed with result 'exit-code'. +# Failed to start Start VDO volume backed by loop0. +# +# TODO: Could be handled by: +# +# systemctl mask vdo-start-by-dev@ +# systemctl unmask vdo-start-by-dev@ +# +# automate... +# + +# use slightly smaller size then 'rounded' 23G - to enforce vdo_logicalSize rounding +vdo create $VDOCONF --name "$VDONAME" --device "$TEST" --vdoSlabSize 128M --vdoLogicalSize 24117240K\ + --blockMapCacheSize 192 \ + --blockMapPeriod 2048 \ + --emulate512 disabled \ + --indexMem 0.5 \ + --maxDiscardSize 10 \ + --sparseIndex disabled \ + --vdoAckThreads 2 \ + --vdoBioRotationInterval 8 \ + --vdoBioThreads 2 \ + --vdoCpuThreads 5 \ + --vdoHashZoneThreads 3 \ + --vdoLogicalThreads 3 \ + --writePolicy async-unsafe +dmsetup table + +# Get VDO table line +dmsetup table "$VDONAME" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee vdo-orig + +mkfs.ext4 -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME" + +# For conversion we +aux lvmconf 'global/vdo_disabled_features = [ "version4" ]' + +# +# Try to prepare 'broken' case where header was moved by older tool to 2M position +# +export LVM_VDO_PREPARE=oldvdoprepareforlvm2M +if which "$LVM_VDO_PREPARE" ; then +# Use old vdoprepareforlvm tool, that always moves header to 2M offset +cp "$VDO_CONFIG" "$VDO_CONFIG.backup" +lvm_import_vdo --abort-after-vdo-convert --vdo-config "$VDO_CONFIG" -v -y --name $vg/$lv "$TEST" +# Restore VDO configuration (as it's been removed with succeful vdo conversion +cp "$VDO_CONFIG.backup" "$VDO_CONFIG" +# Check VDO header is seen at 2M offset +blkid -c /dev/null --probe --offset 2M "$TEST" +fi +unset LVM_VDO_PREPARE + +#lvm_import_vdo --no-snapshot --vdo-config "$VDO_CONFIG" -v -y --name $vg/$lv "$TEST" +lvm_import_vdo --vdo-config "$VDO_CONFIG" --uuid-prefix "$PREFIX" -v -y --name $vg/$lv "$TEST" +dmsetup table + +# check our filesystem is OK +fsck -n "$DM_DEV_DIR/$vg/$lv" + +# Compare converted LV uses same VDO table line +dmsetup table "$vg-${lv}_vpool-vpool" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee new-vdo-lv + +tail -n+3 vdo-orig >vdo-orig-3 +tail -n+3 new-vdo-lv >new-vdo-lv-3 + +# Check there is a match between VDO and LV managed volume +# (when differentiating parameters are deleted first) +# we need to skip first 2 lines as the device size gets rounded to match VG extent size +diff -u vdo-orig-3 new-vdo-lv-3 || die "Found mismatching VDO table lines!" + +check lv_field $vg/$lv size "23.00g" +unset LVM_VDO_PREPARE + diff --git a/test/shell/vg-check-devs-used.sh b/test/shell/vg-check-devs-used.sh new file mode 100644 index 0000000..15cdff6 --- /dev/null +++ b/test/shell/vg-check-devs-used.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 + + +. lib/inittest + +# We need "dm" directory for dm devices in sysfs. +aux driver_at_least 4 15 || skip + +aux prepare_devs 3 8 + +vgcreate $SHARED "$vg" "$dev1" "$dev2" +lvcreate -l100%FREE -n $lv $vg +dd if="$dev1" of="$dev3" bs=1M oflag=direct +pvs --devices $dev2,$dev3 2>err +grep "WARNING: Device mismatch detected for $vg/$lv which is accessing $dev1 instead of $dev3" err + +dd if=/dev/zero of="$dev3" bs=1M count=8 oflag=direct +lvremove -ff $vg + +# Also test if sub LVs with suffixes are correctly processed. +# Check with thick snapshot which has sub LVs with -real and -cow suffix in UUID. +lvcreate -l1 -aey -n $lv $vg +lvcreate -l1 -aey -s $vg/$lv +pvs 2>err +not grep "WARNING: Device mismatch detected for $vg/$lv" err + +vgremove -ff $vg diff --git a/test/shell/vg-name-from-env.sh b/test/shell/vg-name-from-env.sh new file mode 100644 index 0000000..48e471c --- /dev/null +++ b/test/shell/vg-name-from-env.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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. + +test_description='Test the vg name for an lv from env var' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 2 + +pvcreate "$dev1" +pvcreate "$dev2" + +vgcreate $SHARED $vg1 "$dev1" +vgcreate $SHARED $vg2 "$dev2" + +export LVM_VG_NAME=$vg1 + +# should use env +lvcreate -n $lv1 -l 2 +lvcreate -n $lv3 -l 2 + +lvcreate -n $lv2 -l 2 $vg2 +lvcreate -n $lv4 -l 2 $vg2 + +lvs >err +grep $lv1 err +grep $lv3 err +grep $lv2 err +grep $lv4 err + +not lvs $vg1 >err +not grep $lv1 err +not grep $lv3 err +not grep $lv2 err +not grep $lv4 err + +not lvs $vg2 >err +not grep $lv1 err +not grep $lv3 err +not grep $lv2 err +not grep $lv4 err + +lvs $lv1 >err +grep $lv1 err +not grep $lv3 err +not grep $lv2 err +not grep $lv4 err + +lvs $lv1 $lv3 >err +grep $lv1 err +grep $lv3 err +not grep $lv2 err +not grep $lv4 err + +# should use env and fail to fine lv4 in vg1 +not lvs $lv4 >err +not grep $lv1 err +not grep $lv3 err +not grep $lv2 err +not grep $lv4 err + +lvs $vg2/$lv4 >err +not grep $lv1 err +not grep $lv3 err +not grep $lv2 err +grep $lv4 err + +lvs $vg2/$lv2 $vg2/$lv4 >err +not grep $lv1 err +not grep $lv3 err +grep $lv2 err +grep $lv4 err + +# should use env +lvchange -an $lv3 +lvremove $lv3 +not lvremove $lv4 + +lvs >err +grep $lv1 err +not grep $lv3 err +grep $lv2 err +grep $lv4 err + +# should use env +lvcreate -n $lv3 -l 2 +lvchange --addtag foo $lv3 +lvchange -an $lv3 + +# lvremove by tag should apply to all vgs, not env vg +lvchange --addtag foo $vg2/$lv4 +lvchange -an $vg2/$lv4 +lvremove @foo + +lvs >err +grep $lv1 err +not grep $lv3 err +grep $lv2 err +not grep $lv4 err + +vgremove -ff $vg1 $vg2 diff --git a/test/shell/vg-raid-takeover-1.sh b/test/shell/vg-raid-takeover-1.sh new file mode 100644 index 0000000..98e043a --- /dev/null +++ b/test/shell/vg-raid-takeover-1.sh @@ -0,0 +1,202 @@ +#!/usr/bin/env bash + +# Copyright (C) 2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test VG takeover with raid LVs' + +# test does not apply to lvmlockd +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_raid 1 9 0 || skip +aux prepare_devs ${PREPARE_DEVS-3} + +SIDFILE="etc/lvm_test.conf" +LVMLOCAL="etc/lvmlocal.conf" + +DFDIR="$LVM_SYSTEM_DIR/devices" +DF="$DFDIR/system.devices" + +print_lvmlocal() { + { echo "local {"; printf "%s\n" "$@"; echo "}"; } >"$LVMLOCAL" +} + +# Avoid system id validation in the devices file +# which gets in the way of the test switching the +# local system id. +clear_df_systemid() { + if [[ -f $DF ]]; then + sed -e "s|SYSTEMID=.||" "$DF" > tmpdf + cp tmpdf $DF + fi +} + +test_check_mount() { + pvs -o+missing + vgs -o+systemid,partial $vg + lvs -a -o+devices $vg + + mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" + diff pattern1 "$mount_dir/pattern1a" + diff pattern1 "$mount_dir/pattern1c" + umount "$mount_dir" + fsck -n "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv2" "$mount_dir" + diff pattern1 "$mount_dir/pattern1a" + diff pattern1 "$mount_dir/pattern1c" + umount "$mount_dir" + fsck -n "$DM_DEV_DIR/$vg/$lv2" +} + + +SID1=sidfoofile1 +SID2=sidfoofile2 +echo "$SID1" > "$SIDFILE" +clear_df_systemid +aux lvmconf "global/system_id_source = file" \ + "global/system_id_file = \"$SIDFILE\"" +vgcreate $vg "$dev1" "$dev2" "$dev3" +vgs -o+systemid,partial $vg +check vg_field $vg systemid "$SID1" + +lvcreate --type raid1 -L 8 -m1 -n $lv1 $vg "$dev1" "$dev2" +lvcreate --type raid1 -L 8 -m2 -n $lv2 $vg "$dev1" "$dev2" "$dev3" + +# give some time for raid init +aux wait_for_sync $vg $lv1 +aux wait_for_sync $vg $lv2 +lvs -a -o+devices $vg + +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1" +mkfs.ext4 "$DM_DEV_DIR/$vg/$lv2" + +dd if=/dev/urandom of=pattern1 bs=512K count=1 + +mount_dir="mnt_takeover" +mkdir -p "$mount_dir" + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" +dd if=/dev/zero of="$mount_dir/file1" bs=1M count=4 oflag=direct +cp pattern1 "$mount_dir/pattern1a" +cp pattern1 "$mount_dir/pattern1b" +umount "$mount_dir" + +mount "$DM_DEV_DIR/$vg/$lv2" "$mount_dir" +dd if=/dev/zero of="$mount_dir/file1" bs=1M count=4 oflag=direct +cp pattern1 "$mount_dir/pattern1a" +cp pattern1 "$mount_dir/pattern1b" +umount "$mount_dir" + +vgchange -an $vg + +# make the vg foreign +vgchange --yes --systemid "$SID2" $vg +not vgs $vg + +# make one dev missing +aux hide_dev "$dev1" + +# take over the vg, like cluster failover would do +vgchange --majoritypvs --config "local/extra_system_ids=[\"${SID2}\"]" --systemid "$SID1" $vg +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + +lvchange -ay --activationmode degraded $vg/$lv1 +lvchange -ay --activationmode degraded $vg/$lv2 + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" +dd of=/dev/null if="$mount_dir/file1" bs=1M count=4 +diff pattern1 "$mount_dir/pattern1a" +diff pattern1 "$mount_dir/pattern1b" +rm "$mount_dir/pattern1b" +rm "$mount_dir/file1" +cp pattern1 "$mount_dir/pattern1c" +umount "$mount_dir" + +mount "$DM_DEV_DIR/$vg/$lv2" "$mount_dir" +dd of=/dev/null if="$mount_dir/file1" bs=1M count=4 +diff pattern1 "$mount_dir/pattern1a" +diff pattern1 "$mount_dir/pattern1b" +rm "$mount_dir/pattern1b" +rm "$mount_dir/file1" +cp pattern1 "$mount_dir/pattern1c" +umount "$mount_dir" + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + + + +#---------------------------------------------------------- +# test will continue differently when var OTHER_TEST is set +#---------------------------------------------------------- +test -n "${CONTINUE_ELSEWHERE-}" && return 0 + + + +# fails because the missing dev is used by lvs +not vgreduce --removemissing $vg +# works because lvs can be used with missing leg +vgreduce --removemissing --mirrorsonly --force $vg + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + +# decline to repair (answer no) +lvconvert --repair $vg/$lv1 +# fails to find another disk to use to repair +not lvconvert -y --repair $vg/$lv2 + + +test_check_mount + + +aux unhide_dev "$dev1" + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + +vgck --updatemetadata $vg + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + +# remove the failed unused leg, leaving 2 legs +lvconvert -y -m-1 $vg/$lv2 +# remove the failed unused leg, leaving 1 leg +lvconvert -y -m-1 $vg/$lv1 + + +test_check_mount + + +vgextend $vg "$dev1" +lvconvert -y -m+1 $vg/$lv1 "$dev1" +lvconvert -y -m+1 $vg/$lv2 "$dev1" + +# let raid sync new leg +aux wait_for_sync $vg $lv1 +aux wait_for_sync $vg $lv2 + + +test_check_mount + + +vgchange -an $vg +vgremove -f $vg diff --git a/test/shell/vg-raid-takeover-2.sh b/test/shell/vg-raid-takeover-2.sh new file mode 100644 index 0000000..afc8db4 --- /dev/null +++ b/test/shell/vg-raid-takeover-2.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash + +# Copyright (C) 2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test VG takeover with raid LVs' + +CONTINUE_ELSEWHERE=y +PREPARE_DEVS=4 + +. ./shell/vg-raid-takeover-1.sh + +# fails because the missing dev is used by lvs +not vgreduce --removemissing $vg +# works because lvs can be used with missing leg +vgreduce --removemissing --mirrorsonly --force $vg + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + +# unhide_dev before lvconvert --repair +# i.e. the device reappears before the LVs are repaired + +aux unhide_dev "$dev1" + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + +# this repairs lv1 by using dev3 in place of dev1 +lvconvert -y --repair $vg/$lv1 + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + +# add a new disk to use for replacing dev1 in lv2 +vgextend $vg "$dev4" + +lvconvert -y --repair $vg/$lv2 + + +test_check_mount + + +# let the new legs sync +aux wait_for_sync $vg $lv1 +aux wait_for_sync $vg $lv2 + +vgck --updatemetadata $vg + + +test_check_mount + + +vgchange -an $vg +vgremove -f $vg diff --git a/test/shell/vg-raid-takeover-3.sh b/test/shell/vg-raid-takeover-3.sh new file mode 100644 index 0000000..0050c19 --- /dev/null +++ b/test/shell/vg-raid-takeover-3.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# Copyright (C) 2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test VG takeover with raid LVs' + +CONTINUE_ELSEWHERE=y + +. ./shell/vg-raid-takeover-1.sh + +#----------------------- +# replaces dev1 with dev3 +lvconvert -y --repair $vg/$lv1 + +# no other disk to replace dev1 so remove the leg, +# but that's not allowed until the missing disk is removed from the vg +not lvconvert -y -m-1 $vg/$lv2 +vgreduce --removemissing --mirrorsonly --force $vg + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg +lvconvert -y -m-1 $vg/$lv2 + + +test_check_mount + + +aux unhide_dev "$dev1" + +# put dev1 back into lv2, +# requires clearing outdated metadata and putting dev1 back in vg +vgck --updatemetadata $vg +pvs -o+missing +vgextend $vg "$dev1" +pvs -o+missing +lvconvert -y -m+1 $vg/$lv2 "$dev1" + + +test_check_mount + + +vgchange -an $vg +vgremove -f $vg diff --git a/test/shell/vg-raid-takeover-4.sh b/test/shell/vg-raid-takeover-4.sh new file mode 100644 index 0000000..8e29f2d --- /dev/null +++ b/test/shell/vg-raid-takeover-4.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Copyright (C) 2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Test VG takeover with raid LVs' + +CONTINUE_ELSEWHERE=y +PREPARE_DEVS=4 + +. ./shell/vg-raid-takeover-1.sh + +# unhide_dev +# the device reappears before the LVs are repaired +# and before the missing dev is removed from the vg + +aux unhide_dev "$dev1" + +pvs -o+missing +vgs -o+systemid,partial $vg +lvs -a -o+devices $vg + +vgextend --restoremissing $vg "$dev1" + + +test_check_mount + + +vgchange -an $vg +vgremove -f $vg diff --git a/test/shell/vgcfgbackup-lvm1.sh b/test/shell/vgcfgbackup-lvm1.sh new file mode 100644 index 0000000..9b81e28 --- /dev/null +++ b/test/shell/vgcfgbackup-lvm1.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_pvs 4 +get_devs + +if test -n "$LVM_TEST_LVM1" ; then + +pvcreate --metadatacopies 0 "$dev4" + +# No automatic backup +aux lvmconf "backup/backup = 0" + +# vgcfgbackup correctly stores metadata LVM1 with missing PVs + +pvcreate -M1 "${DEVICES[@]}" +vgcreate $SHARED -M1 "$vg" "${DEVICES[@]}" +lvcreate -l1 -n $lv1 $vg "$dev1" +pvremove -ff -y "$dev2" +not lvcreate -l1 -n $lv1 $vg "$dev3" +lvchange -an $vg +vgcfgbackup -f "backup.$$" $vg + +fi diff --git a/test/shell/vgcfgbackup-usage.sh b/test/shell/vgcfgbackup-usage.sh index c8245b0..801f9ce 100644 --- a/test/shell/vgcfgbackup-usage.sh +++ b/test/shell/vgcfgbackup-usage.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2008 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2008-2013 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 @@ -7,47 +8,71 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_pvs 4 +get_devs + +pvcreate --metadatacopies 0 "$dev4" + +# No automatic backup +aux lvmconf "backup/backup = 0" # vgcfgbackup handles similar VG names (bz458941) vg1=${PREFIX}vg00 vg2=${PREFIX}vg01 -vgcreate $vg1 "$dev1" -vgcreate $vg2 "$dev2" -vgcfgbackup -f $TESTDIR/bak-%s >out +vgcreate $SHARED $vg1 "$dev1" +vgcreate $SHARED $vg2 "$dev2" + +# Enforces system backup +test ! -e etc/backup/$vg1 +test ! -e etc/backup/$vg2 +vgcfgbackup +test -e etc/backup/$vg1 +test -e etc/backup/$vg2 + +aux lvmconf "backup/archive = 1" + +vgcfgbackup -f "bak-%s" >out grep "Volume group \"$vg1\" successfully backed up." out grep "Volume group \"$vg2\" successfully backed up." out +# increase seqno +lvcreate -an -Zn -l1 $vg1 + +invalid vgcfgrestore -f "bak-$vg1" $vg1-inv@lid +invalid vgcfgrestore -f "bak-$vg1" $vg1 $vg2 + +vgcfgrestore -l $vg1 | tee out +test "$(grep -c Description out)" -eq 2 + +vgcfgrestore -l -f "bak-$vg1" $vg1 + vgremove -ff $vg1 $vg2 # vgcfgbackup correctly stores metadata with missing PVs # and vgcfgrestore able to restore them when device reappears pv1_uuid=$(get pv_field "$dev1" pv_uuid) pv2_uuid=$(get pv_field "$dev2" pv_uuid) -vgcreate $vg $(cat DEVICES) +vgcreate $SHARED "$vg" "${DEVICES[@]}" 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" +vgcfgbackup -f "backup.$$" $vg +sed 's/flags = \[\"MISSING\"\]/flags = \[\]/' "backup.$$" > "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 $(cat DEVICES) -vgcreate -M1 -c n $vg $(cat DEVICES) -lvcreate -l1 -n $lv1 $vg "$dev1" -pvremove -ff -y "$dev2" -not lvcreate -l1 -n $lv1 $vg "$dev3" -vgcfgbackup -f "$(pwd)/backup.$$" $vg + +# Try to recover nonexisting vgname +not vgcfgrestore -f "backup.$$1" ${vg}_nonexistent +vgcfgrestore -f "backup.$$1" $vg +vgchange -an $vg +vgremove -f $vg + diff --git a/test/shell/vgchange-many.sh b/test/shell/vgchange-many.sh new file mode 100644 index 0000000..389877a --- /dev/null +++ b/test/shell/vgchange-many.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Check perfomance of activation and deactivation + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# Number of LVs to create +TEST_DEVS=1000 +# On low-memory boxes let's not stress too much +test "$(aux total_mem)" -gt 524288 || TEST_DEVS=256 + +aux prepare_pvs 1 400 +get_devs + +vgcreate $SHARED -s 128K "$vg" "${DEVICES[@]}" + +vgcfgbackup -f data $vg + +# Generate a lot of devices (size of 1 extent) +awk -v TEST_DEVS=$TEST_DEVS '/^\t\}/ { + printf("\t}\n\tlogical_volumes {\n"); + cnt=0; + for (i = 0; i < TEST_DEVS; i++) { + printf("\t\tlvol%06d {\n", i); + printf("\t\t\tid = \"%06d-1111-2222-3333-2222-1111-%06d\"\n", i, i); + print "\t\t\tstatus = [\"READ\", \"WRITE\", \"VISIBLE\"]"; + print "\t\t\tsegment_count = 1"; + print "\t\t\tsegment1 {"; + print "\t\t\t\tstart_extent = 0"; + print "\t\t\t\textent_count = 1"; + print "\t\t\t\ttype = \"striped\""; + print "\t\t\t\tstripe_count = 1"; + print "\t\t\t\tstripes = ["; + print "\t\t\t\t\t\"pv0\", " cnt++; + printf("\t\t\t\t]\n\t\t\t}\n\t\t}\n"); + } + } + {print} +' data >data_new + +vgcfgrestore -f data_new $vg + +# Activate and deactivate all of them +vgchange -ay $vg +vgchange -an $vg diff --git a/test/shell/vgchange-maxlv.sh b/test/shell/vgchange-maxlv.sh index 413fef9..626128e 100644 --- a/test/shell/vgchange-maxlv.sh +++ b/test/shell/vgchange-maxlv.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,24 +8,30 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_dmeventd aux prepare_pvs 3 +get_devs -vgcreate -c n -l 2 $vg $(cat DEVICES) -lvcreate -n one -l 1 $vg +vgcreate $SHARED -l 2 "$vg" "${DEVICES[@]}" +lvcreate -aey -n one -l 1 $vg lvcreate -n two -l 1 $vg not lvcreate -n three -l 1 $vg vgremove -ff $vg -vgcreate -c n -l 3 $vg $(cat DEVICES) -lvcreate -n one -l 1 $vg +vgcreate $SHARED -l 3 "$vg" "${DEVICES[@]}" +lvcreate -aey -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 + +vgremove -ff $vg diff --git a/test/shell/vgchange-partial.sh b/test/shell/vgchange-partial.sh index 5b21a40..854b8aa 100644 --- a/test/shell/vgchange-partial.sh +++ b/test/shell/vgchange-partial.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash + # Copyright (C) 2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,9 +8,12 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_vg 2 @@ -37,9 +41,6 @@ not vgchange -u $vg # physicalextentsize_ARG not vgchange -s 2M $vg -# clustered_ARG -not vgchange -c y $vg - # alloc_ARG not vgchange --alloc anywhere $vg @@ -50,3 +51,5 @@ not vgchange --vgmetadatacopies 2 $vg # Ensure that allowed args don't cause disallowed args to get through # not vgchange -p 10 --addtag foo $vg + +vgremove -ff $vg diff --git a/test/shell/vgchange-pvs-online.sh b/test/shell/vgchange-pvs-online.sh new file mode 100644 index 0000000..165e96d --- /dev/null +++ b/test/shell/vgchange-pvs-online.sh @@ -0,0 +1,232 @@ +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +RUNDIR="/run" +test -d "$RUNDIR" || RUNDIR="/var/run" +PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online" +VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online" +PVS_LOOKUP_DIR="$RUNDIR/lvm/pvs_lookup" + +_clear_online_files() { + # wait till udev is finished + aux udev_wait + rm -f "$PVS_ONLINE_DIR"/* + rm -f "$VGS_ONLINE_DIR"/* + rm -f "$PVS_LOOKUP_DIR"/* +} + +. lib/inittest + +aux prepare_devs 4 + +# skip rhel5 which doesn't seem to have /dev/mapper/LVMTESTpv1 +aux driver_at_least 4 15 || skip + +test "$DM_DEV_DIR" = "/dev" || skip "Only works with /dev access -> make check LVM_TEST_DEVDIR=/dev" + +DFDIR="$LVM_SYSTEM_DIR/devices" +mkdir -p "$DFDIR" || true +DF="$DFDIR/system.devices" + +# Because mapping devno to devname gets dm name from sysfs +aux lvmconf 'devices/scan = "/dev"' +bd1="$DM_DEV_DIR/mapper/$(basename $dev1)" +bd2="$DM_DEV_DIR/mapper/$(basename $dev2)" +bd3="$DM_DEV_DIR/mapper/$(basename $dev3)" +bd4="$DM_DEV_DIR/mapper/$(basename $dev4)" +aux extend_filter "a|$bd1|" "a|$bd2|" "a|$bd3|" "a|$bd4|" + +# Changing names will confuse df based on devname +if lvmdevices; then +rm -f "$DF" +touch "$DF" +lvmdevices --adddev "$bd1" +lvmdevices --adddev "$bd2" +lvmdevices --adddev "$bd3" +lvmdevices --adddev "$bd4" +cat "$DF" +fi + +# Using $bd instead of $dev because validation of pvid file content +# checks that the devname begins with /dev. + +# FIXME: test vgchange aay with pvs_online that includes devname in pvid file +# and the devices file entry uses devname with a stale name. + +vgcreate $vg1 "$bd1" "$bd2" +vgcreate $vg2 "$bd3" +pvcreate "$bd4" + +lvcreate -l1 -n $lv1 -an $vg1 +lvcreate -l1 -n $lv2 -an $vg1 +lvcreate -l1 -n $lv1 -an $vg2 + +# Expected use, with vg name and all online files exist for vgchange. + +_clear_online_files + +pvscan --cache "$bd1" +pvscan --cache "$bd2" +vgchange -aay --autoactivation event $vg1 +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg1/$lv2 lv_active "active" +check lv_field $vg2/$lv1 lv_active "" + +pvscan --cache "$bd3" +vgchange -aay --autoactivation event $vg2 +check lv_field $vg2/$lv1 lv_active "active" + +# Count io to check the pvs_online optimization +# is working to limit scanning. + +if which strace; then +vgchange -an +_clear_online_files + +pvscan --cache "$bd1" +pvscan --cache "$bd2" +strace -e io_submit vgchange -aay --autoactivation event $vg1 2>&1|tee trace.out +test "$(grep -c io_submit trace.out)" -eq 3 +rm trace.out + +strace -e io_submit pvscan --cache "$bd3" 2>&1|tee trace.out +test "$(grep -c io_submit trace.out)" -eq 1 +rm trace.out + +strace -e io_submit vgchange -aay --autoactivation event $vg2 2>&1|tee trace.out +test "$(grep -c io_submit trace.out)" -eq 2 +rm trace.out +fi + +# non-standard usage: no VG name arg, vgchange will only used pvs_online files + +vgchange -an +_clear_online_files + +vgchange -aay --autoactivation event +check lv_field $vg1/$lv1 lv_active "" +check lv_field $vg1/$lv2 lv_active "" +check lv_field $vg2/$lv1 lv_active "" + +pvscan --cache "$bd1" +vgchange -aay --autoactivation event +check lv_field $vg1/$lv1 lv_active "" +check lv_field $vg1/$lv2 lv_active "" +check lv_field $vg2/$lv1 lv_active "" + +pvscan --cache "$bd2" +vgchange -aay --autoactivation event +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg1/$lv2 lv_active "active" +check lv_field $vg2/$lv1 lv_active "" + +pvscan --cache "$bd3" +vgchange -aay --autoactivation event +check lv_field $vg2/$lv1 lv_active "active" + +# non-standard usage: include VG name arg, but missing or incomplete pvs_online files + +vgchange -an +_clear_online_files + +# all missing pvs_online, vgchange falls back to full label scan +vgchange -aay --autoactivation event $vg1 +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg1/$lv2 lv_active "active" + +vgchange -an +_clear_online_files + +# incomplete pvs_online, vgchange falls back to full label scan +pvscan --cache "$bd1" +vgchange -aay --autoactivation event $vg1 +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg1/$lv2 lv_active "active" + +vgchange -an +_clear_online_files + +# incomplete pvs_online, pvs_online from different vg, +# no pvs_online found for vg arg so vgchange falls back to full label scan + +pvscan --cache "$bd3" +vgchange -aay --autoactivation event $vg1 +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg1/$lv2 lv_active "active" +check lv_field $vg2/$lv1 lv_active "" + +vgchange -aay --autoactivation event $vg2 +check lv_field $vg2/$lv1 lv_active "active" + +vgchange -an +_clear_online_files + +# same tests but using command options matching udev rule + +pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd1" +pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd2" +vgchange -aay --autoactivation event $vg1 +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg1/$lv2 lv_active "active" +check lv_field $vg2/$lv1 lv_active "" + +pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd3" +vgchange -aay --autoactivation event $vg2 +check lv_field $vg2/$lv1 lv_active "active" + +vgchange -an $vg1 +vgchange -an $vg2 + +# with a full pvscan --cache + +_clear_online_files + +pvscan --cache +check lv_field $vg1/$lv1 lv_active "" +check lv_field $vg2/$lv1 lv_active "" +vgchange -aay --autoactivation event $vg1 +vgchange -aay --autoactivation event $vg2 +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg2/$lv1 lv_active "active" + +vgchange -an $vg1 +vgchange -an $vg2 + +# vgremove clears online files + +PVID1=$(pvs "$bd1" --noheading -o uuid | tr -d - | awk '{print $1}') +PVID2=$(pvs "$bd2" --noheading -o uuid | tr -d - | awk '{print $1}') +PVID3=$(pvs "$bd3" --noheading -o uuid | tr -d - | awk '{print $1}') + +_clear_online_files + +pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd1" +pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd2" +vgchange -aay --autoactivation event $vg1 +check lv_field $vg1/$lv1 lv_active "active" +check lv_field $vg1/$lv2 lv_active "active" +check lv_field $vg2/$lv1 lv_active "" + +pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output "$bd3" +vgchange -aay --autoactivation event $vg2 +check lv_field $vg2/$lv1 lv_active "active" + +ls "$RUNDIR/lvm/pvs_online/$PVID1" +ls "$RUNDIR/lvm/pvs_online/$PVID2" +ls "$RUNDIR/lvm/pvs_online/$PVID3" +ls "$RUNDIR/lvm/pvs_lookup/$vg1" +ls "$RUNDIR/lvm/vgs_online/$vg1" +ls "$RUNDIR/lvm/vgs_online/$vg2" + +vgremove -y $vg1 + +not ls "$RUNDIR/lvm/pvs_online/$PVID1" +not ls "$RUNDIR/lvm/pvs_online/$PVID2" +not ls "$RUNDIR/lvm/pvs_lookup/$vg1" +not ls "$RUNDIR/lvm/vgs_online/$vg1" + +vgremove -y $vg2 + +not ls "$RUNDIR/lvm/pvs_online/$PVID3" +not ls "$RUNDIR/lvm/vgs_online/$vg2" + diff --git a/test/shell/vgchange-sysinit.sh b/test/shell/vgchange-sysinit.sh index d7a166c..5740add 100644 --- a/test/shell/vgchange-sysinit.sh +++ b/test/shell/vgchange-sysinit.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,18 +8,22 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_CLVMD=1 +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest which mkfs.ext3 || skip aux prepare_pvs 2 8 -test -e LOCAL_CLVMD && skip var_lock="$DM_DEV_DIR/$vg1/$lv1" # keep in sync with aux configured lockingdir mount_dir="var/lock/lvm" +mkdir -p $mount_dir +aux lvmconf "global/locking_dir = \"$TESTDIR/$mount_dir\"" cleanup_mounted_and_teardown() { @@ -26,8 +31,8 @@ cleanup_mounted_and_teardown() aux teardown } -vgcreate -c n $vg1 "$dev1" -vgcreate -c n $vg2 "$dev2" +vgcreate $SHARED $vg1 "$dev1" +vgcreate $SHARED $vg2 "$dev2" lvcreate -l 1 -n $lv2 $vg2 vgchange -an $vg2 @@ -49,3 +54,13 @@ vgchange --sysinit -an $vg2 test ! -b "$DM_DEV_DIR/$vg2/$lv2" vgchange --ignorelockingfailure -ay $vg2 + +if test -n "$LVM_TEST_LVMLOCKD"; then +vgremove --config 'global{locking_type=0}' -ff $vg2 +else +# TODO maybe also support --ignorelockingfailure ?? +vgremove --config 'global{locking_type=0}' -ff $vg2 +fi + +umount "$mount_dir" || true +vgremove -ff $vg1 diff --git a/test/shell/vgchange-usage.sh b/test/shell/vgchange-usage.sh index a7bd488..f6fc842 100644 --- a/test/shell/vgchange-usage.sh +++ b/test/shell/vgchange-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,38 +8,90 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA test_description='Exercise some vgchange diagnostics' -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_pvs 4 -aux prepare_pvs 3 pvcreate --metadatacopies 0 "$dev1" -vgcreate $vg $(cat DEVICES) +vgcreate $SHARED -s 4M $vg "$dev1" "$dev2" "$dev3" + +# cannot change anything in exported vg +vgexport $vg +fail vgchange -ay $vg +fail vgchange -p 8 $vg +fail vgchange -x n $vg +fail vgchange --addtag tag $vg +fail vgchange --deltag tag $vg +fail vgchange -s 4k $vg +fail vgchange --uuid $vg +fail vgchange --alloc anywhere $vg +vgimport $vg + +# unsupported combinations of options... +invalid vgchange --ignorelockingfailure --uuid $vg +invalid vgchange --sysinit --alloc normal $vg +invalid vgchange --sysinit --poll y $vg +invalid vgchange -an --poll y $vg +invalid vgchange -an --monitor y $vg +invalid vgchange -ay --refresh $vg vgdisplay $vg # vgchange -p MaxPhysicalVolumes (bz202232) -aux check vg_field $vg max_pv 0 +check vg_field $vg max_pv 0 vgchange -p 128 $vg -aux check vg_field $vg max_pv 128 +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 +check vg_field $vg max_pv 128 + +# try some numbers around MAX limit (uint32) +vgchange -p 4294967295 $vg +invalid vgchange -p 4294967296 $vg +invalid vgchange -p 18446744073709551615 $vg +invalid vgchange -p 18446744073709551616 $vg +check vg_field $vg max_pv 4294967295 # vgchange -l MaxLogicalVolumes -aux check vg_field $vg max_lv 0 +check vg_field $vg max_lv 0 +invalid vgchange -l -128 $vg +vgchange -l 4294967295 $vg +invalid vgchange -l 4294967296 $vg +invalid vgchange -l 18446744073709551615 $vg +invalid vgchange -l 18446744073709551616 $vg +check vg_field $vg max_lv 4294967295 vgchange -l 128 $vg -aux check vg_field $vg max_lv 128 +check vg_field $vg max_lv 128 +# vgchange -s lvcreate -l4 -n $lv1 $vg lvcreate -l4 -n $lv2 $vg +SIZELV2=$(get lv_field $vg/$lv2 size) +check lv_field $vg/$lv2 seg_size_pe "4" +vgchange -s 4K $vg +check vg_field $vg vg_extent_size "4.00k" +check lv_field $vg/$lv2 size "$SIZELV2" +check lv_field $vg/$lv2 seg_size_pe "4096" + 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 +check vg_field $vg max_lv 128 +# check non-resizebility +fail vgchange -x y $vg +check vg_attr_bit resizeable $vg "z" +vgchange -x n $vg +check vg_attr_bit resizeable $vg "-" +fail vgchange -x n $vg +fail vgextend $vg "$dev4" +vgremove -ff $vg diff --git a/test/shell/vgck.sh b/test/shell/vgck.sh new file mode 100644 index 0000000..b6c2cba --- /dev/null +++ b/test/shell/vgck.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 3 +lvcreate -n blabla -L 1 $vg + +dd if=/dev/urandom bs=512 seek=2 count=32 of="$dev2" + +# TODO: aux lvmconf "global/locking_type = 4" + +vgscan 2>&1 | tee vgscan.out || true + +grep "checksum" vgscan.out + +dd if=/dev/urandom bs=512 seek=2 count=32 of="$dev2" + +vgck $vg 2>&1 | tee vgck.out || true +grep "checksum" vgck.out + +vgremove -ff $vg diff --git a/test/shell/vgcreate-many-pvs.sh b/test/shell/vgcreate-many-pvs.sh new file mode 100644 index 0000000..c68afeb --- /dev/null +++ b/test/shell/vgcreate-many-pvs.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +# +# Test to exercise larger number of PVs in a VG +# Related to https://bugzilla.redhat.com/show_bug.cgi?id=736027 +# +# Original measured times of the whole test case before +# and with the acceleration patch from my bare metal hw +# (Lenovo T61, 2.2GHz, 4G RAM, rawhide 2015-03-06 with ndebug kernel): +# +# export LVM_TEST_PVS=300 +# +# make check_local ~52sec (U:29s, S:13s) +# +# With patch from 2015-03-06: +# +# make check_local ~30sec (U:10s, S:12s) +# + +# TODO: extend test suite to monitor performance and report regressions... + +# Use just 100 to get 'decent' speed on slow boxes +LVM_TEST_PVS=${LVM_TEST_PVS:-100} + +#aux prepare_devs $LVM_TEST_PVS 8 +#vgcreate $SHARED $vg $(< DEVICES) + +# prepare_vg is now directly using steps above +aux prepare_vg $LVM_TEST_PVS + +# Check we have decent speed with typical commands +vgs + +lvs + +pvs + +lvcreate -l1 -n $lv1 $vg + +lvremove -f $vg/$lv1 + +vgremove -ff $vg + +# +# TODO Turn this into another test case: +# +#for i in $(seq 1 $LVM_TEST_PVS); do +# vgcreate $SHARED ${vg}$i "$DM_DEV_DIR/mapper/${PREFIX}pv$i" +#done diff --git a/test/shell/vgcreate-usage.sh b/test/shell/vgcreate-usage.sh index db80f0f..1959313 100644 --- a/test/shell/vgcreate-usage.sh +++ b/test/shell/vgcreate-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,11 +8,13 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA test_description='Exercise some vgcreate diagnostics' -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_devs 3 pvcreate "$dev1" "$dev2" @@ -19,89 +22,90 @@ pvcreate --metadatacopies 0 "$dev3" vg=${PREFIX}vg -#COMM 'vgcreate accepts 8.00m physicalextentsize for VG' -vgcreate -c n $vg --physicalextentsize 8.00m "$dev1" "$dev2" +#COMM 'vgcreate $SHARED accepts 8.00m physicalextentsize for VG' +vgcreate $SHARED $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" +#COMM 'vgcreate $SHARED accepts smaller (128) maxlogicalvolumes for VG' +vgcreate $SHARED $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" +#COMM 'vgcreate $SHARED accepts smaller (128) maxphysicalvolumes for VG' +vgcreate $SHARED $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 +#COMM 'vgcreate $SHARED rejects a zero physical extent size' +not vgcreate $SHARED --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 +#COMM 'vgcreate $SHARED rejects "inherit" allocation policy' +not vgcreate $SHARED --alloc inherit $vg "$dev1" "$dev2" 2>err grep "Volume Group allocation policy cannot inherit from anything" err -#COMM 'vgcreate rejects vgname "."' +#COMM 'vgcreate $SHARED rejects vgname "."' vginvalid=.; -not vgcreate -c n $vginvalid "$dev1" "$dev2" 2>err +not vgcreate $SHARED $vginvalid "$dev1" "$dev2" 2>err grep "New volume group name \"$vginvalid\" is invalid" err -#COMM 'vgcreate rejects vgname greater than 128 characters' +#COMM 'vgcreate $SHARED rejects vgname greater than 128 characters' vginvalid=thisnameisridiculouslylongtotestvalidationcodecheckingmaximumsizethisiswhathappenswhenprogrammersgetboredandorarenotcreativedonttrythisathome -not vgcreate -c n $vginvalid "$dev1" "$dev2" 2>err +not vgcreate $SHARED $vginvalid "$dev1" "$dev2" 2>err grep "New volume group name \"$vginvalid\" is invalid" err -#COMM 'vgcreate rejects already existing vgname "/tmp/$vg"' +#COMM 'vgcreate $SHARED rejects already existing vgname "/tmp/$vg"' #touch /tmp/$vg -#not vgcreate $vg "$dev1" "$dev2" 2>err +#not vgcreate $SHARED $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" +#COMM "vgcreate $SHARED rejects repeated invocation (run 2 times) (bz178216)" +vgcreate $SHARED $vg "$dev1" "$dev2" +not vgcreate $SHARED $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" +#COMM "vgcreate $SHARED fails when the only pv has --metadatacopies 0" +not vgcreate $SHARED $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 +not vgcreate $SHARED --physicalextentsize 0k $vg "$dev1" "$dev2" +vgcreate $SHARED --physicalextentsize 4k $vg "$dev1" "$dev2" +check vg_field $vg vg_extent_size 4.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! +not vgcreate $SHARED --physicalextentsize 7K $vg "$dev1" "$dev2" +not vgcreate $SHARED --physicalextentsize 1024t $vg "$dev1" "$dev2" +#not vgcreate $SHARED --physicalextentsize 1T $vg "$dev1" "$dev2" +# FIXME: vgcreate $SHARED allows physicalextentsize larger than pv size! # Test default max_lv, max_pv, extent_size, alloc_policy, clustered -vgcreate -c n $vg "$dev1" "$dev2" +vgcreate $SHARED $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-" +ATTRS="wz--n-" +test -e LOCAL_CLVMD && ATTRS="wz--nc" +if test -n "$LVM_TEST_LVMLOCKD"; then +ATTRS="wz--ns" +fi +check vg_field $vg vg_attr $ATTRS vgremove -ff $vg -# Implicit pvcreate tests, test pvcreate options on vgcreate +# Implicit pvcreate tests, test pvcreate options on vgcreate $SHARED # --force, --yes, --metadata{size|copies|type}, --zero # --dataalignment[offset] pvremove "$dev1" "$dev2" -vgcreate -c n --force --yes --zero y $vg "$dev1" "$dev2" +vgcreate $SHARED --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" +# vgcreate $SHARED (lvm2) succeeds writing LVM label at sector $i + vgcreate $SHARED --labelsector $i $vg "$dev1" dd if="$dev1" bs=512 skip=$i count=1 2>/dev/null | strings | grep LABELONE >/dev/null vgremove -f $vg pvremove -f "$dev1" @@ -110,14 +114,14 @@ done # pvmetadatacopies for i in 1 2 do - vgcreate -c n --pvmetadatacopies $i $vg "$dev1" + vgcreate $SHARED --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" +not vgcreate $SHARED --pvmetadatacopies 0 $vg "$dev1" pvcreate --metadatacopies 1 "$dev2" -vgcreate -c n --pvmetadatacopies 0 $vg "$dev1" "$dev2" +vgcreate $SHARED --pvmetadatacopies 0 $vg "$dev1" "$dev2" check pv_field "$dev1" pv_mda_count 0 check pv_field "$dev2" pv_mda_count 1 vgremove -f $vg @@ -125,7 +129,7 @@ pvremove -f "$dev1" # metadatasize, dataalignment, dataalignmentoffset #COMM 'pvcreate sets data offset next to mda area' -vgcreate -c n --metadatasize 100k --dataalignment 100k $vg "$dev1" +vgcreate $SHARED --metadatasize 100k --dataalignment 100k $vg "$dev1" check pv_field "$dev1" pe_start 200.00k vgremove -f $vg pvremove -f "$dev1" @@ -133,31 +137,36 @@ pvremove -f "$dev1" # data area is aligned to 1M by default, # data area start is shifted by the specified alignment_offset pv_align=1052160 # 1048576 + (7*512) -vgcreate -c n --metadatasize 128k --dataalignmentoffset 7s $vg "$dev1" +vgcreate $SHARED --metadatasize 128k --dataalignmentoffset 7s $vg "$dev1" check pv_field "$dev1" pe_start ${pv_align}B --units b vgremove -f $vg pvremove -f "$dev1" +if test -n "$LVM_TEST_LVM1" ; then +mdatypes='1 2' +else +mdatypes='2' +fi + # metadatatype -for i in 1 2 +for i in $mdatypes do - vgcreate -c n -M $i $vg "$dev1" + vgcreate $SHARED -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" +# vgcreate $SHARED fails if pv belongs to existing vg +vgcreate $SHARED $vg1 "$dev1" "$dev2" +not vgcreate $SHARED $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" +vgcreate $SHARED $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/shell/vgextend-restoremissing.sh b/test/shell/vgextend-restoremissing.sh index fae68e4..afbe5ba 100644 --- a/test/shell/vgextend-restoremissing.sh +++ b/test/shell/vgextend-restoremissing.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,24 +8,51 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_vg 3 -lvcreate -m 1 -l 1 -n mirror $vg -lvchange -a n $vg/mirror +lvcreate -an -Zn --type mirror -m 1 -l 1 -n mirror $vg lvcreate -l 1 -n lv1 $vg "$dev1" +# vgextend require vgname +invalid vgextend +# --metadatacopies => use --pvmetadatacopies +invalid vgextend --metadatacopies 3 $vg "$dev1" 2>&1 | tee out +#grep -- "use --pvmetadatacopies" out +grep -E -- "unrecognized option.*--metadatacopies" out + +# VG name should exist +fail vgextend --restoremissing $vg-invalid "$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 aux disable_dev "$dev1" lvremove $vg/mirror +# try restore the still existing device +fail vgextend --restore $vg "$dev1" aux 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 +not lvcreate -aey --type mirror -m 1 -l 1 -n mirror $vg # write operations fail +# try restore the non-missing device +fail vgextend --restore $vg "$dev2" +# try restore the non-existing device +fail vgextend --restore $vg "$dev2-invalid" +# restore the missing device +vgextend --restore $vg "$dev1" + +vgreduce $vg "$dev3" +vgchange --metadatacopies 1 $vg +# 'n' failing to change volume group +fail vgextend --metadataignore y --pvmetadatacopies 2 $vg "$dev3" +vgextend --yes --metadataignore y --pvmetadatacopies 2 $vg "$dev3" vgck $vg -lvcreate -m 1 -l 1 -n mirror $vg +lvcreate -an -Zn --type mirror -m 1 -l 1 -n mirror $vg + +vgremove -ff $vg diff --git a/test/shell/vgextend-usage.sh b/test/shell/vgextend-usage.sh index 0e347c3..3d5adfd 100644 --- a/test/shell/vgextend-usage.sh +++ b/test/shell/vgextend-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,45 +8,54 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # Exercise various vgextend commands # -. lib/test + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_devs 5 -for mdatype in 1 2 +if test -n "$LVM_TEST_LVM1" ; then +mdatypes='1 2' +else +mdatypes='2' +fi + +for mdatype in $mdatypes do # Explicit pvcreate pvcreate -M$mdatype "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" -vgcreate -M$mdatype $vg1 "$dev1" "$dev2" +vgcreate $SHARED -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" +vgcreate $SHARED -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 +# Implicit pvcreate tests, test pvcreate options on vgcreate $SHARED # --force, --yes, --metadata{size|copies|type}, --zero # --dataalignment[offset] -vgcreate $vg "$dev2" +vgcreate $SHARED $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 +# vgcreate $SHARED (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 LABELONE >/dev/null vgreduce $vg "$dev1" @@ -77,15 +87,15 @@ vgremove -f $vg pvremove -f "$dev1" # vgextend fails if pv belongs to existing vg -vgcreate $vg1 "$dev1" "$dev3" -vgcreate $vg2 "$dev2" +vgcreate $SHARED $vg1 "$dev1" "$dev3" +vgcreate $SHARED $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" +vgcreate $SHARED $vg1 "$dev1" "$dev2" vgchange --resizeable n $vg1 not vgextend $vg1 "$dev3" vgremove -f $vg1 @@ -93,7 +103,7 @@ pvremove -f "$dev1" "$dev2" # all PVs exist in the VG after extended pvcreate "$dev1" -vgcreate $vg1 "$dev2" +vgcreate $SHARED $vg1 "$dev2" vgextend $vg1 "$dev1" "$dev3" check pv_field "$dev1" vg_name $vg1 check pv_field "$dev2" vg_name $vg1 @@ -105,7 +115,7 @@ 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" + vgcreate $SHARED $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 @@ -117,11 +127,11 @@ for ignore in y n; do 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)) + 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)) + check vg_field $vg vg_mda_used_count $(( mdacp * 2 + 1 )) fi check vg_field $vg vg_mda_copies unmanaged vgremove $vg diff --git a/test/shell/vgimportclone.sh b/test/shell/vgimportclone.sh index 9b1c121..13924c3 100644 --- a/test/shell/vgimportclone.sh +++ b/test/shell/vgimportclone.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2010-2014 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 @@ -7,33 +8,140 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest -aux prepare_devs 2 +aux prepare_devs 3 -vgcreate -c n --metadatasize 128k $vg1 "$dev1" +vgcreate $SHARED --metadatasize 128k $vg1 "$dev1" lvcreate -l100%FREE -n $lv1 $vg1 +# Test plain vgexport vgimport tools + +# Argument is needed +invalid vgexport +invalid vgimport +# Cannot combine -a and VG name +invalid vgexport -a $vg +invalid vgimport -a $vg1 +# Cannot export unknonw VG +fail vgexport ${vg1}-non +fail vgimport ${vg1}-non +# Cannot export VG with active volumes +fail vgexport $vg1 + +vgchange -an $vg1 +vgexport $vg1 +# Already exported +fail vgexport $vg1 + +vgimport $vg1 +# Already imported +fail vgimport $vg1 +vgchange -ay $vg1 + +# Since the devices file is using devnames as ids, +# it will not automatically know that dev2 is a +# duplicate after the dd, so we need to remove dev2 +# from df, then add it again after the dd. +if lvmdevices; then + lvmdevices --deldev "$dev2" +fi + # Clone the LUN dd if="$dev1" of="$dev2" bs=256K count=1 -aux notify_lvmetad "$dev2" + +# Requires -y to confirm prompt about adding +# a duplicate pvid. +if lvmdevices; then + lvmdevices -y --adddev "$dev2" +fi # Verify pvs works on each device to give us vgname +aux hide_dev "$dev2" check pv_field "$dev1" vg_name $vg1 +aux unhide_dev "$dev2" + +aux hide_dev "$dev1" check pv_field "$dev2" vg_name $vg1 +aux unhide_dev "$dev1" + +lvmdevices || true +pvs -a -o+uuid # Import the cloned PV to a new VG vgimportclone --basevgname $vg2 "$dev2" -# We need to re-scan *both* $dev1 and $dev2 since a PV, as far as lvmetad is -# concerned, can only live on a single device. With the last pvscan, we told it -# that PV from $dev1 now lives on $dev2, but in fact this is not true anymore, -# since we wrote a different PV over $dev2. -aux notify_lvmetad "$dev2" -aux notify_lvmetad "$dev1" +lvmdevices || true +pvs -a -o+uuid +vgs # Verify we can activate / deactivate the LV from both VGs lvchange -ay $vg1/$lv1 $vg2/$lv1 vgchange -an $vg1 $vg2 + +vgremove -ff $vg1 $vg2 + +pvremove "$dev1" +pvremove "$dev2" + +# Test vgimportclone with incomplete list of devs, and with nomda PV. +vgcreate $SHARED --vgmetadatacopies 2 $vg1 "$dev1" "$dev2" "$dev3" +lvcreate -l1 -an $vg1 +not vgimportclone -n newvgname "$dev1" +not vgimportclone -n newvgname "$dev2" +not vgimportclone -n newvgname "$dev3" +not vgimportclone -n newvgname "$dev1" "$dev2" +not vgimportclone -n newvgname "$dev1" "$dev3" +not vgimportclone -n newvgname "$dev2" "$dev3" +vgimportclone -n ${vg1}new "$dev1" "$dev2" "$dev3" +lvs ${vg1}new +vgremove -y ${vg1}new +pvremove "$dev1" +pvremove "$dev2" +pvremove "$dev3" + +# Test importing a non-duplicate pv using the existing vg name +vgcreate $vg1 "$dev1" +vgimportclone -n $vg1 "$dev1" +vgs ${vg1}1 +not vgs $vg1 +vgremove ${vg1}1 + +# Test importing a non-duplicate pv using the existing vg name +# Another existing VG is using the initial generated vgname with +# the "1" suffix, so "2" is used. +vgcreate $vg1 "$dev1" +vgcreate ${vg1}1 "$dev2" +vgimportclone -n $vg1 "$dev1" +vgs ${vg1}1 +vgs ${vg1}2 +vgremove ${vg1}1 +vgremove ${vg1}2 +pvremove "$dev1" +pvremove "$dev2" + +# Verify that if we provide the -n|--basevgname, +# the number suffix is not added unnecessarily. +vgcreate $SHARED --metadatasize 128k A${vg1}B "$dev1" + +# vg1B is not the same as Avg1B - we don't need number suffix +dd if="$dev1" of="$dev2" bs=256K count=1 +vgimportclone -n ${vg1}B "$dev2" +check pv_field "$dev2" vg_name ${vg1}B + +# Avg1 is not the same as Avg1B - we don't need number suffix +dd if="$dev1" of="$dev2" bs=256K count=1 +vgimportclone -n A${vg1} "$dev2" +check pv_field "$dev2" vg_name A${vg1} + +# Avg1B is the same as Avg1B - we need to add the number suffix +dd if="$dev1" of="$dev2" bs=256K count=1 +vgimportclone -n A${vg1}B "$dev2" +aux vgs +check pv_field "$dev2" vg_name A${vg1}B1 + +vgremove -ff A${vg1}B A${vg1}B1 diff --git a/test/shell/vgimportdevices.sh b/test/shell/vgimportdevices.sh new file mode 100644 index 0000000..384ea44 --- /dev/null +++ b/test/shell/vgimportdevices.sh @@ -0,0 +1,309 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='vgimportdevices' + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_devs 5 + +DFDIR="$LVM_SYSTEM_DIR/devices" +mkdir "$DFDIR" || true +DF="$DFDIR/system.devices" + +aux lvmconf 'devices/use_devicesfile = 1' + +not ls "$DF" +pvcreate "$dev1" +ls "$DF" +grep "$dev1" "$DF" +rm -f "$DF" +dd if=/dev/zero of="$dev1" bs=1M count=1 + +# +# vgimportdevices -a with no prev df +# + +# no devs found +not vgimportdevices -a +not ls "$DF" + +# one orphan pv, no vgs +pvcreate "$dev1" +rm -f "$DF" +not vgimportdevices -a +not ls "$DF" + +# one complete vg +vgcreate $vg1 "$dev1" +rm -f "$DF" +vgimportdevices -a +ls "$DF" +grep "$dev1" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +rm -f "$DF" + +# two complete vgs +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +rm -f "$DF" +vgimportdevices -a +ls "$DF" +grep "$dev1" "$DF" +grep "$dev2" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +rm -f "$DF" + +# one incomplete vg +vgcreate $vg1 "$dev1" "$dev2" +lvcreate -l1 -an $vg1 +rm -f "$DF" +dd if=/dev/zero of="$dev1" bs=1M count=1 +not vgimportdevices -a +not ls "$DF" +vgs $vg1 +pvs "$dev2" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +rm -f "$DF" + +# three complete, one incomplete vg +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +vgcreate $vg3 "$dev3" +vgcreate $vg4 "$dev4" "$dev5" +rm -f "$DF" +dd if=/dev/zero of="$dev5" bs=1M count=1 +vgimportdevices -a +ls "$DF" +grep "$dev1" "$DF" +grep "$dev2" "$DF" +grep "$dev3" "$DF" +not grep "$dev4" "$DF" +not grep "$dev5" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +dd if=/dev/zero of="$dev3" bs=1M count=1 +dd if=/dev/zero of="$dev4" bs=1M count=1 +rm -f "$DF" + + +# +# vgimportdevices -a with existing df +# + +# no devs found +vgcreate $vg1 "$dev1" +grep "$dev1" "$DF" +dd if=/dev/zero of="$dev1" bs=1M count=1 +not vgimportdevices -a +ls "$DF" + +# one complete vg +vgcreate $vg1 "$dev1" +vgimportdevices -a +grep "$dev1" "$DF" +vgcreate --devicesfile "" $vg2 "$dev2" +not grep "$dev2" "$DF" +vgimportdevices -a +grep "$dev1" "$DF" +grep "$dev2" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +rm -f "$DF" + +# two complete vgs +vgcreate --devicesfile "" $vg1 "$dev1" +vgcreate --devicesfile "" $vg2 "$dev2" +rm -f "$DF" +vgimportdevices -a +ls "$DF" +grep "$dev1" "$DF" +grep "$dev2" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +rm -f "$DF" + +# one incomplete vg +vgcreate $vg1 "$dev1" +vgimportdevices -a +grep "$dev1" "$DF" +dd if=/dev/zero of="$dev1" bs=1M count=1 +vgcreate --devicesfile "" $vg2 "$dev2" "$dev3" +not grep "$dev2" "$DF" +not grep "$dev3" "$DF" +dd if=/dev/zero of="$dev2" bs=1M count=1 +not vgimportdevices -a +ls "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +dd if=/dev/zero of="$dev3" bs=1M count=1 +rm -f "$DF" + +# import the same vg again +vgcreate --devicesfile "" $vg1 "$dev1" +not ls "$DF" +vgimportdevices -a +ls "$DF" +grep "$dev1" "$DF" +vgimportdevices -a +ls "$DF" +grep "$dev1" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +rm -f "$DF" + +# import a series of vgs +vgcreate --devicesfile "" $vg1 "$dev1" +vgimportdevices -a +grep "$dev1" "$DF" +vgcreate --devicesfile "" $vg2 "$dev2" +vgimportdevices -a +grep "$dev1" "$DF" +grep "$dev2" "$DF" +vgcreate --devicesfile "" $vg3 "$dev3" +vgimportdevices -a +grep "$dev1" "$DF" +grep "$dev2" "$DF" +grep "$dev3" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +dd if=/dev/zero of="$dev3" bs=1M count=1 +rm -f "$DF" + +# +# vgimportdevices vg with no prev df +# + +# no devs found +not vgimportdevices $vg1 +not ls "$DF" + +# one complete vg +vgcreate $vg1 "$dev1" +rm -f "$DF" +vgimportdevices $vg1 +ls "$DF" +grep "$dev1" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +rm -f "$DF" + +# two complete vgs +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +rm -f "$DF" +vgimportdevices $vg1 +ls "$DF" +grep "$dev1" "$DF" +vgimportdevices $vg2 +ls "$DF" +grep "$dev2" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +rm -f "$DF" + +# one incomplete vg +vgcreate $vg1 "$dev1" "$dev2" +lvcreate -l1 -an $vg1 +rm -f "$DF" +dd if=/dev/zero of="$dev1" bs=1M count=1 +not vgimportdevices $vg1 +not ls "$DF" +vgs $vg1 +pvs "$dev2" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +rm -f "$DF" + +# three complete, one incomplete vg +vgcreate $vg1 "$dev1" +vgcreate $vg2 "$dev2" +vgcreate $vg3 "$dev3" +vgcreate $vg4 "$dev4" "$dev5" +rm -f "$DF" +dd if=/dev/zero of="$dev5" bs=1M count=1 +not vgimportdevices $vg4 +not ls "$DF" +vgimportdevices $vg3 +ls "$DF" +grep "$dev3" "$DF" +not grep "$dev1" "$DF" +not grep "$dev2" "$DF" +not grep "$dev4" "$DF" +not grep "$dev5" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +dd if=/dev/zero of="$dev3" bs=1M count=1 +dd if=/dev/zero of="$dev4" bs=1M count=1 +rm -f "$DF" + +# +# vgimportdevices vg with existing df +# + +# vg not found +vgcreate $vg1 "$dev1" +vgimportdevices -a +grep "$dev1" "$DF" +not vgimportdevices $vg2 +grep "$dev1" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +rm -f "$DF" + +# vg incomplete +vgcreate $vg1 "$dev1" +vgimportdevices -a +grep "$dev1" "$DF" +vgcreate --devicesfile "" $vg2 "$dev2" "$dev3" +dd if=/dev/zero of="$dev2" bs=1M count=1 +not vgimportdevices $vg2 +grep "$dev1" "$DF" +not grep "$dev2" "$DF" +not grep "$dev3" "$DF" + +# reset +dd if=/dev/zero of="$dev1" bs=1M count=1 +dd if=/dev/zero of="$dev2" bs=1M count=1 +dd if=/dev/zero of="$dev3" bs=1M count=1 +dd if=/dev/zero of="$dev4" bs=1M count=1 +rm -f "$DF" + diff --git a/test/shell/vgmerge-operation.sh b/test/shell/vgmerge-operation.sh index bdd5000..0bf517d 100644 --- a/test/shell/vgmerge-operation.sh +++ b/test/shell/vgmerge-operation.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2007-2012 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,17 +8,19 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA test_description='Test vgmerge operation' +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest 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" +vgcreate $vg1 "$dev1" "$dev2" +vgcreate $vg2 "$dev3" "$dev4" lvcreate -l 4 -n $lv1 $vg1 "$dev1" vgchange -an $vg1 check pvlv_counts $vg1 2 1 0 @@ -27,8 +30,8 @@ check 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" +vgcreate $vg1 "$dev1" "$dev2" +vgcreate $vg2 "$dev3" "$dev4" lvcreate -l 4 -n $lv1 $vg1 lvcreate -l 4 -n $lv2 $vg2 vgchange -an $vg1 @@ -40,9 +43,9 @@ check 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 +vgcreate $vg1 "$dev1" "$dev2" +vgcreate $vg2 "$dev3" "$dev4" +lvcreate -aey -l 16 -n $lv1 $vg1 lvcreate -l 4 -s -n $lv2 $vg1/$lv1 vgchange -an $vg1 check pvlv_counts $vg1 2 2 1 @@ -53,9 +56,9 @@ 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 +vgcreate $vg1 "$dev1" "$dev2" "$dev3" +vgcreate $vg2 "$dev4" +lvcreate -aey -l 4 -n $lv1 --type mirror -m1 $vg1 vgchange -an $vg1 check pvlv_counts $vg1 3 1 0 check pvlv_counts $vg2 1 0 0 @@ -65,8 +68,8 @@ lvremove -f $vg2/$lv1 vgremove -f $vg2 # 'vgmerge rejects LV name collision' -vgcreate -c n $vg1 "$dev1" "$dev2" -vgcreate -c n $vg2 "$dev3" "$dev4" +vgcreate $vg1 "$dev1" "$dev2" +vgcreate $vg2 "$dev3" "$dev4" lvcreate -l 4 -n $lv1 $vg1 lvcreate -l 4 -n $lv1 $vg2 vgchange -an $vg1 @@ -77,3 +80,45 @@ grep "Duplicate logical volume name \"$lv1\" in \"$vg2\" and \"$vg1" err check pvlv_counts $vg1 2 1 0 check pvlv_counts $vg2 2 1 0 vgremove -f $vg1 $vg2 + + +# 'vgmerge' handle pmspare for merged VG +if aux have_thin 1 5 0; then + +# With disabled pmspare nothing is created +vgcreate $vg1 "$dev1" "$dev2" +vgcreate $vg2 "$dev3" "$dev4" +lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M --poolmetadataspare n +lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M --poolmetadataspare n +vgchange -an $vg1 $vg2 + +vgmerge --poolmetadataspare n $vg1 $vg2 +check lv_not_exists $vg/lvol0_pmspare +vgremove -ff $vg1 + + +# With pmspare handling there are one created +vgcreate $vg1 "$dev1" "$dev2" +vgcreate $vg2 "$dev3" "$dev4" +lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M --poolmetadataspare n +lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M --poolmetadataspare n +vgchange -an $vg1 $vg2 + +vgmerge $vg1 $vg2 +check lv_field $vg1/lvol0_pmspare size "8.00m" +vgremove -ff $vg1 + + +# When merged, bigger pmspare is preserved +vgcreate $vg1 "$dev1" "$dev2" +vgcreate $vg2 "$dev3" "$dev4" +lvcreate -T -L8M $vg1/pool1 --poolmetadatasize 8M +lvcreate -T -L8M $vg2/pool2 --poolmetadatasize 4M +vgchange -an $vg1 $vg2 + +vgmerge $vg1 $vg2 + +check lv_field $vg1/lvol0_pmspare size "8.00m" +vgremove -ff $vg1 + +fi diff --git a/test/shell/vgmerge-usage.sh b/test/shell/vgmerge-usage.sh index 17779b5..fa9bb19 100644 --- a/test/shell/vgmerge-usage.sh +++ b/test/shell/vgmerge-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008-2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,11 +8,13 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # 'Test vgmerge command options for validity' +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_pvs 4 @@ -21,8 +24,8 @@ 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" +vgcreate $vg2 "$dev1" "$dev2" +vgcreate $vg1 "$dev3" "$dev4" vgmerge $vg2 $vg1 vgremove $vg2 diff --git a/test/shell/vgreduce-removemissing-snapshot.sh b/test/shell/vgreduce-removemissing-snapshot.sh index 488d8fe..a74ff34 100644 --- a/test/shell/vgreduce-removemissing-snapshot.sh +++ b/test/shell/vgreduce-removemissing-snapshot.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,11 +8,13 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + -. lib/test +SKIP_WITH_CLVMD=1 +SKIP_WITH_LVMPOLLD=1 -exit 0 +. lib/inittest # # Snapshots of 'mirrors' are not supported. They can no longer be created. @@ -21,7 +24,7 @@ exit 0 aux prepare_vg 5 -lvcreate -m 3 --ig -L 2M -n 4way $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5":0 +lvcreate --type mirror -m 3 -L 2M -n 4way $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5":0 lvcreate -s $vg/4way -L 2M -n snap lvcreate -i 2 -L 2M $vg "$dev1" "$dev2" -n stripe @@ -33,3 +36,5 @@ vgreduce -v --removemissing --force $vg # "$dev2" "$dev4" lvs -a -o +devices $vg | not grep unknown lvs -a -o +devices $vg check mirror $vg 4way "$dev5" + +vgremove -ff $vg diff --git a/test/shell/vgreduce-usage.sh b/test/shell/vgreduce-usage.sh index 9a55d3c..e6f10f0 100644 --- a/test/shell/vgreduce-usage.sh +++ b/test/shell/vgreduce-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,30 +8,40 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_devs 4 +get_devs -for mdatype in 1 2 +if test -n "$LVM_TEST_LVM1" ; then +mdatypes='1 2' +else +mdatypes='2' +fi + +for mdatype in $mdatypes 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" + vgcreate $SHARED -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" + vgcreate $SHARED -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" + vgcreate $SHARED -M$mdatype $vg1 "$dev1" "$dev2" not vgreduce $vg1 "$dev1" "$dev2" vgremove -f $vg1 @@ -44,14 +55,14 @@ 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" +vgcreate $SHARED -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 +vgcreate $SHARED -M$mdatype $vg1 "$dev1" "$dev2" "$dev3" +lvcreate -aey -n $lv1 --type mirror -m1 -l 4 $vg1 lvcreate -n $lv2 -l 4 $vg1 "$dev2" lvcreate -n $lv3 -l 4 $vg1 "$dev3" vgchange -an $vg1 @@ -68,11 +79,11 @@ not vgs $vg1 # just double-check it's really gone #COMM "vgreduce rejects --removemissing --mirrorsonly --force when nonmirror lv lost too" # (lvm$mdatype) setup: create mirror + linear lvs -vgcreate -c n -M$mdatype $vg1 $(cat DEVICES) +vgcreate $SHARED -M$mdatype "$vg1" "${DEVICES[@]}" lvcreate -n $lv2 -l 4 $vg1 -lvcreate -m1 -n $lv1 -l 4 $vg1 "$dev1" "$dev2" "$dev3" +lvcreate -aey --type mirror -m1 -n $lv1 -l 4 $vg1 "$dev1" "$dev2" "$dev3" lvcreate -n $lv3 -l 4 $vg1 "$dev3" -pvs --segments -o +lv_name $(cat DEVICES) # for record only +pvs --segments -o +lv_name "${DEVICES[@]}" # for record only # (lvm$mdatype) setup: damage one pv vgchange -an $vg1 aux disable_dev "$dev1" @@ -84,6 +95,8 @@ vgreduce --removemissing --mirrorsonly --force $vg1 aux enable_dev "$dev1" -pvs -P $(cat DEVICES) # for record +pvs -P "${DEVICES[@]}" # for record lvs -P $vg1 # for record vgs -P $vg1 # for record + +vgremove -ff $vg1 diff --git a/test/shell/vgremove-corrupt-vg.sh b/test/shell/vgremove-corrupt-vg.sh new file mode 100644 index 0000000..3b17746 --- /dev/null +++ b/test/shell/vgremove-corrupt-vg.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux prepare_vg 3 +lvcreate -n blabla -L 1 $vg -an --zero n + +dd if=/dev/urandom bs=512 seek=2 count=32 of="$dev2" + +vgremove -f $vg diff --git a/test/shell/vgrename-usage.sh b/test/shell/vgrename-usage.sh index 2b8ac5a..3b69453 100644 --- a/test/shell/vgrename-usage.sh +++ b/test/shell/vgrename-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2008 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,9 +8,12 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest aux prepare_devs 4 pvcreate "$dev1" "$dev2" @@ -38,3 +42,18 @@ vgcreate $vg1 "$dev1" vgcreate $vg2 "$dev2" not vgrename $vg1 $vg2 vgremove $vg1 $vg2 + +# vgrename duplicate name +vgcreate $vg1 "$dev1" +aux disable_dev "$dev1" +vgcreate $vg1 "$dev2" +UUID=$(vgs --noheading -o vg_uuid $vg1) +aux enable_dev "$dev1" + +not vgrename $vg1 $vg2 +vgrename $UUID $vg2 +not vgrename $UUID $vg1 + +vgs + +vgremove $vg1 $vg2 diff --git a/test/shell/vgsplit-cache.sh b/test/shell/vgsplit-cache.sh new file mode 100644 index 0000000..65a711f --- /dev/null +++ b/test/shell/vgsplit-cache.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test vgsplit command options with cached volumes + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_cache 1 3 0 || skip + +aux prepare_vg 7 +vgcfgbackup -f vgb $vg + +lvcreate -L5 -n $lv2 $vg "$dev2" +lvcreate -L5 -n $lv3 $vg "$dev3" +lvconvert -y --type cache-pool --poolmetadata $vg/$lv2 $vg/$lv3 + +# Cannot split data and metadata from cache-pool +fail vgsplit $vg $vg1 "$dev2" 2>&1 | tee err +grep "Cannot split cache pool data" err + +fail vgsplit $vg $vg1 "$dev3" 2>&1 | tee err +grep "Cannot split cache pool data" err + +# Cache $lv1 +lvcreate -L1 -n $lv1 $vg "$dev1" +lvconvert -y --cache --cachepool $vg/$lv3 $vg/$lv1 + + + +# Cannot move active cache +fail vgsplit $vg $vg1 "$dev1" "$dev2" "$dev3" 2>&1 | tee err +grep "must be inactive" err + +vgchange -an $vg + + +# Try spliting component into separe VG +fail vgsplit $vg $vg1 "$dev1" 2>&1 | tee err +grep "Cannot split cache origin" err + +fail vgsplit $vg $vg1 "$dev2" 2>&1 | tee err +grep "Cannot split cache origin" err + +fail vgsplit $vg $vg1 "$dev3" 2>&1 | tee err +grep "Cannot split cache origin" err + +fail vgsplit $vg $vg1 "$dev1" "$dev2" 2>&1 | tee err +grep "Cannot split cache origin" err + +fail vgsplit $vg $vg1 "$dev2" "$dev3" 2>&1 | tee err + +# Finaly something that should pass +vgsplit $vg $vg1 "$dev1" "$dev2" "$dev3" + +vgs $vg $vg1 + +test 4 -eq "$(get vg_field $vg pv_count)" +test 3 -eq "$(get vg_field $vg1 pv_count)" + +lvremove -y $vg + +# dm-cache with cachevol must not separated main LV and cachevol + +vgremove -ff $vg +vgremove -ff $vg1 + +# +# Check we handle pmspare for splitted VGs +# +vgcfgrestore -f vgb $vg + +# Create cache-pool and pmspare on single PV1 +lvcreate -L10 --type cache-pool $vg/cpool "$dev1" +# Move spare to separate PV3 +pvmove -n $vg/lvol0_pmspare "$dev1" "$dev3" +# Create origin on PV2 +lvcreate -L10 -n orig $vg "$dev2" +lvconvert -H -y --cachepool $vg/cpool $vg/orig + +vgchange -an $vg + +# Check we do not create new _pmspare +vgsplit --poolmetadataspare n $vg $vg1 "$dev2" "$dev1" + +check lv_exists $vg/lvol0_pmspare +check lv_not_exists $vg1/lvol0_pmspare + +vgremove $vg +vgremove -f $vg1 + + +vgcfgrestore -f vgb $vg + +# Again - now with handling _pmspare by vgsplit +lvcreate -L10 --type cache-pool $vg/cpool "$dev1" +# Move spare to separate PV3 +pvmove -n $vg/lvol0_pmspare "$dev1" "$dev3" +# Create origin on PV2 +lvcreate -L10 -n orig $vg "$dev2" +lvconvert -H -y --cachepool $vg/cpool $vg/orig + +vgchange -an $vg + +# Handle _pmspare (default) +vgsplit --poolmetadataspare y $vg $vg1 "$dev2" "$dev1" + +check lv_not_exists $vg/lvol0_pmspare +check lv_exists $vg1/lvol0_pmspare + +vgremove $vg +vgremove -f $vg1 + + +vgcreate $vg "$dev1" "$dev2" "$dev3" "$dev4" + +lvcreate -L6 -n $lv1 -an $vg "$dev2" +lvcreate -L6 -n $lv2 -an $vg "$dev3" +lvconvert -y --type cache --cachevol $lv2 $vg/$lv1 +fail vgsplit $vg $vg1 "$dev2" +fail vgsplit $vg $vg1 "$dev3" +lvremove $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/vgsplit-operation.sh b/test/shell/vgsplit-operation.sh index c9cc04a..eb24a58 100644 --- a/test/shell/vgsplit-operation.sh +++ b/test/shell/vgsplit-operation.sh @@ -1,5 +1,6 @@ -#!/bin/sh -# Copyright (C) 2007 Red Hat, Inc. All rights reserved. +#!/usr/bin/env bash + +# Copyright (C) 2007,2018 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 @@ -7,18 +8,23 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Test vgsplit operation, including different LV types -. lib/test +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux lvmconf "global/support_mirrored_mirror_log=1" COMM() { - LAST_TEST="$@" + LAST_TEST="$*" } create_vg_() { - vgcreate -c n -s 64k "$@" + vgcreate -s 64k "$@" } aux prepare_pvs 5 10 @@ -40,8 +46,7 @@ COMM "vgsplit correctly splits single linear LV into $i VG ($j args)" create_vg_ $vg1 "$dev1" "$dev2" test $i = existing && create_vg_ $vg2 "$dev3" "$dev4" - lvcreate -l 4 -n $lv1 $vg1 "$dev1" - vgchange -an $vg1 + lvcreate -an -Zn -l 4 -n $lv1 $vg1 "$dev1" if [ $j = PV ]; then vgsplit $vg1 $vg2 "$dev1" else @@ -60,8 +65,7 @@ COMM "vgsplit correctly splits single striped LV into $i VG ($j args)" create_vg_ $vg1 "$dev1" "$dev2" test $i = existing && create_vg_ $vg2 "$dev3" "$dev4" - lvcreate -l 4 -i 2 -n $lv1 $vg1 "$dev1" "$dev2" - vgchange -an $vg1 + lvcreate -an -Zn -l 4 -i 2 -n $lv1 $vg1 "$dev1" "$dev2" if [ $j = PV ]; then vgsplit $vg1 $vg2 "$dev1" "$dev2" else @@ -79,9 +83,12 @@ COMM "vgsplit correctly splits mirror LV into $i VG ($j args)" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" test $i = existing && create_vg_ $vg2 "$dev4" - lvcreate -l 64 -m1 -n $lv1 $vg1 "$dev1" "$dev2" "$dev3" - vgchange -an $vg1 + lvcreate -an -Zn -l 64 --type mirror -m1 -n $lv1 $vg1 "$dev1" "$dev2" "$dev3" if [ $j = PV ]; then + # FIXME: Not an exhaustive check of possible bad combinations + not vgsplit $vg1 $vg2 "$dev1" "$dev2" + not vgsplit $vg1 $vg2 "$dev1" "$dev3" + not vgsplit $vg1 $vg2 "$dev2" "$dev3" vgsplit $vg1 $vg2 "$dev1" "$dev2" "$dev3" else vgsplit -n $lv1 $vg1 $vg2 @@ -93,17 +100,44 @@ COMM "vgsplit correctly splits mirror LV into $i VG ($j args)" fi lvremove -f $vg2/$lv1 vgremove -f $vg2 -# FIXME: ensure split /doesn't/ work when not all devs of mirror specified +# RHBZ 875903 +COMM "vgsplit correctly splits mirror (log+leg on same dev) into $i VG ($j args)" + create_vg_ $vg1 "$dev1" "$dev2" "$dev3" + test $i = existing && create_vg_ $vg2 "$dev4" + + lvcreate -an -Zn -l 64 --type mirror -m1 -n $lv1 $vg1 "$dev1" "$dev2" + if [ $j = PV ]; then + not vgsplit $vg1 $vg2 "$dev1" + not vgsplit $vg1 $vg2 "$dev2" + vgsplit $vg1 $vg2 "$dev1" "$dev2" + else + vgsplit -n $lv1 $vg1 $vg2 + fi + if [ $i = existing ]; then + check pvlv_counts $vg2 3 1 0 + else + check pvlv_counts $vg2 2 1 0 + fi + lvremove -f $vg2/$lv1 + vgremove -f $vg1 $vg2 + +# Can't use mirrored log without cmirrord +# TODO: Should work for inactive device, needs some fixes.... +if test ! -e LOCAL_CLVMD ; then COMM "vgsplit correctly splits mirror LV with mirrored log into $i VG ($j args)" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4" test $i = existing && create_vg_ $vg2 "$dev5" - lvcreate -l 64 --mirrorlog mirrored -m1 -n $lv1 $vg1 \ + lvcreate -an -Zn -l 64 --mirrorlog mirrored --type mirror -m1 -n $lv1 $vg1 \ "$dev1" "$dev2" "$dev3" "$dev4" - vgchange -an $vg1 if [ $j = PV ]; then + # FIXME: Not an exhaustive check of possible bad combinations + not vgsplit $vg1 $vg2 "$dev1" "$dev2" + not vgsplit $vg1 $vg2 "$dev3" "$dev4" + not vgsplit $vg1 $vg2 "$dev1" "$dev3" + not vgsplit $vg1 $vg2 "$dev2" "$dev4" vgsplit $vg1 $vg2 "$dev1" "$dev2" "$dev3" "$dev4" else vgsplit -n $lv1 $vg1 $vg2 @@ -115,13 +149,36 @@ COMM "vgsplit correctly splits mirror LV with mirrored log into $i VG ($j args)" fi lvremove -f $vg2/$lv1 vgremove -f $vg2 -# FIXME: ensure split /doesn't/ work when not all devs of mirror specified + +# RHBZ 875903 +COMM "vgsplit correctly splits mirror LV with mirrored log on same devs into $i VG ($j args)" + create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4" + test $i = existing && create_vg_ $vg2 "$dev5" + + lvcreate -an -Zn -l 64 --mirrorlog mirrored --type mirror -m1 -n $lv1 $vg1 \ + "$dev1" "$dev2" + + if [ $j = PV ]; then + not vgsplit $vg1 $vg2 "$dev1" + not vgsplit $vg1 $vg2 "$dev2" + vgsplit $vg1 $vg2 "$dev1" "$dev2" + else + vgsplit -n $lv1 $vg1 $vg2 + fi + if [ $i = existing ]; then + check pvlv_counts $vg2 3 1 0 + else + check pvlv_counts $vg2 2 1 0 + fi + lvremove -f $vg2/$lv1 + vgremove -f $vg1 $vg2 +fi COMM "vgsplit correctly splits origin and snapshot LV into $i VG ($j args)" create_vg_ $vg1 "$dev1" "$dev2" test $i = existing && create_vg_ $vg2 "$dev3" "$dev4" - lvcreate -l 64 -i 2 -n $lv1 $vg1 "$dev1" "$dev2" + lvcreate -aey -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 @@ -142,7 +199,7 @@ COMM "vgsplit correctly splits linear LV but not snap+origin LV into $i VG ($j a create_vg_ $vg1 "$dev1" "$dev2" test $i = existing && create_vg_ $vg2 "$dev3" - lvcreate -l 64 -i 2 -n $lv1 $vg1 + lvcreate -aey -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" @@ -167,10 +224,9 @@ COMM "vgsplit correctly splits linear LV but not mirror LV into $i VG ($j args)" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" test $i = existing && create_vg_ $vg2 "$dev5" - lvcreate -l 64 -m1 -n $lv1 $vg1 "$dev1" "$dev2" "$dev3" + lvcreate -an -Zn -l 64 --type mirror -m1 -n $lv1 $vg1 "$dev1" "$dev2" "$dev3" vgextend $vg1 "$dev4" - lvcreate -l 64 -n $lv2 $vg1 "$dev4" - vgchange -an $vg1 + lvcreate -an -Zn -l 64 -n $lv2 $vg1 "$dev4" if [ $j = PV ]; then vgsplit $vg1 $vg2 "$dev4" else @@ -184,7 +240,6 @@ COMM "vgsplit correctly splits linear LV but not mirror LV into $i VG ($j args)" check pvlv_counts $vg2 1 1 0 fi vgremove -f $vg1 $vg2 - done done @@ -194,16 +249,15 @@ done # COMM "vgsplit fails splitting 3 striped LVs into VG when only 1 LV specified" create_vg_ $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 +lvcreate -an -Zn -l 4 -n $lv1 -i 2 $vg1 "$dev1" "$dev2" +lvcreate -an -Zn -l 4 -n $lv2 -i 2 $vg1 "$dev2" "$dev3" +lvcreate -an -Zn -l 4 -n $lv3 -i 2 $vg1 "$dev3" "$dev4" not vgsplit -n $lv1 $vg1 $vg2 vgremove -f $vg1 COMM "vgsplit fails splitting one LV with 2 snapshots, only origin LV specified" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4" -lvcreate -l 16 -n $lv1 $vg1 "$dev1" "$dev2" +lvcreate -aey -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" check pvlv_counts $vg1 4 3 2 @@ -215,7 +269,7 @@ vgremove -f $vg1 COMM "vgsplit fails splitting one LV with 2 snapshots, only snapshot LV specified" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4" -lvcreate -l 16 -n $lv1 $vg1 "$dev1" "$dev2" +lvcreate -aey -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" check pvlv_counts $vg1 4 3 2 @@ -227,18 +281,16 @@ vgremove -f $vg1 COMM "vgsplit fails splitting one mirror LV, only one PV specified" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4" -lvcreate -l 16 -n $lv1 -m1 $vg1 "$dev1" "$dev2" "$dev3" +lvcreate -an -Zn -l 16 -n $lv1 --type mirror -m1 $vg1 "$dev1" "$dev2" "$dev3" check 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" create_vg_ $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" +lvcreate -an -Zn -l 16 -n $lv1 --type mirror --nosync -m1 $vg1 "$dev1" "$dev2" "$dev3" +lvcreate -an -Zn -l 16 -n $lv2 -i 2 $vg1 "$dev3" "$dev4" check pvlv_counts $vg1 4 2 0 -vgchange -an $vg1 not vgsplit -n $lv2 $vg1 $vg2 2>err vgremove -f $vg1 @@ -247,7 +299,7 @@ vgremove -f $vg1 # COMM "vgsplit fails, active mirror involved in split" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4" -lvcreate -l 16 -n $lv1 -m1 $vg1 "$dev1" "$dev2" "$dev3" +lvcreate -aey -l 16 -n $lv1 --type mirror --nosync -m1 $vg1 "$dev1" "$dev2" "$dev3" lvcreate -l 16 -n $lv2 $vg1 "$dev4" lvchange -an $vg1/$lv2 check pvlv_counts $vg1 4 2 0 @@ -257,7 +309,7 @@ vgremove -f $vg1 COMM "vgsplit succeeds, active mirror not involved in split" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4" -lvcreate -l 16 -n $lv1 -m1 $vg1 "$dev1" "$dev2" "$dev3" +lvcreate -aey -l 16 -n $lv1 --type mirror --nosync -m1 $vg1 "$dev1" "$dev2" "$dev3" lvcreate -l 16 -n $lv2 $vg1 "$dev4" lvchange -an $vg1/$lv2 check pvlv_counts $vg1 4 2 0 @@ -268,10 +320,9 @@ vgremove -f $vg1 $vg2 COMM "vgsplit fails, active snapshot involved in split" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4" -lvcreate -l 64 -i 2 -n $lv1 $vg1 "$dev1" "$dev2" +lvcreate -aey -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 +lvcreate -an -Zn -l 64 -i 2 -n $lv3 $vg1 "$dev3" "$dev4" check pvlv_counts $vg1 4 3 1 not vgsplit -n $lv2 $vg1 $vg2; check pvlv_counts $vg1 4 3 1 @@ -280,11 +331,10 @@ vgremove -f $vg1 COMM "vgsplit succeeds, active snapshot not involved in split" create_vg_ $vg1 "$dev1" "$dev2" "$dev3" -lvcreate -l 64 -i 2 -n $lv1 $vg1 "$dev1" "$dev2" +lvcreate -aey -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 +lvcreate -an -Zn -l 64 -n $lv3 $vg1 "$dev4" check pvlv_counts $vg1 4 3 1 vgsplit -n $lv3 $vg1 $vg2 check pvlv_counts $vg1 3 2 1 diff --git a/test/shell/vgsplit-raid.sh b/test/shell/vgsplit-raid.sh new file mode 100644 index 0000000..08e2a8e --- /dev/null +++ b/test/shell/vgsplit-raid.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test vgsplit operation, including different LV types +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +COMM() { + LAST_TEST="$*" +} + +create_vg_() { + vgcreate -s 64k "$@" +} + +aux have_raid 1 3 0 || skip + +aux prepare_pvs 5 10 + +# +# 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 RAID LV into $i VG ($j args)" + create_vg_ $vg1 "$dev1" "$dev2" "$dev3" + test $i = existing && create_vg_ $vg2 "$dev5" + + lvcreate -an -Zn -l 64 --type raid5 -i 2 -n $lv1 $vg1 + if [ $j = PV ]; then + not vgsplit $vg1 $vg2 "$dev1" + not vgsplit $vg1 $vg2 "$dev2" + not vgsplit $vg1 $vg2 "$dev1" "$dev2" + vgsplit $vg1 $vg2 "$dev1" "$dev2" "$dev3" + else + vgsplit -n $lv1 $vg1 $vg2 + fi + if [ $i = existing ]; then + check pvlv_counts $vg2 4 1 0 + else + check pvlv_counts $vg2 3 1 0 + fi + vgremove -f $vg2 + done +done diff --git a/test/shell/vgsplit-stacked.sh b/test/shell/vgsplit-stacked.sh index 62a5304..2f99a2e 100644 --- a/test/shell/vgsplit-stacked.sh +++ b/test/shell/vgsplit-stacked.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,21 +8,30 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +SKIP_WITH_LVMPOLLD=1 -. lib/test +. lib/inittest + +aux extend_filter_LVMTEST +aux lvmconf "devices/scan_lvs = 1" -aux lvmconf 'devices/filter = [ "a/dev\/mirror/", "a/dev\/mapper\/.*$/", "a/dev\/LVMTEST/", "r/.*/" ]' aux prepare_pvs 3 -vgcreate $vg1 "$dev1" "$dev2" +vgcreate $SHARED $vg1 "$dev1" "$dev2" lvcreate -n $lv1 -l 100%FREE $vg1 +aux extend_devices "$DM_DEV_DIR/$vg1/$lv1" + #top VG -pvcreate $DM_DEV_DIR/$vg1/$lv1 -vgcreate $vg $DM_DEV_DIR/$vg1/$lv1 "$dev3" +pvcreate "$DM_DEV_DIR/$vg1/$lv1" +vgcreate $SHARED $vg "$DM_DEV_DIR/$vg1/$lv1" "$dev3" vgchange -a n $vg $vg1 # this should fail but not segfault, RHBZ 481793. not vgsplit $vg $vg1 "$dev3" + +vgremove -ff $vg $vg1 diff --git a/test/shell/vgsplit-thin.sh b/test/shell/vgsplit-thin.sh new file mode 100644 index 0000000..abe9f55 --- /dev/null +++ b/test/shell/vgsplit-thin.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test vgsplit command options for validity + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} + +. lib/inittest + +aux have_thin 1 0 0 || skip + +aux prepare_devs 5 +get_devs + +vgcreate "$vg1" "${DEVICES[@]}" +lvcreate -T -L8M $vg1/pool1 -V10M -n $lv1 "$dev1" "$dev2" +lvcreate -T -L8M $vg1/pool2 -V10M -n $lv2 "$dev3" "$dev4" +lvcreate -s -L2M -n snap $vg1/$lv1 "$dev2" + +# Test with external origin if available +lvcreate -l1 -an -pr --zero n -n eorigin $vg1 "$dev5" +aux have_thin 1 5 0 && lvcreate -an -s $vg1/eorigin -n $lv3 --thinpool $vg1/pool1 + +# Cannot move active thin +not vgsplit $vg1 $vg2 "$dev1" "$dev2" "$dev5" + +vgchange -an $vg1 +not vgsplit $vg1 $vg2 "$dev1" +not vgsplit $vg1 $vg2 "$dev2" "$dev3" +vgsplit $vg1 $vg2 "$dev1" "$dev2" "$dev5" +lvs -a -o+devices $vg1 $vg2 + +vgmerge $vg1 $vg2 + +vgremove -ff $vg1 + +# Test vgsplit with ext.origin: +if aux have_thin 1 5 0; then +vgcreate "$vg1" "${DEVICES[@]}" +lvcreate -T -L8M $vg1/pool1 -V10M -n $lv1 "$dev1" "$dev2" +lvcreate -l1 -an -pr -n $lv2 $vg1 "$dev3" +lvcreate -s $vg1/$lv2 -n $lv3 --thinpool $vg1/pool1 +lvcreate -l1 -n $lv4 $vg1 "$dev4" +vgchange -an $vg1 + +# Can not split ext.origin from thin-data: +not vgsplit $vg1 $vg2 "$dev1" "$dev2" +not vgsplit $vg1 $vg2 "$dev3" + +vgsplit $vg1 $vg2 "$dev1" "$dev2" "$dev3" + +vgmerge $vg1 $vg2 + +vgremove -ff $vg1 +fi diff --git a/test/shell/vgsplit-usage.sh b/test/shell/vgsplit-usage.sh index 10167d7..33a606e 100644 --- a/test/shell/vgsplit-usage.sh +++ b/test/shell/vgsplit-usage.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env bash + # Copyright (C) 2007-2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -7,32 +8,42 @@ # # 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 +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Test vgsplit command options for validity -. lib/test +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest aux prepare_devs 5 +get_devs -for mdatype in 1 2 +if test -n "$LVM_TEST_LVM1" ; then +mdatypes='1 2' +else +mdatypes='2' +fi + +for mdatype in $mdatypes do -pvcreate -M$mdatype $(cat DEVICES) +pvcreate -M$mdatype "${DEVICES[@]}" # ensure name order does not matter # NOTE: if we're using lvm1, we must use -M on vgsplit -vgcreate -M$mdatype $vg1 $(cat DEVICES) +vgcreate -M$mdatype "$vg1" "${DEVICES[@]}" vgsplit -M$mdatype $vg1 $vg2 "$dev1" vgremove $vg1 $vg2 -vgcreate -M$mdatype $vg2 $(cat DEVICES) +vgcreate -M$mdatype "$vg2" "${DEVICES[@]}" vgsplit -M$mdatype $vg2 $vg1 "$dev1" vgremove $vg1 $vg2 # vgsplit accepts new vg as destination of split # lvm1 -- bz244792 -vgcreate -M$mdatype $vg1 $(cat DEVICES) +vgcreate -M$mdatype "$vg1" "${DEVICES[@]}" vgsplit $vg1 $vg2 "$dev1" 1>err grep "New volume group \"$vg2\" successfully split from \"$vg1\"" err vgremove $vg1 $vg2 @@ -84,13 +95,6 @@ not vgsplit --alloc cling $vg1 $vg2 "$dev1" 2>err; grep "Volume group \"$vg2\" exists, but new VG option specified" err vgremove $vg1 $vg2 -# 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 $vg1 $vg2 - # vgsplit rejects vg with active lv pvcreate -M$mdatype -ff "$dev3" "$dev4" vgcreate -M$mdatype $vg1 "$dev1" "$dev2" @@ -143,8 +147,22 @@ lvcreate -l 4 -n $lv2 $vg1 vgchange -an $vg1 not vgsplit $vg1 $vg2 "$dev3" 2>err; vgremove -f $vg2 $vg1 + +# Restart clvm because using the same +# devs as lvm1 and then lvm2 causes problems. +if test -e LOCAL_CLVMD ; then + kill "$(< LOCAL_CLVMD)" + for i in $(seq 1 100) ; do + test $i -eq 100 && die "Shutdown of clvmd is too slow." + pgrep clvmd || break + sleep .1 + done # wait for the pid removal + aux prepare_clvmd +fi + done +if test -z "$LVM_TEST_LVM1" ; then # ONLY LVM2 metadata # setup PVs" ' pvcreate --metadatacopies 0 "$dev5" @@ -159,6 +177,7 @@ check pvlv_counts $vg1 2 1 0 vgremove -f $vg1 # vgsplit rejects split because metadata types differ +if test -n "$LVM_TEST_LVM1" ; then pvcreate -ff -M1 "$dev3" "$dev4" pvcreate -ff "$dev1" "$dev2" vgcreate -M1 $vg1 "$dev3" "$dev4" @@ -166,3 +185,5 @@ vgcreate $vg2 "$dev1" "$dev2" not vgsplit $vg1 $vg2 "$dev3" 2>err; grep "Metadata types differ" err vgremove -f $vg1 $vg2 +fi +fi diff --git a/test/shell/vgsplit-vdo.sh b/test/shell/vgsplit-vdo.sh new file mode 100644 index 0000000..1d5ddf8 --- /dev/null +++ b/test/shell/vgsplit-vdo.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# Copyright (C) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test vgsplit command options with vdo volumes + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_vdo 6 2 0 || skip + +aux lvmconf "allocation/vdo_slab_size_mb = 128" + +aux prepare_vg 4 2200 + +lvcreate --vdo -L4G -n $lv1 $vg "$dev1" "$dev2" +lvcreate --vdo -L4G -n $lv2 $vg "$dev3" "$dev4" + +# Cannot move only part of VDO _vdata +not vgsplit $vg $vg2 "$dev3" |& tee out +grep "split" out + +# Cannot move active VDO +not vgsplit $vg $vg2 "$dev3" "$dev4" |& tee out +grep "inactive" out + +lvchange -an $vg/$lv2 + +vgsplit $vg $vg2 "$dev3" "$dev4" + +lvchange -ay $vg2/$lv2 +lvs -ao+devices $vg $vg2 + +# Cannot merge active VDO +not vgmerge $vg $vg2 |& tee out +grep "inactive" out + +lvchange -an $vg2/$lv2 + +vgmerge $vg $vg2 + +lvs -ao+devices $vg + +lvchange -ay $vg/$lv2 + +vgremove -ff $vg diff --git a/test/shell/writecache-cache-blocksize-2.sh b/test/shell/writecache-cache-blocksize-2.sh new file mode 100644 index 0000000..d50b369 --- /dev/null +++ b/test/shell/writecache-cache-blocksize-2.sh @@ -0,0 +1,242 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test dm-writecache and dm-cache with different block size combinations + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +mnt="mnt" +mkdir -p $mnt + +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 16384) printf "B" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_add_new_data_to_mnt() { + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 + sync +} + +_add_more_data_to_mnt() { + mkdir $mnt/more + cp fileA $mnt/more + cp fileB $mnt/more + cp fileC $mnt/more + cp randA $mnt/more + cp randB $mnt/more + cp randC $mnt/more + sync +} + +_verify_data_on_mnt() { + diff randA $mnt/randA + diff randB $mnt/randB + diff randC $mnt/randC + diff fileA $mnt/1/fileA + diff fileB $mnt/1/fileB + diff fileC $mnt/1/fileC + diff fileA $mnt/2/fileA + diff fileB $mnt/2/fileB + diff fileC $mnt/2/fileC +} + +_verify_more_data_on_mnt() { + diff randA $mnt/more/randA + diff randB $mnt/more/randB + diff randC $mnt/more/randC + diff fileA $mnt/more/fileA + diff fileB $mnt/more/fileB + diff fileC $mnt/more/fileC +} + +_verify_data_on_lv() { + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + _verify_data_on_mnt + rm $mnt/randA + rm $mnt/randB + rm $mnt/randC + rm -rf $mnt/1 + rm -rf $mnt/2 + umount $mnt + lvchange -an $vg/$lv1 +} + +# Check that the LBS ($1) and PBS ($2) are accurately reported. +_check_env() { + + check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "$1" + check sysfs "$(< SCSI_DEBUG_DEV)" queue/physical_block_size "$2" + + blockdev --getss "$dev1" + blockdev --getpbsz "$dev1" + blockdev --getss "$dev2" + blockdev --getpbsz "$dev2" +} + +# +# _run_test $BD1 $BD2 $type $optname "..." +# +# $BD1: device to place the main LV on +# $BD2: device to place the cache on +# $type is cache or writecache to use in lvconvert --type $type +# $optname is either --cachevol or --cachepool to use in lvconvert +# "..." a sector size option to use in mkfs.xfs +# + +_run_test() { + vgcreate $SHARED $vg "$1" + vgextend $vg "$2" + lvcreate -n $lv1 -L 300 -an $vg "$1" + lvcreate -n $lv2 -l 4 -an $vg "$2" + lvchange -ay $vg/$lv1 + mkfs.xfs -f $5 "$DM_DEV_DIR/$vg/$lv1" |tee out + _add_new_data_to_mnt + lvconvert --yes --type $3 $4 $lv2 $vg/$lv1 + + # TODO: check expected LBS of LV1 + # blockdev --getss "$DM_DEV_DIR/$vg/$lv1" |tee out + # grep "$N" out + # TODO: check expected PBS of LV1 + # blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" |tee out + # grep "$N" out + + _add_more_data_to_mnt + _verify_data_on_mnt + lvconvert --splitcache $vg/$lv1 + check lv_field $vg/$lv1 segtype linear + blockdev --getss "$DM_DEV_DIR/$vg/$lv1" + blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" + _verify_data_on_mnt + _verify_more_data_on_mnt + umount $mnt + lvchange -an $vg/$lv1 + lvchange -an $vg/$lv2 + _verify_data_on_lv + lvremove $vg/$lv1 + lvremove $vg/$lv2 + vgremove $vg +} + +# Setup: dev1 LBS 512, PBS 4096 (using scsi-debug) +# dev2 LBS 512, PBS 4096 (using scsi-debug) +# dev3 LBS 512, PBS 512 (using loop) +# dev4 LBS 512, PBS 512 (using loop) +# + +# On scsi debug 2 PVs has to fit! +aux prepare_scsi_debug_dev 602 sector_size=512 physblk_exp=3 || skip +aux prepare_devs 2 301 + +# Tests with fs block sizes require a libblkid version that shows BLOCK_SIZE +vgcreate $vg "$dev1" +lvcreate -n $lv1 -L300 $vg +mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" +blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip +lvchange -an $vg +vgremove -ff $vg + +# loopa/loopb have LBS 512 PBS 512 +which fallocate || skip +fallocate -l 301M loopa +fallocate -l 301M loopb + +for i in {1..5}; do + LOOP1=$(losetup -f loopa --show || true) + test -n "$LOOP1" && break +done +for i in {1..5} ; do + LOOP2=$(losetup -f loopb --show || true) + test -n "$LOOP2" && break +done + +# prepare devX mapping so it works for real & fake dev dir +d=3 +for i in "$LOOP1" "$LOOP2"; do + echo "$i" + m=${i##*loop} + test -e "$DM_DEV_DIR/loop$m" || mknod "$DM_DEV_DIR/loop$m" b 7 "$m" + eval "dev$d=\"$DM_DEV_DIR/loop$m\"" + d=$(( d + 1 )) +done + +# verify dev1/dev2 have LBS 512 PBS 4096 +_check_env "512" "4096" + +# verify dev3/dev4 have LBS 512 PBS 512 +blockdev --getss "$LOOP1" | grep 512 +blockdev --getss "$LOOP2" | grep 512 +blockdev --getpbsz "$LOOP1" | grep 512 +blockdev --getpbsz "$LOOP2" | grep 512 + +aux extend_filter "a|$dev3|" "a|$dev4|" +aux extend_devices "$dev3" "$dev4" + +# place main LV on dev1 with LBS 512, PBS 4096 +# and the cache on dev3 with LBS 512, PBS 512 + +_run_test "$dev1" "$dev3" "writecache" "--cachevol" "" +_run_test "$dev1" "$dev3" "cache" "--cachevol" "" +_run_test "$dev1" "$dev3" "cache" "--cachepool" "" + +# place main LV on dev3 with LBS 512, PBS 512 +# and the cache on dev1 with LBS 512, PBS 4096 + +_run_test "$dev3" "$dev1" "writecache" "--cachevol" "" +_run_test "$dev3" "$dev1" "cache" "--cachevol" "" +_run_test "$dev3" "$dev1" "cache" "--cachepool" "" + +# place main LV on dev1 with LBS 512, PBS 4096 +# and the cache on dev3 with LBS 512, PBS 512 +# and force xfs sectsz 512 + +_run_test "$dev1" "$dev3" "writecache" "--cachevol" "-s size=512" +_run_test "$dev1" "$dev3" "cache" "--cachevol" "-s size=512" +_run_test "$dev1" "$dev3" "cache" "--cachepool" "-s size=512" + +# place main LV on dev3 with LBS 512, PBS 512 +# and the cache on dev1 with LBS 512, PBS 4096 +# and force xfs sectsz 4096 + +_run_test "$dev3" "$dev1" "writecache" "--cachevol" "-s size=4096" +_run_test "$dev3" "$dev1" "cache" "--cachevol" "-s size=4096" +_run_test "$dev3" "$dev1" "cache" "--cachepool" "-s size=4096" + + +losetup -d "$LOOP1" || true +losetup -d "$LOOP2" || true +rm loopa loopb + +aux cleanup_scsi_debug_dev diff --git a/test/shell/writecache-cache-blocksize.sh b/test/shell/writecache-cache-blocksize.sh new file mode 100644 index 0000000..18be6ed --- /dev/null +++ b/test/shell/writecache-cache-blocksize.sh @@ -0,0 +1,251 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test dm-writecache and dm-cache with different block size combinations + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +mnt="mnt" +mkdir -p $mnt + +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 16384) printf "B" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_add_new_data_to_mnt() { + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 + sync +} + +_add_more_data_to_mnt() { + mkdir $mnt/more + cp fileA $mnt/more + cp fileB $mnt/more + cp fileC $mnt/more + cp randA $mnt/more + cp randB $mnt/more + cp randC $mnt/more + sync +} + +_verify_data_on_mnt() { + diff randA $mnt/randA + diff randB $mnt/randB + diff randC $mnt/randC + diff fileA $mnt/1/fileA + diff fileB $mnt/1/fileB + diff fileC $mnt/1/fileC + diff fileA $mnt/2/fileA + diff fileB $mnt/2/fileB + diff fileC $mnt/2/fileC +} + +_verify_more_data_on_mnt() { + diff randA $mnt/more/randA + diff randB $mnt/more/randB + diff randC $mnt/more/randC + diff fileA $mnt/more/fileA + diff fileB $mnt/more/fileB + diff fileC $mnt/more/fileC +} + +_verify_data_on_lv() { + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + _verify_data_on_mnt + rm $mnt/randA + rm $mnt/randB + rm $mnt/randC + rm -rf $mnt/1 + rm -rf $mnt/2 + umount $mnt + lvchange -an $vg/$lv1 +} + +# Check that the LBS/PBS that were set up is accurately reported for the devs. +_check_env() { + + check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "$1" + check sysfs "$(< SCSI_DEBUG_DEV)" queue/physical_block_size "$2" + + blockdev --getss "$dev1" + blockdev --getpbsz "$dev1" + blockdev --getss "$dev2" + blockdev --getpbsz "$dev2" +} + +# +# _run_test $BS1 $BS2 $type $optname "..." +# +# $BS1: the xfs sectsz is verified to match $BS1, after mkfs +# $BS2: the lv1 LBS is verified to match $BS2, after cache is added to lv1 +# $type is cache or writecache to use in lvconvert --type $type +# $optname is either --cachevol or --cachepool to use in lvconvert +# "..." a sector size option to use in mkfs.xfs +# + +_run_test() { + vgcreate $SHARED $vg "$dev1" + vgextend $vg "$dev2" + lvcreate -n $lv1 -L 300 -an $vg "$dev1" + lvcreate -n $lv2 -l 4 -an $vg "$dev2" + lvchange -ay $vg/$lv1 + mkfs.xfs -f $5 "$DM_DEV_DIR/$vg/$lv1" |tee out + grep "sectsz=$1" out + _add_new_data_to_mnt + lvconvert --yes --type $3 $4 $lv2 $vg/$lv1 + blockdev --getss "$DM_DEV_DIR/$vg/$lv1" |tee out + grep "$2" out + blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" + _add_more_data_to_mnt + _verify_data_on_mnt + lvconvert --splitcache $vg/$lv1 + check lv_field $vg/$lv1 segtype linear + blockdev --getss "$DM_DEV_DIR/$vg/$lv1" + blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" + _verify_data_on_mnt + _verify_more_data_on_mnt + umount $mnt + lvchange -an $vg/$lv1 + lvchange -an $vg/$lv2 + _verify_data_on_lv + lvremove $vg/$lv1 + lvremove $vg/$lv2 + vgremove $vg +} + +# Setup: LBS 512, PBS 512 +aux prepare_scsi_debug_dev 602 || skip +aux prepare_devs 2 301 + +# Tests with fs block sizes require a libblkid version that shows BLOCK_SIZE +vgcreate $vg "$dev1" +lvcreate -n $lv1 -L300 $vg +mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" +blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip +lvchange -an $vg +vgremove -ff $vg + +_check_env "512" "512" + +# lbs 512, pbs 512, xfs 512, wc bs 512 +_run_test 512 512 "writecache" "--cachevol" "" +# lbs 512, pbs 512, xfs 512, cache bs 512 +_run_test 512 512 "cache" "--cachevol" "" +_run_test 512 512 "cache" "--cachepool" "" + +# lbs 512, pbs 512, xfs -s 4096, wc bs 4096 +_run_test 4096 4096 "writecache" "--cachevol" "-s size=4096" +# lbs 512, pbs 512, xfs -s 4096, cache bs 512 +_run_test 4096 512 "cache" "--cachevol" "-s size=4096" +_run_test 4096 512 "cache" "--cachepool" "-s size=4096" + +aux cleanup_scsi_debug_dev + + +# Setup: LBS 512, PBS 4096 +aux prepare_scsi_debug_dev 602 sector_size=512 physblk_exp=3 +aux prepare_devs 2 301 + +_check_env "512" "4096" + +# lbs 512, pbs 4k, xfs 4k, wc bs 4k +_run_test 4096 4096 "writecache" "--cachevol" "" +# lbs 512, pbs 4k, xfs 4k, cache bs 512 +_run_test 4096 512 "cache" "--cachevol" "" +_run_test 4096 512 "cache" "--cachepool" "" + +# lbs 512, pbs 4k, xfs -s 512, wc bs 512 +_run_test 512 512 "writecache" "--cachevol" "-s size=512" +# lbs 512, pbs 4k, xfs -s 512, cache bs 512 +_run_test 512 512 "cache" "--cachevol" "-s size=512" +_run_test 512 512 "cache" "--cachepool" "-s size=512" + +aux cleanup_scsi_debug_dev + +# Setup: LBS 4096, PBS 4096 +# NOTE: Here we actually need PV of size 304M to get 300M ?? +aux prepare_scsi_debug_dev 608 sector_size=4096 || skip +aux prepare_devs 2 304 + +_check_env "4096" "4096" + +# lbs 4k, pbs 4k, xfs 4k, wc bs 4k +_run_test 4096 4096 "writecache" "--cachevol" "" +# lbs 4k, pbs 4k, xfs 4k, cache bs 4k +_run_test 4096 4096 "cache" "--cachevol" "" +_run_test 4096 4096 "cache" "--cachepool" "" + +aux cleanup_scsi_debug_dev + + +# Setup: LBS 512, PBS 512 +aux prepare_scsi_debug_dev 602 || skip +aux prepare_devs 2 301 + +_check_env "512" "512" + +vgcreate $SHARED $vg "$dev1" +vgextend $vg "$dev2" +lvcreate -n $lv1 -L 300 -an $vg "$dev1" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" +lvconvert --yes --type writecache --cachevol $lv2 --cachesettings "block_size=4096" $vg/$lv1 +lvs -o writecacheblocksize $vg/$lv1 |tee out +grep 4096 out +lvchange -ay $vg/$lv1 +mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" |tee out +grep "sectsz=4096" out +_add_new_data_to_mnt +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" |tee out +grep 4096 out +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +_add_more_data_to_mnt +_verify_data_on_mnt +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +_verify_data_on_mnt +_verify_more_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvchange -an $vg/$lv2 +_verify_data_on_lv +lvremove $vg/$lv1 +lvremove $vg/$lv2 +vgremove $vg + +aux cleanup_scsi_debug_dev diff --git a/test/shell/writecache-large.sh b/test/shell/writecache-large.sh new file mode 100644 index 0000000..000a2cc --- /dev/null +++ b/test/shell/writecache-large.sh @@ -0,0 +1,181 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test writecache usage + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +# scsi_debug devices with 512 LBS 512 PBS +aux prepare_scsi_debug_dev 1200 +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "512" +check sysfs "$(< SCSI_DEBUG_DEV)" queue/physical_block_size "512" + +aux prepare_devs 2 600 +blockdev --getss "$dev1" +blockdev --getpbsz "$dev1" +blockdev --getss "$dev2" +blockdev --getpbsz "$dev2" + +mnt="mnt" +mkdir -p $mnt + +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 16384) printf "B" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_add_new_data_to_mnt() { + mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 + sync +} + +_add_more_data_to_mnt() { + mkdir $mnt/more + cp fileA $mnt/more + cp fileB $mnt/more + cp fileC $mnt/more + cp randA $mnt/more + cp randB $mnt/more + cp randC $mnt/more + sync +} + +_verify_data_on_mnt() { + diff randA $mnt/randA + diff randB $mnt/randB + diff randC $mnt/randC + diff fileA $mnt/1/fileA + diff fileB $mnt/1/fileB + diff fileC $mnt/1/fileC + diff fileA $mnt/2/fileA + diff fileB $mnt/2/fileB + diff fileC $mnt/2/fileC +} + +_verify_more_data_on_mnt() { + diff randA $mnt/more/randA + diff randB $mnt/more/randB + diff randC $mnt/more/randC + diff fileA $mnt/more/fileA + diff fileB $mnt/more/fileB + diff fileC $mnt/more/fileC +} + +_verify_data_on_lv() { + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + _verify_data_on_mnt + rm $mnt/randA + rm $mnt/randB + rm $mnt/randC + rm -rf $mnt/1 + rm -rf $mnt/2 + umount $mnt + lvchange -an $vg/$lv1 +} + +vgcreate $SHARED $vg "$dev1" +vgextend $vg "$dev2" + +# Use a large enough size so that the cleaner will not +# finish immediately when detaching, and will require +# a secondary check from command top level. + +lvcreate -n $lv1 -L 560M -an $vg "$dev1" +lvcreate -n $lv2 -L 500M -an $vg "$dev2" + +lvchange -ay $vg/$lv1 +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" + +lvconvert --yes --type writecache --cachevol $lv2 $vg/$lv1 +dmsetup table $vg-$lv1 +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" + +_add_new_data_to_mnt +_add_more_data_to_mnt +_verify_data_on_mnt + +dd if=/dev/zero of=$mnt/big1 bs=1M count=100 conv=fdatasync +dd if=/dev/zero of=$mnt/big2 bs=1M count=100 conv=fdatasync +dd if=/dev/zero of=$mnt/big3 bs=1M count=100 conv=fdatasync +dd if=/dev/zero of=$mnt/big4 bs=1M count=100 conv=fdatasync + +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +dmsetup table $vg-$lv1 +_verify_data_on_mnt +_verify_more_data_on_mnt +dd if=$mnt/big4 of=/dev/null bs=1M count=100 +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvchange -an $vg/$lv2 +lvremove $vg/$lv1 +lvremove $vg/$lv2 + +# Repeat similar using uncache + +lvcreate -n $lv1 -L 560M -an $vg "$dev1" +lvcreate -n $lv2 -L 500M -an $vg "$dev2" + +lvchange -ay $vg/$lv1 +lvconvert --yes --type writecache --cachevol $lv2 $vg/$lv1 + +_add_new_data_to_mnt +_add_more_data_to_mnt +dd if=/dev/zero of=$mnt/big1 bs=1M count=100 conv=fdatasync + +umount $mnt +lvchange -an $vg/$lv1 + +lvconvert --uncache $vg/$lv1 + +check lv_field $vg/$lv1 segtype linear +not lvs $vg/$lv2 + +lvchange -ay $vg/$lv1 +mount "$DM_DEV_DIR/$vg/$lv1" $mnt + +_verify_data_on_mnt +_verify_more_data_on_mnt + +umount $mnt +lvchange -an $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/writecache-misc.sh b/test/shell/writecache-misc.sh new file mode 100644 index 0000000..ba8196c --- /dev/null +++ b/test/shell/writecache-misc.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test single lv cache options + +SKIP_WITH_LVMPOLLD=1 +SKIP_WITH_LVMLOCKD=1 + +. lib/inittest + +mkfs_mount_umount() +{ + lvt=$1 + + mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lvt" + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + cp pattern1 "$mount_dir/pattern1" + dd if=/dev/zero of="$mount_dir/zeros2M" bs=1M count=32 conv=fdatasync + umount "$mount_dir" +} + +mount_umount() +{ + lvt=$1 + + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + diff pattern1 "$mount_dir/pattern1" + dd if="$mount_dir/zeros2M" of=/dev/null bs=1M count=32 + umount "$mount_dir" +} + +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +# generate random data +dd if=/dev/urandom of=pattern1 bs=512K count=1 + +aux prepare_devs 4 301 + +vgcreate $vg "$dev1" "$dev2" "$dev3" "$dev4" + + +# Create writecache without a specified name so it gets automatic name +lvcreate -n $lv1 -L 300 -an $vg "$dev1" +lvcreate -y --type writecache -l 4 --cachevol $lv1 $vg "$dev2" +check lv_exists $vg lvol0 +lvremove -y $vg + +# +# Test pvmove with writecache +# + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 + +# cannot pvmove the cachevol +not pvmove "$dev2" "$dev3" + +# can pvmove the origin +pvmove "$dev1" "$dev3" + +mount_umount $lv1 + +# can pvmove the origin, naming the lv with the writecache +pvmove -n $vg/$lv1 "$dev3" "$dev1" + +mount_umount $lv1 +lvchange -an $vg/$lv1 +lvremove -y $vg/$lv1 + + +# +# Test partial and degraded activation +# + +lvcreate -n $lv1 -l 16 -an $vg "$dev1" "$dev2" +lvcreate -n $lv2 -l 16 -an $vg "$dev3" "$dev4" + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 +lvs -a -o+devices $vg +lvchange -an $vg/$lv1 + +aux hide_dev "$dev1" +not lvchange -ay $vg/$lv1 +not lvchange -ay --partial $vg/$lv1 +not lvchange -ay --activationmode degraded $vg/$lv1 +aux unhide_dev "$dev1" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 + +aux hide_dev "$dev3" +not lvchange -ay $vg/$lv1 +not lvchange -ay --partial $vg/$lv1 +not lvchange -ay --activationmode degraded $vg/$lv1 +aux unhide_dev "$dev3" +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/writecache-split.sh b/test/shell/writecache-split.sh new file mode 100644 index 0000000..c68f29b --- /dev/null +++ b/test/shell/writecache-split.sh @@ -0,0 +1,265 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test single lv cache options + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +mkfs_mount_umount() +{ + lvt=$1 + + mkfs.xfs -f -s size=4096 "$DM_DEV_DIR/$vg/$lvt" + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + cp pattern1 "$mount_dir/pattern1" + dd if=/dev/zero of="$mount_dir/zeros2M" bs=1M count=32 conv=fdatasync + umount "$mount_dir" +} + +mount_umount() +{ + lvt=$1 + + mount "$DM_DEV_DIR/$vg/$lvt" "$mount_dir" + diff pattern1 "$mount_dir/pattern1" + dd if="$mount_dir/zeros2M" of=/dev/null bs=1M count=32 + umount "$mount_dir" +} + +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +mount_dir="mnt" +mkdir -p "$mount_dir" + +# generate random data +dd if=/dev/urandom of=pattern1 bs=512K count=1 + +aux prepare_devs 4 301 + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +# +# split while inactive +# + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 +lvchange -an $vg/$lv1 + +lvconvert --splitcache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +lvs -o segtype $vg/$lv2 | grep linear + +lvchange -ay $vg/$lv1 +mount_umount $lv1 +lvchange -an $vg/$lv1 + +# +# split while active +# + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 + +lvconvert --splitcache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +lvs -o segtype $vg/$lv2 | grep linear + +mount_umount $lv1 +lvchange -an $vg/$lv1 + +# +# split while cachevol is missing +# + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 +lvchange -an $vg/$lv1 + +aux disable_dev "$dev2" + +lvs -a -o+lv_health_status $vg |tee out +grep $lv1 out | grep partial +grep $lv2 out | grep partial +check lv_attr_bit health $vg/$lv1 "p" + +not lvconvert --splitcache $vg/$lv1 +lvconvert --splitcache --force --yes $vg/$lv1 + +lvs -o segtype $vg/$lv1 | grep linear + +aux enable_dev "$dev2" +lvs -o segtype $vg/$lv2 | grep linear + +vgck --updatemetadata $vg +lvs $vg +vgchange -an $vg +vgextend --restoremissing $vg "$dev2" + + +# +# split while cachevol has 1 of 2 PVs +# + +lvremove $vg/$lv2 +lvcreate -n $lv2 -l 14 -an $vg "$dev2:0-10" "$dev3" + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 +lvchange -an $vg/$lv1 + +aux disable_dev "$dev3" + +lvs -a -o+lv_health_status $vg |tee out +grep $lv1 out | grep partial +grep $lv2 out | grep partial +check lv_attr_bit health $vg/$lv1 "p" + +not lvconvert --splitcache $vg/$lv1 +lvconvert --splitcache --force --yes $vg/$lv1 + +lvs -o segtype $vg/$lv1 | grep linear + +aux enable_dev "$dev3" +lvs -o segtype $vg/$lv2 | grep linear + +vgck --updatemetadata $vg +lvs $vg +vgchange -an $vg +vgextend --restoremissing $vg "$dev3" + +vgremove -ff $vg + +# +# split while cachevol is damaged +# + +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvchange -ay $vg/$lv1 + +mkfs_mount_umount $lv1 + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" +diff pattern1 "$mount_dir/pattern1" +cp pattern1 "$mount_dir/pattern2" +umount "$mount_dir" +lvchange -an $vg/$lv1 + +dd if=/dev/zero of="$dev2" seek=1 bs=1M count=16 + +lvconvert --splitcache --force --yes $vg/$lv1 + +lvchange -ay $vg/$lv1 + +mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir" +diff pattern1 "$mount_dir/pattern1" +umount "$mount_dir" +lvchange -an $vg/$lv1 + +vgremove -ff $vg + +# +# splitcache when origin is raid +# + +vgcreate $vg "$dev1" "$dev2" "$dev3" "$dev4" + +lvcreate --type raid1 -m1 -L6 -n $lv1 -an $vg "$dev1" "$dev2" +lvcreate -L6 -n $lv2 -an $vg "$dev3" +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 +lvchange -ay $vg/$lv1 +lvchange -an $vg/$lv1 +lvconvert --splitcache $vg/$lv1 +lvs $vg/$lv1 +lvs $vg/$lv2 + +vgremove -ff $vg + +# +# vgsplit should not separate cachevol from main lv +# + +vgcreate $vg "$dev1" "$dev2" "$dev3" "$dev4" +lvcreate -L6 -n $lv1 -an $vg "$dev2" +lvcreate -L6 -n $lv2 -an $vg "$dev3" +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 +fail vgsplit $vg $vg1 "$dev2" +fail vgsplit $vg $vg1 "$dev3" +lvremove $vg/$lv1 +vgremove $vg + +# +# uncache +# +vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3" "$dev4" + +# while inactive + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 +lvchange -an $vg/$lv1 + +lvconvert --uncache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +not lvs $vg/$lv2 + +lvchange -ay $vg/$lv1 +mount_umount $lv1 +lvchange -an $vg/$lv1 +lvremove -y $vg/$lv1 + +# while active + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" "$dev4" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" + +lvconvert -y --type writecache --cachevol $lv2 $vg/$lv1 + +lvchange -ay $vg/$lv1 +mkfs_mount_umount $lv1 + +lvconvert --uncache $vg/$lv1 +lvs -o segtype $vg/$lv1 | grep linear +not lvs $vg/$lv2 + +lvchange -an $vg/$lv1 +lvchange -ay $vg/$lv1 +mount_umount $lv1 +lvchange -an $vg/$lv1 +lvremove -y $vg/$lv1 + +vgremove -ff $vg diff --git a/test/shell/writecache.sh b/test/shell/writecache.sh new file mode 100644 index 0000000..9d1a5c0 --- /dev/null +++ b/test/shell/writecache.sh @@ -0,0 +1,272 @@ +#!/usr/bin/env bash + +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Test writecache usage + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +aux have_writecache 1 0 0 || skip +which mkfs.xfs || skip + +# scsi_debug devices with 512 LBS 512 PBS +aux prepare_scsi_debug_dev 602 +check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "512" +check sysfs "$(< SCSI_DEBUG_DEV)" queue/physical_block_size "512" +aux prepare_devs 2 301 + +# Tests with fs block sizes require a libblkid version that shows BLOCK_SIZE +vgcreate $vg "$dev1" +lvcreate -n $lv1 -L 300 $vg +mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" +blkid -p "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip +lvchange -an $vg +vgremove -ff $vg + +# scsi_debug devices with 512 LBS and 4K PBS +#aux prepare_scsi_debug_dev 256 sector_size=512 physblk_exp=3 +#check sysfs "$(< SCSI_DEBUG_DEV)" queue/logical_block_size "512" +#check sysfs "$(< SCSI_DEBUG_DEV)" queue/physical_block_size "4096" +#aux prepare_devs 2 64 + +# loop devs with 512 LBS and 512 PBS +#dd if=/dev/zero of=loopa bs=$((1024*1024)) count=64 2> /dev/null +#dd if=/dev/zero of=loopb bs=$((1024*1024)) count=64 2> /dev/null +#LOOP1=$(losetup -f loopa --show) +#LOOP2=$(losetup -f loopb --show) +#aux extend_filter "a|$LOOP1|" +#aux extend_filter "a|$LOOP2|" +#aux lvmconf 'devices/scan = "/dev"' +#dev1=$LOOP1 +#dev2=$LOOP2 + +# loop devs with 4096 LBS and 4096 PBS +#dd if=/dev/zero of=loopa bs=$((1024*1024)) count=64 2> /dev/null +#dd if=/dev/zero of=loopb bs=$((1024*1024)) count=64 2> /dev/null +#LOOP1=$(losetup -f loopa --sector-size 4096 --show) +#LOOP2=$(losetup -f loopb --sector-size 4096 --show) +#aux extend_filter "a|$LOOP1|" +#aux extend_filter "a|$LOOP2|" +#aux lvmconf 'devices/scan = "/dev"' +#dev1=$LOOP1 +#dev2=$LOOP2 + +# the default is brd ram devs with 512 LBS 4K PBS +# aux prepare_devs 2 64 + +blockdev --getss "$dev1" +blockdev --getpbsz "$dev1" +blockdev --getss "$dev2" +blockdev --getpbsz "$dev2" + + +mnt="mnt" +mkdir -p $mnt + +awk 'BEGIN { while (z++ < 16384) printf "A" }' > fileA +awk 'BEGIN { while (z++ < 16384) printf "B" }' > fileB +awk 'BEGIN { while (z++ < 16384) printf "C" }' > fileC + +# generate random data +dd if=/dev/urandom of=randA bs=512K count=2 +dd if=/dev/urandom of=randB bs=512K count=3 +dd if=/dev/urandom of=randC bs=512K count=4 + +_add_new_data_to_mnt() { + mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1" + + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + + # add original data + cp randA $mnt + cp randB $mnt + cp randC $mnt + mkdir $mnt/1 + cp fileA $mnt/1 + cp fileB $mnt/1 + cp fileC $mnt/1 + mkdir $mnt/2 + cp fileA $mnt/2 + cp fileB $mnt/2 + cp fileC $mnt/2 + sync +} + +_add_more_data_to_mnt() { + mkdir $mnt/more + cp fileA $mnt/more + cp fileB $mnt/more + cp fileC $mnt/more + cp randA $mnt/more + cp randB $mnt/more + cp randC $mnt/more + sync +} + +_verify_data_on_mnt() { + diff randA $mnt/randA + diff randB $mnt/randB + diff randC $mnt/randC + diff fileA $mnt/1/fileA + diff fileB $mnt/1/fileB + diff fileC $mnt/1/fileC + diff fileA $mnt/2/fileA + diff fileB $mnt/2/fileB + diff fileC $mnt/2/fileC +} + +_verify_more_data_on_mnt() { + diff randA $mnt/more/randA + diff randB $mnt/more/randB + diff randC $mnt/more/randC + diff fileA $mnt/more/fileA + diff fileB $mnt/more/fileB + diff fileC $mnt/more/fileC +} + +_verify_data_on_lv() { + lvchange -ay $vg/$lv1 + mount "$DM_DEV_DIR/$vg/$lv1" $mnt + _verify_data_on_mnt + rm $mnt/randA + rm $mnt/randB + rm $mnt/randC + rm -rf $mnt/1 + rm -rf $mnt/2 + umount $mnt + lvchange -an $vg/$lv1 +} + + +vgcreate $SHARED $vg "$dev1" +vgextend $vg "$dev2" + +blockdev --getss "$dev1" +blockdev --getpbsz "$dev1" +blockdev --getss "$dev2" +blockdev --getpbsz "$dev2" + +# Test attach while inactive, detach while inactive +# create fs on LV before writecache is attached + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" +lvchange -ay $vg/$lv1 +_add_new_data_to_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvconvert --yes --type writecache --cachevol $lv2 $vg/$lv1 +check lv_field $vg/$lv1 segtype writecache +lvs -a $vg/${lv2}_cvol --noheadings -o segtype >out +grep linear out +lvchange -ay $vg/$lv1 +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +_add_more_data_to_mnt +_verify_data_on_mnt +_verify_more_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +lvchange -ay $vg/$lv1 +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvchange -an $vg/$lv2 +lvremove $vg/$lv1 +lvremove $vg/$lv2 + +# Test attach while inactive, detach while inactive +# create fs on LV after writecache is attached + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" +lvconvert --yes --type writecache --cachevol $lv2 $vg/$lv1 +check lv_field $vg/$lv1 segtype writecache +lvs -a $vg/${lv2}_cvol --noheadings -o segtype >out +grep linear out +lvchange -ay $vg/$lv1 +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +_add_new_data_to_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvconvert --splitcache $vg/$lv1 +lvchange -ay $vg/$lv1 +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +mount "$DM_DEV_DIR/$vg/$lv1" $mnt +_add_more_data_to_mnt +_verify_data_on_mnt +_verify_more_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +_verify_data_on_lv +lvremove $vg/$lv1 +lvremove $vg/$lv2 + +# Test attach while active, detach while active + +lvcreate -n $lv1 -L 300 -an $vg "$dev1" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" +lvchange -ay $vg/$lv1 +_add_new_data_to_mnt +lvconvert --yes --type writecache --cachevol $lv2 $vg/$lv1 +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +_add_more_data_to_mnt +_verify_data_on_mnt +lvconvert --splitcache $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +_verify_data_on_mnt +_verify_more_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvchange -an $vg/$lv2 +_verify_data_on_lv +lvremove $vg/$lv1 +lvremove $vg/$lv2 + +# Test attach while active, detach while active, +# skip cleaner so flush message is used instead +lvcreate -n $lv1 -L 300 -an $vg "$dev1" +lvcreate -n $lv2 -l 4 -an $vg "$dev2" +lvchange -ay $vg/$lv1 +_add_new_data_to_mnt +lvconvert --yes --type writecache --cachevol $lv2 $vg/$lv1 +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +_add_more_data_to_mnt +_verify_data_on_mnt +lvconvert --splitcache --cachesettings cleaner=0 $vg/$lv1 +check lv_field $vg/$lv1 segtype linear +check lv_field $vg/$lv2 segtype linear +blockdev --getss "$DM_DEV_DIR/$vg/$lv1" +blockdev --getpbsz "$DM_DEV_DIR/$vg/$lv1" +_verify_data_on_mnt +_verify_more_data_on_mnt +umount $mnt +lvchange -an $vg/$lv1 +lvchange -an $vg/$lv2 +_verify_data_on_lv +lvremove $vg/$lv1 +lvremove $vg/$lv2 + +vgremove -ff $vg diff --git a/test/shell/zero-usage.sh b/test/shell/zero-usage.sh new file mode 100644 index 0000000..063f018 --- /dev/null +++ b/test/shell/zero-usage.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Basic usage of zero target + + +SKIP_WITH_LVMPOLLD=1 + +. lib/inittest + +which md5sum || skip + +aux prepare_vg 1 + +lvcreate --type zero -L1 -n $lv1 $vg +lvextend -L+1 $vg/$lv1 + +sum1=$(dd if=/dev/zero bs=2M count=1 | md5sum | cut -f1 -d' ') +sum2=$(dd if="$DM_DEV_DIR/$vg/$lv1" bs=2M count=1 | md5sum | cut -f1 -d' ') + +# has to match +test "$sum1" = "$sum2" + +check lv_field $vg/$lv1 lv_modules "zero" +check lv_field $vg/$lv1 segtype "zero" +check lv_field $vg/$lv1 seg_count "1" +check lv_field $vg/$lv1 seg_size_pe "4" # 4 * 512 + +lvextend -L+1 --type error $vg/$lv1 +lvextend -L+1 --type linear $vg/$lv1 +lvextend -L+1 --type striped $vg/$lv1 +lvextend -L+1 --type zero $vg/$lv1 + +lvs -o+segtype,seg_size $vg +check lv_field $vg/$lv1 seg_count "4" +check lv_field $vg/$lv1 size "6.00m" + +vgremove -ff $vg diff --git a/test/shell/zz-lvmlockd-dlm-remove.sh b/test/shell/zz-lvmlockd-dlm-remove.sh new file mode 100644 index 0000000..c7dfb1d --- /dev/null +++ b/test/shell/zz-lvmlockd-dlm-remove.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Remove the dlm test setup' + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_DLM" ] && skip; + +# FIXME: collect debug logs (only if a test failed?) +# lvmlockctl -d > lvmlockd-debug.txt +# dlm_tool dump > dlm-debug.txt + +lvmlockctl --stop-lockspaces +sleep 1 +killall lvmlockd +sleep 1 +killall lvmlockd || true +sleep 1 +systemctl stop dlm +systemctl stop corosync diff --git a/test/shell/zz-lvmlockd-idm-remove.sh b/test/shell/zz-lvmlockd-idm-remove.sh new file mode 100644 index 0000000..25943a5 --- /dev/null +++ b/test/shell/zz-lvmlockd-idm-remove.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# Copyright (C) 2021 Seagate. 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 v2. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Remove the idm test setup' + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip; + +# FIXME: collect debug logs (only if a test failed?) +# lvmlockctl -d > lvmlockd-debug.txt +# dlm_tool dump > dlm-debug.txt + +lvmlockctl --stop-lockspaces +sleep 1 +killall lvmlockd +sleep 1 +killall lvmlockd || true +sleep 1 +killall seagate_ilm diff --git a/test/shell/zz-lvmlockd-sanlock-remove.sh b/test/shell/zz-lvmlockd-sanlock-remove.sh new file mode 100644 index 0000000..081ee69 --- /dev/null +++ b/test/shell/zz-lvmlockd-sanlock-remove.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# Copyright (C) 2008-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +test_description='Remove the sanlock test setup' + +. lib/inittest + +[ -z "$LVM_TEST_LOCK_TYPE_SANLOCK" ] && skip; + +# FIMXME: get this to run after a test fails + +# Removes the VG with the global lock that was created by +# the corresponding create script. + +vgremove --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' glvg + +# FIXME: collect debug logs (only if a test failed?) +# lvmlockctl -d > lvmlockd-debug.txt +# sanlock log_dump > sanlock-debug.txt + +lvmlockctl --stop-lockspaces +sleep 1 +killall lvmlockd +sleep 1 +killall lvmlockd || true +sleep 1 +killall sanlock +sleep 1 +killall -9 lvmlockd || true +killall -9 sanlock || true + +# FIXME: dmsetup remove LVMTEST*-lvmlock + +dmsetup remove glvg-lvmlock || true +dmsetup remove GL_DEV || true + diff --git a/test/unit/Makefile b/test/unit/Makefile new file mode 100644 index 0000000..05e2501 --- /dev/null +++ b/test/unit/Makefile @@ -0,0 +1,65 @@ +# Copyright (C) 2011-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# NOTE: this Makefile only works as 'include' for toplevel Makefile +# which defined all top_* variables + +UNIT_SOURCE=\ + device_mapper/vdo/status.c \ + \ + test/unit/bcache_t.c \ + test/unit/bcache_utils_t.c \ + test/unit/bitset_t.c \ + test/unit/config_t.c \ + test/unit/dmlist_t.c \ + test/unit/dmstatus_t.c \ + test/unit/framework.c \ + test/unit/io_engine_t.c \ + test/unit/matcher_t.c \ + test/unit/percent_t.c \ + test/unit/radix_tree_t.c \ + test/unit/run.c \ + test/unit/string_t.c \ + test/unit/vdo_t.c + +test/unit/radix_tree_t.o: test/unit/rt_case1.c + +UNIT_TARGET = test/unit/unit-test +UNIT_DEPENDS = $(UNIT_SOURCE:%.c=%.d) +UNIT_OBJECTS = $(UNIT_SOURCE:%.c=%.o) +CLEAN_TARGETS += $(UNIT_DEPENDS) $(UNIT_OBJECTS) \ + $(UNIT_SOURCE:%.c=%.gcda) \ + $(UNIT_SOURCE:%.c=%.gcno) \ + $(UNIT_TARGET) + +lib/liblvm-internal.a: lib +libdaemon/client/libdaemonclient.a: libdaemon + +$(UNIT_TARGET): $(UNIT_OBJECTS) $(LVMINTERNAL_LIBS) + @echo " [LD] $@" + $(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) \ + -o $@ $+ $(LVMLIBS) + +.PHONY: run-unit-test unit-test +unit-test: $(UNIT_TARGET) +run-unit-test: $(UNIT_TARGET) + @echo "Running unit tests" + test -n "$$LVM_TEST_DIR" || LVM_TEST_DIR=$${TMPDIR:-/tmp} ;\ + TESTDIR=$$(mktemp -d -t -p "$$LVM_TEST_DIR" "LVMTEST.XXXXXXXXXX") ;\ + cd "$$TESTDIR" ;\ + LD_LIBRARY_PATH=$(abs_top_builddir)/libdm:$(abs_top_builddir)/daemons/dmeventd $(abs_top_builddir)/$(UNIT_TARGET) run ;\ + cd $$OLDPWD ;\ + $(RM) -r "$${TESTDIR:?}" + +ifeq ("$(DEPENDS)","yes") +-include $(UNIT_SOURCE:%.c=%.d) +endif diff --git a/test/unit/Makefile.in b/test/unit/Makefile.in deleted file mode 100644 index 740eb14..0000000 --- a/test/unit/Makefile.in +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2011-2012 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@ - -VPATH = $(srcdir) -ifeq ("@TESTING@", "yes") -SOURCES = bitset_t.c matcher_t.c config_t.c string_t.c run.c -TARGETS = run -endif - -include $(top_builddir)/make.tmpl -ifeq ("$(TESTING)", "yes") -LDLIBS += -ldevmapper @CUNIT_LIBS@ -CFLAGS += @CUNIT_CFLAGS@ - -check: unit - -unit: $(TARGETS) - @echo Running unit tests - LD_LIBRARY_PATH=$(top_builddir)/libdm ./$(TARGETS) -endif diff --git a/test/unit/bcache_t.c b/test/unit/bcache_t.c new file mode 100644 index 0000000..2668d3f --- /dev/null +++ b/test/unit/bcache_t.c @@ -0,0 +1,1036 @@ +/* + * Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "units.h" +#include "lib/device/bcache.h" + +#include +#include +#include +#include + +#define SHOW_MOCK_CALLS 0 + +/*---------------------------------------------------------------- + * Mock engine + *--------------------------------------------------------------*/ +struct mock_engine { + struct io_engine e; + struct dm_list expected_calls; + struct dm_list issued_io; + unsigned max_io; + sector_t block_size; +}; + +enum method { + E_DESTROY, + E_ISSUE, + E_WAIT, + E_MAX_IO +}; + +struct mock_call { + struct dm_list list; + enum method m; + + bool match_args; + enum dir d; + int di; + block_address b; + bool issue_r; + bool wait_r; +}; + +struct mock_io { + struct dm_list list; + int di; + sector_t sb; + sector_t se; + void *data; + void *context; + bool r; +}; + +static const char *_show_method(enum method m) +{ + switch (m) { + case E_DESTROY: + return "destroy()"; + case E_ISSUE: + return "issue()"; + case E_WAIT: + return "wait()"; + case E_MAX_IO: + return "max_io()"; + } + + return ""; +} + +static void _expect(struct mock_engine *e, enum method m) +{ + struct mock_call *mc = malloc(sizeof(*mc)); + + T_ASSERT(mc); + mc->m = m; + mc->match_args = false; + dm_list_add(&e->expected_calls, &mc->list); +} + +static void _expect_read(struct mock_engine *e, int di, block_address b) +{ + struct mock_call *mc = malloc(sizeof(*mc)); + + T_ASSERT(mc); + mc->m = E_ISSUE; + mc->match_args = true; + mc->d = DIR_READ; + mc->di = di; + mc->b = b; + mc->issue_r = true; + mc->wait_r = true; + dm_list_add(&e->expected_calls, &mc->list); +} + +static void _expect_read_any(struct mock_engine *e) +{ + struct mock_call *mc = malloc(sizeof(*mc)); + + T_ASSERT(mc); + mc->m = E_ISSUE; + mc->match_args = false; + mc->issue_r = true; + mc->wait_r = true; + dm_list_add(&e->expected_calls, &mc->list); +} + +static void _expect_write(struct mock_engine *e, int di, block_address b) +{ + struct mock_call *mc = malloc(sizeof(*mc)); + + T_ASSERT(mc); + mc->m = E_ISSUE; + mc->match_args = true; + mc->d = DIR_WRITE; + mc->di = di; + mc->b = b; + mc->issue_r = true; + mc->wait_r = true; + dm_list_add(&e->expected_calls, &mc->list); +} + +static void _expect_read_bad_issue(struct mock_engine *e, int di, block_address b) +{ + struct mock_call *mc = malloc(sizeof(*mc)); + + T_ASSERT(mc); + mc->m = E_ISSUE; + mc->match_args = true; + mc->d = DIR_READ; + mc->di = di; + mc->b = b; + mc->issue_r = false; + mc->wait_r = true; + dm_list_add(&e->expected_calls, &mc->list); +} + +static void _expect_write_bad_issue(struct mock_engine *e, int di, block_address b) +{ + struct mock_call *mc = malloc(sizeof(*mc)); + + T_ASSERT(mc); + mc->m = E_ISSUE; + mc->match_args = true; + mc->d = DIR_WRITE; + mc->di = di; + mc->b = b; + mc->issue_r = false; + mc->wait_r = true; + dm_list_add(&e->expected_calls, &mc->list); +} + +static void _expect_read_bad_wait(struct mock_engine *e, int di, block_address b) +{ + struct mock_call *mc = malloc(sizeof(*mc)); + + T_ASSERT(mc); + mc->m = E_ISSUE; + mc->match_args = true; + mc->d = DIR_READ; + mc->di = di; + mc->b = b; + mc->issue_r = true; + mc->wait_r = false; + dm_list_add(&e->expected_calls, &mc->list); +} + +static void _expect_write_bad_wait(struct mock_engine *e, int di, block_address b) +{ + struct mock_call *mc = malloc(sizeof(*mc)); + + T_ASSERT(mc); + mc->m = E_ISSUE; + mc->match_args = true; + mc->d = DIR_WRITE; + mc->di = di; + mc->b = b; + mc->issue_r = true; + mc->wait_r = false; + dm_list_add(&e->expected_calls, &mc->list); +} + +static struct mock_call *_match_pop(struct mock_engine *e, enum method m) +{ + + struct mock_call *mc; + + if (dm_list_empty(&e->expected_calls)) + test_fail("unexpected call to method %s\n", _show_method(m)); + + mc = dm_list_item(e->expected_calls.n, struct mock_call); + dm_list_del(&mc->list); + + if (mc->m != m) + test_fail("expected %s, but got %s\n", _show_method(mc->m), _show_method(m)); +#if SHOW_MOCK_CALLS + else + fprintf(stderr, "%s called (expected)\n", _show_method(m)); +#endif + + return mc; +} + +static void _match(struct mock_engine *e, enum method m) +{ + free(_match_pop(e, m)); +} + +static void _no_outstanding_expectations(struct mock_engine *e) +{ + struct mock_call *mc; + + if (!dm_list_empty(&e->expected_calls)) { + fprintf(stderr, "unsatisfied expectations:\n"); + dm_list_iterate_items (mc, &e->expected_calls) + fprintf(stderr, " %s\n", _show_method(mc->m)); + } + T_ASSERT(dm_list_empty(&e->expected_calls)); +} + +static struct mock_engine *_to_mock(struct io_engine *e) +{ + return container_of(e, struct mock_engine, e); +} + +static void _mock_destroy(struct io_engine *e) +{ + struct mock_engine *me = _to_mock(e); + + _match(me, E_DESTROY); + T_ASSERT(dm_list_empty(&me->issued_io)); + T_ASSERT(dm_list_empty(&me->expected_calls)); + free(_to_mock(e)); +} + +static bool _mock_issue(struct io_engine *e, enum dir d, int di, + sector_t sb, sector_t se, void *data, void *context) +{ + bool r, wait_r; + struct mock_io *io; + struct mock_call *mc; + struct mock_engine *me = _to_mock(e); + + mc = _match_pop(me, E_ISSUE); + if (mc->match_args) { + T_ASSERT(d == mc->d); + T_ASSERT(di == mc->di); + T_ASSERT(sb == mc->b * me->block_size); + T_ASSERT(se == (mc->b + 1) * me->block_size); + } + r = mc->issue_r; + wait_r = mc->wait_r; + free(mc); + + if (r) { + io = malloc(sizeof(*io)); + if (!io) + abort(); + + io->di = di; + io->sb = sb; + io->se = se; + io->data = data; + io->context = context; + io->r = wait_r; + + dm_list_add(&me->issued_io, &io->list); + } + + return r; +} + +static bool _mock_wait(struct io_engine *e, io_complete_fn fn) +{ + struct mock_io *io; + struct mock_engine *me = _to_mock(e); + _match(me, E_WAIT); + + // FIXME: provide a way to control how many are completed and whether + // they error. + T_ASSERT(!dm_list_empty(&me->issued_io)); + io = dm_list_item(me->issued_io.n, struct mock_io); + dm_list_del(&io->list); + fn(io->context, io->r ? 0 : -EIO); + free(io); + + return true; +} + +static unsigned _mock_max_io(struct io_engine *e) +{ + struct mock_engine *me = _to_mock(e); + _match(me, E_MAX_IO); + return me->max_io; +} + +static struct mock_engine *_mock_create(unsigned max_io, sector_t block_size) +{ + struct mock_engine *m = malloc(sizeof(*m)); + + T_ASSERT(m); + + m->e.destroy = _mock_destroy; + m->e.issue = _mock_issue; + m->e.wait = _mock_wait; + m->e.max_io = _mock_max_io; + + m->max_io = max_io; + m->block_size = block_size; + dm_list_init(&m->expected_calls); + dm_list_init(&m->issued_io); + + return m; +} + +/*---------------------------------------------------------------- + * Fixtures + *--------------------------------------------------------------*/ +struct fixture { + struct mock_engine *me; + struct bcache *cache; +}; + +static struct fixture *_fixture_init(sector_t block_size, unsigned nr_cache_blocks) +{ + struct fixture *f = malloc(sizeof(*f)); + + T_ASSERT(f); + + f->me = _mock_create(16, block_size); + T_ASSERT(f->me); + + _expect(f->me, E_MAX_IO); + f->cache = bcache_create(block_size, nr_cache_blocks, &f->me->e); + T_ASSERT(f->cache); + + return f; +} + +static void _fixture_exit(struct fixture *f) +{ + if (f) { + _expect(f->me, E_DESTROY); + bcache_destroy(f->cache); + + free(f); + } +} + +static void *_small_fixture_init(void) +{ + return _fixture_init(128, 16); +} + +static void _small_fixture_exit(void *context) +{ + _fixture_exit(context); +} + +static void *_large_fixture_init(void) +{ + return _fixture_init(128, 1024); +} + +static void _large_fixture_exit(void *context) +{ + _fixture_exit(context); +} + +/*---------------------------------------------------------------- + * Tests + *--------------------------------------------------------------*/ +#define MEG 2048 +#define SECTOR_SHIFT 9 +#define PAGE_SIZE_SECTORS ((PAGE_SIZE) >> SECTOR_SHIFT) + +static void good_create(sector_t block_size, unsigned nr_cache_blocks) +{ + struct bcache *cache; + struct mock_engine *me = _mock_create(16, 128); + + _expect(me, E_MAX_IO); + cache = bcache_create(block_size, nr_cache_blocks, &me->e); + T_ASSERT(cache); + + _expect(me, E_DESTROY); + bcache_destroy(cache); +} + +static void bad_create(sector_t block_size, unsigned nr_cache_blocks) +{ + struct bcache *cache; + struct mock_engine *me = _mock_create(16, 128); + + _expect(me, E_MAX_IO); + cache = bcache_create(block_size, nr_cache_blocks, &me->e); + T_ASSERT(!cache); + + _expect(me, E_DESTROY); + me->e.destroy(&me->e); +} + +static void test_create(void *fixture) +{ + good_create(PAGE_SIZE_SECTORS, 16); +} + +static void test_nr_cache_blocks_must_be_positive(void *fixture) +{ + bad_create(PAGE_SIZE_SECTORS, 0); +} + +static void test_block_size_must_be_positive(void *fixture) +{ + bad_create(0, 16); +} + +static void test_block_size_must_be_multiple_of_page_size(void *fixture) +{ + static unsigned _bad_examples[] = {3, 9, 13, 1025}; + + unsigned i; + + for (i = 0; i < DM_ARRAY_SIZE(_bad_examples); i++) + bad_create(_bad_examples[i], 16); + + for (i = 1; i < 100; i++) + good_create(i * PAGE_SIZE_SECTORS, 16); +} + +static void test_get_triggers_read(void *context) +{ + struct fixture *f = context; + + int di = 17; // arbitrary key + struct block *b; + + _expect_read(f->me, di, 0); + _expect(f->me, E_WAIT); + T_ASSERT(bcache_get(f->cache, di, 0, 0, &b)); + bcache_put(b); + + _expect_read(f->me, di, 1); + _expect(f->me, E_WAIT); + T_ASSERT(bcache_get(f->cache, di, 1, GF_DIRTY, &b)); + _expect_write(f->me, di, 1); + _expect(f->me, E_WAIT); + bcache_put(b); +} + +static void test_repeated_reads_are_cached(void *context) +{ + struct fixture *f = context; + + int di = 17; // arbitrary key + unsigned i; + struct block *b; + + _expect_read(f->me, di, 0); + _expect(f->me, E_WAIT); + for (i = 0; i < 100; i++) { + T_ASSERT(bcache_get(f->cache, di, 0, 0, &b)); + bcache_put(b); + } +} + +static void test_block_gets_evicted_with_many_reads(void *context) +{ + struct fixture *f = context; + + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + const unsigned nr_cache_blocks = 16; + + int di = 17; // arbitrary key + unsigned i; + struct block *b; + + for (i = 0; i < nr_cache_blocks; i++) { + _expect_read(me, di, i); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, i, 0, &b)); + bcache_put(b); + } + + // Not enough cache blocks to hold this one + _expect_read(me, di, nr_cache_blocks); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, nr_cache_blocks, 0, &b)); + bcache_put(b); + + // Now if we run through we should find one block has been + // evicted. We go backwards because the oldest is normally + // evicted first. + _expect_read_any(me); + _expect(me, E_WAIT); + for (i = nr_cache_blocks; i; i--) { + T_ASSERT(bcache_get(cache, di, i - 1, 0, &b)); + bcache_put(b); + } +} + +static void test_prefetch_issues_a_read(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + const unsigned nr_cache_blocks = 16; + + int di = 17; // arbitrary key + unsigned i; + struct block *b; + + for (i = 0; i < nr_cache_blocks; i++) { + // prefetch should not wait + _expect_read(me, di, i); + bcache_prefetch(cache, di, i); + } + _no_outstanding_expectations(me); + + for (i = 0; i < nr_cache_blocks; i++) { + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, i, 0, &b)); + bcache_put(b); + } +} + +static void test_too_many_prefetches_does_not_trigger_a_wait(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + + const unsigned nr_cache_blocks = 16; + int di = 17; // arbitrary key + unsigned i; + + for (i = 0; i < 10 * nr_cache_blocks; i++) { + // prefetch should not wait + if (i < nr_cache_blocks) + _expect_read(me, di, i); + bcache_prefetch(cache, di, i); + } + + // Destroy will wait for any in flight IO triggered by prefetches. + for (i = 0; i < nr_cache_blocks; i++) + _expect(me, E_WAIT); +} + +static void test_dirty_data_gets_written_back(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + + int di = 17; // arbitrary key + struct block *b; + + // Expect the read + _expect_read(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, 0, GF_DIRTY, &b)); + bcache_put(b); + + // Expect the write + _expect_write(me, di, 0); + _expect(me, E_WAIT); +} + +static void test_zeroed_data_counts_as_dirty(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + + int di = 17; // arbitrary key + struct block *b; + + // No read + T_ASSERT(bcache_get(cache, di, 0, GF_ZERO, &b)); + bcache_put(b); + + // Expect the write + _expect_write(me, di, 0); + _expect(me, E_WAIT); +} + +static void test_flush_waits_for_all_dirty(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + + const unsigned count = 16; + int di = 17; // arbitrary key + unsigned i; + struct block *b; + + for (i = 0; i < count; i++) { + if (i % 2) { + T_ASSERT(bcache_get(cache, di, i, GF_ZERO, &b)); + } else { + _expect_read(me, di, i); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, i, 0, &b)); + } + bcache_put(b); + } + + for (i = 0; i < count; i++) { + if (i % 2) + _expect_write(me, di, i); + } + + for (i = 0; i < count; i++) { + if (i % 2) + _expect(me, E_WAIT); + } + + T_ASSERT(bcache_flush(cache)); + _no_outstanding_expectations(me); +} + +static void test_multiple_files(void *context) +{ + static int _dis[] = {1, 128, 345, 678, 890}; + + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + unsigned i; + + for (i = 0; i < DM_ARRAY_SIZE(_dis); i++) { + _expect_read(me, _dis[i], 0); + _expect(me, E_WAIT); + + T_ASSERT(bcache_get(cache, _dis[i], 0, 0, &b)); + bcache_put(b); + } +} + +static void test_read_bad_issue(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + + _expect_read_bad_issue(me, 17, 0); + T_ASSERT(!bcache_get(cache, 17, 0, 0, &b)); +} + +static void test_read_bad_issue_intermittent(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + _expect_read_bad_issue(me, di, 0); + T_ASSERT(!bcache_get(cache, di, 0, 0, &b)); + + _expect_read(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, 0, 0, &b)); + bcache_put(b); +} + +static void test_read_bad_wait(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + _expect_read_bad_wait(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(!bcache_get(cache, di, 0, 0, &b)); +} + +static void test_read_bad_wait_intermittent(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + _expect_read_bad_wait(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(!bcache_get(cache, di, 0, 0, &b)); + + _expect_read(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, 0, 0, &b)); + bcache_put(b); +} + +static void test_write_bad_issue_stops_flush(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + T_ASSERT(bcache_get(cache, di, 0, GF_ZERO, &b)); + _expect_write_bad_issue(me, di, 0); + bcache_put(b); + T_ASSERT(!bcache_flush(cache)); + + // we'll let it succeed the second time + _expect_write(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_flush(cache)); +} + +static void test_write_bad_io_stops_flush(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + T_ASSERT(bcache_get(cache, di, 0, GF_ZERO, &b)); + _expect_write_bad_wait(me, di, 0); + _expect(me, E_WAIT); + bcache_put(b); + T_ASSERT(!bcache_flush(cache)); + + // we'll let it succeed the second time + _expect_write(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_flush(cache)); +} + +static void test_invalidate_not_present(void *context) +{ + struct fixture *f = context; + struct bcache *cache = f->cache; + int di = 17; + + T_ASSERT(bcache_invalidate(cache, di, 0)); +} + +static void test_invalidate_present(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + _expect_read(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, 0, 0, &b)); + bcache_put(b); + + T_ASSERT(bcache_invalidate(cache, di, 0)); +} + +static void test_invalidate_after_read_error(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + _expect_read_bad_issue(me, di, 0); + T_ASSERT(!bcache_get(cache, di, 0, 0, &b)); + T_ASSERT(bcache_invalidate(cache, di, 0)); +} + +static void test_invalidate_after_write_error(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + T_ASSERT(bcache_get(cache, di, 0, GF_ZERO, &b)); + bcache_put(b); + + // invalidate should fail if the write fails + _expect_write_bad_wait(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(!bcache_invalidate(cache, di, 0)); + + // and should succeed if the write does + _expect_write(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_invalidate(cache, di, 0)); + + // a read is not required to get the block + _expect_read(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, 0, 0, &b)); + bcache_put(b); +} + +static void test_invalidate_held_block(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + T_ASSERT(bcache_get(cache, di, 0, GF_ZERO, &b)); + + T_ASSERT(!bcache_invalidate(cache, di, 0)); + + _expect_write(me, di, 0); + _expect(me, E_WAIT); + bcache_put(b); +} + +//---------------------------------------------------------------- +// abort tests + +static void test_abort_no_blocks(void *context) +{ + struct fixture *f = context; + struct bcache *cache = f->cache; + int di = 17; + + // We have no expectations + bcache_abort_di(cache, di); +} + +static void test_abort_single_block(void *context) +{ + struct fixture *f = context; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + T_ASSERT(bcache_get(cache, di, 0, GF_ZERO, &b)); + bcache_put(b); + + bcache_abort_di(cache, di); + + // no write should be issued + T_ASSERT(bcache_flush(cache)); +} + +static void test_abort_forces_reread(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di = 17; + + _expect_read(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, 0, GF_DIRTY, &b)); + bcache_put(b); + + bcache_abort_di(cache, di); + T_ASSERT(bcache_flush(cache)); + + // Check the block is re-read + _expect_read(me, di, 0); + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, di, 0, 0, &b)); + bcache_put(b); +} + +static void test_abort_only_specific_di(void *context) +{ + struct fixture *f = context; + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + struct block *b; + int di1 = 17, di2 = 18; + + T_ASSERT(bcache_get(cache, di1, 0, GF_ZERO, &b)); + bcache_put(b); + + T_ASSERT(bcache_get(cache, di1, 1, GF_ZERO, &b)); + bcache_put(b); + + T_ASSERT(bcache_get(cache, di2, 0, GF_ZERO, &b)); + bcache_put(b); + + T_ASSERT(bcache_get(cache, di2, 1, GF_ZERO, &b)); + bcache_put(b); + + bcache_abort_di(cache, di2); + + // writes for di1 should still be issued + _expect_write(me, di1, 0); + _expect_write(me, di1, 1); + + _expect(me, E_WAIT); + _expect(me, E_WAIT); + + T_ASSERT(bcache_flush(cache)); +} + +//---------------------------------------------------------------- +// Chasing a bug reported by dct + +static void _cycle(struct fixture *f, unsigned nr_cache_blocks) +{ + struct mock_engine *me = f->me; + struct bcache *cache = f->cache; + + unsigned i; + struct block *b; + + for (i = 0; i < nr_cache_blocks; i++) { + // prefetch should not wait + _expect_read(me, i, 0); + bcache_prefetch(cache, i, 0); + } + + // This double checks the reads occur in response to the prefetch + _no_outstanding_expectations(me); + + for (i = 0; i < nr_cache_blocks; i++) { + _expect(me, E_WAIT); + T_ASSERT(bcache_get(cache, i, 0, 0, &b)); + bcache_put(b); + } + + _no_outstanding_expectations(me); +} + +static void test_concurrent_reads_after_invalidate(void *context) +{ + struct fixture *f = context; + unsigned i, nr_cache_blocks = 16; + + _cycle(f, nr_cache_blocks); + for (i = 0; i < nr_cache_blocks; i++) + bcache_invalidate_di(f->cache, i); + _cycle(f, nr_cache_blocks); +} + +/*---------------------------------------------------------------- + * Top level + *--------------------------------------------------------------*/ +#define T(path, desc, fn) register_test(ts, "/base/device/bcache/" path, desc, fn) + +static struct test_suite *_tiny_tests(void) +{ + struct test_suite *ts = test_suite_create(NULL, NULL); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("create-destroy", "simple create/destroy", test_create); + T("cache-blocks-positive", "nr cache blocks must be positive", test_nr_cache_blocks_must_be_positive); + T("block-size-positive", "block size must be positive", test_block_size_must_be_positive); + T("block-size-multiple-page", "block size must be a multiple of page size", test_block_size_must_be_multiple_of_page_size); + + return ts; +} + +static struct test_suite *_small_tests(void) +{ + struct test_suite *ts = test_suite_create(_small_fixture_init, _small_fixture_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("get-reads", "bcache_get() triggers read", test_get_triggers_read); + T("reads-cached", "repeated reads are cached", test_repeated_reads_are_cached); + T("blocks-get-evicted", "block get evicted with many reads", test_block_gets_evicted_with_many_reads); + T("prefetch-reads", "prefetch issues a read", test_prefetch_issues_a_read); + T("prefetch-never-waits", "too many prefetches does not trigger a wait", test_too_many_prefetches_does_not_trigger_a_wait); + T("writeback-occurs", "dirty data gets written back", test_dirty_data_gets_written_back); + T("zero-flag-dirties", "zeroed data counts as dirty", test_zeroed_data_counts_as_dirty); + T("read-multiple-files", "read from multiple files", test_multiple_files); + T("read-bad-issue", "read fails if io engine unable to issue", test_read_bad_issue); + T("read-bad-issue-intermittent", "failed issue, followed by succes", test_read_bad_issue_intermittent); + T("read-bad-io", "read issued ok, but io fails", test_read_bad_wait); + T("read-bad-io-intermittent", "failed io, followed by success", test_read_bad_wait_intermittent); + T("write-bad-issue-stops-flush", "flush fails temporarily if any block fails to write", test_write_bad_issue_stops_flush); + T("write-bad-io-stops-flush", "flush fails temporarily if any block fails to write", test_write_bad_io_stops_flush); + T("invalidate-not-present", "invalidate a block that isn't in the cache", test_invalidate_not_present); + T("invalidate-present", "invalidate a block that is in the cache", test_invalidate_present); + T("invalidate-read-error", "invalidate a block that errored", test_invalidate_after_read_error); + T("invalidate-write-error", "invalidate a block that errored", test_invalidate_after_write_error); + T("invalidate-fails-in-held", "invalidating a held block fails", test_invalidate_held_block); + + T("abort-with-no-blocks", "you can call abort, even if there are no blocks in the cache", test_abort_no_blocks); + T("abort-single-block", "single block get silently discarded", test_abort_single_block); + T("abort-forces-read", "if a block has been discarded then another read is necc.", test_abort_forces_reread); + T("abort-specific-di", "abort doesn't effect other dis", test_abort_only_specific_di); + + T("concurrent-reads-after-invalidate", "prefetch should still issue concurrent reads after invalidate", + test_concurrent_reads_after_invalidate); + + return ts; +} + +static struct test_suite *_large_tests(void) +{ + struct test_suite *ts = test_suite_create(_large_fixture_init, _large_fixture_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("flush-waits", "flush waits for all dirty", test_flush_waits_for_all_dirty); + + return ts; +} + +void bcache_tests(struct dm_list *all_tests) +{ + dm_list_add(all_tests, &_tiny_tests()->list); + dm_list_add(all_tests, &_small_tests()->list); + dm_list_add(all_tests, &_large_tests()->list); +} diff --git a/test/unit/bcache_utils_t.c b/test/unit/bcache_utils_t.c new file mode 100644 index 0000000..f052924 --- /dev/null +++ b/test/unit/bcache_utils_t.c @@ -0,0 +1,474 @@ +/* + * Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "units.h" +#include "lib/device/bcache.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +//---------------------------------------------------------------- + +#define T_BLOCK_SIZE (PAGE_SIZE) +#define NR_BLOCKS 64 +#define INIT_PATTERN 123 + +struct fixture { + int fd; + int di; + char fname[32]; + struct bcache *cache; +}; + +static inline uint8_t _pattern_at(uint8_t pat, uint8_t byte) +{ + return pat + byte; +} + +static uint64_t byte(block_address b, uint64_t offset) +{ + return b * T_BLOCK_SIZE + offset; +} + +static void *_fix_init(struct io_engine *engine) +{ + uint8_t buffer[T_BLOCK_SIZE]; + struct fixture *f = malloc(sizeof(*f)); + unsigned b, i; + static int _runs_is_tmpfs = -1; + + memset(buffer, 0, sizeof(buffer)); + T_ASSERT(f); + + if (_runs_is_tmpfs == -1) { + snprintf(f->fname, sizeof(f->fname), "unit-test-XXXXXX"); + /* coverity[secure_temp] don't care */ + f->fd = mkstemp(f->fname); + T_ASSERT(f->fd >= 0); + (void) close(f->fd); + // test if we can reopen with O_DIRECT + if ((f->fd = open(f->fname, O_RDWR | O_DIRECT)) >= 0) { + _runs_is_tmpfs = 0; + (void) close(f->fd); + } else { + _runs_is_tmpfs = 1; // likely running on tmpfs + printf(" Running test in tmpfs, *NOT* using O_DIRECT\n"); + } + (void) unlink(f->fname); + } + + snprintf(f->fname, sizeof(f->fname), "unit-test-XXXXXX"); + /* coverity[secure_temp] don't care */ + f->fd = mkstemp(f->fname); + T_ASSERT(f->fd >= 0); + + for (b = 0; b < NR_BLOCKS; b++) { + for (i = 0; i < sizeof(buffer); i++) + buffer[i] = _pattern_at(INIT_PATTERN, byte(b, i)); + T_ASSERT(write(f->fd, buffer, T_BLOCK_SIZE) > 0); + } + + if (!_runs_is_tmpfs) { + (void) close(f->fd); + // reopen with O_DIRECT + f->fd = open(f->fname, O_RDWR | O_DIRECT); + T_ASSERT(f->fd >= 0); + } + + f->cache = bcache_create(T_BLOCK_SIZE / 512, NR_BLOCKS, engine); + T_ASSERT(f->cache); + + f->di = bcache_set_fd(f->fd); + + return f; +} + +static void *_async_init(void) +{ + struct io_engine *e = create_async_io_engine(); + T_ASSERT(e); + return _fix_init(e); +} + +static void *_sync_init(void) +{ + struct io_engine *e = create_sync_io_engine(); + T_ASSERT(e); + return _fix_init(e); +} + +static void _fix_exit(void *fixture) +{ + struct fixture *f = fixture; + + if (f) { + bcache_destroy(f->cache); + (void) close(f->fd); + bcache_clear_fd(f->di); + (void) unlink(f->fname); + free(f); + } +} + +//---------------------------------------------------------------- + +static void _verify_bytes(struct block *b, uint64_t base, + uint64_t offset, uint64_t len, uint8_t pat) +{ + unsigned i; + + for (i = 0; i < len; i++) + T_ASSERT_EQUAL(((uint8_t *) b->data)[offset + i], _pattern_at(pat, base + offset + i)); +} + +static uint64_t _min(uint64_t lhs, uint64_t rhs) +{ + return rhs < lhs ? rhs : lhs; +} + +static void _verify(struct fixture *f, uint64_t byte_b, uint64_t byte_e, uint8_t pat) +{ + struct block *b; + block_address bb = byte_b / T_BLOCK_SIZE; + block_address be = (byte_e + T_BLOCK_SIZE - 1) / T_BLOCK_SIZE; + uint64_t offset = byte_b % T_BLOCK_SIZE; + uint64_t blen, len = byte_e - byte_b; + + // Verify via bcache_read_bytes + { + unsigned i; + size_t len2 = byte_e - byte_b; + uint8_t *buffer = malloc(len2); + + T_ASSERT(buffer); + memset(buffer, 0, len2); + + T_ASSERT(bcache_read_bytes(f->cache, f->di, byte_b, len2, buffer)); + for (i = 0; i < len; i++) + T_ASSERT_EQUAL(buffer[i], _pattern_at(pat, byte_b + i)); + free(buffer); + } + + // Verify again, driving bcache directly + for (; bb != be; bb++) { + T_ASSERT(bcache_get(f->cache, f->di, bb, 0, &b)); + + blen = _min(T_BLOCK_SIZE - offset, len); + _verify_bytes(b, bb * T_BLOCK_SIZE, offset, blen, pat); + + offset = 0; + len -= blen; + + bcache_put(b); + } +} + +static void _verify_set(struct fixture *f, uint64_t byte_b, uint64_t byte_e, uint8_t val) +{ + unsigned i; + struct block *b; + block_address bb = byte_b / T_BLOCK_SIZE; + block_address be = (byte_e + T_BLOCK_SIZE - 1) / T_BLOCK_SIZE; + uint64_t offset = byte_b % T_BLOCK_SIZE; + uint64_t blen, len = byte_e - byte_b; + + for (; bb != be; bb++) { + T_ASSERT(bcache_get(f->cache, f->di, bb, 0, &b)); + + blen = _min(T_BLOCK_SIZE - offset, len); + for (i = 0; i < blen; i++) + T_ASSERT(((uint8_t *) b->data)[offset + i] == val); + + offset = 0; + len -= blen; + + bcache_put(b); + } +} + +static void _verify_zeroes(struct fixture *f, uint64_t byte_b, uint64_t byte_e) +{ + _verify_set(f, byte_b, byte_e, 0); +} + +static void _do_write(struct fixture *f, uint64_t byte_b, uint64_t byte_e, uint8_t pat) +{ + unsigned i; + size_t len = byte_e - byte_b; + uint8_t *buffer = malloc(len); + + T_ASSERT(buffer); + memset(buffer, 0, len); + + for (i = 0; i < len; i++) + buffer[i] = _pattern_at(pat, byte_b + i); + + T_ASSERT(bcache_write_bytes(f->cache, f->di, byte_b, byte_e - byte_b, buffer)); + free(buffer); +} + +static void _do_zero(struct fixture *f, uint64_t byte_b, uint64_t byte_e) +{ + T_ASSERT(bcache_zero_bytes(f->cache, f->di, byte_b, byte_e - byte_b)); +} + +static void _do_set(struct fixture *f, uint64_t byte_b, uint64_t byte_e, uint8_t val) +{ + T_ASSERT(bcache_set_bytes(f->cache, f->di, byte_b, byte_e - byte_b, val)); +} + +static void _reopen(struct fixture *f) +{ + struct io_engine *engine; + + bcache_destroy(f->cache); + engine = create_async_io_engine(); + T_ASSERT(engine); + + f->cache = bcache_create(T_BLOCK_SIZE / 512, NR_BLOCKS, engine); + T_ASSERT(f->cache); + + f->di = bcache_set_fd(f->fd); +} + +//---------------------------------------------------------------- + +static uint8_t _random_pattern(void) +{ + /* coverity[dont_call] don't care */ + return random(); +} + +static uint64_t _max_byte(void) +{ + return T_BLOCK_SIZE * NR_BLOCKS; +} + +static void _rwv_cycle(struct fixture *f, uint64_t b, uint64_t e) +{ + uint8_t pat = _random_pattern(); + + _verify(f, b, e, INIT_PATTERN); + _do_write(f, b, e, pat); + _reopen(f); + _verify(f, b < 128 ? 0 : b - 128, b, INIT_PATTERN); + _verify(f, b, e, pat); + _verify(f, e, _min(e + 128, _max_byte()), INIT_PATTERN); +} + +static void _test_rw_first_block(void *fixture) +{ + _rwv_cycle(fixture, byte(0, 0), byte(0, T_BLOCK_SIZE)); +} + +static void _test_rw_last_block(void *fixture) +{ + uint64_t last_block = NR_BLOCKS - 1; + _rwv_cycle(fixture, byte(last_block, 0), + byte(last_block, T_BLOCK_SIZE)); +} + +static void _test_rw_several_whole_blocks(void *fixture) +{ + _rwv_cycle(fixture, byte(5, 0), byte(10, 0)); +} + +static void _test_rw_within_single_block(void *fixture) +{ + _rwv_cycle(fixture, byte(7, 3), byte(7, T_BLOCK_SIZE / 2)); +} + +static void _test_rw_cross_one_boundary(void *fixture) +{ + _rwv_cycle(fixture, byte(13, 43), byte(14, 43)); +} + +static void _test_rw_many_boundaries(void *fixture) +{ + _rwv_cycle(fixture, byte(13, 13), byte(23, 13)); +} + +//---------------------------------------------------------------- + +static void _zero_cycle(struct fixture *f, uint64_t b, uint64_t e) +{ + _verify(f, b, e, INIT_PATTERN); + _do_zero(f, b, e); + _reopen(f); + _verify(f, b < 128 ? 0 : b - 128, b, INIT_PATTERN); + _verify_zeroes(f, b, e); + _verify(f, e, _min(e + 128, _max_byte()), INIT_PATTERN); +} + +static void _test_zero_first_block(void *fixture) +{ + _zero_cycle(fixture, byte(0, 0), byte(0, T_BLOCK_SIZE)); +} + +static void _test_zero_last_block(void *fixture) +{ + uint64_t last_block = NR_BLOCKS - 1; + _zero_cycle(fixture, byte(last_block, 0), byte(last_block, T_BLOCK_SIZE)); +} + +static void _test_zero_several_whole_blocks(void *fixture) +{ + _zero_cycle(fixture, byte(5, 0), byte(10, 0)); +} + +static void _test_zero_within_single_block(void *fixture) +{ + _zero_cycle(fixture, byte(7, 3), byte(7, T_BLOCK_SIZE / 2)); +} + +static void _test_zero_cross_one_boundary(void *fixture) +{ + _zero_cycle(fixture, byte(13, 43), byte(14, 43)); +} + +static void _test_zero_many_boundaries(void *fixture) +{ + _zero_cycle(fixture, byte(13, 13), byte(23, 13)); +} + +//---------------------------------------------------------------- + +static void _set_cycle(struct fixture *f, uint64_t b, uint64_t e) +{ + uint8_t val = _random_pattern(); + + _verify(f, b, e, INIT_PATTERN); + _do_set(f, b, e, val); + _reopen(f); + _verify(f, b < 128 ? 0 : b - 128, b, INIT_PATTERN); + _verify_set(f, b, e, val); + _verify(f, e, _min(e + 128, _max_byte()), INIT_PATTERN); +} + +static void _test_set_first_block(void *fixture) +{ + _set_cycle(fixture, byte(0, 0), byte(0, T_BLOCK_SIZE)); +} + +static void _test_set_last_block(void *fixture) +{ + uint64_t last_block = NR_BLOCKS - 1; + _set_cycle(fixture, byte(last_block, 0), byte(last_block, T_BLOCK_SIZE)); +} + +static void _test_set_several_whole_blocks(void *fixture) +{ + _set_cycle(fixture, byte(5, 0), byte(10, 0)); +} + +static void _test_set_within_single_block(void *fixture) +{ + _set_cycle(fixture, byte(7, 3), byte(7, T_BLOCK_SIZE / 2)); +} + +static void _test_set_cross_one_boundary(void *fixture) +{ + _set_cycle(fixture, byte(13, 43), byte(14, 43)); +} + +static void _test_set_many_boundaries(void *fixture) +{ + _set_cycle(fixture, byte(13, 13), byte(23, 13)); +} + +//---------------------------------------------------------------- + +#define T(path, desc, fn) register_test(ts, "/base/device/bcache/utils/async/" path, desc, fn) + +static struct test_suite *_async_tests(void) +{ + struct test_suite *ts = test_suite_create(_async_init, _fix_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + +#define T(path, desc, fn) register_test(ts, "/base/device/bcache/utils/async/" path, desc, fn) + T("rw-first-block", "read/write/verify the first block", _test_rw_first_block); + T("rw-last-block", "read/write/verify the last block", _test_rw_last_block); + T("rw-several-blocks", "read/write/verify several whole blocks", _test_rw_several_whole_blocks); + T("rw-within-single-block", "read/write/verify within single block", _test_rw_within_single_block); + T("rw-cross-one-boundary", "read/write/verify across one boundary", _test_rw_cross_one_boundary); + T("rw-many-boundaries", "read/write/verify many boundaries", _test_rw_many_boundaries); + + T("zero-first-block", "zero the first block", _test_zero_first_block); + T("zero-last-block", "zero the last block", _test_zero_last_block); + T("zero-several-blocks", "zero several whole blocks", _test_zero_several_whole_blocks); + T("zero-within-single-block", "zero within single block", _test_zero_within_single_block); + T("zero-cross-one-boundary", "zero across one boundary", _test_zero_cross_one_boundary); + T("zero-many-boundaries", "zero many boundaries", _test_zero_many_boundaries); + + T("set-first-block", "set the first block", _test_set_first_block); + T("set-last-block", "set the last block", _test_set_last_block); + T("set-several-blocks", "set several whole blocks", _test_set_several_whole_blocks); + T("set-within-single-block", "set within single block", _test_set_within_single_block); + T("set-cross-one-boundary", "set across one boundary", _test_set_cross_one_boundary); + T("set-many-boundaries", "set many boundaries", _test_set_many_boundaries); +#undef T + + return ts; +} + + +static struct test_suite *_sync_tests(void) +{ + struct test_suite *ts = test_suite_create(_sync_init, _fix_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + +#define T(path, desc, fn) register_test(ts, "/base/device/bcache/utils/sync/" path, desc, fn) + T("rw-first-block", "read/write/verify the first block", _test_rw_first_block); + T("rw-last-block", "read/write/verify the last block", _test_rw_last_block); + T("rw-several-blocks", "read/write/verify several whole blocks", _test_rw_several_whole_blocks); + T("rw-within-single-block", "read/write/verify within single block", _test_rw_within_single_block); + T("rw-cross-one-boundary", "read/write/verify across one boundary", _test_rw_cross_one_boundary); + T("rw-many-boundaries", "read/write/verify many boundaries", _test_rw_many_boundaries); + + T("zero-first-block", "zero the first block", _test_zero_first_block); + T("zero-last-block", "zero the last block", _test_zero_last_block); + T("zero-several-blocks", "zero several whole blocks", _test_zero_several_whole_blocks); + T("zero-within-single-block", "zero within single block", _test_zero_within_single_block); + T("zero-cross-one-boundary", "zero across one boundary", _test_zero_cross_one_boundary); + T("zero-many-boundaries", "zero many boundaries", _test_zero_many_boundaries); + + T("set-first-block", "set the first block", _test_set_first_block); + T("set-last-block", "set the last block", _test_set_last_block); + T("set-several-blocks", "set several whole blocks", _test_set_several_whole_blocks); + T("set-within-single-block", "set within single block", _test_set_within_single_block); + T("set-cross-one-boundary", "set across one boundary", _test_set_cross_one_boundary); + T("set-many-boundaries", "set many boundaries", _test_set_many_boundaries); +#undef T + + return ts; +} + +void bcache_utils_tests(struct dm_list *all_tests) +{ + dm_list_add(all_tests, &_async_tests()->list); + dm_list_add(all_tests, &_sync_tests()->list); +} + diff --git a/test/unit/bitset_t.c b/test/unit/bitset_t.c index 499de32..1e74e12 100644 --- a/test/unit/bitset_t.c +++ b/test/unit/bitset_t.c @@ -9,38 +9,43 @@ * * 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 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libdevmapper.h" -#include - -int bitset_init(void); -int bitset_fini(void); +#include "units.h" +#include "device_mapper/all.h" enum { NR_BITS = 137 }; -static struct dm_pool *mem; +static void *_mem_init(void) { + struct dm_pool *mem = dm_pool_create("bitset test", 1024); + if (!mem) { + fprintf(stderr, "out of memory\n"); + exit(1); + } -int bitset_init(void) { - mem = dm_pool_create("bitset test", 1024); - return mem == NULL; + return mem; } -int bitset_fini(void) { - dm_pool_destroy(mem); - return 0; +static void _mem_exit(void *mem) +{ + if (mem) + dm_pool_destroy(mem); } -static void test_get_next(void) +static void test_get_next(void *fixture) { + struct dm_pool *mem = fixture; + int i, j, last = 0, first; dm_bitset_t bs = dm_bitset_create(mem, NR_BITS); + T_ASSERT(bs); + for (i = 0; i < NR_BITS; i++) - CU_ASSERT(!dm_bit(bs, i)); + T_ASSERT(!dm_bit(bs, i)); for (i = 0, j = 1; i < NR_BITS; i += j, j++) dm_bit_set(bs, i); @@ -53,10 +58,10 @@ static void test_get_next(void) } else last = dm_bit_get_next(bs, last); - CU_ASSERT(last == i); + T_ASSERT(last == i); } - CU_ASSERT(dm_bit_get_next(bs, last) == -1); + T_ASSERT(dm_bit_get_next(bs, last) == -1); } static void bit_flip(dm_bitset_t bs, int bit) @@ -68,37 +73,48 @@ static void bit_flip(dm_bitset_t bs, int bit) dm_bit_set(bs, bit); } -static void test_equal(void) +static void test_equal(void *fixture) { + struct dm_pool *mem = fixture; dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS); dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS); - int i, j; + int i, j; + + T_ASSERT(bs1); + T_ASSERT(bs2); + for (i = 0, j = 1; i < NR_BITS; i += j, j++) { dm_bit_set(bs1, i); dm_bit_set(bs2, i); } - CU_ASSERT(dm_bitset_equal(bs1, bs2)); - CU_ASSERT(dm_bitset_equal(bs2, bs1)); + T_ASSERT(dm_bitset_equal(bs1, bs2)); + T_ASSERT(dm_bitset_equal(bs2, bs1)); for (i = 0; i < NR_BITS; i++) { bit_flip(bs1, i); - CU_ASSERT(!dm_bitset_equal(bs1, bs2)); - CU_ASSERT(!dm_bitset_equal(bs2, bs1)); + T_ASSERT(!dm_bitset_equal(bs1, bs2)); + T_ASSERT(!dm_bitset_equal(bs2, bs1)); - CU_ASSERT(dm_bitset_equal(bs1, bs1)); /* comparing with self */ + T_ASSERT(dm_bitset_equal(bs1, bs1)); /* comparing with self */ bit_flip(bs1, i); } } -static void test_and(void) +static void test_and(void *fixture) { + struct dm_pool *mem = fixture; dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS); dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS); dm_bitset_t bs3 = dm_bitset_create(mem, NR_BITS); - int i, j; + int i, j; + + T_ASSERT(bs1); + T_ASSERT(bs2); + T_ASSERT(bs3); + for (i = 0, j = 1; i < NR_BITS; i += j, j++) { dm_bit_set(bs1, i); dm_bit_set(bs2, i); @@ -106,9 +122,9 @@ static void test_and(void) dm_bit_and(bs3, bs1, bs2); - CU_ASSERT(dm_bitset_equal(bs1, bs2)); - CU_ASSERT(dm_bitset_equal(bs1, bs3)); - CU_ASSERT(dm_bitset_equal(bs2, bs3)); + T_ASSERT(dm_bitset_equal(bs1, bs2)); + T_ASSERT(dm_bitset_equal(bs1, bs3)); + T_ASSERT(dm_bitset_equal(bs2, bs3)); dm_bit_clear_all(bs1); dm_bit_clear_all(bs2); @@ -122,12 +138,23 @@ static void test_and(void) dm_bit_and(bs3, bs1, bs2); for (i = 0; i < NR_BITS; i++) - CU_ASSERT(!dm_bit(bs3, i)); + T_ASSERT(!dm_bit(bs3, i)); +} + +#define T(path, desc, fn) register_test(ts, "/base/data-struct/bitset/" path, desc, fn) + +void bitset_tests(struct dm_list *all_tests) +{ + struct test_suite *ts = test_suite_create(_mem_init, _mem_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("get_next", "get next set bit", test_get_next); + T("equal", "equality", test_equal); + T("and", "and all bits", test_and); + + dm_list_add(all_tests, &ts->list); } -CU_TestInfo bitset_list[] = { - { (char*)"get_next", test_get_next }, - { (char*)"equal", test_equal }, - { (char*)"and", test_and }, - CU_TEST_INFO_NULL -}; diff --git a/test/unit/config_t.c b/test/unit/config_t.c index 9a8b693..cd539ab 100644 --- a/test/unit/config_t.c +++ b/test/unit/config_t.c @@ -9,25 +9,26 @@ * * 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 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libdevmapper.h" -#include +#include "units.h" +#include "device_mapper/all.h" -int config_init(void); -int config_fini(void); - -static struct dm_pool *mem; +static void *_mem_init(void) +{ + struct dm_pool *mem = dm_pool_create("config test", 1024); + if (!mem) { + fprintf(stderr, "out of memory\n"); + exit(1); + } -int config_init(void) { - mem = dm_pool_create("config test", 1024); - return mem == NULL; + return mem; } -int config_fini(void) { +static void _mem_exit(void *mem) +{ dm_pool_destroy(mem); - return 0; } static const char *conf = @@ -60,97 +61,120 @@ static const char *overlay = " }\n" "}\n"; -static void test_parse(void) +static void test_parse(void *fixture) { struct dm_config_tree *tree = dm_config_from_string(conf); const struct dm_config_value *value; - CU_ASSERT((long) tree); - CU_ASSERT(dm_config_has_node(tree->root, "id")); - CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes")); - CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0")); - CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0/id")); + T_ASSERT((long) tree); + T_ASSERT(dm_config_has_node(tree->root, "id")); + T_ASSERT(dm_config_has_node(tree->root, "physical_volumes")); + T_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0")); + T_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0/id")); - CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "id", "foo"), "yada-yada")); - CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "idt", "foo"), "foo")); + T_ASSERT(!strcmp(dm_config_find_str(tree->root, "id", "foo"), "yada-yada")); + T_ASSERT(!strcmp(dm_config_find_str(tree->root, "idt", "foo"), "foo")); - CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/bb", "foo"), "foo")); - CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/id", "foo"), "abcd-efgh")); + T_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/bb", "foo"), "foo")); + T_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/id", "foo"), "abcd-efgh")); - CU_ASSERT(!dm_config_get_uint32(tree->root, "id", NULL)); - CU_ASSERT(dm_config_get_uint32(tree->root, "extent_size", NULL)); + T_ASSERT(!dm_config_get_uint32(tree->root, "id", NULL)); + T_ASSERT(dm_config_get_uint32(tree->root, "extent_size", NULL)); /* FIXME: Currently everything parses as a list, even if it's not */ - // CU_ASSERT(!dm_config_get_list(tree->root, "id", NULL)); - // CU_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL)); + // T_ASSERT(!dm_config_get_list(tree->root, "id", NULL)); + // T_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL)); - CU_ASSERT(dm_config_get_list(tree->root, "flags", &value)); - CU_ASSERT(value->next == NULL); /* an empty list */ - CU_ASSERT(dm_config_get_list(tree->root, "status", &value)); - CU_ASSERT(value->next != NULL); /* a non-empty list */ + T_ASSERT(dm_config_get_list(tree->root, "flags", &value)); + T_ASSERT(value->next == NULL); /* an empty list */ + T_ASSERT(dm_config_get_list(tree->root, "status", &value)); + T_ASSERT(value->next != NULL); /* a non-empty list */ dm_config_destroy(tree); } -static void test_clone(void) +static void test_clone(void *fixture) { struct dm_config_tree *tree = dm_config_from_string(conf); - struct dm_config_node *n = dm_config_clone_node(tree, tree->root, 1); + struct dm_config_node *n; const struct dm_config_value *value; + T_ASSERT(tree); + + n = dm_config_clone_node(tree, tree->root, 1); + + T_ASSERT(n); + /* Check that the nodes are actually distinct. */ - CU_ASSERT(n != tree->root); - CU_ASSERT(n->sib != tree->root->sib); - CU_ASSERT(dm_config_find_node(n, "physical_volumes") != NULL); - CU_ASSERT(dm_config_find_node(tree->root, "physical_volumes") != NULL); - CU_ASSERT(dm_config_find_node(n, "physical_volumes") != dm_config_find_node(tree->root, "physical_volumes")); + T_ASSERT(n != tree->root); + T_ASSERT(n->sib != tree->root->sib); + T_ASSERT(dm_config_find_node(n, "physical_volumes") != NULL); + T_ASSERT(dm_config_find_node(tree->root, "physical_volumes") != NULL); + T_ASSERT(dm_config_find_node(n, "physical_volumes") != dm_config_find_node(tree->root, "physical_volumes")); - CU_ASSERT(dm_config_has_node(n, "id")); - CU_ASSERT(dm_config_has_node(n, "physical_volumes")); - CU_ASSERT(dm_config_has_node(n, "physical_volumes/pv0")); - CU_ASSERT(dm_config_has_node(n, "physical_volumes/pv0/id")); + T_ASSERT(dm_config_has_node(n, "id")); + T_ASSERT(dm_config_has_node(n, "physical_volumes")); + T_ASSERT(dm_config_has_node(n, "physical_volumes/pv0")); + T_ASSERT(dm_config_has_node(n, "physical_volumes/pv0/id")); - CU_ASSERT(!strcmp(dm_config_find_str(n, "id", "foo"), "yada-yada")); - CU_ASSERT(!strcmp(dm_config_find_str(n, "idt", "foo"), "foo")); + T_ASSERT(!strcmp(dm_config_find_str(n, "id", "foo"), "yada-yada")); + T_ASSERT(!strcmp(dm_config_find_str(n, "idt", "foo"), "foo")); - CU_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/bb", "foo"), "foo")); - CU_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/id", "foo"), "abcd-efgh")); + T_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/bb", "foo"), "foo")); + T_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/id", "foo"), "abcd-efgh")); - CU_ASSERT(!dm_config_get_uint32(n, "id", NULL)); - CU_ASSERT(dm_config_get_uint32(n, "extent_size", NULL)); + T_ASSERT(!dm_config_get_uint32(n, "id", NULL)); + T_ASSERT(dm_config_get_uint32(n, "extent_size", NULL)); /* FIXME: Currently everything parses as a list, even if it's not */ - // CU_ASSERT(!dm_config_get_list(tree->root, "id", NULL)); - // CU_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL)); + // T_ASSERT(!dm_config_get_list(tree->root, "id", NULL)); + // T_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL)); - CU_ASSERT(dm_config_get_list(n, "flags", &value)); - CU_ASSERT(value->next == NULL); /* an empty list */ - CU_ASSERT(dm_config_get_list(n, "status", &value)); - CU_ASSERT(value->next != NULL); /* a non-empty list */ + T_ASSERT(dm_config_get_list(n, "flags", &value)); + T_ASSERT(value->next == NULL); /* an empty list */ + T_ASSERT(dm_config_get_list(n, "status", &value)); + T_ASSERT(value->next != NULL); /* a non-empty list */ dm_config_destroy(tree); } -static void test_cascade(void) +static void test_cascade(void *fixture) { struct dm_config_tree *t1 = dm_config_from_string(conf), *t2 = dm_config_from_string(overlay), - *tree = dm_config_insert_cascaded_tree(t2, t1); + *tree; + + T_ASSERT(t1); + T_ASSERT(t2); - CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "id", "foo"), "yoda-soda")); - CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "idt", "foo"), "foo")); + tree = dm_config_insert_cascaded_tree(t2, t1); - CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv0/bb", "foo"), "foo")); - CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv1/id", "foo"), "hgfe-dcba")); - CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv3/id", "foo"), "dbcd-efgh")); + T_ASSERT(tree); + + T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "id", "foo"), "yoda-soda")); + T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "idt", "foo"), "foo")); + + T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv0/bb", "foo"), "foo")); + T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv1/id", "foo"), "hgfe-dcba")); + T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv3/id", "foo"), "dbcd-efgh")); dm_config_destroy(t1); dm_config_destroy(t2); } -CU_TestInfo config_list[] = { - { (char*)"parse", test_parse }, - { (char*)"clone", test_clone }, - { (char*)"cascade", test_cascade }, - CU_TEST_INFO_NULL +#define T(path, desc, fn) register_test(ts, "/metadata/config/" path, desc, fn) + +void config_tests(struct dm_list *all_tests) +{ + struct test_suite *ts = test_suite_create(_mem_init, _mem_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("parse", "parsing various", test_parse); + T("clone", "duplicating a config tree", test_clone); + T("cascade", "cascade", test_cascade); + + dm_list_add(all_tests, &ts->list); }; diff --git a/test/unit/dmlist_t.c b/test/unit/dmlist_t.c new file mode 100644 index 0000000..0e33385 --- /dev/null +++ b/test/unit/dmlist_t.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "units.h" +#include "device_mapper/all.h" + +static void test_dmlist_splice(void *fixture) +{ + unsigned i; + struct dm_list a[10]; + struct dm_list list1; + struct dm_list list2; + + dm_list_init(&list1); + dm_list_init(&list2); + + for (i = 0; i < DM_ARRAY_SIZE(a); i++) + dm_list_add(&list1, &a[i]); + + dm_list_splice(&list2, &list1); + T_ASSERT(dm_list_size(&list1) == 0); + T_ASSERT(dm_list_size(&list2) == 10); +} + +#define T(path, desc, fn) register_test(ts, "/base/data-struct/list/" path, desc, fn) + +void dm_list_tests(struct dm_list *all_tests) +{ + struct test_suite *ts = test_suite_create(NULL, NULL); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("splice", "joining lists together", test_dmlist_splice); + + dm_list_add(all_tests, &ts->list); +} diff --git a/test/unit/dmstatus_t.c b/test/unit/dmstatus_t.c new file mode 100644 index 0000000..ac2015e --- /dev/null +++ b/test/unit/dmstatus_t.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "units.h" +#include "device_mapper/all.h" + +static void *_mem_init(void) +{ + struct dm_pool *mem = dm_pool_create("dmstatus test", 1024); + if (!mem) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + return mem; +} + +static void _mem_exit(void *mem) +{ + dm_pool_destroy(mem); +} + +static void _test_mirror_status(void *fixture) +{ + struct dm_pool *mem = fixture; + struct dm_status_mirror *s = NULL; + + T_ASSERT(dm_get_status_mirror(mem, + "2 253:1 253:2 80/81 1 AD 3 disk 253:0 A", + &s)); + if (s) { + T_ASSERT_EQUAL(s->total_regions, 81); + T_ASSERT_EQUAL(s->insync_regions, 80); + T_ASSERT_EQUAL(s->dev_count, 2); + T_ASSERT_EQUAL(s->devs[0].health, 'A'); + T_ASSERT_EQUAL(s->devs[0].major, 253); + T_ASSERT_EQUAL(s->devs[0].minor, 1); + T_ASSERT_EQUAL(s->devs[1].health, 'D'); + T_ASSERT_EQUAL(s->devs[1].major, 253); + T_ASSERT_EQUAL(s->devs[1].minor, 2); + T_ASSERT_EQUAL(s->log_count, 1); + T_ASSERT_EQUAL(s->logs[0].major, 253); + T_ASSERT_EQUAL(s->logs[0].minor, 0); + T_ASSERT_EQUAL(s->logs[0].health, 'A'); + T_ASSERT(!strcmp(s->log_type, "disk")); + } + + T_ASSERT(dm_get_status_mirror(mem, + "4 253:1 253:2 253:3 253:4 10/10 1 ADFF 1 core", + &s)); + if (s) { + T_ASSERT_EQUAL(s->total_regions, 10); + T_ASSERT_EQUAL(s->insync_regions, 10); + T_ASSERT_EQUAL(s->dev_count, 4); + T_ASSERT_EQUAL(s->devs[3].minor, 4); + T_ASSERT_EQUAL(s->devs[3].health, 'F'); + T_ASSERT_EQUAL(s->log_count, 0); + T_ASSERT(!strcmp(s->log_type, "core")); + } +} + +void dm_status_tests(struct dm_list *all_tests) +{ + struct test_suite *ts = test_suite_create(_mem_init, _mem_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + register_test(ts, "/device-mapper/mirror/status", "parsing mirror status", _test_mirror_status); + dm_list_add(all_tests, &ts->list); +} + diff --git a/test/unit/framework.c b/test/unit/framework.c new file mode 100644 index 0000000..de9a8b1 --- /dev/null +++ b/test/unit/framework.c @@ -0,0 +1,66 @@ +#include "framework.h" + +/*---------------------------------------------------------------- + * Assertions + *--------------------------------------------------------------*/ + +jmp_buf test_k; +#define TEST_FAILED 1 + +void test_fail(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + longjmp(test_k, TEST_FAILED); +} + +struct test_suite *test_suite_create(void *(*fixture_init)(void), + void (*fixture_exit)(void *)) +{ + struct test_suite *ts = malloc(sizeof(*ts)); + if (ts) { + ts->fixture_init = fixture_init; + ts->fixture_exit = fixture_exit; + dm_list_init(&ts->tests); + } + + return ts; +} + +void test_suite_destroy(struct test_suite *ts) +{ + struct test_details *td, *tmp; + + dm_list_iterate_items_safe (td, tmp, &ts->tests) { + dm_list_del(&td->list); + free(td); + } + + free(ts); +} + +bool register_test(struct test_suite *ts, + const char *path, const char *desc, + void (*fn)(void *)) +{ + struct test_details *t = malloc(sizeof(*t)); + if (!t) { + fprintf(stderr, "out of memory\n"); + return false; + } + + t->parent = ts; + t->path = path; + t->desc = desc; + t->fn = fn; + dm_list_add(&ts->tests, &t->list); + + return true; +} + +//----------------------------------------------------------------- diff --git a/test/unit/framework.h b/test/unit/framework.h new file mode 100644 index 0000000..f7f5b5b --- /dev/null +++ b/test/unit/framework.h @@ -0,0 +1,51 @@ +#ifndef TEST_UNIT_FRAMEWORK_H +#define TEST_UNIT_FRAMEWORK_H + +#include "device_mapper/all.h" + +#include +#include +#include + +//----------------------------------------------------------------- + +// A test suite gathers a set of tests with a common fixture together. +struct test_suite { + struct dm_list list; + + void *(*fixture_init)(void); + void (*fixture_exit)(void *); + struct dm_list tests; +}; + +struct test_details { + struct test_suite *parent; + struct dm_list list; + + const char *path; + const char *desc; + void (*fn)(void *); +}; + +struct test_suite *test_suite_create(void *(*fixture_init)(void), + void (*fixture_exit)(void *)); +void test_suite_destroy(struct test_suite *ts); + +bool register_test(struct test_suite *ts, + const char *path, const char *desc, void (*fn)(void *)); + +void test_fail(const char *fmt, ...) + __attribute__((noreturn, format (printf, 1, 2))); + +#define T_ASSERT(e) do {if (!(e)) {test_fail("assertion failed: '%s'", # e);} } while(0) +#define T_ASSERT_EQUAL(x, y) T_ASSERT((x) == (y)) +#define T_ASSERT_NOT_EQUAL(x, y) T_ASSERT((x) != (y)) + +extern jmp_buf test_k; +#define TEST_FAILED 1 + +#define PAGE_SIZE ({ int ps = sysconf(_SC_PAGESIZE); (ps > 0) ? ps : 4096 ; }) + +//----------------------------------------------------------------- + +#endif diff --git a/test/unit/io_engine_t.c b/test/unit/io_engine_t.c new file mode 100644 index 0000000..2f6ea5b --- /dev/null +++ b/test/unit/io_engine_t.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "units.h" +#include "lib/device/bcache.h" + +#include +#include +#include +#include +#include +#include +#include + +//---------------------------------------------------------------- + +#define SECTOR_SHIFT 9 +#define SECTOR_SIZE 512 +#define BLOCK_SIZE_SECTORS 8 +#define PAGE_SIZE_SECTORS ((PAGE_SIZE) >> SECTOR_SHIFT) +#define NR_BLOCKS 64 + +struct fixture { + struct io_engine *e; + uint8_t *data; + + char fname[64]; + int fd; + int di; +}; + +static void _fill_buffer(uint8_t *buffer, uint8_t seed, size_t count) +{ + unsigned i; + uint8_t b = seed; + + for (i = 0; i < count; i++) { + buffer[i] = b; + b = ((b << 5) + b) + i; + } +} + +static void _check_buffer(uint8_t *buffer, uint8_t seed, size_t count) +{ + unsigned i; + uint8_t b = seed; + + for (i = 0; i < count; i++) { + T_ASSERT_EQUAL(buffer[i], b); + b = ((b << 5) + b) + i; + } +} + +static void _print_buffer(const char *name, uint8_t *buffer, size_t count) +{ + unsigned col; + + fprintf(stderr, "%s:\n", name); + while (count) { + for (col = 0; count && col < 20; col++) { + fprintf(stderr, "%x, ", (unsigned) *buffer); + col++; + buffer++; + count--; + } + fprintf(stderr, "\n"); + } +} + +static void *_fix_init(void) +{ + struct fixture *f = malloc(sizeof(*f)); + + T_ASSERT(f); + f->e = create_async_io_engine(); + T_ASSERT(f->e); + if (posix_memalign((void **) &f->data, PAGE_SIZE, SECTOR_SIZE * BLOCK_SIZE_SECTORS)) + test_fail("posix_memalign failed"); + + snprintf(f->fname, sizeof(f->fname), "unit-test-XXXXXX"); + /* coverity[secure_temp] don't care */ + f->fd = mkstemp(f->fname); + T_ASSERT(f->fd >= 0); + + _fill_buffer(f->data, 123, SECTOR_SIZE * BLOCK_SIZE_SECTORS); + + T_ASSERT(write(f->fd, f->data, SECTOR_SIZE * BLOCK_SIZE_SECTORS) > 0); + T_ASSERT(lseek(f->fd, 0, SEEK_SET) != -1); + + return f; +} + +static void _fix_exit(void *fixture) +{ + struct fixture *f = fixture; + + if (f) { + (void) close(f->fd); + bcache_clear_fd(f->di); + (void) unlink(f->fname); + free(f->data); + if (f->e) + f->e->destroy(f->e); + free(f); + } +} + +static void _test_create(void *fixture) +{ + // empty +} + +struct io { + bool completed; + int error; +}; + +static void _io_init(struct io *io) +{ + io->completed = false; + io->error = 0; +} + +static void _complete_io(void *context, int io_error) +{ + struct io *io = context; + io->completed = true; + io->error = io_error; +} + +static void _test_read(void *fixture) +{ + struct fixture *f = fixture; + struct io io; + struct bcache *cache = bcache_create(PAGE_SIZE_SECTORS, BLOCK_SIZE_SECTORS, f->e); + T_ASSERT(cache); + + f->di = bcache_set_fd(f->fd); + + T_ASSERT(f->di >= 0); + + _io_init(&io); + T_ASSERT(f->e->issue(f->e, DIR_READ, f->di, 0, BLOCK_SIZE_SECTORS, f->data, &io)); + T_ASSERT(f->e->wait(f->e, _complete_io)); + T_ASSERT(io.completed); + T_ASSERT(!io.error); + + _check_buffer(f->data, 123, SECTOR_SIZE * BLOCK_SIZE_SECTORS); +} + +static void _test_write(void *fixture) +{ + struct fixture *f = fixture; + struct io io; + struct bcache *cache = bcache_create(PAGE_SIZE_SECTORS, BLOCK_SIZE_SECTORS, f->e); + T_ASSERT(cache); + + f->di = bcache_set_fd(f->fd); + + T_ASSERT(f->di >= 0); + + _io_init(&io); + T_ASSERT(f->e->issue(f->e, DIR_WRITE, f->di, 0, BLOCK_SIZE_SECTORS, f->data, &io)); + T_ASSERT(f->e->wait(f->e, _complete_io)); + T_ASSERT(io.completed); + T_ASSERT(!io.error); +} + +static void _test_write_bytes(void *fixture) +{ + struct fixture *f = fixture; + + unsigned offset = 345; + char buf_out[32]; + char buf_in[32]; + struct bcache *cache = bcache_create(PAGE_SIZE_SECTORS, BLOCK_SIZE_SECTORS, f->e); + T_ASSERT(cache); + + f->di = bcache_set_fd(f->fd); + + // T_ASSERT(bcache_read_bytes(cache, f->di, offset, sizeof(buf_in), buf_in)); + _fill_buffer((uint8_t *) buf_out, 234, sizeof(buf_out)); + T_ASSERT(bcache_write_bytes(cache, f->di, offset, sizeof(buf_out), buf_out)); + T_ASSERT(bcache_read_bytes(cache, f->di, offset, sizeof(buf_in), buf_in)); + + _print_buffer("buf_out", (uint8_t *) buf_out, sizeof(buf_out)); + _print_buffer("buf_in", (uint8_t *) buf_in, sizeof(buf_in)); + T_ASSERT(!memcmp(buf_out, buf_in, sizeof(buf_out))); + + bcache_destroy(cache); + f->e = NULL; // already destroyed +} + +//---------------------------------------------------------------- + +#define T(path, desc, fn) register_test(ts, "/base/device/bcache/io-engine/" path, desc, fn) + +static struct test_suite *_tests(void) +{ + struct test_suite *ts = test_suite_create(_fix_init, _fix_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("create-destroy", "simple create/destroy", _test_create); + T("read", "read sanity check", _test_read); + T("write", "write sanity check", _test_write); + T("bcache-write-bytes", "test the utility fns", _test_write_bytes); + + return ts; +} + +void io_engine_tests(struct dm_list *all_tests) +{ + dm_list_add(all_tests, &_tests()->list); +} + diff --git a/test/unit/matcher_t.c b/test/unit/matcher_t.c index 7331a82..89b2988 100644 --- a/test/unit/matcher_t.c +++ b/test/unit/matcher_t.c @@ -10,76 +10,120 @@ * * 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 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libdevmapper.h" -#include "log.h" +#include "units.h" +#include "device_mapper/all.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include "matcher_data.h" -int regex_init(void); -int regex_fini(void); - -static struct dm_pool *mem = NULL; +static void *_mem_init(void) +{ + struct dm_pool *mem = dm_pool_create("bitset test", 1024); + if (!mem) { + fprintf(stderr, "out of memory"); + exit(1); + } -int regex_init(void) { - mem = dm_pool_create("bitset test", 1024); - return mem == NULL; + return mem; } -int regex_fini(void) { +static void _mem_exit(void *mem) +{ dm_pool_destroy(mem); - return 0; } -static struct dm_regex *make_scanner(const char **rx) +static struct dm_regex *make_scanner(struct dm_pool *mem, const char **rx) { struct dm_regex *scanner; int nrx = 0; for (; rx[nrx]; ++nrx); scanner = dm_regex_create(mem, rx, nrx); - CU_ASSERT_FATAL(scanner != NULL); + T_ASSERT(scanner != NULL); return scanner; } -static void test_fingerprints(void) { +static void test_fingerprints(void *fixture) +{ + struct dm_pool *mem = fixture; struct dm_regex *scanner; - scanner = make_scanner(dev_patterns); - CU_ASSERT_EQUAL(dm_regex_fingerprint(scanner), 0x7f556c09); + scanner = make_scanner(mem, dev_patterns); + T_ASSERT_EQUAL(dm_regex_fingerprint(scanner), 0x7f556c09); - scanner = make_scanner(random_patterns); - CU_ASSERT_EQUAL(dm_regex_fingerprint(scanner), 0x9f11076c); + scanner = make_scanner(mem, random_patterns); + T_ASSERT_EQUAL(dm_regex_fingerprint(scanner), 0x9f11076c); } -static void test_matching(void) { +static void test_matching(void *fixture) +{ + struct dm_pool *mem = fixture; struct dm_regex *scanner; int i; - scanner = make_scanner(dev_patterns); + scanner = make_scanner(mem, dev_patterns); for (i = 0; devices[i].str; ++i) - CU_ASSERT_EQUAL(dm_regex_match(scanner, devices[i].str), devices[i].expected - 1); + T_ASSERT_EQUAL(dm_regex_match(scanner, devices[i].str), devices[i].expected - 1); - scanner = make_scanner(nonprint_patterns); + scanner = make_scanner(mem, nonprint_patterns); for (i = 0; nonprint[i].str; ++i) - CU_ASSERT_EQUAL(dm_regex_match(scanner, nonprint[i].str), nonprint[i].expected - 1); + T_ASSERT_EQUAL(dm_regex_match(scanner, nonprint[i].str), nonprint[i].expected - 1); } -CU_TestInfo regex_list[] = { - { (char*)"fingerprints", test_fingerprints }, - { (char*)"matching", test_matching }, - CU_TEST_INFO_NULL -}; +static void test_kabi_query(void *fixture) +{ + // Remember, matches regexes from last to first. + static const char *_patterns[] = { + ".*", ".*/dev/md.*", "loop" + }; + + static struct { + const char *input; + int r; + } _cases[] = { + {"foo", 0}, + {"/dev/mapper/vg-lvol1", 0}, + {"/dev/mapper/vglvol1", 0}, + {"/dev/md1", 1}, + {"loop", 2}, + }; + + int r; + unsigned i; + struct dm_pool *mem = fixture; + struct dm_regex *scanner; + + scanner = dm_regex_create(mem, _patterns, DM_ARRAY_SIZE(_patterns)); + T_ASSERT(scanner != NULL); + + for (i = 0; i < DM_ARRAY_SIZE(_cases); i++) { + r = dm_regex_match(scanner, _cases[i].input); + if (r != _cases[i].r) { + test_fail("'%s' expected to match '%s', but matched %s", + _cases[i].input, + _cases[i].r >= DM_ARRAY_SIZE(_patterns) ? "" : _patterns[_cases[i].r], + r >= DM_ARRAY_SIZE(_patterns) ? "" : _patterns[r]); + } + } + +} + +#define T(path, desc, fn) register_test(ts, "/base/regex/" path, desc, fn) + +void regex_tests(struct dm_list *all_tests) +{ + struct test_suite *ts = test_suite_create(_mem_init, _mem_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("fingerprints", "not sure", test_fingerprints); + T("matching", "test the matcher with a variety of regexes", test_matching); + T("kabi-query", "test the matcher with some specific patterns", test_kabi_query); + + dm_list_add(all_tests, &ts->list); +} diff --git a/test/unit/percent_t.c b/test/unit/percent_t.c new file mode 100644 index 0000000..3575e12 --- /dev/null +++ b/test/unit/percent_t.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "units.h" +#include "device_mapper/all.h" + +#include +#include + +static void test_percent_100(void *fixture) +{ + char buf[32]; + + /* Check 100% is shown only for DM_PERCENT_100*/ + dm_percent_t p_100 = dm_make_percent(100, 100); + dm_percent_t p1_100 = dm_make_percent(100000, 100000); + dm_percent_t n_100 = dm_make_percent(999999, 1000000); + + T_ASSERT_EQUAL(p_100, DM_PERCENT_100); + T_ASSERT_EQUAL(p1_100, DM_PERCENT_100); + T_ASSERT_NOT_EQUAL(n_100, DM_PERCENT_100); + + (void) dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p_100)); + T_ASSERT_EQUAL(strcmp(buf, "100.00"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p1_100)); + T_ASSERT_EQUAL(strcmp(buf, "100.00"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(n_100)); + T_ASSERT_NOT_EQUAL(strcmp(buf, "99.99"), 0); /* Would like to gett */ + + (void) dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_round_float(n_100, 2)); + T_ASSERT_EQUAL(strcmp(buf, "99.99"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%.3f", dm_percent_to_round_float(n_100, 3)); + T_ASSERT_EQUAL(strcmp(buf, "99.999"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%.4f", dm_percent_to_round_float(n_100, 4)); + T_ASSERT_EQUAL(strcmp(buf, "99.9999"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%d", (int)dm_percent_to_round_float(n_100, 0)); + T_ASSERT_EQUAL(strcmp(buf, "99"), 0); +} + +static void test_percent_0(void *fixture) +{ + char buf[32]; + + /* Check 0% is shown only for DM_PERCENT_0 */ + dm_percent_t p_0 = dm_make_percent(0, 100); + dm_percent_t p1_0 = dm_make_percent(0, 100000); + dm_percent_t n_0 = dm_make_percent(1, 1000000); + + T_ASSERT_EQUAL(p_0, DM_PERCENT_0); + T_ASSERT_EQUAL(p1_0, DM_PERCENT_0); + T_ASSERT_NOT_EQUAL(n_0, DM_PERCENT_0); + + (void) dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p_0)); + T_ASSERT_EQUAL(strcmp(buf, "0.00"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p1_0)); + T_ASSERT_EQUAL(strcmp(buf, "0.00"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(n_0)); + T_ASSERT_NOT_EQUAL(strcmp(buf, "0.01"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_round_float(n_0, 2)); + T_ASSERT_EQUAL(strcmp(buf, "0.01"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%.3f", dm_percent_to_round_float(n_0, 3)); + T_ASSERT_EQUAL(strcmp(buf, "0.001"), 0); + + (void) dm_snprintf(buf, sizeof(buf), "%d", (int)dm_percent_to_round_float(n_0, 0)); + T_ASSERT_EQUAL(strcmp(buf, "1"), 0); +} + +#define T(path, desc, fn) register_test(ts, "/base/formatting/percent/" path, desc, fn) + +void percent_tests(struct dm_list *all_tests) +{ + struct test_suite *ts = test_suite_create(NULL, NULL); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("100", "Pretty printing of percentages near 100%", test_percent_100); + T("0", "Pretty printing of percentages near 0%", test_percent_0); + + dm_list_add(all_tests, &ts->list); +} diff --git a/test/unit/radix_tree_t.c b/test/unit/radix_tree_t.c new file mode 100644 index 0000000..b80e4f8 --- /dev/null +++ b/test/unit/radix_tree_t.c @@ -0,0 +1,852 @@ +// Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include "units.h" +#include "base/data-struct/radix-tree.h" +#include "base/memory/container_of.h" + +#include +#include + +//---------------------------------------------------------------- + +static void *rt_init(void) +{ + struct radix_tree *rt = radix_tree_create(NULL, NULL); + T_ASSERT(rt); + return rt; +} + +static void rt_exit(void *fixture) +{ + if (fixture) + radix_tree_destroy(fixture); +} + +static void test_create_destroy(void *fixture) +{ + T_ASSERT(fixture); +} + +static void test_insert_one(void *fixture) +{ + struct radix_tree *rt = fixture; + union radix_value v; + unsigned char k = 'a'; + v.n = 65; + T_ASSERT(radix_tree_insert(rt, &k, &k + 1, v)); + T_ASSERT(radix_tree_is_well_formed(rt)); + v.n = 0; + T_ASSERT(radix_tree_lookup(rt, &k, &k + 1, &v)); + T_ASSERT_EQUAL(v.n, 65); +} + +static void test_single_byte_keys(void *fixture) +{ + unsigned i, count = 256; + struct radix_tree *rt = fixture; + union radix_value v; + uint8_t k; + + for (i = 0; i < count; i++) { + k = i; + v.n = 100 + i; + T_ASSERT(radix_tree_insert(rt, &k, &k + 1, v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + + for (i = 0; i < count; i++) { + k = i; + T_ASSERT(radix_tree_lookup(rt, &k, &k + 1, &v)); + T_ASSERT_EQUAL(v.n, 100 + i); + } +} + +static void test_overwrite_single_byte_keys(void *fixture) +{ + unsigned i, count = 256; + struct radix_tree *rt = fixture; + union radix_value v; + uint8_t k; + + for (i = 0; i < count; i++) { + k = i; + v.n = 100 + i; + T_ASSERT(radix_tree_insert(rt, &k, &k + 1, v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + + for (i = 0; i < count; i++) { + k = i; + v.n = 1000 + i; + T_ASSERT(radix_tree_insert(rt, &k, &k + 1, v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + + for (i = 0; i < count; i++) { + k = i; + T_ASSERT(radix_tree_lookup(rt, &k, &k + 1, &v)); + T_ASSERT_EQUAL(v.n, 1000 + i); + } +} + +static void test_16_bit_keys(void *fixture) +{ + unsigned i, count = 1 << 16; + struct radix_tree *rt = fixture; + union radix_value v; + uint8_t k[2]; + + for (i = 0; i < count; i++) { + k[0] = i / 256; + k[1] = i % 256; + v.n = 100 + i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + + for (i = 0; i < count; i++) { + k[0] = i / 256; + k[1] = i % 256; + T_ASSERT(radix_tree_lookup(rt, k, k + sizeof(k), &v)); + T_ASSERT_EQUAL(v.n, 100 + i); + } +} + +static void test_prefix_keys(void *fixture) +{ + struct radix_tree *rt = fixture; + union radix_value v; + uint8_t k[2]; + + k[0] = 100; + k[1] = 200; + v.n = 1024; + T_ASSERT(radix_tree_insert(rt, k, k + 1, v)); + T_ASSERT(radix_tree_is_well_formed(rt)); + v.n = 2345; + T_ASSERT(radix_tree_insert(rt, k, k + 2, v)); + T_ASSERT(radix_tree_is_well_formed(rt)); + T_ASSERT(radix_tree_lookup(rt, k, k + 1, &v)); + T_ASSERT_EQUAL(v.n, 1024); + T_ASSERT(radix_tree_lookup(rt, k, k + 2, &v)); + T_ASSERT_EQUAL(v.n, 2345); +} + +static void test_prefix_keys_reversed(void *fixture) +{ + struct radix_tree *rt = fixture; + union radix_value v; + uint8_t k[2]; + + k[0] = 100; + k[1] = 200; + v.n = 1024; + T_ASSERT(radix_tree_insert(rt, k, k + 2, v)); + T_ASSERT(radix_tree_is_well_formed(rt)); + v.n = 2345; + T_ASSERT(radix_tree_insert(rt, k, k + 1, v)); + T_ASSERT(radix_tree_is_well_formed(rt)); + T_ASSERT(radix_tree_lookup(rt, k, k + 2, &v)); + T_ASSERT_EQUAL(v.n, 1024); + T_ASSERT(radix_tree_lookup(rt, k, k + 1, &v)); + T_ASSERT_EQUAL(v.n, 2345); +} + +static void _gen_key(uint8_t *b, uint8_t *e) +{ + for (; b != e; b++) + /* coverity[dont_call] don't care */ + *b = rand() % 256; +} + +static void test_sparse_keys(void *fixture) +{ + unsigned n; + struct radix_tree *rt = fixture; + union radix_value v; + uint8_t k[32]; + + for (n = 0; n < 100000; n++) { + _gen_key(k, k + sizeof(k)); + v.n = 1234; + T_ASSERT(radix_tree_insert(rt, k, k + 32, v)); + // FIXME: remove + //T_ASSERT(radix_tree_is_well_formed(rt)); + } + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +static void test_remove_one(void *fixture) +{ + struct radix_tree *rt = fixture; + uint8_t k[4]; + union radix_value v; + + _gen_key(k, k + sizeof(k)); + v.n = 1234; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + T_ASSERT(radix_tree_is_well_formed(rt)); + T_ASSERT(radix_tree_remove(rt, k, k + sizeof(k))); + T_ASSERT(radix_tree_is_well_formed(rt)); + T_ASSERT(!radix_tree_lookup(rt, k, k + sizeof(k), &v)); +} + +static void test_remove_one_byte_keys(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i, j; + uint8_t k[1]; + union radix_value v; + + for (i = 0; i < 256; i++) { + k[0] = i; + v.n = i + 1000; + T_ASSERT(radix_tree_insert(rt, k, k + 1, v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + for (i = 0; i < 256; i++) { + k[0] = i; + T_ASSERT(radix_tree_remove(rt, k, k + 1)); + T_ASSERT(radix_tree_is_well_formed(rt)); + + for (j = i + 1; j < 256; j++) { + k[0] = j; + T_ASSERT(radix_tree_lookup(rt, k, k + 1, &v)); + if (v.n != j + 1000) + test_fail("v.n (%u) != j + 1000 (%u)\n", + (unsigned) v.n, + (unsigned) j + 1000); + } + } + + for (i = 0; i < 256; i++) { + k[0] = i; + T_ASSERT(!radix_tree_lookup(rt, k, k + 1, &v)); + } +} + +static void test_remove_one_byte_keys_reversed(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i, j; + uint8_t k[1]; + union radix_value v; + + for (i = 0; i < 256; i++) { + k[0] = i; + v.n = i + 1000; + T_ASSERT(radix_tree_insert(rt, k, k + 1, v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + for (i = 256; i; i--) { + k[0] = i - 1; + T_ASSERT(radix_tree_remove(rt, k, k + 1)); + T_ASSERT(radix_tree_is_well_formed(rt)); + + for (j = 0; j < i - 1; j++) { + k[0] = j; + T_ASSERT(radix_tree_lookup(rt, k, k + 1, &v)); + if (v.n != j + 1000) + test_fail("v.n (%u) != j + 1000 (%u)\n", + (unsigned) v.n, + (unsigned) j + 1000); + } + } + + for (i = 0; i < 256; i++) { + k[0] = i; + T_ASSERT(!radix_tree_lookup(rt, k, k + 1, &v)); + } +} +static void test_remove_prefix_keys(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i, j; + uint8_t k[32]; + union radix_value v; + + _gen_key(k, k + sizeof(k)); + + for (i = 0; i < 32; i++) { + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + i, v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + for (i = 0; i < 32; i++) { + T_ASSERT(radix_tree_remove(rt, k, k + i)); + T_ASSERT(radix_tree_is_well_formed(rt)); + for (j = i + 1; j < 32; j++) { + T_ASSERT(radix_tree_lookup(rt, k, k + j, &v)); + T_ASSERT_EQUAL(v.n, j); + } + } + + for (i = 0; i < 32; i++) + T_ASSERT(!radix_tree_lookup(rt, k, k + i, &v)); +} + +static void test_remove_prefix_keys_reversed(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i, j; + uint8_t k[32]; + union radix_value v; + + _gen_key(k, k + sizeof(k)); + + for (i = 0; i < 32; i++) { + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + i, v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + for (i = 0; i < 32; i++) { + T_ASSERT(radix_tree_remove(rt, k, k + (31 - i))); + T_ASSERT(radix_tree_is_well_formed(rt)); + for (j = 0; j < 31 - i; j++) { + T_ASSERT(radix_tree_lookup(rt, k, k + j, &v)); + T_ASSERT_EQUAL(v.n, j); + } + } + + for (i = 0; i < 32; i++) + T_ASSERT(!radix_tree_lookup(rt, k, k + i, &v)); +} + +static void test_remove_prefix(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i, count = 0; + uint8_t k[4]; + union radix_value v; + + // populate some random 32bit keys + for (i = 0; i < 100000; i++) { + _gen_key(k, k + sizeof(k)); + if (k[0] == 21) + count++; + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + + // remove keys in a sub range + k[0] = 21; + T_ASSERT_EQUAL(radix_tree_remove_prefix(rt, k, k + 1), count); + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +static void test_remove_prefix_single(void *fixture) +{ + struct radix_tree *rt = fixture; + uint8_t k[4]; + union radix_value v; + + _gen_key(k, k + sizeof(k)); + v.n = 1234; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + T_ASSERT(radix_tree_is_well_formed(rt)); + T_ASSERT_EQUAL(radix_tree_remove_prefix(rt, k, k + 2), 1); + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +static void test_size(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i, dup_count = 0; + uint8_t k[2]; + union radix_value v; + + // populate some random 16bit keys + for (i = 0; i < 10000; i++) { + _gen_key(k, k + sizeof(k)); + if (radix_tree_lookup(rt, k, k + sizeof(k), &v)) + dup_count++; + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + + T_ASSERT_EQUAL(radix_tree_size(rt), 10000 - dup_count); + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +struct visitor { + struct radix_tree_iterator it; + unsigned count; +}; + +static bool _visit(struct radix_tree_iterator *it, + uint8_t *kb, uint8_t *ke, union radix_value v) +{ + struct visitor *vt = container_of(it, struct visitor, it); + vt->count++; + return true; +} + +static void test_iterate_all(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i; + uint8_t k[4]; + union radix_value v; + struct visitor vt; + + // populate some random 32bit keys + for (i = 0; i < 100000; i++) { + _gen_key(k, k + sizeof(k)); + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + vt.count = 0; + vt.it.visit = _visit; + radix_tree_iterate(rt, NULL, NULL, &vt.it); + T_ASSERT_EQUAL(vt.count, radix_tree_size(rt)); +} + +static void test_iterate_subset(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i, subset_count = 0; + uint8_t k[3]; + union radix_value v; + struct visitor vt; + + // populate some random 32bit keys + for (i = 0; i < 100000; i++) { + _gen_key(k, k + sizeof(k)); + if (k[0] == 21 && k[1] == 12) + subset_count++; + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + vt.count = 0; + vt.it.visit = _visit; + k[0] = 21; + k[1] = 12; + radix_tree_iterate(rt, k, k + 2, &vt.it); + T_ASSERT_EQUAL(vt.count, subset_count); +} + +static void test_iterate_single(void *fixture) +{ + struct radix_tree *rt = fixture; + uint8_t k[6]; + union radix_value v; + struct visitor vt; + + _gen_key(k, k + sizeof(k)); + v.n = 1234; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + + T_ASSERT(radix_tree_is_well_formed(rt)); + vt.count = 0; + vt.it.visit = _visit; + radix_tree_iterate(rt, k, k + 3, &vt.it); + T_ASSERT_EQUAL(vt.count, 1); +} + +static void test_iterate_vary_middle(void *fixture) +{ + struct radix_tree *rt = fixture; + unsigned i; + uint8_t k[6]; + union radix_value v; + struct visitor vt; + + _gen_key(k, k + sizeof(k)); + for (i = 0; i < 16; i++) { + k[3] = i; + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + vt.it.visit = _visit; + for (i = 0; i < 16; i++) { + vt.count = 0; + k[3] = i; + radix_tree_iterate(rt, k, k + 4, &vt.it); + T_ASSERT_EQUAL(vt.count, 1); + } +} + +//---------------------------------------------------------------- + +#define DTR_COUNT 100 + +struct counter { + unsigned c; + uint8_t present[DTR_COUNT]; +}; + +static void _counting_dtr(void *context, union radix_value v) +{ + struct counter *c = context; + c->c++; + T_ASSERT(v.n < DTR_COUNT); + c->present[v.n] = 0; +} + +static void test_remove_calls_dtr(void *fixture) +{ + struct counter c; + struct radix_tree *rt = radix_tree_create(_counting_dtr, &c); + T_ASSERT(rt); + + // Bug hunting, so I need the keys to be deterministic + srand(0); + + c.c = 0; + memset(c.present, 1, sizeof(c.present)); + + { + unsigned i; + uint8_t keys[DTR_COUNT * 3]; + union radix_value v; + + // generate and insert a lot of keys + for (i = 0; i < DTR_COUNT; i++) { + bool found = false; + do { + v.n = i; + uint8_t *k = keys + (i * 3); + _gen_key(k, k + 3); + if (!radix_tree_lookup(rt, k, k + 3, &v)) { + T_ASSERT(radix_tree_insert(rt, k, k + 3, v)); + found = true; + } + + } while (!found); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + + // double check + for (i = 0; i < DTR_COUNT; i++) { + uint8_t *k = keys + (i * 3); + T_ASSERT(radix_tree_lookup(rt, k, k + 3, &v)); + } + + for (i = 0; i < DTR_COUNT; i++) { + uint8_t *k = keys + (i * 3); + // FIXME: check the values get passed to the dtr + T_ASSERT(radix_tree_remove(rt, k, k + 3)); + } + + T_ASSERT(c.c == DTR_COUNT); + for (i = 0; i < DTR_COUNT; i++) + T_ASSERT(!c.present[i]); + } + + radix_tree_destroy(rt); +} + +static void test_destroy_calls_dtr(void *fixture) +{ + unsigned i; + struct counter c; + struct radix_tree *rt = radix_tree_create(_counting_dtr, &c); + T_ASSERT(rt); + + // Bug hunting, so I need the keys to be deterministic + srand(0); + + c.c = 0; + memset(c.present, 1, sizeof(c.present)); + + { + uint8_t keys[DTR_COUNT * 3]; + union radix_value v; + + // generate and insert a lot of keys + for (i = 0; i < DTR_COUNT; i++) { + bool found = false; + do { + v.n = i; + uint8_t *k = keys + (i * 3); + _gen_key(k, k + 3); + if (!radix_tree_lookup(rt, k, k + 3, &v)) { + T_ASSERT(radix_tree_insert(rt, k, k + 3, v)); + found = true; + } + + } while (!found); + } + + T_ASSERT(radix_tree_is_well_formed(rt)); + } + + radix_tree_destroy(rt); + T_ASSERT(c.c == DTR_COUNT); + for (i = 0; i < DTR_COUNT; i++) + T_ASSERT(!c.present[i]); +} + +//---------------------------------------------------------------- + +static void test_bcache_scenario(void *fixture) +{ + struct radix_tree *rt = fixture; + + unsigned i; + uint8_t k[6]; + union radix_value v; + + memset(k, 0, sizeof(k)); + + for (i = 0; i < 3; i++) { + // it has to be the 4th byte that varies to + // trigger the bug. + k[4] = i; + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + T_ASSERT(radix_tree_is_well_formed(rt)); + + k[4] = 0; + T_ASSERT(radix_tree_remove(rt, k, k + sizeof(k))); + T_ASSERT(radix_tree_is_well_formed(rt)); + + k[4] = i; + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +//---------------------------------------------------------------- + +static void _bcs2_step1(struct radix_tree *rt) +{ + unsigned i; + uint8_t k[12]; + union radix_value v; + + memset(k, 0, sizeof(k)); + for (i = 0x6; i < 0x69; i++) { + k[0] = i; + v.n = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +static void _bcs2_step2(struct radix_tree *rt) +{ + unsigned i; + uint8_t k[12]; + + memset(k, 0, sizeof(k)); + for (i = 0x6; i < 0x69; i++) { + k[0] = i; + radix_tree_remove_prefix(rt, k, k + 4); + } + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +static void test_bcache_scenario2(void *fixture) +{ + unsigned i; + struct radix_tree *rt = fixture; + uint8_t k[12]; + union radix_value v; + + _bcs2_step1(rt); + _bcs2_step2(rt); + + memset(k, 0, sizeof(k)); + for (i = 0; i < 50; i++) { + k[0] = 0x6; + v.n = 0x6; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + radix_tree_remove_prefix(rt, k, k + 4); + } + T_ASSERT(radix_tree_is_well_formed(rt)); + + _bcs2_step1(rt); + _bcs2_step2(rt); + _bcs2_step1(rt); + _bcs2_step2(rt); + + memset(k, 0, sizeof(k)); + for(i = 0x6; i < 0x37; i++) { + k[0] = i; + k[4] = 0xf; + k[5] = 0x1; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + k[4] = 0; + k[5] = 0; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + T_ASSERT(radix_tree_is_well_formed(rt)); + + memset(k, 0, sizeof(k)); + for (i = 0x38; i < 0x69; i++) { + k[0] = i - 0x32; + k[4] = 0xf; + k[5] = 1; + T_ASSERT(radix_tree_remove(rt, k, k + sizeof(k))); + + k[0] = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + + k[0] = i - 0x32; + k[4] = 0; + k[5] = 0; + T_ASSERT(radix_tree_remove(rt, k, k + sizeof(k))); + + k[0] = i; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + } + T_ASSERT(radix_tree_is_well_formed(rt)); + + memset(k, 0, sizeof(k)); + k[0] = 0x6; + radix_tree_remove_prefix(rt, k, k + 4); + T_ASSERT(radix_tree_is_well_formed(rt)); + + k[0] = 0x38; + k[4] = 0xf; + k[5] = 0x1; + T_ASSERT(radix_tree_remove(rt, k, k + sizeof(k))); + T_ASSERT(radix_tree_is_well_formed(rt)); + + memset(k, 0, sizeof(k)); + k[0] = 0x6; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + T_ASSERT(radix_tree_is_well_formed(rt)); + + k[0] = 0x7; + radix_tree_remove_prefix(rt, k, k + 4); + T_ASSERT(radix_tree_is_well_formed(rt)); + + k[0] = 0x38; + T_ASSERT(radix_tree_remove(rt, k, k + sizeof(k))); + T_ASSERT(radix_tree_is_well_formed(rt)); + + k[0] = 7; + T_ASSERT(radix_tree_insert(rt, k, k + sizeof(k), v)); + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +//---------------------------------------------------------------- + +struct key_parts { + uint32_t fd; + uint64_t b; +} __attribute__ ((packed)); + +union key { + struct key_parts parts; + uint8_t bytes[12]; +}; + +static void __lookup_matches(struct radix_tree *rt, int fd, uint64_t b, uint64_t expected) +{ + union key k; + union radix_value v; + + k.parts.fd = fd; + k.parts.b = b; + T_ASSERT(radix_tree_lookup(rt, k.bytes, k.bytes + sizeof(k.bytes), &v)); + T_ASSERT(v.n == expected); +} + +static void __lookup_fails(struct radix_tree *rt, int fd, uint64_t b) +{ + union key k; + union radix_value v; + + k.parts.fd = fd; + k.parts.b = b; + T_ASSERT(!radix_tree_lookup(rt, k.bytes, k.bytes + sizeof(k.bytes), &v)); +} + +static void __insert(struct radix_tree *rt, int fd, uint64_t b, uint64_t n) +{ + union key k; + union radix_value v; + + k.parts.fd = fd; + k.parts.b = b; + v.n = n; + T_ASSERT(radix_tree_insert(rt, k.bytes, k.bytes + sizeof(k.bytes), v)); +} + +static void __invalidate(struct radix_tree *rt, int fd) +{ + union key k; + + k.parts.fd = fd; + radix_tree_remove_prefix(rt, k.bytes, k.bytes + sizeof(k.parts.fd)); + T_ASSERT(radix_tree_is_well_formed(rt)); +} + +static void test_bcache_scenario3(void *fixture) +{ + struct radix_tree *rt = fixture; + + #include "test/unit/rt_case1.c" +} + +//---------------------------------------------------------------- +#define T(path, desc, fn) register_test(ts, "/base/data-struct/radix-tree/" path, desc, fn) + +void radix_tree_tests(struct dm_list *all_tests) +{ + struct test_suite *ts = test_suite_create(rt_init, rt_exit); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("create-destroy", "create and destroy an empty tree", test_create_destroy); + T("insert-one", "insert one trivial trivial key", test_insert_one); + T("insert-single-byte-keys", "inserts many single byte keys", test_single_byte_keys); + T("overwrite-single-byte-keys", "overwrite many single byte keys", test_overwrite_single_byte_keys); + T("insert-16-bit-keys", "insert many 16bit keys", test_16_bit_keys); + T("prefix-keys", "prefixes of other keys are valid keys", test_prefix_keys); + T("prefix-keys-reversed", "prefixes of other keys are valid keys", test_prefix_keys_reversed); + T("sparse-keys", "see what the memory usage is for sparsely distributed keys", test_sparse_keys); + T("remove-one", "remove one entry", test_remove_one); + T("remove-one-byte-keys", "remove many one byte keys", test_remove_one_byte_keys); + T("remove-one-byte-keys-reversed", "remove many one byte keys reversed", test_remove_one_byte_keys_reversed); + T("remove-prefix-keys", "remove a set of keys that have common prefixes", test_remove_prefix_keys); + T("remove-prefix-keys-reversed", "remove a set of keys that have common prefixes (reversed)", test_remove_prefix_keys_reversed); + T("remove-prefix", "remove a subrange", test_remove_prefix); + T("remove-prefix-single", "remove a subrange with a single entry", test_remove_prefix_single); + T("size-spots-duplicates", "duplicate entries aren't counted twice", test_size); + T("iterate-all", "iterate all entries in tree", test_iterate_all); + T("iterate-subset", "iterate a subset of entries in tree", test_iterate_subset); + T("iterate-single", "iterate a subset that contains a single entry", test_iterate_single); + T("iterate-vary-middle", "iterate keys that vary in the middle", test_iterate_vary_middle); + T("remove-calls-dtr", "remove should call the dtr for the value", test_remove_calls_dtr); + T("destroy-calls-dtr", "destroy should call the dtr for all values", test_destroy_calls_dtr); + T("bcache-scenario", "A specific series of keys from a bcache scenario", test_bcache_scenario); + T("bcache-scenario-2", "A second series of keys from a bcache scenario", test_bcache_scenario2); + T("bcache-scenario-3", "A third series of keys from a bcache scenario", test_bcache_scenario3); + + dm_list_add(all_tests, &ts->list); +} +//---------------------------------------------------------------- diff --git a/test/unit/rt_case1.c b/test/unit/rt_case1.c new file mode 100644 index 0000000..c1677d1 --- /dev/null +++ b/test/unit/rt_case1.c @@ -0,0 +1,1669 @@ + __lookup_fails(rt, 6, 0); + __insert(rt, 6, 0, 0); + __lookup_fails(rt, 7, 0); + __insert(rt, 7, 0, 1); + __lookup_fails(rt, 8, 0); + __insert(rt, 8, 0, 2); + __lookup_fails(rt, 9, 0); + __insert(rt, 9, 0, 3); + __lookup_fails(rt, 10, 0); + __insert(rt, 10, 0, 4); + __lookup_fails(rt, 11, 0); + __insert(rt, 11, 0, 5); + __lookup_fails(rt, 12, 0); + __insert(rt, 12, 0, 6); + __lookup_fails(rt, 13, 0); + __insert(rt, 13, 0, 7); + __lookup_fails(rt, 14, 0); + __insert(rt, 14, 0, 8); + __lookup_fails(rt, 15, 0); + __insert(rt, 15, 0, 9); + __lookup_fails(rt, 16, 0); + __insert(rt, 16, 0, 10); + __lookup_fails(rt, 17, 0); + __insert(rt, 17, 0, 11); + __lookup_fails(rt, 18, 0); + __insert(rt, 18, 0, 12); + __lookup_fails(rt, 19, 0); + __insert(rt, 19, 0, 13); + __lookup_fails(rt, 20, 0); + __insert(rt, 20, 0, 14); + __lookup_fails(rt, 21, 0); + __insert(rt, 21, 0, 15); + __lookup_fails(rt, 22, 0); + __insert(rt, 22, 0, 16); + __lookup_fails(rt, 23, 0); + __insert(rt, 23, 0, 17); + __lookup_fails(rt, 24, 0); + __insert(rt, 24, 0, 18); + __lookup_fails(rt, 25, 0); + __insert(rt, 25, 0, 19); + __lookup_fails(rt, 26, 0); + __insert(rt, 26, 0, 20); + __lookup_fails(rt, 27, 0); + __insert(rt, 27, 0, 21); + __lookup_fails(rt, 28, 0); + __insert(rt, 28, 0, 22); + __lookup_fails(rt, 29, 0); + __insert(rt, 29, 0, 23); + __lookup_fails(rt, 30, 0); + __insert(rt, 30, 0, 24); + __lookup_fails(rt, 31, 0); + __insert(rt, 31, 0, 25); + __lookup_fails(rt, 32, 0); + __insert(rt, 32, 0, 26); + __lookup_fails(rt, 33, 0); + __insert(rt, 33, 0, 27); + __lookup_fails(rt, 34, 0); + __insert(rt, 34, 0, 28); + __lookup_fails(rt, 35, 0); + __insert(rt, 35, 0, 29); + __lookup_fails(rt, 36, 0); + __insert(rt, 36, 0, 30); + __lookup_fails(rt, 37, 0); + __insert(rt, 37, 0, 31); + __lookup_fails(rt, 38, 0); + __insert(rt, 38, 0, 32); + __lookup_fails(rt, 39, 0); + __insert(rt, 39, 0, 33); + __lookup_fails(rt, 40, 0); + __insert(rt, 40, 0, 34); + __lookup_fails(rt, 41, 0); + __insert(rt, 41, 0, 35); + __lookup_fails(rt, 42, 0); + __insert(rt, 42, 0, 36); + __lookup_fails(rt, 43, 0); + __insert(rt, 43, 0, 37); + __lookup_fails(rt, 44, 0); + __insert(rt, 44, 0, 38); + __lookup_fails(rt, 45, 0); + __insert(rt, 45, 0, 39); + __lookup_fails(rt, 46, 0); + __insert(rt, 46, 0, 40); + __lookup_fails(rt, 47, 0); + __insert(rt, 47, 0, 41); + __lookup_fails(rt, 48, 0); + __insert(rt, 48, 0, 42); + __lookup_fails(rt, 49, 0); + __insert(rt, 49, 0, 43); + __lookup_fails(rt, 50, 0); + __insert(rt, 50, 0, 44); + __lookup_fails(rt, 51, 0); + __insert(rt, 51, 0, 45); + __lookup_fails(rt, 52, 0); + __insert(rt, 52, 0, 46); + __lookup_fails(rt, 53, 0); + __insert(rt, 53, 0, 47); + __lookup_fails(rt, 54, 0); + __insert(rt, 54, 0, 48); + __lookup_fails(rt, 55, 0); + __insert(rt, 55, 0, 49); + __lookup_fails(rt, 56, 0); + __insert(rt, 56, 0, 50); + __lookup_fails(rt, 57, 0); + __insert(rt, 57, 0, 51); + __lookup_fails(rt, 58, 0); + __insert(rt, 58, 0, 52); + __lookup_fails(rt, 59, 0); + __insert(rt, 59, 0, 53); + __lookup_fails(rt, 60, 0); + __insert(rt, 60, 0, 54); + __lookup_fails(rt, 61, 0); + __insert(rt, 61, 0, 55); + __lookup_fails(rt, 62, 0); + __insert(rt, 62, 0, 56); + __lookup_fails(rt, 63, 0); + __insert(rt, 63, 0, 57); + __lookup_fails(rt, 64, 0); + __insert(rt, 64, 0, 58); + __lookup_fails(rt, 65, 0); + __insert(rt, 65, 0, 59); + __lookup_fails(rt, 66, 0); + __insert(rt, 66, 0, 60); + __lookup_fails(rt, 67, 0); + __insert(rt, 67, 0, 61); + __lookup_fails(rt, 68, 0); + __insert(rt, 68, 0, 62); + __lookup_fails(rt, 69, 0); + __insert(rt, 69, 0, 63); + __lookup_fails(rt, 70, 0); + __insert(rt, 70, 0, 64); + __lookup_fails(rt, 71, 0); + __insert(rt, 71, 0, 65); + __lookup_fails(rt, 72, 0); + __insert(rt, 72, 0, 66); + __lookup_fails(rt, 73, 0); + __insert(rt, 73, 0, 67); + __lookup_fails(rt, 74, 0); + __insert(rt, 74, 0, 68); + __lookup_fails(rt, 75, 0); + __insert(rt, 75, 0, 69); + __lookup_fails(rt, 76, 0); + __insert(rt, 76, 0, 70); + __lookup_fails(rt, 77, 0); + __insert(rt, 77, 0, 71); + __lookup_fails(rt, 78, 0); + __insert(rt, 78, 0, 72); + __lookup_fails(rt, 79, 0); + __insert(rt, 79, 0, 73); + __lookup_fails(rt, 80, 0); + __insert(rt, 80, 0, 74); + __lookup_fails(rt, 81, 0); + __insert(rt, 81, 0, 75); + __lookup_fails(rt, 82, 0); + __insert(rt, 82, 0, 76); + __lookup_fails(rt, 83, 0); + __insert(rt, 83, 0, 77); + __lookup_fails(rt, 84, 0); + __insert(rt, 84, 0, 78); + __lookup_fails(rt, 85, 0); + __insert(rt, 85, 0, 79); + __lookup_fails(rt, 86, 0); + __insert(rt, 86, 0, 80); + __lookup_fails(rt, 87, 0); + __insert(rt, 87, 0, 81); + __lookup_fails(rt, 88, 0); + __insert(rt, 88, 0, 82); + __lookup_fails(rt, 89, 0); + __insert(rt, 89, 0, 83); + __lookup_fails(rt, 90, 0); + __insert(rt, 90, 0, 84); + __lookup_fails(rt, 91, 0); + __insert(rt, 91, 0, 85); + __lookup_fails(rt, 92, 0); + __insert(rt, 92, 0, 86); + __lookup_fails(rt, 93, 0); + __insert(rt, 93, 0, 87); + __lookup_fails(rt, 94, 0); + __insert(rt, 94, 0, 88); + __lookup_fails(rt, 95, 0); + __insert(rt, 95, 0, 89); + __lookup_fails(rt, 96, 0); + __insert(rt, 96, 0, 90); + __lookup_fails(rt, 97, 0); + __insert(rt, 97, 0, 91); + __lookup_fails(rt, 98, 0); + __insert(rt, 98, 0, 92); + __lookup_fails(rt, 99, 0); + __insert(rt, 99, 0, 93); + __lookup_fails(rt, 100, 0); + __insert(rt, 100, 0, 94); + __lookup_fails(rt, 101, 0); + __insert(rt, 101, 0, 95); + __lookup_fails(rt, 102, 0); + __insert(rt, 102, 0, 96); + __lookup_fails(rt, 103, 0); + __insert(rt, 103, 0, 97); + __lookup_fails(rt, 104, 0); + __insert(rt, 104, 0, 98); + __lookup_fails(rt, 105, 0); + __insert(rt, 105, 0, 99); + __lookup_fails(rt, 106, 0); + __insert(rt, 106, 0, 100); + __lookup_fails(rt, 107, 0); + __insert(rt, 107, 0, 101); + __lookup_fails(rt, 108, 0); + __insert(rt, 108, 0, 102); + __lookup_fails(rt, 109, 0); + __insert(rt, 109, 0, 103); + __lookup_fails(rt, 110, 0); + __insert(rt, 110, 0, 104); + __lookup_fails(rt, 111, 0); + __insert(rt, 111, 0, 105); + __lookup_fails(rt, 112, 0); + __insert(rt, 112, 0, 106); + __lookup_fails(rt, 113, 0); + __insert(rt, 113, 0, 107); + __lookup_fails(rt, 114, 0); + __insert(rt, 114, 0, 108); + __lookup_fails(rt, 115, 0); + __insert(rt, 115, 0, 109); + __lookup_fails(rt, 116, 0); + __insert(rt, 116, 0, 110); + __lookup_fails(rt, 117, 0); + __insert(rt, 117, 0, 111); + __lookup_fails(rt, 118, 0); + __insert(rt, 118, 0, 112); + __lookup_fails(rt, 119, 0); + __insert(rt, 119, 0, 113); + __lookup_fails(rt, 120, 0); + __insert(rt, 120, 0, 114); + __lookup_fails(rt, 121, 0); + __insert(rt, 121, 0, 115); + __lookup_fails(rt, 122, 0); + __insert(rt, 122, 0, 116); + __lookup_fails(rt, 123, 0); + __insert(rt, 123, 0, 117); + __lookup_fails(rt, 124, 0); + __insert(rt, 124, 0, 118); + __lookup_fails(rt, 125, 0); + __insert(rt, 125, 0, 119); + __lookup_fails(rt, 126, 0); + __insert(rt, 126, 0, 120); + __lookup_fails(rt, 127, 0); + __insert(rt, 127, 0, 121); + __lookup_fails(rt, 128, 0); + __insert(rt, 128, 0, 122); + __lookup_fails(rt, 129, 0); + __insert(rt, 129, 0, 123); + __lookup_fails(rt, 130, 0); + __insert(rt, 130, 0, 124); + __lookup_fails(rt, 131, 0); + __insert(rt, 131, 0, 125); + __lookup_fails(rt, 132, 0); + __insert(rt, 132, 0, 126); + __lookup_fails(rt, 133, 0); + __insert(rt, 133, 0, 127); + __lookup_fails(rt, 134, 0); + __insert(rt, 134, 0, 128); + __lookup_fails(rt, 135, 0); + __insert(rt, 135, 0, 129); + __lookup_fails(rt, 136, 0); + __insert(rt, 136, 0, 130); + __lookup_fails(rt, 137, 0); + __insert(rt, 137, 0, 131); + __lookup_fails(rt, 138, 0); + __insert(rt, 138, 0, 132); + __lookup_fails(rt, 139, 0); + __insert(rt, 139, 0, 133); + __lookup_fails(rt, 140, 0); + __insert(rt, 140, 0, 134); + __lookup_fails(rt, 141, 0); + __insert(rt, 141, 0, 135); + __lookup_fails(rt, 142, 0); + __insert(rt, 142, 0, 136); + __lookup_fails(rt, 143, 0); + __insert(rt, 143, 0, 137); + __lookup_fails(rt, 144, 0); + __insert(rt, 144, 0, 138); + __lookup_fails(rt, 145, 0); + __insert(rt, 145, 0, 139); + __lookup_fails(rt, 146, 0); + __insert(rt, 146, 0, 140); + __lookup_fails(rt, 147, 0); + __insert(rt, 147, 0, 141); + __lookup_fails(rt, 148, 0); + __insert(rt, 148, 0, 142); + __lookup_fails(rt, 149, 0); + __insert(rt, 149, 0, 143); + __lookup_fails(rt, 150, 0); + __insert(rt, 150, 0, 144); + __lookup_fails(rt, 151, 0); + __insert(rt, 151, 0, 145); + __lookup_fails(rt, 152, 0); + __insert(rt, 152, 0, 146); + __lookup_fails(rt, 153, 0); + __insert(rt, 153, 0, 147); + __lookup_fails(rt, 154, 0); + __insert(rt, 154, 0, 148); + __lookup_fails(rt, 155, 0); + __insert(rt, 155, 0, 149); + __lookup_fails(rt, 156, 0); + __insert(rt, 156, 0, 150); + __lookup_fails(rt, 157, 0); + __insert(rt, 157, 0, 151); + __lookup_fails(rt, 158, 0); + __insert(rt, 158, 0, 152); + __lookup_fails(rt, 159, 0); + __insert(rt, 159, 0, 153); + __lookup_fails(rt, 160, 0); + __insert(rt, 160, 0, 154); + __lookup_fails(rt, 161, 0); + __insert(rt, 161, 0, 155); + __lookup_fails(rt, 162, 0); + __insert(rt, 162, 0, 156); + __lookup_fails(rt, 163, 0); + __insert(rt, 163, 0, 157); + __lookup_fails(rt, 164, 0); + __insert(rt, 164, 0, 158); + __lookup_fails(rt, 165, 0); + __insert(rt, 165, 0, 159); + __lookup_fails(rt, 166, 0); + __insert(rt, 166, 0, 160); + __lookup_fails(rt, 167, 0); + __insert(rt, 167, 0, 161); + __lookup_fails(rt, 168, 0); + __insert(rt, 168, 0, 162); + __lookup_fails(rt, 169, 0); + __insert(rt, 169, 0, 163); + __lookup_fails(rt, 170, 0); + __insert(rt, 170, 0, 164); + __lookup_fails(rt, 171, 0); + __insert(rt, 171, 0, 165); + __lookup_fails(rt, 172, 0); + __insert(rt, 172, 0, 166); + __lookup_fails(rt, 173, 0); + __insert(rt, 173, 0, 167); + __lookup_fails(rt, 174, 0); + __insert(rt, 174, 0, 168); + __lookup_fails(rt, 175, 0); + __insert(rt, 175, 0, 169); + __lookup_fails(rt, 176, 0); + __insert(rt, 176, 0, 170); + __lookup_fails(rt, 177, 0); + __insert(rt, 177, 0, 171); + __lookup_fails(rt, 178, 0); + __insert(rt, 178, 0, 172); + __lookup_fails(rt, 179, 0); + __insert(rt, 179, 0, 173); + __lookup_fails(rt, 180, 0); + __insert(rt, 180, 0, 174); + __lookup_fails(rt, 181, 0); + __insert(rt, 181, 0, 175); + __lookup_fails(rt, 182, 0); + __insert(rt, 182, 0, 176); + __lookup_fails(rt, 183, 0); + __insert(rt, 183, 0, 177); + __lookup_fails(rt, 184, 0); + __insert(rt, 184, 0, 178); + __lookup_fails(rt, 185, 0); + __insert(rt, 185, 0, 179); + __lookup_fails(rt, 186, 0); + __insert(rt, 186, 0, 180); + __lookup_fails(rt, 187, 0); + __insert(rt, 187, 0, 181); + __lookup_fails(rt, 188, 0); + __insert(rt, 188, 0, 182); + __lookup_fails(rt, 189, 0); + __insert(rt, 189, 0, 183); + __lookup_fails(rt, 190, 0); + __insert(rt, 190, 0, 184); + __lookup_fails(rt, 191, 0); + __insert(rt, 191, 0, 185); + __lookup_fails(rt, 192, 0); + __insert(rt, 192, 0, 186); + __lookup_fails(rt, 193, 0); + __insert(rt, 193, 0, 187); + __lookup_fails(rt, 194, 0); + __insert(rt, 194, 0, 188); + __lookup_fails(rt, 195, 0); + __insert(rt, 195, 0, 189); + __lookup_fails(rt, 196, 0); + __insert(rt, 196, 0, 190); + __lookup_fails(rt, 197, 0); + __insert(rt, 197, 0, 191); + __lookup_fails(rt, 198, 0); + __insert(rt, 198, 0, 192); + __lookup_fails(rt, 199, 0); + __insert(rt, 199, 0, 193); + __lookup_fails(rt, 200, 0); + __insert(rt, 200, 0, 194); + __lookup_fails(rt, 201, 0); + __insert(rt, 201, 0, 195); + __lookup_fails(rt, 202, 0); + __insert(rt, 202, 0, 196); + __lookup_fails(rt, 203, 0); + __insert(rt, 203, 0, 197); + __lookup_fails(rt, 204, 0); + __insert(rt, 204, 0, 198); + __lookup_fails(rt, 205, 0); + __insert(rt, 205, 0, 199); + __lookup_matches(rt, 6, 0, 0); + __invalidate(rt, 6); + __lookup_matches(rt, 7, 0, 1); + __invalidate(rt, 7); + __lookup_matches(rt, 8, 0, 2); + __invalidate(rt, 8); + __lookup_matches(rt, 9, 0, 3); + __invalidate(rt, 9); + __lookup_matches(rt, 10, 0, 4); + __invalidate(rt, 10); + __lookup_matches(rt, 11, 0, 5); + __invalidate(rt, 11); + __lookup_matches(rt, 12, 0, 6); + __lookup_matches(rt, 13, 0, 7); + __invalidate(rt, 13); + __lookup_matches(rt, 14, 0, 8); + __invalidate(rt, 14); + __lookup_matches(rt, 15, 0, 9); + __invalidate(rt, 15); + __lookup_matches(rt, 16, 0, 10); + __invalidate(rt, 16); + __lookup_matches(rt, 17, 0, 11); + __invalidate(rt, 17); + __lookup_matches(rt, 18, 0, 12); + __invalidate(rt, 18); + __lookup_matches(rt, 19, 0, 13); + __invalidate(rt, 19); + __lookup_matches(rt, 20, 0, 14); + __invalidate(rt, 20); + __lookup_matches(rt, 21, 0, 15); + __invalidate(rt, 21); + __lookup_matches(rt, 22, 0, 16); + __invalidate(rt, 22); + __lookup_matches(rt, 23, 0, 17); + __invalidate(rt, 23); + __lookup_matches(rt, 24, 0, 18); + __invalidate(rt, 24); + __lookup_matches(rt, 25, 0, 19); + __invalidate(rt, 25); + __lookup_matches(rt, 26, 0, 20); + __invalidate(rt, 26); + __lookup_matches(rt, 27, 0, 21); + __invalidate(rt, 27); + __lookup_matches(rt, 28, 0, 22); + __invalidate(rt, 28); + __lookup_matches(rt, 29, 0, 23); + __invalidate(rt, 29); + __lookup_matches(rt, 30, 0, 24); + __invalidate(rt, 30); + __lookup_matches(rt, 31, 0, 25); + __invalidate(rt, 31); + __lookup_matches(rt, 32, 0, 26); + __invalidate(rt, 32); + __lookup_matches(rt, 33, 0, 27); + __invalidate(rt, 33); + __lookup_matches(rt, 34, 0, 28); + __invalidate(rt, 34); + __lookup_matches(rt, 35, 0, 29); + __invalidate(rt, 35); + __lookup_matches(rt, 36, 0, 30); + __invalidate(rt, 36); + __lookup_matches(rt, 37, 0, 31); + __invalidate(rt, 37); + __lookup_matches(rt, 38, 0, 32); + __invalidate(rt, 38); + __lookup_matches(rt, 39, 0, 33); + __invalidate(rt, 39); + __lookup_matches(rt, 40, 0, 34); + __invalidate(rt, 40); + __lookup_matches(rt, 41, 0, 35); + __invalidate(rt, 41); + __lookup_matches(rt, 42, 0, 36); + __invalidate(rt, 42); + __lookup_matches(rt, 43, 0, 37); + __invalidate(rt, 43); + __lookup_matches(rt, 44, 0, 38); + __invalidate(rt, 44); + __lookup_matches(rt, 45, 0, 39); + __invalidate(rt, 45); + __lookup_matches(rt, 46, 0, 40); + __lookup_fails(rt, 46, 5); + __insert(rt, 46, 5, 200); + __lookup_matches(rt, 46, 5, 200); + __lookup_fails(rt, 46, 6); + __insert(rt, 46, 6, 201); + __lookup_fails(rt, 46, 7); + __insert(rt, 46, 7, 202); + __lookup_fails(rt, 46, 8); + __insert(rt, 46, 8, 203); + __lookup_matches(rt, 46, 5, 200); + __lookup_matches(rt, 46, 6, 201); + __lookup_matches(rt, 46, 7, 202); + __lookup_matches(rt, 46, 8, 203); + __lookup_matches(rt, 47, 0, 41); + __invalidate(rt, 47); + __lookup_matches(rt, 48, 0, 42); + __invalidate(rt, 48); + __lookup_matches(rt, 49, 0, 43); + __invalidate(rt, 49); + __lookup_matches(rt, 50, 0, 44); + __invalidate(rt, 50); + __lookup_matches(rt, 51, 0, 45); + __invalidate(rt, 51); + __lookup_matches(rt, 52, 0, 46); + __invalidate(rt, 52); + __lookup_matches(rt, 53, 0, 47); + __invalidate(rt, 53); + __lookup_matches(rt, 54, 0, 48); + __invalidate(rt, 54); + __lookup_matches(rt, 55, 0, 49); + __invalidate(rt, 55); + __lookup_matches(rt, 56, 0, 50); + __invalidate(rt, 56); + __lookup_matches(rt, 57, 0, 51); + __invalidate(rt, 57); + __lookup_matches(rt, 58, 0, 52); + __invalidate(rt, 58); + __lookup_matches(rt, 59, 0, 53); + __invalidate(rt, 59); + __lookup_matches(rt, 60, 0, 54); + __invalidate(rt, 60); + __lookup_matches(rt, 61, 0, 55); + __invalidate(rt, 61); + __lookup_matches(rt, 62, 0, 56); + __invalidate(rt, 62); + __lookup_matches(rt, 63, 0, 57); + __invalidate(rt, 63); + __lookup_matches(rt, 64, 0, 58); + __invalidate(rt, 64); + __lookup_matches(rt, 65, 0, 59); + __lookup_fails(rt, 65, 1); + __insert(rt, 65, 1, 204); + __lookup_fails(rt, 65, 2); + __insert(rt, 65, 2, 205); + __lookup_fails(rt, 65, 3); + __insert(rt, 65, 3, 206); + __lookup_fails(rt, 65, 4); + __insert(rt, 65, 4, 207); + __lookup_matches(rt, 65, 0, 59); + __lookup_matches(rt, 65, 1, 204); + __lookup_matches(rt, 65, 2, 205); + __lookup_matches(rt, 65, 3, 206); + __lookup_matches(rt, 65, 4, 207); + __lookup_matches(rt, 66, 0, 60); + __invalidate(rt, 66); + __lookup_matches(rt, 67, 0, 61); + __invalidate(rt, 67); + __lookup_matches(rt, 68, 0, 62); + __invalidate(rt, 68); + __lookup_matches(rt, 69, 0, 63); + __invalidate(rt, 69); + __lookup_matches(rt, 70, 0, 64); + __invalidate(rt, 70); + __lookup_matches(rt, 71, 0, 65); + __invalidate(rt, 71); + __lookup_matches(rt, 72, 0, 66); + __invalidate(rt, 72); + __lookup_matches(rt, 73, 0, 67); + __invalidate(rt, 73); + __lookup_matches(rt, 74, 0, 68); + __invalidate(rt, 74); + __lookup_matches(rt, 75, 0, 69); + __invalidate(rt, 75); + __lookup_matches(rt, 76, 0, 70); + __invalidate(rt, 76); + __lookup_matches(rt, 77, 0, 71); + __invalidate(rt, 77); + __lookup_matches(rt, 78, 0, 72); + __invalidate(rt, 78); + __lookup_matches(rt, 79, 0, 73); + __invalidate(rt, 79); + __lookup_matches(rt, 80, 0, 74); + __invalidate(rt, 80); + __lookup_matches(rt, 81, 0, 75); + __invalidate(rt, 81); + __lookup_matches(rt, 82, 0, 76); + __invalidate(rt, 82); + __lookup_matches(rt, 83, 0, 77); + __invalidate(rt, 83); + __lookup_matches(rt, 84, 0, 78); + __invalidate(rt, 84); + __lookup_matches(rt, 85, 0, 79); + __invalidate(rt, 85); + __lookup_matches(rt, 86, 0, 80); + __invalidate(rt, 86); + __lookup_matches(rt, 87, 0, 81); + __invalidate(rt, 87); + __lookup_matches(rt, 88, 0, 82); + __invalidate(rt, 88); + __lookup_matches(rt, 89, 0, 83); + __invalidate(rt, 89); + __lookup_matches(rt, 90, 0, 84); + __invalidate(rt, 90); + __lookup_matches(rt, 91, 0, 85); + __invalidate(rt, 91); + __lookup_matches(rt, 92, 0, 86); + __invalidate(rt, 92); + __lookup_matches(rt, 93, 0, 87); + __invalidate(rt, 93); + __lookup_matches(rt, 94, 0, 88); + __invalidate(rt, 94); + __lookup_matches(rt, 95, 0, 89); + __invalidate(rt, 95); + __lookup_matches(rt, 96, 0, 90); + __lookup_matches(rt, 97, 0, 91); + __invalidate(rt, 97); + __lookup_matches(rt, 98, 0, 92); + __invalidate(rt, 98); + __lookup_matches(rt, 99, 0, 93); + __invalidate(rt, 99); + __lookup_matches(rt, 100, 0, 94); + __invalidate(rt, 100); + __lookup_matches(rt, 101, 0, 95); + __invalidate(rt, 101); + __lookup_matches(rt, 102, 0, 96); + __invalidate(rt, 102); + __lookup_matches(rt, 103, 0, 97); + __invalidate(rt, 103); + __lookup_matches(rt, 104, 0, 98); + __invalidate(rt, 104); + __lookup_matches(rt, 105, 0, 99); + __invalidate(rt, 105); + __lookup_matches(rt, 106, 0, 100); + __invalidate(rt, 106); + __lookup_matches(rt, 107, 0, 101); + __invalidate(rt, 107); + __lookup_matches(rt, 108, 0, 102); + __invalidate(rt, 108); + __lookup_matches(rt, 109, 0, 103); + __invalidate(rt, 109); + __lookup_matches(rt, 110, 0, 104); + __invalidate(rt, 110); + __lookup_matches(rt, 111, 0, 105); + __invalidate(rt, 111); + __lookup_matches(rt, 112, 0, 106); + __invalidate(rt, 112); + __lookup_matches(rt, 113, 0, 107); + __invalidate(rt, 113); + __lookup_matches(rt, 114, 0, 108); + __invalidate(rt, 114); + __lookup_matches(rt, 115, 0, 109); + __invalidate(rt, 115); + __lookup_matches(rt, 116, 0, 110); + __invalidate(rt, 116); + __lookup_matches(rt, 117, 0, 111); + __invalidate(rt, 117); + __lookup_matches(rt, 118, 0, 112); + __invalidate(rt, 118); + __lookup_matches(rt, 119, 0, 113); + __invalidate(rt, 119); + __lookup_matches(rt, 120, 0, 114); + __invalidate(rt, 120); + __lookup_matches(rt, 121, 0, 115); + __invalidate(rt, 121); + __lookup_matches(rt, 122, 0, 116); + __invalidate(rt, 122); + __lookup_matches(rt, 123, 0, 117); + __invalidate(rt, 123); + __lookup_matches(rt, 124, 0, 118); + __invalidate(rt, 124); + __lookup_matches(rt, 125, 0, 119); + __invalidate(rt, 125); + __lookup_matches(rt, 126, 0, 120); + __invalidate(rt, 126); + __lookup_matches(rt, 127, 0, 121); + __invalidate(rt, 127); + __lookup_matches(rt, 128, 0, 122); + __invalidate(rt, 128); + __lookup_matches(rt, 129, 0, 123); + __invalidate(rt, 129); + __lookup_matches(rt, 130, 0, 124); + __invalidate(rt, 130); + __lookup_matches(rt, 131, 0, 125); + __invalidate(rt, 131); + __lookup_matches(rt, 132, 0, 126); + __invalidate(rt, 132); + __lookup_matches(rt, 133, 0, 127); + __invalidate(rt, 133); + __lookup_matches(rt, 134, 0, 128); + __invalidate(rt, 134); + __lookup_matches(rt, 135, 0, 129); + __invalidate(rt, 135); + __lookup_matches(rt, 136, 0, 130); + __invalidate(rt, 136); + __lookup_matches(rt, 137, 0, 131); + __invalidate(rt, 137); + __lookup_matches(rt, 138, 0, 132); + __invalidate(rt, 138); + __lookup_matches(rt, 139, 0, 133); + __invalidate(rt, 139); + __lookup_matches(rt, 140, 0, 134); + __invalidate(rt, 140); + __lookup_matches(rt, 141, 0, 135); + __invalidate(rt, 141); + __lookup_matches(rt, 142, 0, 136); + __invalidate(rt, 142); + __lookup_matches(rt, 143, 0, 137); + __invalidate(rt, 143); + __lookup_matches(rt, 144, 0, 138); + __invalidate(rt, 144); + __lookup_matches(rt, 145, 0, 139); + __invalidate(rt, 145); + __lookup_matches(rt, 146, 0, 140); + __invalidate(rt, 146); + __lookup_matches(rt, 147, 0, 141); + __invalidate(rt, 147); + __lookup_matches(rt, 148, 0, 142); + __invalidate(rt, 148); + __lookup_matches(rt, 149, 0, 143); + __invalidate(rt, 149); + __lookup_matches(rt, 150, 0, 144); + __invalidate(rt, 150); + __lookup_matches(rt, 151, 0, 145); + __invalidate(rt, 151); + __lookup_matches(rt, 152, 0, 146); + __invalidate(rt, 152); + __lookup_matches(rt, 153, 0, 147); + __invalidate(rt, 153); + __lookup_matches(rt, 154, 0, 148); + __invalidate(rt, 154); + __lookup_matches(rt, 155, 0, 149); + __invalidate(rt, 155); + __lookup_matches(rt, 156, 0, 150); + __invalidate(rt, 156); + __lookup_matches(rt, 157, 0, 151); + __invalidate(rt, 157); + __lookup_matches(rt, 158, 0, 152); + __invalidate(rt, 158); + __lookup_matches(rt, 159, 0, 153); + __invalidate(rt, 159); + __lookup_matches(rt, 160, 0, 154); + __invalidate(rt, 160); + __lookup_matches(rt, 161, 0, 155); + __invalidate(rt, 161); + __lookup_matches(rt, 162, 0, 156); + __invalidate(rt, 162); + __lookup_matches(rt, 163, 0, 157); + __lookup_matches(rt, 164, 0, 158); + __invalidate(rt, 164); + __lookup_matches(rt, 165, 0, 159); + __invalidate(rt, 165); + __lookup_matches(rt, 166, 0, 160); + __invalidate(rt, 166); + __lookup_matches(rt, 167, 0, 161); + __invalidate(rt, 167); + __lookup_matches(rt, 168, 0, 162); + __invalidate(rt, 168); + __lookup_matches(rt, 169, 0, 163); + __invalidate(rt, 169); + __lookup_matches(rt, 170, 0, 164); + __invalidate(rt, 170); + __lookup_matches(rt, 171, 0, 165); + __invalidate(rt, 171); + __lookup_matches(rt, 172, 0, 166); + __invalidate(rt, 172); + __lookup_matches(rt, 173, 0, 167); + __invalidate(rt, 173); + __lookup_matches(rt, 174, 0, 168); + __invalidate(rt, 174); + __lookup_matches(rt, 175, 0, 169); + __invalidate(rt, 175); + __lookup_matches(rt, 176, 0, 170); + __invalidate(rt, 176); + __lookup_matches(rt, 177, 0, 171); + __invalidate(rt, 177); + __lookup_matches(rt, 178, 0, 172); + __invalidate(rt, 178); + __lookup_matches(rt, 179, 0, 173); + __invalidate(rt, 179); + __lookup_matches(rt, 180, 0, 174); + __invalidate(rt, 180); + __lookup_matches(rt, 181, 0, 175); + __invalidate(rt, 181); + __lookup_matches(rt, 182, 0, 176); + __invalidate(rt, 182); + __lookup_matches(rt, 183, 0, 177); + __invalidate(rt, 183); + __lookup_matches(rt, 184, 0, 178); + __invalidate(rt, 184); + __lookup_matches(rt, 185, 0, 179); + __invalidate(rt, 185); + __lookup_matches(rt, 186, 0, 180); + __invalidate(rt, 186); + __lookup_matches(rt, 187, 0, 181); + __invalidate(rt, 187); + __lookup_matches(rt, 188, 0, 182); + __invalidate(rt, 188); + __lookup_matches(rt, 189, 0, 183); + __invalidate(rt, 189); + __lookup_matches(rt, 190, 0, 184); + __invalidate(rt, 190); + __lookup_matches(rt, 191, 0, 185); + __invalidate(rt, 191); + __lookup_matches(rt, 192, 0, 186); + __invalidate(rt, 192); + __lookup_matches(rt, 193, 0, 187); + __invalidate(rt, 193); + __lookup_matches(rt, 194, 0, 188); + __invalidate(rt, 194); + __lookup_matches(rt, 195, 0, 189); + __invalidate(rt, 195); + __lookup_matches(rt, 196, 0, 190); + __invalidate(rt, 196); + __lookup_matches(rt, 197, 0, 191); + __invalidate(rt, 197); + __lookup_matches(rt, 198, 0, 192); + __invalidate(rt, 198); + __lookup_matches(rt, 199, 0, 193); + __invalidate(rt, 199); + __lookup_matches(rt, 200, 0, 194); + __invalidate(rt, 200); + __lookup_matches(rt, 201, 0, 195); + __invalidate(rt, 201); + __lookup_matches(rt, 202, 0, 196); + __invalidate(rt, 202); + __lookup_matches(rt, 203, 0, 197); + __invalidate(rt, 203); + __lookup_matches(rt, 204, 0, 198); + __invalidate(rt, 204); + __lookup_matches(rt, 205, 0, 199); + __invalidate(rt, 205); + __lookup_fails(rt, 6, 0); + __insert(rt, 6, 0, 208); + __lookup_fails(rt, 7, 0); + __insert(rt, 7, 0, 209); + __lookup_fails(rt, 8, 0); + __insert(rt, 8, 0, 210); + __lookup_fails(rt, 9, 0); + __insert(rt, 9, 0, 211); + __lookup_fails(rt, 10, 0); + __insert(rt, 10, 0, 212); + __lookup_fails(rt, 11, 0); + __insert(rt, 11, 0, 213); + __lookup_fails(rt, 13, 0); + __insert(rt, 13, 0, 214); + __lookup_fails(rt, 14, 0); + __insert(rt, 14, 0, 215); + __lookup_fails(rt, 15, 0); + __insert(rt, 15, 0, 216); + __lookup_fails(rt, 16, 0); + __insert(rt, 16, 0, 217); + __lookup_fails(rt, 17, 0); + __insert(rt, 17, 0, 218); + __lookup_fails(rt, 18, 0); + __insert(rt, 18, 0, 219); + __lookup_fails(rt, 19, 0); + __insert(rt, 19, 0, 220); + __lookup_fails(rt, 20, 0); + __insert(rt, 20, 0, 221); + __lookup_fails(rt, 21, 0); + __insert(rt, 21, 0, 222); + __lookup_fails(rt, 22, 0); + __insert(rt, 22, 0, 223); + __lookup_fails(rt, 23, 0); + __insert(rt, 23, 0, 224); + __lookup_fails(rt, 24, 0); + __insert(rt, 24, 0, 225); + __lookup_fails(rt, 25, 0); + __insert(rt, 25, 0, 226); + __lookup_fails(rt, 26, 0); + __insert(rt, 26, 0, 227); + __lookup_fails(rt, 27, 0); + __insert(rt, 27, 0, 228); + __lookup_fails(rt, 28, 0); + __insert(rt, 28, 0, 229); + __lookup_fails(rt, 29, 0); + __insert(rt, 29, 0, 230); + __lookup_fails(rt, 30, 0); + __insert(rt, 30, 0, 231); + __lookup_fails(rt, 31, 0); + __insert(rt, 31, 0, 232); + __lookup_fails(rt, 32, 0); + __insert(rt, 32, 0, 233); + __lookup_fails(rt, 33, 0); + __insert(rt, 33, 0, 234); + __lookup_fails(rt, 34, 0); + __insert(rt, 34, 0, 235); + __lookup_fails(rt, 35, 0); + __insert(rt, 35, 0, 236); + __lookup_fails(rt, 36, 0); + __insert(rt, 36, 0, 237); + __lookup_fails(rt, 37, 0); + __insert(rt, 37, 0, 238); + __lookup_fails(rt, 38, 0); + __insert(rt, 38, 0, 239); + __lookup_fails(rt, 39, 0); + __insert(rt, 39, 0, 240); + __lookup_fails(rt, 40, 0); + __insert(rt, 40, 0, 241); + __lookup_fails(rt, 41, 0); + __insert(rt, 41, 0, 242); + __lookup_fails(rt, 42, 0); + __insert(rt, 42, 0, 243); + __lookup_fails(rt, 43, 0); + __insert(rt, 43, 0, 244); + __lookup_fails(rt, 44, 0); + __insert(rt, 44, 0, 245); + __lookup_fails(rt, 45, 0); + __insert(rt, 45, 0, 246); + __lookup_fails(rt, 47, 0); + __insert(rt, 47, 0, 247); + __lookup_fails(rt, 48, 0); + __insert(rt, 48, 0, 248); + __lookup_fails(rt, 49, 0); + __insert(rt, 49, 0, 249); + __lookup_fails(rt, 50, 0); + __insert(rt, 50, 0, 250); + __lookup_fails(rt, 51, 0); + __insert(rt, 51, 0, 251); + __lookup_fails(rt, 52, 0); + __insert(rt, 52, 0, 252); + __lookup_fails(rt, 53, 0); + __insert(rt, 53, 0, 253); + __lookup_fails(rt, 54, 0); + __insert(rt, 54, 0, 254); + __lookup_fails(rt, 55, 0); + __insert(rt, 55, 0, 255); + __lookup_fails(rt, 56, 0); + __insert(rt, 56, 0, 256); + __lookup_fails(rt, 57, 0); + __insert(rt, 57, 0, 257); + __lookup_fails(rt, 58, 0); + __insert(rt, 58, 0, 258); + __lookup_fails(rt, 59, 0); + __insert(rt, 59, 0, 259); + __lookup_fails(rt, 60, 0); + __insert(rt, 60, 0, 260); + __lookup_fails(rt, 61, 0); + __insert(rt, 61, 0, 261); + __lookup_fails(rt, 62, 0); + __insert(rt, 62, 0, 262); + __lookup_fails(rt, 63, 0); + __insert(rt, 63, 0, 263); + __lookup_fails(rt, 64, 0); + __insert(rt, 64, 0, 264); + __lookup_fails(rt, 66, 0); + __insert(rt, 66, 0, 265); + __lookup_fails(rt, 67, 0); + __insert(rt, 67, 0, 266); + __lookup_fails(rt, 68, 0); + __insert(rt, 68, 0, 267); + __lookup_fails(rt, 69, 0); + __insert(rt, 69, 0, 268); + __lookup_fails(rt, 70, 0); + __insert(rt, 70, 0, 269); + __lookup_fails(rt, 71, 0); + __insert(rt, 71, 0, 270); + __lookup_fails(rt, 72, 0); + __insert(rt, 72, 0, 271); + __lookup_fails(rt, 73, 0); + __insert(rt, 73, 0, 272); + __lookup_fails(rt, 74, 0); + __insert(rt, 74, 0, 273); + __lookup_fails(rt, 75, 0); + __insert(rt, 75, 0, 274); + __lookup_fails(rt, 76, 0); + __insert(rt, 76, 0, 275); + __lookup_fails(rt, 77, 0); + __insert(rt, 77, 0, 276); + __lookup_fails(rt, 78, 0); + __insert(rt, 78, 0, 277); + __lookup_fails(rt, 79, 0); + __insert(rt, 79, 0, 278); + __lookup_fails(rt, 80, 0); + __insert(rt, 80, 0, 279); + __lookup_fails(rt, 81, 0); + __insert(rt, 81, 0, 280); + __lookup_fails(rt, 82, 0); + __insert(rt, 82, 0, 281); + __lookup_fails(rt, 83, 0); + __insert(rt, 83, 0, 282); + __lookup_fails(rt, 84, 0); + __insert(rt, 84, 0, 283); + __lookup_fails(rt, 85, 0); + __insert(rt, 85, 0, 284); + __lookup_fails(rt, 86, 0); + __insert(rt, 86, 0, 285); + __lookup_fails(rt, 87, 0); + __insert(rt, 87, 0, 286); + __lookup_fails(rt, 88, 0); + __insert(rt, 88, 0, 287); + __lookup_fails(rt, 89, 0); + __insert(rt, 89, 0, 288); + __lookup_fails(rt, 90, 0); + __insert(rt, 90, 0, 289); + __lookup_fails(rt, 91, 0); + __insert(rt, 91, 0, 290); + __lookup_fails(rt, 92, 0); + __insert(rt, 92, 0, 291); + __lookup_fails(rt, 93, 0); + __insert(rt, 93, 0, 292); + __lookup_fails(rt, 94, 0); + __insert(rt, 94, 0, 293); + __lookup_fails(rt, 95, 0); + __insert(rt, 95, 0, 294); + __lookup_fails(rt, 97, 0); + __insert(rt, 97, 0, 295); + __lookup_fails(rt, 98, 0); + __insert(rt, 98, 0, 296); + __lookup_fails(rt, 99, 0); + __insert(rt, 99, 0, 297); + __lookup_fails(rt, 100, 0); + __insert(rt, 100, 0, 298); + __lookup_fails(rt, 101, 0); + __insert(rt, 101, 0, 299); + __lookup_fails(rt, 102, 0); + __insert(rt, 102, 0, 300); + __lookup_fails(rt, 103, 0); + __insert(rt, 103, 0, 301); + __lookup_fails(rt, 104, 0); + __insert(rt, 104, 0, 302); + __lookup_fails(rt, 105, 0); + __insert(rt, 105, 0, 303); + __lookup_fails(rt, 106, 0); + __insert(rt, 106, 0, 304); + __lookup_fails(rt, 107, 0); + __insert(rt, 107, 0, 305); + __lookup_fails(rt, 108, 0); + __insert(rt, 108, 0, 306); + __lookup_fails(rt, 109, 0); + __insert(rt, 109, 0, 307); + __lookup_fails(rt, 110, 0); + __insert(rt, 110, 0, 308); + __lookup_fails(rt, 111, 0); + __insert(rt, 111, 0, 309); + __lookup_fails(rt, 112, 0); + __insert(rt, 112, 0, 310); + __lookup_fails(rt, 113, 0); + __insert(rt, 113, 0, 311); + __lookup_fails(rt, 114, 0); + __insert(rt, 114, 0, 312); + __lookup_fails(rt, 115, 0); + __insert(rt, 115, 0, 313); + __lookup_fails(rt, 116, 0); + __insert(rt, 116, 0, 314); + __lookup_fails(rt, 117, 0); + __insert(rt, 117, 0, 315); + __lookup_fails(rt, 118, 0); + __insert(rt, 118, 0, 316); + __lookup_fails(rt, 119, 0); + __insert(rt, 119, 0, 317); + __lookup_fails(rt, 120, 0); + __insert(rt, 120, 0, 318); + __lookup_fails(rt, 121, 0); + __insert(rt, 121, 0, 319); + __lookup_fails(rt, 122, 0); + __insert(rt, 122, 0, 320); + __lookup_fails(rt, 123, 0); + __insert(rt, 123, 0, 321); + __lookup_fails(rt, 124, 0); + __insert(rt, 124, 0, 322); + __lookup_fails(rt, 125, 0); + __insert(rt, 125, 0, 323); + __lookup_fails(rt, 126, 0); + __insert(rt, 126, 0, 324); + __lookup_fails(rt, 127, 0); + __insert(rt, 127, 0, 325); + __lookup_fails(rt, 128, 0); + __insert(rt, 128, 0, 326); + __lookup_fails(rt, 129, 0); + __insert(rt, 129, 0, 327); + __lookup_fails(rt, 130, 0); + __insert(rt, 130, 0, 328); + __lookup_fails(rt, 131, 0); + __insert(rt, 131, 0, 329); + __lookup_fails(rt, 132, 0); + __insert(rt, 132, 0, 330); + __lookup_fails(rt, 133, 0); + __insert(rt, 133, 0, 331); + __lookup_fails(rt, 134, 0); + __insert(rt, 134, 0, 332); + __lookup_fails(rt, 135, 0); + __insert(rt, 135, 0, 333); + __lookup_fails(rt, 136, 0); + __insert(rt, 136, 0, 334); + __lookup_fails(rt, 137, 0); + __insert(rt, 137, 0, 335); + __lookup_fails(rt, 138, 0); + __insert(rt, 138, 0, 336); + __lookup_fails(rt, 139, 0); + __insert(rt, 139, 0, 337); + __lookup_fails(rt, 140, 0); + __insert(rt, 140, 0, 338); + __lookup_fails(rt, 141, 0); + __insert(rt, 141, 0, 339); + __lookup_fails(rt, 142, 0); + __insert(rt, 142, 0, 340); + __lookup_fails(rt, 143, 0); + __insert(rt, 143, 0, 341); + __lookup_fails(rt, 144, 0); + __insert(rt, 144, 0, 342); + __lookup_fails(rt, 145, 0); + __insert(rt, 145, 0, 343); + __lookup_fails(rt, 146, 0); + __insert(rt, 146, 0, 344); + __lookup_fails(rt, 147, 0); + __insert(rt, 147, 0, 345); + __lookup_fails(rt, 148, 0); + __insert(rt, 148, 0, 346); + __lookup_fails(rt, 149, 0); + __insert(rt, 149, 0, 347); + __lookup_fails(rt, 150, 0); + __insert(rt, 150, 0, 348); + __lookup_fails(rt, 151, 0); + __insert(rt, 151, 0, 349); + __lookup_fails(rt, 152, 0); + __insert(rt, 152, 0, 350); + __lookup_fails(rt, 153, 0); + __insert(rt, 153, 0, 351); + __lookup_fails(rt, 154, 0); + __insert(rt, 154, 0, 352); + __lookup_fails(rt, 155, 0); + __insert(rt, 155, 0, 353); + __lookup_fails(rt, 156, 0); + __insert(rt, 156, 0, 354); + __lookup_fails(rt, 157, 0); + __insert(rt, 157, 0, 355); + __lookup_fails(rt, 158, 0); + __insert(rt, 158, 0, 356); + __lookup_fails(rt, 159, 0); + __insert(rt, 159, 0, 357); + __lookup_fails(rt, 160, 0); + __insert(rt, 160, 0, 358); + __lookup_fails(rt, 161, 0); + __insert(rt, 161, 0, 359); + __lookup_fails(rt, 162, 0); + __insert(rt, 162, 0, 360); + __lookup_fails(rt, 164, 0); + __insert(rt, 164, 0, 361); + __lookup_fails(rt, 165, 0); + __insert(rt, 165, 0, 362); + __lookup_fails(rt, 166, 0); + __insert(rt, 166, 0, 363); + __lookup_fails(rt, 167, 0); + __insert(rt, 167, 0, 364); + __lookup_fails(rt, 168, 0); + __insert(rt, 168, 0, 365); + __lookup_fails(rt, 169, 0); + __insert(rt, 169, 0, 366); + __lookup_fails(rt, 170, 0); + __insert(rt, 170, 0, 367); + __lookup_fails(rt, 171, 0); + __insert(rt, 171, 0, 368); + __lookup_fails(rt, 172, 0); + __insert(rt, 172, 0, 369); + __lookup_fails(rt, 173, 0); + __insert(rt, 173, 0, 370); + __lookup_fails(rt, 174, 0); + __insert(rt, 174, 0, 371); + __lookup_fails(rt, 175, 0); + __insert(rt, 175, 0, 372); + __lookup_fails(rt, 176, 0); + __insert(rt, 176, 0, 373); + __lookup_fails(rt, 177, 0); + __insert(rt, 177, 0, 374); + __lookup_fails(rt, 178, 0); + __insert(rt, 178, 0, 375); + __lookup_fails(rt, 179, 0); + __insert(rt, 179, 0, 376); + __lookup_fails(rt, 180, 0); + __insert(rt, 180, 0, 377); + __lookup_fails(rt, 181, 0); + __insert(rt, 181, 0, 378); + __lookup_fails(rt, 182, 0); + __insert(rt, 182, 0, 379); + __lookup_fails(rt, 183, 0); + __insert(rt, 183, 0, 380); + __lookup_fails(rt, 184, 0); + __insert(rt, 184, 0, 381); + __lookup_fails(rt, 185, 0); + __insert(rt, 185, 0, 382); + __lookup_fails(rt, 186, 0); + __insert(rt, 186, 0, 383); + __lookup_fails(rt, 187, 0); + __insert(rt, 187, 0, 384); + __lookup_fails(rt, 188, 0); + __insert(rt, 188, 0, 385); + __lookup_fails(rt, 189, 0); + __insert(rt, 189, 0, 386); + __lookup_fails(rt, 190, 0); + __insert(rt, 190, 0, 387); + __lookup_fails(rt, 191, 0); + __insert(rt, 191, 0, 388); + __lookup_fails(rt, 192, 0); + __insert(rt, 192, 0, 389); + __lookup_fails(rt, 193, 0); + __insert(rt, 193, 0, 390); + __lookup_fails(rt, 194, 0); + __insert(rt, 194, 0, 391); + __lookup_fails(rt, 195, 0); + __insert(rt, 195, 0, 392); + __lookup_fails(rt, 196, 0); + __insert(rt, 196, 0, 393); + __lookup_fails(rt, 197, 0); + __insert(rt, 197, 0, 394); + __lookup_fails(rt, 198, 0); + __insert(rt, 198, 0, 395); + __lookup_fails(rt, 199, 0); + __insert(rt, 199, 0, 396); + __lookup_fails(rt, 200, 0); + __insert(rt, 200, 0, 397); + __lookup_fails(rt, 201, 0); + __insert(rt, 201, 0, 398); + __lookup_fails(rt, 202, 0); + __insert(rt, 202, 0, 399); + __lookup_fails(rt, 203, 0); + __insert(rt, 203, 0, 400); + __lookup_fails(rt, 204, 0); + __insert(rt, 204, 0, 401); + __lookup_fails(rt, 205, 0); + __insert(rt, 205, 0, 402); + __lookup_fails(rt, 206, 0); + __insert(rt, 206, 0, 403); + __lookup_fails(rt, 207, 0); + __insert(rt, 207, 0, 404); + __lookup_fails(rt, 208, 0); + __insert(rt, 208, 0, 405); + __lookup_fails(rt, 209, 0); + __insert(rt, 209, 0, 406); + __lookup_fails(rt, 210, 0); + __insert(rt, 210, 0, 407); + __lookup_matches(rt, 6, 0, 208); + __invalidate(rt, 6); + __lookup_matches(rt, 7, 0, 209); + __invalidate(rt, 7); + __lookup_matches(rt, 8, 0, 210); + __invalidate(rt, 8); + __lookup_matches(rt, 9, 0, 211); + __invalidate(rt, 9); + __lookup_matches(rt, 10, 0, 212); + __invalidate(rt, 10); + __lookup_matches(rt, 11, 0, 213); + __invalidate(rt, 11); + __lookup_matches(rt, 13, 0, 214); + __invalidate(rt, 13); + __lookup_matches(rt, 14, 0, 215); + __invalidate(rt, 14); + __lookup_matches(rt, 15, 0, 216); + __invalidate(rt, 15); + __lookup_matches(rt, 16, 0, 217); + __invalidate(rt, 16); + __lookup_matches(rt, 17, 0, 218); + __invalidate(rt, 17); + __lookup_matches(rt, 18, 0, 219); + __invalidate(rt, 18); + __lookup_matches(rt, 19, 0, 220); + __invalidate(rt, 19); + __lookup_matches(rt, 20, 0, 221); + __invalidate(rt, 20); + __lookup_matches(rt, 21, 0, 222); + __invalidate(rt, 21); + __lookup_matches(rt, 22, 0, 223); + __invalidate(rt, 22); + __lookup_matches(rt, 23, 0, 224); + __invalidate(rt, 23); + __lookup_matches(rt, 24, 0, 225); + __invalidate(rt, 24); + __lookup_matches(rt, 25, 0, 226); + __invalidate(rt, 25); + __lookup_matches(rt, 26, 0, 227); + __invalidate(rt, 26); + __lookup_matches(rt, 27, 0, 228); + __invalidate(rt, 27); + __lookup_matches(rt, 28, 0, 229); + __invalidate(rt, 28); + __lookup_matches(rt, 29, 0, 230); + __invalidate(rt, 29); + __lookup_matches(rt, 30, 0, 231); + __invalidate(rt, 30); + __lookup_matches(rt, 31, 0, 232); + __invalidate(rt, 31); + __lookup_matches(rt, 32, 0, 233); + __invalidate(rt, 32); + __lookup_matches(rt, 33, 0, 234); + __invalidate(rt, 33); + __lookup_matches(rt, 34, 0, 235); + __invalidate(rt, 34); + __lookup_matches(rt, 35, 0, 236); + __invalidate(rt, 35); + __lookup_matches(rt, 36, 0, 237); + __invalidate(rt, 36); + __lookup_matches(rt, 37, 0, 238); + __invalidate(rt, 37); + __lookup_matches(rt, 38, 0, 239); + __invalidate(rt, 38); + __lookup_matches(rt, 39, 0, 240); + __invalidate(rt, 39); + __lookup_matches(rt, 40, 0, 241); + __invalidate(rt, 40); + __lookup_matches(rt, 41, 0, 242); + __invalidate(rt, 41); + __lookup_matches(rt, 42, 0, 243); + __invalidate(rt, 42); + __lookup_matches(rt, 43, 0, 244); + __invalidate(rt, 43); + __lookup_matches(rt, 44, 0, 245); + __invalidate(rt, 44); + __lookup_matches(rt, 45, 0, 246); + __invalidate(rt, 45); + __lookup_matches(rt, 47, 0, 247); + __invalidate(rt, 47); + __lookup_matches(rt, 48, 0, 248); + __invalidate(rt, 48); + __lookup_matches(rt, 49, 0, 249); + __invalidate(rt, 49); + __lookup_matches(rt, 50, 0, 250); + __invalidate(rt, 50); + __lookup_matches(rt, 51, 0, 251); + __invalidate(rt, 51); + __lookup_matches(rt, 52, 0, 252); + __invalidate(rt, 52); + __lookup_matches(rt, 53, 0, 253); + __invalidate(rt, 53); + __lookup_matches(rt, 54, 0, 254); + __invalidate(rt, 54); + __lookup_matches(rt, 55, 0, 255); + __invalidate(rt, 55); + __lookup_matches(rt, 56, 0, 256); + __invalidate(rt, 56); + __lookup_matches(rt, 57, 0, 257); + __invalidate(rt, 57); + __lookup_matches(rt, 58, 0, 258); + __invalidate(rt, 58); + __lookup_matches(rt, 59, 0, 259); + __invalidate(rt, 59); + __lookup_matches(rt, 60, 0, 260); + __invalidate(rt, 60); + __lookup_matches(rt, 61, 0, 261); + __invalidate(rt, 61); + __lookup_matches(rt, 62, 0, 262); + __invalidate(rt, 62); + __lookup_matches(rt, 63, 0, 263); + __invalidate(rt, 63); + __lookup_matches(rt, 64, 0, 264); + __invalidate(rt, 64); + __lookup_matches(rt, 66, 0, 265); + __invalidate(rt, 66); + __lookup_matches(rt, 67, 0, 266); + __invalidate(rt, 67); + __lookup_matches(rt, 68, 0, 267); + __invalidate(rt, 68); + __lookup_matches(rt, 69, 0, 268); + __invalidate(rt, 69); + __lookup_matches(rt, 70, 0, 269); + __invalidate(rt, 70); + __lookup_matches(rt, 71, 0, 270); + __invalidate(rt, 71); + __lookup_matches(rt, 72, 0, 271); + __invalidate(rt, 72); + __lookup_matches(rt, 73, 0, 272); + __lookup_matches(rt, 74, 0, 273); + __invalidate(rt, 74); + __lookup_matches(rt, 75, 0, 274); + __invalidate(rt, 75); + __lookup_matches(rt, 76, 0, 275); + __invalidate(rt, 76); + __lookup_matches(rt, 77, 0, 276); + __invalidate(rt, 77); + __lookup_matches(rt, 78, 0, 277); + __invalidate(rt, 78); + __lookup_matches(rt, 79, 0, 278); + __invalidate(rt, 79); + __lookup_matches(rt, 80, 0, 279); + __invalidate(rt, 80); + __lookup_matches(rt, 81, 0, 280); + __invalidate(rt, 81); + __lookup_matches(rt, 82, 0, 281); + __invalidate(rt, 82); + __lookup_matches(rt, 83, 0, 282); + __invalidate(rt, 83); + __lookup_matches(rt, 84, 0, 283); + __invalidate(rt, 84); + __lookup_matches(rt, 85, 0, 284); + __invalidate(rt, 85); + __lookup_matches(rt, 86, 0, 285); + __invalidate(rt, 86); + __lookup_matches(rt, 87, 0, 286); + __invalidate(rt, 87); + __lookup_matches(rt, 88, 0, 287); + __invalidate(rt, 88); + __lookup_matches(rt, 89, 0, 288); + __invalidate(rt, 89); + __lookup_matches(rt, 90, 0, 289); + __invalidate(rt, 90); + __lookup_matches(rt, 91, 0, 290); + __invalidate(rt, 91); + __lookup_matches(rt, 92, 0, 291); + __invalidate(rt, 92); + __lookup_matches(rt, 93, 0, 292); + __invalidate(rt, 93); + __lookup_matches(rt, 94, 0, 293); + __invalidate(rt, 94); + __lookup_matches(rt, 95, 0, 294); + __invalidate(rt, 95); + __lookup_matches(rt, 97, 0, 295); + __invalidate(rt, 97); + __lookup_matches(rt, 98, 0, 296); + __invalidate(rt, 98); + __lookup_matches(rt, 99, 0, 297); + __invalidate(rt, 99); + __lookup_matches(rt, 100, 0, 298); + __invalidate(rt, 100); + __lookup_matches(rt, 101, 0, 299); + __invalidate(rt, 101); + __lookup_matches(rt, 102, 0, 300); + __invalidate(rt, 102); + __lookup_matches(rt, 103, 0, 301); + __invalidate(rt, 103); + __lookup_matches(rt, 104, 0, 302); + __invalidate(rt, 104); + __lookup_matches(rt, 105, 0, 303); + __invalidate(rt, 105); + __lookup_matches(rt, 106, 0, 304); + __invalidate(rt, 106); + __lookup_matches(rt, 107, 0, 305); + __invalidate(rt, 107); + __lookup_matches(rt, 108, 0, 306); + __invalidate(rt, 108); + __lookup_matches(rt, 109, 0, 307); + __invalidate(rt, 109); + __lookup_matches(rt, 110, 0, 308); + __invalidate(rt, 110); + __lookup_matches(rt, 111, 0, 309); + __invalidate(rt, 111); + __lookup_matches(rt, 112, 0, 310); + __invalidate(rt, 112); + __lookup_matches(rt, 113, 0, 311); + __invalidate(rt, 113); + __lookup_matches(rt, 114, 0, 312); + __invalidate(rt, 114); + __lookup_matches(rt, 115, 0, 313); + __invalidate(rt, 115); + __lookup_matches(rt, 116, 0, 314); + __invalidate(rt, 116); + __lookup_matches(rt, 117, 0, 315); + __invalidate(rt, 117); + __lookup_matches(rt, 118, 0, 316); + __invalidate(rt, 118); + __lookup_matches(rt, 119, 0, 317); + __invalidate(rt, 119); + __lookup_matches(rt, 120, 0, 318); + __invalidate(rt, 120); + __lookup_matches(rt, 121, 0, 319); + __invalidate(rt, 121); + __lookup_matches(rt, 122, 0, 320); + __invalidate(rt, 122); + __lookup_matches(rt, 123, 0, 321); + __invalidate(rt, 123); + __lookup_matches(rt, 124, 0, 322); + __invalidate(rt, 124); + __lookup_matches(rt, 125, 0, 323); + __invalidate(rt, 125); + __lookup_matches(rt, 126, 0, 324); + __invalidate(rt, 126); + __lookup_matches(rt, 127, 0, 325); + __invalidate(rt, 127); + __lookup_matches(rt, 128, 0, 326); + __invalidate(rt, 128); + __lookup_matches(rt, 129, 0, 327); + __invalidate(rt, 129); + __lookup_matches(rt, 130, 0, 328); + __invalidate(rt, 130); + __lookup_matches(rt, 131, 0, 329); + __invalidate(rt, 131); + __lookup_matches(rt, 132, 0, 330); + __invalidate(rt, 132); + __lookup_matches(rt, 133, 0, 331); + __invalidate(rt, 133); + __lookup_matches(rt, 134, 0, 332); + __invalidate(rt, 134); + __lookup_matches(rt, 135, 0, 333); + __invalidate(rt, 135); + __lookup_matches(rt, 136, 0, 334); + __invalidate(rt, 136); + __lookup_matches(rt, 137, 0, 335); + __invalidate(rt, 137); + __lookup_matches(rt, 138, 0, 336); + __invalidate(rt, 138); + __lookup_matches(rt, 139, 0, 337); + __invalidate(rt, 139); + __lookup_matches(rt, 140, 0, 338); + __invalidate(rt, 140); + __lookup_matches(rt, 141, 0, 339); + __invalidate(rt, 141); + __lookup_matches(rt, 142, 0, 340); + __invalidate(rt, 142); + __lookup_matches(rt, 143, 0, 341); + __invalidate(rt, 143); + __lookup_matches(rt, 144, 0, 342); + __invalidate(rt, 144); + __lookup_matches(rt, 145, 0, 343); + __invalidate(rt, 145); + __lookup_matches(rt, 146, 0, 344); + __invalidate(rt, 146); + __lookup_matches(rt, 147, 0, 345); + __invalidate(rt, 147); + __lookup_matches(rt, 148, 0, 346); + __invalidate(rt, 148); + __lookup_matches(rt, 149, 0, 347); + __invalidate(rt, 149); + __lookup_matches(rt, 150, 0, 348); + __invalidate(rt, 150); + __lookup_matches(rt, 151, 0, 349); + __invalidate(rt, 151); + __lookup_matches(rt, 152, 0, 350); + __invalidate(rt, 152); + __lookup_matches(rt, 153, 0, 351); + __invalidate(rt, 153); + __lookup_matches(rt, 154, 0, 352); + __invalidate(rt, 154); + __lookup_matches(rt, 155, 0, 353); + __invalidate(rt, 155); + __lookup_matches(rt, 156, 0, 354); + __invalidate(rt, 156); + __lookup_matches(rt, 157, 0, 355); + __invalidate(rt, 157); + __lookup_matches(rt, 158, 0, 356); + __invalidate(rt, 158); + __lookup_matches(rt, 159, 0, 357); + __invalidate(rt, 159); + __lookup_matches(rt, 160, 0, 358); + __invalidate(rt, 160); + __lookup_matches(rt, 161, 0, 359); + __invalidate(rt, 161); + __lookup_matches(rt, 162, 0, 360); + __invalidate(rt, 162); + __lookup_matches(rt, 164, 0, 361); + __invalidate(rt, 164); + __lookup_matches(rt, 165, 0, 362); + __invalidate(rt, 165); + __lookup_matches(rt, 166, 0, 363); + __invalidate(rt, 166); + __lookup_matches(rt, 167, 0, 364); + __invalidate(rt, 167); + __lookup_matches(rt, 168, 0, 365); + __invalidate(rt, 168); + __lookup_matches(rt, 169, 0, 366); + __invalidate(rt, 169); + __lookup_matches(rt, 170, 0, 367); + __invalidate(rt, 170); + __lookup_matches(rt, 171, 0, 368); + __invalidate(rt, 171); + __lookup_matches(rt, 172, 0, 369); + __invalidate(rt, 172); + __lookup_matches(rt, 173, 0, 370); + __invalidate(rt, 173); + __lookup_matches(rt, 174, 0, 371); + __invalidate(rt, 174); + __lookup_matches(rt, 175, 0, 372); + __invalidate(rt, 175); + __lookup_matches(rt, 176, 0, 373); + __invalidate(rt, 176); + __lookup_matches(rt, 177, 0, 374); + __invalidate(rt, 177); + __lookup_matches(rt, 178, 0, 375); + __invalidate(rt, 178); + __lookup_matches(rt, 179, 0, 376); + __invalidate(rt, 179); + __lookup_matches(rt, 180, 0, 377); + __invalidate(rt, 180); + __lookup_matches(rt, 181, 0, 378); + __invalidate(rt, 181); + __lookup_matches(rt, 182, 0, 379); + __invalidate(rt, 182); + __lookup_matches(rt, 183, 0, 380); + __invalidate(rt, 183); + __lookup_matches(rt, 184, 0, 381); + __invalidate(rt, 184); + __lookup_matches(rt, 185, 0, 382); + __invalidate(rt, 185); + __lookup_matches(rt, 186, 0, 383); + __invalidate(rt, 186); + __lookup_matches(rt, 187, 0, 384); + __invalidate(rt, 187); + __lookup_matches(rt, 188, 0, 385); + __invalidate(rt, 188); + __lookup_matches(rt, 189, 0, 386); + __invalidate(rt, 189); + __lookup_matches(rt, 190, 0, 387); + __invalidate(rt, 190); + __lookup_matches(rt, 191, 0, 388); + __invalidate(rt, 191); + __lookup_matches(rt, 192, 0, 389); + __invalidate(rt, 192); + __lookup_matches(rt, 193, 0, 390); + __invalidate(rt, 193); + __lookup_matches(rt, 194, 0, 391); + __invalidate(rt, 194); + __lookup_matches(rt, 195, 0, 392); + __invalidate(rt, 195); + __lookup_matches(rt, 196, 0, 393); + __invalidate(rt, 196); + __lookup_matches(rt, 197, 0, 394); + __invalidate(rt, 197); + __lookup_matches(rt, 198, 0, 395); + __invalidate(rt, 198); + __lookup_matches(rt, 199, 0, 396); + __invalidate(rt, 199); + __lookup_matches(rt, 200, 0, 397); + __invalidate(rt, 200); + __lookup_matches(rt, 201, 0, 398); + __invalidate(rt, 201); + __lookup_matches(rt, 202, 0, 399); + __invalidate(rt, 202); + __lookup_matches(rt, 203, 0, 400); + __invalidate(rt, 203); + __lookup_matches(rt, 204, 0, 401); + __invalidate(rt, 204); + __lookup_matches(rt, 205, 0, 402); + __invalidate(rt, 205); + __lookup_matches(rt, 206, 0, 403); + __invalidate(rt, 206); + __lookup_matches(rt, 207, 0, 404); + __invalidate(rt, 207); + __lookup_matches(rt, 208, 0, 405); + __invalidate(rt, 208); + __lookup_matches(rt, 209, 0, 406); + __invalidate(rt, 209); + __lookup_matches(rt, 210, 0, 407); + __invalidate(rt, 210); + __lookup_fails(rt, 6, 0); + __insert(rt, 6, 0, 408); + __lookup_fails(rt, 7, 0); + __insert(rt, 7, 0, 409); + __lookup_fails(rt, 8, 0); + __insert(rt, 8, 0, 410); + __lookup_fails(rt, 9, 0); + __insert(rt, 9, 0, 411); + __lookup_fails(rt, 10, 0); + __insert(rt, 10, 0, 412); + __lookup_fails(rt, 11, 0); + __insert(rt, 11, 0, 413); + __lookup_fails(rt, 13, 0); + __insert(rt, 13, 0, 414); + __lookup_fails(rt, 14, 0); + __insert(rt, 14, 0, 415); + __lookup_fails(rt, 15, 0); + __insert(rt, 15, 0, 416); + __lookup_fails(rt, 16, 0); + __insert(rt, 16, 0, 417); + __lookup_fails(rt, 17, 0); + __insert(rt, 17, 0, 418); + __lookup_fails(rt, 18, 0); + __insert(rt, 18, 0, 419); + __lookup_fails(rt, 19, 0); + __insert(rt, 19, 0, 420); + __lookup_fails(rt, 20, 0); + __insert(rt, 20, 0, 421); + __lookup_fails(rt, 21, 0); + __insert(rt, 21, 0, 422); + __lookup_fails(rt, 22, 0); + __insert(rt, 22, 0, 423); + __lookup_fails(rt, 23, 0); + __insert(rt, 23, 0, 424); + __lookup_matches(rt, 6, 0, 408); + __invalidate(rt, 6); + __lookup_matches(rt, 7, 0, 409); + __invalidate(rt, 7); + __lookup_matches(rt, 8, 0, 410); + __invalidate(rt, 8); + __lookup_matches(rt, 9, 0, 411); + __invalidate(rt, 9); + __lookup_matches(rt, 10, 0, 412); + __invalidate(rt, 10); + __lookup_matches(rt, 11, 0, 413); + __invalidate(rt, 11); + __lookup_matches(rt, 13, 0, 414); + __invalidate(rt, 13); + __lookup_matches(rt, 14, 0, 415); diff --git a/test/unit/run.c b/test/unit/run.c index 482498a..84b867b 100644 --- a/test/unit/run.c +++ b/test/unit/run.c @@ -1,29 +1,312 @@ -#include -#include - -#define DECL(n) \ - extern CU_TestInfo n ## _list[]; \ - int n ## _init(void); \ - int n ## _fini(void); -#define USE(n) { (char*) #n, n##_init, n##_fini, n##_list } - -DECL(bitset); -DECL(regex); -DECL(config); -DECL(string); - -CU_SuiteInfo suites[] = { - USE(bitset), - USE(regex), - USE(config), - USE(string), - CU_SUITE_INFO_NULL +#include "units.h" + +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------- + +#define MAX_COMPONENTS 16 + +struct token { + const char *b, *e; }; -int main(int argc, char **argv) { - CU_initialize_registry(); - CU_register_suites(suites); - CU_basic_set_mode(CU_BRM_VERBOSE); - CU_basic_run_tests(); - return CU_get_number_of_failures() != 0; +static bool _pop_component(const char *path, struct token *result) +{ + const char *b, *e; + + while (*path && *path == '/') + path++; + + b = path; + while (*path && (*path != '/')) + path++; + e = path; + + if (b == e) + return false; + + result->b = b; + result->e = e; + return true; +} + +static unsigned _split_components(const char *path, struct token *toks, unsigned len) +{ + unsigned count = 0; + struct token tok; + tok.e = path; + + while (len && _pop_component(tok.e, &tok)) { + *toks = tok; + toks++; + count++; + len--; + } + + return count; +} + +static void _indent(FILE *stream, unsigned count) +{ + unsigned i; + + for (i = 0; i < count; i++) + fprintf(stream, " "); +} + +static void _print_token(FILE *stream, struct token *t) +{ + const char *ptr; + + for (ptr = t->b; ptr != t->e; ptr++) + fprintf(stream, "%c", *ptr); +} + +static int _char_cmp(char l, char r) +{ + if (l < r) + return -1; + + else if (r < l) + return 1; + + else + return 0; +} + +static int _tok_cmp(struct token *lhs, struct token *rhs) +{ + const char *l = lhs->b, *le = lhs->e; + const char *r = rhs->b, *re = rhs->e; + + while ((l != le) && (r != re) && (*l == *r)) { + l++; + r++; + } + + if ((l != le) && (r != re)) + return _char_cmp(*l, *r); + + else if (r != re) + return -1; + + else if (l != le) + return 1; + + else + return 0; +} + +static void _print_path_delta(FILE *stream, + struct token *old, unsigned old_len, + struct token *new, unsigned new_len, + const char *desc) +{ + unsigned i, common_prefix = 0, len, d; + unsigned max_prefix = old_len < new_len ? old_len : new_len; + + for (i = 0; i < max_prefix; i++) { + if (_tok_cmp(old + i, new + i)) + break; + else + common_prefix++; + } + + for (; i < new_len; i++) { + _indent(stream, common_prefix); + _print_token(stream, new + i); + common_prefix++; + if (i < new_len - 1) + fprintf(stream, "\n"); + } + + len = (new_len > 0) ? common_prefix * 2 + (new[new_len - 1].e - new[new_len - 1].b) : 0; + + fprintf(stream, " "); + for (d = len; d < 60; d++) + fprintf(stream, "."); + fprintf(stream, " "); + fprintf(stream, "%s", desc); + fprintf(stream, "\n"); +} + +typedef struct token comp_t[MAX_COMPONENTS]; + +static void _list_tests(struct test_details **tests, unsigned nr) +{ + unsigned i, current = 0, current_len, last_len = 0; + + comp_t components[2]; + + for (i = 0; i < nr; i++) { + struct test_details *t = tests[i]; + current_len = _split_components(t->path, components[current], MAX_COMPONENTS); + _print_path_delta(stderr, components[!current], last_len, + components[current], current_len, t->desc); + + last_len = current_len; + current = !current; + } +} + +static void _destroy_tests(struct dm_list *suites) +{ + struct test_suite *ts, *tmp; + + dm_list_iterate_items_safe (ts, tmp, suites) + test_suite_destroy(ts); +} + +static const char *red(bool c) +{ + return c ? "\x1B[31m" : ""; +} + +static const char *green(bool c) +{ + return c ? "\x1B[32m" : ""; +} + +static const char *normal(bool c) +{ + return c ? "\x1B[0m" : ""; +} + +static void _run_test(struct test_details *t, bool use_colour, unsigned *passed, unsigned *total) +{ + void *fixture; + struct test_suite *ts = t->parent; + fprintf(stderr, "[RUN ] %s\n", t->path); + + (*total)++; + if (setjmp(test_k)) + fprintf(stderr, "%s[ FAIL]%s %s\n", red(use_colour), normal(use_colour), t->path); + else { + if (ts->fixture_init) + fixture = ts->fixture_init(); + else + fixture = NULL; + + t->fn(fixture); + + if (ts->fixture_exit) + ts->fixture_exit(fixture); + + (*passed)++; + fprintf(stderr, "%s[ OK]%s\n", green(use_colour), normal(use_colour)); + /* coverity[leaked_storage] fixture released by fixture_exit */ + } } + +static bool _run_tests(struct test_details **tests, unsigned nr) +{ + bool use_colour = isatty(fileno(stderr)); + unsigned i, passed = 0, total = 0; + + for (i = 0; i < nr; i++) + _run_test(tests[i], use_colour, &passed, &total); + + fprintf(stderr, "\n%u/%u tests passed\n", passed, total); + + return passed == total; +} + +static void _usage(void) +{ + fprintf(stderr, "Usage: unit-test [pattern]\n"); +} + +static int _cmp_paths(const void *lhs, const void *rhs) +{ + struct test_details *l = *((struct test_details **) lhs); + struct test_details *r = *((struct test_details **) rhs); + + return strcmp(l->path, r->path); +} + +static unsigned _filter(const char *pattern, struct test_details **tests, unsigned nr) +{ + unsigned i, found = 0; + regex_t rx; + + if (regcomp(&rx, pattern, 0)) { + fprintf(stderr, "couldn't compile regex '%s'\n", pattern); + exit(1); + } + + for (i = 0; i < nr; i++) + if (tests[i] && !regexec(&rx, tests[i]->path, 0, NULL, 0)) + tests[found++] = tests[i]; + + regfree(&rx); + + return found; +} + +int main(int argc, char **argv) +{ + int r; + unsigned i, nr_tests; + struct test_suite *ts; + struct test_details *t, **t_array; + struct dm_list suites; + + dm_list_init(&suites); + register_all_tests(&suites); + + // count all tests + nr_tests = 0; + dm_list_iterate_items (ts, &suites) + dm_list_iterate_items (t, &ts->tests) + nr_tests++; + + // stick them in an array + t_array = malloc(sizeof(*t_array) * nr_tests); + if (!t_array) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + memset(t_array, 0, sizeof(*t_array) * nr_tests); + + i = 0; + dm_list_iterate_items (ts, &suites) + dm_list_iterate_items (t, &ts->tests) + t_array[i++] = t; + + // filter + if (argc == 3) + nr_tests = _filter(argv[2], t_array, nr_tests); + + // sort + qsort(t_array, nr_tests, sizeof(*t_array), _cmp_paths); + + // run or list them + if (argc == 1) + r = !_run_tests(t_array, nr_tests); + else { + const char *cmd = argv[1]; + if (!strcmp(cmd, "run")) + r = !_run_tests(t_array, nr_tests); + + else if (!strcmp(cmd, "list")) { + _list_tests(t_array, nr_tests); + r = 0; + + } else { + _usage(); + r = 1; + } + } + + free(t_array); + _destroy_tests(&suites); + + return r; +} + +//----------------------------------------------------------------- diff --git a/test/unit/string_t.c b/test/unit/string_t.c index df72505..82c6448 100644 --- a/test/unit/string_t.c +++ b/test/unit/string_t.c @@ -9,50 +9,48 @@ * * 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 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libdevmapper.h" +#include "units.h" +#include "device_mapper/all.h" #include #include -#include - -int string_init(void); -int string_fini(void); - -static struct dm_pool *mem = NULL; - -int string_init(void) +#if 0 +static int _mem_init(void) { - mem = dm_pool_create("string test", 1024); + struct dm_pool *mem = dm_pool_create("string test", 1024); + if (!mem) { + fprintf(stderr, "out of memory\n"); + exit(1); + } - return (mem == NULL); + return mem; } -int string_fini(void) +static void _mem_exit(void *mem) { dm_pool_destroy(mem); - - return 0; } /* TODO: Add more string unit tests here */ +#endif -static void test_strncpy(void) +static void test_strncpy(void *fixture) { const char st[] = "1234567890"; char buf[sizeof(st)]; - CU_ASSERT_EQUAL(dm_strncpy(buf, st, sizeof(buf)), 1); - CU_ASSERT_EQUAL(strcmp(buf, st), 0); + T_ASSERT_EQUAL(dm_strncpy(buf, st, sizeof(buf)), 1); + T_ASSERT_EQUAL(strcmp(buf, st), 0); - CU_ASSERT_EQUAL(dm_strncpy(buf, st, sizeof(buf) - 1), 0); - CU_ASSERT_EQUAL(strlen(buf) + 1, sizeof(buf) - 1); + T_ASSERT_EQUAL(dm_strncpy(buf, st, sizeof(buf) - 1), 0); + T_ASSERT_EQUAL(strlen(buf) + 1, sizeof(buf) - 1); } -static void test_asprint(void) +static void test_asprint(void *fixture) { const char st0[] = ""; const char st1[] = "12345678901"; @@ -61,23 +59,33 @@ static void test_asprint(void) int a; a = dm_asprintf(&buf, "%s", st0); - CU_ASSERT_EQUAL(strcmp(buf, st0), 0); - CU_ASSERT_EQUAL(a, sizeof(st0)); + T_ASSERT_EQUAL(strcmp(buf, st0), 0); + T_ASSERT_EQUAL(a, sizeof(st0)); free(buf); a = dm_asprintf(&buf, "%s", st1); - CU_ASSERT_EQUAL(strcmp(buf, st1), 0); - CU_ASSERT_EQUAL(a, sizeof(st1)); + T_ASSERT_EQUAL(strcmp(buf, st1), 0); + T_ASSERT_EQUAL(a, sizeof(st1)); free(buf); a = dm_asprintf(&buf, "%s", st2); - CU_ASSERT_EQUAL(a, sizeof(st2)); - CU_ASSERT_EQUAL(strcmp(buf, st2), 0); + T_ASSERT_EQUAL(a, sizeof(st2)); + T_ASSERT_EQUAL(strcmp(buf, st2), 0); free(buf); } -CU_TestInfo string_list[] = { - { (char*)"asprint", test_asprint }, - { (char*)"strncpy", test_strncpy }, - CU_TEST_INFO_NULL -}; +#define T(path, desc, fn) register_test(ts, "/base/data-struct/string/" path, desc, fn) + +void string_tests(struct dm_list *all_tests) +{ + struct test_suite *ts = test_suite_create(NULL, NULL); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + T("asprint", "tests asprint", test_asprint); + T("strncpy", "tests string copying", test_strncpy); + + dm_list_add(all_tests, &ts->list); +} diff --git a/test/unit/unit-test.sh b/test/unit/unit-test.sh new file mode 100644 index 0000000..f545f14 --- /dev/null +++ b/test/unit/unit-test.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +SKIP_WITH_LVMLOCKD=1 +SKIP_WITH_LVMPOLLD=1 + +SKIP_ROOT_DM_CHECK=1 + +. lib/inittest + +aux unittest run diff --git a/test/unit/units.h b/test/unit/units.h new file mode 100644 index 0000000..d7ac6ad --- /dev/null +++ b/test/unit/units.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TEST_UNIT_UNITS_H +#define TEST_UNIT_UNITS_H + +#include "framework.h" + +//----------------------------------------------------------------- + +// Declare the function that adds tests suites here ... +void bcache_tests(struct dm_list *suites); +void bcache_utils_tests(struct dm_list *suites); +void bitset_tests(struct dm_list *suites); +void config_tests(struct dm_list *suites); +void dm_list_tests(struct dm_list *suites); +void dm_status_tests(struct dm_list *suites); +void io_engine_tests(struct dm_list *suites); +void percent_tests(struct dm_list *suites); +void radix_tree_tests(struct dm_list *suites); +void regex_tests(struct dm_list *suites); +void string_tests(struct dm_list *suites); +void vdo_tests(struct dm_list *suites); + +// ... and call it in here. +static inline void register_all_tests(struct dm_list *suites) +{ + bcache_tests(suites); + bcache_utils_tests(suites); + bitset_tests(suites); + config_tests(suites); + dm_list_tests(suites); + dm_status_tests(suites); + io_engine_tests(suites); + percent_tests(suites); + radix_tree_tests(suites); + regex_tests(suites); + string_tests(suites); + vdo_tests(suites); +} + +//----------------------------------------------------------------- + +#endif diff --git a/test/unit/vdo_t.c b/test/unit/vdo_t.c new file mode 100644 index 0000000..27ad26b --- /dev/null +++ b/test/unit/vdo_t.c @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "units.h" +#include "device_mapper/vdo/target.h" + +//---------------------------------------------------------------- + +static bool _status_eq(struct dm_vdo_status *lhs, struct dm_vdo_status *rhs) +{ + return !strcmp(lhs->device, rhs->device) && + (lhs->operating_mode == rhs->operating_mode) && + (lhs->recovering == rhs->recovering) && + (lhs->index_state == rhs->index_state) && + (lhs->compression_state == rhs->compression_state) && + (lhs->used_blocks == rhs->used_blocks) && + (lhs->total_blocks == rhs->total_blocks); +} + +#if 0 +static const char *_op_mode(enum dm_vdo_operating_mode m) +{ + switch (m) { + case DM_VDO_MODE_RECOVERING: + return "recovering"; + case DM_VDO_MODE_READ_ONLY: + return "read-only"; + case DM_VDO_MODE_NORMAL: + return "normal"; + } + + return ""; +} + +static const char *_index_state(enum dm_vdo_index_state is) +{ + switch (is) { + case DM_VDO_INDEX_ERROR: + return "error"; + case DM_VDO_INDEX_CLOSED: + return "closed"; + case DM_VDO_INDEX_OPENING: + return "opening"; + case DM_VDO_INDEX_CLOSING: + return "closing"; + case DM_VDO_INDEX_OFFLINE: + return "offline"; + case DM_VDO_INDEX_ONLINE: + return "online"; + case DM_VDO_INDEX_UNKNOWN: + return "unknown"; + } + + return ""; +} + +static void _print_status(FILE *stream, struct dm_vdo_status *s) +{ + fprintf(stream, "device); + fprintf(stream, "%s ", _op_mode(s->operating_mode)); + fprintf(stream, "%s ", s->recovering ? "recovering" : "-"); + fprintf(stream, "%s ", _index_state(s->index_state)); + fprintf(stream, "%s ", s->compression_state == DM_VDO_COMPRESSION_ONLINE ? "online" : "offline"); + fprintf(stream, "%llu ", (unsigned long long) s->used_blocks); + fprintf(stream, "%llu", (unsigned long long) s->total_blocks); + fprintf(stream, ">"); +} +#endif + +struct example_good { + const char *input; + struct dm_vdo_status status; +}; + +static void _check_good(struct example_good *es, unsigned count) +{ + unsigned i; + + for (i = 0; i < count; i++) { + struct example_good *e = es + i; + struct dm_vdo_status_parse_result pr; + + T_ASSERT(dm_vdo_status_parse(NULL, e->input, &pr)); +#if 0 + _print_status(stderr, pr.status); + fprintf(stderr, "\n"); + _print_status(stderr, &e->status); + fprintf(stderr, "\n"); +#endif + T_ASSERT(_status_eq(&e->status, pr.status)); + free(pr.status); + } +} + +struct example_bad { + const char *input; + const char *reason; +}; + +static void _check_bad(struct example_bad *es, unsigned count) +{ + unsigned i; + + for (i = 0; i < count; i++) { + struct example_bad *e = es + i; + struct dm_vdo_status_parse_result pr; + + T_ASSERT(!dm_vdo_status_parse(NULL, e->input, &pr)); + T_ASSERT(!strcmp(e->reason, pr.error)); + } +} + +static void _test_device_names_good(void *fixture) +{ + static struct example_good _es[] = { + {"foo1234 read-only - error online 0 1234", + {(char *) "foo1234", DM_VDO_MODE_READ_ONLY, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"f read-only - error online 0 1234", + {(char *) "f", DM_VDO_MODE_READ_ONLY, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + }; + + _check_good(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_operating_mode_good(void *fixture) +{ + static struct example_good _es[] = { + {"device-name recovering - error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name read-only - error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_READ_ONLY, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name normal - error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_NORMAL, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + }; + + _check_good(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_operating_mode_bad(void *fixture) +{ + static struct example_bad _es[] = { + {"device-name investigating - error online 0 1234", + "couldn't parse 'operating mode'"}}; + + _check_bad(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_recovering_good(void *fixture) +{ + static struct example_good _es[] = { + {"device-name recovering - error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name read-only recovering error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_READ_ONLY, true, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + }; + + _check_good(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_recovering_bad(void *fixture) +{ + static struct example_bad _es[] = { + {"device-name normal fish error online 0 1234", + "couldn't parse 'recovering'"}}; + + _check_bad(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_index_state_good(void *fixture) +{ + static struct example_good _es[] = { + {"device-name recovering - error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name recovering - closed online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_CLOSED, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name recovering - opening online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_OPENING, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name recovering - closing online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_CLOSING, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name recovering - offline online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_OFFLINE, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name recovering - online online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ONLINE, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name recovering - unknown online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_UNKNOWN, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + }; + + _check_good(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_index_state_bad(void *fixture) +{ + static struct example_bad _es[] = { + {"device-name normal - fish online 0 1234", + "couldn't parse 'index state'"}}; + + _check_bad(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_compression_state_good(void *fixture) +{ + static struct example_good _es[] = { + {"device-name recovering - error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name read-only - error offline 0 1234", + {(char *) "device-name", DM_VDO_MODE_READ_ONLY, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_OFFLINE, 0, 1234}}, + }; + + _check_good(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_compression_state_bad(void *fixture) +{ + static struct example_bad _es[] = { + {"device-name normal - error fish 0 1234", + "couldn't parse 'compression state'"}}; + + _check_bad(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_used_blocks_good(void *fixture) +{ + static struct example_good _es[] = { + {"device-name recovering - error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name read-only - error offline 1 1234", + {(char *) "device-name", DM_VDO_MODE_READ_ONLY, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_OFFLINE, 1, 1234}}, + {"device-name read-only - error offline 12 1234", + {(char *) "device-name", DM_VDO_MODE_READ_ONLY, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_OFFLINE, 12, 1234}}, + {"device-name read-only - error offline 3456 1234", + {(char *) "device-name", DM_VDO_MODE_READ_ONLY, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_OFFLINE, 3456, 1234}}, + }; + + _check_good(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_used_blocks_bad(void *fixture) +{ + static struct example_bad _es[] = { + {"device-name normal - error online fish 1234", + "couldn't parse 'used blocks'"}}; + + _check_bad(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_total_blocks_good(void *fixture) +{ + static struct example_good _es[] = { + {"device-name recovering - error online 0 1234", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1234}}, + {"device-name recovering - error online 0 1", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 1}}, + {"device-name recovering - error online 0 0", + {(char *) "device-name", DM_VDO_MODE_RECOVERING, false, DM_VDO_INDEX_ERROR, DM_VDO_COMPRESSION_ONLINE, 0, 0}}, + }; + + _check_good(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_total_blocks_bad(void *fixture) +{ + static struct example_bad _es[] = { + {"device-name normal - error online 0 fish", + "couldn't parse 'total blocks'"}}; + + _check_bad(_es, DM_ARRAY_SIZE(_es)); +} + +static void _test_status_bad(void *fixture) +{ + struct example_bad _bad[] = { + {"", "couldn't get token for device"}, + {"device-name read-only - error online 0 1000 lksd", "too many tokens"} + }; + + _check_bad(_bad, DM_ARRAY_SIZE(_bad)); +} + +//---------------------------------------------------------------- + +#define T(path, desc, fn) register_test(ts, "/device-mapper/vdo/status/" path, desc, fn) + +static struct test_suite *_tests(void) +{ + struct test_suite *ts = test_suite_create(NULL, NULL); + if (!ts) { + fprintf(stderr, "out of memory\n"); + exit(1); + }; + + T("device-names", "parse various device names", _test_device_names_good); + T("operating-mode-good", "operating mode, good examples", _test_operating_mode_good); + T("operating-mode-bad", "operating mode, bad examples", _test_operating_mode_bad); + T("recovering-good", "recovering, good examples", _test_recovering_good); + T("recovering-bad", "recovering, bad examples", _test_recovering_bad); + T("index-state-good", "index state, good examples", _test_index_state_good); + T("index-state-bad", "index state, bad examples", _test_index_state_bad); + T("compression-state-good", "compression state, good examples", _test_compression_state_good); + T("compression-state-bad", "compression state, bad examples", _test_compression_state_bad); + T("used-blocks-good", "used blocks, good examples", _test_used_blocks_good); + T("used-blocks-bad", "used blocks, bad examples", _test_used_blocks_bad); + T("total-blocks-good", "total blocks, good examples", _test_total_blocks_good); + T("total-blocks-bad", "total blocks, bad examples", _test_total_blocks_bad); + T("bad", "parse various badly formed vdo status lines", _test_status_bad); + + return ts; +} + +void vdo_tests(struct dm_list *all_tests) +{ + dm_list_add(all_tests, &_tests()->list); +} + +//---------------------------------------------------------------- -- cgit v1.2.3