mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-24 21:44:22 +03:00
Compare commits
3 Commits
dev-dct-ne
...
dev-bmr-dm
Author | SHA1 | Date | |
---|---|---|---|
|
261b1e54e4 | ||
|
08658195b9 | ||
|
3d85c9ae57 |
13
README
13
README
@@ -8,15 +8,10 @@ There is no warranty - see COPYING and COPYING.LIB.
|
||||
Tarballs are available from:
|
||||
ftp://sourceware.org/pub/lvm2/
|
||||
ftp://sources.redhat.com/pub/lvm2/
|
||||
https://github.com/lvmteam/lvm2/releases
|
||||
|
||||
The source code is stored in git:
|
||||
https://sourceware.org/git/?p=lvm2.git
|
||||
git clone git://sourceware.org/git/lvm2.git
|
||||
mirrored to:
|
||||
https://github.com/lvmteam/lvm2
|
||||
git clone https://github.com/lvmteam/lvm2.git
|
||||
git clone git@github.com:lvmteam/lvm2.git
|
||||
|
||||
Mailing list for general discussion related to LVM2:
|
||||
linux-lvm@redhat.com
|
||||
@@ -34,14 +29,6 @@ and multipath-tools:
|
||||
dm-devel@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/dm-devel
|
||||
|
||||
Website:
|
||||
https://sourceware.org/lvm2/
|
||||
|
||||
Report upstream bugs at:
|
||||
https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper
|
||||
or open issues at:
|
||||
https://github.com/lvmteam/lvm2/issues
|
||||
|
||||
The source code repository used until 7th June 2012 is accessible here:
|
||||
http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2.
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
1.02.145-git (2017-10-06)
|
||||
1.02.141-git (2017-05-03)
|
||||
|
83
WHATS_NEW
83
WHATS_NEW
@@ -1,84 +1,5 @@
|
||||
Version 2.02.176 -
|
||||
===================================
|
||||
Ignore --stripes/--stripesize on RAID takeover
|
||||
Improve used paths for generated systemd units and init shells.
|
||||
Disallow creation of snapshot of mirror/raid subLV (was never supported).
|
||||
Fix regression in more advanced vgname extraction in lvconvert (2.02.169).
|
||||
Allow lvcreate to be used for caching of _tdata LV.
|
||||
Avoid internal error when resizing cache type _tdata LV (not yet supported).
|
||||
Show original converted names when lvconverting LV to pool volume.
|
||||
Move lib code used only by liblvm into metadata-liblvm.c.
|
||||
Distinguish between device not found and excluded by filter.
|
||||
Monitor external origin LVs.
|
||||
Remove the replicator code, including configure --with-replicators.
|
||||
Allow lvcreate --type mirror to work with 100%FREE.
|
||||
Improve selection of resource name for complex volume activation lock.
|
||||
Avoid cutting first character of resource name for activation lock.
|
||||
Support for encrypted devices in fsadm.
|
||||
Improve thin pool overprovisioning and repair warning messages.
|
||||
Fix incorrect adjustment of region size on striped RaidLVs.
|
||||
|
||||
Version 2.02.175 - 6th October 2017
|
||||
===================================
|
||||
Use --help with blockdev when checking for --getsize64 support in fsadm.
|
||||
Dump lvmdbusd debug information with SIGUSR1.
|
||||
Fix metadata corruption in vgsplit and vgmerge intermediate states.
|
||||
Add PV_MOVED_VG PV status flag to mark PVs moving between VGs.
|
||||
Fix lvmdbus hang and recognise unknown VG correctly.
|
||||
Improve error messages when command rules fail.
|
||||
Require LV name with pvmove in a shared VG.
|
||||
Allow shared active mirror LVs with lvmlockd, dlm, and cmirrord.
|
||||
Support lvconvert --repair with cache and cachepool volumes.
|
||||
lvconvert --repair respects --poolmetadataspare option.
|
||||
Mark that we don't plan to develop liblvm2app and python bindings any further.
|
||||
Fix thin pool creation in shared VG. (2.02.173)
|
||||
|
||||
Version 2.02.174 - 13th September 2017
|
||||
======================================
|
||||
Prevent raid1 split with trackchanges in a shared VG.
|
||||
Avoid double unlocking of client & lockspace mutexes in lvmlockd.
|
||||
Fix leaking of file descriptor for non-blocking filebased locking.
|
||||
Fix check for 2nd mda at end of disk fits if using pvcreate --restorefile.
|
||||
Use maximum metadataarea size that fits with pvcreate --restorefile.
|
||||
Always clear cached bootloaderarea when wiping label e.g. in pvcreate.
|
||||
Disallow --bootloaderareasize with pvcreate --restorefile.
|
||||
Fix lvmlockd check for running lock managers during lock adoption.
|
||||
Add --withgeneralpreamble and --withlocalpreamble to lvmconfig.
|
||||
Improve makefiles' linking.
|
||||
Fix some paths in generated makefiles to respected configured settings.
|
||||
Add warning when creating thin-pool with zeroing and chunk size >= 512KiB.
|
||||
Introduce exit code 4 EINIT_FAILED to replace -1 when initialisation fails.
|
||||
Add synchronization points with udev during reshape of raid LVs.
|
||||
|
||||
Version 2.02.173 - 20th July 2017
|
||||
=================================
|
||||
Add synchronization points with udev during conversion of raid LVs.
|
||||
Improve --size args validation and report more detailed error message.
|
||||
Initialize debugging mutex before any debug message in clvmd.
|
||||
Log error instead of warn when noticing connection problem with lvmetad.
|
||||
Fix memory leak in lvmetad when working with duplicates.
|
||||
Remove restrictions on reshaping open and clustered raid devices.
|
||||
Add incompatible data_offset to raid metadata to fix reshape activation.
|
||||
Accept 'lvm -h' and 'lvm --help' as well as 'lvm help' for help.
|
||||
Suppress error message from accept() on clean lvmetad shutdown.
|
||||
Tidy clvmd client list processing and fix segfaults.
|
||||
Protect clvmd debug log messages with mutex and add client id.
|
||||
Fix shellcheck reported issues for script files.
|
||||
|
||||
Version 2.02.172 - 28th June 2017
|
||||
=================================
|
||||
Add missing NULL to argv array when spliting cmdline arguments.
|
||||
Add display_percent helper function for printing percent values.
|
||||
lvconvert --repair handles failing raid legs (present but marked 'D'ead).
|
||||
Do not lvdisplay --maps unset settings of cache pool.
|
||||
Fix lvdisplay --maps for cache pool without policy settings.
|
||||
Support aborting of flushing cache LV.
|
||||
Reenable conversion of data and metadata thin-pool volumes to raid.
|
||||
Improve raid status reporting with lvs.
|
||||
No longer necessary to '--force' a repair for RAID1.
|
||||
Linear to RAID1 upconverts now use "recover" sync action, not "resync".
|
||||
Improve lvcreate --cachepool arg validation.
|
||||
Limit maximum size of thin-pool for specific chunk size.
|
||||
Version 2.02.172 -
|
||||
===============================
|
||||
Print a warning about in-use PVs with no VG using them.
|
||||
Disable automatic clearing of PVs that look like in-use orphans.
|
||||
Cache format2 flag is now using segment name type field.
|
||||
|
35
WHATS_NEW_DM
35
WHATS_NEW_DM
@@ -1,36 +1,5 @@
|
||||
Version 1.02.145 -
|
||||
===================================
|
||||
Fix RT_LIBS reference in generated libdevmapper.pc for pkg-config
|
||||
|
||||
Version 1.02.144 - 6th October 2017
|
||||
===================================
|
||||
Schedule exit when received SIGTERM in dmeventd.
|
||||
Also try to unmount /boot on blkdeactivate -u if on top of supported device.
|
||||
Use blkdeactivate -r wait in blk-availability systemd service/initscript.
|
||||
Add blkdeactivate -r wait option to wait for MD resync/recovery/reshape.
|
||||
Fix blkdeactivate regression with failing DM/MD devs deactivation (1.02.142).
|
||||
Fix typo in blkdeactivate's '--{dm,lvm,mpath}options' option name.
|
||||
Correct return value testing when get reserved values for reporting.
|
||||
Take -S with dmsetup suspend/resume/clear/wipe_table/remove/deps/status/table.
|
||||
|
||||
Version 1.02.143 - 13th September 2017
|
||||
======================================
|
||||
Restore umask when creation of node fails.
|
||||
Add --concise to dmsetup create for many devices with tables in one command.
|
||||
Accept minor number without major in library when it knows dm major number.
|
||||
Introduce single-line concise table output format: dmsetup table --concise
|
||||
|
||||
Version 1.02.142 - 20th July 2017
|
||||
=================================
|
||||
Create /dev/disk/by-part{uuid,label} and gpt-auto-root symlinks with udev.
|
||||
|
||||
Version 1.02.141 - 28th June 2017
|
||||
=================================
|
||||
Fix reusing of dm_task structure for status reading (used by dmeventd).
|
||||
Add dm_percent_to_round_float for adjusted percentage rounding.
|
||||
Reset array with dead rimage devices once raid gets in sync.
|
||||
Drop unneeded --config option from raid dmeventd plugin.
|
||||
dm_get_status_raid() handle better some incosistent md statuses.
|
||||
Version 1.02.141 -
|
||||
===============================
|
||||
Accept truncated files in calls to dm_stats_update_regions_from_fd().
|
||||
Restore Warning by 5% increment when thin-pool is over 80% (1.02.138).
|
||||
|
||||
|
@@ -32,8 +32,8 @@ include $(top_builddir)/make.tmpl
|
||||
.PHONY: install_conf install_localconf install_profiles
|
||||
|
||||
generate:
|
||||
LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withgeneralpreamble --withcomments --ignorelocal --withspaces > example.conf.in
|
||||
LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withlocalpreamble --withcomments --withspaces local > lvmlocal.conf.in
|
||||
(cat $(top_srcdir)/conf/example.conf.base && LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withcomments --ignorelocal --withspaces) > example.conf.in
|
||||
(cat $(top_srcdir)/conf/lvmlocal.conf.base && LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withcomments --withspaces local) > lvmlocal.conf.in
|
||||
|
||||
install_conf: $(CONFSRC)
|
||||
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||
|
23
conf/example.conf.base
Normal file
23
conf/example.conf.base
Normal file
@@ -0,0 +1,23 @@
|
||||
# This is an example configuration file for the LVM2 system.
|
||||
# It contains the default settings that would be used if there was no
|
||||
# @DEFAULT_SYS_DIR@/lvm.conf file.
|
||||
#
|
||||
# Refer to 'man lvm.conf' for further information including the file layout.
|
||||
#
|
||||
# Refer to 'man lvm.conf' for information about how settings configured in
|
||||
# this file are combined with built-in values and command line options to
|
||||
# arrive at the final values used by LVM.
|
||||
#
|
||||
# Refer to 'man lvmconfig' for information about displaying the built-in
|
||||
# and configured values used by LVM.
|
||||
#
|
||||
# If a default value is set in this file (not commented out), then a
|
||||
# new version of LVM using this file will continue using that value,
|
||||
# even if the new version of LVM changes the built-in default value.
|
||||
#
|
||||
# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set
|
||||
# the environment variable LVM_SYSTEM_DIR before running the tools.
|
||||
#
|
||||
# N.B. Take care that each setting only appears once if uncommenting
|
||||
# example settings in this file.
|
||||
|
@@ -379,9 +379,8 @@ allocation {
|
||||
|
||||
# Configuration option allocation/raid_stripe_all_devices.
|
||||
# Stripe across all PVs when RAID stripes are not specified.
|
||||
# If enabled, all PVs in the VG or on the command line are used for
|
||||
# raid0/4/5/6/10 when the command does not specify the number of
|
||||
# stripes to use.
|
||||
# If enabled, all PVs in the VG or on the command line are used for raid0/4/5/6/10
|
||||
# when the command does not specify the number of stripes to use.
|
||||
# This was the default behaviour until release 2.02.162.
|
||||
# This configuration option has an automatic default value.
|
||||
# raid_stripe_all_devices = 0
|
||||
@@ -940,7 +939,7 @@ global {
|
||||
use_lvmetad = @DEFAULT_USE_LVMETAD@
|
||||
|
||||
# Configuration option global/lvmetad_update_wait_time.
|
||||
# Number of seconds a command will wait for lvmetad update to finish.
|
||||
# The number of seconds a command will wait for lvmetad update to finish.
|
||||
# After waiting for this period, a command will not use lvmetad, and
|
||||
# will revert to disk scanning.
|
||||
# This configuration option has an automatic default value.
|
||||
|
19
conf/lvmlocal.conf.base
Normal file
19
conf/lvmlocal.conf.base
Normal file
@@ -0,0 +1,19 @@
|
||||
# This is a local configuration file template for the LVM2 system
|
||||
# which should be installed as @DEFAULT_SYS_DIR@/lvmlocal.conf .
|
||||
#
|
||||
# Refer to 'man lvm.conf' for information about the file layout.
|
||||
#
|
||||
# To put this file in a different directory and override
|
||||
# @DEFAULT_SYS_DIR@ set the environment variable LVM_SYSTEM_DIR before
|
||||
# running the tools.
|
||||
#
|
||||
# The lvmlocal.conf file is normally expected to contain only the
|
||||
# "local" section which contains settings that should not be shared or
|
||||
# repeated among different hosts. (But if other sections are present,
|
||||
# they *will* get processed. Settings in this file override equivalent
|
||||
# ones in lvm.conf and are in turn overridden by ones in any enabled
|
||||
# lvm_<tag>.conf files.)
|
||||
#
|
||||
# Please take care that each setting only appears once if uncommenting
|
||||
# example settings in this file and never copy this file between hosts.
|
||||
|
368
configure
vendored
368
configure
vendored
@@ -643,7 +643,6 @@ LVMETAD_PIDFILE
|
||||
DMEVENTD_PIDFILE
|
||||
WRITE_INSTALL
|
||||
VALGRIND_POOL
|
||||
USRSBINDIR
|
||||
USE_TRACKING
|
||||
UDEV_HAS_BUILTIN_BLKID
|
||||
UDEV_RULE_EXEC_DETECTION
|
||||
@@ -657,13 +656,11 @@ TESTING
|
||||
STATIC_LINK
|
||||
STATICDIR
|
||||
SNAPSHOTS
|
||||
SYSCONFDIR
|
||||
SELINUX_PC
|
||||
SELINUX_LIBS
|
||||
SBINDIR
|
||||
REPLICATORS
|
||||
READLINE_LIBS
|
||||
RT_LIBS
|
||||
RT_LIB
|
||||
RAID
|
||||
PYTHON3DIR
|
||||
PYTHON2DIR
|
||||
@@ -707,15 +704,13 @@ FSADM
|
||||
ELDFLAGS
|
||||
DM_LIB_PATCHLEVEL
|
||||
DMEVENTD_PATH
|
||||
AIO_LIBS
|
||||
DMEVENTD
|
||||
DL_LIBS
|
||||
AIO
|
||||
DEVMAPPER
|
||||
DEFAULT_USE_LVMLOCKD
|
||||
DEFAULT_USE_LVMPOLLD
|
||||
DEFAULT_USE_LVMETAD
|
||||
DEFAULT_USE_BLKID_WIPING
|
||||
DEFAULT_SYS_LOCK_DIR
|
||||
DEFAULT_SYS_DIR
|
||||
DEFAULT_SPARSE_SEGTYPE
|
||||
DEFAULT_RUN_DIR
|
||||
@@ -832,7 +827,6 @@ WC
|
||||
CHMOD
|
||||
CSCOPE_CMD
|
||||
CFLOW_CMD
|
||||
AR
|
||||
RANLIB
|
||||
MKDIR_P
|
||||
SET_MAKE
|
||||
@@ -926,6 +920,7 @@ with_mirrors
|
||||
with_raid
|
||||
with_default_mirror_segtype
|
||||
with_default_raid10_segtype
|
||||
with_replicators
|
||||
with_default_sparse_segtype
|
||||
with_thin
|
||||
with_thin_check
|
||||
@@ -956,7 +951,6 @@ enable_profiling
|
||||
enable_testing
|
||||
enable_valgrind_pool
|
||||
enable_devmapper
|
||||
enable_aio
|
||||
enable_lvmetad
|
||||
enable_lvmpolld
|
||||
enable_lvmlockd_sanlock
|
||||
@@ -1695,7 +1689,6 @@ Optional Features:
|
||||
--enable-testing enable testing targets in the makefile
|
||||
--enable-valgrind-pool enable valgrind awareness of pools
|
||||
--disable-devmapper disable LVM2 device-mapper interaction
|
||||
--disable-aio disable async i/o
|
||||
--enable-lvmetad enable the LVM Metadata Daemon
|
||||
--enable-lvmpolld enable the LVM Polling Daemon
|
||||
--enable-lvmlockd-sanlock
|
||||
@@ -1762,6 +1755,7 @@ Optional Packages:
|
||||
default mirror segtype: raid1/mirror [raid1]
|
||||
--with-default-raid10-segtype=TYPE
|
||||
default mirror segtype: raid10/mirror [raid10]
|
||||
--with-replicators=TYPE replicator support: internal/shared/none [none]
|
||||
--with-default-sparse-segtype=TYPE
|
||||
default sparse segtype: thin/snapshot [thin]
|
||||
--with-thin=TYPE thin provisioning support: internal/shared/none
|
||||
@@ -3175,7 +3169,6 @@ fi
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
|
||||
# equivalent to -rdynamic
|
||||
ELDFLAGS="-Wl,--export-dynamic"
|
||||
# FIXME Generate list and use --dynamic-list=.dlopen.sym
|
||||
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
||||
@@ -3183,7 +3176,6 @@ case "$host_os" in
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
AIO=yes
|
||||
BUILD_LVMETAD=no
|
||||
BUILD_LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
@@ -3203,7 +3195,6 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LIB_SUFFIX=dylib
|
||||
DEVMAPPER=yes
|
||||
AIO=no
|
||||
ODIRECT=no
|
||||
DM_IOCTLS=no
|
||||
SELINUX=no
|
||||
@@ -4956,98 +4947,6 @@ else
|
||||
RANLIB="$ac_cv_prog_RANLIB"
|
||||
fi
|
||||
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}ar; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_AR+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$AR"; then
|
||||
ac_cv_prog_AR="$AR" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_AR="${ac_tool_prefix}ar"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
AR=$ac_cv_prog_AR
|
||||
if test -n "$AR"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
|
||||
$as_echo "$AR" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
if test -z "$ac_cv_prog_AR"; then
|
||||
ac_ct_AR=$AR
|
||||
# Extract the first word of "ar", so it can be a program name with args.
|
||||
set dummy ar; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_ac_ct_AR+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$ac_ct_AR"; then
|
||||
ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_AR="ar"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
ac_ct_AR=$ac_cv_prog_ac_ct_AR
|
||||
if test -n "$ac_ct_AR"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
|
||||
$as_echo "$ac_ct_AR" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
if test "x$ac_ct_AR" = x; then
|
||||
AR=""
|
||||
else
|
||||
case $cross_compiling:$ac_tool_warned in
|
||||
yes:)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
ac_tool_warned=yes ;;
|
||||
esac
|
||||
AR=$ac_ct_AR
|
||||
fi
|
||||
else
|
||||
AR="$ac_cv_prog_AR"
|
||||
fi
|
||||
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}cflow", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}cflow; ac_word=$2
|
||||
@@ -8248,14 +8147,9 @@ $as_echo "$ac_cv_flag_HAVE_FULL_RELRO" >&6; }
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
################################################################################
|
||||
test "$exec_prefix" = NONE -a "$prefix" = NONE && exec_prefix=""
|
||||
|
||||
test "x$prefix" = xNONE && prefix=$ac_default_prefix
|
||||
# Let make expand exec_prefix.
|
||||
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
|
||||
|
||||
if test "$prefix" = NONE; then
|
||||
datarootdir=${ac_default_prefix}/share
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking file owner" >&5
|
||||
@@ -8579,6 +8473,28 @@ _ACEOF
|
||||
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include replicators" >&5
|
||||
$as_echo_n "checking whether to include replicators... " >&6; }
|
||||
|
||||
# Check whether --with-replicators was given.
|
||||
if test "${with_replicators+set}" = set; then :
|
||||
withval=$with_replicators; REPLICATORS=$withval
|
||||
else
|
||||
REPLICATORS=none
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $REPLICATORS" >&5
|
||||
$as_echo "$REPLICATORS" >&6; }
|
||||
|
||||
case "$REPLICATORS" in
|
||||
none|shared) ;;
|
||||
internal)
|
||||
$as_echo "#define REPLICATOR_INTERNAL 1" >>confdefs.h
|
||||
;;
|
||||
*) as_fn_error $? "--with-replicators parameter invalid ($REPLICATORS)" "$LINENO" 5 ;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
# Check whether --with-default-sparse-segtype was given.
|
||||
if test "${with_default_sparse_segtype+set}" = set; then :
|
||||
@@ -9340,11 +9256,6 @@ $as_echo "$as_me: WARNING: $CACHE_CHECK_CMD: Old version \"$CACHE_CHECK_VSN\" fo
|
||||
CACHE_CHECK_VERSION_WARN=y
|
||||
CACHE_CHECK_NEEDS_CHECK=no
|
||||
fi
|
||||
if test "$CACHE_CHECK_VSN_MINOR" -lt 7 ; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $CACHE_CHECK_CMD: Old version \"$CACHE_CHECK_VSN\" does not support new cache format V2" >&5
|
||||
$as_echo "$as_me: WARNING: $CACHE_CHECK_CMD: Old version \"$CACHE_CHECK_VSN\" does not support new cache format V2" >&2;}
|
||||
CACHE_CHECK_VERSION_WARN=y
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# Empty means a config way to ignore cache dumping
|
||||
@@ -9707,6 +9618,8 @@ _ACEOF
|
||||
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable readline" >&5
|
||||
$as_echo_n "checking whether to enable readline... " >&6; }
|
||||
# Check whether --enable-readline was given.
|
||||
if test "${enable_readline+set}" = set; then :
|
||||
enableval=$enable_readline; READLINE=$enableval
|
||||
@@ -9714,6 +9627,8 @@ else
|
||||
READLINE=maybe
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $READLINE" >&5
|
||||
$as_echo "$READLINE" >&6; }
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable realtime support" >&5
|
||||
@@ -11831,67 +11746,6 @@ $as_echo "#define DEVMAPPER_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use aio" >&5
|
||||
$as_echo_n "checking whether to use aio... " >&6; }
|
||||
# Check whether --enable-aio was given.
|
||||
if test "${enable_aio+set}" = set; then :
|
||||
enableval=$enable_aio; AIO=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AIO" >&5
|
||||
$as_echo "$AIO" >&6; }
|
||||
|
||||
if test "$AIO" = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for io_setup in -laio" >&5
|
||||
$as_echo_n "checking for io_setup in -laio... " >&6; }
|
||||
if ${ac_cv_lib_aio_io_setup+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-laio $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char io_setup ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return io_setup ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_aio_io_setup=yes
|
||||
else
|
||||
ac_cv_lib_aio_io_setup=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_aio_io_setup" >&5
|
||||
$as_echo "$ac_cv_lib_aio_io_setup" >&6; }
|
||||
if test "x$ac_cv_lib_aio_io_setup" = xyes; then :
|
||||
|
||||
$as_echo "#define AIO_SUPPORT 1" >>confdefs.h
|
||||
|
||||
AIO_LIBS="-laio"
|
||||
AIO_SUPPORT=yes
|
||||
else
|
||||
AIO_LIBS=
|
||||
AIO_SUPPORT=no
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build LVMetaD" >&5
|
||||
$as_echo_n "checking whether to build LVMetaD... " >&6; }
|
||||
@@ -12289,7 +12143,7 @@ if test "$NOTIFYDBUS_SUPPORT" = yes; then
|
||||
|
||||
$as_echo "#define NOTIFYDBUS_SUPPORT 1" >>confdefs.h
|
||||
|
||||
SYSTEMD_LIBS="-lsystemd"
|
||||
LIBS="-lsystemd $LIBS"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -12369,6 +12223,8 @@ fi
|
||||
|
||||
################################################################################
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable libblkid detection of signatures when wiping" >&5
|
||||
$as_echo_n "checking whether to enable libblkid detection of signatures when wiping... " >&6; }
|
||||
# Check whether --enable-blkid_wiping was given.
|
||||
if test "${enable_blkid_wiping+set}" = set; then :
|
||||
enableval=$enable_blkid_wiping; BLKID_WIPING=$enableval
|
||||
@@ -12376,8 +12232,9 @@ else
|
||||
BLKID_WIPING=maybe
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BLKID_WIPING" >&5
|
||||
$as_echo "$BLKID_WIPING" >&6; }
|
||||
|
||||
DEFAULT_USE_BLKID_WIPING=0
|
||||
if test "$BLKID_WIPING" != no; then
|
||||
pkg_config_init
|
||||
|
||||
@@ -12457,19 +12314,20 @@ else
|
||||
BLKID_LIBS=$pkg_cv_BLKID_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
BLKID_WIPING=yes
|
||||
BLKID_PC="blkid"
|
||||
DEFAULT_USE_BLKID_WIPING=1
|
||||
test "$BLKID_WIPING" = maybe && BLKID_WIPING=yes
|
||||
fi
|
||||
if test "$BLKID_WIPING" = yes; then
|
||||
BLKID_PC="blkid"
|
||||
DEFAULT_USE_BLKID_WIPING=1
|
||||
|
||||
$as_echo "#define BLKID_WIPING_SUPPORT 1" >>confdefs.h
|
||||
|
||||
|
||||
else
|
||||
DEFAULT_USE_BLKID_WIPING=0
|
||||
fi
|
||||
else
|
||||
DEFAULT_USE_BLKID_WIPING=0
|
||||
fi
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable libblkid detection of signatures when wiping" >&5
|
||||
$as_echo_n "checking whether to enable libblkid detection of signatures when wiping... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BLKID_WIPING" >&5
|
||||
$as_echo "$BLKID_WIPING" >&6; }
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define DEFAULT_USE_BLKID_WIPING $DEFAULT_USE_BLKID_WIPING
|
||||
@@ -12477,6 +12335,8 @@ _ACEOF
|
||||
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use udev-systemd protocol for jobs in background" >&5
|
||||
$as_echo_n "checking whether to use udev-systemd protocol for jobs in background... " >&6; }
|
||||
# Check whether --enable-udev-systemd-background-jobs was given.
|
||||
if test "${enable_udev_systemd_background_jobs+set}" = set; then :
|
||||
enableval=$enable_udev_systemd_background_jobs; UDEV_SYSTEMD_BACKGROUND_JOBS=$enableval
|
||||
@@ -12484,6 +12344,8 @@ else
|
||||
UDEV_SYSTEMD_BACKGROUND_JOBS=maybe
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $UDEV_SYSTEMD_BACKGROUND_JOBS" >&5
|
||||
$as_echo "$UDEV_SYSTEMD_BACKGROUND_JOBS" >&6; }
|
||||
|
||||
if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" != no; then
|
||||
pkg_config_init
|
||||
@@ -12564,15 +12426,10 @@ else
|
||||
SYSTEMD_LIBS=$pkg_cv_SYSTEMD_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
UDEV_SYSTEMD_BACKGROUND_JOBS=yes
|
||||
test "$UDEV_SYSTEMD_BACKGROUND_JOBS" = maybe && UDEV_SYSTEMD_BACKGROUND_JOBS=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use udev-systemd protocol for jobs in background" >&5
|
||||
$as_echo_n "checking whether to use udev-systemd protocol for jobs in background... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $UDEV_SYSTEMD_BACKGROUND_JOBS" >&5
|
||||
$as_echo "$UDEV_SYSTEMD_BACKGROUND_JOBS" >&6; }
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable synchronisation with udev processing" >&5
|
||||
$as_echo_n "checking whether to enable synchronisation with udev processing... " >&6; }
|
||||
@@ -12843,10 +12700,6 @@ $as_echo "$APPLIB" >&6; }
|
||||
test "$APPLIB" = yes \
|
||||
&& LVM2APP_LIB=-llvm2app \
|
||||
|| LVM2APP_LIB=
|
||||
if test "$APPLIB"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Python bindings are deprecated. Use D-Bus API" >&5
|
||||
$as_echo "$as_me: WARNING: Python bindings are deprecated. Use D-Bus API" >&2;}
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compile liblvm2cmd.so" >&5
|
||||
@@ -12877,10 +12730,6 @@ fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LVMDBUSD" >&5
|
||||
$as_echo "$BUILD_LVMDBUSD" >&6; }
|
||||
if test "$NOTIFYDBUS_SUPPORT" = yes && test "BUILD_LVMDBUSD" = yes; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building D-Bus support without D-Bus notifications." >&5
|
||||
$as_echo "$as_me: WARNING: Building D-Bus support without D-Bus notifications." >&2;}
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build Python wrapper for liblvm2app.so" >&5
|
||||
@@ -12966,7 +12815,7 @@ if ${am_cv_pathless_PYTHON+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
|
||||
for am_cv_pathless_PYTHON in python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do
|
||||
for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do
|
||||
test "$am_cv_pathless_PYTHON" = none && break
|
||||
prog="import sys
|
||||
# split strings by '.' and convert to numeric. Append some zeros
|
||||
@@ -13534,7 +13383,7 @@ if ${am_cv_pathless_PYTHON+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
|
||||
for am_cv_pathless_PYTHON in python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do
|
||||
for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do
|
||||
test "$am_cv_pathless_PYTHON" = none && break
|
||||
prog="import sys
|
||||
# split strings by '.' and convert to numeric. Append some zeros
|
||||
@@ -13928,8 +13777,6 @@ $as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
if test "$PYTHON_BINDINGS" = yes -o "$PYTHON2_BINDINGS" = yes -o "$PYTHON3_BINDINGS" = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Python bindings are deprecated. Use D-Bus API" >&5
|
||||
$as_echo "$as_me: WARNING: Python bindings are deprecated. Use D-Bus API" >&2;}
|
||||
test "$APPLIB" != yes && as_fn_error $? "Python_bindings require --enable-applib" "$LINENO" 5
|
||||
fi
|
||||
|
||||
@@ -13978,15 +13825,15 @@ $as_echo "$BLKDEACTIVATE" >&6; }
|
||||
$as_echo_n "checking whether to use dmeventd... " >&6; }
|
||||
# Check whether --enable-dmeventd was given.
|
||||
if test "${enable_dmeventd+set}" = set; then :
|
||||
enableval=$enable_dmeventd; BUILD_DMEVENTD=$enableval
|
||||
else
|
||||
BUILD_DMEVENTD=no
|
||||
enableval=$enable_dmeventd; DMEVENTD=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_DMEVENTD" >&5
|
||||
$as_echo "$BUILD_DMEVENTD" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DMEVENTD" >&5
|
||||
$as_echo "$DMEVENTD" >&6; }
|
||||
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
BUILD_DMEVENTD=$DMEVENTD
|
||||
|
||||
if test "$DMEVENTD" = yes; then
|
||||
if test "$MIRRORS" != internal; then
|
||||
as_fn_error $? "--enable-dmeventd currently requires --with-mirrors=internal" "$LINENO" 5
|
||||
fi
|
||||
@@ -14089,6 +13936,9 @@ $as_echo "#define HAVE_CANONICALIZE_FILE_NAME 1" >>confdefs.h
|
||||
fi
|
||||
|
||||
|
||||
################################################################################
|
||||
test "$exec_prefix" = NONE -a "$prefix" = NONE && exec_prefix=""
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
|
||||
$as_echo_n "checking for dlopen in -ldl... " >&6; }
|
||||
@@ -14374,24 +14224,8 @@ fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
RT_LIBS=
|
||||
HAVE_REALTIME=no
|
||||
if test "$REALTIME" = yes; then
|
||||
for ac_func in clock_gettime
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
|
||||
if test "x$ac_cv_func_clock_gettime" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_CLOCK_GETTIME 1
|
||||
_ACEOF
|
||||
HAVE_REALTIME=yes
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
if test "$HAVE_REALTIME" != yes; then :
|
||||
# try again with -lrt
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
|
||||
$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
|
||||
if ${ac_cv_lib_rt_clock_gettime+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
@@ -14428,15 +14262,18 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
|
||||
$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
|
||||
if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
|
||||
RT_LIBS="-lrt"; HAVE_REALTIME=yes
|
||||
HAVE_REALTIME=yes
|
||||
else
|
||||
HAVE_REALTIME=no
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if test "$HAVE_REALTIME" = yes; then
|
||||
|
||||
$as_echo "#define HAVE_REALTIME 1" >>confdefs.h
|
||||
|
||||
LIBS="-lrt $LIBS"
|
||||
RT_LIB="-lrt"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Disabling realtime clock" >&5
|
||||
$as_echo "$as_me: WARNING: Disabling realtime clock" >&2;}
|
||||
@@ -14605,8 +14442,7 @@ if test "x$ac_cv_lib_readline_readline" = xyes; then :
|
||||
|
||||
$as_echo "#define READLINE_SUPPORT 1" >>confdefs.h
|
||||
|
||||
READLINE=yes
|
||||
LIBS=$lvm_saved_libs
|
||||
LIBS=$lvm_saved_libs
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_line_buffer in -lreadline" >&5
|
||||
$as_echo_n "checking for rl_line_buffer in -lreadline... " >&6; }
|
||||
if ${ac_cv_lib_readline_rl_line_buffer+:} false; then :
|
||||
@@ -14926,10 +14762,6 @@ fi
|
||||
done
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable readline" >&5
|
||||
$as_echo_n "checking whether to enable readline... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $READLINE" >&5
|
||||
$as_echo "$READLINE" >&6; }
|
||||
|
||||
if test "$BUILD_CMIRRORD" = yes; then
|
||||
for ac_func in atexit
|
||||
@@ -14948,15 +14780,13 @@ done
|
||||
fi
|
||||
|
||||
if test "$BUILD_LVMLOCKD" = yes; then
|
||||
if test "$HAVE_REALTIME" != yes; then :
|
||||
as_fn_error $? "Realtime clock support is mandatory for lvmlockd." "$LINENO" 5
|
||||
fi
|
||||
for ac_func in strtoull
|
||||
for ac_func in clock_gettime strtoull
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "strtoull" "ac_cv_func_strtoull"
|
||||
if test "x$ac_cv_func_strtoull" = xyes; then :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_STRTOULL 1
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
@@ -15276,7 +15106,7 @@ done
|
||||
|
||||
fi
|
||||
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
if test "$DMEVENTD" = yes; then
|
||||
for ac_header in arpa/inet.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "$ac_includes_default"
|
||||
@@ -15470,25 +15300,28 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
SYSCONFDIR="$(eval echo $(eval echo $sysconfdir))"
|
||||
|
||||
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
||||
LVM_PATH="$SBINDIR/lvm"
|
||||
lvm_exec_prefix=$exec_prefix
|
||||
test "$lvm_exec_prefix" = NONE && lvm_exec_prefix=$prefix
|
||||
test "$lvm_exec_prefix" = NONE && lvm_exec_prefix=$ac_default_prefix
|
||||
LVM_PATH="$lvm_exec_prefix/sbin/lvm"
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define LVM_PATH "$LVM_PATH"
|
||||
_ACEOF
|
||||
|
||||
|
||||
USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
|
||||
CLVMD_PATH="$USRSBINDIR/clvmd"
|
||||
clvmd_prefix=$ac_default_prefix
|
||||
test "$prefix" != NONE && clvmd_prefix=$prefix
|
||||
CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define CLVMD_PATH "$CLVMD_PATH"
|
||||
_ACEOF
|
||||
|
||||
|
||||
FSADM_PATH="$SBINDIR/fsadm"
|
||||
|
||||
FSADM_PATH="$lvm_exec_prefix/sbin/fsadm"
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define FSADM_PATH "$FSADM_PATH"
|
||||
@@ -15518,7 +15351,7 @@ if test "$BUILD_DMEVENTD" = yes; then
|
||||
if test "${with_dmeventd_path+set}" = set; then :
|
||||
withval=$with_dmeventd_path; DMEVENTD_PATH=$withval
|
||||
else
|
||||
DMEVENTD_PATH="$SBINDIR/dmeventd"
|
||||
DMEVENTD_PATH="$lvm_exec_prefix/sbin/dmeventd"
|
||||
fi
|
||||
|
||||
|
||||
@@ -15599,11 +15432,6 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
# Select default system locking dir, prefer /run/lock over /var/lock
|
||||
DEFAULT_SYS_LOCK_DIR="$RUN_DIR/lock"
|
||||
test -d "$DEFAULT_SYS_LOCK_DIR" || DEFAULT_SYS_LOCK_DIR="/var/lock"
|
||||
|
||||
# Support configurable locking subdir for lvm
|
||||
|
||||
# Check whether --with-default-locking-dir was given.
|
||||
if test "${with_default_locking_dir+set}" = set; then :
|
||||
@@ -15611,7 +15439,8 @@ if test "${with_default_locking_dir+set}" = set; then :
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for default lock directory" >&5
|
||||
$as_echo_n "checking for default lock directory... " >&6; }
|
||||
DEFAULT_LOCK_DIR="$DEFAULT_SYS_LOCK_DIR/lvm"
|
||||
DEFAULT_LOCK_DIR="$RUN_DIR/lock/lvm"
|
||||
test -d "$RUN_DIR/lock" || DEFAULT_LOCK_DIR="/var/lock/lvm"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEFAULT_LOCK_DIR" >&5
|
||||
$as_echo "$DEFAULT_LOCK_DIR" >&6; }
|
||||
fi
|
||||
@@ -15833,12 +15662,6 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15847,7 +15670,7 @@ _ACEOF
|
||||
|
||||
|
||||
################################################################################
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
@@ -16573,6 +16396,7 @@ do
|
||||
"lib/format_pool/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format_pool/Makefile" ;;
|
||||
"lib/locking/Makefile") CONFIG_FILES="$CONFIG_FILES lib/locking/Makefile" ;;
|
||||
"lib/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;;
|
||||
"lib/replicator/Makefile") CONFIG_FILES="$CONFIG_FILES lib/replicator/Makefile" ;;
|
||||
"include/lvm-version.h") CONFIG_FILES="$CONFIG_FILES include/lvm-version.h" ;;
|
||||
"lib/raid/Makefile") CONFIG_FILES="$CONFIG_FILES lib/raid/Makefile" ;;
|
||||
"lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
|
||||
@@ -17223,8 +17047,8 @@ $as_echo "$as_me: WARNING: Support for thin provisioning is limited since some t
|
||||
fi
|
||||
|
||||
if test -n "$THIN_CHECK_VERSION_WARN"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You should also install latest thin_check vsn 0.7.0 (or later) for lvm2 thin provisioning" >&5
|
||||
$as_echo "$as_me: WARNING: You should also install latest thin_check vsn 0.7.0 (or later) for lvm2 thin provisioning" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You should also install thin_check vsn 0.3.2 (or later) to use lvm2 thin provisioning" >&5
|
||||
$as_echo "$as_me: WARNING: You should also install thin_check vsn 0.3.2 (or later) to use lvm2 thin provisioning" >&2;}
|
||||
fi
|
||||
|
||||
if test -n "$CACHE_CONFIGURE_WARN"; then :
|
||||
@@ -17232,12 +17056,6 @@ if test -n "$CACHE_CONFIGURE_WARN"; then :
|
||||
$as_echo "$as_me: WARNING: Support for cache is limited since some cache tools are missing!" >&2;}
|
||||
fi
|
||||
|
||||
if test -n "$CACHE_CHECK_VERSION_WARN"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You should install latest cache_check vsn 0.7.0 to use lvm2 cache metadata format 2" >&5
|
||||
$as_echo "$as_me: WARNING: You should install latest cache_check vsn 0.7.0 to use lvm2 cache metadata format 2" >&2;}
|
||||
fi
|
||||
|
||||
|
||||
if test "$ODIRECT" != yes; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: O_DIRECT disabled: low-memory pvmove may lock up" >&5
|
||||
$as_echo "$as_me: WARNING: O_DIRECT disabled: low-memory pvmove may lock up" >&2;}
|
||||
|
162
configure.in
162
configure.in
@@ -31,7 +31,6 @@ AS_IF([test -z "$CFLAGS"], [COPTIMISE_FLAG="-O2"])
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
|
||||
# equivalent to -rdynamic
|
||||
ELDFLAGS="-Wl,--export-dynamic"
|
||||
# FIXME Generate list and use --dynamic-list=.dlopen.sym
|
||||
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
||||
@@ -39,7 +38,6 @@ case "$host_os" in
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
AIO=yes
|
||||
BUILD_LVMETAD=no
|
||||
BUILD_LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
@@ -59,7 +57,6 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LIB_SUFFIX=dylib
|
||||
DEVMAPPER=yes
|
||||
AIO=no
|
||||
ODIRECT=no
|
||||
DM_IOCTLS=no
|
||||
SELINUX=no
|
||||
@@ -87,7 +84,6 @@ AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_MKDIR_P
|
||||
AC_PROG_RANLIB
|
||||
AC_CHECK_TOOL(AR, ar)
|
||||
AC_PATH_TOOL(CFLOW_CMD, cflow)
|
||||
AC_PATH_TOOL(CSCOPE_CMD, cscope)
|
||||
AC_PATH_TOOL(CHMOD, chmod)
|
||||
@@ -193,15 +189,9 @@ AC_SUBST(HAVE_FULL_RELRO)
|
||||
################################################################################
|
||||
dnl -- Prefix is /usr by default, the exec_prefix default is setup later
|
||||
AC_PREFIX_DEFAULT(/usr)
|
||||
|
||||
################################################################################
|
||||
dnl -- Clear default exec_prefix - install into /sbin rather than /usr/sbin
|
||||
test "$exec_prefix" = NONE -a "$prefix" = NONE && exec_prefix=""
|
||||
|
||||
test "x$prefix" = xNONE && prefix=$ac_default_prefix
|
||||
# Let make expand exec_prefix.
|
||||
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
|
||||
|
||||
if test "$prefix" = NONE; then
|
||||
datarootdir=${ac_default_prefix}/share
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup the ownership of the files
|
||||
@@ -416,6 +406,22 @@ AC_DEFINE_UNQUOTED([DEFAULT_RAID10_SEGTYPE], ["$DEFAULT_RAID10_SEGTYPE"],
|
||||
[Default segtype used for raid10 volumes.])
|
||||
|
||||
################################################################################
|
||||
dnl -- asynchronous volume replicator inclusion type
|
||||
AC_MSG_CHECKING(whether to include replicators)
|
||||
AC_ARG_WITH(replicators,
|
||||
AC_HELP_STRING([--with-replicators=TYPE],
|
||||
[replicator support: internal/shared/none [none]]),
|
||||
REPLICATORS=$withval, REPLICATORS=none)
|
||||
AC_MSG_RESULT($REPLICATORS)
|
||||
|
||||
case "$REPLICATORS" in
|
||||
none|shared) ;;
|
||||
internal) AC_DEFINE([REPLICATOR_INTERNAL], 1,
|
||||
[Define to 1 to include built-in support for replicators.]) ;;
|
||||
*) AC_MSG_ERROR([--with-replicators parameter invalid ($REPLICATORS)]) ;;
|
||||
esac
|
||||
|
||||
|
||||
AC_ARG_WITH(default-sparse-segtype,
|
||||
AC_HELP_STRING([--with-default-sparse-segtype=TYPE],
|
||||
[default sparse segtype: thin/snapshot [thin]]),
|
||||
@@ -611,10 +617,6 @@ case "$CACHE" in
|
||||
CACHE_CHECK_VERSION_WARN=y
|
||||
CACHE_CHECK_NEEDS_CHECK=no
|
||||
fi
|
||||
if test "$CACHE_CHECK_VSN_MINOR" -lt 7 ; then
|
||||
AC_MSG_WARN([$CACHE_CHECK_CMD: Old version "$CACHE_CHECK_VSN" does not support new cache format V2])
|
||||
CACHE_CHECK_VERSION_WARN=y
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# Empty means a config way to ignore cache dumping
|
||||
@@ -668,9 +670,11 @@ AC_DEFINE_UNQUOTED([CACHE_RESTORE_CMD], ["$CACHE_RESTORE_CMD"],
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable readline
|
||||
AC_MSG_CHECKING(whether to enable readline)
|
||||
AC_ARG_ENABLE([readline],
|
||||
AC_HELP_STRING([--disable-readline], [disable readline support]),
|
||||
READLINE=$enableval, READLINE=maybe)
|
||||
AC_MSG_RESULT($READLINE)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable realtime clock support
|
||||
@@ -1123,24 +1127,6 @@ if test "$DEVMAPPER" = yes; then
|
||||
AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable LVM2 device-mapper interaction.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable aio
|
||||
AC_MSG_CHECKING(whether to use aio)
|
||||
AC_ARG_ENABLE(aio,
|
||||
AC_HELP_STRING([--disable-aio],
|
||||
[disable async i/o]),
|
||||
AIO=$enableval)
|
||||
AC_MSG_RESULT($AIO)
|
||||
|
||||
if test "$AIO" = yes; then
|
||||
AC_CHECK_LIB(aio, io_setup,
|
||||
[AC_DEFINE([AIO_SUPPORT], 1, [Define to 1 if aio is available.])
|
||||
AIO_LIBS="-laio"
|
||||
AIO_SUPPORT=yes],
|
||||
[AIO_LIBS=
|
||||
AIO_SUPPORT=no ])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Build lvmetad
|
||||
AC_MSG_CHECKING(whether to build LVMetaD)
|
||||
@@ -1312,7 +1298,7 @@ AC_MSG_RESULT($NOTIFYDBUS_SUPPORT)
|
||||
|
||||
if test "$NOTIFYDBUS_SUPPORT" = yes; then
|
||||
AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])
|
||||
SYSTEMD_LIBS="-lsystemd"
|
||||
LIBS="-lsystemd $LIBS"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -1324,43 +1310,50 @@ fi
|
||||
################################################################################
|
||||
|
||||
dnl -- Enable blkid wiping functionality
|
||||
AC_MSG_CHECKING(whether to enable libblkid detection of signatures when wiping)
|
||||
AC_ARG_ENABLE(blkid_wiping,
|
||||
AC_HELP_STRING([--disable-blkid_wiping],
|
||||
[disable libblkid detection of signatures when wiping and use native code instead]),
|
||||
BLKID_WIPING=$enableval, BLKID_WIPING=maybe)
|
||||
AC_MSG_RESULT($BLKID_WIPING)
|
||||
|
||||
DEFAULT_USE_BLKID_WIPING=0
|
||||
if test "$BLKID_WIPING" != no; then
|
||||
pkg_config_init
|
||||
PKG_CHECK_MODULES(BLKID, blkid >= 2.24,
|
||||
[ BLKID_WIPING=yes
|
||||
BLKID_PC="blkid"
|
||||
DEFAULT_USE_BLKID_WIPING=1
|
||||
AC_DEFINE([BLKID_WIPING_SUPPORT], 1, [Define to 1 to use libblkid detection of signatures when wiping.])
|
||||
], [if test "$BLKID_WIPING" = maybe; then
|
||||
[test "$BLKID_WIPING" = maybe && BLKID_WIPING=yes],
|
||||
[if test "$BLKID_WIPING" = maybe; then
|
||||
BLKID_WIPING=no
|
||||
else
|
||||
AC_MSG_ERROR([bailing out... blkid library >= 2.24 is required])
|
||||
fi])
|
||||
if test "$BLKID_WIPING" = yes; then
|
||||
BLKID_PC="blkid"
|
||||
DEFAULT_USE_BLKID_WIPING=1
|
||||
AC_DEFINE([BLKID_WIPING_SUPPORT], 1, [Define to 1 to use libblkid detection of signatures when wiping.])
|
||||
else
|
||||
DEFAULT_USE_BLKID_WIPING=0
|
||||
fi
|
||||
else
|
||||
DEFAULT_USE_BLKID_WIPING=0
|
||||
fi
|
||||
AC_MSG_CHECKING([whether to enable libblkid detection of signatures when wiping])
|
||||
AC_MSG_RESULT($BLKID_WIPING)
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_USE_BLKID_WIPING, [$DEFAULT_USE_BLKID_WIPING],
|
||||
[Use blkid wiping by default.])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable udev-systemd protocol to instantiate a service for background jobs
|
||||
dnl -- Requires systemd version 205 at least (including support for systemd-run)
|
||||
AC_MSG_CHECKING(whether to use udev-systemd protocol for jobs in background)
|
||||
AC_ARG_ENABLE(udev-systemd-background-jobs,
|
||||
AC_HELP_STRING([--disable-udev-systemd-background-jobs],
|
||||
[disable udev-systemd protocol to instantiate a service for background job]),
|
||||
UDEV_SYSTEMD_BACKGROUND_JOBS=$enableval,
|
||||
UDEV_SYSTEMD_BACKGROUND_JOBS=maybe)
|
||||
AC_MSG_RESULT($UDEV_SYSTEMD_BACKGROUND_JOBS)
|
||||
|
||||
if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" != no; then
|
||||
pkg_config_init
|
||||
PKG_CHECK_MODULES(SYSTEMD, systemd >= 205,
|
||||
[UDEV_SYSTEMD_BACKGROUND_JOBS=yes],
|
||||
[test "$UDEV_SYSTEMD_BACKGROUND_JOBS" = maybe && UDEV_SYSTEMD_BACKGROUND_JOBS=yes],
|
||||
[if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" = maybe; then
|
||||
UDEV_SYSTEMD_BACKGROUND_JOBS=no
|
||||
else
|
||||
@@ -1368,9 +1361,6 @@ if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" != no; then
|
||||
fi])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(whether to use udev-systemd protocol for jobs in background)
|
||||
AC_MSG_RESULT($UDEV_SYSTEMD_BACKGROUND_JOBS)
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable udev synchronisation
|
||||
AC_MSG_CHECKING(whether to enable synchronisation with udev processing)
|
||||
@@ -1474,8 +1464,6 @@ AC_SUBST([LVM2APP_LIB])
|
||||
test "$APPLIB" = yes \
|
||||
&& LVM2APP_LIB=-llvm2app \
|
||||
|| LVM2APP_LIB=
|
||||
AS_IF([test "$APPLIB"],
|
||||
[AC_MSG_WARN([Python bindings are deprecated. Use D-Bus API])])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable cmdlib
|
||||
@@ -1496,8 +1484,6 @@ AC_ARG_ENABLE(dbus-service,
|
||||
AC_HELP_STRING([--enable-dbus-service], [install D-Bus support]),
|
||||
BUILD_LVMDBUSD=$enableval, BUILD_LVMDBUSD=no)
|
||||
AC_MSG_RESULT($BUILD_LVMDBUSD)
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = yes && test "BUILD_LVMDBUSD" = yes],
|
||||
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications.])])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable Python liblvm2app bindings
|
||||
@@ -1560,7 +1546,6 @@ if test "$BUILD_LVMDBUSD" = yes; then
|
||||
fi
|
||||
|
||||
if test "$PYTHON_BINDINGS" = yes -o "$PYTHON2_BINDINGS" = yes -o "$PYTHON3_BINDINGS" = yes; then
|
||||
AC_MSG_WARN([Python bindings are deprecated. Use D-Bus API])
|
||||
test "$APPLIB" != yes && AC_MSG_ERROR([Python_bindings require --enable-applib])
|
||||
fi
|
||||
|
||||
@@ -1596,11 +1581,13 @@ dnl -- enable dmeventd handling
|
||||
AC_MSG_CHECKING(whether to use dmeventd)
|
||||
AC_ARG_ENABLE(dmeventd, AC_HELP_STRING([--enable-dmeventd],
|
||||
[enable the device-mapper event daemon]),
|
||||
BUILD_DMEVENTD=$enableval, BUILD_DMEVENTD=no)
|
||||
AC_MSG_RESULT($BUILD_DMEVENTD)
|
||||
DMEVENTD=$enableval)
|
||||
AC_MSG_RESULT($DMEVENTD)
|
||||
|
||||
BUILD_DMEVENTD=$DMEVENTD
|
||||
|
||||
dnl -- dmeventd currently requires internal mirror support
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
if test "$DMEVENTD" = yes; then
|
||||
if test "$MIRRORS" != internal; then
|
||||
AC_MSG_ERROR([--enable-dmeventd currently requires --with-mirrors=internal])
|
||||
fi
|
||||
@@ -1624,6 +1611,10 @@ AC_CHECK_LIB(c, canonicalize_file_name,
|
||||
AC_DEFINE([HAVE_CANONICALIZE_FILE_NAME], 1,
|
||||
[Define to 1 if canonicalize_file_name is available.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Clear default exec_prefix - install into /sbin rather than /usr/sbin
|
||||
test "$exec_prefix" = NONE -a "$prefix" = NONE && exec_prefix=""
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for dlopen
|
||||
AC_CHECK_LIB(dl, dlopen,
|
||||
@@ -1680,16 +1671,13 @@ fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for realtime clock support
|
||||
RT_LIBS=
|
||||
HAVE_REALTIME=no
|
||||
if test "$REALTIME" = yes; then
|
||||
AC_CHECK_FUNCS([clock_gettime], HAVE_REALTIME=yes)
|
||||
|
||||
AS_IF([test "$HAVE_REALTIME" != yes], [ # try again with -lrt
|
||||
AC_CHECK_LIB([rt], [clock_gettime], RT_LIBS="-lrt"; HAVE_REALTIME=yes)])
|
||||
AC_CHECK_LIB(rt, clock_gettime, HAVE_REALTIME=yes, HAVE_REALTIME=no)
|
||||
|
||||
if test "$HAVE_REALTIME" = yes; then
|
||||
AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
|
||||
LIBS="-lrt $LIBS"
|
||||
RT_LIB="-lrt"
|
||||
else
|
||||
AC_MSG_WARN(Disabling realtime clock)
|
||||
fi
|
||||
@@ -1733,7 +1721,6 @@ Note: (n)curses also seems to work as a substitute for termcap. This was
|
||||
AC_DEFINE([READLINE_SUPPORT], 1,
|
||||
[Define to 1 to include the LVM readline shell.])
|
||||
dnl -- Try only with -lreadline and check for different symbol
|
||||
READLINE=yes
|
||||
LIBS=$lvm_saved_libs
|
||||
AC_CHECK_LIB([readline], [rl_line_buffer],
|
||||
[ READLINE_LIBS="-lreadline" ], [
|
||||
@@ -1840,16 +1827,13 @@ dnl -- Ensure additional headers required
|
||||
if test "$READLINE" = yes; then
|
||||
AC_CHECK_HEADERS(readline/readline.h readline/history.h,,hard_bailout)
|
||||
fi
|
||||
AC_MSG_CHECKING(whether to enable readline)
|
||||
AC_MSG_RESULT($READLINE)
|
||||
|
||||
if test "$BUILD_CMIRRORD" = yes; then
|
||||
AC_CHECK_FUNCS(atexit,,hard_bailout)
|
||||
fi
|
||||
|
||||
if test "$BUILD_LVMLOCKD" = yes; then
|
||||
AS_IF([test "$HAVE_REALTIME" != yes], [AC_MSG_ERROR([Realtime clock support is mandatory for lvmlockd.])])
|
||||
AC_CHECK_FUNCS(strtoull,,hard_bailout)
|
||||
AC_CHECK_FUNCS(clock_gettime strtoull,,hard_bailout)
|
||||
fi
|
||||
|
||||
if test "$BUILD_LVMPOLLD" = yes; then
|
||||
@@ -1869,7 +1853,7 @@ if test "$CLUSTER" != none; then
|
||||
AC_CHECK_FUNCS(socket,,hard_bailout)
|
||||
fi
|
||||
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
if test "$DMEVENTD" = yes; then
|
||||
AC_CHECK_HEADERS(arpa/inet.h,,hard_bailout)
|
||||
fi
|
||||
|
||||
@@ -1896,17 +1880,20 @@ if test -n "$MODPROBE_CMD"; then
|
||||
AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
|
||||
fi
|
||||
|
||||
SYSCONFDIR="$(eval echo $(eval echo $sysconfdir))"
|
||||
|
||||
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
||||
LVM_PATH="$SBINDIR/lvm"
|
||||
lvm_exec_prefix=$exec_prefix
|
||||
test "$lvm_exec_prefix" = NONE && lvm_exec_prefix=$prefix
|
||||
test "$lvm_exec_prefix" = NONE && lvm_exec_prefix=$ac_default_prefix
|
||||
LVM_PATH="$lvm_exec_prefix/sbin/lvm"
|
||||
AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
|
||||
|
||||
USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
|
||||
CLVMD_PATH="$USRSBINDIR/clvmd"
|
||||
clvmd_prefix=$ac_default_prefix
|
||||
test "$prefix" != NONE && clvmd_prefix=$prefix
|
||||
CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
|
||||
AC_DEFINE_UNQUOTED(CLVMD_PATH, ["$CLVMD_PATH"], [Path to clvmd binary.])
|
||||
|
||||
FSADM_PATH="$SBINDIR/fsadm"
|
||||
|
||||
FSADM_PATH="$lvm_exec_prefix/sbin/fsadm"
|
||||
AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
|
||||
|
||||
################################################################################
|
||||
@@ -1926,7 +1913,7 @@ if test "$BUILD_DMEVENTD" = yes; then
|
||||
AC_HELP_STRING([--with-dmeventd-path=PATH],
|
||||
[dmeventd path [EPREFIX/sbin/dmeventd]]),
|
||||
DMEVENTD_PATH=$withval,
|
||||
DMEVENTD_PATH="$SBINDIR/dmeventd")
|
||||
DMEVENTD_PATH="$lvm_exec_prefix/sbin/dmeventd")
|
||||
AC_DEFINE_UNQUOTED(DMEVENTD_PATH, ["$DMEVENTD_PATH"],
|
||||
[Path to dmeventd binary.])
|
||||
fi
|
||||
@@ -1969,17 +1956,13 @@ AC_ARG_WITH(default-cache-subdir,
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_CACHE_SUBDIR, ["$DEFAULT_CACHE_SUBDIR"],
|
||||
[Name of default metadata cache subdirectory.])
|
||||
|
||||
# Select default system locking dir, prefer /run/lock over /var/lock
|
||||
DEFAULT_SYS_LOCK_DIR="$RUN_DIR/lock"
|
||||
test -d "$DEFAULT_SYS_LOCK_DIR" || DEFAULT_SYS_LOCK_DIR="/var/lock"
|
||||
|
||||
# Support configurable locking subdir for lvm
|
||||
AC_ARG_WITH(default-locking-dir,
|
||||
AC_HELP_STRING([--with-default-locking-dir=DIR],
|
||||
[default locking directory [autodetect_lock_dir/lvm]]),
|
||||
DEFAULT_LOCK_DIR=$withval,
|
||||
[AC_MSG_CHECKING(for default lock directory)
|
||||
DEFAULT_LOCK_DIR="$DEFAULT_SYS_LOCK_DIR/lvm"
|
||||
DEFAULT_LOCK_DIR="$RUN_DIR/lock/lvm"
|
||||
test -d "$RUN_DIR/lock" || DEFAULT_LOCK_DIR="/var/lock/lvm"
|
||||
AC_MSG_RESULT($DEFAULT_LOCK_DIR)])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_LOCK_DIR, ["$DEFAULT_LOCK_DIR"],
|
||||
[Name of default locking directory.])
|
||||
@@ -2074,17 +2057,15 @@ AC_SUBST(DEFAULT_RAID10_SEGTYPE)
|
||||
AC_SUBST(DEFAULT_RUN_DIR)
|
||||
AC_SUBST(DEFAULT_SPARSE_SEGTYPE)
|
||||
AC_SUBST(DEFAULT_SYS_DIR)
|
||||
AC_SUBST(DEFAULT_SYS_LOCK_DIR)
|
||||
AC_SUBST(DEFAULT_USE_BLKID_WIPING)
|
||||
AC_SUBST(DEFAULT_USE_LVMETAD)
|
||||
AC_SUBST(DEFAULT_USE_LVMPOLLD)
|
||||
AC_SUBST(DEFAULT_USE_LVMLOCKD)
|
||||
AC_SUBST(DEVMAPPER)
|
||||
AC_SUBST(AIO)
|
||||
AC_SUBST(DLM_CFLAGS)
|
||||
AC_SUBST(DLM_LIBS)
|
||||
AC_SUBST(DL_LIBS)
|
||||
AC_SUBST(AIO_LIBS)
|
||||
AC_SUBST(DMEVENTD)
|
||||
AC_SUBST(DMEVENTD_PATH)
|
||||
AC_SUBST(DM_LIB_PATCHLEVEL)
|
||||
AC_SUBST(ELDFLAGS)
|
||||
@@ -2134,18 +2115,15 @@ AC_SUBST(PYTHON3DIR)
|
||||
AC_SUBST(QUORUM_CFLAGS)
|
||||
AC_SUBST(QUORUM_LIBS)
|
||||
AC_SUBST(RAID)
|
||||
AC_SUBST(RT_LIBS)
|
||||
AC_SUBST(RT_LIB)
|
||||
AC_SUBST(READLINE_LIBS)
|
||||
AC_SUBST(REPLICATORS)
|
||||
AC_SUBST(SACKPT_CFLAGS)
|
||||
AC_SUBST(SACKPT_LIBS)
|
||||
AC_SUBST(SALCK_CFLAGS)
|
||||
AC_SUBST(SALCK_LIBS)
|
||||
AC_SUBST(SBINDIR)
|
||||
AC_SUBST(SELINUX_LIBS)
|
||||
AC_SUBST(SELINUX_PC)
|
||||
AC_SUBST(SYSCONFDIR)
|
||||
AC_SUBST(SYSTEMD_LIBS)
|
||||
AC_SUBST(SNAPSHOTS)
|
||||
AC_SUBST(STATICDIR)
|
||||
AC_SUBST(STATIC_LINK)
|
||||
@@ -2167,7 +2145,6 @@ AC_SUBST(UDEV_SYSTEMD_BACKGROUND_JOBS)
|
||||
AC_SUBST(UDEV_RULE_EXEC_DETECTION)
|
||||
AC_SUBST(UDEV_HAS_BUILTIN_BLKID)
|
||||
AC_SUBST(USE_TRACKING)
|
||||
AC_SUBST(USRSBINDIR)
|
||||
AC_SUBST(VALGRIND_POOL)
|
||||
AC_SUBST(WRITE_INSTALL)
|
||||
AC_SUBST(DMEVENTD_PIDFILE)
|
||||
@@ -2224,6 +2201,7 @@ lib/format1/Makefile
|
||||
lib/format_pool/Makefile
|
||||
lib/locking/Makefile
|
||||
lib/mirror/Makefile
|
||||
lib/replicator/Makefile
|
||||
include/lvm-version.h
|
||||
lib/raid/Makefile
|
||||
lib/snapshot/Makefile
|
||||
@@ -2282,14 +2260,10 @@ AS_IF([test -n "$THIN_CONFIGURE_WARN"],
|
||||
[AC_MSG_WARN([Support for thin provisioning is limited since some thin provisioning tools are missing!])])
|
||||
|
||||
AS_IF([test -n "$THIN_CHECK_VERSION_WARN"],
|
||||
[AC_MSG_WARN([You should also install latest thin_check vsn 0.7.0 (or later) for lvm2 thin provisioning])])
|
||||
[AC_MSG_WARN([You should also install thin_check vsn 0.3.2 (or later) to use lvm2 thin provisioning])])
|
||||
|
||||
AS_IF([test -n "$CACHE_CONFIGURE_WARN"],
|
||||
[AC_MSG_WARN([Support for cache is limited since some cache tools are missing!])])
|
||||
|
||||
AS_IF([test -n "$CACHE_CHECK_VERSION_WARN"],
|
||||
[AC_MSG_WARN([You should install latest cache_check vsn 0.7.0 to use lvm2 cache metadata format 2])])
|
||||
|
||||
|
||||
AS_IF([test "$ODIRECT" != yes],
|
||||
[AC_MSG_WARN([O_DIRECT disabled: low-memory pvmove may lock up])])
|
||||
|
@@ -41,19 +41,6 @@ struct lv_segment *last_seg(const struct logical_volume *lv)
|
||||
return ((struct lv_segment **)lv)[0];
|
||||
}
|
||||
|
||||
const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile)
|
||||
{
|
||||
return "STRING";
|
||||
}
|
||||
|
||||
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
||||
{
|
||||
if (lv)
|
||||
return lv;
|
||||
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
/* simple_memccpy() from glibc */
|
||||
void *memccpy(void *dest, const void *src, int c, size_t n)
|
||||
{
|
||||
|
@@ -31,9 +31,9 @@ SALCK_LIBS = @SALCK_LIBS@
|
||||
SALCK_CFLAGS = @SALCK_CFLAGS@
|
||||
|
||||
SOURCES = \
|
||||
clvmd-command.c\
|
||||
clvmd.c\
|
||||
lvm-functions.c\
|
||||
clvmd-command.c \
|
||||
clvmd.c \
|
||||
lvm-functions.c \
|
||||
refresh_clvmd.c
|
||||
|
||||
ifneq (,$(findstring cman,, "@CLVMD@,"))
|
||||
@@ -72,21 +72,26 @@ endif
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
LVMLIBS = $(LVMINTERNAL_LIBS)
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
LVMLIBS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += $(LVMINTERNAL_LIBS) -ldevmapper $(PTHREAD_LIBS)
|
||||
CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
|
||||
LVMLIBS += -ldevmapper
|
||||
LIBS += $(PTHREAD_LIBS)
|
||||
|
||||
ifeq ("@AIO@", "yes")
|
||||
LIBS += $(AIO_LIBS)
|
||||
endif
|
||||
CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
|
||||
LDFLAGS += $(EXTRA_EXEC_LDFLAGS)
|
||||
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) \
|
||||
-o clvmd $(OBJECTS) $(LMLIBS) $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \
|
||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
.PHONY: install_clvmd
|
||||
|
||||
|
@@ -171,10 +171,8 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
|
||||
/* Check the status of the command and return the error text */
|
||||
if (status) {
|
||||
if (*buf)
|
||||
*retlen = dm_snprintf(*buf, buflen, "%s", strerror(status)) + 1;
|
||||
else
|
||||
*retlen = 0;
|
||||
*retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s",
|
||||
strerror(status)) : -1);
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -208,7 +206,7 @@ static int lock_vg(struct local_client *client)
|
||||
lock_mode = ((int) lock_cmd & LCK_TYPE_MASK);
|
||||
/* lock_flags = args[1]; */
|
||||
lockname = &args[2];
|
||||
DEBUGLOG("(%p) doing PRE command LOCK_VG '%s' at %x\n", client, lockname, lock_cmd);
|
||||
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||
|
||||
if (lock_mode == LCK_UNLOCK) {
|
||||
if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname)))
|
||||
@@ -325,7 +323,7 @@ void cmd_client_cleanup(struct local_client *client)
|
||||
int lkid;
|
||||
char *lockname;
|
||||
|
||||
DEBUGLOG("(%p) Client thread cleanup\n", client);
|
||||
DEBUGLOG("Client thread cleanup (%p)\n", client);
|
||||
if (!client->bits.localsock.private)
|
||||
return;
|
||||
|
||||
@@ -334,7 +332,7 @@ void cmd_client_cleanup(struct local_client *client)
|
||||
dm_hash_iterate(v, lock_hash) {
|
||||
lkid = (int)(long)dm_hash_get_data(lock_hash, v);
|
||||
lockname = dm_hash_get_key(lock_hash, v);
|
||||
DEBUGLOG("(%p) Cleanup: Unlocking lock %s %x\n", client, lockname, lkid);
|
||||
DEBUGLOG("Cleanup (%p): Unlocking lock %s %x\n", client, lockname, lkid);
|
||||
(void) sync_unlock(lockname, lkid);
|
||||
}
|
||||
|
||||
|
@@ -425,6 +425,8 @@ static void _add_up_node(const char *csid)
|
||||
DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
|
||||
|
||||
ninfo->state = NODE_CLVMD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
|
@@ -58,7 +58,6 @@
|
||||
/* Head of the fd list. Also contains
|
||||
the cluster_socket details */
|
||||
static struct local_client local_client_head;
|
||||
static int _local_client_count = 0;
|
||||
|
||||
static unsigned short global_xid = 0; /* Last transaction ID issued */
|
||||
|
||||
@@ -69,37 +68,6 @@ static unsigned max_csid_len;
|
||||
static unsigned max_cluster_message;
|
||||
static unsigned max_cluster_member_name_len;
|
||||
|
||||
static void _add_client(struct local_client *new_client, struct local_client *existing_client)
|
||||
{
|
||||
_local_client_count++;
|
||||
DEBUGLOG("(%p) Adding listener for fd %d. (Now %d monitored fds.)\n", new_client, new_client->fd, _local_client_count);
|
||||
new_client->next = existing_client->next;
|
||||
existing_client->next = new_client;
|
||||
}
|
||||
|
||||
int add_client(struct local_client *new_client)
|
||||
{
|
||||
_add_client(new_client, &local_client_head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns 0 if delfd is found and removed from list */
|
||||
static int _del_client(struct local_client *delfd)
|
||||
{
|
||||
struct local_client *lastfd, *thisfd;
|
||||
|
||||
for (lastfd = &local_client_head; (thisfd = lastfd->next); lastfd = thisfd)
|
||||
if (thisfd == delfd) {
|
||||
DEBUGLOG("(%p) Removing listener for fd %d\n", thisfd, thisfd->fd);
|
||||
lastfd->next = delfd->next;
|
||||
_local_client_count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Structure of items on the LVM thread list */
|
||||
struct lvm_thread_cmd {
|
||||
struct dm_list list;
|
||||
@@ -124,7 +92,6 @@ static const size_t STACK_SIZE = 128 * 1024;
|
||||
static pthread_attr_t stack_attr;
|
||||
static int lvm_thread_exit = 0;
|
||||
static pthread_mutex_t lvm_thread_mutex;
|
||||
static pthread_mutex_t _debuglog_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t lvm_thread_cond;
|
||||
static pthread_barrier_t lvm_start_barrier;
|
||||
static struct dm_list lvm_cmd_head;
|
||||
@@ -251,17 +218,14 @@ void debuglog(const char *fmt, ...)
|
||||
|
||||
switch (clvmd_get_debug()) {
|
||||
case DEBUG_STDERR:
|
||||
pthread_mutex_lock(&_debuglog_mutex);
|
||||
va_start(ap,fmt);
|
||||
time(&P);
|
||||
fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime_r(&P, buf_ctime) + 4);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fflush(stderr);
|
||||
pthread_mutex_unlock(&_debuglog_mutex);
|
||||
break;
|
||||
case DEBUG_SYSLOG:
|
||||
pthread_mutex_lock(&_debuglog_mutex);
|
||||
if (!syslog_init) {
|
||||
openlog("clvmd", LOG_PID, LOG_DAEMON);
|
||||
syslog_init = 1;
|
||||
@@ -270,7 +234,6 @@ void debuglog(const char *fmt, ...)
|
||||
va_start(ap,fmt);
|
||||
vsyslog(LOG_DEBUG, fmt, ap);
|
||||
va_end(ap);
|
||||
pthread_mutex_unlock(&_debuglog_mutex);
|
||||
break;
|
||||
case DEBUG_OFF:
|
||||
break;
|
||||
@@ -621,7 +584,6 @@ int main(int argc, char *argv[])
|
||||
local_client_head.fd = clops->get_main_cluster_fd();
|
||||
local_client_head.type = CLUSTER_MAIN_SOCK;
|
||||
local_client_head.callback = clops->cluster_fd_callback;
|
||||
_local_client_count++;
|
||||
|
||||
/* Add the local socket to the list */
|
||||
if (!(newfd = dm_zalloc(sizeof(struct local_client)))) {
|
||||
@@ -632,14 +594,14 @@ int main(int argc, char *argv[])
|
||||
newfd->fd = local_sock;
|
||||
newfd->type = LOCAL_RENDEZVOUS;
|
||||
newfd->callback = local_rendezvous_callback;
|
||||
|
||||
(void) add_client(newfd);
|
||||
newfd->next = local_client_head.next;
|
||||
local_client_head.next = newfd;
|
||||
|
||||
/* This needs to be started after cluster initialisation
|
||||
as it may need to take out locks */
|
||||
DEBUGLOG("Starting LVM thread\n");
|
||||
DEBUGLOG("(%p) Main cluster socket fd %d with local socket %d (%p)\n",
|
||||
&local_client_head, local_client_head.fd, newfd->fd, newfd);
|
||||
DEBUGLOG("Main cluster socket fd %d (%p) with local socket %d (%p)\n",
|
||||
local_client_head.fd, &local_client_head, newfd->fd, newfd);
|
||||
|
||||
/* Don't let anyone else to do work until we are started */
|
||||
if (pthread_create(&lvm_thread, &stack_attr, lvm_thread_fn, &lvm_params)) {
|
||||
@@ -675,7 +637,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
while ((delfd = local_client_head.next)) {
|
||||
local_client_head.next = delfd->next;
|
||||
_local_client_count--;
|
||||
/* Failing cleanup_zombie leaks... */
|
||||
if (delfd->type == LOCAL_SOCK && !cleanup_zombie(delfd))
|
||||
cmd_client_cleanup(delfd); /* calls sync_unlock */
|
||||
@@ -737,13 +698,13 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
|
||||
pthread_mutex_init(&newfd->bits.localsock.mutex, NULL);
|
||||
|
||||
if (fcntl(client_fd, F_SETFD, 1))
|
||||
DEBUGLOG("(%p) Setting CLOEXEC on client fd %d failed: %s\n", thisfd, client_fd, strerror(errno));
|
||||
DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno));
|
||||
|
||||
newfd->fd = client_fd;
|
||||
newfd->type = LOCAL_SOCK;
|
||||
newfd->callback = local_sock_callback;
|
||||
newfd->bits.localsock.all_success = 1;
|
||||
DEBUGLOG("(%p) Got new connection on fd %d\n", newfd, newfd->fd);
|
||||
DEBUGLOG("Got new connection on fd %d (%p)\n", newfd->fd, newfd);
|
||||
*new_client = newfd;
|
||||
}
|
||||
return 1;
|
||||
@@ -765,8 +726,8 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
|
||||
if (len == sizeof(int))
|
||||
memcpy(&status, buffer, sizeof(int));
|
||||
|
||||
DEBUGLOG("(%p) Read on pipe %d, %d bytes, status %d\n",
|
||||
thisfd, thisfd->fd, len, status);
|
||||
DEBUGLOG("Read on pipe %d, %d bytes, status %d\n",
|
||||
thisfd->fd, len, status);
|
||||
|
||||
/* EOF on pipe or an error, close it */
|
||||
if (len <= 0) {
|
||||
@@ -789,11 +750,11 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
DEBUGLOG("(%p) Background routine status was %d, sock_client %p\n",
|
||||
thisfd, status, sock_client);
|
||||
DEBUGLOG("Background routine status was %d, sock_client (%p)\n",
|
||||
status, sock_client);
|
||||
/* But has the client gone away ?? */
|
||||
if (!sock_client) {
|
||||
DEBUGLOG("(%p) Got pipe response for dead client, ignoring it\n", thisfd);
|
||||
DEBUGLOG("Got pipe response for dead client, ignoring it\n");
|
||||
} else {
|
||||
/* If error then just return that code */
|
||||
if (status)
|
||||
@@ -833,7 +794,7 @@ static void timedout_callback(struct local_client *client, const char *csid,
|
||||
return;
|
||||
|
||||
clops->name_from_csid(csid, nodename);
|
||||
DEBUGLOG("(%p) Checking for a reply from %s\n", client, nodename);
|
||||
DEBUGLOG("Checking for a reply from %s\n", nodename);
|
||||
pthread_mutex_lock(&client->bits.localsock.mutex);
|
||||
|
||||
reply = client->bits.localsock.replies;
|
||||
@@ -843,7 +804,7 @@ static void timedout_callback(struct local_client *client, const char *csid,
|
||||
pthread_mutex_unlock(&client->bits.localsock.mutex);
|
||||
|
||||
if (!reply) {
|
||||
DEBUGLOG("(%p) Node %s timed-out\n", client, nodename);
|
||||
DEBUGLOG("Node %s timed-out\n", nodename);
|
||||
add_reply_to_list(client, ETIMEDOUT, csid,
|
||||
"Command timed out", 18);
|
||||
}
|
||||
@@ -858,7 +819,7 @@ static void timedout_callback(struct local_client *client, const char *csid,
|
||||
*/
|
||||
static void request_timed_out(struct local_client *client)
|
||||
{
|
||||
DEBUGLOG("(%p) Request timed-out. padding\n", client);
|
||||
DEBUGLOG("Request timed-out. padding\n");
|
||||
clops->cluster_do_node_callback(client, timedout_callback);
|
||||
|
||||
if (!client->bits.localsock.threadid)
|
||||
@@ -892,11 +853,13 @@ static void main_loop(int cmd_timeout)
|
||||
while (!quit) {
|
||||
fd_set in;
|
||||
int select_status;
|
||||
struct local_client *thisfd, *nextfd;
|
||||
struct local_client *thisfd;
|
||||
struct timeval tv = { cmd_timeout, 0 };
|
||||
int quorate = clops->is_quorate();
|
||||
int client_count = 0;
|
||||
int max_fd = 0;
|
||||
struct local_client *lastfd = &local_client_head;
|
||||
struct local_client *nextfd = local_client_head.next;
|
||||
|
||||
/* Wait on the cluster FD and all local sockets/pipes */
|
||||
local_client_head.fd = clops->get_main_cluster_fd();
|
||||
@@ -912,22 +875,21 @@ static void main_loop(int cmd_timeout)
|
||||
fprintf(stderr, "WARNING: Your cluster may freeze up if the number of clvmd file descriptors (%d) exceeds %d.\n", max_fd + 1, FD_SETSIZE);
|
||||
}
|
||||
|
||||
for (thisfd = &local_client_head; thisfd; thisfd = nextfd) {
|
||||
nextfd = thisfd->next;
|
||||
for (thisfd = &local_client_head; thisfd; thisfd = nextfd, nextfd = thisfd ? thisfd->next : NULL) {
|
||||
|
||||
if (thisfd->removeme && !cleanup_zombie(thisfd)) {
|
||||
/* cleanup_zombie might have removed the next list element */
|
||||
nextfd = thisfd->next;
|
||||
|
||||
(void) _del_client(thisfd);
|
||||
|
||||
DEBUGLOG("(%p) removeme set with %d monitored fds remaining\n", thisfd, _local_client_count);
|
||||
struct local_client *free_fd = thisfd;
|
||||
lastfd->next = nextfd;
|
||||
DEBUGLOG("removeme set for %p with %d monitored fds remaining\n", free_fd, client_count - 1);
|
||||
|
||||
/* Queue cleanup, this also frees the client struct */
|
||||
add_to_lvmqueue(thisfd, NULL, 0, NULL);
|
||||
add_to_lvmqueue(free_fd, NULL, 0, NULL);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
lastfd = thisfd;
|
||||
|
||||
if (thisfd->removeme)
|
||||
continue;
|
||||
|
||||
@@ -977,15 +939,16 @@ static void main_loop(int cmd_timeout)
|
||||
type == CLUSTER_INTERNAL)
|
||||
goto closedown;
|
||||
|
||||
DEBUGLOG("(%p) ret == %d, errno = %d. removing client\n",
|
||||
thisfd, ret, errno);
|
||||
DEBUGLOG("ret == %d, errno = %d. removing client\n",
|
||||
ret, errno);
|
||||
thisfd->removeme = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* New client...simply add it to the list */
|
||||
if (newfd) {
|
||||
_add_client(newfd, thisfd);
|
||||
newfd->next = thisfd->next;
|
||||
thisfd->next = newfd;
|
||||
thisfd = newfd;
|
||||
}
|
||||
}
|
||||
@@ -1003,8 +966,8 @@ static void main_loop(int cmd_timeout)
|
||||
thisfd->bits.localsock.expected_replies !=
|
||||
thisfd->bits.localsock.num_replies) {
|
||||
/* Send timed out message + replies we already have */
|
||||
DEBUGLOG("Request to client %p timed-out (send: %ld, now: %ld)\n",
|
||||
thisfd, thisfd->bits.localsock.sent_time, the_time);
|
||||
DEBUGLOG("Request timed-out (send: %ld, now: %ld)\n",
|
||||
thisfd->bits.localsock.sent_time, the_time);
|
||||
|
||||
thisfd->bits.localsock.all_success = 0;
|
||||
|
||||
@@ -1105,31 +1068,31 @@ static void be_daemon(int timeout)
|
||||
break;
|
||||
|
||||
default: /* Parent */
|
||||
(void) close(devnull);
|
||||
(void) close(child_pipe[1]);
|
||||
wait_for_child(child_pipe[0], timeout); /* noreturn */
|
||||
wait_for_child(child_pipe[0], timeout);
|
||||
}
|
||||
|
||||
/* Detach ourself from the calling environment */
|
||||
if ((dup2(devnull, STDIN_FILENO) == -1) ||
|
||||
(dup2(devnull, STDOUT_FILENO) == -1) ||
|
||||
(dup2(devnull, STDERR_FILENO) == -1)) {
|
||||
if (close(0) || close(1) || close(2)) {
|
||||
perror("Error closing terminal FDs");
|
||||
exit(4);
|
||||
}
|
||||
setsid();
|
||||
|
||||
if (dup2(devnull, 0) < 0 || dup2(devnull, 1) < 0
|
||||
|| dup2(devnull, 2) < 0) {
|
||||
perror("Error setting terminal FDs to /dev/null");
|
||||
log_error("Error setting terminal FDs to /dev/null: %m");
|
||||
exit(5);
|
||||
}
|
||||
|
||||
if ((devnull > STDERR_FILENO) && close(devnull)) {
|
||||
log_sys_error("close", "/dev/null");
|
||||
exit(7);
|
||||
}
|
||||
|
||||
if (chdir("/")) {
|
||||
log_error("Error setting current directory to /: %m");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
setsid();
|
||||
}
|
||||
|
||||
static int verify_message(char *buf, int len)
|
||||
@@ -1216,8 +1179,8 @@ static int cleanup_zombie(struct local_client *thisfd)
|
||||
if (!thisfd->bits.localsock.cleanup_needed)
|
||||
return 0;
|
||||
|
||||
DEBUGLOG("(%p) EOF on local socket %d: inprogress=%d\n",
|
||||
thisfd, thisfd->fd, thisfd->bits.localsock.in_progress);
|
||||
DEBUGLOG("EOF on local socket: inprogress=%d\n",
|
||||
thisfd->bits.localsock.in_progress);
|
||||
|
||||
if ((pipe_client = thisfd->bits.localsock.pipe_client))
|
||||
pipe_client = pipe_client->bits.pipe.client;
|
||||
@@ -1239,7 +1202,7 @@ static int cleanup_zombie(struct local_client *thisfd)
|
||||
|
||||
/* Kill the subthread & free resources */
|
||||
if (thisfd->bits.localsock.threadid) {
|
||||
DEBUGLOG("(%p) Waiting for pre&post thread\n", pipe_client);
|
||||
DEBUGLOG("Waiting for pre&post thread (%p)\n", pipe_client);
|
||||
pthread_mutex_lock(&thisfd->bits.localsock.mutex);
|
||||
thisfd->bits.localsock.state = PRE_COMMAND;
|
||||
thisfd->bits.localsock.finished = 1;
|
||||
@@ -1250,22 +1213,26 @@ static int cleanup_zombie(struct local_client *thisfd)
|
||||
(void **) &status)))
|
||||
log_sys_error("pthread_join", "");
|
||||
|
||||
DEBUGLOG("(%p) Joined pre&post thread\n", pipe_client);
|
||||
DEBUGLOG("Joined pre&post thread\n");
|
||||
|
||||
thisfd->bits.localsock.threadid = 0;
|
||||
|
||||
/* Remove the pipe client */
|
||||
if (thisfd->bits.localsock.pipe_client) {
|
||||
struct local_client *delfd = thisfd->bits.localsock.pipe_client;
|
||||
struct local_client *delfd;
|
||||
struct local_client *lastfd;
|
||||
|
||||
(void) close(delfd->fd); /* Close pipe */
|
||||
(void) close(thisfd->bits.localsock.pipe_client->fd); /* Close pipe */
|
||||
(void) close(thisfd->bits.localsock.pipe);
|
||||
|
||||
/* Remove pipe client */
|
||||
if (!_del_client(delfd)) {
|
||||
dm_free(delfd);
|
||||
thisfd->bits.localsock.pipe_client = NULL;
|
||||
}
|
||||
for (lastfd = &local_client_head; (delfd = lastfd->next); lastfd = delfd)
|
||||
if (thisfd->bits.localsock.pipe_client == delfd) {
|
||||
thisfd->bits.localsock.pipe_client = NULL;
|
||||
lastfd->next = delfd->next;
|
||||
dm_free(delfd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1296,7 +1263,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
if (len == -1 && errno == EINTR)
|
||||
return 1;
|
||||
|
||||
DEBUGLOG("(%p) Read on local socket %d, len = %d\n", thisfd, thisfd->fd, len);
|
||||
DEBUGLOG("Read on local socket %d, len = %d\n", thisfd->fd, len);
|
||||
|
||||
if (len && verify_message(buffer, len) < 0) {
|
||||
log_error("read_from_local_sock from %d len %d bad verify.",
|
||||
@@ -1370,15 +1337,15 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
char *argptr = inheader->node + strlen(inheader->node) + 1;
|
||||
|
||||
while (missing_len > 0) {
|
||||
DEBUGLOG("(%p) got %d bytes, need another %d (total %d)\n",
|
||||
thisfd, argslen, missing_len, inheader->arglen);
|
||||
DEBUGLOG("got %d bytes, need another %d (total %d)\n",
|
||||
argslen, missing_len, inheader->arglen);
|
||||
len = read(thisfd->fd, argptr + argslen, missing_len);
|
||||
if (len == -1 && errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (len <= 0) {
|
||||
/* EOF or error on socket */
|
||||
DEBUGLOG("(%p) EOF on local socket\n", thisfd);
|
||||
DEBUGLOG("EOF on local socket\n");
|
||||
dm_free(thisfd->bits.localsock.cmd);
|
||||
thisfd->bits.localsock.cmd = NULL;
|
||||
return 0;
|
||||
@@ -1406,7 +1373,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
.status = ENOENT
|
||||
};
|
||||
|
||||
DEBUGLOG("(%p) Unknown node: '%s'\n", thisfd, inheader->node);
|
||||
DEBUGLOG("Unknown node: '%s'\n", inheader->node);
|
||||
send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
|
||||
"Error sending ENOENT reply to local user");
|
||||
thisfd->bits.localsock.expected_replies = 0;
|
||||
@@ -1432,7 +1399,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
.status = EBUSY
|
||||
};
|
||||
|
||||
DEBUGLOG("(%p) Creating pipe failed: %s\n", thisfd, strerror(errno));
|
||||
DEBUGLOG("Creating pipe failed: %s\n", strerror(errno));
|
||||
send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
|
||||
"Error sending EBUSY reply to local user");
|
||||
return len;
|
||||
@@ -1452,7 +1419,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
return len;
|
||||
}
|
||||
|
||||
DEBUGLOG("(%p) Creating pipe, [%d, %d]\n", thisfd, comms_pipe[0], comms_pipe[1]);
|
||||
DEBUGLOG("Creating pipe, [%d, %d]\n", comms_pipe[0], comms_pipe[1]);
|
||||
|
||||
if (fcntl(comms_pipe[0], F_SETFD, 1))
|
||||
DEBUGLOG("setting CLOEXEC on pipe[0] failed: %s\n", strerror(errno));
|
||||
@@ -1463,8 +1430,8 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
newfd->type = THREAD_PIPE;
|
||||
newfd->callback = local_pipe_callback;
|
||||
newfd->bits.pipe.client = thisfd;
|
||||
|
||||
_add_client(newfd, thisfd);
|
||||
newfd->next = thisfd->next;
|
||||
thisfd->next = newfd;
|
||||
|
||||
/* Store a cross link to the pipe */
|
||||
thisfd->bits.localsock.pipe_client = newfd;
|
||||
@@ -1477,10 +1444,10 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
thisfd->bits.localsock.in_progress = TRUE;
|
||||
thisfd->bits.localsock.state = PRE_COMMAND;
|
||||
thisfd->bits.localsock.cleanup_needed = 1;
|
||||
DEBUGLOG("(%p) Creating pre&post thread for pipe fd %d\n", newfd, newfd->fd);
|
||||
DEBUGLOG("Creating pre&post thread for pipe fd %d (%p)\n", newfd->fd, newfd);
|
||||
status = pthread_create(&thisfd->bits.localsock.threadid,
|
||||
&stack_attr, pre_and_post_thread, thisfd);
|
||||
DEBUGLOG("(%p) Created pre&post thread, state = %d\n", newfd, status);
|
||||
DEBUGLOG("Created pre&post thread, state = %d\n", status);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -1488,6 +1455,13 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
/* Add a file descriptor from the cluster or comms interface to
|
||||
our list of FDs for select
|
||||
*/
|
||||
int add_client(struct local_client *new_client)
|
||||
{
|
||||
new_client->next = local_client_head.next;
|
||||
local_client_head.next = new_client;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called when the pre-command has completed successfully - we
|
||||
now execute the real command on all the requested nodes */
|
||||
@@ -1498,8 +1472,8 @@ static int distribute_command(struct local_client *thisfd)
|
||||
int len = thisfd->bits.localsock.cmd_len;
|
||||
|
||||
thisfd->xid = global_xid++;
|
||||
DEBUGLOG("(%p) distribute command: XID = %d, flags=0x%x (%s%s)\n",
|
||||
thisfd, thisfd->xid, inheader->flags,
|
||||
DEBUGLOG("distribute command: XID = %d, flags=0x%x (%s%s)\n",
|
||||
thisfd->xid, inheader->flags,
|
||||
(inheader->flags & CLVMD_FLAG_LOCAL) ? "LOCAL" : "",
|
||||
(inheader->flags & CLVMD_FLAG_REMOTE) ? "REMOTE" : "");
|
||||
|
||||
@@ -1521,7 +1495,7 @@ static int distribute_command(struct local_client *thisfd)
|
||||
*/
|
||||
add_to_lvmqueue(thisfd, inheader, len, NULL);
|
||||
|
||||
DEBUGLOG("(%p) Sending message to all cluster nodes\n", thisfd);
|
||||
DEBUGLOG("Sending message to all cluster nodes\n");
|
||||
inheader->xid = thisfd->xid;
|
||||
send_message(inheader, len, NULL, -1,
|
||||
"Error forwarding message to cluster");
|
||||
@@ -1540,11 +1514,11 @@ static int distribute_command(struct local_client *thisfd)
|
||||
|
||||
/* Are we the requested node ?? */
|
||||
if (memcmp(csid, our_csid, max_csid_len) == 0) {
|
||||
DEBUGLOG("(%p) Doing command on local node only\n", thisfd);
|
||||
DEBUGLOG("Doing command on local node only\n");
|
||||
add_to_lvmqueue(thisfd, inheader, len, NULL);
|
||||
} else {
|
||||
DEBUGLOG("(%p) Sending message to single node: %s\n",
|
||||
thisfd, inheader->node);
|
||||
DEBUGLOG("Sending message to single node: %s\n",
|
||||
inheader->node);
|
||||
inheader->xid = thisfd->xid;
|
||||
send_message(inheader, len, csid, -1,
|
||||
"Error forwarding message to cluster node");
|
||||
@@ -1555,7 +1529,7 @@ static int distribute_command(struct local_client *thisfd)
|
||||
thisfd->bits.localsock.in_progress = TRUE;
|
||||
thisfd->bits.localsock.expected_replies = 1;
|
||||
thisfd->bits.localsock.num_replies = 0;
|
||||
DEBUGLOG("(%p) Doing command explicitly on local node only\n", thisfd);
|
||||
DEBUGLOG("Doing command explicitly on local node only\n");
|
||||
add_to_lvmqueue(thisfd, inheader, len, NULL);
|
||||
}
|
||||
|
||||
@@ -1681,7 +1655,7 @@ static void add_reply_to_list(struct local_client *client, int status,
|
||||
|
||||
reply->status = status;
|
||||
clops->name_from_csid(csid, reply->node);
|
||||
DEBUGLOG("(%p) Reply from node %s: %d bytes\n", client, reply->node, len);
|
||||
DEBUGLOG("Reply from node %s: %d bytes\n", reply->node, len);
|
||||
|
||||
if (len > 0) {
|
||||
if (!(reply->replymsg = dm_malloc(len)))
|
||||
@@ -1708,8 +1682,8 @@ static void add_reply_to_list(struct local_client *client, int status,
|
||||
client->bits.localsock.state = POST_COMMAND;
|
||||
pthread_cond_signal(&client->bits.localsock.cond);
|
||||
}
|
||||
DEBUGLOG("(%p) Got %d replies, expecting: %d\n",
|
||||
client, client->bits.localsock.num_replies,
|
||||
DEBUGLOG("Got %d replies, expecting: %d\n",
|
||||
client->bits.localsock.num_replies,
|
||||
client->bits.localsock.expected_replies);
|
||||
}
|
||||
pthread_mutex_unlock(&client->bits.localsock.mutex);
|
||||
@@ -1724,7 +1698,7 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
|
||||
sigset_t ss;
|
||||
int pipe_fd = client->bits.localsock.pipe;
|
||||
|
||||
DEBUGLOG("(%p) Pre&post thread pipe fd %d\n", client, pipe_fd);
|
||||
DEBUGLOG("Pre&post thread (%p), pipe fd %d\n", client, pipe_fd);
|
||||
pthread_mutex_lock(&client->bits.localsock.mutex);
|
||||
|
||||
/* Ignore SIGUSR1 (handled by master process) but enable
|
||||
@@ -1744,7 +1718,7 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
|
||||
if ((status = do_pre_command(client)))
|
||||
client->bits.localsock.all_success = 0;
|
||||
|
||||
DEBUGLOG("(%p) Pre&post thread writes status %d down to pipe fd %d\n",
|
||||
DEBUGLOG("Pre&post thread (%p) writes status %d down to pipe fd %d\n",
|
||||
client, status, pipe_fd);
|
||||
|
||||
/* Tell the parent process we have finished this bit */
|
||||
@@ -1762,13 +1736,13 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
|
||||
/* We may need to wait for the condition variable before running the post command */
|
||||
if (client->bits.localsock.state != POST_COMMAND &&
|
||||
!client->bits.localsock.finished) {
|
||||
DEBUGLOG("(%p) Pre&post thread waiting to do post command, state = %d\n",
|
||||
DEBUGLOG("Pre&post thread (%p) waiting to do post command, state = %d\n",
|
||||
client, client->bits.localsock.state);
|
||||
pthread_cond_wait(&client->bits.localsock.cond,
|
||||
&client->bits.localsock.mutex);
|
||||
}
|
||||
|
||||
DEBUGLOG("(%p) Pre&post thread got post command condition...\n", client);
|
||||
DEBUGLOG("Pre&post thread (%p) got post command condition...\n", client);
|
||||
|
||||
/* POST function must always run, even if the client aborts */
|
||||
status = 0;
|
||||
@@ -1782,15 +1756,15 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
|
||||
next_pre:
|
||||
if (client->bits.localsock.state != PRE_COMMAND &&
|
||||
!client->bits.localsock.finished) {
|
||||
DEBUGLOG("(%p) Pre&post thread waiting for next pre command\n", client);
|
||||
DEBUGLOG("Pre&post thread (%p) waiting for next pre command\n", client);
|
||||
pthread_cond_wait(&client->bits.localsock.cond,
|
||||
&client->bits.localsock.mutex);
|
||||
}
|
||||
|
||||
DEBUGLOG("(%p) Pre&post thread got pre command condition...\n", client);
|
||||
DEBUGLOG("Pre&post thread (%p) got pre command condition...\n", client);
|
||||
}
|
||||
pthread_mutex_unlock(&client->bits.localsock.mutex);
|
||||
DEBUGLOG("(%p) Pre&post thread finished\n", client);
|
||||
DEBUGLOG("Pre&post thread (%p) finished\n", client);
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
@@ -1808,8 +1782,8 @@ static int process_local_command(struct clvm_header *msg, int msglen,
|
||||
if (!(replybuf = dm_malloc(max_cluster_message)))
|
||||
return -1;
|
||||
|
||||
DEBUGLOG("(%p) process_local_command: %s msg=%p, msglen =%d\n",
|
||||
client, decode_cmd(msg->cmd), msg, msglen);
|
||||
DEBUGLOG("process_local_command: %s msg=%p, msglen =%d, client=%p\n",
|
||||
decode_cmd(msg->cmd), msg, msglen, client);
|
||||
|
||||
/* If remote flag is set, just set a successful status code. */
|
||||
if (msg->flags & CLVMD_FLAG_REMOTE)
|
||||
@@ -1824,8 +1798,8 @@ static int process_local_command(struct clvm_header *msg, int msglen,
|
||||
if (xid == client->xid)
|
||||
add_reply_to_list(client, status, our_csid, replybuf, replylen);
|
||||
else
|
||||
DEBUGLOG("(%p) Local command took too long, discarding xid %d, current is %d\n",
|
||||
client, xid, client->xid);
|
||||
DEBUGLOG("Local command took too long, discarding xid %d, current is %d\n",
|
||||
xid, client->xid);
|
||||
|
||||
dm_free(replybuf);
|
||||
|
||||
@@ -1867,7 +1841,7 @@ static void send_local_reply(struct local_client *client, int status, int fd)
|
||||
char *ptr;
|
||||
int message_len = 0;
|
||||
|
||||
DEBUGLOG("(%p) Send local reply\n", client);
|
||||
DEBUGLOG("Send local reply\n");
|
||||
|
||||
/* Work out the total size of the reply */
|
||||
while (thisreply) {
|
||||
@@ -1884,7 +1858,7 @@ static void send_local_reply(struct local_client *client, int status, int fd)
|
||||
/* Add in the size of our header */
|
||||
message_len = message_len + sizeof(struct clvm_header);
|
||||
if (!(replybuf = dm_malloc(message_len))) {
|
||||
DEBUGLOG("(%p) Memory allocation fails\n", client);
|
||||
DEBUGLOG("Memory allocation fails\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2013,7 +1987,6 @@ static int send_message(void *buf, int msglen, const char *csid, int fd,
|
||||
(void) nanosleep (&delay, &remtime);
|
||||
continue;
|
||||
}
|
||||
DEBUGLOG("%s", errtext);
|
||||
log_error("%s", errtext);
|
||||
break;
|
||||
}
|
||||
@@ -2027,7 +2000,7 @@ static int process_work_item(struct lvm_thread_cmd *cmd)
|
||||
{
|
||||
/* If msg is NULL then this is a cleanup request */
|
||||
if (cmd->msg == NULL) {
|
||||
DEBUGLOG("(%p) process_work_item: free\n", cmd->client);
|
||||
DEBUGLOG("process_work_item: free %p\n", cmd->client);
|
||||
cmd_client_cleanup(cmd->client);
|
||||
pthread_mutex_destroy(&cmd->client->bits.localsock.mutex);
|
||||
pthread_cond_destroy(&cmd->client->bits.localsock.cond);
|
||||
@@ -2036,11 +2009,11 @@ static int process_work_item(struct lvm_thread_cmd *cmd)
|
||||
}
|
||||
|
||||
if (!cmd->remote) {
|
||||
DEBUGLOG("(%p) process_work_item: local\n", cmd->client);
|
||||
DEBUGLOG("process_work_item: local\n");
|
||||
process_local_command(cmd->msg, cmd->msglen, cmd->client,
|
||||
cmd->xid);
|
||||
} else {
|
||||
DEBUGLOG("(%p) process_work_item: remote\n", cmd->client);
|
||||
DEBUGLOG("process_work_item: remote\n");
|
||||
process_remote_command(cmd->msg, cmd->msglen, cmd->client->fd,
|
||||
cmd->csid);
|
||||
}
|
||||
@@ -2134,8 +2107,8 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
|
||||
} else
|
||||
cmd->remote = 0;
|
||||
|
||||
DEBUGLOG("(%p) add_to_lvmqueue: cmd=%p, msg=%p, len=%d, csid=%p, xid=%d\n",
|
||||
client, cmd, msg, msglen, csid, cmd->xid);
|
||||
DEBUGLOG("add_to_lvmqueue: cmd=%p. client=%p, msg=%p, len=%d, csid=%p, xid=%d\n",
|
||||
cmd, client, msg, msglen, csid, cmd->xid);
|
||||
pthread_mutex_lock(&lvm_thread_mutex);
|
||||
if (lvm_thread_exit) {
|
||||
pthread_mutex_unlock(&lvm_thread_mutex);
|
||||
@@ -2271,8 +2244,7 @@ static void check_all_callback(struct local_client *client, const char *csid,
|
||||
If not, returns -1 and prints out a list of errant nodes */
|
||||
static int check_all_clvmds_running(struct local_client *client)
|
||||
{
|
||||
DEBUGLOG("(%p) check_all_clvmds_running\n", client);
|
||||
|
||||
DEBUGLOG("check_all_clvmds_running\n");
|
||||
return clops->cluster_do_node_callback(client, check_all_callback);
|
||||
}
|
||||
|
||||
@@ -2311,11 +2283,13 @@ static void ntoh_clvm(struct clvm_header *hdr)
|
||||
static void sigusr2_handler(int sig)
|
||||
{
|
||||
DEBUGLOG("SIGUSR2 received\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static void sigterm_handler(int sig)
|
||||
{
|
||||
quit = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
static void sighup_handler(int sig)
|
||||
|
@@ -661,7 +661,6 @@ int do_refresh_cache(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd->use_aio = 0;
|
||||
init_full_scan_done(0);
|
||||
init_ignore_suspended_devices(1);
|
||||
lvmcache_force_next_label_scan();
|
||||
@@ -921,7 +920,6 @@ int init_clvm(struct dm_hash_table *excl_uuid)
|
||||
/* Check lvm.conf is setup for cluster-LVM */
|
||||
check_config();
|
||||
init_ignore_suspended_devices(1);
|
||||
cmd->use_aio = 0;
|
||||
|
||||
/* Trap log messages so we can pass them back to the user */
|
||||
init_log_fn(lvm2_log_fn);
|
||||
|
@@ -29,7 +29,7 @@ include $(top_builddir)/make.tmpl
|
||||
LIBS += -ldevmapper
|
||||
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
|
||||
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS) $(EXTRA_EXEC_CFLAGS)
|
||||
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LDFLAGS += $(EXTRA_EXEC_LDFLAGS)
|
||||
|
||||
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
||||
|
@@ -56,16 +56,18 @@ include $(top_builddir)/make.tmpl
|
||||
all: device-mapper
|
||||
device-mapper: $(TARGETS)
|
||||
|
||||
LIBS += -ldevmapper
|
||||
LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS)
|
||||
|
||||
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
|
||||
LIBS += -ldevmapper $(PTHREAD_LIBS)
|
||||
|
||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||
$(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
|
||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \
|
||||
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
|
||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
|
||||
dmeventd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
|
||||
|
||||
ifeq ("@PKGCONFIG@", "yes")
|
||||
INSTALL_LIB_TARGETS += install_pkgconfig
|
||||
|
@@ -62,8 +62,6 @@
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#define DM_SIGNALED_EXIT 1
|
||||
#define DM_SCHEDULED_EXIT 2
|
||||
static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */
|
||||
|
||||
/* List (un)link macros. */
|
||||
@@ -1752,7 +1750,7 @@ static void _init_thread_signals(void)
|
||||
*/
|
||||
static void _exit_handler(int sig __attribute__((unused)))
|
||||
{
|
||||
_exit_now = DM_SIGNALED_EXIT;
|
||||
_exit_now = 1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -2250,14 +2248,11 @@ int main(int argc, char *argv[])
|
||||
for (;;) {
|
||||
if (_idle_since) {
|
||||
if (_exit_now) {
|
||||
if (_exit_now == DM_SCHEDULED_EXIT)
|
||||
break; /* Only prints shutdown message */
|
||||
log_info("dmeventd detected break while being idle "
|
||||
"for %ld second(s), exiting.",
|
||||
(long) (time(NULL) - _idle_since));
|
||||
break;
|
||||
}
|
||||
if (idle_exit_timeout) {
|
||||
} else if (idle_exit_timeout) {
|
||||
now = time(NULL);
|
||||
if (now < _idle_since)
|
||||
_idle_since = now; /* clock change? */
|
||||
@@ -2268,14 +2263,15 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_exit_now == DM_SIGNALED_EXIT) {
|
||||
_exit_now = DM_SCHEDULED_EXIT;
|
||||
} else if (_exit_now) {
|
||||
_exit_now = 0;
|
||||
/*
|
||||
* When '_exit_now' is set, signal has been received,
|
||||
* but can not simply exit unless all
|
||||
* threads are done processing.
|
||||
*/
|
||||
log_info("dmeventd received break, scheduling exit.");
|
||||
log_warn("WARNING: There are still devices being monitored.");
|
||||
log_warn("WARNING: Refusing to exit.");
|
||||
}
|
||||
_process_request(&fifos);
|
||||
_cleanup_unused_threads();
|
||||
|
@@ -250,9 +250,10 @@ static int _daemon_read(struct dm_event_fifos *fifos,
|
||||
if (ret < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
|
||||
log_error("Unable to read from event server.");
|
||||
return 0;
|
||||
else {
|
||||
log_error("Unable to read from event server.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytes += ret;
|
||||
@@ -328,9 +329,10 @@ static int _daemon_write(struct dm_event_fifos *fifos,
|
||||
if (ret < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
|
||||
log_error("Unable to talk to event daemon.");
|
||||
return 0;
|
||||
else {
|
||||
log_error("Unable to talk to event daemon.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytes += ret;
|
||||
@@ -452,8 +454,7 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
if (close(fifos->client))
|
||||
log_sys_debug("close", fifos->client_path);
|
||||
return 1;
|
||||
}
|
||||
if (errno != ENXIO && errno != ENOENT) {
|
||||
} else if (errno != ENXIO && errno != ENOENT) {
|
||||
/* problem */
|
||||
log_sys_error("open", fifos->client_path);
|
||||
return 0;
|
||||
|
@@ -58,23 +58,6 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
dead = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we are converting from non-RAID to RAID (e.g. linear -> raid1)
|
||||
* and too many original devices die, such that we cannot continue
|
||||
* the "recover" operation, the sync action will go to "idle", the
|
||||
* unsynced devs will remain at 'a', and the original devices will
|
||||
* NOT SWITCH TO 'D', but will remain at 'A' - hoping to be revived.
|
||||
*
|
||||
* This is simply the way the kernel works...
|
||||
*/
|
||||
if (!strcmp(status->sync_action, "idle") &&
|
||||
(status->dev_health[0] == 'a') &&
|
||||
(status->insync_regions < status->total_regions)) {
|
||||
log_error("Primary sources for new RAID, %s, have failed.",
|
||||
device);
|
||||
dead = 1; /* run it through LVM repair */
|
||||
}
|
||||
|
||||
if (dead) {
|
||||
if (status->insync_regions < status->total_regions) {
|
||||
if (!state->warned) {
|
||||
@@ -98,8 +81,6 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
}
|
||||
} else {
|
||||
state->failed = 0;
|
||||
if (status->insync_regions == status->total_regions)
|
||||
memset(&state->raid_devs, 0, sizeof(state->raid_devs));
|
||||
log_info("%s array, %s, is %s in-sync.",
|
||||
status->raid_type, device,
|
||||
(status->insync_regions == status->total_regions) ? "now" : "not");
|
||||
@@ -153,7 +134,8 @@ int register_device(const char *device,
|
||||
goto_bad;
|
||||
|
||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
|
||||
"lvconvert --repair --use-policies", device))
|
||||
"lvconvert --config devices{ignore_suspended_devices=1} "
|
||||
"--repair --use-policies", device))
|
||||
goto_bad;
|
||||
|
||||
*user = state;
|
||||
|
@@ -231,7 +231,7 @@ void process_event(struct dm_task *dmt,
|
||||
|
||||
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
|
||||
log_warn("WARNING: Snapshot %s is now %.2f%% full.",
|
||||
device, dm_percent_to_round_float(percent, 2));
|
||||
device, dm_percent_to_float(percent));
|
||||
|
||||
/* Try to extend the snapshot, in accord with user-set policies */
|
||||
if (!_extend(state->cmd_lvextend))
|
||||
|
@@ -172,8 +172,8 @@ void process_event(struct dm_task *dmt,
|
||||
|
||||
#if THIN_DEBUG
|
||||
log_debug("Watch for tp-data:%.2f%% tp-metadata:%.2f%%.",
|
||||
dm_percent_to_round_float(state->data_percent_check, 2),
|
||||
dm_percent_to_round_float(state->metadata_percent_check, 2));
|
||||
dm_percent_to_float(state->data_percent_check),
|
||||
dm_percent_to_float(state->metadata_percent_check));
|
||||
#endif
|
||||
if (!_wait_for_pid(state)) {
|
||||
log_warn("WARNING: Skipping event, child %d is still running (%s).",
|
||||
@@ -254,7 +254,7 @@ void process_event(struct dm_task *dmt,
|
||||
if ((state->metadata_percent > WARNING_THRESH) &&
|
||||
(state->metadata_percent > state->metadata_percent_check))
|
||||
log_warn("WARNING: Thin pool %s metadata is now %.2f%% full.",
|
||||
device, dm_percent_to_round_float(state->metadata_percent, 2));
|
||||
device, dm_percent_to_float(state->metadata_percent));
|
||||
if (state->metadata_percent > CHECK_MINIMUM) {
|
||||
/* Run action when usage raised more than CHECK_STEP since the last time */
|
||||
if (state->metadata_percent > state->metadata_percent_check)
|
||||
@@ -269,7 +269,7 @@ void process_event(struct dm_task *dmt,
|
||||
if ((state->data_percent > WARNING_THRESH) &&
|
||||
(state->data_percent > state->data_percent_check))
|
||||
log_warn("WARNING: Thin pool %s data is now %.2f%% full.",
|
||||
device, dm_percent_to_round_float(state->data_percent, 2));
|
||||
device, dm_percent_to_float(state->data_percent));
|
||||
if (state->data_percent > CHECK_MINIMUM) {
|
||||
/* Run action when usage raised more than CHECK_STEP since the last time */
|
||||
if (state->data_percent > state->data_percent_check)
|
||||
|
@@ -34,16 +34,17 @@ include $(top_builddir)/make.tmpl
|
||||
all: device-mapper
|
||||
device-mapper: $(TARGETS)
|
||||
|
||||
CFLAGS_dmfilemapd.o += $(EXTRA_EXEC_CFLAGS)
|
||||
LIBS += -ldevmapper
|
||||
|
||||
CFLAGS_dmfilemapd.o += $(EXTRA_EXEC_CFLAGS)
|
||||
|
||||
dmfilemapd: $(LIB_SHARED) dmfilemapd.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) \
|
||||
-o $@ dmfilemapd.o $(DL_LIBS) $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -L. -o $@ dmfilemapd.o \
|
||||
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
dmfilemapd.static: $(LIB_STATIC) dmfilemapd.o $(interfacebuilddir)/libdevmapper.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L$(interfacebuilddir) \
|
||||
-o $@ dmfilemapd.o $(DL_LIBS) $(LIBS) $(STATIC_LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
|
||||
dmfilemapd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
|
||||
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
@@ -64,3 +65,4 @@ install_dmfilemapd: $(INSTALL_DMFILEMAPD_TARGETS)
|
||||
install: install_dmfilemapd
|
||||
|
||||
install_device-mapper: install_dmfilemapd
|
||||
|
||||
|
@@ -225,9 +225,8 @@ static int _is_open(const char *path)
|
||||
while ((proc_dp = readdir(proc_d)) != NULL) {
|
||||
if (!isdigit(proc_dp->d_name[0]))
|
||||
continue;
|
||||
errno = 0;
|
||||
pid = (pid_t) strtol(proc_dp->d_name, NULL, 10);
|
||||
if (errno || !pid)
|
||||
if (!pid)
|
||||
continue;
|
||||
if (_is_open_in_pid(pid, path)) {
|
||||
if (closedir(proc_d))
|
||||
@@ -279,9 +278,8 @@ static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
|
||||
fm->nr_regions = 1;
|
||||
|
||||
/* parse <fd> */
|
||||
errno = 0;
|
||||
fm->fd = (int) strtol(argv[0], &endptr, 10);
|
||||
if (errno || *endptr) {
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse file descriptor: %s", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -290,9 +288,8 @@ static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
|
||||
argv++;
|
||||
|
||||
/* parse <group_id> */
|
||||
errno = 0;
|
||||
fm->group_id = strtoull(argv[0], &endptr, 10);
|
||||
if (*endptr || errno) {
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse group identifier: %s", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -335,9 +332,8 @@ static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
|
||||
|
||||
/* parse [<foreground>[<verbose>]] */
|
||||
if (argc) {
|
||||
errno = 0;
|
||||
_foreground = (int) strtol(argv[0], &endptr, 10);
|
||||
if (errno || *endptr) {
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse debug argument: %s.",
|
||||
argv[0]);
|
||||
return 0;
|
||||
@@ -345,9 +341,8 @@ static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
|
||||
argc--;
|
||||
argv++;
|
||||
if (argc) {
|
||||
errno = 0;
|
||||
_verbose = (int) strtol(argv[0], &endptr, 10);
|
||||
if (errno || *endptr) {
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse verbose "
|
||||
"argument: %s", argv[0]);
|
||||
return 0;
|
||||
@@ -667,11 +662,11 @@ static int _daemonise(struct filemap_monitor *fm)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* TODO: Use libdaemon/server/daemon-server.c _daemonise() */
|
||||
|
||||
for (fd = (int) sysconf(_SC_OPEN_MAX) - 1; fd > STDERR_FILENO; fd--) {
|
||||
if (fd == fm->fd)
|
||||
continue;
|
||||
(void) close(fd);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -714,8 +709,7 @@ static int _dmfilemapd(struct filemap_monitor *fm)
|
||||
* The correct program_id is retrieved from the group leader
|
||||
* following the call to dm_stats_list().
|
||||
*/
|
||||
if (!(dms = dm_stats_create(NULL)))
|
||||
goto_bad;
|
||||
dms = dm_stats_create(NULL);
|
||||
|
||||
if (!dm_stats_bind_from_fd(dms, fm->fd)) {
|
||||
log_error("Could not bind dm_stats handle to file descriptor "
|
||||
|
@@ -158,6 +158,5 @@ def _run_cmd(req):
|
||||
|
||||
|
||||
def cmd_runner(request):
|
||||
t = threading.Thread(target=_run_cmd, args=(request,),
|
||||
name="cmd_runner %s" % str(request.method))
|
||||
t = threading.Thread(target=_run_cmd, args=(request,))
|
||||
t.start()
|
||||
|
@@ -152,8 +152,7 @@ class StateUpdate(object):
|
||||
load(refresh=False, emit_signal=False, need_main_thread=False)
|
||||
|
||||
self.thread = threading.Thread(target=StateUpdate.update_thread,
|
||||
args=(self,),
|
||||
name="StateUpdate.update_thread")
|
||||
args=(self,))
|
||||
|
||||
def load(self, refresh=True, emit_signal=True, cache_refresh=True,
|
||||
log=True, need_main_thread=True):
|
||||
|
@@ -8,7 +8,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .automatedproperties import AutomatedProperties
|
||||
from .utils import job_obj_path_generate, mt_async_call
|
||||
from .utils import job_obj_path_generate, mt_async_result, mt_run_no_wait
|
||||
from . import cfg
|
||||
from .cfg import JOB_INTERFACE
|
||||
import dbus
|
||||
@@ -30,7 +30,7 @@ class WaitingClient(object):
|
||||
# Remove ourselves from waiting client
|
||||
wc.job_state.remove_waiting_client(wc)
|
||||
wc.timer_id = -1
|
||||
mt_async_call(wc.cb, wc.job_state.Complete)
|
||||
mt_async_result(wc.cb, wc.job_state.Complete)
|
||||
wc.job_state = None
|
||||
|
||||
def __init__(self, job_state, tmo, cb, cbe):
|
||||
@@ -55,7 +55,7 @@ class WaitingClient(object):
|
||||
GLib.source_remove(self.timer_id)
|
||||
self.timer_id = -1
|
||||
|
||||
mt_async_call(self.cb, self.job_state.Complete)
|
||||
mt_async_result(self.cb, self.job_state.Complete)
|
||||
self.job_state = None
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ class Job(AutomatedProperties):
|
||||
@Complete.setter
|
||||
def Complete(self, value):
|
||||
self.state.Complete = value
|
||||
mt_async_call(Job._signal_complete, self)
|
||||
mt_run_no_wait(Job._signal_complete, self)
|
||||
|
||||
@property
|
||||
def GetError(self):
|
||||
|
@@ -63,24 +63,6 @@ def check_bb_size(value):
|
||||
return v
|
||||
|
||||
|
||||
def install_signal_handlers():
|
||||
# Because of the glib main loop stuff the python signal handler code is
|
||||
# apparently not usable and we need to use the glib calls instead
|
||||
signal_add = None
|
||||
|
||||
if hasattr(GLib, 'unix_signal_add'):
|
||||
signal_add = GLib.unix_signal_add
|
||||
elif hasattr(GLib, 'unix_signal_add_full'):
|
||||
signal_add = GLib.unix_signal_add_full
|
||||
|
||||
if signal_add:
|
||||
signal_add(GLib.PRIORITY_HIGH, signal.SIGHUP, utils.handler, signal.SIGHUP)
|
||||
signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, utils.handler, signal.SIGINT)
|
||||
signal_add(GLib.PRIORITY_HIGH, signal.SIGUSR1, utils.handler, signal.SIGUSR1)
|
||||
else:
|
||||
log_error("GLib.unix_signal_[add|add_full] are NOT available!")
|
||||
|
||||
|
||||
def main():
|
||||
start = time.time()
|
||||
# Add simple command line handling
|
||||
@@ -130,7 +112,12 @@ def main():
|
||||
# List of threads that we start up
|
||||
thread_list = []
|
||||
|
||||
install_signal_handlers()
|
||||
# Install signal handlers
|
||||
for s in [signal.SIGHUP, signal.SIGINT]:
|
||||
try:
|
||||
signal.signal(s, utils.handler)
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
dbus.mainloop.glib.threads_init()
|
||||
@@ -151,8 +138,7 @@ def main():
|
||||
|
||||
# Using a thread to process requests, we cannot hang the dbus library
|
||||
# thread that is handling the dbus interface
|
||||
thread_list.append(threading.Thread(target=process_request,
|
||||
name='process_request'))
|
||||
thread_list.append(threading.Thread(target=process_request))
|
||||
|
||||
# Have a single thread handling updating lvm and the dbus model so we
|
||||
# don't have multiple threads doing this as the same time
|
||||
@@ -190,7 +176,5 @@ def main():
|
||||
for thread in thread_list:
|
||||
thread.join()
|
||||
except KeyboardInterrupt:
|
||||
# If we are unable to register signal handler, we will end up here when
|
||||
# the service gets a ^C or a kill -2 <parent pid>
|
||||
utils.handler(signal.SIGINT)
|
||||
utils.handler(signal.SIGINT, None)
|
||||
return 0
|
||||
|
@@ -79,9 +79,7 @@ class PvState(State):
|
||||
|
||||
self.lv = self._lv_object_list(vg_name)
|
||||
|
||||
# It's possible to have a vg_name and no uuid with the main example
|
||||
# being when the vg_name == '[unknown]'
|
||||
if vg_uuid and vg_name:
|
||||
if vg_name:
|
||||
self.vg_path = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
vg_uuid, vg_name, vg_obj_path_generate)
|
||||
else:
|
||||
|
@@ -13,7 +13,7 @@ from gi.repository import GLib
|
||||
from .job import Job
|
||||
from . import cfg
|
||||
import traceback
|
||||
from .utils import log_error, mt_async_call
|
||||
from .utils import log_error, mt_async_result
|
||||
|
||||
|
||||
class RequestEntry(object):
|
||||
@@ -116,9 +116,9 @@ class RequestEntry(object):
|
||||
if error_rc == 0:
|
||||
if self.cb:
|
||||
if self._return_tuple:
|
||||
mt_async_call(self.cb, (result, '/'))
|
||||
mt_async_result(self.cb, (result, '/'))
|
||||
else:
|
||||
mt_async_call(self.cb, result)
|
||||
mt_async_result(self.cb, result)
|
||||
else:
|
||||
if self.cb_error:
|
||||
if not error_exception:
|
||||
@@ -129,7 +129,7 @@ class RequestEntry(object):
|
||||
else:
|
||||
error_exception = Exception(error_msg)
|
||||
|
||||
mt_async_call(self.cb_error, error_exception)
|
||||
mt_async_result(self.cb_error, error_exception)
|
||||
else:
|
||||
# We have a job and it's complete, indicate that it's done.
|
||||
self._job.Complete = True
|
||||
|
@@ -20,8 +20,7 @@ from lvmdbusd import cfg
|
||||
# noinspection PyUnresolvedReferences
|
||||
from gi.repository import GLib
|
||||
import threading
|
||||
import traceback
|
||||
import signal
|
||||
|
||||
|
||||
STDOUT_TTY = os.isatty(sys.stdout.fileno())
|
||||
|
||||
@@ -282,47 +281,12 @@ def log_error(msg, *attributes):
|
||||
_common_log(msg, *attributes)
|
||||
|
||||
|
||||
def dump_threads_stackframe():
|
||||
ident_to_name = {}
|
||||
|
||||
for thread_object in threading.enumerate():
|
||||
ident_to_name[thread_object.ident] = thread_object
|
||||
|
||||
stacks = []
|
||||
for thread_ident, frame in sys._current_frames().items():
|
||||
stack = traceback.format_list(traceback.extract_stack(frame))
|
||||
|
||||
# There is a possibility that a thread gets created after we have
|
||||
# enumerated all threads, so this lookup table may be incomplete, so
|
||||
# account for this
|
||||
if thread_ident in ident_to_name:
|
||||
thread_name = ident_to_name[thread_ident].name
|
||||
else:
|
||||
thread_name = "unknown"
|
||||
|
||||
stacks.append("Thread: %s" % (thread_name))
|
||||
stacks.append("".join(stack))
|
||||
|
||||
log_error("Dumping thread stack frames!\n" + "\n".join(stacks))
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
def handler(signum):
|
||||
try:
|
||||
if signum == signal.SIGUSR1:
|
||||
dump_threads_stackframe()
|
||||
else:
|
||||
cfg.run.value = 0
|
||||
log_debug('Exiting daemon with signal %d' % signum)
|
||||
if cfg.loop is not None:
|
||||
cfg.loop.quit()
|
||||
except:
|
||||
st = traceback.format_exc()
|
||||
log_error("signal handler: exception (logged, not reported!) \n %s" % st)
|
||||
|
||||
# It's important we report that we handled the exception for the exception
|
||||
# handler to continue to work, especially for signal 10 (SIGUSR1)
|
||||
return True
|
||||
def handler(signum, frame):
|
||||
cfg.run.value = 0
|
||||
log_debug('Signal handler called with signal %d' % signum)
|
||||
if cfg.loop is not None:
|
||||
cfg.loop.quit()
|
||||
|
||||
|
||||
def pv_obj_path_generate():
|
||||
@@ -570,27 +534,21 @@ def add_no_notify(cmdline):
|
||||
# ensure all dbus library interaction is done from the same thread!
|
||||
|
||||
|
||||
def _async_handler(call_back, parameters):
|
||||
params_str = ", ".join(str(x) for x in parameters)
|
||||
log_debug('Main thread execution, callback = %s, parameters = (%s)' %
|
||||
(str(call_back), params_str))
|
||||
|
||||
try:
|
||||
if parameters:
|
||||
call_back(*parameters)
|
||||
else:
|
||||
call_back()
|
||||
except:
|
||||
st = traceback.format_exc()
|
||||
log_error("mt_async_call: exception (logged, not reported!) \n %s" % st)
|
||||
def _async_result(call_back, results):
|
||||
log_debug('Results = %s' % str(results))
|
||||
call_back(results)
|
||||
|
||||
|
||||
# Execute the function on the main thread with the provided parameters, do
|
||||
# not return *any* value or wait for the execution to complete!
|
||||
def mt_async_call(function_call_back, *parameters):
|
||||
GLib.idle_add(_async_handler, function_call_back, parameters)
|
||||
# Return result in main thread
|
||||
def mt_async_result(call_back, results):
|
||||
GLib.idle_add(_async_result, call_back, results)
|
||||
|
||||
|
||||
# Take the supplied function and run it on the main thread and not wait for
|
||||
# a result!
|
||||
def mt_run_no_wait(function, param):
|
||||
GLib.idle_add(function, param)
|
||||
|
||||
# Run the supplied function and arguments on the main thread and wait for them
|
||||
# to complete while allowing the ability to get the return value too.
|
||||
#
|
||||
@@ -610,7 +568,6 @@ class MThreadRunner(object):
|
||||
def __init__(self, function, *args):
|
||||
self.f = function
|
||||
self.rc = None
|
||||
self.exception = None
|
||||
self.args = args
|
||||
self.function_complete = False
|
||||
self.cond = threading.Condition(threading.Lock())
|
||||
@@ -620,21 +577,13 @@ class MThreadRunner(object):
|
||||
with self.cond:
|
||||
if not self.function_complete:
|
||||
self.cond.wait()
|
||||
if self.exception:
|
||||
raise self.exception
|
||||
return self.rc
|
||||
|
||||
def _run(self):
|
||||
try:
|
||||
if self.args:
|
||||
self.rc = self.f(*self.args)
|
||||
else:
|
||||
self.rc = self.f()
|
||||
except BaseException as be:
|
||||
self.exception = be
|
||||
st = traceback.format_exc()
|
||||
log_error("MThreadRunner: exception \n %s" % st)
|
||||
log_error("Exception will be raised in calling thread!")
|
||||
if len(self.args):
|
||||
self.rc = self.f(*self.args)
|
||||
else:
|
||||
self.rc = self.f()
|
||||
|
||||
|
||||
def _remove_objects(dbus_objects_rm):
|
||||
|
@@ -16,7 +16,7 @@ top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SOURCES = lvmetad-core.c
|
||||
SOURCES2 = lvmetactl.c
|
||||
SOURCES2 = testclient.c
|
||||
|
||||
TARGETS = lvmetad lvmetactl
|
||||
|
||||
@@ -28,19 +28,22 @@ CFLOW_TARGET = lvmetad
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
CFLAGS_lvmetactl.o += $(EXTRA_EXEC_CFLAGS)
|
||||
CFLAGS_lvmetad-core.o += $(EXTRA_EXEC_CFLAGS)
|
||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(RT_LIBS) $(DAEMON_LIBS) -ldevmapper $(PTHREAD_LIBS)
|
||||
LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
|
||||
|
||||
LIBS += $(PTHREAD_LIBS)
|
||||
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS)
|
||||
CLDFLAGS += -L$(top_builddir)/libdaemon/server
|
||||
CFLAGS += $(EXTRA_EXEC_CFLAGS)
|
||||
|
||||
lvmetad: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) -ldaemonserver $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LVMLIBS) $(LIBS)
|
||||
|
||||
lvmetactl: lvmetactl.o $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmetactl.o $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmetactl.o $(LVMLIBS)
|
||||
|
||||
CLEAN_TARGETS += lvmetactl.o
|
||||
|
||||
|
@@ -258,21 +258,6 @@ static void destroy_metadata_hashes(lvmetad_state *s)
|
||||
dm_hash_iterate(n, s->pvid_to_pvmeta)
|
||||
dm_config_destroy(dm_hash_get_data(s->pvid_to_pvmeta, n));
|
||||
|
||||
dm_hash_iterate(n, s->vgid_to_vgname)
|
||||
dm_free(dm_hash_get_data(s->vgid_to_vgname, n));
|
||||
|
||||
dm_hash_iterate(n, s->vgname_to_vgid)
|
||||
dm_free(dm_hash_get_data(s->vgname_to_vgid, n));
|
||||
|
||||
dm_hash_iterate(n, s->vgid_to_info)
|
||||
dm_free(dm_hash_get_data(s->vgid_to_info, n));
|
||||
|
||||
dm_hash_iterate(n, s->device_to_pvid)
|
||||
dm_free(dm_hash_get_data(s->device_to_pvid, n));
|
||||
|
||||
dm_hash_iterate(n, s->pvid_to_vgid)
|
||||
dm_free(dm_hash_get_data(s->pvid_to_vgid, n));
|
||||
|
||||
dm_hash_destroy(s->pvid_to_pvmeta);
|
||||
dm_hash_destroy(s->vgid_to_metadata);
|
||||
dm_hash_destroy(s->vgid_to_vgname);
|
||||
@@ -808,8 +793,7 @@ static int _update_pvid_to_vgid(lvmetad_state *s, struct dm_config_tree *vg,
|
||||
|
||||
if ((mode == REMOVE_EMPTY) && vgid_old) {
|
||||
/* This copies the vgid_old string, doesn't reference it. */
|
||||
if ((dm_hash_lookup(to_check, vgid_old) != (void*) 1) &&
|
||||
!dm_hash_insert(to_check, vgid_old, (void*) 1)) {
|
||||
if (!dm_hash_insert(to_check, vgid_old, (void*) 1)) {
|
||||
ERROR(s, "update_pvid_to_vgid out of memory for hash insert vgid_old %s", vgid_old);
|
||||
goto abort_daemon;
|
||||
}
|
||||
@@ -885,13 +869,16 @@ static int remove_metadata(lvmetad_state *s, const char *vgid, int update_pvids)
|
||||
|
||||
/* free the unmapped data */
|
||||
|
||||
if (info_lookup)
|
||||
dm_free(info_lookup);
|
||||
if (meta_lookup)
|
||||
dm_config_destroy(meta_lookup);
|
||||
if (name_lookup)
|
||||
dm_free(name_lookup);
|
||||
if (outdated_pvs_lookup)
|
||||
dm_config_destroy(outdated_pvs_lookup);
|
||||
dm_free(info_lookup);
|
||||
dm_free(name_lookup);
|
||||
dm_free(vgid_lookup);
|
||||
if (vgid_lookup)
|
||||
dm_free(vgid_lookup);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1218,8 +1205,10 @@ static int _update_metadata_add_new(lvmetad_state *s, const char *new_name, cons
|
||||
out:
|
||||
out_free:
|
||||
if (!new_name_dup || !new_vgid_dup || abort_daemon) {
|
||||
dm_free(new_name_dup);
|
||||
dm_free(new_vgid_dup);
|
||||
if (new_name_dup)
|
||||
dm_free(new_name_dup);
|
||||
if (new_vgid_dup)
|
||||
dm_free(new_vgid_dup);
|
||||
ERROR(s, "lvmetad could not be updated and is aborting.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -1809,7 +1798,8 @@ static response pv_gone(lvmetad_state *s, request r)
|
||||
}
|
||||
|
||||
dm_config_destroy(pvmeta);
|
||||
dm_free(old_pvid);
|
||||
if (old_pvid)
|
||||
dm_free(old_pvid);
|
||||
|
||||
return daemon_reply_simple("OK", NULL );
|
||||
}
|
||||
@@ -1922,7 +1912,7 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
const char *arg_pvid = NULL;
|
||||
const char *arg_pvid_lookup = NULL;
|
||||
const char *new_pvid = NULL;
|
||||
char *new_pvid_dup = NULL;
|
||||
const char *new_pvid_dup = NULL;
|
||||
const char *arg_name = NULL;
|
||||
const char *arg_vgid = NULL;
|
||||
const char *arg_vgid_lookup = NULL;
|
||||
@@ -2085,7 +2075,7 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
if (!(new_pvid_dup = dm_strdup(new_pvid)))
|
||||
goto nomem_free1;
|
||||
|
||||
if (!dm_hash_insert_binary(s->device_to_pvid, &new_device, sizeof(new_device), new_pvid_dup))
|
||||
if (!dm_hash_insert_binary(s->device_to_pvid, &new_device, sizeof(new_device), (char *)new_pvid_dup))
|
||||
goto nomem_free2;
|
||||
|
||||
if (!dm_hash_insert(s->pvid_to_pvmeta, new_pvid, new_pvmeta))
|
||||
@@ -2121,8 +2111,6 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
DEBUGLOG(s, "pv_found ignore duplicate device %" PRIu64 " of existing PV for pvid %s",
|
||||
arg_device, arg_pvid);
|
||||
dm_config_destroy(new_pvmeta);
|
||||
/* device_to_pvid no longer references prev_pvid_lookup */
|
||||
dm_free((void*)prev_pvid_on_dev);
|
||||
s->flags |= GLFL_DISABLE;
|
||||
s->flags |= GLFL_DISABLE_REASON_DUPLICATES;
|
||||
return reply_fail("Ignore duplicate PV");
|
||||
@@ -2133,7 +2121,7 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
if (!(new_pvid_dup = dm_strdup(new_pvid)))
|
||||
goto nomem_free1;
|
||||
|
||||
if (!dm_hash_insert_binary(s->device_to_pvid, &arg_device, sizeof(arg_device), new_pvid_dup))
|
||||
if (!dm_hash_insert_binary(s->device_to_pvid, &arg_device, sizeof(arg_device), (char *)new_pvid_dup))
|
||||
goto nomem_free2;
|
||||
|
||||
if (!dm_hash_insert(s->pvid_to_pvmeta, new_pvid, new_pvmeta))
|
||||
@@ -2233,7 +2221,8 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
}
|
||||
|
||||
/* This was unhashed from device_to_pvid above. */
|
||||
dm_free((void *)prev_pvid_on_dev);
|
||||
if (prev_pvid_on_dev)
|
||||
dm_free((void *)prev_pvid_on_dev);
|
||||
|
||||
return daemon_reply_simple("OK",
|
||||
"status = %s", vg_status,
|
||||
@@ -2245,7 +2234,7 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
NULL);
|
||||
|
||||
nomem_free2:
|
||||
dm_free(new_pvid_dup);
|
||||
dm_free((char *)new_pvid_dup);
|
||||
nomem_free1:
|
||||
dm_config_destroy(new_pvmeta);
|
||||
nomem:
|
||||
@@ -2572,12 +2561,14 @@ static void _dump_pairs(struct buffer *buf, struct dm_hash_table *ht, const char
|
||||
dm_hash_iterate(n, ht) {
|
||||
const char *key = dm_hash_get_key(ht, n),
|
||||
*val = dm_hash_get_data(ht, n);
|
||||
buffer_append(buf, " ");
|
||||
if (int_key)
|
||||
(void) dm_asprintf(&append, " %d = \"%s\"\n", *(const int*)key, val);
|
||||
(void) dm_asprintf(&append, "%d = \"%s\"", *(const int*)key, val);
|
||||
else
|
||||
(void) dm_asprintf(&append, " %s = \"%s\"\n", key, val);
|
||||
(void) dm_asprintf(&append, "%s = \"%s\"", key, val);
|
||||
if (append)
|
||||
buffer_append(buf, append);
|
||||
buffer_append(buf, "\n");
|
||||
dm_free(append);
|
||||
}
|
||||
buffer_append(buf, "}\n");
|
||||
@@ -2595,9 +2586,11 @@ static void _dump_info_version(struct buffer *buf, struct dm_hash_table *ht, con
|
||||
while (n) {
|
||||
const char *key = dm_hash_get_key(ht, n);
|
||||
info = dm_hash_get_data(ht, n);
|
||||
(void) dm_asprintf(&append, " %s = %lld\n", key, (long long)info->external_version);
|
||||
buffer_append(buf, " ");
|
||||
(void) dm_asprintf(&append, "%s = %lld", key, (long long)info->external_version);
|
||||
if (append)
|
||||
buffer_append(buf, append);
|
||||
buffer_append(buf, "\n");
|
||||
dm_free(append);
|
||||
n = dm_hash_get_next(ht, n);
|
||||
}
|
||||
@@ -2616,9 +2609,11 @@ static void _dump_info_flags(struct buffer *buf, struct dm_hash_table *ht, const
|
||||
while (n) {
|
||||
const char *key = dm_hash_get_key(ht, n);
|
||||
info = dm_hash_get_data(ht, n);
|
||||
(void) dm_asprintf(&append, " %s = %llx\n", key, (long long)info->flags);
|
||||
buffer_append(buf, " ");
|
||||
(void) dm_asprintf(&append, "%s = %llx", key, (long long)info->flags);
|
||||
if (append)
|
||||
buffer_append(buf, append);
|
||||
buffer_append(buf, "\n");
|
||||
dm_free(append);
|
||||
n = dm_hash_get_next(ht, n);
|
||||
}
|
||||
|
@@ -19,12 +19,10 @@ SOURCES = lvmlockd-core.c
|
||||
|
||||
ifeq ("@BUILD_LOCKDSANLOCK@", "yes")
|
||||
SOURCES += lvmlockd-sanlock.c
|
||||
LOCK_LIBS += -lsanlock_client
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_LOCKDDLM@", "yes")
|
||||
SOURCES += lvmlockd-dlm.c
|
||||
LOCK_LIBS += -ldlm_lt
|
||||
endif
|
||||
|
||||
TARGETS = lvmlockd lvmlockctl
|
||||
@@ -33,17 +31,29 @@ TARGETS = lvmlockd lvmlockctl
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
CFLAGS += $(EXTRA_EXEC_CFLAGS)
|
||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(RT_LIBS) $(DAEMON_LIBS) -ldevmapper $(PTHREAD_LIBS)
|
||||
LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
|
||||
|
||||
LIBS += $(PTHREAD_LIBS)
|
||||
|
||||
ifeq ("@BUILD_LOCKDSANLOCK@", "yes")
|
||||
LIBS += -lsanlock_client
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_LOCKDDLM@", "yes")
|
||||
LIBS += -ldlm_lt
|
||||
endif
|
||||
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server
|
||||
CLDFLAGS += -L$(top_builddir)/libdaemon/server
|
||||
|
||||
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LOCK_LIBS) -ldaemonserver $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LVMLIBS) $(LIBS)
|
||||
|
||||
lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(LIBS)
|
||||
lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(LVMLIBS)
|
||||
|
||||
install_lvmlockd: lvmlockd
|
||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
@@ -379,7 +379,7 @@ static int setup_dump_socket(void)
|
||||
rv = bind(s, (struct sockaddr *) &dump_addr, dump_addrlen);
|
||||
if (rv < 0) {
|
||||
rv = -errno;
|
||||
if (close(s))
|
||||
if (!close(s))
|
||||
log_error("failed to close dump socket");
|
||||
return rv;
|
||||
}
|
||||
|
@@ -48,6 +48,5 @@ static inline void lvmlockd_close(daemon_handle h)
|
||||
#define EVGKILLED 217 /* sanlock lost access to leases and VG is killed. */
|
||||
#define ELOCKIO 218 /* sanlock io errors during lock op, may be transient. */
|
||||
#define EREMOVED 219
|
||||
#define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */
|
||||
|
||||
#endif /* _LVM_LVMLOCKD_CLIENT_H */
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#include "lvm-version.h"
|
||||
#include "lvmetad-client.h"
|
||||
#include "lvmlockd-client.h"
|
||||
#include "dm-ioctl.h" /* for DM_UUID_LEN */
|
||||
|
||||
/* #include <assert.h> */
|
||||
#include <errno.h>
|
||||
@@ -2652,16 +2651,10 @@ out_act:
|
||||
ls->drop_vg = drop_vg;
|
||||
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
|
||||
global_dlm_lockspace_exists = 0;
|
||||
|
||||
/*
|
||||
* Avoid a name collision of the same lockspace is added again before
|
||||
* this thread is cleaned up. We just set ls->name to a "junk" value
|
||||
* for the short period until the struct is freed. We could make it
|
||||
* 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.
|
||||
*/
|
||||
dm_strncpy(tmp_name, ls->name, sizeof(tmp_name));
|
||||
snprintf(ls->name, sizeof(ls->name), "REM:%s", tmp_name);
|
||||
/* Avoid a name collision of the same lockspace is added again before this thread is cleaned up. */
|
||||
memset(tmp_name, 0, sizeof(tmp_name));
|
||||
snprintf(tmp_name, MAX_NAME, "REM:%s", ls->name);
|
||||
memcpy(ls->name, tmp_name, MAX_NAME);
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
|
||||
/* worker_thread will join this thread, and free the ls */
|
||||
@@ -3310,6 +3303,7 @@ static int work_init_lv(struct action *act)
|
||||
lm_type = ls->lm_type;
|
||||
memcpy(vg_args, ls->vg_args, MAX_ARGS);
|
||||
free_offset = ls->free_lock_offset;
|
||||
ls->free_lock_offset = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
|
||||
@@ -3539,15 +3533,11 @@ static int setup_worker_thread(void)
|
||||
|
||||
static void close_worker_thread(void)
|
||||
{
|
||||
int perrno;
|
||||
|
||||
pthread_mutex_lock(&worker_mutex);
|
||||
worker_stop = 1;
|
||||
pthread_cond_signal(&worker_cond);
|
||||
pthread_mutex_unlock(&worker_mutex);
|
||||
|
||||
if ((perrno = pthread_join(worker_thread, NULL)))
|
||||
log_error("pthread_join worker_thread error %d", perrno);
|
||||
pthread_join(worker_thread, NULL);
|
||||
}
|
||||
|
||||
/* client_mutex is locked */
|
||||
@@ -3676,17 +3666,7 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
if (!gl_lsname_dlm[0])
|
||||
strcat(result_flags, "NO_GL_LS,");
|
||||
} else {
|
||||
int found_lm = 0;
|
||||
|
||||
if (lm_support_dlm() && lm_is_running_dlm())
|
||||
found_lm++;
|
||||
if (lm_support_sanlock() && lm_is_running_sanlock())
|
||||
found_lm++;
|
||||
|
||||
if (!found_lm)
|
||||
strcat(result_flags, "NO_GL_LS,NO_LM");
|
||||
else
|
||||
strcat(result_flags, "NO_GL_LS");
|
||||
strcat(result_flags, "NO_GL_LS,");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3783,8 +3763,7 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
if (dump_fd >= 0) {
|
||||
/* To avoid deadlock, send data here after the reply. */
|
||||
send_dump_buf(dump_fd, dump_len);
|
||||
if (close(dump_fd))
|
||||
log_error("failed to close dump socket %d", dump_fd);
|
||||
close(dump_fd);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -3857,9 +3836,8 @@ static int add_lock_action(struct action *act)
|
||||
pthread_mutex_lock(&lockspaces_mutex);
|
||||
if (ls_name[0])
|
||||
ls = find_lockspace_name(ls_name);
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
if (!ls) {
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
|
||||
if (act->op == LD_OP_UPDATE && act->rt == LD_RT_VG) {
|
||||
log_debug("lockspace \"%s\" not found ignored for vg update", ls_name);
|
||||
return -ENOLS;
|
||||
@@ -4776,8 +4754,8 @@ static void *client_thread_main(void *arg_in)
|
||||
} else {
|
||||
pthread_mutex_unlock(&cl->mutex);
|
||||
}
|
||||
} else
|
||||
pthread_mutex_unlock(&client_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&client_mutex);
|
||||
}
|
||||
out:
|
||||
return NULL;
|
||||
@@ -4801,15 +4779,11 @@ static int setup_client_thread(void)
|
||||
|
||||
static void close_client_thread(void)
|
||||
{
|
||||
int perrno;
|
||||
|
||||
pthread_mutex_lock(&client_mutex);
|
||||
client_stop = 1;
|
||||
pthread_cond_signal(&client_cond);
|
||||
pthread_mutex_unlock(&client_mutex);
|
||||
|
||||
if ((perrno = pthread_join(client_thread, NULL)))
|
||||
log_error("pthread_join client_thread error %d", perrno);
|
||||
pthread_join(client_thread, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4933,10 +4907,14 @@ static int get_lockd_vgs(struct list_head *vg_lockd)
|
||||
continue;
|
||||
|
||||
for (lv_cn = md_cn->child; lv_cn; lv_cn = lv_cn->sib) {
|
||||
snprintf(find_str_path, PATH_MAX, "%s/lock_type", lv_cn->key);
|
||||
lock_type = dm_config_find_str(lv_cn, find_str_path, NULL);
|
||||
|
||||
if (!lock_type)
|
||||
continue;
|
||||
|
||||
snprintf(find_str_path, PATH_MAX, "%s/lock_args", lv_cn->key);
|
||||
lock_args = dm_config_find_str(lv_cn, find_str_path, NULL);
|
||||
if (!lock_args)
|
||||
continue;
|
||||
|
||||
snprintf(find_str_path, PATH_MAX, "%s/id", lv_cn->key);
|
||||
lv_uuid = dm_config_find_str(lv_cn, find_str_path, NULL);
|
||||
@@ -4982,7 +4960,7 @@ out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static char _dm_uuid[DM_UUID_LEN];
|
||||
static char _dm_uuid[64];
|
||||
|
||||
static char *get_dm_uuid(char *dm_name)
|
||||
{
|
||||
@@ -5201,17 +5179,20 @@ static void adopt_locks(void)
|
||||
* Get list of lockspaces from lock managers.
|
||||
* Get list of VGs from lvmetad with a lockd type.
|
||||
* Get list of active lockd type LVs from /dev.
|
||||
*
|
||||
* ECONNREFUSED means the lock manager is not running.
|
||||
* This is expected for at least one of them.
|
||||
*/
|
||||
|
||||
if (lm_support_dlm() && lm_is_running_dlm()) {
|
||||
if (lm_support_dlm()) {
|
||||
rv = lm_get_lockspaces_dlm(&ls_found);
|
||||
if (rv < 0)
|
||||
if ((rv < 0) && (rv != -ECONNREFUSED))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (lm_support_sanlock() && lm_is_running_sanlock()) {
|
||||
if (lm_support_sanlock()) {
|
||||
rv = lm_get_lockspaces_sanlock(&ls_found);
|
||||
if (rv < 0)
|
||||
if ((rv < 0) && (rv != -ECONNREFUSED))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -5288,7 +5269,7 @@ static void adopt_locks(void)
|
||||
list_for_each_entry_safe(ls1, l1safe, &ls_found, list) {
|
||||
|
||||
/* The dlm global lockspace is special and doesn't match a VG. */
|
||||
if ((ls1->lm_type == LD_LM_DLM) && !strcmp(ls1->name, gl_lsname_dlm)) {
|
||||
if (!strcmp(ls1->name, gl_lsname_dlm)) {
|
||||
list_del(&ls1->list);
|
||||
free(ls1);
|
||||
continue;
|
||||
|
@@ -224,10 +224,7 @@ static int lock_lv_offset_from_args(char *lv_args, uint64_t *lock_lv_offset)
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
errno = 0;
|
||||
*lock_lv_offset = strtoull(offset_str, NULL, 10);
|
||||
if (errno)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -356,19 +353,12 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
||||
log_debug("sanlock daemon version %08x proto %08x",
|
||||
daemon_version, daemon_proto);
|
||||
|
||||
rv = sanlock_align(&disk);
|
||||
if (rv <= 0) {
|
||||
if (rv == -EACCES) {
|
||||
log_error("S %s init_vg_san sanlock error -EACCES: no permission to access %s",
|
||||
ls_name, disk.path);
|
||||
return -EDEVOPEN;
|
||||
} else {
|
||||
log_error("S %s init_vg_san sanlock error %d trying to get align size of %s",
|
||||
ls_name, rv, disk.path);
|
||||
return -EARGS;
|
||||
}
|
||||
} else
|
||||
align_size = rv;
|
||||
align_size = sanlock_align(&disk);
|
||||
if (align_size <= 0) {
|
||||
log_error("S %s init_vg_san bad disk align size %d %s",
|
||||
ls_name, align_size, disk.path);
|
||||
return -EARGS;
|
||||
}
|
||||
|
||||
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
|
||||
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
|
||||
@@ -945,9 +935,7 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
|
||||
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
|
||||
struct sanlk_resourced rd;
|
||||
uint64_t offset;
|
||||
uint64_t start_offset;
|
||||
int rv;
|
||||
int round = 0;
|
||||
|
||||
if (daemon_test) {
|
||||
*free_offset = (1048576 * LV_LOCK_BEGIN) + (1048576 * (daemon_test_lv_count + 1));
|
||||
@@ -960,22 +948,9 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
|
||||
rd.rs.num_disks = 1;
|
||||
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
|
||||
|
||||
if (ls->free_lock_offset)
|
||||
offset = ls->free_lock_offset;
|
||||
else
|
||||
offset = lms->align_size * LV_LOCK_BEGIN;
|
||||
|
||||
start_offset = offset;
|
||||
offset = lms->align_size * LV_LOCK_BEGIN;
|
||||
|
||||
while (1) {
|
||||
if (offset >= start_offset && round) {
|
||||
/* This indicates the all space are allocated. */
|
||||
log_debug("S %s init_lv_san read back to start offset %llu",
|
||||
ls->name, (unsigned long long)offset);
|
||||
rv = -EMSGSIZE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rd.rs.disks[0].offset = offset;
|
||||
|
||||
memset(rd.rs.name, 0, SANLK_NAME_LEN);
|
||||
@@ -985,14 +960,7 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
|
||||
/* This indicates the end of the device is reached. */
|
||||
log_debug("S %s find_free_lock_san read limit offset %llu",
|
||||
ls->name, (unsigned long long)offset);
|
||||
|
||||
/* remember the NO SPACE offset, if no free area left,
|
||||
* search from this offset after extend */
|
||||
*free_offset = offset;
|
||||
|
||||
offset = lms->align_size * LV_LOCK_BEGIN;
|
||||
round = 1;
|
||||
continue;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -27,14 +27,18 @@ CFLOW_TARGET = lvmpolld
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
CFLAGS += $(EXTRA_EXEC_CFLAGS)
|
||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(DAEMON_LIBS) -ldaemonserver -ldevmapper $(PTHREAD_LIBS)
|
||||
LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
|
||||
|
||||
LIBS += $(PTHREAD_LIBS)
|
||||
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(DAEMON_LDFLAGS)
|
||||
CLDFLAGS += -L$(top_builddir)/libdaemon/server
|
||||
CFLAGS += $(DAEMON_CFLAGS)
|
||||
|
||||
lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LVMLIBS) $(LIBS)
|
||||
|
||||
install_lvmpolld: lvmpolld
|
||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
@@ -207,10 +207,6 @@ Optional feature arguments are:
|
||||
block, then the cache block is invalidated.
|
||||
To enable passthrough mode the cache must be clean.
|
||||
|
||||
metadata2 : use version 2 of the metadata. This stores the dirty bits
|
||||
in a separate btree, which improves speed of shutting
|
||||
down the cache.
|
||||
|
||||
A policy called 'default' is always registered. This is an alias for
|
||||
the policy we currently think is giving best all round performance.
|
||||
|
||||
@@ -290,7 +286,7 @@ message, which takes an arbitrary number of cblock ranges. Each cblock
|
||||
range's end value is "one past the end", meaning 5-10 expresses a range
|
||||
of values from 5 to 9. Each cblock must be expressed as a decimal
|
||||
value, in the future a variant message that takes cblock ranges
|
||||
expressed in hexadecimal may be needed to better support efficient
|
||||
expressed in hexidecimal may be needed to better support efficient
|
||||
invalidation of larger caches. The cache must be in passthrough mode
|
||||
when invalidate_cblocks is used.
|
||||
|
||||
|
@@ -11,57 +11,23 @@ Parameters: <cipher> <key> <iv_offset> <device path> \
|
||||
<offset> [<#opt_params> <opt_params>]
|
||||
|
||||
<cipher>
|
||||
Encryption cipher, encryption mode and Initial Vector (IV) generator.
|
||||
|
||||
The cipher specifications format is:
|
||||
cipher[:keycount]-chainmode-ivmode[:ivopts]
|
||||
Encryption cipher and an optional IV generation mode.
|
||||
(In format cipher[:keycount]-chainmode-ivmode[:ivopts]).
|
||||
Examples:
|
||||
des
|
||||
aes-cbc-essiv:sha256
|
||||
aes-xts-plain64
|
||||
serpent-xts-plain64
|
||||
twofish-ecb
|
||||
|
||||
Cipher format also supports direct specification with kernel crypt API
|
||||
format (selected by capi: prefix). The IV specification is the same
|
||||
as for the first format type.
|
||||
This format is mainly used for specification of authenticated modes.
|
||||
|
||||
The crypto API cipher specifications format is:
|
||||
capi:cipher_api_spec-ivmode[:ivopts]
|
||||
Examples:
|
||||
capi:cbc(aes)-essiv:sha256
|
||||
capi:xts(aes)-plain64
|
||||
Examples of authenticated modes:
|
||||
capi:gcm(aes)-random
|
||||
capi:authenc(hmac(sha256),xts(aes))-random
|
||||
capi:rfc7539(chacha20,poly1305)-random
|
||||
|
||||
The /proc/crypto contains a list of curently loaded crypto modes.
|
||||
/proc/crypto contains supported crypto modes
|
||||
|
||||
<key>
|
||||
Key used for encryption. It is encoded either as a hexadecimal number
|
||||
or it can be passed as <key_string> prefixed with single colon
|
||||
character (':') for keys residing in kernel keyring service.
|
||||
Key used for encryption. It is encoded as a hexadecimal number.
|
||||
You can only use key sizes that are valid for the selected cipher
|
||||
in combination with the selected iv mode.
|
||||
Note that for some iv modes the key string can contain additional
|
||||
keys (for example IV seed) so the key contains more parts concatenated
|
||||
into a single string.
|
||||
|
||||
<key_string>
|
||||
The kernel keyring key is identified by string in following format:
|
||||
<key_size>:<key_type>:<key_description>.
|
||||
|
||||
<key_size>
|
||||
The encryption key size in bytes. The kernel key payload size must match
|
||||
the value passed in <key_size>.
|
||||
|
||||
<key_type>
|
||||
Either 'logon' or 'user' kernel key type.
|
||||
|
||||
<key_description>
|
||||
The kernel keyring key description crypt target should look for
|
||||
when loading key of <key_type>.
|
||||
|
||||
<keycount>
|
||||
Multi-key compatibility mode. You can define <keycount> keys and
|
||||
then sectors are encrypted according to their offsets (sector 0 uses key0;
|
||||
@@ -110,32 +76,6 @@ submit_from_crypt_cpus
|
||||
thread because it benefits CFQ to have writes submitted using the
|
||||
same context.
|
||||
|
||||
integrity:<bytes>:<type>
|
||||
The device requires additional <bytes> metadata per-sector stored
|
||||
in per-bio integrity structure. This metadata must by provided
|
||||
by underlying dm-integrity target.
|
||||
|
||||
The <type> can be "none" if metadata is used only for persistent IV.
|
||||
|
||||
For Authenticated Encryption with Additional Data (AEAD)
|
||||
the <type> is "aead". An AEAD mode additionally calculates and verifies
|
||||
integrity for the encrypted device. The additional space is then
|
||||
used for storing authentication tag (and persistent IV if needed).
|
||||
|
||||
sector_size:<bytes>
|
||||
Use <bytes> as the encryption unit instead of 512 bytes sectors.
|
||||
This option can be in range 512 - 4096 bytes and must be power of two.
|
||||
Virtual device will announce this size as a minimal IO and logical sector.
|
||||
|
||||
iv_large_sectors
|
||||
IV generators will use sector number counted in <sector_size> units
|
||||
instead of default 512 bytes sectors.
|
||||
|
||||
For example, if <sector_size> is 4096 bytes, plain64 IV for the second
|
||||
sector will be 8 (without flag) and 1 if iv_large_sectors is present.
|
||||
The <iv_offset> must be multiple of <sector_size> (in 512 bytes units)
|
||||
if this flag is specified.
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
|
||||
@@ -145,13 +85,7 @@ https://gitlab.com/cryptsetup/cryptsetup
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create a crypt device using dmsetup
|
||||
dmsetup create crypt1 --table "0 `blockdev --getsz $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
|
||||
]]
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create a crypt device using dmsetup when encryption key is stored in keyring service
|
||||
dmsetup create crypt2 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 :32:logon:my_prefix:my_key 0 $1 0"
|
||||
dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
|
||||
]]
|
||||
|
||||
[[
|
||||
|
@@ -16,12 +16,12 @@ Example scripts
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create device delaying rw operation for 500ms
|
||||
echo "0 `blockdev --getsz $1` delay $1 0 500" | dmsetup create delayed
|
||||
echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed
|
||||
]]
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create device delaying only write operation for 500ms and
|
||||
# splitting reads and writes to different devices $1 $2
|
||||
echo "0 `blockdev --getsz $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
|
||||
echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
|
||||
]]
|
||||
|
@@ -42,7 +42,7 @@ Optional feature parameters:
|
||||
<direction>: Either 'r' to corrupt reads or 'w' to corrupt writes.
|
||||
'w' is incompatible with drop_writes.
|
||||
<value>: The value (from 0-255) to write.
|
||||
<flags>: Perform the replacement only if bio->bi_opf has all the
|
||||
<flags>: Perform the replacement only if bio->bi_rw has all the
|
||||
selected flags set.
|
||||
|
||||
Examples:
|
||||
|
@@ -1,199 +0,0 @@
|
||||
The dm-integrity target emulates a block device that has additional
|
||||
per-sector tags that can be used for storing integrity information.
|
||||
|
||||
A general problem with storing integrity tags with every sector is that
|
||||
writing the sector and the integrity tag must be atomic - i.e. in case of
|
||||
crash, either both sector and integrity tag or none of them is written.
|
||||
|
||||
To guarantee write atomicity, the dm-integrity target uses journal, it
|
||||
writes sector data and integrity tags into a journal, commits the journal
|
||||
and then copies the data and integrity tags to their respective location.
|
||||
|
||||
The dm-integrity target can be used with the dm-crypt target - in this
|
||||
situation the dm-crypt target creates the integrity data and passes them
|
||||
to the dm-integrity target via bio_integrity_payload attached to the bio.
|
||||
In this mode, the dm-crypt and dm-integrity targets provide authenticated
|
||||
disk encryption - if the attacker modifies the encrypted device, an I/O
|
||||
error is returned instead of random data.
|
||||
|
||||
The dm-integrity target can also be used as a standalone target, in this
|
||||
mode it calculates and verifies the integrity tag internally. In this
|
||||
mode, the dm-integrity target can be used to detect silent data
|
||||
corruption on the disk or in the I/O path.
|
||||
|
||||
|
||||
When loading the target for the first time, the kernel driver will format
|
||||
the device. But it will only format the device if the superblock contains
|
||||
zeroes. If the superblock is neither valid nor zeroed, the dm-integrity
|
||||
target can't be loaded.
|
||||
|
||||
To use the target for the first time:
|
||||
1. overwrite the superblock with zeroes
|
||||
2. load the dm-integrity target with one-sector size, the kernel driver
|
||||
will format the device
|
||||
3. unload the dm-integrity target
|
||||
4. read the "provided_data_sectors" value from the superblock
|
||||
5. load the dm-integrity target with the the target size
|
||||
"provided_data_sectors"
|
||||
6. if you want to use dm-integrity with dm-crypt, load the dm-crypt target
|
||||
with the size "provided_data_sectors"
|
||||
|
||||
|
||||
Target arguments:
|
||||
|
||||
1. the underlying block device
|
||||
|
||||
2. the number of reserved sector at the beginning of the device - the
|
||||
dm-integrity won't read of write these sectors
|
||||
|
||||
3. the size of the integrity tag (if "-" is used, the size is taken from
|
||||
the internal-hash algorithm)
|
||||
|
||||
4. mode:
|
||||
D - direct writes (without journal) - in this mode, journaling is
|
||||
not used and data sectors and integrity tags are written
|
||||
separately. In case of crash, it is possible that the data
|
||||
and integrity tag doesn't match.
|
||||
J - journaled writes - data and integrity tags are written to the
|
||||
journal and atomicity is guaranteed. In case of crash,
|
||||
either both data and tag or none of them are written. The
|
||||
journaled mode degrades write throughput twice because the
|
||||
data have to be written twice.
|
||||
R - recovery mode - in this mode, journal is not replayed,
|
||||
checksums are not checked and writes to the device are not
|
||||
allowed. This mode is useful for data recovery if the
|
||||
device cannot be activated in any of the other standard
|
||||
modes.
|
||||
|
||||
5. the number of additional arguments
|
||||
|
||||
Additional arguments:
|
||||
|
||||
journal_sectors:number
|
||||
The size of journal, this argument is used only if formatting the
|
||||
device. If the device is already formatted, the value from the
|
||||
superblock is used.
|
||||
|
||||
interleave_sectors:number
|
||||
The number of interleaved sectors. This values is rounded down to
|
||||
a power of two. If the device is already formatted, the value from
|
||||
the superblock is used.
|
||||
|
||||
buffer_sectors:number
|
||||
The number of sectors in one buffer. The value is rounded down to
|
||||
a power of two.
|
||||
|
||||
The tag area is accessed using buffers, the buffer size is
|
||||
configurable. The large buffer size means that the I/O size will
|
||||
be larger, but there could be less I/Os issued.
|
||||
|
||||
journal_watermark:number
|
||||
The journal watermark in percents. When the size of the journal
|
||||
exceeds this watermark, the thread that flushes the journal will
|
||||
be started.
|
||||
|
||||
commit_time:number
|
||||
Commit time in milliseconds. When this time passes, the journal is
|
||||
written. The journal is also written immediatelly if the FLUSH
|
||||
request is received.
|
||||
|
||||
internal_hash:algorithm(:key) (the key is optional)
|
||||
Use internal hash or crc.
|
||||
When this argument is used, the dm-integrity target won't accept
|
||||
integrity tags from the upper target, but it will automatically
|
||||
generate and verify the integrity tags.
|
||||
|
||||
You can use a crc algorithm (such as crc32), then integrity target
|
||||
will protect the data against accidental corruption.
|
||||
You can also use a hmac algorithm (for example
|
||||
"hmac(sha256):0123456789abcdef"), in this mode it will provide
|
||||
cryptographic authentication of the data without encryption.
|
||||
|
||||
When this argument is not used, the integrity tags are accepted
|
||||
from an upper layer target, such as dm-crypt. The upper layer
|
||||
target should check the validity of the integrity tags.
|
||||
|
||||
journal_crypt:algorithm(:key) (the key is optional)
|
||||
Encrypt the journal using given algorithm to make sure that the
|
||||
attacker can't read the journal. You can use a block cipher here
|
||||
(such as "cbc(aes)") or a stream cipher (for example "chacha20",
|
||||
"salsa20", "ctr(aes)" or "ecb(arc4)").
|
||||
|
||||
The journal contains history of last writes to the block device,
|
||||
an attacker reading the journal could see the last sector nubmers
|
||||
that were written. From the sector numbers, the attacker can infer
|
||||
the size of files that were written. To protect against this
|
||||
situation, you can encrypt the journal.
|
||||
|
||||
journal_mac:algorithm(:key) (the key is optional)
|
||||
Protect sector numbers in the journal from accidental or malicious
|
||||
modification. To protect against accidental modification, use a
|
||||
crc algorithm, to protect against malicious modification, use a
|
||||
hmac algorithm with a key.
|
||||
|
||||
This option is not needed when using internal-hash because in this
|
||||
mode, the integrity of journal entries is checked when replaying
|
||||
the journal. Thus, modified sector number would be detected at
|
||||
this stage.
|
||||
|
||||
block_size:number
|
||||
The size of a data block in bytes. The larger the block size the
|
||||
less overhead there is for per-block integrity metadata.
|
||||
Supported values are 512, 1024, 2048 and 4096 bytes. If not
|
||||
specified the default block size is 512 bytes.
|
||||
|
||||
The journal mode (D/J), buffer_sectors, journal_watermark, commit_time can
|
||||
be changed when reloading the target (load an inactive table and swap the
|
||||
tables with suspend and resume). The other arguments should not be changed
|
||||
when reloading the target because the layout of disk data depend on them
|
||||
and the reloaded target would be non-functional.
|
||||
|
||||
|
||||
The layout of the formatted block device:
|
||||
* reserved sectors (they are not used by this target, they can be used for
|
||||
storing LUKS metadata or for other purpose), the size of the reserved
|
||||
area is specified in the target arguments
|
||||
* superblock (4kiB)
|
||||
* magic string - identifies that the device was formatted
|
||||
* version
|
||||
* log2(interleave sectors)
|
||||
* integrity tag size
|
||||
* the number of journal sections
|
||||
* provided data sectors - the number of sectors that this target
|
||||
provides (i.e. the size of the device minus the size of all
|
||||
metadata and padding). The user of this target should not send
|
||||
bios that access data beyond the "provided data sectors" limit.
|
||||
* flags - a flag is set if journal_mac is used
|
||||
* journal
|
||||
The journal is divided into sections, each section contains:
|
||||
* metadata area (4kiB), it contains journal entries
|
||||
every journal entry contains:
|
||||
* logical sector (specifies where the data and tag should
|
||||
be written)
|
||||
* last 8 bytes of data
|
||||
* integrity tag (the size is specified in the superblock)
|
||||
every metadata sector ends with
|
||||
* mac (8-bytes), all the macs in 8 metadata sectors form a
|
||||
64-byte value. It is used to store hmac of sector
|
||||
numbers in the journal section, to protect against a
|
||||
possibility that the attacker tampers with sector
|
||||
numbers in the journal.
|
||||
* commit id
|
||||
* data area (the size is variable; it depends on how many journal
|
||||
entries fit into the metadata area)
|
||||
every sector in the data area contains:
|
||||
* data (504 bytes of data, the last 8 bytes are stored in
|
||||
the journal entry)
|
||||
* commit id
|
||||
To test if the whole journal section was written correctly, every
|
||||
512-byte sector of the journal ends with 8-byte commit id. If the
|
||||
commit id matches on all sectors in a journal section, then it is
|
||||
assumed that the section was written correctly. If the commit id
|
||||
doesn't match, the section was written partially and it should not
|
||||
be replayed.
|
||||
* one or more runs of interleaved tags and data. Each run contains:
|
||||
* tag area - it contains integrity tags. There is one tag for each
|
||||
sector in the data area
|
||||
* data area - it contains data sectors. The number of data sectors
|
||||
in one run must be a power of two. log2 of this value is stored
|
||||
in the superblock.
|
@@ -16,15 +16,15 @@ Example scripts
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create an identity mapping for a device
|
||||
echo "0 `blockdev --getsz $1` linear $1 0" | dmsetup create identity
|
||||
echo "0 `blockdev --getsize $1` linear $1 0" | dmsetup create identity
|
||||
]]
|
||||
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Join 2 devices together
|
||||
size1=`blockdev --getsz $1`
|
||||
size2=`blockdev --getsz $2`
|
||||
size1=`blockdev --getsize $1`
|
||||
size2=`blockdev --getsize $2`
|
||||
echo "0 $size1 linear $1 0
|
||||
$size1 $size2 linear $2 0" | dmsetup create joined
|
||||
]]
|
||||
@@ -44,7 +44,7 @@ if (!defined($dev)) {
|
||||
die("Please specify a device.\n");
|
||||
}
|
||||
|
||||
my $dev_size = `blockdev --getsz $dev`;
|
||||
my $dev_size = `blockdev --getsize $dev`;
|
||||
my $extents = int($dev_size / $extent_size) -
|
||||
(($dev_size % $extent_size) ? 1 : 0);
|
||||
|
||||
|
@@ -14,14 +14,14 @@ Log Ordering
|
||||
|
||||
We log things in order of completion once we are sure the write is no longer in
|
||||
cache. This means that normal WRITE requests are not actually logged until the
|
||||
next REQ_PREFLUSH request. This is to make it easier for userspace to replay
|
||||
the log in a way that correlates to what is on disk and not what is in cache,
|
||||
to make it easier to detect improper waiting/flushing.
|
||||
next REQ_FLUSH request. This is to make it easier for userspace to replay the
|
||||
log in a way that correlates to what is on disk and not what is in cache, to
|
||||
make it easier to detect improper waiting/flushing.
|
||||
|
||||
This works by attaching all WRITE requests to a list once the write completes.
|
||||
Once we see a REQ_PREFLUSH request we splice this list onto the request and once
|
||||
Once we see a REQ_FLUSH request we splice this list onto the request and once
|
||||
the FLUSH request completes we log all of the WRITEs and then the FLUSH. Only
|
||||
completed WRITEs, at the time the REQ_PREFLUSH is issued, are added in order to
|
||||
completed WRITEs, at the time the REQ_FLUSH is issued, are added in order to
|
||||
simulate the worst case scenario with regard to power failures. Consider the
|
||||
following example (W means write, C means complete):
|
||||
|
||||
|
@@ -14,12 +14,8 @@ The target is named "raid" and it accepts the following parameters:
|
||||
<#raid_devs> <metadata_dev0> <dev0> [.. <metadata_devN> <devN>]
|
||||
|
||||
<raid_type>:
|
||||
raid0 RAID0 striping (no resilience)
|
||||
raid1 RAID1 mirroring
|
||||
raid4 RAID4 with dedicated last parity disk
|
||||
raid5_n RAID5 with dedicated last parity disk supporting takeover
|
||||
Same as raid4
|
||||
-Transitory layout
|
||||
raid4 RAID4 dedicated parity disk
|
||||
raid5_la RAID5 left asymmetric
|
||||
- rotating parity 0 with data continuation
|
||||
raid5_ra RAID5 right asymmetric
|
||||
@@ -34,19 +30,7 @@ The target is named "raid" and it accepts the following parameters:
|
||||
- rotating parity N (right-to-left) with data restart
|
||||
raid6_nc RAID6 N continue
|
||||
- rotating parity N (right-to-left) with data continuation
|
||||
raid6_n_6 RAID6 with dedicate parity disks
|
||||
- parity and Q-syndrome on the last 2 disks;
|
||||
layout for takeover from/to raid4/raid5_n
|
||||
raid6_la_6 Same as "raid_la" plus dedicated last Q-syndrome disk
|
||||
- layout for takeover from raid5_la from/to raid6
|
||||
raid6_ra_6 Same as "raid5_ra" dedicated last Q-syndrome disk
|
||||
- layout for takeover from raid5_ra from/to raid6
|
||||
raid6_ls_6 Same as "raid5_ls" dedicated last Q-syndrome disk
|
||||
- layout for takeover from raid5_ls from/to raid6
|
||||
raid6_rs_6 Same as "raid5_rs" dedicated last Q-syndrome disk
|
||||
- layout for takeover from raid5_rs from/to raid6
|
||||
raid10 Various RAID10 inspired algorithms chosen by additional params
|
||||
(see raid10_format and raid10_copies below)
|
||||
- RAID10: Striped Mirrors (aka 'Striping on top of mirrors')
|
||||
- RAID1E: Integrated Adjacent Stripe Mirroring
|
||||
- RAID1E: Integrated Offset Stripe Mirroring
|
||||
@@ -132,57 +116,10 @@ The target is named "raid" and it accepts the following parameters:
|
||||
Here we see layouts closely akin to 'RAID1E - Integrated
|
||||
Offset Stripe Mirroring'.
|
||||
|
||||
[delta_disks <N>]
|
||||
The delta_disks option value (-251 < N < +251) triggers
|
||||
device removal (negative value) or device addition (positive
|
||||
value) to any reshape supporting raid levels 4/5/6 and 10.
|
||||
RAID levels 4/5/6 allow for addition of devices (metadata
|
||||
and data device tuple), raid10_near and raid10_offset only
|
||||
allow for device addition. raid10_far does not support any
|
||||
reshaping at all.
|
||||
A minimum of devices have to be kept to enforce resilience,
|
||||
which is 3 devices for raid4/5 and 4 devices for raid6.
|
||||
|
||||
[data_offset <sectors>]
|
||||
This option value defines the offset into each data device
|
||||
where the data starts. This is used to provide out-of-place
|
||||
reshaping space to avoid writing over data whilst
|
||||
changing the layout of stripes, hence an interruption/crash
|
||||
may happen at any time without the risk of losing data.
|
||||
E.g. when adding devices to an existing raid set during
|
||||
forward reshaping, the out-of-place space will be allocated
|
||||
at the beginning of each raid device. The kernel raid4/5/6/10
|
||||
MD personalities supporting such device addition will read the data from
|
||||
the existing first stripes (those with smaller number of stripes)
|
||||
starting at data_offset to fill up a new stripe with the larger
|
||||
number of stripes, calculate the redundancy blocks (CRC/Q-syndrome)
|
||||
and write that new stripe to offset 0. Same will be applied to all
|
||||
N-1 other new stripes. This out-of-place scheme is used to change
|
||||
the RAID type (i.e. the allocation algorithm) as well, e.g.
|
||||
changing from raid5_ls to raid5_n.
|
||||
|
||||
[journal_dev <dev>]
|
||||
This option adds a journal device to raid4/5/6 raid sets and
|
||||
uses it to close the 'write hole' caused by the non-atomic updates
|
||||
to the component devices which can cause data loss during recovery.
|
||||
The journal device is used as writethrough thus causing writes to
|
||||
be throttled versus non-journaled raid4/5/6 sets.
|
||||
Takeover/reshape is not possible with a raid4/5/6 journal device;
|
||||
it has to be deconfigured before requesting these.
|
||||
|
||||
[journal_mode <mode>]
|
||||
This option sets the caching mode on journaled raid4/5/6 raid sets
|
||||
(see 'journal_dev <dev>' above) to 'writethrough' or 'writeback'.
|
||||
If 'writeback' is selected the journal device has to be resilient
|
||||
and must not suffer from the 'write hole' problem itself (e.g. use
|
||||
raid1 or raid10) to avoid a single point of failure.
|
||||
|
||||
<#raid_devs>: The number of devices composing the array.
|
||||
Each device consists of two entries. The first is the device
|
||||
containing the metadata (if any); the second is the one containing the
|
||||
data. A Maximum of 64 metadata/data device entries are supported
|
||||
up to target version 1.8.0.
|
||||
1.9.0 supports up to 253 which is enforced by the used MD kernel runtime.
|
||||
data.
|
||||
|
||||
If a drive has failed or is missing at creation time, a '-' can be
|
||||
given for both the metadata and data drives for a given position.
|
||||
@@ -258,14 +195,6 @@ recovery. Here is a fuller description of the individual fields:
|
||||
in RAID1/10 or wrong parity values found in RAID4/5/6.
|
||||
This value is valid only after a "check" of the array
|
||||
is performed. A healthy array has a 'mismatch_cnt' of 0.
|
||||
<data_offset> The current data offset to the start of the user data on
|
||||
each component device of a raid set (see the respective
|
||||
raid parameter to support out-of-place reshaping).
|
||||
<journal_char> 'A' - active write-through journal device.
|
||||
'a' - active write-back journal device.
|
||||
'D' - dead journal device.
|
||||
'-' - no journal device.
|
||||
|
||||
|
||||
Message Interface
|
||||
-----------------
|
||||
@@ -278,6 +207,7 @@ include:
|
||||
"recover"- Initiate/continue a recover process.
|
||||
"check" - Initiate a check (i.e. a "scrub") of the array.
|
||||
"repair" - Initiate a repair of the array.
|
||||
"reshape"- Currently unsupported (-EINVAL).
|
||||
|
||||
|
||||
Discard Support
|
||||
@@ -327,19 +257,3 @@ Version History
|
||||
1.5.2 'mismatch_cnt' is zero unless [last_]sync_action is "check".
|
||||
1.6.0 Add discard support (and devices_handle_discard_safely module param).
|
||||
1.7.0 Add support for MD RAID0 mappings.
|
||||
1.8.0 Explicitly check for compatible flags in the superblock metadata
|
||||
and reject to start the raid set if any are set by a newer
|
||||
target version, thus avoiding data corruption on a raid set
|
||||
with a reshape in progress.
|
||||
1.9.0 Add support for RAID level takeover/reshape/region size
|
||||
and set size reduction.
|
||||
1.9.1 Fix activation of existing RAID 4/10 mapped devices
|
||||
1.9.2 Don't emit '- -' on the status table line in case the constructor
|
||||
fails reading a superblock. Correctly emit 'maj:min1 maj:min2' and
|
||||
'D' on the status line. If '- -' is passed into the constructor, emit
|
||||
'- -' on the table line and '-' as the status line health character.
|
||||
1.10.0 Add support for raid4/5/6 journal device
|
||||
1.10.1 Fix data corruption on reshape request
|
||||
1.11.0 Fix table line argument order
|
||||
(wrong raid10_copies/raid10_format sequence)
|
||||
1.11.1 Add raid4/5/6 journal write-back support via journal_mode option
|
||||
|
@@ -37,9 +37,9 @@ if (!$num_devs) {
|
||||
die("Specify at least one device\n");
|
||||
}
|
||||
|
||||
$min_dev_size = `blockdev --getsz $devs[0]`;
|
||||
$min_dev_size = `blockdev --getsize $devs[0]`;
|
||||
for ($i = 1; $i < $num_devs; $i++) {
|
||||
my $this_size = `blockdev --getsz $devs[$i]`;
|
||||
my $this_size = `blockdev --getsize $devs[$i]`;
|
||||
$min_dev_size = ($min_dev_size < $this_size) ?
|
||||
$min_dev_size : $this_size;
|
||||
}
|
||||
|
@@ -123,7 +123,7 @@ Assume that you have volumes vg1/switch0 vg1/switch1 vg1/switch2 with
|
||||
the same size.
|
||||
|
||||
Create a switch device with 64kB region size:
|
||||
dmsetup create switch --table "0 `blockdev --getsz /dev/vg1/switch0`
|
||||
dmsetup create switch --table "0 `blockdev --getsize /dev/vg1/switch0`
|
||||
switch 3 128 0 /dev/vg1/switch0 0 /dev/vg1/switch1 0 /dev/vg1/switch2 0"
|
||||
|
||||
Set mappings for the first 7 entries to point to devices switch0, switch1,
|
||||
|
@@ -1,144 +0,0 @@
|
||||
dm-zoned
|
||||
========
|
||||
|
||||
The dm-zoned device mapper target exposes a zoned block device (ZBC and
|
||||
ZAC compliant devices) as a regular block device without any write
|
||||
pattern constraints. In effect, it implements a drive-managed zoned
|
||||
block device which hides from the user (a file system or an application
|
||||
doing raw block device accesses) the sequential write constraints of
|
||||
host-managed zoned block devices and can mitigate the potential
|
||||
device-side performance degradation due to excessive random writes on
|
||||
host-aware zoned block devices.
|
||||
|
||||
For a more detailed description of the zoned block device models and
|
||||
their constraints see (for SCSI devices):
|
||||
|
||||
http://www.t10.org/drafts.htm#ZBC_Family
|
||||
|
||||
and (for ATA devices):
|
||||
|
||||
http://www.t13.org/Documents/UploadedDocuments/docs2015/di537r05-Zoned_Device_ATA_Command_Set_ZAC.pdf
|
||||
|
||||
The dm-zoned implementation is simple and minimizes system overhead (CPU
|
||||
and memory usage as well as storage capacity loss). For a 10TB
|
||||
host-managed disk with 256 MB zones, dm-zoned memory usage per disk
|
||||
instance is at most 4.5 MB and as little as 5 zones will be used
|
||||
internally for storing metadata and performaing reclaim operations.
|
||||
|
||||
dm-zoned target devices are formatted and checked using the dmzadm
|
||||
utility available at:
|
||||
|
||||
https://github.com/hgst/dm-zoned-tools
|
||||
|
||||
Algorithm
|
||||
=========
|
||||
|
||||
dm-zoned implements an on-disk buffering scheme to handle non-sequential
|
||||
write accesses to the sequential zones of a zoned block device.
|
||||
Conventional zones are used for caching as well as for storing internal
|
||||
metadata.
|
||||
|
||||
The zones of the device are separated into 2 types:
|
||||
|
||||
1) Metadata zones: these are conventional zones used to store metadata.
|
||||
Metadata zones are not reported as useable capacity to the user.
|
||||
|
||||
2) Data zones: all remaining zones, the vast majority of which will be
|
||||
sequential zones used exclusively to store user data. The conventional
|
||||
zones of the device may be used also for buffering user random writes.
|
||||
Data in these zones may be directly mapped to the conventional zone, but
|
||||
later moved to a sequential zone so that the conventional zone can be
|
||||
reused for buffering incoming random writes.
|
||||
|
||||
dm-zoned exposes a logical device with a sector size of 4096 bytes,
|
||||
irrespective of the physical sector size of the backend zoned block
|
||||
device being used. This allows reducing the amount of metadata needed to
|
||||
manage valid blocks (blocks written).
|
||||
|
||||
The on-disk metadata format is as follows:
|
||||
|
||||
1) The first block of the first conventional zone found contains the
|
||||
super block which describes the on disk amount and position of metadata
|
||||
blocks.
|
||||
|
||||
2) Following the super block, a set of blocks is used to describe the
|
||||
mapping of the logical device blocks. The mapping is done per chunk of
|
||||
blocks, with the chunk size equal to the zoned block device size. The
|
||||
mapping table is indexed by chunk number and each mapping entry
|
||||
indicates the zone number of the device storing the chunk of data. Each
|
||||
mapping entry may also indicate if the zone number of a conventional
|
||||
zone used to buffer random modification to the data zone.
|
||||
|
||||
3) A set of blocks used to store bitmaps indicating the validity of
|
||||
blocks in the data zones follows the mapping table. A valid block is
|
||||
defined as a block that was written and not discarded. For a buffered
|
||||
data chunk, a block is always valid only in the data zone mapping the
|
||||
chunk or in the buffer zone of the chunk.
|
||||
|
||||
For a logical chunk mapped to a conventional zone, all write operations
|
||||
are processed by directly writing to the zone. If the mapping zone is a
|
||||
sequential zone, the write operation is processed directly only if the
|
||||
write offset within the logical chunk is equal to the write pointer
|
||||
offset within of the sequential data zone (i.e. the write operation is
|
||||
aligned on the zone write pointer). Otherwise, write operations are
|
||||
processed indirectly using a buffer zone. In that case, an unused
|
||||
conventional zone is allocated and assigned to the chunk being
|
||||
accessed. Writing a block to the buffer zone of a chunk will
|
||||
automatically invalidate the same block in the sequential zone mapping
|
||||
the chunk. If all blocks of the sequential zone become invalid, the zone
|
||||
is freed and the chunk buffer zone becomes the primary zone mapping the
|
||||
chunk, resulting in native random write performance similar to a regular
|
||||
block device.
|
||||
|
||||
Read operations are processed according to the block validity
|
||||
information provided by the bitmaps. Valid blocks are read either from
|
||||
the sequential zone mapping a chunk, or if the chunk is buffered, from
|
||||
the buffer zone assigned. If the accessed chunk has no mapping, or the
|
||||
accessed blocks are invalid, the read buffer is zeroed and the read
|
||||
operation terminated.
|
||||
|
||||
After some time, the limited number of convnetional zones available may
|
||||
be exhausted (all used to map chunks or buffer sequential zones) and
|
||||
unaligned writes to unbuffered chunks become impossible. To avoid this
|
||||
situation, a reclaim process regularly scans used conventional zones and
|
||||
tries to reclaim the least recently used zones by copying the valid
|
||||
blocks of the buffer zone to a free sequential zone. Once the copy
|
||||
completes, the chunk mapping is updated to point to the sequential zone
|
||||
and the buffer zone freed for reuse.
|
||||
|
||||
Metadata Protection
|
||||
===================
|
||||
|
||||
To protect metadata against corruption in case of sudden power loss or
|
||||
system crash, 2 sets of metadata zones are used. One set, the primary
|
||||
set, is used as the main metadata region, while the secondary set is
|
||||
used as a staging area. Modified metadata is first written to the
|
||||
secondary set and validated by updating the super block in the secondary
|
||||
set, a generation counter is used to indicate that this set contains the
|
||||
newest metadata. Once this operation completes, in place of metadata
|
||||
block updates can be done in the primary metadata set. This ensures that
|
||||
one of the set is always consistent (all modifications committed or none
|
||||
at all). Flush operations are used as a commit point. Upon reception of
|
||||
a flush request, metadata modification activity is temporarily blocked
|
||||
(for both incoming BIO processing and reclaim process) and all dirty
|
||||
metadata blocks are staged and updated. Normal operation is then
|
||||
resumed. Flushing metadata thus only temporarily delays write and
|
||||
discard requests. Read requests can be processed concurrently while
|
||||
metadata flush is being executed.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
A zoned block device must first be formatted using the dmzadm tool. This
|
||||
will analyze the device zone configuration, determine where to place the
|
||||
metadata sets on the device and initialize the metadata sets.
|
||||
|
||||
Ex:
|
||||
|
||||
dmzadm --format /dev/sdxx
|
||||
|
||||
For a formatted device, the target can be created normally with the
|
||||
dmsetup utility. The only parameter that dm-zoned requires is the
|
||||
underlying zoned block device name. Ex:
|
||||
|
||||
echo "0 `blockdev --getsize ${dev}` zoned ${dev}" | dmsetup create dmz-`basename ${dev}`
|
@@ -1,8 +1,5 @@
|
||||
/* include/configure.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define to 1 if aio is available. */
|
||||
#undef AIO_SUPPORT
|
||||
|
||||
/* Define to 1 to use libblkid detection of signatures when wiping. */
|
||||
#undef BLKID_WIPING_SUPPORT
|
||||
|
||||
@@ -688,6 +685,9 @@
|
||||
/* Define to 1 to include the LVM readline shell. */
|
||||
#undef READLINE_SUPPORT
|
||||
|
||||
/* Define to 1 to include built-in support for replicators. */
|
||||
#undef REPLICATOR_INTERNAL
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#undef RETSIGTYPE
|
||||
|
||||
|
@@ -36,6 +36,10 @@ ifeq ("@RAID@", "shared")
|
||||
SUBDIRS += raid
|
||||
endif
|
||||
|
||||
ifeq ("@REPLICATORS@", "shared")
|
||||
SUBDIRS += replicator
|
||||
endif
|
||||
|
||||
ifeq ("@THIN@", "shared")
|
||||
SUBDIRS += thin
|
||||
endif
|
||||
@@ -44,10 +48,6 @@ ifeq ("@CACHE@", "shared")
|
||||
SUBDIRS += cache_segtype
|
||||
endif
|
||||
|
||||
ifeq ("@CLUSTER@", "shared")
|
||||
SUBDIRS += locking
|
||||
endif
|
||||
|
||||
SOURCES =\
|
||||
activate/activate.c \
|
||||
cache/lvmcache.c \
|
||||
@@ -96,13 +96,13 @@ SOURCES =\
|
||||
metadata/lv_manip.c \
|
||||
metadata/merge.c \
|
||||
metadata/metadata.c \
|
||||
metadata/metadata-liblvm.c \
|
||||
metadata/mirror.c \
|
||||
metadata/pool_manip.c \
|
||||
metadata/pv.c \
|
||||
metadata/pv_manip.c \
|
||||
metadata/pv_map.c \
|
||||
metadata/raid_manip.c \
|
||||
metadata/replicator_manip.c \
|
||||
metadata/segtype.c \
|
||||
metadata/snapshot_manip.c \
|
||||
metadata/thin_manip.c \
|
||||
@@ -149,6 +149,10 @@ ifeq ("@CLUSTER@", "internal")
|
||||
SOURCES += locking/cluster_locking.c
|
||||
endif
|
||||
|
||||
ifeq ("@CLUSTER@", "shared")
|
||||
SUBDIRS += locking
|
||||
endif
|
||||
|
||||
ifeq ("@SNAPSHOTS@", "internal")
|
||||
SOURCES += snapshot/snapshot.c
|
||||
endif
|
||||
@@ -161,6 +165,10 @@ ifeq ("@RAID@", "internal")
|
||||
SOURCES += raid/raid.c
|
||||
endif
|
||||
|
||||
ifeq ("@REPLICATORS@", "internal")
|
||||
SOURCES += replicator/replicator.c
|
||||
endif
|
||||
|
||||
ifeq ("@THIN@", "internal")
|
||||
SOURCES += thin/thin.c
|
||||
endif
|
||||
@@ -196,6 +204,11 @@ ifeq ("@BUILD_LVMLOCKD@", "yes")
|
||||
locking/lvmlockd.c
|
||||
endif
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd
|
||||
LIBS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
LIB_NAME = liblvm-internal
|
||||
LIB_STATIC = $(LIB_NAME).a
|
||||
|
||||
@@ -207,6 +220,7 @@ ifeq ($(MAKECMDGOALS),distclean)
|
||||
mirror \
|
||||
notify \
|
||||
raid \
|
||||
replicator \
|
||||
thin \
|
||||
cache_segtype \
|
||||
locking
|
||||
@@ -215,10 +229,10 @@ endif
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
PROGS_CFLAGS = $(BLKID_CFLAGS) $(UDEV_CFLAGS)
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
CFLAGS += $(BLKID_CFLAGS) $(UDEV_CFLAGS) $(VALGRIND_CFLAGS)
|
||||
|
||||
$(SUBDIRS): $(LIB_STATIC)
|
||||
|
||||
CLEAN_TARGETS += misc/configure.h misc/lvm-version.h
|
||||
|
@@ -28,7 +28,6 @@
|
||||
#include "config.h"
|
||||
#include "segtype.h"
|
||||
#include "sharedlib.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
@@ -151,15 +150,15 @@ static int _lv_passes_volumes_filter(struct cmd_context *cmd, const struct logic
|
||||
|| str_list_match_list(&cmd->tags,
|
||||
&lv->vg->tags, NULL))
|
||||
return 1;
|
||||
|
||||
continue;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
/* If supplied tag matches LV or VG tag, activate */
|
||||
if (str_list_match_item(&lv->tags, str) ||
|
||||
str_list_match_item(&lv->vg->tags, str))
|
||||
return 1;
|
||||
|
||||
continue;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If supplied name is vgname[/lvname] */
|
||||
@@ -782,8 +781,7 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
|
||||
if (lv_is_used_cache_pool(lv)) {
|
||||
/* INFO is not set as cache-pool cannot be active.
|
||||
* STATUS is collected from cache LV */
|
||||
if (!(lv_seg = get_only_segment_using_this_lv(lv)))
|
||||
return_0;
|
||||
lv_seg = get_only_segment_using_this_lv(lv);
|
||||
(void) _lv_info(cmd, lv_seg->lv, 1, NULL, lv_seg, &status->seg_status, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
@@ -798,18 +796,14 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
|
||||
status->info.exists = 0; /* So pool LV is not active */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lv_is_external_origin(lv)) {
|
||||
} else if (lv_is_external_origin(lv)) {
|
||||
if (!_lv_info(cmd, lv, 0, &status->info, NULL, NULL,
|
||||
with_open_count, with_read_ahead))
|
||||
return_0;
|
||||
|
||||
(void) _lv_info(cmd, lv, 1, NULL, lv_seg, &status->seg_status, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lv_is_origin(lv)) {
|
||||
} else if (lv_is_origin(lv)) {
|
||||
/* Query segment status for 'layered' (-real) device most of the time,
|
||||
* only for merging snapshot, query its progress.
|
||||
* TODO: single LV may need couple status to be exposed at once....
|
||||
@@ -826,9 +820,7 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
|
||||
/* Grab STATUS from layered -real */
|
||||
(void) _lv_info(cmd, lv, 1, NULL, lv_seg, &status->seg_status, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lv_is_cow(lv)) {
|
||||
} else if (lv_is_cow(lv)) {
|
||||
if (lv_is_merging_cow(lv)) {
|
||||
olv = origin_from_cow(lv);
|
||||
|
||||
@@ -843,6 +835,7 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
|
||||
* When merge is in progress, query merging origin LV instead.
|
||||
* COW volume is already mapped as error target in this case.
|
||||
*/
|
||||
status->lv = olv;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1708,7 +1701,7 @@ static char *_build_target_uuid(struct cmd_context *cmd, const struct logical_vo
|
||||
|
||||
if (lv_is_thin_pool(lv))
|
||||
layer = "tpool"; /* Monitor "tpool" for the "thin pool". */
|
||||
else if (lv_is_origin(lv) || lv_is_external_origin(lv))
|
||||
else if (lv_is_origin(lv))
|
||||
layer = "real"; /* Monitor "real" for "snapshot-origin". */
|
||||
else
|
||||
layer = NULL;
|
||||
@@ -1856,15 +1849,12 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
|
||||
* However in case command would have crashed, such LV is
|
||||
* left unmonitored and may potentially require dmeventd.
|
||||
*/
|
||||
if (lv_is_cache_pool_data(lv) || lv_is_cache_pool_metadata(lv)) {
|
||||
if (!(seg = find_pool_seg(first_seg(lv))))
|
||||
return_0;
|
||||
if (!lv_is_used_cache_pool(seg->lv)) {
|
||||
log_debug_activation("Skipping %smonitor of %s.%s",
|
||||
(monitor) ? "" : "un", display_lvname(lv),
|
||||
(monitor) ? " Cache pool activation for clearing only." : "");
|
||||
return 1;
|
||||
}
|
||||
if ((lv_is_cache_pool_data(lv) || lv_is_cache_pool_metadata(lv)) &&
|
||||
!lv_is_used_cache_pool((find_pool_seg(first_seg(lv))->lv))) {
|
||||
log_debug_activation("Skipping %smonitor of %s.%s",
|
||||
(monitor) ? "" : "un", display_lvname(lv),
|
||||
(monitor) ? " Cache pool activation for clearing only." : "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1950,13 +1940,6 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (seg->external_lv &&
|
||||
!monitor_dev_for_events(cmd, seg->external_lv,
|
||||
(!monitor) ? laopts : NULL, monitor)) {
|
||||
stack;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (seg->metadata_lv &&
|
||||
!monitor_dev_for_events(cmd, seg->metadata_lv, NULL, monitor)) {
|
||||
stack;
|
||||
@@ -2124,17 +2107,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* Save old and new (current and precommitted) versions of the
|
||||
* VG metadata for lv_resume() to use, since lv_resume can't
|
||||
* read metadata given that devices are suspended. lv_resume()
|
||||
* will resume LVs using the old/current metadata if the vg_commit
|
||||
* did happen (or failed), and it will resume LVs using the
|
||||
* new/precommitted metadata if the vg_commit succeeded.
|
||||
*/
|
||||
lvmcache_save_suspended_vg(lv->vg, 0);
|
||||
lvmcache_save_suspended_vg(lv_pre->vg, 1);
|
||||
|
||||
if (!info.exists || info.suspended) {
|
||||
if (!error_if_not_suspended) {
|
||||
r = 1;
|
||||
@@ -2144,6 +2116,9 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!lv_read_replicator_vgs(lv))
|
||||
goto_out;
|
||||
|
||||
lv_calculate_readahead(lv, NULL);
|
||||
|
||||
/*
|
||||
@@ -2265,8 +2240,10 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
out:
|
||||
if (lv_pre_to_free)
|
||||
release_vg(lv_pre_to_free->vg);
|
||||
if (lv_to_free)
|
||||
if (lv_to_free) {
|
||||
lv_release_replicator_vgs(lv_to_free);
|
||||
release_vg(lv_to_free->vg);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -2293,54 +2270,15 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lv_activate_opts *laopts, int error_if_not_active,
|
||||
const struct logical_volume *lv)
|
||||
{
|
||||
struct volume_group *vg = NULL;
|
||||
struct logical_volume *lv_found = NULL;
|
||||
const union lvid *lvid;
|
||||
const char *vgid;
|
||||
const struct logical_volume *lv_to_free = NULL;
|
||||
struct lvinfo info;
|
||||
int r = 0;
|
||||
|
||||
if (!activation())
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* When called in clvmd, lvid_s is set and lv is not. We need to
|
||||
* get the VG metadata without reading disks because devs are
|
||||
* suspended. lv_suspend() saved old and new VG metadata for us
|
||||
* to use here. If vg_commit() happened, lvmcache_get_suspended_vg
|
||||
* will return the new metadata for us to use in resuming LVs.
|
||||
* If vg_commit() did not happen, lvmcache_get_suspended_vg
|
||||
* returns the old metadata which we use to resume LVs.
|
||||
*/
|
||||
if (!lv && lvid_s) {
|
||||
lvid = (const union lvid *) lvid_s;
|
||||
vgid = (const char *)lvid->id[0].uuid;
|
||||
|
||||
if ((vg = lvmcache_get_suspended_vg(vgid))) {
|
||||
log_debug_activation("Resuming LVID %s found saved vg seqno %d %s", lvid_s, vg->seqno, vg->name);
|
||||
if ((lv_found = find_lv_in_vg_by_lvid(vg, lvid))) {
|
||||
log_debug_activation("Resuming LVID %s found saved LV %s", lvid_s, display_lvname(lv_found));
|
||||
lv = lv_found;
|
||||
} else
|
||||
log_debug_activation("Resuming LVID %s did not find saved LV", lvid_s);
|
||||
} else
|
||||
log_debug_activation("Resuming LVID %s did not find saved VG", lvid_s);
|
||||
|
||||
/*
|
||||
* resume must have been called without a preceding suspend,
|
||||
* so we need to read the vg.
|
||||
*/
|
||||
|
||||
if (!lv) {
|
||||
log_debug_activation("Resuming LVID %s reading VG", lvid_s);
|
||||
if (!(lv_found = lv_from_lvid(cmd, lvid_s, 0))) {
|
||||
log_debug_activation("Resuming LVID %s failed to read VG", lvid_s);
|
||||
goto out;
|
||||
}
|
||||
|
||||
lv = lv_found;
|
||||
}
|
||||
}
|
||||
if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
goto_out;
|
||||
|
||||
if (!lv_is_origin(lv) && !lv_is_thin_volume(lv) && !lv_is_thin_pool(lv))
|
||||
laopts->origin_only = 0;
|
||||
@@ -2385,6 +2323,9 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
if (lv_to_free)
|
||||
release_vg(lv_to_free->vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -2486,6 +2427,9 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
|
||||
goto_out;
|
||||
}
|
||||
|
||||
if (!lv_read_replicator_vgs(lv))
|
||||
goto_out;
|
||||
|
||||
if (!monitor_dev_for_events(cmd, lv, &laopts, 0))
|
||||
stack;
|
||||
|
||||
@@ -2500,8 +2444,10 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
|
||||
r = 0;
|
||||
}
|
||||
out:
|
||||
if (lv_to_free)
|
||||
if (lv_to_free) {
|
||||
lv_release_replicator_vgs(lv_to_free);
|
||||
release_vg(lv_to_free->vg);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -2511,10 +2457,6 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv, const struct logical_volume *lv)
|
||||
{
|
||||
const struct logical_volume *lv_to_free = NULL;
|
||||
struct volume_group *vg = NULL;
|
||||
struct logical_volume *lv_found = NULL;
|
||||
const union lvid *lvid;
|
||||
const char *vgid;
|
||||
int r = 0;
|
||||
|
||||
if (!activation()) {
|
||||
@@ -2522,24 +2464,6 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called while devices are suspended,
|
||||
* so try to use the copy of the vg that was saved in
|
||||
* lv_suspend.
|
||||
*/
|
||||
if (!lv && lvid_s) {
|
||||
lvid = (const union lvid *) lvid_s;
|
||||
vgid = (const char *)lvid->id[0].uuid;
|
||||
|
||||
if ((vg = lvmcache_get_suspended_vg(vgid))) {
|
||||
log_debug_activation("activation_filter for %s found saved VG seqno %d %s", lvid_s, vg->seqno, vg->name);
|
||||
if ((lv_found = find_lv_in_vg_by_lvid(vg, lvid))) {
|
||||
log_debug_activation("activation_filter for %s found saved LV %s", lvid_s, display_lvname(lv_found));
|
||||
lv = lv_found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
goto_out;
|
||||
|
||||
@@ -2638,6 +2562,9 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!lv_read_replicator_vgs(lv))
|
||||
goto_out;
|
||||
|
||||
lv_calculate_readahead(lv, NULL);
|
||||
|
||||
critical_section_inc(cmd, "activating");
|
||||
@@ -2649,8 +2576,10 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
stack;
|
||||
|
||||
out:
|
||||
if (lv_to_free)
|
||||
if (lv_to_free) {
|
||||
lv_release_replicator_vgs(lv_to_free);
|
||||
release_vg(lv_to_free->vg);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@@ -174,7 +174,7 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
|
||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
|
||||
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
|
||||
int lv_raid_message(const struct logical_volume *lv, const char *msg);
|
||||
int lv_cache_status(const struct logical_volume *cache_lv,
|
||||
int lv_cache_status(const struct logical_volume *lv,
|
||||
struct lv_status_cache **status);
|
||||
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
|
||||
dm_percent_t *percent);
|
||||
@@ -202,12 +202,12 @@ int lv_has_target_type(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
const char *layer, const char *target_type);
|
||||
|
||||
int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
const struct lv_activate_opts *laopts, int monitor);
|
||||
const struct lv_activate_opts *laopts, int do_reg);
|
||||
|
||||
#ifdef DMEVENTD
|
||||
# include "libdevmapper-event.h"
|
||||
char *get_monitor_dso_path(struct cmd_context *cmd, const char *libpath);
|
||||
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
|
||||
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *libpath,
|
||||
const struct logical_volume *lv, int *pending);
|
||||
int target_register_events(struct cmd_context *cmd, const char *dso, const struct logical_volume *lv,
|
||||
int evmask __attribute__((unused)), int set, int timeout);
|
||||
|
@@ -275,8 +275,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
|
||||
target_params = NULL; /* Marking this target_params unusable */
|
||||
} while (target);
|
||||
|
||||
if (!target_name ||
|
||||
!_get_segment_status_from_target_params(target_name, target_params, seg_status))
|
||||
if (!_get_segment_status_from_target_params(target_name, target_params, seg_status))
|
||||
stack;
|
||||
}
|
||||
|
||||
@@ -1038,8 +1037,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
goto_out;
|
||||
}
|
||||
|
||||
log_debug_activation("LV percent: %s",
|
||||
display_percent(dm->cmd, *overall_percent));
|
||||
log_debug_activation("LV percent: %.2f", dm_percent_to_float(*overall_percent));
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
@@ -1056,11 +1054,10 @@ static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
|
||||
if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
return 1;
|
||||
|
||||
if (_original_uuid_format_check_required(dm->cmd) &&
|
||||
_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
else if (_original_uuid_format_check_required(dm->cmd) &&
|
||||
_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1774,6 +1771,84 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add replicator devices
|
||||
*
|
||||
* Using _add_dev_to_dtree() directly instead of _add_lv_to_dtree()
|
||||
* to avoid extra checks with extensions.
|
||||
*/
|
||||
static int _add_partial_replicator_to_dtree(struct dev_manager *dm,
|
||||
struct dm_tree *dtree,
|
||||
const struct logical_volume *lv)
|
||||
{
|
||||
struct logical_volume *rlv = first_seg(lv)->replicator;
|
||||
struct replicator_device *rdev;
|
||||
struct replicator_site *rsite;
|
||||
struct dm_tree_node *rep_node, *rdev_node;
|
||||
const char *uuid;
|
||||
|
||||
if (!lv_is_active_replicator_dev(lv)) {
|
||||
if (!_add_dev_to_dtree(dm, dtree, lv->rdevice->lv,
|
||||
NULL))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add _rlog and replicator device */
|
||||
if (!_add_dev_to_dtree(dm, dtree, first_seg(rlv)->rlog_lv, NULL))
|
||||
return_0;
|
||||
|
||||
if (!_add_dev_to_dtree(dm, dtree, rlv, NULL))
|
||||
return_0;
|
||||
|
||||
if (!(uuid = build_dm_uuid(dm->mem, rlv, NULL)))
|
||||
return_0;
|
||||
|
||||
rep_node = dm_tree_find_node_by_uuid(dtree, uuid);
|
||||
|
||||
/* Add all related devices for replicator */
|
||||
dm_list_iterate_items(rsite, &rlv->rsites)
|
||||
dm_list_iterate_items(rdev, &rsite->rdevices) {
|
||||
if (rsite->state == REPLICATOR_STATE_ACTIVE) {
|
||||
/* Add _rimage LV */
|
||||
if (!_add_dev_to_dtree(dm, dtree, rdev->lv, NULL))
|
||||
return_0;
|
||||
|
||||
/* Add replicator-dev LV, except of the already added one */
|
||||
if ((lv != rdev->replicator_dev->lv) &&
|
||||
!_add_dev_to_dtree(dm, dtree,
|
||||
rdev->replicator_dev->lv, NULL))
|
||||
return_0;
|
||||
|
||||
/* If replicator exists - try connect existing heads */
|
||||
if (rep_node) {
|
||||
uuid = build_dm_uuid(dm->mem,
|
||||
rdev->replicator_dev->lv,
|
||||
NULL);
|
||||
if (!uuid)
|
||||
return_0;
|
||||
|
||||
rdev_node = dm_tree_find_node_by_uuid(dtree, uuid);
|
||||
if (rdev_node)
|
||||
dm_tree_node_set_presuspend_node(rdev_node,
|
||||
rep_node);
|
||||
}
|
||||
}
|
||||
|
||||
if (!rdev->rsite->vg_name)
|
||||
continue;
|
||||
|
||||
if (!_add_dev_to_dtree(dm, dtree, rdev->lv, NULL))
|
||||
return_0;
|
||||
|
||||
if (rdev->slog &&
|
||||
!_add_dev_to_dtree(dm, dtree, rdev->slog, NULL))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct pool_cb_data {
|
||||
struct dev_manager *dm;
|
||||
const struct logical_volume *pool_lv;
|
||||
@@ -2078,6 +2153,11 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
}
|
||||
}
|
||||
|
||||
/* Adding LV head of replicator adds all other related devs */
|
||||
if (lv_is_replicator_dev(lv) &&
|
||||
!_add_partial_replicator_to_dtree(dm, dtree, lv))
|
||||
return_0;
|
||||
|
||||
/* Add any LVs used by segments in this LV */
|
||||
dm_list_iterate_items(seg, &lv->segments) {
|
||||
if (seg->external_lv && dm->track_external_lv_deps &&
|
||||
@@ -2441,6 +2521,64 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
struct lv_activate_opts *laopts,
|
||||
const char *layer);
|
||||
|
||||
/* Add all replicators' LVs */
|
||||
static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm,
|
||||
struct dm_tree *dtree,
|
||||
struct lv_segment *seg,
|
||||
struct lv_activate_opts *laopts)
|
||||
{
|
||||
struct replicator_device *rdev;
|
||||
struct replicator_site *rsite;
|
||||
|
||||
/* For inactive replicator add linear mapping */
|
||||
if (!lv_is_active_replicator_dev(seg->lv)) {
|
||||
if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->rdevice->lv, laopts, NULL))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add rlog and replicator nodes */
|
||||
if (!seg->replicator ||
|
||||
!first_seg(seg->replicator)->rlog_lv ||
|
||||
!_add_new_lv_to_dtree(dm, dtree,
|
||||
first_seg(seg->replicator)->rlog_lv,
|
||||
laopts, NULL) ||
|
||||
!_add_new_lv_to_dtree(dm, dtree, seg->replicator, laopts, NULL))
|
||||
return_0;
|
||||
|
||||
/* Activation of one replicator_dev node activates all other nodes */
|
||||
dm_list_iterate_items(rsite, &seg->replicator->rsites) {
|
||||
dm_list_iterate_items(rdev, &rsite->rdevices) {
|
||||
if (rdev->lv &&
|
||||
!_add_new_lv_to_dtree(dm, dtree, rdev->lv,
|
||||
laopts, NULL))
|
||||
return_0;
|
||||
|
||||
if (rdev->slog &&
|
||||
!_add_new_lv_to_dtree(dm, dtree, rdev->slog,
|
||||
laopts, NULL))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
/* Add remaining replicator-dev nodes in the second loop
|
||||
* to avoid multiple retries for inserting all elements */
|
||||
dm_list_iterate_items(rsite, &seg->replicator->rsites) {
|
||||
if (rsite->state != REPLICATOR_STATE_ACTIVE)
|
||||
continue;
|
||||
dm_list_iterate_items(rdev, &rsite->rdevices) {
|
||||
if (rdev->replicator_dev->lv == seg->lv)
|
||||
continue;
|
||||
if (!rdev->replicator_dev->lv ||
|
||||
!_add_new_lv_to_dtree(dm, dtree,
|
||||
rdev->replicator_dev->lv,
|
||||
laopts, NULL))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_new_external_lv_to_dtree(struct dev_manager *dm,
|
||||
struct dm_tree *dtree,
|
||||
struct logical_volume *external_lv,
|
||||
@@ -2541,6 +2679,11 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
lv_layer(seg->pool_lv)))
|
||||
return_0;
|
||||
|
||||
if (seg_is_replicator_dev(seg)) {
|
||||
if (!_add_replicator_dev_target_to_dtree(dm, dtree, seg, laopts))
|
||||
return_0;
|
||||
}
|
||||
|
||||
/* Add any LVs used by this segment */
|
||||
for (s = 0; s < seg->area_count; ++s) {
|
||||
if ((seg_type(seg, s) == AREA_LV) &&
|
||||
|
@@ -186,11 +186,11 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
!stat(lv_path, &buf)) {
|
||||
if (buf_lp.st_rdev == buf.st_rdev)
|
||||
return 1;
|
||||
|
||||
log_warn("Symlink %s that should have been "
|
||||
"created by udev does not have "
|
||||
"correct target. Falling back to "
|
||||
"direct link creation", lv_path);
|
||||
else
|
||||
log_warn("Symlink %s that should have been "
|
||||
"created by udev does not have "
|
||||
"correct target. Falling back to "
|
||||
"direct link creation", lv_path);
|
||||
} else
|
||||
log_warn("Symlink %s that should have been "
|
||||
"created by udev could not be checked "
|
||||
@@ -239,9 +239,7 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
|
||||
return 1;
|
||||
log_sys_error("lstat", lv_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_udev_get_sync_support() && udev_checking() && check_udev)
|
||||
} else if (dm_udev_get_sync_support() && udev_checking() && check_udev)
|
||||
log_warn("The link %s should have been removed by udev "
|
||||
"but it is still present. Falling back to "
|
||||
"direct link removal.", lv_path);
|
||||
@@ -480,9 +478,9 @@ int fs_rename_lv(const struct logical_volume *lv, const char *dev,
|
||||
_fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
lv->name, dev, "", lv->vg->cmd->current_settings.udev_rules));
|
||||
}
|
||||
|
||||
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, old_lvname, lv->vg->cmd->current_settings.udev_rules);
|
||||
else
|
||||
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, old_lvname, lv->vg->cmd->current_settings.udev_rules);
|
||||
}
|
||||
|
||||
void fs_unlock(void)
|
||||
|
654
lib/cache/lvmcache.c
vendored
654
lib/cache/lvmcache.c
vendored
@@ -63,42 +63,15 @@ struct lvmcache_vginfo {
|
||||
char *lock_type;
|
||||
uint32_t mda_checksum;
|
||||
size_t mda_size;
|
||||
int independent_metadata_location; /* metadata read from independent areas */
|
||||
|
||||
/*
|
||||
* The following are not related to lvmcache or vginfo,
|
||||
* but are borrowing the vginfo to store the data.
|
||||
*
|
||||
* suspended_vg_* are used only by clvmd suspend/resume.
|
||||
* In suspend, both old (current) and new (precommitted)
|
||||
* metadata is saved. (Each in three forms: buffer, cft,
|
||||
* and vg). In resume, if the vg was committed
|
||||
* (suspended_vg_committed is set), then LVs are resumed
|
||||
* using the new metadata, but if the vg wasn't committed,
|
||||
* then LVs are resumed using the old metadata.
|
||||
*
|
||||
* suspended_vg_committed is set to 1 when clvmd gets
|
||||
* LCK_VG_COMMIT from vg_commit().
|
||||
*
|
||||
* These fields are only used between suspend and resume
|
||||
* in clvmd, and should never be used in any other way.
|
||||
* The contents of this data are never changed. This
|
||||
* data does not really belong in lvmcache, it's unrelated
|
||||
* to lvmcache or vginfo, but it's just a convenient place
|
||||
* for clvmd to stash the VG between suspend and resume
|
||||
* (since the same caller isn't present to pass the VG to
|
||||
* both suspend and resume in the case of clvmd.)
|
||||
*
|
||||
* This data is not really a "cache" of the VG, it is just
|
||||
* a location to pass the VG between suspend and resume.
|
||||
*/
|
||||
int suspended_vg_committed;
|
||||
char *suspended_vg_old_buf;
|
||||
struct dm_config_tree *suspended_vg_old_cft;
|
||||
struct volume_group *suspended_vg_old;
|
||||
char *suspended_vg_new_buf;
|
||||
struct dm_config_tree *suspended_vg_new_cft;
|
||||
struct volume_group *suspended_vg_new;
|
||||
size_t vgmetadata_size;
|
||||
char *vgmetadata; /* Copy of VG metadata as format_text string */
|
||||
struct dm_config_tree *cft; /* Config tree created from vgmetadata */
|
||||
/* Lifetime is directly tied to vgmetadata */
|
||||
struct volume_group *cached_vg;
|
||||
unsigned holders;
|
||||
unsigned vg_use_count; /* Counter of vg reusage */
|
||||
unsigned precommitted; /* Is vgmetadata live or precommitted? */
|
||||
unsigned cached_vg_invalidated; /* Signal to regenerate cached_vg */
|
||||
};
|
||||
|
||||
static struct dm_hash_table *_pvid_hash = NULL;
|
||||
@@ -165,7 +138,73 @@ void lvmcache_seed_infos_from_lvmetad(struct cmd_context *cmd)
|
||||
_has_scanned = 1;
|
||||
}
|
||||
|
||||
static void _update_cache_info_lock_state(struct lvmcache_info *info, int locked)
|
||||
/* Volume Group metadata cache functions */
|
||||
static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
if (!vginfo || !vginfo->vgmetadata)
|
||||
return;
|
||||
|
||||
dm_free(vginfo->vgmetadata);
|
||||
|
||||
vginfo->vgmetadata = NULL;
|
||||
|
||||
/* Release also cached config tree */
|
||||
if (vginfo->cft) {
|
||||
dm_config_destroy(vginfo->cft);
|
||||
vginfo->cft = NULL;
|
||||
}
|
||||
|
||||
log_debug_cache("Metadata cache: VG %s wiped.", vginfo->vgname);
|
||||
|
||||
release_vg(vginfo->cached_vg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache VG metadata against the vginfo with matching vgid.
|
||||
*/
|
||||
static void _store_metadata(struct volume_group *vg, unsigned precommitted)
|
||||
{
|
||||
char uuid[64] __attribute__((aligned(8)));
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(size = export_vg_to_buffer(vg, &data))) {
|
||||
stack;
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Avoid reparsing of the same data string */
|
||||
if (vginfo->vgmetadata && vginfo->vgmetadata_size == size &&
|
||||
strcmp(vginfo->vgmetadata, data) == 0)
|
||||
dm_free(data);
|
||||
else {
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
vginfo->vgmetadata_size = size;
|
||||
vginfo->vgmetadata = data;
|
||||
}
|
||||
|
||||
vginfo->precommitted = precommitted;
|
||||
|
||||
if (!id_write_format((const struct id *)vginfo->vgid, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug_cache("Metadata cache: VG %s (%s) stored (%" PRIsize_t " bytes%s).",
|
||||
vginfo->vgname, uuid, size,
|
||||
precommitted ? ", precommitted" : "");
|
||||
}
|
||||
|
||||
static void _update_cache_info_lock_state(struct lvmcache_info *info,
|
||||
int locked,
|
||||
int *cached_vgmetadata_valid)
|
||||
{
|
||||
int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
|
||||
|
||||
@@ -173,8 +212,10 @@ static void _update_cache_info_lock_state(struct lvmcache_info *info, int locked
|
||||
* Cache becomes invalid whenever lock state changes unless
|
||||
* exclusive VG_GLOBAL is held (i.e. while scanning).
|
||||
*/
|
||||
if (!lvmcache_vgname_is_locked(VG_GLOBAL) && (was_locked != locked))
|
||||
if (!lvmcache_vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
|
||||
info->status |= CACHE_INVALID;
|
||||
*cached_vgmetadata_valid = 0;
|
||||
}
|
||||
|
||||
if (locked)
|
||||
info->status |= CACHE_LOCKED;
|
||||
@@ -186,9 +227,14 @@ static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
|
||||
int locked)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
int cached_vgmetadata_valid = 1;
|
||||
|
||||
dm_list_iterate_items(info, &vginfo->infos)
|
||||
_update_cache_info_lock_state(info, locked);
|
||||
_update_cache_info_lock_state(info, locked,
|
||||
&cached_vgmetadata_valid);
|
||||
|
||||
if (!cached_vgmetadata_valid)
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
}
|
||||
|
||||
static void _update_cache_lock_state(const char *vgname, int locked)
|
||||
@@ -201,35 +247,6 @@ static void _update_cache_lock_state(const char *vgname, int locked)
|
||||
_update_cache_vginfo_lock_state(vginfo, locked);
|
||||
}
|
||||
|
||||
static void _suspended_vg_free(struct lvmcache_vginfo *vginfo, int free_old, int free_new)
|
||||
{
|
||||
if (free_old) {
|
||||
if (vginfo->suspended_vg_old_buf)
|
||||
dm_free(vginfo->suspended_vg_old_buf);
|
||||
if (vginfo->suspended_vg_old_cft)
|
||||
dm_config_destroy(vginfo->suspended_vg_old_cft);
|
||||
if (vginfo->suspended_vg_old)
|
||||
release_vg(vginfo->suspended_vg_old);
|
||||
|
||||
vginfo->suspended_vg_old_buf = NULL;
|
||||
vginfo->suspended_vg_old_cft = NULL;
|
||||
vginfo->suspended_vg_old = NULL;
|
||||
}
|
||||
|
||||
if (free_new) {
|
||||
if (vginfo->suspended_vg_new_buf)
|
||||
dm_free(vginfo->suspended_vg_new_buf);
|
||||
if (vginfo->suspended_vg_new_cft)
|
||||
dm_config_destroy(vginfo->suspended_vg_new_cft);
|
||||
if (vginfo->suspended_vg_new)
|
||||
release_vg(vginfo->suspended_vg_new);
|
||||
|
||||
vginfo->suspended_vg_new_buf = NULL;
|
||||
vginfo->suspended_vg_new_cft = NULL;
|
||||
vginfo->suspended_vg_new = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void _drop_metadata(const char *vgname, int drop_precommitted)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
@@ -238,98 +255,25 @@ static void _drop_metadata(const char *vgname, int drop_precommitted)
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
|
||||
return;
|
||||
|
||||
if (drop_precommitted)
|
||||
/*
|
||||
* Invalidate cached PV labels.
|
||||
* If cached precommitted metadata exists that means we
|
||||
* already invalidated the PV labels (before caching it)
|
||||
* and we must not do it again.
|
||||
*/
|
||||
if (!drop_precommitted && vginfo->precommitted && !vginfo->vgmetadata)
|
||||
log_error(INTERNAL_ERROR "metadata commit (or revert) missing before "
|
||||
"dropping metadata from cache.");
|
||||
|
||||
if (drop_precommitted || !vginfo->precommitted)
|
||||
dm_list_iterate_items(info, &vginfo->infos)
|
||||
info->status |= CACHE_INVALID;
|
||||
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
|
||||
/* VG revert */
|
||||
if (drop_precommitted)
|
||||
_suspended_vg_free(vginfo, 0, 1);
|
||||
else
|
||||
_suspended_vg_free(vginfo, 1, 1);
|
||||
}
|
||||
|
||||
void lvmcache_save_suspended_vg(struct volume_group *vg, int precommitted)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct format_instance *fid;
|
||||
struct format_instance_ctx fic;
|
||||
struct volume_group *susp_vg = NULL;
|
||||
struct dm_config_tree *susp_cft = NULL;
|
||||
char *susp_buf = NULL;
|
||||
size_t size;
|
||||
int new = precommitted;
|
||||
int old = !precommitted;
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id)))
|
||||
goto_bad;
|
||||
|
||||
/* already saved */
|
||||
if (old && vginfo->suspended_vg_old &&
|
||||
(vginfo->suspended_vg_old->seqno == vg->seqno))
|
||||
return;
|
||||
|
||||
/* already saved */
|
||||
if (new && vginfo->suspended_vg_new &&
|
||||
(vginfo->suspended_vg_new->seqno == vg->seqno))
|
||||
return;
|
||||
|
||||
_suspended_vg_free(vginfo, old, new);
|
||||
|
||||
if (!(size = export_vg_to_buffer(vg, &susp_buf)))
|
||||
goto_bad;
|
||||
|
||||
fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
|
||||
fic.context.vg_ref.vg_name = vginfo->vgname;
|
||||
fic.context.vg_ref.vg_id = vginfo->vgid;
|
||||
if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt, &fic)))
|
||||
goto_bad;
|
||||
|
||||
if (!(susp_cft = config_tree_from_string_without_dup_node_check(susp_buf)))
|
||||
goto_bad;
|
||||
|
||||
if (!(susp_vg = import_vg_from_config_tree(susp_cft, fid)))
|
||||
goto_bad;
|
||||
|
||||
if (old) {
|
||||
vginfo->suspended_vg_old_buf = susp_buf;
|
||||
vginfo->suspended_vg_old_cft = susp_cft;
|
||||
vginfo->suspended_vg_old = susp_vg;
|
||||
log_debug_cache("lvmcache saved suspended vg old seqno %d %s", vg->seqno, vg->name);
|
||||
} else {
|
||||
vginfo->suspended_vg_new_buf = susp_buf;
|
||||
vginfo->suspended_vg_new_cft = susp_cft;
|
||||
vginfo->suspended_vg_new = susp_vg;
|
||||
log_debug_cache("lvmcache saved suspended vg new seqno %d %s", vg->seqno, vg->name);
|
||||
}
|
||||
return;
|
||||
|
||||
bad:
|
||||
_suspended_vg_free(vginfo, old, new);
|
||||
log_debug_cache("lvmcache failed to save suspended pre %d vg %s", precommitted, vg->name);
|
||||
}
|
||||
|
||||
struct volume_group *lvmcache_get_suspended_vg(const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgid(vgid)))
|
||||
return_NULL;
|
||||
|
||||
|
||||
if (vginfo->suspended_vg_committed)
|
||||
return vginfo->suspended_vg_new;
|
||||
else
|
||||
return vginfo->suspended_vg_old;
|
||||
}
|
||||
|
||||
void lvmcache_drop_suspended_vg(struct volume_group *vg)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id)))
|
||||
return;
|
||||
|
||||
_suspended_vg_free(vginfo, 1, 1);
|
||||
vginfo->precommitted = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -344,7 +288,11 @@ void lvmcache_commit_metadata(const char *vgname)
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
|
||||
return;
|
||||
|
||||
vginfo->suspended_vg_committed = 1;
|
||||
if (vginfo->precommitted) {
|
||||
log_debug_cache("Precommitted metadata cache: VG %s upgraded to committed.",
|
||||
vginfo->vgname);
|
||||
vginfo->precommitted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted)
|
||||
@@ -594,6 +542,7 @@ const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd,
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
struct label *label;
|
||||
struct dm_list *devh, *tmp;
|
||||
struct dm_list devs;
|
||||
struct device_list *devl;
|
||||
@@ -638,7 +587,7 @@ const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd,
|
||||
|
||||
dm_list_iterate_safe(devh, tmp, &devs) {
|
||||
devl = dm_list_item(devh, struct device_list);
|
||||
label_read(devl->dev, NULL, UINT64_C(0));
|
||||
(void) label_read(devl->dev, &label, UINT64_C(0));
|
||||
dm_list_del(&devl->list);
|
||||
dm_free(devl);
|
||||
}
|
||||
@@ -726,6 +675,18 @@ static int _info_is_valid(struct lvmcache_info *info)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* Invalid if any info is invalid */
|
||||
dm_list_iterate_items(info, &vginfo->infos)
|
||||
if (!_info_is_valid(info))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* vginfo is invalid if it does not contain at least one valid info */
|
||||
static int _vginfo_is_invalid(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
@@ -791,7 +752,7 @@ char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid)
|
||||
struct lvmcache_info *info;
|
||||
char *vgname;
|
||||
|
||||
if (!lvmcache_device_from_pvid(cmd, (const struct id *)pvid, NULL)) {
|
||||
if (!lvmcache_device_from_pvid(cmd, (const struct id *)pvid, NULL, NULL)) {
|
||||
log_error("Couldn't find device with uuid %s.", pvid);
|
||||
return NULL;
|
||||
}
|
||||
@@ -807,42 +768,19 @@ char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid)
|
||||
return vgname;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: get rid of the CACHE_INVALID state and rescanning
|
||||
* infos with that flag. The code should just know which devices
|
||||
* need scanning and when.
|
||||
*/
|
||||
static int _label_scan_invalid(struct cmd_context *cmd)
|
||||
static void _rescan_entry(struct lvmcache_info *info)
|
||||
{
|
||||
struct dm_list devs;
|
||||
struct dm_hash_node *n;
|
||||
struct device_list *devl;
|
||||
struct lvmcache_info *info;
|
||||
int dev_count = 0;
|
||||
int ret;
|
||||
struct label *label;
|
||||
|
||||
dm_list_init(&devs);
|
||||
if (info->status & CACHE_INVALID)
|
||||
(void) label_read(info->dev, &label, UINT64_C(0));
|
||||
}
|
||||
|
||||
dm_hash_iterate(n, _pvid_hash) {
|
||||
if (!(info = dm_hash_get_data(_pvid_hash, n)))
|
||||
continue;
|
||||
static int _scan_invalid(void)
|
||||
{
|
||||
dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _rescan_entry);
|
||||
|
||||
if (!(info->status & CACHE_INVALID))
|
||||
continue;
|
||||
|
||||
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
|
||||
return_0;
|
||||
|
||||
devl->dev = info->dev;
|
||||
dm_list_add(&devs, &devl->list);
|
||||
dev_count++;
|
||||
}
|
||||
|
||||
log_debug_cache("Scanning %d devs with invalid info.", dev_count);
|
||||
|
||||
ret = label_scan_devs(cmd, &devs);
|
||||
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1157,89 +1095,17 @@ next:
|
||||
goto next;
|
||||
}
|
||||
|
||||
/*
|
||||
* The initial label_scan at the start of the command is done without
|
||||
* holding VG locks. Then for each VG identified during the label_scan,
|
||||
* vg_read(vgname) is called while holding the VG lock. The labels
|
||||
* and metadata on this VG's devices could have changed between the
|
||||
* initial unlocked label_scan and the current vg_read(). So, we reread
|
||||
* the labels/metadata for each device in the VG now that we hold the
|
||||
* lock, and use this for processing the VG.
|
||||
*
|
||||
* FIXME: In some cases, the data read by label_scan may be fine, and not
|
||||
* need to be reread here. e.g. a reporting command, possibly with a
|
||||
* special option, could skip this second reread. Or, we could look
|
||||
* at the VG seqno in each copy of the metadata read in the first label
|
||||
* scan, and if they all match, consider it good enough to use for
|
||||
* reporting without rereading it. (A command modifying the VG would
|
||||
* always want to reread while the lock is held before modifying.)
|
||||
*
|
||||
* A label scan is ultimately creating associations between devices
|
||||
* and VGs so that when vg_read wants to get VG metadata, it knows
|
||||
* which devices to read. In the special case where VG metadata is
|
||||
* stored in files on the file system (configured in lvm.conf), the
|
||||
* vginfo->independent_metadata_location flag is set during label scan.
|
||||
* When we get here to rescan, we are revalidating the device to VG
|
||||
* mapping from label scan by repeating the label scan on a subset of
|
||||
* devices. If we see independent_metadata_location is set from the
|
||||
* initial label scan, we know that there is nothing to do because
|
||||
* there is no device to VG mapping to revalidate, since the VG metadata
|
||||
* comes directly from files.
|
||||
*/
|
||||
|
||||
int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid)
|
||||
{
|
||||
struct dm_list devs;
|
||||
struct device_list *devl;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (lvmetad_used())
|
||||
return 1;
|
||||
|
||||
dm_list_init(&devs);
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* When the VG metadata is from an independent location,
|
||||
* then rescanning the devices in the VG won't find the
|
||||
* metadata, and will destroy the vginfo/info associations
|
||||
* that were created during label scan when the
|
||||
* independent locations were read.
|
||||
*/
|
||||
if (vginfo->independent_metadata_location)
|
||||
return 1;
|
||||
|
||||
dm_list_iterate_items(info, &vginfo->infos) {
|
||||
if (!(devl = dm_malloc(sizeof(*devl)))) {
|
||||
log_error("device_list element allocation failed");
|
||||
return 0;
|
||||
}
|
||||
devl->dev = info->dev;
|
||||
dm_list_add(&devs, &devl->list);
|
||||
}
|
||||
|
||||
label_scan_devs(cmd, &devs);
|
||||
|
||||
/*
|
||||
* TODO: grab vginfo again, and compare vginfo->infos
|
||||
* to what was found above before rereading labels.
|
||||
* If there are any info->devs now that were not in the
|
||||
* first devs list, then do label_read on those also.
|
||||
*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
{
|
||||
struct dm_list del_cache_devs;
|
||||
struct dm_list add_cache_devs;
|
||||
struct lvmcache_info *info;
|
||||
struct device_list *devl;
|
||||
struct label *label;
|
||||
struct dev_iter *iter;
|
||||
struct device *dev;
|
||||
struct format_type *fmt;
|
||||
int dev_count = 0;
|
||||
|
||||
int r = 0;
|
||||
|
||||
@@ -1257,40 +1123,34 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan devices whose info struct has the INVALID flag set.
|
||||
* When scanning has read the pv_header, mda_header and
|
||||
* mda locations, it will clear the INVALID flag (via
|
||||
* lvmcache_make_valid).
|
||||
*/
|
||||
if (_has_scanned && !_force_label_scan) {
|
||||
r = _label_scan_invalid(cmd);
|
||||
r = _scan_invalid();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (_force_label_scan && (cmd->full_filter && !cmd->full_filter->use_count) && !refresh_filters(cmd))
|
||||
goto_out;
|
||||
|
||||
if (!cmd->full_filter) {
|
||||
log_error("label scan is missing full filter");
|
||||
if (!cmd->full_filter || !(iter = dev_iter_create(cmd->full_filter, _force_label_scan))) {
|
||||
log_error("dev_iter creation failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_very_verbose("Scanning device labels");
|
||||
|
||||
/*
|
||||
* Duplicates found during this label scan are added to _found_duplicate_devs().
|
||||
*/
|
||||
_destroy_duplicate_device_list(&_found_duplicate_devs);
|
||||
|
||||
/*
|
||||
* Do the actual scanning. This populates lvmcache
|
||||
* with infos/vginfos based on reading headers from
|
||||
* each device, and a vg summary from each mda.
|
||||
*
|
||||
* Note that this will *skip* scanning a device if
|
||||
* an info struct already exists in lvmcache for
|
||||
* the device.
|
||||
*/
|
||||
label_scan(cmd);
|
||||
while ((dev = dev_iter_get(iter))) {
|
||||
(void) label_read(dev, &label, UINT64_C(0));
|
||||
dev_count++;
|
||||
}
|
||||
|
||||
dev_iter_destroy(iter);
|
||||
|
||||
log_very_verbose("Scanned %d device labels", dev_count);
|
||||
|
||||
/*
|
||||
* _choose_preferred_devs() returns:
|
||||
@@ -1324,7 +1184,7 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
|
||||
dm_list_iterate_items(devl, &add_cache_devs) {
|
||||
log_debug_cache("Rescan preferred device %s for lvmcache", dev_name(devl->dev));
|
||||
label_read(devl->dev, NULL, UINT64_C(0));
|
||||
(void) label_read(devl->dev, &label, UINT64_C(0));
|
||||
}
|
||||
|
||||
dm_list_splice(&_unused_duplicate_devs, &del_cache_devs);
|
||||
@@ -1356,12 +1216,129 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
return r;
|
||||
}
|
||||
|
||||
struct volume_group *lvmcache_get_vg(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid, unsigned precommitted)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct volume_group *vg = NULL;
|
||||
struct format_instance *fid;
|
||||
struct format_instance_ctx fic;
|
||||
|
||||
/*
|
||||
* We currently do not store precommitted metadata in lvmetad at
|
||||
* all. This means that any request for precommitted metadata is served
|
||||
* using the classic scanning mechanics, and read from disk or from
|
||||
* lvmcache.
|
||||
*/
|
||||
if (lvmetad_used() && !precommitted) {
|
||||
/* Still serve the locally cached VG if available */
|
||||
if (vgid && (vginfo = lvmcache_vginfo_from_vgid(vgid)) &&
|
||||
vginfo->vgmetadata && (vg = vginfo->cached_vg))
|
||||
goto out;
|
||||
return lvmetad_vg_lookup(cmd, vgname, vgid);
|
||||
}
|
||||
|
||||
if (!vgid || !(vginfo = lvmcache_vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
|
||||
return NULL;
|
||||
|
||||
if (!_vginfo_is_valid(vginfo))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Don't return cached data if either:
|
||||
* (i) precommitted metadata is requested but we don't have it cached
|
||||
* - caller should read it off disk;
|
||||
* (ii) live metadata is requested but we have precommitted metadata cached
|
||||
* and no devices are suspended so caller may read it off disk.
|
||||
*
|
||||
* If live metadata is requested but we have precommitted metadata cached
|
||||
* and devices are suspended, we assume this precommitted metadata has
|
||||
* already been preloaded and committed so it's OK to return it as live.
|
||||
* Note that we do not clear the PRECOMMITTED flag.
|
||||
*/
|
||||
if ((precommitted && !vginfo->precommitted) ||
|
||||
(!precommitted && vginfo->precommitted && !critical_section()))
|
||||
return NULL;
|
||||
|
||||
/* Use already-cached VG struct when available */
|
||||
if ((vg = vginfo->cached_vg) && !vginfo->cached_vg_invalidated)
|
||||
goto out;
|
||||
|
||||
release_vg(vginfo->cached_vg);
|
||||
|
||||
fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
|
||||
fic.context.vg_ref.vg_name = vginfo->vgname;
|
||||
fic.context.vg_ref.vg_id = vgid;
|
||||
if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt, &fic)))
|
||||
return_NULL;
|
||||
|
||||
/* Build config tree from vgmetadata, if not yet cached */
|
||||
if (!vginfo->cft &&
|
||||
!(vginfo->cft =
|
||||
config_tree_from_string_without_dup_node_check(vginfo->vgmetadata)))
|
||||
goto_bad;
|
||||
|
||||
if (!(vg = import_vg_from_config_tree(vginfo->cft, fid)))
|
||||
goto_bad;
|
||||
|
||||
/* Cache VG struct for reuse */
|
||||
vginfo->cached_vg = vg;
|
||||
vginfo->holders = 1;
|
||||
vginfo->vg_use_count = 0;
|
||||
vginfo->cached_vg_invalidated = 0;
|
||||
vg->vginfo = vginfo;
|
||||
|
||||
if (!dm_pool_lock(vg->vgmem, detect_internal_vg_cache_corruption()))
|
||||
goto_bad;
|
||||
|
||||
out:
|
||||
vginfo->holders++;
|
||||
vginfo->vg_use_count++;
|
||||
log_debug_cache("Using cached %smetadata for VG %s with %u holder(s).",
|
||||
vginfo->precommitted ? "pre-committed " : "",
|
||||
vginfo->vgname, vginfo->holders);
|
||||
|
||||
return vg;
|
||||
|
||||
bad:
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// #if 0
|
||||
int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
log_debug_cache("VG %s decrementing %d holder(s) at %p.",
|
||||
vginfo->cached_vg->name, vginfo->holders, vginfo->cached_vg);
|
||||
|
||||
if (--vginfo->holders)
|
||||
return 0;
|
||||
|
||||
if (vginfo->vg_use_count > 1)
|
||||
log_debug_cache("VG %s reused %d times.",
|
||||
vginfo->cached_vg->name, vginfo->vg_use_count);
|
||||
|
||||
/* Debug perform crc check only when it's been used more then once */
|
||||
if (!dm_pool_unlock(vginfo->cached_vg->vgmem,
|
||||
detect_internal_vg_cache_corruption() &&
|
||||
(vginfo->vg_use_count > 1)))
|
||||
stack;
|
||||
|
||||
vginfo->cached_vg->vginfo = NULL;
|
||||
vginfo->cached_vg = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
// #endif
|
||||
|
||||
int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
|
||||
struct dm_list *vgnameids)
|
||||
{
|
||||
struct vgnameid_list *vgnl;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
lvmcache_label_scan(cmd);
|
||||
|
||||
dm_list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!include_internal && is_orphan_vg(vginfo->vgname))
|
||||
continue;
|
||||
@@ -1466,45 +1443,61 @@ struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
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)
|
||||
static struct device *_device_from_pvid(const struct id *pvid,
|
||||
uint64_t *label_sector)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
struct label *label;
|
||||
|
||||
if ((info = lvmcache_info_from_pvid((const char *) pvid, NULL, 0))) {
|
||||
if (info->label && label_sector)
|
||||
*label_sector = info->label->sector;
|
||||
return info->dev;
|
||||
}
|
||||
if (lvmetad_used()) {
|
||||
if (info->label && label_sector)
|
||||
*label_sector = info->label->sector;
|
||||
return info->dev;
|
||||
}
|
||||
|
||||
if (label_read(info->dev, &label, UINT64_C(0))) {
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
if (id_equal(pvid, (struct id *) &info->dev->pvid)) {
|
||||
if (label_sector)
|
||||
*label_sector = label->sector;
|
||||
return info->dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector)
|
||||
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
|
||||
unsigned *scan_done_once, uint64_t *label_sector)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
/* Already cached ? */
|
||||
dev = _device_from_pvid(pvid, label_sector);
|
||||
if (dev)
|
||||
return dev;
|
||||
|
||||
lvmcache_label_scan(cmd);
|
||||
|
||||
/* Try again */
|
||||
dev = _device_from_pvid(pvid, label_sector);
|
||||
if (dev)
|
||||
return dev;
|
||||
|
||||
if (critical_section() || (scan_done_once && *scan_done_once))
|
||||
return NULL;
|
||||
|
||||
lvmcache_force_next_label_scan();
|
||||
lvmcache_label_scan(cmd);
|
||||
if (scan_done_once)
|
||||
*scan_done_once = 1;
|
||||
|
||||
/* Try again */
|
||||
dev = _device_from_pvid(pvid, label_sector);
|
||||
if (dev)
|
||||
return dev;
|
||||
|
||||
log_debug_devs("No device with uuid %s.", (const char *)pvid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1512,6 +1505,7 @@ const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
|
||||
const char *devname)
|
||||
{
|
||||
struct device *dev;
|
||||
struct label *label;
|
||||
|
||||
if (!(dev = dev_cache_get(devname, cmd->filter))) {
|
||||
log_error("%s: Couldn't find device. Check your filters?",
|
||||
@@ -1519,7 +1513,7 @@ const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!label_read(dev, NULL, UINT64_C(0)))
|
||||
if (!(label_read(dev, &label, UINT64_C(0))))
|
||||
return NULL;
|
||||
|
||||
return dev->pvid;
|
||||
@@ -1541,6 +1535,8 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
|
||||
struct lvmcache_vginfo *primary_vginfo, *vginfo2;
|
||||
int r = 1;
|
||||
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
|
||||
vginfo2 = primary_vginfo = lvmcache_vginfo_from_vgname(vginfo->vgname, NULL);
|
||||
|
||||
if (vginfo == primary_vginfo) {
|
||||
@@ -1563,7 +1559,6 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
|
||||
dm_free(vginfo->system_id);
|
||||
dm_free(vginfo->vgname);
|
||||
dm_free(vginfo->creation_host);
|
||||
_suspended_vg_free(vginfo, 1, 1);
|
||||
|
||||
if (*vginfo->vgid && _vgid_hash &&
|
||||
lvmcache_vginfo_from_vgid(vginfo->vgid) == vginfo)
|
||||
@@ -1605,6 +1600,8 @@ void lvmcache_del(struct lvmcache_info *info)
|
||||
info->label->labeller->ops->destroy_label(info->label->labeller,
|
||||
info->label);
|
||||
dm_free(info);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1901,7 +1898,8 @@ static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstat
|
||||
info->vginfo->creation_host))
|
||||
goto set_lock_type;
|
||||
|
||||
dm_free(info->vginfo->creation_host);
|
||||
if (info->vginfo->creation_host)
|
||||
dm_free(info->vginfo->creation_host);
|
||||
|
||||
if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
|
||||
log_error("cache creation host alloc failed for %s.",
|
||||
@@ -1920,7 +1918,8 @@ set_lock_type:
|
||||
if (info->vginfo->lock_type && !strcmp(lock_type, info->vginfo->lock_type))
|
||||
goto set_system_id;
|
||||
|
||||
dm_free(info->vginfo->lock_type);
|
||||
if (info->vginfo->lock_type)
|
||||
dm_free(info->vginfo->lock_type);
|
||||
|
||||
if (!(info->vginfo->lock_type = dm_strdup(lock_type))) {
|
||||
log_error("cache lock_type alloc failed for %s", lock_type);
|
||||
@@ -1938,7 +1937,8 @@ set_system_id:
|
||||
if (info->vginfo->system_id && !strcmp(system_id, info->vginfo->system_id))
|
||||
goto out;
|
||||
|
||||
dm_free(info->vginfo->system_id);
|
||||
if (info->vginfo->system_id)
|
||||
dm_free(info->vginfo->system_id);
|
||||
|
||||
if (!(info->vginfo->system_id = dm_strdup(system_id))) {
|
||||
log_error("cache system_id alloc failed for %s", system_id);
|
||||
@@ -2002,6 +2002,12 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, struct lvmcache_vg
|
||||
!is_orphan_vg(info->vginfo->vgname) && critical_section())
|
||||
return 1;
|
||||
|
||||
/* If making a PV into an orphan, any cached VG metadata may become
|
||||
* invalid, incorrectly still referencing device structs.
|
||||
* (Example: pvcreate -ff) */
|
||||
if (is_orphan_vg(vgname) && info->vginfo && !is_orphan_vg(info->vginfo->vgname))
|
||||
info->vginfo->cached_vg_invalidated = 1;
|
||||
|
||||
/* If moving PV from orphan to real VG, always mark it valid */
|
||||
if (!is_orphan_vg(vgname))
|
||||
info->status &= ~CACHE_INVALID;
|
||||
@@ -2039,6 +2045,10 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
|
||||
return_0;
|
||||
}
|
||||
|
||||
/* store text representation of vg to cache */
|
||||
if (vg->cmd->current_settings.cache_vgmetadata)
|
||||
_store_metadata(vg, precommitted);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2602,10 +2612,6 @@ struct label *lvmcache_get_label(struct lvmcache_info *info) {
|
||||
return info->label;
|
||||
}
|
||||
|
||||
/*
|
||||
* After label_scan reads pv_header, mda_header and mda locations
|
||||
* from a PV, it clears the INVALID flag.
|
||||
*/
|
||||
void lvmcache_make_valid(struct lvmcache_info *info) {
|
||||
info->status &= ~CACHE_INVALID;
|
||||
}
|
||||
@@ -2661,14 +2667,6 @@ int lvmcache_vgid_is_cached(const char *vgid) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void lvmcache_set_independent_location(const char *vgname)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if ((vginfo = lvmcache_vginfo_from_vgname(vgname, NULL)))
|
||||
vginfo->independent_metadata_location = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true iff it is impossible to find out from this info alone whether the
|
||||
* PV in question is or is not an orphan.
|
||||
|
20
lib/cache/lvmcache.h
vendored
20
lib/cache/lvmcache.h
vendored
@@ -74,7 +74,6 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset);
|
||||
*/
|
||||
void lvmcache_force_next_label_scan(void);
|
||||
int lvmcache_label_scan(struct cmd_context *cmd);
|
||||
int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid);
|
||||
|
||||
/* Add/delete a device */
|
||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
@@ -106,8 +105,10 @@ struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
|
||||
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *dev, int valid_only);
|
||||
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||
const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgname);
|
||||
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
|
||||
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd, const char *devname);
|
||||
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
|
||||
unsigned *scan_done_once, uint64_t *label_sector);
|
||||
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
|
||||
const char *devname);
|
||||
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
|
||||
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
|
||||
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
|
||||
@@ -133,6 +134,9 @@ int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
|
||||
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid);
|
||||
|
||||
/* Returns cached volume group metadata. */
|
||||
struct volume_group *lvmcache_get_vg(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid, unsigned precommitted);
|
||||
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
|
||||
void lvmcache_commit_metadata(const char *vgname);
|
||||
|
||||
@@ -177,7 +181,7 @@ int lvmcache_foreach_ba(struct lvmcache_info *info,
|
||||
int (*fun)(struct disk_locn *, void *),
|
||||
void *baton);
|
||||
|
||||
int lvmcache_foreach_pv(struct lvmcache_vginfo *vginfo,
|
||||
int lvmcache_foreach_pv(struct lvmcache_vginfo *vg,
|
||||
int (*fun)(struct lvmcache_info *, void *), void * baton);
|
||||
|
||||
uint64_t lvmcache_device_size(struct lvmcache_info *info);
|
||||
@@ -211,12 +215,4 @@ void lvmcache_remove_unchosen_duplicate(struct device *dev);
|
||||
|
||||
int lvmcache_pvid_in_unchosen_duplicates(const char *pvid);
|
||||
|
||||
void lvmcache_save_suspended_vg(struct volume_group *vg, int precommitted);
|
||||
struct volume_group *lvmcache_get_suspended_vg(const char *vgid);
|
||||
void lvmcache_drop_suspended_vg(struct volume_group *vg);
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
508
lib/cache/lvmetad.c
vendored
508
lib/cache/lvmetad.c
vendored
@@ -39,7 +39,7 @@ static int64_t _lvmetad_update_timeout;
|
||||
|
||||
static int _found_lvm1_metadata = 0;
|
||||
|
||||
static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg, const char *vgid, struct format_type *fmt);
|
||||
static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg);
|
||||
|
||||
static uint64_t _monotonic_seconds(void)
|
||||
{
|
||||
@@ -145,14 +145,13 @@ int lvmetad_connect(struct cmd_context *cmd)
|
||||
_lvmetad_use = 1;
|
||||
_lvmetad_cmd = cmd;
|
||||
return 1;
|
||||
} else {
|
||||
log_debug_lvmetad("Failed to connect to lvmetad: %s", strerror(_lvmetad.error));
|
||||
_lvmetad_connected = 0;
|
||||
_lvmetad_use = 0;
|
||||
_lvmetad_cmd = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug_lvmetad("Failed to connect to lvmetad: %s", strerror(_lvmetad.error));
|
||||
_lvmetad_connected = 0;
|
||||
_lvmetad_use = 0;
|
||||
_lvmetad_cmd = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lvmetad_used(void)
|
||||
@@ -663,7 +662,7 @@ static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char
|
||||
}
|
||||
|
||||
if (reply.error) {
|
||||
log_error("lvmetad cannot be used due to error: %s", strerror(reply.error));
|
||||
log_warn("WARNING: lvmetad cannot be used due to error: %s", strerror(reply.error));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -1090,17 +1089,14 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
|
||||
* invalidated the cached vg.
|
||||
*/
|
||||
if (rescan) {
|
||||
if (!(vg2 = _lvmetad_pvscan_vg(cmd, vg, vgid, fmt))) {
|
||||
if (!(vg2 = lvmetad_pvscan_vg(cmd, vg))) {
|
||||
log_debug_lvmetad("VG %s from lvmetad not found during rescan.", vgname);
|
||||
fid = NULL;
|
||||
release_vg(vg);
|
||||
vg = NULL;
|
||||
goto out;
|
||||
}
|
||||
fid->ref_count++;
|
||||
release_vg(vg);
|
||||
fid->ref_count--;
|
||||
fmt->ops->destroy_instance(fid);
|
||||
vg = vg2;
|
||||
fid = vg2->fid;
|
||||
}
|
||||
@@ -1108,14 +1104,14 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!_pv_update_struct_pv(pvl->pv, fid)) {
|
||||
vg = NULL;
|
||||
goto_out; /* FIXME: use an error path that disables lvmetad */
|
||||
goto_out; /* FIXME error path */
|
||||
}
|
||||
}
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs_outdated) {
|
||||
if (!_pv_update_struct_pv(pvl->pv, fid)) {
|
||||
vg = NULL;
|
||||
goto_out; /* FIXME: use an error path that disables lvmetad */
|
||||
goto_out; /* FIXME error path */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1284,7 +1280,7 @@ int lvmetad_vg_update_finish(struct volume_group *vg)
|
||||
if (pvl->pv->dev && !lvmetad_pv_found(vg->cmd, &pvl->pv->id, pvl->pv->dev,
|
||||
vgu->fid ? vgu->fid->fmt : pvl->pv->fmt,
|
||||
pvl->pv->label_sector, NULL, NULL, NULL))
|
||||
return_0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
vg->lvmetad_update_pending = 0;
|
||||
@@ -1759,7 +1755,6 @@ int lvmetad_pv_gone_by_dev(struct device *dev)
|
||||
*/
|
||||
|
||||
struct _lvmetad_pvscan_baton {
|
||||
struct cmd_context *cmd;
|
||||
struct volume_group *vg;
|
||||
struct format_instance *fid;
|
||||
};
|
||||
@@ -1767,14 +1762,10 @@ struct _lvmetad_pvscan_baton {
|
||||
static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
|
||||
{
|
||||
struct _lvmetad_pvscan_baton *b = baton;
|
||||
struct device *mda_dev = mda_get_device(mda);
|
||||
struct label_read_data *ld;
|
||||
struct volume_group *vg;
|
||||
|
||||
ld = get_label_read_data(b->cmd, mda_dev);
|
||||
|
||||
if (mda_is_ignored(mda) ||
|
||||
!(vg = mda->ops->vg_read(b->fid, "", mda, ld, NULL, NULL)))
|
||||
!(vg = mda->ops->vg_read(b->fid, "", mda, NULL, NULL, 1)))
|
||||
return 1;
|
||||
|
||||
/* FIXME Also ensure contents match etc. */
|
||||
@@ -1786,37 +1777,6 @@ static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: handle errors and do proper comparison of metadata from each area
|
||||
* like vg_read and fall back to real vg_read from disk if there's any problem.
|
||||
*/
|
||||
|
||||
static int _lvmetad_pvscan_vg_single(struct metadata_area *mda, void *baton)
|
||||
{
|
||||
struct _lvmetad_pvscan_baton *b = baton;
|
||||
struct device *mda_dev = mda_get_device(mda);
|
||||
struct label_read_data *ld;
|
||||
struct volume_group *vg = NULL;
|
||||
|
||||
if (mda_is_ignored(mda))
|
||||
return 1;
|
||||
|
||||
ld = get_label_read_data(b->cmd, mda_dev);
|
||||
|
||||
if (!(vg = mda->ops->vg_read(b->fid, "", mda, ld, NULL, NULL)))
|
||||
return 1;
|
||||
|
||||
if (!b->vg)
|
||||
b->vg = vg;
|
||||
else if (vg->seqno > b->vg->seqno) {
|
||||
release_vg(b->vg);
|
||||
b->vg = vg;
|
||||
} else
|
||||
release_vg(vg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lock manager may detect that the vg cached in lvmetad is out of date,
|
||||
* due to something like an lvcreate from another host.
|
||||
@@ -1826,41 +1786,41 @@ static int _lvmetad_pvscan_vg_single(struct metadata_area *mda, void *baton)
|
||||
* the VG, and that PV may have been reused for another VG.
|
||||
*/
|
||||
|
||||
static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
const char *vgid, struct format_type *fmt)
|
||||
static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
|
||||
char uuid[64] __attribute__((aligned(8)));
|
||||
struct label *label;
|
||||
struct volume_group *vg_ret = NULL;
|
||||
struct dm_config_tree *vgmeta_ret = NULL;
|
||||
struct dm_config_tree *vgmeta;
|
||||
struct pv_list *pvl, *pvl_new;
|
||||
struct device_list *devl, *devlsafe;
|
||||
struct device_list *devl, *devl_new, *devlsafe;
|
||||
struct dm_list pvs_scan;
|
||||
struct dm_list pvs_drop;
|
||||
struct lvmcache_vginfo *vginfo = NULL;
|
||||
struct dm_list pvs_new;
|
||||
struct lvmcache_info *info = NULL;
|
||||
struct format_instance *fid;
|
||||
struct format_instance_ctx fic = { .type = 0 };
|
||||
struct _lvmetad_pvscan_baton baton;
|
||||
struct volume_group *save_vg;
|
||||
struct dm_config_tree *save_meta;
|
||||
struct device *save_dev = NULL;
|
||||
uint32_t save_seqno = 0;
|
||||
int found_new_pvs = 0;
|
||||
int retried_reads = 0;
|
||||
int missing_devs = 0;
|
||||
int check_new_pvs = 0;
|
||||
int found;
|
||||
|
||||
save_vg = NULL;
|
||||
save_meta = NULL;
|
||||
save_dev = NULL;
|
||||
save_seqno = 0;
|
||||
|
||||
dm_list_init(&pvs_scan);
|
||||
dm_list_init(&pvs_drop);
|
||||
dm_list_init(&pvs_new);
|
||||
|
||||
log_debug_lvmetad("Rescan VG %s to update lvmetad (seqno %u).", vg->name, vg->seqno);
|
||||
log_debug_lvmetad("Rescanning VG %s (seqno %u).", vg->name, vg->seqno);
|
||||
|
||||
/*
|
||||
* Make sure this command knows about all PVs from lvmetad.
|
||||
* Another host may have added a PV to the VG, and some
|
||||
* commands do not always populate their lvmcache with
|
||||
* all devs from lvmetad, so they would fail to find
|
||||
* the new PV when scanning the VG. So make sure this
|
||||
* command knows about all PVs from lvmetad.
|
||||
*/
|
||||
lvmcache_seed_infos_from_lvmetad(cmd);
|
||||
|
||||
@@ -1875,111 +1835,54 @@ static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct v
|
||||
dm_list_add(&pvs_scan, &devl->list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rescan labels/metadata only from devs that we previously
|
||||
* saw in the VG. If we find below that there are new PVs
|
||||
* in the VG, we'll have to rescan all devices to find which
|
||||
* device(s) are now being used.
|
||||
*/
|
||||
log_debug_lvmetad("Rescan VG %s scanning data from devs in previous metadata.", vg->name);
|
||||
|
||||
label_scan_devs(cmd, &pvs_scan);
|
||||
scan_more:
|
||||
|
||||
/*
|
||||
* Check if any pvs_scan entries are no longer PVs.
|
||||
* In that case, label_read/_find_label_header will have
|
||||
* found no label_header, and would have dropped the
|
||||
* info struct for the device from lvmcache. So, if
|
||||
* we look up the info struct here and don't find it,
|
||||
* we can infer it's no longer a PV.
|
||||
*
|
||||
* FIXME: we should record specific results from the
|
||||
* label_read and then check specifically for whatever
|
||||
* result means "no label was found", rather than going
|
||||
* about this indirectly via the lvmcache side effects.
|
||||
*/
|
||||
dm_list_iterate_items_safe(devl, devlsafe, &pvs_scan) {
|
||||
if (!(info = lvmcache_info_from_pvid(devl->dev->pvid, devl->dev, 0))) {
|
||||
/* Another host removed this PV from the VG. */
|
||||
log_debug_lvmetad("Rescan VG %s from %s dropping dev (no label).",
|
||||
vg->name, dev_name(devl->dev));
|
||||
dm_list_move(&pvs_drop, &devl->list);
|
||||
}
|
||||
}
|
||||
|
||||
fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
|
||||
fic.context.vg_ref.vg_name = vg->name;
|
||||
fic.context.vg_ref.vg_id = vgid;
|
||||
|
||||
retry_reads:
|
||||
|
||||
if (!(fid = fmt->ops->create_instance(fmt, &fic))) {
|
||||
/* FIXME: are there only internal reasons for failures here? */
|
||||
log_error("Reading VG %s failed to create format instance.", vg->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* FIXME: not sure if this is necessary */
|
||||
fid->ref_count++;
|
||||
|
||||
baton.fid = fid;
|
||||
baton.cmd = cmd;
|
||||
|
||||
/*
|
||||
* FIXME: this vg_read path does not have the ability to repair
|
||||
* any problems with the VG, e.g. VG on one dev has an older
|
||||
* seqno. When vg_read() is reworked, we need to fall back
|
||||
* to using that from here (and vg_read's from lvmetad) when
|
||||
* there is a problem. Perhaps by disabling lvmetad when a
|
||||
* VG problem is detected, causing commands to fully fall
|
||||
* back to disk, which will repair the VG. Then lvmetad can
|
||||
* be repopulated and re-enabled (possibly automatically.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Do a low level vg_read on each dev, verify the vg returned
|
||||
* from metadata on each device is for the VG being read
|
||||
* (the PV may have been removed from the VG being read and
|
||||
* added to a different one), and return this vg to the caller
|
||||
* as the current vg to use.
|
||||
*
|
||||
* The label scan above will have saved in lvmcache which
|
||||
* vg each device is used in, so we could figure that part
|
||||
* out without doing the vg_read.
|
||||
* Run the equivalent of lvmetad_pvscan_single on each dev in the VG.
|
||||
*/
|
||||
dm_list_iterate_items_safe(devl, devlsafe, &pvs_scan) {
|
||||
if (!devl->dev)
|
||||
continue;
|
||||
|
||||
log_debug_lvmetad("Rescan VG %s getting metadata from %s.",
|
||||
vg->name, dev_name(devl->dev));
|
||||
log_debug_lvmetad("Rescan VG %s scanning %s.", vg->name, dev_name(devl->dev));
|
||||
|
||||
if (!label_read(devl->dev, &label, 0)) {
|
||||
/* Another host removed this PV from the VG. */
|
||||
log_debug_lvmetad("Rescan VG %s found %s was removed.", vg->name, dev_name(devl->dev));
|
||||
|
||||
if ((info = lvmcache_info_from_pvid(devl->dev->pvid, NULL, 0)))
|
||||
lvmcache_del(info);
|
||||
|
||||
/*
|
||||
* The info struct for this dev knows what and where
|
||||
* the mdas are for this dev (the label scan saved
|
||||
* the mda locations for this dev on the lvmcache info struct).
|
||||
*/
|
||||
if (!(info = lvmcache_info_from_pvid(devl->dev->pvid, devl->dev, 0))) {
|
||||
log_debug_lvmetad("Rescan VG %s from %s dropping dev (no info).",
|
||||
vg->name, dev_name(devl->dev));
|
||||
dm_list_move(&pvs_drop, &devl->list);
|
||||
continue;
|
||||
}
|
||||
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
|
||||
baton.vg = NULL;
|
||||
baton.fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic);
|
||||
if (!baton.fid)
|
||||
return_NULL;
|
||||
|
||||
if (baton.fid->fmt->features & FMT_OBSOLETE) {
|
||||
log_debug_lvmetad("Ignoring obsolete format on PV %s in VG %s.", dev_name(devl->dev), vg->name);
|
||||
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
|
||||
dm_list_move(&pvs_drop, &devl->list);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read VG metadata from this dev's mdas.
|
||||
*/
|
||||
lvmcache_foreach_mda(info, _lvmetad_pvscan_vg_single, &baton);
|
||||
lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
|
||||
|
||||
/*
|
||||
* The PV may have been removed from the VG by another host
|
||||
* since we last read the VG.
|
||||
*/
|
||||
if (!baton.vg) {
|
||||
log_debug_lvmetad("Rescan VG %s from %s dropping dev (no metadata).",
|
||||
vg->name, dev_name(devl->dev));
|
||||
log_debug_lvmetad("Rescan VG %s did not find %s.", vg->name, dev_name(devl->dev));
|
||||
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
|
||||
dm_list_move(&pvs_drop, &devl->list);
|
||||
continue;
|
||||
}
|
||||
@@ -1989,15 +1892,10 @@ static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct v
|
||||
* different VG since we last read the VG.
|
||||
*/
|
||||
if (strcmp(baton.vg->name, vg->name)) {
|
||||
log_debug_lvmetad("Rescan VG %s from %s dropping dev (other VG %s).",
|
||||
vg->name, dev_name(devl->dev), baton.vg->name);
|
||||
release_vg(baton.vg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(vgmeta = export_vg_to_config_tree(baton.vg))) {
|
||||
log_error("VG export to config tree failed");
|
||||
log_debug_lvmetad("Rescan VG %s found different VG %s on PV %s.",
|
||||
vg->name, baton.vg->name, dev_name(devl->dev));
|
||||
release_vg(baton.vg);
|
||||
dm_list_move(&pvs_drop, &devl->list);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2007,35 +1905,20 @@ static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct v
|
||||
* read from each other dev.
|
||||
*/
|
||||
|
||||
if (save_vg && (save_seqno != baton.vg->seqno)) {
|
||||
/* FIXME: fall back to vg_read to correct this. */
|
||||
log_warn("WARNING: inconsistent metadata for VG %s on devices %s seqno %u and %s seqno %u.",
|
||||
vg->name, dev_name(save_dev), save_seqno,
|
||||
dev_name(devl->dev), baton.vg->seqno);
|
||||
log_warn("WARNING: temporarily disable lvmetad to repair metadata.");
|
||||
if (!save_seqno)
|
||||
save_seqno = baton.vg->seqno;
|
||||
|
||||
/* Use the most recent */
|
||||
if (save_seqno < baton.vg->seqno) {
|
||||
release_vg(save_vg);
|
||||
dm_config_destroy(save_meta);
|
||||
save_vg = baton.vg;
|
||||
save_meta = vgmeta;
|
||||
save_seqno = baton.vg->seqno;
|
||||
save_dev = devl->dev;
|
||||
} else {
|
||||
release_vg(baton.vg);
|
||||
dm_config_destroy(vgmeta);
|
||||
}
|
||||
continue;
|
||||
if (!(vgmeta = export_vg_to_config_tree(baton.vg))) {
|
||||
log_error("VG export to config tree failed");
|
||||
release_vg(baton.vg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!save_vg) {
|
||||
save_vg = baton.vg;
|
||||
save_meta = vgmeta;
|
||||
save_seqno = baton.vg->seqno;
|
||||
if (!vgmeta_ret) {
|
||||
vgmeta_ret = vgmeta;
|
||||
save_dev = devl->dev;
|
||||
} else {
|
||||
struct dm_config_node *meta1 = save_meta->root;
|
||||
struct dm_config_node *meta1 = vgmeta_ret->root;
|
||||
struct dm_config_node *meta2 = vgmeta->root;
|
||||
struct dm_config_node *sib1 = meta1->sib;
|
||||
struct dm_config_node *sib2 = meta2->sib;
|
||||
@@ -2060,128 +1943,73 @@ static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct v
|
||||
meta2->sib = NULL;
|
||||
|
||||
if (compare_config(meta1, meta2)) {
|
||||
/* FIXME: fall back to vg_read to correct this. */
|
||||
log_warn("WARNING: inconsistent metadata for VG %s on devices %s seqno %u and %s seqno %u.",
|
||||
vg->name, dev_name(save_dev), save_seqno,
|
||||
dev_name(devl->dev), baton.vg->seqno);
|
||||
log_warn("WARNING: temporarily disable lvmetad to repair metadata.");
|
||||
log_error("VG %s metadata comparison failed for device %s vs %s",
|
||||
vg->name, dev_name(devl->dev), save_dev ? dev_name(save_dev) : "none");
|
||||
_log_debug_inequality(vg->name, save_meta->root, vgmeta->root);
|
||||
_log_debug_inequality(vg->name, vgmeta_ret->root, vgmeta->root);
|
||||
|
||||
meta1->sib = sib1;
|
||||
meta2->sib = sib2;
|
||||
|
||||
/* no right choice, just use the previous copy */
|
||||
release_vg(baton.vg);
|
||||
dm_config_destroy(vgmeta);
|
||||
dm_config_destroy(vgmeta_ret);
|
||||
release_vg(baton.vg);
|
||||
return NULL;
|
||||
}
|
||||
meta1->sib = sib1;
|
||||
meta2->sib = sib2;
|
||||
release_vg(baton.vg);
|
||||
dm_config_destroy(vgmeta);
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: see above */
|
||||
fid->ref_count--;
|
||||
|
||||
/*
|
||||
* Look for any new PVs in the VG metadata that were not in our
|
||||
* previous version of the VG.
|
||||
*
|
||||
* (Don't look for new PVs after a rescan and retry.)
|
||||
*/
|
||||
found_new_pvs = 0;
|
||||
|
||||
if (save_vg && !retried_reads) {
|
||||
dm_list_iterate_items(pvl_new, &save_vg->pvs) {
|
||||
found = 0;
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (pvl_new->pv->dev != pvl->pv->dev)
|
||||
continue;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* PV in new VG metadata not found in old VG metadata.
|
||||
* There's a good chance we don't know about this new
|
||||
* PV or what device it's on; a label scan is needed
|
||||
* of all devices so we know which device the VG is
|
||||
* now using.
|
||||
*/
|
||||
if (!found) {
|
||||
found_new_pvs++;
|
||||
strncpy(pvid_s, (char *) &pvl_new->pv->id, sizeof(pvid_s) - 1);
|
||||
if (!id_write_format((const struct id *)&pvid_s, uuid, sizeof(uuid)))
|
||||
stack;
|
||||
log_debug_lvmetad("Rescan VG %s found new PV %s.", vg->name, uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!save_vg && retried_reads) {
|
||||
log_error("VG %s not found after rescanning devices.", vg->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a full rescan of devices, then look up which devices the
|
||||
* scan found for this VG name, and select those devices to
|
||||
* read metadata from in the loop above (rather than the list
|
||||
* of devices we created from our last copy of the vg metadata.)
|
||||
*
|
||||
* Case 1: VG we knew is no longer on any of the devices we knew it
|
||||
* to be on (save_vg is NULL, which means the metadata wasn't found
|
||||
* when reading mdas on each of the initial pvs_scan devices).
|
||||
* Rescan all devs and then retry reading metadata from the devs that
|
||||
* the scan finds associated with this VG.
|
||||
*
|
||||
* Case 2: VG has new PVs but we don't know what devices they are
|
||||
* so rescan all devs and then retry reading metadata from the devs
|
||||
* that the scan finds associated with this VG.
|
||||
*
|
||||
* (N.B. after a retry, we don't check for found_new_pvs.)
|
||||
*/
|
||||
if (!save_vg || found_new_pvs) {
|
||||
if (!save_vg)
|
||||
log_debug_lvmetad("Rescan VG %s did not find VG on previous devs.", vg->name);
|
||||
if (found_new_pvs)
|
||||
log_debug_lvmetad("Rescan VG %s scanning all devs to find new PVs.", vg->name);
|
||||
|
||||
label_scan_force(cmd);
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vg->name, NULL))) {
|
||||
log_error("VG %s vg info not found after rescanning devices.", vg->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set pvs_scan to devs that the label scan found
|
||||
* in the VG and retry the metadata reading loop.
|
||||
* Look for any new PVs in the VG metadata that were not in our
|
||||
* previous version of the VG. Add them to pvs_new to be
|
||||
* scanned in this loop just like the old PVs.
|
||||
*/
|
||||
dm_list_init(&pvs_scan);
|
||||
|
||||
if (!lvmcache_get_vg_devs(cmd, vginfo, &pvs_scan)) {
|
||||
log_error("VG %s info devs not found after rescanning devices.", vg->name);
|
||||
goto out;
|
||||
if (!check_new_pvs) {
|
||||
check_new_pvs = 1;
|
||||
dm_list_iterate_items(pvl_new, &baton.vg->pvs) {
|
||||
found = 0;
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (pvl_new->pv->dev != pvl->pv->dev)
|
||||
continue;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
if (!pvl_new->pv->dev) {
|
||||
strncpy(pvid_s, (char *) &pvl_new->pv->id, sizeof(pvid_s) - 1);
|
||||
if (!id_write_format((const struct id *)&pvid_s, uuid, sizeof(uuid)))
|
||||
stack;
|
||||
log_error("Device not found for PV %s in VG %s", uuid, vg->name);
|
||||
missing_devs++;
|
||||
continue;
|
||||
}
|
||||
if (!(devl_new = dm_pool_zalloc(cmd->mem, sizeof(*devl_new))))
|
||||
return_NULL;
|
||||
devl_new->dev = pvl_new->pv->dev;
|
||||
dm_list_add(&pvs_new, &devl_new->list);
|
||||
log_debug_lvmetad("Rescan VG %s found %s was added.", vg->name, dev_name(devl_new->dev));
|
||||
}
|
||||
}
|
||||
|
||||
log_debug_lvmetad("Rescan VG %s has %d PVs after label scan.",
|
||||
vg->name, dm_list_size(&pvs_scan));
|
||||
release_vg(baton.vg);
|
||||
}
|
||||
|
||||
if (save_vg)
|
||||
release_vg(save_vg);
|
||||
if (save_meta)
|
||||
dm_config_destroy(save_meta);
|
||||
save_vg = NULL;
|
||||
save_meta = NULL;
|
||||
save_dev = NULL;
|
||||
save_seqno = 0;
|
||||
found_new_pvs = 0;
|
||||
retried_reads = 1;
|
||||
goto retry_reads;
|
||||
/*
|
||||
* Do the same scanning above for any new PVs.
|
||||
*/
|
||||
if (!dm_list_empty(&pvs_new)) {
|
||||
dm_list_init(&pvs_scan);
|
||||
dm_list_splice(&pvs_scan, &pvs_new);
|
||||
dm_list_init(&pvs_new);
|
||||
log_debug_lvmetad("Rescan VG %s found new PVs to scan.", vg->name);
|
||||
goto scan_more;
|
||||
}
|
||||
|
||||
if (missing_devs) {
|
||||
if (vgmeta_ret)
|
||||
dm_config_destroy(vgmeta_ret);
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2190,50 +2018,52 @@ static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct v
|
||||
dm_list_iterate_items(devl, &pvs_drop) {
|
||||
if (!devl->dev)
|
||||
continue;
|
||||
log_debug_lvmetad("Rescan VG %s removing %s from lvmetad.", vg->name, dev_name(devl->dev));
|
||||
if (!lvmetad_pv_gone_by_dev(devl->dev)) {
|
||||
/* FIXME: use an error path that disables lvmetad */
|
||||
log_error("Failed to remove %s from lvmetad.", dev_name(devl->dev));
|
||||
}
|
||||
log_debug_lvmetad("Rescan VG %s dropping %s.", vg->name, dev_name(devl->dev));
|
||||
if (!lvmetad_pv_gone_by_dev(devl->dev))
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update lvmetad with the newly read version of the VG.
|
||||
* When the seqno is unchanged the cached VG can be left.
|
||||
* Update the VG in lvmetad.
|
||||
*/
|
||||
if (save_vg && (save_seqno != vg->seqno)) {
|
||||
dm_list_iterate_items(devl, &pvs_scan) {
|
||||
if (!devl->dev)
|
||||
continue;
|
||||
log_debug_lvmetad("Rescan VG %s removing %s from lvmetad to replace.",
|
||||
vg->name, dev_name(devl->dev));
|
||||
if (!lvmetad_pv_gone_by_dev(devl->dev)) {
|
||||
/* FIXME: use an error path that disables lvmetad */
|
||||
log_error("Failed to remove %s from lvmetad.", dev_name(devl->dev));
|
||||
}
|
||||
if (vgmeta_ret) {
|
||||
fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic);
|
||||
if (!(vg_ret = import_vg_from_config_tree(vgmeta_ret, fid))) {
|
||||
log_error("VG import from config tree failed");
|
||||
lvmcache_fmt(info)->ops->destroy_instance(fid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_debug_lvmetad("Rescan VG %s updating lvmetad from seqno %u to seqno %u.",
|
||||
vg->name, vg->seqno, save_seqno);
|
||||
|
||||
/*
|
||||
* If this vg_update fails the cached metadata in
|
||||
* lvmetad will remain invalid.
|
||||
* Update lvmetad with the newly read version of the VG.
|
||||
* When the seqno is unchanged the cached VG can be left.
|
||||
*/
|
||||
save_vg->lvmetad_update_pending = 1;
|
||||
if (!lvmetad_vg_update_finish(save_vg)) {
|
||||
/* FIXME: use an error path that disables lvmetad */
|
||||
log_error("Failed to update lvmetad with new VG meta");
|
||||
if (save_seqno != vg->seqno) {
|
||||
dm_list_iterate_items(devl, &pvs_scan) {
|
||||
if (!devl->dev)
|
||||
continue;
|
||||
log_debug_lvmetad("Rescan VG %s dropping to replace %s.", vg->name, dev_name(devl->dev));
|
||||
if (!lvmetad_pv_gone_by_dev(devl->dev))
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
log_debug_lvmetad("Rescan VG %s updating lvmetad from seqno %u to seqno %u.",
|
||||
vg->name, vg->seqno, save_seqno);
|
||||
|
||||
/*
|
||||
* If this vg_update fails the cached metadata in
|
||||
* lvmetad will remain invalid.
|
||||
*/
|
||||
vg_ret->lvmetad_update_pending = 1;
|
||||
if (!lvmetad_vg_update_finish(vg_ret))
|
||||
log_error("Failed to update lvmetad with new VG meta");
|
||||
}
|
||||
dm_config_destroy(vgmeta_ret);
|
||||
}
|
||||
out:
|
||||
if (!save_vg && fid)
|
||||
fmt->ops->destroy_instance(fid);
|
||||
if (save_meta)
|
||||
dm_config_destroy(save_meta);
|
||||
if (save_vg)
|
||||
log_debug_lvmetad("Rescan VG %s done (new seqno %u).", save_vg->name, save_vg->seqno);
|
||||
return save_vg;
|
||||
if (vg_ret)
|
||||
log_debug_lvmetad("Rescan VG %s done (seqno %u).", vg_ret->name, vg_ret->seqno);
|
||||
return vg_ret;
|
||||
}
|
||||
|
||||
int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
|
||||
@@ -2243,12 +2073,9 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
|
||||
struct label *label;
|
||||
struct lvmcache_info *info;
|
||||
struct _lvmetad_pvscan_baton baton;
|
||||
const struct format_type *fmt;
|
||||
/* Create a dummy instance. */
|
||||
struct format_instance_ctx fic = { .type = 0 };
|
||||
|
||||
log_debug_lvmetad("Scan metadata from dev %s", dev_name(dev));
|
||||
|
||||
if (!lvmetad_used()) {
|
||||
log_error("Cannot proceed since lvmetad is not active.");
|
||||
return 0;
|
||||
@@ -2259,31 +2086,23 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) {
|
||||
log_print_unless_silent("No PV info found on %s for PVID %s.", dev_name(dev), dev->pvid);
|
||||
if (!label_read(dev, &label, 0)) {
|
||||
log_print_unless_silent("No PV label found on %s.", dev_name(dev));
|
||||
if (!lvmetad_pv_gone_by_dev(dev))
|
||||
goto_bad;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(label = lvmcache_get_label(info))) {
|
||||
log_print_unless_silent("No PV label found for %s.", dev_name(dev));
|
||||
if (!lvmetad_pv_gone_by_dev(dev))
|
||||
goto_bad;
|
||||
return 1;
|
||||
}
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
|
||||
fmt = lvmcache_fmt(info);
|
||||
|
||||
baton.cmd = cmd;
|
||||
baton.vg = NULL;
|
||||
baton.fid = fmt->ops->create_instance(fmt, &fic);
|
||||
baton.fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic);
|
||||
|
||||
if (!baton.fid)
|
||||
goto_bad;
|
||||
|
||||
if (fmt->features & FMT_OBSOLETE) {
|
||||
fmt->ops->destroy_instance(baton.fid);
|
||||
if (baton.fid->fmt->features & FMT_OBSOLETE) {
|
||||
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
|
||||
log_warn("WARNING: Disabling lvmetad cache which does not support obsolete (lvm1) metadata.");
|
||||
lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_LVM1);
|
||||
_found_lvm1_metadata = 1;
|
||||
@@ -2297,9 +2116,9 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
|
||||
lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
|
||||
|
||||
if (!baton.vg)
|
||||
fmt->ops->destroy_instance(baton.fid);
|
||||
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
|
||||
|
||||
if (!lvmetad_pv_found(cmd, (const struct id *) &dev->pvid, dev, fmt,
|
||||
if (!lvmetad_pv_found(cmd, (const struct id *) &dev->pvid, dev, lvmcache_fmt(info),
|
||||
label->sector, baton.vg, found_vgnames, changed_vgnames)) {
|
||||
release_vg(baton.vg);
|
||||
goto_bad;
|
||||
@@ -2365,13 +2184,6 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
|
||||
replacing_other_update = 1;
|
||||
}
|
||||
|
||||
label_scan(cmd);
|
||||
|
||||
if (lvmcache_found_duplicate_pvs()) {
|
||||
log_warn("WARNING: Scan found duplicate PVs.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Scanning all devices to update lvmetad.");
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->lvmetad_filter, 1))) {
|
||||
@@ -2742,8 +2554,6 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
|
||||
*/
|
||||
_lvmetad_get_pv_cache_list(cmd, &pvc_before);
|
||||
|
||||
log_debug_lvmetad("Rescan all devices to validate global cache.");
|
||||
|
||||
/*
|
||||
* Update the local lvmetad cache so it correctly reflects any
|
||||
* changes made on remote hosts. (It's possible that this command
|
||||
@@ -2812,7 +2622,7 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
|
||||
_update_changed_pvs_in_udev(cmd, &pvc_before, &pvc_after);
|
||||
}
|
||||
|
||||
log_debug_lvmetad("Rescanned all devices");
|
||||
log_debug_lvmetad("Validating global lvmetad cache finished");
|
||||
}
|
||||
|
||||
int lvmetad_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid)
|
||||
|
@@ -51,18 +51,11 @@ static void _cache_display(const struct lv_segment *seg)
|
||||
|
||||
log_print(" Chunk size\t\t%s",
|
||||
display_size(seg->lv->vg->cmd, pool_seg->chunk_size));
|
||||
log_print(" Metadata format\t%u", pool_seg->cache_metadata_format);
|
||||
log_print(" Mode\t\t%s", get_cache_mode_name(pool_seg));
|
||||
log_print(" Policy\t\t%s", pool_seg->policy_name);
|
||||
|
||||
if (pool_seg->cache_metadata_format != CACHE_METADATA_FORMAT_UNSELECTED)
|
||||
log_print(" Metadata format\t%u", pool_seg->cache_metadata_format);
|
||||
|
||||
if (pool_seg->cache_mode != CACHE_MODE_UNSELECTED)
|
||||
log_print(" Mode\t\t%s", get_cache_mode_name(pool_seg));
|
||||
|
||||
if (pool_seg->policy_name)
|
||||
log_print(" Policy\t\t%s", pool_seg->policy_name);
|
||||
|
||||
if (pool_seg->policy_settings &&
|
||||
(n = pool_seg->policy_settings->child))
|
||||
if ((n = pool_seg->policy_settings->child))
|
||||
dm_config_write_node(n, _cache_out_line, NULL);
|
||||
|
||||
log_print(" ");
|
||||
|
@@ -54,7 +54,7 @@
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
static const size_t _linebuffer_size = 4096;
|
||||
static const size_t linebuffer_size = 4096;
|
||||
|
||||
/*
|
||||
* Copy the input string, removing invalid characters.
|
||||
@@ -474,12 +474,10 @@ bad:
|
||||
|
||||
int process_profilable_config(struct cmd_context *cmd)
|
||||
{
|
||||
const char *units;
|
||||
|
||||
if (!(cmd->default_settings.unit_factor =
|
||||
dm_units_to_factor(units = find_config_tree_str(cmd, global_units_CFG, NULL),
|
||||
dm_units_to_factor(find_config_tree_str(cmd, global_units_CFG, NULL),
|
||||
&cmd->default_settings.unit_type, 1, NULL))) {
|
||||
log_error("Unrecognised configuration setting for global/units: %s", units);
|
||||
log_error("Invalid units specification");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -542,7 +540,6 @@ static int _process_config(struct cmd_context *cmd)
|
||||
const struct dm_config_value *cv;
|
||||
int64_t pv_min_kb;
|
||||
int udev_disabled = 0;
|
||||
int scan_size_kb;
|
||||
char sysfs_dir[PATH_MAX];
|
||||
|
||||
if (!_check_config(cmd))
|
||||
@@ -626,29 +623,6 @@ static int _process_config(struct cmd_context *cmd)
|
||||
cmd->default_settings.udev_sync = udev_disabled ? 0 :
|
||||
find_config_tree_bool(cmd, activation_udev_sync_CFG, NULL);
|
||||
|
||||
#ifdef AIO_SUPPORT
|
||||
cmd->use_aio = find_config_tree_bool(cmd, devices_scan_async_CFG, NULL);
|
||||
#else
|
||||
cmd->use_aio = 0;
|
||||
if (find_config_tree_bool(cmd, devices_scan_async_CFG, NULL))
|
||||
log_verbose("Ignoring scan_async, no async I/O support.");
|
||||
#endif
|
||||
scan_size_kb = find_config_tree_int(cmd, devices_scan_size_CFG, NULL);
|
||||
|
||||
if (!scan_size_kb || (scan_size_kb < 0) || (scan_size_kb % 4)) {
|
||||
log_warn("WARNING: Ignoring invalid scan_size %d KB, using default %u KB.",
|
||||
scan_size_kb, DEFAULT_SCAN_SIZE_KB);
|
||||
log_warn("scan_size has units of KB and must be a multiple of 4 KB.");
|
||||
scan_size_kb = DEFAULT_SCAN_SIZE_KB;
|
||||
}
|
||||
|
||||
cmd->default_settings.scan_size_kb = scan_size_kb;
|
||||
|
||||
if (cmd->use_aio)
|
||||
log_debug("Using async io with scan_size %u KB.", scan_size_kb);
|
||||
else
|
||||
log_debug("Using sync io with scan_size %u KB.", scan_size_kb);
|
||||
|
||||
/*
|
||||
* Set udev_fallback lazily on first use since it requires
|
||||
* checking DM driver version which is an extra ioctl!
|
||||
@@ -709,6 +683,9 @@ static int _process_config(struct cmd_context *cmd)
|
||||
if (find_config_tree_bool(cmd, report_two_word_unknown_device_CFG, NULL))
|
||||
init_unknown_device_name("unknown device");
|
||||
|
||||
init_detect_internal_vg_cache_corruption
|
||||
(find_config_tree_bool(cmd, global_detect_internal_vg_cache_corruption_CFG, NULL));
|
||||
|
||||
if (!_init_system_id(cmd))
|
||||
return_0;
|
||||
|
||||
@@ -1522,6 +1499,11 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
dm_list_add(&cmd->segtypes, &segtype->list);
|
||||
}
|
||||
|
||||
#ifdef REPLICATOR_INTERNAL
|
||||
if (!init_replicator_segtype(cmd, &seglib))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef RAID_INTERNAL
|
||||
if (!init_raid_segtypes(cmd, &seglib))
|
||||
return 0;
|
||||
@@ -1894,7 +1876,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
/* Set in/out stream buffering before glibc */
|
||||
if (set_buffering) {
|
||||
/* Allocate 2 buffers */
|
||||
if (!(cmd->linebuffer = dm_malloc(2 * _linebuffer_size))) {
|
||||
if (!(cmd->linebuffer = dm_malloc(2 * linebuffer_size))) {
|
||||
log_error("Failed to allocate line buffer.");
|
||||
goto out;
|
||||
}
|
||||
@@ -1905,7 +1887,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
(flags & O_ACCMODE) != O_WRONLY) {
|
||||
if (!reopen_standard_stream(&stdin, "r"))
|
||||
goto_out;
|
||||
if (setvbuf(stdin, cmd->linebuffer, _IOLBF, _linebuffer_size)) {
|
||||
if (setvbuf(stdin, cmd->linebuffer, _IOLBF, linebuffer_size)) {
|
||||
log_sys_error("setvbuf", "");
|
||||
goto out;
|
||||
}
|
||||
@@ -1916,8 +1898,8 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
(flags & O_ACCMODE) != O_RDONLY) {
|
||||
if (!reopen_standard_stream(&stdout, "w"))
|
||||
goto_out;
|
||||
if (setvbuf(stdout, cmd->linebuffer + _linebuffer_size,
|
||||
_IOLBF, _linebuffer_size)) {
|
||||
if (setvbuf(stdout, cmd->linebuffer + linebuffer_size,
|
||||
_IOLBF, linebuffer_size)) {
|
||||
log_sys_error("setvbuf", "");
|
||||
goto out;
|
||||
}
|
||||
@@ -2017,6 +1999,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
if (set_filters && !init_filters(cmd, 1))
|
||||
goto_out;
|
||||
|
||||
cmd->default_settings.cache_vgmetadata = 1;
|
||||
cmd->current_settings = cmd->default_settings;
|
||||
|
||||
cmd->initialized.config = 1;
|
||||
@@ -2026,6 +2009,7 @@ out:
|
||||
cmd = NULL;
|
||||
}
|
||||
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@@ -2246,8 +2230,6 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
!cmd->filter->dump(cmd->filter, 1))
|
||||
stack;
|
||||
|
||||
label_scan_destroy(cmd);
|
||||
|
||||
archive_exit(cmd);
|
||||
backup_exit(cmd);
|
||||
lvmcache_destroy(cmd, 0, 0);
|
||||
|
@@ -39,7 +39,7 @@ struct config_info {
|
||||
int udev_rules;
|
||||
int udev_sync;
|
||||
int udev_fallback;
|
||||
int scan_size_kb;
|
||||
int cache_vgmetadata;
|
||||
const char *msg_prefix;
|
||||
const char *fmt_name;
|
||||
uint64_t unit_factor;
|
||||
@@ -160,12 +160,9 @@ struct cmd_context {
|
||||
unsigned lockd_vg_rescan:1;
|
||||
unsigned lockd_vg_default_sh:1;
|
||||
unsigned lockd_vg_enforce_sh:1;
|
||||
unsigned lockd_lv_sh:1;
|
||||
unsigned vg_notify:1;
|
||||
unsigned lv_notify:1;
|
||||
unsigned pv_notify:1;
|
||||
unsigned use_aio:1;
|
||||
unsigned pvscan_cache_single:1;
|
||||
|
||||
/*
|
||||
* Filtering.
|
||||
|
@@ -65,11 +65,11 @@ struct config_source {
|
||||
* Map each ID to respective definition of the configuration item.
|
||||
*/
|
||||
static struct cfg_def_item _cfg_def_items[CFG_COUNT + 1] = {
|
||||
#define cfg_section(id, name, parent, flags, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_SECTION, {0}, (flags), since_version, {0}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg(id, name, parent, flags, type, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment) {id, parent, name, type, {.v_##type = (default_value)}, (flags), since_version, {.v_UNCONFIGURED = (unconfigured_value)}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_runtime(id, name, parent, flags, type, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, type, {.fn_##type = get_default_##id}, (flags) | CFG_DEFAULT_RUN_TIME, since_version, {.fn_UNCONFIGURED = get_default_unconfigured_##id}, deprecated_since_version, (deprecation_comment), comment},
|
||||
#define cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_ARRAY | (types), {.v_CFG_TYPE_STRING = (default_value)}, (flags), (since_version), {.v_UNCONFIGURED = (unconfigured_value)}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_array_runtime(id, name, parent, flags, types, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_ARRAY | (types), {.fn_CFG_TYPE_STRING = get_default_##id}, (flags) | CFG_DEFAULT_RUN_TIME, (since_version), {.fn_UNCONFIGURED = get_default_unconfigured_##id}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_section(id, name, parent, flags, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_SECTION, {0}, flags, since_version, {0}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg(id, name, parent, flags, type, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment) {id, parent, name, type, {.v_##type = default_value}, flags, since_version, {.v_UNCONFIGURED = unconfigured_value}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_runtime(id, name, parent, flags, type, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, type, {.fn_##type = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, {.fn_UNCONFIGURED = get_default_unconfigured_##id}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.v_CFG_TYPE_STRING = default_value}, flags, since_version, {.v_UNCONFIGURED = unconfigured_value}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_array_runtime(id, name, parent, flags, types, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.fn_CFG_TYPE_STRING = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, {.fn_UNCONFIGURED = get_default_unconfigured_##id}, deprecated_since_version, deprecation_comment, comment},
|
||||
#include "config_settings.h"
|
||||
#undef cfg_section
|
||||
#undef cfg
|
||||
@@ -481,8 +481,7 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
|
||||
|
||||
if (profile->source == CONFIG_PROFILE_COMMAND)
|
||||
return _override_config_tree_from_command_profile(cmd, profile);
|
||||
|
||||
if (profile->source == CONFIG_PROFILE_METADATA)
|
||||
else if (profile->source == CONFIG_PROFILE_METADATA)
|
||||
return _override_config_tree_from_metadata_profile(cmd, profile);
|
||||
|
||||
log_error(INTERNAL_ERROR "override_config_tree_from_profile: incorrect profile source type");
|
||||
@@ -494,7 +493,7 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
|
||||
* and function avoids parsing of mda into config tree which
|
||||
* remains unmodified and should not be used.
|
||||
*/
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, char *buf_async,
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
int checksum_only, int no_dup_node_check)
|
||||
@@ -517,18 +516,7 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, char *bu
|
||||
if (!(dev->flags & DEV_REGULAR) || size2)
|
||||
use_mmap = 0;
|
||||
|
||||
if (buf_async) {
|
||||
if (!(buf = dm_malloc(size + size2))) {
|
||||
log_error("Failed to allocate circular buffer.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf, buf_async + offset, size);
|
||||
if (size2)
|
||||
memcpy(buf + size, buf_async + offset2, size2);
|
||||
|
||||
fb = buf;
|
||||
} else if (use_mmap) {
|
||||
if (use_mmap) {
|
||||
mmap_offset = offset % lvm_getpagesize();
|
||||
/* memory map the file */
|
||||
fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
|
||||
@@ -543,7 +531,6 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, char *bu
|
||||
log_error("Failed to allocate circular buffer.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_read_circular(dev, (uint64_t) offset, size,
|
||||
(uint64_t) offset2, size2, buf)) {
|
||||
goto out;
|
||||
@@ -613,7 +600,7 @@ int config_file_read(struct dm_config_tree *cft)
|
||||
}
|
||||
}
|
||||
|
||||
r = config_file_read_fd(cft, cf->dev, NULL, 0, (size_t) info.st_size, 0, 0,
|
||||
r = config_file_read_fd(cft, cf->dev, 0, (size_t) info.st_size, 0, 0,
|
||||
(checksum_fn_t) NULL, 0, 0, 0);
|
||||
|
||||
if (!cf->keep_open) {
|
||||
@@ -632,9 +619,9 @@ struct timespec config_file_timestamp(struct dm_config_tree *cft)
|
||||
}
|
||||
|
||||
#define cfg_def_get_item_p(id) (&_cfg_def_items[id])
|
||||
#define cfg_def_get_default_unconfigured_value_hint(cmd,item) (((item)->flags & CFG_DEFAULT_RUN_TIME) ? (item)->default_unconfigured_value.fn_UNCONFIGURED(cmd) : (item)->default_unconfigured_value.v_UNCONFIGURED)
|
||||
#define cfg_def_get_default_value_hint(cmd,item,type,profile) (((item)->flags & CFG_DEFAULT_RUN_TIME) ? (item)->default_value.fn_##type(cmd,profile) : (item)->default_value.v_##type)
|
||||
#define cfg_def_get_default_value(cmd,item,type,profile) ((item)->flags & CFG_DEFAULT_UNDEFINED ? 0 : cfg_def_get_default_value_hint(cmd,item,type,profile))
|
||||
#define cfg_def_get_default_unconfigured_value_hint(cmd,item) ((item->flags & CFG_DEFAULT_RUN_TIME) ? item->default_unconfigured_value.fn_UNCONFIGURED(cmd) : item->default_unconfigured_value.v_UNCONFIGURED)
|
||||
#define cfg_def_get_default_value_hint(cmd,item,type,profile) ((item->flags & CFG_DEFAULT_RUN_TIME) ? item->default_value.fn_##type(cmd,profile) : item->default_value.v_##type)
|
||||
#define cfg_def_get_default_value(cmd,item,type,profile) (item->flags & CFG_DEFAULT_UNDEFINED ? 0 : cfg_def_get_default_value_hint(cmd,item,type,profile))
|
||||
|
||||
static int _cfg_def_make_path(char *buf, size_t buf_size, int id, cfg_def_item_t *item, int xlate)
|
||||
{
|
||||
@@ -755,16 +742,14 @@ static struct dm_config_value *_get_def_array_values(struct cmd_context *cmd,
|
||||
switch (toupper(token[0])) {
|
||||
case 'I':
|
||||
case 'B':
|
||||
errno = 0;
|
||||
v->v.i = strtoll(token + 1, &r, 10);
|
||||
if (errno || *r)
|
||||
if (*r)
|
||||
goto bad;
|
||||
v->type = DM_CFG_INT;
|
||||
break;
|
||||
case 'F':
|
||||
errno = 0;
|
||||
v->v.f = strtod(token + 1, &r);
|
||||
if (errno || *r)
|
||||
if (*r)
|
||||
goto bad;
|
||||
v->type = DM_CFG_FLOAT;
|
||||
break;
|
||||
@@ -1892,12 +1877,6 @@ int config_write(struct dm_config_tree *cft,
|
||||
}
|
||||
|
||||
log_verbose("Dumping configuration to %s", file);
|
||||
|
||||
if (tree_spec->withgeneralpreamble)
|
||||
fprintf(baton.fp, CFG_PREAMBLE_GENERAL);
|
||||
if (tree_spec->withlocalpreamble)
|
||||
fprintf(baton.fp, CFG_PREAMBLE_LOCAL);
|
||||
|
||||
if (!argc) {
|
||||
if (!dm_config_write_node_out(cft->root, &_out_spec, &baton)) {
|
||||
log_error("Failure while writing to %s", file);
|
||||
|
@@ -141,7 +141,6 @@ typedef struct cfg_def_item {
|
||||
uint16_t deprecated_since_version; /* version since this item is deprecated */
|
||||
const char *deprecation_comment; /* comment about reasons for deprecation and settings that supersede this one */
|
||||
const char *comment; /* comment */
|
||||
const char *file_premable; /* comment text to use at the start of the file */
|
||||
} cfg_def_item_t;
|
||||
|
||||
/* configuration definition tree types */
|
||||
@@ -174,8 +173,6 @@ struct config_def_tree_spec {
|
||||
unsigned withversions:1; /* include versions */
|
||||
unsigned withspaces:1; /* add more spaces in output for better readability */
|
||||
unsigned unconfigured:1; /* use unconfigured path strings */
|
||||
unsigned withgeneralpreamble:1; /* include preamble for a general config file */
|
||||
unsigned withlocalpreamble:1; /* include preamble for a local config file */
|
||||
uint8_t *check_status; /* status of last tree check (currently needed for CFG_DEF_TREE_MISSING only) */
|
||||
};
|
||||
|
||||
@@ -239,7 +236,7 @@ config_source_t config_get_source_type(struct dm_config_tree *cft);
|
||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_t size);
|
||||
|
||||
struct dm_config_tree *config_open(config_source_t source, const char *filename, int keep_open);
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, char *buf_async,
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
int skip_parse, int no_dup_node_check);
|
||||
|
@@ -121,30 +121,6 @@
|
||||
|
||||
cfg_section(root_CFG_SECTION, "(root)", root_CFG_SECTION, 0, vsn(0, 0, 0), 0, NULL, NULL)
|
||||
|
||||
#define CFG_PREAMBLE_GENERAL \
|
||||
"# This is an example configuration file for the LVM2 system.\n" \
|
||||
"# It contains the default settings that would be used if there was no\n" \
|
||||
"# @DEFAULT_SYS_DIR@/lvm.conf file.\n" \
|
||||
"#\n" \
|
||||
"# Refer to 'man lvm.conf' for further information including the file layout.\n" \
|
||||
"#\n" \
|
||||
"# Refer to 'man lvm.conf' for information about how settings configured in\n" \
|
||||
"# this file are combined with built-in values and command line options to\n" \
|
||||
"# arrive at the final values used by LVM.\n" \
|
||||
"#\n" \
|
||||
"# Refer to 'man lvmconfig' for information about displaying the built-in\n" \
|
||||
"# and configured values used by LVM.\n" \
|
||||
"#\n" \
|
||||
"# If a default value is set in this file (not commented out), then a\n" \
|
||||
"# new version of LVM using this file will continue using that value,\n" \
|
||||
"# even if the new version of LVM changes the built-in default value.\n" \
|
||||
"#\n" \
|
||||
"# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set\n" \
|
||||
"# the environment variable LVM_SYSTEM_DIR before running the tools.\n" \
|
||||
"#\n" \
|
||||
"# N.B. Take care that each setting only appears once if uncommenting\n" \
|
||||
"# example settings in this file.\n\n"
|
||||
|
||||
cfg_section(config_CFG_SECTION, "config", root_CFG_SECTION, 0, vsn(2, 2, 99), 0, NULL,
|
||||
"How LVM configuration settings are handled.\n")
|
||||
|
||||
@@ -185,26 +161,6 @@ cfg_section(tags_CFG_SECTION, "tags", root_CFG_SECTION, CFG_DEFAULT_COMMENTED, v
|
||||
cfg_section(local_CFG_SECTION, "local", root_CFG_SECTION, 0, vsn(2, 2, 117), 0, NULL,
|
||||
"LVM settings that are specific to the local host.\n")
|
||||
|
||||
#define CFG_PREAMBLE_LOCAL \
|
||||
"# This is a local configuration file template for the LVM2 system\n" \
|
||||
"# which should be installed as @DEFAULT_SYS_DIR@/lvmlocal.conf .\n" \
|
||||
"#\n" \
|
||||
"# Refer to 'man lvm.conf' for information about the file layout.\n" \
|
||||
"#\n" \
|
||||
"# To put this file in a different directory and override\n" \
|
||||
"# @DEFAULT_SYS_DIR@ set the environment variable LVM_SYSTEM_DIR before\n" \
|
||||
"# running the tools.\n" \
|
||||
"#\n" \
|
||||
"# The lvmlocal.conf file is normally expected to contain only the\n" \
|
||||
"# \"local\" section which contains settings that should not be shared or\n" \
|
||||
"# repeated among different hosts. (But if other sections are present,\n" \
|
||||
"# they *will* get processed. Settings in this file override equivalent\n" \
|
||||
"# ones in lvm.conf and are in turn overridden by ones in any enabled\n" \
|
||||
"# lvm_<tag>.conf files.)\n" \
|
||||
"#\n" \
|
||||
"# Please take care that each setting only appears once if uncommenting\n" \
|
||||
"# example settings in this file and never copy this file between hosts.\n\n"
|
||||
|
||||
cfg(config_checks_CFG, "checks", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 99), NULL, 0, NULL,
|
||||
"If enabled, any LVM configuration mismatch is reported.\n"
|
||||
"This implies checking that the configuration key is understood by\n"
|
||||
@@ -457,26 +413,6 @@ cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_
|
||||
"Enabling this setting allows the VG to be used as usual even with\n"
|
||||
"uncertain devices.\n")
|
||||
|
||||
cfg(devices_scan_async_CFG, "scan_async", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SCAN_ASYNC, vsn(2, 2, 173), NULL, 0, NULL,
|
||||
"Use async I/O to read headers and metadata from disks in parallel.\n")
|
||||
|
||||
cfg(devices_scan_size_CFG, "scan_size", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SCAN_SIZE_KB, vsn(2, 2, 173), NULL, 0, NULL,
|
||||
"Number of KiB to read from each disk when scanning disks.\n"
|
||||
"The initial scan size is intended to cover all the headers\n"
|
||||
"and metadata that LVM places at the start of each disk so\n"
|
||||
"that a single read operation can retrieve them all.\n"
|
||||
"Any headers or metadata that lie beyond this size require\n"
|
||||
"an additional disk read. Must be a multiple of 4KiB.\n")
|
||||
|
||||
cfg(devices_async_events_CFG, "async_events", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_ASYNC_EVENTS, vsn(2, 2, 173), NULL, 0, NULL,
|
||||
"Max number of concurrent async reads when scanning disks.\n"
|
||||
"Up to this many disks can be read concurrently when scanning\n"
|
||||
"disks with async I/O. If there are more disks than this,\n"
|
||||
"they will be scanned serially with synchronous reads.\n"
|
||||
"Increasing this number to match a larger number of disks may\n"
|
||||
"improve performance, but will increase memory requirements.\n"
|
||||
"This setting is limitted by the system aio configuration.\n")
|
||||
|
||||
cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 77), NULL, 0, NULL,
|
||||
"Advise LVM which PVs to use when searching for new space.\n"
|
||||
"When searching for free space to extend an LV, the 'cling' allocation\n"
|
||||
@@ -888,8 +824,11 @@ cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_
|
||||
"Treat any internal errors as fatal errors, aborting the process that\n"
|
||||
"encountered the internal error. Please only enable for debugging.\n")
|
||||
|
||||
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 96), NULL, vsn(2, 2, 174), NULL,
|
||||
"No longer used.\n")
|
||||
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION, vsn(2, 2, 96), NULL, 0, NULL,
|
||||
"Internal verification of VG structures.\n"
|
||||
"Check if CRC matches when a parsed VG is used multiple times. This\n"
|
||||
"is useful to catch unexpected changes to cached VG structures.\n"
|
||||
"Please only enable for debugging.\n")
|
||||
|
||||
cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_METADATA_READ_ONLY, vsn(2, 2, 75), NULL, 0, NULL,
|
||||
"No operations that change on-disk metadata are permitted.\n"
|
||||
|
@@ -104,9 +104,9 @@
|
||||
#define DEFAULT_THIN_REPAIR_OPTION1 ""
|
||||
#define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1
|
||||
#define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
|
||||
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2) /* KB */
|
||||
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (16 * 1024 * 1024) /* KB */
|
||||
#define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048 /* KB */
|
||||
#define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
|
||||
#define DEFAULT_THIN_POOL_OPTIMAL_SIZE (128 * 1024 * 1024) /* KB */
|
||||
#define DEFAULT_THIN_POOL_CHUNK_SIZE_POLICY "generic"
|
||||
#define DEFAULT_THIN_POOL_CHUNK_SIZE 64 /* KB */
|
||||
#define DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE 512 /* KB */
|
||||
@@ -179,6 +179,7 @@
|
||||
#define DEFAULT_LOGLEVEL 0
|
||||
#define DEFAULT_INDENT 1
|
||||
#define DEFAULT_ABORT_ON_INTERNAL_ERRORS 0
|
||||
#define DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION 0
|
||||
#define DEFAULT_UNITS "r"
|
||||
#define DEFAULT_SUFFIX 1
|
||||
#define DEFAULT_HOSTTAGS 0
|
||||
@@ -266,8 +267,4 @@
|
||||
#define DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD 100
|
||||
#define DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT 20
|
||||
|
||||
#define DEFAULT_ASYNC_EVENTS 100
|
||||
#define DEFAULT_SCAN_ASYNC 1
|
||||
#define DEFAULT_SCAN_SIZE_KB 128
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
|
@@ -320,8 +320,8 @@ static int _compare_paths(const char *path0, const char *path1)
|
||||
/* ASCII comparison */
|
||||
if (strcmp(path0, path1) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_alias(struct device *dev, const char *path)
|
||||
@@ -706,12 +706,6 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
}
|
||||
}
|
||||
|
||||
if (dm_hash_lookup(_cache.names, path) == dev) {
|
||||
/* Hash already has matching entry present */
|
||||
log_debug("Path already cached %s.", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
|
||||
log_error("Failed to duplicate path string.");
|
||||
return 0;
|
||||
@@ -898,10 +892,10 @@ int dev_cache_index_devs(void)
|
||||
if (errno == ENOENT) {
|
||||
sysfs_has_dev_block = 0;
|
||||
return 1;
|
||||
} else {
|
||||
log_sys_error("stat", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_sys_error("stat", path);
|
||||
return 0;
|
||||
}
|
||||
} else if (!sysfs_has_dev_block)
|
||||
return 1;
|
||||
@@ -1081,8 +1075,6 @@ static void _full_scan(int dev_scan)
|
||||
if (_cache.has_scanned && !dev_scan)
|
||||
return;
|
||||
|
||||
log_debug_devs("Adding device paths to dev cache");
|
||||
|
||||
_insert_dirs(&_cache.dirs);
|
||||
|
||||
(void) dev_cache_index_devs();
|
||||
@@ -1092,8 +1084,6 @@ static void _full_scan(int dev_scan)
|
||||
|
||||
_cache.has_scanned = 1;
|
||||
init_full_scan_done(1);
|
||||
|
||||
log_debug_devs("Added %d device paths to dev cache", dm_hash_get_num_entries(_cache.names));
|
||||
}
|
||||
|
||||
int dev_cache_has_scanned(void)
|
||||
@@ -1374,19 +1364,6 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
|
||||
return dev_name(dev);
|
||||
}
|
||||
|
||||
/* Provide a custom reason when a device is ignored */
|
||||
const char *dev_cache_filtered_reason(const char *name)
|
||||
{
|
||||
const char *reason = "not found";
|
||||
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
|
||||
if (d)
|
||||
/* FIXME Record which filter caused the exclusion */
|
||||
reason = "excluded by a filter";
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
||||
{
|
||||
struct stat buf;
|
||||
|
@@ -55,7 +55,6 @@ int dev_cache_add_dir(const char *path);
|
||||
int dev_cache_add_loopfile(const char *path);
|
||||
__attribute__((nonnull(1)))
|
||||
struct device *dev_cache_get(const char *name, struct dev_filter *f);
|
||||
const char *dev_cache_filtered_reason(const char *name);
|
||||
|
||||
// TODO
|
||||
struct device *dev_cache_get_by_devt(dev_t device, struct dev_filter *f);
|
||||
|
@@ -405,8 +405,8 @@ int dev_get_size(struct device *dev, uint64_t *size)
|
||||
|
||||
if ((dev->flags & DEV_REGULAR))
|
||||
return _dev_get_size_file(dev, size);
|
||||
|
||||
return _dev_get_size_dev(dev, size);
|
||||
else
|
||||
return _dev_get_size_dev(dev, size);
|
||||
}
|
||||
|
||||
int dev_get_read_ahead(struct device *dev, uint32_t *read_ahead)
|
||||
@@ -827,319 +827,3 @@ int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
|
||||
|
||||
return (len == 0);
|
||||
}
|
||||
|
||||
#ifdef AIO_SUPPORT
|
||||
|
||||
/*
|
||||
* io_setup() wrapper:
|
||||
* async_event_count is the max number of concurrent async
|
||||
* i/os, i.e. the number of devices that can be read at once
|
||||
*
|
||||
* max_io_alloc_count: max number of aio structs to allocate,
|
||||
* each with a buf_len size buffer.
|
||||
*
|
||||
* max_buf_alloc_bytes: max number of bytes to use for buffers
|
||||
* attached to all aio structs; each aio struct gets a
|
||||
* buf_len size buffer.
|
||||
*
|
||||
* When only max_io_alloc_count is set, it is used directly.
|
||||
*
|
||||
* When only max_buf_alloc_bytes is set, the number of aio
|
||||
* structs is determined by this number divided by buf_len.
|
||||
*
|
||||
* When both are set, max_io_alloc_count is reduced, if needed,
|
||||
* to whatever value max_buf_alloc_bytes would allow.
|
||||
*
|
||||
* When both are zero, there is no limit on the number of aio
|
||||
* structs. If allocation fails for an aio struct or its buffer,
|
||||
* the code should revert to synchronous io.
|
||||
*/
|
||||
|
||||
struct dev_async_context *dev_async_context_setup(unsigned async_event_count,
|
||||
unsigned max_io_alloc_count,
|
||||
unsigned max_buf_alloc_bytes,
|
||||
int buf_len)
|
||||
{
|
||||
struct dev_async_context *ac;
|
||||
unsigned nr_events = DEFAULT_ASYNC_EVENTS;
|
||||
int count;
|
||||
int error;
|
||||
|
||||
if (async_event_count)
|
||||
nr_events = async_event_count;
|
||||
|
||||
if (!(ac = malloc(sizeof(struct dev_async_context))))
|
||||
return_0;
|
||||
|
||||
memset(ac, 0, sizeof(struct dev_async_context));
|
||||
|
||||
dm_list_init(&ac->unused_ios);
|
||||
|
||||
error = io_setup(nr_events, &ac->aio_ctx);
|
||||
|
||||
if (error < 0) {
|
||||
log_warn("WARNING: async io setup error %d with %u events.", error, nr_events);
|
||||
free(ac);
|
||||
return_0;
|
||||
}
|
||||
|
||||
|
||||
if (!max_io_alloc_count && !max_buf_alloc_bytes)
|
||||
count = 0;
|
||||
else if (!max_io_alloc_count && max_buf_alloc_bytes)
|
||||
count = max_buf_alloc_bytes / buf_len;
|
||||
else if (max_io_alloc_count && max_buf_alloc_bytes) {
|
||||
if (max_io_alloc_count * buf_len > max_buf_alloc_bytes)
|
||||
count = max_buf_alloc_bytes / buf_len;
|
||||
} else
|
||||
count = max_io_alloc_count;
|
||||
|
||||
ac->max_ios = count;
|
||||
return ac;
|
||||
}
|
||||
|
||||
void dev_async_context_destroy(struct dev_async_context *ac)
|
||||
{
|
||||
io_destroy(ac->aio_ctx);
|
||||
free(ac);
|
||||
}
|
||||
|
||||
static struct dev_async_io *_async_io_alloc(int buf_len)
|
||||
{
|
||||
struct dev_async_io *aio;
|
||||
char *buf;
|
||||
char **p_buf;
|
||||
|
||||
/*
|
||||
* mem pool doesn't seem to work for this, probably because
|
||||
* of the memalign that follows.
|
||||
*/
|
||||
if (!(aio = malloc(sizeof(struct dev_async_io))))
|
||||
return_0;
|
||||
|
||||
memset(aio, 0, sizeof(struct dev_async_io));
|
||||
|
||||
buf = NULL;
|
||||
p_buf = &buf;
|
||||
|
||||
if (posix_memalign((void *)p_buf, getpagesize(), buf_len)) {
|
||||
free(aio);
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
aio->buf = buf;
|
||||
aio->buf_len = buf_len;
|
||||
return aio;
|
||||
}
|
||||
|
||||
static void _async_io_free(struct dev_async_io *aio)
|
||||
{
|
||||
if (aio->buf)
|
||||
free(aio->buf);
|
||||
free(aio);
|
||||
}
|
||||
|
||||
int dev_async_alloc_ios(struct dev_async_context *ac, int num, int buf_len, int *available)
|
||||
{
|
||||
struct dev_async_io *aio;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
/* FIXME: check if num wants more pre allocated? */
|
||||
if (!dm_list_empty(&ac->unused_ios))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* When no limit is used and no pre-alloc number is set,
|
||||
* then no ios are allocated up front, but the are
|
||||
* allocated as needed in get().
|
||||
*/
|
||||
if (!ac->max_ios && !num) {
|
||||
*available = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (num && !ac->max_ios)
|
||||
count = num;
|
||||
else if (!num && ac->max_ios)
|
||||
count = ac->max_ios;
|
||||
else if (num > ac->max_ios)
|
||||
count = ac->max_ios;
|
||||
else if (num < ac->max_ios)
|
||||
count = num;
|
||||
else
|
||||
count = ac->max_ios;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!(aio = _async_io_alloc(buf_len))) {
|
||||
ac->num_ios = i;
|
||||
*available = i;
|
||||
return 1;
|
||||
}
|
||||
dm_list_add(&ac->unused_ios, &aio->list);
|
||||
}
|
||||
|
||||
ac->num_ios = count;
|
||||
*available = count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dev_async_free_ios(struct dev_async_context *ac)
|
||||
{
|
||||
struct dev_async_io *aio, *aio2;
|
||||
|
||||
dm_list_iterate_items_safe(aio, aio2, &ac->unused_ios) {
|
||||
dm_list_del(&aio->list);
|
||||
_async_io_free(aio);
|
||||
}
|
||||
}
|
||||
|
||||
struct dev_async_io *dev_async_io_get(struct dev_async_context *ac, int buf_len)
|
||||
{
|
||||
struct dm_list *aio_item;
|
||||
struct dev_async_io *aio;
|
||||
|
||||
if (!(aio_item = dm_list_first(&ac->unused_ios)))
|
||||
goto alloc_new;
|
||||
|
||||
aio = dm_list_item(aio_item, struct dev_async_io);
|
||||
dm_list_del(&aio->list);
|
||||
return aio;
|
||||
|
||||
alloc_new:
|
||||
/* alloc on demand if there is no max or we have used less than max */
|
||||
if (!ac->max_ios || (ac->num_ios < ac->max_ios)) {
|
||||
if ((aio = _async_io_alloc(buf_len))) {
|
||||
ac->num_ios++;
|
||||
return aio;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dev_async_io_put(struct dev_async_context *ac, struct dev_async_io *aio)
|
||||
{
|
||||
if (!ac)
|
||||
_async_io_free(aio);
|
||||
else {
|
||||
memset(aio->buf, 0, aio->buf_len);
|
||||
aio->dev = NULL;
|
||||
aio->len = 0;
|
||||
aio->done = 0;
|
||||
aio->result = 0;
|
||||
dm_list_add(&ac->unused_ios, &aio->list);
|
||||
}
|
||||
}
|
||||
|
||||
/* io_submit() wrapper */
|
||||
|
||||
int dev_async_read_submit(struct dev_async_context *ac, struct dev_async_io *aio,
|
||||
struct device *dev, uint32_t len, uint64_t offset, int *nospace)
|
||||
{
|
||||
struct iocb *iocb = &aio->iocb;
|
||||
int error;
|
||||
|
||||
*nospace = 0;
|
||||
|
||||
if (len > aio->buf_len)
|
||||
return_0;
|
||||
|
||||
aio->len = len;
|
||||
|
||||
iocb->data = aio;
|
||||
iocb->aio_fildes = dev_fd(dev);
|
||||
iocb->aio_lio_opcode = IO_CMD_PREAD;
|
||||
iocb->u.c.buf = aio->buf;
|
||||
iocb->u.c.nbytes = len;
|
||||
iocb->u.c.offset = offset;
|
||||
|
||||
error = io_submit(ac->aio_ctx, 1, &iocb);
|
||||
if (error == -EAGAIN)
|
||||
*nospace = 1;
|
||||
if (error < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* io_getevents() wrapper */
|
||||
|
||||
int dev_async_getevents(struct dev_async_context *ac, int wait_count, struct timespec *timeout)
|
||||
{
|
||||
int wait_nr;
|
||||
int rv;
|
||||
int i;
|
||||
|
||||
retry:
|
||||
memset(&ac->events, 0, sizeof(ac->events));
|
||||
|
||||
if (wait_count >= MAX_GET_EVENTS)
|
||||
wait_nr = MAX_GET_EVENTS;
|
||||
else
|
||||
wait_nr = wait_count;
|
||||
|
||||
rv = io_getevents(ac->aio_ctx, 1, wait_nr, (struct io_event *)&ac->events, timeout);
|
||||
|
||||
if (rv == -EINTR)
|
||||
goto retry;
|
||||
if (rv < 0)
|
||||
return 0;
|
||||
if (!rv)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < rv; i++) {
|
||||
struct iocb *iocb = ac->events[i].obj;
|
||||
struct dev_async_io *aio = iocb->data;
|
||||
aio->result = ac->events[i].res;
|
||||
aio->done = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* AIO_SUPPORT */
|
||||
|
||||
struct dev_async_context *dev_async_context_setup(unsigned async_event_count,
|
||||
unsigned max_io_alloc_count,
|
||||
unsigned max_buf_alloc_bytes,
|
||||
int buf_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dev_async_context_destroy(struct dev_async_context *ac)
|
||||
{
|
||||
}
|
||||
|
||||
int dev_async_alloc_ios(struct dev_async_context *ac, int num, int buf_len, int *available)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dev_async_free_ios(struct dev_async_context *ac)
|
||||
{
|
||||
}
|
||||
|
||||
struct dev_async_io *dev_async_io_get(struct dev_async_context *ac, int buf_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dev_async_io_put(struct dev_async_context *ac, struct dev_async_io *aio)
|
||||
{
|
||||
}
|
||||
|
||||
int dev_async_read_submit(struct dev_async_context *ac, struct dev_async_io *aio,
|
||||
struct device *dev, uint32_t len, uint64_t offset, int *nospace)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_async_getevents(struct dev_async_context *ac, int wait_count, struct timespec *timeout)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* AIO_SUPPORT */
|
||||
|
@@ -28,7 +28,7 @@
|
||||
#define MD_SB_MAGIC 0xa92b4efc
|
||||
#define MD_RESERVED_BYTES (64 * 1024ULL)
|
||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
|
||||
#define MD_NEW_SIZE_SECTORS(x) (((x) & ~(MD_RESERVED_SECTORS - 1)) \
|
||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
|
||||
- MD_RESERVED_SECTORS)
|
||||
#define MD_MAX_SYSFS_SIZE 64
|
||||
|
||||
@@ -261,7 +261,8 @@ out:
|
||||
/*
|
||||
* Retrieve chunk size from md device using sysfs.
|
||||
*/
|
||||
static unsigned long _dev_md_chunk_size(struct dev_types *dt, struct device *dev)
|
||||
static unsigned long dev_md_chunk_size(struct dev_types *dt,
|
||||
struct device *dev)
|
||||
{
|
||||
const char *attribute = "chunk_size";
|
||||
unsigned long chunk_size_bytes = 0UL;
|
||||
@@ -279,7 +280,7 @@ static unsigned long _dev_md_chunk_size(struct dev_types *dt, struct device *dev
|
||||
/*
|
||||
* Retrieve level from md device using sysfs.
|
||||
*/
|
||||
static int _dev_md_level(struct dev_types *dt, struct device *dev)
|
||||
static int dev_md_level(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
char level_string[MD_MAX_SYSFS_SIZE];
|
||||
const char *attribute = "level";
|
||||
@@ -302,7 +303,7 @@ static int _dev_md_level(struct dev_types *dt, struct device *dev)
|
||||
/*
|
||||
* Retrieve raid_disks from md device using sysfs.
|
||||
*/
|
||||
static int _dev_md_raid_disks(struct dev_types *dt, struct device *dev)
|
||||
static int dev_md_raid_disks(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
const char *attribute = "raid_disks";
|
||||
int raid_disks = 0;
|
||||
@@ -326,15 +327,15 @@ unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev)
|
||||
unsigned long stripe_width_sectors = 0UL;
|
||||
int level, raid_disks, data_disks;
|
||||
|
||||
chunk_size_sectors = _dev_md_chunk_size(dt, dev);
|
||||
chunk_size_sectors = dev_md_chunk_size(dt, dev);
|
||||
if (!chunk_size_sectors)
|
||||
return 0;
|
||||
|
||||
level = _dev_md_level(dt, dev);
|
||||
level = dev_md_level(dt, dev);
|
||||
if (level < 0)
|
||||
return 0;
|
||||
|
||||
raid_disks = _dev_md_raid_disks(dt, dev);
|
||||
raid_disks = dev_md_raid_disks(dt, dev);
|
||||
if (!raid_disks)
|
||||
return 0;
|
||||
|
||||
|
@@ -20,7 +20,8 @@
|
||||
#define MAX_PAGESIZE (64 * 1024)
|
||||
#define SIGNATURE_SIZE 10
|
||||
|
||||
static int _swap_detect_signature(const char *buf)
|
||||
static int
|
||||
_swap_detect_signature(const char *buf)
|
||||
{
|
||||
if (memcmp(buf, "SWAP-SPACE", 10) == 0 ||
|
||||
memcmp(buf, "SWAPSPACE2", 10) == 0)
|
||||
|
@@ -76,7 +76,7 @@ struct dev_types *create_dev_types(const char *proc_dir,
|
||||
i++;
|
||||
|
||||
/* If it's not a number it may be name of section */
|
||||
line_maj = atoi(line + i);
|
||||
line_maj = atoi(((char *) (line + i)));
|
||||
|
||||
if (line_maj < 0 || line_maj >= NUMBER_OF_MAJORS) {
|
||||
/*
|
||||
@@ -615,38 +615,38 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
|
||||
if (force < DONT_PROMPT) {
|
||||
log_error(MSG_FAILED_SIG_OFFSET, type, name);
|
||||
return 0;
|
||||
} else {
|
||||
log_error("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
|
||||
log_error("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
if (blkid_probe_lookup_value(probe, "SBMAGIC", &magic, &len)) {
|
||||
if (force < DONT_PROMPT) {
|
||||
log_error(MSG_FAILED_SIG_LENGTH, type, name);
|
||||
return 0;
|
||||
} else {
|
||||
log_warn("WARNING: " MSG_FAILED_SIG_LENGTH MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
|
||||
log_warn("WARNING: " MSG_FAILED_SIG_LENGTH MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
} else if (!blkid_probe_lookup_value(probe, "PTTYPE", &type, NULL)) {
|
||||
if (blkid_probe_lookup_value(probe, "PTMAGIC_OFFSET", &offset, NULL)) {
|
||||
if (force < DONT_PROMPT) {
|
||||
log_error(MSG_FAILED_SIG_OFFSET, type, name);
|
||||
return 0;
|
||||
} else {
|
||||
log_warn("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
|
||||
log_warn("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
if (blkid_probe_lookup_value(probe, "PTMAGIC", &magic, &len)) {
|
||||
if (force < DONT_PROMPT) {
|
||||
log_error(MSG_FAILED_SIG_LENGTH, type, name);
|
||||
return 0;
|
||||
} else {
|
||||
log_warn("WARNING: " MSG_FAILED_SIG_LENGTH MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
|
||||
log_warn("WARNING: " MSG_FAILED_SIG_LENGTH MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
usage = "partition table";
|
||||
} else
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#include "uuid.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <libaio.h>
|
||||
|
||||
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
|
||||
#define DEV_REGULAR 0x00000002 /* Regular file? */
|
||||
@@ -91,32 +90,6 @@ struct device_area {
|
||||
uint64_t size; /* Bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
* We'll collect the results of this many async reads
|
||||
* in one system call. It shouldn't matter much what
|
||||
* number is used here.
|
||||
*/
|
||||
#define MAX_GET_EVENTS 16
|
||||
|
||||
struct dev_async_context {
|
||||
io_context_t aio_ctx;
|
||||
struct io_event events[MAX_GET_EVENTS]; /* for processing completions */
|
||||
struct dm_list unused_ios; /* unused/available aio structcs */
|
||||
int num_ios; /* number of allocated aio structs */
|
||||
int max_ios; /* max number of aio structs to allocate */
|
||||
};
|
||||
|
||||
struct dev_async_io {
|
||||
struct dm_list list;
|
||||
struct iocb iocb;
|
||||
struct device *dev;
|
||||
char *buf;
|
||||
uint32_t buf_len; /* size of buf */
|
||||
uint32_t len; /* size of submitted io */
|
||||
int done;
|
||||
int result;
|
||||
};
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
*/
|
||||
@@ -171,26 +144,4 @@ void dev_destroy_file(struct device *dev);
|
||||
/* Return a valid device name from the alias list; NULL otherwise */
|
||||
const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
|
||||
struct dev_async_context *dev_async_context_setup(unsigned async_event_count,
|
||||
unsigned max_io_alloc_count,
|
||||
unsigned max_buf_alloc_bytes,
|
||||
int buf_len);
|
||||
void dev_async_context_destroy(struct dev_async_context *ac);
|
||||
|
||||
/* allocate aio structs (with buffers), up to the max specified during context setup */
|
||||
int dev_async_alloc_ios(struct dev_async_context *ac, int num, int buf_len, int *available);
|
||||
|
||||
/* free aio structs (and buffers) */
|
||||
void dev_async_free_ios(struct dev_async_context *ac);
|
||||
|
||||
/* get an available aio struct (with buffer) */
|
||||
struct dev_async_io *dev_async_io_get(struct dev_async_context *ac, int buf_len);
|
||||
|
||||
/* make an aio struct (with buffer) available for use (by another get) */
|
||||
void dev_async_io_put(struct dev_async_context *ac, struct dev_async_io *aio);
|
||||
|
||||
int dev_async_read_submit(struct dev_async_context *ac, struct dev_async_io *aio,
|
||||
struct device *dev, uint32_t len, uint64_t offset, int *nospace);
|
||||
int dev_async_getevents(struct dev_async_context *ac, int wait_count, struct timespec *timeout);
|
||||
|
||||
#endif
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -152,30 +152,6 @@ const char *display_lvname(const struct logical_volume *lv)
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Display percentage with (TODO) configurable precision */
|
||||
const char *display_percent(struct cmd_context *cmd, dm_percent_t percent)
|
||||
{
|
||||
char *buf;
|
||||
int r;
|
||||
|
||||
/* Reusing same ring buffer we use for displaying LV names */
|
||||
if ((cmd->display_lvname_idx + NAME_LEN) >= sizeof((cmd->display_buffer)))
|
||||
cmd->display_lvname_idx = 0;
|
||||
|
||||
buf = cmd->display_buffer + cmd->display_lvname_idx;
|
||||
/* TODO: Make configurable hardcoded 2 digits */
|
||||
r = dm_snprintf(buf, NAME_LEN, "%.2f", dm_percent_to_round_float(percent, 2));
|
||||
|
||||
if (r < 0) {
|
||||
log_error("Percentage %d does not fit.", percent);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cmd->display_lvname_idx += r + 1;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Size supplied in sectors */
|
||||
static const char *_display_size(const struct cmd_context *cmd,
|
||||
uint64_t size, dm_size_suffix_t suffix_type)
|
||||
@@ -517,8 +493,8 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
log_print("LV Pool metadata %s", seg->metadata_lv->name);
|
||||
log_print("LV Pool data %s", seg_lv(seg, 0)->name);
|
||||
} else if (lv_is_cache_origin(lv)) {
|
||||
if ((seg = get_only_segment_using_this_lv(lv)))
|
||||
log_print("LV origin of Cache LV %s", seg->lv->name);
|
||||
log_print("LV origin of Cache LV %s",
|
||||
get_only_segment_using_this_lv(lv)->lv->name);
|
||||
} else if (lv_is_cache(lv)) {
|
||||
seg = first_seg(lv);
|
||||
if (inkernel && !lv_cache_status(lv, &cache_status))
|
||||
@@ -549,12 +525,12 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
snap_seg ? snap_seg->origin->size : lv->size));
|
||||
|
||||
if (cache_status) {
|
||||
log_print("Cache used blocks %s%%",
|
||||
display_percent(cmd, cache_status->data_usage));
|
||||
log_print("Cache metadata blocks %s%%",
|
||||
display_percent(cmd, cache_status->metadata_usage));
|
||||
log_print("Cache dirty blocks %s%%",
|
||||
display_percent(cmd, cache_status->dirty_usage));
|
||||
log_print("Cache used blocks %.2f%%",
|
||||
dm_percent_to_float(cache_status->data_usage));
|
||||
log_print("Cache metadata blocks %.2f%%",
|
||||
dm_percent_to_float(cache_status->metadata_usage));
|
||||
log_print("Cache dirty blocks %.2f%%",
|
||||
dm_percent_to_float(cache_status->dirty_usage));
|
||||
log_print("Cache read hits/misses " FMTu64 " / " FMTu64,
|
||||
cache_status->cache->read_hits,
|
||||
cache_status->cache->read_misses);
|
||||
@@ -570,16 +546,16 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
if (thin_data_active)
|
||||
log_print("Allocated pool data %s%%",
|
||||
display_percent(cmd, thin_data_percent));
|
||||
log_print("Allocated pool data %.2f%%",
|
||||
dm_percent_to_float(thin_data_percent));
|
||||
|
||||
if (thin_metadata_active)
|
||||
log_print("Allocated metadata %s%%",
|
||||
display_percent(cmd, thin_metadata_percent));
|
||||
log_print("Allocated metadata %.2f%%",
|
||||
dm_percent_to_float(thin_metadata_percent));
|
||||
|
||||
if (thin_active)
|
||||
log_print("Mapped size %s%%",
|
||||
display_percent(cmd, thin_percent));
|
||||
log_print("Mapped size %.2f%%",
|
||||
dm_percent_to_float(thin_percent));
|
||||
|
||||
log_print("Current LE %u",
|
||||
snap_seg ? snap_seg->origin->le_count : lv->le_count);
|
||||
@@ -590,8 +566,8 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
log_print("COW-table LE %u", lv->le_count);
|
||||
|
||||
if (snap_active)
|
||||
log_print("Allocated to snapshot %s%%",
|
||||
display_percent(cmd, snap_percent));
|
||||
log_print("Allocated to snapshot %.2f%%",
|
||||
dm_percent_to_float(snap_percent));
|
||||
|
||||
log_print("Snapshot chunk size %s",
|
||||
display_size(cmd, (uint64_t) snap_seg->chunk_size));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
const char *display_lvname(const struct logical_volume *lv);
|
||||
|
||||
const char *display_percent(struct cmd_context *cmd, dm_percent_t percent);
|
||||
|
||||
/* Specify size in KB */
|
||||
const char *display_size(const struct cmd_context *cmd, uint64_t size);
|
||||
const char *display_size_long(const struct cmd_context *cmd, uint64_t size);
|
||||
|
@@ -274,9 +274,8 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
||||
if (!_set_lookup(ds, dev->dev)) {
|
||||
log_debug_devs("%s: Skipping (sysfs)", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
|
@@ -180,9 +180,9 @@ out:
|
||||
static struct volume_group *_format1_vg_read(struct format_instance *fid,
|
||||
const char *vg_name,
|
||||
struct metadata_area *mda __attribute__((unused)),
|
||||
struct label_read_data *ld __attribute__((unused)),
|
||||
struct cached_vg_fmtdata **vg_fmtdata __attribute__((unused)),
|
||||
unsigned *use_previous_vg __attribute__((unused)))
|
||||
unsigned *use_previous_vg __attribute__((unused)),
|
||||
int single_device __attribute__((unused)))
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct disk_list *dl;
|
||||
|
@@ -134,35 +134,37 @@ static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
|
||||
if (lv_num == UNMAPPED_EXTENT)
|
||||
continue;
|
||||
|
||||
lv_num--;
|
||||
lvm = lvms[lv_num];
|
||||
else {
|
||||
lv_num--;
|
||||
lvm = lvms[lv_num];
|
||||
|
||||
if (!lvm) {
|
||||
log_error("Invalid LV in extent map "
|
||||
"(PV %s, PE %" PRIu32
|
||||
", LV %" PRIu32
|
||||
", LE %" PRIu32 ")",
|
||||
dev_name(pv->dev), i,
|
||||
lv_num, e[i].le_num);
|
||||
return 0;
|
||||
if (!lvm) {
|
||||
log_error("Invalid LV in extent map "
|
||||
"(PV %s, PE %" PRIu32
|
||||
", LV %" PRIu32
|
||||
", LE %" PRIu32 ")",
|
||||
dev_name(pv->dev), i,
|
||||
lv_num, e[i].le_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
le = e[i].le_num;
|
||||
|
||||
if (le >= lvm->lv->le_count) {
|
||||
log_error("logical extent number "
|
||||
"out of bounds");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm->map[le].pv) {
|
||||
log_error("logical extent (%u) "
|
||||
"already mapped.", le);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lvm->map[le].pv = pv;
|
||||
lvm->map[le].pe = i;
|
||||
}
|
||||
|
||||
le = e[i].le_num;
|
||||
|
||||
if (le >= lvm->lv->le_count) {
|
||||
log_error("logical extent number "
|
||||
"out of bounds");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm->map[le].pv) {
|
||||
log_error("logical extent (%u) "
|
||||
"already mapped.", le);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lvm->map[le].pv = pv;
|
||||
lvm->map[le].pe = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -55,7 +55,6 @@ static int _lvm1_write(struct label *label __attribute__((unused)), void *buf __
|
||||
}
|
||||
|
||||
static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
|
||||
struct label_read_data *ld,
|
||||
struct label **label)
|
||||
{
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
|
@@ -101,9 +101,9 @@ static int _check_usp(const char *vgname, struct user_subpool *usp, int sp_count
|
||||
static struct volume_group *_pool_vg_read(struct format_instance *fid,
|
||||
const char *vg_name,
|
||||
struct metadata_area *mda __attribute__((unused)),
|
||||
struct label_read_data *ld __attribute__((unused)),
|
||||
struct cached_vg_fmtdata **vg_fmtdata __attribute__((unused)),
|
||||
unsigned *use_previous_vg __attribute__((unused)))
|
||||
unsigned *use_previous_vg __attribute__((unused)),
|
||||
int single_device __attribute__((unused)))
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct user_subpool *usp;
|
||||
|
@@ -56,7 +56,6 @@ static int _pool_write(struct label *label __attribute__((unused)), void *buf __
|
||||
}
|
||||
|
||||
static int _pool_read(struct labeller *l, struct device *dev, void *buf,
|
||||
struct label_read_data *ld,
|
||||
struct label **label)
|
||||
{
|
||||
struct pool_list pl;
|
||||
|
@@ -321,7 +321,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
|
||||
* retrieve the archive time and description.
|
||||
*/
|
||||
/* FIXME Use variation on _vg_read */
|
||||
if (!(vg = text_read_metadata_file(tf, af->path, &when, &desc))) {
|
||||
if (!(vg = text_vg_import_file(tf, af->path, &when, &desc))) {
|
||||
log_error("Unable to read archive file.");
|
||||
tf->fmt->ops->destroy_instance(tf);
|
||||
return;
|
||||
|
@@ -320,7 +320,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
dm_list_iterate_items(mda, &tf->metadata_areas_in_use) {
|
||||
if (!(vg = mda->ops->vg_read(tf, vg_name, mda, NULL, NULL, NULL)))
|
||||
if (!(vg = mda->ops->vg_read(tf, vg_name, mda, NULL, NULL, 0)))
|
||||
stack;
|
||||
break;
|
||||
}
|
||||
|
@@ -42,7 +42,7 @@ typedef int (*nl_fn) (struct formatter * f);
|
||||
#define _out_with_comment(f, buffer, fmt, ap) \
|
||||
do { \
|
||||
va_start(ap, fmt); \
|
||||
r = (f)->out_with_comment((f), (buffer), (fmt), ap); \
|
||||
r = f->out_with_comment(f, buffer, fmt, ap); \
|
||||
va_end(ap); \
|
||||
} while (r == -1)
|
||||
|
||||
@@ -910,8 +910,8 @@ static int _print_historical_lv(struct formatter *f, struct historical_logical_v
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
dm_free(descendants_buffer);
|
||||
|
||||
if (descendants_buffer)
|
||||
dm_free(descendants_buffer);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@@ -48,7 +48,6 @@ static const struct flag _pv_flags[] = {
|
||||
{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
|
||||
{MISSING_PV, "MISSING", COMPATIBLE_FLAG},
|
||||
{MISSING_PV, "MISSING", STATUS_FLAG},
|
||||
{PV_MOVED_VG, NULL, 0},
|
||||
{UNLABELLED_PV, NULL, 0},
|
||||
{0, NULL, 0}
|
||||
};
|
||||
@@ -63,11 +62,9 @@ static const struct flag _lv_flags[] = {
|
||||
{LOCKED, "LOCKED", STATUS_FLAG},
|
||||
{LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
|
||||
{LV_REBUILD, "REBUILD", STATUS_FLAG},
|
||||
{LV_RESHAPE, "RESHAPE", SEGTYPE_FLAG},
|
||||
{LV_RESHAPE_DATA_OFFSET, "RESHAPE_DATA_OFFSET", SEGTYPE_FLAG},
|
||||
{LV_RESHAPE_DELTA_DISKS_PLUS, "RESHAPE_DELTA_DISKS_PLUS", SEGTYPE_FLAG},
|
||||
{LV_RESHAPE_DELTA_DISKS_MINUS, "RESHAPE_DELTA_DISKS_MINUS", SEGTYPE_FLAG},
|
||||
{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", SEGTYPE_FLAG},
|
||||
{LV_RESHAPE_DELTA_DISKS_PLUS, "RESHAPE_DELTA_DISKS_PLUS", STATUS_FLAG},
|
||||
{LV_RESHAPE_DELTA_DISKS_MINUS, "RESHAPE_DELTA_DISKS_MINUS", STATUS_FLAG},
|
||||
{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", STATUS_FLAG},
|
||||
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
|
||||
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
|
||||
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
|
||||
@@ -90,6 +87,8 @@ static const struct flag _lv_flags[] = {
|
||||
{PARTIAL_LV, NULL, 0},
|
||||
{POSTORDER_FLAG, NULL, 0},
|
||||
{VIRTUAL_ORIGIN, NULL, 0},
|
||||
{REPLICATOR, NULL, 0},
|
||||
{REPLICATOR_LOG, NULL, 0},
|
||||
{THIN_VOLUME, NULL, 0},
|
||||
{THIN_POOL, NULL, 0},
|
||||
{THIN_POOL_DATA, NULL, 0},
|
||||
|
@@ -152,8 +152,8 @@ static uint64_t _get_prev_sector_circular(uint64_t region_start,
|
||||
{
|
||||
if (region_ptr >= region_start + SECTOR_SIZE)
|
||||
return region_ptr - SECTOR_SIZE;
|
||||
|
||||
return (region_start + region_size - SECTOR_SIZE);
|
||||
else
|
||||
return (region_start + region_size - SECTOR_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -190,7 +190,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
|
||||
if (!dev_open_readonly(area->dev))
|
||||
return_0;
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fmt, area, NULL)))
|
||||
if (!(mdah = raw_read_mda_header(fmt, area)))
|
||||
goto_out;
|
||||
|
||||
rlocn = mdah->raw_locns;
|
||||
@@ -268,7 +268,8 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
dm_free(buf);
|
||||
if (buf)
|
||||
dm_free(buf);
|
||||
if (!dev_close(area->dev))
|
||||
stack;
|
||||
return r;
|
||||
@@ -316,26 +317,15 @@ static void _xlate_mdah(struct mda_header *mdah)
|
||||
}
|
||||
}
|
||||
|
||||
static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev_area,
|
||||
struct label_read_data *ld)
|
||||
static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev_area)
|
||||
{
|
||||
if (!dev_open_readonly(dev_area->dev))
|
||||
return_0;
|
||||
|
||||
if (!ld || (ld->buf_len < dev_area->start + MDA_HEADER_SIZE)) {
|
||||
log_debug_metadata("Reading mda header sector from %s at %llu",
|
||||
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
|
||||
|
||||
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
|
||||
if (!dev_close(dev_area->dev))
|
||||
stack;
|
||||
return_0;
|
||||
}
|
||||
} else {
|
||||
log_debug_metadata("Copying mda header sector from %s buffer at %llu",
|
||||
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
|
||||
|
||||
memcpy(mdah, ld->buf + dev_area->start, MDA_HEADER_SIZE);
|
||||
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
|
||||
if (!dev_close(dev_area->dev))
|
||||
stack;
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!dev_close(dev_area->dev))
|
||||
@@ -377,8 +367,7 @@ static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev
|
||||
}
|
||||
|
||||
struct mda_header *raw_read_mda_header(const struct format_type *fmt,
|
||||
struct device_area *dev_area,
|
||||
struct label_read_data *ld)
|
||||
struct device_area *dev_area)
|
||||
{
|
||||
struct mda_header *mdah;
|
||||
|
||||
@@ -387,7 +376,7 @@ struct mda_header *raw_read_mda_header(const struct format_type *fmt,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_raw_read_mda_header(mdah, dev_area, ld)) {
|
||||
if (!_raw_read_mda_header(mdah, dev_area)) {
|
||||
dm_pool_free(fmt->cmd->mem, mdah);
|
||||
return NULL;
|
||||
}
|
||||
@@ -414,14 +403,8 @@ static int _raw_write_mda_header(const struct format_type *fmt,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: unify this with read_metadata_location() which is used
|
||||
* in the label scanning path.
|
||||
*/
|
||||
|
||||
static struct raw_locn *_read_metadata_location_vg(struct device_area *dev_area,
|
||||
static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
struct mda_header *mdah,
|
||||
struct label_read_data *ld,
|
||||
const char *vgname,
|
||||
int *precommitted)
|
||||
{
|
||||
@@ -456,28 +439,18 @@ static struct raw_locn *_read_metadata_location_vg(struct device_area *dev_area,
|
||||
if (!*vgname)
|
||||
return rlocn;
|
||||
|
||||
/*
|
||||
* Verify that the VG metadata pointed to by the rlocn
|
||||
* begins with a valid vgname.
|
||||
*/
|
||||
if (!ld || (ld->buf_len < dev_area->start + rlocn->offset + NAME_LEN)) {
|
||||
/* FIXME Loop through rlocns two-at-a-time. List null-terminated. */
|
||||
/* FIXME Ignore if checksum incorrect!!! */
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
sizeof(vgnamebuf), vgnamebuf))
|
||||
goto_bad;
|
||||
} else {
|
||||
memset(vgnamebuf, 0, sizeof(vgnamebuf));
|
||||
memcpy(vgnamebuf, ld->buf + dev_area->start + rlocn->offset, NAME_LEN);
|
||||
}
|
||||
/* FIXME Loop through rlocns two-at-a-time. List null-terminated. */
|
||||
/* FIXME Ignore if checksum incorrect!!! */
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
sizeof(vgnamebuf), vgnamebuf))
|
||||
goto_bad;
|
||||
|
||||
if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
|
||||
(isspace(vgnamebuf[len]) || vgnamebuf[len] == '{'))
|
||||
return rlocn;
|
||||
|
||||
log_debug_metadata("Volume group name found in metadata on %s at %" PRIu64 " does "
|
||||
"not match expected name %s.",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset, vgname);
|
||||
else
|
||||
log_debug_metadata("Volume group name found in metadata does "
|
||||
"not match expected name %s.", vgname);
|
||||
|
||||
bad:
|
||||
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, dev_area->dev, 0)) &&
|
||||
@@ -515,10 +488,10 @@ static int _raw_holds_vgname(struct format_instance *fid,
|
||||
if (!dev_open_readonly(dev_area->dev))
|
||||
return_0;
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, dev_area, NULL)))
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, dev_area)))
|
||||
return_0;
|
||||
|
||||
if (_read_metadata_location_vg(dev_area, mdah, NULL, vgname, &noprecommit))
|
||||
if (_find_vg_rlocn(dev_area, mdah, vgname, &noprecommit))
|
||||
r = 1;
|
||||
|
||||
if (!dev_close(dev_area->dev))
|
||||
@@ -530,10 +503,10 @@ static int _raw_holds_vgname(struct format_instance *fid,
|
||||
static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
|
||||
const char *vgname,
|
||||
struct device_area *area,
|
||||
struct label_read_data *ld,
|
||||
struct cached_vg_fmtdata **vg_fmtdata,
|
||||
unsigned *use_previous_vg,
|
||||
int precommitted)
|
||||
int precommitted,
|
||||
int single_device)
|
||||
{
|
||||
struct volume_group *vg = NULL;
|
||||
struct raw_locn *rlocn;
|
||||
@@ -542,10 +515,10 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
|
||||
char *desc;
|
||||
uint32_t wrap = 0;
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, area, ld)))
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, area)))
|
||||
goto_out;
|
||||
|
||||
if (!(rlocn = _read_metadata_location_vg(area, mdah, ld, vgname, &precommitted))) {
|
||||
if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, &precommitted))) {
|
||||
log_debug_metadata("VG %s not found on %s", vgname, dev_name(area->dev));
|
||||
goto out;
|
||||
}
|
||||
@@ -559,25 +532,25 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
|
||||
goto out;
|
||||
}
|
||||
|
||||
vg = text_read_metadata(fid, area->dev, NULL, ld, vg_fmtdata, use_previous_vg,
|
||||
(off_t) (area->start + rlocn->offset),
|
||||
(uint32_t) (rlocn->size - wrap),
|
||||
(off_t) (area->start + MDA_HEADER_SIZE),
|
||||
wrap,
|
||||
calc_crc,
|
||||
rlocn->checksum,
|
||||
&when, &desc);
|
||||
/* FIXME 64-bit */
|
||||
if (!(vg = text_vg_import_fd(fid, NULL, vg_fmtdata, use_previous_vg, single_device, area->dev,
|
||||
(off_t) (area->start + rlocn->offset),
|
||||
(uint32_t) (rlocn->size - wrap),
|
||||
(off_t) (area->start + MDA_HEADER_SIZE),
|
||||
wrap, calc_crc, rlocn->checksum, &when,
|
||||
&desc)) && (!use_previous_vg || !*use_previous_vg))
|
||||
goto_out;
|
||||
|
||||
if (!vg) {
|
||||
/* FIXME: detect and handle errors, and distinguish from the optimization
|
||||
that skips parsing the metadata which also returns NULL. */
|
||||
}
|
||||
|
||||
log_debug_metadata("Found metadata on %s at %"PRIu64" size %"PRIu64" for VG %s",
|
||||
dev_name(area->dev),
|
||||
area->start + rlocn->offset,
|
||||
rlocn->size,
|
||||
vgname);
|
||||
if (vg)
|
||||
log_debug_metadata("Read %s %smetadata (%u) from %s at %" PRIu64 " size %"
|
||||
PRIu64, vg->name, precommitted ? "pre-commit " : "",
|
||||
vg->seqno, dev_name(area->dev),
|
||||
area->start + rlocn->offset, rlocn->size);
|
||||
else
|
||||
log_debug_metadata("Skipped reading %smetadata from %s at %" PRIu64 " size %"
|
||||
PRIu64 " with matching checksum.", precommitted ? "pre-commit " : "",
|
||||
dev_name(area->dev),
|
||||
area->start + rlocn->offset, rlocn->size);
|
||||
|
||||
if (vg && precommitted)
|
||||
vg->status |= PRECOMMITTED;
|
||||
@@ -589,9 +562,9 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
|
||||
static struct volume_group *_vg_read_raw(struct format_instance *fid,
|
||||
const char *vgname,
|
||||
struct metadata_area *mda,
|
||||
struct label_read_data *ld,
|
||||
struct cached_vg_fmtdata **vg_fmtdata,
|
||||
unsigned *use_previous_vg)
|
||||
unsigned *use_previous_vg,
|
||||
int single_device)
|
||||
{
|
||||
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
|
||||
struct volume_group *vg;
|
||||
@@ -599,7 +572,7 @@ static struct volume_group *_vg_read_raw(struct format_instance *fid,
|
||||
if (!dev_open_readonly(mdac->area.dev))
|
||||
return_NULL;
|
||||
|
||||
vg = _vg_read_raw_area(fid, vgname, &mdac->area, ld, vg_fmtdata, use_previous_vg, 0);
|
||||
vg = _vg_read_raw_area(fid, vgname, &mdac->area, vg_fmtdata, use_previous_vg, 0, single_device);
|
||||
|
||||
if (!dev_close(mdac->area.dev))
|
||||
stack;
|
||||
@@ -610,7 +583,6 @@ static struct volume_group *_vg_read_raw(struct format_instance *fid,
|
||||
static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
|
||||
const char *vgname,
|
||||
struct metadata_area *mda,
|
||||
struct label_read_data *ld,
|
||||
struct cached_vg_fmtdata **vg_fmtdata,
|
||||
unsigned *use_previous_vg)
|
||||
{
|
||||
@@ -620,7 +592,7 @@ static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
|
||||
if (!dev_open_readonly(mdac->area.dev))
|
||||
return_NULL;
|
||||
|
||||
vg = _vg_read_raw_area(fid, vgname, &mdac->area, ld, vg_fmtdata, use_previous_vg, 1);
|
||||
vg = _vg_read_raw_area(fid, vgname, &mdac->area, vg_fmtdata, use_previous_vg, 1, 0);
|
||||
|
||||
if (!dev_close(mdac->area.dev))
|
||||
stack;
|
||||
@@ -637,17 +609,14 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
struct mda_header *mdah;
|
||||
struct pv_list *pvl;
|
||||
int r = 0;
|
||||
uint64_t new_wrap = 0, old_wrap = 0, new_end;
|
||||
uint64_t new_wrap = 0, old_wrap = 0, new_end;
|
||||
int found = 0;
|
||||
int noprecommit = 0;
|
||||
const char *old_vg_name = NULL;
|
||||
|
||||
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (pvl->pv->dev == mdac->area.dev) {
|
||||
found = 1;
|
||||
if (pvl->pv->status & PV_MOVED_VG)
|
||||
old_vg_name = vg->old_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -658,10 +627,11 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
if (!dev_open(mdac->area.dev))
|
||||
return_0;
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area, NULL)))
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area)))
|
||||
goto_out;
|
||||
|
||||
rlocn = _read_metadata_location_vg(&mdac->area, mdah, NULL, old_vg_name ? : vg->name, &noprecommit);
|
||||
rlocn = _find_vg_rlocn(&mdac->area, mdah,
|
||||
vg->old_name ? vg->old_name : vg->name, &noprecommit);
|
||||
mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah);
|
||||
|
||||
if (!fidtc->raw_metadata_buf &&
|
||||
@@ -749,14 +719,11 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
|
||||
int r = 0;
|
||||
int found = 0;
|
||||
int noprecommit = 0;
|
||||
const char *old_vg_name = NULL;
|
||||
|
||||
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (pvl->pv->dev == mdac->area.dev) {
|
||||
found = 1;
|
||||
if (pvl->pv->status & PV_MOVED_VG)
|
||||
old_vg_name = vg->old_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -764,10 +731,12 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
|
||||
if (!found)
|
||||
return 1;
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area, NULL)))
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area)))
|
||||
goto_out;
|
||||
|
||||
if (!(rlocn = _read_metadata_location_vg(&mdac->area, mdah, NULL, old_vg_name ? : vg->name, &noprecommit))) {
|
||||
if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah,
|
||||
vg->old_name ? vg->old_name : vg->name,
|
||||
&noprecommit))) {
|
||||
mdah->raw_locns[0].offset = 0;
|
||||
mdah->raw_locns[0].size = 0;
|
||||
mdah->raw_locns[0].checksum = 0;
|
||||
@@ -874,10 +843,10 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
if (!dev_open(mdac->area.dev))
|
||||
return_0;
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area, NULL)))
|
||||
if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area)))
|
||||
goto_out;
|
||||
|
||||
if (!(rlocn = _read_metadata_location_vg(&mdac->area, mdah, NULL, vg->name, &noprecommit))) {
|
||||
if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
|
||||
rlocn = &mdah->raw_locns[0];
|
||||
mdah->raw_locns[1].offset = 0;
|
||||
}
|
||||
@@ -911,10 +880,8 @@ static struct volume_group *_vg_read_file_name(struct format_instance *fid,
|
||||
time_t when;
|
||||
char *desc;
|
||||
|
||||
if (!(vg = text_read_metadata_file(fid, read_path, &when, &desc))) {
|
||||
log_error("Failed to read VG %s from %s", vgname, read_path);
|
||||
return NULL;
|
||||
}
|
||||
if (!(vg = text_vg_import_file(fid, read_path, &when, &desc)))
|
||||
return_NULL;
|
||||
|
||||
/*
|
||||
* Currently you can only have a single volume group per
|
||||
@@ -927,9 +894,8 @@ static struct volume_group *_vg_read_file_name(struct format_instance *fid,
|
||||
log_error("'%s' does not contain volume group '%s'.",
|
||||
read_path, vgname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log_debug_metadata("Read volume group %s from %s", vg->name, read_path);
|
||||
} else
|
||||
log_debug_metadata("Read volume group %s from %s", vg->name, read_path);
|
||||
|
||||
return vg;
|
||||
}
|
||||
@@ -937,9 +903,9 @@ static struct volume_group *_vg_read_file_name(struct format_instance *fid,
|
||||
static struct volume_group *_vg_read_file(struct format_instance *fid,
|
||||
const char *vgname,
|
||||
struct metadata_area *mda,
|
||||
struct label_read_data *ld,
|
||||
struct cached_vg_fmtdata **vg_fmtdata,
|
||||
unsigned *use_previous_vg __attribute__((unused)))
|
||||
unsigned *use_previous_vg __attribute__((unused)),
|
||||
int single_device __attribute__((unused)))
|
||||
{
|
||||
struct text_context *tc = (struct text_context *) mda->metadata_locn;
|
||||
|
||||
@@ -949,7 +915,6 @@ static struct volume_group *_vg_read_file(struct format_instance *fid,
|
||||
static struct volume_group *_vg_read_precommit_file(struct format_instance *fid,
|
||||
const char *vgname,
|
||||
struct metadata_area *mda,
|
||||
struct label_read_data *ld,
|
||||
struct cached_vg_fmtdata **vg_fmtdata,
|
||||
unsigned *use_previous_vg __attribute__((unused)))
|
||||
{
|
||||
@@ -1078,11 +1043,6 @@ static int _vg_commit_file(struct format_instance *fid, struct volume_group *vg,
|
||||
|
||||
if (strcmp(slash, vg->name)) {
|
||||
len = slash - tc->path_live;
|
||||
if ((len + strlen(vg->name)) > (sizeof(new_name) - 1)) {
|
||||
log_error("Renaming path %s is too long for VG %s.",
|
||||
tc->path_live, vg->name);
|
||||
return 0;
|
||||
}
|
||||
strncpy(new_name, tc->path_live, len);
|
||||
strcpy(new_name + len, vg->name);
|
||||
log_debug_metadata("Renaming %s to %s", tc->path_live, new_name);
|
||||
@@ -1138,9 +1098,6 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
|
||||
|
||||
dir_list = &((struct mda_lists *) fmt->private)->dirs;
|
||||
|
||||
if (!dm_list_empty(dir_list))
|
||||
log_debug_metadata("Scanning independent files for %s", vgname ? vgname : "VGs");
|
||||
|
||||
dm_list_iterate_items(dl, dir_list) {
|
||||
if (!(d = opendir(dl->dir))) {
|
||||
log_sys_error("opendir", dl->dir);
|
||||
@@ -1173,14 +1130,10 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
|
||||
stack;
|
||||
break;
|
||||
}
|
||||
|
||||
log_debug_metadata("Scanning independent file %s for VG %s", path, scanned_vgname);
|
||||
|
||||
if ((vg = _vg_read_file_name(fid, scanned_vgname,
|
||||
path))) {
|
||||
/* FIXME Store creation host in vg */
|
||||
lvmcache_update_vg(vg, 0);
|
||||
lvmcache_set_independent_location(vg->name);
|
||||
release_vg(vg);
|
||||
}
|
||||
}
|
||||
@@ -1192,9 +1145,8 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int read_metadata_location_summary(const struct format_type *fmt,
|
||||
struct mda_header *mdah, struct label_read_data *ld,
|
||||
struct device_area *dev_area,
|
||||
int vgname_from_mda(const struct format_type *fmt,
|
||||
struct mda_header *mdah, struct device_area *dev_area,
|
||||
struct lvmcache_vgsummary *vgsummary, uint64_t *mda_free_sectors)
|
||||
{
|
||||
struct raw_locn *rlocn;
|
||||
@@ -1202,12 +1154,13 @@ int read_metadata_location_summary(const struct format_type *fmt,
|
||||
unsigned int len = 0;
|
||||
char buf[NAME_LEN + 1] __attribute__((aligned(8)));
|
||||
uint64_t buffer_size, current_usage;
|
||||
unsigned used_cached_metadata = 0;
|
||||
|
||||
if (mda_free_sectors)
|
||||
*mda_free_sectors = ((dev_area->size - MDA_HEADER_SIZE) / 2) >> SECTOR_SHIFT;
|
||||
|
||||
if (!mdah) {
|
||||
log_error(INTERNAL_ERROR "read_metadata_location_summary called with NULL pointer for mda_header");
|
||||
log_error(INTERNAL_ERROR "vgname_from_mda called with NULL pointer for mda_header");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1218,21 +1171,15 @@ int read_metadata_location_summary(const struct format_type *fmt,
|
||||
* If no valid offset, do not try to search for vgname
|
||||
*/
|
||||
if (!rlocn->offset) {
|
||||
log_debug_metadata("Metadata location on %s at %"PRIu64" has offset 0.",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset);
|
||||
log_debug("%s: found metadata with offset 0.",
|
||||
dev_name(dev_area->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the VG metadata pointed to by the rlocn
|
||||
* begins with a valid vgname.
|
||||
*/
|
||||
if (!ld || (ld->buf_len < dev_area->start + rlocn->offset + NAME_LEN)) {
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, buf))
|
||||
return_0;
|
||||
} else {
|
||||
memcpy(buf, ld->buf + dev_area->start + rlocn->offset, NAME_LEN);
|
||||
}
|
||||
/* Do quick check for a vgname */
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
NAME_LEN, buf))
|
||||
return_0;
|
||||
|
||||
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
|
||||
len < (NAME_LEN - 1))
|
||||
@@ -1241,19 +1188,16 @@ int read_metadata_location_summary(const struct format_type *fmt,
|
||||
buf[len] = '\0';
|
||||
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(buf)) {
|
||||
log_error("Metadata location on %s at %"PRIu64" begins with invalid VG name.",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset);
|
||||
if (!validate_name(buf))
|
||||
return_0;
|
||||
}
|
||||
|
||||
/* We found a VG - now check the metadata */
|
||||
if (rlocn->offset + rlocn->size > mdah->size)
|
||||
wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
|
||||
|
||||
if (wrap > rlocn->offset) {
|
||||
log_error("Metadata location on %s at %"PRIu64" is too large for circular buffer.",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset);
|
||||
log_error("%s: metadata too large for circular buffer",
|
||||
dev_name(dev_area->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1261,29 +1205,30 @@ int read_metadata_location_summary(const struct format_type *fmt,
|
||||
vgsummary->mda_checksum = rlocn->checksum;
|
||||
vgsummary->mda_size = rlocn->size;
|
||||
|
||||
if (!text_read_metadata_summary(fmt, dev_area->dev, ld,
|
||||
if (lvmcache_lookup_mda(vgsummary))
|
||||
used_cached_metadata = 1;
|
||||
|
||||
/* FIXME 64-bit */
|
||||
if (!text_vgsummary_import(fmt, dev_area->dev,
|
||||
(off_t) (dev_area->start + rlocn->offset),
|
||||
(uint32_t) (rlocn->size - wrap),
|
||||
(off_t) (dev_area->start + MDA_HEADER_SIZE),
|
||||
wrap, calc_crc, vgsummary->vgname ? 1 : 0,
|
||||
vgsummary)) {
|
||||
log_error("Metadata location on %s at %"PRIu64" has invalid summary for VG.",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset);
|
||||
vgsummary))
|
||||
return_0;
|
||||
}
|
||||
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(vgsummary->vgname)) {
|
||||
log_error("Metadata location on %s at %"PRIu64" has invalid VG name.",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset);
|
||||
if (!validate_name(vgsummary->vgname))
|
||||
return_0;
|
||||
}
|
||||
|
||||
log_debug_metadata("Metadata location on %s at %"PRIu64" size %"PRIu64" has summary for VG %s",
|
||||
log_debug_metadata("%s: %s metadata at %" PRIu64 " size %" PRIu64
|
||||
" (in area at %" PRIu64 " size %" PRIu64
|
||||
") for %s (" FMTVGID ")",
|
||||
dev_name(dev_area->dev),
|
||||
used_cached_metadata ? "Using cached" : "Found",
|
||||
dev_area->start + rlocn->offset,
|
||||
rlocn->size,
|
||||
vgsummary->vgname);
|
||||
rlocn->size, dev_area->start, dev_area->size, vgsummary->vgname,
|
||||
(char *)&vgsummary->vgid);
|
||||
|
||||
if (mda_free_sectors) {
|
||||
current_usage = (rlocn->size + SECTOR_SIZE - UINT64_C(1)) -
|
||||
@@ -1299,8 +1244,6 @@ int read_metadata_location_summary(const struct format_type *fmt,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* used for independent_metadata_areas */
|
||||
|
||||
static int _scan_raw(const struct format_type *fmt, const char *vgname __attribute__((unused)))
|
||||
{
|
||||
struct raw_list *rl;
|
||||
@@ -1312,34 +1255,27 @@ static int _scan_raw(const struct format_type *fmt, const char *vgname __attribu
|
||||
|
||||
raw_list = &((struct mda_lists *) fmt->private)->raws;
|
||||
|
||||
if (!dm_list_empty(raw_list))
|
||||
log_debug_metadata("Scanning independent raw locations for %s", vgname ? vgname : "VGs");
|
||||
|
||||
fid.fmt = fmt;
|
||||
dm_list_init(&fid.metadata_areas_in_use);
|
||||
dm_list_init(&fid.metadata_areas_ignored);
|
||||
|
||||
dm_list_iterate_items(rl, raw_list) {
|
||||
log_debug_metadata("Scanning independent dev %s", dev_name(rl->dev_area.dev));
|
||||
|
||||
/* FIXME We're reading mdah twice here... */
|
||||
if (!dev_open_readonly(rl->dev_area.dev)) {
|
||||
stack;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fmt, &rl->dev_area, NULL))) {
|
||||
if (!(mdah = raw_read_mda_header(fmt, &rl->dev_area))) {
|
||||
stack;
|
||||
goto close_dev;
|
||||
}
|
||||
|
||||
/* TODO: caching as in read_metadata_location() (trigger this code?) */
|
||||
if (read_metadata_location_summary(fmt, mdah, NULL, &rl->dev_area, &vgsummary, NULL)) {
|
||||
vg = _vg_read_raw_area(&fid, vgsummary.vgname, &rl->dev_area, NULL, NULL, NULL, 0);
|
||||
if (vg) {
|
||||
/* TODO: caching as in vgname_from_mda() (trigger this code?) */
|
||||
if (vgname_from_mda(fmt, mdah, &rl->dev_area, &vgsummary, NULL)) {
|
||||
vg = _vg_read_raw_area(&fid, vgsummary.vgname, &rl->dev_area, NULL, NULL, 0, 0);
|
||||
if (vg)
|
||||
lvmcache_update_vg(vg, 0);
|
||||
lvmcache_set_independent_location(vg->name);
|
||||
}
|
||||
}
|
||||
close_dev:
|
||||
if (!dev_close(rl->dev_area.dev))
|
||||
@@ -1349,13 +1285,9 @@ static int _scan_raw(const struct format_type *fmt, const char *vgname __attribu
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* used for independent_metadata_areas */
|
||||
|
||||
static int _text_scan(const struct format_type *fmt, const char *vgname)
|
||||
{
|
||||
_scan_file(fmt, vgname);
|
||||
_scan_raw(fmt, vgname);
|
||||
return 1;
|
||||
return (_scan_file(fmt, vgname) & _scan_raw(fmt, vgname));
|
||||
}
|
||||
|
||||
struct _write_single_mda_baton {
|
||||
@@ -1698,10 +1630,10 @@ static int _text_pv_initialise(const struct format_type *fmt,
|
||||
log_error("%s: Bootloader area would overlap "
|
||||
"data area.", pv_dev_name(pv));
|
||||
return 0;
|
||||
} else {
|
||||
pv->ba_start = pva->ba_start ? : final_alignment;
|
||||
pv->ba_size = pva->ba_size;
|
||||
}
|
||||
|
||||
pv->ba_start = pva->ba_start ? : final_alignment;
|
||||
pv->ba_size = pva->ba_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1807,8 +1739,6 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
|
||||
.mda_import_text = _mda_import_text_raw
|
||||
};
|
||||
|
||||
/* used only for sending info to lvmetad */
|
||||
|
||||
static int _mda_export_text_raw(struct metadata_area *mda,
|
||||
struct dm_config_tree *cft,
|
||||
struct dm_config_node *parent)
|
||||
@@ -1816,13 +1746,7 @@ static int _mda_export_text_raw(struct metadata_area *mda,
|
||||
struct mda_context *mdc = (struct mda_context *) mda->metadata_locn;
|
||||
char mdah[MDA_HEADER_SIZE]; /* temporary */
|
||||
|
||||
if (!mdc) {
|
||||
log_error(INTERNAL_ERROR "mda_export_text_raw no mdc");
|
||||
return 1; /* pretend the MDA does not exist */
|
||||
}
|
||||
|
||||
/* FIXME: why aren't ignore,start,size,free_sectors available? */
|
||||
if (!_raw_read_mda_header((struct mda_header *)mdah, &mdc->area, NULL))
|
||||
if (!mdc || !_raw_read_mda_header((struct mda_header *)mdah, &mdc->area))
|
||||
return 1; /* pretend the MDA does not exist */
|
||||
|
||||
return config_make_nodes(cft, parent, NULL,
|
||||
@@ -1833,8 +1757,6 @@ static int _mda_export_text_raw(struct metadata_area *mda,
|
||||
NULL) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* used only for receiving info from lvmetad */
|
||||
|
||||
static int _mda_import_text_raw(struct lvmcache_info *info, const struct dm_config_node *cn)
|
||||
{
|
||||
struct device *device;
|
||||
@@ -2064,13 +1986,26 @@ static int _create_vg_text_instance(struct format_instance *fid,
|
||||
}
|
||||
|
||||
if (type & FMT_INSTANCE_MDAS) {
|
||||
/*
|
||||
* TODO in theory, this function should be never reached
|
||||
* while in critical_section(), because lvmcache's
|
||||
* cached_vg should be valid. However, this assumption
|
||||
* sometimes fails (possibly due to inconsistent
|
||||
* (precommit) metadata and/or missing devices), and
|
||||
* calling lvmcache_label_scan inside the critical
|
||||
* section may be fatal (i.e. deadlock).
|
||||
*/
|
||||
if (!critical_section())
|
||||
/* Scan PVs in VG for any further MDAs */
|
||||
lvmcache_label_scan(fid->fmt->cmd);
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vg_name, vg_id)))
|
||||
goto_out;
|
||||
if (!lvmcache_fid_add_mdas_vg(vginfo, fid))
|
||||
goto_out;
|
||||
}
|
||||
|
||||
/* FIXME If PV list or raw metadata area count are not as expected rescan */
|
||||
/* FIXME Check raw metadata area count - rescan if required */
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -2135,7 +2070,7 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
|
||||
{
|
||||
struct format_instance *fid = pv->fid;
|
||||
const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
|
||||
uint64_t ba_size, pe_start, first_unallocated;
|
||||
uint64_t ba_size, pe_start, pe_end;
|
||||
uint64_t alignment, alignment_offset;
|
||||
uint64_t disk_size;
|
||||
uint64_t mda_start;
|
||||
@@ -2270,24 +2205,14 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
|
||||
* if defined or locked. If pe_start is not defined yet, count
|
||||
* with any existing MDA0. If MDA0 does not exist, just use
|
||||
* LABEL_SCAN_SIZE.
|
||||
*
|
||||
* The first_unallocated here is the first unallocated byte
|
||||
* beyond existing pe_end if there is any preallocated data area
|
||||
* reserved already so we can take that as lower limit for our MDA1
|
||||
* start calculation. If data area is not reserved yet, we set
|
||||
* first_unallocated to 0, meaning this is not our limiting factor
|
||||
* and we will look at other limiting factors if they exist.
|
||||
* Of course, if we have preallocated data area, we also must
|
||||
* have pe_start assigned too (simply, data area needs its start
|
||||
* and end specification).
|
||||
*/
|
||||
first_unallocated = pv->pe_count ? (pv->pe_start + pv->pe_count *
|
||||
(uint64_t)pv->pe_size) << SECTOR_SHIFT
|
||||
: 0;
|
||||
pe_end = pv->pe_count ? (pv->pe_start +
|
||||
pv->pe_count * (uint64_t)pv->pe_size - 1) << SECTOR_SHIFT
|
||||
: 0;
|
||||
|
||||
if (pe_start || pe_start_locked) {
|
||||
limit = first_unallocated ? first_unallocated : pe_start;
|
||||
limit_name = first_unallocated ? "pe_end" : "pe_start";
|
||||
limit = pe_end ? pe_end : pe_start;
|
||||
limit_name = pe_end ? "pe_end" : "pe_start";
|
||||
} else {
|
||||
if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 0)) &&
|
||||
(mdac = mda->metadata_locn)) {
|
||||
@@ -2306,7 +2231,7 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
|
||||
}
|
||||
}
|
||||
|
||||
if (limit >= disk_size)
|
||||
if (limit > disk_size)
|
||||
goto bad;
|
||||
|
||||
if (mda_size > disk_size) {
|
||||
@@ -2332,6 +2257,16 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
|
||||
mda_start = disk_size - mda_size;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If PV's pe_end not set yet, set it to the end of the
|
||||
* area that precedes the MDA1 we've just calculated.
|
||||
* FIXME: do we need to set this? Isn't it always set before?
|
||||
*/
|
||||
/*if (!pe_end) {
|
||||
pe_end = mda_start;
|
||||
pv->pe_end = pe_end >> SECTOR_SHIFT;
|
||||
}*/
|
||||
}
|
||||
|
||||
if (limit_applied)
|
||||
@@ -2348,9 +2283,9 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
|
||||
}
|
||||
|
||||
/* Wipe metadata area with zeroes. */
|
||||
if (!dev_set(pv->dev, mda_start,
|
||||
(size_t) ((mda_size > wipe_size) ?
|
||||
wipe_size : mda_size), 0)) {
|
||||
if (!dev_set((struct device *) pv->dev, mda_start,
|
||||
(size_t) ((mda_size > wipe_size) ?
|
||||
wipe_size : mda_size), 0)) {
|
||||
log_error("Failed to wipe new metadata area "
|
||||
"at the %s of the %s",
|
||||
mda_index ? "end" : "start",
|
||||
@@ -2533,7 +2468,7 @@ static int _get_config_disk_area(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dev_area.dev = lvmcache_device_from_pvid(cmd, &id, NULL))) {
|
||||
if (!(dev_area.dev = lvmcache_device_from_pvid(cmd, &id, NULL, NULL))) {
|
||||
char buffer[64] __attribute__((aligned(8)));
|
||||
|
||||
if (!id_write_format(&id, buffer, sizeof(buffer)))
|
||||
|
@@ -49,6 +49,7 @@ struct text_vg_version_ops {
|
||||
int (*check_version) (const struct dm_config_tree * cf);
|
||||
struct volume_group *(*read_vg) (struct format_instance * fid,
|
||||
const struct dm_config_tree *cf,
|
||||
unsigned use_cached_pvs,
|
||||
unsigned allow_lvmetad_extensions);
|
||||
void (*read_desc) (struct dm_pool * mem, const struct dm_config_tree *cf,
|
||||
time_t *when, char **desc);
|
||||
@@ -63,28 +64,27 @@ int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint6
|
||||
int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm_config_value *cv);
|
||||
|
||||
int print_segtype_lvflags(char *buffer, size_t size, uint64_t status);
|
||||
int read_segtype_lvflags(uint64_t *status, char *segtype_str);
|
||||
int read_segtype_lvflags(uint64_t *status, char *segtype_scr);
|
||||
|
||||
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
|
||||
size_t text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf);
|
||||
struct volume_group *text_read_metadata_file(struct format_instance *fid,
|
||||
struct volume_group *text_vg_import_file(struct format_instance *fid,
|
||||
const char *file,
|
||||
time_t *when, char **desc);
|
||||
struct volume_group *text_read_metadata(struct format_instance *fid,
|
||||
struct device *dev,
|
||||
struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
const char *file,
|
||||
struct label_read_data *ld,
|
||||
struct cached_vg_fmtdata **vg_fmtdata,
|
||||
unsigned *use_previous_vg,
|
||||
int single_device,
|
||||
struct device *dev,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
checksum_fn_t checksum_fn,
|
||||
uint32_t checksum,
|
||||
time_t *when, char **desc);
|
||||
|
||||
int text_read_metadata_summary(const struct format_type *fmt,
|
||||
int text_vgsummary_import(const struct format_type *fmt,
|
||||
struct device *dev,
|
||||
struct label_read_data *ld,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
checksum_fn_t checksum_fn,
|
||||
|
@@ -35,9 +35,8 @@ static void _init_text_import(void)
|
||||
/*
|
||||
* Find out vgname on a given device.
|
||||
*/
|
||||
int text_read_metadata_summary(const struct format_type *fmt,
|
||||
int text_vgsummary_import(const struct format_type *fmt,
|
||||
struct device *dev,
|
||||
struct label_read_data *ld,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
checksum_fn_t checksum_fn,
|
||||
@@ -46,52 +45,20 @@ int text_read_metadata_summary(const struct format_type *fmt,
|
||||
{
|
||||
struct dm_config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
char *buf = NULL;
|
||||
int r = 0;
|
||||
|
||||
if (ld) {
|
||||
if (ld->buf_len >= (offset + size))
|
||||
buf = ld->buf;
|
||||
else {
|
||||
/*
|
||||
* Needs data beyond the end of the ld buffer.
|
||||
* Will do a new synchronous read to get the data.
|
||||
* (scan_size could also be made larger.)
|
||||
*/
|
||||
log_debug_metadata("label scan buffer for %s len %u does not include metadata at %llu size %u",
|
||||
dev_name(dev), ld->buf_len, (unsigned long long)offset, size);
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_init_text_import();
|
||||
|
||||
if (!(cft = config_open(CONFIG_FILE_SPECIAL, NULL, 0)))
|
||||
return_0;
|
||||
|
||||
if (dev) {
|
||||
if (buf)
|
||||
log_debug_metadata("Copying metadata summary for %s at %llu size %d (+%d)",
|
||||
dev_name(dev), (unsigned long long)offset,
|
||||
size, size2);
|
||||
else
|
||||
log_debug_metadata("Reading metadata summary from %s at %llu size %d (+%d)",
|
||||
dev_name(dev), (unsigned long long)offset,
|
||||
size, size2);
|
||||
|
||||
if (!config_file_read_fd(cft, dev, buf, offset, size,
|
||||
if ((!dev && !config_file_read(cft)) ||
|
||||
(dev && !config_file_read_fd(cft, dev, offset, size,
|
||||
offset2, size2, checksum_fn,
|
||||
vgsummary->mda_checksum,
|
||||
checksum_only, 1)) {
|
||||
/* FIXME: handle errors */
|
||||
log_error("Couldn't read volume group metadata from %s.", dev_name(dev));
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (!config_file_read(cft)) {
|
||||
log_error("Couldn't read volume group metadata from file.");
|
||||
goto out;
|
||||
}
|
||||
checksum_only, 1))) {
|
||||
log_error("Couldn't read volume group metadata.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (checksum_only) {
|
||||
@@ -124,12 +91,12 @@ struct cached_vg_fmtdata {
|
||||
size_t cached_mda_size;
|
||||
};
|
||||
|
||||
struct volume_group *text_read_metadata(struct format_instance *fid,
|
||||
struct device *dev,
|
||||
struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
const char *file,
|
||||
struct label_read_data *ld,
|
||||
struct cached_vg_fmtdata **vg_fmtdata,
|
||||
unsigned *use_previous_vg,
|
||||
int single_device,
|
||||
struct device *dev,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
checksum_fn_t checksum_fn,
|
||||
@@ -139,18 +106,8 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
|
||||
struct volume_group *vg = NULL;
|
||||
struct dm_config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
char *buf = NULL;
|
||||
int skip_parse;
|
||||
|
||||
/*
|
||||
* This struct holds the checksum and size of the VG metadata
|
||||
* that was read from a previous device. When we read the VG
|
||||
* metadata from this device, we can skip parsing it into a
|
||||
* cft (saving time) if the checksum of the metadata buffer
|
||||
* we read from this device matches the size/checksum saved in
|
||||
* the mda_header/rlocn struct on this device, and matches the
|
||||
* size/checksum from the previous device.
|
||||
*/
|
||||
if (vg_fmtdata && !*vg_fmtdata &&
|
||||
!(*vg_fmtdata = dm_pool_zalloc(fid->mem, sizeof(**vg_fmtdata)))) {
|
||||
log_error("Failed to allocate VG fmtdata for text format.");
|
||||
@@ -170,49 +127,15 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
|
||||
((*vg_fmtdata)->cached_mda_checksum == checksum) &&
|
||||
((*vg_fmtdata)->cached_mda_size == (size + size2));
|
||||
|
||||
if (ld) {
|
||||
if (ld->buf_len >= (offset + size))
|
||||
buf = ld->buf;
|
||||
else {
|
||||
/*
|
||||
* Needs data beyond the end of the ld buffer.
|
||||
* Will do a new synchronous read to get the data.
|
||||
* (scan_size could also be made larger.)
|
||||
*/
|
||||
log_debug_metadata("label scan buffer for %s len %u does not include metadata at %llu size %u",
|
||||
dev_name(dev), ld->buf_len, (unsigned long long)offset, size);
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
if (buf)
|
||||
log_debug_metadata("Copying metadata for %s at %llu size %d (+%d)",
|
||||
dev_name(dev), (unsigned long long)offset,
|
||||
size, size2);
|
||||
else
|
||||
log_debug_metadata("Reading metadata from %s at %llu size %d (+%d)",
|
||||
dev_name(dev), (unsigned long long)offset,
|
||||
size, size2);
|
||||
|
||||
if (!config_file_read_fd(cft, dev, buf, offset, size,
|
||||
if ((!dev && !config_file_read(cft)) ||
|
||||
(dev && !config_file_read_fd(cft, dev, offset, size,
|
||||
offset2, size2, checksum_fn, checksum,
|
||||
skip_parse, 1)) {
|
||||
/* FIXME: handle errors */
|
||||
log_error("Couldn't read volume group metadata from %s.", dev_name(dev));
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (!config_file_read(cft)) {
|
||||
log_error("Couldn't read volume group metadata from file.");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
skip_parse, 1)))
|
||||
goto_out;
|
||||
|
||||
if (skip_parse) {
|
||||
if (use_previous_vg)
|
||||
*use_previous_vg = 1;
|
||||
log_debug_metadata("Skipped parsing metadata on %s", dev_name(dev));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -223,7 +146,7 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
|
||||
if (!(*vsn)->check_version(cft))
|
||||
continue;
|
||||
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft, 0)))
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft, single_device, 0)))
|
||||
goto_out;
|
||||
|
||||
(*vsn)->read_desc(vg->vgmem, cft, when, desc);
|
||||
@@ -243,20 +166,17 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
|
||||
return vg;
|
||||
}
|
||||
|
||||
struct volume_group *text_read_metadata_file(struct format_instance *fid,
|
||||
struct volume_group *text_vg_import_file(struct format_instance *fid,
|
||||
const char *file,
|
||||
time_t *when, char **desc)
|
||||
{
|
||||
return text_read_metadata(fid, NULL, file, NULL, NULL, NULL,
|
||||
(off_t)0, 0, (off_t)0, 0,
|
||||
NULL,
|
||||
0,
|
||||
return text_vg_import_fd(fid, file, NULL, NULL, 0, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
|
||||
when, desc);
|
||||
}
|
||||
|
||||
static struct volume_group *_import_vg_from_config_tree(const struct dm_config_tree *cft,
|
||||
struct format_instance *fid,
|
||||
unsigned for_lvmetad)
|
||||
unsigned allow_lvmetad_extensions)
|
||||
{
|
||||
struct volume_group *vg = NULL;
|
||||
struct text_vg_version_ops **vsn;
|
||||
@@ -271,7 +191,7 @@ static struct volume_group *_import_vg_from_config_tree(const struct dm_config_t
|
||||
* The only path to this point uses cached vgmetadata,
|
||||
* so it can use cached PV state too.
|
||||
*/
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft, for_lvmetad)))
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft, 1, allow_lvmetad_extensions)))
|
||||
stack;
|
||||
else if ((vg_missing = vg_missing_pv_count(vg))) {
|
||||
log_verbose("There are %d physical volumes missing.",
|
||||
|
@@ -32,16 +32,18 @@ typedef int (*section_fn) (struct format_instance * fid,
|
||||
struct volume_group * vg, const struct dm_config_node * pvn,
|
||||
const struct dm_config_node * vgn,
|
||||
struct dm_hash_table * pv_hash,
|
||||
struct dm_hash_table * lv_hash);
|
||||
struct dm_hash_table * lv_hash,
|
||||
unsigned *scan_done_once,
|
||||
unsigned report_missing_devices);
|
||||
|
||||
#define _read_int32(root, path, result) \
|
||||
dm_config_get_uint32(root, path, (uint32_t *) (result))
|
||||
dm_config_get_uint32(root, path, (uint32_t *) result)
|
||||
|
||||
#define _read_uint32(root, path, result) \
|
||||
dm_config_get_uint32(root, path, (result))
|
||||
dm_config_get_uint32(root, path, result)
|
||||
|
||||
#define _read_uint64(root, path, result) \
|
||||
dm_config_get_uint64(root, path, (result))
|
||||
dm_config_get_uint64(root, path, result)
|
||||
|
||||
/*
|
||||
* Logs an attempt to read an invalid format file.
|
||||
@@ -178,7 +180,9 @@ static int _read_pv(struct format_instance *fid,
|
||||
struct volume_group *vg, const struct dm_config_node *pvn,
|
||||
const struct dm_config_node *vgn __attribute__((unused)),
|
||||
struct dm_hash_table *pv_hash,
|
||||
struct dm_hash_table *lv_hash __attribute__((unused)))
|
||||
struct dm_hash_table *lv_hash __attribute__((unused)),
|
||||
unsigned *scan_done_once,
|
||||
unsigned report_missing_devices)
|
||||
{
|
||||
struct dm_pool *mem = vg->vgmem;
|
||||
struct physical_volume *pv;
|
||||
@@ -216,16 +220,16 @@ static int _read_pv(struct format_instance *fid,
|
||||
/*
|
||||
* Convert the uuid into a device.
|
||||
*/
|
||||
if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, &pv->label_sector))) {
|
||||
if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
|
||||
&pv->label_sector))) {
|
||||
char buffer[64] __attribute__((aligned(8)));
|
||||
|
||||
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
|
||||
buffer[0] = '\0';
|
||||
|
||||
if (fid->fmt->cmd && !fid->fmt->cmd->pvscan_cache_single)
|
||||
if (report_missing_devices)
|
||||
log_error_once("Couldn't find device with uuid %s.", buffer);
|
||||
else
|
||||
log_debug_metadata("Couldn't find device with uuid %s.", buffer);
|
||||
log_very_verbose("Couldn't find device with uuid %s.", buffer);
|
||||
}
|
||||
|
||||
if (!(pv->vg_name = dm_pool_strdup(mem, vg->name)))
|
||||
@@ -570,7 +574,9 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
|
||||
struct volume_group *vg, const struct dm_config_node *lvn,
|
||||
const struct dm_config_node *vgn __attribute__((unused)),
|
||||
struct dm_hash_table *pv_hash __attribute__((unused)),
|
||||
struct dm_hash_table *lv_hash)
|
||||
struct dm_hash_table *lv_hash,
|
||||
unsigned *scan_done_once __attribute__((unused)),
|
||||
unsigned report_missing_devices __attribute__((unused)))
|
||||
{
|
||||
struct dm_pool *mem = vg->vgmem;
|
||||
struct logical_volume *lv;
|
||||
@@ -725,7 +731,9 @@ static int _read_historical_lvnames(struct format_instance *fid __attribute__((u
|
||||
struct volume_group *vg, const struct dm_config_node *hlvn,
|
||||
const struct dm_config_node *vgn __attribute__((unused)),
|
||||
struct dm_hash_table *pv_hash __attribute__((unused)),
|
||||
struct dm_hash_table *lv_hash __attribute__((unused)))
|
||||
struct dm_hash_table *lv_hash __attribute__((unused)),
|
||||
unsigned *scan_done_once __attribute__((unused)),
|
||||
unsigned report_missing_devices __attribute__((unused)))
|
||||
{
|
||||
struct dm_pool *mem = vg->vgmem;
|
||||
struct generic_logical_volume *glv;
|
||||
@@ -794,7 +802,9 @@ static int _read_historical_lvnames_interconnections(struct format_instance *fid
|
||||
struct volume_group *vg, const struct dm_config_node *hlvn,
|
||||
const struct dm_config_node *vgn __attribute__((unused)),
|
||||
struct dm_hash_table *pv_hash __attribute__((unused)),
|
||||
struct dm_hash_table *lv_hash __attribute__((unused)))
|
||||
struct dm_hash_table *lv_hash __attribute__((unused)),
|
||||
unsigned *scan_done_once __attribute__((unused)),
|
||||
unsigned report_missing_devices __attribute__((unused)))
|
||||
{
|
||||
struct dm_pool *mem = vg->vgmem;
|
||||
const char *historical_lv_name, *origin_name = NULL;
|
||||
@@ -904,7 +914,9 @@ static int _read_lvsegs(struct format_instance *fid,
|
||||
struct volume_group *vg, const struct dm_config_node *lvn,
|
||||
const struct dm_config_node *vgn __attribute__((unused)),
|
||||
struct dm_hash_table *pv_hash,
|
||||
struct dm_hash_table *lv_hash)
|
||||
struct dm_hash_table *lv_hash,
|
||||
unsigned *scan_done_once __attribute__((unused)),
|
||||
unsigned report_missing_devices __attribute__((unused)))
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
|
||||
@@ -965,9 +977,12 @@ static int _read_sections(struct format_instance *fid,
|
||||
struct volume_group *vg, const struct dm_config_node *vgn,
|
||||
struct dm_hash_table *pv_hash,
|
||||
struct dm_hash_table *lv_hash,
|
||||
int optional)
|
||||
int optional,
|
||||
unsigned *scan_done_once)
|
||||
{
|
||||
const struct dm_config_node *n;
|
||||
/* Only report missing devices when doing a scan */
|
||||
unsigned report_missing_devices = scan_done_once ? !*scan_done_once : 1;
|
||||
|
||||
if (!dm_config_get_section(vgn, section, &n)) {
|
||||
if (!optional) {
|
||||
@@ -979,7 +994,8 @@ static int _read_sections(struct format_instance *fid,
|
||||
}
|
||||
|
||||
for (n = n->child; n; n = n->sib) {
|
||||
if (!fn(fid, vg, n, vgn, pv_hash, lv_hash))
|
||||
if (!fn(fid, vg, n, vgn, pv_hash, lv_hash,
|
||||
scan_done_once, report_missing_devices))
|
||||
return_0;
|
||||
}
|
||||
|
||||
@@ -988,13 +1004,15 @@ static int _read_sections(struct format_instance *fid,
|
||||
|
||||
static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
const struct dm_config_tree *cft,
|
||||
unsigned for_lvmetad)
|
||||
unsigned use_cached_pvs,
|
||||
unsigned allow_lvmetad_extensions)
|
||||
{
|
||||
const struct dm_config_node *vgn;
|
||||
const struct dm_config_value *cv;
|
||||
const char *str, *format_str, *system_id;
|
||||
struct volume_group *vg;
|
||||
struct dm_hash_table *pv_hash = NULL, *lv_hash = NULL;
|
||||
unsigned scan_done_once = use_cached_pvs;
|
||||
uint64_t vgstatus;
|
||||
|
||||
/* skip any top-level values */
|
||||
@@ -1149,15 +1167,15 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
}
|
||||
|
||||
if (!_read_sections(fid, "physical_volumes", _read_pv, vg,
|
||||
vgn, pv_hash, lv_hash, 0)) {
|
||||
vgn, pv_hash, lv_hash, 0, &scan_done_once)) {
|
||||
log_error("Couldn't find all physical volumes for volume "
|
||||
"group %s.", vg->name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (for_lvmetad)
|
||||
if (allow_lvmetad_extensions)
|
||||
_read_sections(fid, "outdated_pvs", _read_pv, vg,
|
||||
vgn, pv_hash, lv_hash, 1);
|
||||
vgn, pv_hash, lv_hash, 1, &scan_done_once);
|
||||
else if (dm_config_has_node(vgn, "outdated_pvs"))
|
||||
log_error(INTERNAL_ERROR "Unexpected outdated_pvs section in metadata of VG %s.", vg->name);
|
||||
|
||||
@@ -1169,28 +1187,28 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
}
|
||||
|
||||
if (!_read_sections(fid, "logical_volumes", _read_lvnames, vg,
|
||||
vgn, pv_hash, lv_hash, 1)) {
|
||||
vgn, pv_hash, lv_hash, 1, NULL)) {
|
||||
log_error("Couldn't read all logical volume names for volume "
|
||||
"group %s.", vg->name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!_read_sections(fid, "historical_logical_volumes", _read_historical_lvnames, vg,
|
||||
vgn, pv_hash, lv_hash, 1)) {
|
||||
vgn, pv_hash, lv_hash, 1, NULL)) {
|
||||
log_error("Couldn't read all historical logical volumes for volume "
|
||||
"group %s.", vg->name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!_read_sections(fid, "logical_volumes", _read_lvsegs, vg,
|
||||
vgn, pv_hash, lv_hash, 1)) {
|
||||
vgn, pv_hash, lv_hash, 1, NULL)) {
|
||||
log_error("Couldn't read all logical volumes for "
|
||||
"volume group %s.", vg->name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!_read_sections(fid, "historical_logical_volumes", _read_historical_lvnames_interconnections,
|
||||
vg, vgn, pv_hash, lv_hash, 1)) {
|
||||
vg, vgn, pv_hash, lv_hash, 1, NULL)) {
|
||||
log_error("Couldn't read all removed logical volume interconnections "
|
||||
"for volume group %s.", vg->name);
|
||||
goto bad;
|
||||
|
@@ -81,8 +81,7 @@ struct mda_header {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mda_header *raw_read_mda_header(const struct format_type *fmt,
|
||||
struct device_area *dev_area,
|
||||
struct label_read_data *ld);
|
||||
struct device_area *dev_area);
|
||||
|
||||
struct mda_lists {
|
||||
struct dm_list dirs;
|
||||
@@ -104,8 +103,7 @@ struct mda_context {
|
||||
#define LVM2_LABEL "LVM2 001"
|
||||
#define MDA_SIZE_MIN (8 * (unsigned) lvm_getpagesize())
|
||||
|
||||
int read_metadata_location_summary(const struct format_type *fmt, struct mda_header *mdah,
|
||||
struct label_read_data *ld,
|
||||
int vgname_from_mda(const struct format_type *fmt, struct mda_header *mdah,
|
||||
struct device_area *dev_area, struct lvmcache_vgsummary *vgsummary,
|
||||
uint64_t *mda_free_sectors);
|
||||
|
||||
|
@@ -308,22 +308,14 @@ static int _text_initialise_label(struct labeller *l __attribute__((unused)),
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct _mda_baton {
|
||||
struct _update_mda_baton {
|
||||
struct lvmcache_info *info;
|
||||
struct label *label;
|
||||
struct label_read_data *ld;
|
||||
};
|
||||
|
||||
/*
|
||||
* FIXME: optimize reads when there is a second mda at the end
|
||||
* of the PV. For the second mda we should also have a single
|
||||
* large read covering mda_header and metadata, and we should
|
||||
* be able to reuse it in vg_read.
|
||||
*/
|
||||
|
||||
static int _read_mda_header_and_metadata(struct metadata_area *mda, void *baton)
|
||||
static int _update_mda(struct metadata_area *mda, void *baton)
|
||||
{
|
||||
struct _mda_baton *p = baton;
|
||||
struct _update_mda_baton *p = baton;
|
||||
const struct format_type *fmt = p->label->labeller->fmt;
|
||||
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
|
||||
struct mda_header *mdah;
|
||||
@@ -342,7 +334,7 @@ static int _read_mda_header_and_metadata(struct metadata_area *mda, void *baton)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(mdah = raw_read_mda_header(fmt, &mdac->area, p->ld))) {
|
||||
if (!(mdah = raw_read_mda_header(fmt, &mdac->area))) {
|
||||
stack;
|
||||
goto close_dev;
|
||||
}
|
||||
@@ -358,7 +350,7 @@ static int _read_mda_header_and_metadata(struct metadata_area *mda, void *baton)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (read_metadata_location_summary(fmt, mdah, p->ld, &mdac->area, &vgsummary,
|
||||
if (vgname_from_mda(fmt, mdah, &mdac->area, &vgsummary,
|
||||
&mdac->free_sectors) &&
|
||||
!lvmcache_update_vgname_and_id(p->info, &vgsummary)) {
|
||||
if (!dev_close(mdac->area.dev))
|
||||
@@ -373,29 +365,22 @@ close_dev:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* When label_read_data *ld is set, it means that we have read the first
|
||||
* ld->buf_len bytes of the device and already have that data, so we don't need
|
||||
* to do any dev_read's (as long as the desired dev_read offset+size is less
|
||||
* then ld->buf_len).
|
||||
*/
|
||||
|
||||
static int _text_read(struct labeller *l, struct device *dev, void *label_buf,
|
||||
struct label_read_data *ld, struct label **label)
|
||||
static int _text_read(struct labeller *l, struct device *dev, void *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) label_buf;
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
struct pv_header *pvhdr;
|
||||
struct pv_header_extension *pvhdr_ext;
|
||||
struct lvmcache_info *info;
|
||||
struct disk_locn *dlocn_xl;
|
||||
uint64_t offset;
|
||||
uint32_t ext_version;
|
||||
struct _mda_baton baton;
|
||||
struct _update_mda_baton baton;
|
||||
|
||||
/*
|
||||
* PV header base
|
||||
*/
|
||||
pvhdr = (struct pv_header *) ((char *) label_buf + xlate32(lh->offset_xl));
|
||||
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
|
||||
|
||||
if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev,
|
||||
FMT_TEXT_ORPHAN_VG_NAME,
|
||||
@@ -451,10 +436,8 @@ static int _text_read(struct labeller *l, struct device *dev, void *label_buf,
|
||||
out:
|
||||
baton.info = info;
|
||||
baton.label = *label;
|
||||
baton.ld = ld;
|
||||
|
||||
lvmcache_foreach_mda(info, _read_mda_header_and_metadata, &baton);
|
||||
|
||||
lvmcache_foreach_mda(info, _update_mda, &baton);
|
||||
lvmcache_make_valid(info);
|
||||
|
||||
return 1;
|
||||
|
1020
lib/label/label.c
1020
lib/label/label.c
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,6 @@
|
||||
|
||||
#include "uuid.h"
|
||||
#include "device.h"
|
||||
#include "toolcontext.h"
|
||||
|
||||
#define LABEL_ID "LABELONE"
|
||||
#define LABEL_SIZE SECTOR_SIZE /* Think very carefully before changing this */
|
||||
@@ -29,17 +28,6 @@ struct labeller;
|
||||
|
||||
void allow_reads_with_lvmetad(void);
|
||||
|
||||
struct label_read_data {
|
||||
struct dev_async_io *aio;
|
||||
char *buf; /* points to aio->buf */
|
||||
struct device *dev;
|
||||
struct dm_list list;
|
||||
int buf_len; /* same as aio->buf_len */
|
||||
int result; /* same as aio->result */
|
||||
int try_sync;
|
||||
int process_done;
|
||||
};
|
||||
|
||||
/* On disk - 32 bytes */
|
||||
struct label_header {
|
||||
int8_t id[8]; /* LABELONE */
|
||||
@@ -75,8 +63,7 @@ struct label_ops {
|
||||
* Read a label from a volume.
|
||||
*/
|
||||
int (*read) (struct labeller * l, struct device * dev,
|
||||
void *label_buf,
|
||||
struct label_read_data *ld, struct label ** label);
|
||||
void *buf, struct label ** label);
|
||||
|
||||
/*
|
||||
* Additional consistency checks for the paranoid.
|
||||
@@ -112,16 +99,11 @@ int label_register_handler(struct labeller *handler);
|
||||
struct labeller *label_get_handler(const char *name);
|
||||
|
||||
int label_remove(struct device *dev);
|
||||
int label_read(struct device *dev, struct label **label, uint64_t scan_sector);
|
||||
int label_read(struct device *dev, struct label **result,
|
||||
uint64_t scan_sector);
|
||||
int label_write(struct device *dev, struct label *label);
|
||||
int label_verify(struct device *dev);
|
||||
struct label *label_create(struct labeller *labeller);
|
||||
void label_destroy(struct label *label);
|
||||
|
||||
int label_scan_force(struct cmd_context *cmd);
|
||||
int label_scan(struct cmd_context *cmd);
|
||||
int label_scan_devs(struct cmd_context *cmd, struct dm_list *devs);
|
||||
struct label_read_data *get_label_read_data(struct cmd_context *cmd, struct device *dev);
|
||||
void label_scan_destroy(struct cmd_context *cmd);
|
||||
|
||||
#endif
|
||||
|
@@ -515,18 +515,15 @@ static int _lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
return _lock_for_cluster(cmd, clvmd_cmd, flags, lockname);
|
||||
}
|
||||
|
||||
static int _decode_lock_type(const char *response)
|
||||
static int decode_lock_type(const char *response)
|
||||
{
|
||||
if (!response)
|
||||
return LCK_NULL;
|
||||
|
||||
if (!strcmp(response, "EX"))
|
||||
else if (!strcmp(response, "EX"))
|
||||
return LCK_EXCL;
|
||||
|
||||
if (!strcmp(response, "CR"))
|
||||
else if (!strcmp(response, "CR"))
|
||||
return LCK_READ;
|
||||
|
||||
if (!strcmp(response, "PR"))
|
||||
else if (!strcmp(response, "PR"))
|
||||
return LCK_PREAD;
|
||||
|
||||
return_0;
|
||||
@@ -566,8 +563,8 @@ int query_resource(const char *resource, const char *node, int *mode)
|
||||
* If two nodes report different locks,
|
||||
* something is broken - just return more important mode.
|
||||
*/
|
||||
if (_decode_lock_type(response[i].response) > *mode)
|
||||
*mode = _decode_lock_type(response[i].response);
|
||||
if (decode_lock_type(response[i].response) > *mode)
|
||||
*mode = decode_lock_type(response[i].response);
|
||||
|
||||
log_debug_locking("Lock held for %s, node %s : %s", resource,
|
||||
response[i].node, response[i].response);
|
||||
|
@@ -51,8 +51,8 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
switch (flags & LCK_SCOPE_MASK) {
|
||||
case LCK_ACTIVATION:
|
||||
if (dm_snprintf(lockfile, sizeof(lockfile),
|
||||
"%s/A_%s", _lock_dir, resource) < 0) {
|
||||
log_error("Too long locking filename %s/A_%s.", _lock_dir, resource);
|
||||
"%s/A_%s", _lock_dir, resource + 1) < 0) {
|
||||
log_error("Too long locking filename %s/A_%s.", _lock_dir, resource + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -187,9 +187,9 @@ int init_locking(int type, struct cmd_context *cmd, int suppress_messages)
|
||||
"be inaccessible.");
|
||||
if (init_file_locking(&_locking, cmd, suppress_messages))
|
||||
return 1;
|
||||
|
||||
log_error_suppress(suppress_messages,
|
||||
"File-based locking initialisation failed.");
|
||||
else
|
||||
log_error_suppress(suppress_messages,
|
||||
"File-based locking initialisation failed.");
|
||||
}
|
||||
|
||||
if (!ignorelockingfailure())
|
||||
@@ -232,9 +232,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
|
||||
log_error("%s exists: Is the original LVM driver using "
|
||||
"this volume group?", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (errno != ENOENT && errno != ENOTDIR) {
|
||||
} else if (errno != ENOENT && errno != ENOTDIR) {
|
||||
log_sys_error("stat", path);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -166,25 +166,22 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_LV_CLUSTERED(lv) \
|
||||
(vg_is_clustered((lv)->vg) ? LCK_CLUSTER_VG : 0)
|
||||
|
||||
#define lock_lv_vol(cmd, lv, flags) lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv), lv)
|
||||
#define lock_lv_vol(cmd, lv, flags) \
|
||||
(find_replicator_vgs((lv)) ? \
|
||||
lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv), lv) : \
|
||||
0)
|
||||
|
||||
/*
|
||||
* Activation locks are wrapped around activation commands that have to
|
||||
* be processed atomically one-at-a-time.
|
||||
* If a VG WRITE lock is held or clustered activation activates simple LV
|
||||
* an activation lock is redundant.
|
||||
* If a VG WRITE lock is held, an activation lock is redundant.
|
||||
*
|
||||
* Some LV types do require taking a lock common for whole group of LVs.
|
||||
* TODO: For simplicity reasons ATM take a VG activation global lock and
|
||||
* later more fine-grained component detection algorithm can be added
|
||||
* FIXME Test and support this for thin and cache types.
|
||||
* FIXME Add cluster support.
|
||||
*/
|
||||
|
||||
#define lv_type_requires_activation_lock(lv) ((lv_is_thin_type(lv) || lv_is_cache_type(lv) || lv_is_mirror_type(lv) || lv_is_raid_type(lv) || lv_is_origin(lv) || lv_is_snapshot(lv)) ? 1 : 0)
|
||||
#define lv_activation_lock_name(lv) (lv_type_requires_activation_lock(lv) ? (lv)->vg->name : (lv)->lvid.s)
|
||||
#define lv_requires_activation_lock_now(lv) ((!vg_write_lock_held() && (!vg_is_clustered((lv)->vg) || !lv_type_requires_activation_lock(lv))) ? 1 : 0)
|
||||
|
||||
#define lock_activation(cmd, lv) (lv_requires_activation_lock_now(lv) ? lock_vol(cmd, lv_activation_lock_name(lv), LCK_ACTIVATE_LOCK, lv) : 1)
|
||||
#define unlock_activation(cmd, lv) (lv_requires_activation_lock_now(lv) ? lock_vol(cmd, lv_activation_lock_name(lv), LCK_ACTIVATE_UNLOCK, lv) : 1)
|
||||
#define lv_supports_activation_locking(lv) (!vg_is_clustered((lv)->vg) && !lv_is_thin_type(lv) && !lv_is_cache_type(lv))
|
||||
#define lock_activation(cmd, lv) (vg_write_lock_held() && lv_supports_activation_locking(lv) ? 1 : lock_vol(cmd, (lv)->lvid.s, LCK_ACTIVATE_LOCK, lv))
|
||||
#define unlock_activation(cmd, lv) (vg_write_lock_held() && lv_supports_activation_locking(lv) ? 1 : lock_vol(cmd, (lv)->lvid.s, LCK_ACTIVATE_UNLOCK, lv))
|
||||
|
||||
/*
|
||||
* Place temporary exclusive 'activation' lock around an LV locking operation
|
||||
|
@@ -115,9 +115,6 @@ static void _flags_str_to_lockd_flags(const char *flags_str, uint32_t *lockd_fla
|
||||
if (strstr(flags_str, "NO_GL_LS"))
|
||||
*lockd_flags |= LD_RF_NO_GL_LS;
|
||||
|
||||
if (strstr(flags_str, "NO_LM"))
|
||||
*lockd_flags |= LD_RF_NO_LM;
|
||||
|
||||
if (strstr(flags_str, "DUP_GL_LS"))
|
||||
*lockd_flags |= LD_RF_DUP_GL_LS;
|
||||
|
||||
@@ -137,7 +134,7 @@ static void _flags_str_to_lockd_flags(const char *flags_str, uint32_t *lockd_fla
|
||||
* will not return. daemon_reply_int reverts to this
|
||||
* value if it finds no result value.
|
||||
*/
|
||||
#define NO_LOCKD_RESULT (-1000)
|
||||
#define NO_LOCKD_RESULT -1000
|
||||
|
||||
static int _lockd_result(daemon_reply reply, int *result, uint32_t *lockd_flags)
|
||||
{
|
||||
@@ -368,9 +365,6 @@ static int _remove_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
|
||||
|
||||
static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg, int extend_mb)
|
||||
{
|
||||
struct device *dev;
|
||||
char path[PATH_MAX];
|
||||
uint64_t old_size_bytes, new_size_bytes;
|
||||
struct logical_volume *lv = vg->sanlock_lv;
|
||||
struct lvresize_params lp = {
|
||||
.sign = SIGN_NONE,
|
||||
@@ -380,49 +374,12 @@ static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
|
||||
.force = 1,
|
||||
};
|
||||
|
||||
old_size_bytes = lv->size * SECTOR_SIZE;
|
||||
|
||||
if (!lv_resize(lv, &lp, &vg->pvs)) {
|
||||
log_error("Extend sanlock LV %s to size %s failed.",
|
||||
log_error("Extend LV %s to size %s failed.",
|
||||
display_lvname(lv), display_size(cmd, lp.size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_size_bytes = lv->size * SECTOR_SIZE;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/mapper/%s-%s", lv->vg->cmd->dev_dir,
|
||||
lv->vg->name, lv->name) < 0) {
|
||||
log_error("Extend sanlock LV %s name too long - extended size not zeroed.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("Extend sanlock LV zeroing blocks from offset " FMTu64 " bytes len %u bytes",
|
||||
old_size_bytes, (uint32_t)(new_size_bytes - old_size_bytes));
|
||||
|
||||
log_print("Zeroing %u MiB on extended internal lvmlock LV...", extend_mb);
|
||||
|
||||
if (!(dev = dev_cache_get(path, NULL))) {
|
||||
log_error("Extend sanlock LV %s cannot find device.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_open_quiet(dev)) {
|
||||
log_error("Extend sanlock LV %s cannot open device.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_set(dev, old_size_bytes, new_size_bytes - old_size_bytes, 0)) {
|
||||
log_error("Extend sanlock LV %s cannot zero device.", display_lvname(lv));
|
||||
dev_close_immediate(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_flush(dev);
|
||||
|
||||
if (!dev_close_immediate(dev))
|
||||
stack;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -667,10 +624,6 @@ static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, in
|
||||
case -EARGS:
|
||||
log_error("VG %s init failed: invalid parameters for sanlock", vg->name);
|
||||
break;
|
||||
case -EDEVOPEN:
|
||||
log_error("VG %s init failed: sanlock cannot open device /dev/mapper/%s-%s", vg->name, vg->name, LOCKD_SANLOCK_LV_NAME);
|
||||
log_error("Check that sanlock has permission to access disks.");
|
||||
break;
|
||||
case -EMANAGER:
|
||||
log_error("VG %s init failed: lock manager sanlock is not running", vg->name);
|
||||
break;
|
||||
@@ -1369,9 +1322,6 @@ int lockd_gl_create(struct cmd_context *cmd, const char *def_mode, const char *v
|
||||
log_error("Global lock failed: check that VG holding global lock exists and is started.");
|
||||
else
|
||||
log_error("Global lock failed: check that global lockspace is started.");
|
||||
|
||||
if (lockd_flags & LD_RF_NO_LM)
|
||||
log_error("Start a lock manager, lvmlockd did not find one running.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1575,9 +1525,6 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
|
||||
* access to lease storage.
|
||||
*/
|
||||
|
||||
if (result == -ENOLS && (lockd_flags & LD_RF_NO_LM))
|
||||
log_error("Start a lock manager, lvmlockd did not find one running.");
|
||||
|
||||
if (result == -ENOLS ||
|
||||
result == -ESTARTING ||
|
||||
result == -EVGKILLED ||
|
||||
@@ -1596,7 +1543,6 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
|
||||
log_error("Global lock failed: storage failed for sanlock leases");
|
||||
else
|
||||
log_error("Global lock failed: error %d", result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2046,15 +1992,6 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a hack for mirror LVs which need to know at a very low level
|
||||
* which lock mode the LV is being activated with so that it can pick
|
||||
* a mirror log type during activation. Do not use this for anything
|
||||
* else.
|
||||
*/
|
||||
if (mode && !strcmp(mode, "sh"))
|
||||
cmd->lockd_lv_sh = 1;
|
||||
|
||||
if (!mode)
|
||||
mode = "ex";
|
||||
|
||||
@@ -2140,10 +2077,6 @@ static int _lockd_lv_thin(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
} else if (lv_is_thin_pool(lv)) {
|
||||
pool_lv = lv;
|
||||
|
||||
} else if (lv_is_thin_pool_data(lv)) {
|
||||
/* FIXME: there should be a function to get pool lv from data lv. */
|
||||
pool_lv = lv_parent(lv);
|
||||
|
||||
} else {
|
||||
/* This should not happen AFAIK. */
|
||||
log_error("Lock on incorrect thin lv type %s/%s",
|
||||
@@ -2172,31 +2105,6 @@ static int _lockd_lv_thin(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
pool_lv->lock_args, def_mode, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only the combination of dlm + corosync + cmirrord allows
|
||||
* mirror LVs to be activated in shared mode on multiple nodes.
|
||||
*/
|
||||
static int _lockd_lv_mirror(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
const char *def_mode, uint32_t flags)
|
||||
{
|
||||
if (!strcmp(lv->vg->lock_type, "sanlock"))
|
||||
flags |= LDLV_MODE_NO_SH;
|
||||
|
||||
else if (!strcmp(lv->vg->lock_type, "dlm") && def_mode && !strcmp(def_mode, "sh")) {
|
||||
#ifdef CMIRRORD_PIDFILE
|
||||
if (!cmirrord_is_running()) {
|
||||
log_error("cmirrord must be running to activate an LV in shared mode.");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
flags |= LDLV_MODE_NO_SH;
|
||||
#endif
|
||||
}
|
||||
|
||||
return lockd_lv_name(cmd, lv->vg, lv->name, &lv->lvid.id[1],
|
||||
lv->lock_args, def_mode, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the VG has no lock_type, then this function can return immediately.
|
||||
* The LV itself may have no lock (NULL lv->lock_args), but the lock request
|
||||
@@ -2250,14 +2158,12 @@ int lockd_lv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
*/
|
||||
if (lv_is_external_origin(lv) ||
|
||||
lv_is_thin_type(lv) ||
|
||||
lv_is_mirror_type(lv) ||
|
||||
lv_is_raid_type(lv) ||
|
||||
lv_is_cache_type(lv)) {
|
||||
flags |= LDLV_MODE_NO_SH;
|
||||
}
|
||||
|
||||
if (lv_is_mirror_type(lv))
|
||||
return _lockd_lv_mirror(cmd, lv, def_mode, flags);
|
||||
|
||||
return lockd_lv_name(cmd, lv->vg, lv->name, &lv->lvid.id[1],
|
||||
lv->lock_args, def_mode, flags);
|
||||
}
|
||||
@@ -2425,10 +2331,6 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
|
||||
return 1;
|
||||
|
||||
} else if (seg_is_cache(lp) || seg_is_cache_pool(lp)) {
|
||||
/*
|
||||
* This should not happen because the command defs are
|
||||
* checked and excluded for shared VGs early in lvcreate.
|
||||
*/
|
||||
log_error("Use lvconvert for cache with lock type %s", vg->lock_type);
|
||||
return 0;
|
||||
|
||||
@@ -2484,9 +2386,6 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
|
||||
/*
|
||||
* Creating a thin pool and a thin lv in it. We could
|
||||
* probably make this work.
|
||||
*
|
||||
* This should not happen because the command defs are
|
||||
* checked and excluded for shared VGs early in lvcreate.
|
||||
*/
|
||||
log_error("Create thin pool and thin LV separately with lock type %s",
|
||||
vg->lock_type);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user