mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-07 15:33:21 +03:00
Compare commits
18 Commits
dev-mcsont
...
dev-dct-re
Author | SHA1 | Date | |
---|---|---|---|
|
adcdc20a67 | ||
|
dbd2e3855c | ||
|
22c55786d9 | ||
|
a02cda4e70 | ||
|
c36d9a73ac | ||
|
77c8e031af | ||
|
92534a31eb | ||
|
b1ceee55a6 | ||
|
4de9e82b75 | ||
|
a3601b4004 | ||
|
21f7dfe510 | ||
|
da39cf4a9e | ||
|
b536ae04d5 | ||
|
ce8d1ed130 | ||
|
a812f98c42 | ||
|
838ba5930c | ||
|
990c824c21 | ||
|
4eff1da46f |
@@ -1 +1 @@
|
||||
1.02.163-git (2019-06-10)
|
||||
1.02.155-git (2018-10-31)
|
||||
|
29
WHATS_NEW
29
WHATS_NEW
@@ -1,22 +1,5 @@
|
||||
Version 2.03.05 -
|
||||
================================
|
||||
Fix command definition for pvchange -a.
|
||||
Add vgck --updatemetadata command that will repair metadata problems.
|
||||
Improve VG reading to work if one good copy of metadata is found.
|
||||
Report/display/scan commands that read VGs will no longer write/repair.
|
||||
Move metadata repairs from VG reading to VG writing.
|
||||
Add config setting md_component_checks to control MD component checks.
|
||||
Add end of device MD component checks when dev has no udev info.
|
||||
|
||||
Version 2.03.04 - 10th June 2019
|
||||
================================
|
||||
Remove unused_duplicate_devs from cmd causing segfault in dmeventd.
|
||||
|
||||
Version 2.03.03 - 07th June 2019
|
||||
================================
|
||||
Report no_discard_passdown for cache LVs with lvs -o+kernel_discards.
|
||||
Add pvck --dump option to extract metadata.
|
||||
Fix signal delivery checking race in libdaemon (lvmetad).
|
||||
Version 2.03.02 -
|
||||
===================================
|
||||
Add missing Before=shutdown.target to LVM2 services to fix shutdown ordering.
|
||||
Skip autoactivation for a PV when PV size does not match device size.
|
||||
Remove first-pvscan-initialization which should no longer be needed.
|
||||
@@ -49,14 +32,10 @@ Version 2.03.03 - 07th June 2019
|
||||
Fix missing unlock on lvm2 dmeventd plugin error path initialization.
|
||||
Improve Makefile dependency tracking.
|
||||
Move VDO support towards V2 target (6.2) support.
|
||||
|
||||
Version 2.03.02 - 18th December 2018
|
||||
====================================
|
||||
Fix missing proper initialization of pv_list struct when adding pv.
|
||||
Fix (de)activation of RaidLVs with visible SubLVs.
|
||||
Prohibit mirrored 'mirror' log via lvcreate and lvconvert.
|
||||
Fix (de)activation of RaidLVs with visible SubLVs
|
||||
Prohibit mirrored 'mirror' log via lvcreate and lvconvert
|
||||
Use sync io if async io_setup fails, or use_aio=0 is set in config.
|
||||
Fix more issues reported by coverity scan.
|
||||
|
||||
Version 2.03.01 - 31st October 2018
|
||||
===================================
|
||||
|
15
WHATS_NEW_DM
15
WHATS_NEW_DM
@@ -1,21 +1,10 @@
|
||||
Version 1.02.163 -
|
||||
=================================
|
||||
|
||||
Version 1.02.161 - 10th June 2019
|
||||
=================================
|
||||
|
||||
Version 1.02.159 - 07th June 2019
|
||||
=================================
|
||||
Parsing of cache status understand no_discard_passdown.
|
||||
Version 1.02.155 -
|
||||
====================================
|
||||
Ensure migration_threshold for cache is at least 8 chunks.
|
||||
|
||||
Version 1.02.155 - 18th December 2018
|
||||
=====================================
|
||||
Include correct internal header inside libdm list.c.
|
||||
Enhance ioctl flattening and add parameters only when needed.
|
||||
Add DM_DEVICE_ARM_POLL for API completness matching kernel.
|
||||
Do not add parameters for RESUME with DM_DEVICE_CREATE dm task.
|
||||
Fix dmstats report printing no output.
|
||||
|
||||
Version 1.02.153 - 31st October 2018
|
||||
====================================
|
||||
|
@@ -88,22 +88,6 @@ devices {
|
||||
#
|
||||
external_device_info_source = "none"
|
||||
|
||||
# Configuration option devices/hints.
|
||||
# Use a local file to remember which devices have PVs on them.
|
||||
# Some commands will use this as an optimization to reduce device
|
||||
# scanning, and will only scan the listed PVs. Removing the hint file
|
||||
# will cause lvm to generate a new one. Disable hints if PVs will
|
||||
# be copied onto devices using non-lvm commands, like dd.
|
||||
#
|
||||
# Accepted values:
|
||||
# all
|
||||
# Use all hints.
|
||||
# none
|
||||
# Use no hints.
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# hints = "all"
|
||||
|
||||
# Configuration option devices/preferred_names.
|
||||
# Select which path name to display for a block device.
|
||||
# If multiple path names exist for a block device, and LVM needs to
|
||||
@@ -183,52 +167,17 @@ devices {
|
||||
sysfs_scan = 1
|
||||
|
||||
# Configuration option devices/scan_lvs.
|
||||
# Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.
|
||||
# When 1, LVM will detect PVs layered on LVs, and caution must be
|
||||
# taken to avoid a host accessing a layered VG that may not belong
|
||||
# to it, e.g. from a guest image. This generally requires excluding
|
||||
# the LVs with device filters. Also, when this setting is enabled,
|
||||
# every LVM command will scan every active LV on the system (unless
|
||||
# filtered), which can cause performance problems on systems with
|
||||
# many active LVs. When this setting is 0, LVM will not detect or
|
||||
# use PVs that exist on LVs, and will not allow a PV to be created on
|
||||
# an LV. The LVs are ignored using a built in device filter that
|
||||
# identifies and excludes LVs.
|
||||
scan_lvs = 0
|
||||
# Scan LVM LVs for layered PVs.
|
||||
scan_lvs = 1
|
||||
|
||||
# Configuration option devices/multipath_component_detection.
|
||||
# Ignore devices that are components of DM multipath devices.
|
||||
multipath_component_detection = 1
|
||||
|
||||
# Configuration option devices/md_component_detection.
|
||||
# Enable detection and exclusion of MD component devices.
|
||||
# An MD component device is a block device that MD uses as part
|
||||
# of a software RAID virtual device. When an LVM PV is created
|
||||
# on an MD device, LVM must only use the top level MD device as
|
||||
# the PV, and should ignore the underlying component devices.
|
||||
# In cases where the MD superblock is located at the end of the
|
||||
# component devices, it is more difficult for LVM to consistently
|
||||
# identify an MD component, see the md_component_checks setting.
|
||||
# Ignore devices that are components of software RAID (md) devices.
|
||||
md_component_detection = 1
|
||||
|
||||
# Configuration option devices/md_component_checks.
|
||||
# The checks LVM should use to detect MD component devices.
|
||||
# MD component devices are block devices used by MD software RAID.
|
||||
#
|
||||
# Accepted values:
|
||||
# auto
|
||||
# LVM will skip scanning the end of devices when it has other
|
||||
# indications that the device is not an MD component.
|
||||
# start
|
||||
# LVM will only scan the start of devices for MD superblocks.
|
||||
# This does not incur extra I/O by LVM.
|
||||
# full
|
||||
# LVM will scan the start and end of devices for MD superblocks.
|
||||
# This requires an extra read at the end of devices.
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# md_component_checks = "auto"
|
||||
|
||||
# Configuration option devices/fw_raid_component_detection.
|
||||
# Ignore devices that are components of firmware RAID devices.
|
||||
# LVM must use an external_device_info_source other than none for this
|
||||
@@ -771,8 +720,7 @@ log {
|
||||
|
||||
# Configuration option log/indent.
|
||||
# Indent messages according to their severity.
|
||||
# This configuration option has an automatic default value.
|
||||
# indent = 0
|
||||
indent = 1
|
||||
|
||||
# Configuration option log/command_names.
|
||||
# Display the command name on each line of output.
|
||||
@@ -798,20 +746,6 @@ log {
|
||||
# available: memory, devices, io, activation, allocation,
|
||||
# metadata, cache, locking, lvmpolld. Use "all" to see everything.
|
||||
debug_classes = [ "memory", "devices", "io", "activation", "allocation", "metadata", "cache", "locking", "lvmpolld", "dbus" ]
|
||||
|
||||
# Configuration option log/debug_file_fields.
|
||||
# The fields included in debug output written to log file.
|
||||
# Use "all" to include everything (the default).
|
||||
# This configuration option is advanced.
|
||||
# This configuration option has an automatic default value.
|
||||
# debug_file_fields = [ "time", "command", "fileline", "message" ]
|
||||
|
||||
# Configuration option log/debug_output_fields.
|
||||
# The fields included in debug output written to stderr.
|
||||
# Use "all" to include everything (the default).
|
||||
# This configuration option is advanced.
|
||||
# This configuration option has an automatic default value.
|
||||
# debug_output_fields = [ "time", "command", "fileline", "message" ]
|
||||
}
|
||||
|
||||
# Configuration section backup.
|
||||
@@ -1240,16 +1174,6 @@ global {
|
||||
# When enabled, an LVM command that changes PVs, changes VG metadata,
|
||||
# or changes the activation state of an LV will send a notification.
|
||||
notify_dbus = 1
|
||||
|
||||
# Configuration option global/io_memory_size.
|
||||
# The amount of memory in KiB that LVM allocates to perform disk io.
|
||||
# LVM performance may benefit from more io memory when there are many
|
||||
# disks or VG metadata is large. Increasing this size may be necessary
|
||||
# when a single copy of VG metadata is larger than the current setting.
|
||||
# This value should usually not be decreased from the default; setting
|
||||
# it too low can result in lvm failing to read VGs.
|
||||
# This configuration option has an automatic default value.
|
||||
# io_memory_size = 8192
|
||||
}
|
||||
|
||||
# Configuration section activation.
|
||||
|
107
configure
vendored
107
configure
vendored
@@ -742,7 +742,6 @@ CLDNOWHOLEARCHIVE
|
||||
CLDFLAGS
|
||||
CACHE
|
||||
BUILD_DMFILEMAPD
|
||||
BUILD_LOCKDDLM_CONTROL
|
||||
BUILD_LOCKDDLM
|
||||
BUILD_LOCKDSANLOCK
|
||||
BUILD_LVMLOCKD
|
||||
@@ -772,8 +771,6 @@ BLKID_LIBS
|
||||
BLKID_CFLAGS
|
||||
NOTIFY_DBUS_LIBS
|
||||
NOTIFY_DBUS_CFLAGS
|
||||
LOCKD_DLM_CONTROL_LIBS
|
||||
LOCKD_DLM_CONTROL_CFLAGS
|
||||
LOCKD_DLM_LIBS
|
||||
LOCKD_DLM_CFLAGS
|
||||
LOCKD_SANLOCK_LIBS
|
||||
@@ -935,7 +932,6 @@ enable_devmapper
|
||||
enable_lvmpolld
|
||||
enable_lvmlockd_sanlock
|
||||
enable_lvmlockd_dlm
|
||||
enable_lvmlockd_dlmcontrol
|
||||
enable_use_lvmlockd
|
||||
with_lvmlockd_pidfile
|
||||
enable_use_lvmpolld
|
||||
@@ -1004,8 +1000,6 @@ LOCKD_SANLOCK_CFLAGS
|
||||
LOCKD_SANLOCK_LIBS
|
||||
LOCKD_DLM_CFLAGS
|
||||
LOCKD_DLM_LIBS
|
||||
LOCKD_DLM_CONTROL_CFLAGS
|
||||
LOCKD_DLM_CONTROL_LIBS
|
||||
NOTIFY_DBUS_CFLAGS
|
||||
NOTIFY_DBUS_LIBS
|
||||
BLKID_CFLAGS
|
||||
@@ -1649,8 +1643,6 @@ Optional Features:
|
||||
--enable-lvmlockd-sanlock
|
||||
enable the LVM lock daemon using sanlock
|
||||
--enable-lvmlockd-dlm enable the LVM lock daemon using dlm
|
||||
--enable-lvmlockd-dlmcontrol
|
||||
enable lvmlockd remote refresh using libdlmcontrol
|
||||
--disable-use-lvmlockd disable usage of LVM lock daemon
|
||||
--disable-use-lvmpolld disable usage of LVM Poll Daemon
|
||||
--enable-dmfilemapd enable the dmstats filemap daemon
|
||||
@@ -1796,10 +1788,6 @@ Some influential environment variables:
|
||||
C compiler flags for LOCKD_DLM, overriding pkg-config
|
||||
LOCKD_DLM_LIBS
|
||||
linker flags for LOCKD_DLM, overriding pkg-config
|
||||
LOCKD_DLM_CONTROL_CFLAGS
|
||||
C compiler flags for LOCKD_DLM_CONTROL, overriding pkg-config
|
||||
LOCKD_DLM_CONTROL_LIBS
|
||||
linker flags for LOCKD_DLM_CONTROL, overriding pkg-config
|
||||
NOTIFY_DBUS_CFLAGS
|
||||
C compiler flags for NOTIFY_DBUS, overriding pkg-config
|
||||
NOTIFY_DBUS_LIBS
|
||||
@@ -3089,7 +3077,6 @@ case "$host_os" in
|
||||
BUILD_LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
LOCKDDLM=no
|
||||
LOCKDDLM_CONTROL=no
|
||||
ODIRECT=yes
|
||||
DM_IOCTLS=yes
|
||||
SELINUX=yes
|
||||
@@ -6647,7 +6634,7 @@ $as_echo "#define _REENTRANT 1" >>confdefs.h
|
||||
|
||||
################################################################################
|
||||
for ac_func in ftruncate gethostname getpagesize gettimeofday localtime_r \
|
||||
memchr memset mkdir mkfifo munmap nl_langinfo pselect realpath rmdir setenv \
|
||||
memchr memset mkdir mkfifo munmap nl_langinfo realpath rmdir setenv \
|
||||
setlocale strcasecmp strchr strcspn strdup strerror strncasecmp strndup \
|
||||
strrchr strspn strstr strtol strtoul uname
|
||||
do :
|
||||
@@ -10971,97 +10958,6 @@ $as_echo "#define LOCKDDLM_SUPPORT 1" >>confdefs.h
|
||||
BUILD_LVMLOCKD=yes
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockddlmcontrol" >&5
|
||||
$as_echo_n "checking whether to build lvmlockddlmcontrol... " >&6; }
|
||||
# Check whether --enable-lvmlockd-dlmcontrol was given.
|
||||
if test "${enable_lvmlockd_dlmcontrol+set}" = set; then :
|
||||
enableval=$enable_lvmlockd_dlmcontrol; LOCKDDLM_CONTROL=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LOCKDDLM_CONTROL" >&5
|
||||
$as_echo "$LOCKDDLM_CONTROL" >&6; }
|
||||
|
||||
BUILD_LOCKDDLM_CONTROL=$LOCKDDLM_CONTROL
|
||||
|
||||
if test "$BUILD_LOCKDDLM_CONTROL" = yes; then
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LOCKD_DLM_CONTROL" >&5
|
||||
$as_echo_n "checking for LOCKD_DLM_CONTROL... " >&6; }
|
||||
|
||||
if test -n "$LOCKD_DLM_CONTROL_CFLAGS"; then
|
||||
pkg_cv_LOCKD_DLM_CONTROL_CFLAGS="$LOCKD_DLM_CONTROL_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdlmcontrol >= 3.2\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libdlmcontrol >= 3.2") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LOCKD_DLM_CONTROL_CFLAGS=`$PKG_CONFIG --cflags "libdlmcontrol >= 3.2" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$LOCKD_DLM_CONTROL_LIBS"; then
|
||||
pkg_cv_LOCKD_DLM_CONTROL_LIBS="$LOCKD_DLM_CONTROL_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdlmcontrol >= 3.2\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libdlmcontrol >= 3.2") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LOCKD_DLM_CONTROL_LIBS=`$PKG_CONFIG --libs "libdlmcontrol >= 3.2" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
LOCKD_DLM_CONTROL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libdlmcontrol >= 3.2" 2>&1`
|
||||
else
|
||||
LOCKD_DLM_CONTROL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libdlmcontrol >= 3.2" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$LOCKD_DLM_CONTROL_PKG_ERRORS" >&5
|
||||
|
||||
$bailout
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
$bailout
|
||||
else
|
||||
LOCKD_DLM_CONTROL_CFLAGS=$pkg_cv_LOCKD_DLM_CONTROL_CFLAGS
|
||||
LOCKD_DLM_CONTROL_LIBS=$pkg_cv_LOCKD_DLM_CONTROL_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
HAVE_LOCKD_DLM_CONTROL=yes
|
||||
fi
|
||||
|
||||
$as_echo "#define LOCKDDLM_CONTROL_SUPPORT 1" >>confdefs.h
|
||||
|
||||
BUILD_LVMLOCKD=yes
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockd" >&5
|
||||
$as_echo_n "checking whether to build lvmlockd... " >&6; }
|
||||
@@ -13888,7 +13784,6 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
|
@@ -153,7 +153,7 @@ AC_DEFINE([_REENTRANT], 1, [Define to use re-entrant thread safe versions])
|
||||
################################################################################
|
||||
dnl -- Check for functions
|
||||
AC_CHECK_FUNCS([ftruncate gethostname getpagesize gettimeofday localtime_r \
|
||||
memchr memset mkdir mkfifo munmap nl_langinfo pselect realpath rmdir setenv \
|
||||
memchr memset mkdir mkfifo munmap nl_langinfo realpath rmdir setenv \
|
||||
setlocale strcasecmp strchr strcspn strdup strerror strncasecmp strndup \
|
||||
strrchr strspn strstr strtol strtoul uname], , [AC_MSG_ERROR(bailing out)])
|
||||
AC_FUNC_ALLOCA
|
||||
|
@@ -2230,7 +2230,7 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
struct action *act_op_free = NULL;
|
||||
struct list_head tmp_act;
|
||||
struct list_head act_close;
|
||||
char tmp_name[MAX_NAME+5];
|
||||
char tmp_name[MAX_NAME+1];
|
||||
int free_vg = 0;
|
||||
int drop_vg = 0;
|
||||
int error = 0;
|
||||
@@ -2624,10 +2624,8 @@ out_act:
|
||||
* blank or fill it with garbage, but instead set it to REM:<name>
|
||||
* to make it easier to follow progress of freeing is via log_debug.
|
||||
*/
|
||||
memset(tmp_name, 0, sizeof(tmp_name));
|
||||
memcpy(tmp_name, "REM:", 4);
|
||||
strncpy(tmp_name+4, ls->name, sizeof(tmp_name)-4);
|
||||
memcpy(ls->name, tmp_name, sizeof(ls->name));
|
||||
dm_strncpy(tmp_name, ls->name, sizeof(tmp_name));
|
||||
snprintf(ls->name, sizeof(ls->name), "REM:%s", tmp_name);
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
|
||||
/* worker_thread will join this thread, and free the ls */
|
||||
|
@@ -128,18 +128,16 @@ static int read_cluster_name(char *clustername)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_VERSION 16
|
||||
|
||||
int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
||||
{
|
||||
char clustername[MAX_ARGS+1];
|
||||
char lock_args_version[MAX_VERSION+1];
|
||||
char lock_args_version[MAX_ARGS+1];
|
||||
int rv;
|
||||
|
||||
memset(clustername, 0, sizeof(clustername));
|
||||
memset(lock_args_version, 0, sizeof(lock_args_version));
|
||||
|
||||
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
|
||||
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
|
||||
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
|
||||
|
||||
rv = read_cluster_name(clustername);
|
||||
@@ -151,9 +149,7 @@ int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
||||
return -EARGS;
|
||||
}
|
||||
|
||||
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, clustername);
|
||||
if (rv >= MAX_ARGS)
|
||||
log_debug("init_vg_dlm vg_args may be too long %d %s", rv, vg_args);
|
||||
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, clustername);
|
||||
rv = 0;
|
||||
|
||||
log_debug("init_vg_dlm done %s vg_args %s", ls_name, vg_args);
|
||||
|
@@ -500,15 +500,13 @@ static int get_sizes_lockspace(char *path, int *sector_size, int *align_size)
|
||||
* version and lv name, and returns the real lock_args in vg_args.
|
||||
*/
|
||||
|
||||
#define MAX_VERSION 16
|
||||
|
||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
||||
{
|
||||
struct sanlk_lockspace ss;
|
||||
struct sanlk_resourced rd;
|
||||
struct sanlk_disk disk;
|
||||
char lock_lv_name[MAX_ARGS+1];
|
||||
char lock_args_version[MAX_VERSION+1];
|
||||
char lock_args_version[MAX_ARGS+1];
|
||||
const char *gl_name = NULL;
|
||||
uint32_t daemon_version;
|
||||
uint32_t daemon_proto;
|
||||
@@ -528,7 +526,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
||||
return -EARGS;
|
||||
}
|
||||
|
||||
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
|
||||
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
|
||||
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
|
||||
|
||||
/* see comment above about input vg_args being only lock_lv_name */
|
||||
@@ -545,9 +543,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
||||
if (daemon_test) {
|
||||
if (!gl_lsname_sanlock[0])
|
||||
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
|
||||
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
|
||||
if (rv >= MAX_ARGS)
|
||||
log_debug("init_vg_san vg_args may be too long %d %s", rv, vg_args);
|
||||
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -639,9 +635,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
||||
if (!strcmp(gl_name, R_NAME_GL))
|
||||
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
|
||||
|
||||
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
|
||||
if (rv >= MAX_ARGS)
|
||||
log_debug("init_vg_san vg_args may be too long %d %s", rv, vg_args);
|
||||
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
|
||||
|
||||
log_debug("S %s init_vg_san done vg_args %s", ls_name, vg_args);
|
||||
|
||||
@@ -698,7 +692,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
|
||||
{
|
||||
struct sanlk_resourced rd;
|
||||
char lock_lv_name[MAX_ARGS+1];
|
||||
char lock_args_version[MAX_VERSION+1];
|
||||
char lock_args_version[MAX_ARGS+1];
|
||||
uint64_t offset;
|
||||
int rv;
|
||||
|
||||
@@ -713,7 +707,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
|
||||
return rv;
|
||||
}
|
||||
|
||||
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
|
||||
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
|
||||
LV_LOCK_ARGS_MAJOR, LV_LOCK_ARGS_MINOR, LV_LOCK_ARGS_PATCH);
|
||||
|
||||
if (daemon_test) {
|
||||
|
@@ -915,7 +915,7 @@ int main(int argc, char *argv[])
|
||||
int option_index = 0;
|
||||
int client = 0, server = 0;
|
||||
unsigned action = ACTION_MAX;
|
||||
struct timespec timeout;
|
||||
struct timeval timeout;
|
||||
daemon_idle di = { .ptimeout = &timeout };
|
||||
struct lvmpolld_state ls = { .log_config = "" };
|
||||
daemon_state s = {
|
||||
|
@@ -903,7 +903,6 @@ int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
|
||||
#define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002
|
||||
#define DM_CACHE_FEATURE_PASSTHROUGH 0x00000004
|
||||
#define DM_CACHE_FEATURE_METADATA2 0x00000008 /* cache v1.10 */
|
||||
#define DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN 0x00000010
|
||||
|
||||
struct dm_config_node;
|
||||
/*
|
||||
|
@@ -51,8 +51,6 @@ struct parser {
|
||||
|
||||
struct dm_pool *mem;
|
||||
int no_dup_node_check; /* whether to disable dup node checking */
|
||||
const char *key; /* last obtained key */
|
||||
unsigned ignored_creation_time;
|
||||
};
|
||||
|
||||
struct config_output {
|
||||
@@ -178,7 +176,7 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
|
||||
/* TODO? if (start == end) return 1; */
|
||||
|
||||
struct parser *p;
|
||||
if (!(p = dm_pool_zalloc(cft->mem, sizeof(*p))))
|
||||
if (!(p = dm_pool_alloc(cft->mem, sizeof(*p))))
|
||||
return_0;
|
||||
|
||||
p->mem = cft->mem;
|
||||
@@ -617,7 +615,6 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
|
||||
match(TOK_SECTION_E);
|
||||
} else {
|
||||
match(TOK_EQ);
|
||||
p->key = root->key;
|
||||
if (!(value = _value(p)))
|
||||
return_NULL;
|
||||
if (root->v)
|
||||
@@ -685,17 +682,8 @@ static struct dm_config_value *_type(struct parser *p)
|
||||
errno = 0;
|
||||
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
|
||||
if (errno) {
|
||||
if (errno == ERANGE && p->key &&
|
||||
strcmp("creation_time", p->key) == 0) {
|
||||
/* Due to a bug in some older 32bit builds (<2.02.169),
|
||||
* lvm was able to produce invalid creation_time string */
|
||||
v->v.i = 1527120000; /* Pick 2018-05-24 day instead */
|
||||
if (!p->ignored_creation_time++)
|
||||
log_warn("WARNING: Invalid creation_time found in metadata (repaired with next metadata update).");
|
||||
} else {
|
||||
log_error("Failed to read int token.");
|
||||
return NULL;
|
||||
}
|
||||
log_error("Failed to read int token.");
|
||||
return NULL;
|
||||
}
|
||||
match(TOK_INT);
|
||||
break;
|
||||
|
@@ -296,8 +296,6 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
|
||||
s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
|
||||
else if (!strncmp(p, "metadata2 ", 10))
|
||||
s->feature_flags |= DM_CACHE_FEATURE_METADATA2;
|
||||
else if (!strncmp(p, "no_discard_passdown ", 20))
|
||||
s->feature_flags |= DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN;
|
||||
else
|
||||
log_error("Unknown feature in status: %s", params);
|
||||
|
||||
|
@@ -292,9 +292,6 @@
|
||||
/* Define to 1 if you have the <paths.h> header file. */
|
||||
#undef HAVE_PATHS_H
|
||||
|
||||
/* Define to 1 if you have the `pselect' function. */
|
||||
#undef HAVE_PSELECT
|
||||
|
||||
/* Define to 1 if the system has the type `ptrdiff_t'. */
|
||||
#undef HAVE_PTRDIFF_T
|
||||
|
||||
@@ -534,9 +531,6 @@
|
||||
/* Locale-dependent data */
|
||||
#undef LOCALEDIR
|
||||
|
||||
/* Define to 1 to include code that uses lvmlockd dlm control option. */
|
||||
#undef LOCKDDLM_CONTROL_SUPPORT
|
||||
|
||||
/* Define to 1 to include code that uses lvmlockd dlm option. */
|
||||
#undef LOCKDDLM_SUPPORT
|
||||
|
||||
|
@@ -70,6 +70,7 @@ SOURCES =\
|
||||
metadata/lv_manip.c \
|
||||
metadata/merge.c \
|
||||
metadata/metadata.c \
|
||||
metadata/read.c \
|
||||
metadata/mirror.c \
|
||||
metadata/pool_manip.c \
|
||||
metadata/pv.c \
|
||||
|
315
lib/cache/lvmcache.c
vendored
315
lib/cache/lvmcache.c
vendored
@@ -40,12 +40,12 @@ struct lvmcache_info {
|
||||
uint32_t ext_version; /* Extension version */
|
||||
uint32_t ext_flags; /* Extension flags */
|
||||
uint32_t status;
|
||||
bool mda1_bad; /* label scan found bad metadata in mda1 */
|
||||
bool mda2_bad; /* label scan found bad metadata in mda2 */
|
||||
bool summary_seqno_mismatch; /* two mdas on this dev has mismatching metadata */
|
||||
int summary_seqno; /* vg seqno found on this dev during scan */
|
||||
int mda1_seqno;
|
||||
int mda2_seqno;
|
||||
unsigned summary_seqno_mismatch:1; /* two mdas on this dev has mismatching metadata */
|
||||
unsigned mda1_bad:1; /* label scan found bad metadata in mda1 */
|
||||
unsigned mda2_bad:1; /* label scan found bad metadata in mda2 */
|
||||
};
|
||||
|
||||
/* One per VG */
|
||||
@@ -65,7 +65,7 @@ struct lvmcache_vginfo {
|
||||
uint32_t mda_checksum;
|
||||
size_t mda_size;
|
||||
int seqno;
|
||||
bool scan_summary_mismatch; /* vgsummary from devs had mismatching seqno or checksum */
|
||||
int scan_summary_mismatch; /* vgsummary from devs had mismatching seqno or checksum */
|
||||
};
|
||||
|
||||
static struct dm_hash_table *_pvid_hash = NULL;
|
||||
@@ -74,7 +74,7 @@ static struct dm_hash_table *_vgname_hash = NULL;
|
||||
static DM_LIST_INIT(_vginfos);
|
||||
static DM_LIST_INIT(_found_duplicate_devs);
|
||||
static DM_LIST_INIT(_unused_duplicate_devs);
|
||||
static DM_LIST_INIT(_prev_unused_duplicate_devs);
|
||||
static int _scanning_in_progress = 0;
|
||||
static int _vgs_locked = 0;
|
||||
static int _found_duplicate_pvs = 0; /* If we never see a duplicate PV we can skip checking for them later. */
|
||||
static int _found_duplicate_vgnames = 0;
|
||||
@@ -90,7 +90,6 @@ int lvmcache_init(struct cmd_context *cmd)
|
||||
dm_list_init(&_vginfos);
|
||||
dm_list_init(&_found_duplicate_devs);
|
||||
dm_list_init(&_unused_duplicate_devs);
|
||||
dm_list_init(&_prev_unused_duplicate_devs);
|
||||
|
||||
if (!(_vgname_hash = dm_hash_create(128)))
|
||||
return 0;
|
||||
@@ -106,17 +105,23 @@ int lvmcache_init(struct cmd_context *cmd)
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute__((unused)))
|
||||
{
|
||||
_vgs_locked++;
|
||||
if (strcmp(vgname, VG_GLOBAL))
|
||||
_vgs_locked++;
|
||||
}
|
||||
|
||||
void lvmcache_unlock_vgname(const char *vgname)
|
||||
{
|
||||
/* FIXME Do this per-VG */
|
||||
if (!--_vgs_locked) {
|
||||
if (strcmp(vgname, VG_GLOBAL) && !--_vgs_locked) {
|
||||
dev_size_seqno_inc(); /* invalidate all cached dev sizes */
|
||||
}
|
||||
}
|
||||
|
||||
int lvmcache_vgs_locked(void)
|
||||
{
|
||||
return _vgs_locked;
|
||||
}
|
||||
|
||||
/*
|
||||
* When lvmcache sees a duplicate PV, this is set.
|
||||
* process_each_pv() can avoid searching for duplicates
|
||||
@@ -178,37 +183,36 @@ static void _destroy_duplicate_device_list(struct dm_list *head)
|
||||
dm_list_init(head);
|
||||
}
|
||||
|
||||
bool lvmcache_has_bad_metadata(struct device *dev)
|
||||
int lvmcache_has_bad_metadata(struct device *dev)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) {
|
||||
/* shouldn't happen */
|
||||
log_error("No lvmcache info for checking bad metadata on %s", dev_name(dev));
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info->mda1_bad || info->mda2_bad)
|
||||
return true;
|
||||
return false;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda)
|
||||
{
|
||||
if (mda->mda_num == 1)
|
||||
info->mda1_bad = true;
|
||||
info->mda1_bad = 1;
|
||||
else if (mda->mda_num == 2)
|
||||
info->mda2_bad = true;
|
||||
info->mda2_bad = 1;
|
||||
dm_list_add(&info->bad_mdas, &mda->list);
|
||||
}
|
||||
|
||||
void lvmcache_get_bad_mdas(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid,
|
||||
struct dm_list *bad_mda_list)
|
||||
struct dm_list *bad_mdas)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
struct mda_list *mdal;
|
||||
struct metadata_area *mda, *mda2;
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
|
||||
@@ -218,10 +222,8 @@ void lvmcache_get_bad_mdas(struct cmd_context *cmd,
|
||||
|
||||
dm_list_iterate_items(info, &vginfo->infos) {
|
||||
dm_list_iterate_items_safe(mda, mda2, &info->bad_mdas) {
|
||||
if (!(mdal = zalloc(sizeof(*mdal))))
|
||||
continue;
|
||||
mdal->mda = mda;
|
||||
dm_list_add(bad_mda_list, &mdal->list);
|
||||
dm_list_del(&mda->list);
|
||||
dm_list_add(bad_mdas, &mda->list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,6 +280,60 @@ struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname, const ch
|
||||
return vginfo;
|
||||
}
|
||||
|
||||
const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid,
|
||||
unsigned revalidate_labels)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
struct dm_list *devh, *tmp;
|
||||
struct dm_list devs;
|
||||
struct device_list *devl;
|
||||
char vgid_found[ID_LEN + 1] __attribute__((aligned(8)));
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this function is called repeatedly, only the first one needs to revalidate.
|
||||
*/
|
||||
if (!revalidate_labels)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* This function is normally called before reading metadata so
|
||||
* we check cached labels here. Unfortunately vginfo is volatile.
|
||||
*/
|
||||
dm_list_init(&devs);
|
||||
dm_list_iterate_items(info, &vginfo->infos) {
|
||||
if (!(devl = malloc(sizeof(*devl)))) {
|
||||
log_error("device_list element allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
devl->dev = info->dev;
|
||||
dm_list_add(&devs, &devl->list);
|
||||
}
|
||||
|
||||
memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
|
||||
|
||||
dm_list_iterate_safe(devh, tmp, &devs) {
|
||||
devl = dm_list_item(devh, struct device_list);
|
||||
label_read(devl->dev);
|
||||
dm_list_del(&devl->list);
|
||||
free(devl);
|
||||
}
|
||||
|
||||
/* If vginfo changed, caller needs to rescan */
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid_found)) ||
|
||||
strncmp(vginfo->vgid, vgid_found, ID_LEN))
|
||||
return NULL;
|
||||
|
||||
out:
|
||||
return vginfo->fmt;
|
||||
}
|
||||
|
||||
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
@@ -552,11 +608,8 @@ next:
|
||||
*/
|
||||
|
||||
if (!(info = lvmcache_info_from_pvid(alt->dev->pvid, NULL, 0))) {
|
||||
/*
|
||||
* This will happen if a duplicate dev has been dropped already,
|
||||
* e.g. it was found to be an md component.
|
||||
*/
|
||||
log_debug("PVID %s on duplicate device %s not found in cache.",
|
||||
/* This shouldn't happen */
|
||||
log_warn("WARNING: PV %s on duplicate device %s not found in cache.",
|
||||
alt->dev->pvid, dev_name(alt->dev));
|
||||
goto next;
|
||||
}
|
||||
@@ -583,14 +636,14 @@ next:
|
||||
|
||||
if (!prev_unchosen1 && !prev_unchosen2) {
|
||||
/*
|
||||
* The prev list saves the unchosen preference across
|
||||
* The cmd list saves the unchosen preference across
|
||||
* lvmcache_destroy. Sometimes a single command will
|
||||
* fill lvmcache, destroy it, and refill it, and we
|
||||
* want the same duplicate preference to be preserved
|
||||
* in each instance of lvmcache for a single command.
|
||||
*/
|
||||
prev_unchosen1 = dev_in_device_list(dev1, &_prev_unused_duplicate_devs);
|
||||
prev_unchosen2 = dev_in_device_list(dev2, &_prev_unused_duplicate_devs);
|
||||
prev_unchosen1 = dev_in_device_list(dev1, &cmd->unused_duplicate_devs);
|
||||
prev_unchosen2 = dev_in_device_list(dev2, &cmd->unused_duplicate_devs);
|
||||
}
|
||||
|
||||
dev1_major = MAJOR(dev1->dev);
|
||||
@@ -856,6 +909,12 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
|
||||
log_debug_cache("Finding VG info");
|
||||
|
||||
/* Avoid recursion when a PVID can't be found! */
|
||||
if (_scanning_in_progress)
|
||||
return 0;
|
||||
|
||||
_scanning_in_progress = 1;
|
||||
|
||||
/* FIXME: can this happen? */
|
||||
if (!cmd->filter) {
|
||||
log_error("label scan is missing filter");
|
||||
@@ -936,6 +995,8 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
_scanning_in_progress = 0;
|
||||
|
||||
dm_list_iterate_items(vginfo, &_vginfos) {
|
||||
if (is_orphan_vg(vginfo->vgname))
|
||||
continue;
|
||||
@@ -947,26 +1008,49 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
return r;
|
||||
}
|
||||
|
||||
int lvmcache_get_vgnameids(struct cmd_context *cmd,
|
||||
struct dm_list *vgnameids,
|
||||
const char *only_this_vgname,
|
||||
int include_internal)
|
||||
/*
|
||||
* lvmcache_label_scan() detects duplicates in the basic label_scan(), then
|
||||
* filters out some dups, and chooses preferred duplicates to use.
|
||||
*/
|
||||
|
||||
void lvmcache_pvscan_duplicate_check(struct cmd_context *cmd)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
/* Check if label_scan() detected any dups. */
|
||||
if (!_found_duplicate_pvs)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Once all the dups are identified, they are moved from the
|
||||
* "found" list to the "unused" list to sort out.
|
||||
*/
|
||||
dm_list_splice(&_unused_duplicate_devs, &_found_duplicate_devs);
|
||||
|
||||
/*
|
||||
* Remove items from the dups list that we know are the same
|
||||
* underlying dev, e.g. md components, that we want to just ignore.
|
||||
*/
|
||||
_filter_duplicate_devs(cmd);
|
||||
|
||||
/*
|
||||
* no more dups after ignoring some
|
||||
*/
|
||||
if (!_found_duplicate_pvs)
|
||||
return;
|
||||
|
||||
/* Duplicates are found where we would have to pick one. */
|
||||
|
||||
dm_list_iterate_items(devl, &_unused_duplicate_devs)
|
||||
log_warn("WARNING: found device with duplicate %s", dev_name(devl->dev));
|
||||
}
|
||||
|
||||
int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
|
||||
struct dm_list *vgnameids)
|
||||
{
|
||||
struct vgnameid_list *vgnl;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if (only_this_vgname) {
|
||||
if (!(vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl)))) {
|
||||
log_error("vgnameid_list allocation failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
vgnl->vg_name = dm_pool_strdup(cmd->mem, only_this_vgname);
|
||||
vgnl->vgid = NULL;
|
||||
dm_list_add(vgnameids, &vgnl->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!include_internal && is_orphan_vg(vginfo->vgname))
|
||||
continue;
|
||||
@@ -990,6 +1074,49 @@ int lvmcache_get_vgnameids(struct cmd_context *cmd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid)
|
||||
{
|
||||
struct dm_list *pvids;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(pvids = str_list_create(cmd->mem))) {
|
||||
log_error("pvids list allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
|
||||
return pvids;
|
||||
|
||||
dm_list_iterate_items(info, &vginfo->infos) {
|
||||
if (!str_list_add(cmd->mem, pvids,
|
||||
dm_pool_strdup(cmd->mem, info->dev->pvid))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return pvids;
|
||||
}
|
||||
|
||||
int lvmcache_get_vg_devs(struct cmd_context *cmd,
|
||||
struct lvmcache_vginfo *vginfo,
|
||||
struct dm_list *devs)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
struct device_list *devl;
|
||||
|
||||
dm_list_iterate_items(info, &vginfo->infos) {
|
||||
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
|
||||
return_0;
|
||||
|
||||
devl->dev = info->dev;
|
||||
dm_list_add(devs, &devl->list);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct device *_device_from_pvid(const struct id *pvid, uint64_t *label_sector)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
@@ -1476,11 +1603,11 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, struct lvmcache_vg
|
||||
|
||||
} else if (info->summary_seqno > vgsummary->seqno) {
|
||||
/* This mda has older metadata than the prev mda on this dev. */
|
||||
info->summary_seqno_mismatch = true;
|
||||
info->summary_seqno_mismatch = 1;
|
||||
|
||||
} else if (info->summary_seqno < vgsummary->seqno) {
|
||||
/* This mda has newer metadata than the prev mda on this dev. */
|
||||
info->summary_seqno_mismatch = true;
|
||||
info->summary_seqno_mismatch = 1;
|
||||
info->summary_seqno = vgsummary->seqno;
|
||||
}
|
||||
}
|
||||
@@ -1500,7 +1627,7 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, struct lvmcache_vg
|
||||
goto update_vginfo;
|
||||
|
||||
} else if (vgsummary->seqno < vginfo->seqno) {
|
||||
vginfo->scan_summary_mismatch = true;
|
||||
vginfo->scan_summary_mismatch = 1;
|
||||
|
||||
log_debug_cache("lvmcache %s mda%d VG %s older seqno %u checksum %x mda_size %zu",
|
||||
dev_name(info->dev), vgsummary->mda_num, vgname,
|
||||
@@ -1508,7 +1635,7 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, struct lvmcache_vg
|
||||
return 1;
|
||||
|
||||
} else if (vgsummary->seqno > vginfo->seqno) {
|
||||
vginfo->scan_summary_mismatch = true;
|
||||
vginfo->scan_summary_mismatch = 1;
|
||||
|
||||
/* Replace vginfo values with values from newer metadata. */
|
||||
vginfo->seqno = vgsummary->seqno;
|
||||
@@ -1536,7 +1663,7 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, struct lvmcache_vg
|
||||
vgname, dev_name(info->dev), vgsummary->mda_num,
|
||||
vgsummary->mda_checksum, vgsummary->mda_size,
|
||||
vginfo->mda_checksum, vginfo->mda_size);
|
||||
vginfo->scan_summary_mismatch = true;
|
||||
vginfo->scan_summary_mismatch = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1958,8 +2085,8 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
|
||||
dm_list_init(&_vginfos);
|
||||
|
||||
/*
|
||||
* Move the current _unused_duplicate_devs to _prev_unused_duplicate_devs
|
||||
* before destroying _unused_duplicate_devs.
|
||||
* Copy the current _unused_duplicate_devs into a cmd list before
|
||||
* destroying _unused_duplicate_devs.
|
||||
*
|
||||
* One command can init/populate/destroy lvmcache multiple times. Each
|
||||
* time it will encounter duplicates and choose the preferrred devs.
|
||||
@@ -1967,8 +2094,8 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
|
||||
* the unpreferred devs here so that _choose_preferred_devs can use
|
||||
* this to make the same choice each time.
|
||||
*/
|
||||
_destroy_duplicate_device_list(&_prev_unused_duplicate_devs);
|
||||
dm_list_splice(&_prev_unused_duplicate_devs, &_unused_duplicate_devs);
|
||||
dm_list_init(&cmd->unused_duplicate_devs);
|
||||
lvmcache_get_unused_duplicate_devs(cmd, &cmd->unused_duplicate_devs);
|
||||
_destroy_duplicate_device_list(&_unused_duplicate_devs);
|
||||
_destroy_duplicate_device_list(&_found_duplicate_devs); /* should be empty anyway */
|
||||
_found_duplicate_pvs = 0;
|
||||
@@ -2270,6 +2397,26 @@ uint32_t lvmcache_ext_flags(struct lvmcache_info *info) {
|
||||
return info->ext_flags;
|
||||
}
|
||||
|
||||
int lvmcache_is_orphan(struct lvmcache_info *info) {
|
||||
if (!info->vginfo)
|
||||
return 1; /* FIXME? */
|
||||
return is_orphan_vg(info->vginfo->vgname);
|
||||
}
|
||||
|
||||
int lvmcache_vgid_is_cached(const char *vgid) {
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
vginfo = lvmcache_vginfo_from_vgid(vgid);
|
||||
|
||||
if (!vginfo || !vginfo->vgname)
|
||||
return 0;
|
||||
|
||||
if (is_orphan_vg(vginfo->vgname))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info)
|
||||
{
|
||||
if (!info)
|
||||
@@ -2386,17 +2533,17 @@ int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const ch
|
||||
* lvmcache: info for dev5 is deleted, FIXME: use a defective state
|
||||
*/
|
||||
|
||||
bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid)
|
||||
int lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if (!vgname || !vgid)
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
if ((vginfo = lvmcache_vginfo_from_vgid(vgid)))
|
||||
return vginfo->scan_summary_mismatch;
|
||||
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint64_t _max_metadata_size;
|
||||
@@ -2425,70 +2572,40 @@ int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct metadata_area *lvmcache_get_mda(struct cmd_context *cmd,
|
||||
const char *vgname,
|
||||
struct device *dev,
|
||||
int use_mda_num)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
struct metadata_area *mda;
|
||||
|
||||
if (!use_mda_num)
|
||||
use_mda_num = 1;
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
|
||||
return NULL;
|
||||
|
||||
dm_list_iterate_items(info, &vginfo->infos) {
|
||||
if (info->dev != dev)
|
||||
continue;
|
||||
|
||||
dm_list_iterate_items(mda, &info->mdas) {
|
||||
if ((use_mda_num == 1) && (mda->status & MDA_PRIMARY))
|
||||
return mda;
|
||||
if ((use_mda_num == 2) && !(mda->status & MDA_PRIMARY))
|
||||
return mda;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is used by the metadata repair command to check if
|
||||
* the metadata on a dev needs repair because it's old.
|
||||
*/
|
||||
bool lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, const char *vgid, struct device *dev)
|
||||
int lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, const char *vgid, struct device *dev)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* shouldn't happen */
|
||||
if (!vgname || !vgid)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
/* shouldn't happen */
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgid(vgid)))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
/* shouldn't happen */
|
||||
if (!(info = lvmcache_info_from_pvid(dev->pvid, NULL, 0)))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
/* writing to a new PV */
|
||||
if (!info->summary_seqno)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
/* on same dev, one mda has newer metadata than the other */
|
||||
if (info->summary_seqno_mismatch)
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
/* one or both mdas on this dev has older metadata than another dev */
|
||||
if (vginfo->seqno > info->summary_seqno)
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lvmcache_get_outdated_devs(struct cmd_context *cmd,
|
||||
@@ -2519,7 +2636,7 @@ void lvmcache_del_outdated_devs(struct cmd_context *cmd,
|
||||
struct lvmcache_info *info, *info2;
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
|
||||
log_error(INTERNAL_ERROR "lvmcache_del_outdated_devs no vginfo");
|
||||
log_error(INTERNAL_ERROR "lvmcache_get_outdated_devs no vginfo");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2550,7 +2667,7 @@ void lvmcache_get_outdated_mdas(struct cmd_context *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
bool lvmcache_is_outdated_dev(struct cmd_context *cmd,
|
||||
int lvmcache_is_outdated_dev(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid,
|
||||
struct device *dev)
|
||||
{
|
||||
@@ -2559,13 +2676,13 @@ bool lvmcache_is_outdated_dev(struct cmd_context *cmd,
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
|
||||
log_error(INTERNAL_ERROR "lvmcache_get_outdated_mdas no vginfo");
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(info, &vginfo->outdated_infos) {
|
||||
if (info->dev == dev)
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
57
lib/cache/lvmcache.h
vendored
57
lib/cache/lvmcache.h
vendored
@@ -91,8 +91,12 @@ void lvmcache_lock_vgname(const char *vgname, int read_only);
|
||||
void lvmcache_unlock_vgname(const char *vgname);
|
||||
|
||||
/* Queries */
|
||||
const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd, const char *vgname, const char *vgid, unsigned revalidate_labels);
|
||||
int lvmcache_lookup_mda(struct lvmcache_vgsummary *vgsummary);
|
||||
|
||||
/* Decrement and test if there are still vg holders in vginfo. */
|
||||
int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
|
||||
|
||||
struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
|
||||
const char *vgid);
|
||||
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
|
||||
@@ -102,11 +106,14 @@ const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgnam
|
||||
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
|
||||
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
|
||||
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
|
||||
int lvmcache_vgs_locked(void);
|
||||
|
||||
int lvmcache_get_vgnameids(struct cmd_context *cmd,
|
||||
struct dm_list *vgnameids,
|
||||
const char *only_this_vgname,
|
||||
int include_internal);
|
||||
int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
|
||||
struct dm_list *vgnameids);
|
||||
|
||||
/* Returns list of struct dm_str_list containing pool-allocated copy of pvids */
|
||||
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid);
|
||||
|
||||
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
|
||||
void lvmcache_commit_metadata(const char *vgname);
|
||||
@@ -160,17 +167,16 @@ int lvmcache_foreach_pv(struct lvmcache_vginfo *vginfo,
|
||||
uint64_t lvmcache_device_size(struct lvmcache_info *info);
|
||||
void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size);
|
||||
struct device *lvmcache_device(struct lvmcache_info *info);
|
||||
int lvmcache_is_orphan(struct lvmcache_info *info);
|
||||
unsigned lvmcache_mda_count(struct lvmcache_info *info);
|
||||
int lvmcache_vgid_is_cached(const char *vgid);
|
||||
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info);
|
||||
|
||||
struct metadata_area *lvmcache_get_mda(struct cmd_context *cmd,
|
||||
const char *vgname,
|
||||
struct device *dev,
|
||||
int use_mda_num);
|
||||
|
||||
int lvmcache_found_duplicate_pvs(void);
|
||||
int lvmcache_found_duplicate_vgnames(void);
|
||||
|
||||
void lvmcache_pvscan_duplicate_check(struct cmd_context *cmd);
|
||||
|
||||
int lvmcache_get_unused_duplicate_devs(struct cmd_context *cmd, struct dm_list *head);
|
||||
|
||||
int vg_has_duplicate_pvs(struct volume_group *vg);
|
||||
@@ -182,24 +188,40 @@ void lvmcache_get_max_name_lengths(struct cmd_context *cmd,
|
||||
|
||||
int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid);
|
||||
|
||||
void lvmcache_lock_ordering(int enable);
|
||||
|
||||
int lvmcache_dev_is_unchosen_duplicate(struct device *dev);
|
||||
|
||||
void lvmcache_remove_unchosen_duplicate(struct device *dev);
|
||||
|
||||
int lvmcache_pvid_in_unchosen_duplicates(const char *pvid);
|
||||
|
||||
bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
|
||||
int lvmcache_get_vg_devs(struct cmd_context *cmd,
|
||||
struct lvmcache_vginfo *vginfo,
|
||||
struct dm_list *devs);
|
||||
void lvmcache_set_independent_location(const char *vgname);
|
||||
|
||||
int lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
|
||||
|
||||
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid);
|
||||
|
||||
/*
|
||||
* These are clvmd-specific functions and are not related to lvmcache.
|
||||
* FIXME: rename these with a clvm_ prefix in place of lvmcache_
|
||||
*/
|
||||
void lvmcache_save_vg(struct volume_group *vg, int precommitted);
|
||||
struct volume_group *lvmcache_get_saved_vg(const char *vgid, int precommitted);
|
||||
struct volume_group *lvmcache_get_saved_vg_latest(const char *vgid);
|
||||
void lvmcache_drop_saved_vgid(const char *vgid);
|
||||
|
||||
uint64_t lvmcache_max_metadata_size(void);
|
||||
void lvmcache_save_metadata_size(uint64_t val);
|
||||
|
||||
int dev_in_device_list(struct device *dev, struct dm_list *head);
|
||||
|
||||
bool lvmcache_has_bad_metadata(struct device *dev);
|
||||
int lvmcache_has_bad_metadata(struct device *dev);
|
||||
|
||||
bool lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, const char *vgid, struct device *dev);
|
||||
int lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, const char *vgid, struct device *dev);
|
||||
|
||||
void lvmcache_get_outdated_devs(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid,
|
||||
@@ -209,9 +231,9 @@ void lvmcache_get_outdated_mdas(struct cmd_context *cmd,
|
||||
struct device *dev,
|
||||
struct dm_list **mdas);
|
||||
|
||||
bool lvmcache_is_outdated_dev(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid,
|
||||
struct device *dev);
|
||||
int lvmcache_is_outdated_dev(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid,
|
||||
struct device *dev);
|
||||
|
||||
void lvmcache_del_outdated_devs(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid);
|
||||
@@ -219,7 +241,8 @@ void lvmcache_del_outdated_devs(struct cmd_context *cmd,
|
||||
void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda);
|
||||
|
||||
void lvmcache_get_bad_mdas(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid,
|
||||
struct dm_list *bad_mda_list);
|
||||
const char *vgname, const char *vgid,
|
||||
struct dm_list *bad_mdas);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -1715,6 +1715,8 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
|
||||
if (!init_lvmcache_orphans(cmd))
|
||||
goto_out;
|
||||
|
||||
dm_list_init(&cmd->unused_duplicate_devs);
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
goto_out;
|
||||
|
||||
@@ -1819,7 +1821,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
*/
|
||||
|
||||
activation_release();
|
||||
hints_exit(cmd);
|
||||
hints_exit();
|
||||
lvmcache_destroy(cmd, 0, 0);
|
||||
label_scan_destroy(cmd);
|
||||
label_exit();
|
||||
@@ -1939,7 +1941,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
|
||||
archive_exit(cmd);
|
||||
backup_exit(cmd);
|
||||
hints_exit(cmd);
|
||||
hints_exit();
|
||||
lvmcache_destroy(cmd, 0, 0);
|
||||
label_scan_destroy(cmd);
|
||||
label_exit();
|
||||
|
@@ -160,9 +160,6 @@ struct cmd_context {
|
||||
unsigned lockd_vg_default_sh:1;
|
||||
unsigned lockd_vg_enforce_sh:1;
|
||||
unsigned lockd_lv_sh_for_ex:1;
|
||||
unsigned lockd_global_ex:1; /* set while global lock held ex (lockd) */
|
||||
unsigned lockf_global_ex:1; /* set while global lock held ex (flock) */
|
||||
unsigned nolocking:1;
|
||||
unsigned vg_notify:1;
|
||||
unsigned lv_notify:1;
|
||||
unsigned pv_notify:1;
|
||||
@@ -172,7 +169,6 @@ struct cmd_context {
|
||||
unsigned pvscan_cache_single:1;
|
||||
unsigned can_use_one_scan:1;
|
||||
unsigned is_clvmd:1;
|
||||
unsigned md_component_detection:1;
|
||||
unsigned use_full_md_check:1;
|
||||
unsigned is_activating:1;
|
||||
unsigned enable_hints:1; /* hints are enabled for cmds in general */
|
||||
@@ -186,7 +182,6 @@ struct cmd_context {
|
||||
*/
|
||||
struct dev_filter *filter;
|
||||
struct dm_list hints;
|
||||
const char *md_component_checks;
|
||||
|
||||
/*
|
||||
* Configuration.
|
||||
@@ -237,6 +232,7 @@ struct cmd_context {
|
||||
const char *report_list_item_separator;
|
||||
const char *time_format;
|
||||
unsigned rand_seed;
|
||||
struct dm_list unused_duplicate_devs; /* save preferences between lvmcache instances */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -368,30 +368,7 @@ cfg(devices_multipath_component_detection_CFG, "multipath_component_detection",
|
||||
"Ignore devices that are components of DM multipath devices.\n")
|
||||
|
||||
cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL, 0, NULL,
|
||||
"Enable detection and exclusion of MD component devices.\n"
|
||||
"An MD component device is a block device that MD uses as part\n"
|
||||
"of a software RAID virtual device. When an LVM PV is created\n"
|
||||
"on an MD device, LVM must only use the top level MD device as\n"
|
||||
"the PV, and should ignore the underlying component devices.\n"
|
||||
"In cases where the MD superblock is located at the end of the\n"
|
||||
"component devices, it is more difficult for LVM to consistently\n"
|
||||
"identify an MD component, see the md_component_checks setting.\n")
|
||||
|
||||
cfg(devices_md_component_checks_CFG, "md_component_checks", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MD_COMPONENT_CHECKS, vsn(2, 3, 2), NULL, 0, NULL,
|
||||
"The checks LVM should use to detect MD component devices.\n"
|
||||
"MD component devices are block devices used by MD software RAID.\n"
|
||||
"#\n"
|
||||
"Accepted values:\n"
|
||||
" auto\n"
|
||||
" LVM will skip scanning the end of devices when it has other\n"
|
||||
" indications that the device is not an MD component.\n"
|
||||
" start\n"
|
||||
" LVM will only scan the start of devices for MD superblocks.\n"
|
||||
" This does not incur extra I/O by LVM.\n"
|
||||
" full\n"
|
||||
" LVM will scan the start and end of devices for MD superblocks.\n"
|
||||
" This requires an extra read at the end of devices.\n"
|
||||
"#\n")
|
||||
"Ignore devices that are components of software RAID (md) devices.\n")
|
||||
|
||||
cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FW_RAID_COMPONENT_DETECTION, vsn(2, 2, 112), NULL, 0, NULL,
|
||||
"Ignore devices that are components of firmware RAID devices.\n"
|
||||
|
@@ -318,6 +318,4 @@
|
||||
|
||||
#define DEFAULT_IO_MEMORY_SIZE_KB 8192
|
||||
|
||||
#define DEFAULT_MD_COMPONENT_CHECKS "auto"
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
|
@@ -88,21 +88,8 @@ static uint64_t _v1_sb_offset(uint64_t size, md_minor_version_t minor_version)
|
||||
return sb_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* _udev_dev_is_md_component() only works if
|
||||
* external_device_info_source="udev"
|
||||
*
|
||||
* but
|
||||
*
|
||||
* udev_dev_is_md_component() in dev-type.c only works if
|
||||
* obtain_device_list_from_udev=1
|
||||
*
|
||||
* and neither of those config setting matches very well
|
||||
* with what we're doing here.
|
||||
*/
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
static int _udev_dev_is_md_component(struct device *dev)
|
||||
static int _udev_dev_is_md(struct device *dev)
|
||||
{
|
||||
const char *value;
|
||||
struct dev_ext *ext;
|
||||
@@ -110,17 +97,14 @@ static int _udev_dev_is_md_component(struct device *dev)
|
||||
if (!(ext = dev_ext_get(dev)))
|
||||
return_0;
|
||||
|
||||
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE))) {
|
||||
dev->flags |= DEV_UDEV_INFO_MISSING;
|
||||
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID);
|
||||
}
|
||||
#else
|
||||
static int _udev_dev_is_md_component(struct device *dev)
|
||||
static int _udev_dev_is_md(struct device *dev)
|
||||
{
|
||||
dev->flags |= DEV_UDEV_INFO_MISSING;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -128,7 +112,7 @@ static int _udev_dev_is_md_component(struct device *dev)
|
||||
/*
|
||||
* Returns -1 on error
|
||||
*/
|
||||
static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
|
||||
static int _native_dev_is_md(struct device *dev, uint64_t *offset_found, int full)
|
||||
{
|
||||
md_minor_version_t minor;
|
||||
uint64_t size, sb_offset;
|
||||
@@ -204,7 +188,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
|
||||
int dev_is_md(struct device *dev, uint64_t *offset_found, int full)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -214,25 +198,19 @@ int dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
|
||||
* information is not in udev db.
|
||||
*/
|
||||
if ((dev->ext.src == DEV_EXT_NONE) || offset_found) {
|
||||
ret = _native_dev_is_md_component(dev, offset_found, full);
|
||||
ret = _native_dev_is_md(dev, offset_found, full);
|
||||
|
||||
if (!full) {
|
||||
if (!ret || (ret == -EAGAIN)) {
|
||||
if (udev_dev_is_md_component(dev))
|
||||
ret = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (ret && (ret != -EAGAIN))
|
||||
dev->flags |= DEV_IS_MD_COMPONENT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dev->ext.src == DEV_EXT_UDEV) {
|
||||
ret = _udev_dev_is_md_component(dev);
|
||||
if (ret && (ret != -EAGAIN))
|
||||
dev->flags |= DEV_IS_MD_COMPONENT;
|
||||
return ret;
|
||||
}
|
||||
if (dev->ext.src == DEV_EXT_UDEV)
|
||||
return _udev_dev_is_md(dev);
|
||||
|
||||
log_error(INTERNAL_ERROR "Missing hook for MD device recognition "
|
||||
"using external device info source %s", dev_ext_name(dev));
|
||||
@@ -461,7 +439,7 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev)
|
||||
|
||||
#else
|
||||
|
||||
int dev_is_md_component(struct device *dev __attribute__((unused)),
|
||||
int dev_is_md(struct device *dev __attribute__((unused)),
|
||||
uint64_t *sb __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
|
@@ -866,7 +866,7 @@ static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name,
|
||||
wiped = &wiped_tmp;
|
||||
*wiped = 0;
|
||||
|
||||
if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md_component) ||
|
||||
if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md) ||
|
||||
!_wipe_signature(dev, "swap signature", name, 10, yes, force, wiped, dev_is_swap) ||
|
||||
!_wipe_signature(dev, "LUKS signature", name, 8, yes, force, wiped, dev_is_luks))
|
||||
return 0;
|
||||
@@ -1170,10 +1170,8 @@ int udev_dev_is_md_component(struct device *dev)
|
||||
const char *value;
|
||||
int ret = 0;
|
||||
|
||||
if (!obtain_device_list_from_udev()) {
|
||||
dev->flags |= DEV_UDEV_INFO_MISSING;
|
||||
if (!obtain_device_list_from_udev())
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(udev_device = _udev_get_dev(dev)))
|
||||
return 0;
|
||||
@@ -1182,7 +1180,6 @@ int udev_dev_is_md_component(struct device *dev)
|
||||
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID)) {
|
||||
log_debug("Device %s is md raid component based on blkid variable in udev db (%s=\"%s\").",
|
||||
dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value);
|
||||
dev->flags |= DEV_IS_MD_COMPONENT;
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
@@ -1200,7 +1197,6 @@ int udev_dev_is_mpath_component(struct device *dev)
|
||||
|
||||
int udev_dev_is_md_component(struct device *dev)
|
||||
{
|
||||
dev->flags |= DEV_UDEV_INFO_MISSING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -57,7 +57,7 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev);
|
||||
int major_is_scsi_device(struct dev_types *dt, int major);
|
||||
|
||||
/* Signature/superblock recognition with position returned where found. */
|
||||
int dev_is_md_component(struct device *dev, uint64_t *sb, int full);
|
||||
int dev_is_md(struct device *dev, uint64_t *sb, int full);
|
||||
int dev_is_swap(struct device *dev, uint64_t *signature, int full);
|
||||
int dev_is_luks(struct device *dev, uint64_t *signature, int full);
|
||||
int dasd_is_cdl_formatted(struct device *dev);
|
||||
|
@@ -36,8 +36,6 @@
|
||||
#define DEV_FILTER_OUT_SCAN 0x00004000 /* filtered out during label scan */
|
||||
#define DEV_BCACHE_WRITE 0x00008000 /* bcache_fd is open with RDWR */
|
||||
#define DEV_SCAN_FOUND_LABEL 0x00010000 /* label scan read dev and found label */
|
||||
#define DEV_IS_MD_COMPONENT 0x00020000 /* device is an md component */
|
||||
#define DEV_UDEV_INFO_MISSING 0x00040000 /* we have no udev info for this device */
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
|
@@ -93,7 +93,7 @@ static int _passes_md_filter(struct cmd_context *cmd, struct dev_filter *f __att
|
||||
if (!md_filtering())
|
||||
return 1;
|
||||
|
||||
ret = dev_is_md_component(dev, NULL, cmd->use_full_md_check);
|
||||
ret = dev_is_md(dev, NULL, cmd->use_full_md_check);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
/* let pass, call again after scan */
|
||||
|
@@ -121,6 +121,158 @@ static struct device *_mda_get_device_raw(struct metadata_area *mda)
|
||||
return mdac->area.dev;
|
||||
}
|
||||
|
||||
/*
|
||||
* For circular region between region_start and region_start + region_size,
|
||||
* back up one SECTOR_SIZE from 'region_ptr' and return the value.
|
||||
* This allows reverse traversal through text metadata area to find old
|
||||
* metadata.
|
||||
*
|
||||
* Parameters:
|
||||
* region_start: start of the region (bytes)
|
||||
* region_size: size of the region (bytes)
|
||||
* region_ptr: pointer within the region (bytes)
|
||||
* NOTE: region_start <= region_ptr <= region_start + region_size
|
||||
*/
|
||||
static uint64_t _get_prev_sector_circular(uint64_t region_start,
|
||||
uint64_t region_size,
|
||||
uint64_t region_ptr)
|
||||
{
|
||||
if (region_ptr >= region_start + SECTOR_SIZE)
|
||||
return region_ptr - SECTOR_SIZE;
|
||||
|
||||
return (region_start + region_size - SECTOR_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Analyze a metadata area for old metadata records in the circular buffer.
|
||||
* This function just looks through and makes a first pass at the data in
|
||||
* the sectors for particular things.
|
||||
* FIXME: do something with each metadata area (try to extract vg, write
|
||||
* raw data to file, etc)
|
||||
*/
|
||||
static int _pv_analyze_mda_raw (const struct format_type * fmt,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct mda_header *mdah;
|
||||
struct raw_locn *rlocn;
|
||||
uint64_t area_start;
|
||||
uint64_t area_size;
|
||||
uint64_t prev_sector, prev_sector2;
|
||||
uint64_t latest_mrec_offset;
|
||||
uint64_t offset;
|
||||
uint64_t offset2;
|
||||
size_t size;
|
||||
size_t size2;
|
||||
char *buf=NULL;
|
||||
struct device_area *area;
|
||||
struct mda_context *mdac;
|
||||
uint32_t bad_fields = 0;
|
||||
int r=0;
|
||||
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
|
||||
log_print("Found text metadata area: offset=" FMTu64 ", size="
|
||||
FMTu64, mdac->area.start, mdac->area.size);
|
||||
area = &mdac->area;
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fmt, area, mda_is_primary(mda), 0, &bad_fields)))
|
||||
goto_out;
|
||||
|
||||
rlocn = mdah->raw_locns;
|
||||
|
||||
/*
|
||||
* The device area includes the metadata header as well as the
|
||||
* records, so remove the metadata header from the start and size
|
||||
*/
|
||||
area_start = area->start + MDA_HEADER_SIZE;
|
||||
area_size = area->size - MDA_HEADER_SIZE;
|
||||
latest_mrec_offset = rlocn->offset + area->start;
|
||||
|
||||
/*
|
||||
* Start searching at rlocn (point of live metadata) and go
|
||||
* backwards.
|
||||
*/
|
||||
prev_sector = _get_prev_sector_circular(area_start, area_size,
|
||||
latest_mrec_offset);
|
||||
offset = prev_sector;
|
||||
size = SECTOR_SIZE;
|
||||
offset2 = size2 = 0;
|
||||
|
||||
while (prev_sector != latest_mrec_offset) {
|
||||
prev_sector2 = prev_sector;
|
||||
prev_sector = _get_prev_sector_circular(area_start, area_size,
|
||||
prev_sector);
|
||||
if (prev_sector > prev_sector2)
|
||||
goto_out;
|
||||
/*
|
||||
* FIXME: for some reason, the whole metadata region from
|
||||
* area->start to area->start+area->size is not used.
|
||||
* Only ~32KB seems to contain valid metadata records
|
||||
* (LVM2 format - format_text). As a result, I end up with
|
||||
* "dm_config_maybe_section" returning true when there's no valid
|
||||
* metadata in a sector (sectors with all nulls).
|
||||
*/
|
||||
if (!(buf = malloc(size + size2)))
|
||||
goto_out;
|
||||
|
||||
if (!dev_read_bytes(area->dev, offset, size, buf)) {
|
||||
log_error("Failed to read dev %s offset %llu size %llu",
|
||||
dev_name(area->dev),
|
||||
(unsigned long long)offset,
|
||||
(unsigned long long)size);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size2) {
|
||||
if (!dev_read_bytes(area->dev, offset2, size2, buf + size)) {
|
||||
log_error("Failed to read dev %s offset %llu size %llu",
|
||||
dev_name(area->dev),
|
||||
(unsigned long long)offset2,
|
||||
(unsigned long long)size2);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: We could add more sophisticated metadata detection
|
||||
*/
|
||||
if (dm_config_maybe_section(buf, size + size2)) {
|
||||
/* FIXME: Validate region, pull out timestamp?, etc */
|
||||
/* FIXME: Do something with this region */
|
||||
log_verbose ("Found LVM2 metadata record at "
|
||||
"offset=" FMTu64 ", size=" FMTsize_t ", "
|
||||
"offset2=" FMTu64 " size2=" FMTsize_t,
|
||||
offset, size, offset2, size2);
|
||||
offset = prev_sector;
|
||||
size = SECTOR_SIZE;
|
||||
offset2 = size2 = 0;
|
||||
} else {
|
||||
/*
|
||||
* Not a complete metadata record, assume we have
|
||||
* metadata and just increase the size and offset.
|
||||
* Start the second region if the previous sector is
|
||||
* wrapping around towards the end of the disk.
|
||||
*/
|
||||
if (prev_sector > offset) {
|
||||
offset2 = prev_sector;
|
||||
size2 += SECTOR_SIZE;
|
||||
} else {
|
||||
offset = prev_sector;
|
||||
size += SECTOR_SIZE;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
free(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int _text_lv_setup(struct format_instance *fid __attribute__((unused)),
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
@@ -164,6 +316,8 @@ static void _xlate_mdah(struct mda_header *mdah)
|
||||
static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev_area,
|
||||
int primary_mda, uint32_t ignore_bad_fields, uint32_t *bad_fields)
|
||||
{
|
||||
int bad = 0;
|
||||
|
||||
log_debug_metadata("Reading mda header sector from %s at %llu",
|
||||
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
|
||||
|
||||
@@ -180,34 +334,49 @@ static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev
|
||||
log_warn("WARNING: wrong checksum %x in mda header on %s at %llu",
|
||||
mdah->checksum_xl,
|
||||
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
|
||||
*bad_fields |= BAD_MDA_CHECKSUM;
|
||||
|
||||
if (!(ignore_bad_fields & BAD_MDA_CHECKSUM)) {
|
||||
*bad_fields |= BAD_MDA_CHECKSUM;
|
||||
bad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
_xlate_mdah(mdah);
|
||||
|
||||
if (memcmp(mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
|
||||
log_warn("WARNING: wrong magic number in mda header on %s at %llu",
|
||||
if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
|
||||
log_warn("WARNING: wrong magic number %.8s in mda header on %s at %llu",
|
||||
mdah->magic,
|
||||
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
|
||||
*bad_fields |= BAD_MDA_MAGIC;
|
||||
|
||||
if (!(ignore_bad_fields & BAD_MDA_MAGIC)) {
|
||||
*bad_fields |= BAD_MDA_MAGIC;
|
||||
bad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mdah->version != FMTT_VERSION) {
|
||||
log_warn("WARNING: wrong version %u in mda header on %s at %llu",
|
||||
mdah->version,
|
||||
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
|
||||
*bad_fields |= BAD_MDA_VERSION;
|
||||
|
||||
if (!(ignore_bad_fields & BAD_MDA_VERSION)) {
|
||||
*bad_fields |= BAD_MDA_VERSION;
|
||||
bad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mdah->start != dev_area->start) {
|
||||
log_warn("WARNING: wrong start sector %llu in mda header on %s at %llu",
|
||||
(unsigned long long)mdah->start,
|
||||
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
|
||||
*bad_fields |= BAD_MDA_START;
|
||||
|
||||
if (!(ignore_bad_fields & BAD_MDA_START)) {
|
||||
*bad_fields |= BAD_MDA_START;
|
||||
bad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
*bad_fields &= ~ignore_bad_fields;
|
||||
|
||||
if (*bad_fields)
|
||||
if (bad)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@@ -237,7 +406,7 @@ static int _raw_write_mda_header(const struct format_type *fmt,
|
||||
struct device *dev, int primary_mda,
|
||||
uint64_t start_byte, struct mda_header *mdah)
|
||||
{
|
||||
memcpy(mdah->magic, FMTT_MAGIC, sizeof(mdah->magic));
|
||||
strncpy((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic));
|
||||
mdah->version = FMTT_VERSION;
|
||||
mdah->start = start_byte;
|
||||
|
||||
@@ -1836,6 +2005,7 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
|
||||
.mda_free_sectors = _mda_free_sectors_raw,
|
||||
.mda_total_sectors = _mda_total_sectors_raw,
|
||||
.mda_in_vg = _mda_in_vg_raw,
|
||||
.pv_analyze_mda = _pv_analyze_mda_raw,
|
||||
.mda_locns_match = _mda_locns_match_raw,
|
||||
.mda_get_device = _mda_get_device_raw,
|
||||
};
|
||||
|
@@ -30,7 +30,7 @@ static int _text_can_handle(struct labeller *l __attribute__((unused)),
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
|
||||
if (!memcmp(lh->type, LVM2_LABEL, sizeof(lh->type)))
|
||||
if (!strncmp((char *)lh->type, LVM2_LABEL, sizeof(lh->type)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -95,9 +95,9 @@ static int _text_write(struct label *label, void *buf)
|
||||
* PV header base
|
||||
*/
|
||||
/* FIXME Move to where label is created */
|
||||
memcpy(label->type, LVM2_LABEL, sizeof(label->type));
|
||||
strncpy(label->type, LVM2_LABEL, sizeof(label->type));
|
||||
|
||||
memcpy(lh->type, LVM2_LABEL, sizeof(lh->type));
|
||||
strncpy((char *)lh->type, label->type, sizeof(label->type));
|
||||
|
||||
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
@@ -315,7 +315,7 @@ void del_mdas(struct dm_list *mdas)
|
||||
static int _text_initialise_label(struct labeller *l __attribute__((unused)),
|
||||
struct label *label)
|
||||
{
|
||||
memcpy(label->type, LVM2_LABEL, sizeof(label->type));
|
||||
strncpy(label->type, LVM2_LABEL, sizeof(label->type));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -294,15 +294,12 @@ static int _clear_hints(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lock_hints(struct cmd_context *cmd, int mode, int nonblock)
|
||||
static int _lock_hints(int mode, int nonblock)
|
||||
{
|
||||
int fd;
|
||||
int op = mode;
|
||||
int ret;
|
||||
|
||||
if (cmd->nolocking)
|
||||
return 1;
|
||||
|
||||
if (nonblock)
|
||||
op |= LOCK_NB;
|
||||
|
||||
@@ -329,13 +326,10 @@ static int _lock_hints(struct cmd_context *cmd, int mode, int nonblock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _unlock_hints(struct cmd_context *cmd)
|
||||
static void _unlock_hints(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (cmd->nolocking)
|
||||
return;
|
||||
|
||||
if (_hints_fd == -1) {
|
||||
log_warn("unlock_hints no existing fd");
|
||||
return;
|
||||
@@ -350,11 +344,11 @@ static void _unlock_hints(struct cmd_context *cmd)
|
||||
_hints_fd = -1;
|
||||
}
|
||||
|
||||
void hints_exit(struct cmd_context *cmd)
|
||||
void hints_exit(void)
|
||||
{
|
||||
if (_hints_fd == -1)
|
||||
return;
|
||||
return _unlock_hints(cmd);
|
||||
return _unlock_hints();
|
||||
}
|
||||
|
||||
static struct hint *_find_hint_name(struct dm_list *hints, const char *name)
|
||||
@@ -901,11 +895,6 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
|
||||
if (!(dev->flags & DEV_SCAN_FOUND_LABEL))
|
||||
continue;
|
||||
|
||||
if (dev->flags & DEV_IS_MD_COMPONENT) {
|
||||
log_debug("exclude md component from hints %s", dev_name(dev));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* No vgname will be found here for a PV with no mdas,
|
||||
* in which case the vgname hint will be incomplete.
|
||||
@@ -952,7 +941,7 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
|
||||
|
||||
out_unlock:
|
||||
/* get_hints() took ex lock before returning with newhints set */
|
||||
_unlock_hints(cmd);
|
||||
_unlock_hints();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -990,13 +979,17 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
|
||||
* an issue we could easily write the pid in the nohints file, and
|
||||
* others could check if the pid is still around before obeying it.)
|
||||
*
|
||||
* The function is meant to be called after the global ex lock has been
|
||||
* The intention is to call this function after the global ex lock has been
|
||||
* taken, which is the official lock serializing commands changing which
|
||||
* devs are PVs or not. This means that a command should never block in
|
||||
* this function due to another command that has used this function --
|
||||
* they would be serialized by the official global lock first.
|
||||
* e.g. two pvcreates should never block each other from the hint lock,
|
||||
* but rather from the global lock.
|
||||
* but rather from the global lock...
|
||||
*
|
||||
* Unfortunately, the global(orphan) lock is not used consistently so it's not
|
||||
* quite doing its job right and needs some cleanup. Until that's done,
|
||||
* concurrent commands like pvcreate may block each other on the hint lock.
|
||||
*/
|
||||
|
||||
void clear_hint_file(struct cmd_context *cmd)
|
||||
@@ -1017,7 +1010,7 @@ void clear_hint_file(struct cmd_context *cmd)
|
||||
if (!_touch_nohints())
|
||||
stack;
|
||||
|
||||
if (!_lock_hints(cmd, LOCK_EX, 0))
|
||||
if (!_lock_hints(LOCK_EX, 0))
|
||||
stack;
|
||||
|
||||
_unlink_nohints();
|
||||
@@ -1053,7 +1046,7 @@ void pvscan_recreate_hints_begin(struct cmd_context *cmd)
|
||||
if (!_touch_nohints())
|
||||
stack;
|
||||
|
||||
if (!_lock_hints(cmd, LOCK_EX, 0))
|
||||
if (!_lock_hints(LOCK_EX, 0))
|
||||
stack;
|
||||
|
||||
_unlink_nohints();
|
||||
@@ -1205,7 +1198,7 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
log_debug("get_hints: newhints file");
|
||||
if (!_hints_exists())
|
||||
_touch_hints();
|
||||
if (!_lock_hints(cmd, LOCK_EX, NONBLOCK))
|
||||
if (!_lock_hints(LOCK_EX, NONBLOCK))
|
||||
return 0;
|
||||
/* create new hints after scan */
|
||||
*newhints = NEWHINTS_FILE;
|
||||
@@ -1219,7 +1212,7 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
log_debug("get_hints: no file");
|
||||
if (!_touch_hints())
|
||||
return 0;
|
||||
if (!_lock_hints(cmd, LOCK_EX, NONBLOCK))
|
||||
if (!_lock_hints(LOCK_EX, NONBLOCK))
|
||||
return 0;
|
||||
/* create new hints after scan */
|
||||
*newhints = NEWHINTS_INIT;
|
||||
@@ -1232,7 +1225,7 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
* We hold a sh lock on the hints file while reading it to prevent
|
||||
* another command from clearing it while we're reading
|
||||
*/
|
||||
if (!_lock_hints(cmd, LOCK_SH, NONBLOCK)) {
|
||||
if (!_lock_hints(LOCK_SH, NONBLOCK)) {
|
||||
log_debug("get_hints: lock fail");
|
||||
return 0;
|
||||
}
|
||||
@@ -1242,11 +1235,11 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
*/
|
||||
if (!_read_hint_file(cmd, &hints_list, &needs_refresh)) {
|
||||
log_debug("get_hints: read fail");
|
||||
_unlock_hints(cmd);
|
||||
_unlock_hints();
|
||||
return 0;
|
||||
}
|
||||
|
||||
_unlock_hints(cmd);
|
||||
_unlock_hints();
|
||||
|
||||
/*
|
||||
* The content of the hint file is invalid and should be refreshed,
|
||||
@@ -1255,7 +1248,7 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
if (needs_refresh) {
|
||||
log_debug("get_hints: needs refresh");
|
||||
|
||||
if (!_lock_hints(cmd, LOCK_EX, NONBLOCK))
|
||||
if (!_lock_hints(LOCK_EX, NONBLOCK))
|
||||
return 0;
|
||||
|
||||
/* create new hints after scan */
|
||||
@@ -1272,7 +1265,7 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
if (dm_list_empty(&hints_list)) {
|
||||
log_debug("get_hints: no entries");
|
||||
|
||||
if (!_lock_hints(cmd, LOCK_EX, NONBLOCK))
|
||||
if (!_lock_hints(LOCK_EX, NONBLOCK))
|
||||
return 0;
|
||||
|
||||
/* create new hints after scan */
|
||||
|
@@ -35,7 +35,7 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints, int *newhints,
|
||||
|
||||
int validate_hints(struct cmd_context *cmd, struct dm_list *hints);
|
||||
|
||||
void hints_exit(struct cmd_context *cmd);
|
||||
void hints_exit(void);
|
||||
|
||||
void pvscan_recreate_hints_begin(struct cmd_context *cmd);
|
||||
|
||||
|
@@ -139,7 +139,7 @@ int label_remove(struct device *dev)
|
||||
|
||||
wipe = 0;
|
||||
|
||||
if (!memcmp(lh->id, LABEL_ID, sizeof(lh->id))) {
|
||||
if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
|
||||
if (xlate64(lh->sector_xl) == sector)
|
||||
wipe = 1;
|
||||
} else {
|
||||
@@ -192,7 +192,7 @@ int label_write(struct device *dev, struct label *label)
|
||||
|
||||
memset(buf, 0, LABEL_SIZE);
|
||||
|
||||
memcpy(lh->id, LABEL_ID, sizeof(lh->id));
|
||||
strncpy((char *)lh->id, LABEL_ID, sizeof(lh->id));
|
||||
lh->sector_xl = xlate64(label->sector);
|
||||
lh->offset_xl = xlate32(sizeof(*lh));
|
||||
|
||||
@@ -293,7 +293,7 @@ static struct labeller *_find_lvm_header(struct device *dev,
|
||||
|
||||
lh = (struct label_header *) (scan_buf + (sector << SECTOR_SHIFT));
|
||||
|
||||
if (!memcmp(lh->id, LABEL_ID, sizeof(lh->id))) {
|
||||
if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
|
||||
if (found) {
|
||||
log_error("Ignoring additional label on %s at sector %llu",
|
||||
dev_name(dev), (unsigned long long)(block_sector + sector));
|
||||
@@ -867,11 +867,8 @@ static void _free_hints(struct dm_list *hints)
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan devices on the system to discover which are LVM devices.
|
||||
* Info about the LVM devices (PVs) is saved in lvmcache in a
|
||||
* basic/summary form (info/vginfo structs). The vg_read phase
|
||||
* uses this summary info to know which PVs to look at for
|
||||
* processing a given VG.
|
||||
* Scan and cache lvm data from all devices on the system.
|
||||
* The cache should be empty/reset before calling this.
|
||||
*/
|
||||
|
||||
int label_scan(struct cmd_context *cmd)
|
||||
@@ -883,8 +880,7 @@ int label_scan(struct cmd_context *cmd)
|
||||
struct device_list *devl, *devl2;
|
||||
struct device *dev;
|
||||
uint64_t max_metadata_size_bytes;
|
||||
int using_hints;
|
||||
int create_hints = 0; /* NEWHINTS_NONE */
|
||||
int newhints = 0;
|
||||
|
||||
log_debug_devs("Finding devices to scan");
|
||||
|
||||
@@ -893,37 +889,20 @@ int label_scan(struct cmd_context *cmd)
|
||||
dm_list_init(&hints_list);
|
||||
|
||||
/*
|
||||
* dev_cache_scan() creates a list of devices on the system
|
||||
* (saved in in dev-cache) which we can iterate through to
|
||||
* search for LVM devs. The dev cache list either comes from
|
||||
* looking at dev nodes under /dev, or from udev.
|
||||
* Iterate through all the devices in dev-cache (block devs that appear
|
||||
* under /dev that could possibly hold a PV and are not excluded by
|
||||
* filters). Read each to see if it's an lvm device, and if so
|
||||
* populate lvmcache with some basic info about the device and the VG
|
||||
* on it. This info will be used by the vg_read() phase of the
|
||||
* command.
|
||||
*/
|
||||
dev_cache_scan();
|
||||
|
||||
/*
|
||||
* Set up the iterator that is needed to step through each device in
|
||||
* dev cache.
|
||||
*/
|
||||
if (!(iter = dev_iter_create(cmd->filter, 0))) {
|
||||
log_error("Scanning failed to get devices.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug_devs("Filtering devices to scan");
|
||||
|
||||
/*
|
||||
* Iterate through all devices in dev cache and apply filters
|
||||
* to exclude devs that we do not need to scan. Those devs
|
||||
* that pass the filters are returned by the iterator and
|
||||
* saved in a list of devs that we will proceed to scan to
|
||||
* check if they are LVM devs. IOW this loop is the
|
||||
* application of filters (those that do not require reading
|
||||
* the devs) to the list of all devices. It does that because
|
||||
* the 'cmd->filter' is used above when setting up the iterator.
|
||||
* Unfortunately, it's not obvious that this is what's happening
|
||||
* here. filters that require reading the device are not applied
|
||||
* here, but in process_block(), see DEV_FILTER_AFTER_SCAN.
|
||||
*/
|
||||
while ((dev = dev_iter_get(cmd, iter))) {
|
||||
if (!(devl = zalloc(sizeof(*devl))))
|
||||
continue;
|
||||
@@ -942,12 +921,13 @@ int label_scan(struct cmd_context *cmd)
|
||||
/*
|
||||
* When md devices exist that use the old superblock at the
|
||||
* end of the device, then in order to detect and filter out
|
||||
* the component devices of those md devs, we enable the full
|
||||
* md filter which scans both the start and the end of every
|
||||
* device. This doubles the amount of scanning i/o, which we
|
||||
* want to avoid. FIXME: this forces start+end scanning of
|
||||
* every device, but it would be more efficient to limit the
|
||||
* end scan only to PVs.
|
||||
* the component devices of those md devs, we need to enable
|
||||
* the full md filter which scans both the start and the end
|
||||
* of every device. This doubles the amount of scanning i/o,
|
||||
* which we want to avoid. FIXME: it may not be worth the
|
||||
* cost of double i/o just to avoid displaying md component
|
||||
* devs in 'pvs', which is a pretty harmless effect from a
|
||||
* pretty uncommon situation.
|
||||
*/
|
||||
if (dev_is_md_with_end_superblock(cmd->dev_types, dev))
|
||||
cmd->use_full_md_check = 1;
|
||||
@@ -960,10 +940,7 @@ int label_scan(struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
/*
|
||||
* In some common cases we can avoid scanning all devices
|
||||
* by using hints which tell us which devices are PVs, which
|
||||
* are the only devices we actually need to scan. Without
|
||||
* hints we need to scan all devs to find which are PVs.
|
||||
* In some common cases we can avoid scanning all devices.
|
||||
*
|
||||
* TODO: if the command is using hints and a single vgname
|
||||
* arg, we can also take the vg lock here, prior to scanning.
|
||||
@@ -973,12 +950,10 @@ int label_scan(struct cmd_context *cmd)
|
||||
* able to avoid rescan in vg_read, but locking early would
|
||||
* apply to more cases.)
|
||||
*/
|
||||
if (!get_hints(cmd, &hints_list, &create_hints, &all_devs, &scan_devs)) {
|
||||
if (!get_hints(cmd, &hints_list, &newhints, &all_devs, &scan_devs)) {
|
||||
dm_list_splice(&scan_devs, &all_devs);
|
||||
dm_list_init(&hints_list);
|
||||
using_hints = 0;
|
||||
} else
|
||||
using_hints = 1;
|
||||
}
|
||||
|
||||
log_debug("Will scan %d devices skip %d", dm_list_size(&scan_devs), dm_list_size(&all_devs));
|
||||
|
||||
@@ -1024,51 +999,23 @@ int label_scan(struct cmd_context *cmd)
|
||||
|
||||
dm_list_init(&cmd->hints);
|
||||
|
||||
/*
|
||||
* If we're using hints to limit which devs we scanned, verify
|
||||
* that those hints were valid, and if not we need to scan the
|
||||
* rest of the devs.
|
||||
*/
|
||||
if (using_hints) {
|
||||
if (!dm_list_empty(&hints_list)) {
|
||||
if (!validate_hints(cmd, &hints_list)) {
|
||||
/*
|
||||
* We scanned a subset of all devices based on hints.
|
||||
* With the results from the scan we may decide that
|
||||
* the hints are not valid, so scan all others.
|
||||
*/
|
||||
log_debug("Will scan %d remaining devices", dm_list_size(&all_devs));
|
||||
_scan_list(cmd, cmd->filter, &all_devs, NULL);
|
||||
_free_hints(&hints_list);
|
||||
using_hints = 0;
|
||||
create_hints = 0;
|
||||
newhints = 0;
|
||||
} else {
|
||||
/* The hints may be used by another device iteration. */
|
||||
dm_list_splice(&cmd->hints, &hints_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stronger exclusion of md components that might have been
|
||||
* misidentified as PVs due to having an end-of-device md superblock.
|
||||
* If we're not using hints, and are not already doing a full md check
|
||||
* on devs being scanned, then if udev info is missing for a PV, scan
|
||||
* the end of the PV to verify it's not an md component. The full
|
||||
* dev_is_md_component call will do new reads at the end of the dev.
|
||||
*/
|
||||
if (cmd->md_component_detection && !cmd->use_full_md_check && !using_hints &&
|
||||
!strcmp(cmd->md_component_checks, "auto")) {
|
||||
int once = 0;
|
||||
dm_list_iterate_items(devl, &scan_devs) {
|
||||
if (!(devl->dev->flags & DEV_SCAN_FOUND_LABEL))
|
||||
continue;
|
||||
if (!(devl->dev->flags & DEV_UDEV_INFO_MISSING))
|
||||
continue;
|
||||
if (!once++)
|
||||
log_debug_devs("Scanning end of PVs with no udev info for MD components");
|
||||
|
||||
if (dev_is_md_component(devl->dev, NULL, 1)) {
|
||||
log_debug_devs("Drop PV from MD component %s", dev_name(devl->dev));
|
||||
devl->dev->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
lvmcache_del_dev(devl->dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &all_devs) {
|
||||
dm_list_del(&devl->list);
|
||||
free(devl);
|
||||
@@ -1079,15 +1026,8 @@ int label_scan(struct cmd_context *cmd)
|
||||
free(devl);
|
||||
}
|
||||
|
||||
/*
|
||||
* If hints were not available/usable, then we scanned all devs,
|
||||
* and we now know which are PVs. Save this list of PVs we've
|
||||
* identified as hints for the next command to use.
|
||||
* (create_hints variable has NEWHINTS_X value which indicates
|
||||
* the reason for creating the new hints.)
|
||||
*/
|
||||
if (create_hints)
|
||||
write_hint_file(cmd, create_hints);
|
||||
if (newhints)
|
||||
write_hint_file(cmd, newhints);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1104,6 +1044,8 @@ int label_scan_devs(struct cmd_context *cmd, struct dev_filter *f, struct dm_lis
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
/* FIXME: get rid of this, it's only needed for lvmetad in which
|
||||
case we should be setting up bcache in one place. */
|
||||
if (!scan_bcache) {
|
||||
if (!_setup_bcache(0))
|
||||
return 0;
|
||||
@@ -1245,6 +1187,74 @@ int label_read(struct device *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a label from a specfic, non-zero sector. This is used in only
|
||||
* one place: pvck/pv_analyze.
|
||||
*/
|
||||
|
||||
int label_read_sector(struct device *dev, uint64_t read_sector)
|
||||
{
|
||||
struct block *bb = NULL;
|
||||
uint64_t block_num;
|
||||
uint64_t block_sector;
|
||||
uint64_t start_sector;
|
||||
int is_lvm_device = 0;
|
||||
int result;
|
||||
int ret;
|
||||
|
||||
block_num = read_sector / BCACHE_BLOCK_SIZE_IN_SECTORS;
|
||||
block_sector = block_num * BCACHE_BLOCK_SIZE_IN_SECTORS;
|
||||
start_sector = read_sector % BCACHE_BLOCK_SIZE_IN_SECTORS;
|
||||
|
||||
if (!label_scan_open(dev)) {
|
||||
log_error("Error opening device %s for prefetch %llu sector.",
|
||||
dev_name(dev), (unsigned long long)block_num);
|
||||
return false;
|
||||
}
|
||||
|
||||
bcache_prefetch(scan_bcache, dev->bcache_fd, block_num);
|
||||
|
||||
if (!bcache_get(scan_bcache, dev->bcache_fd, block_num, 0, &bb)) {
|
||||
log_error("Scan failed to read %s at %llu",
|
||||
dev_name(dev), (unsigned long long)block_num);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: check if scan_sector is larger than the bcache block size.
|
||||
* If it is, we need to fetch a later block from bcache.
|
||||
*/
|
||||
|
||||
result = _process_block(NULL, NULL, dev, bb, block_sector, start_sector, &is_lvm_device);
|
||||
|
||||
if (!result && is_lvm_device) {
|
||||
log_error("Scan failed to process %s", dev_name(dev));
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!result || !is_lvm_device) {
|
||||
log_error("Could not find LVM label on %s", dev_name(dev));
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
out:
|
||||
if (bb)
|
||||
bcache_put(bb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is only needed when commands are using lvmetad, in which case they
|
||||
* don't do an initial label_scan, but may later need to rescan certain devs
|
||||
* from disk and call this function. FIXME: is there some better number to
|
||||
* choose here? How should we predict the number of devices that might need
|
||||
* scanning when using lvmetad?
|
||||
*/
|
||||
|
||||
int label_scan_setup_bcache(void)
|
||||
{
|
||||
if (!scan_bcache) {
|
||||
@@ -1282,18 +1292,6 @@ int label_scan_open_excl(struct device *dev)
|
||||
return label_scan_open(dev);
|
||||
}
|
||||
|
||||
int label_scan_open_rw(struct device *dev)
|
||||
{
|
||||
if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_WRITE)) {
|
||||
/* FIXME: avoid tossing out bcache blocks just to replace fd. */
|
||||
log_debug("Close and reopen rw %s", dev_name(dev));
|
||||
bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
|
||||
_scan_dev_close(dev);
|
||||
}
|
||||
dev->flags |= DEV_BCACHE_WRITE;
|
||||
return label_scan_open(dev);
|
||||
}
|
||||
|
||||
bool dev_read_bytes(struct device *dev, uint64_t start, size_t len, void *data)
|
||||
{
|
||||
if (!scan_bcache) {
|
||||
@@ -1303,7 +1301,7 @@ bool dev_read_bytes(struct device *dev, uint64_t start, size_t len, void *data)
|
||||
}
|
||||
|
||||
if (dev->bcache_fd <= 0) {
|
||||
/* This is not often needed. */
|
||||
/* This is not often needed, perhaps only with lvmetad. */
|
||||
if (!label_scan_open(dev)) {
|
||||
log_error("Error opening device %s for reading at %llu length %u.",
|
||||
dev_name(dev), (unsigned long long)start, (uint32_t)len);
|
||||
@@ -1343,7 +1341,7 @@ bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data)
|
||||
}
|
||||
|
||||
if (dev->bcache_fd <= 0) {
|
||||
/* This is not often needed. */
|
||||
/* This is not often needed, perhaps only with lvmetad. */
|
||||
dev->flags |= DEV_BCACHE_WRITE;
|
||||
if (!label_scan_open(dev)) {
|
||||
log_error("Error opening device %s for writing at %llu length %u.",
|
||||
@@ -1389,7 +1387,7 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len)
|
||||
}
|
||||
|
||||
if (dev->bcache_fd <= 0) {
|
||||
/* This is not often needed. */
|
||||
/* This is not often needed, perhaps only with lvmetad. */
|
||||
dev->flags |= DEV_BCACHE_WRITE;
|
||||
if (!label_scan_open(dev)) {
|
||||
log_error("Error opening device %s for writing at %llu length %u.",
|
||||
@@ -1438,7 +1436,7 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val)
|
||||
}
|
||||
|
||||
if (dev->bcache_fd <= 0) {
|
||||
/* This is not often needed. */
|
||||
/* This is not often needed, perhaps only with lvmetad. */
|
||||
dev->flags |= DEV_BCACHE_WRITE;
|
||||
if (!label_scan_open(dev)) {
|
||||
log_error("Error opening device %s for writing at %llu length %u.",
|
||||
|
@@ -115,7 +115,6 @@ void label_scan_confirm(struct device *dev);
|
||||
int label_scan_setup_bcache(void);
|
||||
int label_scan_open(struct device *dev);
|
||||
int label_scan_open_excl(struct device *dev);
|
||||
int label_scan_open_rw(struct device *dev);
|
||||
|
||||
/*
|
||||
* Wrappers around bcache equivalents.
|
||||
|
@@ -44,7 +44,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
{
|
||||
char lockfile[PATH_MAX];
|
||||
|
||||
if (!strcmp(resource, VG_GLOBAL)) {
|
||||
if (is_orphan_vg(resource) || is_global_vg(resource)) {
|
||||
if (dm_snprintf(lockfile, sizeof(lockfile),
|
||||
"%s/P_%s", _lock_dir, resource + 1) < 0) {
|
||||
log_error("Too long locking filename %s/P_%s.", _lock_dir, resource + 1);
|
||||
|
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/locking/locking.h"
|
||||
#include "lib/locking/lvmlockd.h"
|
||||
#include "locking_types.h"
|
||||
#include "lib/misc/lvm-string.h"
|
||||
#include "lib/activate/activate.h"
|
||||
@@ -156,20 +155,12 @@ int init_locking(struct cmd_context *cmd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fin_locking(struct cmd_context *cmd)
|
||||
void fin_locking(void)
|
||||
{
|
||||
/* file locking disabled */
|
||||
if (!_locking.flags)
|
||||
return;
|
||||
|
||||
/*
|
||||
* These may be automatically released when the
|
||||
* command ends, without an explicit unlock call,
|
||||
* in which case these flags would not be cleared.
|
||||
*/
|
||||
cmd->lockf_global_ex = 0;
|
||||
cmd->lockd_global_ex = 0;
|
||||
|
||||
_locking.fin_locking();
|
||||
}
|
||||
|
||||
@@ -194,14 +185,13 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
|
||||
{
|
||||
char resource[258] __attribute__((aligned(8)));
|
||||
uint32_t lck_type = flags & LCK_TYPE_MASK;
|
||||
int is_global = !strcmp(vol, VG_GLOBAL);
|
||||
|
||||
if (is_orphan_vg(vol))
|
||||
return 1;
|
||||
|
||||
if (!_blocking_supported)
|
||||
flags |= LCK_NONBLOCK;
|
||||
|
||||
if (is_orphan_vg(vol))
|
||||
vol = VG_ORPHANS;
|
||||
|
||||
if (!dm_strncpy(resource, vol, sizeof(resource))) {
|
||||
log_error(INTERNAL_ERROR "Resource name %s is too long.", vol);
|
||||
return 0;
|
||||
@@ -221,7 +211,7 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
|
||||
if (lck_type != LCK_WRITE)
|
||||
goto out_hold;
|
||||
|
||||
if (cmd->is_activating && !is_global)
|
||||
if (cmd->is_activating && strcmp(vol, VG_GLOBAL))
|
||||
goto out_hold;
|
||||
|
||||
goto out_fail;
|
||||
@@ -262,7 +252,7 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
|
||||
* refuse write lock requests.
|
||||
*/
|
||||
if (cmd->metadata_read_only) {
|
||||
if (lck_type == LCK_WRITE) {
|
||||
if ((lck_type == LCK_WRITE) && strcmp(vol, VG_GLOBAL)) {
|
||||
log_error("Operation prohibited while global/metadata_read_only is set.");
|
||||
goto out_fail;
|
||||
}
|
||||
@@ -274,9 +264,6 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
|
||||
goto out_fail;
|
||||
|
||||
out_hold:
|
||||
if (is_global)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* FIXME: other parts of the code want to check if a VG is
|
||||
* locked by looking in lvmcache. They shouldn't need to
|
||||
@@ -292,8 +279,6 @@ out_hold:
|
||||
return 1;
|
||||
|
||||
out_fail:
|
||||
if (is_global)
|
||||
return 0;
|
||||
if (lck_type == LCK_UNLOCK)
|
||||
_update_vg_lock_count(resource, flags);
|
||||
return 0;
|
||||
@@ -333,93 +318,3 @@ int sync_local_dev_names(struct cmd_context* cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lockf_global_ex flag is used to prevent changing
|
||||
* an explicitly acquired ex global lock to sh in process_each.
|
||||
*/
|
||||
|
||||
static int _lockf_global(struct cmd_context *cmd, const char *mode, int convert)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
int ret;
|
||||
|
||||
if (convert)
|
||||
flags |= LCK_CONVERT;
|
||||
|
||||
if (!strcmp(mode, "ex")) {
|
||||
flags |= LCK_WRITE;
|
||||
|
||||
if (cmd->lockf_global_ex) {
|
||||
log_warn("global flock already held ex");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = lock_vol(cmd, VG_GLOBAL, flags, NULL);
|
||||
if (ret)
|
||||
cmd->lockf_global_ex = 1;
|
||||
|
||||
} else if (!strcmp(mode, "sh")) {
|
||||
if (cmd->lockf_global_ex)
|
||||
return 1;
|
||||
|
||||
flags |= LCK_READ;
|
||||
|
||||
ret = lock_vol(cmd, VG_GLOBAL, flags, NULL);
|
||||
|
||||
} else if (!strcmp(mode, "un")) {
|
||||
ret = lock_vol(cmd, VG_GLOBAL, LCK_UNLOCK, NULL);
|
||||
cmd->lockf_global_ex = 0;
|
||||
} else {
|
||||
log_error(INTERNAL_ERROR "Unknown locking mode %s.", mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lockf_global(struct cmd_context *cmd, const char *mode)
|
||||
{
|
||||
return _lockf_global(cmd, mode, 0);
|
||||
}
|
||||
|
||||
int lockf_global_convert(struct cmd_context *cmd, const char *mode)
|
||||
{
|
||||
/* some uncommon cases like pvchange -a can call this multiple times */
|
||||
if (cmd->lockf_global_ex && !strcmp(mode, "ex"))
|
||||
return 1;
|
||||
|
||||
return _lockf_global(cmd, mode, 1);
|
||||
}
|
||||
|
||||
int lock_global(struct cmd_context *cmd, const char *mode)
|
||||
{
|
||||
if (!lockf_global(cmd, mode))
|
||||
return 0;
|
||||
|
||||
if (!lockd_global(cmd, mode)) {
|
||||
lockf_global(cmd, "un");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The global lock is already held, convert it to another mode.
|
||||
*
|
||||
* Currently only used for sh->ex.
|
||||
*
|
||||
* (The lockf_global_ex flag would need overriding
|
||||
* to handle ex->sh.)
|
||||
*/
|
||||
|
||||
int lock_global_convert(struct cmd_context *cmd, const char *mode)
|
||||
{
|
||||
if (!lockf_global_convert(cmd, mode))
|
||||
return 0;
|
||||
|
||||
if (!lockd_global(cmd, mode))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -22,16 +22,18 @@
|
||||
struct logical_volume;
|
||||
|
||||
int init_locking(struct cmd_context *cmd, int file_locking_sysinit, int file_locking_readonly, int file_locking_ignorefail);
|
||||
void fin_locking(struct cmd_context *cmd);
|
||||
void fin_locking(void);
|
||||
void reset_locking(void);
|
||||
int vg_write_lock_held(void);
|
||||
|
||||
/*
|
||||
* Lock/unlock on-disk volume group data.
|
||||
* Use VG_GLOBAL as a global lock.
|
||||
* Use VG_ORPHANS to lock all orphan PVs.
|
||||
* Use VG_GLOBAL as a global lock and to wipe the internal cache.
|
||||
* char *vol holds volume group name.
|
||||
* If more than one lock needs to be held simultaneously, they must be
|
||||
* acquired in alphabetical order of 'vol' (to avoid deadlocks).
|
||||
* acquired in alphabetical order of 'vol' (to avoid deadlocks), with
|
||||
* VG_ORPHANS last.
|
||||
*/
|
||||
int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const struct logical_volume *lv);
|
||||
|
||||
@@ -45,8 +47,10 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
|
||||
* Bottom 8 bits except LCK_LOCAL form args[0] in cluster comms.
|
||||
*/
|
||||
#define LCK_NONBLOCK 0x00000010U /* Don't block waiting for lock? */
|
||||
#define LCK_CONVERT 0x00000020U
|
||||
|
||||
/*
|
||||
* Special cases of VG locks.
|
||||
*/
|
||||
#define VG_ORPHANS "#orphans"
|
||||
#define VG_GLOBAL "#global"
|
||||
|
||||
@@ -73,9 +77,4 @@ int sync_local_dev_names(struct cmd_context* cmd);
|
||||
struct volume_group;
|
||||
int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive);
|
||||
|
||||
int lockf_global(struct cmd_context *cmd, const char *mode);
|
||||
int lockf_global_convert(struct cmd_context *cmd, const char *mode);
|
||||
int lock_global(struct cmd_context *cmd, const char *mode);
|
||||
int lock_global_convert(struct cmd_context *cmd, const char *mode);
|
||||
|
||||
#endif
|
||||
|
@@ -1315,7 +1315,7 @@ int lockd_start_wait(struct cmd_context *cmd)
|
||||
* Future lockd_gl/lockd_gl_create calls will acquire the existing gl.
|
||||
*/
|
||||
|
||||
int lockd_global_create(struct cmd_context *cmd, const char *def_mode, const char *vg_lock_type)
|
||||
int lockd_gl_create(struct cmd_context *cmd, const char *def_mode, const char *vg_lock_type)
|
||||
{
|
||||
const char *mode = NULL;
|
||||
uint32_t lockd_flags;
|
||||
@@ -1460,12 +1460,6 @@ int lockd_global_create(struct cmd_context *cmd, const char *def_mode, const cha
|
||||
/* --shared with vgcreate does not mean include_shared_vgs */
|
||||
cmd->include_shared_vgs = 0;
|
||||
|
||||
/*
|
||||
* This is done to prevent converting an explicitly acquired
|
||||
* ex lock to sh in process_each.
|
||||
*/
|
||||
cmd->lockd_global_ex = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1548,7 +1542,7 @@ int lockd_global_create(struct cmd_context *cmd, const char *def_mode, const cha
|
||||
* are unprotected.
|
||||
*/
|
||||
|
||||
int lockd_global(struct cmd_context *cmd, const char *def_mode)
|
||||
int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
|
||||
{
|
||||
const char *mode = NULL;
|
||||
const char *opts = NULL;
|
||||
@@ -1578,16 +1572,10 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode)
|
||||
if (!mode)
|
||||
mode = def_mode;
|
||||
if (!mode) {
|
||||
log_error("Unknown lvmlockd global lock mode");
|
||||
log_error("Unknown lock-gl mode");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(mode, "sh") && cmd->lockd_global_ex)
|
||||
return 1;
|
||||
|
||||
if (!strcmp(mode, "un") && cmd->lockd_global_ex)
|
||||
cmd->lockd_global_ex = 0;
|
||||
|
||||
req:
|
||||
log_debug("lockd global mode %s", mode);
|
||||
|
||||
@@ -1731,14 +1719,6 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode)
|
||||
}
|
||||
|
||||
allow:
|
||||
|
||||
/*
|
||||
* This is done to prevent converting an explicitly acquired
|
||||
* ex lock to sh in process_each.
|
||||
*/
|
||||
if (!strcmp(mode, "ex"))
|
||||
cmd->lockd_global_ex = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -13,10 +13,12 @@
|
||||
|
||||
#include "libdaemon/client/config-util.h"
|
||||
#include "libdaemon/client/daemon-client.h"
|
||||
#include "lib/metadata/metadata-exported.h" /* is_lockd_type() */
|
||||
|
||||
#define LOCKD_SANLOCK_LV_NAME "lvmlock"
|
||||
|
||||
/* lockd_gl flags */
|
||||
#define LDGL_UPDATE_NAMES 0x00000001
|
||||
|
||||
/* lockd_lv flags */
|
||||
#define LDLV_MODE_NO_SH 0x00000001
|
||||
#define LDLV_PERSISTENT 0x00000002
|
||||
@@ -41,9 +43,6 @@
|
||||
|
||||
#ifdef LVMLOCKD_SUPPORT
|
||||
|
||||
struct lvresize_params;
|
||||
struct lvcreate_params;
|
||||
|
||||
/* lvmlockd connection and communication */
|
||||
|
||||
void lvmlockd_set_socket(const char *sock);
|
||||
@@ -72,8 +71,8 @@ int lockd_start_wait(struct cmd_context *cmd);
|
||||
|
||||
/* locking */
|
||||
|
||||
int lockd_global_create(struct cmd_context *cmd, const char *def_mode, const char *vg_lock_type);
|
||||
int lockd_global(struct cmd_context *cmd, const char *def_mode);
|
||||
int lockd_gl_create(struct cmd_context *cmd, const char *def_mode, const char *vg_lock_type);
|
||||
int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags);
|
||||
int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
|
||||
uint32_t flags, uint32_t *lockd_state);
|
||||
int lockd_vg_update(struct volume_group *vg);
|
||||
@@ -170,7 +169,7 @@ static inline int lockd_start_wait(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lockd_global_create(struct cmd_context *cmd, const char *def_mode, const char *vg_lock_type)
|
||||
static inline int lockd_gl_create(struct cmd_context *cmd, const char *def_mode, const char *vg_lock_type)
|
||||
{
|
||||
/*
|
||||
* When lvm is built without lvmlockd support, creating a VG with
|
||||
@@ -183,7 +182,7 @@ static inline int lockd_global_create(struct cmd_context *cmd, const char *def_m
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int lockd_global(struct cmd_context *cmd, const char *def_mode)
|
||||
static inline int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@@ -245,11 +245,6 @@ char *lvseg_kernel_discards_dup_with_info_and_seg_status(struct dm_pool *mem, co
|
||||
return 0;
|
||||
}
|
||||
s = get_pool_discards_name(d);
|
||||
} else if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
|
||||
if (lvdm->seg_status.cache->feature_flags &
|
||||
DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN) {
|
||||
s = "nopassdown";
|
||||
}
|
||||
}
|
||||
|
||||
if (!(ret = dm_pool_strdup(mem, s))) {
|
||||
|
@@ -7365,7 +7365,7 @@ int wipe_lv(struct logical_volume *lv, struct wipe_params wp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!label_scan_open_rw(dev)) {
|
||||
if (!label_scan_open(dev)) {
|
||||
log_error("Failed to open %s/%s for wiping and zeroing.", lv->vg->name, lv->name);
|
||||
goto out;
|
||||
}
|
||||
|
@@ -186,6 +186,7 @@
|
||||
#define READ_WARN_INCONSISTENT 0x00080000U
|
||||
#define READ_FOR_UPDATE 0x00100000U /* A meta-flag, useful with toollib for_each_* functions. */
|
||||
#define PROCESS_SKIP_SCAN 0x00200000U /* skip lvmcache_label_scan in process_each_pv */
|
||||
#define PROCESS_SKIP_ORPHAN_LOCK 0x00400000U /* skip lock_vol(VG_ORPHAN) in vg_read */
|
||||
|
||||
/* vg_read returns these in error_flags */
|
||||
#define FAILED_NOT_ENABLED 0x00000001U
|
||||
@@ -696,12 +697,16 @@ int unlink_lv_from_vg(struct logical_volume *lv);
|
||||
void lv_set_visible(struct logical_volume *lv);
|
||||
void lv_set_hidden(struct logical_volume *lv);
|
||||
|
||||
int get_vgnameids(struct cmd_context *cmd, struct dm_list *vgnameids,
|
||||
const char *only_this_vgname, int include_internal);
|
||||
|
||||
int pv_write(struct cmd_context *cmd, struct physical_volume *pv, int allow_non_orphan);
|
||||
int move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
|
||||
const char *pv_name);
|
||||
int move_pvs_used_by_lv(struct volume_group *vg_from,
|
||||
struct volume_group *vg_to,
|
||||
const char *lv_name);
|
||||
int is_global_vg(const char *vg_name);
|
||||
int is_orphan_vg(const char *vg_name);
|
||||
int is_real_vg(const char *vg_name);
|
||||
int vg_missing_pv_count(const struct volume_group *vg);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -250,7 +250,7 @@ struct name_list {
|
||||
|
||||
struct mda_list {
|
||||
struct dm_list list;
|
||||
struct metadata_area *mda;
|
||||
struct device_area mda;
|
||||
};
|
||||
|
||||
struct peg_list {
|
||||
|
@@ -6471,7 +6471,7 @@ int lv_raid_convert(struct logical_volume *lv,
|
||||
return_0;
|
||||
|
||||
region_size = new_region_size ? : seg->region_size;
|
||||
region_size = region_size ? : (uint32_t)get_default_region_size(lv->vg->cmd);
|
||||
region_size = region_size ? : get_default_region_size(lv->vg->cmd);
|
||||
|
||||
/*
|
||||
* Check acceptible options mirrors, region_size,
|
||||
|
964
lib/metadata/read.c
Normal file
964
lib/metadata/read.c
Normal file
@@ -0,0 +1,964 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/device/device.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/misc/lvm-string.h"
|
||||
#include "lib/misc/lvm-file.h"
|
||||
#include "lib/cache/lvmcache.h"
|
||||
#include "lib/mm/memlock.h"
|
||||
#include "lib/datastruct/str_list.h"
|
||||
#include "lib/metadata/pv_alloc.h"
|
||||
#include "lib/metadata/segtype.h"
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/display/display.h"
|
||||
#include "lib/locking/locking.h"
|
||||
#include "lib/format_text/archiver.h"
|
||||
#include "lib/format_text/format-text.h"
|
||||
#include "lib/format_text/layout.h"
|
||||
#include "lib/format_text/import-export.h"
|
||||
#include "lib/config/defaults.h"
|
||||
#include "lib/locking/lvmlockd.h"
|
||||
#include "lib/notify/lvmnotify.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
static int _check_pv_ext(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
uint32_t ext_version, ext_flags;
|
||||
struct pv_list *pvl;
|
||||
|
||||
if (vg_is_foreign(vg))
|
||||
return 1;
|
||||
|
||||
if (vg_is_shared(vg))
|
||||
return 1;
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (is_missing_pv(pvl->pv))
|
||||
continue;
|
||||
|
||||
/* is_missing_pv doesn't catch NULL dev */
|
||||
if (!pvl->pv->dev)
|
||||
continue;
|
||||
|
||||
if (!(info = lvmcache_info_from_pvid(pvl->pv->dev->pvid, pvl->pv->dev, 0)))
|
||||
continue;
|
||||
|
||||
ext_version = lvmcache_ext_version(info);
|
||||
if (ext_version < PV_HEADER_EXTENSION_VSN) {
|
||||
log_warn("WARNING: PV %s in VG %s is using an old PV header, modify the VG to update.",
|
||||
dev_name(pvl->pv->dev), vg->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
ext_flags = lvmcache_ext_flags(info);
|
||||
if (!(ext_flags & PV_EXT_USED)) {
|
||||
log_warn("WARNING: PV %s in VG %s is missing the used flag in PV header.",
|
||||
dev_name(pvl->pv->dev), vg->name);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define DEV_LIST_DELIM ", "
|
||||
|
||||
static int _check_devs_used_correspond_with_lv(struct dm_pool *mem, struct dm_list *list, struct logical_volume *lv)
|
||||
{
|
||||
struct device_list *dl;
|
||||
int found_inconsistent = 0;
|
||||
struct device *dev;
|
||||
struct lv_segment *seg;
|
||||
uint32_t s;
|
||||
int warned_about_no_dev = 0;
|
||||
char *used_devnames = NULL, *assumed_devnames = NULL;
|
||||
|
||||
if (!(list = dev_cache_get_dev_list_for_lvid(lv->lvid.s + ID_LEN)))
|
||||
return 1;
|
||||
|
||||
dm_list_iterate_items(dl, list) {
|
||||
dev = dl->dev;
|
||||
if (!(dev->flags & DEV_ASSUMED_FOR_LV)) {
|
||||
if (!found_inconsistent) {
|
||||
if (!dm_pool_begin_object(mem, 32))
|
||||
return_0;
|
||||
found_inconsistent = 1;
|
||||
} else {
|
||||
if (!dm_pool_grow_object(mem, DEV_LIST_DELIM, sizeof(DEV_LIST_DELIM) - 1))
|
||||
return_0;
|
||||
}
|
||||
if (!dm_pool_grow_object(mem, dev_name(dev), 0))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_inconsistent)
|
||||
return 1;
|
||||
|
||||
if (!dm_pool_grow_object(mem, "\0", 1))
|
||||
return_0;
|
||||
used_devnames = dm_pool_end_object(mem);
|
||||
|
||||
found_inconsistent = 0;
|
||||
dm_list_iterate_items(seg, &lv->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg_type(seg, s) == AREA_PV) {
|
||||
if (!(dev = seg_dev(seg, s))) {
|
||||
if (!warned_about_no_dev) {
|
||||
log_warn("WARNING: Couldn't find all devices for LV %s "
|
||||
"while checking used and assumed devices.",
|
||||
display_lvname(lv));
|
||||
warned_about_no_dev = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!(dev->flags & DEV_USED_FOR_LV)) {
|
||||
if (!found_inconsistent) {
|
||||
if (!dm_pool_begin_object(mem, 32))
|
||||
return_0;
|
||||
found_inconsistent = 1;
|
||||
} else {
|
||||
if (!dm_pool_grow_object(mem, DEV_LIST_DELIM, sizeof(DEV_LIST_DELIM) - 1))
|
||||
return_0;
|
||||
}
|
||||
if (!dm_pool_grow_object(mem, dev_name(dev), 0))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found_inconsistent) {
|
||||
if (!dm_pool_grow_object(mem, "\0", 1))
|
||||
return_0;
|
||||
assumed_devnames = dm_pool_end_object(mem);
|
||||
log_warn("WARNING: Device mismatch detected for %s which is accessing %s instead of %s.",
|
||||
display_lvname(lv), used_devnames, assumed_devnames);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _check_devs_used_correspond_with_vg(struct volume_group *vg)
|
||||
{
|
||||
struct dm_pool *mem;
|
||||
char vgid[ID_LEN + 1];
|
||||
struct pv_list *pvl;
|
||||
struct lv_list *lvl;
|
||||
struct dm_list *list;
|
||||
struct device_list *dl;
|
||||
int found_inconsistent = 0;
|
||||
|
||||
strncpy(vgid, (const char *) vg->id.uuid, sizeof(vgid));
|
||||
vgid[ID_LEN] = '\0';
|
||||
|
||||
/* Mark all PVs in VG as used. */
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
/*
|
||||
* FIXME: It's not clear if the meaning
|
||||
* of "missing" should always include the
|
||||
* !pv->dev case, or if "missing" is the
|
||||
* more narrow case where VG metadata has
|
||||
* been written with the MISSING flag.
|
||||
*/
|
||||
if (!pvl->pv->dev)
|
||||
continue;
|
||||
if (is_missing_pv(pvl->pv))
|
||||
continue;
|
||||
pvl->pv->dev->flags |= DEV_ASSUMED_FOR_LV;
|
||||
}
|
||||
|
||||
if (!(list = dev_cache_get_dev_list_for_vgid(vgid)))
|
||||
return;
|
||||
|
||||
dm_list_iterate_items(dl, list) {
|
||||
if (!(dl->dev->flags & DEV_OPEN_FAILURE) &&
|
||||
!(dl->dev->flags & DEV_ASSUMED_FOR_LV)) {
|
||||
found_inconsistent = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_inconsistent) {
|
||||
if (!(mem = dm_pool_create("vg_devs_check", 1024)))
|
||||
return;
|
||||
|
||||
dm_list_iterate_items(lvl, &vg->lvs) {
|
||||
if (!_check_devs_used_correspond_with_lv(mem, list, lvl->lv)) {
|
||||
dm_pool_destroy(mem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dm_pool_destroy(mem);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void _destroy_fid(struct format_instance **fid)
|
||||
{
|
||||
if (*fid) {
|
||||
(*fid)->fmt->ops->destroy_instance(*fid);
|
||||
*fid = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int _access_vg_clustered(struct cmd_context *cmd, const struct volume_group *vg)
|
||||
{
|
||||
if (vg_is_clustered(vg)) {
|
||||
/*
|
||||
* force_access_clustered is only set when forcibly
|
||||
* converting a clustered vg to lock type none.
|
||||
*/
|
||||
if (cmd->force_access_clustered) {
|
||||
log_debug("Allowing forced access to clustered vg %s", vg->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_verbose("Skipping clustered VG %s.", vg->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _allow_extra_system_id(struct cmd_context *cmd, const char *system_id)
|
||||
{
|
||||
const struct dm_config_node *cn;
|
||||
const struct dm_config_value *cv;
|
||||
const char *str;
|
||||
|
||||
if (!(cn = find_config_tree_array(cmd, local_extra_system_ids_CFG, NULL)))
|
||||
return 0;
|
||||
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type == DM_CFG_EMPTY_ARRAY)
|
||||
break;
|
||||
/* Ignore invalid data: Warning message already issued by config.c */
|
||||
if (cv->type != DM_CFG_STRING)
|
||||
continue;
|
||||
str = cv->v.str;
|
||||
if (!*str)
|
||||
continue;
|
||||
|
||||
if (!strcmp(str, system_id))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _access_vg_lock_type(struct cmd_context *cmd, struct volume_group *vg,
|
||||
uint32_t lockd_state, uint32_t *failure)
|
||||
{
|
||||
if (cmd->lockd_vg_disable)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Local VG requires no lock from lvmlockd.
|
||||
*/
|
||||
if (!vg_is_shared(vg))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* When lvmlockd is not used, lockd VGs are ignored by lvm
|
||||
* and cannot be used, with two exceptions:
|
||||
*
|
||||
* . The --shared option allows them to be revealed with
|
||||
* reporting/display commands.
|
||||
*
|
||||
* . If a command asks to operate on one specifically
|
||||
* by name, then an error is printed.
|
||||
*/
|
||||
if (!lvmlockd_use()) {
|
||||
/*
|
||||
* Some reporting/display commands have the --shared option
|
||||
* (like --foreign) to allow them to reveal lockd VGs that
|
||||
* are otherwise ignored. The --shared option must only be
|
||||
* permitted in commands that read the VG for report or display,
|
||||
* not any that write the VG or activate LVs.
|
||||
*/
|
||||
if (cmd->include_shared_vgs)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Some commands want the error printed by vg_read, others by ignore_vg.
|
||||
* Those using ignore_vg may choose to skip the error.
|
||||
*/
|
||||
if (cmd->vg_read_print_access_error) {
|
||||
log_error("Cannot access VG %s with lock type %s that requires lvmlockd.",
|
||||
vg->name, vg->lock_type);
|
||||
}
|
||||
|
||||
*failure |= FAILED_LOCK_TYPE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lock request from lvmlockd failed. If the lock was ex,
|
||||
* we cannot continue. If the lock was sh, we could also fail
|
||||
* to continue but since the lock was sh, it means the VG is
|
||||
* only being read, and it doesn't hurt to allow reading with
|
||||
* no lock.
|
||||
*/
|
||||
if (lockd_state & LDST_FAIL) {
|
||||
if ((lockd_state & LDST_EX) || cmd->lockd_vg_enforce_sh) {
|
||||
log_error("Cannot access VG %s due to failed lock.", vg->name);
|
||||
*failure |= FAILED_LOCK_MODE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_warn("Reading VG %s without a lock.", vg->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (test_mode()) {
|
||||
log_error("Test mode is not yet supported with lock type %s.", vg->lock_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_system_id_allowed(struct cmd_context *cmd, const char *system_id)
|
||||
{
|
||||
/*
|
||||
* A VG without a system_id can be accessed by anyone.
|
||||
*/
|
||||
if (!system_id || !system_id[0])
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Allowed if the host and VG system_id's match.
|
||||
*/
|
||||
if (cmd->system_id && !strcmp(cmd->system_id, system_id))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Allowed if a host's extra system_id matches.
|
||||
*/
|
||||
if (cmd->system_id && _allow_extra_system_id(cmd, system_id))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Not allowed if the host does not have a system_id
|
||||
* and the VG does, or if the host and VG's system_id's
|
||||
* do not match.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _access_vg_systemid(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
/*
|
||||
* A few commands allow read-only access to foreign VGs.
|
||||
*/
|
||||
if (cmd->include_foreign_vgs)
|
||||
return 1;
|
||||
|
||||
if (is_system_id_allowed(cmd, vg->system_id))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Allow VG access if the local host has active LVs in it.
|
||||
*/
|
||||
if (lvs_in_vg_activated(vg)) {
|
||||
log_warn("WARNING: Found LVs active in VG %s with foreign system ID %s. Possible data corruption.",
|
||||
vg->name, vg->system_id);
|
||||
if (cmd->include_active_foreign_vgs)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an error when reading a VG that has a system_id
|
||||
* and the host system_id is unknown.
|
||||
*/
|
||||
if (!cmd->system_id || cmd->unknown_system_id) {
|
||||
log_error("Cannot access VG %s with system ID %s with unknown local system ID.",
|
||||
vg->name, vg->system_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some commands want the error printed by vg_read, others by ignore_vg.
|
||||
* Those using ignore_vg may choose to skip the error.
|
||||
*/
|
||||
if (cmd->vg_read_print_access_error) {
|
||||
log_error("Cannot access VG %s with system ID %s with local system ID %s.",
|
||||
vg->name, vg->system_id, cmd->system_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Silently ignore foreign vgs. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
const char *vgname,
|
||||
const char *vgid,
|
||||
unsigned precommitted)
|
||||
{
|
||||
const struct format_type *fmt = cmd->fmt;
|
||||
struct format_instance *fid = NULL;
|
||||
struct format_instance_ctx fic;
|
||||
struct volume_group *vg, *vg_ret = NULL;
|
||||
struct metadata_area *mda, *mda2;
|
||||
unsigned use_precommitted = precommitted;
|
||||
struct device *mda_dev, *dev_ret;
|
||||
struct cached_vg_fmtdata *vg_fmtdata = NULL; /* Additional format-specific data about the vg */
|
||||
int found_old_metadata = 0;
|
||||
unsigned use_previous_vg;
|
||||
|
||||
log_debug_metadata("Reading VG %s %s", vgname ?: "<no name>", vgid ?: "<no vgid>");
|
||||
|
||||
/*
|
||||
* Rescan the devices that are associated with this vg in lvmcache.
|
||||
* This repeats what was done by the command's initial label scan,
|
||||
* but only the devices associated with this VG.
|
||||
*
|
||||
* The lvmcache info about these devs is from the initial label scan
|
||||
* performed by the command before the vg lock was held. Now the VG
|
||||
* lock is held, so we rescan all the info from the devs in case
|
||||
* something changed between the initial scan and now that the lock
|
||||
* is held.
|
||||
*
|
||||
* Some commands (e.g. reporting) are fine reporting data read by
|
||||
* the label scan. It doesn't matter if the devs changed between
|
||||
* the label scan and here, we can report what was seen in the
|
||||
* scan, even though it is the old state, since we will not be
|
||||
* making any modifications. If the VG was being modified during
|
||||
* the scan, and caused us to see inconsistent metadata on the
|
||||
* different PVs in the VG, then we do want to rescan the devs
|
||||
* here to get a consistent view of the VG. Note that we don't
|
||||
* know if the scan found all the PVs in the VG at this point.
|
||||
* We don't know that until vg_read looks at the list of PVs in
|
||||
* the metadata and compares that to the devices found by the scan.
|
||||
*
|
||||
* It's possible that a change made to the VG during scan was
|
||||
* adding or removing a PV from the VG. In this case, the list
|
||||
* of devices associated with the VG in lvmcache would change
|
||||
* due to the rescan.
|
||||
*
|
||||
* The devs in the VG may be persistently inconsistent due to some
|
||||
* previous problem. In this case, rescanning the labels here will
|
||||
* find the same inconsistency. The VG repair (mistakenly done by
|
||||
* vg_read below) is supposed to fix that.
|
||||
*
|
||||
* FIXME: sort out the usage of the global lock (which is mixed up
|
||||
* with the orphan lock), and when we can tell that the global
|
||||
* lock is taken prior to the label scan, and still held here,
|
||||
* we can also skip the rescan in that case.
|
||||
*/
|
||||
if (!cmd->can_use_one_scan || lvmcache_scan_mismatch(cmd, vgname, vgid)) {
|
||||
log_debug_metadata("Rescanning devices for %s", vgname);
|
||||
lvmcache_label_rescan_vg(cmd, vgname, vgid);
|
||||
} else {
|
||||
log_debug_metadata("Skipped rescanning devices for %s", vgname);
|
||||
}
|
||||
|
||||
/* Now determine the correct vgname if none was supplied */
|
||||
if (!vgname && !(vgname = lvmcache_vgname_from_vgid(cmd->mem, vgid))) {
|
||||
log_debug_metadata("Cache did not find VG name from vgid %s", vgid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Determine the correct vgid if none was supplied */
|
||||
if (!vgid && !(vgid = lvmcache_vgid_from_vgname(cmd, vgname))) {
|
||||
log_debug_metadata("Cache did not find VG vgid from name %s", vgname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* A "format instance" is an abstraction for a VG location,
|
||||
* i.e. where a VG's metadata exists on disk.
|
||||
*
|
||||
* An fic (format_instance_ctx) is a temporary struct used
|
||||
* to create an fid (format_instance). The fid hangs around
|
||||
* and is used to create a 'vg' to which it connected (vg->fid).
|
||||
*
|
||||
* The 'fic' describes a VG in terms of fmt/name/id.
|
||||
*
|
||||
* The 'fid' describes a VG in more detail than the fic,
|
||||
* holding information about where to find the VG metadata.
|
||||
*
|
||||
* The 'vg' describes the VG in the most detail representing
|
||||
* all the VG metadata.
|
||||
*
|
||||
* The fic and fid are set up by create_instance() to describe
|
||||
* the VG location. This happens before the VG metadata is
|
||||
* assembled into the more familiar struct volume_group "vg".
|
||||
*
|
||||
* The fid has one main purpose: to keep track of the metadata
|
||||
* locations for a given VG. It does this by putting 'mda'
|
||||
* structs on fid->metadata_areas_in_use, which specify where
|
||||
* metadata is located on disk. It gets this information
|
||||
* (metadata locations for a specific VG) from the command's
|
||||
* initial label scan. The info is passed indirectly via
|
||||
* lvmcache info/vginfo structs, which are created by the
|
||||
* label scan and then copied into fid by create_instance().
|
||||
*
|
||||
* FIXME: just use the vginfo/info->mdas lists directly instead
|
||||
* of copying them into the fid list.
|
||||
*/
|
||||
|
||||
fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
|
||||
fic.context.vg_ref.vg_name = vgname;
|
||||
fic.context.vg_ref.vg_id = vgid;
|
||||
|
||||
/*
|
||||
* Sets up the metadata areas that we need to read below.
|
||||
* For each info in vginfo->infos, for each mda in info->mdas,
|
||||
* (found during label_scan), copy the mda to fid->metadata_areas_in_use
|
||||
*/
|
||||
if (!(fid = fmt->ops->create_instance(fmt, &fic))) {
|
||||
log_error("Failed to create format instance");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We use the fid globally here so prevent the release_vg
|
||||
* call to destroy the fid - we may want to reuse it!
|
||||
*/
|
||||
fid->ref_count++;
|
||||
|
||||
|
||||
/*
|
||||
* label_scan found PVs for this VG and set up lvmcache to describe the
|
||||
* VG/PVs that we use here to read the VG. It created 'vginfo' for the
|
||||
* VG, and created an 'info' attached to vginfo for each PV. It also
|
||||
* added a metadata_area struct to info->mdas for each metadata area it
|
||||
* found on the PV. The info->mdas structs are copied to
|
||||
* fid->metadata_areas_in_use by create_instance above, and here we
|
||||
* read VG metadata from each of those mdas.
|
||||
*/
|
||||
dm_list_iterate_items(mda, &fid->metadata_areas_in_use) {
|
||||
mda_dev = mda_get_device(mda);
|
||||
|
||||
/* I don't think this can happen */
|
||||
if (!mda_dev) {
|
||||
log_warn("Ignoring metadata for VG %s from missing dev.", vgname);
|
||||
continue;
|
||||
}
|
||||
|
||||
use_previous_vg = 0;
|
||||
|
||||
if (use_precommitted) {
|
||||
log_debug_metadata("Reading VG %s precommit metadata from %s %llu",
|
||||
vgname, dev_name(mda_dev), (unsigned long long)mda->header_start);
|
||||
|
||||
vg = mda->ops->vg_read_precommit(fid, vgname, mda, &vg_fmtdata, &use_previous_vg);
|
||||
|
||||
if (!vg && !use_previous_vg) {
|
||||
log_warn("WARNING: Reading VG %s precommit on %s failed.", vgname, dev_name(mda_dev));
|
||||
vg_fmtdata = NULL;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
log_debug_metadata("Reading VG %s metadata from %s %llu",
|
||||
vgname, dev_name(mda_dev), (unsigned long long)mda->header_start);
|
||||
|
||||
vg = mda->ops->vg_read(fid, vgname, mda, &vg_fmtdata, &use_previous_vg);
|
||||
|
||||
if (!vg && !use_previous_vg) {
|
||||
log_warn("WARNING: Reading VG %s on %s failed.", vgname, dev_name(mda_dev));
|
||||
vg_fmtdata = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vg)
|
||||
continue;
|
||||
|
||||
if (vg && !vg_ret) {
|
||||
vg_ret = vg;
|
||||
dev_ret = mda_dev;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the newest copy of the metadata found on any mdas.
|
||||
* Above, We could check if the scan found an old metadata
|
||||
* seqno in this mda and just skip reading it again; then these
|
||||
* seqno checks would just be sanity checks.
|
||||
*/
|
||||
|
||||
if (vg->seqno == vg_ret->seqno) {
|
||||
release_vg(vg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vg->seqno > vg_ret->seqno) {
|
||||
log_warn("WARNING: ignoring metadata seqno %u on %s for seqno %u on %s for VG %s.",
|
||||
vg_ret->seqno, dev_name(dev_ret),
|
||||
vg->seqno, dev_name(mda_dev), vg->name);
|
||||
found_old_metadata = 1;
|
||||
release_vg(vg_ret);
|
||||
vg_ret = vg;
|
||||
dev_ret = mda_dev;
|
||||
vg_fmtdata = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vg_ret->seqno > vg->seqno) {
|
||||
log_warn("WARNING: ignoring metadata seqno %u on %s for seqno %u on %s for VG %s.",
|
||||
vg->seqno, dev_name(mda_dev),
|
||||
vg_ret->seqno, dev_name(dev_ret), vg->name);
|
||||
found_old_metadata = 1;
|
||||
release_vg(vg);
|
||||
vg_fmtdata = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_old_metadata)
|
||||
log_warn("WARNING: Inconsistent metadata found for VG %s", vgname);
|
||||
|
||||
vg = NULL;
|
||||
|
||||
if (vg_ret)
|
||||
set_pv_devices(fid, vg_ret);
|
||||
|
||||
fid->ref_count--;
|
||||
|
||||
if (!vg_ret) {
|
||||
_destroy_fid(&fid);
|
||||
goto_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Correct the lvmcache representation of the VG using the metadata
|
||||
* that we have chosen above (vg_ret).
|
||||
*
|
||||
* The vginfo/info representation created by label_scan was not
|
||||
* entirely correct since it did not use the full or final metadata.
|
||||
*
|
||||
* In lvmcache, PVs with no mdas were not attached to the vginfo during
|
||||
* label_scan because label_scan didn't know where they should go. Now
|
||||
* that we have the VG metadata we can tell, so use that to attach those
|
||||
* info's to the vginfo.
|
||||
*
|
||||
* Also, outdated PVs that have been removed from the VG were incorrectly
|
||||
* attached to the vginfo during label_scan, and now need to be detached.
|
||||
*/
|
||||
lvmcache_update_vg_from_read(vg_ret, vg_ret->status & PRECOMMITTED);
|
||||
|
||||
/*
|
||||
* lvmcache_update_vg identified outdated mdas that we read above that
|
||||
* are not actually part of the VG. Remove those outdated mdas from
|
||||
* the fid's list of mdas.
|
||||
*/
|
||||
dm_list_iterate_items_safe(mda, mda2, &fid->metadata_areas_in_use) {
|
||||
mda_dev = mda_get_device(mda);
|
||||
if (lvmcache_is_outdated_dev(cmd, vg_ret->name, (const char *)&vg_ret->id, mda_dev)) {
|
||||
log_debug_metadata("vg_read %s ignore mda for outdated dev %s",
|
||||
vg_ret->name, dev_name(mda_dev));
|
||||
dm_list_del(&mda->list);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return vg_ret;
|
||||
}
|
||||
|
||||
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const char *vgid,
|
||||
uint32_t read_flags, uint32_t lockd_state,
|
||||
uint32_t *error_flags, struct volume_group **error_vg)
|
||||
{
|
||||
char uuidstr[64] __attribute__((aligned(8)));
|
||||
struct volume_group *vg = NULL;
|
||||
struct lv_list *lvl;
|
||||
struct pv_list *pvl;
|
||||
int missing_pv_dev = 0;
|
||||
int missing_pv_flag = 0;
|
||||
uint32_t failure = 0;
|
||||
int writing = (read_flags & READ_FOR_UPDATE);
|
||||
|
||||
/*
|
||||
* FIXME: is this function still used to read orphans?
|
||||
* If so, replace any callers with vg_read_orphans.
|
||||
*/
|
||||
if (is_orphan_vg(vg_name)) {
|
||||
int skip_lock = read_flags & PROCESS_SKIP_ORPHAN_LOCK;
|
||||
log_very_verbose("Reading orphan VG %s", vg_name);
|
||||
|
||||
if (!skip_lock && !lock_vol(cmd, vg_name, LCK_VG_READ, NULL))
|
||||
return_NULL;
|
||||
|
||||
vg = vg_read_orphans(cmd, vg_name);
|
||||
|
||||
if (!skip_lock)
|
||||
unlock_vg(cmd, vg, vg_name);
|
||||
|
||||
*error_flags = 0;
|
||||
*error_vg = NULL;
|
||||
return vg;
|
||||
}
|
||||
|
||||
if (!validate_name(vg_name)) {
|
||||
log_error("Volume group name \"%s\" has invalid characters.", vg_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!lock_vol(cmd, vg_name, writing ? LCK_VG_WRITE : LCK_VG_READ, NULL)) {
|
||||
log_error("Can't get lock for %s", vg_name);
|
||||
failure |= FAILED_LOCKING;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (!(vg = _vg_read(cmd, vg_name, vgid, 0))) {
|
||||
/* Some callers don't care if the VG doesn't exist and don't want an error message. */
|
||||
if (!(read_flags & READ_OK_NOTFOUND))
|
||||
log_error("Volume group \"%s\" not found", vg_name);
|
||||
failure |= FAILED_NOTFOUND;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check and warn if PV ext info is not in sync with VG metadata
|
||||
* (vg_write fixes.)
|
||||
*/
|
||||
_check_pv_ext(cmd, vg);
|
||||
|
||||
if (!vg_strip_outdated_historical_lvs(vg))
|
||||
log_warn("WARNING: failed to strip outdated historical lvs.");
|
||||
|
||||
/*
|
||||
* Check for missing devices in the VG. In most cases a VG cannot be
|
||||
* changed while it's missing devices. This restriction is implemented
|
||||
* here in vg_read. Below we return an error from vg_read if the
|
||||
* vg_read flag indicates that the command is going to modify the VG.
|
||||
* (We should probably implement this restriction elsewhere instead of
|
||||
* returning an error from vg_read.)
|
||||
*
|
||||
* The PV's device may be present while the PV for the device has the
|
||||
* MISSING_PV flag set in the metadata. This happened because the VG
|
||||
* was written while this dev was missing, so the MISSING flag was
|
||||
* written in the metadata for PV. Now the device has reappeared.
|
||||
* However, the VG has changed since the device was last present, and
|
||||
* if the device has outdated data it may not be safe to just start
|
||||
* using it again.
|
||||
*
|
||||
* If there were no PE's used on the PV, we can just clear the MISSING
|
||||
* flag, but if there were PE's used we need to continue to treat the
|
||||
* PV as if the device is missing, limiting operations like the VG has
|
||||
* a missing device, and requiring the user to remove the reappeared
|
||||
* device from the VG, like a missing device, with vgreduce
|
||||
* --removemissing.
|
||||
*/
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!id_write_format(&pvl->pv->id, uuidstr, sizeof(uuidstr)))
|
||||
uuidstr[0] = '\0';
|
||||
|
||||
if (!pvl->pv->dev) {
|
||||
/* The obvious and common case of a missing device. */
|
||||
|
||||
log_warn("WARNING: VG %s is missing PV %s.", vg_name, uuidstr);
|
||||
missing_pv_dev++;
|
||||
|
||||
} else if (pvl->pv->status & MISSING_PV) {
|
||||
/* A device that was missing but has reappeared. */
|
||||
|
||||
if (pvl->pv->pe_alloc_count == 0) {
|
||||
log_warn("WARNING: VG %s has unused reappeared PV %s %s.", vg_name, dev_name(pvl->pv->dev), uuidstr);
|
||||
pvl->pv->status &= ~MISSING_PV;
|
||||
/* tell vgextend restoremissing that MISSING flag was cleared here */
|
||||
pvl->pv->unused_missing_cleared = 1;
|
||||
} else {
|
||||
log_warn("WARNING: VG %s was missing PV %s %s.", vg_name, dev_name(pvl->pv->dev), uuidstr);
|
||||
missing_pv_flag++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_pv_dev || missing_pv_flag)
|
||||
vg_mark_partial_lvs(vg, 1);
|
||||
|
||||
if (!check_pv_segments(vg)) {
|
||||
log_error(INTERNAL_ERROR "PV segments corrupted in %s.", vg->name);
|
||||
failure |= FAILED_INTERNAL_ERROR;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(lvl, &vg->lvs) {
|
||||
if (!check_lv_segments(lvl->lv, 0)) {
|
||||
log_error(INTERNAL_ERROR "LV segments corrupted in %s.", lvl->lv->name);
|
||||
failure |= FAILED_INTERNAL_ERROR;
|
||||
goto_bad;
|
||||
}
|
||||
}
|
||||
|
||||
dm_list_iterate_items(lvl, &vg->lvs) {
|
||||
/* Checks that cross-reference other LVs. */
|
||||
if (!check_lv_segments(lvl->lv, 1)) {
|
||||
log_error(INTERNAL_ERROR "LV segments corrupted in %s.", lvl->lv->name);
|
||||
failure |= FAILED_INTERNAL_ERROR;
|
||||
goto_bad;
|
||||
}
|
||||
}
|
||||
|
||||
if (!check_pv_dev_sizes(vg))
|
||||
log_warn("WARNING: One or more devices used as PVs in VG %s have changed sizes.", vg->name);
|
||||
|
||||
_check_devs_used_correspond_with_vg(vg);
|
||||
|
||||
if (!_access_vg_lock_type(cmd, vg, lockd_state, &failure)) {
|
||||
/* Either FAILED_LOCK_TYPE or FAILED_LOCK_MODE were set. */
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (!_access_vg_systemid(cmd, vg)) {
|
||||
failure |= FAILED_SYSTEMID;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (!_access_vg_clustered(cmd, vg)) {
|
||||
failure |= FAILED_CLUSTERED;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (writing && !(read_flags & READ_ALLOW_EXPORTED) && vg_is_exported(vg)) {
|
||||
log_error("Volume group %s is exported", vg->name);
|
||||
failure |= FAILED_EXPORTED;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (writing && !(vg->status & LVM_WRITE)) {
|
||||
log_error("Volume group %s is read-only", vg->name);
|
||||
failure |= FAILED_READ_ONLY;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (!cmd->handles_missing_pvs && (missing_pv_dev || missing_pv_flag) && writing) {
|
||||
log_error("Cannot change VG %s while PVs are missing.", vg->name);
|
||||
log_error("See vgreduce --removemissing and vgextend --restoremissing.");
|
||||
failure |= FAILED_NOT_ENABLED;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (!cmd->handles_unknown_segments && vg_has_unknown_segments(vg) && writing) {
|
||||
log_error("Cannot change VG %s with unknown segments in it!", vg->name);
|
||||
failure |= FAILED_NOT_ENABLED; /* FIXME new failure code here? */
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we are reading the VG with the intention of writing it,
|
||||
* we save a second copy of the VG in vg->vg_committed. This
|
||||
* copy remains unmodified by the command operation, and is used
|
||||
* later if there is an error and we want to reactivate LVs.
|
||||
* FIXME: be specific about exactly when this works correctly.
|
||||
*/
|
||||
if (writing) {
|
||||
struct dm_config_tree *cft;
|
||||
|
||||
if (dm_pool_locked(vg->vgmem)) {
|
||||
/* FIXME: can this happen? */
|
||||
log_warn("WARNING: vg_read no vg copy: pool locked");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vg->vg_committed) {
|
||||
/* FIXME: can this happen? */
|
||||
log_warn("WARNING: vg_read no vg copy: copy exists");
|
||||
release_vg(vg->vg_committed);
|
||||
vg->vg_committed = NULL;
|
||||
}
|
||||
|
||||
if (vg->vg_precommitted) {
|
||||
/* FIXME: can this happen? */
|
||||
log_warn("WARNING: vg_read no vg copy: pre copy exists");
|
||||
release_vg(vg->vg_precommitted);
|
||||
vg->vg_precommitted = NULL;
|
||||
}
|
||||
|
||||
if (!(cft = export_vg_to_config_tree(vg))) {
|
||||
log_warn("WARNING: vg_read no vg copy: copy export failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(vg->vg_committed = import_vg_from_config_tree(cft, vg->fid)))
|
||||
log_warn("WARNING: vg_read no vg copy: copy import failed");
|
||||
|
||||
dm_config_destroy(cft);
|
||||
} else {
|
||||
if (vg->vg_precommitted)
|
||||
log_error(INTERNAL_ERROR "vg_read vg %p vg_precommitted %p", vg, vg->vg_precommitted);
|
||||
if (vg->vg_committed)
|
||||
log_error(INTERNAL_ERROR "vg_read vg %p vg_committed %p", vg, vg->vg_committed);
|
||||
}
|
||||
out:
|
||||
/* We return with the VG lock held when read is successful. */
|
||||
*error_flags = SUCCESS;
|
||||
if (error_vg)
|
||||
*error_vg = NULL;
|
||||
return vg;
|
||||
|
||||
bad:
|
||||
*error_flags = failure;
|
||||
|
||||
/*
|
||||
* FIXME: get rid of this case so we don't have to return the vg when
|
||||
* there's an error. It is here for process_each_pv() which wants to
|
||||
* eliminate the VG's devs from the list of devs it is processing, even
|
||||
* when it can't access the VG because of wrong system id or similar.
|
||||
* This could be done by looking at lvmcache info structs intead of 'vg'.
|
||||
* It's also used by process_each_vg/process_each_lv which want to
|
||||
* include error_vg values (like system_id) in error messages.
|
||||
* These values could also be found from lvmcache vginfo.
|
||||
*/
|
||||
if (error_vg && vg) {
|
||||
if (vg->vg_precommitted)
|
||||
log_error(INTERNAL_ERROR "vg_read vg %p vg_precommitted %p", vg, vg->vg_precommitted);
|
||||
if (vg->vg_committed)
|
||||
log_error(INTERNAL_ERROR "vg_read vg %p vg_committed %p", vg, vg->vg_committed);
|
||||
|
||||
/* caller must unlock_vg and release_vg */
|
||||
*error_vg = vg;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
if (vg) {
|
||||
unlock_vg(cmd, vg, vg_name);
|
||||
release_vg(vg);
|
||||
}
|
||||
if (error_vg)
|
||||
*error_vg = NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Simply a version of vg_read() that automatically sets the READ_FOR_UPDATE
|
||||
* flag, which means the caller intends to write the VG after reading it,
|
||||
* so vg_read should acquire an exclusive file lock on the vg.
|
||||
*/
|
||||
struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_name,
|
||||
const char *vgid, uint32_t read_flags, uint32_t lockd_state)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
uint32_t error_flags = 0;
|
||||
|
||||
vg = vg_read(cmd, vg_name, vgid, read_flags | READ_FOR_UPDATE, lockd_state, &error_flags, NULL);
|
||||
|
||||
return vg;
|
||||
}
|
@@ -56,20 +56,6 @@ static void _undo_flock(const char *file, int fd)
|
||||
log_sys_debug("close", file);
|
||||
}
|
||||
|
||||
static struct lock_list *_get_lock_list_entry(const char *file)
|
||||
{
|
||||
struct lock_list *ll;
|
||||
struct dm_list *llh;
|
||||
|
||||
dm_list_iterate(llh, &_lock_list) {
|
||||
ll = dm_list_item(llh, struct lock_list);
|
||||
|
||||
if (!strcmp(ll->res, file))
|
||||
return ll;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _release_lock(const char *file, int unlock)
|
||||
{
|
||||
struct lock_list *ll;
|
||||
@@ -181,8 +167,8 @@ int lock_file(const char *file, uint32_t flags)
|
||||
{
|
||||
int operation;
|
||||
uint32_t nonblock = flags & LCK_NONBLOCK;
|
||||
uint32_t convert = flags & LCK_CONVERT;
|
||||
int r;
|
||||
|
||||
struct lock_list *ll;
|
||||
char state;
|
||||
|
||||
@@ -202,20 +188,6 @@ int lock_file(const char *file, uint32_t flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (convert) {
|
||||
if (nonblock)
|
||||
operation |= LOCK_NB;
|
||||
if (!(ll = _get_lock_list_entry(file)))
|
||||
return 0;
|
||||
log_very_verbose("Locking %s %c%c convert", ll->res, state,
|
||||
nonblock ? ' ' : 'B');
|
||||
r = flock(ll->lf, operation);
|
||||
if (!r)
|
||||
return 1;
|
||||
log_error("Failed to convert flock on %s %d", file, errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(ll = malloc(sizeof(struct lock_list))))
|
||||
return_0;
|
||||
|
||||
|
@@ -31,6 +31,7 @@ static int _fwraid_filtering = 0;
|
||||
static int _pvmove = 0;
|
||||
static int _obtain_device_list_from_udev = DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV;
|
||||
static enum dev_ext_e _external_device_info_source = DEV_EXT_NONE;
|
||||
static int _trust_cache = 0; /* Don't scan when incomplete VGs encountered */
|
||||
static int _debug_level = 0;
|
||||
static int _debug_classes_logged = 0;
|
||||
static int _security_level = SECURITY_LEVEL;
|
||||
@@ -106,6 +107,11 @@ void init_external_device_info_source(enum dev_ext_e src)
|
||||
_external_device_info_source = src;
|
||||
}
|
||||
|
||||
void init_trust_cache(int trustcache)
|
||||
{
|
||||
_trust_cache = trustcache;
|
||||
}
|
||||
|
||||
void init_security_level(int level)
|
||||
{
|
||||
_security_level = level;
|
||||
@@ -279,6 +285,11 @@ enum dev_ext_e external_device_info_source(void)
|
||||
return _external_device_info_source;
|
||||
}
|
||||
|
||||
int trust_cache(void)
|
||||
{
|
||||
return _trust_cache;
|
||||
}
|
||||
|
||||
int background_polling(void)
|
||||
{
|
||||
return _background_polling;
|
||||
|
@@ -32,6 +32,7 @@ void init_fwraid_filtering(int level);
|
||||
void init_pvmove(int level);
|
||||
void init_external_device_info_source(enum dev_ext_e src);
|
||||
void init_obtain_device_list_from_udev(int device_list_from_udev);
|
||||
void init_trust_cache(int trustcache);
|
||||
void init_debug(int level);
|
||||
void init_debug_classes_logged(int classes);
|
||||
void init_cmd_name(int status);
|
||||
@@ -64,6 +65,7 @@ int fwraid_filtering(void);
|
||||
int pvmove_mode(void);
|
||||
int obtain_device_list_from_udev(void);
|
||||
enum dev_ext_e external_device_info_source(void);
|
||||
int trust_cache(void);
|
||||
int verbose_level(void);
|
||||
int silent_mode(void);
|
||||
int debug_level(void);
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#include "lib/metadata/lv_alloc.h"
|
||||
#include "lib/config/defaults.h"
|
||||
|
||||
static const char _writecache_module[] = "writecache";
|
||||
|
||||
#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;
|
||||
|
@@ -85,7 +85,7 @@ static int _is_idle(daemon_state s)
|
||||
return s.idle && s.idle->is_idle && !s.threads->next;
|
||||
}
|
||||
|
||||
static struct timespec *_get_timeout(daemon_state s)
|
||||
static struct timeval *_get_timeout(daemon_state s)
|
||||
{
|
||||
return s.idle ? s.idle->ptimeout : NULL;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ static void _reset_timeout(daemon_state s)
|
||||
{
|
||||
if (s.idle) {
|
||||
s.idle->ptimeout->tv_sec = 1;
|
||||
s.idle->ptimeout->tv_nsec = 0;
|
||||
s.idle->ptimeout->tv_usec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,8 +559,6 @@ void daemon_start(daemon_state s)
|
||||
thread_state _threads = { .next = NULL };
|
||||
unsigned timeout_count = 0;
|
||||
fd_set in;
|
||||
sigset_t new_set, old_set;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Switch to C locale to avoid reading large locale-archive file used by
|
||||
@@ -628,7 +626,8 @@ void daemon_start(daemon_state s)
|
||||
if (!s.foreground)
|
||||
kill(getppid(), SIGTERM);
|
||||
|
||||
/* * Use daemon_main for daemon-specific init and polling, or
|
||||
/*
|
||||
* Use daemon_main for daemon-specific init and polling, or
|
||||
* use daemon_init for daemon-specific init and generic lib polling.
|
||||
*/
|
||||
|
||||
@@ -642,39 +641,22 @@ void daemon_start(daemon_state s)
|
||||
if (!s.daemon_init(&s))
|
||||
failed = 1;
|
||||
|
||||
if (s.socket_fd >= FD_SETSIZE)
|
||||
failed = 1; /* FD out of available selectable set */
|
||||
|
||||
sigfillset(&new_set);
|
||||
sigprocmask(SIG_SETMASK, NULL, &old_set);
|
||||
|
||||
while (!failed) {
|
||||
_reset_timeout(s);
|
||||
FD_ZERO(&in);
|
||||
FD_SET(s.socket_fd, &in);
|
||||
|
||||
sigprocmask(SIG_SETMASK, &new_set, NULL);
|
||||
if (_shutdown_requested && !s.threads->next) {
|
||||
sigprocmask(SIG_SETMASK, &old_set, NULL);
|
||||
INFO(&s, "%s shutdown requested", s.name);
|
||||
break;
|
||||
}
|
||||
ret = pselect(s.socket_fd + 1, &in, NULL, NULL, _get_timeout(s), &old_set);
|
||||
sigprocmask(SIG_SETMASK, &old_set, NULL);
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN &&
|
||||
(EWOULDBLOCK == EAGAIN || errno != EWOULDBLOCK))
|
||||
perror("select error");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (select(FD_SETSIZE, &in, NULL, NULL, _get_timeout(s)) < 0 && errno != EINTR)
|
||||
perror("select error");
|
||||
if (FD_ISSET(s.socket_fd, &in)) {
|
||||
timeout_count = 0;
|
||||
_handle_connect(s);
|
||||
}
|
||||
|
||||
_reap(s, 0);
|
||||
|
||||
if (_shutdown_requested && !s.threads->next)
|
||||
break;
|
||||
|
||||
/* s.idle == NULL equals no shutdown on timeout */
|
||||
if (_is_idle(s)) {
|
||||
DEBUGLOG(&s, "timeout occured");
|
||||
|
@@ -47,7 +47,7 @@ struct timeval;
|
||||
typedef struct {
|
||||
volatile unsigned is_idle;
|
||||
unsigned max_timeouts;
|
||||
struct timespec *ptimeout;
|
||||
struct timeval *ptimeout;
|
||||
} daemon_idle;
|
||||
|
||||
struct daemon_state;
|
||||
|
@@ -1893,7 +1893,6 @@ int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
|
||||
#define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002
|
||||
#define DM_CACHE_FEATURE_PASSTHROUGH 0x00000004
|
||||
#define DM_CACHE_FEATURE_METADATA2 0x00000008 /* cache v1.10 */
|
||||
#define DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN 0x00000010
|
||||
|
||||
struct dm_config_node;
|
||||
/*
|
||||
|
@@ -51,8 +51,6 @@ struct parser {
|
||||
|
||||
struct dm_pool *mem;
|
||||
int no_dup_node_check; /* whether to disable dup node checking */
|
||||
const char *key; /* last obtained key */
|
||||
unsigned ignored_creation_time;
|
||||
};
|
||||
|
||||
struct config_output {
|
||||
@@ -178,7 +176,7 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
|
||||
/* TODO? if (start == end) return 1; */
|
||||
|
||||
struct parser *p;
|
||||
if (!(p = dm_pool_zalloc(cft->mem, sizeof(*p))))
|
||||
if (!(p = dm_pool_alloc(cft->mem, sizeof(*p))))
|
||||
return_0;
|
||||
|
||||
p->mem = cft->mem;
|
||||
@@ -617,7 +615,6 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
|
||||
match(TOK_SECTION_E);
|
||||
} else {
|
||||
match(TOK_EQ);
|
||||
p->key = root->key;
|
||||
if (!(value = _value(p)))
|
||||
return_NULL;
|
||||
if (root->v)
|
||||
@@ -685,17 +682,8 @@ static struct dm_config_value *_type(struct parser *p)
|
||||
errno = 0;
|
||||
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
|
||||
if (errno) {
|
||||
if (errno == ERANGE && p->key &&
|
||||
strcmp("creation_time", p->key) == 0) {
|
||||
/* Due to a bug in some older 32bit builds (<2.02.169),
|
||||
* lvm was able to produce invalid creation_time string */
|
||||
v->v.i = 1527120000; /* Pick 2018-05-24 day instead */
|
||||
if (!p->ignored_creation_time++)
|
||||
log_warn("WARNING: Invalid creation_time found in metadata (repaired with next metadata update).");
|
||||
} else {
|
||||
log_error("Failed to read int token.");
|
||||
return NULL;
|
||||
}
|
||||
log_error("Failed to read int token.");
|
||||
return NULL;
|
||||
}
|
||||
match(TOK_INT);
|
||||
break;
|
||||
|
@@ -296,8 +296,6 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
|
||||
s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
|
||||
else if (!strncmp(p, "metadata2 ", 10))
|
||||
s->feature_flags |= DM_CACHE_FEATURE_METADATA2;
|
||||
else if (!strncmp(p, "no_discard_passdown ", 20))
|
||||
s->feature_flags |= DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN;
|
||||
else
|
||||
log_error("Unknown feature in status: %s", params);
|
||||
|
||||
|
@@ -16,26 +16,74 @@ lvchange - Change the attributes of logical volume(s)
|
||||
\fB--activationmode\fP \fBpartial\fP|\fBdegraded\fP|\fBcomplete\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--addtag\fP \fITag\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--cachemode\fP \fBwritethrough\fP|\fBwriteback\fP|\fBpassthrough\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--cachepolicy\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--cachesettings\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--compression\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--config\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-C\fP|\fB--contiguous\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-d\fP|\fB--debug\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--deduplication\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--deltag\fP \fITag\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--detachprofile\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--discards\fP \fBpassdown\fP|\fBnopassdown\fP|\fBignore\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--errorwhenfull\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-f\fP|\fB--force\fP
|
||||
.ad b
|
||||
@@ -68,10 +116,22 @@ lvchange - Change the attributes of logical volume(s)
|
||||
\fB-j\fP|\fB--major\fP \fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--[raid]maxrecoveryrate\fP \fISize\fP[k|UNIT]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--metadataprofile\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--minor\fP \fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--[raid]minrecoveryrate\fP \fISize\fP[k|UNIT]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--monitor\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
@@ -88,6 +148,10 @@ lvchange - Change the attributes of logical volume(s)
|
||||
\fB-P\fP|\fB--partial\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-p\fP|\fB--permission\fP \fBrw\fP|\fBr\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-M\fP|\fB--persistent\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
@@ -104,6 +168,10 @@ lvchange - Change the attributes of logical volume(s)
|
||||
\fB-q\fP|\fB--quiet\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-r\fP|\fB--readahead\fP \fBauto\fP|\fBnone\fP|\fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--readonly\fP
|
||||
.ad b
|
||||
@@ -128,6 +196,10 @@ lvchange - Change the attributes of logical volume(s)
|
||||
\fB-S\fP|\fB--select\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-k\fP|\fB--setactivationskip\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--[raid]syncaction\fP \fBcheck\fP|\fBrepair\fP
|
||||
.ad b
|
||||
@@ -148,9 +220,21 @@ lvchange - Change the attributes of logical volume(s)
|
||||
\fB--version\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--[raid]writebehind\fP \fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--[raid]writemostly\fP \fIPV\fP[\fB:t\fP|\fBn\fP|\fBy\fP]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-Z\fP|\fB--zero\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.SH DESCRIPTION
|
||||
lvchange changes LV attributes in the VG, changes LV activation in the
|
||||
kernel, and includes other utilities for LV maintenance.
|
||||
@@ -565,6 +649,34 @@ See \fBlvmraid\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--addtag\fP \fITag\fP
|
||||
.br
|
||||
Adds a tag to a PV, VG or LV. This option can be repeated to add
|
||||
multiple tags at once. See \fBlvm\fP(8) for information about tags.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
|
||||
.br
|
||||
Determines the allocation policy when a command needs to allocate
|
||||
Physical Extents (PEs) from the VG. Each VG and LV has an allocation policy
|
||||
which can be changed with vgchange/lvchange, or overriden on the
|
||||
command line.
|
||||
\fBnormal\fP applies common sense rules such as not placing parallel stripes
|
||||
on the same PV.
|
||||
\fBinherit\fP applies the VG policy to an LV.
|
||||
\fBcontiguous\fP requires new PEs be placed adjacent to existing PEs.
|
||||
\fBcling\fP places new PEs on the same PV as existing PEs in the same
|
||||
stripe of the LV.
|
||||
If there are sufficient PEs for an allocation, but normal does not
|
||||
use them, \fBanywhere\fP will use them even if it reduces performance,
|
||||
e.g. by placing two stripes on the same PV.
|
||||
Optional positional PV args on the command line can also be used to limit
|
||||
which PVs the command will use for allocation.
|
||||
See \fBlvm\fP(8) for more information about allocation.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Specifies if metadata should be backed up automatically after a change.
|
||||
@@ -572,6 +684,41 @@ Enabling this is strongly advised! See \fBvgcfgbackup\fP(8) for more information
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--cachemode\fP \fBwritethrough\fP|\fBwriteback\fP|\fBpassthrough\fP
|
||||
.br
|
||||
Specifies when writes to a cache LV should be considered complete.
|
||||
\fBwriteback\fP considers a write complete as soon as it is
|
||||
stored in the cache pool.
|
||||
\fBwritethough\fP considers a write complete only when it has
|
||||
been stored in both the cache pool and on the origin LV.
|
||||
While writethrough may be slower for writes, it is more
|
||||
resilient if something should happen to a device associated with the
|
||||
cache pool LV. With \fBpassthrough\fP, all reads are served
|
||||
from the origin LV (all reads miss the cache) and all writes are
|
||||
forwarded to the origin LV; additionally, write hits cause cache
|
||||
block invalidates. See \fBlvmcache\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--cachepolicy\fP \fIString\fP
|
||||
.br
|
||||
Specifies the cache policy for a cache LV.
|
||||
See \fBlvmcache\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--cachesettings\fP \fIString\fP
|
||||
.br
|
||||
Specifies tunable values for a cache LV in "Key = Value" form.
|
||||
Repeat this option to specify multiple values.
|
||||
(The default values should usually be adequate.)
|
||||
The special string value \fBdefault\fP switches
|
||||
settings back to their default kernel values and removes
|
||||
them from the list of settings stored in LVM metadata.
|
||||
See \fBlvmcache\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
.br
|
||||
The command profile to use for command configuration.
|
||||
@@ -579,6 +726,13 @@ See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--compression\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Controls whether compression is enabled or disable for VDO volume.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--config\fP \fIString\fP
|
||||
.br
|
||||
Config settings for the command. These override lvm.conf settings.
|
||||
@@ -588,6 +742,16 @@ See \fBlvm.conf\fP(5) for more information about config.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-C\fP|\fB--contiguous\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Sets or resets the contiguous allocation policy for LVs.
|
||||
Default is no contiguous allocation based on a next free principle.
|
||||
It is only possible to change a non-contiguous allocation policy
|
||||
to contiguous if all of the allocated physical extents in the LV
|
||||
are already contiguous.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-d\fP|\fB--debug\fP ...
|
||||
.br
|
||||
Set debug level. Repeat from 1 to 6 times to increase the detail of
|
||||
@@ -595,6 +759,40 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--deduplication\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Controls whether deduplication is enabled or disable for VDO volume.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--deltag\fP \fITag\fP
|
||||
.br
|
||||
Deletes a tag from a PV, VG or LV. This option can be repeated to delete
|
||||
multiple tags at once. See \fBlvm\fP(8) for information about tags.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--detachprofile\fP
|
||||
.br
|
||||
Detaches a metadata profile from a VG or LV.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--discards\fP \fBpassdown\fP|\fBnopassdown\fP|\fBignore\fP
|
||||
.br
|
||||
Specifies how the device-mapper thin pool layer in the kernel should
|
||||
handle discards.
|
||||
\fBignore\fP causes the thin pool to ignore discards.
|
||||
\fBnopassdown\fP causes the thin pool to process discards itself to
|
||||
allow reuse of unneeded extents in the thin pool.
|
||||
\fBpassdown\fP causes the thin pool to process discards itself
|
||||
(like nopassdown) and pass the discards to the underlying device.
|
||||
See \fBlvmthin\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
If set to no, the command will not attempt to use device-mapper.
|
||||
@@ -602,6 +800,19 @@ For testing and debugging.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--errorwhenfull\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Specifies thin pool behavior when data space is exhausted.
|
||||
When yes, device-mapper will immediately return an error
|
||||
when a thin pool is full and an I/O request requires space.
|
||||
When no, device-mapper will queue these I/O requests for a
|
||||
period of time to allow the thin pool to be extended.
|
||||
Errors are returned if no space is available after the timeout.
|
||||
(Also see dm-thin-pool kernel module option no_space_timeout.)
|
||||
See \fBlvmthin\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-f\fP|\fB--force\fP ...
|
||||
.br
|
||||
Override various checks, confirmations and protections.
|
||||
@@ -655,12 +866,37 @@ Sets the major number of an LV block device.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--[raid]maxrecoveryrate\fP \fISize\fP[k|UNIT]
|
||||
.br
|
||||
Sets the maximum recovery rate for a RAID LV. The rate value
|
||||
is an amount of data per second for each device in the array.
|
||||
Setting the rate to 0 means it will be unbounded.
|
||||
See \fBlvmraid\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--metadataprofile\fP \fIString\fP
|
||||
.br
|
||||
The metadata profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--minor\fP \fINumber\fP
|
||||
.br
|
||||
Sets the minor number of an LV block device.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--[raid]minrecoveryrate\fP \fISize\fP[k|UNIT]
|
||||
.br
|
||||
Sets the minimum recovery rate for a RAID LV. The rate value
|
||||
is an amount of data per second for each device in the array.
|
||||
Setting the rate to 0 means it will be unbounded.
|
||||
See \fBlvmraid\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--monitor\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Start (yes) or stop (no) monitoring an LV with dmeventd.
|
||||
@@ -694,6 +930,12 @@ Metadata may not be changed with this option.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-p\fP|\fB--permission\fP \fBrw\fP|\fBr\fP
|
||||
.br
|
||||
Set access permission to read only \fBr\fP or read and write \fBrw\fP.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-M\fP|\fB--persistent\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
When yes, makes the specified minor number persistent.
|
||||
@@ -726,6 +968,15 @@ Repeat once to also suppress any prompts with answer 'no'.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-r\fP|\fB--readahead\fP \fBauto\fP|\fBnone\fP|\fINumber\fP
|
||||
.br
|
||||
Sets read ahead sector count of an LV.
|
||||
\fBauto\fP is the default which allows the kernel to choose
|
||||
a suitable value automatically.
|
||||
\fBnone\fP is equivalent to zero.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--readonly\fP
|
||||
.br
|
||||
Run the command in a special read-only mode which will read on-disk
|
||||
@@ -793,6 +1044,17 @@ used to choose items to process.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-k\fP|\fB--setactivationskip\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Persistently sets (yes) or clears (no) the "activation skip" flag on an LV.
|
||||
An LV with this flag set is not activated unless the
|
||||
--ignoreactivationskip option is used by the activation command.
|
||||
This flag is set by default on new thin snapshot LVs.
|
||||
The flag is not applied to deactivation.
|
||||
The current value of the flag is indicated in the lvs lv_attr bits.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--[raid]syncaction\fP \fBcheck\fP|\fBrepair\fP
|
||||
.br
|
||||
Initiate different types of RAID synchronization.
|
||||
@@ -840,12 +1102,43 @@ Display version information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--[raid]writebehind\fP \fINumber\fP
|
||||
.br
|
||||
The maximum number of outstanding writes that are allowed to
|
||||
devices in a RAID1 LV that is marked write-mostly.
|
||||
Once this value is exceeded, writes become synchronous (i.e. all writes
|
||||
to the constituent devices must complete before the array signals the
|
||||
write has completed). Setting the value to zero clears the preference
|
||||
and allows the system to choose the value arbitrarily.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--[raid]writemostly\fP \fIPV\fP[\fB:t\fP|\fBn\fP|\fBy\fP]
|
||||
.br
|
||||
Mark a device in a RAID1 LV as write-mostly. All reads
|
||||
to these drives will be avoided unless absolutely necessary. This keeps
|
||||
the number of I/Os to the drive to a minimum. The default behavior is to
|
||||
set the write-mostly attribute for the specified PV.
|
||||
It is also possible to remove the write-mostly flag by adding the
|
||||
suffix \fB:n\fP at the end of the PV name, or to toggle the value with
|
||||
the suffix \fB:t\fP. Repeat this option to change the attribute on
|
||||
multiple PVs.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.br
|
||||
Do not prompt for confirmation interactively but always assume the
|
||||
answer yes. Use with extreme caution.
|
||||
(For automatic no, see -qq.)
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-Z\fP|\fB--zero\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Set zeroing mode for thin pool. Note: already provisioned blocks from pool
|
||||
in non-zero mode are not cleared in unwritten parts when setting --zero y.
|
||||
.ad b
|
||||
.SH VARIABLES
|
||||
.HP
|
||||
\fIVG\fP
|
||||
|
@@ -42,10 +42,6 @@ lvconvert - Change logical volume layout
|
||||
\fB--cachesettings\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--cachevol\fP \fILV\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT]
|
||||
.ad b
|
||||
@@ -571,7 +567,7 @@ Convert LV to a thin LV, using the original LV as an external origin.
|
||||
.br
|
||||
-
|
||||
|
||||
Attach a cache pool to an LV, converts the LV to type cache.
|
||||
Attach a cache to an LV, converts the LV to type cache.
|
||||
.br
|
||||
.P
|
||||
\fBlvconvert\fP \fB--type\fP \fBcache\fP \fB--cachepool\fP \fILV\fP \fILV\fP\fI_linear_striped_thinpool_vdo_vdopool_vdopooldata_raid\fP
|
||||
@@ -633,7 +629,7 @@ Attach a cache pool to an LV, converts the LV to type cache.
|
||||
Attach a writecache to an LV, converts the LV to type writecache.
|
||||
.br
|
||||
.P
|
||||
\fBlvconvert\fP \fB--type\fP \fBwritecache\fP \fB--cachevol\fP \fILV\fP \fILV\fP\fI_linear_striped_raid\fP
|
||||
\fBlvconvert\fP \fB--type\fP \fBwritecache\fP \fB--cachepool\fP \fILV\fP \fILV\fP\fI_linear_striped_raid\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
@@ -645,49 +641,6 @@ Attach a writecache to an LV, converts the LV to type writecache.
|
||||
.br
|
||||
-
|
||||
|
||||
Attach a cache to an LV, converts the LV to type cache.
|
||||
.br
|
||||
.P
|
||||
\fBlvconvert\fP \fB--type\fP \fBcache\fP \fB--cachevol\fP \fILV\fP \fILV\fP\fI_linear_striped_thinpool_raid\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-H\fP|\fB--cache\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-Z\fP|\fB--zero\fP \fBy\fP|\fBn\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT] ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--cachemetadataformat\fP \fBauto\fP|\fB1\fP|\fB2\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--cachemode\fP \fBwritethrough\fP|\fBwriteback\fP|\fBpassthrough\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--cachepolicy\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--cachesettings\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--poolmetadatasize\fP \fISize\fP[m|UNIT] ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
-
|
||||
|
||||
Convert LV to type thin-pool.
|
||||
.br
|
||||
.P
|
||||
@@ -1094,7 +1047,7 @@ See \fBlvmcache\fP(7) for more information.
|
||||
.ad l
|
||||
\fB--cachepool\fP \fILV\fP
|
||||
.br
|
||||
The name of a cache pool.
|
||||
The name of a cache pool LV.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
@@ -1110,12 +1063,6 @@ See \fBlvmcache\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--cachevol\fP \fILV\fP
|
||||
.br
|
||||
The name of a cache volume.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT]
|
||||
.br
|
||||
The size of chunks in a snapshot, cache pool or thin pool.
|
||||
@@ -1742,7 +1689,7 @@ Convert LV to a thin LV, using the original LV as an external origin
|
||||
.br
|
||||
-
|
||||
|
||||
Attach a cache pool to an LV (infers --type cache).
|
||||
Attach a cache to an LV (infers --type cache).
|
||||
.br
|
||||
.P
|
||||
\fBlvconvert\fP \fB-H\fP|\fB--cache\fP \fB--cachepool\fP \fILV\fP \fILV\fP\fI_linear_striped_thinpool_vdo_vdopool_vdopooldata_raid\fP
|
||||
|
@@ -309,8 +309,7 @@ numeric suffix.
|
||||
In the usage section below, when creating a pool and the name is omitted
|
||||
the new LV pool name is generated with the
|
||||
"vpool" for vdo-pools for prefix and a unique numeric suffix.
|
||||
|
||||
Pool name can be specified together with \fIVG\fP name i.e.:
|
||||
Also pool name can be specified together with \fIVG\fP name i.e.:
|
||||
vg00/mythinpool.
|
||||
.SH USAGE
|
||||
Create a linear LV.
|
||||
@@ -1098,7 +1097,7 @@ See \fBlvmcache\fP(7) for more information.
|
||||
.ad l
|
||||
\fB--cachepool\fP \fILV\fP
|
||||
.br
|
||||
The name of a cache pool.
|
||||
The name of a cache pool LV.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
|
@@ -92,6 +92,10 @@ if information changes between commands.
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--trustcache\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unbuffered\fP ]
|
||||
.ad b
|
||||
.br
|
||||
@@ -402,6 +406,12 @@ back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--trustcache\fP
|
||||
.br
|
||||
Avoids certain device scanning during command processing. Do not use.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unbuffered\fP
|
||||
.br
|
||||
Produce output immediately without sorting or aligning the columns properly.
|
||||
|
@@ -96,6 +96,10 @@ lvs produces formatted output about LVs.
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--trustcache\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unbuffered\fP ]
|
||||
.ad b
|
||||
.br
|
||||
@@ -423,6 +427,12 @@ back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--trustcache\fP
|
||||
.br
|
||||
Avoids certain device scanning during command processing. Do not use.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unbuffered\fP
|
||||
.br
|
||||
Produce output immediately without sorting or aligning the columns properly.
|
||||
|
@@ -16,7 +16,7 @@ others are optional.
|
||||
Change properties of all PVs.
|
||||
.br
|
||||
.P
|
||||
\fBpvchange\fP \fB-a\fP|\fB--all\fP
|
||||
\fBpvchange\fP
|
||||
.RS 4
|
||||
( \fB-x\fP|\fB--allocatable\fP \fBy\fP|\fBn\fP,
|
||||
.ad b
|
||||
@@ -25,6 +25,10 @@ Change properties of all PVs.
|
||||
\fB-u\fP|\fB--uuid\fP,
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-a\fP|\fB--all\fP,
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--addtag\fP \fITag\fP,
|
||||
.ad b
|
||||
@@ -160,12 +164,25 @@ Common options for lvm:
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
.ad l
|
||||
\fB--addtag\fP \fITag\fP
|
||||
.br
|
||||
Adds a tag to a PV, VG or LV. This option can be repeated to add
|
||||
multiple tags at once. See \fBlvm\fP(8) for information about tags.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-a\fP|\fB--all\fP
|
||||
.br
|
||||
Change all visible PVs.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-x\fP|\fB--allocatable\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Enable or disable allocation of physical extents on this PV.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Specifies if metadata should be backed up automatically after a change.
|
||||
@@ -196,6 +213,13 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--deltag\fP \fITag\fP
|
||||
.br
|
||||
Deletes a tag from a PV, VG or LV. This option can be repeated to delete
|
||||
multiple tags at once. See \fBlvm\fP(8) for information about tags.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
If set to no, the command will not attempt to use device-mapper.
|
||||
@@ -229,6 +253,15 @@ Display long help text.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--metadataignore\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Specifies the metadataignore property of a PV.
|
||||
If yes, metadata areas on the PV are ignored, and lvm will
|
||||
not store metadata in the metadata areas of the PV.
|
||||
If no, lvm will store metadata on the PV.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
|
@@ -1,8 +1 @@
|
||||
pvck checks LVM metadata on PVs.
|
||||
|
||||
Use the --dump option to extract metadata from PVs for debugging.
|
||||
With dump, set --pvmetadatacopies 2 to extract metadata from a
|
||||
second metadata area at the end of the device. Use the --file
|
||||
option to save the raw metadata to a specified file. (The raw
|
||||
metadata is not usable with vgcfgbackup and vgcfgrestore.)
|
||||
|
||||
pvck checks the LVM metadata for consistency on PVs.
|
||||
|
@@ -1,57 +1,25 @@
|
||||
.TH PVCK 8 "LVM TOOLS #VERSION#" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
pvck - Check metadata on physical volumes
|
||||
pvck - Check the consistency of physical volume(s)
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
\fBpvck\fP \fIoption_args\fP \fIposition_args\fP
|
||||
\fBpvck\fP \fIposition_args\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
pvck checks LVM metadata on PVs.
|
||||
|
||||
Use the --dump option to extract metadata from PVs for debugging.
|
||||
With dump, set --pvmetadatacopies 2 to extract metadata from a
|
||||
second metadata area at the end of the device. Use the --file
|
||||
option to save the raw metadata to a specified file. (The raw
|
||||
metadata is not usable with vgcfgbackup and vgcfgrestore.)
|
||||
|
||||
pvck checks the LVM metadata for consistency on PVs.
|
||||
.SH USAGE
|
||||
Check for metadata on a device
|
||||
.br
|
||||
.P
|
||||
\fBpvck\fP \fIPV\fP ...
|
||||
.br
|
||||
.RS 4
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
|
||||
Print metadata from a device
|
||||
.br
|
||||
.P
|
||||
\fBpvck\fP \fB--dump\fP \fIString\fP \fIPV\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-f\fP|\fB--file\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--[pv]metadatacopies\fP \fB0\fP|\fB1\fP|\fB2\fP ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
|
||||
Common options for command:
|
||||
.
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB--labelsector\fP \fINumber\fP ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
|
||||
Common options for lvm:
|
||||
.
|
||||
@@ -145,21 +113,6 @@ For testing and debugging.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--dump\fP \fIString\fP
|
||||
.br
|
||||
Dump metadata from a PV. Option values include \fBmetadata\fP
|
||||
to print or save the current text metadata, \fBmetadata_area\fP
|
||||
to save the entire text metadata area to a file, \fBmetadata_all\fP
|
||||
to save the current and any previous complete versions of metadata
|
||||
to a file, and \fBheaders\fP to print and check LVM headers.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-f\fP|\fB--file\fP \fIString\fP
|
||||
.br
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-h\fP|\fB--help\fP
|
||||
.br
|
||||
Display help text.
|
||||
@@ -201,18 +154,6 @@ on the command.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--[pv]metadatacopies\fP \fB0\fP|\fB1\fP|\fB2\fP
|
||||
.br
|
||||
The number of metadata areas to set aside on a PV for storing VG metadata.
|
||||
When 2, one copy of the VG metadata is stored at the front of the PV
|
||||
and a second copy is stored at the end.
|
||||
When 1, one copy of the VG metadata is stored at the front of the PV.
|
||||
When 0, no copies of the VG metadata are stored on the given PV.
|
||||
This may be useful in VGs containing many PVs (this places limitations
|
||||
on the ability to use vgsplit later.)
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP ...
|
||||
.br
|
||||
Suppress output and log messages. Overrides --debug and --verbose.
|
||||
|
@@ -92,6 +92,10 @@ pvs produces formatted output about PVs.
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--trustcache\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unbuffered\fP ]
|
||||
.ad b
|
||||
.br
|
||||
@@ -412,6 +416,12 @@ back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--trustcache\fP
|
||||
.br
|
||||
Avoids certain device scanning during command processing. Do not use.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unbuffered\fP
|
||||
.br
|
||||
Produce output immediately without sorting or aligning the columns properly.
|
||||
|
@@ -18,6 +18,14 @@ vgchange - Change volume group attributes
|
||||
\fB--activationmode\fP \fBpartial\fP|\fBdegraded\fP|\fBcomplete\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--addtag\fP \fITag\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
@@ -34,6 +42,14 @@ vgchange - Change volume group attributes
|
||||
\fB-d\fP|\fB--debug\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--deltag\fP \fITag\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--detachprofile\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
@@ -74,10 +90,22 @@ vgchange - Change volume group attributes
|
||||
\fB--locktype\fP \fBsanlock\fP|\fBdlm\fP|\fBnone\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-l\fP|\fB--logicalvolume\fP \fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--longhelp\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-p\fP|\fB--maxphysicalvolumes\fP \fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--metadataprofile\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--monitor\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
@@ -94,6 +122,10 @@ vgchange - Change volume group attributes
|
||||
\fB-P\fP|\fB--partial\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-s\fP|\fB--physicalextentsize\fP \fISize\fP[m|UNIT]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--poll\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
@@ -102,6 +134,10 @@ vgchange - Change volume group attributes
|
||||
\fB--profile\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--pvmetadatacopies\fP \fB0\fP|\fB1\fP|\fB2\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP
|
||||
.ad b
|
||||
@@ -118,6 +154,10 @@ vgchange - Change volume group attributes
|
||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-x\fP|\fB--resizeable\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-S\fP|\fB--select\fP \fIString\fP
|
||||
.ad b
|
||||
@@ -134,6 +174,10 @@ vgchange - Change volume group attributes
|
||||
\fB-t\fP|\fB--test\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-u\fP|\fB--uuid\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP
|
||||
.ad b
|
||||
@@ -142,6 +186,10 @@ vgchange - Change volume group attributes
|
||||
\fB--version\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--[vg]metadatacopies\fP \fBall\fP|\fBunmanaged\fP|\fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.ad b
|
||||
@@ -622,6 +670,34 @@ See \fBlvmraid\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--addtag\fP \fITag\fP
|
||||
.br
|
||||
Adds a tag to a PV, VG or LV. This option can be repeated to add
|
||||
multiple tags at once. See \fBlvm\fP(8) for information about tags.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
|
||||
.br
|
||||
Determines the allocation policy when a command needs to allocate
|
||||
Physical Extents (PEs) from the VG. Each VG and LV has an allocation policy
|
||||
which can be changed with vgchange/lvchange, or overriden on the
|
||||
command line.
|
||||
\fBnormal\fP applies common sense rules such as not placing parallel stripes
|
||||
on the same PV.
|
||||
\fBinherit\fP applies the VG policy to an LV.
|
||||
\fBcontiguous\fP requires new PEs be placed adjacent to existing PEs.
|
||||
\fBcling\fP places new PEs on the same PV as existing PEs in the same
|
||||
stripe of the LV.
|
||||
If there are sufficient PEs for an allocation, but normal does not
|
||||
use them, \fBanywhere\fP will use them even if it reduces performance,
|
||||
e.g. by placing two stripes on the same PV.
|
||||
Optional positional PV args on the command line can also be used to limit
|
||||
which PVs the command will use for allocation.
|
||||
See \fBlvm\fP(8) for more information about allocation.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Specifies if metadata should be backed up automatically after a change.
|
||||
@@ -652,6 +728,20 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--deltag\fP \fITag\fP
|
||||
.br
|
||||
Deletes a tag from a PV, VG or LV. This option can be repeated to delete
|
||||
multiple tags at once. See \fBlvm\fP(8) for information about tags.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--detachprofile\fP
|
||||
.br
|
||||
Detaches a metadata profile from a VG or LV.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
If set to no, the command will not attempt to use device-mapper.
|
||||
@@ -723,12 +813,34 @@ See \fBlvmlockd\fP(8) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-l\fP|\fB--logicalvolume\fP \fINumber\fP
|
||||
.br
|
||||
Sets the maximum number of LVs allowed in a VG.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--longhelp\fP
|
||||
.br
|
||||
Display long help text.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-p\fP|\fB--maxphysicalvolumes\fP \fINumber\fP
|
||||
.br
|
||||
Sets the maximum number of PVs that can belong to the VG.
|
||||
The value 0 removes any limitation.
|
||||
For large numbers of PVs, also see options --pvmetadatacopies,
|
||||
and --vgmetadatacopies for improving performance.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--metadataprofile\fP \fIString\fP
|
||||
.br
|
||||
The metadata profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--monitor\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Start (yes) or stop (no) monitoring an LV with dmeventd.
|
||||
@@ -762,6 +874,20 @@ Metadata may not be changed with this option.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-s\fP|\fB--physicalextentsize\fP \fISize\fP[m|UNIT]
|
||||
.br
|
||||
Sets the physical extent size of PVs in the VG.
|
||||
The value must be either a power of 2 of at least 1 sector
|
||||
(where the sector size is the largest sector size of the PVs
|
||||
currently used in the VG), or at least 128KiB.
|
||||
Once this value has been set, it is difficult to change
|
||||
without recreating the VG, unless no extents need moving.
|
||||
Before increasing the physical extent size, you might need to use lvresize,
|
||||
pvresize and/or pvmove so that everything fits. For example, every
|
||||
contiguous range of extents used in a LV must start and end on an extent boundary.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--poll\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
When yes, start the background transformation of an LV.
|
||||
@@ -781,6 +907,18 @@ on the command.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--pvmetadatacopies\fP \fB0\fP|\fB1\fP|\fB2\fP
|
||||
.br
|
||||
The number of metadata areas to set aside on a PV for storing VG metadata.
|
||||
When 2, one copy of the VG metadata is stored at the front of the PV
|
||||
and a second copy is stored at the end.
|
||||
When 1, one copy of the VG metadata is stored at the front of the PV.
|
||||
When 0, no copies of the VG metadata are stored on the given PV.
|
||||
This may be useful in VGs containing many PVs (this places limitations
|
||||
on the ability to use vgsplit later.)
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP ...
|
||||
.br
|
||||
Suppress output and log messages. Overrides --debug and --verbose.
|
||||
@@ -819,6 +957,13 @@ output in JSON format. See \fBlvmreport\fP(7) for more information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-x\fP|\fB--resizeable\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Enables or disables the addition or removal of PVs to/from a VG
|
||||
(by vgextend/vgreduce).
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-S\fP|\fB--select\fP \fIString\fP
|
||||
.br
|
||||
Select objects for processing and reporting based on specified criteria.
|
||||
@@ -863,6 +1008,12 @@ back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-u\fP|\fB--uuid\fP
|
||||
.br
|
||||
Generate new random UUID for specified VGs.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
@@ -876,6 +1027,24 @@ Display version information.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--[vg]metadatacopies\fP \fBall\fP|\fBunmanaged\fP|\fINumber\fP
|
||||
.br
|
||||
Number of copies of the VG metadata that are kept.
|
||||
VG metadata is kept in VG metadata areas on PVs in the VG,
|
||||
i.e. reserved space at the start and/or end of the PVs.
|
||||
Keeping a copy of the VG metadata on every PV can reduce performance
|
||||
in VGs containing a large number of PVs.
|
||||
When this number is set to a non-zero value, LVM will automatically
|
||||
choose PVs on which to store metadata, using the metadataignore flags
|
||||
on PVs to achieve the specified number.
|
||||
The number can also be replaced with special string values:
|
||||
\fBunmanaged\fP causes LVM to not automatically manage the PV
|
||||
metadataignore flags.
|
||||
\fBall\fP causes LVM to first clear the metadataignore flags on
|
||||
all PVs, and then to become unmanaged.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.br
|
||||
Do not prompt for confirmation interactively but always assume the
|
||||
|
@@ -3,7 +3,7 @@
|
||||
vgck - Check the consistency of volume group(s)
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
\fBvgck\fP \fIoption_args\fP \fIposition_args\fP
|
||||
\fBvgck\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
@@ -12,9 +12,6 @@ vgck - Check the consistency of volume group(s)
|
||||
.SH DESCRIPTION
|
||||
vgck checks LVM metadata for consistency.
|
||||
.SH USAGE
|
||||
Read and display information about a VG.
|
||||
.br
|
||||
.P
|
||||
\fBvgck\fP
|
||||
.br
|
||||
.RS 4
|
||||
@@ -29,21 +26,6 @@ Read and display information about a VG.
|
||||
[ \fIVG\fP|\fITag\fP ... ]
|
||||
.RE
|
||||
|
||||
Rewrite VG metadata to correct problems.
|
||||
.br
|
||||
.P
|
||||
\fBvgck\fP \fB--updatemetadata\fP \fIVG\fP
|
||||
.br
|
||||
.RS 4
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
|
||||
Common options for command:
|
||||
.
|
||||
.RS 4
|
||||
.RE
|
||||
|
||||
Common options for lvm:
|
||||
.
|
||||
.RS 4
|
||||
@@ -196,12 +178,6 @@ back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--updatemetadata\fP
|
||||
.br
|
||||
Update VG metadata to correct problems.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
|
@@ -88,6 +88,10 @@ vgs produces formatted output about VGs.
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--trustcache\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unbuffered\fP ]
|
||||
.ad b
|
||||
.br
|
||||
@@ -399,6 +403,12 @@ back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--trustcache\fP
|
||||
.br
|
||||
Avoids certain device scanning during command processing. Do not use.
|
||||
.ad b
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unbuffered\fP
|
||||
.br
|
||||
Produce output immediately without sorting or aligning the columns properly.
|
||||
|
@@ -49,9 +49,9 @@ include $(top_builddir)/make.tmpl
|
||||
T ?= .
|
||||
S ?= @ # never match anything by default
|
||||
VERBOSE ?= 0
|
||||
ALL := $(shell find -L $(srcdir) \( -path \*/shell/\*.sh -or -path \*/api/\*.sh -or -path \*/unit/\*.sh \) | $(SORT))
|
||||
ALL := $(shell find -L $(srcdir) \( -path \*/shell/\*.sh -or -path \*/unit/\*.sh \) | $(SORT))
|
||||
comma = ,
|
||||
RUN := $(shell find -L $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/api/\*.sh -or -path \*/unit/\*.sh \) -and -regex "$(srcdir)/.*($(subst $(comma),|,$(T))).*" -and -not -regex "$(srcdir)/.*($(subst $(comma),|,$(S))).*" | $(SORT))
|
||||
RUN := $(shell find -L $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/unit/\*.sh \) -and -regex "$(srcdir)/.*($(subst $(comma),|,$(T))).*" -and -not -regex "$(srcdir)/.*($(subst $(comma),|,$(S))).*" | $(SORT))
|
||||
RUN_BASE = $(subst $(srcdir)/,,$(RUN))
|
||||
|
||||
ifeq ("@BUILD_LVMPOLLD@", "yes")
|
||||
@@ -200,9 +200,8 @@ LIB_SHARED = check aux inittest utils get lvm-wrapper
|
||||
|
||||
install: .tests-stamp lib/paths-installed
|
||||
@echo $(srcdir)
|
||||
$(Q) $(INSTALL_DIR) $(DATADIR)/{shell,api,unit,lib,dbus} $(EXECDIR)
|
||||
$(Q) $(INSTALL_DIR) $(DATADIR)/{shell,unit,lib,dbus} $(EXECDIR)
|
||||
$(Q) $(INSTALL_DATA) shell/*.sh $(DATADIR)/shell
|
||||
$(INSTALL_DATA) api/*.sh $(DATADIR)/api
|
||||
$(Q) $(INSTALL_DATA) unit/*.sh $(DATADIR)/unit
|
||||
-$(Q) $(INSTALL_PROGRAM) unit/unit-test $(DATADIR)/unit
|
||||
-$(Q) $(INSTALL_PROGRAM) dbus/*.py $(DATADIR)/dbus/
|
||||
@@ -292,7 +291,7 @@ lib/paths-installed: lib/paths-common
|
||||
$(Q) $(RM) $@-t
|
||||
$(Q) cat lib/paths-common > $@-t
|
||||
$(Q) echo 'installed_testsuite=1' >> $@-t
|
||||
$(Q) echo 'export PATH=@libexecdir@/lvm2-testsuite:@datadir@/lvm2-testsuite/lib:@datadir@/lvm2-testsuite/api:$$PATH' >> $@-t
|
||||
$(Q) echo 'export PATH=@libexecdir@/lvm2-testsuite:@datadir@/lvm2-testsuite/lib:$$PATH' >> $@-t
|
||||
$(Q) mv $@-t $@
|
||||
|
||||
lib/paths: lib/paths-common
|
||||
|
@@ -1090,7 +1090,7 @@ extend_filter() {
|
||||
for rx in "$@"; do
|
||||
filter=$(echo "$filter" | sed -e "s:\\[:[ \"$rx\", :")
|
||||
done
|
||||
lvmconf "$filter" "devices/scan_lvs = 1"
|
||||
lvmconf "$filter"
|
||||
}
|
||||
|
||||
extend_filter_LVMTEST() {
|
||||
@@ -1421,7 +1421,7 @@ target_at_least() {
|
||||
fi
|
||||
|
||||
local version
|
||||
version=$(dmsetup targets 2>/dev/null | grep "^${1##dm-} " 2>/dev/null)
|
||||
version=$(dmsetup targets 2>/dev/null | grep "${1##dm-} " 2>/dev/null)
|
||||
version=${version##* v}
|
||||
|
||||
version_at_least "$version" "${@:2}" || {
|
||||
@@ -1478,14 +1478,6 @@ have_vdo() {
|
||||
target_at_least dm-vdo "$@"
|
||||
}
|
||||
|
||||
have_writecache() {
|
||||
lvm segtypes 2>/dev/null | grep -q writecache$ || {
|
||||
echo "writecache is not built-in." >&2
|
||||
return 1
|
||||
}
|
||||
target_at_least dm-writecache "$@"
|
||||
}
|
||||
|
||||
have_raid() {
|
||||
target_at_least dm-raid "$@"
|
||||
|
||||
|
@@ -1,45 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2019 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Check reporting of no_discard_passdown
|
||||
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
# Until new version of cache_check tools - no integrity validation
|
||||
LVM_TEST_CACHE_CHECK_CMD=""
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux kernel_at_least 5 1 || skip
|
||||
|
||||
aux have_cache 2 0
|
||||
|
||||
aux prepare_vg 1
|
||||
|
||||
# Create thinLV without discard
|
||||
lvcreate --discards=ignore -T -V20 -L20 -n $lv $vg/pool
|
||||
|
||||
aux extend_filter_LVMTEST
|
||||
|
||||
# Use discard-less LV as PV for $vg1
|
||||
pvcreate "$DM_DEV_DIR/$vg/$lv"
|
||||
vgcreate -s 128K $vg1 "$DM_DEV_DIR/$vg/$lv"
|
||||
|
||||
# Create simple cache LV
|
||||
lvcreate -L2 -n $lv1 $vg1
|
||||
lvcreate -H -L2 $vg1/$lv1
|
||||
|
||||
#lvs -ao+kernel_discards $vg1
|
||||
check lv_field $vg1/$lv1 kernel_discards "nopassdown"
|
||||
|
||||
vgremove -f $vg1
|
||||
vgremove -f $vg
|
@@ -1,40 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2019 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Check we can read metadata with out-of-range creation time
|
||||
|
||||
# Due to a bug in 32-bit version lvm2 <2.02.169 produced metadata
|
||||
# contained invalid number for creation_time
|
||||
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_vg 1
|
||||
|
||||
lvcreate -an -L1 -n $lv1 $vg
|
||||
|
||||
vgcfgbackup -f back $vg
|
||||
|
||||
sed -e 's/creation_time = \(.*\)$/creation_time = 12029933779523993599/g' back >backnew
|
||||
|
||||
vgcfgrestore -f backnew $vg |& tee err
|
||||
|
||||
# Check the time was spotted
|
||||
grep Invalid err
|
||||
|
||||
vgcfgbackup -f back $vg |& tee err
|
||||
|
||||
# Check the time is not a problem anymore
|
||||
not grep Invalid err
|
||||
|
||||
vgremove -ff $vg
|
@@ -46,14 +46,7 @@ PWD2="mymJeD8ivEhE"
|
||||
PWD3="ocMakf3fAcQO"
|
||||
SKIP_DETACHED=
|
||||
|
||||
if which cryptsetup ; then
|
||||
# use older format luks1 - otherwise the test would need to pass password everywhere...
|
||||
case $(cryptsetup --version) in
|
||||
"cryptsetup 2"*) FORMAT_PARAMS="$FORMAT_PARAMS --type luks1" ;;
|
||||
esac
|
||||
else
|
||||
check_cryptsetup=${check_cryptsetup:-cryptsetup}
|
||||
fi
|
||||
which cryptsetup || check_cryptsetup=${check_cryptsetup:-cryptsetup}
|
||||
|
||||
which mkfs.ext2 || check_ext2=${check_ext2:-mkfs.ext2}
|
||||
which mkfs.ext3 || check_ext3=${check_ext3:-mkfs.ext3}
|
||||
@@ -137,7 +130,7 @@ get_crypt_kname() {
|
||||
# $1 device
|
||||
# $2 pass
|
||||
crypt_format() {
|
||||
echo "$2" | cryptsetup luksFormat $FORMAT_PARAMS "$1"
|
||||
echo "$2" | cryptsetup luksFormat "$FORMAT_PARAMS" "$1"
|
||||
}
|
||||
|
||||
|
||||
@@ -268,7 +261,7 @@ test_ext3_small_shrink() {
|
||||
}
|
||||
|
||||
test_xfs_resize() {
|
||||
mkfs.xfs -l internal,size=1536b -f "$3"
|
||||
mkfs.xfs -l internal,size=1000b -f "$3"
|
||||
|
||||
fsadm --lvresize resize $1 30M
|
||||
# Fails - not enough space for 4M fs
|
||||
@@ -283,7 +276,7 @@ test_xfs_resize() {
|
||||
}
|
||||
|
||||
test_xfs_small_shrink() {
|
||||
mkfs.xfs -l internal,size=1536b -f "$3"
|
||||
mkfs.xfs -l internal,size=1000b -f "$3"
|
||||
|
||||
not lvresize -L-1 -r $1
|
||||
fscheck_xfs "$3"
|
||||
@@ -347,7 +340,7 @@ test_ext3_inactive() {
|
||||
|
||||
test_xfs_inactive() {
|
||||
crypt_open "$2" $PWD2 "$4"
|
||||
mkfs.xfs -l internal,size=1536b -f "$3"
|
||||
mkfs.xfs -l internal,size=1000b -f "$3"
|
||||
crypt_close "$4"
|
||||
|
||||
not fsadm --lvresize resize $1 30M
|
||||
@@ -428,7 +421,7 @@ test_ext3_plain() {
|
||||
}
|
||||
|
||||
test_xfs_plain() {
|
||||
mkfs.xfs -l internal,size=1536b -f "$3"
|
||||
mkfs.xfs -l internal,size=1000b -f "$3"
|
||||
|
||||
not fsadm --lvresize resize $1 30M
|
||||
not lvresize -L+10M -r $1
|
||||
@@ -494,7 +487,7 @@ test_ext3_detached() {
|
||||
}
|
||||
|
||||
test_xfs_detached() {
|
||||
mkfs.xfs -l internal,size=1536b -f "$3"
|
||||
mkfs.xfs -l internal,size=1000b -f "$3"
|
||||
|
||||
not fsadm --lvresize resize $1 30M
|
||||
not lvresize -L+10M -r $1
|
||||
|
@@ -53,15 +53,12 @@ grep -v -E "$dev1|$dev2" $HINTS > tmptest
|
||||
not grep scan: tmptest
|
||||
|
||||
# test that 'pvs' submits only two reads, one for each PV in hints
|
||||
|
||||
if [ -e "/usr/bin/strace" ]; then
|
||||
strace -e io_submit pvs 2>&1|tee tmptest
|
||||
test "$(grep io_submit tmptest | wc -l)" -eq 2
|
||||
|
||||
# test that 'pvs -a' submits six reads, one for each device
|
||||
strace -e io_submit pvs -a 2>&1|tee tmptest
|
||||
test "$(grep io_submit tmptest | wc -l)" -eq 6
|
||||
fi
|
||||
|
||||
#
|
||||
# vg2 uses dev3,dev4
|
||||
|
@@ -39,7 +39,7 @@ makeold
|
||||
|
||||
# reports old metadata
|
||||
vgs $vg 2>&1 | tee cmd.out
|
||||
grep "ignoring metadata" cmd.out
|
||||
grep "ignoring old metadata" cmd.out
|
||||
check lv_field $vg/resized lv_size "8.00m"
|
||||
|
||||
# corrects old metadata
|
||||
@@ -47,7 +47,7 @@ lvcreate -l1 -an $vg
|
||||
|
||||
# no old report
|
||||
vgs $vg 2>&1 | tee cmd.out
|
||||
not grep "ignoring metadata" cmd.out
|
||||
not grep "ignoring old metadata" cmd.out
|
||||
check lv_field $vg/resized lv_size "8.00m"
|
||||
|
||||
|
||||
|
@@ -21,26 +21,26 @@ aux prepare_devs 3
|
||||
pvcreate "$dev1" "$dev2"
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2"
|
||||
|
||||
# if wait_for_locks set, vgremove should wait for global lock
|
||||
# if wait_for_locks set, vgremove should wait for orphan lock
|
||||
# flock process should have exited by the time first vgremove completes
|
||||
flock -w 5 "$TESTDIR/var/lock/lvm/P_global" sleep 10 &
|
||||
while ! test -f "$TESTDIR/var/lock/lvm/P_global" ; do sleep .1 ; done
|
||||
flock -w 5 "$TESTDIR/var/lock/lvm/P_orphans" sleep 10 &
|
||||
while ! test -f "$TESTDIR/var/lock/lvm/P_orphans" ; do sleep .1 ; done
|
||||
|
||||
vgremove --config 'global { wait_for_locks = 1 }' $vg
|
||||
not vgremove --config 'global { wait_for_locks = 1 }' $vg
|
||||
|
||||
test ! -f "$TESTDIR/var/lock/lvm/P_global"
|
||||
test ! -f "$TESTDIR/var/lock/lvm/P_orphans"
|
||||
|
||||
# if wait_for_locks not set, vgremove should fail on non-blocking lock
|
||||
# we must wait for flock process at the end - vgremove won't wait
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2"
|
||||
flock -w 5 "$TESTDIR/var/lock/lvm/P_global" sleep 10 &
|
||||
flock -w 5 "$TESTDIR/var/lock/lvm/P_orphans" sleep 10 &
|
||||
|
||||
while ! test -f "$TESTDIR/var/lock/lvm/P_global" ; do sleep .1 ; done
|
||||
while ! test -f "$TESTDIR/var/lock/lvm/P_orphans" ; do sleep .1 ; done
|
||||
flock_pid=$(jobs -p)
|
||||
|
||||
not vgremove --config 'global { wait_for_locks = 0 }' $vg
|
||||
test -f "$TESTDIR/var/lock/lvm/P_global" # still running
|
||||
test -f "$TESTDIR/var/lock/lvm/P_orphans" # still running
|
||||
kill "$flock_pid"
|
||||
|
||||
vgremove -ff $vg
|
||||
|
@@ -32,8 +32,7 @@ lvcreate -aey -L 16M -n $lv $vg
|
||||
check lv_field $vg/$lv segtype "linear"
|
||||
check lv_field $vg/$lv stripes 1
|
||||
check lv_field $vg/$lv data_stripes 1
|
||||
wipefs -a $DM_DEV_DIR/$vg/$lv
|
||||
mkfs -t ext4 $DM_DEV_DIR/$vg/$lv
|
||||
echo y|mkfs -t ext4 $DM_DEV_DIR/$vg/$lv
|
||||
fsck -fn $DM_DEV_DIR/$vg/$lv
|
||||
|
||||
# Convert linear -> raid1 (takeover)
|
||||
|
@@ -31,8 +31,7 @@ lvcreate -aey -L 16M -n $lv $vg
|
||||
check lv_field $vg/$lv segtype "linear"
|
||||
check lv_field $vg/$lv stripes 1
|
||||
check lv_field $vg/$lv data_stripes 1
|
||||
wipefs -a $DM_DEV_DIR/$vg/$lv
|
||||
mkfs -t ext4 $DM_DEV_DIR/$vg/$lv
|
||||
echo y|mkfs -t ext4 $DM_DEV_DIR/$vg/$lv
|
||||
fsck -fn $DM_DEV_DIR/$vg/$lv
|
||||
|
||||
# Convert linear -> raid1
|
||||
|
@@ -30,8 +30,7 @@ lvcreate -aey -L 16M -n $lv1 $vg
|
||||
check lv_field $vg/$lv1 segtype "linear"
|
||||
check lv_field $vg/$lv1 stripes 1
|
||||
check lv_field $vg/$lv1 data_stripes 1
|
||||
wipefs -a $DM_DEV_DIR/$vg/$lv1
|
||||
mkfs -t ext4 $DM_DEV_DIR/$vg/$lv1
|
||||
echo y|mkfs -t ext4 $DM_DEV_DIR/$vg/$lv1
|
||||
fsck -fn $DM_DEV_DIR/$vg/$lv1
|
||||
|
||||
# Convert linear -> raid1
|
||||
|
@@ -44,8 +44,7 @@ lvcreate --yes --type raid5_ls --stripes 13 -L190M -n$lv1 $vg
|
||||
check lv_first_seg_field $vg/$lv1 segtype "raid5_ls"
|
||||
check lv_first_seg_field $vg/$lv1 data_stripes 13
|
||||
check lv_first_seg_field $vg/$lv1 stripes 14
|
||||
wipefs -a /dev/$vg/$lv1
|
||||
mkfs -t ext4 /dev/$vg/$lv1
|
||||
echo y|mkfs -t ext4 /dev/$vg/$lv1
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
mkdir -p $mount_dir
|
||||
|
@@ -32,8 +32,7 @@ check lv_first_seg_field $vg/$lv segtype "striped"
|
||||
check lv_first_seg_field $vg/$lv stripes 4
|
||||
check lv_first_seg_field $vg/$lv data_stripes 4
|
||||
check lv_first_seg_field $vg/$lv stripesize "64.00k"
|
||||
wipefs -a $DM_DEV_DIR/$vg/$lv
|
||||
mkfs -t ext4 $DM_DEV_DIR/$vg/$lv
|
||||
echo y|mkfs -t ext4 $DM_DEV_DIR/$vg/$lv
|
||||
fsck -fn $DM_DEV_DIR/$vg/$lv
|
||||
lvextend -y -L64M $DM_DEV_DIR/$vg/$lv
|
||||
|
||||
|
@@ -33,8 +33,7 @@ check lv_field $vg/$lv1 data_stripes 4
|
||||
check lv_field $vg/$lv1 stripes 4
|
||||
check lv_field $vg/$lv1 stripesize "32.00k"
|
||||
check lv_field $vg/$lv1 reshape_len_le ""
|
||||
wipefs -a $DM_DEV_DIR/$vg/$lv1
|
||||
mkfs -t ext4 $DM_DEV_DIR/$vg/$lv1
|
||||
echo y|mkfs -t ext4 $DM_DEV_DIR/$vg/$lv1
|
||||
fsck -fn $DM_DEV_DIR/$vg/$lv1
|
||||
|
||||
# Convert striped -> raid5(_n)
|
||||
|
@@ -45,8 +45,7 @@ check lv_first_seg_field $vg/$lv1 segtype "raid5_ls"
|
||||
check lv_first_seg_field $vg/$lv1 stripesize "64.00k"
|
||||
check lv_first_seg_field $vg/$lv1 data_stripes 10
|
||||
check lv_first_seg_field $vg/$lv1 stripes 11
|
||||
wipefs -a /dev/$vg/$lv1
|
||||
mkfs -t ext4 /dev/$vg/$lv1
|
||||
echo y|mkfs -t ext4 /dev/$vg/$lv1
|
||||
fsck -fn /dev/$vg/$lv1
|
||||
|
||||
mkdir -p $mount_dir
|
||||
|
@@ -48,8 +48,7 @@ check lv_first_seg_field $vg/$lv1 segtype "raid5_ls"
|
||||
check lv_first_seg_field $vg/$lv1 stripesize "64.00k"
|
||||
check lv_first_seg_field $vg/$lv1 data_stripes 10
|
||||
check lv_first_seg_field $vg/$lv1 stripes 11
|
||||
wipefs -a /dev/$vg/$lv1
|
||||
mkfs -t ext4 /dev/$vg/$lv1
|
||||
echo y|mkfs -t ext4 /dev/$vg/$lv1
|
||||
|
||||
mkdir -p "$mount_dir"
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" "$mount_dir"
|
||||
|
@@ -45,8 +45,7 @@ check lv_first_seg_field $vg/$lv1 segtype "raid5_ls"
|
||||
check lv_first_seg_field $vg/$lv1 stripesize "64.00k"
|
||||
check lv_first_seg_field $vg/$lv1 data_stripes 10
|
||||
check lv_first_seg_field $vg/$lv1 stripes 11
|
||||
wipefs -a /dev/$vg/$lv1
|
||||
mkfs -t ext4 /dev/$vg/$lv1
|
||||
echo y|mkfs -t ext4 /dev/$vg/$lv1
|
||||
|
||||
mkdir -p $mount_dir
|
||||
mount "$DM_DEV_DIR/$vg/$lv1" $mount_dir
|
||||
|
@@ -29,8 +29,7 @@ lvcreate -aey -L 16M -n $lv $vg
|
||||
check lv_field $vg/$lv segtype "linear"
|
||||
check lv_field $vg/$lv stripes 1
|
||||
check lv_field $vg/$lv data_stripes 1
|
||||
wipefs -a $DM_DEV_DIR/$vg/$lv
|
||||
mkfs -t ext4 $DM_DEV_DIR/$vg/$lv
|
||||
echo y|mkfs -t ext4 $DM_DEV_DIR/$vg/$lv
|
||||
fsck -fn $DM_DEV_DIR/$vg/$lv
|
||||
|
||||
# Convert linear -> raid1
|
||||
|
@@ -26,7 +26,7 @@ aux prepare_vg 8
|
||||
# FIXME: lvconvert leaks 'error' devices
|
||||
detect_error_leak_()
|
||||
{
|
||||
dmsetup table -S "name=~^$vg-" | awk '{print $3}'| not grep error || \
|
||||
dmsetup table -S "name=~^$vg-" | not grep "error" || \
|
||||
die "Device(s) with error target should not be here."
|
||||
}
|
||||
|
||||
|
@@ -30,8 +30,7 @@ check lv_field $vg/$lv1 segtype "raid5"
|
||||
check lv_field $vg/$lv1 stripes 4
|
||||
check lv_field $vg/$lv1 data_stripes 3
|
||||
check lv_field $vg/$lv1 region_size "256.00k"
|
||||
wipefs -a $DM_DEV_DIR/$vg/$lv1
|
||||
mkfs -t ext4 $DM_DEV_DIR/$vg/$lv1
|
||||
echo y|mkfs -t ext4 $DM_DEV_DIR/$vg/$lv1
|
||||
fsck -fn $DM_DEV_DIR/$vg/$lv1
|
||||
aux wait_for_sync $vg $lv1
|
||||
fsck -fn $DM_DEV_DIR/$vg/$lv1
|
||||
|
@@ -12,34 +12,12 @@
|
||||
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
RUNDIR="/run"
|
||||
test -d "$RUNDIR" || RUNDIR="/var/run"
|
||||
PVS_ONLINE_DIR="$RUNDIR/lvm/pvs_online"
|
||||
VGS_ONLINE_DIR="$RUNDIR/lvm/vgs_online"
|
||||
|
||||
_clear_online_files() {
|
||||
# wait till udev is finished
|
||||
aux udev_wait
|
||||
rm -f "$PVS_ONLINE_DIR"/*
|
||||
rm -f "$VGS_ONLINE_DIR"/*
|
||||
}
|
||||
|
||||
. lib/inittest
|
||||
|
||||
test -f /proc/mdstat && grep -q raid1 /proc/mdstat || \
|
||||
modprobe raid1 || skip
|
||||
|
||||
aux lvmconf 'devices/md_component_detection = 1'
|
||||
|
||||
# This stops lvm from taking advantage of hints which
|
||||
# will have already excluded md components.
|
||||
aux lvmconf 'devices/hints = "none"'
|
||||
|
||||
# This stops lvm from asking udev if a dev is an md component.
|
||||
# LVM will ask udev if a dev is an md component, but we don't
|
||||
# want to rely on that ability in this test.
|
||||
aux lvmconf 'devices/obtain_device_list_from_udev = 0'
|
||||
|
||||
aux extend_filter_LVMTEST "a|/dev/md|"
|
||||
|
||||
aux prepare_devs 2
|
||||
@@ -48,107 +26,6 @@ aux prepare_devs 2
|
||||
# by default using metadata format 1.0 with data at the end of device
|
||||
aux prepare_md_dev 1 64 2 "$dev1" "$dev2"
|
||||
|
||||
cat /proc/mdstat
|
||||
|
||||
mddev=$(< MD_DEV)
|
||||
pvdev=$(< MD_DEV_PV)
|
||||
|
||||
vgcreate $vg "$mddev"
|
||||
|
||||
lvcreate -n $lv1 -l 2 $vg
|
||||
lvcreate -n $lv2 -l 2 -an $vg
|
||||
|
||||
lvchange -ay $vg/$lv2
|
||||
check lv_field $vg/$lv1 lv_active "active"
|
||||
|
||||
# lvm does not show md components as PVs
|
||||
pvs "$mddev"
|
||||
not pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs > out
|
||||
not grep "$dev1" out
|
||||
not grep "$dev2" out
|
||||
|
||||
sleep 1
|
||||
|
||||
vgchange -an $vg
|
||||
sleep 1
|
||||
|
||||
# When the md device is started, lvm will see that and know to
|
||||
# scan for md components, so stop the md device to remove this
|
||||
# advantage so we will test the fallback detection.
|
||||
mdadm --stop "$mddev"
|
||||
aux udev_wait
|
||||
|
||||
# The md components should still be detected and excluded.
|
||||
not pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs > out
|
||||
not grep "$dev1" out
|
||||
not grep "$dev2" out
|
||||
|
||||
pvs -vvvv
|
||||
|
||||
# should not activate from the md legs
|
||||
not vgchange -ay $vg
|
||||
|
||||
# should not show an active lv
|
||||
rm out
|
||||
lvs -o active $vg |tee out || true
|
||||
not grep "active" out
|
||||
|
||||
# should not allow updating vg
|
||||
not lvcreate -l1 $vg
|
||||
|
||||
# should not activate from the md legs
|
||||
_clear_online_files
|
||||
pvscan --cache -aay "$dev1"
|
||||
pvscan --cache -aay "$dev2"
|
||||
|
||||
# should not show an active lv
|
||||
rm out
|
||||
lvs -o active $vg |tee out || true
|
||||
not grep "active" out
|
||||
|
||||
# start the md dev
|
||||
mdadm --assemble "$mddev" "$dev1" "$dev2"
|
||||
aux udev_wait
|
||||
|
||||
# Now that the md dev is online, pvs can see it
|
||||
# and check for components even if
|
||||
# md_component_checks is "start" (which disables
|
||||
# most default end-of-device scans)
|
||||
aux lvmconf 'devices/md_component_checks = "start"'
|
||||
|
||||
not pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs > out
|
||||
not grep "$dev1" out
|
||||
not grep "$dev2" out
|
||||
|
||||
|
||||
vgchange -ay $vg
|
||||
|
||||
check lv_field $vg/$lv1 lv_active "active"
|
||||
|
||||
vgchange -an $vg
|
||||
aux udev_wait
|
||||
|
||||
vgremove -f $vg
|
||||
|
||||
aux cleanup_md_dev
|
||||
|
||||
# Put this setting back to the default
|
||||
aux lvmconf 'devices/md_component_checks = "auto"'
|
||||
|
||||
# create 2 disk MD raid0 array
|
||||
# by default using metadata format 1.0 with data at the end of device
|
||||
# When a raid0 md array is stopped, the components will not look like
|
||||
# duplicate PVs as they do with raid1.
|
||||
aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
|
||||
|
||||
cat /proc/mdstat
|
||||
|
||||
mddev=$(< MD_DEV)
|
||||
pvdev=$(< MD_DEV_PV)
|
||||
|
||||
@@ -160,81 +37,56 @@ lvcreate -n $lv1 -l 2 $vg
|
||||
lvcreate -n $lv2 -l 2 -an $vg
|
||||
|
||||
lvchange -ay $vg/$lv2
|
||||
check lv_field $vg/$lv1 lv_active "active"
|
||||
|
||||
# lvm does not show md components as PVs
|
||||
pvs "$mddev"
|
||||
not pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs > out
|
||||
not grep "$dev1" out
|
||||
not grep "$dev2" out
|
||||
lvs $vg
|
||||
|
||||
sleep 1
|
||||
pvs -vvvv 2>&1|tee pvs.out
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
vgchange -ay -vvvv $vg 2>&1| tee vgchange.out
|
||||
|
||||
lvs $vg
|
||||
pvs
|
||||
|
||||
vgchange -an $vg
|
||||
sleep 1
|
||||
|
||||
# When the md device is started, lvm will see that and know to
|
||||
# scan for md components, so stop the md device to remove this
|
||||
# advantage so we will test the fallback detection.
|
||||
mdadm --stop "$mddev"
|
||||
aux udev_wait
|
||||
|
||||
# The md components should still be detected and excluded.
|
||||
not pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs > out
|
||||
not grep "$dev1" out
|
||||
not grep "$dev2" out
|
||||
# with md superblock 1.0 this pvs will report duplicates
|
||||
# for the two md legs since the md device itself is not
|
||||
# started
|
||||
pvs 2>&1 |tee out
|
||||
cat out
|
||||
grep "prefers device" out
|
||||
|
||||
pvs -vvvv
|
||||
pvs -vvvv 2>&1| tee pvs2.out
|
||||
|
||||
# should not activate from the md legs
|
||||
not vgchange -ay $vg
|
||||
not vgchange -ay -vvvv $vg 2>&1|tee vgchange-fail.out
|
||||
|
||||
# should not show an active lv
|
||||
rm out
|
||||
lvs -o active $vg |tee out || true
|
||||
not grep "active" out
|
||||
|
||||
# should not allow updating vg
|
||||
not lvcreate -l1 $vg
|
||||
|
||||
# should not activate from the md legs
|
||||
_clear_online_files
|
||||
pvscan --cache -aay "$dev1"
|
||||
pvscan --cache -aay "$dev2"
|
||||
|
||||
# should not show an active lv
|
||||
rm out
|
||||
lvs -o active $vg |tee out || true
|
||||
not grep "active" out
|
||||
lvs $vg
|
||||
|
||||
# start the md dev
|
||||
mdadm --assemble "$mddev" "$dev1" "$dev2"
|
||||
aux udev_wait
|
||||
|
||||
# Now that the md dev is online, pvs can see it
|
||||
# and check for components even if
|
||||
# md_component_checks is "start" (which disables
|
||||
# most default end-of-device scans)
|
||||
aux lvmconf 'devices/md_component_checks = "start"'
|
||||
# Now that the md dev is online, pvs can see it and
|
||||
# ignore the two legs, so there's no duplicate warning
|
||||
|
||||
not pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs > out
|
||||
not grep "$dev1" out
|
||||
not grep "$dev2" out
|
||||
pvs 2>&1 |tee out
|
||||
cat out
|
||||
not grep "prefers device" out
|
||||
|
||||
vgchange -ay $vg 2>&1 |tee out
|
||||
|
||||
check lv_field $vg/$lv1 lv_active "active"
|
||||
cat out
|
||||
not grep "prefers device" out
|
||||
|
||||
vgchange -an $vg
|
||||
aux udev_wait
|
||||
|
||||
vgremove -f $vg
|
||||
|
||||
aux cleanup_md_dev
|
||||
|
||||
# vgremove -f $vg
|
||||
|
@@ -1,80 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3
|
||||
get_devs
|
||||
|
||||
#
|
||||
# Test corrupted mda_header.version field, which also
|
||||
# causes the mda_header checksum to be bad.
|
||||
#
|
||||
# FIXME: if a VG has only a single PV, this repair
|
||||
# doesn't work since there's no good PV to get
|
||||
# metadata from. A more advanced repair capability
|
||||
# is needed.
|
||||
#
|
||||
|
||||
dd if=/dev/zero of="$dev1" || true
|
||||
dd if=/dev/zero of="$dev2" || true
|
||||
dd if=/dev/zero of="$dev3" || true
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
pvs
|
||||
|
||||
if [ -e "/usr/bin/xxd" ]; then
|
||||
|
||||
# read mda_header which is 4k from start of disk
|
||||
dd if="$dev1" of=meta1 bs=4k count=1 skip=1
|
||||
|
||||
# convert binary to text
|
||||
xxd meta1 > meta1.txt
|
||||
|
||||
# Corrupt mda_header by changing the version field from 0100 to 0200
|
||||
sed 's/0000010:\ 304e\ 2a3e\ 0100\ 0000\ 0010\ 0000\ 0000\ 0000/0000010:\ 304e\ 2a3e\ 0200\ 0000\ 0010\ 0000\ 0000\ 0000/' meta1.txt > meta1-bad.txt
|
||||
|
||||
# convert text to binary
|
||||
xxd -r meta1-bad.txt > meta1-bad
|
||||
|
||||
# write bad mda_header back to disk
|
||||
dd if=meta1-bad of="$dev1" bs=4k seek=1
|
||||
|
||||
# pvs reports bad metadata header
|
||||
pvs 2>&1 | tee out
|
||||
grep "bad metadata header" out
|
||||
|
||||
fi
|
||||
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
# bad metadata in one mda doesn't prevent using
|
||||
# the VG since other mdas are fine and usable
|
||||
lvcreate -l1 $vg
|
||||
|
||||
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "bad metadata header" out
|
||||
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -ff $vg
|
||||
|
||||
|
@@ -1,236 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3
|
||||
get_devs
|
||||
|
||||
dd if=/dev/zero of="$dev1" || true
|
||||
dd if=/dev/zero of="$dev2" || true
|
||||
dd if=/dev/zero of="$dev3" || true
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
pvs
|
||||
|
||||
dd if="$dev1" of=meta1 bs=4k count=2
|
||||
|
||||
sed 's/flags =/flagx =/' meta1 > meta1.bad
|
||||
|
||||
dd if=meta1.bad of="$dev1"
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
grep "bad metadata text" out
|
||||
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
# bad metadata in one mda doesn't prevent using
|
||||
# the VG since other mdas are fine and usable
|
||||
lvcreate -l1 $vg
|
||||
|
||||
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "bad metadata text" out
|
||||
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -ff $vg
|
||||
|
||||
|
||||
#
|
||||
# Same test as above, but corrupt metadata text
|
||||
# on two of the three PVs, leaving one good
|
||||
# copy of the metadata.
|
||||
#
|
||||
|
||||
dd if=/dev/zero of="$dev1" || true
|
||||
dd if=/dev/zero of="$dev2" || true
|
||||
dd if=/dev/zero of="$dev3" || true
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
pvs
|
||||
|
||||
dd if="$dev1" of=meta1 bs=4k count=2
|
||||
dd if="$dev2" of=meta2 bs=4k count=2
|
||||
|
||||
sed 's/READ/RRRR/' meta1 > meta1.bad
|
||||
sed 's/seqno =/sss =/' meta2 > meta2.bad
|
||||
|
||||
dd if=meta1.bad of="$dev1"
|
||||
dd if=meta2.bad of="$dev2"
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
grep "bad metadata text" out > out2
|
||||
grep "$dev1" out2
|
||||
grep "$dev2" out2
|
||||
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
# bad metadata in one mda doesn't prevent using
|
||||
# the VG since other mdas are fine
|
||||
lvcreate -l1 $vg
|
||||
|
||||
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "bad metadata text" out
|
||||
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -ff $vg
|
||||
|
||||
#
|
||||
# Three PVs where two have one mda, and the third
|
||||
# has two mdas. The first mda is corrupted on all
|
||||
# thee PVs, but the second mda on the third PV
|
||||
# makes the VG usable.
|
||||
#
|
||||
|
||||
dd if=/dev/zero of="$dev1" || true
|
||||
dd if=/dev/zero of="$dev2" || true
|
||||
dd if=/dev/zero of="$dev3" || true
|
||||
|
||||
pvcreate "$dev1"
|
||||
pvcreate "$dev2"
|
||||
pvcreate --pvmetadatacopies 2 "$dev3"
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
pvs
|
||||
|
||||
dd if="$dev1" of=meta1 bs=4k count=2
|
||||
dd if="$dev2" of=meta2 bs=4k count=2
|
||||
dd if="$dev3" of=meta3 bs=4k count=2
|
||||
|
||||
sed 's/READ/RRRR/' meta1 > meta1.bad
|
||||
sed 's/seqno =/sss =/' meta2 > meta2.bad
|
||||
sed 's/id =/id/' meta3 > meta3.bad
|
||||
|
||||
dd if=meta1.bad of="$dev1"
|
||||
dd if=meta2.bad of="$dev2"
|
||||
dd if=meta3.bad of="$dev3"
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
grep "bad metadata text" out > out2
|
||||
grep "$dev1" out2
|
||||
grep "$dev2" out2
|
||||
grep "$dev3" out2
|
||||
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
# bad metadata in some mdas doesn't prevent using
|
||||
# the VG if there's a good mda found
|
||||
lvcreate -l1 $vg
|
||||
|
||||
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "bad metadata text" out
|
||||
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -ff $vg
|
||||
|
||||
#
|
||||
# Test that vgck --updatemetadata will update old metadata
|
||||
# and repair bad metadata text at the same time from different
|
||||
# devices.
|
||||
#
|
||||
|
||||
dd if=/dev/zero of="$dev1" || true
|
||||
dd if=/dev/zero of="$dev2" || true
|
||||
dd if=/dev/zero of="$dev3" || true
|
||||
|
||||
pvcreate "$dev1"
|
||||
pvcreate "$dev2"
|
||||
pvcreate --pvmetadatacopies 2 "$dev3"
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
# Put bad metadata onto dev1
|
||||
dd if="$dev1" of=meta1 bs=4k count=2
|
||||
sed 's/READ/RRRR/' meta1 > meta1.bad
|
||||
dd if=meta1.bad of="$dev1"
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
grep "bad metadata text" out > out2
|
||||
grep "$dev1" out2
|
||||
|
||||
# We can still use the VG with other available
|
||||
# mdas, skipping the bad mda.
|
||||
|
||||
lvcreate -n $lv1 -l1 -an $vg "$dev1"
|
||||
lvcreate -n $lv2 -l1 -an $vg "$dev1"
|
||||
|
||||
# Put old metadata onto dev2 by updating
|
||||
# the VG while dev2 is disabled.
|
||||
aux disable_dev "$dev2"
|
||||
|
||||
pvs
|
||||
pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
lvs $vg/$lv1
|
||||
lvs $vg/$lv2
|
||||
|
||||
lvremove $vg/$lv2
|
||||
|
||||
aux enable_dev "$dev2"
|
||||
|
||||
# Both old and bad metadata are reported.
|
||||
pvs 2>&1 | tee out
|
||||
grep "ignoring metadata seqno" out
|
||||
grep "bad metadata text" out
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
lvs $vg/$lv1
|
||||
not lvs $vg/$lv2
|
||||
|
||||
# fixes the bad metadata on dev1, and
|
||||
# fixes the old metadata on dev2.
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "ignoring metadata seqno" out
|
||||
not grep "bad metadata text" out
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
lvs $vg/$lv1
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -ff $vg
|
||||
|
@@ -1,177 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3
|
||||
get_devs
|
||||
|
||||
#
|
||||
# Test "old metadata" repair which occurs when the VG is written
|
||||
# and one of the PVs in the VG does not get written to, and then
|
||||
# the PV reappears with the old metadata. This can happen if
|
||||
# a command is killed or crashes after writing new metadata to
|
||||
# only some of the PVs in the VG, or if a PV is temporarily
|
||||
# inaccessible while a VG is written.
|
||||
#
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
#
|
||||
# Test that vgck --updatemetadata will update old metadata.
|
||||
#
|
||||
|
||||
lvcreate -n $lv1 -l1 -an $vg "$dev1"
|
||||
lvcreate -n $lv2 -l1 -an $vg "$dev1"
|
||||
|
||||
aux disable_dev "$dev2"
|
||||
|
||||
pvs
|
||||
pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
lvs $vg/$lv1
|
||||
lvs $vg/$lv2
|
||||
|
||||
lvremove $vg/$lv2
|
||||
|
||||
aux enable_dev "$dev2"
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
grep "ignoring metadata seqno" out
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
lvs $vg/$lv1
|
||||
not lvs $vg/$lv2
|
||||
|
||||
# fixes the old metadata on dev1
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "ignoring metadata seqno" out
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
lvs $vg/$lv1
|
||||
not lvs $vg/$lv2
|
||||
|
||||
#
|
||||
# Test that any writing command will also update the
|
||||
# old metadata.
|
||||
#
|
||||
|
||||
lvcreate -n $lv2 -l1 -an $vg "$dev1"
|
||||
|
||||
aux disable_dev "$dev2"
|
||||
|
||||
pvs
|
||||
pvs "$dev1"
|
||||
not pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
lvs $vg/$lv1
|
||||
lvs $vg/$lv2
|
||||
|
||||
lvremove $vg/$lv2
|
||||
|
||||
aux enable_dev "$dev2"
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
grep "ignoring metadata seqno" out
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
lvs $vg/$lv1
|
||||
not lvs $vg/$lv2
|
||||
|
||||
# fixes the old metadata on dev1
|
||||
lvcreate -n $lv3 -l1 -an $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "ignoring metadata seqno" out
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
lvs $vg/$lv1
|
||||
not lvs $vg/$lv2
|
||||
|
||||
vgremove -ff $vg
|
||||
|
||||
#
|
||||
# First two PVs with one mda, where both have old metadata.
|
||||
# Third PV with two mdas, where the first mda has old
|
||||
# metadata, and the second mda has current metadata.
|
||||
#
|
||||
|
||||
dd if=/dev/zero of="$dev1" || true
|
||||
dd if=/dev/zero of="$dev2" || true
|
||||
dd if=/dev/zero of="$dev3" || true
|
||||
|
||||
pvcreate "$dev1"
|
||||
pvcreate "$dev2"
|
||||
pvcreate --pvmetadatacopies 2 "$dev3"
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
lvcreate -n $lv1 -l1 -an $vg "$dev3"
|
||||
lvcreate -n $lv2 -l1 -an $vg "$dev3"
|
||||
|
||||
# Save the metadata at this point...
|
||||
dd if="$dev1" of=meta1 bs=4k count=4
|
||||
dd if="$dev2" of=meta2 bs=4k count=4
|
||||
dd if="$dev3" of=meta3 bs=4k count=4
|
||||
|
||||
# and now change metadata so the saved copies are old
|
||||
lvcreate -n $lv3 -l1 -an $vg "$dev3"
|
||||
|
||||
# Copy the saved metadata back to the three
|
||||
# devs first mda, leaving the second mda on
|
||||
# dev3 as the only latest copy of the metadata.
|
||||
|
||||
dd if=meta1 of="$dev1"
|
||||
dd if=meta2 of="$dev2"
|
||||
dd if=meta3 of="$dev3"
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
grep "ignoring metadata seqno" out
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
# We still see the three LVs since we are using
|
||||
# the latest copy of metadata from dev3:mda2
|
||||
|
||||
lvs $vg/$lv1
|
||||
lvs $vg/$lv2
|
||||
lvs $vg/$lv3
|
||||
|
||||
# This command which writes the VG should update
|
||||
# all of the old copies.
|
||||
lvcreate -n $lv4 -l1 -an $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "ignoring metadata seqno" out
|
||||
pvs "$dev1"
|
||||
pvs "$dev2"
|
||||
pvs "$dev3"
|
||||
|
||||
lvs $vg/$lv1
|
||||
lvs $vg/$lv2
|
||||
lvs $vg/$lv3
|
||||
lvs $vg/$lv4
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -ff $vg
|
@@ -123,16 +123,13 @@ check_and_cleanup_lvs_()
|
||||
recover_vg_()
|
||||
{
|
||||
aux enable_dev "$@"
|
||||
|
||||
# ensure hints are updated
|
||||
pvscan --cache
|
||||
# clear outdated metadata on PVs so they can be used again
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvscan --cache
|
||||
|
||||
pvcreate -ff "$@"
|
||||
# wipefs -a "$@"
|
||||
vgextend $vg "$@"
|
||||
|
||||
check_and_cleanup_lvs_
|
||||
}
|
||||
|
||||
|
@@ -1,86 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3
|
||||
get_devs
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
lvcreate -n $lv1 -L8M $vg "$dev2"
|
||||
lvcreate -n $lv2 -L8M $vg "$dev3"
|
||||
lvcreate -n $lv3 -L8M $vg "$dev2"
|
||||
lvcreate -n $lv4 -L8M $vg "$dev3"
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Fail device that is not used by any LVs.
|
||||
aux disable_dev "$dev1"
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Cannot do normal activation of LVs not using failed PV.
|
||||
lvchange -ay $vg/$lv1
|
||||
lvchange -ay $vg/$lv2
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
# Check that MISSING flag is not set in ondisk metadata.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
not grep MISSING meta
|
||||
rm meta
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# lvremove is one of the few commands that is allowed to run
|
||||
# when PVs are missing. The vg_write from this command sets
|
||||
# the MISSING flag on the PV in the ondisk metadata.
|
||||
# (this could be changed, the MISSING flag wouldn't need
|
||||
# to be set in the first place since the PV isn't used.)
|
||||
lvremove $vg/$lv1
|
||||
|
||||
# Check that MISSING flag is set in ondisk metadata.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
grep MISSING meta
|
||||
rm meta
|
||||
|
||||
# with MISSING flag in metadata, restrictions apply
|
||||
not lvcreate -l1 $vg
|
||||
|
||||
aux enable_dev "$dev1"
|
||||
|
||||
# No LVs are using the PV with MISSING flag, so no restrictions
|
||||
# are applied, and the vg_write here clears the MISSING flag on disk.
|
||||
lvcreate -l1 $vg
|
||||
|
||||
# Check that MISSING flag is not set in ondisk metadata.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
not grep MISSING meta
|
||||
rm meta
|
||||
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -ff $vg
|
||||
|
@@ -1,152 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3
|
||||
get_devs
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
lvcreate -n $lv1 -L8M --type mirror -m 1 $vg
|
||||
lvcreate -n $lv2 -L8M --type mirror -m 1 $vg
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Fail one leg of each mirror LV.
|
||||
aux disable_dev "$dev1"
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Cannot do normal activate of either LV with a failed leg.
|
||||
not lvchange -ay $vg/$lv1
|
||||
not lvchange -ay $vg/$lv2
|
||||
|
||||
# Can activate with partial option.
|
||||
lvchange -ay --activationmode partial $vg/$lv1
|
||||
lvchange -ay --activationmode partial $vg/$lv2
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Repair lv1 so it no longer uses failed dev.
|
||||
lvconvert --repair --yes $vg/$lv1
|
||||
|
||||
# Check that MISSING flag is set in ondisk metadata,
|
||||
# it should have been written by the lvconvert since the
|
||||
# missing PV is still used by lv2.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
grep MISSING meta
|
||||
rm meta
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Verify normal activation is possible of lv1 since it's
|
||||
# not using any failed devs, and partial activation is
|
||||
# required for lv2 since it's still using the failed dev.
|
||||
vgchange -an $vg
|
||||
lvchange -ay $vg/$lv1
|
||||
not lvchange -ay $vg/$lv2
|
||||
vgchange -an $vg
|
||||
|
||||
aux enable_dev "$dev1"
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# TODO: check that lv2 has partial flag, lv1 does not
|
||||
# (there's no partial reporting option, only attr p.)
|
||||
|
||||
# Check that MISSING flag is still set in ondisk
|
||||
# metadata since the previously missing dev is still
|
||||
# used by lv2.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
grep MISSING meta
|
||||
rm meta
|
||||
|
||||
|
||||
# The missing pv restrictions still apply even after
|
||||
# the dev has reappeared since it has the MISSING flag.
|
||||
not lvchange -ay $vg/$lv2
|
||||
not lvcreate -l1 $vg
|
||||
|
||||
# Update old metadata on the previously missing PV.
|
||||
# This should not clear the MISSING flag because the
|
||||
# previously missing PV is still used by lv2.
|
||||
# This would be done by any command that writes
|
||||
# metadata, e.g. lvcreate, but since we are in a
|
||||
# state with a missing pv, most commands that write
|
||||
# metadata are restricted, so use a command that
|
||||
# explicitly writes/fixes metadata.
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
# Check that MISSING flag is still set in ondisk
|
||||
# metadata since the previously missing dev is still
|
||||
# used by lv2.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
grep MISSING meta
|
||||
rm meta
|
||||
|
||||
|
||||
# The missing pv restrictions still apply since it
|
||||
# has the MISSING flag.
|
||||
not lvchange -ay $vg/$lv2
|
||||
not lvcreate -l1 $vg
|
||||
|
||||
lvchange -ay --activationmode partial $vg/$lv2
|
||||
|
||||
# After repair, no more LVs will be using the previously
|
||||
# missing PV.
|
||||
lvconvert --repair --yes $vg/$lv2
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
# The next write of the metadata will clear the MISSING
|
||||
# flag in ondisk metadata because the previously missing
|
||||
# PV is no longer used by any LVs.
|
||||
|
||||
# Run a command to write ondisk metadata, which should clear
|
||||
# the MISSING flag, could also use vgck --updatemetadata vg.
|
||||
lvcreate -l1 $vg
|
||||
|
||||
# Check that the MISSING flag is no longer set
|
||||
# in the ondisk metadata.
|
||||
pvck --dump metadata "$dev2" > meta
|
||||
not grep MISSING meta
|
||||
rm meta
|
||||
|
||||
|
||||
pvs
|
||||
vgs
|
||||
lvs -a -o+devices
|
||||
|
||||
vgchange -an $vg
|
||||
vgremove -ff $vg
|
||||
|
@@ -1,66 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3
|
||||
get_devs
|
||||
|
||||
#
|
||||
# Test handling of "outdated PV" which occurs when a PV goes missing
|
||||
# from a VG, and while it's missing the PV is removed from the VG.
|
||||
# Then the PV reappears with the old VG metadata that shows it is a
|
||||
# member. That outdated metadata needs to be cleared.
|
||||
#
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
lvcreate -n $lv1 -l1 -an $vg "$dev1"
|
||||
lvcreate -n $lv2 -l1 -an $vg "$dev1"
|
||||
|
||||
aux disable_dev "$dev2"
|
||||
|
||||
vgreduce --removemissing $vg
|
||||
|
||||
pvs
|
||||
|
||||
aux enable_dev "$dev2"
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
grep "outdated" out
|
||||
|
||||
not pvs "$dev2"
|
||||
|
||||
# The VG can still be used with the outdated PV around
|
||||
lvcreate -n $lv3 -l1 $vg
|
||||
lvchange -ay $vg
|
||||
lvs $vg
|
||||
lvchange -an $vg
|
||||
|
||||
# Clears the outdated PV
|
||||
vgck --updatemetadata $vg
|
||||
|
||||
pvs 2>&1 | tee out
|
||||
not grep "outdated" out
|
||||
|
||||
# The PV is no longer in the VG
|
||||
pvs "$dev2" | tee out
|
||||
not grep "$vg" out
|
||||
|
||||
# The cleared PV can be added back to the VG
|
||||
vgextend $vg "$dev2"
|
||||
|
||||
pvs "$dev2" | tee out
|
||||
grep "$vg" out
|
||||
|
||||
vgremove -ff $vg
|
||||
|
@@ -1,119 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_devs 3
|
||||
get_devs
|
||||
|
||||
dd if=/dev/zero of="$dev1" || true
|
||||
dd if=/dev/zero of="$dev2" || true
|
||||
dd if=/dev/zero of="$dev3" || true
|
||||
|
||||
pvcreate "$dev1"
|
||||
pvcreate "$dev2"
|
||||
pvcreate --pvmetadatacopies 2 "$dev3"
|
||||
|
||||
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
|
||||
|
||||
pvck --dump headers "$dev1" > h1
|
||||
pvck --dump headers "$dev2" > h2
|
||||
pvck --dump headers "$dev3" > h3
|
||||
|
||||
grep "label_header at 512" h1
|
||||
grep "label_header at 512" h2
|
||||
grep "label_header at 512" h3
|
||||
|
||||
grep "pv_header at 544" h1
|
||||
grep "pv_header at 544" h2
|
||||
grep "pv_header at 544" h3
|
||||
|
||||
grep "pv_header.disk_locn\[0\].offset 1048576" h1
|
||||
grep "pv_header.disk_locn\[0\].offset 1048576" h2
|
||||
grep "pv_header.disk_locn\[0\].offset 1048576" h3
|
||||
|
||||
grep "pv_header.disk_locn\[2\].offset 4096" h1
|
||||
grep "pv_header.disk_locn\[2\].offset 4096" h2
|
||||
grep "pv_header.disk_locn\[2\].offset 4096" h3
|
||||
|
||||
grep "pv_header.disk_locn\[2\].size 1044480" h1
|
||||
grep "pv_header.disk_locn\[2\].size 1044480" h2
|
||||
grep "pv_header.disk_locn\[2\].size 1044480" h3
|
||||
|
||||
grep "mda_header_1 at 4096" h1
|
||||
grep "mda_header_1 at 4096" h2
|
||||
grep "mda_header_1 at 4096" h3
|
||||
|
||||
grep "mda_header_1.start 4096" h1
|
||||
grep "mda_header_1.start 4096" h2
|
||||
grep "mda_header_1.start 4096" h3
|
||||
|
||||
grep "mda_header_1.size 1044480" h1
|
||||
grep "mda_header_1.size 1044480" h2
|
||||
grep "mda_header_1.size 1044480" h3
|
||||
|
||||
grep "mda_header_2 at " h3
|
||||
grep "mda_header_2.start " h3
|
||||
|
||||
grep "metadata text at " h1
|
||||
grep "metadata text at " h2
|
||||
grep "metadata text at " h3
|
||||
|
||||
not grep CHECK h1
|
||||
not grep CHECK h2
|
||||
not grep CHECK h3
|
||||
|
||||
pvck --dump metadata "$dev1" > m1
|
||||
pvck --dump metadata "$dev2" > m2
|
||||
pvck --dump metadata "$dev3" > m3
|
||||
pvck --dump metadata --pvmetadatacopies 2 "$dev3" > m3b
|
||||
|
||||
diff m1 m2
|
||||
diff m1 m3
|
||||
|
||||
not diff m1 m3b > tmp
|
||||
grep "metadata text at" tmp
|
||||
|
||||
lvcreate -an -l1 $vg
|
||||
|
||||
pvck --dump metadata_all -f all1 "$dev1" > out1
|
||||
pvck --dump metadata_all -f all2 "$dev2" > out2
|
||||
pvck --dump metadata_all -f all3 "$dev3" > out3
|
||||
pvck --dump metadata_all --pvmetadatacopies 2 -f all3b "$dev3" > out3b
|
||||
|
||||
diff out1 out2
|
||||
diff out1 out3
|
||||
|
||||
grep "seqno 1 with" out1
|
||||
grep "seqno 1 with" out3b
|
||||
grep "seqno 2 with" out1
|
||||
grep "seqno 2 with" out3b
|
||||
|
||||
diff all1 all2
|
||||
diff all1 all3
|
||||
diff all1 all3b
|
||||
|
||||
grep "seqno = 1" all1
|
||||
grep "seqno = 2" all1
|
||||
|
||||
|
||||
pvck --dump metadata_area -f area1 "$dev1"
|
||||
pvck --dump metadata_area -f area2 "$dev2"
|
||||
pvck --dump metadata_area -f area3 "$dev3"
|
||||
pvck --dump metadata_area -f area3b "$dev3"
|
||||
|
||||
diff area1 area2
|
||||
diff area1 area3
|
||||
diff area1 area3b
|
||||
|
||||
vgremove -ff $vg
|
||||
|
@@ -33,9 +33,9 @@ test_pvmove_resume() {
|
||||
# next LV on same VG and differetnt PV (we want to test 2 pvmoves per VG)
|
||||
lvcreate -an -Zn -l30 -n $lv2 $vg "$dev3"
|
||||
|
||||
aux delay_dev "$dev4" 0 500 "$(get first_extent_sector "$dev4"):"
|
||||
aux delay_dev "$dev4" 0 250 "$(get first_extent_sector "$dev4"):"
|
||||
test -e HAVE_DM_DELAY || { lvremove -f $vg; return 0; }
|
||||
aux delay_dev "$dev5" 0 500 "$(get first_extent_sector "$dev5"):"
|
||||
aux delay_dev "$dev5" 0 250 "$(get first_extent_sector "$dev5"):"
|
||||
|
||||
pvmove -i5 "$dev1" "$dev4" &
|
||||
PVMOVE=$!
|
||||
|
@@ -27,7 +27,7 @@ _clear_online_files() {
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux prepare_pvs 8
|
||||
aux prepare_pvs 3
|
||||
|
||||
vgcreate $vg1 "$dev1" "$dev2"
|
||||
lvcreate -n $lv1 -l 4 -a n $vg1
|
||||
@@ -59,19 +59,6 @@ pvscan --cache -aay "$dev1" "$dev2"
|
||||
check lv_field $vg1/$lv1 lv_active "active"
|
||||
lvchange -an $vg1
|
||||
|
||||
# check that a cache command without aay will
|
||||
# just record online state, and that a following
|
||||
# pvscan cache aay that does not record any new
|
||||
# online files will activate the vg
|
||||
_clear_online_files
|
||||
pvscan --cache "$dev1"
|
||||
check lv_field $vg1/$lv1 lv_active ""
|
||||
pvscan --cache "$dev2"
|
||||
check lv_field $vg1/$lv1 lv_active ""
|
||||
pvscan --cache -aay
|
||||
check lv_field $vg1/$lv1 lv_active "active"
|
||||
lvchange -an $vg1
|
||||
|
||||
# Set up tests where one dev has no metadata
|
||||
|
||||
vgchange -an $vg1
|
||||
@@ -109,6 +96,18 @@ lvchange -an $vg1
|
||||
|
||||
_clear_online_files
|
||||
|
||||
pvscan --cache "$dev1"
|
||||
check lv_field $vg1/$lv1 lv_active ""
|
||||
pvscan --cache "$dev2"
|
||||
check lv_field $vg1/$lv1 lv_active ""
|
||||
pvscan --cache -aay
|
||||
check lv_field $vg1/$lv1 lv_active "active"
|
||||
lvchange -an $vg1
|
||||
|
||||
# like previous
|
||||
|
||||
_clear_online_files
|
||||
|
||||
pvscan --cache "$dev1"
|
||||
check lv_field $vg1/$lv1 lv_active ""
|
||||
pvscan --cache -aay "$dev2"
|
||||
@@ -134,9 +133,7 @@ not ls "$RUNDIR/lvm/pvs_online/$PVID3"
|
||||
|
||||
# pvscan cache ignores pv in a foreign vg
|
||||
|
||||
if [ -e "/etc/machine-id" ]; then
|
||||
|
||||
aux lvmconf "global/system_id_source = machineid"
|
||||
aux lvmconf "global/system_id_source = uname"
|
||||
|
||||
_clear_online_files
|
||||
|
||||
@@ -170,42 +167,5 @@ cat tmp
|
||||
grep $lv2 tmp
|
||||
check lv_field $vg2/$lv2 lv_active "" --foreign
|
||||
|
||||
fi
|
||||
|
||||
|
||||
# Test the case where pvscan --cache -aay (with no devs)
|
||||
# gets the final PV to complete the VG, where that final PV
|
||||
# does not hold VG metadata. In this case it needs to rely
|
||||
# on VG metadata that has been saved from a previously
|
||||
# scanned PV from the same VG.
|
||||
#
|
||||
# We can't control which order of devices pvscan will see,
|
||||
# so create several PVs without metadata surrounding one
|
||||
# PV with metadata, to make it likely that pvscan will
|
||||
# get a final PV without metadata.
|
||||
|
||||
pvcreate --metadatacopies 0 "$dev4"
|
||||
pvcreate --metadatacopies 0 "$dev5"
|
||||
pvcreate --metadatacopies 1 "$dev6"
|
||||
pvcreate --metadatacopies 0 "$dev7"
|
||||
pvcreate --metadatacopies 0 "$dev8"
|
||||
vgcreate $vg3 "$dev4" "$dev5" "$dev6" "$dev7" "$dev8"
|
||||
lvcreate -n $lv1 -l 4 -a n $vg3
|
||||
|
||||
_clear_online_files
|
||||
|
||||
check lv_field $vg3/$lv1 lv_active ""
|
||||
pvscan --cache "$dev4"
|
||||
check lv_field $vg3/$lv1 lv_active ""
|
||||
pvscan --cache "$dev5"
|
||||
check lv_field $vg3/$lv1 lv_active ""
|
||||
pvscan --cache "$dev6"
|
||||
check lv_field $vg3/$lv1 lv_active ""
|
||||
pvscan --cache "$dev7"
|
||||
check lv_field $vg3/$lv1 lv_active ""
|
||||
pvscan --cache "$dev8"
|
||||
check lv_field $vg3/$lv1 lv_active ""
|
||||
pvscan --cache -aay
|
||||
check lv_field $vg3/$lv1 lv_active "active"
|
||||
lvchange -an $vg3
|
||||
|
||||
|
@@ -59,9 +59,7 @@ check lv_field $vg1/$lv1 lv_active ""
|
||||
pvscan --cache -aay "$dev1"
|
||||
pvscan --cache -aay "$dev2"
|
||||
check lv_field $vg1/$lv1 lv_active "active"
|
||||
lvchange -an -vvvv $vg1/$lv1
|
||||
dmsetup ls
|
||||
lvremove $vg1/$lv1
|
||||
lvchange -an $vg1/$lv1
|
||||
|
||||
# When MDA is ignored on PV, do not read any VG
|
||||
# metadata from such PV as it may contain old
|
||||
|
@@ -73,7 +73,7 @@ lvresize --poolmetadatasize 64 $vg/$lv7
|
||||
lvresize --poolmetadatasize +8 $vg/$lv7
|
||||
not lvresize -y --poolmetadatasize -8 $vg/$lv7
|
||||
|
||||
lvextend --poolmetadatasize +4 $vg/$lv7
|
||||
lvextend --poolmetadatasize +8 $vg/$lv7
|
||||
not lvextend -y --poolmetadatasize -8 $vg/$lv7
|
||||
fi
|
||||
|
||||
|
10
tools/args.h
10
tools/args.h
@@ -213,13 +213,6 @@ arg(driverloaded_ARG, '\0', "driverloaded", bool_VAL, 0, 0,
|
||||
"If set to no, the command will not attempt to use device-mapper.\n"
|
||||
"For testing and debugging.\n")
|
||||
|
||||
arg(dump_ARG, '\0', "dump", string_VAL, 0, 0,
|
||||
"Dump metadata from a PV. Option values include \\fBmetadata\\fP\n"
|
||||
"to print or save the current text metadata, \\fBmetadata_area\\fP\n"
|
||||
"to save the entire text metadata area to a file, \\fBmetadata_all\\fP\n"
|
||||
"to save the current and any previous complete versions of metadata\n"
|
||||
"to a file, and \\fBheaders\\fP to print and check LVM headers.\n")
|
||||
|
||||
arg(errorwhenfull_ARG, '\0', "errorwhenfull", bool_VAL, 0, 0,
|
||||
"Specifies thin pool behavior when data space is exhausted.\n"
|
||||
"When yes, device-mapper will immediately return an error\n"
|
||||
@@ -713,8 +706,9 @@ arg(trackchanges_ARG, '\0', "trackchanges", 0, 0, 0,
|
||||
"merging the split image (see --mergemirrors) or permanently splitting\n"
|
||||
"the image (see --splitmirrors with --name.\n")
|
||||
|
||||
/* TODO: hide this? */
|
||||
arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0,
|
||||
"No longer used.\n")
|
||||
"Avoids certain device scanning during command processing. Do not use.\n")
|
||||
|
||||
arg(type_ARG, '\0', "type", segtype_VAL, 0, 0,
|
||||
"The LV type, also known as \"segment type\" or \"segtype\".\n"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user