mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-26 01:44:19 +03:00
Compare commits
11 Commits
dev-dct-ne
...
dev-bmr-dm
Author | SHA1 | Date | |
---|---|---|---|
|
d60364c634 | ||
|
b5ac2c458a | ||
|
181975e635 | ||
|
820843fcb6 | ||
|
d487fcfb0e | ||
|
f1e42e2186 | ||
|
3c69a7248a | ||
|
00e716b037 | ||
|
926ce7e279 | ||
|
6582cc4ff2 | ||
|
618f9ab04b |
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.146-git (2017-11-03)
|
||||
1.02.139-git (2017-03-28)
|
||||
|
140
WHATS_NEW
140
WHATS_NEW
@@ -1,143 +1,5 @@
|
||||
Version 2.02.177 -
|
||||
====================================
|
||||
Fix memleak of string buffer when vgcfgbackup runs in secure mode.
|
||||
Do not print error when clvmd cannot find running clvmd.
|
||||
Prevent start of new merge of snapshot if origin is already being merged.
|
||||
|
||||
Version 2.02.176 - 3rd November 2017
|
||||
====================================
|
||||
Keep Install section only in lvm2-{lvmetad,lvmpolld}.socket systemd unit.
|
||||
Fix segfault in lvm_pv_remove in liblvm. (2.02.173)
|
||||
Do not allow storing VG metadata with LV without any segment.
|
||||
Fix printed message when thin snapshot was already merged.
|
||||
Remove created spare LV when creation of thin-pool failed.
|
||||
Avoid reading ignored metadata when mda gets used again.
|
||||
Fix detection of moved PVs in vgsplit. (2.02.175)
|
||||
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.
|
||||
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.
|
||||
Support storing status flags via segtype name field.
|
||||
Stop using '--yes' mode when fsadm runs without terminal.
|
||||
Extend validation of filesystems resized by fsadm.
|
||||
Enhance lvconvert automatic settings of possible (raid) LV types.
|
||||
Allow lvchange to change properties on a thin pool data sub LV.
|
||||
Fix lvcreate extent percentage calculation for mirrors.
|
||||
Don't reinstate still-missing devices when correcting inconsistent metadata.
|
||||
Properly handle subshell return codes in fsadm.
|
||||
Disallow cachepool creation with policy cleaner and mode writeback.
|
||||
|
||||
Version 2.02.171 - 3rd May 2017
|
||||
===============================
|
||||
Fix memory warnings by using mempools for command definition processing.
|
||||
Fix running commands from a script file.
|
||||
Add pvcreate prompt when device size doesn't match setphysicalvolumesize.
|
||||
lvconvert - preserve region size on raid1 image count changes
|
||||
Adjust pvresize/pvcreate messages and prompt if underlying dev size differs.
|
||||
raid - sanely handle insufficient space on takeover.
|
||||
Fix configure --enable-notify-dbus status message.
|
||||
Change configure option name prefix from --enable-lockd to --enable-lvmlockd.
|
||||
lvcreate - raise mirror/raid default regionsize to 2MiB
|
||||
Add missing configurable prefix to configuration file installation directory.
|
||||
|
||||
Version 2.02.170 - 13th April 2017
|
||||
Version 2.02.170 -
|
||||
==================================
|
||||
Introduce global/fsadm_executable to make fsadm path configurable.
|
||||
Look for limited thin pool metadata size when using 16G metadata.
|
||||
Add lvconvert pool creation rule disallowing options with poolmetadata.
|
||||
Fix lvconvert when the same LV is incorrectly reused in options.
|
||||
Fix lvconvert VG name validation in option values.
|
||||
Fix missing lvmlockd LV locks in lvchange and lvconvert.
|
||||
Fix dmeventd setup for lvchange --poll.
|
||||
Fix use of --poll and --monitor with lvchange and vgchange.
|
||||
Disallow lvconvert of hidden LV to a pool.
|
||||
Ignore --partial option when not used for activation.
|
||||
Allow --activationmode option with lvchange --refresh.
|
||||
Better message on lvconvert --regionsize
|
||||
Allow valid lvconvert --regionsize change
|
||||
Add raid10 alias raid10_near
|
||||
Handle insufficient PVs on lvconvert takeover
|
||||
Fix SIGINT blocking to prevent corrupted metadata
|
||||
Fix systemd unit existence check for lvmconf --services --startstopservices.
|
||||
Check and use PATH_MAX buffers when creating vgrename device paths.
|
||||
|
||||
Version 2.02.169 - 28th March 2017
|
||||
==================================
|
||||
|
53
WHATS_NEW_DM
53
WHATS_NEW_DM
@@ -1,56 +1,5 @@
|
||||
Version 1.02.146 -
|
||||
====================================
|
||||
Suppress integrity encryption keys in 'table' output unless --showkeys supplied.
|
||||
|
||||
Version 1.02.145 - 3rd November 2017
|
||||
====================================
|
||||
Keep Install section only in dm-event.socket systemd unit.
|
||||
Issue a specific error with dmsetup status if device is unknown.
|
||||
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.
|
||||
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).
|
||||
|
||||
Version 1.02.140 - 3rd May 2017
|
||||
===============================
|
||||
Add missing configure --enable-dmfilemapd status message and fix --disable.
|
||||
|
||||
Version 1.02.139 - 13th April 2017
|
||||
Version 1.02.139 -
|
||||
==================================
|
||||
Fix assignment in _target_version() when dm task can't run.
|
||||
Flush stdout on each iteration when using --count or --interval.
|
||||
Show detailed error message when execvp fails while starting dmfilemapd.
|
||||
Fix segmentation fault when dmfilemapd is run with no arguments.
|
||||
Numerous minor dmfilemapd fixes from coverity.
|
||||
|
||||
Version 1.02.138 - 28th March 2017
|
||||
==================================
|
||||
|
@@ -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 \
|
||||
@@ -48,8 +48,8 @@ install_localconf: $(CONFLOCAL)
|
||||
fi
|
||||
|
||||
install_profiles: $(PROFILES)
|
||||
$(INSTALL_DIR) $(profiledir)
|
||||
$(INSTALL_DATA) $(PROFILES) $(profiledir)/
|
||||
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_PROFILE_DIR)
|
||||
$(INSTALL_DATA) $(PROFILES) $(DESTDIR)$(DEFAULT_PROFILE_DIR)/
|
||||
|
||||
install_lvm2: install_conf install_localconf install_profiles
|
||||
|
||||
|
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
|
||||
@@ -390,17 +389,6 @@ allocation {
|
||||
# Cache pool metadata and data will always use different PVs.
|
||||
cache_pool_metadata_require_separate_pvs = 0
|
||||
|
||||
# Configuration option allocation/cache_metadata_format.
|
||||
# Sets default metadata format for new cache.
|
||||
#
|
||||
# Accepted values:
|
||||
# 0 Automatically detected best available format
|
||||
# 1 Original format
|
||||
# 2 Improved 2nd. generation format
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_metadata_format = 0
|
||||
|
||||
# Configuration option allocation/cache_mode.
|
||||
# The default cache mode used for new cache.
|
||||
#
|
||||
@@ -415,6 +403,17 @@ allocation {
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_mode = "writethrough"
|
||||
|
||||
# Configuration option allocation/cache_metadata_format.
|
||||
# Sets default metadata format for new cache.
|
||||
#
|
||||
# Accepted values:
|
||||
# 0 Automatically detected best available format
|
||||
# 1 Original format
|
||||
# 2 Improved 2nd. generation format
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_metadata_format = 0
|
||||
|
||||
# Configuration option allocation/cache_policy.
|
||||
# The default cache policy used for new cache volume.
|
||||
# Since kernel 4.2 the default policy is smq (Stochastic multiqueue),
|
||||
@@ -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.
|
||||
@@ -1070,12 +1069,6 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_repair_options = [ "" ]
|
||||
|
||||
# Configuration option global/fsadm_executable.
|
||||
# The full path to the fsadm command.
|
||||
# LVM uses this command to help with lvresize -r operations.
|
||||
# This configuration option has an automatic default value.
|
||||
# fsadm_executable = "@FSADM_PATH@"
|
||||
|
||||
# Configuration option global/system_id_source.
|
||||
# The method LVM uses to set the local system ID.
|
||||
# Volume Groups can also be given a system ID (by vgcreate, vgchange,
|
||||
@@ -1298,7 +1291,7 @@ activation {
|
||||
# The clean/dirty state of data is tracked for each region.
|
||||
# The value is rounded down to a power of two if necessary, and
|
||||
# is ignored if it is not a multiple of the machine memory page size.
|
||||
raid_region_size = 2048
|
||||
raid_region_size = 512
|
||||
|
||||
# Configuration option activation/error_when_full.
|
||||
# Return errors if a thin pool runs out of space.
|
||||
|
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.
|
||||
|
434
configure
vendored
434
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
|
||||
@@ -702,20 +699,18 @@ HAVE_VALGRIND
|
||||
HAVE_REALTIME
|
||||
HAVE_LIBDL
|
||||
BLKDEACTIVATE
|
||||
FSADM_PATH
|
||||
FSADM
|
||||
ELDFLAGS
|
||||
DM_LIB_PATCHLEVEL
|
||||
DMFILEMAPD
|
||||
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
|
||||
@@ -742,6 +737,7 @@ CLDWHOLEARCHIVE
|
||||
CLDNOWHOLEARCHIVE
|
||||
CLDFLAGS
|
||||
CACHE
|
||||
BUILD_NOTIFYDBUS
|
||||
BUILD_DMFILEMAPD
|
||||
BUILD_LOCKDDLM
|
||||
BUILD_LOCKDSANLOCK
|
||||
@@ -825,14 +821,13 @@ THIN_CHECK_CMD
|
||||
HAVE_FULL_RELRO
|
||||
HAVE_PIE
|
||||
POW_LIB
|
||||
ALLOCA
|
||||
LIBOBJS
|
||||
ALLOCA
|
||||
SORT
|
||||
WC
|
||||
CHMOD
|
||||
CSCOPE_CMD
|
||||
CFLOW_CMD
|
||||
AR
|
||||
RANLIB
|
||||
MKDIR_P
|
||||
SET_MAKE
|
||||
@@ -926,6 +921,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,11 +952,10 @@ enable_profiling
|
||||
enable_testing
|
||||
enable_valgrind_pool
|
||||
enable_devmapper
|
||||
enable_aio
|
||||
enable_lvmetad
|
||||
enable_lvmpolld
|
||||
enable_lvmlockd_sanlock
|
||||
enable_lvmlockd_dlm
|
||||
enable_lockd_sanlock
|
||||
enable_lockd_dlm
|
||||
enable_use_lvmlockd
|
||||
with_lvmlockd_pidfile
|
||||
enable_use_lvmetad
|
||||
@@ -1695,12 +1690,10 @@ 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
|
||||
enable the LVM lock daemon using sanlock
|
||||
--enable-lvmlockd-dlm enable the LVM lock daemon using dlm
|
||||
--enable-lockd-sanlock enable the LVM lock daemon using sanlock
|
||||
--enable-lockd-dlm enable the LVM lock daemon using dlm
|
||||
--disable-use-lvmlockd disable usage of LVM lock daemon
|
||||
--disable-use-lvmetad disable usage of LVM Metadata Daemon
|
||||
--disable-use-lvmpolld disable usage of LVM Poll Daemon
|
||||
@@ -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; }
|
||||
@@ -11919,11 +11773,11 @@ $as_echo "$BUILD_LVMPOLLD" >&6; }
|
||||
################################################################################
|
||||
BUILD_LVMLOCKD=no
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockdsanlock" >&5
|
||||
$as_echo_n "checking whether to build lvmlockdsanlock... " >&6; }
|
||||
# Check whether --enable-lvmlockd-sanlock was given.
|
||||
if test "${enable_lvmlockd_sanlock+set}" = set; then :
|
||||
enableval=$enable_lvmlockd_sanlock; LOCKDSANLOCK=$enableval
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lockdsanlock" >&5
|
||||
$as_echo_n "checking whether to build lockdsanlock... " >&6; }
|
||||
# Check whether --enable-lockd-sanlock was given.
|
||||
if test "${enable_lockd_sanlock+set}" = set; then :
|
||||
enableval=$enable_lockd_sanlock; LOCKDSANLOCK=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LOCKDSANLOCK" >&5
|
||||
@@ -12010,11 +11864,11 @@ $as_echo "#define LOCKDSANLOCK_SUPPORT 1" >>confdefs.h
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockddlm" >&5
|
||||
$as_echo_n "checking whether to build lvmlockddlm... " >&6; }
|
||||
# Check whether --enable-lvmlockd-dlm was given.
|
||||
if test "${enable_lvmlockd_dlm+set}" = set; then :
|
||||
enableval=$enable_lvmlockd_dlm; LOCKDDLM=$enableval
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lockddlm" >&5
|
||||
$as_echo_n "checking whether to build lockddlm... " >&6; }
|
||||
# Check whether --enable-lockd-dlm was given.
|
||||
if test "${enable_lockd_dlm+set}" = set; then :
|
||||
enableval=$enable_lockd_dlm; LOCKDDLM=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LOCKDDLM" >&5
|
||||
@@ -12250,18 +12104,17 @@ _ACEOF
|
||||
$as_echo_n "checking whether to build dmfilemapd... " >&6; }
|
||||
# Check whether --enable-dmfilemapd was given.
|
||||
if test "${enable_dmfilemapd+set}" = set; then :
|
||||
enableval=$enable_dmfilemapd; BUILD_DMFILEMAPD=$enableval
|
||||
else
|
||||
BUILD_DMFILEMAPD=no
|
||||
enableval=$enable_dmfilemapd; DMFILEMAPD=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_DMFILEMAPD" >&5
|
||||
$as_echo "$BUILD_DMFILEMAPD" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DMFILEMAPD" >&5
|
||||
$as_echo "$DMFILEMAPD" >&6; }
|
||||
BUILD_DMFILEMAPD=$DMFILEMAPD
|
||||
|
||||
$as_echo "#define DMFILEMAPD \$BUILD_DMFILEMAPD" >>confdefs.h
|
||||
$as_echo "#define DMFILEMAPD 1" >>confdefs.h
|
||||
|
||||
|
||||
if test "$BUILD_DMFILEMAPD" = yes; then
|
||||
if test "$DMFILEMAPD" = yes; then
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "linux/fiemap.h" "ac_cv_header_linux_fiemap_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_linux_fiemap_h" = xyes; then :
|
||||
|
||||
@@ -12277,23 +12130,23 @@ fi
|
||||
$as_echo_n "checking whether to build notifydbus... " >&6; }
|
||||
# Check whether --enable-notify-dbus was given.
|
||||
if test "${enable_notify_dbus+set}" = set; then :
|
||||
enableval=$enable_notify_dbus; NOTIFYDBUS_SUPPORT=$enableval
|
||||
else
|
||||
NOTIFYDBUS_SUPPORT=no
|
||||
enableval=$enable_notify_dbus; NOTIFYDBUS=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $NOTIFYDBUS_SUPPORT" >&5
|
||||
$as_echo "$NOTIFYDBUS_SUPPORT" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $NOTIFYDBUS" >&5
|
||||
$as_echo "$NOTIFYDBUS" >&6; }
|
||||
|
||||
if test "$NOTIFYDBUS_SUPPORT" = yes; then
|
||||
BUILD_NOTIFYDBUS=$NOTIFYDBUS
|
||||
|
||||
if test "$BUILD_NOTIFYDBUS" = yes; then
|
||||
|
||||
$as_echo "#define NOTIFYDBUS_SUPPORT 1" >>confdefs.h
|
||||
|
||||
SYSTEMD_LIBS="-lsystemd"
|
||||
LIBS="-lsystemd $LIBS"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test "$NOTIFYDBUS_SUPPORT" = yes; then
|
||||
if test "$BUILD_NOTIFYDBUS" = yes; then
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for NOTIFY_DBUS" >&5
|
||||
@@ -12369,6 +12222,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 +12231,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 +12313,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 +12334,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 +12343,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 +12425,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 +12699,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 +12729,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 +12814,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 +13382,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 +13776,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 +13824,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 +13935,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 +14223,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 +14261,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 +14441,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 +14761,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 +14779,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 +15105,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"
|
||||
@@ -15345,7 +15174,7 @@ done
|
||||
|
||||
fi
|
||||
|
||||
if test "$BUILD_DMFILEMAPD" = yes; then
|
||||
if test "$DMFILEMAPD" = yes; then
|
||||
for ac_header in sys/inotify.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "sys/inotify.h" "ac_cv_header_sys_inotify_h" "$ac_includes_default"
|
||||
@@ -15470,31 +15299,26 @@ _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"
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define FSADM_PATH "$FSADM_PATH"
|
||||
_ACEOF
|
||||
|
||||
|
||||
################################################################################
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
|
||||
@@ -15518,7 +15342,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 +15423,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 +15430,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
|
||||
@@ -15835,11 +15655,6 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15847,7 +15662,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 +16388,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 +17039,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 +17048,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;}
|
||||
|
202
configure.in
202
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)
|
||||
@@ -1164,10 +1150,10 @@ AC_MSG_RESULT($BUILD_LVMPOLLD)
|
||||
################################################################################
|
||||
BUILD_LVMLOCKD=no
|
||||
|
||||
dnl -- Build lvmlockdsanlock
|
||||
AC_MSG_CHECKING(whether to build lvmlockdsanlock)
|
||||
AC_ARG_ENABLE(lvmlockd-sanlock,
|
||||
AC_HELP_STRING([--enable-lvmlockd-sanlock],
|
||||
dnl -- Build lockdsanlock
|
||||
AC_MSG_CHECKING(whether to build lockdsanlock)
|
||||
AC_ARG_ENABLE(lockd-sanlock,
|
||||
AC_HELP_STRING([--enable-lockd-sanlock],
|
||||
[enable the LVM lock daemon using sanlock]),
|
||||
LOCKDSANLOCK=$enableval)
|
||||
AC_MSG_RESULT($LOCKDSANLOCK)
|
||||
@@ -1182,10 +1168,10 @@ if test "$BUILD_LOCKDSANLOCK" = yes; then
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Build lvmlockddlm
|
||||
AC_MSG_CHECKING(whether to build lvmlockddlm)
|
||||
AC_ARG_ENABLE(lvmlockd-dlm,
|
||||
AC_HELP_STRING([--enable-lvmlockd-dlm],
|
||||
dnl -- Build lockddlm
|
||||
AC_MSG_CHECKING(whether to build lockddlm)
|
||||
AC_ARG_ENABLE(lockd-dlm,
|
||||
AC_HELP_STRING([--enable-lockd-dlm],
|
||||
[enable the LVM lock daemon using dlm]),
|
||||
LOCKDDLM=$enableval)
|
||||
AC_MSG_RESULT($LOCKDDLM)
|
||||
@@ -1292,12 +1278,13 @@ dnl -- Check dmfilemapd
|
||||
AC_MSG_CHECKING(whether to build dmfilemapd)
|
||||
AC_ARG_ENABLE(dmfilemapd, AC_HELP_STRING([--enable-dmfilemapd],
|
||||
[enable the dmstats filemap daemon]),
|
||||
BUILD_DMFILEMAPD=$enableval, BUILD_DMFILEMAPD=no)
|
||||
AC_MSG_RESULT($BUILD_DMFILEMAPD)
|
||||
AC_DEFINE([DMFILEMAPD], $BUILD_DMFILEMAPD, [Define to 1 to enable the device-mapper filemap daemon.])
|
||||
DMFILEMAPD=$enableval)
|
||||
AC_MSG_RESULT($DMFILEMAPD)
|
||||
BUILD_DMFILEMAPD=$DMFILEMAPD
|
||||
AC_DEFINE([DMFILEMAPD], 1, [Define to 1 to enable the device-mapper filemap daemon.])
|
||||
|
||||
dnl -- dmfilemapd requires FIEMAP
|
||||
if test "$BUILD_DMFILEMAPD" = yes; then
|
||||
if test "$DMFILEMAPD" = yes; then
|
||||
AC_CHECK_HEADER([linux/fiemap.h], , [AC_MSG_ERROR(--enable-dmfilemapd requires fiemap.h)])
|
||||
fi
|
||||
|
||||
@@ -1307,60 +1294,69 @@ AC_MSG_CHECKING(whether to build notifydbus)
|
||||
AC_ARG_ENABLE(notify-dbus,
|
||||
AC_HELP_STRING([--enable-notify-dbus],
|
||||
[enable LVM notification using dbus]),
|
||||
NOTIFYDBUS_SUPPORT=$enableval, NOTIFYDBUS_SUPPORT=no)
|
||||
AC_MSG_RESULT($NOTIFYDBUS_SUPPORT)
|
||||
NOTIFYDBUS=$enableval)
|
||||
AC_MSG_RESULT($NOTIFYDBUS)
|
||||
|
||||
if test "$NOTIFYDBUS_SUPPORT" = yes; then
|
||||
BUILD_NOTIFYDBUS=$NOTIFYDBUS
|
||||
|
||||
if test "$BUILD_NOTIFYDBUS" = yes; then
|
||||
AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])
|
||||
SYSTEMD_LIBS="-lsystemd"
|
||||
LIBS="-lsystemd $LIBS"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Look for dbus libraries
|
||||
if test "$NOTIFYDBUS_SUPPORT" = yes; then
|
||||
if test "$BUILD_NOTIFYDBUS" = yes; then
|
||||
PKG_CHECK_MODULES(NOTIFY_DBUS, systemd >= 221, [HAVE_NOTIFY_DBUS=yes], $bailout)
|
||||
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 +1364,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 +1467,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 +1487,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 +1549,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 +1584,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 +1614,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 +1674,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 +1724,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 +1830,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 +1856,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
|
||||
|
||||
@@ -1885,7 +1872,7 @@ if test "$UDEV_SYNC" = yes; then
|
||||
AC_CHECK_HEADERS(sys/ipc.h sys/sem.h,,hard_bailout)
|
||||
fi
|
||||
|
||||
if test "$BUILD_DMFILEMAPD" = yes; then
|
||||
if test "$DMFILEMAPD" = yes; then
|
||||
AC_CHECK_HEADERS([sys/inotify.h],,hard_bailout)
|
||||
fi
|
||||
|
||||
@@ -1896,19 +1883,18 @@ 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"
|
||||
AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
|
||||
|
||||
################################################################################
|
||||
dnl -- dmeventd pidfile and executable path
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
@@ -1926,7 +1912,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 +1955,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.])
|
||||
@@ -2036,6 +2018,7 @@ AC_SUBST(BUILD_LVMLOCKD)
|
||||
AC_SUBST(BUILD_LOCKDSANLOCK)
|
||||
AC_SUBST(BUILD_LOCKDDLM)
|
||||
AC_SUBST(BUILD_DMFILEMAPD)
|
||||
AC_SUBST(BUILD_NOTIFYDBUS)
|
||||
AC_SUBST(CACHE)
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(CFLOW_CMD)
|
||||
@@ -2074,22 +2057,20 @@ 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(DMFILEMAPD)
|
||||
AC_SUBST(DM_LIB_PATCHLEVEL)
|
||||
AC_SUBST(ELDFLAGS)
|
||||
AC_SUBST(FSADM)
|
||||
AC_SUBST(FSADM_PATH)
|
||||
AC_SUBST(BLKDEACTIVATE)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
@@ -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);
|
||||
@@ -2151,14 +2124,6 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
|
||||
}
|
||||
|
||||
/* Return 0 if we can talk to an existing clvmd */
|
||||
/*
|
||||
* FIXME:
|
||||
*
|
||||
* This function returns only -1 or 0, but there are
|
||||
* different levels of errors, some of them should stop
|
||||
* further execution of clvmd thus another state is needed
|
||||
* and some error message need to be only informational.
|
||||
*/
|
||||
static int check_local_clvmd(void)
|
||||
{
|
||||
int local_socket;
|
||||
@@ -2178,11 +2143,7 @@ static int check_local_clvmd(void)
|
||||
|
||||
if (connect(local_socket,(struct sockaddr *) &sockaddr,
|
||||
sizeof(sockaddr))) {
|
||||
/* connection failure is expected state */
|
||||
if (errno == ENOENT)
|
||||
log_sys_debug("connect", "local socket");
|
||||
else
|
||||
log_sys_error("connect", "local socket");
|
||||
log_sys_error("connect", "local socket");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
@@ -2283,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);
|
||||
}
|
||||
|
||||
@@ -2323,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) \
|
||||
|
@@ -182,7 +182,7 @@ int cluster_send(struct clog_request *rq)
|
||||
}
|
||||
|
||||
/*
|
||||
* Once the request heads for the cluster, the luid loses
|
||||
* Once the request heads for the cluster, the luid looses
|
||||
* all its meaning.
|
||||
*/
|
||||
rq->u_rq.luid = 0;
|
||||
|
@@ -377,7 +377,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
|
||||
uint32_t block_on_error = 0;
|
||||
|
||||
int disk_log;
|
||||
char disk_path[PATH_MAX];
|
||||
char disk_path[128];
|
||||
int unlink_path = 0;
|
||||
long page_size;
|
||||
int pages;
|
||||
|
@@ -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. */
|
||||
@@ -865,7 +863,6 @@ static int _event_wait(struct thread_status *thread)
|
||||
* This is so that you can break out of waiting on an event,
|
||||
* either for a timeout event, or to cancel the thread.
|
||||
*/
|
||||
sigemptyset(&old);
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGALRM);
|
||||
if (pthread_sigmask(SIG_UNBLOCK, &set, &old) != 0) {
|
||||
@@ -1753,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__
|
||||
@@ -2251,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? */
|
||||
@@ -2269,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))
|
||||
|
@@ -47,8 +47,10 @@ struct dso_state {
|
||||
struct dm_pool *mem;
|
||||
int metadata_percent_check;
|
||||
int metadata_percent;
|
||||
int metadata_warn_once;
|
||||
int data_percent_check;
|
||||
int data_percent;
|
||||
int data_warn_once;
|
||||
uint64_t known_metadata_size;
|
||||
uint64_t known_data_size;
|
||||
unsigned fails;
|
||||
@@ -172,8 +174,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).",
|
||||
@@ -251,10 +253,11 @@ void process_event(struct dm_task *dmt,
|
||||
* action is called for: >50%, >55% ... >95%, 100%
|
||||
*/
|
||||
state->metadata_percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
|
||||
if ((state->metadata_percent > WARNING_THRESH) &&
|
||||
(state->metadata_percent > state->metadata_percent_check))
|
||||
if (state->metadata_percent <= WARNING_THRESH)
|
||||
state->metadata_warn_once = 0; /* Dropped bellow threshold, reset warn once */
|
||||
else if (!state->metadata_warn_once++) /* Warn once when raised above threshold */
|
||||
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)
|
||||
@@ -266,10 +269,11 @@ void process_event(struct dm_task *dmt,
|
||||
state->metadata_percent_check = CHECK_MINIMUM;
|
||||
|
||||
state->data_percent = dm_make_percent(tps->used_data_blocks, tps->total_data_blocks);
|
||||
if ((state->data_percent > WARNING_THRESH) &&
|
||||
(state->data_percent > state->data_percent_check))
|
||||
if (state->data_percent <= WARNING_THRESH)
|
||||
state->data_warn_once = 0;
|
||||
else if (!state->data_warn_once++)
|
||||
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))
|
||||
@@ -267,6 +266,8 @@ static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(fm, 0, sizeof(*fm));
|
||||
|
||||
/*
|
||||
* We don't know the true nr_regions at daemon start time,
|
||||
* and it is not worth a dm_stats_list()/group walk to count:
|
||||
@@ -279,9 +280,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 +290,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 +334,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 +343,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;
|
||||
@@ -362,33 +359,30 @@ static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _filemap_fd_update_blocks(struct filemap_monitor *fm)
|
||||
static int _filemap_fd_check_changed(struct filemap_monitor *fm)
|
||||
{
|
||||
int64_t blocks, old_blocks;
|
||||
struct stat buf;
|
||||
|
||||
if (fm->fd < 0) {
|
||||
log_error("Filemap fd is not open.");
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstat(fm->fd, &buf)) {
|
||||
log_error("Failed to fstat filemap file descriptor.");
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fm->blocks = buf.st_blocks;
|
||||
blocks = buf.st_blocks;
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* first check? */
|
||||
if (fm->blocks < 0)
|
||||
old_blocks = buf.st_blocks;
|
||||
else
|
||||
old_blocks = fm->blocks;
|
||||
|
||||
static int _filemap_fd_check_changed(struct filemap_monitor *fm)
|
||||
{
|
||||
int64_t old_blocks;
|
||||
|
||||
old_blocks = fm->blocks;
|
||||
|
||||
if (!_filemap_fd_update_blocks(fm))
|
||||
return -1;
|
||||
fm->blocks = blocks;
|
||||
|
||||
return (fm->blocks != old_blocks);
|
||||
}
|
||||
@@ -539,7 +533,6 @@ static void _filemap_monitor_destroy(struct filemap_monitor *fm)
|
||||
_filemap_monitor_close_fd(fm);
|
||||
}
|
||||
dm_free((void *) fm->program_id);
|
||||
dm_free(fm->path);
|
||||
}
|
||||
|
||||
static int _filemap_monitor_check_same_file(int fd1, int fd2)
|
||||
@@ -570,7 +563,6 @@ static int _filemap_monitor_check_file_unlinked(struct filemap_monitor *fm)
|
||||
ssize_t len;
|
||||
|
||||
fm->deleted = 0;
|
||||
same = 0;
|
||||
|
||||
if ((fd = open(fm->path, O_RDONLY)) < 0)
|
||||
goto check_unlinked;
|
||||
@@ -597,7 +589,7 @@ check_unlinked:
|
||||
log_error("Could not format pid path.");
|
||||
return 0;
|
||||
}
|
||||
if ((len = readlink(path_buf, link_buf, sizeof(link_buf) - 1)) < 0) {
|
||||
if ((len = readlink(path_buf, link_buf, sizeof(link_buf))) < 0) {
|
||||
log_error("readlink failed for " DEFAULT_PROC_DIR "/%d/fd/%d.",
|
||||
getpid(), fm->fd);
|
||||
return 0;
|
||||
@@ -667,11 +659,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;
|
||||
@@ -691,10 +683,7 @@ static int _update_regions(struct dm_stats *dms, struct filemap_monitor *fm)
|
||||
for (region = regions; *region != DM_STATS_REGIONS_ALL; region++)
|
||||
nr_regions++;
|
||||
|
||||
if (!nr_regions)
|
||||
log_warn("File contains no extents: exiting.");
|
||||
|
||||
if (nr_regions && (regions[0] != fm->group_id)) {
|
||||
if (regions[0] != fm->group_id) {
|
||||
log_warn("group_id changed from " FMTu64 " to " FMTu64,
|
||||
fm->group_id, regions[0]);
|
||||
fm->group_id = regions[0];
|
||||
@@ -714,8 +703,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 "
|
||||
@@ -726,9 +714,6 @@ static int _dmfilemapd(struct filemap_monitor *fm)
|
||||
if (!_filemap_monitor_set_notify(fm))
|
||||
goto bad;
|
||||
|
||||
if (!_filemap_fd_update_blocks(fm))
|
||||
goto bad;
|
||||
|
||||
if (!dm_stats_list(dms, DM_STATS_ALL_PROGRAMS)) {
|
||||
log_error("Failed to list stats handle.");
|
||||
goto bad;
|
||||
@@ -762,16 +747,17 @@ static int _dmfilemapd(struct filemap_monitor *fm)
|
||||
if ((check = _filemap_fd_check_changed(fm)) < 0)
|
||||
goto bad;
|
||||
|
||||
if (check && !_update_regions(dms, fm))
|
||||
goto bad;
|
||||
if (!check)
|
||||
goto wait;
|
||||
|
||||
running = !!fm->nr_regions;
|
||||
if (!running)
|
||||
continue;
|
||||
if (!_update_regions(dms, fm))
|
||||
goto bad;
|
||||
|
||||
wait:
|
||||
_filemap_monitor_wait(FILEMAPD_WAIT_USECS);
|
||||
|
||||
running = !!fm->nr_regions;
|
||||
|
||||
/* mode=inode termination condions */
|
||||
if (fm->mode == DM_FILEMAPD_FOLLOW_INODE) {
|
||||
if (!_filemap_monitor_check_file_unlinked(fm))
|
||||
@@ -814,12 +800,8 @@ int main(int argc, char **argv)
|
||||
{
|
||||
struct filemap_monitor fm;
|
||||
|
||||
memset(&fm, 0, sizeof(fm));
|
||||
|
||||
if (!_parse_args(argc, argv, &fm)) {
|
||||
dm_free(fm.path);
|
||||
if (!_parse_args(argc, argv, &fm))
|
||||
return 1;
|
||||
}
|
||||
|
||||
_setup_logging();
|
||||
|
||||
|
@@ -100,7 +100,7 @@ class AutomatedProperties(dbus.service.Object):
|
||||
raise dbus.exceptions.DBusException(
|
||||
obj._ap_interface,
|
||||
'The object %s does not implement the %s interface'
|
||||
% (obj.__class__, interface_name))
|
||||
% (self.__class__, interface_name))
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
||||
in_signature='s', out_signature='a{sv}',
|
||||
|
@@ -9,13 +9,12 @@
|
||||
|
||||
import subprocess
|
||||
from . import cfg
|
||||
from .cmdhandler import options_to_cli_args, LvmExecutionMeta
|
||||
from .cmdhandler import options_to_cli_args
|
||||
import dbus
|
||||
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug,\
|
||||
add_no_notify
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
|
||||
|
||||
def pv_move_lv_cmd(move_options, lv_full_name,
|
||||
@@ -48,11 +47,6 @@ def _move_merge(interface_name, command, job_state):
|
||||
# Instruct lvm to not register an event with us
|
||||
command = add_no_notify(command)
|
||||
|
||||
#(self, start, ended, cmd, ec, stdout_txt, stderr_txt)
|
||||
meta = LvmExecutionMeta(time.time(), 0, command, -1000, None, None)
|
||||
|
||||
cfg.blackbox.add(meta)
|
||||
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE,
|
||||
env=os.environ,
|
||||
stderr=subprocess.PIPE, close_fds=True)
|
||||
@@ -80,11 +74,6 @@ def _move_merge(interface_name, command, job_state):
|
||||
|
||||
out = process.communicate()
|
||||
|
||||
with meta.lock:
|
||||
meta.ended = time.time()
|
||||
meta.ec = process.returncode
|
||||
meta.stderr_txt = out[1]
|
||||
|
||||
if process.returncode == 0:
|
||||
job_state.Percent = 100
|
||||
else:
|
||||
@@ -158,6 +147,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()
|
||||
|
@@ -37,7 +37,6 @@ cmd_lock = threading.RLock()
|
||||
class LvmExecutionMeta(object):
|
||||
|
||||
def __init__(self, start, ended, cmd, ec, stdout_txt, stderr_txt):
|
||||
self.lock = threading.RLock()
|
||||
self.start = start
|
||||
self.ended = ended
|
||||
self.cmd = cmd
|
||||
@@ -46,13 +45,12 @@ class LvmExecutionMeta(object):
|
||||
self.stderr_txt = stderr_txt
|
||||
|
||||
def __str__(self):
|
||||
with self.lock:
|
||||
return "EC= %d for %s\n" \
|
||||
"STARTED: %f, ENDED: %f\n" \
|
||||
"STDOUT=%s\n" \
|
||||
"STDERR=%s\n" % \
|
||||
(self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
|
||||
self.stderr_txt)
|
||||
return "EC= %d for %s\n" \
|
||||
"STARTED: %f, ENDED: %f\n" \
|
||||
"STDOUT=%s\n" \
|
||||
"STDERR=%s\n" % \
|
||||
(self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
|
||||
self.stderr_txt)
|
||||
|
||||
|
||||
class LvmFlightRecorder(object):
|
||||
@@ -281,7 +279,7 @@ def vg_lv_create(vg_name, create_options, name, size_bytes, pv_dests):
|
||||
cmd = ['lvcreate']
|
||||
cmd.extend(options_to_cli_args(create_options))
|
||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
||||
cmd.extend(['--name', name, vg_name, '--yes'])
|
||||
cmd.extend(['--name', name, vg_name])
|
||||
pv_dest_ranges(cmd, pv_dests)
|
||||
return call(cmd)
|
||||
|
||||
@@ -306,8 +304,6 @@ def _vg_lv_create_common_cmd(create_options, size_bytes, thin_pool):
|
||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
||||
else:
|
||||
cmd.extend(['--thin', '--size', str(size_bytes) + 'B'])
|
||||
|
||||
cmd.extend(['--yes'])
|
||||
return cmd
|
||||
|
||||
|
||||
@@ -344,7 +340,7 @@ def _vg_lv_create_raid(vg_name, create_options, name, raid_type, size_bytes,
|
||||
if stripe_size_kb != 0:
|
||||
cmd.extend(['--stripesize', str(stripe_size_kb)])
|
||||
|
||||
cmd.extend(['--name', name, vg_name, '--yes'])
|
||||
cmd.extend(['--name', name, vg_name])
|
||||
return call(cmd)
|
||||
|
||||
|
||||
@@ -365,7 +361,7 @@ def vg_lv_create_mirror(
|
||||
cmd.extend(['--type', 'mirror'])
|
||||
cmd.extend(['--mirrors', str(num_copies)])
|
||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
||||
cmd.extend(['--name', name, vg_name, '--yes'])
|
||||
cmd.extend(['--name', name, vg_name])
|
||||
return call(cmd)
|
||||
|
||||
|
||||
@@ -419,7 +415,7 @@ def lv_lv_create(lv_full_name, create_options, name, size_bytes):
|
||||
cmd = ['lvcreate']
|
||||
cmd.extend(options_to_cli_args(create_options))
|
||||
cmd.extend(['--virtualsize', str(size_bytes) + 'B', '-T'])
|
||||
cmd.extend(['--name', name, lv_full_name, '--yes'])
|
||||
cmd.extend(['--name', name, lv_full_name])
|
||||
return call(cmd)
|
||||
|
||||
|
||||
@@ -555,7 +551,7 @@ def pv_resize(device, size_bytes, create_options):
|
||||
cmd.extend(options_to_cli_args(create_options))
|
||||
|
||||
if size_bytes != 0:
|
||||
cmd.extend(['--yes', '--setphysicalvolumesize', str(size_bytes) + 'B'])
|
||||
cmd.extend(['--setphysicalvolumesize', str(size_bytes) + 'B'])
|
||||
|
||||
cmd.extend([device])
|
||||
return call(cmd)
|
||||
@@ -620,10 +616,10 @@ def vg_reduce(vg_name, missing, pv_devices, reduce_options):
|
||||
cmd = ['vgreduce']
|
||||
cmd.extend(options_to_cli_args(reduce_options))
|
||||
|
||||
if len(pv_devices) == 0:
|
||||
cmd.append('--all')
|
||||
if missing:
|
||||
cmd.append('--removemissing')
|
||||
elif len(pv_devices) == 0:
|
||||
cmd.append('--all')
|
||||
|
||||
cmd.append(vg_name)
|
||||
cmd.extend(pv_devices)
|
||||
|
@@ -82,10 +82,10 @@ class StateUpdate(object):
|
||||
|
||||
@staticmethod
|
||||
def update_thread(obj):
|
||||
queued_requests = []
|
||||
while cfg.run.value != 0:
|
||||
# noinspection PyBroadException
|
||||
try:
|
||||
queued_requests = []
|
||||
refresh = True
|
||||
emit_signal = True
|
||||
cache_refresh = True
|
||||
@@ -96,7 +96,7 @@ class StateUpdate(object):
|
||||
wait = not obj.deferred
|
||||
obj.deferred = False
|
||||
|
||||
if len(queued_requests) == 0 and wait:
|
||||
if wait:
|
||||
queued_requests.append(obj.queue.get(True, 2))
|
||||
|
||||
# Ok we have one or the deferred queue has some,
|
||||
@@ -131,17 +131,11 @@ class StateUpdate(object):
|
||||
for i in queued_requests:
|
||||
i.set_result(num_changes)
|
||||
|
||||
# Only clear out the requests after we have given them a result
|
||||
# otherwise we can orphan the waiting threads and they never
|
||||
# wake up if we get an exception
|
||||
queued_requests = []
|
||||
|
||||
except queue.Empty:
|
||||
pass
|
||||
except Exception:
|
||||
st = traceback.format_exc()
|
||||
log_error("update_thread exception: \n%s" % st)
|
||||
cfg.blackbox.dump()
|
||||
|
||||
def __init__(self):
|
||||
self.lock = threading.RLock()
|
||||
@@ -152,8 +146,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
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
from utils import log_debug
|
||||
from .automatedproperties import AutomatedProperties
|
||||
|
||||
from . import utils
|
||||
@@ -47,7 +48,7 @@ class Manager(AutomatedProperties):
|
||||
pv = cfg.om.get_object_path_by_uuid_lvm_id(device, device)
|
||||
if pv:
|
||||
raise dbus.exceptions.DBusException(
|
||||
MANAGER_INTERFACE, "PV %s Already exists!" % device)
|
||||
MANAGER_INTERFACE, "PV Already exists!")
|
||||
|
||||
rc, out, err = cmdhandler.pv_create(create_options, [device])
|
||||
Manager.handle_execute(rc, out, err)
|
||||
@@ -144,7 +145,7 @@ class Manager(AutomatedProperties):
|
||||
p = cfg.om.get_object_path_by_uuid_lvm_id(key, key)
|
||||
if not p:
|
||||
p = '/'
|
||||
utils.log_debug('LookUpByLvmId: key = %s, result = %s' % (key, p))
|
||||
log_debug('LookUpByLvmId: key = %s, result = %s' % (key, p))
|
||||
return p
|
||||
|
||||
@dbus.service.method(
|
||||
|
@@ -223,9 +223,8 @@ class ObjectManager(AutomatedProperties):
|
||||
:param lvm_id: The lvm identifier
|
||||
"""
|
||||
with self.rlock:
|
||||
lookup_rc = self._id_lookup(lvm_id)
|
||||
if lookup_rc:
|
||||
return self.get_object_by_path(lookup_rc)
|
||||
if lvm_id in self._id_to_object_path:
|
||||
return self.get_object_by_path(self._id_to_object_path[lvm_id])
|
||||
return None
|
||||
|
||||
def get_object_path_by_lvm_id(self, lvm_id):
|
||||
@@ -235,9 +234,8 @@ class ObjectManager(AutomatedProperties):
|
||||
:return: Object path or '/' if not found
|
||||
"""
|
||||
with self.rlock:
|
||||
lookup_rc = self._id_lookup(lvm_id)
|
||||
if lookup_rc:
|
||||
return lookup_rc
|
||||
if lvm_id in self._id_to_object_path:
|
||||
return self._id_to_object_path[lvm_id]
|
||||
return '/'
|
||||
|
||||
def _uuid_verify(self, path, uuid, lvm_id):
|
||||
|
@@ -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():
|
||||
@@ -555,9 +519,7 @@ def add_no_notify(cmdline):
|
||||
if '--config' in cmdline:
|
||||
for i, arg in enumerate(cmdline):
|
||||
if arg == '--config':
|
||||
if len(cmdline) <= i+1:
|
||||
raise dbus.exceptions.DBusException("Missing value for --config option.")
|
||||
cmdline[i+1] += " global/notify_dbus=0"
|
||||
cmdline[i] += "global/notify_dbus=0"
|
||||
break
|
||||
else:
|
||||
cmdline.extend(['--config', 'global/notify_dbus=0'])
|
||||
@@ -570,27 +532,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 +566,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 +575,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
|
||||
|
||||
@@ -151,9 +148,6 @@
|
||||
/* Library version */
|
||||
#undef DM_LIB_VERSION
|
||||
|
||||
/* Path to fsadm binary. */
|
||||
#undef FSADM_PATH
|
||||
|
||||
/* Define to 1 if you have the `alarm' function. */
|
||||
#undef HAVE_ALARM
|
||||
|
||||
@@ -688,6 +682,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);
|
||||
|
@@ -260,11 +260,6 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
|
||||
start *= seg_status->seg->le;
|
||||
length *= _seg_len(seg_status->seg);
|
||||
|
||||
/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */
|
||||
if (lv_is_thin_pool_metadata(seg_status->seg->lv) &&
|
||||
(length > DM_THIN_MAX_METADATA_SIZE))
|
||||
length = DM_THIN_MAX_METADATA_SIZE;
|
||||
|
||||
do {
|
||||
target = dm_get_next_target(dmt, target, &target_start,
|
||||
&target_length, &target_name, &target_params);
|
||||
@@ -275,8 +270,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 +1032,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 +1049,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 +1766,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;
|
||||
@@ -1787,7 +1857,7 @@ struct pool_cb_data {
|
||||
static int _pool_callback(struct dm_tree_node *node,
|
||||
dm_node_callback_t type, void *cb_data)
|
||||
{
|
||||
int ret, status = 0, fd;
|
||||
int ret, status, fd;
|
||||
const struct dm_config_node *cn;
|
||||
const struct dm_config_value *cv;
|
||||
const struct pool_cb_data *data = cb_data;
|
||||
@@ -2078,6 +2148,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 +2516,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 +2674,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)
|
||||
|
709
lib/cache/lvmcache.c
vendored
709
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;
|
||||
}
|
||||
|
||||
@@ -2372,29 +2382,56 @@ int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_insta
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_populate_pv_fields(struct lvmcache_info *info,
|
||||
struct volume_group *vg,
|
||||
struct physical_volume *pv)
|
||||
static int _get_pv_if_in_vg(struct lvmcache_info *info,
|
||||
struct physical_volume *pv)
|
||||
{
|
||||
struct data_area_list *da;
|
||||
|
||||
if (!info->label) {
|
||||
log_error("No cached label for orphan PV %s", pv_dev_name(pv));
|
||||
return 0;
|
||||
char vgname[NAME_LEN + 1];
|
||||
char vgid[ID_LEN + 1];
|
||||
|
||||
if (info->vginfo && info->vginfo->vgname &&
|
||||
!is_orphan_vg(info->vginfo->vgname)) {
|
||||
/*
|
||||
* get_pv_from_vg_by_id() may call
|
||||
* lvmcache_label_scan() and drop cached
|
||||
* vginfo so make a local copy of string.
|
||||
*/
|
||||
(void) dm_strncpy(vgname, info->vginfo->vgname, sizeof(vgname));
|
||||
memcpy(vgid, info->vginfo->vgid, sizeof(vgid));
|
||||
|
||||
if (get_pv_from_vg_by_id(info->fmt, vgname, vgid,
|
||||
info->dev->pvid, pv))
|
||||
return 1;
|
||||
}
|
||||
|
||||
pv->label_sector = info->label->sector;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lvmcache_populate_pv_fields(struct lvmcache_info *info,
|
||||
struct physical_volume *pv,
|
||||
int scan_label_only)
|
||||
{
|
||||
struct data_area_list *da;
|
||||
|
||||
/* Have we already cached vgname? */
|
||||
if (!scan_label_only && _get_pv_if_in_vg(info, pv))
|
||||
return 1;
|
||||
|
||||
/* Perform full scan (just the first time) and try again */
|
||||
if (!scan_label_only && !critical_section() && !full_scan_done()) {
|
||||
lvmcache_force_next_label_scan();
|
||||
lvmcache_label_scan(info->fmt->cmd);
|
||||
|
||||
if (_get_pv_if_in_vg(info, pv))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Orphan */
|
||||
pv->dev = info->dev;
|
||||
pv->fmt = info->fmt;
|
||||
pv->size = info->device_size >> SECTOR_SHIFT;
|
||||
pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
|
||||
memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
|
||||
|
||||
if (!pv->size) {
|
||||
log_error("PV %s size is zero.", dev_name(info->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Currently only support exactly one data area */
|
||||
if (dm_list_size(&info->das) != 1) {
|
||||
log_error("Must be exactly one data area (found %d) on PV %s",
|
||||
@@ -2575,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;
|
||||
}
|
||||
@@ -2634,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.
|
||||
|
24
lib/cache/lvmcache.h
vendored
24
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);
|
||||
|
||||
@@ -142,8 +146,8 @@ int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fi
|
||||
int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid);
|
||||
int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid);
|
||||
int lvmcache_populate_pv_fields(struct lvmcache_info *info,
|
||||
struct volume_group *vg,
|
||||
struct physical_volume *pv);
|
||||
struct physical_volume *pv,
|
||||
int scan_label_only);
|
||||
int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt);
|
||||
void lvmcache_del_mdas(struct lvmcache_info *info);
|
||||
void lvmcache_del_das(struct lvmcache_info *info);
|
||||
@@ -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(" ");
|
||||
@@ -265,39 +258,6 @@ static void _destroy(struct segment_type *segtype)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
/*
|
||||
* Parse and look for kernel symbol in /proc/kallsyms
|
||||
* this could be our only change to figure out there is
|
||||
* cache policy symbol already in the monolithic kernel
|
||||
* where 'modprobe dm-cache-smq' will simply not work
|
||||
*/
|
||||
static int _lookup_kallsyms(const char *symbol)
|
||||
{
|
||||
static const char _syms[] = "/proc/kallsyms";
|
||||
int ret = 0;
|
||||
char *line = NULL;
|
||||
size_t len;
|
||||
FILE *s;
|
||||
|
||||
if (!(s = fopen(_syms, "r")))
|
||||
log_sys_debug("fopen", _syms);
|
||||
else {
|
||||
while (getline(&line, &len, s) != -1)
|
||||
if (strstr(line, symbol)) {
|
||||
ret = 1; /* Found symbol */
|
||||
log_debug("Found kernel symbol%s.", symbol); /* space is in symbol */
|
||||
break;
|
||||
}
|
||||
|
||||
free(line);
|
||||
if (fclose(s))
|
||||
log_sys_debug("fclose", _syms);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int _target_present(struct cmd_context *cmd,
|
||||
const struct lv_segment *seg __attribute__((unused)),
|
||||
unsigned *attributes __attribute__((unused)))
|
||||
@@ -310,15 +270,14 @@ static int _target_present(struct cmd_context *cmd,
|
||||
unsigned cache_alias;
|
||||
const char feature[12];
|
||||
const char module[12]; /* check dm-%s */
|
||||
const char ksymbol[12]; /* check for kernel symbol */
|
||||
const char *aliasing;
|
||||
} _features[] = {
|
||||
{ 1, 10, CACHE_FEATURE_METADATA2, 0, "metadata2" },
|
||||
/* Assumption: cache >=1.9 always aliases MQ policy */
|
||||
{ 1, 10, CACHE_FEATURE_METADATA2, 0, "metadata2" },
|
||||
{ 1, 9, CACHE_FEATURE_POLICY_SMQ, CACHE_FEATURE_POLICY_MQ, "policy_smq", "cache-smq",
|
||||
" smq_exit", " and aliases cache-mq" },
|
||||
{ 1, 8, CACHE_FEATURE_POLICY_SMQ, 0, "policy_smq", "cache-smq", " smq_exit" },
|
||||
{ 1, 3, CACHE_FEATURE_POLICY_MQ, 0, "policy_mq", "cache-mq", " mq_init" },
|
||||
" and aliases cache-mq" },
|
||||
{ 1, 8, CACHE_FEATURE_POLICY_SMQ, 0, "policy_smq", "cache-smq" },
|
||||
{ 1, 3, CACHE_FEATURE_POLICY_MQ, 0, "policy_mq", "cache-mq" },
|
||||
};
|
||||
static const char _lvmconf[] = "global/cache_disabled_features";
|
||||
static unsigned _attrs = 0;
|
||||
@@ -364,8 +323,7 @@ static int _target_present(struct cmd_context *cmd,
|
||||
}
|
||||
if (((maj > _features[i].maj) ||
|
||||
(maj == _features[i].maj && min >= _features[i].min)) &&
|
||||
((_features[i].ksymbol[0] && _lookup_kallsyms(_features[i].ksymbol)) ||
|
||||
module_present(cmd, _features[i].module))) {
|
||||
module_present(cmd, _features[i].module)) {
|
||||
log_debug_activation("Cache policy %s is available%s.",
|
||||
_features[i].module,
|
||||
_features[i].aliasing ? : "");
|
||||
|
@@ -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;
|
||||
@@ -554,7 +541,7 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, char *bu
|
||||
if (checksum_fn && checksum !=
|
||||
(checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size),
|
||||
(const uint8_t *)(fb + size), size2))) {
|
||||
log_error("%s: Checksum error at offset %" PRIu64, dev_name(dev), (uint64_t) offset);
|
||||
log_error("%s: Checksum error", dev_name(dev));
|
||||
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,23 +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, 176), 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, 176), 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, 176), 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. This setting may be limited by the system\n"
|
||||
"aio configuration. This should not exceed the open files limit.\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"
|
||||
@@ -530,9 +469,8 @@ cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separa
|
||||
|
||||
cfg(allocation_raid_stripe_all_devices_CFG, "raid_stripe_all_devices", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES, vsn(2, 2, 162), NULL, 0, NULL,
|
||||
"Stripe across all PVs when RAID stripes are not specified.\n"
|
||||
"If enabled, all PVs in the VG or on the command line are used for\n"
|
||||
"raid0/4/5/6/10 when the command does not specify the number of\n"
|
||||
"stripes to use.\n"
|
||||
"If enabled, all PVs in the VG or on the command line are used for raid0/4/5/6/10\n"
|
||||
"when the command does not specify the number of stripes to use.\n"
|
||||
"This was the default behaviour until release 2.02.162.\n")
|
||||
|
||||
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
|
||||
@@ -885,8 +823,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"
|
||||
@@ -993,7 +934,7 @@ cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL,
|
||||
"devices/global_filter.\n")
|
||||
|
||||
cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LVMETAD_UPDATE_WAIT_TIME, vsn(2, 2, 151), NULL, 0, NULL,
|
||||
"Number of seconds a command will wait for lvmetad update to finish.\n"
|
||||
"The number of seconds a command will wait for lvmetad update to finish.\n"
|
||||
"After waiting for this period, a command will not use lvmetad, and\n"
|
||||
"will revert to disk scanning.\n")
|
||||
|
||||
@@ -1094,10 +1035,6 @@ cfg_array(global_cache_check_options_CFG, "cache_check_options", global_CFG_SECT
|
||||
cfg_array(global_cache_repair_options_CFG, "cache_repair_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_REPAIR_OPTIONS_CONFIG, vsn(2, 2, 108), NULL, 0, NULL,
|
||||
"List of options passed to the cache_repair command.\n")
|
||||
|
||||
cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FSADM_PATH, vsn(2, 2, 170), "@FSADM_PATH@", 0, NULL,
|
||||
"The full path to the fsadm command.\n"
|
||||
"LVM uses this command to help with lvresize -r operations.\n")
|
||||
|
||||
cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_SYSTEM_ID_SOURCE, vsn(2, 2, 117), NULL, 0, NULL,
|
||||
"The method LVM uses to set the local system ID.\n"
|
||||
"Volume Groups can also be given a system ID (by vgcreate, vgchange,\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 */
|
||||
@@ -135,8 +135,6 @@
|
||||
#define DEFAULT_CACHE_METADATA_FORMAT CACHE_METADATA_FORMAT_UNSELECTED /* Autodetect */
|
||||
#define DEFAULT_CACHE_MODE "writethrough"
|
||||
|
||||
#define DEFAULT_FSADM_PATH FSADM_PATH
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
||||
#define DEFAULT_FORMAT "lvm2"
|
||||
@@ -179,6 +177,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
|
||||
@@ -201,7 +200,7 @@
|
||||
#define DEFAULT_ACTIVATION_MODE "degraded"
|
||||
#define DEFAULT_USE_LINEAR_TARGET 1
|
||||
#define DEFAULT_STRIPE_FILLER "error"
|
||||
#define DEFAULT_RAID_REGION_SIZE 2048 /* KB */
|
||||
#define DEFAULT_RAID_REGION_SIZE 512 /* KB */
|
||||
#define DEFAULT_INTERVAL 15
|
||||
|
||||
#define DEFAULT_MAX_HISTORY 100
|
||||
@@ -266,8 +265,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;
|
||||
@@ -939,20 +933,12 @@ static int _insert_udev_dir(struct udev *udev, const char *dir)
|
||||
struct udev_device *device;
|
||||
int r = 1;
|
||||
|
||||
if (!(udev_enum = udev_enumerate_new(udev))) {
|
||||
log_error("Failed to udev_enumerate_new.");
|
||||
return 0;
|
||||
}
|
||||
if (!(udev_enum = udev_enumerate_new(udev)))
|
||||
goto bad;
|
||||
|
||||
if (udev_enumerate_add_match_subsystem(udev_enum, "block")) {
|
||||
log_error("Failed to udev_enumerate_add_match_subsystem.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (udev_enumerate_scan_devices(udev_enum)) {
|
||||
log_error("Failed to udev_enumerate_scan_devices.");
|
||||
goto out;
|
||||
}
|
||||
if (udev_enumerate_add_match_subsystem(udev_enum, "block") ||
|
||||
udev_enumerate_scan_devices(udev_enum))
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* Report any missing information as "log_very_verbose" only, do not
|
||||
@@ -989,10 +975,13 @@ static int _insert_udev_dir(struct udev *udev, const char *dir)
|
||||
udev_device_unref(device);
|
||||
}
|
||||
|
||||
out:
|
||||
udev_enumerate_unref(udev_enum);
|
||||
|
||||
return r;
|
||||
|
||||
bad:
|
||||
log_error("Failed to enumerate udev device list.");
|
||||
udev_enumerate_unref(udev_enum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _insert_dirs(struct dm_list *dirs)
|
||||
@@ -1086,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();
|
||||
@@ -1097,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)
|
||||
@@ -1379,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,324 +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 = 0;
|
||||
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 *done_count)
|
||||
{
|
||||
int wait_nr;
|
||||
int rv;
|
||||
int i;
|
||||
|
||||
*done_count = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
*done_count = rv;
|
||||
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,
|
||||
int *done_count)
|
||||
{
|
||||
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,27 +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,
|
||||
int *done_count);
|
||||
|
||||
#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)
|
||||
|
||||
@@ -358,12 +358,11 @@ static int _print_header(struct cmd_context *cmd, struct formatter *f,
|
||||
static int _print_flag_config(struct formatter *f, uint64_t status, int type)
|
||||
{
|
||||
char buffer[4096];
|
||||
|
||||
if (!print_flags(buffer, sizeof(buffer), type, STATUS_FLAG, status))
|
||||
if (!print_flags(status, type | STATUS_FLAG, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!print_flags(buffer, sizeof(buffer), type, COMPATIBLE_FLAG, status))
|
||||
if (!print_flags(status, type, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
outf(f, "flags = %s", buffer);
|
||||
|
||||
@@ -502,13 +501,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
|
||||
*/
|
||||
static const char *_get_pv_name_from_uuid(struct formatter *f, char *uuid)
|
||||
{
|
||||
const char *pv_name = dm_hash_lookup(f->pv_names, uuid);
|
||||
|
||||
if (!pv_name)
|
||||
log_error(INTERNAL_ERROR "PV name for uuid %s missing from text metadata export hash table.",
|
||||
uuid);
|
||||
|
||||
return pv_name;
|
||||
return dm_hash_lookup(f->pv_names, uuid);
|
||||
}
|
||||
|
||||
static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv)
|
||||
@@ -584,11 +577,6 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
static int _print_segment(struct formatter *f, struct volume_group *vg,
|
||||
int count, struct lv_segment *seg)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
if (!print_segtype_lvflags(buffer, sizeof(buffer), seg->lv->status))
|
||||
return_0;
|
||||
|
||||
outf(f, "segment%u {", count);
|
||||
_inc_indent(f);
|
||||
|
||||
@@ -599,8 +587,7 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
|
||||
if (seg->reshape_len)
|
||||
outsize(f, (uint64_t) seg->reshape_len * vg->extent_size,
|
||||
"reshape_count = %u", seg->reshape_len);
|
||||
|
||||
outf(f, "type = \"%s%s\"", seg->segtype->name, buffer);
|
||||
outf(f, "type = \"%s\"", seg->segtype->name);
|
||||
|
||||
if (!_out_list(f, &seg->tags, "tags"))
|
||||
return_0;
|
||||
@@ -620,7 +607,6 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
{
|
||||
const char *name;
|
||||
unsigned int s;
|
||||
struct physical_volume *pv;
|
||||
|
||||
outnl(f);
|
||||
|
||||
@@ -630,13 +616,7 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
switch (seg_type(seg, s)) {
|
||||
case AREA_PV:
|
||||
if (!(pv = seg_pv(seg, s))) {
|
||||
log_error(INTERNAL_ERROR "Missing PV for area %" PRIu32 " of %s segment of LV %s.",
|
||||
s, type, display_lvname(seg->lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(name = _get_pv_name(f, pv)))
|
||||
if (!(name = _get_pv_name(f, seg_pv(seg, s))))
|
||||
return_0;
|
||||
|
||||
outf(f, "\"%s\", %u%s", name,
|
||||
@@ -670,8 +650,6 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
|
||||
break;
|
||||
case AREA_UNASSIGNED:
|
||||
log_error(INTERNAL_ERROR "Invalid type for area %" PRIu32 " of %s segment of LV %s.",
|
||||
s, type, display_lvname(seg->lv));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -910,8 +888,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;
|
||||
}
|
||||
|
||||
|
@@ -47,8 +47,6 @@ static const struct flag _pv_flags[] = {
|
||||
{ALLOCATABLE_PV, "ALLOCATABLE", STATUS_FLAG},
|
||||
{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,15 +61,13 @@ 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},
|
||||
{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG},
|
||||
{LV_METADATA_FORMAT, "METADATA_FORMAT", STATUS_FLAG},
|
||||
{LV_NOSCAN, NULL, 0},
|
||||
{LV_TEMPORARY, NULL, 0},
|
||||
{POOL_METADATA_SPARE, NULL, 0},
|
||||
@@ -90,6 +86,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},
|
||||
@@ -103,9 +101,9 @@ static const struct flag _lv_flags[] = {
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
||||
static const struct flag *_get_flags(enum pv_vg_lv_e type)
|
||||
static const struct flag *_get_flags(int type)
|
||||
{
|
||||
switch (type) {
|
||||
switch (type & ~STATUS_FLAG) {
|
||||
case VG_FLAGS:
|
||||
return _vg_flags;
|
||||
|
||||
@@ -116,7 +114,7 @@ static const struct flag *_get_flags(enum pv_vg_lv_e type)
|
||||
return _lv_flags;
|
||||
}
|
||||
|
||||
log_error(INTERNAL_ERROR "Unknown flag set requested.");
|
||||
log_error("Unknown flag set requested.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -125,7 +123,7 @@ static const struct flag *_get_flags(enum pv_vg_lv_e type)
|
||||
* using one of the tables defined at the top of
|
||||
* the file.
|
||||
*/
|
||||
int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint64_t status)
|
||||
int print_flags(uint64_t status, int type, char *buffer, size_t size)
|
||||
{
|
||||
int f, first = 1;
|
||||
const struct flag *flags;
|
||||
@@ -134,13 +132,13 @@ int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint6
|
||||
return_0;
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "["))
|
||||
return_0;
|
||||
return 0;
|
||||
|
||||
for (f = 0; flags[f].mask; f++) {
|
||||
if (status & flags[f].mask) {
|
||||
status &= ~flags[f].mask;
|
||||
|
||||
if (mask != flags[f].kind)
|
||||
if ((type & STATUS_FLAG) != flags[f].kind)
|
||||
continue;
|
||||
|
||||
/* Internal-only flag? */
|
||||
@@ -149,18 +147,18 @@ int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint6
|
||||
|
||||
if (!first) {
|
||||
if (!emit_to_buffer(&buffer, &size, ", "))
|
||||
return_0;
|
||||
return 0;
|
||||
} else
|
||||
first = 0;
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "\"%s\"",
|
||||
flags[f].description))
|
||||
return_0;
|
||||
flags[f].description))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "]"))
|
||||
return_0;
|
||||
return 0;
|
||||
|
||||
if (status)
|
||||
log_warn(INTERNAL_ERROR "Metadata inconsistency: "
|
||||
@@ -169,9 +167,9 @@ int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint6
|
||||
return 1;
|
||||
}
|
||||
|
||||
int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm_config_value *cv)
|
||||
int read_flags(uint64_t *status, int type, const struct dm_config_value *cv)
|
||||
{
|
||||
unsigned f;
|
||||
int f;
|
||||
uint64_t s = UINT64_C(0);
|
||||
const struct flag *flags;
|
||||
|
||||
@@ -188,8 +186,7 @@ int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm
|
||||
}
|
||||
|
||||
for (f = 0; flags[f].description; f++)
|
||||
if ((flags[f].kind & mask) &&
|
||||
!strcmp(flags[f].description, cv->v.str)) {
|
||||
if (!strcmp(flags[f].description, cv->v.str)) {
|
||||
s |= flags[f].mask;
|
||||
break;
|
||||
}
|
||||
@@ -203,7 +200,7 @@ int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm
|
||||
* by this case.
|
||||
*/
|
||||
s |= PARTIAL_VG;
|
||||
} else if (!flags[f].description && (mask & STATUS_FLAG)) {
|
||||
} else if (!flags[f].description && (type & STATUS_FLAG)) {
|
||||
log_error("Unknown status flag '%s'.", cv->v.str);
|
||||
return 0;
|
||||
}
|
||||
@@ -215,71 +212,3 @@ int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm
|
||||
*status |= s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse extra status flags from segment "type" string.
|
||||
* These flags are seen as INCOMPATIBLE by any older lvm2 code.
|
||||
* All flags separated by '+' are trimmed from passed string.
|
||||
* All UNKNOWN flags will again cause the "UNKNOWN" segtype.
|
||||
*
|
||||
* Note: using these segtype status flags instead of actual
|
||||
* status flags ensures wanted incompatiblity.
|
||||
*/
|
||||
int read_segtype_lvflags(uint64_t *status, char *segtype_str)
|
||||
{
|
||||
unsigned i;
|
||||
const struct flag *flags = _lv_flags;
|
||||
char *delim;
|
||||
char *flag, *buffer, *str;
|
||||
|
||||
if (!(str = strchr(segtype_str, '+')))
|
||||
return 1; /* No flags */
|
||||
|
||||
if (!(buffer = dm_strdup(str + 1))) {
|
||||
log_error("Cannot duplicate segment string.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
delim = buffer;
|
||||
|
||||
do {
|
||||
flag = delim;
|
||||
if ((delim = strchr(delim, '+')))
|
||||
*delim++ = '\0';
|
||||
|
||||
for (i = 0; flags[i].description; i++)
|
||||
if ((flags[i].kind & SEGTYPE_FLAG) &&
|
||||
!strcmp(flags[i].description, flag)) {
|
||||
*status |= flags[i].mask;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (delim && flags[i].description); /* Till no more flags in type appear */
|
||||
|
||||
if (!flags[i].description)
|
||||
/* Unknown flag is incompatible - returns unmodified segtype_str */
|
||||
log_warn("WARNING: Unrecognised flag %s in segment type %s.",
|
||||
flag, segtype_str);
|
||||
else
|
||||
*str = '\0'; /* Cut away 1st. '+' */
|
||||
|
||||
dm_free(buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int print_segtype_lvflags(char *buffer, size_t size, uint64_t status)
|
||||
{
|
||||
unsigned i;
|
||||
const struct flag *flags = _lv_flags;
|
||||
|
||||
buffer[0] = 0;
|
||||
for (i = 0; flags[i].mask; i++)
|
||||
if ((flags[i].kind & SEGTYPE_FLAG) &&
|
||||
(status & flags[i].mask) &&
|
||||
!emit_to_buffer(&buffer, &size, "+%s",
|
||||
flags[i].description))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -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)
|
||||
{
|
||||
@@ -432,15 +415,12 @@ static struct raw_locn *_read_metadata_location_vg(struct device_area *dev_area,
|
||||
struct lvmcache_vgsummary vgsummary_orphan = {
|
||||
.vgname = FMT_TEXT_ORPHAN_VG_NAME,
|
||||
};
|
||||
int rlocn_was_ignored;
|
||||
|
||||
memcpy(&vgsummary_orphan.vgid, FMT_TEXT_ORPHAN_VG_NAME, sizeof(FMT_TEXT_ORPHAN_VG_NAME));
|
||||
|
||||
rlocn = mdah->raw_locns; /* Slot 0 */
|
||||
rlocn_precommitted = rlocn + 1; /* Slot 1 */
|
||||
|
||||
rlocn_was_ignored = rlocn_is_ignored(rlocn);
|
||||
|
||||
/* Should we use precommitted metadata? */
|
||||
if (*precommitted && rlocn_precommitted->size &&
|
||||
(rlocn_precommitted->offset != rlocn->offset)) {
|
||||
@@ -459,35 +439,18 @@ static struct raw_locn *_read_metadata_location_vg(struct device_area *dev_area,
|
||||
if (!*vgname)
|
||||
return rlocn;
|
||||
|
||||
/*
|
||||
* If live rlocn has ignored flag, data will be out-of-date so skip further checks.
|
||||
*/
|
||||
if (rlocn_was_ignored)
|
||||
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 %smetadata on %s at %" PRIu64 " does "
|
||||
"not match expected name %s.",
|
||||
*precommitted ? "precommitted " : "",
|
||||
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)) &&
|
||||
@@ -525,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))
|
||||
@@ -540,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;
|
||||
@@ -552,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;
|
||||
}
|
||||
@@ -569,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;
|
||||
@@ -599,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;
|
||||
@@ -609,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;
|
||||
@@ -620,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)
|
||||
{
|
||||
@@ -630,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;
|
||||
@@ -647,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;
|
||||
}
|
||||
}
|
||||
@@ -668,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 &&
|
||||
@@ -759,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;
|
||||
}
|
||||
}
|
||||
@@ -774,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;
|
||||
@@ -788,14 +747,6 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
|
||||
mdah->raw_locns[2].size = 0;
|
||||
mdah->raw_locns[2].checksum = 0;
|
||||
rlocn = &mdah->raw_locns[0];
|
||||
} else if (precommit && rlocn_is_ignored(rlocn) && !mda_is_ignored(mda)) {
|
||||
/*
|
||||
* If precommitting into a previously-ignored mda, wipe the live rlocn
|
||||
* as a precaution so that nothing can use it by mistake.
|
||||
*/
|
||||
mdah->raw_locns[0].offset = 0;
|
||||
mdah->raw_locns[0].size = 0;
|
||||
mdah->raw_locns[0].checksum = 0;
|
||||
}
|
||||
|
||||
if (precommit)
|
||||
@@ -812,14 +763,12 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
|
||||
rlocn->offset = mdac->rlocn.offset;
|
||||
rlocn->size = mdac->rlocn.size;
|
||||
rlocn->checksum = mdac->rlocn.checksum;
|
||||
log_debug_metadata("%sCommitting %s %smetadata (%u) to %s header at %"
|
||||
PRIu64, precommit ? "Pre-" : "", vg->name,
|
||||
mda_is_ignored(mda) ? "(ignored) " : "", vg->seqno,
|
||||
log_debug_metadata("%sCommitting %s metadata (%u) to %s header at %"
|
||||
PRIu64, precommit ? "Pre-" : "", vg->name, vg->seqno,
|
||||
dev_name(mdac->area.dev), mdac->area.start);
|
||||
} else
|
||||
log_debug_metadata("Wiping pre-committed %s %smetadata from %s "
|
||||
log_debug_metadata("Wiping pre-committed %s metadata from %s "
|
||||
"header at %" PRIu64, vg->name,
|
||||
mda_is_ignored(mda) ? "(ignored) " : "",
|
||||
dev_name(mdac->area.dev), mdac->area.start);
|
||||
|
||||
rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
|
||||
@@ -894,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;
|
||||
}
|
||||
@@ -931,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
|
||||
@@ -947,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;
|
||||
}
|
||||
@@ -957,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;
|
||||
|
||||
@@ -969,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)))
|
||||
{
|
||||
@@ -1098,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);
|
||||
@@ -1158,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);
|
||||
@@ -1193,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);
|
||||
}
|
||||
}
|
||||
@@ -1212,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;
|
||||
@@ -1222,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;
|
||||
}
|
||||
|
||||
@@ -1238,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))
|
||||
@@ -1261,65 +1188,47 @@ 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we see this metadata before?
|
||||
* Look in lvmcache to see if there is vg info matching
|
||||
* the checksum/size that we see in the mda_header (rlocn)
|
||||
* on this device. If so, then vgsummary->name is is set
|
||||
* and controls if the "checksum_only" flag passed to
|
||||
* text_read_metadata_summary() is 1 or 0.
|
||||
*
|
||||
* If checksum_only = 1, then text_read_metadata_summary()
|
||||
* will read the metadata from this device, and run the
|
||||
* checksum function on it. If the calculated checksum
|
||||
* of the metadata matches the checksum in the mda_header,
|
||||
* which also matches the checksum saved in vginfo from
|
||||
* another device, then it skips parsing the metadata into
|
||||
* a config tree, which saves considerable cpu time.
|
||||
*/
|
||||
/* Did we see this metadata before? */
|
||||
vgsummary->mda_checksum = rlocn->checksum;
|
||||
vgsummary->mda_size = rlocn->size;
|
||||
lvmcache_lookup_mda(vgsummary);
|
||||
|
||||
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("Found metadata summary on %s at %"PRIu64" size %"PRIu64" 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)) -
|
||||
@@ -1335,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;
|
||||
@@ -1348,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))
|
||||
@@ -1385,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 {
|
||||
@@ -1620,6 +1516,36 @@ static uint64_t _metadata_locn_offset_raw(void *metadata_locn)
|
||||
return mdac->area.start;
|
||||
}
|
||||
|
||||
static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, int scan_label_only)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
struct device *dev;
|
||||
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
|
||||
return_0;
|
||||
|
||||
if (lvmetad_used()) {
|
||||
info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
|
||||
if (!info && !lvmetad_pv_lookup_by_dev(fmt->cmd, dev, NULL))
|
||||
return 0;
|
||||
info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
|
||||
} else {
|
||||
struct label *label;
|
||||
if (!(label_read(dev, &label, UINT64_C(0))))
|
||||
return_0;
|
||||
info = label->info;
|
||||
}
|
||||
|
||||
if (!info)
|
||||
return_0;
|
||||
|
||||
if (!lvmcache_populate_pv_fields(info, pv, scan_label_only))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _text_pv_initialise(const struct format_type *fmt,
|
||||
struct pv_create_args *pva,
|
||||
struct physical_volume *pv)
|
||||
@@ -1704,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1813,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)
|
||||
@@ -1822,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,
|
||||
@@ -1839,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;
|
||||
@@ -2070,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:
|
||||
@@ -2141,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;
|
||||
@@ -2276,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)) {
|
||||
@@ -2312,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) {
|
||||
@@ -2338,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)
|
||||
@@ -2354,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",
|
||||
@@ -2468,6 +2397,7 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
|
||||
|
||||
static struct format_handler _text_handler = {
|
||||
.scan = _text_scan,
|
||||
.pv_read = _text_pv_read,
|
||||
.pv_initialise = _text_pv_initialise,
|
||||
.pv_setup = _text_pv_setup,
|
||||
.pv_add_metadata_area = _text_pv_add_metadata_area,
|
||||
@@ -2538,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)))
|
||||
|
@@ -35,20 +35,19 @@
|
||||
* VGs, PVs and LVs all have status bitsets, we gather together
|
||||
* common code for reading and writing them.
|
||||
*/
|
||||
enum pv_vg_lv_e {
|
||||
PV_FLAGS = 1,
|
||||
enum {
|
||||
COMPATIBLE_FLAG = 0x0,
|
||||
VG_FLAGS,
|
||||
PV_FLAGS,
|
||||
LV_FLAGS,
|
||||
STATUS_FLAG = 0x8,
|
||||
};
|
||||
|
||||
#define COMPATIBLE_FLAG 0x01
|
||||
#define STATUS_FLAG 0x02
|
||||
#define SEGTYPE_FLAG 0x04
|
||||
|
||||
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);
|
||||
@@ -59,32 +58,28 @@ struct text_vg_version_ops {
|
||||
|
||||
struct text_vg_version_ops *text_vg_vsn1_init(void);
|
||||
|
||||
int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint64_t status);
|
||||
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 print_flags(uint64_t status, int type, char *buffer, size_t size);
|
||||
int read_flags(uint64_t *status, int type, const struct dm_config_value *cv);
|
||||
|
||||
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,57 +45,24 @@ 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) {
|
||||
/* Checksum matches already-cached content - no need to reparse. */
|
||||
log_debug_metadata("Skipped parsing metadata on %s", dev_name(dev));
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
@@ -125,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,
|
||||
@@ -140,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.");
|
||||
@@ -171,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;
|
||||
}
|
||||
|
||||
@@ -224,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);
|
||||
@@ -244,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;
|
||||
@@ -272,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.
|
||||
@@ -138,14 +140,13 @@ static int _read_flag_config(const struct dm_config_node *n, uint64_t *status, i
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For backward compatible metadata accept both type of flags */
|
||||
if (!(read_flags(status, type, STATUS_FLAG | SEGTYPE_FLAG, cv))) {
|
||||
if (!(read_flags(status, type | STATUS_FLAG, cv))) {
|
||||
log_error("Could not read status flags.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_config_get_list(n, "flags", &cv)) {
|
||||
if (!(read_flags(status, type, COMPATIBLE_FLAG, cv))) {
|
||||
if (!(read_flags(status, type, cv))) {
|
||||
log_error("Could not read flags.");
|
||||
return 0;
|
||||
}
|
||||
@@ -178,7 +179,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 +219,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)))
|
||||
@@ -354,7 +357,6 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
||||
uint32_t area_extents, start_extent, extent_count, reshape_count, data_copies;
|
||||
struct segment_type *segtype;
|
||||
const char *segtype_str;
|
||||
char *segtype_with_flags;
|
||||
|
||||
if (!sn_child) {
|
||||
log_error("Empty segment section.");
|
||||
@@ -386,24 +388,9 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Locally duplicate to parse out status flag bits */
|
||||
if (!(segtype_with_flags = dm_pool_strdup(mem, segtype_str))) {
|
||||
log_error("Cannot duplicate segtype string.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!read_segtype_lvflags(&lv->status, segtype_with_flags)) {
|
||||
log_error("Couldn't read segtype for logical volume %s.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(segtype = get_segtype_from_string(lv->vg->cmd, segtype_with_flags)))
|
||||
if (!(segtype = get_segtype_from_string(lv->vg->cmd, segtype_str)))
|
||||
return_0;
|
||||
|
||||
/* Can drop temporary string here as nothing has allocated from VGMEM meanwhile */
|
||||
dm_pool_free(mem, segtype_with_flags);
|
||||
|
||||
if (segtype->ops->text_import_area_count &&
|
||||
!segtype->ops->text_import_area_count(sn_child, &area_count))
|
||||
return_0;
|
||||
@@ -570,7 +557,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 +714,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 +785,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 +897,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 +960,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 +977,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 +987,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 +1150,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 +1170,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;
|
||||
|
1543
lib/label/label.c
1543
lib/label/label.c
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user