2213 lines
81 KiB
Diff
2213 lines
81 KiB
Diff
commit 11388698bad4336c156b11f8e1f51b664b34f57c
|
|
Author: Peter Rajnoha <prajnoha@redhat.com>
|
|
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 <device>... if unable to umount/deactivate.
|
|
+ Add dev-block-<major>:<minor>.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 <dirent.h>
|
|
|
|
#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 <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
-#ifdef linux
|
|
+#ifdef __linux__
|
|
# include <linux/types.h>
|
|
#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 <sys/mman.h>
|
|
+#include <pthread.h>
|
|
|
|
-/* 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)/$(<F)
|