From 80cdbd35ad51f1f6601640d66bb2641a7dbece73 Mon Sep 17 00:00:00 2001 From: Peter Rajnoha Date: Nov 14 2013 07:39:09 +0000 Subject: New upstream release (v2.02.104). --- diff --git a/.gitignore b/.gitignore index 003837c..4493cc4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ /LVM2.2.02.99.tgz /LVM2.2.02.102.tgz /LVM2.2.02.103.tgz +/LVM2.2.02.104.tgz diff --git a/LVM2.2.02.103.tgz.asc b/LVM2.2.02.103.tgz.asc deleted file mode 100644 index e683773..0000000 --- a/LVM2.2.02.103.tgz.asc +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.11 (GNU/Linux) - -iEYEABECAAYFAlJOxOEACgkQIoGRwVZ+LBdzIgCgyYCGSy7BHxalqU5knEnK0gkZ -Ku4AoN1ojAchwqP/1Mu1Hacq5RXGlf4R -=4ZOd ------END PGP SIGNATURE----- diff --git a/LVM2.2.02.104.tgz.asc b/LVM2.2.02.104.tgz.asc new file mode 100644 index 0000000..e214e87 --- /dev/null +++ b/LVM2.2.02.104.tgz.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.11 (GNU/Linux) + +iEYEABECAAYFAlKDiQ4ACgkQIoGRwVZ+LBc0PwCg4iyLn/+zxXfpT3UK028JZTRd +EDoAoKQ7+P+1qcSqlhEs7/5c5GywwqL7 +=V0Vj +-----END PGP SIGNATURE----- diff --git a/lvm2-2_02_104-additional-fixes-from-v104.patch b/lvm2-2_02_104-additional-fixes-from-v104.patch deleted file mode 100644 index 47c7194..0000000 --- a/lvm2-2_02_104-additional-fixes-from-v104.patch +++ /dev/null @@ -1,2212 +0,0 @@ -commit 11388698bad4336c156b11f8e1f51b664b34f57c -Author: Peter Rajnoha -Date: Fri Oct 25 08:22:33 2013 +0200 - - Additional fixes from upcoming v104. ---- - WHATS_NEW | 29 ++++++ - WHATS_NEW_DM | 6 ++ - configure | 26 +++++- - configure.in | 17 +++- - daemons/clvmd/clvmd.c | 2 +- - daemons/clvmd/lvm-functions.c | 2 +- - daemons/lvmetad/lvmetad-core.c | 25 +++-- - lib/activate/activate.c | 90 ++++++++++++------ - lib/activate/activate.h | 19 +++- - lib/activate/dev_manager.c | 19 +++- - lib/cache/lvmetad.c | 2 - - lib/device/device-types.h | 1 + - lib/format_text/flags.c | 6 +- - lib/locking/file_locking.c | 6 +- - lib/locking/no_locking.c | 6 +- - lib/metadata/lv.c | 8 +- - lib/metadata/lv_manip.c | 17 +++- - lib/metadata/metadata-exported.h | 7 ++ - lib/metadata/metadata.c | 76 ++++++++++------ - lib/metadata/metadata.h | 3 - - lib/metadata/snapshot_manip.c | 10 ++ - lib/metadata/thin_manip.c | 1 + - lib/snapshot/snapshot.c | 59 ++++++------ - libdaemon/client/daemon-io.c | 2 +- - libdaemon/server/daemon-server.c | 6 +- - libdm/Makefile.in | 2 +- - libdm/libdevmapper.h | 2 +- - libdm/libdm-common.c | 13 ++- - libdm/mm/pool-fast.c | 4 + - libdm/mm/pool.c | 9 +- - man/pvscan.8.in | 4 +- - scripts/Makefile.in | 2 + - scripts/blkdeactivate.sh.in | 5 +- - scripts/lvm2_pvscan_systemd_red_hat@.service.in | 14 +++ - scripts/vgimportclone.sh | 8 +- - test/Makefile.in | 12 ++- - test/lib/aux.sh | 2 +- - test/lib/get.sh | 2 +- - test/lib/harness.c | 30 +++--- - test/shell/lvconvert-repair-raid.sh | 2 +- - test/shell/lvconvert-repair-thin.sh | 116 ++++++++++++++++++++++++ - test/shell/lvconvert-thin-external.sh | 8 ++ - test/shell/lvcreate-usage.sh | 18 ++-- - test/shell/lvmcache-exercise.sh | 17 +++- - test/shell/snapshot-usage.sh | 37 +++++++- - test/shell/vgrename-usage.sh | 15 +++ - tools/dmsetup.c | 2 +- - tools/lvchange.c | 3 +- - tools/lvconvert.c | 23 ++++- - tools/lvremove.c | 8 -- - tools/pvscan.c | 61 ++++++++++--- - tools/vgrename.c | 2 + - udev/11-dm-lvm.rules.in | 15 +++ - udev/13-dm-disk.rules.in | 3 +- - udev/69-dm-lvm-metad.rules.in | 4 +- - udev/Makefile.in | 8 +- - 56 files changed, 697 insertions(+), 199 deletions(-) - -diff --git a/WHATS_NEW b/WHATS_NEW -index d69e74e..49f37a4 100644 ---- a/WHATS_NEW -+++ b/WHATS_NEW -@@ -1,3 +1,32 @@ -+Version 2.02.104 -+=================================== -+ Add internal flag for temporary LVs to properly direct udev to not interfere. -+ Fix endless loop in blkdeactivate ... if unable to umount/deactivate. -+ Add dev-block-:.device systemd alias for complete PV tracking. -+ Use major:minor as short form of --major and --minor arg for pvscan --cache. -+ Remove 2>/dev/null from three lvm commands executed by vgimportclone. -+ Add configure --enable-udev-systemd-background-jobs. -+ Add lvm2-pvscan@.service to run pvscan as a service for lvmetad/autoactivation. -+ Fix lvconvert swap of poolmetadata volume for active thin pool. -+ Check for open count with a timeout before removal/deactivation of an LV. -+ Report RAID images split with tracking as out-of-sync ("I"). -+ Improve parsing of snapshot lv segment. -+ Add workaround for deactivation problem of opened virtual snapshot. -+ Disable unsupported merge for virtual snapshot. -+ Move code to remove virtual snapshot from tools to lib for lvm2app. -+ Fix possible race during daemon worker thread creation (lvmetad). -+ Fix possible deadlock while clearing lvmetad cache for full rescan. -+ Fix possible race while creating/destroying memory pools. -+ Recognise NVM Express devices in filter. -+ Fix failing metadata repair when lvmetad is used. -+ Fix incorrect memory handling when reading messages from lvmetad. -+ Fix locking in lvmetad when handling the PV which is gone. -+ Recognize new flag to skip udev scanning in udev rules and act appropriately. -+ Add support for flagging an LV to skip udev scanning during activation. -+ Improve message when unable to change discards setting on active thin pool. -+ Run full scan before vgrename operation to avoid any cache name collision. -+ Fix lvconvert when converting to a thin pool and thin LV at once. -+ - Version 2.02.103 - 4th October 2013 - =================================== - Ensure vgid matches before removing vgname entry from lvmetad cache. -diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM -index 9dfd9bf..6742ad4 100644 ---- a/WHATS_NEW_DM -+++ b/WHATS_NEW_DM -@@ -1,3 +1,9 @@ -+Version 1.02.83 -+================================== -+ Skip race errors when non-udev dmsetup build runs on udev-enabled system. -+ Skip error message when holders are not present in sysfs. -+ Use __linux__ instead of linux define to make libdevmapper.h C compliant. -+ - Version 1.02.82 - 4th October 2013 - ================================== - Define symbolic names for subsystem udev flags in libdevmapper for easier use. -diff --git a/configure b/configure -index 20a706a..002a7d2 100755 ---- a/configure -+++ b/configure -@@ -613,6 +613,7 @@ DMEVENTD_PIDFILE - WRITE_INSTALL - UDEV_HAS_BUILTIN_BLKID - UDEV_RULE_EXEC_DETECTION -+UDEV_SYSTEMD_BACKGROUND_JOBS - UDEV_SYNC - UDEV_RULES - UDEV_PC -@@ -849,6 +850,7 @@ enable_valgrind_pool - enable_devmapper - enable_lvmetad - with_lvmetad_pidfile -+enable_udev_systemd_background_jobs - enable_udev_sync - enable_udev_rules - enable_udev_rule_exec_detection -@@ -1552,6 +1554,9 @@ Optional Features: - --enable-valgrind-pool enable valgrind awareness of pools - --disable-devmapper disable LVM2 device-mapper interaction - --enable-lvmetad enable the LVM Metadata Daemon -+ --enable-udev-systemd-background-jobs -+ enable udev-systemd protocol to instantiate a -+ service for background job - --enable-udev_sync enable synchronisation with udev processing - --enable-udev_rules install rule files needed for udev synchronisation - --enable-udev-rule-exec-detection -@@ -9090,6 +9095,19 @@ _ACEOF - fi - - ################################################################################ -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use udev-systemd protocol for jobs in background" >&5 -+$as_echo_n "checking whether to use udev-systemd protocol for jobs in background... " >&6; } -+# Check whether --enable-udev-systemd-background-jobs was given. -+if test "${enable_udev_systemd_background_jobs+set}" = set; then : -+ enableval=$enable_udev_systemd_background_jobs; UDEV_SYSTEMD_BACKGROUND_JOBS=$enableval -+else -+ UDEV_SYSTEMD_BACKGROUND_JOBS=no -+fi -+ -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $UDEV_SYSTEMD_BACKGROUND_JOBS" >&5 -+$as_echo "$UDEV_SYSTEMD_BACKGROUND_JOBS" >&6; } -+ -+################################################################################ - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable synchronisation with udev processing" >&5 - $as_echo_n "checking whether to enable synchronisation with udev processing... " >&6; } - # Check whether --enable-udev_sync was given. -@@ -9668,8 +9686,7 @@ if [ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \ - fi - - ################################################################################ --if [ "$DMEVENTD" = yes -o "$CLVMD" != none ] ; then -- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_lock in -lpthread" >&5 -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_lock in -lpthread" >&5 - $as_echo_n "checking for pthread_mutex_lock in -lpthread... " >&6; } - if test "${ac_cv_lib_pthread_pthread_mutex_lock+set}" = set; then : - $as_echo_n "(cached) " >&6 -@@ -9711,7 +9728,6 @@ else - hard_bailout - fi - --fi - - ################################################################################ - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable selinux support" >&5 -@@ -10933,8 +10949,9 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'` - - - -+ - ################################################################################ --ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmetad/Makefile conf/Makefile conf/example.conf conf/default.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.socket scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" -+ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmetad/Makefile conf/Makefile conf/example.conf conf/default.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.socket scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" - - cat >confcache <<\_ACEOF - # This file is a shell script that caches the results of configure -@@ -11671,6 +11688,7 @@ do - "scripts/lvm2_lvmetad_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_lvmetad_init_red_hat" ;; - "scripts/lvm2_lvmetad_systemd_red_hat.socket") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_lvmetad_systemd_red_hat.socket" ;; - "scripts/lvm2_lvmetad_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_lvmetad_systemd_red_hat.service" ;; -+ "scripts/lvm2_pvscan_systemd_red_hat@.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_pvscan_systemd_red_hat@.service" ;; - "scripts/lvm2_monitoring_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_monitoring_init_red_hat" ;; - "scripts/dm_event_systemd_red_hat.socket") CONFIG_FILES="$CONFIG_FILES scripts/dm_event_systemd_red_hat.socket" ;; - "scripts/dm_event_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/dm_event_systemd_red_hat.service" ;; -diff --git a/configure.in b/configure.in -index 611ab37..07b0afc 100644 ---- a/configure.in -+++ b/configure.in -@@ -940,6 +940,15 @@ if test x$BUILD_LVMETAD = xyes; then - fi - - ################################################################################ -+dnl -- Enable udev-systemd protocol to instantiate a service for background jobs -+AC_MSG_CHECKING(whether to use udev-systemd protocol for jobs in background) -+AC_ARG_ENABLE(udev-systemd-background-jobs, -+ AC_HELP_STRING([--enable-udev-systemd-background-jobs], -+ [enable udev-systemd protocol to instantiate a service for background job]), -+ UDEV_SYSTEMD_BACKGROUND_JOBS=$enableval, UDEV_SYSTEMD_BACKGROUND_JOBS=no) -+AC_MSG_RESULT($UDEV_SYSTEMD_BACKGROUND_JOBS) -+ -+################################################################################ - dnl -- Enable udev synchronisation - AC_MSG_CHECKING(whether to enable synchronisation with udev processing) - AC_ARG_ENABLE(udev_sync, -@@ -1181,10 +1190,8 @@ Features cannot be 'shared' when building statically - fi - - ################################################################################ --if [[ "$DMEVENTD" = yes -o "$CLVMD" != none ]] ; then -- AC_CHECK_LIB([pthread], [pthread_mutex_lock], -- [PTHREAD_LIBS="-lpthread"], hard_bailout) --fi -+AC_CHECK_LIB([pthread], [pthread_mutex_lock], -+ [PTHREAD_LIBS="-lpthread"], hard_bailout) - - ################################################################################ - dnl -- Disable selinux -@@ -1628,6 +1635,7 @@ AC_SUBST(UDEV_LIBS) - AC_SUBST(UDEV_PC) - AC_SUBST(UDEV_RULES) - AC_SUBST(UDEV_SYNC) -+AC_SUBST(UDEV_SYSTEMD_BACKGROUND_JOBS) - AC_SUBST(UDEV_RULE_EXEC_DETECTION) - AC_SUBST(UDEV_HAS_BUILTIN_BLKID) - AC_SUBST(CUNIT_LIBS) -@@ -1702,6 +1710,7 @@ scripts/cmirrord_init_red_hat - scripts/lvm2_lvmetad_init_red_hat - scripts/lvm2_lvmetad_systemd_red_hat.socket - scripts/lvm2_lvmetad_systemd_red_hat.service -+scripts/lvm2_pvscan_systemd_red_hat@.service - scripts/lvm2_monitoring_init_red_hat - scripts/dm_event_systemd_red_hat.socket - scripts/dm_event_systemd_red_hat.service -diff --git a/daemons/clvmd/clvmd.c b/daemons/clvmd/clvmd.c -index bed8e68..d57c0fd 100644 ---- a/daemons/clvmd/clvmd.c -+++ b/daemons/clvmd/clvmd.c -@@ -1124,7 +1124,7 @@ static int verify_message(char *buf, int len) - - /* TODO: we may be able to narrow len/flags/clientid/arglen checks based on cmd */ - -- if (h->flags & ~(CLVMD_FLAG_LOCAL | CLVMD_FLAG_SYSTEMLV | CLVMD_FLAG_NODEERRS)) { -+ if (h->flags & ~(CLVMD_FLAG_LOCAL | CLVMD_FLAG_SYSTEMLV | CLVMD_FLAG_NODEERRS | CLVMD_FLAG_REMOTE)) { - log_error("verify_message bad flags %x", h->flags); - return -1; - } -diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c -index da7d335..b15732f 100644 ---- a/daemons/clvmd/lvm-functions.c -+++ b/daemons/clvmd/lvm-functions.c -@@ -401,7 +401,7 @@ static int do_activate_lv(char *resource, unsigned char command, unsigned char l - } - - /* Now activate it */ -- if (!lv_activate(cmd, resource, exclusive, NULL)) -+ if (!lv_activate(cmd, resource, exclusive, 0, 0, NULL)) - goto error; - - return 0; -diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c -index e1ec5a8..285c8cc 100644 ---- a/daemons/lvmetad/lvmetad-core.c -+++ b/daemons/lvmetad/lvmetad-core.c -@@ -551,7 +551,7 @@ static int compare_config(struct dm_config_node *a, struct dm_config_node *b) - return result; - } - --static int vg_remove_if_missing(lvmetad_state *s, const char *vgid); -+static int vg_remove_if_missing(lvmetad_state *s, const char *vgid, int update_pvids); - - /* You need to be holding the pvid_to_vgid lock already to call this. */ - static int update_pvid_to_vgid(lvmetad_state *s, struct dm_config_tree *vg, -@@ -590,7 +590,7 @@ static int update_pvid_to_vgid(lvmetad_state *s, struct dm_config_tree *vg, - n = dm_hash_get_next(to_check, n)) { - check_vgid = dm_hash_get_key(to_check, n); - lock_vg(s, check_vgid); -- vg_remove_if_missing(s, check_vgid); -+ vg_remove_if_missing(s, check_vgid, 0); - unlock_vg(s, check_vgid); - } - -@@ -631,7 +631,7 @@ static int remove_metadata(lvmetad_state *s, const char *vgid, int update_pvids) - } - - /* The VG must be locked. */ --static int vg_remove_if_missing(lvmetad_state *s, const char *vgid) -+static int vg_remove_if_missing(lvmetad_state *s, const char *vgid, int update_pvids) - { - struct dm_config_tree *vg; - struct dm_config_node *pv; -@@ -658,7 +658,7 @@ static int vg_remove_if_missing(lvmetad_state *s, const char *vgid) - - if (missing) { - DEBUGLOG(s, "removing empty VG %s", vgid); -- remove_metadata(s, vgid, 0); -+ remove_metadata(s, vgid, update_pvids); - } - - unlock_pvid_to_pvmeta(s); -@@ -796,11 +796,24 @@ static response pv_gone(lvmetad_state *s, request r) - - pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvid); - pvid_old = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device)); -+ char *vgid = dm_hash_lookup(s->pvid_to_vgid, pvid); -+ -+ if (vgid && !(vgid = dm_strdup(vgid))) { -+ unlock_pvid_to_pvmeta(s); -+ return reply_fail("out of memory"); -+ } -+ - dm_hash_remove_binary(s->device_to_pvid, &device, sizeof(device)); - dm_hash_remove(s->pvid_to_pvmeta, pvid); -- vg_remove_if_missing(s, dm_hash_lookup(s->pvid_to_vgid, pvid)); - unlock_pvid_to_pvmeta(s); - -+ if (vgid) { -+ lock_vg(s, vgid); -+ vg_remove_if_missing(s, vgid, 1); -+ unlock_vg(s, vgid); -+ dm_free(vgid); -+ } -+ - if (pvid_old) - dm_free(pvid_old); - -@@ -816,8 +829,8 @@ static response pv_clear_all(lvmetad_state *s, request r) - DEBUGLOG(s, "pv_clear_all"); - - lock_pvid_to_pvmeta(s); -- lock_vgid_to_metadata(s); - lock_pvid_to_vgid(s); -+ lock_vgid_to_metadata(s); - - destroy_metadata_hashes(s); - create_metadata_hashes(s); -diff --git a/lib/activate/activate.c b/lib/activate/activate.c -index 28549fc..006681e 100644 ---- a/lib/activate/activate.c -+++ b/lib/activate/activate.c -@@ -251,8 +251,8 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer, - { - return 0; - } --int lv_check_not_in_use(struct cmd_context *cmd __attribute__((unused)), -- struct logical_volume *lv, struct lvinfo *info) -+int lv_check_not_in_use(struct cmd_context *cmd, struct logical_volume *lv, -+ struct lvinfo *info) - { - return 0; - } -@@ -337,12 +337,13 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s, - { - return 1; - } --int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, struct logical_volume *lv) -+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, int noscan, -+ int temporary, struct logical_volume *lv) - { - return 1; - } - int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive, -- struct logical_volume *lv) -+ int noscan, int temporary, struct logical_volume *lv) - { - return 1; - } -@@ -675,33 +676,48 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer, - return r; - } - --int lv_check_not_in_use(struct cmd_context *cmd __attribute__((unused)), -- struct logical_volume *lv, struct lvinfo *info) -+#define OPEN_COUNT_CHECK_RETRIES 25 -+#define OPEN_COUNT_CHECK_USLEEP_DELAY 200000 -+ -+int lv_check_not_in_use(struct cmd_context *cmd, struct logical_volume *lv, -+ struct lvinfo *info) - { -+ unsigned int open_count_check_retries; -+ - if (!info->exists) - return 1; - - /* If sysfs is not used, use open_count information only. */ -- if (!*dm_sysfs_dir()) { -- if (info->open_count) { -- log_error("Logical volume %s/%s in use.", -+ if (dm_sysfs_dir()) { -+ if (dm_device_has_holders(info->major, info->minor)) { -+ log_error("Logical volume %s/%s is used by another device.", - lv->vg->name, lv->name); - return 0; - } - -- return 1; -- } -- -- if (dm_device_has_holders(info->major, info->minor)) { -- log_error("Logical volume %s/%s is used by another device.", -- lv->vg->name, lv->name); -- return 0; -+ if (dm_device_has_mounted_fs(info->major, info->minor)) { -+ log_error("Logical volume %s/%s contains a filesystem in use.", -+ lv->vg->name, lv->name); -+ return 0; -+ } - } - -- if (dm_device_has_mounted_fs(info->major, info->minor)) { -- log_error("Logical volume %s/%s contains a filesystem in use.", -- lv->vg->name, lv->name); -- return 0; -+ open_count_check_retries = retry_deactivation() ? OPEN_COUNT_CHECK_RETRIES : 1; -+ while (open_count_check_retries--) { -+ if (info->open_count > 0) { -+ if (open_count_check_retries) { -+ usleep(OPEN_COUNT_CHECK_USLEEP_DELAY); -+ log_debug_activation("Retrying open_count check for %s/%s.", -+ lv->vg->name, lv->name); -+ if (!lv_info(cmd, lv, 0, info, 1, 0)) -+ return -1; -+ continue; -+ } -+ log_error("Logical volume %s/%s in use.", -+ lv->vg->name, lv->name); -+ return 0; -+ } else -+ break; - } - - return 1; -@@ -887,6 +903,18 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg) - struct dm_status_raid *status; - - if (!seg_is_raid(first_seg(lv))) { -+ /* -+ * Make it easier for user to know what to do when -+ * they are using thinpool. -+ */ -+ if (lv_is_thin_pool(lv) && -+ (lv_is_raid(seg_lv(first_seg(lv), 0)) || -+ lv_is_raid(first_seg(lv)->metadata_lv))) { -+ log_error("Thinpool data or metadata volume" -+ " must be specified. (e.g. \"%s/%s_tdata\")", -+ lv->vg->name, lv->name); -+ return 0; -+ } - log_error("%s/%s must be a RAID logical volume to" - " perform this action.", lv->vg->name, lv->name); - return 0; -@@ -1928,7 +1956,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, struct logical_vo - goto out; - } - -- if (lv_is_visible(lv)) { -+ if (lv_is_visible(lv) || lv_is_virtual_origin(lv)) { - if (!lv_check_not_in_use(cmd, lv, &info)) - goto_out; - -@@ -2027,9 +2055,11 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, - if (filter) - laopts->read_only = _passes_readonly_filter(cmd, lv); - -- log_debug_activation("Activating %s/%s%s%s.", lv->vg->name, lv->name, -+ log_debug_activation("Activating %s/%s%s%s%s%s.", lv->vg->name, lv->name, - laopts->exclusive ? " exclusively" : "", -- laopts->read_only ? " read-only" : ""); -+ laopts->read_only ? " read-only" : "", -+ laopts->noscan ? " noscan" : "", -+ laopts->temporary ? " temporary" : ""); - - if (!lv_info(cmd, lv, 0, &info, 0, 0)) - goto_out; -@@ -2066,9 +2096,12 @@ out: - } - - /* Activate LV */ --int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, struct logical_volume *lv) -+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, -+ int noscan, int temporary, struct logical_volume *lv) - { -- struct lv_activate_opts laopts = { .exclusive = exclusive }; -+ struct lv_activate_opts laopts = { .exclusive = exclusive, -+ .noscan = noscan, -+ .temporary = temporary }; - - if (!_lv_activate(cmd, lvid_s, &laopts, 0, lv)) - return_0; -@@ -2077,9 +2110,12 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, stru - } - - /* Activate LV only if it passes filter */ --int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive, struct logical_volume *lv) -+int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive, -+ int noscan, int temporary, struct logical_volume *lv) - { -- struct lv_activate_opts laopts = { .exclusive = exclusive }; -+ struct lv_activate_opts laopts = { .exclusive = exclusive, -+ .noscan = noscan, -+ .temporary = temporary }; - - if (!_lv_activate(cmd, lvid_s, &laopts, 1, lv)) - return_0; -diff --git a/lib/activate/activate.h b/lib/activate/activate.h -index f34d376..df888cd 100644 ---- a/lib/activate/activate.h -+++ b/lib/activate/activate.h -@@ -38,6 +38,18 @@ struct lv_activate_opts { - int skip_in_use; - unsigned revert; - unsigned read_only; -+ unsigned noscan; /* Mark this LV to avoid its scanning. This also -+ directs udev to use proper udev flag to avoid -+ any scanning in udev. This udev flag is automatically -+ dropped in udev db on any spurious event that follows. */ -+ unsigned temporary; /* Mark this LV as temporary. It means, the LV -+ * is created, used and deactivated within single -+ * LVM command execution. Such LVs are mostly helper -+ * LVs to do some action or cleanup before the proper -+ * LV is created. This also directs udev to use proper -+ * set of flags to avoid any scanning in udev. These udev -+ * flags are persistent in udev db for any spurious event -+ * that follows. */ - }; - - /* target attribute flags */ -@@ -80,9 +92,10 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned o - int lv_resume(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only, struct logical_volume *lv); - int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s, - unsigned origin_only, unsigned exclusive, unsigned revert, struct logical_volume *lv); --int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, struct logical_volume *lv); --int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, -- int exclusive, struct logical_volume *lv); -+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, -+ int noscan, int temporary, struct logical_volume *lv); -+int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive, -+ int noscan, int temporary, struct logical_volume *lv); - int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, struct logical_volume *lv); - - int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv); -diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c -index b8233bf..0b911f2 100644 ---- a/lib/activate/dev_manager.c -+++ b/lib/activate/dev_manager.c -@@ -30,6 +30,7 @@ - #include - - #define MAX_TARGET_PARAMSIZE 50000 -+#define LVM_UDEV_NOSCAN_FLAG DM_SUBSYSTEM_UDEV_FLAG0 - - typedef enum { - PRELOAD, -@@ -1399,7 +1400,7 @@ static int _check_udev_fallback(struct cmd_context *cmd) - #endif /* UDEV_SYNC_SUPPORT */ - - static uint16_t _get_udev_flags(struct dev_manager *dm, struct logical_volume *lv, -- const char *layer) -+ const char *layer, int noscan, int temporary) - { - uint16_t udev_flags = 0; - -@@ -1447,6 +1448,16 @@ static uint16_t _get_udev_flags(struct dev_manager *dm, struct logical_volume *l - udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG | - DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG; - -+ /* -+ * LVM subsystem specific flags. -+ */ -+ if (noscan) -+ udev_flags |= DM_SUBSYSTEM_UDEV_FLAG0; -+ -+ if (temporary) -+ udev_flags |= DM_UDEV_DISABLE_DISK_RULES_FLAG | -+ DM_UDEV_DISABLE_OTHER_RULES_FLAG; -+ - return udev_flags; - } - -@@ -1493,7 +1504,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, - } - - if (info.exists && !dm_tree_add_dev_with_udev_flags(dtree, info.major, info.minor, -- _get_udev_flags(dm, lv, layer))) { -+ _get_udev_flags(dm, lv, layer, 0, 0))) { - log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree", - info.major, info.minor); - return 0; -@@ -2334,7 +2345,7 @@ static int _set_udev_flags_for_children(struct dev_manager *dm, - } - - dm_tree_node_set_udev_flags(child, -- _get_udev_flags(dm, lvl->lv, NULL)); -+ _get_udev_flags(dm, lvl->lv, NULL, 0, 0)); - } - - return 1; -@@ -2411,7 +2422,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, - read_only_lv(lv, laopts), - ((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0, - lvlayer, -- _get_udev_flags(dm, lv, layer)))) -+ _get_udev_flags(dm, lv, layer, laopts->noscan, laopts->temporary)))) - return_0; - - /* Store existing name so we can do rename later */ -diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c -index f43283f..8940704 100644 ---- a/lib/cache/lvmetad.c -+++ b/lib/cache/lvmetad.c -@@ -392,8 +392,6 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna - pvl->pv->dev = lvmcache_device(info); - if (!pvl->pv->dev) - pvl->pv->status |= MISSING_PV; -- else -- check_reappeared_pv(vg, pvl->pv); - if (!lvmcache_fid_add_mdas_pv(info, fid)) { - vg = NULL; - goto_out; /* FIXME error path */ -diff --git a/lib/device/device-types.h b/lib/device/device-types.h -index d25c2f0..d716878 100644 ---- a/lib/device/device-types.h -+++ b/lib/device/device-types.h -@@ -61,5 +61,6 @@ static const dev_known_type_t _dev_known_types[] = { - {"skd", 16, "STEC"}, - {"scm", 8, "Storage Class Memory (IBM S/390)"}, - {"bcache", 1, "bcache block device cache"}, -+ {"nvme", 64, "NVM Express"}, - {"", 0, ""} - }; -diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c -index 5077576..e31429e 100644 ---- a/lib/format_text/flags.c -+++ b/lib/format_text/flags.c -@@ -61,6 +61,8 @@ static const struct flag _lv_flags[] = { - {LV_REBUILD, "REBUILD", STATUS_FLAG}, - {LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG}, - {LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG}, -+ {LV_NOSCAN, NULL, 0}, -+ {LV_TEMPORARY, NULL, 0}, - {POOL_METADATA_SPARE, NULL, 0}, - {RAID, NULL, 0}, - {RAID_META, NULL, 0}, -@@ -144,8 +146,8 @@ int print_flags(uint64_t status, int type, char *buffer, size_t size) - return 0; - - if (status) -- log_warn("Metadata inconsistency: Not all flags successfully " -- "exported."); -+ log_warn(INTERNAL_ERROR "Metadata inconsistency: " -+ "Not all flags successfully exported."); - - return 1; - } -diff --git a/lib/locking/file_locking.c b/lib/locking/file_locking.c -index 5e49bc4..ab3dabd 100644 ---- a/lib/locking/file_locking.c -+++ b/lib/locking/file_locking.c -@@ -305,7 +305,8 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource, - break; - case LCK_READ: - log_very_verbose("Locking LV %s (R)", resource); -- if (!lv_activate_with_filter(cmd, resource, 0, lv_ondisk(lv))) -+ if (!lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0, -+ lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv))) - return 0; - break; - case LCK_PREAD: -@@ -318,7 +319,8 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource, - break; - case LCK_EXCL: - log_very_verbose("Locking LV %s (EX)", resource); -- if (!lv_activate_with_filter(cmd, resource, 1, lv_ondisk(lv))) -+ if (!lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0, -+ lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv))) - return 0; - break; - default: -diff --git a/lib/locking/no_locking.c b/lib/locking/no_locking.c -index 5f3f0b6..dac2f80 100644 ---- a/lib/locking/no_locking.c -+++ b/lib/locking/no_locking.c -@@ -48,11 +48,13 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource, - case LCK_UNLOCK: - return lv_resume_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1: 0, 0, (flags & LCK_REVERT) ? 1 : 0, lv_ondisk(lv)); - case LCK_READ: -- return lv_activate_with_filter(cmd, resource, 0, lv_ondisk(lv)); -+ return lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0, -+ lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv)); - case LCK_WRITE: - return lv_suspend_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1 : 0, 0, lv_ondisk(lv), lv); - case LCK_EXCL: -- return lv_activate_with_filter(cmd, resource, 1, lv_ondisk(lv)); -+ return lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0, -+ lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv)); - default: - break; - } -diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c -index e3fda18..e59bd8e 100644 ---- a/lib/metadata/lv.c -+++ b/lib/metadata/lv.c -@@ -565,7 +565,13 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv) - else if (lv->status & MIRROR_IMAGE) - repstr[0] = (_lv_mimage_in_sync(lv)) ? 'i' : 'I'; - else if (lv->status & RAID_IMAGE) -- repstr[0] = (_lv_raid_image_in_sync(lv)) ? 'i' : 'I'; -+ /* -+ * Visible RAID_IMAGES are sub-LVs that have been exposed for -+ * top-level use by being split from the RAID array with -+ * '--splitmirrors 1 --trackchanges'. They always report 'I'. -+ */ -+ repstr[0] = (!lv_is_visible(lv) && _lv_raid_image_in_sync(lv)) ? -+ 'i' : 'I'; - else if (lv->status & MIRROR_LOG) - repstr[0] = 'l'; - else if (lv_is_cow(lv)) -diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c -index f42db1d..88fceb2 100644 ---- a/lib/metadata/lv_manip.c -+++ b/lib/metadata/lv_manip.c -@@ -89,7 +89,7 @@ static int _lv_is_on_pv(struct cmd_context *cmd, - struct physical_volume *pv2; - struct lv_segment *seg; - -- if (!lv || !(seg = first_seg(lv))) -+ if (!lv || !(first_seg(lv))) - return_0; - - /* -@@ -4685,6 +4685,7 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume * - struct dm_list *snh, *snht; - struct lv_list *lvl; - struct lvinfo info; -+ struct logical_volume *origin; - int is_last_pool; - - if (lv_is_cow(lv)) { -@@ -4713,7 +4714,10 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume * - return 0; - } - } -- } -+ } else if (!level && lv_is_virtual_origin(origin = origin_from_cow(lv))) -+ /* If this is a sparse device, remove its origin too. */ -+ /* Stacking is not supported */ -+ lv = origin; - } - - if (lv_is_origin(lv)) { -@@ -5421,6 +5425,8 @@ int set_lv(struct cmd_context *cmd, struct logical_volume *lv, - if (!dev_close_immediate(dev)) - stack; - -+ lv->status &= ~LV_NOSCAN; -+ - return 1; - } - -@@ -5977,6 +5983,13 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, - goto out; - } - -+ /* Do not scan this LV until properly zeroed. */ -+ if (lp->zero) -+ lv->status |= LV_NOSCAN; -+ -+ if (lp->temporary) -+ lv->status |= LV_TEMPORARY; -+ - if (lv_is_thin_pool(lv)) { - if (is_change_activating(lp->activate)) { - if (vg_is_clustered(lv->vg)) { -diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h -index 308dcfe..c00e4e5 100644 ---- a/lib/metadata/metadata-exported.h -+++ b/lib/metadata/metadata-exported.h -@@ -102,6 +102,12 @@ - #define LV_WRITEMOSTLY UINT64_C(0x0000020000000000) /* LV (RAID1) */ - - #define LV_ACTIVATION_SKIP UINT64_C(0x0000040000000000) /* LV */ -+#define LV_NOSCAN UINT64_C(0x0000080000000000) /* LV - internal use only - the LV -+ should not be scanned */ -+#define LV_TEMPORARY UINT64_C(0x0000100000000000) /* LV - internal use only - the LV -+ is supposed to be created and -+ removed during single LVM -+ command execution. */ - - /* Format features flags */ - #define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */ -@@ -720,6 +726,7 @@ struct lvcreate_params { - int log_count; /* mirror */ - int nosync; /* mirror */ - int poolmetadataspare; /* thin pool */ -+ int temporary; /* temporary LV */ - #define ACTIVATION_SKIP_SET 0x01 /* request to set LV activation skip flag state */ - #define ACTIVATION_SKIP_SET_ENABLED 0x02 /* set the LV activation skip flag state to 'enabled' */ - #define ACTIVATION_SKIP_IGNORE 0x04 /* request to ignore LV activation skip flag (if any) */ -diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c -index 4ffd502..8571e0a 100644 ---- a/lib/metadata/metadata.c -+++ b/lib/metadata/metadata.c -@@ -2883,10 +2883,11 @@ int vg_missing_pv_count(const struct volume_group *vg) - return ret; - } - --void check_reappeared_pv(struct volume_group *correct_vg, -- struct physical_volume *pv) -+static int _check_reappeared_pv(struct volume_group *correct_vg, -+ struct physical_volume *pv, int act) - { - struct pv_list *pvl; -+ int rv = 0; - - /* - * Skip these checks in case the tool is going to deal with missing -@@ -2894,21 +2895,47 @@ void check_reappeared_pv(struct volume_group *correct_vg, - * confusing. - */ - if (correct_vg->cmd->handles_missing_pvs) -- return; -+ return rv; - - dm_list_iterate_items(pvl, &correct_vg->pvs) - if (pv->dev == pvl->pv->dev && is_missing_pv(pvl->pv)) { -- log_warn("Missing device %s reappeared, updating " -- "metadata for VG %s to version %u.", -- pv_dev_name(pvl->pv), pv_vg_name(pvl->pv), -- correct_vg->seqno); -+ if (act) -+ log_warn("Missing device %s reappeared, updating " -+ "metadata for VG %s to version %u.", -+ pv_dev_name(pvl->pv), pv_vg_name(pvl->pv), -+ correct_vg->seqno); - if (pvl->pv->pe_alloc_count == 0) { -- pv->status &= ~MISSING_PV; -- pvl->pv->status &= ~MISSING_PV; -- } else -+ if (act) { -+ pv->status &= ~MISSING_PV; -+ pvl->pv->status &= ~MISSING_PV; -+ } -+ ++ rv; -+ } else if (act) - log_warn("Device still marked missing because of allocated data " - "on it, remove volumes and consider vgreduce --removemissing."); - } -+ return rv; -+} -+ -+static int _repair_inconsistent_vg(struct volume_group *vg) -+{ -+ unsigned saved_handles_missing_pvs = vg->cmd->handles_missing_pvs; -+ -+ vg->cmd->handles_missing_pvs = 1; -+ if (!vg_write(vg)) { -+ log_error("Automatic metadata correction failed"); -+ vg->cmd->handles_missing_pvs = saved_handles_missing_pvs; -+ return 0; -+ } -+ -+ vg->cmd->handles_missing_pvs = saved_handles_missing_pvs; -+ -+ if (!vg_commit(vg)) { -+ log_error("Automatic metadata correction commit failed"); -+ return 0; -+ } -+ -+ return 1; - } - - static int _check_mda_in_use(struct metadata_area *mda, void *_in_use) -@@ -2951,12 +2978,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, - int inconsistent_mdas = 0; - int inconsistent_mda_count = 0; - unsigned use_precommitted = precommitted; -- unsigned saved_handles_missing_pvs = cmd->handles_missing_pvs; - struct dm_list *pvids; - struct pv_list *pvl, *pvl2; - struct dm_list all_pvs; - char uuid[64] __attribute__((aligned(8))); - unsigned seqno = 0; -+ int reappeared = 0; - - if (is_orphan_vg(vgname)) { - if (use_precommitted) { -@@ -2969,8 +2996,16 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, - } - - if (lvmetad_active() && !use_precommitted) { -- *consistent = 1; -- return lvmcache_get_vg(cmd, vgname, vgid, precommitted); -+ if ((correct_vg = lvmcache_get_vg(cmd, vgname, vgid, precommitted))) { -+ dm_list_iterate_items(pvl, &correct_vg->pvs) -+ if (pvl->pv->dev) -+ reappeared += _check_reappeared_pv(correct_vg, pvl->pv, *consistent); -+ if (reappeared && *consistent) -+ *consistent = _repair_inconsistent_vg(correct_vg); -+ else -+ *consistent = !reappeared; -+ } -+ return correct_vg; - } - - /* -@@ -3339,22 +3374,11 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, - * update metadata and remove MISSING flag - */ - dm_list_iterate_items(pvl, &all_pvs) -- check_reappeared_pv(correct_vg, pvl->pv); -+ _check_reappeared_pv(correct_vg, pvl->pv, 1); - -- cmd->handles_missing_pvs = 1; -- if (!vg_write(correct_vg)) { -- log_error("Automatic metadata correction failed"); -+ if (!_repair_inconsistent_vg(correct_vg)) { - _free_pv_list(&all_pvs); - release_vg(correct_vg); -- cmd->handles_missing_pvs = saved_handles_missing_pvs; -- return NULL; -- } -- cmd->handles_missing_pvs = saved_handles_missing_pvs; -- -- if (!vg_commit(correct_vg)) { -- log_error("Automatic metadata correction commit " -- "failed"); -- release_vg(correct_vg); - return NULL; - } - -diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h -index 2408c23..21ac204 100644 ---- a/lib/metadata/metadata.h -+++ b/lib/metadata/metadata.h -@@ -486,7 +486,4 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name, - uint64_t find_min_mda_size(struct dm_list *mdas); - char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tags); - --void check_reappeared_pv(struct volume_group *correct_vg, -- struct physical_volume *pv); -- - #endif -diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c -index 325a4e8..fc1273e 100644 ---- a/lib/metadata/snapshot_manip.c -+++ b/lib/metadata/snapshot_manip.c -@@ -227,6 +227,16 @@ int vg_remove_snapshot(struct logical_volume *cow) - struct logical_volume *origin = origin_from_cow(cow); - int is_origin_active = lv_is_active(origin); - -+ if (is_origin_active && -+ lv_is_virtual_origin(origin)) { -+ if (!deactivate_lv(origin->vg->cmd, origin)) { -+ log_error("Failed to deactivate logical volume \"%s\"", -+ origin->name); -+ return 0; -+ } -+ is_origin_active = 0; -+ } -+ - dm_list_del(&cow->snapshot->origin_list); - origin->origin_count--; - -diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c -index a6e0fc2..bd5b117 100644 ---- a/lib/metadata/thin_manip.c -+++ b/lib/metadata/thin_manip.c -@@ -809,6 +809,7 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg - .stripes = 1, - .vg_name = vg->name, - .zero = 1, -+ .temporary = 1, - }; - - dm_list_init(&lp.tags); -diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c -index 506d618..91e778f 100644 ---- a/lib/snapshot/snapshot.c -+++ b/lib/snapshot/snapshot.c -@@ -23,6 +23,10 @@ - #include "str_list.h" - #include "defaults.h" - -+#define SEG_LOG_ERROR(t, p...) \ -+ log_error(t " segment %s of logical volume %s.", ## p, \ -+ dm_config_parent_name(sn), seg->lv->name), 0; -+ - static const char *_snap_name(const struct lv_segment *seg) - { - return seg->segtype->name; -@@ -41,50 +45,45 @@ static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node - struct dm_hash_table *pv_hash __attribute__((unused))) - { - uint32_t chunk_size; -- const char *org_name, *cow_name; - struct logical_volume *org, *cow; -- int old_suppress, merge = 0; -+ const char *org_name = NULL, *cow_name = NULL; -+ int merge = 0; - - if (!dm_config_get_uint32(sn, "chunk_size", &chunk_size)) { - log_error("Couldn't read chunk size for snapshot."); - return 0; - } - -- old_suppress = log_suppress(1); -- -- if ((cow_name = dm_config_find_str(sn, "merging_store", NULL))) { -- if (dm_config_find_str(sn, "cow_store", NULL)) { -- log_suppress(old_suppress); -- log_error("Both snapshot cow and merging storage were specified."); -- return 0; -- } -+ if (dm_config_has_node(sn, "merging_store")) { -+ if (!(cow_name = dm_config_find_str(sn, "merging_store", NULL))) -+ return SEG_LOG_ERROR("Merging store must be a string in"); - merge = 1; - } -- else if (!(cow_name = dm_config_find_str(sn, "cow_store", NULL))) { -- log_suppress(old_suppress); -- log_error("Snapshot cow storage not specified."); -- return 0; -- } - -- if (!(org_name = dm_config_find_str(sn, "origin", NULL))) { -- log_suppress(old_suppress); -- log_error("Snapshot origin not specified."); -- return 0; -+ if (dm_config_has_node(sn, "cow_store")) { -+ if (cow_name) -+ return SEG_LOG_ERROR("Both snapshot cow and merging storage were specified in"); -+ -+ if (!(cow_name = dm_config_find_str(sn, "cow_store", NULL))) -+ return SEG_LOG_ERROR("Cow store must be a string in"); - } - -- log_suppress(old_suppress); -+ if (!cow_name) -+ return SEG_LOG_ERROR("Snapshot cow storage not specified in"); - -- if (!(cow = find_lv(seg->lv->vg, cow_name))) { -- log_error("Unknown logical volume specified for " -- "snapshot cow store."); -- return 0; -- } -+ if (!dm_config_has_node(sn, "origin")) -+ return SEG_LOG_ERROR("Snapshot origin not specified in"); - -- if (!(org = find_lv(seg->lv->vg, org_name))) { -- log_error("Unknown logical volume specified for " -- "snapshot origin."); -- return 0; -- } -+ if (!(org_name = dm_config_find_str(sn, "origin", NULL))) -+ return SEG_LOG_ERROR("Snapshot origin must be a string in"); -+ -+ if (!(cow = find_lv(seg->lv->vg, cow_name))) -+ return SEG_LOG_ERROR("Unknown logical volume %s specified for " -+ "snapshot cow store in", cow_name); -+ -+ if (!(org = find_lv(seg->lv->vg, org_name))) -+ return SEG_LOG_ERROR("Unknown logical volume %s specified for " -+ "snapshot origin in", org_name); - - init_snapshot_seg(seg, org, cow, chunk_size, merge); - -diff --git a/libdaemon/client/daemon-io.c b/libdaemon/client/daemon-io.c -index 906f375..e2c5180 100644 ---- a/libdaemon/client/daemon-io.c -+++ b/libdaemon/client/daemon-io.c -@@ -38,7 +38,7 @@ int buffer_read(int fd, struct buffer *buffer) { - result = read(fd, buffer->mem + buffer->used, buffer->allocated - buffer->used); - if (result > 0) { - buffer->used += result; -- if (!strncmp((buffer->mem) + buffer->used - 4, "\n##\n", 4)) { -+ if (buffer->used >= 4 && !strncmp((buffer->mem) + buffer->used - 4, "\n##\n", 4)) { - buffer->used -= 4; - buffer->mem[buffer->used] = 0; - break; /* success, we have the full message now */ -diff --git a/libdaemon/server/daemon-server.c b/libdaemon/server/daemon-server.c -index df2c852..b114b9f 100644 ---- a/libdaemon/server/daemon-server.c -+++ b/libdaemon/server/daemon-server.c -@@ -381,6 +381,7 @@ static void *client_thread(void *baton) - request req; - response res; - -+ b->client.thread_id = pthread_self(); - buffer_init(&req.buffer); - - while (1) { -@@ -431,6 +432,7 @@ static int handle_connect(daemon_state s) - struct sockaddr_un sockaddr; - client_handle client = { .thread_id = 0 }; - socklen_t sl = sizeof(sockaddr); -+ pthread_t tid; - - client.socket_fd = accept(s.socket_fd, (struct sockaddr *) &sockaddr, &sl); - if (client.socket_fd < 0) -@@ -446,10 +448,10 @@ static int handle_connect(daemon_state s) - baton->s = s; - baton->client = client; - -- if (pthread_create(&baton->client.thread_id, NULL, client_thread, baton)) -+ if (pthread_create(&tid, NULL, client_thread, baton)) - return 0; - -- pthread_detach(baton->client.thread_id); -+ pthread_detach(tid); - - return 1; - } -diff --git a/libdm/Makefile.in b/libdm/Makefile.in -index bddb0a0..2aa70d4 100644 ---- a/libdm/Makefile.in -+++ b/libdm/Makefile.in -@@ -57,7 +57,7 @@ include $(top_builddir)/make.tmpl - DEFS += -DDM_DEVICE_UID=@DM_DEVICE_UID@ -DDM_DEVICE_GID=@DM_DEVICE_GID@ \ - -DDM_DEVICE_MODE=@DM_DEVICE_MODE@ - --LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) -+LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS) - - device-mapper: all - -diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h -index aaf00b2..adfbb76 100644 ---- a/libdm/libdevmapper.h -+++ b/libdm/libdevmapper.h -@@ -21,7 +21,7 @@ - #include - #include - --#ifdef linux -+#ifdef __linux__ - # include - #endif - -diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c -index b66911c..9a52f2e 100644 ---- a/libdm/libdm-common.c -+++ b/libdm/libdm-common.c -@@ -966,7 +966,9 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor, - - (void) dm_prepare_selinux_context(path, S_IFBLK); - old_mask = umask(0); -- if (mknod(path, S_IFBLK | mode, dev) < 0) { -+ -+ /* The node may already have been created by udev. So ignore EEXIST. */ -+ if (mknod(path, S_IFBLK | mode, dev) < 0 && errno != EEXIST) { - log_error("%s: mknod for %s failed: %s", path, dev_name, strerror(errno)); - umask(old_mask); - (void) dm_prepare_selinux_context(NULL, 0); -@@ -998,7 +1000,8 @@ static int _rm_dev_node(const char *dev_name, int warn_if_udev_failed) - log_warn("Node %s was not removed by udev. " - "Falling back to direct node removal.", path); - -- if (unlink(path) < 0) { -+ /* udev may already have deleted the node. Ignore ENOENT. */ -+ if (unlink(path) < 0 && errno != ENOENT) { - log_error("Unable to unlink device node for '%s'", dev_name); - return 0; - } -@@ -1054,7 +1057,8 @@ static int _rename_dev_node(const char *old_name, const char *new_name, - "Falling back to direct node rename.", - oldpath, newpath); - -- if (rename(oldpath, newpath) < 0) { -+ /* udev may already have renamed the node. Ignore ENOENT. */ -+ if (rename(oldpath, newpath) < 0 && errno != ENOENT) { - log_error("Unable to rename device node from '%s' to '%s'", - old_name, new_name); - return 0; -@@ -1795,7 +1799,8 @@ int dm_device_has_holders(uint32_t major, uint32_t minor) - } - - if (stat(sysfs_path, &st)) { -- log_sys_error("stat", sysfs_path); -+ if (errno != ENOENT) -+ log_sys_error("stat", sysfs_path); - return 0; - } - -diff --git a/libdm/mm/pool-fast.c b/libdm/mm/pool-fast.c -index 2b494d6..edb31a0 100644 ---- a/libdm/mm/pool-fast.c -+++ b/libdm/mm/pool-fast.c -@@ -62,7 +62,9 @@ struct dm_pool *dm_pool_create(const char *name, size_t chunk_hint) - while (new_size < p->chunk_size) - new_size <<= 1; - p->chunk_size = new_size; -+ pthread_mutex_lock(&_dm_pools_mutex); - dm_list_add(&_dm_pools, &p->list); -+ pthread_mutex_unlock(&_dm_pools_mutex); - return p; - } - -@@ -77,7 +79,9 @@ void dm_pool_destroy(struct dm_pool *p) - c = pr; - } - -+ pthread_mutex_lock(&_dm_pools_mutex); - dm_list_del(&p->list); -+ pthread_mutex_unlock(&_dm_pools_mutex); - dm_free(p); - } - -diff --git a/libdm/mm/pool.c b/libdm/mm/pool.c -index fd08307..ef006a4 100644 ---- a/libdm/mm/pool.c -+++ b/libdm/mm/pool.c -@@ -15,9 +15,10 @@ - - #include "dmlib.h" - #include -+#include - --/* FIXME: thread unsafe */ - static DM_LIST_INIT(_dm_pools); -+static pthread_mutex_t _dm_pools_mutex = PTHREAD_MUTEX_INITIALIZER; - void dm_pools_check_leaks(void); - - #ifdef DEBUG_ENFORCE_POOL_LOCKING -@@ -81,8 +82,11 @@ void dm_pools_check_leaks(void) - { - struct dm_pool *p; - -- if (dm_list_empty(&_dm_pools)) -+ pthread_mutex_lock(&_dm_pools_mutex); -+ if (dm_list_empty(&_dm_pools)) { -+ pthread_mutex_unlock(&_dm_pools_mutex); - return; -+ } - - log_error("You have a memory leak (not released memory pool):"); - dm_list_iterate_items(p, &_dm_pools) { -@@ -94,6 +98,7 @@ void dm_pools_check_leaks(void) - log_error(" [%p] %s", p, p->name); - #endif - } -+ pthread_mutex_unlock(&_dm_pools_mutex); - log_error(INTERNAL_ERROR "Unreleased memory pool(s) found."); - } - -diff --git a/man/pvscan.8.in b/man/pvscan.8.in -index 211c82b..37ecaaf 100644 ---- a/man/pvscan.8.in -+++ b/man/pvscan.8.in -@@ -25,7 +25,9 @@ pvscan \- scan all disks for physical volumes - .B \-\-minor - .I minor - | --.IR DevicePath ]... -+.IR DevicePath -+| -+.IR major:minor ]... - .SH DESCRIPTION - pvscan scans all supported LVM block devices in the system for - physical volumes. -diff --git a/scripts/Makefile.in b/scripts/Makefile.in -index a658903..3616afa 100644 ---- a/scripts/Makefile.in -+++ b/scripts/Makefile.in -@@ -107,6 +107,7 @@ endif - ifeq ("@BUILD_LVMETAD@", "yes") - $(INSTALL_DATA) lvm2_lvmetad_systemd_red_hat.socket $(systemd_unit_dir)/lvm2-lvmetad.socket - $(INSTALL_DATA) lvm2_lvmetad_systemd_red_hat.service $(systemd_unit_dir)/lvm2-lvmetad.service -+ $(INSTALL_DATA) lvm2_pvscan_systemd_red_hat@.service $(systemd_unit_dir)/lvm2-pvscan@.service - endif - - install_tmpfiles_configuration: -@@ -118,6 +119,7 @@ DISTCLEAN_TARGETS += clvmd_init_red_hat cmirrord_init_red_hat \ - dm_event_systemd_red_hat.socket dm_event_systemd_red_hat.service \ - lvm2_monitoring_systemd_red_hat.service \ - lvm2_lvmetad_systemd_red_hat.socket lvm2_lvmetad_systemd_red_hat.service \ -+ lvm2_pvscan_systemd_red_hat@.service \ - lvm2_tmpfiles_red_hat.conf blk_availability_init_red_hat \ - blk_availability_systemd_red_hat.service \ - blkdeactivate.sh -diff --git a/scripts/blkdeactivate.sh.in b/scripts/blkdeactivate.sh.in -index b6d0117..f454154 100644 ---- a/scripts/blkdeactivate.sh.in -+++ b/scripts/blkdeactivate.sh.in -@@ -323,7 +323,10 @@ deactivate_all() { - $LSBLK_READ <<< "`$LSBLK --nodeps $1`" - - # check if the device is not on the skip list already -- test -z ${SKIP_DEVICE_LIST["$kname"]} || continue -+ test -z ${SKIP_DEVICE_LIST["$kname"]} || { -+ shift -+ continue -+ } - - deactivate - else -diff --git a/scripts/lvm2_pvscan_systemd_red_hat@.service.in b/scripts/lvm2_pvscan_systemd_red_hat@.service.in -new file mode 100644 -index 0000000..4225982 ---- /dev/null -+++ b/scripts/lvm2_pvscan_systemd_red_hat@.service.in -@@ -0,0 +1,14 @@ -+[Unit] -+Description=LVM2 PV scan on device %i -+Documentation=man:pvscan(8) -+DefaultDependencies=no -+BindsTo=dev-block-%i.device -+After=lvm2-lvmetad.socket -+Before=shutdown.target -+Conflicts=shutdown.target -+ -+[Service] -+Type=oneshot -+RemainAfterExit=yes -+ExecStart=@sbindir@/pvscan --cache --activate ay /dev/block/%i -+ExecStop=@sbindir@/pvscan --cache %i -diff --git a/scripts/vgimportclone.sh b/scripts/vgimportclone.sh -index d6ad75d..7087557 100755 ---- a/scripts/vgimportclone.sh -+++ b/scripts/vgimportclone.sh -@@ -204,8 +204,8 @@ for ARG - do - if [ -b "$ARG" ] - then -- PVS_OUT=`"${LVM}" pvs ${LVM_OPTS} --noheadings -o vg_name "$ARG" 2>/dev/null` -- checkvalue $? "$ARG is not a PV." -+ PVS_OUT=`"${LVM}" pvs ${LVM_OPTS} --noheadings -o vg_name "$ARG"` -+ checkvalue $? "$ARG could not be verified to be a PV without errors." - PV_VGNAME=$(echo $PVS_OUT | $GREP -v '[[:space:]]+$') - [ -z "$PV_VGNAME" ] && die 3 "$ARG is not in a VG." - -@@ -227,7 +227,7 @@ fi - ### Get the existing state so we can use it later - ##################################################################### - --OLDVGS=`"${LVM}" vgs ${LVM_OPTS} -o name --noheadings 2>/dev/null` -+OLDVGS=`"${LVM}" vgs ${LVM_OPTS} -o name --noheadings` - checkvalue $? "Current VG names could not be collected without errors" - - ##################################################################### -@@ -280,7 +280,7 @@ export LVM_SYSTEM_DIR=${TMP_LVM_SYSTEM_DIR} - ### Rename the VG(s) and change the VG and PV UUIDs. - ##################################################################### - --PVINFO=`"${LVM}" pvs ${LVM_OPTS} -o pv_name,vg_name,vg_attr --noheadings --separator : 2>/dev/null` -+PVINFO=`"${LVM}" pvs ${LVM_OPTS} -o pv_name,vg_name,vg_attr --noheadings --separator :` - checkvalue $? "PV info could not be collected without errors" - - # output VG info so each line looks like: name:exported?:disk1,disk2,... -diff --git a/test/Makefile.in b/test/Makefile.in -index 1b9789f..943a4ce 100644 ---- a/test/Makefile.in -+++ b/test/Makefile.in -@@ -25,6 +25,10 @@ abs_top_builddir = "@abs_top_builddir@" - abs_top_srcdir = "@abs_top_srcdir@" - - LVM_TEST_RESULTS ?= results -+export LVM_TEST_THIN_CHECK_CMD?=@THIN_CHECK_CMD@ -+export LVM_TEST_THIN_DUMP_CMD?=@THIN_DUMP_CMD@ -+export LVM_TEST_THIN_REPAIR_CMD?=@THIN_REPAIR_CMD@ -+ - SUBDIRS = api unit - SOURCES = lib/not.c lib/harness.c - -@@ -34,7 +38,8 @@ 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 $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/api/\*.sh \) -and -regex "$(srcdir)/.*($(subst $(comma),|,$(T))).*" -and -not -regex "$(srcdir)/.*($(subst $(comma),|,$(S))).*" | sort) - RUN_BASE = $(subst $(srcdir)/,,$(RUN)) - - # Shell quote; -@@ -57,12 +62,15 @@ help: - @echo " help Display callable targets." - @echo -e "\nSupported variables:" - @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_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_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_UNLIMITED Set to get unlimited test log (>32MB)" - @echo " LVM_VERIFY_UDEV Default verify state for lvm.conf." - @echo " S Skip given test (regex)." -diff --git a/test/lib/aux.sh b/test/lib/aux.sh -index d27d263..f51fc0d 100644 ---- a/test/lib/aux.sh -+++ b/test/lib/aux.sh -@@ -162,7 +162,7 @@ teardown_devs() { - local stray_loops=( $(losetup -a | grep "$COMMON_PREFIX" | cut -d: -f1) ) - test ${#stray_loops[@]} -eq 0 || { - echo "Removing stray loop devices containing $COMMON_PREFIX: ${stray_loops[@]}" -- losetup -d "${stray_loops[@]}" -+ for i in "${stray_loops[@]}" ; do losetup -d $i ; done - } - } - } -diff --git a/test/lib/get.sh b/test/lib/get.sh -index 7b97c06..5dd5451 100644 ---- a/test/lib/get.sh -+++ b/test/lib/get.sh -@@ -1,4 +1,4 @@ --#!/bin/sh -+#!/usr/bin/env bash - # Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved. - # - # This copyrighted material is made available to anyone wishing to use, -diff --git a/test/lib/harness.c b/test/lib/harness.c -index 0036502..8c9f4a7 100644 ---- a/test/lib/harness.c -+++ b/test/lib/harness.c -@@ -173,7 +173,7 @@ static void _append_buf(const char *buf, size_t len) - kill(-pid, SIGINT); - return; - } -- readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 4096; -+ readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 16384; - readbuf = realloc(readbuf, readbuf_sz); - } - -@@ -221,7 +221,7 @@ static const char *_append_with_stamp(const char *buf, int stamp) - - static void drain(int fd) - { -- char buf[4096]; -+ char buf[4096 + 1]; - const char *bp; - int stamp = 0; - int sz; -@@ -322,7 +322,7 @@ static void failed(int i, char *f, int st) { - - ++ s.nfailed; - s.status[i] = FAILED; -- printf("FAILED.\n"); -+ printf("FAILED (status %d).\n", WEXITSTATUS(st)); - if (!verbose && readbuf) { - printf("-- FAILED %s ------------------------------------\n", f); - dump(); -@@ -340,12 +340,12 @@ static void run(int i, char *f) { - 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]); - } -+ close(fds[0]); - if (strchr(f, ':')) { - strcpy(flavour, f); - *strchr(flavour, ':') = 0; -@@ -372,6 +372,7 @@ static void run(int i, char *f) { - FILE *varlogmsg; - int fd_vlm = -1; - -+ //close(fds[1]); - snprintf(buf, sizeof(buf), "%s ...", f); - printf("Running %-60s ", buf); - fflush(stdout); -@@ -404,14 +405,14 @@ static void run(int i, char *f) { - } - - FD_ZERO(&set); -- FD_SET(fds[1], &set); -+ FD_SET(fds[0], &set); - selectwait.tv_sec = 0; - selectwait.tv_usec = 500000; /* timeout 0.5s */ -- if (select(fds[1] + 1, &set, NULL, NULL, &selectwait) <= 0) { -+ if (select(fds[0] + 1, &set, NULL, NULL, &selectwait) <= 0) { - no_write++; - continue; - } -- drain(fds[1]); -+ drain(fds[0]); - no_write = 0; - if (fd_vlm >= 0) - drain(fd_vlm); -@@ -420,7 +421,7 @@ static void run(int i, char *f) { - perror("waitpid"); - exit(206); - } -- drain(fds[1]); -+ drain(fds[0]); - if (fd_vlm >= 0) - drain(fd_vlm); - if (die == 2) -@@ -472,12 +473,13 @@ int main(int argc, char **argv) { - results = getenv("LVM_TEST_RESULTS") ? : "results"; - (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; - } -@@ -537,10 +539,10 @@ int main(int argc, char **argv) { - printf("skipped: %s\n", argv[i]); - break; - case INTERRUPTED: -- printf("interrupted: %s\n", argv[i]); -+ printf("INTERRUPTED: %s\n", argv[i]); - break; - case TIMEOUT: -- printf("timeout: %s\n", argv[i]); -+ printf("TIMEOUT: %s\n", argv[i]); - break; - default: /* do nothing */ ; - } -diff --git a/test/shell/lvconvert-repair-raid.sh b/test/shell/lvconvert-repair-raid.sh -index 84e247d..71c84c1 100644 ---- a/test/shell/lvconvert-repair-raid.sh -+++ b/test/shell/lvconvert-repair-raid.sh -@@ -29,7 +29,7 @@ vgextend $vg "$dev3" - lvremove -ff $vg - - # RAID6 double replace --lvcreate --type raid5 -i 3 -l 2 -n $lv1 $vg \ -+lvcreate --type raid6 -i 3 -l 2 -n $lv1 $vg \ - "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" - aux wait_for_sync $vg $lv1 - aux disable_dev "$dev4" "$dev5" -diff --git a/test/shell/lvconvert-repair-thin.sh b/test/shell/lvconvert-repair-thin.sh -new file mode 100644 -index 0000000..aa301d6 ---- /dev/null -+++ b/test/shell/lvconvert-repair-thin.sh -@@ -0,0 +1,116 @@ -+#!/bin/sh -+ -+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ -+# Test repairing of broken thin pool metadata -+ -+. lib/test -+ -+which mkfs.ext2 || skip -+ -+# By default use tools from configuration (exported through Makefile) -+# Allow user to override location of binaries to take tools from different laces -+# Maybe check also version of the tools here? -+test -n "$LVM_TEST_THIN_CHECK_CMD" || LVM_TEST_THIN_CHECK_CMD=$(which thin_check) || skip -+test -n "$LVM_TEST_THIN_DUMP_CMD" || LVM_TEST_THIN_DUMP_CMD=$(which thin_dump) || skip -+test -n "$LVM_TEST_THIN_REPAIR_CMD" || LVM_TEST_THIN_REPAIR_CMD=$(which thin_repair) || skip -+ -+# -+# Main -+# -+aux have_thin 1 0 0 || skip -+ -+aux prepare_vg 4 -+ -+# Create LV -+lvcreate -T -L20 -V10 -n $lv1 $vg/pool "$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 -+ -+# Make some repairable metadata damage?? -+vgchange -an $vg -+ -+lvconvert --repair $vg/pool -+ -+lvs -a $vg -+ -+# Test swapping - swap out thin-pool's metadata with our repair volume -+lvconvert -y -f --poolmetadata $vg/repair --thinpool $vg/pool -+ -+lvchange -aey $vg/repair $vg/fixed -+ -+#dd if=$DM_DEV_DIR/$vg/repair of=back bs=1M -+ -+# Make some 'repairable' damage?? -+dd if=/dev/zero of=$DM_DEV_DIR/$vg/repair bs=1 seek=40960 count=1 -+ -+#dd if=$DM_DEV_DIR/$vg/repair of=back_trashed bs=1M -+#not vgchange -ay $vg -+ -+#lvconvert --repair $vg/pool -+ -+# Using now SHOULD - since thin tools currently do not seem to work -+should not $THIN_CHECK $DM_DEV_DIR/$vg/repair -+ -+should not $LVM_TEST_THIN_DUMP_CMD $DM_DEV_DIR/$vg/repair | tee dump -+ -+should $LVM_TEST_THIN_REPAIR_CMD -i $DM_DEV_DIR/$vg/repair -o $DM_DEV_DIR/$vg/fixed -+ -+should $LVM_TEST_THIN_DUMP_CMD --repair $DM_DEV_DIR/$vg/repair | tee repaired_xml -+ -+should $LVM_TEST_THIN_CHECK_CMD $DM_DEV_DIR/$vg/fixed -+ -+# Swap repaired metadata back -+lvconvert -y -f --poolmetadata $vg/fixed --thinpool $vg/pool -+lvs -a $vg -+ -+# Activate pool - this should now work -+should vgchange -ay $vg -+ -+lvs -a -o+devices $vg -+dmsetup table -+dmsetup info -c -+dmsetup ls --tree -+ -+lvchange -an $vg -+ -+# FIXME: Currently in deep troubles - we can't remove thin volume from broken pool -+should lvremove -ff $vg -+ -+# let's not block PVs with openned _tdata/_tmeta devices -+dmsetup remove $vg-pool_tdata || true -+dmsetup remove $vg-pool_tmeta || true -+ -+dmsetup table -+ -+# FIXME: needs also --yes with double force -+pvremove --yes -ff "$dev1" -+pvremove --yes -ff "$dev2" -+ -+# FIXME: pv1 & pv2 are removed so pv3 & pv4 have no real LVs, -+# yet vgremove is refusing to do its jobs and suggest --partial?? -+should vgremove -ff $vg -+ -+# FIXME: stressing even more - there are no pool PV, we do not pass... -+should vgreduce --removemissing -f $vg -+should vgremove -ff $vg -+ -+# Let's do a final forced cleanup -+pvremove --yes -ff "$dev3" -+pvremove --yes -ff "$dev4" -diff --git a/test/shell/lvconvert-thin-external.sh b/test/shell/lvconvert-thin-external.sh -index a700b37..d9d4d19 100644 ---- a/test/shell/lvconvert-thin-external.sh -+++ b/test/shell/lvconvert-thin-external.sh -@@ -144,5 +144,13 @@ 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 --thin --thinpool $vg/pool $vg/thin --originname thin-origin -+check lv_field $vg/thin segtype thin -+check lv_field $vg/thin-origin segtype linear - - vgremove -ff $vg -diff --git a/test/shell/lvcreate-usage.sh b/test/shell/lvcreate-usage.sh -index 68a15a9..105fbce 100644 ---- a/test/shell/lvcreate-usage.sh -+++ b/test/shell/lvcreate-usage.sh -@@ -1,5 +1,5 @@ - #!/bin/sh --# Copyright (C) 2008-2011 Red Hat, Inc. All rights reserved. -+# 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 -@@ -15,7 +15,7 @@ - - aux prepare_pvs 4 - aux pvcreate --metadatacopies 0 "$dev1" --vgcreate -cn $vg $(cat DEVICES) -+vgcreate $vg $(cat DEVICES) - - # "lvcreate rejects repeated invocation (run 2 times) (bz178216)" - lvcreate -n $lv -l 4 $vg -@@ -58,7 +58,7 @@ test -z "$(lvdisplay $vg)" - # Setting max_lv works. (bz490298) - lvremove -ff $vg - vgchange -l 3 $vg --lvcreate -l1 -n $lv1 $vg -+lvcreate -aey -l1 -n $lv1 $vg - lvcreate -l1 -s -n $lv2 $vg/$lv1 - lvcreate -l1 -n $lv3 $vg - not lvcreate -l1 -n $lv4 $vg -@@ -71,13 +71,13 @@ not lvcreate -l1 -n $lv4 $vg - not lvcreate -l1 --type mirror -m1 -n $lv4 $vg - - lvremove -ff $vg/$lv3 --lvcreate -l1 --type mirror -m1 -n $lv3 $vg -+lvcreate -aey -l1 --type mirror -m1 -n $lv3 $vg - vgs -o +max_lv $vg - not lvcreate -l1 -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 -@@ -90,8 +90,8 @@ vgchange -l 0 $vg - # 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 -+vgcreate $vg $(cat DEVICES) -+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 -@@ -111,10 +111,10 @@ 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 --type mirror -m 1 $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 --type mirror -m 1 $vg -+lvcreate -aey -L 32m -n $lv --regionsize 4m --type mirror -m 1 $vg - check lv_field $vg/$lv regionsize "4.00m" - lvremove -ff $vg - -diff --git a/test/shell/lvmcache-exercise.sh b/test/shell/lvmcache-exercise.sh -index b1e2b92..6e8efda 100644 ---- a/test/shell/lvmcache-exercise.sh -+++ b/test/shell/lvmcache-exercise.sh -@@ -1,5 +1,5 @@ - #!/bin/sh --# Copyright (C) 2008 Red Hat, Inc. All rights reserved. -+# 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 -@@ -14,10 +14,23 @@ - aux prepare_pvs 5 - - vgcreate $vg1 "$dev1" --vgcreate $vg2 "$dev3" -+vgcreate $vg2 "$dev3" "$dev4" "$dev5" - - aux disable_dev "$dev1" - pvscan - vgcreate $vg1 "$dev2" - aux enable_dev "$dev1" - pvs -+ -+# reappearing device (rhbz 995440) -+lvcreate -aey -m2 --type mirror -l4 --alloc anywhere --corelog -n $lv1 $vg2 -+ -+aux disable_dev "$dev3" -+lvconvert --yes --repair $vg2/$lv1 -+aux enable_dev "$dev3" -+ -+# here it should fix any reappeared devices -+lvs -+ -+lvs -a $vg2 -o+devices 2>&1 | tee out -+not grep reappeared out -diff --git a/test/shell/snapshot-usage.sh b/test/shell/snapshot-usage.sh -index 9c1c2f6..3d4d308 100644 ---- a/test/shell/snapshot-usage.sh -+++ b/test/shell/snapshot-usage.sh -@@ -17,6 +17,13 @@ fill() { - dd if=/dev/zero of=$DM_DEV_DIR/$vg1/lvol0 bs=$1 count=1 - } - -+cleanup_tail() -+{ -+ test -z "$SLEEP_PID" || kill $SLEEP_PID -+ wait -+ aux teardown -+} -+ - aux prepare_pvs 1 - vgcreate -s 4M $vg $(cat DEVICES) - -@@ -30,6 +37,34 @@ aux lvmconf "activation/snapshot_autoextend_percent = 20" \ - pvcreate --setphysicalvolumesize 4T $DM_DEV_DIR/$vg/$lv - vgcreate -s 1K $vg1 $DM_DEV_DIR/$vg/$lv - -+# Test removal of opened snapshot -+lvcreate -V50 -L10 -n $lv1 -s $vg1 -+ -+lvs -a -o+lv_active $vg1 -+lvchange -an $vg1 -+ -+# Snapshot get exclusive activation -+lvchange -ay $vg1 -+lvs -a -o+lv_active $vg1 -+ -+trap 'cleanup_tail' EXIT -+# Keep device busy (but not mounted) for a while -+sleep 30 < $DM_DEV_DIR/$vg1/$lv1 & -+SLEEP_PID=$! -+ -+# 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 -+not dmsetup info $vg1-$lv1 >/dev/null || \ -+ die "$vg1/$lv1 expected to be removed, but there are mappings!" -+ - # Check border size - lvcreate -aey -L4095G $vg1 - lvcreate -s -L100K $vg1/lvol0 -@@ -79,7 +114,7 @@ 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 -aey -V15E -l1 -n $lv1 -s $vg1 - check lv_field $vg1/$lv1 origin_size "15.00e" - -diff --git a/test/shell/vgrename-usage.sh b/test/shell/vgrename-usage.sh -index 2b8ac5a..59576ac 100644 ---- a/test/shell/vgrename-usage.sh -+++ b/test/shell/vgrename-usage.sh -@@ -38,3 +38,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/tools/dmsetup.c b/tools/dmsetup.c -index 517e8aa..a0ee23e 100644 ---- a/tools/dmsetup.c -+++ b/tools/dmsetup.c -@@ -1147,7 +1147,7 @@ static int _udevcomplete_all(CMD_ARGS) - unsigned age = 0; - time_t t; - -- if (argc == 2 && (sscanf(argv[1], "%i", &age) != 1)) { -+ if (argc == 2 && (sscanf(argv[1], "%u", &age) != 1)) { - log_error("Failed to read age_in_minutes parameter."); - return 0; - } -diff --git a/tools/lvchange.c b/tools/lvchange.c -index 1d4f0a5..6ae9720 100644 ---- a/tools/lvchange.c -+++ b/tools/lvchange.c -@@ -120,8 +120,7 @@ static int lvchange_pool_update(struct cmd_context *cmd, - if (((discards == THIN_DISCARDS_IGNORE) || - (first_seg(lv)->discards == THIN_DISCARDS_IGNORE)) && - pool_is_active(lv)) -- log_error("Cannot change discards state for active " -- "pool volume \"%s\".", lv->name); -+ log_error("Cannot change support for discards while pool volume \"%s\" is active.", lv->name); - else { - first_seg(lv)->discards = discards; - update++; -diff --git a/tools/lvconvert.c b/tools/lvconvert.c -index 49881fa..a6c1187 100644 ---- a/tools/lvconvert.c -+++ b/tools/lvconvert.c -@@ -1891,6 +1891,10 @@ static int lvconvert_merge(struct cmd_context *cmd, - find_merging_snapshot(origin)->cow->name); - return 0; - } -+ if (lv_is_virtual_origin(origin)) { -+ log_error("Snapshot %s has virtual origin.", lv->name); -+ return 0; -+ } - - /* - * Prevent merge with open device(s) as it would likely lead -@@ -2266,11 +2270,12 @@ static int _lvconvert_thinpool(struct cmd_context *cmd, - int r = 0; - const char *old_name; - struct lv_segment *seg; -- struct logical_volume *data_lv = pool_lv; -+ struct logical_volume *data_lv; - struct logical_volume *metadata_lv; - struct logical_volume *pool_metadata_lv; - struct logical_volume *external_lv = NULL; - char metadata_name[NAME_LEN], data_name[NAME_LEN]; -+ int activate_pool; - - if (!lv_is_visible(pool_lv)) { - log_error("Can't convert internal LV %s/%s.", -@@ -2299,17 +2304,22 @@ static int _lvconvert_thinpool(struct cmd_context *cmd, - } - - if (lv_is_thin_pool(pool_lv)) { -+ activate_pool = lv_is_active(pool_lv); - r = 1; /* Already existing thin pool */ - goto out; - } - } - -+ data_lv = pool_lv; - if (lv_is_thin_type(pool_lv) && !lp->pool_metadata_lv_name) { - log_error("Can't use thin logical volume %s/%s for thin pool data.", - pool_lv->vg->name, pool_lv->name); - return 0; - } - -+ /* Allow to have only thinpool active and restore it's active state */ -+ activate_pool = lv_is_active(pool_lv); -+ - /* We are changing target type, so deactivate first */ - if (!deactivate_lv(cmd, pool_lv)) { - log_error("Aborting. Failed to deactivate logical volume %s/%s.", -@@ -2317,6 +2327,13 @@ static int _lvconvert_thinpool(struct cmd_context *cmd, - return 0; - } - -+ if (lv_is_thin_pool(pool_lv) && pool_is_active(pool_lv)) { -+ /* If any thin volume is also active - abort here */ -+ log_error("Cannot convert pool %s/%s with active thin volumes.", -+ pool_lv->vg->name, pool_lv->name); -+ return 0; -+ } -+ - if ((dm_snprintf(metadata_name, sizeof(metadata_name), "%s_tmeta", - pool_lv->name) < 0) || - (dm_snprintf(data_name, sizeof(data_name), "%s_tdata", -@@ -2418,6 +2435,7 @@ static int _lvconvert_thinpool(struct cmd_context *cmd, - goto mda_write; - } - -+ metadata_lv->status |= LV_NOSCAN; - if (!lv_is_active(metadata_lv) && - !activate_lv_local(cmd, metadata_lv)) { - log_error("Aborting. Failed to activate thin metadata lv."); -@@ -2510,7 +2528,8 @@ mda_write: - if (!vg_write(pool_lv->vg) || !vg_commit(pool_lv->vg)) - return_0; - -- if (!activate_lv_excl(cmd, pool_lv)) { -+ if (activate_pool && -+ !activate_lv_excl(cmd, pool_lv)) { - log_error("Failed to activate pool logical volume %s/%s.", - pool_lv->vg->name, pool_lv->name); - /* Deactivate subvolumes */ -diff --git a/tools/lvremove.c b/tools/lvremove.c -index 4f48746..dfc435c 100644 ---- a/tools/lvremove.c -+++ b/tools/lvremove.c -@@ -18,14 +18,6 @@ - static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv, - void *handle __attribute__((unused))) - { -- struct logical_volume *origin; -- -- /* -- * If this is a sparse device, remove its origin too. -- */ -- if (lv_is_cow(lv) && lv_is_virtual_origin(origin = origin_from_cow(lv))) -- lv = origin; -- - if (!lv_remove_with_dependencies(cmd, lv, (force_t) arg_count(cmd, force_ARG), 0)) - return_ECMD_FAILED; - -diff --git a/tools/pvscan.c b/tools/pvscan.c -index 3f16b05..b6a07bd 100644 ---- a/tools/pvscan.c -+++ b/tools/pvscan.c -@@ -132,6 +132,27 @@ out: - return r; - } - -+static int _clear_dev_from_lvmetad_cache(dev_t devno, int32_t major, int32_t minor, -+ activation_handler handler) -+{ -+ char *buf; -+ -+ if (!dm_asprintf(&buf, "%" PRIi32 ":%" PRIi32, major, minor)) -+ stack; -+ if (!lvmetad_pv_gone(devno, buf ? : "", handler)) { -+ if (buf) -+ dm_free(buf); -+ return 0; -+ } -+ -+ log_print_unless_silent("Device %s not found. " -+ "Cleared from lvmetad cache.", buf ? : ""); -+ if (buf) -+ dm_free(buf); -+ -+ return 1; -+} -+ - static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv) - { - int ret = ECMD_PROCESSED; -@@ -142,7 +163,6 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv) - int devno_args = 0; - struct arg_value_group_list *current_group; - dev_t devno; -- char *buf; - activation_handler handler = NULL; - - /* -@@ -193,11 +213,30 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv) - /* Process any command line PVs first. */ - while (argc--) { - pv_name = *argv++; -- dev = dev_cache_get(pv_name, cmd->lvmetad_filter); -- if (!dev) { -- log_error("Physical Volume %s not found.", pv_name); -- ret = ECMD_FAILED; -- continue; -+ if (pv_name[0] == '/') { -+ /* device path */ -+ if (!(dev = dev_cache_get(pv_name, cmd->lvmetad_filter))) { -+ log_error("Physical Volume %s not found.", pv_name); -+ ret = ECMD_FAILED; -+ continue; -+ } -+ } -+ else { -+ /* device major:minor */ -+ if (sscanf(pv_name, "%d:%d", &major, &minor) != 2) { -+ log_error("Failed to parse major:minor from %s", pv_name); -+ ret = ECMD_FAILED; -+ continue; -+ } -+ devno = MKDEV((dev_t)major, minor); -+ if (!(dev = dev_cache_get_by_devt(devno, cmd->lvmetad_filter))) { -+ if (!(_clear_dev_from_lvmetad_cache(devno, major, minor, handler))) { -+ stack; -+ ret = ECMD_FAILED; -+ break; -+ } -+ continue; -+ } - } - if (sigint_caught()) { - ret = ECMD_FAILED; -@@ -225,19 +264,11 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv) - devno = MKDEV((dev_t)major, minor); - - if (!(dev = dev_cache_get_by_devt(devno, cmd->lvmetad_filter))) { -- if (!dm_asprintf(&buf, "%" PRIi32 ":%" PRIi32, major, minor)) -+ if (!(_clear_dev_from_lvmetad_cache(devno, major, minor, handler))) { - stack; -- if (!lvmetad_pv_gone(devno, buf ? : "", handler)) { - ret = ECMD_FAILED; -- if (buf) -- dm_free(buf); - break; - } -- -- log_print_unless_silent("Device %s not found. " -- "Cleared from lvmetad cache.", buf ? : ""); -- if (buf) -- dm_free(buf); - continue; - } - if (sigint_caught()) { -diff --git a/tools/vgrename.c b/tools/vgrename.c -index 154a6f3..b5e778f 100644 ---- a/tools/vgrename.c -+++ b/tools/vgrename.c -@@ -83,6 +83,8 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path, - if (!lvmetad_vg_list_to_lvmcache(cmd)) - stack; - -+ lvmcache_label_scan(cmd, 2); -+ - /* Avoid duplicates */ - if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) { - log_error("No complete volume groups found"); -diff --git a/udev/11-dm-lvm.rules.in b/udev/11-dm-lvm.rules.in -index f21d0aa..5032280 100644 ---- a/udev/11-dm-lvm.rules.in -+++ b/udev/11-dm-lvm.rules.in -@@ -20,6 +20,21 @@ ENV{DM_UUID}!="LVM-?*", GOTO="lvm_end" - # Use DM name and split it up into its VG/LV/layer constituents. - IMPORT{program}="(DM_EXEC)/dmsetup splitname --nameprefixes --noheadings --rows $env{DM_NAME}" - -+# DM_SUBSYSTEM_UDEV_FLAG0 is the 'NOSCAN' flag for LVM subsystem. -+# This flag is used to temporarily disable selected rules to prevent any -+# processing or scanning done on the LVM volume before LVM has any chance -+# to zero any stale metadata found within the LV data area. Such stale -+# metadata could cause false claim of the LV device, keeping it open etc. -+# -+# If the NOSCAN flag is present, backup selected existing flags used to -+# disable rules, then set them firmly so those selected rules are surely skipped. -+# Restore these flags once the NOSCAN flag is dropped (which is normally any -+# uevent that follows for this LV, even an artificially generated one). -+ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_NOSCAN}="1", ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" -+ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", IMPORT{db}="DM_NOSCAN", IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD" -+ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}", \ -+ ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG_OLD}="", ENV{DM_NOSCAN}="" -+ - ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}=="1", GOTO="lvm_end" - - OPTIONS+="event_timeout=180" -diff --git a/udev/13-dm-disk.rules.in b/udev/13-dm-disk.rules.in -index 1920260..4b64dd6 100644 ---- a/udev/13-dm-disk.rules.in -+++ b/udev/13-dm-disk.rules.in -@@ -18,6 +18,7 @@ SYMLINK+="disk/by-id/dm-name-$env{DM_NAME}" - ENV{DM_UUID}=="?*", SYMLINK+="disk/by-id/dm-uuid-$env{DM_UUID}" - - ENV{DM_SUSPENDED}=="1", GOTO="dm_end" -+ENV{DM_NOSCAN}=="1", GOTO="dm_watch" - - (BLKID_RULE) - ENV{DM_UDEV_LOW_PRIORITY_FLAG}=="1", OPTIONS="link_priority=-100" -@@ -32,7 +33,7 @@ ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk - # (like creating a filesystem, changing filesystem label etc.). - # - # But let's use this until we have something better... -- -+LABEL="dm_watch" - OPTIONS+="watch" - - LABEL="dm_end" -diff --git a/udev/69-dm-lvm-metad.rules.in b/udev/69-dm-lvm-metad.rules.in -index ba43396..3e303b1 100644 ---- a/udev/69-dm-lvm-metad.rules.in -+++ b/udev/69-dm-lvm-metad.rules.in -@@ -17,6 +17,8 @@ - SUBSYSTEM!="block", GOTO="lvm_end" - (LVM_EXEC_RULE) - -+ENV{DM_NOSCAN}=="1", GOTO="lvm_end" -+ - # If the PV label got lost, inform lvmetad immediately. - # Detect the lost PV label by comparing previous ID_FS_TYPE value with current one. - ENV{.ID_FS_TYPE_NEW}="$env{ID_FS_TYPE}" -@@ -77,6 +79,6 @@ LABEL="lvm_scan" - # MD | | X | X* | | - # loop | | X | X* | | - # other | X | | X | | X --RUN+="(LVM_EXEC)/lvm pvscan --background --cache --activate ay --major $major --minor $minor", ENV{LVM_SCANNED}="1" -+(PVSCAN_RULE) - - LABEL="lvm_end" -diff --git a/udev/Makefile.in b/udev/Makefile.in -index 5c15bdb..40a4671 100644 ---- a/udev/Makefile.in -+++ b/udev/Makefile.in -@@ -46,8 +46,14 @@ else - BLKID_RULE=IMPORT{program}=\"${SBIN}\/blkid -o udev -p \$$tempnode\" - endif - -+ifeq ("@UDEV_SYSTEMD_BACKGROUND_JOBS@", "yes") -+PVSCAN_RULE=ENV{SYSTEMD_ALIAS}=\"\/dev\/block\/\$$major:\$$minor\"\nENV{ID_MODEL}=\"LVM PV \$$env{ID_FS_UUID_ENC} on \/dev\/\$$name\"\nENV{SYSTEMD_WANTS}=\"lvm2-pvscan@\$$major:\$$minor.service\" -+else -+PVSCAN_RULE=RUN\+\=\"$(LVM_EXEC)/lvm pvscan --background --cache --activate ay --major \$$major --minor \$$minor\", ENV{LVM_SCANNED}=\"1\" -+endif -+ - %.rules: %.rules.in -- $(SED) -e "s+(DM_DIR)+$(DM_DIR)+;s+(BLKID_RULE)+$(BLKID_RULE)+;s+(DM_EXEC_RULE)+$(DM_EXEC_RULE)+;s+(DM_EXEC)+$(DM_EXEC)+;s+(LVM_EXEC_RULE)+$(LVM_EXEC_RULE)+;s+(LVM_EXEC)+$(LVM_EXEC)+;" $< >$@ -+ $(SED) -e "s+(DM_DIR)+$(DM_DIR)+;s+(BLKID_RULE)+$(BLKID_RULE)+;s+(PVSCAN_RULE)+$(PVSCAN_RULE)+;s+(DM_EXEC_RULE)+$(DM_EXEC_RULE)+;s+(DM_EXEC)+$(DM_EXEC)+;s+(LVM_EXEC_RULE)+$(LVM_EXEC_RULE)+;s+(LVM_EXEC)+$(LVM_EXEC)+;" $< >$@ - - %_install: %.rules - $(INSTALL_DATA) -D $< $(udevdir)/$(... if unable to umount/deactivate. - Add dev-block-:.device systemd alias for complete PV tracking. -diff --git a/tools/lvconvert.c b/tools/lvconvert.c -index a6c1187..92a2022 100644 ---- a/tools/lvconvert.c -+++ b/tools/lvconvert.c -@@ -2435,14 +2435,8 @@ static int _lvconvert_thinpool(struct cmd_context *cmd, - goto mda_write; - } - -- metadata_lv->status |= LV_NOSCAN; -- if (!lv_is_active(metadata_lv) && -- !activate_lv_local(cmd, metadata_lv)) { -- log_error("Aborting. Failed to activate thin metadata lv."); -- return 0; -- } -- if (!set_lv(cmd, metadata_lv, UINT64_C(0), 0)) { -- log_error("Aborting. Failed to wipe thin metadata lv."); -+ if (!deactivate_lv(cmd, metadata_lv)) { -+ log_error("Aborting. Failed to deactivate thin metadata lv."); - return 0; - } - -@@ -2462,6 +2456,16 @@ static int _lvconvert_thinpool(struct cmd_context *cmd, - &lp->thin_chunk_size_calc_policy, &lp->chunk_size, - &lp->discards, &lp->poolmetadata_size, &lp->zero)) - return_0; -+ -+ metadata_lv->status |= LV_TEMPORARY; -+ if (!activate_lv_local(cmd, metadata_lv)) { -+ log_error("Aborting. Failed to activate thin metadata lv."); -+ return 0; -+ } -+ if (!set_lv(cmd, metadata_lv, UINT64_C(0), 0)) { -+ log_error("Aborting. Failed to wipe thin metadata lv."); -+ return 0; -+ } - } - - if (!deactivate_lv(cmd, metadata_lv)) { -diff --git a/udev/11-dm-lvm.rules.in b/udev/11-dm-lvm.rules.in -index 5032280..9ca0375 100644 ---- a/udev/11-dm-lvm.rules.in -+++ b/udev/11-dm-lvm.rules.in -@@ -32,7 +32,7 @@ IMPORT{program}="(DM_EXEC)/dmsetup splitname --nameprefixes --noheadings --rows - # uevent that follows for this LV, even an artificially generated one). - ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_NOSCAN}="1", ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" - ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", IMPORT{db}="DM_NOSCAN", IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD" --ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}", \ -+ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", ENV{DM_NOSCAN}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}", \ - ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG_OLD}="", ENV{DM_NOSCAN}="" - - ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}=="1", GOTO="lvm_end" -diff --git a/udev/69-dm-lvm-metad.rules.in b/udev/69-dm-lvm-metad.rules.in -index 3e303b1..5b15b6f 100644 ---- a/udev/69-dm-lvm-metad.rules.in -+++ b/udev/69-dm-lvm-metad.rules.in -@@ -17,7 +17,7 @@ - SUBSYSTEM!="block", GOTO="lvm_end" - (LVM_EXEC_RULE) - --ENV{DM_NOSCAN}=="1", GOTO="lvm_end" -+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="lvm_end" - - # If the PV label got lost, inform lvmetad immediately. - # Detect the lost PV label by comparing previous ID_FS_TYPE value with current one. -@@ -51,6 +51,7 @@ KERNEL!="md[0-9]*", GOTO="next" - IMPORT{db}="LVM_MD_PV_ACTIVATED" - ACTION=="add", ENV{LVM_MD_PV_ACTIVATED}=="1", GOTO="lvm_scan" - ACTION=="change", ENV{LVM_MD_PV_ACTIVATED}!="1", TEST=="md/array_state", ENV{LVM_MD_PV_ACTIVATED}="1", GOTO="lvm_scan" -+ACTION=="add", KERNEL=="md[0-9]*p[0-9]*", GOTO="lvm_scan" - GOTO="lvm_end" - - # Loop device: diff --git a/lvm2.spec b/lvm2.spec index 8a199b4..d4741b5 100644 --- a/lvm2.spec +++ b/lvm2.spec @@ -1,4 +1,4 @@ -%define device_mapper_version 1.02.82 +%define device_mapper_version 1.02.83 %define enable_thin 1 %define enable_lvmetad 1 @@ -36,16 +36,14 @@ Summary: Userland logical volume management tools Name: lvm2 -Version: 2.02.103 -Release: 3%{?dist} +Version: 2.02.104 +Release: 1%{?dist} License: GPLv2 Group: System Environment/Base URL: http://sources.redhat.com/lvm2 Source0: ftp://sources.redhat.com/pub/lvm2/releases/LVM2.%{version}.tgz Patch0: lvm2-set-default-preferred_names.patch Patch1: lvm2-enable-lvmetad-by-default.patch -Patch2: lvm2-2_02_104-additional-fixes-from-v104.patch -Patch3: lvm2-2_02_104-additional-udev-fixes-from-v104.patch BuildRequires: libselinux-devel >= %{libselinux_version}, libsepol-devel BuildRequires: ncurses-devel @@ -82,8 +80,6 @@ or more physical volumes and creating one or more logical volumes %setup -q -n LVM2.%{version} %patch0 -p1 -b .preferred_names %patch1 -p1 -b .enable_lvmetad -%patch2 -p1 -b .v104 -%patch3 -p1 -b .v104_udev %build %define _default_pid_dir /run @@ -581,6 +577,21 @@ the device-mapper event library. %{_libdir}/pkgconfig/devmapper-event.pc %changelog +* Thu Nov 14 2013 Peter Rajnoha - 2.02.104-1 +- Workaround VG refresh race during autoactivation by retrying the refresh. +- Handle failures in temporary mirror used when adding images to mirrors. +- Fix and improve logic for implicitely exclusive activations. +- Return success when LV cannot be activated because of volume_list filter. +- Return proper error state for remote exclusive activation. +- Fix clvmd message verification to not reject REMOTE flag. (2.02.100) +- Compare equality of double values with DBL_EPSILON predefined constant. +- Use additional gcc warning flags by default. +- Add ignore_lvm_mirrors to config file to read/ignore labels on mirrors. +- Use #ifdef __linux__ instead of linux throughout. +- Consistently report on stderr when device is not found for dmsetup info. +- Skip race errors when non-udev dmsetup build runs on udev-enabled system. +- Skip error message when holders are not present in sysfs. + * Wed Oct 30 2013 Peter Rajnoha - 2.02.103-3 - Fix missing lvmetad scan for PVs found on MD partitions. - Respect DM_UDEV_DISABLE_OTHER_RULES_FLAG in lvmetad udev rules. diff --git a/sources b/sources index c3e5512..b589796 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -e427e3494aaf86da2d363f344deb3837 LVM2.2.02.103.tgz +3d82cdb63259b4386c0cc308b4e1f221 LVM2.2.02.104.tgz diff --git a/upstream b/upstream index 6e3a375..b68c657 100644 --- a/upstream +++ b/upstream @@ -1 +1 @@ -LVM2.2.02.103.tgz +LVM2.2.02.104.tgz