mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-10-30 20:23:49 +03:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			dev-dct-de
			...
			dev-dct-pv
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c93d169857 | ||
|  | c3e97e0cb9 | 
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -30,19 +30,14 @@ make.tmpl | ||||
| /config.log | ||||
| /config.status | ||||
| /configure.scan | ||||
| /cscope.* | ||||
| /cscope.out | ||||
| /html/ | ||||
| /python/ | ||||
| /reports/ | ||||
| /tags | ||||
| /tmp/ | ||||
|  | ||||
| coverity/coverity_model.xml | ||||
|  | ||||
| # gcov files: | ||||
| *.gcda | ||||
| *.gcno | ||||
|  | ||||
| tools/man-generator | ||||
| tools/man-generator.c | ||||
|  | ||||
|   | ||||
							
								
								
									
										45
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								Makefile.in
									
									
									
									
									
								
							| @@ -18,7 +18,7 @@ top_builddir = @top_builddir@ | ||||
| abs_top_builddir = @abs_top_builddir@ | ||||
| abs_top_srcdir = @abs_top_srcdir@ | ||||
|  | ||||
| SUBDIRS = libdm conf daemons include lib libdaemon man scripts tools | ||||
| SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools | ||||
|  | ||||
| ifeq ("@UDEV_RULES@", "yes") | ||||
|   SUBDIRS += udev | ||||
| @@ -47,6 +47,8 @@ include $(top_srcdir)/base/Makefile | ||||
| include $(top_srcdir)/device_mapper/Makefile | ||||
| include $(top_srcdir)/test/unit/Makefile | ||||
|  | ||||
| libdm: include | ||||
| libdaemon: include | ||||
| lib: libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET) | ||||
| daemons: lib libdaemon tools | ||||
| scripts: lib | ||||
| @@ -54,13 +56,16 @@ tools: lib libdaemon | ||||
| po: tools daemons | ||||
| man: tools | ||||
| all_man: tools | ||||
| scripts: libdm | ||||
| test: tools daemons | ||||
| unit-test  run-unit-test: test | ||||
|  | ||||
| lib.device-mapper: include.device-mapper | ||||
| libdm.device-mapper: include.device-mapper | ||||
| daemons.device-mapper: libdm.device-mapper | ||||
| tools.device-mapper: libdm.device-mapper | ||||
| scripts.device-mapper: include.device-mapper | ||||
| device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper | ||||
| device_mapper: device-mapper | ||||
|  | ||||
| ifeq ("@INTL@", "yes") | ||||
| lib.pofile: include.pofile | ||||
| @@ -76,10 +81,9 @@ daemons.cflow: tools.cflow | ||||
| cflow: include.cflow | ||||
| endif | ||||
|  | ||||
| CSCOPE_DIRS = base daemons device_mapper include lib libdaemon scripts tools libdm test | ||||
| ifneq ("@CSCOPE_CMD@", "") | ||||
| cscope.out: | ||||
| 	@CSCOPE_CMD@ -b -R $(patsubst %,-s%,$(addprefix $(srcdir)/,$(CSCOPE_DIRS))) | ||||
| 	@CSCOPE_CMD@ -b -R -s$(top_srcdir) | ||||
| all: cscope.out | ||||
| endif | ||||
| DISTCLEAN_TARGETS += cscope.out | ||||
| @@ -112,11 +116,11 @@ rpm: dist | ||||
| 	$(LN_S) -f $(abs_top_srcdir)/spec/packages.inc $(rpmbuilddir)/SOURCES | ||||
| 	DM_VER=$$(cut -d- -f1 $(top_srcdir)/VERSION_DM);\ | ||||
| 	GIT_VER=$$(cd $(top_srcdir); git describe | cut -d- --output-delimiter=. -f2,3 || echo 0);\ | ||||
| 	$(SED) -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \ | ||||
| 	sed -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \ | ||||
| 	    -e "s,^\(Version:[^0-9%]*\)[0-9.]*$$,\1 $(LVM_VER)," \ | ||||
| 	    -e "s,^\(Release:[^0-9%]*\)[0-9.]\+,\1 $$GIT_VER," \ | ||||
| 	    $(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc | ||||
| 	V=$(V) rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec | ||||
| 	rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec | ||||
|  | ||||
| generate: conf.generate man.generate | ||||
| 	$(MAKE) -C conf generate | ||||
| @@ -150,31 +154,6 @@ install_all_man: | ||||
| install_tmpfiles_configuration: | ||||
| 	$(MAKE) -C scripts install_tmpfiles_configuration | ||||
|  | ||||
| help: | ||||
| 	@echo -e "\nAvailable targets:" | ||||
| 	@echo "  all			Default target." | ||||
| 	@echo "  all_man		Build all man pages with generators." | ||||
| 	@echo "  clean			Remove all compile files." | ||||
| 	@echo "  device-mapper		Device mapper part of lvm2." | ||||
| 	@echo "  dist			Generate distributable file." | ||||
| 	@echo "  distclean		Remove all build files." | ||||
| 	@echo "  generate		Generate man pages for sources." | ||||
| 	@echo "  help			Display callable targets." | ||||
| 	@echo "  install		Install all files." | ||||
| 	@echo "  install_all_man	Install all man pages." | ||||
| 	@echo "  install_cluster	Install cmirrord." | ||||
| 	@echo "  install_device-mapper	Install device mapper files." | ||||
| 	@echo "  install_initscripts	Install initialization scripts." | ||||
| 	@echo "  install_lvm2		Install lvm2 files." | ||||
| 	@echo "  install_systemd_units	Install systemd units." | ||||
| 	@echo "  lcov			Generate lcov output." | ||||
| 	@echo "  lcov-dated		Generate lcov with timedate suffix." | ||||
| 	@echo "  lcov-reset		Reset lcov counters" | ||||
| 	@echo "  man			Build man pages." | ||||
| 	@echo "  rpm			Build rpm." | ||||
| 	@echo "  run-unit-test		Run unit tests." | ||||
| 	@echo "  tags			Generate c/etags." | ||||
|  | ||||
| ifneq ("$(LCOV)", "") | ||||
| .PHONY: lcov-reset lcov lcov-dated | ||||
|  | ||||
| @@ -204,8 +183,8 @@ endif | ||||
| ifneq ($(shell which ctags 2>/dev/null),) | ||||
| .PHONY: tags | ||||
| tags: | ||||
| 	test -z "$(shell find $(addprefix $(top_srcdir)/,$(CSCOPE_DIRS)) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags | ||||
| 	test -f tags || find $(addprefix $(top_srcdir)/,$(CSCOPE_DIRS)) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' + | ||||
| 	test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags | ||||
| 	test -f tags || find $(top_srcdir) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' + | ||||
|  | ||||
| CLEAN_TARGETS += tags | ||||
| endif | ||||
|   | ||||
							
								
								
									
										11
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README
									
									
									
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| This tree contains the LVM2 and device-mapper tools and libraries. | ||||
|  | ||||
| This is development branch, for stable 2.02 release see stable-2.02 branch. | ||||
| This is development branch, for stable 2.02 release see 2018-06-01-stable | ||||
| branch. | ||||
|  | ||||
| For more information about LVM2 read the changelog in the WHATS_NEW file. | ||||
| Installation instructions are in INSTALL. | ||||
| @@ -9,6 +10,7 @@ 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: | ||||
| @@ -43,9 +45,6 @@ Report upstream bugs at: | ||||
| or open issues at: | ||||
|   https://github.com/lvmteam/lvm2/issues | ||||
|  | ||||
| The source code repository used until 7th June 2012 is accessible using CVS: | ||||
| The source code repository used until 7th June 2012 is accessible here: | ||||
|   http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2. | ||||
|  | ||||
|   cvs -d :pserver:cvs@sourceware.org:/cvs/lvm2 login cvs | ||||
|   cvs -d :pserver:cvs@sourceware.org:/cvs/lvm2 checkout LVM2 | ||||
|  | ||||
| The password is cvs. | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| 1.02.185-git (2022-02-07) | ||||
| 1.02.165-git (2019-06-15) | ||||
|   | ||||
							
								
								
									
										217
									
								
								WHATS_NEW
									
									
									
									
									
								
							
							
						
						
									
										217
									
								
								WHATS_NEW
									
									
									
									
									
								
							| @@ -1,215 +1,5 @@ | ||||
| Version 2.03.16 -  | ||||
| ==================================== | ||||
|  | ||||
| Version 2.03.15 - 07th February 2022 | ||||
| ==================================== | ||||
|   Remove service based autoactivation. global/event_activation = 0 is NOOP. | ||||
|   Improve support for metadata profiles for --type writecache. | ||||
|   Use cache or active DM device when available with new kernels. | ||||
|   Introduce function to utilize UUIDs from DM_DEVICE_LIST. | ||||
|   Increase some hash table size to better support large device sets. | ||||
|  | ||||
| Version 2.03.14 - 20th October 2021 | ||||
| =================================== | ||||
|   Device scanning is skipping directories on different filesystems. | ||||
|   Print info message with too many or too large archived files. | ||||
|   Reduce metadata readings during scanning phase. | ||||
|   Optimize computation of crc32 check sum with multiple PVs. | ||||
|   Enhance recover path on cache creation failure. | ||||
|   Filter out unsupported MQ/SMQ cache policy setting. | ||||
|   Fix memleak in mpath filter. | ||||
|   Support newer location for VDO statistics. | ||||
|   Add support for VDO async-unsafe write policy. | ||||
|   Improve lvm_import_vdo script. | ||||
|   Support VDO LV with lvcreate -ky. | ||||
|   Fix lvconvert for VDO LV bigger then 2T. | ||||
|   Create VDO LVs automatically without zeroing. | ||||
|   Rename vdoimport to lvm_import_vdo. | ||||
|  | ||||
| Version 2.03.13 - 11th August 2021 | ||||
| ================================== | ||||
|   Changes in udev support: | ||||
|   - obtain_device_list_from_udev defaults to 0. | ||||
|   - see devices/external_device_info_source, | ||||
|     devices/obtain_device_list_from_udev, and devices/multipath_wwids_file help | ||||
|     in lvm.conf | ||||
|   Fix devices file handling of loop with deleted backing file. | ||||
|   Fix devices file handling of scsi_debug WWIDs. | ||||
|   Fix many static analysis issues. | ||||
|   Support --poolmetadataspare with vgsplit and vgmerge. | ||||
|   Fix detection of active components of external origin volume. | ||||
|   Add vdoimport tool to support conversion of VDO volumes. | ||||
|   Support configurable allocation/vdo_pool_header_size. | ||||
|   Fix handling of lvconvert --type vdo-pool --virtualsize. | ||||
|   Simplified handling of archive() and backup() internal calls. | ||||
|   Add 'idm' locking type for IDM lock manager. | ||||
|   Fix load of kvdo target when it is not present in memory (2.03.12). | ||||
|  | ||||
| Version 2.03.12 - 07th May 2021 | ||||
| =============================== | ||||
|   Allow attaching cache to thin data volume. | ||||
|   Fix memleak when generating list of outdated pvs. | ||||
|   Better hyphenation usage in man pages. | ||||
|   Replace use of deprecated security_context_t with char*. | ||||
|   Configure supports AIO_LIBS and AIO_CFLAGS. | ||||
|   Improve build process for static builds. | ||||
|   New --setautoactivation option to modify LV or VG auto activation. | ||||
|   New metadata based autoactivation property for LVs and VGs. | ||||
|   Improve signal handling with lvmpolld. | ||||
|   Signal handler can interrupt command also for SIGTERM. | ||||
|   Lvreduce --yes support. | ||||
|   Add configure option --with/out-symvers for non-glibc builds. | ||||
|   Report error when the filesystem is missing on fsadm resized volume. | ||||
|   Handle better blockdev with --getsize64 support for fsadm. | ||||
|   Do not include editline/history.h when using editline library. | ||||
|   Support error and zero segtype for thin-pool data for testing. | ||||
|   Support mixed extension for striped, error and zero segtypes. | ||||
|   Support resize also for stacked virtual volumes. | ||||
|   Skip dm-zero devices just like with dm-error target. | ||||
|   Reduce ioctl() calls when checking target status. | ||||
|   Merge polling does not fail, when LV is found to be already merged. | ||||
|   Poll volumes with at least 100ms delays. | ||||
|   Do not flush dm cache when cached LV is going to be removed. | ||||
|   New lvmlockctl_kill_command configuration option. | ||||
|   Support interruption while waiting on device close before deactivation. | ||||
|   Flush thin-pool messages before removing more thin volumes. | ||||
|   Improve hash function with less collisions and make it faster. | ||||
|   Reduce ioctl count when deactivating volumes. | ||||
|   Reduce number of metadata parsing. | ||||
|   Enhance performance of lvremove and vgremove commands. | ||||
|   Support interruption when taking archive and backup. | ||||
|   Accelerate large lvremoves. | ||||
|   Speedup search for cached device nodes. | ||||
|   Speedup command initialization. | ||||
|   Add devices file feature, off by default for now. | ||||
|   Support extension of writecached volumes. | ||||
|   Fix problem with unbound variable usage within fsadm. | ||||
|   Fix IMSM MD RAID detection on 4k devices. | ||||
|   Check for presence of VDO target before starting any conversion. | ||||
|   Support metatadata profiles with volume VDO pool conversions. | ||||
|   Support -Zn for conversion of already formated VDO pools. | ||||
|   Avoid removing LVs on error path of lvconvert during creation volumes. | ||||
|   Fix crashing lvdisplay when thin volume was waiting for merge. | ||||
|   Support option --errorwhenfull when converting volume to thin-pool. | ||||
|   Improve thin-performance profile support conversion to thin-pool. | ||||
|   Add workaround to avoid read of internal 'converted' devices. | ||||
|   Prohibit merging snapshot into the read-only thick snapshot origin. | ||||
|   Restore support for flipping rw/r permissions for thin snapshot origin. | ||||
|   Support resize of cached volumes. | ||||
|   Disable autoactivation with global/event_activation=0. | ||||
|   Check if lvcreate passes read_only_volume_list with tags and skips zeroing. | ||||
|   Allocation prints better error when metadata cannot fit on a single PV. | ||||
|   Pvmove can better resolve full thin-pool tree move. | ||||
|   Limit pool metadata spare to 16GiB. | ||||
|   Improves conversion and allocation of pool metadata. | ||||
|   Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0. | ||||
|   Enhance lvdisplay to report raid available/partial. | ||||
|   Support online rename of VDO pools. | ||||
|   Improve removal of pmspare when last pool is removed. | ||||
|   Fix problem with wiping of converted LVs. | ||||
|   Fix memleak in scanning  (2.03.11). | ||||
|   Fix corner case allocation for thin-pools. | ||||
|  | ||||
| Version 2.03.11 - 08th January 2021 | ||||
| =================================== | ||||
|   Fix pvck handling MDA at offset different from 4096. | ||||
|   Partial or degraded activation of writecache is not allowed. | ||||
|   Enhance error handling for fsadm and handle correct fsck result. | ||||
|   Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values. | ||||
|   Support using BLKZEROOUT for clearing devices. | ||||
|   Support interruption when wipping LVs. | ||||
|   Support interruption for bcache waiting. | ||||
|   Fix bcache when device has too many failing writes. | ||||
|   Fix bcache waiting for IO completion with failing disks. | ||||
|   Configure use own python path name order to prefer using python3. | ||||
|   Add configure --enable-editline support as an alternative to readline. | ||||
|   Enhance reporting and error handling when creating thin volumes. | ||||
|   Enable vgsplit for VDO volumes. | ||||
|   Lvextend of vdo pool volumes ensure at least 1 new VDO slab is added. | ||||
|   Use revert_lv() on reload error path after vg_revert(). | ||||
|   Configure --with-integrity enabled. | ||||
|   Restore lost signal blocking while VG lock is held. | ||||
|   Improve estimation of needed extents when creating thin-pool. | ||||
|   Use extra 1% when resizing thin-pool metadata LV with --use-policy. | ||||
|   Enhance --use-policy percentage rounding. | ||||
|   Configure --with-vdo and --with-writecache as internal segments. | ||||
|   Improving VDO man page examples. | ||||
|   Allow pvmove of writecache origin. | ||||
|   Report integrity fields. | ||||
|   Integrity volumes defaults to journal mode. | ||||
|   Switch code base to use flexible array syntax. | ||||
|   Fix 64bit math when calculation cachevol size. | ||||
|   Preserve uint32_t for seqno handling. | ||||
|   Switch from mmap to plain read when loading regular files. | ||||
|   Update lvmvdo man page and better explain DISCARD usage. | ||||
|  | ||||
| Version 2.03.10 - 09th August 2020 | ||||
| ================================== | ||||
|   Add writecache and integrity support to lvmdbusd. | ||||
|   Generate unique cachevol name when default required from lvcreate. | ||||
|   Converting RAID1 volume to one with same number of legs now succeeds with a | ||||
|   warning. | ||||
|   Fix conversion to raid from striped lagging type. | ||||
|   Fix conversion to 'mirrored' mirror log with larger regionsize. | ||||
|   Zero pool metadata on allocation (disable with allocation/zero_metadata=0). | ||||
|   Failure in zeroing or wiping will fail command (bypass with -Zn, -Wn). | ||||
|   Add lvcreate of new cache or writecache lv with single command. | ||||
|   Fix running out of free buffers for async writing for larger writes. | ||||
|   Add integrity with raid capability. | ||||
|   Fix support for lvconvert --repair used by foreign apps (i.e. Docker). | ||||
|  | ||||
| Version 2.03.09 - 26th March 2020 | ||||
| ================================= | ||||
|   Fix formating of vdopool (vdo_slab_size_mb was smaller by 2 bits). | ||||
|   Fix showing of a dm kernel error when uncaching a volume with cachevol. | ||||
|  | ||||
| Version 2.03.08 - 11th February 2020 | ||||
| ==================================== | ||||
|   Prevent problematic snapshots of writecache volumes. | ||||
|   Add error handling for failing allocation in _reserve_area(). | ||||
|   Fix memleak in syncing of internal cache. | ||||
|   Fix pvck dump_current_text memleak. | ||||
|   Fix lvmlockd result code on error path for _query_lock_lv(). | ||||
|   Update pvck man page and help output. | ||||
|   Reject invalid writecache high/low_watermark setting. | ||||
|   Report writecache status. | ||||
|   Accept more output lines from vdo_format. | ||||
|   Prohibit reshaping of stacked raid LVs. | ||||
|   Avoid running cache input arg validation when creating vdo pool. | ||||
|   Prevent raid reshaping of stacked volumes. | ||||
|   Added VDO lvmdbusd methods for enable/disable compression & dedupe. | ||||
|   Added VDO lvmdbusd method for converting LV to VDO pool. | ||||
|  | ||||
| Version 2.03.07 - 30th November 2019 | ||||
| ==================================== | ||||
|   Subcommand in vgck for repairing headers and metadata. | ||||
|   Ensure minimum required region size on striped RaidLV creation. | ||||
|   Fix resize of thin-pool with data and metadata of different segtype. | ||||
|   Improve mirror type leg splitting. | ||||
|   Improve error path handling in daemons on shutdown. | ||||
|   Fix activation order when removing merged snapshot. | ||||
|   Experimental VDO support for lvmdbusd. | ||||
|  | ||||
| Version 2.03.06 - 23rd October 2019 | ||||
| =================================== | ||||
|   Add _cpool suffix to cache-pool LV name when used by caching LV. | ||||
|   No longer store extra UUID for cmeta and cdata cachevol layer. | ||||
|   Enhance activation of cache devices with cachevols. | ||||
|   Add _cvol in list of protected suffixes and start use it with DM UUID. | ||||
|   Rename LV converted to cachevol to use _cvol suffix. | ||||
|   Use normal LVs for wiping of cachevols. | ||||
|   Reload cleanered cache DM only with cleaner policy. | ||||
|   Fix cmd return when zeroing of cachevol fails. | ||||
|   Extend lvs to show all VDO properties. | ||||
|   Preserve VDO write policy with vdopool. | ||||
|   Increase default vdo bio threads to 4. | ||||
|   Continue report when cache_status fails. | ||||
|   Add support for DM_DEVICE_GET_TARGET_VERSION into device_mapper. | ||||
|   Fix cmirrord usage of header files from device_mapper subdir. | ||||
|   Allow standalone activation of VDO pool just like for thin-pools. | ||||
|   Activate thin-pool layered volume as 'read-only' device. | ||||
|   Ignore crypto devices with UUID signature CRYPT-SUBDEV. | ||||
|   Enhance validation for thin and cache pool conversion and swapping. | ||||
| Version 2.03.06 -  | ||||
| ================================ | ||||
|   Improve internal removal of cached devices. | ||||
|   Synchronize with udev when dropping snapshot. | ||||
|   Add missing device synchronization point before removing pvmove node. | ||||
| @@ -308,6 +98,7 @@ Version 2.03.00 - 10th October 2018 | ||||
|   Remove clvmd | ||||
|   Remove lvmlib (api) | ||||
|   Remove lvmetad | ||||
|   lvconvert: provide possible layouts between linear and striped/raid | ||||
|   Use versionsort to fix archive file expiry beyond 100000 files. | ||||
|  | ||||
| Version 2.02.178-rc1 - 24th May 2018 | ||||
| @@ -1827,7 +1618,7 @@ Version 2.02.105 - 20th January 2014 | ||||
|   Allow lvmetad to reuse stale socket. | ||||
|   Only unlink lvmetad socket on error if created by the same process. | ||||
|   Append missing newline to lvmetad missing socket path error message. | ||||
|   Check for non-zero alignment in _text_pv_add_metadata_area() to not div by 0. | ||||
|   Check for non-zero aligment in _text_pv_add_metadata_area() to not div by 0. | ||||
|   Add allocation/use_blkid_wiping to lvm.conf to enable blkid wiping. | ||||
|   Enable blkid_wiping by default if the blkid library is present. | ||||
|   Add configure --disable-blkid_wiping to disable libblkid signature detection. | ||||
|   | ||||
							
								
								
									
										50
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							| @@ -1,49 +1,5 @@ | ||||
| Version 1.02.185 -  | ||||
| ===================================== | ||||
|  | ||||
| Version 1.02.183 - 07th February 2022 | ||||
| ===================================== | ||||
|   Unmangle UUIDs for DM_DEVICE_LIST ioctl. | ||||
|  | ||||
| Version 1.02.181 - 20th October 2021 | ||||
| ==================================== | ||||
|   Add IMA support with 'dmsetup measure' command. | ||||
|   Add defines DM_NAME_LIST_FLAG_HAS_UUID, DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID. | ||||
|   Enhance tracking of activated devices when preloading dm tree. | ||||
|   Fix bug in construction of cache table line (regression from 1.02.159). | ||||
|  | ||||
| Version 1.02.179 - 11th August 2021 | ||||
| =================================== | ||||
|  | ||||
| Version 1.02.177 - 07th May 2021 | ||||
| ================================ | ||||
|   Configure proceeds without libaio to allow build of device-mapper only. | ||||
|   Fix symbol versioning build with -O2 -flto. | ||||
|   Add dm_tree_node_add_thin_pool_target_v1 with crop_metadata support. | ||||
|  | ||||
| Version 1.02.175 - 08th January 2021 | ||||
| ==================================== | ||||
|  | ||||
| Version 1.02.173 - 09th August 2020 | ||||
| =================================== | ||||
|   Add support for VDO in blkdeactivate script. | ||||
|  | ||||
| Version 1.02.171 - 26th March 2020 | ||||
| ================================== | ||||
|   Try to remove all created devices on dm preload tree error path. | ||||
|   Fix dm_list interators with gcc 10 optimization (-ftree-pta). | ||||
|   Dmeventd handles timer without looping on short intervals. | ||||
|  | ||||
| Version 1.02.169 - 11th February 2020 | ||||
| ===================================== | ||||
|   Enhance error messages for device creation. | ||||
|  | ||||
| Version 1.02.167 - 30th November 2019 | ||||
| ===================================== | ||||
|  | ||||
| Version 1.02.165 - 23rd October 2019 | ||||
| ==================================== | ||||
|   Add support for DM_DEVICE_GET_TARGET_VERSION. | ||||
| Version 1.02.165 -  | ||||
| ================================= | ||||
|   Add debug of dmsetup udevcomplete with hexa print DM_COOKIE_COMPLETED. | ||||
|   Fix versioning of dm_stats_create_region and dm_stats_create_region. | ||||
|  | ||||
| @@ -574,7 +530,7 @@ Version 1.02.86 - 23rd June 2014 | ||||
|   Add DM_REPORT_FIELD_TYPE_STRING_LIST: separate string and string list fields. | ||||
|   Add dm_str_list to libdevmapper for string list type definition and its reuse. | ||||
|   Add dmsetup -S/--select to define selection criteria for dmsetup reports. | ||||
|   Add dm_report_init_with_selection to initialize report with selection criteria. | ||||
|   Add dm_report_init_with_selection to intialize report with selection criteria. | ||||
|   Add DM_REPORT_FIELD_TYPE_SIZE: separate number and size reporting fields. | ||||
|   Use RemoveOnStop for dm-event.socket systemd unit. | ||||
|   Document env var 'DM_DEFAULT_NAME_MANGLING_MODE' in dmsetup man page. | ||||
|   | ||||
							
								
								
									
										26
									
								
								aclocal.m4
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								aclocal.m4
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| # generated automatically by aclocal 1.16.2 -*- Autoconf -*- | ||||
| # generated automatically by aclocal 1.15.1 -*- Autoconf -*- | ||||
|  | ||||
| # Copyright (C) 1996-2020 Free Software Foundation, Inc. | ||||
| # Copyright (C) 1996-2017 Free Software Foundation, Inc. | ||||
|  | ||||
| # This file is free software; the Free Software Foundation | ||||
| # gives unlimited permission to copy and/or distribute it, | ||||
| @@ -413,7 +413,7 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], | ||||
|         [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) | ||||
| ])dnl PKG_HAVE_DEFINE_WITH_MODULES | ||||
|  | ||||
| # Copyright (C) 1999-2020 Free Software Foundation, Inc. | ||||
| # Copyright (C) 1999-2017 Free Software Foundation, Inc. | ||||
| # | ||||
| # This file is free software; the Free Software Foundation | ||||
| # gives unlimited permission to copy and/or distribute it, | ||||
| @@ -446,12 +446,10 @@ AC_DEFUN([AM_PATH_PYTHON], | ||||
|  [ | ||||
|   dnl Find a Python interpreter.  Python versions prior to 2.0 are not | ||||
|   dnl supported. (2.0 was released on October 16, 2000). | ||||
|   dnl FIXME: Remove the need to hard-code Python versions here. | ||||
|   m4_define_default([_AM_PYTHON_INTERPRETER_LIST], | ||||
| [python python2 python3 dnl | ||||
|  python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl | ||||
|  python3.2 python3.1 python3.0 dnl | ||||
|  python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl | ||||
|  python2.0]) | ||||
| [python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl | ||||
|  python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) | ||||
|  | ||||
|   AC_ARG_VAR([PYTHON], [the Python interpreter]) | ||||
|  | ||||
| @@ -496,14 +494,12 @@ AC_DEFUN([AM_PATH_PYTHON], | ||||
|     m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) | ||||
|   else | ||||
|  | ||||
|   dnl Query Python for its version number.  Although site.py simply uses | ||||
|   dnl sys.version[:3], printing that failed with Python 3.10, since the | ||||
|   dnl trailing zero was eliminated. So now we output just the major | ||||
|   dnl and minor version numbers, as numbers. Apparently the tertiary | ||||
|   dnl version is not of interest. | ||||
|   dnl Query Python for its version number.  Getting [:3] seems to be | ||||
|   dnl the best way to do this; it's what "site.py" does in the standard | ||||
|   dnl library. | ||||
|  | ||||
|   AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], | ||||
|     [am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[[:2]])"`]) | ||||
|     [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) | ||||
|   AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) | ||||
|  | ||||
|   dnl Use the values of $prefix and $exec_prefix for the corresponding | ||||
| @@ -653,7 +649,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] | ||||
| sys.exit(sys.hexversion < minverhex)" | ||||
|   AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) | ||||
|  | ||||
| # Copyright (C) 2001-2020 Free Software Foundation, Inc. | ||||
| # Copyright (C) 2001-2017 Free Software Foundation, Inc. | ||||
| # | ||||
| # This file is free software; the Free Software Foundation | ||||
| # gives unlimited permission to copy and/or distribute it, | ||||
|   | ||||
| @@ -22,26 +22,17 @@ struct dm_hash_node { | ||||
| 	void *data; | ||||
| 	unsigned data_len; | ||||
| 	unsigned keylen; | ||||
| 	unsigned hash; | ||||
| 	char key[0]; | ||||
| }; | ||||
|  | ||||
| struct dm_hash_table { | ||||
| 	unsigned num_nodes; | ||||
| 	unsigned num_hint; | ||||
| 	unsigned mask_slots;    /* (slots - 1) -> used as hash mask */ | ||||
| 	unsigned collisions;    /* Collissions of hash keys */ | ||||
| 	unsigned search;        /* How many keys were searched */ | ||||
| 	unsigned found;         /* How many nodes were found */ | ||||
| 	unsigned same_hash;     /* Was there a colision with same masked hash and len ? */ | ||||
| 	unsigned num_slots; | ||||
| 	struct dm_hash_node **slots; | ||||
| }; | ||||
|  | ||||
| #if 0 /* TO BE REMOVED */ | ||||
| static unsigned _hash(const void *key, unsigned len) | ||||
| { | ||||
| 	/* Permutation of the Integers 0 through 255 */ | ||||
| 	static unsigned char _nums[] = { | ||||
| /* Permutation of the Integers 0 through 255 */ | ||||
| static unsigned char _nums[] = { | ||||
| 	1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51, | ||||
| 	87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65, | ||||
| 	49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28, | ||||
| @@ -66,16 +57,29 @@ static unsigned _hash(const void *key, unsigned len) | ||||
| 	44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184, | ||||
| 	163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120, | ||||
| 	209 | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| 	const uint8_t *str = key; | ||||
| 	unsigned h = 0, g; | ||||
| static struct dm_hash_node *_create_node(const char *str, unsigned len) | ||||
| { | ||||
| 	struct dm_hash_node *n = malloc(sizeof(*n) + len); | ||||
|  | ||||
| 	if (n) { | ||||
| 		memcpy(n->key, str, len); | ||||
| 		n->keylen = len; | ||||
| 	} | ||||
|  | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static unsigned long _hash(const char *str, unsigned len) | ||||
| { | ||||
| 	unsigned long h = 0, g; | ||||
| 	unsigned i; | ||||
|  | ||||
| 	for (i = 0; i < len; i++) { | ||||
| 		h <<= 4; | ||||
| 		h += _nums[*str++]; | ||||
| 		g = h & ((unsigned) 0xf << 16u); | ||||
| 		h += _nums[(unsigned char) *str++]; | ||||
| 		g = h & ((unsigned long) 0xf << 16u); | ||||
| 		if (g) { | ||||
| 			h ^= g >> 16u; | ||||
| 			h ^= g >> 5u; | ||||
| @@ -85,99 +89,30 @@ static unsigned _hash(const void *key, unsigned len) | ||||
| 	return h; | ||||
| } | ||||
|  | ||||
| /* In-kernel DM hashing, still lots of collisions */ | ||||
| static unsigned _hash_in_kernel(const char *key, unsigned len) | ||||
| { | ||||
| 	const unsigned char *str = (unsigned char *)key; | ||||
| 	const unsigned hash_mult = 2654435387U; | ||||
| 	unsigned hash = 0, i; | ||||
|  | ||||
| 	for (i = 0; i < len; ++i) | ||||
| 		hash = (hash + str[i]) * hash_mult; | ||||
|  | ||||
| 	return hash; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #undef get16bits | ||||
| #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) | ||||
| #define get16bits(d) (*((const uint16_t *) (d))) | ||||
| #endif | ||||
|  | ||||
| #if !defined (get16bits) | ||||
| #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ | ||||
|                        +(uint32_t)(((const uint8_t *)(d))[0]) ) | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Adapted Bob Jenkins hash to read by 2 bytes if possible. | ||||
|  * https://secure.wikimedia.org/wikipedia/en/wiki/Jenkins_hash_function | ||||
|  * | ||||
|  * Reduces amount of hash collisions | ||||
|  */ | ||||
| static unsigned _hash(const void *key, unsigned len) | ||||
| { | ||||
| 	const uint8_t *str = (uint8_t*) key; | ||||
| 	unsigned hash = 0, i; | ||||
| 	unsigned sz = len / 2; | ||||
|  | ||||
| 	for(i = 0; i < sz; ++i) { | ||||
| 		hash += get16bits(str + 2 * i); | ||||
| 		hash += (hash << 10); | ||||
| 		hash ^= (hash >> 6); | ||||
| 	} | ||||
|  | ||||
| 	if (len & 1) { | ||||
| 		hash += str[len - 1]; | ||||
| 		hash += (hash << 10); | ||||
| 		hash ^= (hash >> 6); | ||||
| 	} | ||||
|  | ||||
| 	hash += (hash << 3); | ||||
| 	hash ^= (hash >> 11); | ||||
| 	hash += (hash << 15); | ||||
|  | ||||
| 	return hash; | ||||
| } | ||||
|  | ||||
| static struct dm_hash_node *_create_node(const void *key, unsigned len) | ||||
| { | ||||
| 	struct dm_hash_node *n = malloc(sizeof(*n) + len); | ||||
|  | ||||
| 	if (n) { | ||||
| 		memcpy(n->key, key, len); | ||||
| 		n->keylen = len; | ||||
| 	} | ||||
|  | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| struct dm_hash_table *dm_hash_create(unsigned size_hint) | ||||
| { | ||||
| 	size_t len; | ||||
| 	unsigned new_size = 16u; | ||||
| 	struct dm_hash_table *hc = zalloc(sizeof(*hc)); | ||||
|  | ||||
| 	if (!hc) { | ||||
| 		log_error("Failed to allocate memory for hash."); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	hc->num_hint = size_hint; | ||||
| 	if (!hc) | ||||
| 		return_0; | ||||
|  | ||||
| 	/* round size hint up to a power of two */ | ||||
| 	while (new_size < size_hint) | ||||
| 		new_size = new_size << 1; | ||||
|  | ||||
| 	hc->mask_slots = new_size - 1; | ||||
| 	hc->num_slots = new_size; | ||||
| 	len = sizeof(*(hc->slots)) * new_size; | ||||
| 	if (!(hc->slots = zalloc(len))) { | ||||
| 		free(hc); | ||||
| 		log_error("Failed to allocate slots for hash."); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (!(hc->slots = zalloc(len))) | ||||
| 		goto_bad; | ||||
|  | ||||
| 	return hc; | ||||
|  | ||||
|       bad: | ||||
| 	free(hc->slots); | ||||
| 	free(hc); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void _free_nodes(struct dm_hash_table *t) | ||||
| @@ -185,16 +120,7 @@ static void _free_nodes(struct dm_hash_table *t) | ||||
| 	struct dm_hash_node *c, *n; | ||||
| 	unsigned i; | ||||
|  | ||||
| #ifdef DEBUG | ||||
| 	log_debug("Free hash hint:%d slots:%d nodes:%d (s:%d f:%d c:%d h:%d)", | ||||
| 		  t->num_hint, t->mask_slots + 1, t->num_nodes, | ||||
| 		  t->search, t->found, t->collisions, t->same_hash); | ||||
| #endif | ||||
|  | ||||
| 	if (!t->num_nodes) | ||||
| 		return; | ||||
|  | ||||
| 	for (i = 0; i <= t->mask_slots; i++) | ||||
| 	for (i = 0; i < t->num_slots; i++) | ||||
| 		for (c = t->slots[i]; c; c = n) { | ||||
| 			n = c->next; | ||||
| 			free(c); | ||||
| @@ -208,30 +134,21 @@ void dm_hash_destroy(struct dm_hash_table *t) | ||||
| 	free(t); | ||||
| } | ||||
|  | ||||
| static struct dm_hash_node **_findh(struct dm_hash_table *t, const void *key, | ||||
| 				    uint32_t len, unsigned hash) | ||||
| { | ||||
| 	struct dm_hash_node **c; | ||||
|  | ||||
| 	++t->search; | ||||
| 	for (c = &t->slots[hash & t->mask_slots]; *c; c = &((*c)->next)) { | ||||
| 		if ((*c)->keylen == len && (*c)->hash == hash) { | ||||
| 			if (!memcmp(key, (*c)->key, len)) { | ||||
| 				++t->found; | ||||
| 				break; | ||||
| 			} | ||||
| 			++t->same_hash; | ||||
| 		} | ||||
| 		++t->collisions; | ||||
| 	} | ||||
|  | ||||
| 	return c; | ||||
| } | ||||
|  | ||||
| static struct dm_hash_node **_find(struct dm_hash_table *t, const void *key, | ||||
| 				   uint32_t len) | ||||
| { | ||||
| 	return _findh(t, key, len, _hash(key, len)); | ||||
| 	unsigned h = _hash(key, len) & (t->num_slots - 1); | ||||
| 	struct dm_hash_node **c; | ||||
|  | ||||
| 	for (c = &t->slots[h]; *c; c = &((*c)->next)) { | ||||
| 		if ((*c)->keylen != len) | ||||
| 			continue; | ||||
|  | ||||
| 		if (!memcmp(key, (*c)->key, len)) | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	return c; | ||||
| } | ||||
|  | ||||
| void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key, | ||||
| @@ -245,8 +162,7 @@ void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key, | ||||
| int dm_hash_insert_binary(struct dm_hash_table *t, const void *key, | ||||
| 			  uint32_t len, void *data) | ||||
| { | ||||
| 	unsigned hash = _hash(key, len); | ||||
| 	struct dm_hash_node **c = _findh(t, key, len, hash); | ||||
| 	struct dm_hash_node **c = _find(t, key, len); | ||||
|  | ||||
| 	if (*c) | ||||
| 		(*c)->data = data; | ||||
| @@ -257,7 +173,6 @@ int dm_hash_insert_binary(struct dm_hash_table *t, const void *key, | ||||
| 			return 0; | ||||
|  | ||||
| 		n->data = data; | ||||
| 		n->hash = hash; | ||||
| 		n->next = 0; | ||||
| 		*c = n; | ||||
| 		t->num_nodes++; | ||||
| @@ -301,7 +216,7 @@ static struct dm_hash_node **_find_str_with_val(struct dm_hash_table *t, | ||||
| 	struct dm_hash_node **c; | ||||
| 	unsigned h; | ||||
|         | ||||
| 	h = _hash(key, len) & t->mask_slots; | ||||
| 	h = _hash(key, len) & (t->num_slots - 1); | ||||
|  | ||||
| 	for (c = &t->slots[h]; *c; c = &((*c)->next)) { | ||||
| 		if ((*c)->keylen != len) | ||||
| @@ -332,7 +247,7 @@ int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key, | ||||
| 	n->data = (void *)val; | ||||
| 	n->data_len = val_len; | ||||
|  | ||||
| 	h = _hash(key, len) & t->mask_slots; | ||||
| 	h = _hash(key, len) & (t->num_slots - 1); | ||||
|  | ||||
| 	first = t->slots[h]; | ||||
|  | ||||
| @@ -400,7 +315,7 @@ void *dm_hash_lookup_with_count(struct dm_hash_table *t, const char *key, int *c | ||||
|  | ||||
| 	*count = 0; | ||||
|  | ||||
| 	h = _hash(key, len) & t->mask_slots; | ||||
| 	h = _hash(key, len) & (t->num_slots - 1); | ||||
|  | ||||
| 	for (c = &t->slots[h]; *c; c = &((*c)->next)) { | ||||
| 		if ((*c)->keylen != len) | ||||
| @@ -429,7 +344,7 @@ void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f) | ||||
| 	struct dm_hash_node *c, *n; | ||||
| 	unsigned i; | ||||
|  | ||||
| 	for (i = 0; i <= t->mask_slots; i++) | ||||
| 	for (i = 0; i < t->num_slots; i++) | ||||
| 		for (c = t->slots[i]; c; c = n) { | ||||
| 			n = c->next; | ||||
| 			f(c->data); | ||||
| @@ -439,8 +354,8 @@ void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f) | ||||
| void dm_hash_wipe(struct dm_hash_table *t) | ||||
| { | ||||
| 	_free_nodes(t); | ||||
| 	memset(t->slots, 0, sizeof(struct dm_hash_node *) * (t->mask_slots + 1)); | ||||
| 	t->num_nodes = t->collisions = t->search = t->same_hash = 0u; | ||||
| 	memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots); | ||||
| 	t->num_nodes = 0u; | ||||
| } | ||||
|  | ||||
| char *dm_hash_get_key(struct dm_hash_table *t __attribute__((unused)), | ||||
| @@ -460,7 +375,7 @@ static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s) | ||||
| 	struct dm_hash_node *c = NULL; | ||||
| 	unsigned i; | ||||
|  | ||||
| 	for (i = s; i <= t->mask_slots && !c; i++) | ||||
| 	for (i = s; i < t->num_slots && !c; i++) | ||||
| 		c = t->slots[i]; | ||||
|  | ||||
| 	return c; | ||||
| @@ -473,5 +388,7 @@ struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t) | ||||
|  | ||||
| struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n) | ||||
| { | ||||
| 	return n->next ? n->next : _next_slot(t, (n->hash & t->mask_slots) + 1); | ||||
| 	unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1); | ||||
|  | ||||
| 	return n->next ? n->next : _next_slot(t, h + 1); | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| #ifndef BASE_DATA_STRUCT_LIST_H | ||||
| #define BASE_DATA_STRUCT_LIST_H | ||||
|  | ||||
| #include "base/memory/container_of.h" | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| /* | ||||
| @@ -100,7 +98,7 @@ struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *e | ||||
|  * contained in a structure of type t, return the containing structure. | ||||
|  */ | ||||
| #define dm_list_struct_base(v, t, head) \ | ||||
|     container_of(v, t, head) | ||||
|     ((t *)((const char *)(v) - (const char *)&((t *) 0)->head)) | ||||
|  | ||||
| /* | ||||
|  * Given the address v of an instance of 'struct dm_list list' contained in | ||||
| @@ -113,7 +111,7 @@ struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *e | ||||
|  * return another element f. | ||||
|  */ | ||||
| #define dm_struct_field(v, t, e, f) \ | ||||
|     (((t *)((uintptr_t)(v) - offsetof(t, e)))->f) | ||||
|     (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f) | ||||
|  | ||||
| /* | ||||
|  * Given the address v of a known element e in a known structure of type t, | ||||
|   | ||||
| @@ -47,7 +47,7 @@ struct value_chain { | ||||
| struct prefix_chain { | ||||
| 	struct value child; | ||||
| 	unsigned len; | ||||
| 	uint8_t prefix[]; | ||||
| 	uint8_t prefix[0]; | ||||
| }; | ||||
|  | ||||
| struct node4 { | ||||
| @@ -1032,7 +1032,7 @@ void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, | ||||
| { | ||||
| 	struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke); | ||||
| 	if (lr.kb == ke || _prefix_chain_matches(&lr, ke)) | ||||
| 		(void) _iterate(lr.v, it); | ||||
|         	_iterate(lr.v, it); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| // Copyright (C) 2018 - 2020 Red Hat, Inc. All rights reserved. | ||||
| // Copyright (C) 2018 Red Hat, Inc. All rights reserved. | ||||
| //  | ||||
| // This file is part of LVM2. | ||||
| // | ||||
| @@ -13,12 +13,10 @@ | ||||
| #ifndef BASE_MEMORY_CONTAINER_OF_H | ||||
| #define BASE_MEMORY_CONTAINER_OF_H | ||||
|  | ||||
| #include <stddef.h>  // offsetof | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| #define container_of(v, t, head) \ | ||||
|     ((t *)((char *)(v) - offsetof(t, head))) | ||||
|     ((t *)((const char *)(v) - (const char *)&((t *) 0)->head)) | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -28,13 +28,13 @@ local { | ||||
| 	# main configuration file, e.g. lvm.conf. When used, it must be set to | ||||
| 	# a unique value among all hosts sharing access to the storage, | ||||
| 	# e.g. a host name. | ||||
| 	# | ||||
| 	#  | ||||
| 	# Example | ||||
| 	# Set no system ID: | ||||
| 	# system_id = "" | ||||
| 	# Set the system_id to a specific name: | ||||
| 	# system_id = "host1" | ||||
| 	# | ||||
| 	#  | ||||
| 	# This configuration option has an automatic default value. | ||||
| 	# system_id = "" | ||||
|  | ||||
|   | ||||
							
								
								
									
										509
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										509
									
								
								configure.ac
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -46,7 +46,6 @@ const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile | ||||
| 	return "STRING"; | ||||
| } | ||||
|  | ||||
| /* | ||||
| struct logical_volume *origin_from_cow(const struct logical_volume *lv) | ||||
| { | ||||
| 	if (lv) | ||||
| @@ -54,7 +53,6 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv) | ||||
|  | ||||
| 	__coverity_panic__(); | ||||
| } | ||||
| */ | ||||
|  | ||||
| /* simple_memccpy() from glibc */ | ||||
| void *memccpy(void *dest, const void *src, int c, size_t n) | ||||
|   | ||||
| @@ -22,9 +22,6 @@ SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c | ||||
|  | ||||
| TARGETS = cmirrord | ||||
|  | ||||
| CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) | ||||
| CFLOW_TARGET := $(TARGETS) | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| LMLIBS += $(CPG_LIBS) | ||||
| @@ -36,8 +33,6 @@ cmirrord: $(OBJECTS) | ||||
| 	$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \ | ||||
| 		$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS) | ||||
|  | ||||
| install_cluster: $(TARGETS) | ||||
| install: $(TARGETS) | ||||
| 	@echo "    [INSTALL] $<" | ||||
| 	$(Q) $(INSTALL_PROGRAM) -D $< $(usrsbindir)/$(<F) | ||||
|  | ||||
| install: install_cluster | ||||
| 	$(Q) $(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord | ||||
|   | ||||
| @@ -245,7 +245,6 @@ static void daemonize(void) | ||||
| 	} | ||||
|  | ||||
| 	LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON); | ||||
| 	/* coverity[leaked_handle] devnull cannot leak here */ | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -108,7 +108,7 @@ static SaVersionT version = { 'B', 1, 1 }; | ||||
| #endif | ||||
|  | ||||
| #define DEBUGGING_HISTORY 100 | ||||
| #define DEBUGGING_BUFLEN 270 | ||||
| #define DEBUGGING_BUFLEN 128 | ||||
| #define LOG_SPRINT(cc, f, arg...) do {				\ | ||||
| 		cc->idx++;					\ | ||||
| 		cc->idx = cc->idx % DEBUGGING_HISTORY;		\ | ||||
| @@ -1383,7 +1383,7 @@ static void cpg_leave_callback(struct clog_cpg *match, | ||||
| 			       size_t member_list_entries) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	int j, fd = -1; | ||||
| 	int j, fd; | ||||
| 	uint32_t lowest = match->lowest_id; | ||||
| 	struct clog_request *rq, *n; | ||||
| 	struct checkpoint_data *p_cp, *c_cp; | ||||
| @@ -1548,7 +1548,7 @@ static void cpg_config_callback(cpg_handle_t handle, const struct cpg_name *gnam | ||||
| 				   member_list, member_list_entries); | ||||
| } | ||||
|  | ||||
| static cpg_callbacks_t cpg_callbacks = { | ||||
| cpg_callbacks_t cpg_callbacks = { | ||||
| 	.cpg_deliver_fn = cpg_message_callback, | ||||
| 	.cpg_confchg_fn = cpg_config_callback, | ||||
| }; | ||||
|   | ||||
| @@ -12,8 +12,8 @@ | ||||
| #ifndef _LVM_CLOG_CLUSTER_H | ||||
| #define _LVM_CLOG_CLUSTER_H | ||||
|  | ||||
| #include "libdm/libdevmapper.h" | ||||
| #include "libdm/misc/dm-log-userspace.h" | ||||
| #include "libdm/libdevmapper.h" | ||||
|  | ||||
| #define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */ | ||||
| #define DM_ULOG_CHECKPOINT_READY 21 | ||||
| @@ -39,7 +39,7 @@ struct clog_request { | ||||
| 	 * machine.  If the two are equal, there is no need | ||||
| 	 * to do endian conversions. | ||||
| 	 */ | ||||
| 	union version_u { | ||||
| 	union { | ||||
| 		uint64_t version[2]; /* LE version and native version */ | ||||
| 		struct dm_list list; | ||||
| 	} u; | ||||
|   | ||||
| @@ -34,7 +34,7 @@ | ||||
| #define LOG_OFFSET 2 | ||||
|  | ||||
| #define RESYNC_HISTORY 50 | ||||
| #define RESYNC_BUFLEN 270 | ||||
| #define RESYNC_BUFLEN 128 | ||||
| //static char resync_history[RESYNC_HISTORY][128]; | ||||
| //static int idx = 0; | ||||
| #define LOG_SPRINT(_lc, f, arg...) do {					\ | ||||
| @@ -378,7 +378,7 @@ static int _clog_ctr(char *uuid, uint64_t luid, | ||||
| 	uint32_t block_on_error = 0; | ||||
|  | ||||
| 	int disk_log; | ||||
| 	char disk_path[PATH_MAX] = { 0 }; | ||||
| 	char disk_path[PATH_MAX]; | ||||
| 	int unlink_path = 0; | ||||
| 	long page_size; | ||||
| 	int pages; | ||||
| @@ -658,7 +658,8 @@ static int clog_dtr(struct dm_ulog_request *rq) | ||||
| 	if (lc->disk_fd != -1 && close(lc->disk_fd)) | ||||
| 		LOG_ERROR("Failed to close disk log: %s", | ||||
| 			  strerror(errno)); | ||||
| 	free(lc->disk_buffer); | ||||
| 	if (lc->disk_buffer) | ||||
| 		free(lc->disk_buffer); | ||||
| 	free(lc->clean_bits); | ||||
| 	free(lc->sync_bits); | ||||
| 	free(lc); | ||||
|   | ||||
| @@ -12,8 +12,7 @@ | ||||
| #ifndef _LVM_CLOG_FUNCTIONS_H | ||||
| #define _LVM_CLOG_FUNCTIONS_H | ||||
|  | ||||
| #include "libdm/libdevmapper.h" | ||||
| #include "libdm/misc/dm-log-userspace.h" | ||||
| #include "device_mapper/misc/dm-log-userspace.h" | ||||
| #include "cluster.h" | ||||
|  | ||||
| #define LOG_RESUMED   1 | ||||
|   | ||||
| @@ -14,21 +14,11 @@ | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| abs_srcdir = @abs_srcdir@ | ||||
|  | ||||
| SOURCES = libdevmapper-event.c | ||||
| SOURCES2 = dmeventd.c | ||||
|  | ||||
| TARGETS = dmeventd | ||||
| CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES) $(SOURCES2) \ | ||||
| 	plugins/lvm2/dmeventd_lvm.c \ | ||||
| 	plugins/mirror/dmeventd_mirror.c \ | ||||
| 	plugins/raid/dmeventd_raid.c \ | ||||
| 	plugins/snapshot/dmeventd_snapshot.c \ | ||||
| 	plugins/thin/dmeventd_thin.c \ | ||||
| 	plugins/vdo/dmeventd_vdo.c \ | ||||
| 	) | ||||
| CFLOW_TARGET := $(TARGETS) | ||||
|  | ||||
| .PHONY: install_lib_dynamic install_lib_static install_include \ | ||||
| 	install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \ | ||||
| @@ -47,7 +37,6 @@ endif | ||||
|  | ||||
| LIB_VERSION = $(LIB_VERSION_DM) | ||||
| LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) | ||||
| LIBS = $(PTHREAD_LIBS) -L$(interfacebuilddir) -ldevmapper | ||||
|  | ||||
| CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a | ||||
|  | ||||
| @@ -57,6 +46,7 @@ endif | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
| CFLOW_TARGET = dmeventd | ||||
|  | ||||
| EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h | ||||
| EXPORTED_FN_PREFIX = dm_event | ||||
| @@ -65,26 +55,34 @@ include $(top_builddir)/make.tmpl | ||||
|  | ||||
| all: device-mapper | ||||
| device-mapper: $(TARGETS) | ||||
| plugins.device-mapper: $(LIB_SHARED) | ||||
|  | ||||
| CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS) | ||||
| LIBS += $(PTHREAD_LIBS) -L$(top_builddir)/libdm -ldevmapper | ||||
|  | ||||
| dmeventd: $(LIB_SHARED) dmeventd.o | ||||
| 	@echo "    [CC] $@" | ||||
| 	$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \ | ||||
| 		-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) | ||||
| 	$(Q) $(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \ | ||||
| 		-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) -lm | ||||
|  | ||||
| dmeventd.static: $(LIB_STATIC) dmeventd.o | ||||
| 	@echo "    [CC] $@" | ||||
| 	$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static dmeventd.o \ | ||||
| 	$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \ | ||||
| 		-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS) | ||||
|  | ||||
| ifeq ("@PKGCONFIG@", "yes") | ||||
|   INSTALL_LIB_TARGETS += install_pkgconfig | ||||
| endif | ||||
|  | ||||
| ifneq ("$(CFLOW_CMD)", "") | ||||
| CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) | ||||
| -include $(top_builddir)/lib/liblvm-internal.cflow | ||||
| -include $(top_builddir)/lib/liblvm2cmd.cflow | ||||
| -include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow | ||||
| -include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow | ||||
| endif | ||||
|  | ||||
| install_include: $(srcdir)/libdevmapper-event.h | ||||
| 	@echo "    [INSTALL] $(<F)" | ||||
| 	@echo "    [INSTALL] $<" | ||||
| 	$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F) | ||||
|  | ||||
| install_pkgconfig: libdevmapper-event.pc | ||||
|   | ||||
| @@ -678,9 +678,6 @@ static int _get_status(struct message_data *message_data) | ||||
| 	char **buffers; | ||||
| 	char *message; | ||||
|  | ||||
| 	if (!message_data->id) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	_lock_mutex(); | ||||
| 	count = dm_list_size(&_thread_registry); | ||||
| 	buffers = alloca(sizeof(char*) * count); | ||||
| @@ -755,7 +752,7 @@ static void _exit_timeout(void *unused __attribute__((unused))) | ||||
| static void *_timeout_thread(void *unused __attribute__((unused))) | ||||
| { | ||||
| 	struct thread_status *thread; | ||||
| 	struct timespec timeout, real_time; | ||||
| 	struct timespec timeout; | ||||
| 	time_t curr_time; | ||||
| 	int ret; | ||||
|  | ||||
| @@ -766,16 +763,7 @@ static void *_timeout_thread(void *unused __attribute__((unused))) | ||||
| 	while (!dm_list_empty(&_timeout_registry)) { | ||||
| 		timeout.tv_sec = 0; | ||||
| 		timeout.tv_nsec = 0; | ||||
| #ifndef HAVE_REALTIME | ||||
| 		curr_time = time(NULL); | ||||
| #else | ||||
| 		if (clock_gettime(CLOCK_REALTIME, &real_time)) { | ||||
| 			log_error("Failed to read clock_gettime()."); | ||||
| 			break; | ||||
| 		} | ||||
| 		/* 10ms back to the future */ | ||||
| 		curr_time = real_time.tv_sec + ((real_time.tv_nsec > (1000000000 - 10000000)) ? 1 : 0); | ||||
| #endif | ||||
|  | ||||
| 		dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) { | ||||
| 			if (thread->next_time <= curr_time) { | ||||
| @@ -1075,7 +1063,6 @@ out: | ||||
| 	 * "label at end of compound statement" */ | ||||
| 	; | ||||
|  | ||||
| 	/* coverity[lock_order] _global_mutex is kept locked */ | ||||
| 	pthread_cleanup_pop(1); | ||||
|  | ||||
| 	return NULL; | ||||
| @@ -1498,34 +1485,37 @@ static int _client_read(struct dm_event_fifos *fifos, | ||||
| 		t.tv_usec = 0; | ||||
| 		ret = select(fifos->client + 1, &fds, NULL, NULL, &t); | ||||
|  | ||||
| 		if (!ret && bytes) | ||||
| 			continue; /* trying to finish read */ | ||||
| 		if (!ret && !bytes)	/* nothing to read */ | ||||
| 			return 0; | ||||
|  | ||||
| 		if (ret <= 0)	/* nothing to read */ | ||||
| 			goto bad; | ||||
| 		if (!ret)	/* trying to finish read */ | ||||
| 			continue; | ||||
|  | ||||
| 		if (ret < 0)	/* error */ | ||||
| 			return 0; | ||||
|  | ||||
| 		ret = read(fifos->client, buf + bytes, size - bytes); | ||||
| 		bytes += ret > 0 ? ret : 0; | ||||
| 		if (!msg->data && (bytes == 2 * sizeof(uint32_t))) { | ||||
| 		if (header && (bytes == 2 * sizeof(uint32_t))) { | ||||
| 			msg->cmd = ntohl(header[0]); | ||||
| 			size = msg->size = ntohl(header[1]); | ||||
| 			bytes = 0; | ||||
|  | ||||
| 			if (!(size = msg->size = ntohl(header[1]))) | ||||
| 				break; | ||||
|  | ||||
| 			if (!(buf = msg->data = malloc(msg->size))) | ||||
| 				goto bad; | ||||
| 			if (!size) | ||||
| 				break; /* No data -> error */ | ||||
| 			buf = msg->data = malloc(msg->size); | ||||
| 			if (!buf) | ||||
| 				break; /* No mem -> error */ | ||||
| 			header = 0; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (bytes == size) | ||||
| 		return 1; | ||||
| 	if (bytes != size) { | ||||
| 		free(msg->data); | ||||
| 		msg->data = NULL; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| bad: | ||||
| 	free(msg->data); | ||||
| 	msg->data = NULL; | ||||
|  | ||||
| 	return 0; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -1746,8 +1736,7 @@ static void _init_thread_signals(void) | ||||
| 	sigset_t my_sigset; | ||||
| 	struct sigaction act = { .sa_handler = _sig_alarm }; | ||||
|  | ||||
| 	if (sigaction(SIGALRM, &act, NULL)) | ||||
| 		log_sys_debug("sigaction", "SIGLARM"); | ||||
| 	sigaction(SIGALRM, &act, NULL); | ||||
| 	sigfillset(&my_sigset); | ||||
|  | ||||
| 	/* These are used for exiting */ | ||||
| @@ -1756,8 +1745,7 @@ static void _init_thread_signals(void) | ||||
| 	sigdelset(&my_sigset, SIGHUP); | ||||
| 	sigdelset(&my_sigset, SIGQUIT); | ||||
|  | ||||
| 	if (pthread_sigmask(SIG_BLOCK, &my_sigset, NULL)) | ||||
| 		log_sys_error("pthread_sigmask", "SIG_BLOCK"); | ||||
| 	pthread_sigmask(SIG_BLOCK, &my_sigset, NULL); | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -2033,8 +2021,8 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos) | ||||
| static void _restart_dmeventd(void) | ||||
| { | ||||
| 	struct dm_event_fifos fifos = { | ||||
| 		.client = -1, | ||||
| 		.server = -1, | ||||
| 		.client = -1, | ||||
| 		/* FIXME Make these either configurable or depend directly on dmeventd_path */ | ||||
| 		.client_path = DM_EVENT_FIFO_CLIENT, | ||||
| 		.server_path = DM_EVENT_FIFO_SERVER | ||||
| @@ -2073,7 +2061,7 @@ static void _restart_dmeventd(void) | ||||
| 			++count; | ||||
| 		} | ||||
|  | ||||
| 	if (!(_initial_registrations = zalloc(sizeof(char*) * (count + 1)))) { | ||||
| 	if (!(_initial_registrations = malloc(sizeof(char*) * (count + 1)))) { | ||||
| 		fprintf(stderr, "Memory allocation registration failed.\n"); | ||||
| 		goto bad; | ||||
| 	} | ||||
| @@ -2085,6 +2073,7 @@ static void _restart_dmeventd(void) | ||||
| 		} | ||||
| 		message += strlen(message) + 1; | ||||
| 	} | ||||
| 	_initial_registrations[count] = NULL; | ||||
|  | ||||
| 	if (version >= 2) { | ||||
| 		if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) { | ||||
| @@ -2247,8 +2236,7 @@ int main(int argc, char *argv[]) | ||||
|  | ||||
| 	_init_thread_signals(); | ||||
|  | ||||
| 	if (pthread_mutex_init(&_global_mutex, NULL)) | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	pthread_mutex_init(&_global_mutex, NULL); | ||||
|  | ||||
| 	if (!_systemd_activation && !_open_fifos(&fifos)) | ||||
| 		exit(EXIT_FIFO_FAILURE); | ||||
|   | ||||
| @@ -237,16 +237,16 @@ static int _daemon_read(struct dm_event_fifos *fifos, | ||||
| 			ret = select(fifos->server + 1, &fds, NULL, NULL, &tval); | ||||
| 			if (ret < 0 && errno != EINTR) { | ||||
| 				log_error("Unable to read from event server."); | ||||
| 				goto bad; | ||||
| 				return 0; | ||||
| 			} | ||||
| 			if ((ret == 0) && (i > 4) && !bytes) { | ||||
| 				log_error("No input from event server."); | ||||
| 				goto bad; | ||||
| 				return 0; | ||||
| 			} | ||||
| 		} | ||||
| 		if (ret < 1) { | ||||
| 			log_error("Unable to read from event server."); | ||||
| 			goto bad; | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		ret = read(fifos->server, buf + bytes, size); | ||||
| @@ -255,32 +255,25 @@ static int _daemon_read(struct dm_event_fifos *fifos, | ||||
| 				continue; | ||||
|  | ||||
| 			log_error("Unable to read from event server."); | ||||
| 			goto bad; | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		bytes += ret; | ||||
| 		if (!msg->data && (bytes == 2 * sizeof(uint32_t))) { | ||||
| 		if (header && (bytes == 2 * sizeof(uint32_t))) { | ||||
| 			msg->cmd = ntohl(header[0]); | ||||
| 			msg->size = ntohl(header[1]); | ||||
| 			buf = msg->data = malloc(msg->size); | ||||
| 			size = msg->size; | ||||
| 			bytes = 0; | ||||
|  | ||||
| 			if (!(size = msg->size = ntohl(header[1]))) | ||||
| 				break; | ||||
|  | ||||
| 			if (!(buf = msg->data = malloc(msg->size))) { | ||||
| 				log_error("Unable to allocate message data."); | ||||
| 				return 0; | ||||
| 			} | ||||
| 			header = 0; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (bytes == size) | ||||
| 		return 1; | ||||
|  | ||||
| bad: | ||||
| 	free(msg->data); | ||||
| 	msg->data = NULL; | ||||
|  | ||||
| 	return 0; | ||||
| 	if (bytes != size) { | ||||
| 		free(msg->data); | ||||
| 		msg->data = NULL; | ||||
| 	} | ||||
| 	return bytes == size; | ||||
| } | ||||
|  | ||||
| /* Write message to daemon. */ | ||||
| @@ -615,8 +608,8 @@ static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_messag | ||||
| { | ||||
| 	int ret; | ||||
| 	struct dm_event_fifos fifos = { | ||||
| 		.client = -1, | ||||
| 		.server = -1, | ||||
| 		.client = -1, | ||||
| 		/* FIXME Make these either configurable or depend directly on dmeventd_path */ | ||||
| 		.client_path = DM_EVENT_FIFO_CLIENT, | ||||
| 		.server_path = DM_EVENT_FIFO_SERVER | ||||
| @@ -709,11 +702,15 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh) | ||||
| static char *_fetch_string(char **src, const int delimiter) | ||||
| { | ||||
| 	char *p, *ret; | ||||
| 	size_t len = (p = strchr(*src, delimiter)) ? | ||||
| 		(size_t)(p - *src) : strlen(*src); | ||||
|  | ||||
| 	if ((ret = strndup(*src, len))) | ||||
| 		*src += len + 1; | ||||
| 	if ((p = strchr(*src, delimiter))) | ||||
| 		*p = 0; | ||||
|  | ||||
| 	if ((ret = strdup(*src))) | ||||
| 		*src += strlen(ret) + 1; | ||||
|  | ||||
| 	if (p) | ||||
| 		*p = delimiter; | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|   | ||||
| @@ -71,7 +71,7 @@ int dmeventd_lvm2_init(void) | ||||
| 	if (!_lvm_handle) { | ||||
| 		lvm2_log_fn(_lvm2_print_log); | ||||
|  | ||||
| 		if (!(_lvm_handle = lvm2_init_threaded())) | ||||
| 		if (!(_lvm_handle = lvm2_init())) | ||||
| 			goto out; | ||||
|  | ||||
| 		/* | ||||
|   | ||||
| @@ -25,6 +25,9 @@ LIB_NAME = libdevmapper-event-lvm2mirror | ||||
| LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| install_lvm2: install_dm_plugin | ||||
|   | ||||
| @@ -24,6 +24,9 @@ LIB_NAME = libdevmapper-event-lvm2raid | ||||
| LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| install_lvm2: install_dm_plugin | ||||
|   | ||||
| @@ -77,18 +77,11 @@ static int _process_raid_event(struct dso_state *state, char *params, const char | ||||
|  | ||||
| 	if (dead) { | ||||
| 		/* | ||||
| 		 * Use the first event to run a repair ignoring any additional ones. | ||||
| 		 * Use the first event to run a repair ignoring any additonal ones. | ||||
| 		 * | ||||
| 		 * We presume lvconvert to do pre-repair | ||||
| 		 * checks to avoid bloat in this plugin. | ||||
| 		 */ | ||||
| 		if (!state->warned && status->insync_regions < status->total_regions) { | ||||
| 			state->warned = 1; | ||||
| 			log_warn("WARNING: waiting for resynchronization to finish " | ||||
| 				 "before initiating repair on RAID device %s.", device); | ||||
| 			/* Fall through to allow lvconvert to run. */ | ||||
| 		} | ||||
|  | ||||
| 		if (state->failed) | ||||
| 			goto out; /* already reported */ | ||||
|  | ||||
|   | ||||
| @@ -24,6 +24,9 @@ LIB_NAME = libdevmapper-event-lvm2thin | ||||
| LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| install_lvm2: install_dm_plugin | ||||
|   | ||||
| @@ -24,6 +24,9 @@ LIB_NAME = libdevmapper-event-lvm2vdo | ||||
| LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| install_lvm2: install_dm_plugin | ||||
|   | ||||
| @@ -16,13 +16,7 @@ | ||||
| #include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h" | ||||
| #include "daemons/dmeventd/libdevmapper-event.h" | ||||
|  | ||||
| /* | ||||
|  * Use parser from new device_mapper library. | ||||
|  * Although during compilation we can see dm_vdo_status_parse() | ||||
|  * in runtime we are linked agains systems libdm 'older' library | ||||
|  * which does not provide this symbol and plugin fails to load | ||||
|  */ | ||||
| /* coverity[unnecessary_header] used for parsing */ | ||||
| /* Use parser from new device_mapper library */ | ||||
| #include "device_mapper/vdo/status.c" | ||||
|  | ||||
| #include <sys/wait.h> | ||||
|   | ||||
| @@ -15,8 +15,7 @@ srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
|  | ||||
| lvmdbuspydir = $(python3dir)/lvmdbusd | ||||
| lvmdbusdir = $(DESTDIR)$(lvmdbuspydir) | ||||
| lvmdbusdir = $(python3dir)/lvmdbusd | ||||
|  | ||||
| LVMDBUS_SRCDIR_FILES = \ | ||||
| 	automatedproperties.py \ | ||||
| @@ -54,16 +53,16 @@ include $(top_builddir)/make.tmpl | ||||
| all: | ||||
| 	$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD) | ||||
|  | ||||
| install_lvmdbusd: $(LVMDBUSD) | ||||
| install_lvmdbusd: | ||||
| 	@echo "    [INSTALL] $<" | ||||
| 	$(Q) $(INSTALL_DIR) $(sbindir) | ||||
| 	$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir) | ||||
| 	$(Q) $(INSTALL_DIR) $(lvmdbusdir) | ||||
| 	$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(lvmdbusdir)) | ||||
| 	$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(lvmdbusdir) | ||||
| 	$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbuspydir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES) | ||||
| 	$(Q) $(CHMOD) 755 $(lvmdbusdir)/__pycache__ | ||||
| 	$(Q) $(CHMOD) 444 $(lvmdbusdir)/__pycache__/*.py[co] | ||||
| 	$(Q) $(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir) | ||||
| 	$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir)) | ||||
| 	$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir) | ||||
| 	$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES) | ||||
| 	$(Q) $(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__ | ||||
| 	$(Q) $(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co] | ||||
|  | ||||
| install_lvm2: install_lvmdbusd | ||||
|  | ||||
|   | ||||
| @@ -157,15 +157,14 @@ class AutomatedProperties(dbus.service.Object): | ||||
| 		if not self._ap_search_method: | ||||
| 			return 0 | ||||
|  | ||||
| 		search = self.lvm_id | ||||
| 		if search_key: | ||||
| 			search = search_key | ||||
|  | ||||
| 		# Either we have the new object state or we need to go fetch it | ||||
| 		if object_state: | ||||
| 			new_state = object_state | ||||
| 		else: | ||||
| 			if search_key: | ||||
| 				search = search_key | ||||
| 			else: | ||||
| 				search = self.lvm_id | ||||
|  | ||||
| 			new_state = self._ap_search_method([search])[0] | ||||
| 			assert isinstance(new_state, State) | ||||
|  | ||||
|   | ||||
| @@ -9,14 +9,13 @@ | ||||
|  | ||||
| import subprocess | ||||
| from . import cfg | ||||
| from .cmdhandler import options_to_cli_args, LvmExecutionMeta, call_lvm | ||||
| from .cmdhandler import options_to_cli_args, LvmExecutionMeta | ||||
| import dbus | ||||
| from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug,\ | ||||
| 					mt_async_call | ||||
| from .request import RequestEntry | ||||
| 	add_no_notify | ||||
| import os | ||||
| import threading | ||||
| import time | ||||
| import traceback | ||||
|  | ||||
|  | ||||
| def pv_move_lv_cmd(move_options, lv_full_name, | ||||
| @@ -40,50 +39,58 @@ def lv_merge_cmd(merge_options, lv_full_name): | ||||
| 	return cmd | ||||
|  | ||||
|  | ||||
| def _load_wrapper(ignored): | ||||
| 	cfg.load() | ||||
|  | ||||
|  | ||||
| def _move_callback(job_state, line_str): | ||||
| 	try: | ||||
| 		if line_str.count(':') == 2: | ||||
| 			(device, ignore, percentage) = line_str.split(':') | ||||
|  | ||||
| 			job_state.Percent = int(round( | ||||
| 				float(percentage.strip()[:-1]), 1)) | ||||
|  | ||||
| 			# While the move is in progress we need to periodically update | ||||
| 			# the state to reflect where everything is at.  we will do this | ||||
| 			# by scheduling the load to occur in the main work queue. | ||||
| 			r = RequestEntry( | ||||
| 				-1, _load_wrapper, ("_move_callback: load",), None, None, False) | ||||
| 			cfg.worker_q.put(r) | ||||
| 	except ValueError: | ||||
| 		log_error("Trying to parse percentage which failed for %s" % line_str) | ||||
|  | ||||
|  | ||||
| def _move_merge(interface_name, command, job_state): | ||||
| 	# We need to execute these command stand alone by forking & exec'ing | ||||
| 	# the command always as we will be getting periodic output from them on | ||||
| 	# the status of the long running operation. | ||||
| 	command.insert(0, cfg.LVM_CMD) | ||||
|  | ||||
| 	# 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) | ||||
|  | ||||
| 	ec, stdout, stderr = call_lvm(command, line_cb=_move_callback, | ||||
| 									cb_data=job_state) | ||||
| 	process = subprocess.Popen(command, stdout=subprocess.PIPE, | ||||
| 								env=os.environ, | ||||
| 								stderr=subprocess.PIPE, close_fds=True) | ||||
|  | ||||
| 	log_debug("Background process for %s is %d" % | ||||
| 				(str(command), process.pid)) | ||||
|  | ||||
| 	lines_iterator = iter(process.stdout.readline, b"") | ||||
| 	for line in lines_iterator: | ||||
| 		line_str = line.decode("utf-8") | ||||
|  | ||||
| 		# Check to see if the line has the correct number of separators | ||||
| 		try: | ||||
| 			if line_str.count(':') == 2: | ||||
| 				(device, ignore, percentage) = line_str.split(':') | ||||
| 				job_state.Percent = round( | ||||
| 					float(percentage.strip()[:-1]), 1) | ||||
|  | ||||
| 				# While the move is in progress we need to periodically update | ||||
| 				# the state to reflect where everything is at. | ||||
| 				cfg.load() | ||||
| 		except ValueError: | ||||
| 			log_error("Trying to parse percentage which failed for %s" % | ||||
| 				line_str) | ||||
|  | ||||
| 	out = process.communicate() | ||||
|  | ||||
| 	with meta.lock: | ||||
| 		meta.ended = time.time() | ||||
| 		meta.ec = ec | ||||
| 		meta.stderr_txt = stderr | ||||
| 		meta.ec = process.returncode | ||||
| 		meta.stderr_txt = out[1] | ||||
|  | ||||
| 	if ec == 0: | ||||
| 	if process.returncode == 0: | ||||
| 		job_state.Percent = 100 | ||||
| 	else: | ||||
| 		raise dbus.exceptions.DBusException( | ||||
| 			interface_name, | ||||
| 			'Exit code %s, stderr = %s' % (str(ec), stderr)) | ||||
| 			'Exit code %s, stderr = %s' % (str(process.returncode), out[1])) | ||||
|  | ||||
| 	cfg.load() | ||||
| 	return '/' | ||||
|   | ||||
| @@ -47,11 +47,9 @@ BUS_NAME = os.getenv('LVM_DBUS_NAME', 'com.redhat.lvmdbus1') | ||||
| BASE_INTERFACE = 'com.redhat.lvmdbus1' | ||||
| PV_INTERFACE = BASE_INTERFACE + '.Pv' | ||||
| VG_INTERFACE = BASE_INTERFACE + '.Vg' | ||||
| VG_VDO_INTERFACE = BASE_INTERFACE + '.VgVdo' | ||||
| LV_INTERFACE = BASE_INTERFACE + '.Lv' | ||||
| LV_COMMON_INTERFACE = BASE_INTERFACE + '.LvCommon' | ||||
| THIN_POOL_INTERFACE = BASE_INTERFACE + '.ThinPool' | ||||
| VDO_POOL_INTERFACE = BASE_INTERFACE + '.VdoPool' | ||||
| CACHE_POOL_INTERFACE = BASE_INTERFACE + '.CachePool' | ||||
| LV_CACHED = BASE_INTERFACE + '.CachedLv' | ||||
| SNAPSHOT_INTERFACE = BASE_INTERFACE + '.Snapshot' | ||||
| @@ -63,7 +61,6 @@ PV_OBJ_PATH = BASE_OBJ_PATH + '/Pv' | ||||
| VG_OBJ_PATH = BASE_OBJ_PATH + '/Vg' | ||||
| LV_OBJ_PATH = BASE_OBJ_PATH + '/Lv' | ||||
| THIN_POOL_PATH = BASE_OBJ_PATH + "/ThinPool" | ||||
| VDO_POOL_PATH = BASE_OBJ_PATH + "/VdoPool" | ||||
| CACHE_POOL_PATH = BASE_OBJ_PATH + "/CachePool" | ||||
| HIDDEN_LV_PATH = BASE_OBJ_PATH + "/HiddenLv" | ||||
| MANAGER_OBJ_PATH = BASE_OBJ_PATH + '/Manager' | ||||
| @@ -74,7 +71,6 @@ pv_id = itertools.count() | ||||
| vg_id = itertools.count() | ||||
| lv_id = itertools.count() | ||||
| thin_id = itertools.count() | ||||
| vdo_id = itertools.count() | ||||
| cache_pool_id = itertools.count() | ||||
| job_id = itertools.count() | ||||
| hidden_lv = itertools.count() | ||||
| @@ -83,9 +79,6 @@ hidden_lv = itertools.count() | ||||
| load = None | ||||
| event = None | ||||
|  | ||||
| # Boolean to denote if lvm supports VDO integration | ||||
| vdo_support = False | ||||
|  | ||||
| # Global cached state | ||||
| db = None | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,6 @@ | ||||
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| from subprocess import Popen, PIPE | ||||
| import select | ||||
| import time | ||||
| import threading | ||||
| from itertools import chain | ||||
| @@ -17,8 +16,7 @@ import traceback | ||||
| import os | ||||
|  | ||||
| from lvmdbusd import cfg | ||||
| from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify,\ | ||||
| 							make_non_block, read_decoded | ||||
| from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify | ||||
| from lvmdbusd.lvm_shell_proxy import LVMShellProxy | ||||
|  | ||||
| try: | ||||
| @@ -84,23 +82,16 @@ def _debug_c(cmd, exit_code, out): | ||||
| 	log_error(("STDERR=\n %s\n" % out[1])) | ||||
|  | ||||
|  | ||||
| def call_lvm(command, debug=False, line_cb=None, | ||||
| 			 cb_data=None): | ||||
| def call_lvm(command, debug=False): | ||||
| 	""" | ||||
| 	Call an executable and return a tuple of exitcode, stdout, stderr | ||||
| 	:param command: Command to execute | ||||
| 	:param debug:   Dump debug to stdout | ||||
| 	:param line_cb:	Call the supplied function for each line read from | ||||
| 					stdin, CALL MUST EXECUTE QUICKLY and not *block* | ||||
| 					otherwise call_lvm function will fail to read | ||||
| 					stdin/stdout.  Return value of call back is ignored | ||||
| 	:param cb_data: Supplied to callback to allow caller access to | ||||
| 								its own data | ||||
|  | ||||
| 	# Callback signature | ||||
| 	def my_callback(my_context, line_read_stdin) | ||||
| 		pass | ||||
| 	:param command:     Command to execute | ||||
| 	:param debug:       Dump debug to stdout | ||||
| 	""" | ||||
| 	# print 'STACK:' | ||||
| 	# for line in traceback.format_stack(): | ||||
| 	#    print line.strip() | ||||
|  | ||||
| 	# Prepend the full lvm executable so that we can run different versions | ||||
| 	# in different locations on the same box | ||||
| 	command.insert(0, cfg.LVM_CMD) | ||||
| @@ -108,44 +99,10 @@ def call_lvm(command, debug=False, line_cb=None, | ||||
|  | ||||
| 	process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True, | ||||
| 					env=os.environ) | ||||
| 	out = process.communicate() | ||||
|  | ||||
| 	stdout_text = "" | ||||
| 	stderr_text = "" | ||||
| 	stdout_index = 0 | ||||
| 	make_non_block(process.stdout) | ||||
| 	make_non_block(process.stderr) | ||||
|  | ||||
| 	while True: | ||||
| 		try: | ||||
| 			rd_fd = [process.stdout.fileno(), process.stderr.fileno()] | ||||
| 			ready = select.select(rd_fd, [], [], 2) | ||||
|  | ||||
| 			for r in ready[0]: | ||||
| 				if r == process.stdout.fileno(): | ||||
| 					stdout_text += read_decoded(process.stdout) | ||||
| 				elif r == process.stderr.fileno(): | ||||
| 					stderr_text += read_decoded(process.stderr) | ||||
|  | ||||
| 			if line_cb is not None: | ||||
| 				# Process the callback for each line read! | ||||
| 				while True: | ||||
| 					i = stdout_text.find("\n", stdout_index) | ||||
| 					if i != -1: | ||||
| 						try: | ||||
| 							line_cb(cb_data, stdout_text[stdout_index:i]) | ||||
| 						except: | ||||
| 							st = traceback.format_exc() | ||||
| 							log_error("call_lvm: line_cb exception: \n %s" % st) | ||||
| 						stdout_index = i + 1 | ||||
| 					else: | ||||
| 						break | ||||
|  | ||||
| 			# Check to see if process has terminated, None when running | ||||
| 			if process.poll() is not None: | ||||
| 				break | ||||
| 		except IOError as ioe: | ||||
| 			log_debug("call_lvm:" + str(ioe)) | ||||
| 			pass | ||||
| 	stdout_text = bytes(out[0]).decode("utf-8") | ||||
| 	stderr_text = bytes(out[1]).decode("utf-8") | ||||
|  | ||||
| 	if debug or process.returncode != 0: | ||||
| 		_debug_c(command, process.returncode, (stdout_text, stderr_text)) | ||||
| @@ -431,24 +388,6 @@ def vg_create_thin_pool(md_full_name, data_full_name, create_options): | ||||
| 	return call(cmd) | ||||
|  | ||||
|  | ||||
| def vg_create_vdo_pool_lv_and_lv(vg_name, pool_name, lv_name, data_size, | ||||
| 									virtual_size, create_options): | ||||
| 	cmd = ['lvcreate'] | ||||
| 	cmd.extend(options_to_cli_args(create_options)) | ||||
| 	cmd.extend(['-y', '--type', 'vdo', '-n', lv_name, | ||||
| 				'-L', '%dB' % data_size, '-V', '%dB' % virtual_size, | ||||
| 				"%s/%s" % (vg_name, pool_name)]) | ||||
| 	return call(cmd) | ||||
|  | ||||
|  | ||||
| def vg_create_vdo_pool(pool_full_name, lv_name, virtual_size, create_options): | ||||
| 	cmd = ['lvconvert'] | ||||
| 	cmd.extend(options_to_cli_args(create_options)) | ||||
| 	cmd.extend(['--type', 'vdo-pool', '-n', lv_name, '--force', '-y', | ||||
| 				'-V', '%dB' % virtual_size, pool_full_name]) | ||||
| 	return call(cmd) | ||||
|  | ||||
|  | ||||
| def lv_remove(lv_path, remove_options): | ||||
| 	cmd = ['lvremove'] | ||||
| 	cmd.extend(options_to_cli_args(remove_options)) | ||||
| @@ -496,15 +435,6 @@ def lv_cache_lv(cache_pool_full_name, lv_full_name, cache_options): | ||||
| 	return call(cmd) | ||||
|  | ||||
|  | ||||
| def lv_writecache_lv(cache_lv_full_name, lv_full_name, cache_options): | ||||
| 	# lvconvert --type writecache --cachevol VG/CacheLV VG/OriginLV | ||||
| 	cmd = ['lvconvert'] | ||||
| 	cmd.extend(options_to_cli_args(cache_options)) | ||||
| 	cmd.extend(['-y', '--type', 'writecache', '--cachevol', | ||||
| 				cache_lv_full_name, lv_full_name]) | ||||
| 	return call(cmd) | ||||
|  | ||||
|  | ||||
| def lv_detach_cache(lv_full_name, detach_options, destroy_cache): | ||||
| 	cmd = ['lvconvert'] | ||||
| 	if destroy_cache: | ||||
| @@ -520,28 +450,6 @@ def lv_detach_cache(lv_full_name, detach_options, destroy_cache): | ||||
| 	return call(cmd) | ||||
|  | ||||
|  | ||||
| def lv_vdo_compression(lv_path, enable, comp_options): | ||||
| 	cmd = ['lvchange', '--compression'] | ||||
| 	if enable: | ||||
| 		cmd.append('y') | ||||
| 	else: | ||||
| 		cmd.append('n') | ||||
| 	cmd.extend(options_to_cli_args(comp_options)) | ||||
| 	cmd.append(lv_path) | ||||
| 	return call(cmd) | ||||
|  | ||||
|  | ||||
| def lv_vdo_deduplication(lv_path, enable, dedup_options): | ||||
| 	cmd = ['lvchange', '--deduplication'] | ||||
| 	if enable: | ||||
| 		cmd.append('y') | ||||
| 	else: | ||||
| 		cmd.append('n') | ||||
| 	cmd.extend(options_to_cli_args(dedup_options)) | ||||
| 	cmd.append(lv_path) | ||||
| 	return call(cmd) | ||||
|  | ||||
|  | ||||
| def supports_json(): | ||||
| 	cmd = ['help'] | ||||
| 	rc, out, err = call(cmd) | ||||
| @@ -554,16 +462,6 @@ def supports_json(): | ||||
| 	return False | ||||
|  | ||||
|  | ||||
| def supports_vdo(): | ||||
| 	cmd = ['segtypes'] | ||||
| 	rc, out, err = call(cmd) | ||||
| 	if rc == 0: | ||||
| 		if "vdo" in out: | ||||
| 			log_debug("We have VDO support") | ||||
| 			return True | ||||
| 	return False | ||||
|  | ||||
|  | ||||
| def lvm_full_report_json(): | ||||
| 	pv_columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free', | ||||
| 					'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free', | ||||
| @@ -591,22 +489,6 @@ def lvm_full_report_json(): | ||||
|  | ||||
| 	lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid'] | ||||
|  | ||||
| 	if cfg.vdo_support: | ||||
| 		lv_columns.extend( | ||||
| 			['vdo_operating_mode', 'vdo_compression_state', 'vdo_index_state', | ||||
| 				'vdo_used_size', 'vdo_saving_percent'] | ||||
| 		) | ||||
|  | ||||
| 		lv_seg_columns.extend( | ||||
| 			['vdo_compression', 'vdo_deduplication', | ||||
| 				'vdo_use_metadata_hints', 'vdo_minimum_io_size', | ||||
| 				'vdo_block_map_cache_size', 'vdo_block_map_era_length', | ||||
| 				'vdo_use_sparse_index', 'vdo_index_memory_size', | ||||
| 				'vdo_slab_size', 'vdo_ack_threads', 'vdo_bio_threads', | ||||
| 				'vdo_bio_rotation', 'vdo_cpu_threads', 'vdo_hash_zone_threads', | ||||
| 				'vdo_logical_threads', 'vdo_physical_threads', | ||||
| 				'vdo_max_discard', 'vdo_write_policy', 'vdo_header_size']) | ||||
|  | ||||
| 	cmd = _dc('fullreport', [ | ||||
| 		'-a',		# Need hidden too | ||||
| 		'--configreport', 'pv', '-o', ','.join(pv_columns), | ||||
| @@ -627,13 +509,7 @@ def lvm_full_report_json(): | ||||
| 			assert(type(out) == dict) | ||||
| 			return out | ||||
| 		else: | ||||
| 			try: | ||||
| 				return json.loads(out) | ||||
| 			except json.decoder.JSONDecodeError as joe: | ||||
| 				log_error("JSONDecodeError %s, \n JSON=\n%s\n" % | ||||
| 							(str(joe), out)) | ||||
| 				raise joe | ||||
|  | ||||
| 			return json.loads(out) | ||||
| 	return None | ||||
|  | ||||
|  | ||||
| @@ -826,7 +702,6 @@ def activate_deactivate(op, name, activate, control_flags, options): | ||||
| 		op += 'n' | ||||
|  | ||||
| 	cmd.append(op) | ||||
| 	cmd.append("-y") | ||||
| 	cmd.append(name) | ||||
| 	return call(cmd) | ||||
|  | ||||
|   | ||||
| @@ -20,55 +20,19 @@ import traceback | ||||
|  | ||||
| def _main_thread_load(refresh=True, emit_signal=True): | ||||
| 	num_total_changes = 0 | ||||
| 	to_remove = [] | ||||
|  | ||||
| 	(changes, remove) = load_pvs( | ||||
| 	num_total_changes += load_pvs( | ||||
| 		refresh=refresh, | ||||
| 		emit_signal=emit_signal, | ||||
| 		cache_refresh=False)[1:] | ||||
| 	num_total_changes += changes | ||||
| 	to_remove.extend(remove) | ||||
|  | ||||
| 	(changes, remove) = load_vgs( | ||||
| 		cache_refresh=False)[1] | ||||
| 	num_total_changes += load_vgs( | ||||
| 		refresh=refresh, | ||||
| 		emit_signal=emit_signal, | ||||
| 		cache_refresh=False)[1:] | ||||
|  | ||||
| 	num_total_changes += changes | ||||
| 	to_remove.extend(remove) | ||||
|  | ||||
| 	(lv_changes, remove) = load_lvs( | ||||
| 		cache_refresh=False)[1] | ||||
| 	num_total_changes += load_lvs( | ||||
| 		refresh=refresh, | ||||
| 		emit_signal=emit_signal, | ||||
| 		cache_refresh=False)[1:] | ||||
|  | ||||
| 	num_total_changes += lv_changes | ||||
| 	to_remove.extend(remove) | ||||
|  | ||||
| 	# When the LVs change it can cause another change in the VGs which is | ||||
| 	# missed if we don't scan through the VGs again.  We could achieve this | ||||
| 	# the other way and re-scan the LVs, but in general there are more LVs than | ||||
| 	# VGs, thus this should be more efficient.  This happens when a LV interface | ||||
| 	# changes causing the dbus object representing it to be removed and | ||||
| 	# recreated. | ||||
| 	if refresh and lv_changes > 0: | ||||
| 		(changes, remove) = load_vgs( | ||||
| 			refresh=refresh, | ||||
| 			emit_signal=emit_signal, | ||||
| 			cache_refresh=False)[1:] | ||||
|  | ||||
| 	num_total_changes += changes | ||||
| 	to_remove.extend(remove) | ||||
|  | ||||
| 	# Remove any objects that are no longer needed.  We do this after we process | ||||
| 	# all the objects to ensure that references still exist for objects that | ||||
| 	# are processed after them. | ||||
| 	to_remove.reverse() | ||||
| 	for i in to_remove: | ||||
| 		dbus_obj = cfg.om.get_object_by_path(i) | ||||
| 		if dbus_obj: | ||||
| 			cfg.om.remove_object(dbus_obj, True) | ||||
| 			num_total_changes += 1 | ||||
| 		cache_refresh=False)[1] | ||||
|  | ||||
| 	return num_total_changes | ||||
|  | ||||
|   | ||||
| @@ -75,10 +75,11 @@ def common(retrieve, o_type, search_keys, | ||||
|  | ||||
| 		object_path = None | ||||
|  | ||||
| 	to_remove = [] | ||||
| 	if refresh: | ||||
| 		to_remove = list(existing_paths.keys()) | ||||
| 		for k in list(existing_paths.keys()): | ||||
| 			cfg.om.remove_object(cfg.om.get_object_by_path(k), True) | ||||
| 			num_changes += 1 | ||||
|  | ||||
| 	num_changes += len(rc) | ||||
|  | ||||
| 	return rc, num_changes, to_remove | ||||
| 	return rc, num_changes | ||||
|   | ||||
| @@ -10,14 +10,14 @@ | ||||
| from .automatedproperties import AutomatedProperties | ||||
|  | ||||
| from . import utils | ||||
| from .utils import vg_obj_path_generate, log_error, _handle_execute | ||||
| from .utils import vg_obj_path_generate, log_error | ||||
| import dbus | ||||
| from . import cmdhandler | ||||
| from . import cfg | ||||
| from .cfg import LV_INTERFACE, THIN_POOL_INTERFACE, SNAPSHOT_INTERFACE, \ | ||||
| 	LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED, VDO_POOL_INTERFACE | ||||
| 	LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED | ||||
| from .request import RequestEntry | ||||
| from .utils import n, n32, d | ||||
| from .utils import n, n32 | ||||
| from .loader import common | ||||
| from .state import State | ||||
| from . import background | ||||
| @@ -74,66 +74,23 @@ def lvs_state_retrieve(selection, cache_refresh=True): | ||||
| 	lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key) | ||||
|  | ||||
| 	for l in lvs: | ||||
| 		if cfg.vdo_support: | ||||
| 			rc.append(LvStateVdo( | ||||
| 				l['lv_uuid'], l['lv_name'], | ||||
| 				l['lv_path'], n(l['lv_size']), | ||||
| 				l['vg_name'], | ||||
| 				l['vg_uuid'], l['pool_lv_uuid'], | ||||
| 				l['pool_lv'], l['origin_uuid'], l['origin'], | ||||
| 				n32(l['data_percent']), l['lv_attr'], | ||||
| 				l['lv_tags'], l['lv_active'], l['data_lv'], | ||||
| 				l['metadata_lv'], l['segtype'], l['lv_role'], | ||||
| 				l['lv_layout'], | ||||
| 				n32(l['snap_percent']), | ||||
| 				n32(l['metadata_percent']), | ||||
| 				n32(l['copy_percent']), | ||||
| 				n32(l['sync_percent']), | ||||
| 				n(l['lv_metadata_size']), | ||||
| 				l['move_pv'], | ||||
| 				l['move_pv_uuid'], | ||||
| 				l['vdo_operating_mode'], | ||||
| 				l['vdo_compression_state'], | ||||
| 				l['vdo_index_state'], | ||||
| 				n(l['vdo_used_size']), | ||||
| 				d(l['vdo_saving_percent']), | ||||
| 				l['vdo_compression'], | ||||
| 				l['vdo_deduplication'], | ||||
| 				l['vdo_use_metadata_hints'], | ||||
| 				n32(l['vdo_minimum_io_size']), | ||||
| 				n(l['vdo_block_map_cache_size']), | ||||
| 				n32(l['vdo_block_map_era_length']), | ||||
| 				l['vdo_use_sparse_index'], | ||||
| 				n(l['vdo_index_memory_size']), | ||||
| 				n(l['vdo_slab_size']), | ||||
| 				n32(l['vdo_ack_threads']), | ||||
| 				n32(l['vdo_bio_threads']), | ||||
| 				n32(l['vdo_bio_rotation']), | ||||
| 				n32(l['vdo_cpu_threads']), | ||||
| 				n32(l['vdo_hash_zone_threads']), | ||||
| 				n32(l['vdo_logical_threads']), | ||||
| 				n32(l['vdo_physical_threads']), | ||||
| 				n32(l['vdo_max_discard']), | ||||
| 				l['vdo_write_policy'], | ||||
| 				n32(l['vdo_header_size']))) | ||||
| 		else: | ||||
| 			rc.append(LvState( | ||||
| 				l['lv_uuid'], l['lv_name'], | ||||
| 				l['lv_path'], n(l['lv_size']), | ||||
| 				l['vg_name'], | ||||
| 				l['vg_uuid'], l['pool_lv_uuid'], | ||||
| 				l['pool_lv'], l['origin_uuid'], l['origin'], | ||||
| 				n32(l['data_percent']), l['lv_attr'], | ||||
| 				l['lv_tags'], l['lv_active'], l['data_lv'], | ||||
| 				l['metadata_lv'], l['segtype'], l['lv_role'], | ||||
| 				l['lv_layout'], | ||||
| 				n32(l['snap_percent']), | ||||
| 				n32(l['metadata_percent']), | ||||
| 				n32(l['copy_percent']), | ||||
| 				n32(l['sync_percent']), | ||||
| 				n(l['lv_metadata_size']), | ||||
| 				l['move_pv'], | ||||
| 				l['move_pv_uuid'])) | ||||
| 		rc.append(LvState( | ||||
| 			l['lv_uuid'], l['lv_name'], | ||||
| 			l['lv_path'], n(l['lv_size']), | ||||
| 			l['vg_name'], | ||||
| 			l['vg_uuid'], l['pool_lv_uuid'], | ||||
| 			l['pool_lv'], l['origin_uuid'], l['origin'], | ||||
| 			n32(l['data_percent']), l['lv_attr'], | ||||
| 			l['lv_tags'], l['lv_active'], l['data_lv'], | ||||
| 			l['metadata_lv'], l['segtype'], l['lv_role'], | ||||
| 			l['lv_layout'], | ||||
| 			n32(l['snap_percent']), | ||||
| 			n32(l['metadata_percent']), | ||||
| 			n32(l['copy_percent']), | ||||
| 			n32(l['sync_percent']), | ||||
| 			n(l['lv_metadata_size']), | ||||
| 			l['move_pv'], | ||||
| 			l['move_pv_uuid'])) | ||||
| 	return rc | ||||
|  | ||||
|  | ||||
| @@ -237,8 +194,6 @@ class LvState(State): | ||||
| 	def _object_type_create(self): | ||||
| 		if self.Attr[0] == 't': | ||||
| 			return LvThinPool | ||||
| 		elif self.Attr[0] == 'd': | ||||
| 			return LvVdoPool | ||||
| 		elif self.Attr[0] == 'C': | ||||
| 			if 'pool' in self.layout: | ||||
| 				return LvCachePool | ||||
| @@ -265,34 +220,6 @@ class LvState(State): | ||||
| 		return (klass, path_method) | ||||
|  | ||||
|  | ||||
| class LvStateVdo(LvState): | ||||
|  | ||||
| 	def __init__(self, Uuid, Name, Path, SizeBytes, | ||||
| 					vg_name, vg_uuid, pool_lv_uuid, PoolLv, | ||||
| 					origin_uuid, OriginLv, DataPercent, Attr, Tags, active, | ||||
| 					data_lv, metadata_lv, segtypes, role, layout, SnapPercent, | ||||
| 					MetaDataPercent, CopyPercent, SyncPercent, | ||||
| 					MetaDataSizeBytes, move_pv, move_pv_uuid, | ||||
| 					vdo_operating_mode, vdo_compression_state, vdo_index_state, | ||||
| 					vdo_used_size,vdo_saving_percent,vdo_compression, | ||||
| 					vdo_deduplication,vdo_use_metadata_hints, | ||||
| 					vdo_minimum_io_size,vdo_block_map_cache_size, | ||||
| 					vdo_block_map_era_length,vdo_use_sparse_index, | ||||
| 					vdo_index_memory_size,vdo_slab_size,vdo_ack_threads, | ||||
| 					vdo_bio_threads,vdo_bio_rotation,vdo_cpu_threads, | ||||
| 					vdo_hash_zone_threads,vdo_logical_threads, | ||||
| 					vdo_physical_threads,vdo_max_discard, | ||||
| 					vdo_write_policy,vdo_header_size): | ||||
| 		super(LvStateVdo, self).__init__(Uuid, Name, Path, SizeBytes, | ||||
| 					vg_name, vg_uuid, pool_lv_uuid, PoolLv, | ||||
| 					origin_uuid, OriginLv, DataPercent, Attr, Tags, active, | ||||
| 					data_lv, metadata_lv, segtypes, role, layout, SnapPercent, | ||||
| 					MetaDataPercent, CopyPercent, SyncPercent, | ||||
| 					MetaDataSizeBytes, move_pv, move_pv_uuid) | ||||
|  | ||||
| 		utils.init_class_from_arguments(self, "vdo_", snake_to_pascal=True) | ||||
|  | ||||
|  | ||||
| # noinspection PyPep8Naming | ||||
| @utils.dbus_property(LV_COMMON_INTERFACE, 'Uuid', 's') | ||||
| @utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's') | ||||
| @@ -348,7 +275,13 @@ class LvCommon(AutomatedProperties): | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def handle_execute(rc, out, err): | ||||
| 		_handle_execute(rc, out, err, LV_INTERFACE) | ||||
| 		if rc == 0: | ||||
| 			cfg.load() | ||||
| 		else: | ||||
| 			# Need to work on error handling, need consistent | ||||
| 			raise dbus.exceptions.DBusException( | ||||
| 				LV_INTERFACE, | ||||
| 				'Exit code %s, stderr = %s' % (str(rc), err)) | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def validate_dbus_object(lv_uuid, lv_name): | ||||
| @@ -388,7 +321,6 @@ class LvCommon(AutomatedProperties): | ||||
| 					'l': 'mirror log device', 'c': 'under conversion', | ||||
| 					'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data', | ||||
| 					'e': 'raid or pool metadata or pool metadata spare', | ||||
| 					'd': 'vdo pool', 'D': 'vdo pool data', 'g': 'integrity', | ||||
| 					'-': 'Unspecified'} | ||||
| 		return self.attr_struct(0, type_map) | ||||
|  | ||||
| @@ -524,7 +456,8 @@ class Lv(LvCommon): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		LvCommon.validate_dbus_object(lv_uuid, lv_name) | ||||
| 		# Remove the LV, if successful then remove from the model | ||||
| 		LvCommon.handle_execute(*cmdhandler.lv_remove(lv_name, remove_options)) | ||||
| 		rc, out, err = cmdhandler.lv_remove(lv_name, remove_options) | ||||
| 		LvCommon.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -544,8 +477,9 @@ class Lv(LvCommon): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		LvCommon.validate_dbus_object(lv_uuid, lv_name) | ||||
| 		# Rename the logical volume | ||||
| 		LvCommon.handle_execute(*cmdhandler.lv_rename(lv_name, new_name, | ||||
| 												rename_options)) | ||||
| 		rc, out, err = cmdhandler.lv_rename(lv_name, new_name, | ||||
| 											rename_options) | ||||
| 		LvCommon.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -594,11 +528,13 @@ class Lv(LvCommon): | ||||
| 				remainder = space % 512 | ||||
| 				optional_size = space + 512 - remainder | ||||
|  | ||||
| 		LvCommon.handle_execute(*cmdhandler.vg_lv_snapshot( | ||||
| 			lv_name, snapshot_options,name, optional_size)) | ||||
| 		rc, out, err = cmdhandler.vg_lv_snapshot( | ||||
| 			lv_name, snapshot_options, name, optional_size) | ||||
| 		LvCommon.handle_execute(rc, out, err) | ||||
| 		full_name = "%s/%s" % (dbo.vg_name_lookup(), name) | ||||
| 		return cfg.om.get_object_path_by_lvm_id(full_name) | ||||
|  | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| 		dbus_interface=LV_INTERFACE, | ||||
| 		in_signature='stia{sv}', | ||||
| @@ -634,8 +570,9 @@ class Lv(LvCommon): | ||||
| 				pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2])) | ||||
|  | ||||
| 		size_change = new_size_bytes - dbo.SizeBytes | ||||
| 		LvCommon.handle_execute(*cmdhandler.lv_resize( | ||||
| 			dbo.lvm_id, size_change,pv_dests, resize_options)) | ||||
| 		rc, out, err = cmdhandler.lv_resize(dbo.lvm_id, size_change, | ||||
| 											pv_dests, resize_options) | ||||
| 		LvCommon.handle_execute(rc, out, err) | ||||
| 		return "/" | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -670,8 +607,9 @@ class Lv(LvCommon): | ||||
| 								options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		LvCommon.validate_dbus_object(uuid, lv_name) | ||||
| 		LvCommon.handle_execute(*cmdhandler.activate_deactivate( | ||||
| 			'lvchange', lv_name, activate, control_flags, options)) | ||||
| 		rc, out, err = cmdhandler.activate_deactivate( | ||||
| 			'lvchange', lv_name, activate, control_flags, options) | ||||
| 		LvCommon.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -705,8 +643,9 @@ class Lv(LvCommon): | ||||
| 	def _add_rm_tags(uuid, lv_name, tags_add, tags_del, tag_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		LvCommon.validate_dbus_object(uuid, lv_name) | ||||
| 		LvCommon.handle_execute(*cmdhandler.lv_tag( | ||||
| 			lv_name, tags_add, tags_del, tag_options)) | ||||
| 		rc, out, err = cmdhandler.lv_tag( | ||||
| 			lv_name, tags_add, tags_del, tag_options) | ||||
| 		LvCommon.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -743,152 +682,6 @@ class Lv(LvCommon): | ||||
| 			cb, cbe, return_tuple=False) | ||||
| 		cfg.worker_q.put(r) | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def _writecache_lv(lv_uuid, lv_name, lv_object_path, cache_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name) | ||||
|  | ||||
| 		# Make sure we have dbus object representing lv to cache | ||||
| 		lv_to_cache = cfg.om.get_object_by_path(lv_object_path) | ||||
|  | ||||
| 		if lv_to_cache: | ||||
| 			fcn = lv_to_cache.lv_full_name() | ||||
| 			rc, out, err = cmdhandler.lv_writecache_lv( | ||||
| 				dbo.lv_full_name(), fcn, cache_options) | ||||
| 			if rc == 0: | ||||
| 				# When we cache an LV, the cache pool and the lv that is getting | ||||
| 				# cached need to be removed from the object manager and | ||||
| 				# re-created as their interfaces have changed! | ||||
| 				mt_remove_dbus_objects((dbo, lv_to_cache)) | ||||
| 				cfg.load() | ||||
|  | ||||
| 				lv_converted = cfg.om.get_object_path_by_lvm_id(fcn) | ||||
| 			else: | ||||
| 				raise dbus.exceptions.DBusException( | ||||
| 					LV_INTERFACE, | ||||
| 					'Exit code %s, stderr = %s' % (str(rc), err)) | ||||
| 		else: | ||||
| 			raise dbus.exceptions.DBusException( | ||||
| 				LV_INTERFACE, 'LV to cache with object path %s not present!' % | ||||
| 				lv_object_path) | ||||
| 		return lv_converted | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| 		dbus_interface=LV_INTERFACE, | ||||
| 		in_signature='oia{sv}', | ||||
| 		out_signature='(oo)', | ||||
| 		async_callbacks=('cb', 'cbe')) | ||||
| 	def WriteCacheLv(self, lv_object, tmo, cache_options, cb, cbe): | ||||
| 		r = RequestEntry( | ||||
| 			tmo, Lv._writecache_lv, | ||||
| 			(self.Uuid, self.lvm_id, lv_object, | ||||
| 			cache_options), cb, cbe) | ||||
| 		cfg.worker_q.put(r) | ||||
|  | ||||
|  | ||||
| # noinspection PyPep8Naming | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'OperatingMode', 's') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'CompressionState', 's') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'IndexState', 's') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'UsedSize', 't') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'SavingPercent', 'd') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'Compression', 's') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'Deduplication', 's') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'UseMetadataHints', 's') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'MinimumIoSize', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'BlockMapCacheSize', "t") | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'BlockMapEraLength', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'UseSparseIndex', 's') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'IndexMemorySize', 't') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'SlabSize', 't') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'AckThreads', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'BioThreads', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'BioRotation', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'CpuThreads', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'HashZoneThreads', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'LogicalThreads', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'PhysicalThreads', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'MaxDiscard', 'u') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'WritePolicy', 's') | ||||
| @utils.dbus_property(VDO_POOL_INTERFACE, 'HeaderSize', 'u') | ||||
| class LvVdoPool(Lv): | ||||
| 	_DataLv_meta = ("o", VDO_POOL_INTERFACE) | ||||
|  | ||||
| 	def __init__(self, object_path, object_state): | ||||
| 		super(LvVdoPool, self).__init__(object_path, object_state) | ||||
| 		self.set_interface(VDO_POOL_INTERFACE) | ||||
| 		self._data_lv, _ = self._get_data_meta() | ||||
|  | ||||
| 	@property | ||||
| 	def DataLv(self): | ||||
| 		return dbus.ObjectPath(self._data_lv) | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def _enable_disable_compression(pool_uuid, pool_name, enable, comp_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		LvCommon.validate_dbus_object(pool_uuid, pool_name) | ||||
| 		# Rename the logical volume | ||||
| 		LvCommon.handle_execute(*cmdhandler.lv_vdo_compression( | ||||
| 			pool_name, enable, comp_options)) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| 		dbus_interface=VDO_POOL_INTERFACE, | ||||
| 		in_signature='ia{sv}', | ||||
| 		out_signature='o', | ||||
| 		async_callbacks=('cb', 'cbe')) | ||||
| 	def EnableCompression(self, tmo, comp_options, cb, cbe): | ||||
| 		r = RequestEntry( | ||||
| 			tmo, LvVdoPool._enable_disable_compression, | ||||
| 			(self.Uuid, self.lvm_id, True, comp_options), | ||||
| 			cb, cbe, False) | ||||
| 		cfg.worker_q.put(r) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| 	dbus_interface=VDO_POOL_INTERFACE, | ||||
| 	in_signature='ia{sv}', | ||||
| 	out_signature='o', | ||||
| 	async_callbacks=('cb', 'cbe')) | ||||
| 	def DisableCompression(self, tmo, comp_options, cb, cbe): | ||||
| 		r = RequestEntry( | ||||
| 			tmo, LvVdoPool._enable_disable_compression, | ||||
| 			(self.Uuid, self.lvm_id, False, comp_options), | ||||
| 			cb, cbe, False) | ||||
| 		cfg.worker_q.put(r) | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def _enable_disable_deduplication(pool_uuid, pool_name, enable, dedup_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		LvCommon.validate_dbus_object(pool_uuid, pool_name) | ||||
| 		# Rename the logical volume | ||||
| 		LvCommon.handle_execute(*cmdhandler.lv_vdo_deduplication( | ||||
| 			pool_name, enable, dedup_options)) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| 		dbus_interface=VDO_POOL_INTERFACE, | ||||
| 		in_signature='ia{sv}', | ||||
| 		out_signature='o', | ||||
| 		async_callbacks=('cb', 'cbe')) | ||||
| 	def EnableDeduplication(self, tmo, dedup_options, cb, cbe): | ||||
| 		r = RequestEntry( | ||||
| 			tmo, LvVdoPool._enable_disable_deduplication, | ||||
| 			(self.Uuid, self.lvm_id, True, dedup_options), | ||||
| 			cb, cbe, False) | ||||
| 		cfg.worker_q.put(r) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| 	dbus_interface=VDO_POOL_INTERFACE, | ||||
| 	in_signature='ia{sv}', | ||||
| 	out_signature='o', | ||||
| 	async_callbacks=('cb', 'cbe')) | ||||
| 	def DisableDeduplication(self, tmo, dedup_options, cb, cbe): | ||||
| 		r = RequestEntry( | ||||
| 			tmo, LvVdoPool._enable_disable_deduplication, | ||||
| 			(self.Uuid, self.lvm_id, False, dedup_options), | ||||
| 			cb, cbe, False) | ||||
| 		cfg.worker_q.put(r) | ||||
|  | ||||
|  | ||||
| # noinspection PyPep8Naming | ||||
| class LvThinPool(Lv): | ||||
| @@ -912,8 +705,10 @@ class LvThinPool(Lv): | ||||
| 	def _lv_create(lv_uuid, lv_name, name, size_bytes, create_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name) | ||||
| 		LvCommon.handle_execute(*cmdhandler.lv_lv_create( | ||||
| 			lv_name, create_options, name, size_bytes)) | ||||
|  | ||||
| 		rc, out, err = cmdhandler.lv_lv_create( | ||||
| 			lv_name, create_options, name, size_bytes) | ||||
| 		LvCommon.handle_execute(rc, out, err) | ||||
| 		full_name = "%s/%s" % (dbo.vg_name_lookup(), name) | ||||
| 		return cfg.om.get_object_path_by_lvm_id(full_name) | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
|  | ||||
| import subprocess | ||||
| import shlex | ||||
| from fcntl import fcntl, F_GETFL, F_SETFL | ||||
| import os | ||||
| import traceback | ||||
| import sys | ||||
| @@ -28,8 +29,7 @@ except ImportError: | ||||
|  | ||||
|  | ||||
| from lvmdbusd.cfg import LVM_CMD | ||||
| from lvmdbusd.utils import log_debug, log_error, add_no_notify, make_non_block,\ | ||||
| 							read_decoded | ||||
| from lvmdbusd.utils import log_debug, log_error, add_no_notify | ||||
|  | ||||
| SHELL_PROMPT = "lvm> " | ||||
|  | ||||
| @@ -43,6 +43,13 @@ def _quote_arg(arg): | ||||
|  | ||||
| class LVMShellProxy(object): | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def _read(stream): | ||||
| 		tmp = stream.read() | ||||
| 		if tmp: | ||||
| 			return tmp.decode("utf-8") | ||||
| 		return '' | ||||
|  | ||||
| 	# Read until we get prompt back and a result | ||||
| 	# @param: no_output	Caller expects no output to report FD | ||||
| 	# Returns stdout, report, stderr (report is JSON!) | ||||
| @@ -68,11 +75,11 @@ class LVMShellProxy(object): | ||||
|  | ||||
| 				for r in ready[0]: | ||||
| 					if r == self.lvm_shell.stdout.fileno(): | ||||
| 						stdout += read_decoded(self.lvm_shell.stdout) | ||||
| 						stdout += LVMShellProxy._read(self.lvm_shell.stdout) | ||||
| 					elif r == self.report_stream.fileno(): | ||||
| 						report += read_decoded(self.report_stream) | ||||
| 						report += LVMShellProxy._read(self.report_stream) | ||||
| 					elif r == self.lvm_shell.stderr.fileno(): | ||||
| 						stderr += read_decoded(self.lvm_shell.stderr) | ||||
| 						stderr += LVMShellProxy._read(self.lvm_shell.stderr) | ||||
|  | ||||
| 				# Check to see if the lvm process died on us | ||||
| 				if self.lvm_shell.poll(): | ||||
| @@ -117,6 +124,11 @@ class LVMShellProxy(object): | ||||
| 		assert (num_written == len(cmd_bytes)) | ||||
| 		self.lvm_shell.stdin.flush() | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def _make_non_block(stream): | ||||
| 		flags = fcntl(stream, F_GETFL) | ||||
| 		fcntl(stream, F_SETFL, flags | os.O_NONBLOCK) | ||||
|  | ||||
| 	def __init__(self): | ||||
|  | ||||
| 		# Create a temp directory | ||||
| @@ -150,8 +162,8 @@ class LVMShellProxy(object): | ||||
| 			stderr=subprocess.PIPE, close_fds=True, shell=True) | ||||
|  | ||||
| 		try: | ||||
| 			make_non_block(self.lvm_shell.stdout) | ||||
| 			make_non_block(self.lvm_shell.stderr) | ||||
| 			LVMShellProxy._make_non_block(self.lvm_shell.stdout) | ||||
| 			LVMShellProxy._make_non_block(self.lvm_shell.stderr) | ||||
|  | ||||
| 			# wait for the first prompt | ||||
| 			errors = self._read_until_prompt(no_output=True)[2] | ||||
|   | ||||
| @@ -20,7 +20,7 @@ from lvmdbusd.utils import log_debug, log_error | ||||
|  | ||||
|  | ||||
| class DataStore(object): | ||||
| 	def __init__(self, usejson=True, vdo_support=False): | ||||
| 	def __init__(self, usejson=True): | ||||
| 		self.pvs = {} | ||||
| 		self.vgs = {} | ||||
| 		self.lvs = {} | ||||
| @@ -43,8 +43,6 @@ class DataStore(object): | ||||
| 		else: | ||||
| 			self.json = usejson | ||||
|  | ||||
| 		self.vdo_support = vdo_support | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def _insert_record(table, key, record, allowed_multiple): | ||||
| 		if key in table: | ||||
| @@ -243,7 +241,8 @@ class DataStore(object): | ||||
|  | ||||
| 		return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup) | ||||
|  | ||||
| 	def _parse_lvs_json(self, _all): | ||||
| 	@staticmethod | ||||
| 	def _parse_lvs_json(_all): | ||||
|  | ||||
| 		c_lvs = OrderedDict() | ||||
| 		c_lv_full_lookup = {} | ||||
| @@ -263,13 +262,8 @@ class DataStore(object): | ||||
| 				if 'seg' in r: | ||||
| 					for s in r['seg']: | ||||
| 						r = c_lvs[s['lv_uuid']] | ||||
| 						r.setdefault('seg_pe_ranges', []).\ | ||||
| 							append(s['seg_pe_ranges']) | ||||
| 						r.setdefault('seg_pe_ranges', []).append(s['seg_pe_ranges']) | ||||
| 						r.setdefault('segtype', []).append(s['segtype']) | ||||
| 						if self.vdo_support: | ||||
| 							for seg_key, seg_val in s.items(): | ||||
| 								if seg_key.startswith("vdo_"): | ||||
| 									r[seg_key] = seg_val | ||||
|  | ||||
| 		return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup) | ||||
|  | ||||
|   | ||||
| @@ -29,7 +29,7 @@ from .utils import log_debug, log_error | ||||
| import argparse | ||||
| import os | ||||
| import sys | ||||
| from .cmdhandler import LvmFlightRecorder, supports_vdo | ||||
| from .cmdhandler import LvmFlightRecorder | ||||
| from .request import RequestEntry | ||||
|  | ||||
|  | ||||
| @@ -44,10 +44,10 @@ def process_request(): | ||||
| 		try: | ||||
| 			req = cfg.worker_q.get(True, 5) | ||||
| 			log_debug( | ||||
| 				"Method start: %s with args %s (callback = %s)" % | ||||
| 				(str(req.method), str(req.arguments), str(req.cb))) | ||||
| 				"Running method: %s with args %s" % | ||||
| 				(str(req.method), str(req.arguments))) | ||||
| 			req.run_cmd() | ||||
| 			log_debug("Method complete: %s" % str(req.method)) | ||||
| 			log_debug("Method complete ") | ||||
| 		except queue.Empty: | ||||
| 			pass | ||||
| 		except Exception: | ||||
| @@ -127,14 +127,6 @@ def main(): | ||||
| 		log_error("You cannot specify --lvmshell and --nojson") | ||||
| 		sys.exit(1) | ||||
|  | ||||
| 	# We will dynamically add interfaces which support vdo if it | ||||
| 	# exists. | ||||
| 	cfg.vdo_support = supports_vdo() | ||||
|  | ||||
| 	if cfg.vdo_support and not cfg.args.use_json: | ||||
| 		log_error("You cannot specify --nojson when lvm has VDO support") | ||||
| 		sys.exit(1) | ||||
|  | ||||
| 	# List of threads that we start up | ||||
| 	thread_list = [] | ||||
|  | ||||
| @@ -155,12 +147,12 @@ def main(): | ||||
| 	cfg.om = Lvm(BASE_OBJ_PATH) | ||||
| 	cfg.om.register_object(Manager(MANAGER_OBJ_PATH)) | ||||
|  | ||||
| 	cfg.db = lvmdb.DataStore(cfg.args.use_json, cfg.vdo_support) | ||||
| 	cfg.db = lvmdb.DataStore(cfg.args.use_json) | ||||
|  | ||||
| 	# 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, | ||||
| 										name='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 | ||||
|   | ||||
| @@ -27,7 +27,7 @@ class Manager(AutomatedProperties): | ||||
|  | ||||
| 	@property | ||||
| 	def Version(self): | ||||
| 		return dbus.String('1.1.0') | ||||
| 		return dbus.String('1.0.0') | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def handle_execute(rc, out, err): | ||||
| @@ -107,10 +107,10 @@ class Manager(AutomatedProperties): | ||||
| 		rc = cfg.load(log=False) | ||||
|  | ||||
| 		if rc != 0: | ||||
| 			utils.log_debug('Manager.Refresh - exit %d %d' % (rc, lc), | ||||
| 			utils.log_debug('Manager.Refresh - exit %d' % (rc), | ||||
| 							'bg_black', 'fg_light_red') | ||||
| 		else: | ||||
| 			utils.log_debug('Manager.Refresh - exit %d %d' % (rc, lc)) | ||||
| 			utils.log_debug('Manager.Refresh - exit %d' % (rc)) | ||||
| 		return rc + lc | ||||
|  | ||||
| 	@dbus.service.method( | ||||
|   | ||||
| @@ -14,7 +14,7 @@ import dbus | ||||
| from .cfg import PV_INTERFACE | ||||
| from . import cmdhandler | ||||
| from .utils import vg_obj_path_generate, n, pv_obj_path_generate, \ | ||||
| 	lv_object_path_method, _handle_execute | ||||
| 	lv_object_path_method | ||||
| from .loader import common | ||||
| from .request import RequestEntry | ||||
| from .state import State | ||||
| @@ -138,12 +138,19 @@ class Pv(AutomatedProperties): | ||||
| 		# Remove the PV, if successful then remove from the model | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Pv.validate_dbus_object(pv_uuid, pv_name) | ||||
| 		Pv.handle_execute(*cmdhandler.pv_remove(pv_name, remove_options)) | ||||
| 		rc, out, err = cmdhandler.pv_remove(pv_name, remove_options) | ||||
| 		Pv.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def handle_execute(rc, out, err): | ||||
| 		return _handle_execute(rc, out, err, PV_INTERFACE) | ||||
| 		if rc == 0: | ||||
| 			cfg.load() | ||||
| 		else: | ||||
| 			# Need to work on error handling, need consistent | ||||
| 			raise dbus.exceptions.DBusException( | ||||
| 				PV_INTERFACE, | ||||
| 				'Exit code %s, stderr = %s' % (str(rc), err)) | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def validate_dbus_object(pv_uuid, pv_name): | ||||
| @@ -171,8 +178,10 @@ class Pv(AutomatedProperties): | ||||
| 	def _resize(pv_uuid, pv_name, new_size_bytes, resize_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Pv.validate_dbus_object(pv_uuid, pv_name) | ||||
| 		Pv.handle_execute(*cmdhandler.pv_resize(pv_name, new_size_bytes, | ||||
| 												resize_options)) | ||||
|  | ||||
| 		rc, out, err = cmdhandler.pv_resize(pv_name, new_size_bytes, | ||||
| 												resize_options) | ||||
| 		Pv.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -191,8 +200,9 @@ class Pv(AutomatedProperties): | ||||
| 	def _allocation_enabled(pv_uuid, pv_name, yes_no, allocation_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Pv.validate_dbus_object(pv_uuid, pv_name) | ||||
| 		Pv.handle_execute(*cmdhandler.pv_allocatable(pv_name, yes_no, | ||||
| 														allocation_options)) | ||||
| 		rc, out, err = cmdhandler.pv_allocatable( | ||||
| 			pv_name, yes_no, allocation_options) | ||||
| 		Pv.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
|   | ||||
| @@ -52,8 +52,8 @@ def filter_event(action, device): | ||||
| 	# when appropriate. | ||||
| 	refresh = False | ||||
|  | ||||
| 	if 'ID_FS_TYPE' in device: | ||||
| 		fs_type_new = device['ID_FS_TYPE'] | ||||
| 	if '.ID_FS_TYPE_NEW' in device: | ||||
| 		fs_type_new = device['.ID_FS_TYPE_NEW'] | ||||
|  | ||||
| 		if 'LVM' in fs_type_new: | ||||
| 			refresh = True | ||||
|   | ||||
| @@ -14,7 +14,6 @@ import ctypes | ||||
| import os | ||||
| import string | ||||
| import datetime | ||||
| from fcntl import fcntl, F_GETFL, F_SETFL | ||||
|  | ||||
| import dbus | ||||
| from lvmdbusd import cfg | ||||
| @@ -27,15 +26,6 @@ import signal | ||||
| STDOUT_TTY = os.isatty(sys.stdout.fileno()) | ||||
|  | ||||
|  | ||||
| def _handle_execute(rc, out, err, interface): | ||||
| 	if rc == 0: | ||||
| 		cfg.load() | ||||
| 	else: | ||||
| 		# Need to work on error handling, need consistent | ||||
| 		raise dbus.exceptions.DBusException( | ||||
| 			interface, 'Exit code %s, stderr = %s' % (str(rc), err)) | ||||
|  | ||||
|  | ||||
| def rtype(dbus_type): | ||||
| 	""" | ||||
| 	Decorator making sure that the decorated function returns a value of | ||||
| @@ -67,20 +57,8 @@ def n32(v): | ||||
| 	return int(float(v)) | ||||
|  | ||||
|  | ||||
| @rtype(dbus.Double) | ||||
| def d(v): | ||||
| 	if not v: | ||||
| 		return 0.0 | ||||
| 	return float(v) | ||||
|  | ||||
|  | ||||
| def _snake_to_pascal(s): | ||||
| 	return ''.join(x.title() for x in s.split('_')) | ||||
|  | ||||
|  | ||||
| # noinspection PyProtectedMember | ||||
| def init_class_from_arguments( | ||||
| 		obj_instance, begin_suffix=None, snake_to_pascal=False): | ||||
| def init_class_from_arguments(obj_instance): | ||||
| 	for k, v in list(sys._getframe(1).f_locals.items()): | ||||
| 		if k != 'self': | ||||
| 			nt = k | ||||
| @@ -91,17 +69,8 @@ def init_class_from_arguments( | ||||
| 			cur = getattr(obj_instance, nt, v) | ||||
|  | ||||
| 			# print 'Init class %s = %s' % (nt, str(v)) | ||||
| 			if not (cur and len(str(cur)) and (v is None or len(str(v))) == 0)\ | ||||
| 					and (begin_suffix is None or nt.startswith(begin_suffix)): | ||||
|  | ||||
| 				if begin_suffix and nt.startswith(begin_suffix): | ||||
| 					name = nt[len(begin_suffix):] | ||||
| 					if snake_to_pascal: | ||||
| 						name = _snake_to_pascal(name) | ||||
|  | ||||
| 					setattr(obj_instance, name, v) | ||||
| 				else: | ||||
| 					setattr(obj_instance, nt, v) | ||||
| 			if not (cur and len(str(cur)) and (v is None or len(str(v))) == 0): | ||||
| 				setattr(obj_instance, nt, v) | ||||
|  | ||||
|  | ||||
| def get_properties(f): | ||||
| @@ -369,8 +338,6 @@ def lv_object_path_method(name, meta): | ||||
| 		return _hidden_lv_obj_path_generate | ||||
| 	elif meta[0][0] == 't': | ||||
| 		return _thin_pool_obj_path_generate | ||||
| 	elif meta[0][0] == 'd': | ||||
| 		return _vdo_pool_object_path_generate | ||||
| 	elif meta[0][0] == 'C' and 'pool' in meta[1]: | ||||
| 		return _cache_pool_obj_path_generate | ||||
|  | ||||
| @@ -388,10 +355,6 @@ def _thin_pool_obj_path_generate(): | ||||
| 	return cfg.THIN_POOL_PATH + "/%d" % next(cfg.thin_id) | ||||
|  | ||||
|  | ||||
| def _vdo_pool_object_path_generate(): | ||||
| 	return cfg.VDO_POOL_PATH + "/%d" % next(cfg.vdo_id) | ||||
|  | ||||
|  | ||||
| def _cache_pool_obj_path_generate(): | ||||
| 	return cfg.CACHE_POOL_PATH + "/%d" % next(cfg.cache_pool_id) | ||||
|  | ||||
| @@ -483,7 +446,7 @@ _ALLOWABLE_CH_SET = set(_ALLOWABLE_CH) | ||||
| _ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+' | ||||
| _ALLOWABLE_VG_LV_CH_SET = set(_ALLOWABLE_VG_LV_CH) | ||||
| _LV_NAME_RESERVED = ("_cdata", "_cmeta", "_corig", "_mimage", "_mlog", | ||||
| 	"_pmspare", "_rimage", "_rmeta", "_tdata", "_tmeta", "_vorigin", "_vdata") | ||||
| 	"_pmspare", "_rimage", "_rmeta", "_tdata", "_tmeta", "_vorigin") | ||||
|  | ||||
| # Tags can have the characters, based on the code | ||||
| # a-zA-Z0-9._-+/=!:&# | ||||
| @@ -682,16 +645,3 @@ def _remove_objects(dbus_objects_rm): | ||||
| # Remove dbus objects from main thread | ||||
| def mt_remove_dbus_objects(objs): | ||||
| 	MThreadRunner(_remove_objects, objs).done() | ||||
|  | ||||
|  | ||||
| # Make stream non-blocking | ||||
| def make_non_block(stream): | ||||
| 	flags = fcntl(stream, F_GETFL) | ||||
| 	fcntl(stream, F_SETFL, flags | os.O_NONBLOCK) | ||||
|  | ||||
|  | ||||
| def read_decoded(stream): | ||||
| 	tmp = stream.read() | ||||
| 	if tmp: | ||||
| 		return tmp.decode("utf-8") | ||||
| 	return '' | ||||
|   | ||||
| @@ -10,11 +10,10 @@ | ||||
| from .automatedproperties import AutomatedProperties | ||||
|  | ||||
| from . import utils | ||||
| from .utils import pv_obj_path_generate, vg_obj_path_generate, n, \ | ||||
| 	_handle_execute | ||||
| from .utils import pv_obj_path_generate, vg_obj_path_generate, n | ||||
| import dbus | ||||
| from . import cfg | ||||
| from .cfg import VG_INTERFACE, VG_VDO_INTERFACE | ||||
| from .cfg import VG_INTERFACE | ||||
| from . import cmdhandler | ||||
| from .request import RequestEntry | ||||
| from .loader import common | ||||
| @@ -47,7 +46,7 @@ def vgs_state_retrieve(selection, cache_refresh=True): | ||||
|  | ||||
| def load_vgs(vg_specific=None, object_path=None, refresh=False, | ||||
| 		emit_signal=False, cache_refresh=True): | ||||
| 	return common(vgs_state_retrieve, (Vg, VgVdo, ), vg_specific, object_path, refresh, | ||||
| 	return common(vgs_state_retrieve, (Vg,), vg_specific, object_path, refresh, | ||||
| 					emit_signal, cache_refresh) | ||||
|  | ||||
|  | ||||
| @@ -99,11 +98,7 @@ class VgState(State): | ||||
| 		if not path: | ||||
| 			path = cfg.om.get_object_path_by_uuid_lvm_id( | ||||
| 				self.Uuid, self.internal_name, vg_obj_path_generate) | ||||
|  | ||||
| 		if cfg.vdo_support: | ||||
| 			return VgVdo(path, self) | ||||
| 		else: | ||||
| 			return Vg(path, self) | ||||
| 		return Vg(path, self) | ||||
|  | ||||
| 	# noinspection PyMethodMayBeStatic | ||||
| 	def creation_signature(self): | ||||
| @@ -159,7 +154,13 @@ class Vg(AutomatedProperties): | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def handle_execute(rc, out, err): | ||||
| 		return _handle_execute(rc, out, err, VG_INTERFACE) | ||||
| 		if rc == 0: | ||||
| 			cfg.load() | ||||
| 		else: | ||||
| 			# Need to work on error handling, need consistent | ||||
| 			raise dbus.exceptions.DBusException( | ||||
| 				VG_INTERFACE, | ||||
| 				'Exit code %s, stderr = %s' % (str(rc), err)) | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def validate_dbus_object(vg_uuid, vg_name): | ||||
| @@ -175,8 +176,9 @@ class Vg(AutomatedProperties): | ||||
| 	def _rename(uuid, vg_name, new_name, rename_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*cmdhandler.vg_rename( | ||||
| 			uuid, new_name, rename_options)) | ||||
| 		rc, out, err = cmdhandler.vg_rename( | ||||
| 			uuid, new_name, rename_options) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -195,7 +197,8 @@ class Vg(AutomatedProperties): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		# Remove the VG, if successful then remove from the model | ||||
| 		Vg.handle_execute(*cmdhandler.vg_remove(vg_name, remove_options)) | ||||
| 		rc, out, err = cmdhandler.vg_remove(vg_name, remove_options) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -211,7 +214,8 @@ class Vg(AutomatedProperties): | ||||
| 	@staticmethod | ||||
| 	def _change(uuid, vg_name, change_options): | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*cmdhandler.vg_change(change_options, vg_name)) | ||||
| 		rc, out, err = cmdhandler.vg_change(change_options, vg_name) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	# TODO: This should be broken into a number of different methods | ||||
| @@ -247,8 +251,9 @@ class Vg(AutomatedProperties): | ||||
| 						VG_INTERFACE, | ||||
| 						'PV Object path not found = %s!' % pv_op) | ||||
|  | ||||
| 		Vg.handle_execute(*cmdhandler.vg_reduce( | ||||
| 			vg_name, missing, pv_devices, reduce_options)) | ||||
| 		rc, out, err = cmdhandler.vg_reduce(vg_name, missing, pv_devices, | ||||
| 											reduce_options) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -278,8 +283,9 @@ class Vg(AutomatedProperties): | ||||
| 					VG_INTERFACE, 'PV Object path not found = %s!' % i) | ||||
|  | ||||
| 		if len(extend_devices): | ||||
| 			Vg.handle_execute(*cmdhandler.vg_extend( | ||||
| 				vg_name, extend_devices, extend_options)) | ||||
| 			rc, out, err = cmdhandler.vg_extend(vg_name, extend_devices, | ||||
| 												extend_options) | ||||
| 			Vg.handle_execute(rc, out, err) | ||||
| 		else: | ||||
| 			raise dbus.exceptions.DBusException( | ||||
| 				VG_INTERFACE, 'No pv_object_paths provided!') | ||||
| @@ -333,8 +339,10 @@ class Vg(AutomatedProperties): | ||||
|  | ||||
| 				pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2])) | ||||
|  | ||||
| 		Vg.handle_execute(*cmdhandler.vg_lv_create( | ||||
| 			vg_name, create_options, name, size_bytes, pv_dests)) | ||||
| 		rc, out, err = cmdhandler.vg_lv_create( | ||||
| 			vg_name, create_options, name, size_bytes, pv_dests) | ||||
|  | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return Vg.fetch_new_lv(vg_name, name) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -372,8 +380,11 @@ class Vg(AutomatedProperties): | ||||
| 			thin_pool, create_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*cmdhandler.vg_lv_create_linear( | ||||
| 			vg_name, create_options, name, size_bytes, thin_pool)) | ||||
|  | ||||
| 		rc, out, err = cmdhandler.vg_lv_create_linear( | ||||
| 			vg_name, create_options, name, size_bytes, thin_pool) | ||||
|  | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return Vg.fetch_new_lv(vg_name, name) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -395,9 +406,10 @@ class Vg(AutomatedProperties): | ||||
| 			stripe_size_kb, thin_pool, create_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*cmdhandler.vg_lv_create_striped( | ||||
| 		rc, out, err = cmdhandler.vg_lv_create_striped( | ||||
| 			vg_name, create_options, name, size_bytes, | ||||
| 			num_stripes, stripe_size_kb, thin_pool)) | ||||
| 			num_stripes, stripe_size_kb, thin_pool) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return Vg.fetch_new_lv(vg_name, name) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -422,8 +434,9 @@ class Vg(AutomatedProperties): | ||||
| 			num_copies, create_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*cmdhandler.vg_lv_create_mirror( | ||||
| 			vg_name, create_options, name, size_bytes, num_copies)) | ||||
| 		rc, out, err = cmdhandler.vg_lv_create_mirror( | ||||
| 			vg_name, create_options, name, size_bytes, num_copies) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return Vg.fetch_new_lv(vg_name, name) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -446,9 +459,10 @@ class Vg(AutomatedProperties): | ||||
| 						num_stripes, stripe_size_kb, create_options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*cmdhandler.vg_lv_create_raid( | ||||
| 		rc, out, err = cmdhandler.vg_lv_create_raid( | ||||
| 			vg_name, create_options, name, raid_type, size_bytes, | ||||
| 			num_stripes, stripe_size_kb)) | ||||
| 			num_stripes, stripe_size_kb) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return Vg.fetch_new_lv(vg_name, name) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -546,8 +560,9 @@ class Vg(AutomatedProperties): | ||||
| 				raise dbus.exceptions.DBusException( | ||||
| 					VG_INTERFACE, 'PV object path = %s not found' % p) | ||||
|  | ||||
| 		Vg.handle_execute(*cmdhandler.pv_tag( | ||||
| 			pv_devices, tags_add, tags_del, tag_options)) | ||||
| 		rc, out, err = cmdhandler.pv_tag( | ||||
| 			pv_devices, tags_add, tags_del, tag_options) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -588,8 +603,9 @@ class Vg(AutomatedProperties): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
|  | ||||
| 		Vg.handle_execute(*cmdhandler.vg_tag( | ||||
| 			vg_name, tags_add, tags_del, tag_options)) | ||||
| 		rc, out, err = cmdhandler.vg_tag( | ||||
| 			vg_name, tags_add, tags_del, tag_options) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -628,7 +644,8 @@ class Vg(AutomatedProperties): | ||||
| 	def _vg_change_set(uuid, vg_name, method, value, options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*method(vg_name, value, options)) | ||||
| 		rc, out, err = method(vg_name, value, options) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -688,8 +705,9 @@ class Vg(AutomatedProperties): | ||||
| 								options): | ||||
| 		# Make sure we have a dbus object representing it | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*cmdhandler.activate_deactivate( | ||||
| 			'vgchange', vg_name, activate, control_flags, options)) | ||||
| 		rc, out, err = cmdhandler.activate_deactivate( | ||||
| 			'vgchange', vg_name, activate, control_flags, options) | ||||
| 		Vg.handle_execute(rc, out, err) | ||||
| 		return '/' | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| @@ -777,71 +795,3 @@ class Vg(AutomatedProperties): | ||||
| 	@property | ||||
| 	def Clustered(self): | ||||
| 		return self._attribute(5, 'c') | ||||
|  | ||||
|  | ||||
| class VgVdo(Vg): | ||||
|  | ||||
| 	# noinspection PyUnusedLocal,PyPep8Naming | ||||
| 	def __init__(self, object_path, object_state): | ||||
| 		super(VgVdo, self).__init__(object_path, vgs_state_retrieve) | ||||
| 		self.set_interface(VG_VDO_INTERFACE) | ||||
| 		self._object_path = object_path | ||||
| 		self.state = object_state | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def _lv_vdo_pool_create_with_lv(uuid, vg_name, pool_name, lv_name, | ||||
| 									data_size, virtual_size, create_options): | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
| 		Vg.handle_execute(*cmdhandler.vg_create_vdo_pool_lv_and_lv( | ||||
| 			vg_name, pool_name, lv_name, data_size, virtual_size, | ||||
| 			create_options)) | ||||
| 		return Vg.fetch_new_lv(vg_name, pool_name) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| 		dbus_interface=VG_VDO_INTERFACE, | ||||
| 		in_signature='ssttia{sv}', | ||||
| 		out_signature='(oo)', | ||||
| 		async_callbacks=('cb', 'cbe')) | ||||
| 	def CreateVdoPoolandLv(self, pool_name, lv_name, data_size, virtual_size, | ||||
| 							tmo, create_options, cb, cbe): | ||||
| 		utils.validate_lv_name(VG_VDO_INTERFACE, self.Name, pool_name) | ||||
| 		utils.validate_lv_name(VG_VDO_INTERFACE, self.Name, lv_name) | ||||
|  | ||||
| 		r = RequestEntry(tmo, VgVdo._lv_vdo_pool_create_with_lv, | ||||
| 							(self.state.Uuid, self.state.lvm_id, | ||||
| 							pool_name, lv_name, round_size(data_size), | ||||
| 							round_size(virtual_size), | ||||
| 							create_options), cb, cbe) | ||||
| 		cfg.worker_q.put(r) | ||||
|  | ||||
| 	@staticmethod | ||||
| 	def _vdo_pool_create(uuid, vg_name, pool_lv, name, virtual_size, create_options): | ||||
| 		Vg.validate_dbus_object(uuid, vg_name) | ||||
|  | ||||
| 		# Retrieve the full name of the pool lv | ||||
| 		pool = cfg.om.get_object_by_path(pool_lv) | ||||
| 		if not pool: | ||||
| 			msg = 'LV with object path %s not present!' % \ | ||||
| 					(pool_lv) | ||||
| 			raise dbus.exceptions.DBusException(VG_VDO_INTERFACE, msg) | ||||
|  | ||||
| 		Vg.handle_execute(*cmdhandler.vg_create_vdo_pool( | ||||
| 			pool.lv_full_name(), name, virtual_size, | ||||
| 			create_options)) | ||||
| 		return Vg.fetch_new_lv(vg_name, pool.Name) | ||||
|  | ||||
| 	@dbus.service.method( | ||||
| 		dbus_interface=VG_VDO_INTERFACE, | ||||
| 		in_signature='ostia{sv}', | ||||
| 		out_signature='(oo)', | ||||
| 		async_callbacks=('cb', 'cbe')) | ||||
| 	def CreateVdoPool(self, pool_lv, name, virtual_size, | ||||
| 						tmo, create_options, cb, cbe): | ||||
| 		utils.validate_lv_name(VG_VDO_INTERFACE, self.Name, name) | ||||
|  | ||||
| 		r = RequestEntry(tmo, VgVdo._vdo_pool_create, | ||||
| 							(self.state.Uuid, self.state.lvm_id, | ||||
| 							pool_lv, name, | ||||
| 							round_size(virtual_size), | ||||
| 							create_options), cb, cbe) | ||||
| 		cfg.worker_q.put(r) | ||||
|   | ||||
| @@ -30,31 +30,18 @@ ifeq ("@BUILD_LOCKDDLM@", "yes") | ||||
|   LOCK_LIBS += -ldlmcontrol | ||||
| endif | ||||
|  | ||||
| ifeq ("@BUILD_LOCKDIDM@", "yes") | ||||
|   SOURCES += lvmlockd-idm.c | ||||
|   LOCK_LIBS += -lseagate_ilm -lblkid | ||||
| endif | ||||
|  | ||||
| SOURCES2 = lvmlockctl.c | ||||
|  | ||||
| TARGETS = lvmlockd lvmlockctl | ||||
|  | ||||
| CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) | ||||
| CFLOW_TARGET = lvmlockd | ||||
|  | ||||
| .PHONY: install_lvmlockd install_lvmlockctl | ||||
| .PHONY: install_lvmlockd | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| CFLAGS += $(EXTRA_EXEC_CFLAGS) | ||||
| CFLAGS += $(EXTRA_EXEC_CFLAGS) $(SYSTEMD_CFLAGS) | ||||
| INCLUDES += -I$(top_srcdir)/libdaemon/server | ||||
| LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) | ||||
| LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS) | ||||
|  | ||||
| ifeq ($(USE_SD_NOTIFY),yes) | ||||
| 	CFLAGS += $(shell pkg-config --cflags libsystemd) -DUSE_SD_NOTIFY | ||||
| 	LIBS += $(shell pkg-config --libs libsystemd) | ||||
| endif | ||||
| LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) | ||||
| LIBS += $(PTHREAD_LIBS) $(SYSTEMD_LIBS) | ||||
|  | ||||
| lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS) | ||||
| 	@echo "    [CC] $@" | ||||
|   | ||||
| @@ -18,11 +18,8 @@ | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <syslog.h> | ||||
| #include <ctype.h> | ||||
| #include <sys/socket.h> | ||||
| #include <sys/un.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/wait.h> | ||||
|  | ||||
| static int quit = 0; | ||||
| static int info = 0; | ||||
| @@ -33,7 +30,6 @@ static int kill_vg = 0; | ||||
| static int drop_vg = 0; | ||||
| static int gl_enable = 0; | ||||
| static int gl_disable = 0; | ||||
| static int use_stderr = 0; | ||||
| static int stop_lockspaces = 0; | ||||
| static char *arg_vg_name = NULL; | ||||
|  | ||||
| @@ -51,22 +47,6 @@ do { \ | ||||
| 	printf(fmt "\n", ##args); \ | ||||
| } while (0) | ||||
|  | ||||
| #define log_sys_emerg(fmt, args...) \ | ||||
| do { \ | ||||
| 	if (use_stderr) \ | ||||
| 		fprintf(stderr, fmt "\n", ##args); \ | ||||
| 	else \ | ||||
| 		syslog(LOG_EMERG, fmt, ##args); \ | ||||
| } while (0) | ||||
|  | ||||
| #define log_sys_warn(fmt, args...) \ | ||||
| do { \ | ||||
| 	if (use_stderr) \ | ||||
| 		fprintf(stderr, fmt "\n", ##args); \ | ||||
| 	else \ | ||||
| 		syslog(LOG_WARNING, fmt, ##args); \ | ||||
| } while (0) | ||||
|  | ||||
| #define MAX_LINE 512 | ||||
|  | ||||
| /* copied from lvmlockd-internal.h */ | ||||
| @@ -300,12 +280,13 @@ static void format_info_line(char *line, char *r_name, char *r_type) | ||||
|  | ||||
| static void format_info(void) | ||||
| { | ||||
| 	char line[MAX_LINE] = { 0 }; | ||||
| 	char r_name[MAX_NAME+1] = { 0 }; | ||||
| 	char r_type[MAX_NAME+1] = { 0 }; | ||||
| 	char line[MAX_LINE]; | ||||
| 	char r_name[MAX_NAME+1]; | ||||
| 	char r_type[MAX_NAME+1]; | ||||
| 	int i, j; | ||||
|  | ||||
| 	j = 0; | ||||
| 	memset(line, 0, sizeof(line)); | ||||
|  | ||||
| 	for (i = 0; i < dump_len; i++) { | ||||
| 		line[j++] = dump_buf[i]; | ||||
| @@ -345,8 +326,6 @@ static int _lvmlockd_result(daemon_reply reply, int *result) | ||||
| { | ||||
| 	int reply_result; | ||||
|  | ||||
| 	*result = NO_LOCKD_RESULT; | ||||
|  | ||||
| 	if (reply.error) { | ||||
| 		log_error("lvmlockd_result reply error %d", reply.error); | ||||
| 		return 0; | ||||
| @@ -358,7 +337,7 @@ static int _lvmlockd_result(daemon_reply reply, int *result) | ||||
| 	} | ||||
|  | ||||
| 	reply_result = daemon_reply_int(reply, "op_result", NO_LOCKD_RESULT); | ||||
| 	if (reply_result == NO_LOCKD_RESULT) { | ||||
| 	if (reply_result == -1000) { | ||||
| 		log_error("lvmlockd_result no op_result"); | ||||
| 		return 0; | ||||
| 	} | ||||
| @@ -457,7 +436,6 @@ retry: | ||||
| 	if (count < dump_len) | ||||
| 		goto retry; | ||||
|  | ||||
| 	dump_buf[count] = 0; | ||||
| 	rv = 0; | ||||
| 	if ((info && dump) || !strcmp(req_name, "dump")) | ||||
| 		printf("%s\n", dump_buf); | ||||
| @@ -523,274 +501,51 @@ static int do_stop_lockspaces(void) | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| static int _reopen_fd_to_null(int fd) | ||||
| static int do_kill(void) | ||||
| { | ||||
| 	int null_fd; | ||||
| 	int r = 0; | ||||
|  | ||||
| 	if ((null_fd = open("/dev/null", O_RDWR)) == -1) { | ||||
| 		log_error("open error /dev/null %d", errno); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (close(fd)) { | ||||
| 		log_error("close error fd %d %d", fd, errno); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (dup2(null_fd, fd) == -1) { | ||||
| 		log_error("dup2 error %d", errno); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	r = 1; | ||||
| out: | ||||
| 	if (close(null_fd)) { | ||||
| 		log_error("close error fd %d %d", null_fd, errno); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| #define MAX_AV_COUNT 32 | ||||
| #define ONE_ARG_LEN 1024 | ||||
|  | ||||
| static void _run_command_pipe(const char *cmd_str, pid_t *pid_out, FILE **fp_out) | ||||
| { | ||||
| 	char arg[ONE_ARG_LEN]; | ||||
| 	char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */ | ||||
| 	char *arg_dup; | ||||
| 	int av_count = 0; | ||||
| 	int cmd_len; | ||||
| 	int arg_len; | ||||
| 	pid_t pid = 0; | ||||
| 	FILE *fp = NULL; | ||||
| 	int pipefd[2]; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < MAX_AV_COUNT + 1; i++) | ||||
| 		av[i] = NULL; | ||||
|  | ||||
| 	cmd_len = strlen(cmd_str); | ||||
|  | ||||
| 	memset(&arg, 0, sizeof(arg)); | ||||
| 	arg_len = 0; | ||||
|  | ||||
| 	for (i = 0; i < cmd_len; i++) { | ||||
| 		if (!cmd_str[i]) | ||||
| 			break; | ||||
|  | ||||
| 		if (av_count == MAX_AV_COUNT) | ||||
| 			goto out; | ||||
|  | ||||
| 		if (cmd_str[i] == '\\') { | ||||
| 			if (i == (cmd_len - 1)) | ||||
| 				break; | ||||
| 			i++; | ||||
|  | ||||
| 			if (cmd_str[i] == '\\') { | ||||
| 				arg[arg_len++] = cmd_str[i]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (isspace(cmd_str[i])) { | ||||
| 				arg[arg_len++] = cmd_str[i]; | ||||
| 				continue; | ||||
| 			} else { | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) { | ||||
| 			arg[arg_len++] = cmd_str[i]; | ||||
| 		} else if (isspace(cmd_str[i])) { | ||||
| 			if (arg_len) { | ||||
| 				if (!(arg_dup = strdup(arg))) | ||||
| 					goto out; | ||||
| 				av[av_count++] = arg_dup; | ||||
| 			} | ||||
|  | ||||
| 			memset(arg, 0, sizeof(arg)); | ||||
| 			arg_len = 0; | ||||
| 		} else { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (arg_len) { | ||||
| 		if (av_count >= MAX_AV_COUNT) | ||||
| 			goto out; | ||||
| 		if (!(arg_dup = strdup(arg))) | ||||
| 			goto out; | ||||
| 		av[av_count++] = arg_dup; | ||||
| 	} | ||||
|  | ||||
| 	if (pipe(pipefd)) { | ||||
| 		log_error("pipe error %d", errno); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	pid = fork(); | ||||
|  | ||||
| 	if (pid < 0) { | ||||
| 		log_error("fork error %d", errno); | ||||
| 		pid = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (pid == 0) { | ||||
| 		/* Child -> writer, convert pipe[0] to STDOUT */ | ||||
| 		if (!_reopen_fd_to_null(STDIN_FILENO)) | ||||
| 			log_error("reopen STDIN error"); | ||||
| 		else if (close(pipefd[0 /*read*/])) | ||||
| 			log_error("close error pipe[0] %d", errno); | ||||
| 		else if (close(STDOUT_FILENO)) | ||||
| 			log_error("close error STDOUT %d", errno); | ||||
| 		else if (dup2(pipefd[1 /*write*/], STDOUT_FILENO) == -1) | ||||
| 			log_error("dup2 error STDOUT %d", errno); | ||||
| 		else if (close(pipefd[1])) | ||||
| 			log_error("close error pipe[1] %d", errno); | ||||
| 		else { | ||||
| 			execvp(av[0], av); | ||||
| 			log_error("execvp error %d", errno); | ||||
| 		} | ||||
| 		_exit(errno); | ||||
| 	} | ||||
|  | ||||
| 	/* Parent -> reader */ | ||||
| 	if (close(pipefd[1 /*write*/])) | ||||
| 		log_error("close error STDOUT %d", errno); | ||||
|  | ||||
| 	if (!(fp = fdopen(pipefd[0 /*read*/],  "r"))) { | ||||
| 		log_error("fdopen STDIN error %d", errno); | ||||
| 		if (close(pipefd[0])) | ||||
| 			log_error("close error STDIN %d", errno); | ||||
| 	} | ||||
|  | ||||
|  out: | ||||
| 	for (i = 0; i < MAX_AV_COUNT + 1; i++) | ||||
| 		free(av[i]); | ||||
|  | ||||
| 	*pid_out = pid; | ||||
| 	*fp_out = fp; | ||||
| } | ||||
|  | ||||
| /* Returns -1 on error, 0 on success. */ | ||||
|  | ||||
| static int _close_command_pipe(pid_t pid, FILE *fp) | ||||
| { | ||||
| 	int status, estatus; | ||||
| 	int ret = -1; | ||||
|  | ||||
| 	if (waitpid(pid, &status, 0) != pid) { | ||||
| 		log_error("waitpid error pid %d %d", pid, errno); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (WIFEXITED(status)) { | ||||
| 		/* pid exited with an exit code */ | ||||
| 		estatus = WEXITSTATUS(status); | ||||
|  | ||||
| 		/* exit status 0: child success */ | ||||
| 		if (!estatus) { | ||||
| 			ret = 0; | ||||
| 			goto out; | ||||
| 		} | ||||
|  | ||||
| 		/* exit status not zero: child error */ | ||||
| 		log_error("child exit error %d", estatus); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (WIFSIGNALED(status)) { | ||||
| 		/* pid terminated due to a signal */ | ||||
| 		log_error("child exit from signal"); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	log_error("child exit problem"); | ||||
|  | ||||
| out: | ||||
| 	if (fp && fclose(fp)) | ||||
| 		log_error("fclose error STDIN %d", errno); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| /* Returns -1 on error, 0 on success. */ | ||||
|  | ||||
| static int _get_kill_command(char *kill_cmd) | ||||
| { | ||||
| 	char config_cmd[PATH_MAX + 128] = { 0 }; | ||||
| 	char config_val[1024] = { 0 }; | ||||
| 	char line[PATH_MAX] = { 0 }; | ||||
| 	pid_t pid = 0; | ||||
| 	FILE *fp = NULL; | ||||
|  | ||||
| 	snprintf(config_cmd, PATH_MAX, "%s config --typeconfig full global/lvmlockctl_kill_command", LVM_PATH); | ||||
|  | ||||
| 	_run_command_pipe(config_cmd, &pid, &fp); | ||||
|  | ||||
| 	if (!pid) { | ||||
| 		log_error("failed to run %s", config_cmd); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (!fp) { | ||||
| 		log_error("failed to get output %s", config_cmd); | ||||
| 		_close_command_pipe(pid, fp); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (!fgets(line, sizeof(line), fp)) { | ||||
| 		log_error("no output from %s", config_cmd); | ||||
| 		goto bad; | ||||
| 	} | ||||
|  | ||||
| 	if (sscanf(line, "lvmlockctl_kill_command=\"%256[^\n\"]\"", config_val) != 1) { | ||||
| 		log_error("unrecognized config value from %s", config_cmd); | ||||
| 		goto bad; | ||||
| 	} | ||||
|  | ||||
| 	if (!config_val[0] || (config_val[0] == ' ')) { | ||||
| 		log_error("invalid config value from %s", config_cmd); | ||||
| 		goto bad; | ||||
| 	} | ||||
|  | ||||
| 	if (config_val[0] != '/') { | ||||
| 		log_error("lvmlockctl_kill_command must be full path"); | ||||
| 		goto bad; | ||||
| 	} | ||||
|  | ||||
| 	printf("Found lvmlockctl_kill_command: %s\n", config_val); | ||||
|  | ||||
| 	snprintf(kill_cmd, PATH_MAX, "%s %s", config_val, arg_vg_name); | ||||
| 	kill_cmd[PATH_MAX-1] = '\0'; | ||||
|  | ||||
| 	_close_command_pipe(pid, fp); | ||||
| 	return 0; | ||||
| bad: | ||||
| 	_close_command_pipe(pid, fp); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| /* Returns -1 on error, 0 on success. */ | ||||
|  | ||||
| static int _run_kill_command(char *kill_cmd) | ||||
| { | ||||
| 	pid_t pid = 0; | ||||
| 	FILE *fp = NULL; | ||||
| 	daemon_reply reply; | ||||
| 	int result; | ||||
| 	int rv; | ||||
|  | ||||
| 	_run_command_pipe(kill_cmd, &pid, &fp); | ||||
| 	rv = _close_command_pipe(pid, fp); | ||||
| 	syslog(LOG_EMERG, "Lost access to sanlock lease storage in VG %s.", arg_vg_name); | ||||
| 	/* These two lines explain the manual alternative to the FIXME below. */ | ||||
| 	syslog(LOG_EMERG, "Immediately deactivate LVs in VG %s.", arg_vg_name); | ||||
| 	syslog(LOG_EMERG, "Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name); | ||||
|  | ||||
| 	if (!pid) | ||||
| 		return -1; | ||||
| 	/* | ||||
| 	 * It may not be strictly necessary to notify lvmlockd of the kill, but | ||||
| 	 * lvmlockd can use this information to avoid attempting any new lock | ||||
| 	 * requests in the VG (which would fail anyway), and can return an | ||||
| 	 * error indicating that the VG has been killed. | ||||
| 	 */ | ||||
|  | ||||
| 	if (rv < 0) | ||||
| 		return -1; | ||||
| 	reply = _lvmlockd_send("kill_vg", | ||||
| 				"cmd = %s", "lvmlockctl", | ||||
| 				"pid = " FMTd64, (int64_t) getpid(), | ||||
| 				"vg_name = %s", arg_vg_name, | ||||
| 				NULL); | ||||
|  | ||||
| 	return 0; | ||||
| 	if (!_lvmlockd_result(reply, &result)) { | ||||
| 		log_error("lvmlockd result %d", result); | ||||
| 		rv = result; | ||||
| 	} else { | ||||
| 		rv = 0; | ||||
| 	} | ||||
|  | ||||
| 	daemon_reply_destroy(reply); | ||||
|  | ||||
| 	/* | ||||
| 	 * FIXME: here is where we should implement a strong form of | ||||
| 	 * blkdeactivate, and if it completes successfully, automatically call | ||||
| 	 * do_drop() afterward.  (The drop step may not always be necessary | ||||
| 	 * if the lvm commands run while shutting things down release all the | ||||
| 	 * leases.) | ||||
| 	 * | ||||
| 	 * run_strong_blkdeactivate(); | ||||
| 	 * do_drop(); | ||||
| 	 */ | ||||
|  | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| static int do_drop(void) | ||||
| @@ -799,7 +554,7 @@ static int do_drop(void) | ||||
| 	int result; | ||||
| 	int rv; | ||||
|  | ||||
| 	log_sys_warn("Dropping locks for VG %s.", arg_vg_name); | ||||
| 	syslog(LOG_WARNING, "Dropping locks for VG %s.", arg_vg_name); | ||||
|  | ||||
| 	/* | ||||
| 	 * Check for misuse by looking for any active LVs in the VG | ||||
| @@ -827,84 +582,6 @@ static int do_drop(void) | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| static int do_kill(void) | ||||
| { | ||||
| 	char kill_cmd[PATH_MAX] = { 0 }; | ||||
| 	daemon_reply reply; | ||||
| 	int no_kill_command = 0; | ||||
| 	int result; | ||||
| 	int rv; | ||||
|  | ||||
| 	log_sys_emerg("lvmlockd lost access to locks in VG %s.", arg_vg_name); | ||||
|  | ||||
| 	rv = _get_kill_command(kill_cmd); | ||||
| 	if (rv < 0) { | ||||
| 		log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name); | ||||
| 		log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name); | ||||
| 		no_kill_command = 1; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * It may not be strictly necessary to notify lvmlockd of the kill, but | ||||
| 	 * lvmlockd can use this information to avoid attempting any new lock | ||||
| 	 * requests in the VG (which would fail anyway), and can return an | ||||
| 	 * error indicating that the VG has been killed. | ||||
| 	 */ | ||||
| 	_lvmlockd = lvmlockd_open(NULL); | ||||
| 	if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) { | ||||
| 		log_error("Cannot connect to lvmlockd for kill_vg."); | ||||
| 		goto run; | ||||
| 	} | ||||
| 	reply = _lvmlockd_send("kill_vg", | ||||
| 				"cmd = %s", "lvmlockctl", | ||||
| 				"pid = " FMTd64, (int64_t) getpid(), | ||||
| 				"vg_name = %s", arg_vg_name, | ||||
| 				NULL); | ||||
| 	if (!_lvmlockd_result(reply, &result)) | ||||
| 		log_error("lvmlockd result %d kill_vg", result); | ||||
| 	daemon_reply_destroy(reply); | ||||
| 	lvmlockd_close(_lvmlockd); | ||||
|  | ||||
|  run: | ||||
| 	if (no_kill_command) | ||||
| 		return 0; | ||||
|  | ||||
| 	rv = _run_kill_command(kill_cmd); | ||||
| 	if (rv < 0) { | ||||
| 		log_sys_emerg("Failed to run VG %s kill command %s", arg_vg_name, kill_cmd); | ||||
| 		log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name); | ||||
| 		log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	log_sys_warn("Successful VG %s kill command %s", arg_vg_name, kill_cmd); | ||||
|  | ||||
| 	/* | ||||
| 	 * If kill command was successfully, call do_drop().  (The drop step | ||||
| 	 * may not always be necessary if the lvm commands run while shutting | ||||
| 	 * things down release all the leases.) | ||||
| 	 */ | ||||
| 	rv = 0; | ||||
| 	_lvmlockd = lvmlockd_open(NULL); | ||||
| 	if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) { | ||||
| 		log_sys_emerg("Failed to connect to lvmlockd to drop locks in VG %s.", arg_vg_name); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	reply = _lvmlockd_send("drop_vg", | ||||
| 				"cmd = %s", "lvmlockctl", | ||||
| 				"pid = " FMTd64, (int64_t) getpid(), | ||||
| 				"vg_name = %s", arg_vg_name, | ||||
| 				NULL); | ||||
| 	if (!_lvmlockd_result(reply, &result)) { | ||||
| 		log_sys_emerg("Failed to drop locks in VG %s", arg_vg_name); | ||||
| 		rv = result; | ||||
| 	} | ||||
| 	daemon_reply_destroy(reply); | ||||
| 	lvmlockd_close(_lvmlockd); | ||||
|  | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| static void print_usage(void) | ||||
| { | ||||
| 	printf("lvmlockctl options\n"); | ||||
| @@ -922,7 +599,7 @@ static void print_usage(void) | ||||
| 	printf("--force | -f 0|1>\n"); | ||||
| 	printf("      Force option for other commands.\n"); | ||||
| 	printf("--kill | -k <vgname>\n"); | ||||
| 	printf("      Kill access to the VG locks are lost (see lvmlockctl_kill_command).\n"); | ||||
| 	printf("      Kill access to the VG when sanlock cannot renew lease.\n"); | ||||
| 	printf("--drop | -r <vgname>\n"); | ||||
| 	printf("      Clear locks for the VG when it is unused after kill (-k).\n"); | ||||
| 	printf("--gl-enable | -E <vgname>\n"); | ||||
| @@ -931,8 +608,6 @@ static void print_usage(void) | ||||
| 	printf("      Tell lvmlockd to disable the global lock in a sanlock VG.\n"); | ||||
| 	printf("--stop-lockspaces | -S\n"); | ||||
| 	printf("      Stop all lockspaces.\n"); | ||||
| 	printf("--stderr | -e\n"); | ||||
| 	printf("      Send kill and drop messages to stderr instead of syslog\n"); | ||||
| } | ||||
|  | ||||
| static int read_options(int argc, char *argv[]) | ||||
| @@ -952,7 +627,6 @@ static int read_options(int argc, char *argv[]) | ||||
| 		{"gl-enable",       required_argument, 0,  'E' }, | ||||
| 		{"gl-disable",      required_argument, 0,  'D' }, | ||||
| 		{"stop-lockspaces", no_argument,       0,  'S' }, | ||||
| 		{"stderr",          no_argument,       0,  'e' }, | ||||
| 		{0, 0, 0, 0 } | ||||
| 	}; | ||||
|  | ||||
| @@ -962,7 +636,7 @@ static int read_options(int argc, char *argv[]) | ||||
| 	} | ||||
|  | ||||
| 	while (1) { | ||||
| 		c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", long_options, &option_index); | ||||
| 		c = getopt_long(argc, argv, "hqidE:D:w:k:r:S", long_options, &option_index); | ||||
| 		if (c == -1) | ||||
| 			break; | ||||
|  | ||||
| @@ -988,30 +662,23 @@ static int read_options(int argc, char *argv[]) | ||||
| 			break; | ||||
| 		case 'k': | ||||
| 			kill_vg = 1; | ||||
| 			free(arg_vg_name); | ||||
| 			arg_vg_name = strdup(optarg); | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			drop_vg = 1; | ||||
| 			free(arg_vg_name); | ||||
| 			arg_vg_name = strdup(optarg); | ||||
| 			break; | ||||
| 		case 'E': | ||||
| 			gl_enable = 1; | ||||
| 			free(arg_vg_name); | ||||
| 			arg_vg_name = strdup(optarg); | ||||
| 			break; | ||||
| 		case 'D': | ||||
| 			gl_disable = 1; | ||||
| 			free(arg_vg_name); | ||||
| 			arg_vg_name = strdup(optarg); | ||||
| 			break; | ||||
| 		case 'S': | ||||
| 			stop_lockspaces = 1; | ||||
| 			break; | ||||
| 		case 'e': | ||||
| 			use_stderr = 1; | ||||
| 			break; | ||||
| 		default: | ||||
| 			print_usage(); | ||||
| 			exit(1); | ||||
| @@ -1030,12 +697,8 @@ int main(int argc, char **argv) | ||||
| 	if (rv < 0) | ||||
| 		return rv; | ||||
|  | ||||
| 	/* do_kill handles lvmlockd connections itself */ | ||||
| 	if (kill_vg) | ||||
| 		return do_kill(); | ||||
|  | ||||
|  | ||||
| 	_lvmlockd = lvmlockd_open(NULL); | ||||
|  | ||||
| 	if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) { | ||||
| 		log_error("Cannot connect to lvmlockd."); | ||||
| 		return -1; | ||||
| @@ -1056,6 +719,11 @@ int main(int argc, char **argv) | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (kill_vg) { | ||||
| 		rv = do_kill(); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (drop_vg) { | ||||
| 		rv = do_drop(); | ||||
| 		goto out; | ||||
|   | ||||
| @@ -14,7 +14,6 @@ | ||||
| #include "libdaemon/client/daemon-client.h" | ||||
|  | ||||
| #define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket" | ||||
| #define LVMLOCKD_ADOPT_FILE DEFAULT_RUN_DIR "/lvmlockd.adopt" | ||||
|  | ||||
| /* Wrappers to open/close connection */ | ||||
|  | ||||
| @@ -23,9 +22,9 @@ static inline daemon_handle lvmlockd_open(const char *sock) | ||||
| 	daemon_info lvmlockd_info = { | ||||
| 		.path = "lvmlockd", | ||||
| 		.socket = sock ?: LVMLOCKD_SOCKET, | ||||
| 		.autostart = 0, | ||||
| 		.protocol = "lvmlockd", | ||||
| 		.protocol_version = 1, | ||||
| 		.autostart = 0 | ||||
| 	}; | ||||
|  | ||||
| 	return daemon_open(lvmlockd_info); | ||||
| @@ -33,7 +32,7 @@ static inline daemon_handle lvmlockd_open(const char *sock) | ||||
|  | ||||
| static inline void lvmlockd_close(daemon_handle h) | ||||
| { | ||||
| 	daemon_close(h); | ||||
| 	return daemon_close(h); | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -119,7 +119,6 @@ static int read_cluster_name(char *clustername) | ||||
| 			log_error(close_error_msg, fd); | ||||
| 		return rv; | ||||
| 	} | ||||
| 	clustername[rv] = 0; | ||||
|  | ||||
| 	n = strstr(clustername, "\n"); | ||||
| 	if (n) | ||||
| @@ -328,7 +327,8 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r) | ||||
| 		log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv); | ||||
| 	} | ||||
|  out: | ||||
| 	free(rdd->vb); | ||||
| 	if (rdd->vb) | ||||
| 		free(rdd->vb); | ||||
|  | ||||
| 	memset(rdd, 0, sizeof(struct rd_dlm)); | ||||
| 	r->lm_init = 0; | ||||
| @@ -398,18 +398,12 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode, | ||||
| 			  (void *)1, (void *)1, (void *)1, | ||||
| 			  NULL, NULL); | ||||
|  | ||||
| 	if (rv == -1 && (errno == EAGAIN)) { | ||||
| 	if (rv == -1 && errno == -EAGAIN) { | ||||
| 		log_debug("S %s R %s adopt_dlm adopt mode %d try other mode", | ||||
| 			  ls->name, r->name, ld_mode); | ||||
| 		rv = -EUCLEAN; | ||||
| 		goto fail; | ||||
| 	} | ||||
| 	if (rv == -1 && (errno == ENOENT)) { | ||||
| 		log_debug("S %s R %s adopt_dlm adopt mode %d no lock", | ||||
| 			  ls->name, r->name, ld_mode); | ||||
| 		rv = -ENOENT; | ||||
| 		goto fail; | ||||
| 	} | ||||
| 	if (rv < 0) { | ||||
| 		log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d", | ||||
| 			  ls->name, r->name, mode, flags, rv, errno); | ||||
| @@ -791,18 +785,17 @@ int lm_is_running_dlm(void) | ||||
|  | ||||
| int lm_refresh_lv_start_dlm(struct action *act) | ||||
| { | ||||
| 	char path[PATH_MAX] = { 0 }; | ||||
| 	char path[PATH_MAX]; | ||||
| 	char command[DLMC_RUN_COMMAND_LEN]; | ||||
| 	char run_uuid[DLMC_RUN_UUID_LEN]; | ||||
| 	char *p, *vgname, *lvname; | ||||
| 	int rv; | ||||
|  | ||||
| 	/* split /dev/vgname/lvname into vgname and lvname strings */ | ||||
| 	strncpy(path, act->path, PATH_MAX-1); | ||||
| 	strncpy(path, act->path, strlen(act->path)); | ||||
|  | ||||
| 	/* skip past dev */ | ||||
| 	if (!(p = strchr(path + 1, '/'))) | ||||
| 		return -EINVAL; | ||||
| 	p = strchr(path + 1, '/'); | ||||
|  | ||||
| 	/* skip past slashes */ | ||||
| 	while (*p == '/') | ||||
|   | ||||
| @@ -1,837 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2020-2021 Seagate Ltd. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
|  * This copyrighted material is made available to anyone wishing to use, | ||||
|  * modify, copy, or redistribute it subject to the terms and conditions | ||||
|  * of the GNU Lesser General Public License v.2.1. | ||||
|  */ | ||||
|  | ||||
| #define _XOPEN_SOURCE 500  /* pthread */ | ||||
| #define _ISOC99_SOURCE | ||||
|  | ||||
| #include "tools/tool.h" | ||||
|  | ||||
| #include "daemon-server.h" | ||||
| #include "lib/mm/xlate.h" | ||||
|  | ||||
| #include "lvmlockd-internal.h" | ||||
| #include "daemons/lvmlockd/lvmlockd-client.h" | ||||
|  | ||||
| #include "ilm.h" | ||||
|  | ||||
| #include <blkid/blkid.h> | ||||
| #include <ctype.h> | ||||
| #include <dirent.h> | ||||
| #include <errno.h> | ||||
| #include <poll.h> | ||||
| #include <regex.h> | ||||
| #include <stddef.h> | ||||
| #include <syslog.h> | ||||
| #include <sys/sysmacros.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #define IDM_TIMEOUT	60000	/* unit: millisecond, 60 seconds */ | ||||
|  | ||||
| /* | ||||
|  * Each lockspace thread has its own In-Drive Mutex (IDM) lock manager's | ||||
|  * connection.  After established socket connection, the lockspace has | ||||
|  * been created in IDM lock manager and afterwards use the socket file | ||||
|  * descriptor to send any requests for lock related operations. | ||||
|  */ | ||||
|  | ||||
| struct lm_idm { | ||||
| 	int sock;	/* IDM lock manager connection */ | ||||
| }; | ||||
|  | ||||
| struct rd_idm { | ||||
| 	struct idm_lock_id id; | ||||
| 	struct idm_lock_op op; | ||||
| 	uint64_t vb_timestamp; | ||||
| 	struct val_blk *vb; | ||||
| }; | ||||
|  | ||||
| int lm_data_size_idm(void) | ||||
| { | ||||
| 	return sizeof(struct rd_idm); | ||||
| } | ||||
|  | ||||
| static uint64_t read_utc_us(void) | ||||
| { | ||||
| 	struct timespec cur_time; | ||||
|  | ||||
| 	clock_gettime(CLOCK_REALTIME, &cur_time); | ||||
|  | ||||
| 	/* | ||||
| 	 * Convert to microseconds unit.  IDM reserves the MSB in 8 bytes | ||||
| 	 * and the low 56 bits are used for timestamp; 56 bits can support | ||||
| 	 * calendar year to 2284, so it has 260 years for overflow.  Thus it | ||||
| 	 * is quite safe for overflow issue when wrote this code. | ||||
| 	 */ | ||||
| 	return cur_time.tv_sec * 1000000 + cur_time.tv_nsec / 1000; | ||||
| } | ||||
|  | ||||
| static int uuid_read_format(char *uuid_str, const char *buffer) | ||||
| { | ||||
| 	int out = 0; | ||||
|  | ||||
| 	/* just strip out any dashes */ | ||||
| 	while (*buffer) { | ||||
|  | ||||
| 		if (*buffer == '-') { | ||||
| 			buffer++; | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (out >= 32) { | ||||
| 			log_error("Too many characters to be uuid."); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		uuid_str[out++] = *buffer; | ||||
| 		buffer++; | ||||
| 	} | ||||
|  | ||||
| 	if (out != 32) { | ||||
| 		log_error("Couldn't read uuid: incorrect number of " | ||||
| 			  "characters."); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| #define SYSFS_ROOT		"/sys" | ||||
| #define BUS_SCSI_DEVS		"/bus/scsi/devices" | ||||
|  | ||||
| static struct idm_lock_op glb_lock_op; | ||||
|  | ||||
| static void lm_idm_free_dir_list(struct dirent **dir_list, int dir_num) | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < dir_num; ++i) | ||||
| 		free(dir_list[i]); | ||||
| 	free(dir_list); | ||||
| } | ||||
|  | ||||
| static int lm_idm_scsi_directory_select(const struct dirent *s) | ||||
| { | ||||
| 	regex_t regex; | ||||
| 	int ret; | ||||
|  | ||||
| 	/* Only select directory with the format x:x:x:x */ | ||||
| 	ret = regcomp(®ex, "^[0-9]+:[0-9]+:[0-9]+:[0-9]+$", REG_EXTENDED); | ||||
| 	if (ret) | ||||
| 		return 0; | ||||
|  | ||||
| 	ret = regexec(®ex, s->d_name, 0, NULL, 0); | ||||
| 	if (!ret) { | ||||
| 		regfree(®ex); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	regfree(®ex); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int lm_idm_scsi_find_block_dirctory(const char *block_path) | ||||
| { | ||||
| 	struct stat stats; | ||||
|  | ||||
| 	if ((stat(block_path, &stats) >= 0) && S_ISDIR(stats.st_mode)) | ||||
| 		return 0; | ||||
|  | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int lm_idm_scsi_block_node_select(const struct dirent *s) | ||||
| { | ||||
| 	if (DT_LNK != s->d_type && DT_DIR != s->d_type) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (DT_DIR == s->d_type) { | ||||
| 		/* Skip this directory: '.' and parent: '..' */ | ||||
| 		if (!strcmp(s->d_name, ".") || !strcmp(s->d_name, "..")) | ||||
| 			return 0; | ||||
| 	} | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int lm_idm_scsi_find_block_node(const char *blk_path, char **blk_dev) | ||||
| { | ||||
|         struct dirent **dir_list; | ||||
|         int dir_num; | ||||
|  | ||||
|         dir_num = scandir(blk_path, &dir_list, lm_idm_scsi_block_node_select, NULL); | ||||
|         if (dir_num < 0) { | ||||
| 		log_error("Cannot find valid directory entry in %s", blk_path); | ||||
|                 return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Should have only one block name under the path, if the dir_num is | ||||
| 	 * not 1 (e.g. 0 or any number bigger than 1), it must be wrong and | ||||
| 	 * should never happen. | ||||
| 	 */ | ||||
| 	if (dir_num == 1) | ||||
| 		*blk_dev = strdup(dir_list[0]->d_name); | ||||
| 	else | ||||
| 		*blk_dev = NULL; | ||||
|  | ||||
| 	lm_idm_free_dir_list(dir_list, dir_num); | ||||
|  | ||||
| 	if (!*blk_dev) | ||||
| 		return -1; | ||||
|  | ||||
|         return dir_num; | ||||
| } | ||||
|  | ||||
| static int lm_idm_scsi_search_propeller_partition(char *dev) | ||||
| { | ||||
| 	int i, nparts; | ||||
| 	blkid_probe pr; | ||||
| 	blkid_partlist ls; | ||||
| 	int found = -1; | ||||
|  | ||||
| 	pr = blkid_new_probe_from_filename(dev); | ||||
| 	if (!pr) { | ||||
| 		log_error("%s: failed to create a new libblkid probe", dev); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* Binary interface */ | ||||
| 	ls = blkid_probe_get_partitions(pr); | ||||
| 	if (!ls) { | ||||
| 		log_error("%s: failed to read partitions", dev); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* List partitions */ | ||||
| 	nparts = blkid_partlist_numof_partitions(ls); | ||||
| 	if (!nparts) | ||||
| 		goto done; | ||||
|  | ||||
| 	for (i = 0; i < nparts; i++) { | ||||
| 		const char *p; | ||||
| 		blkid_partition par = blkid_partlist_get_partition(ls, i); | ||||
|  | ||||
| 		p = blkid_partition_get_name(par); | ||||
| 		if (p) { | ||||
| 			log_debug("partition name='%s'", p); | ||||
|  | ||||
| 			if (!strcmp(p, "propeller")) | ||||
| 				found = blkid_partition_get_partno(par); | ||||
| 		} | ||||
|  | ||||
| 		if (found >= 0) | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| done: | ||||
| 	blkid_free_probe(pr); | ||||
| 	return found; | ||||
| } | ||||
|  | ||||
| static char *lm_idm_scsi_get_block_device_node(const char *scsi_path) | ||||
| { | ||||
| 	char *blk_path = NULL; | ||||
| 	char *blk_dev = NULL; | ||||
| 	char *dev_node = NULL; | ||||
| 	int ret; | ||||
|  | ||||
| 	/* | ||||
| 	 * Locate the "block" directory, such like: | ||||
| 	 * /sys/bus/scsi/devices/1:0:0:0/block | ||||
| 	 */ | ||||
| 	ret = asprintf(&blk_path, "%s/%s", scsi_path, "block"); | ||||
| 	if (ret < 0) { | ||||
| 		log_error("Fail to allocate block path for %s", scsi_path); | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	ret = lm_idm_scsi_find_block_dirctory(blk_path); | ||||
| 	if (ret < 0) { | ||||
| 		log_error("Fail to find block path %s", blk_path); | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Locate the block device name, such like: | ||||
| 	 * /sys/bus/scsi/devices/1:0:0:0/block/sdb | ||||
| 	 * | ||||
| 	 * After return from this function and if it makes success, | ||||
| 	 * the global variable "blk_dev" points to the block device | ||||
| 	 * name, in this example it points to string "sdb". | ||||
| 	 */ | ||||
| 	ret = lm_idm_scsi_find_block_node(blk_path, &blk_dev); | ||||
| 	if (ret < 0) { | ||||
| 		log_error("Fail to find block node"); | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	ret = asprintf(&dev_node, "/dev/%s", blk_dev); | ||||
| 	if (ret < 0) { | ||||
| 		log_error("Fail to allocate memory for blk node path"); | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	ret = lm_idm_scsi_search_propeller_partition(dev_node); | ||||
| 	if (ret < 0) | ||||
| 		goto fail; | ||||
|  | ||||
| 	free(blk_path); | ||||
| 	free(blk_dev); | ||||
| 	return dev_node; | ||||
|  | ||||
| fail: | ||||
| 	free(blk_path); | ||||
| 	free(blk_dev); | ||||
| 	free(dev_node); | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static int lm_idm_get_gl_lock_pv_list(void) | ||||
| { | ||||
| 	struct dirent **dir_list; | ||||
| 	char scsi_bus_path[PATH_MAX]; | ||||
| 	char *drive_path; | ||||
| 	int i, dir_num, ret; | ||||
|  | ||||
| 	if (glb_lock_op.drive_num) | ||||
| 		return 0; | ||||
|  | ||||
| 	snprintf(scsi_bus_path, sizeof(scsi_bus_path), "%s%s", | ||||
| 		 SYSFS_ROOT, BUS_SCSI_DEVS); | ||||
|  | ||||
| 	dir_num = scandir(scsi_bus_path, &dir_list, | ||||
| 			  lm_idm_scsi_directory_select, NULL); | ||||
| 	if (dir_num < 0) {  /* scsi mid level may not be loaded */ | ||||
| 		log_error("Attached devices: none"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < dir_num; i++) { | ||||
| 		char *scsi_path; | ||||
|  | ||||
| 		ret = asprintf(&scsi_path, "%s/%s", scsi_bus_path, | ||||
| 			       dir_list[i]->d_name); | ||||
| 		if (ret < 0) { | ||||
| 			log_error("Fail to allocate memory for scsi directory"); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		if (glb_lock_op.drive_num >= ILM_DRIVE_MAX_NUM) { | ||||
| 			log_error("Global lock: drive number %d exceeds limitation (%d) ?!", | ||||
| 				  glb_lock_op.drive_num, ILM_DRIVE_MAX_NUM); | ||||
| 			free(scsi_path); | ||||
| 			goto failed; | ||||
| 		} | ||||
|  | ||||
| 		drive_path = lm_idm_scsi_get_block_device_node(scsi_path); | ||||
| 		if (!drive_path) { | ||||
| 			free(scsi_path); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		glb_lock_op.drives[glb_lock_op.drive_num] = drive_path; | ||||
| 		glb_lock_op.drive_num++; | ||||
|  | ||||
| 		free(scsi_path); | ||||
| 	} | ||||
|  | ||||
| 	lm_idm_free_dir_list(dir_list, dir_num); | ||||
| 	return 0; | ||||
|  | ||||
| failed: | ||||
| 	lm_idm_free_dir_list(dir_list, dir_num); | ||||
|  | ||||
| 	for (i = 0; i < glb_lock_op.drive_num; i++) { | ||||
| 		if (glb_lock_op.drives[i]) { | ||||
| 			free(glb_lock_op.drives[i]); | ||||
| 			glb_lock_op.drives[i] = NULL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static void lm_idm_update_vb_timestamp(uint64_t *vb_timestamp) | ||||
| { | ||||
| 	uint64_t utc_us = read_utc_us(); | ||||
|  | ||||
| 	/* | ||||
| 	 * It's possible that the multiple nodes have no clock | ||||
| 	 * synchronization with microsecond prcision and the time | ||||
| 	 * is going backward.  For this case, simply increment the | ||||
| 	 * existing timestamp and write out to drive. | ||||
| 	 */ | ||||
| 	if (*vb_timestamp >= utc_us) | ||||
| 		(*vb_timestamp)++; | ||||
| 	else | ||||
| 		*vb_timestamp = utc_us; | ||||
| } | ||||
|  | ||||
| int lm_prepare_lockspace_idm(struct lockspace *ls) | ||||
| { | ||||
| 	struct lm_idm *lm = NULL; | ||||
|  | ||||
| 	lm = malloc(sizeof(struct lm_idm)); | ||||
| 	if (!lm) { | ||||
| 		log_error("S %s prepare_lockspace_idm fail to allocate lm_idm for %s", | ||||
| 			  ls->name, ls->vg_name); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 	memset(lm, 0x0, sizeof(struct lm_idm)); | ||||
|  | ||||
| 	ls->lm_data = lm; | ||||
| 	log_debug("S %s prepare_lockspace_idm done", ls->name); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int lm_add_lockspace_idm(struct lockspace *ls, int adopt) | ||||
| { | ||||
| 	char killpath[IDM_FAILURE_PATH_LEN]; | ||||
| 	char killargs[IDM_FAILURE_ARGS_LEN]; | ||||
| 	struct lm_idm *lmi = (struct lm_idm *)ls->lm_data; | ||||
| 	int rv; | ||||
|  | ||||
| 	if (daemon_test) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (!strcmp(ls->name, S_NAME_GL_IDM)) { | ||||
| 		/* | ||||
| 		 * Prepare the pv list for global lock, if the drive contains | ||||
| 		 * "propeller" partition, then this drive will be considered | ||||
| 		 * as a member of pv list. | ||||
| 		 */ | ||||
| 		rv = lm_idm_get_gl_lock_pv_list(); | ||||
| 		if (rv < 0) { | ||||
| 			log_error("S %s add_lockspace_idm fail to get pv list for glb lock", | ||||
| 				  ls->name); | ||||
| 			return -EIO; | ||||
| 		} else { | ||||
| 			log_error("S %s add_lockspace_idm get pv list for glb lock", | ||||
| 				  ls->name); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Construct the execution path for command "lvmlockctl" by using the | ||||
| 	 * path to the lvm binary and appending "lockctl". | ||||
| 	 */ | ||||
| 	memset(killpath, 0, sizeof(killpath)); | ||||
| 	snprintf(killpath, IDM_FAILURE_PATH_LEN, "%slockctl", LVM_PATH); | ||||
|  | ||||
| 	/* Pass the argument "--kill vg_name" for killpath */ | ||||
| 	memset(killargs, 0, sizeof(killargs)); | ||||
| 	snprintf(killargs, IDM_FAILURE_ARGS_LEN, "--kill %s", ls->vg_name); | ||||
|  | ||||
| 	/* Connect with IDM lock manager per every lockspace. */ | ||||
| 	rv = ilm_connect(&lmi->sock); | ||||
| 	if (rv < 0) { | ||||
| 		log_error("S %s add_lockspace_idm fail to connect the lock manager %d", | ||||
| 			  ls->name, lmi->sock); | ||||
| 		lmi->sock = 0; | ||||
| 		rv = -EMANAGER; | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	rv = ilm_set_killpath(lmi->sock, killpath, killargs); | ||||
| 	if (rv < 0) { | ||||
| 		log_error("S %s add_lockspace_idm fail to set kill path %d", | ||||
| 			  ls->name, rv); | ||||
| 		rv = -EMANAGER; | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	log_debug("S %s add_lockspace_idm kill path is: \"%s %s\"", | ||||
| 		  ls->name, killpath, killargs); | ||||
|  | ||||
| 	log_debug("S %s add_lockspace_idm done", ls->name); | ||||
| 	return 0; | ||||
|  | ||||
| fail: | ||||
| 	if (lmi && lmi->sock) | ||||
| 		close(lmi->sock); | ||||
|  | ||||
| 	free(lmi); | ||||
|  | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg) | ||||
| { | ||||
| 	struct lm_idm *lmi = (struct lm_idm *)ls->lm_data; | ||||
| 	int i, rv = 0; | ||||
|  | ||||
| 	if (daemon_test) | ||||
| 		goto out; | ||||
|  | ||||
| 	rv = ilm_disconnect(lmi->sock); | ||||
| 	if (rv < 0) | ||||
| 		log_error("S %s rem_lockspace_idm error %d", ls->name, rv); | ||||
|  | ||||
| 	/* Release pv list for global lock */ | ||||
| 	if (!strcmp(ls->name, "lvm_global")) { | ||||
| 		for (i = 0; i < glb_lock_op.drive_num; i++) { | ||||
| 			if (glb_lock_op.drives[i]) { | ||||
| 				free(glb_lock_op.drives[i]); | ||||
| 				glb_lock_op.drives[i] = NULL; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| out: | ||||
| 	free(lmi); | ||||
| 	ls->lm_data = NULL; | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| static int lm_add_resource_idm(struct lockspace *ls, struct resource *r) | ||||
| { | ||||
| 	struct rd_idm *rdi = (struct rd_idm *)r->lm_data; | ||||
|  | ||||
| 	if (r->type == LD_RT_GL || r->type == LD_RT_VG) { | ||||
| 		rdi->vb = zalloc(sizeof(struct val_blk)); | ||||
| 		if (!rdi->vb) | ||||
| 			return -ENOMEM; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int lm_rem_resource_idm(struct lockspace *ls, struct resource *r) | ||||
| { | ||||
| 	struct rd_idm *rdi = (struct rd_idm *)r->lm_data; | ||||
|  | ||||
| 	free(rdi->vb); | ||||
|  | ||||
| 	memset(rdi, 0, sizeof(struct rd_idm)); | ||||
| 	r->lm_init = 0; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int to_idm_mode(int ld_mode) | ||||
| { | ||||
| 	switch (ld_mode) { | ||||
| 	case LD_LK_EX: | ||||
| 		return IDM_MODE_EXCLUSIVE; | ||||
| 	case LD_LK_SH: | ||||
| 		return IDM_MODE_SHAREABLE; | ||||
| 	default: | ||||
| 		break; | ||||
| 	}; | ||||
|  | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode, | ||||
| 		struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs, | ||||
| 		int adopt) | ||||
| { | ||||
| 	struct lm_idm *lmi = (struct lm_idm *)ls->lm_data; | ||||
| 	struct rd_idm *rdi = (struct rd_idm *)r->lm_data; | ||||
| 	char **drive_path = NULL; | ||||
| 	uint64_t timestamp; | ||||
| 	int reset_vb = 0; | ||||
| 	int rv, i; | ||||
|  | ||||
| 	if (!r->lm_init) { | ||||
| 		rv = lm_add_resource_idm(ls, r); | ||||
| 		if (rv < 0) | ||||
| 			return rv; | ||||
| 		r->lm_init = 1; | ||||
| 	} | ||||
|  | ||||
| 	rdi->op.mode = to_idm_mode(ld_mode); | ||||
| 	if (rv < 0) { | ||||
| 		log_error("lock_idm invalid mode %d", ld_mode); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	log_debug("S %s R %s lock_idm", ls->name, r->name); | ||||
|  | ||||
| 	if (daemon_test) { | ||||
| 		if (rdi->vb) { | ||||
| 			vb_out->version = le16_to_cpu(rdi->vb->version); | ||||
| 			vb_out->flags = le16_to_cpu(rdi->vb->flags); | ||||
| 			vb_out->r_version = le32_to_cpu(rdi->vb->r_version); | ||||
| 		} | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	rdi->op.timeout = IDM_TIMEOUT; | ||||
|  | ||||
| 	/* | ||||
| 	 * Generate the UUID string, for RT_VG, it only needs to generate | ||||
| 	 * UUID string for VG level, for RT_LV, it needs to generate | ||||
| 	 * UUID strings for both VG and LV levels.  At the end, these IDs | ||||
| 	 * are used as identifier for IDM in drive firmware. | ||||
| 	 */ | ||||
| 	if (r->type == LD_RT_VG || r->type == LD_RT_LV) | ||||
| 		log_debug("S %s R %s VG uuid %s", ls->name, r->name, ls->vg_uuid); | ||||
| 	if (r->type == LD_RT_LV) | ||||
| 		log_debug("S %s R %s LV uuid %s", ls->name, r->name, lv_uuid); | ||||
|  | ||||
| 	memset(&rdi->id, 0x0, sizeof(struct idm_lock_id)); | ||||
| 	if (r->type == LD_RT_VG) { | ||||
| 		uuid_read_format(rdi->id.vg_uuid, ls->vg_uuid); | ||||
| 	} else if (r->type == LD_RT_LV) { | ||||
| 		uuid_read_format(rdi->id.vg_uuid, ls->vg_uuid); | ||||
| 		uuid_read_format(rdi->id.lv_uuid, lv_uuid); | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Establish the drive path list for lock, since different lock type | ||||
| 	 * has different drive list; the GL lock uses the global pv list, | ||||
| 	 * the VG lock uses the pv list spanned for the whole volume group, | ||||
| 	 * the LV lock uses the pv list for the logical volume. | ||||
| 	 */ | ||||
| 	switch (r->type) { | ||||
| 	case LD_RT_GL: | ||||
| 		drive_path = glb_lock_op.drives; | ||||
| 		rdi->op.drive_num = glb_lock_op.drive_num; | ||||
| 		break; | ||||
| 	case LD_RT_VG: | ||||
| 		drive_path = (char **)ls->pvs.path; | ||||
| 		rdi->op.drive_num = ls->pvs.num; | ||||
| 		break; | ||||
| 	case LD_RT_LV: | ||||
| 		drive_path = (char **)pvs->path; | ||||
| 		rdi->op.drive_num = pvs->num; | ||||
| 		break; | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	if (!drive_path) { | ||||
| 		log_error("S %s R %s cannot find the valid drive path array", | ||||
| 			  ls->name, r->name); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	if (rdi->op.drive_num >= ILM_DRIVE_MAX_NUM) { | ||||
| 		log_error("S %s R %s exceeds limitation for drive path array", | ||||
| 			  ls->name, r->name); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < rdi->op.drive_num; i++) | ||||
| 		rdi->op.drives[i] = drive_path[i]; | ||||
|  | ||||
| 	log_debug("S %s R %s mode %d drive_num %d timeout %d", | ||||
| 		  ls->name, r->name, rdi->op.mode, | ||||
| 		  rdi->op.drive_num, rdi->op.timeout); | ||||
|  | ||||
| 	for (i = 0; i < rdi->op.drive_num; i++) | ||||
| 		log_debug("S %s R %s drive path[%d] %s", | ||||
| 			  ls->name, r->name, i, rdi->op.drives[i]); | ||||
|  | ||||
| 	rv = ilm_lock(lmi->sock, &rdi->id, &rdi->op); | ||||
| 	if (rv < 0) { | ||||
| 		log_debug("S %s R %s lock_idm acquire mode %d rv %d", | ||||
| 			  ls->name, r->name, ld_mode, rv); | ||||
| 		return -ELOCKIO; | ||||
| 	} | ||||
|  | ||||
| 	if (rdi->vb) { | ||||
| 		rv = ilm_read_lvb(lmi->sock, &rdi->id, (char *)×tamp, | ||||
| 				  sizeof(uint64_t)); | ||||
|  | ||||
| 		/* | ||||
| 		 * If fail to read value block, which might be caused by drive | ||||
| 		 * failure, notify up layer to invalidate metadata. | ||||
| 		 */ | ||||
| 		if (rv < 0) { | ||||
| 			log_error("S %s R %s lock_idm get_lvb error %d", | ||||
| 				  ls->name, r->name, rv); | ||||
| 			reset_vb = 1; | ||||
|  | ||||
| 			/* Reset timestamp */ | ||||
| 			rdi->vb_timestamp = 0; | ||||
|  | ||||
| 		/* | ||||
| 		 * If the cached timestamp mismatches with the stored value | ||||
| 		 * in the IDM, this means another host has updated timestamp | ||||
| 		 * for the new VB.  Let's reset VB and notify up layer to | ||||
| 		 * invalidate metadata. | ||||
| 		 */ | ||||
| 		} else if (rdi->vb_timestamp != timestamp) { | ||||
| 			log_debug("S %s R %s lock_idm get lvb timestamp %lu:%lu", | ||||
| 				  ls->name, r->name, rdi->vb_timestamp, | ||||
| 				  timestamp); | ||||
|  | ||||
| 			rdi->vb_timestamp = timestamp; | ||||
| 			reset_vb = 1; | ||||
| 		} | ||||
|  | ||||
| 		if (reset_vb == 1) { | ||||
| 			memset(rdi->vb, 0, sizeof(struct val_blk)); | ||||
| 			memset(vb_out, 0, sizeof(struct val_blk)); | ||||
|  | ||||
| 			/* | ||||
| 			 * The lock is still acquired, but the vb values has | ||||
| 			 * been invalidated. | ||||
| 			 */ | ||||
| 			rv = 0; | ||||
| 			goto out; | ||||
| 		} | ||||
|  | ||||
| 		/* Otherwise, copy the cached VB to up layer */ | ||||
| 		memcpy(vb_out, rdi->vb, sizeof(struct val_blk)); | ||||
| 	} | ||||
|  | ||||
| out: | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| int lm_convert_idm(struct lockspace *ls, struct resource *r, | ||||
| 		   int ld_mode, uint32_t r_version) | ||||
| { | ||||
| 	struct lm_idm *lmi = (struct lm_idm *)ls->lm_data; | ||||
| 	struct rd_idm *rdi = (struct rd_idm *)r->lm_data; | ||||
| 	int mode, rv; | ||||
|  | ||||
| 	if (rdi->vb && r_version && (r->mode == LD_LK_EX)) { | ||||
| 		if (!rdi->vb->version) { | ||||
| 			/* first time vb has been written */ | ||||
| 			rdi->vb->version = VAL_BLK_VERSION; | ||||
| 		} | ||||
| 		rdi->vb->r_version = r_version; | ||||
|  | ||||
| 		log_debug("S %s R %s convert_idm set r_version %u", | ||||
| 			  ls->name, r->name, r_version); | ||||
|  | ||||
| 		lm_idm_update_vb_timestamp(&rdi->vb_timestamp); | ||||
| 		log_debug("S %s R %s convert_idm vb %x %x %u timestamp %lu", | ||||
| 			  ls->name, r->name, rdi->vb->version, rdi->vb->flags, | ||||
| 			  rdi->vb->r_version, rdi->vb_timestamp); | ||||
| 	} | ||||
|  | ||||
| 	mode = to_idm_mode(ld_mode); | ||||
| 	if (mode < 0) { | ||||
| 		log_error("S %s R %s convert_idm invalid mode %d", | ||||
| 			  ls->name, r->name, ld_mode); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	log_debug("S %s R %s convert_idm", ls->name, r->name); | ||||
|  | ||||
| 	if (daemon_test) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (rdi->vb && r_version && (r->mode == LD_LK_EX)) { | ||||
| 		rv = ilm_write_lvb(lmi->sock, &rdi->id, | ||||
| 				   (char *)rdi->vb_timestamp, sizeof(uint64_t)); | ||||
| 		if (rv < 0) { | ||||
| 			log_error("S %s R %s convert_idm write lvb error %d", | ||||
| 				  ls->name, r->name, rv); | ||||
| 			return -ELMERR; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	rv = ilm_convert(lmi->sock, &rdi->id, mode); | ||||
| 	if (rv < 0) | ||||
| 		log_error("S %s R %s convert_idm convert error %d", | ||||
| 			  ls->name, r->name, rv); | ||||
|  | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| int lm_unlock_idm(struct lockspace *ls, struct resource *r, | ||||
| 		  uint32_t r_version, uint32_t lmu_flags) | ||||
| { | ||||
| 	struct lm_idm *lmi = (struct lm_idm *)ls->lm_data; | ||||
| 	struct rd_idm *rdi = (struct rd_idm *)r->lm_data; | ||||
| 	int rv; | ||||
|  | ||||
| 	if (rdi->vb && r_version && (r->mode == LD_LK_EX)) { | ||||
| 		if (!rdi->vb->version) { | ||||
| 			/* first time vb has been written */ | ||||
| 			rdi->vb->version = VAL_BLK_VERSION; | ||||
| 		} | ||||
| 		if (r_version) | ||||
| 			rdi->vb->r_version = r_version; | ||||
|  | ||||
| 		lm_idm_update_vb_timestamp(&rdi->vb_timestamp); | ||||
| 		log_debug("S %s R %s unlock_idm vb %x %x %u timestamp %lu", | ||||
| 			  ls->name, r->name, rdi->vb->version, rdi->vb->flags, | ||||
| 			  rdi->vb->r_version, rdi->vb_timestamp); | ||||
| 	} | ||||
|  | ||||
| 	log_debug("S %s R %s unlock_idm", ls->name, r->name); | ||||
|  | ||||
| 	if (daemon_test) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (rdi->vb && r_version && (r->mode == LD_LK_EX)) { | ||||
| 		rv = ilm_write_lvb(lmi->sock, &rdi->id, | ||||
| 				   (char *)&rdi->vb_timestamp, sizeof(uint64_t)); | ||||
| 		if (rv < 0) { | ||||
| 			log_error("S %s R %s unlock_idm set_lvb error %d", | ||||
| 				  ls->name, r->name, rv); | ||||
| 			return -ELMERR; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	rv = ilm_unlock(lmi->sock, &rdi->id); | ||||
| 	if (rv < 0) | ||||
| 		log_error("S %s R %s unlock_idm error %d", ls->name, r->name, rv); | ||||
|  | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| int lm_hosts_idm(struct lockspace *ls, int notify) | ||||
| { | ||||
| 	struct resource *r; | ||||
| 	struct lm_idm *lmi = (struct lm_idm *)ls->lm_data; | ||||
| 	struct rd_idm *rdi; | ||||
| 	int count, self, found_others = 0; | ||||
| 	int rv; | ||||
|  | ||||
| 	list_for_each_entry(r, &ls->resources, list) { | ||||
| 		if (!r->lm_init) | ||||
| 			continue; | ||||
|  | ||||
| 		rdi = (struct rd_idm *)r->lm_data; | ||||
|  | ||||
| 		rv = ilm_get_host_count(lmi->sock, &rdi->id, &rdi->op, | ||||
| 					&count, &self); | ||||
| 		if (rv < 0) { | ||||
| 			log_error("S %s lm_hosts_idm error %d", ls->name, rv); | ||||
| 			return rv; | ||||
| 		} | ||||
|  | ||||
| 		/* Fixup: need to reduce self count */ | ||||
| 		if (count > found_others) | ||||
| 			found_others = count; | ||||
| 	} | ||||
|  | ||||
| 	return found_others; | ||||
| } | ||||
|  | ||||
| int lm_get_lockspaces_idm(struct list_head *ls_rejoin) | ||||
| { | ||||
| 	/* TODO: Need to add support for adoption. */ | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| int lm_is_running_idm(void) | ||||
| { | ||||
| 	int sock, rv; | ||||
|  | ||||
| 	if (daemon_test) | ||||
| 		return gl_use_idm; | ||||
|  | ||||
| 	rv = ilm_connect(&sock); | ||||
| 	if (rv < 0) { | ||||
| 		log_error("Fail to connect seagate IDM lock manager %d", rv); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	ilm_disconnect(sock); | ||||
| 	return 1; | ||||
| } | ||||
| @@ -11,8 +11,6 @@ | ||||
| #ifndef _LVM_LVMLOCKD_INTERNAL_H | ||||
| #define _LVM_LVMLOCKD_INTERNAL_H | ||||
|  | ||||
| #include "base/memory/container_of.h" | ||||
|  | ||||
| #define MAX_NAME 64 | ||||
| #define MAX_ARGS 64 | ||||
|  | ||||
| @@ -20,7 +18,6 @@ | ||||
| #define R_NAME_GL          "GLLK" | ||||
| #define R_NAME_VG          "VGLK" | ||||
| #define S_NAME_GL_DLM      "lvm_global" | ||||
| #define S_NAME_GL_IDM      "lvm_global" | ||||
| #define LVM_LS_PREFIX      "lvm_"           /* ls name is prefix + vg_name */ | ||||
| /* global lockspace name for sanlock is a vg name */ | ||||
|  | ||||
| @@ -30,7 +27,6 @@ enum { | ||||
| 	LD_LM_UNUSED = 1, /* place holder so values match lib/locking/lvmlockd.h */ | ||||
| 	LD_LM_DLM = 2, | ||||
| 	LD_LM_SANLOCK = 3, | ||||
| 	LD_LM_IDM = 4, | ||||
| }; | ||||
|  | ||||
| /* operation types */ | ||||
| @@ -120,11 +116,6 @@ struct client { | ||||
|  */ | ||||
| #define DEFAULT_MAX_RETRIES 4 | ||||
|  | ||||
| struct pvs { | ||||
| 	char **path; | ||||
| 	int num; | ||||
| }; | ||||
|  | ||||
| struct action { | ||||
| 	struct list_head list; | ||||
| 	uint32_t client_id; | ||||
| @@ -147,7 +138,6 @@ struct action { | ||||
| 	char vg_args[MAX_ARGS+1]; | ||||
| 	char lv_args[MAX_ARGS+1]; | ||||
| 	char vg_sysid[MAX_NAME+1]; | ||||
| 	struct pvs pvs;			/* PV list for idm */ | ||||
| }; | ||||
|  | ||||
| struct resource { | ||||
| @@ -155,7 +145,6 @@ struct resource { | ||||
| 	char name[MAX_NAME+1];		/* vg name or lv name */ | ||||
| 	int8_t type;			/* resource type LD_RT_ */ | ||||
| 	int8_t mode; | ||||
| 	int8_t adopt_mode; | ||||
| 	unsigned int sh_count;		/* number of sh locks on locks list */ | ||||
| 	uint32_t version; | ||||
| 	uint32_t last_client_id;	/* last client_id to lock or unlock resource */ | ||||
| @@ -166,7 +155,7 @@ struct resource { | ||||
| 	struct list_head locks; | ||||
| 	struct list_head actions; | ||||
| 	char lv_args[MAX_ARGS+1]; | ||||
| 	char lm_data[];			/* lock manager specific data */ | ||||
| 	char lm_data[0];		/* lock manager specific data */ | ||||
| }; | ||||
|  | ||||
| #define LD_LF_PERSISTENT 0x00000001 | ||||
| @@ -192,7 +181,6 @@ struct lockspace { | ||||
| 	uint64_t free_lock_offset;	/* for sanlock, start search for free lock here */ | ||||
| 	int free_lock_sector_size;	/* for sanlock */ | ||||
| 	int free_lock_align_size;	/* for sanlock */ | ||||
| 	struct pvs pvs;			/* for idm: PV list */ | ||||
|  | ||||
| 	uint32_t start_client_id;	/* client_id that started the lockspace */ | ||||
| 	pthread_t thread;		/* makes synchronous lock requests */ | ||||
| @@ -228,6 +216,10 @@ struct val_blk { | ||||
| /* lm_unlock flags */ | ||||
| #define LMUF_FREE_VG 0x00000001 | ||||
|  | ||||
| #define container_of(ptr, type, member) ({                      \ | ||||
| 	const typeof( ((type *)0)->member ) *__mptr = (ptr);    \ | ||||
| 	(type *)( (char *)__mptr - offsetof(type,member) );}) | ||||
|  | ||||
| static inline void INIT_LIST_HEAD(struct list_head *list) | ||||
| { | ||||
| 	list->next = list; | ||||
| @@ -334,13 +326,10 @@ static inline int list_empty(const struct list_head *head) | ||||
| EXTERN int gl_type_static; | ||||
| EXTERN int gl_use_dlm; | ||||
| EXTERN int gl_use_sanlock; | ||||
| EXTERN int gl_use_idm; | ||||
| EXTERN int gl_vg_removed; | ||||
| EXTERN char gl_lsname_dlm[MAX_NAME+1]; | ||||
| EXTERN char gl_lsname_sanlock[MAX_NAME+1]; | ||||
| EXTERN char gl_lsname_idm[MAX_NAME+1]; | ||||
| EXTERN int global_dlm_lockspace_exists; | ||||
| EXTERN int global_idm_lockspace_exists; | ||||
|  | ||||
| EXTERN int daemon_test; /* run as much as possible without a live lock manager */ | ||||
| EXTERN int daemon_debug; | ||||
| @@ -631,102 +620,4 @@ static inline int lm_support_sanlock(void) | ||||
|  | ||||
| #endif /* sanlock support */ | ||||
|  | ||||
| #ifdef LOCKDIDM_SUPPORT | ||||
|  | ||||
| int lm_data_size_idm(void); | ||||
| int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args); | ||||
| int lm_prepare_lockspace_idm(struct lockspace *ls); | ||||
| int lm_add_lockspace_idm(struct lockspace *ls, int adopt); | ||||
| int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg); | ||||
| int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode, | ||||
| 		struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs, | ||||
| 		int adopt); | ||||
| int lm_convert_idm(struct lockspace *ls, struct resource *r, | ||||
| 		   int ld_mode, uint32_t r_version); | ||||
| int lm_unlock_idm(struct lockspace *ls, struct resource *r, | ||||
| 		  uint32_t r_version, uint32_t lmu_flags); | ||||
| int lm_hosts_idm(struct lockspace *ls, int notify); | ||||
| int lm_get_lockspaces_idm(struct list_head *ls_rejoin); | ||||
| int lm_is_running_idm(void); | ||||
| int lm_rem_resource_idm(struct lockspace *ls, struct resource *r); | ||||
|  | ||||
| static inline int lm_support_idm(void) | ||||
| { | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| static inline int lm_data_size_idm(void) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags, | ||||
| 			  char *vg_args) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_prepare_lockspace_idm(struct lockspace *ls) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode, | ||||
| 		       struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs, | ||||
| 		       int adopt) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_convert_idm(struct lockspace *ls, struct resource *r, | ||||
| 			  int ld_mode, uint32_t r_version) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_unlock_idm(struct lockspace *ls, struct resource *r, | ||||
| 			 uint32_t r_version, uint32_t lmu_flags) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_hosts_idm(struct lockspace *ls, int notify) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_get_lockspaces_idm(struct list_head *ls_rejoin) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_is_running_idm(void) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static inline int lm_rem_resource_idm(struct lockspace *ls, struct resource *r) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static inline int lm_support_idm(void) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| #endif /* Seagate IDM support */ | ||||
|  | ||||
| #endif	/* _LVM_LVMLOCKD_INTERNAL_H */ | ||||
|   | ||||
| @@ -227,17 +227,6 @@ int lm_data_size_sanlock(void) | ||||
|  | ||||
| static uint64_t daemon_test_lv_count; | ||||
|  | ||||
| /* | ||||
|  * Copy a null-terminated string "str" into a fixed | ||||
|  * size (SANLK_NAME_LEN) struct field "buf" which is | ||||
|  * not null terminated. | ||||
|  */ | ||||
| static void strcpy_name_len(char *buf, char *str, int len) | ||||
| { | ||||
| 	/* coverity[buffer_size_warning] */ | ||||
| 	strncpy(buf, str, SANLK_NAME_LEN); | ||||
| } | ||||
|  | ||||
| static int lock_lv_name_from_args(char *vg_args, char *lock_lv_name) | ||||
| { | ||||
| 	return last_string_from_args(vg_args, lock_lv_name); | ||||
| @@ -585,7 +574,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN); | ||||
| 	strncpy(ss.name, ls_name, SANLK_NAME_LEN); | ||||
| 	memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN); | ||||
| 	ss.host_id_disk.offset = 0; | ||||
| 	ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) : | ||||
| @@ -618,7 +607,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar | ||||
| 		gl_name = R_NAME_GL; | ||||
|  | ||||
| 	memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN); | ||||
| 	strcpy_name_len(rd.rs.name, (char *)gl_name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.name, gl_name, SANLK_NAME_LEN); | ||||
| 	memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN); | ||||
| 	rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN; | ||||
| 	rd.rs.num_disks = 1; | ||||
| @@ -633,7 +622,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar | ||||
| 	} | ||||
|  | ||||
| 	memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN); | ||||
| 	strcpy_name_len(rd.rs.name, (char *)R_NAME_VG, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.name, R_NAME_VG, SANLK_NAME_LEN); | ||||
| 	memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN); | ||||
| 	rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN; | ||||
| 	rd.rs.num_disks = 1; | ||||
| @@ -667,8 +656,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar | ||||
| 	rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : | ||||
| 					      (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M); | ||||
| 	memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN); | ||||
| 	strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN); | ||||
| 	strcpy_name_len(rd.rs.name, (char *)"#unused", SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN); | ||||
| 	strcpy(rd.rs.name, "#unused"); | ||||
|  | ||||
| 	offset = align_size * LV_LOCK_BEGIN; | ||||
|  | ||||
| @@ -736,7 +725,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN); | ||||
| 	rd.rs.num_disks = 1; | ||||
| 	if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, vg_name, lock_lv_name))) | ||||
| 		return rv; | ||||
| @@ -811,7 +800,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, | ||||
| 			log_debug("S %s init_lv_san %s found unused area at %llu", | ||||
| 				  ls_name, lv_name, (unsigned long long)offset); | ||||
|  | ||||
| 			strcpy_name_len(rd.rs.name, lv_name, SANLK_NAME_LEN); | ||||
| 			strncpy(rd.rs.name, lv_name, SANLK_NAME_LEN); | ||||
| 			rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : | ||||
| 							      (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M); | ||||
|  | ||||
| @@ -910,7 +899,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ | ||||
| 	if (!sector_size || !align_size) | ||||
| 		return -1; | ||||
|  | ||||
| 	strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN); | ||||
| 	strncpy(ss.name, ls_name, SANLK_NAME_LEN); | ||||
|  | ||||
| 	rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout); | ||||
| 	if (rv < 0) { | ||||
| @@ -935,7 +924,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ | ||||
| 		return rv; | ||||
| 	} | ||||
|  | ||||
| 	memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN); | ||||
|  | ||||
| 	rv = sanlock_write_resource(&rd.rs, 0, 0, 0); | ||||
| 	if (rv < 0) { | ||||
| @@ -960,7 +949,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ | ||||
| 		return rv; | ||||
| 	} | ||||
|  | ||||
| 	memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN); | ||||
|  | ||||
| 	rv = sanlock_write_resource(&rd.rs, 0, 0, 0); | ||||
| 	if (rv < 0) { | ||||
| @@ -994,7 +983,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN); | ||||
| 		strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN); | ||||
|  | ||||
| 		rv = sanlock_write_resource(&rd.rs, 0, 0, 0); | ||||
| 		if (rv) { | ||||
| @@ -1020,7 +1009,7 @@ int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r) | ||||
| 	if (daemon_test) | ||||
| 		return 0; | ||||
|  | ||||
| 	strcpy_name_len(rs->name, (char *)"#unused", SANLK_NAME_LEN); | ||||
| 	strcpy(rs->name, "#unused"); | ||||
|  | ||||
| 	rv = sanlock_write_resource(rs, 0, 0, 0); | ||||
| 	if (rv < 0) { | ||||
| @@ -1054,14 +1043,14 @@ int lm_ex_disable_gl_sanlock(struct lockspace *ls) | ||||
| 	memset(&rd1, 0, sizeof(rd1)); | ||||
| 	memset(&rd2, 0, sizeof(rd2)); | ||||
|  | ||||
| 	strcpy_name_len(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strcpy_name_len(rd1.rs.name, (char *)R_NAME_GL, SANLK_NAME_LEN); | ||||
| 	strncpy(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd1.rs.name, R_NAME_GL, SANLK_NAME_LEN); | ||||
|  | ||||
| 	strcpy_name_len(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strcpy_name_len(rd2.rs.name, (char *)R_NAME_GL_DISABLED, SANLK_NAME_LEN); | ||||
| 	strncpy(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd2.rs.name, R_NAME_GL_DISABLED, SANLK_NAME_LEN); | ||||
|  | ||||
| 	rd1.rs.num_disks = 1; | ||||
| 	memcpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1); | ||||
| 	strncpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1); | ||||
| 	rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN; | ||||
| 	 | ||||
| 	rd1.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : | ||||
| @@ -1123,11 +1112,11 @@ int lm_able_gl_sanlock(struct lockspace *ls, int enable) | ||||
|  | ||||
| 	memset(&rd, 0, sizeof(rd)); | ||||
|  | ||||
| 	strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strcpy_name_len(rd.rs.name, (char *)gl_name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.name, gl_name, SANLK_NAME_LEN); | ||||
|  | ||||
| 	rd.rs.num_disks = 1; | ||||
| 	memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1); | ||||
| 	strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1); | ||||
| 	rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN; | ||||
| 	rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : | ||||
| 						   (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M); | ||||
| @@ -1164,12 +1153,12 @@ static int gl_is_enabled(struct lockspace *ls, struct lm_sanlock *lms) | ||||
|  | ||||
| 	memset(&rd, 0, sizeof(rd)); | ||||
|  | ||||
| 	strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
|  | ||||
| 	/* leave rs.name empty, it is what we're checking */ | ||||
|  | ||||
| 	rd.rs.num_disks = 1; | ||||
| 	memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1); | ||||
| 	strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1); | ||||
|  | ||||
| 	offset = lms->align_size * GL_LOCK_BEGIN; | ||||
| 	rd.rs.disks[0].offset = offset; | ||||
| @@ -1235,9 +1224,9 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int * | ||||
|  | ||||
| 	memset(&rd, 0, sizeof(rd)); | ||||
|  | ||||
| 	strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	rd.rs.num_disks = 1; | ||||
| 	memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1); | ||||
| 	strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1); | ||||
| 	rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : | ||||
| 						   (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M); | ||||
|  | ||||
| @@ -1422,7 +1411,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls) | ||||
| 	memcpy(lms->ss.name, lsname, SANLK_NAME_LEN); | ||||
| 	lms->ss.host_id_disk.offset = 0; | ||||
| 	lms->ss.host_id = ls->host_id; | ||||
| 	memcpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1); | ||||
| 	strncpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1); | ||||
|  | ||||
| 	if (daemon_test) { | ||||
| 		if (!gl_lsname_sanlock[0]) { | ||||
| @@ -1514,7 +1503,8 @@ out: | ||||
| fail: | ||||
| 	if (lms && lms->sock) | ||||
| 		close(lms->sock); | ||||
| 	free(lms); | ||||
| 	if (lms) | ||||
| 		free(lms); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| @@ -1576,8 +1566,10 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg) | ||||
| 		goto out; | ||||
|  | ||||
| 	rv = sanlock_rem_lockspace(&lms->ss, 0); | ||||
| 	if (rv < 0) | ||||
| 	if (rv < 0) { | ||||
| 		log_error("S %s rem_lockspace_san error %d", ls->name, rv); | ||||
| 		return rv; | ||||
| 	} | ||||
|  | ||||
| 	if (free_vg) { | ||||
| 		/* | ||||
| @@ -1586,7 +1578,7 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg) | ||||
| 		 * This shouldn't be generally necessary, but there may some races | ||||
| 		 * between nodes starting and removing a vg which this could help. | ||||
| 		 */ | ||||
| 		strcpy_name_len(lms->ss.name, (char *)"#unused", SANLK_NAME_LEN); | ||||
| 		strncpy(lms->ss.name, "#unused", SANLK_NAME_LEN); | ||||
|  | ||||
| 		rv = sanlock_write_lockspace(&lms->ss, 0, 0, sanlock_io_timeout); | ||||
| 		if (rv < 0) { | ||||
| @@ -1614,8 +1606,8 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r) | ||||
| 	struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data; | ||||
| 	struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data; | ||||
|  | ||||
| 	strcpy_name_len(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strcpy_name_len(rds->rs.name, r->name, SANLK_NAME_LEN); | ||||
| 	strncpy(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN); | ||||
| 	strncpy(rds->rs.name, r->name, SANLK_NAME_LEN); | ||||
| 	rds->rs.num_disks = 1; | ||||
| 	memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN); | ||||
| 	rds->rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M); | ||||
| @@ -1642,7 +1634,8 @@ int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r) | ||||
|  | ||||
| 	/* FIXME: assert r->mode == UN or unlock if it's not? */ | ||||
|  | ||||
| 	free(rds->vb); | ||||
| 	if (rds->vb) | ||||
| 		free(rds->vb); | ||||
|  | ||||
| 	memset(rds, 0, sizeof(struct rd_sanlock)); | ||||
| 	r->lm_init = 0; | ||||
| @@ -1658,7 +1651,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, | ||||
| 	struct sanlk_options opt; | ||||
| 	uint64_t lock_lv_offset; | ||||
| 	uint32_t flags = 0; | ||||
| 	struct val_blk vb = { 0 }; | ||||
| 	struct val_blk vb; | ||||
| 	int added = 0; | ||||
| 	int rv; | ||||
|  | ||||
| @@ -2044,7 +2037,7 @@ static int release_rename(struct lockspace *ls, struct resource *r) | ||||
| 	res1 = (struct sanlk_resource *)&rd1; | ||||
| 	res2 = (struct sanlk_resource *)&rd2; | ||||
|  | ||||
| 	strcpy_name_len(res2->name, (char *)"invalid_removed", SANLK_NAME_LEN); | ||||
| 	strcpy(res2->name, "invalid_removed"); | ||||
|  | ||||
| 	res_args[0] = res1; | ||||
| 	res_args[1] = res2; | ||||
| @@ -2237,8 +2230,8 @@ int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin) | ||||
|  | ||||
| 		ls->lm_type = LD_LM_SANLOCK; | ||||
| 		ls->host_id = ss->host_id; | ||||
| 		memcpy(ls->name, ss->name, SANLK_NAME_LEN); | ||||
| 		memcpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), SANLK_NAME_LEN - strlen(LVM_LS_PREFIX)); | ||||
| 		strncpy(ls->name, ss->name, MAX_NAME); | ||||
| 		strncpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), MAX_NAME); | ||||
| 		list_add_tail(&ls->list, ls_rejoin); | ||||
|  | ||||
| 		ss++; | ||||
|   | ||||
| @@ -19,11 +19,12 @@ SOURCES = lvmpolld-core.c lvmpolld-data-utils.c lvmpolld-cmd-utils.c | ||||
|  | ||||
| TARGETS = lvmpolld | ||||
|  | ||||
| CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) | ||||
| CFLOW_TARGET := $(TARGETS) | ||||
|  | ||||
| .PHONY: install_lvmpolld | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
| CFLOW_TARGET = lvmpolld | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| CFLAGS += $(EXTRA_EXEC_CFLAGS) | ||||
|   | ||||
| @@ -92,12 +92,6 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary, | ||||
| 	if (!add_to_cmd_arr(&cmd_argv, "-An", &i)) | ||||
| 		goto err; | ||||
|  | ||||
| 	if (pdlv->devicesfile) { | ||||
| 		if (!add_to_cmd_arr(&cmd_argv, "--devicesfile", &i) || | ||||
| 		    !add_to_cmd_arr(&cmd_argv, pdlv->devicesfile, &i)) | ||||
| 			goto err; | ||||
| 	} | ||||
|  | ||||
| 	/* terminating NULL */ | ||||
| 	if (!add_to_cmd_arr(&cmd_argv, NULL, &i)) | ||||
| 		goto err; | ||||
|   | ||||
| @@ -149,7 +149,7 @@ static void _lvmpolld_global_unlock(struct lvmpolld_state *ls) | ||||
| static int _fini(struct daemon_state *s) | ||||
| { | ||||
| 	int done; | ||||
| 	const struct timespec t = { .tv_nsec = 10000000 }; /* .01 sec */ | ||||
| 	const struct timespec t = { .tv_nsec = 250000000 }; /* .25 sec */ | ||||
| 	struct lvmpolld_state *ls = s->private; | ||||
|  | ||||
| 	DEBUGLOG(s, "fini"); | ||||
| @@ -236,7 +236,9 @@ static int poll_for_output(struct lvmpolld_lv *pdlv, struct lvmpolld_thread_data | ||||
| 	} | ||||
|  | ||||
| 	while (1) { | ||||
| 		r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000); | ||||
| 		do { | ||||
| 			r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000); | ||||
| 		} while (r < 0 && errno == EINTR); | ||||
|  | ||||
| 		DEBUGLOG(pdlv->ls, "%s: %s %d", PD_LOG_PREFIX, "poll() returned", r); | ||||
| 		if (r < 0) { | ||||
| @@ -372,7 +374,7 @@ static void debug_print(struct lvmpolld_state *ls, const char * const* ptr) | ||||
|  | ||||
| static void *fork_and_poll(void *args) | ||||
| { | ||||
| 	int outfd, errfd, state = 0; | ||||
| 	int outfd, errfd, state; | ||||
| 	struct lvmpolld_thread_data *data; | ||||
| 	pid_t r; | ||||
|  | ||||
| @@ -553,15 +555,14 @@ static struct lvmpolld_lv *construct_pdlv(request req, struct lvmpolld_state *ls | ||||
| 				     const char *interval, const char *id, | ||||
| 				     const char *vgname, const char *lvname, | ||||
| 				     const char *sysdir, enum poll_type type, | ||||
| 				     unsigned abort_polling, unsigned uinterval, | ||||
| 				     const char *devicesfile) | ||||
| 				     unsigned abort_polling, unsigned uinterval) | ||||
| { | ||||
| 	const char **cmdargv, **cmdenvp; | ||||
| 	struct lvmpolld_lv *pdlv; | ||||
| 	unsigned handle_missing_pvs = daemon_request_int(req, LVMPD_PARM_HANDLE_MISSING_PVS, 0); | ||||
|  | ||||
| 	pdlv = pdlv_create(ls, id, vgname, lvname, sysdir, type, | ||||
| 			   interval, uinterval, pdst, devicesfile); | ||||
| 			   interval, uinterval, pdst); | ||||
|  | ||||
| 	if (!pdlv) { | ||||
| 		ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to create internal LV data structure."); | ||||
| @@ -620,7 +621,6 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re | ||||
| 	const char *lvname = daemon_request_str(req, LVMPD_PARM_LVNAME, NULL); | ||||
| 	const char *vgname = daemon_request_str(req, LVMPD_PARM_VGNAME, NULL); | ||||
| 	const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL); | ||||
| 	const char *devicesfile = daemon_request_str(req, LVMPD_PARM_DEVICESFILE, NULL); | ||||
| 	unsigned abort_polling = daemon_request_int(req, LVMPD_PARM_ABORT, 0); | ||||
|  | ||||
| 	assert(type < POLL_TYPE_MAX); | ||||
| @@ -680,7 +680,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re | ||||
| 		pdlv->init_rq_count++; /* safe. protected by store lock */ | ||||
| 	} else { | ||||
| 		pdlv = construct_pdlv(req, ls, pdst, interval, id, vgname, | ||||
| 				      lvname, sysdir, type, abort_polling, 2 * uinterval, devicesfile); | ||||
| 				      lvname, sysdir, type, abort_polling, 2 * uinterval); | ||||
| 		if (!pdlv) { | ||||
| 			pdst_unlock(pdst); | ||||
| 			free(id); | ||||
|   | ||||
| @@ -93,13 +93,11 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id, | ||||
| 			   const char *vgname, const char *lvname, | ||||
| 			   const char *sysdir, enum poll_type type, | ||||
| 			   const char *sinterval, unsigned pdtimeout, | ||||
| 			   struct lvmpolld_store *pdst, | ||||
| 			   const char *devicesfile) | ||||
| 			   struct lvmpolld_store *pdst) | ||||
| { | ||||
| 	char *lvmpolld_id = strdup(id), /* copy */ | ||||
| 	     *full_lvname = _construct_full_lvname(vgname, lvname), /* copy */ | ||||
| 	     *lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */ | ||||
| 	char *devicesfile_dup = devicesfile ? strdup(devicesfile) : NULL; | ||||
|  | ||||
| 	struct lvmpolld_lv tmp = { | ||||
| 		.ls = ls, | ||||
| @@ -107,7 +105,6 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id, | ||||
| 		.lvmpolld_id = lvmpolld_id, | ||||
| 		.lvid = _get_lvid(lvmpolld_id, sysdir), | ||||
| 		.lvname = full_lvname, | ||||
| 		.devicesfile = devicesfile_dup, | ||||
| 		.lvm_system_dir_env = lvm_system_dir_env, | ||||
| 		.sinterval = strdup(sinterval), /* copy */ | ||||
| 		.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout, | ||||
| @@ -127,7 +124,6 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id, | ||||
| 	return pdlv; | ||||
|  | ||||
| err: | ||||
| 	free((void *)devicesfile_dup); | ||||
| 	free((void *)full_lvname); | ||||
| 	free((void *)lvmpolld_id); | ||||
| 	free((void *)lvm_system_dir_env); | ||||
| @@ -140,7 +136,6 @@ err: | ||||
| void pdlv_destroy(struct lvmpolld_lv *pdlv) | ||||
| { | ||||
| 	free((void *)pdlv->lvmpolld_id); | ||||
| 	free((void *)pdlv->devicesfile); | ||||
| 	free((void *)pdlv->lvname); | ||||
| 	free((void *)pdlv->sinterval); | ||||
| 	free((void *)pdlv->lvm_system_dir_env); | ||||
|   | ||||
| @@ -49,7 +49,6 @@ struct lvmpolld_lv { | ||||
| 	const enum poll_type type; | ||||
| 	const char *const lvid; | ||||
| 	const char *const lvmpolld_id; | ||||
| 	const char *const devicesfile; | ||||
| 	const char *const lvname; /* full vg/lv name */ | ||||
| 	const unsigned pdtimeout; /* in seconds */ | ||||
| 	const char *const sinterval; | ||||
| @@ -102,8 +101,7 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id, | ||||
| 			   const char *vgname, const char *lvname, | ||||
| 			   const char *sysdir, enum poll_type type, | ||||
| 			   const char *sinterval, unsigned pdtimeout, | ||||
| 			   struct lvmpolld_store *pdst, | ||||
| 			   const char *devicesfile); | ||||
| 			   struct lvmpolld_store *pdst); | ||||
|  | ||||
| /* only call with appropriate struct lvmpolld_store lock held */ | ||||
| void pdlv_destroy(struct lvmpolld_lv *pdlv); | ||||
|   | ||||
| @@ -35,7 +35,6 @@ | ||||
| #define LVMPD_PARM_SYSDIR		"sysdir" | ||||
| #define LVMPD_PARM_VALUE		"value" /* either retcode or signal value */ | ||||
| #define LVMPD_PARM_VGNAME		"vgname" | ||||
| #define LVMPD_PARM_DEVICESFILE		"devicesfile" | ||||
|  | ||||
| #define LVMPD_RESP_FAILED	"failed" | ||||
| #define LVMPD_RESP_FINISHED	"finished" | ||||
|   | ||||
| @@ -121,9 +121,7 @@ enum { | ||||
|  | ||||
| 	DM_DEVICE_SET_GEOMETRY, | ||||
|  | ||||
| 	DM_DEVICE_ARM_POLL, | ||||
|  | ||||
| 	DM_DEVICE_GET_TARGET_VERSION | ||||
| 	DM_DEVICE_ARM_POLL | ||||
| }; | ||||
|  | ||||
| /* | ||||
| @@ -164,30 +162,20 @@ struct dm_info { | ||||
| struct dm_deps { | ||||
| 	uint32_t count; | ||||
| 	uint32_t filler; | ||||
| 	uint64_t device[]; | ||||
| 	uint64_t device[0]; | ||||
| }; | ||||
|  | ||||
| struct dm_names { | ||||
| 	uint64_t dev; | ||||
| 	uint32_t next;		/* Offset to next struct from start of this struct */ | ||||
| 	char name[]; | ||||
| }; | ||||
|  | ||||
| struct dm_active_device { | ||||
| 	struct dm_list list; | ||||
| 	int major; | ||||
| 	int minor; | ||||
| 	char *name;	/* device name */ | ||||
|  | ||||
| 	uint32_t event_nr; /* valid when DM_DEVICE_LIST_HAS_EVENT_NR is set */ | ||||
| 	char *uuid;	/* valid uuid when DM_DEVICE_LIST_HAS_UUID is set */ | ||||
| 	char name[0]; | ||||
| }; | ||||
|  | ||||
| struct dm_versions { | ||||
| 	uint32_t next;		/* Offset to next struct from start of this struct */ | ||||
| 	uint32_t version[3]; | ||||
|  | ||||
| 	char name[]; | ||||
| 	char name[0]; | ||||
| }; | ||||
|  | ||||
| int dm_get_library_version(char *version, size_t size); | ||||
| @@ -220,25 +208,6 @@ const char *dm_task_get_message_response(struct dm_task *dmt); | ||||
|  */ | ||||
| const char *dm_task_get_name(const struct dm_task *dmt); | ||||
| struct dm_names *dm_task_get_names(struct dm_task *dmt); | ||||
| /* | ||||
|  * Retrieve the list of devices and put them into easily accessible | ||||
|  * struct dm_active_device list elements. | ||||
|  * devs_features provides flag-set with used features so it's easy to check | ||||
|  * whether the kernel provides i.e. UUID info together with DM names | ||||
|  */ | ||||
| #define DM_DEVICE_LIST_HAS_EVENT_NR	1 | ||||
| #define DM_DEVICE_LIST_HAS_UUID		2 | ||||
| int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list, | ||||
| 			    unsigned *devs_features); | ||||
| /* | ||||
|  * -1: no idea about uuid (not provided by DM_DEVICE_LIST ioctl) | ||||
|  *  0: uuid not present | ||||
|  *  1: listed and dm_active_device will be set for not NULL pointer | ||||
|  */ | ||||
| int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid, | ||||
| 				const struct dm_active_device **dev); | ||||
| /* Release all associated memory with list of active DM devices */ | ||||
| void dm_device_list_destroy(struct dm_list **devs_list); | ||||
|  | ||||
| int dm_task_set_ro(struct dm_task *dmt); | ||||
| int dm_task_set_newname(struct dm_task *dmt, const char *newname); | ||||
| @@ -263,8 +232,6 @@ int dm_task_suppress_identical_reload(struct dm_task *dmt); | ||||
| int dm_task_secure_data(struct dm_task *dmt); | ||||
| int dm_task_retry_remove(struct dm_task *dmt); | ||||
| int dm_task_deferred_remove(struct dm_task *dmt); | ||||
| int dm_task_ima_measurement(struct dm_task *dmt); | ||||
| void dm_task_skip_reload_params_compare(struct dm_task *dmt); | ||||
|  | ||||
| /* | ||||
|  * Record timestamp immediately after the ioctl returns. | ||||
| @@ -414,7 +381,7 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params, | ||||
| 			struct dm_status_cache **status); | ||||
|  | ||||
| struct dm_status_writecache { | ||||
| 	uint64_t error; | ||||
| 	uint32_t error; | ||||
| 	uint64_t total_blocks; | ||||
| 	uint64_t free_blocks; | ||||
| 	uint64_t writeback_blocks; | ||||
| @@ -423,15 +390,6 @@ struct dm_status_writecache { | ||||
| int dm_get_status_writecache(struct dm_pool *mem, const char *params, | ||||
|                              struct dm_status_writecache **status); | ||||
|  | ||||
| struct dm_status_integrity { | ||||
| 	uint64_t number_of_mismatches; | ||||
| 	uint64_t provided_data_sectors; | ||||
| 	uint64_t recalc_sector; | ||||
| }; | ||||
|  | ||||
| int dm_get_status_integrity(struct dm_pool *mem, const char *params, | ||||
|                             struct dm_status_integrity **status); | ||||
|  | ||||
| /* | ||||
|  * Parse params from STATUS call for snapshot target | ||||
|  * | ||||
| @@ -981,8 +939,6 @@ struct writecache_settings { | ||||
| 	uint64_t autocommit_time; /* in milliseconds */ | ||||
| 	uint32_t fua; | ||||
| 	uint32_t nofua; | ||||
| 	uint32_t cleaner; | ||||
| 	uint32_t max_age; | ||||
|  | ||||
| 	/* | ||||
| 	 * Allow an unrecognized key and its val to be passed to the kernel for | ||||
| @@ -1002,8 +958,6 @@ struct writecache_settings { | ||||
| 	unsigned autocommit_time_set:1; | ||||
| 	unsigned fua_set:1; | ||||
| 	unsigned nofua_set:1; | ||||
| 	unsigned cleaner_set:1; | ||||
| 	unsigned max_age_set:1; | ||||
| }; | ||||
|  | ||||
| int dm_tree_node_add_writecache_target(struct dm_tree_node *node, | ||||
| @@ -1014,42 +968,12 @@ int dm_tree_node_add_writecache_target(struct dm_tree_node *node, | ||||
| 				uint32_t writecache_block_size, | ||||
| 				struct writecache_settings *settings); | ||||
|  | ||||
| struct integrity_settings { | ||||
| 	char mode[8]; | ||||
| 	uint32_t tag_size; | ||||
| 	uint32_t block_size;       /* optional table param always set by lvm */ | ||||
| 	const char *internal_hash; /* optional table param always set by lvm */ | ||||
|  | ||||
| 	uint32_t journal_sectors; | ||||
| 	uint32_t interleave_sectors; | ||||
| 	uint32_t buffer_sectors; | ||||
| 	uint32_t journal_watermark; | ||||
| 	uint32_t commit_time; | ||||
| 	uint32_t bitmap_flush_interval; | ||||
| 	uint64_t sectors_per_bit; | ||||
|  | ||||
| 	unsigned journal_sectors_set:1; | ||||
| 	unsigned interleave_sectors_set:1; | ||||
| 	unsigned buffer_sectors_set:1; | ||||
| 	unsigned journal_watermark_set:1; | ||||
| 	unsigned commit_time_set:1; | ||||
| 	unsigned bitmap_flush_interval_set:1; | ||||
| 	unsigned sectors_per_bit_set:1; | ||||
| }; | ||||
|  | ||||
| int dm_tree_node_add_integrity_target(struct dm_tree_node *node, | ||||
| 				uint64_t size, | ||||
| 				const char *origin_uuid, | ||||
| 				const char *meta_uuid, | ||||
| 				struct integrity_settings *settings, | ||||
| 				int recalculate); | ||||
|  | ||||
| /* | ||||
|  * VDO target | ||||
|  */ | ||||
| int dm_tree_node_add_vdo_target(struct dm_tree_node *node, | ||||
| 				uint64_t size, | ||||
| 				const char *vdo_pool_name, | ||||
| 				const char *data_uuid, | ||||
| 				uint64_t data_size, | ||||
| 				const struct dm_vdo_target_params *param); | ||||
| @@ -1102,10 +1026,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node, | ||||
| #define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128)) | ||||
| #define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152)) | ||||
| /* | ||||
|  * Max supported size for thin pool metadata device (17045913600 bytes) | ||||
|  * Max supported size for thin pool  metadata device (17112760320 bytes) | ||||
|  * Limitation is hardcoded into the kernel and bigger device size | ||||
|  * is not accepted. | ||||
|  * drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS | ||||
|  * But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly | ||||
|  * Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9))) | ||||
|  */ | ||||
| #define DM_THIN_MAX_METADATA_SIZE   (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024) | ||||
|  | ||||
| @@ -1118,16 +1042,6 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node, | ||||
| 				      uint64_t low_water_mark, | ||||
| 				      unsigned skip_block_zeroing); | ||||
|  | ||||
| int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node, | ||||
| 					 uint64_t size, | ||||
| 					 uint64_t transaction_id, | ||||
| 					 const char *metadata_uuid, | ||||
| 					 const char *pool_uuid, | ||||
| 					 uint32_t data_block_size, | ||||
| 					 uint64_t low_water_mark, | ||||
| 					 unsigned skip_block_zeroing, | ||||
| 					 unsigned crop_metadata); | ||||
|  | ||||
| /* Supported messages for thin provision target */ | ||||
| typedef enum { | ||||
| 	DM_THIN_MESSAGE_CREATE_SNAP,		/* device_id, origin_id */ | ||||
| @@ -1358,7 +1272,7 @@ int dm_bit_get_next(dm_bitset_t bs, int last_bit); | ||||
| int dm_bit_get_last(dm_bitset_t bs); | ||||
| int dm_bit_get_prev(dm_bitset_t bs, int last_bit); | ||||
|  | ||||
| #define DM_BITS_PER_INT ((unsigned)sizeof(int) * CHAR_BIT) | ||||
| #define DM_BITS_PER_INT (sizeof(int) * CHAR_BIT) | ||||
|  | ||||
| #define dm_bit(bs, i) \ | ||||
|    ((bs)[((i) / DM_BITS_PER_INT) + 1] & (0x1 << ((i) & (DM_BITS_PER_INT - 1)))) | ||||
|   | ||||
| @@ -150,8 +150,7 @@ dm_bitset_t dm_bitset_parse_list(const char *str, struct dm_pool *mem, | ||||
| 				 size_t min_num_bits) | ||||
| { | ||||
| 	unsigned a, b; | ||||
| 	int c, old_c, totaldigits, ndigits; | ||||
| 	size_t nmaskbits; | ||||
| 	int c, old_c, totaldigits, ndigits, nmaskbits; | ||||
| 	int at_start, in_range; | ||||
| 	dm_bitset_t mask = NULL; | ||||
| 	const char *start = str; | ||||
| @@ -243,3 +242,18 @@ bad: | ||||
| 	} | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| /* | ||||
|  * Maintain backward compatibility with older versions that did not | ||||
|  * accept a 'min_num_bits' argument to dm_bitset_parse_list(). | ||||
|  */ | ||||
| dm_bitset_t dm_bitset_parse_list_v1_02_129(const char *str, struct dm_pool *mem); | ||||
| dm_bitset_t dm_bitset_parse_list_v1_02_129(const char *str, struct dm_pool *mem) | ||||
| { | ||||
| 	return dm_bitset_parse_list(str, mem, 0); | ||||
| } | ||||
|  | ||||
| #else /* if defined(__GNUC__) */ | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -119,9 +119,6 @@ static struct cmd_data _cmd_data_v4[] = { | ||||
| #ifdef DM_DEV_ARM_POLL | ||||
| 	{"armpoll",	DM_DEV_ARM_POLL,	{4, 36, 0}}, | ||||
| #endif | ||||
| #ifdef DM_GET_TARGET_VERSION | ||||
| 	{"target-version", DM_GET_TARGET_VERSION, {4, 41, 0}}, | ||||
| #endif | ||||
| }; | ||||
| /* *INDENT-ON* */ | ||||
|  | ||||
| @@ -205,7 +202,7 @@ static int _get_proc_number(const char *file, const char *name, | ||||
| 	} | ||||
|  | ||||
| 	while (getline(&line, &len, fl) != -1) { | ||||
| 		if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) { | ||||
| 		if (sscanf(line, "%d %255s\n", &num, &nm[0]) == 2) { | ||||
| 			if (!strcmp(name, nm)) { | ||||
| 				if (number) { | ||||
| 					*number = num; | ||||
| @@ -493,10 +490,7 @@ static void _dm_task_free_targets(struct dm_task *dmt) | ||||
|  | ||||
| 	for (t = dmt->head; t; t = n) { | ||||
| 		n = t->next; | ||||
| 		if (dmt->secure_data) | ||||
| 			_dm_zfree_string(t->params); | ||||
| 		else | ||||
| 			free(t->params); | ||||
| 		_dm_zfree_string(t->params); | ||||
| 		free(t->type); | ||||
| 		free(t); | ||||
| 	} | ||||
| @@ -507,10 +501,7 @@ static void _dm_task_free_targets(struct dm_task *dmt) | ||||
| void dm_task_destroy(struct dm_task *dmt) | ||||
| { | ||||
| 	_dm_task_free_targets(dmt); | ||||
| 	if (dmt->secure_data) | ||||
| 		_dm_zfree_dmi(dmt->dmi.v4); | ||||
| 	else | ||||
| 		free(dmt->dmi.v4); | ||||
| 	_dm_zfree_dmi(dmt->dmi.v4); | ||||
| 	free(dmt->dev_name); | ||||
| 	free(dmt->mangled_dev_name); | ||||
| 	free(dmt->newname); | ||||
| @@ -616,7 +607,8 @@ int dm_check_version(void) | ||||
| int dm_cookie_supported(void) | ||||
| { | ||||
| 	return (dm_check_version() && | ||||
| 		((_dm_version == 4) ? _dm_version_minor >= 15 : _dm_version > 4)); | ||||
| 		_dm_version >= 4 && | ||||
| 		_dm_version_minor >= 15); | ||||
| } | ||||
|  | ||||
| static int _dm_inactive_supported(void) | ||||
| @@ -754,159 +746,6 @@ struct dm_deps *dm_task_get_deps(struct dm_task *dmt) | ||||
| 				   dmt->dmi.v4->data_start); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Round up the ptr to an 8-byte boundary. | ||||
|  * Follow kernel pattern. | ||||
|  */ | ||||
| #define ALIGN_MASK 7 | ||||
| static size_t _align_val(size_t val) | ||||
| { | ||||
| 	return (val + ALIGN_MASK) & ~ALIGN_MASK; | ||||
| } | ||||
| static void *_align_ptr(void *ptr) | ||||
| { | ||||
| 	return (void *)_align_val((size_t)ptr); | ||||
| } | ||||
|  | ||||
| static int _check_has_event_nr(void) { | ||||
| 	static int _has_event_nr = -1; | ||||
|  | ||||
| 	if (_has_event_nr < 0) | ||||
| 		_has_event_nr = dm_check_version() && | ||||
| 			((_dm_version == 4) ?  _dm_version_minor >= 38 : _dm_version > 4); | ||||
|  | ||||
| 	return _has_event_nr; | ||||
| } | ||||
|  | ||||
| struct dm_device_list { | ||||
| 	struct dm_list list; | ||||
| 	unsigned count; | ||||
| 	unsigned features; | ||||
| 	struct dm_hash_table *uuids; | ||||
| }; | ||||
|  | ||||
| int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list, | ||||
| 			    unsigned *devs_features) | ||||
| { | ||||
| 	struct dm_names *names, *names1; | ||||
| 	struct dm_active_device *dm_dev, *dm_new_dev; | ||||
| 	struct dm_device_list *devs; | ||||
| 	unsigned next = 0; | ||||
| 	uint32_t *event_nr; | ||||
| 	char *uuid_ptr; | ||||
| 	size_t len; | ||||
| 	int cnt = 0; | ||||
|  | ||||
| 	*devs_list = 0; | ||||
| 	*devs_features = 0; | ||||
|  | ||||
| 	if ((names = dm_task_get_names(dmt)) && names->dev) { | ||||
| 		names1 = names; | ||||
| 		if (!names->name[0]) | ||||
| 			cnt = -1; /* -> cnt == 0 when no device is really present */ | ||||
| 		do { | ||||
| 			names1 = (struct dm_names *)((char *) names1 + next); | ||||
| 			next = names1->next; | ||||
| 			++cnt; | ||||
| 		} while (next); | ||||
| 	} | ||||
|  | ||||
| 	if (!(devs = malloc(sizeof(*devs) + (cnt ? cnt * sizeof(*dm_dev) + (char*)names1 - (char*)names + 256 : 0)))) | ||||
| 		return_0; | ||||
|  | ||||
| 	dm_list_init(&devs->list); | ||||
| 	devs->count = cnt; | ||||
| 	devs->uuids = NULL; | ||||
|  | ||||
| 	if (!cnt) { | ||||
| 		/* nothing in the list -> mark all features present */ | ||||
| 		*devs_features |= (DM_DEVICE_LIST_HAS_EVENT_NR | DM_DEVICE_LIST_HAS_UUID); | ||||
| 		goto out; /* nothing else to do */ | ||||
| 	} | ||||
|  | ||||
| 	dm_dev = (struct dm_active_device *) (devs + 1); | ||||
|  | ||||
| 	do { | ||||
| 		names = (struct dm_names *)((char *) names + next); | ||||
|  | ||||
| 		dm_dev->major = MAJOR(names->dev); | ||||
| 		dm_dev->minor = MINOR(names->dev); | ||||
| 		dm_dev->name = (char*)(dm_dev + 1); | ||||
| 		dm_dev->event_nr = 0; | ||||
| 		dm_dev->uuid = NULL; | ||||
|  | ||||
| 		strcpy(dm_dev->name, names->name); | ||||
| 		len = strlen(names->name) + 1; | ||||
|  | ||||
| 		dm_new_dev = _align_ptr((char*)(dm_dev + 1) + len); | ||||
| 		if (_check_has_event_nr()) { | ||||
| 			/* Hash for UUIDs with some more bits to reduce colision count */ | ||||
| 			if (!devs->uuids && !(devs->uuids = dm_hash_create(cnt * 8))) { | ||||
| 				free(devs); | ||||
| 				return_0; | ||||
| 			} | ||||
|  | ||||
| 			*devs_features |= DM_DEVICE_LIST_HAS_EVENT_NR; | ||||
| 			event_nr = _align_ptr(names->name + len); | ||||
| 			dm_dev->event_nr = event_nr[0]; | ||||
|  | ||||
| 			if ((event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) { | ||||
| 				*devs_features |= DM_DEVICE_LIST_HAS_UUID; | ||||
| 				uuid_ptr = _align_ptr(event_nr + 2); | ||||
| 				dm_dev->uuid = (char*) dm_new_dev; | ||||
| 				dm_new_dev = _align_ptr((char*)dm_new_dev + strlen(uuid_ptr) + 1); | ||||
| 				strcpy(dm_dev->uuid, uuid_ptr); | ||||
| 				if (!dm_hash_insert(devs->uuids, dm_dev->uuid, dm_dev)) | ||||
| 					return_0; // FIXME | ||||
| #if 0 | ||||
| 				log_debug("Active %s (%s) %d:%d event:%u", | ||||
| 					  dm_dev->name, dm_dev->uuid, | ||||
| 					  dm_dev->major, dm_dev->minor, dm_dev->event_nr); | ||||
| #endif | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		dm_list_add(&devs->list, &dm_dev->list); | ||||
| 		dm_dev = dm_new_dev; | ||||
| 		next = names->next; | ||||
| 	} while (next); | ||||
|  | ||||
|     out: | ||||
| 	*devs_list = (struct dm_list *)devs; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid, | ||||
| 				const struct dm_active_device **dev) | ||||
| { | ||||
| 	struct dm_device_list *devs = (struct dm_device_list *) devs_list; | ||||
| 	struct dm_active_device *dm_dev; | ||||
|  | ||||
| 	if (devs->uuids && | ||||
| 	    (dm_dev = dm_hash_lookup(devs->uuids, uuid))) { | ||||
| 		if (dev) | ||||
| 			*dev = dm_dev; | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void dm_device_list_destroy(struct dm_list **devs_list) | ||||
| { | ||||
| 	struct dm_device_list *devs = (struct dm_device_list *) *devs_list; | ||||
|  | ||||
| 	if (devs) { | ||||
| 		if (devs->uuids) | ||||
| 			dm_hash_destroy(devs->uuids); | ||||
|  | ||||
| 		free(devs); | ||||
| 		*devs_list = NULL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| struct dm_names *dm_task_get_names(struct dm_task *dmt) | ||||
| { | ||||
| 	return (struct dm_names *) (((char *) dmt->dmi.v4) + | ||||
| @@ -963,11 +802,6 @@ int dm_task_suppress_identical_reload(struct dm_task *dmt) | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| void dm_task_skip_reload_params_compare(struct dm_task *dmt) | ||||
| { | ||||
| 	dmt->skip_reload_params_compare = 1; | ||||
| } | ||||
|  | ||||
| int dm_task_set_add_node(struct dm_task *dmt, dm_add_node_t add_node) | ||||
| { | ||||
| 	switch (add_node) { | ||||
| @@ -1078,13 +912,6 @@ int dm_task_secure_data(struct dm_task *dmt) | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int dm_task_ima_measurement(struct dm_task *dmt) | ||||
| { | ||||
| 	dmt->ima_measurement = 1; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int dm_task_retry_remove(struct dm_task *dmt) | ||||
| { | ||||
| 	dmt->retry_remove = 1; | ||||
| @@ -1277,7 +1104,7 @@ static int _add_params(int type) | ||||
|  | ||||
| static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count) | ||||
| { | ||||
| 	size_t min_size; | ||||
| 	const size_t min_size = 16 * 1024; | ||||
| 	const int (*version)[3]; | ||||
|  | ||||
| 	struct dm_ioctl *dmi; | ||||
| @@ -1296,18 +1123,6 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count) | ||||
| 	else if (dmt->head) | ||||
| 		log_debug_activation(INTERNAL_ERROR "dm '%s' ioctl should not define parameters.", | ||||
| 				     _cmd_data_v4[dmt->type].name); | ||||
| 	switch (dmt->type) { | ||||
| 	case DM_DEVICE_CREATE: | ||||
| 	case DM_DEVICE_DEPS: | ||||
| 	case DM_DEVICE_LIST: | ||||
| 	case DM_DEVICE_STATUS: | ||||
| 	case DM_DEVICE_TABLE: | ||||
| 	case DM_DEVICE_TARGET_MSG: | ||||
| 		min_size = 16 * 1024; | ||||
| 		break; | ||||
| 	default: | ||||
| 		min_size = 2 * 1024; | ||||
| 	} | ||||
|  | ||||
| 	if (count && (dmt->sector || dmt->message)) { | ||||
| 		log_error("targets and message are incompatible"); | ||||
| @@ -1409,11 +1224,9 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count) | ||||
| 	/* FIXME Until resume ioctl supplies name, use dev_name for readahead */ | ||||
| 	if (DEV_NAME(dmt) && (dmt->type != DM_DEVICE_RESUME || dmt->minor < 0 || | ||||
| 			      dmt->major < 0)) | ||||
| 		/* coverity[buffer_size_warning] */ | ||||
| 		strncpy(dmi->name, DEV_NAME(dmt), sizeof(dmi->name)); | ||||
|  | ||||
| 	if (DEV_UUID(dmt)) | ||||
| 		/* coverity[buffer_size_warning] */ | ||||
| 		strncpy(dmi->uuid, DEV_UUID(dmt), sizeof(dmi->uuid)); | ||||
|  | ||||
| 	if (dmt->type == DM_DEVICE_SUSPEND) | ||||
| @@ -1452,14 +1265,6 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count) | ||||
| 		} | ||||
| 		dmi->flags |= DM_UUID_FLAG; | ||||
| 	} | ||||
| 	if (dmt->ima_measurement) { | ||||
| 		if (_dm_version_minor < 45) { | ||||
| 			log_error("WARNING: IMA measurement unsupported by " | ||||
| 				  "kernel.  Aborting operation."); | ||||
| 			goto bad; | ||||
| 		} | ||||
| 		dmi->flags |= DM_IMA_MEASUREMENT_FLAG; | ||||
| 	} | ||||
|  | ||||
| 	dmi->target_count = count; | ||||
| 	dmi->event_nr = dmt->event_nr; | ||||
| @@ -1521,7 +1326,7 @@ static int _process_mapper_dir(struct dm_task *dmt) | ||||
| 	} | ||||
|  | ||||
| 	if (closedir(d)) | ||||
| 		log_sys_debug("closedir", dir); | ||||
| 		log_sys_error("closedir", dir); | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
| @@ -1593,7 +1398,8 @@ static int _udev_complete(struct dm_task *dmt) | ||||
| static int _check_uevent_generated(struct dm_ioctl *dmi) | ||||
| { | ||||
| 	if (!dm_check_version() || | ||||
| 	    ((_dm_version == 4) ? _dm_version_minor < 17 : _dm_version < 4)) | ||||
| 	    _dm_version < 4 || | ||||
| 	    _dm_version_minor < 17) | ||||
| 		/* can't check, assume uevent is generated */ | ||||
| 		return 1; | ||||
|  | ||||
| @@ -1654,7 +1460,6 @@ static int _create_and_load_v4(struct dm_task *dmt) | ||||
| 	task->head = dmt->head; | ||||
| 	task->tail = dmt->tail; | ||||
| 	task->secure_data = dmt->secure_data; | ||||
| 	task->ima_measurement = dmt->ima_measurement; | ||||
|  | ||||
| 	r = dm_task_run(task); | ||||
|  | ||||
| @@ -1767,36 +1572,11 @@ static int _reload_with_suppression_v4(struct dm_task *dmt) | ||||
| 		len = strlen(t2->params); | ||||
| 		while (len-- > 0 && t2->params[len] == ' ') | ||||
| 			t2->params[len] = '\0'; | ||||
|  | ||||
| 		if (t1->start != t2->start) { | ||||
| 			log_debug("reload %u:%u diff start %llu %llu type %s %s", task->major, task->minor, | ||||
| 				   (unsigned long long)t1->start, (unsigned long long)t2->start, t1->type, t2->type); | ||||
| 		if ((t1->start != t2->start) || | ||||
| 		    (t1->length != t2->length) || | ||||
| 		    (strcmp(t1->type, t2->type)) || | ||||
| 		    (strcmp(t1->params, t2->params))) | ||||
| 			goto no_match; | ||||
| 		} | ||||
| 		if (t1->length != t2->length) { | ||||
| 			log_debug("reload %u:%u diff length %llu %llu type %s %s", task->major, task->minor, | ||||
| 				  (unsigned long long)t1->length, (unsigned long long)t2->length, t1->type, t2->type); | ||||
| 			goto no_match; | ||||
| 		} | ||||
| 		if (strcmp(t1->type, t2->type)) { | ||||
| 			log_debug("reload %u:%u diff type %s %s", task->major, task->minor, t1->type, t2->type); | ||||
| 			goto no_match; | ||||
| 		} | ||||
| 		if (strcmp(t1->params, t2->params)) { | ||||
| 			if (dmt->skip_reload_params_compare) { | ||||
| 				log_debug("reload %u:%u diff params ignore for type %s", | ||||
| 					  task->major, task->minor, t1->type); | ||||
| 				log_debug("reload params1 %s", t1->params); | ||||
| 				log_debug("reload params2 %s", t2->params); | ||||
| 			} else { | ||||
| 				log_debug("reload %u:%u diff params for type %s", | ||||
| 					  task->major, task->minor, t1->type); | ||||
| 				log_debug("reload params1 %s", t1->params); | ||||
| 				log_debug("reload params2 %s", t2->params); | ||||
| 				goto no_match; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		t1 = t1->next; | ||||
| 		t2 = t2->next; | ||||
| 	} | ||||
| @@ -1959,34 +1739,23 @@ static int _do_dm_ioctl_unmangle_string(char *str, const char *str_name, | ||||
| static int _dm_ioctl_unmangle_names(int type, struct dm_ioctl *dmi) | ||||
| { | ||||
| 	char buf[DM_NAME_LEN]; | ||||
| 	char buf_uuid[DM_UUID_LEN]; | ||||
| 	struct dm_name_list *names; | ||||
| 	struct dm_names *names; | ||||
| 	unsigned next = 0; | ||||
| 	char *name; | ||||
| 	int r = 1; | ||||
| 	uint32_t *event_nr; | ||||
| 	char *uuid_ptr; | ||||
| 	dm_string_mangling_t mangling_mode = dm_get_name_mangling_mode(); | ||||
|  | ||||
| 	if ((name = dmi->name)) | ||||
| 		r &= _do_dm_ioctl_unmangle_string(name, "name", buf, sizeof(buf), | ||||
| 						  mangling_mode); | ||||
| 		r = _do_dm_ioctl_unmangle_string(name, "name", buf, sizeof(buf), | ||||
| 						 dm_get_name_mangling_mode()); | ||||
|  | ||||
| 	if (type == DM_DEVICE_LIST && | ||||
| 	    ((names = ((struct dm_name_list *) ((char *)dmi + dmi->data_start)))) && | ||||
| 	    ((names = ((struct dm_names *) ((char *)dmi + dmi->data_start)))) && | ||||
| 	    names->dev) { | ||||
| 		do { | ||||
| 			names = (struct dm_name_list *)((char *) names + next); | ||||
| 			event_nr = _align_ptr(names->name + strlen(names->name) + 1); | ||||
| 			r &= _do_dm_ioctl_unmangle_string(names->name, "name", | ||||
| 							  buf, sizeof(buf), mangling_mode); | ||||
| 			/* Unmangle also UUID within same loop */ | ||||
| 			if (_check_has_event_nr() && | ||||
| 			    (event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) { | ||||
| 				uuid_ptr = _align_ptr(event_nr + 2); | ||||
| 				r &= _do_dm_ioctl_unmangle_string(uuid_ptr, "UUID", buf_uuid, | ||||
| 								  sizeof(buf_uuid), mangling_mode); | ||||
| 			} | ||||
| 			names = (struct dm_names *)((char *) names + next); | ||||
| 			r = _do_dm_ioctl_unmangle_string(names->name, "name", | ||||
| 							 buf, sizeof(buf), | ||||
| 							 dm_get_name_mangling_mode()); | ||||
| 			next = names->next; | ||||
| 		} while (next); | ||||
| 	} | ||||
| @@ -2079,7 +1848,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, | ||||
| 	} | ||||
|  | ||||
| 	log_debug_activation("dm %s %s%s %s%s%s %s%.0d%s%.0d%s" | ||||
| 			     "%s[ %s%s%s%s%s%s%s%s%s%s] %.0" PRIu64 " %s [%u] (*%u)", | ||||
| 			     "%s[ %s%s%s%s%s%s%s%s%s] %.0" PRIu64 " %s [%u] (*%u)", | ||||
| 			     _cmd_data_v4[dmt->type].name, | ||||
| 			     dmt->new_uuid ? "UUID " : "", | ||||
| 			     dmi->name, dmi->uuid, dmt->newname ? " " : "", | ||||
| @@ -2097,7 +1866,6 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, | ||||
| 			     dmt->retry_remove ? "retryremove " : "", | ||||
| 			     dmt->deferred_remove ? "deferredremove " : "", | ||||
| 			     dmt->secure_data ? "securedata " : "", | ||||
| 			     dmt->ima_measurement ? "ima_measurement " : "", | ||||
| 			     dmt->query_inactive_table ? "inactive " : "", | ||||
| 			     dmt->enable_checks ? "enablechecks " : "", | ||||
| 			     dmt->sector, _sanitise_message(dmt->message), | ||||
| @@ -2390,3 +2158,52 @@ void dm_lib_exit(void) | ||||
| 	_version_ok = 1; | ||||
| 	_version_checked = 0; | ||||
| } | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| /* | ||||
|  * Maintain binary backward compatibility. | ||||
|  * Version script mechanism works with 'gcc' compatible compilers only. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * This following code is here to retain ABI compatibility after adding | ||||
|  * the field deferred_remove to struct dm_info in version 1.02.89. | ||||
|  * | ||||
|  * Binaries linked against version 1.02.88 of libdevmapper or earlier | ||||
|  * will use this function that returns dm_info without the | ||||
|  * deferred_remove field. | ||||
|  * | ||||
|  * Binaries compiled against version 1.02.89 onwards will use | ||||
|  * the new function dm_task_get_info_with_deferred_remove due to the | ||||
|  * #define. | ||||
|  * | ||||
|  * N.B. Keep this function at the end of the file to make sure that | ||||
|  * no code in this file accidentally calls it. | ||||
|  */ | ||||
|  | ||||
| int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info); | ||||
| int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info) | ||||
| { | ||||
| 	struct dm_info new_info; | ||||
|  | ||||
| 	if (!dm_task_get_info(dmt, &new_info)) | ||||
| 		return 0; | ||||
|  | ||||
| 	memcpy(info, &new_info, offsetof(struct dm_info, deferred_remove)); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *info); | ||||
| int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *info) | ||||
| { | ||||
| 	struct dm_info new_info; | ||||
|  | ||||
| 	if (!dm_task_get_info(dmt, &new_info)) | ||||
| 		return 0; | ||||
|  | ||||
| 	memcpy(info, &new_info, offsetof(struct dm_info, internal_suspend)); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -59,7 +59,6 @@ struct dm_task { | ||||
| 	int skip_lockfs; | ||||
| 	int query_inactive_table; | ||||
| 	int suppress_identical_reload; | ||||
| 	int skip_reload_params_compare; | ||||
| 	dm_add_node_t add_node; | ||||
| 	uint64_t existing_table_size; | ||||
| 	int cookie_set; | ||||
| @@ -70,7 +69,6 @@ struct dm_task { | ||||
| 	int enable_checks; | ||||
| 	int expected_errno; | ||||
| 	int ioctl_errno; | ||||
| 	int ima_measurement; | ||||
|  | ||||
| 	int record_timestamp; | ||||
|  | ||||
|   | ||||
| @@ -338,7 +338,6 @@ struct dm_task *dm_task_create(int type) | ||||
| 	dmt->new_uuid = 0; | ||||
| 	dmt->secure_data = 0; | ||||
| 	dmt->record_timestamp = 0; | ||||
| 	dmt->ima_measurement = 0; | ||||
|  | ||||
| 	return dmt; | ||||
| } | ||||
| @@ -383,7 +382,7 @@ static int _find_dm_name_of_device(dev_t st_rdev, char *buf, size_t buf_len) | ||||
| 	} | ||||
|  | ||||
| 	if (closedir(d)) | ||||
| 		log_sys_debug("closedir", _dm_dir); | ||||
| 		log_sys_error("closedir", _dm_dir); | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
| @@ -513,7 +512,7 @@ int unmangle_string(const char *str, const char *str_name, size_t len, | ||||
| 	int strict = mode != DM_STRING_MANGLING_NONE; | ||||
| 	char str_rest[DM_NAME_LEN]; | ||||
| 	size_t i, j; | ||||
| 	unsigned int code; | ||||
| 	int code; | ||||
| 	int r = 0; | ||||
|  | ||||
| 	if (!str || !buf) | ||||
| @@ -932,7 +931,7 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size, | ||||
|  | ||||
| #ifdef HAVE_SELINUX | ||||
| static int _selabel_lookup(const char *path, mode_t mode, | ||||
| 			   char **scontext) | ||||
| 			   security_context_t *scontext) | ||||
| { | ||||
| #ifdef HAVE_SELINUX_LABEL_H | ||||
| 	if (!_selabel_handle && | ||||
| @@ -975,7 +974,7 @@ static int _is_selinux_enabled(void) | ||||
| int dm_prepare_selinux_context(const char *path, mode_t mode) | ||||
| { | ||||
| #ifdef HAVE_SELINUX | ||||
| 	char *scontext = NULL; | ||||
| 	security_context_t scontext = NULL; | ||||
|  | ||||
| 	if (_is_selinux_enabled() <= 0) | ||||
| 		return 1; | ||||
| @@ -1003,7 +1002,7 @@ int dm_prepare_selinux_context(const char *path, mode_t mode) | ||||
| int dm_set_selinux_context(const char *path, mode_t mode) | ||||
| { | ||||
| #ifdef HAVE_SELINUX | ||||
| 	char *scontext = NULL; | ||||
| 	security_context_t scontext = NULL; | ||||
|  | ||||
| 	if (_is_selinux_enabled() <= 0) | ||||
| 		return 1; | ||||
| @@ -1225,7 +1224,7 @@ int get_dev_node_read_ahead(const char *dev_name, uint32_t major, uint32_t minor | ||||
| 	int len; | ||||
| 	int r = 1; | ||||
| 	int fd; | ||||
| 	long read_ahead_long = 0; | ||||
| 	long read_ahead_long; | ||||
|  | ||||
| 	/* | ||||
| 	 * If we know the device number, use sysfs if we can. | ||||
| @@ -1921,7 +1920,7 @@ static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, si | ||||
| 			continue; | ||||
|  | ||||
| 		if ((sz = dm_snprintf(path, sizeof(path), "%sblock/%s/dev", | ||||
| 				      _sysfs_dir, name)) < 5) { | ||||
| 				      _sysfs_dir, name)) == -1) { | ||||
| 			log_warn("Couldn't create path for %s.", name); | ||||
| 			continue; | ||||
| 		} | ||||
| @@ -2013,8 +2012,7 @@ static int _sysfs_get_kernel_name(uint32_t major, uint32_t minor, char *buf, siz | ||||
| 			log_sys_error("readlink", sysfs_path); | ||||
| 		else { | ||||
| 			log_sys_debug("readlink", sysfs_path); | ||||
| 			r = _sysfs_find_kernel_name(major, minor, buf, buf_size); | ||||
| 			goto out; | ||||
| 			return _sysfs_find_kernel_name(major, minor, buf, buf_size); | ||||
| 		} | ||||
| 		goto bad; | ||||
| 	} | ||||
| @@ -2035,7 +2033,6 @@ static int _sysfs_get_kernel_name(uint32_t major, uint32_t minor, char *buf, siz | ||||
| 	strcpy(buf, name); | ||||
| 	r = 1; | ||||
| bad: | ||||
| out: | ||||
| 	free(temp_buf); | ||||
| 	free(sysfs_path); | ||||
|  | ||||
|   | ||||
| @@ -599,7 +599,7 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node * | ||||
| 		match(TOK_IDENTIFIER); | ||||
| 	} | ||||
|  | ||||
| 	if (!*str) { | ||||
| 	if (!strlen(str)) { | ||||
| 		log_error("Parse error at byte %" PRIptrdiff_t " (line %d): empty section identifier", | ||||
| 			  p->tb - p->fb + 1, p->line); | ||||
| 		return NULL; | ||||
| @@ -983,7 +983,7 @@ static const char *_find_config_str(const void *start, node_lookup_fn find_fn, | ||||
| 	} | ||||
|  | ||||
| 	if (fail) | ||||
| 		log_very_verbose("%s not found in config: defaulting to \"%s\"", | ||||
| 		log_very_verbose("%s not found in config: defaulting to %s", | ||||
| 				 path, fail); | ||||
| 	return fail; | ||||
| } | ||||
|   | ||||
| @@ -38,7 +38,6 @@ enum { | ||||
| 	SEG_STRIPED, | ||||
| 	SEG_ZERO, | ||||
| 	SEG_WRITECACHE, | ||||
| 	SEG_INTEGRITY, | ||||
| 	SEG_THIN_POOL, | ||||
| 	SEG_THIN, | ||||
| 	SEG_VDO, | ||||
| @@ -79,7 +78,6 @@ static const struct { | ||||
| 	{ SEG_STRIPED, "striped" }, | ||||
| 	{ SEG_ZERO, "zero"}, | ||||
| 	{ SEG_WRITECACHE, "writecache"}, | ||||
| 	{ SEG_INTEGRITY, "integrity"}, | ||||
| 	{ SEG_THIN_POOL, "thin-pool"}, | ||||
| 	{ SEG_THIN, "thin"}, | ||||
| 	{ SEG_VDO, "vdo" }, | ||||
| @@ -223,11 +221,6 @@ struct load_segment { | ||||
| 	int writecache_pmem;				/* writecache, 1 if pmem, 0 if ssd */ | ||||
| 	uint32_t writecache_block_size;			/* writecache, in bytes */ | ||||
| 	struct writecache_settings writecache_settings;	/* writecache */ | ||||
|  | ||||
| 	uint64_t integrity_data_sectors;		/* integrity (provided_data_sectors) */ | ||||
| 	struct dm_tree_node *integrity_meta_node;	/* integrity */ | ||||
| 	struct integrity_settings integrity_settings;	/* integrity */ | ||||
| 	int integrity_recalculate;			/* integrity */ | ||||
| }; | ||||
|  | ||||
| /* Per-device properties */ | ||||
| @@ -274,16 +267,6 @@ struct load_properties { | ||||
| 	 */ | ||||
| 	unsigned delay_resume_if_extended; | ||||
|  | ||||
| 	/* | ||||
| 	 * When comparing table lines to decide if a reload is | ||||
| 	 * needed, ignore any differences betwen the lvm device | ||||
| 	 * params and the kernel-reported device params. | ||||
| 	 * dm-integrity reports many internal parameters on the | ||||
| 	 * table line when lvm does not explicitly set them, | ||||
| 	 * causing lvm and the kernel to have differing params. | ||||
| 	 */ | ||||
| 	unsigned skip_reload_params_compare; | ||||
|  | ||||
| 	/* | ||||
| 	 * Call node_send_messages(), set to 2 if there are messages | ||||
| 	 * When != 0, it validates matching transaction id, thus thin-pools | ||||
| @@ -330,7 +313,16 @@ struct dm_tree_node { | ||||
| 	dm_node_callback_fn callback; | ||||
| 	void *callback_data; | ||||
|  | ||||
| 	int activated;                  /* tracks activation during preload */ | ||||
| 	/* | ||||
| 	 * TODO: | ||||
| 	 *	Add advanced code which tracks of send ioctls and their | ||||
| 	 *	proper revert operation for more advanced recovery | ||||
| 	 *	Current code serves mostly only to recovery when | ||||
| 	 *	thin pool metadata check fails and command would | ||||
| 	 *	have left active thin data and metadata subvolumes. | ||||
| 	 */ | ||||
| 	struct dm_list activated;	/* Head of activated nodes for preload revert */ | ||||
| 	struct dm_list activated_list;	/* List of activated nodes for preload revert */ | ||||
| }; | ||||
|  | ||||
| struct dm_tree { | ||||
| @@ -365,18 +357,19 @@ struct dm_tree *dm_tree_create(void) | ||||
| 	dtree->root.dtree = dtree; | ||||
| 	dm_list_init(&dtree->root.uses); | ||||
| 	dm_list_init(&dtree->root.used_by); | ||||
| 	dm_list_init(&dtree->root.activated); | ||||
| 	dtree->skip_lockfs = 0; | ||||
| 	dtree->no_flush = 0; | ||||
| 	dtree->mem = dmem; | ||||
| 	dtree->optional_uuid_suffixes = NULL; | ||||
|  | ||||
| 	if (!(dtree->devs = dm_hash_create(61))) { | ||||
| 	if (!(dtree->devs = dm_hash_create(8))) { | ||||
| 		log_error("dtree hash creation failed"); | ||||
| 		dm_pool_destroy(dtree->mem); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (!(dtree->uuids = dm_hash_create(31))) { | ||||
| 	if (!(dtree->uuids = dm_hash_create(32))) { | ||||
| 		log_error("dtree uuid hash creation failed"); | ||||
| 		dm_hash_destroy(dtree->devs); | ||||
| 		dm_pool_destroy(dtree->mem); | ||||
| @@ -549,6 +542,7 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree, | ||||
|  | ||||
| 	dm_list_init(&node->uses); | ||||
| 	dm_list_init(&node->used_by); | ||||
| 	dm_list_init(&node->activated); | ||||
| 	dm_list_init(&node->props.segs); | ||||
|  | ||||
| 	dev = MKDEV(info->major, info->minor); | ||||
| @@ -604,7 +598,7 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree, | ||||
| 	default_uuid_prefix = dm_uuid_prefix(); | ||||
| 	default_uuid_prefix_len = strlen(default_uuid_prefix); | ||||
|  | ||||
| 	if (suffix_list && (suffix_position = strrchr(uuid, '-'))) { | ||||
| 	if (suffix_list && (suffix_position = rindex(uuid, '-'))) { | ||||
| 		while ((suffix = suffix_list[i++])) { | ||||
| 			if (strcmp(suffix_position + 1, suffix)) | ||||
| 				continue; | ||||
| @@ -1578,37 +1572,8 @@ static int _thin_pool_node_message(struct dm_tree_node *dnode, struct thin_messa | ||||
| 	} | ||||
|  | ||||
| 	if (!_node_message(dnode->info.major, dnode->info.minor, | ||||
| 			   tm->expected_errno, buf)) { | ||||
| 		switch (m->type) { | ||||
| 		case DM_THIN_MESSAGE_CREATE_SNAP: | ||||
| 		case DM_THIN_MESSAGE_CREATE_THIN: | ||||
| 			if (errno == EEXIST) { | ||||
| 				/* | ||||
| 				 * ATM errno from ioctl() is preserved through code error path chain | ||||
| 				 * If this would ever change, another way need to be used to | ||||
| 				 * obtain result from failed DM message | ||||
| 				 */ | ||||
| 				log_error("Thin pool %s already contain thin device with device_id %u.", | ||||
| 					  _node_name(dnode), m->u.m_create_snap.device_id); | ||||
| 				/* | ||||
| 				 * TODO: | ||||
| 				 * | ||||
| 				 * Give some useful advice how to solve this problem, | ||||
| 				 * until lvconvert --repair can handle this automatically | ||||
| 				 */ | ||||
| 				log_error("Manual intervention may be required to remove device dev_id=%u in thin pool metadata.", | ||||
| 					  m->u.m_create_snap.device_id); | ||||
| 				log_error("Optionally new thin volume with device_id=%u can be manually added into a volume group.", | ||||
| 					  m->u.m_create_snap.device_id); | ||||
| 				log_warn("WARNING: When uncertain how to do this, contact support!"); | ||||
| 				return 0; | ||||
| 			} | ||||
| 			/* fall through */ | ||||
| 		default: | ||||
| 			return_0; | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| 			   tm->expected_errno, buf)) | ||||
| 		return_0; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| @@ -1655,15 +1620,6 @@ static int _thin_pool_node_send_messages(struct dm_tree_node *dnode, | ||||
| 	if (!have_messages || !send) | ||||
| 		return 1; /* transaction_id is matching */ | ||||
|  | ||||
| 	if (stp.fail || stp.read_only || stp.needs_check) { | ||||
| 		log_error("Cannot send messages to thin pool %s%s%s%s.", | ||||
| 			  _node_name(dnode), | ||||
| 			  stp.fail ? " in failed state" : "", | ||||
| 			  stp.read_only ? " with read only metadata" : "", | ||||
| 			  stp.needs_check ? " which needs check first" : ""); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	dm_list_iterate_items(tmsg, &seg->thin_messages) { | ||||
| 		if (!(_thin_pool_node_message(dnode, tmsg))) | ||||
| 			return_0; | ||||
| @@ -2125,7 +2081,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode, | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| static int _create_node(struct dm_tree_node *dnode, struct dm_tree_node *parent) | ||||
| static int _create_node(struct dm_tree_node *dnode) | ||||
| { | ||||
| 	int r = 0; | ||||
| 	struct dm_task *dmt; | ||||
| @@ -2174,15 +2130,38 @@ static int _create_node(struct dm_tree_node *dnode, struct dm_tree_node *parent) | ||||
| 				  "Unable to get DM task info for %s.", | ||||
| 				  dnode->name); | ||||
| 	} | ||||
|  | ||||
| 	if (r) | ||||
| 		dnode->activated = 1; | ||||
| out: | ||||
| 	dm_task_destroy(dmt); | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * _remove_node | ||||
|  * | ||||
|  * This function is only used to remove a DM device that has failed | ||||
|  * to load any table. | ||||
|  */ | ||||
| static int _remove_node(struct dm_tree_node *dnode) | ||||
| { | ||||
| 	if (!dnode->info.exists) | ||||
| 		return 1; | ||||
|  | ||||
| 	if (dnode->info.live_table || dnode->info.inactive_table) { | ||||
| 		log_error(INTERNAL_ERROR | ||||
| 			  "_remove_node called on device with loaded table(s)."); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!_deactivate_node(dnode->name, dnode->info.major, dnode->info.minor, | ||||
| 			      &dnode->dtree->cookie, dnode->udev_flags, 0)) { | ||||
| 		log_error("Failed to clean-up device with no table: %s.", | ||||
| 			  _node_name(dnode)); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node) | ||||
| { | ||||
| 	if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) { | ||||
| @@ -2371,7 +2350,7 @@ static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *s | ||||
|  | ||||
| 	EMIT_PARAMS(pos, " %u ", seg->mirror_area_count); | ||||
|  | ||||
| 	if (!_emit_areas_line(dmt, seg, params, paramsize, &pos)) | ||||
| 	if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (handle_errors) | ||||
| @@ -2573,7 +2552,7 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major, | ||||
| 	/* Print number of metadata/data device pairs */ | ||||
| 	EMIT_PARAMS(pos, " %u", area_count); | ||||
|  | ||||
| 	if (!_emit_areas_line(dmt, seg, params, paramsize, &pos)) | ||||
| 	if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0) | ||||
| 		return_0; | ||||
|  | ||||
| 	return 1; | ||||
| @@ -2633,7 +2612,7 @@ static int _cache_emit_segment_line(struct dm_task *dmt, | ||||
| 	EMIT_PARAMS(pos, " %s", name); | ||||
|  | ||||
| 	/* Do not pass migration_threshold 2048 which is default */ | ||||
| 	EMIT_PARAMS(pos, " %u", (seg->policy_argc + ((seg->migration_threshold != 2048) ? 1 : 0)) * 2); | ||||
| 	EMIT_PARAMS(pos, " %u", (seg->policy_argc + (seg->migration_threshold != 2048) ? 1 : 0) * 2); | ||||
| 	if (seg->migration_threshold != 2048) | ||||
| 		    EMIT_PARAMS(pos, " migration_threshold %u", seg->migration_threshold); | ||||
| 	if (seg->policy_settings) | ||||
| @@ -2674,10 +2653,6 @@ static int _writecache_emit_segment_line(struct dm_task *dmt, | ||||
| 		count += 1; | ||||
| 	if (seg->writecache_settings.nofua_set) | ||||
| 		count += 1; | ||||
| 	if (seg->writecache_settings.cleaner_set && seg->writecache_settings.cleaner) | ||||
| 		count += 1; | ||||
| 	if (seg->writecache_settings.max_age_set) | ||||
| 		count += 2; | ||||
| 	if (seg->writecache_settings.new_key) | ||||
| 		count += 2; | ||||
|  | ||||
| @@ -2721,14 +2696,6 @@ static int _writecache_emit_segment_line(struct dm_task *dmt, | ||||
| 		EMIT_PARAMS(pos, " nofua"); | ||||
| 	} | ||||
|  | ||||
| 	if (seg->writecache_settings.cleaner_set && seg->writecache_settings.cleaner) { | ||||
| 		EMIT_PARAMS(pos, " cleaner"); | ||||
| 	} | ||||
|  | ||||
| 	if (seg->writecache_settings.max_age_set) { | ||||
| 		EMIT_PARAMS(pos, " max_age %u", seg->writecache_settings.max_age); | ||||
| 	} | ||||
|  | ||||
| 	if (seg->writecache_settings.new_key) { | ||||
| 		EMIT_PARAMS(pos, " %s %s", | ||||
| 			seg->writecache_settings.new_key, | ||||
| @@ -2738,87 +2705,6 @@ static int _writecache_emit_segment_line(struct dm_task *dmt, | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int _integrity_emit_segment_line(struct dm_task *dmt, | ||||
| 				    struct load_segment *seg, | ||||
| 				    char *params, size_t paramsize) | ||||
| { | ||||
| 	struct integrity_settings *set = &seg->integrity_settings; | ||||
| 	int pos = 0; | ||||
| 	int count; | ||||
| 	char origin_dev[DM_FORMAT_DEV_BUFSIZE]; | ||||
| 	char meta_dev[DM_FORMAT_DEV_BUFSIZE]; | ||||
|  | ||||
| 	if (!_build_dev_string(origin_dev, sizeof(origin_dev), seg->origin)) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (seg->integrity_meta_node && | ||||
| 	    !_build_dev_string(meta_dev, sizeof(meta_dev), seg->integrity_meta_node)) | ||||
| 		return_0; | ||||
|  | ||||
| 	count = 3; /* block_size, internal_hash, fix_padding options are always passed */ | ||||
|  | ||||
| 	if (seg->integrity_meta_node) | ||||
| 		count++; | ||||
|  | ||||
| 	if (seg->integrity_recalculate) | ||||
| 		count++; | ||||
|  | ||||
| 	if (set->journal_sectors_set) | ||||
| 		count++; | ||||
| 	if (set->interleave_sectors_set) | ||||
| 		count++; | ||||
| 	if (set->buffer_sectors_set) | ||||
| 		count++; | ||||
| 	if (set->journal_watermark_set) | ||||
| 		count++; | ||||
| 	if (set->commit_time_set) | ||||
| 		count++; | ||||
| 	if (set->bitmap_flush_interval_set) | ||||
| 		count++; | ||||
| 	if (set->sectors_per_bit_set) | ||||
| 		count++; | ||||
|  | ||||
| 	EMIT_PARAMS(pos, "%s 0 %u %s %d fix_padding block_size:%u internal_hash:%s", | ||||
| 		    origin_dev, | ||||
| 		    set->tag_size, | ||||
| 		    set->mode, | ||||
| 		    count, | ||||
| 		    set->block_size, | ||||
| 		    set->internal_hash); | ||||
|  | ||||
| 	if (seg->integrity_meta_node) | ||||
| 		EMIT_PARAMS(pos, " meta_device:%s", meta_dev); | ||||
|  | ||||
| 	if (seg->integrity_recalculate) | ||||
| 		EMIT_PARAMS(pos, " recalculate"); | ||||
|  | ||||
| 	if (set->journal_sectors_set) | ||||
| 		EMIT_PARAMS(pos, " journal_sectors:%u", set->journal_sectors); | ||||
|  | ||||
| 	if (set->interleave_sectors_set) | ||||
| 		EMIT_PARAMS(pos, " ineterleave_sectors:%u", set->interleave_sectors); | ||||
|  | ||||
| 	if (set->buffer_sectors_set) | ||||
| 		EMIT_PARAMS(pos, " buffer_sectors:%u", set->buffer_sectors); | ||||
|  | ||||
| 	if (set->journal_watermark_set) | ||||
| 		EMIT_PARAMS(pos, " journal_watermark:%u", set->journal_watermark); | ||||
|  | ||||
| 	if (set->commit_time_set) | ||||
| 		EMIT_PARAMS(pos, " commit_time:%u", set->commit_time); | ||||
|  | ||||
| 	if (set->bitmap_flush_interval_set) | ||||
| 		EMIT_PARAMS(pos, " bitmap_flush_interval:%u", set->bitmap_flush_interval); | ||||
|  | ||||
| 	if (set->sectors_per_bit_set) | ||||
| 		EMIT_PARAMS(pos, " sectors_per_bit:%llu", (unsigned long long)set->sectors_per_bit); | ||||
|  | ||||
| 	if (!dm_task_secure_data(dmt)) | ||||
| 		stack; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int _thin_pool_emit_segment_line(struct dm_task *dmt, | ||||
| 					struct load_segment *seg, | ||||
| 					char *params, size_t paramsize) | ||||
| @@ -2869,13 +2755,12 @@ static int _vdo_emit_segment_line(struct dm_task *dmt, | ||||
| 		    "maxDiscard %u ack %u bio %u bioRotationInterval %u cpu %u hash %u logical %u physical %u", | ||||
| 		    data_dev, | ||||
| 		    seg->vdo_data_size / 8, // this parameter is in 4K units | ||||
| 		    seg->vdo_params.minimum_io_size * UINT32_C(512), //  sector to byte units | ||||
| 		    seg->vdo_params.minimum_io_size, | ||||
| 		    seg->vdo_params.block_map_cache_size_mb * UINT64_C(256),	// 1MiB -> 4KiB units | ||||
| 		    seg->vdo_params.block_map_era_length, | ||||
| 		    seg->vdo_params.use_metadata_hints ? "on" : "off" , | ||||
| 		    (seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_SYNC) ? "sync" : | ||||
| 			(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC) ? "async" : | ||||
| 			(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC_UNSAFE) ? "async-unsafe" : "auto", // policy | ||||
| 			(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC) ? "async" : "auto", // policy | ||||
| 		    seg->vdo_name, | ||||
| 		    seg->vdo_params.max_discard, | ||||
| 		    seg->vdo_params.ack_threads, | ||||
| @@ -2920,6 +2805,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major, | ||||
| 			      size_t paramsize) | ||||
| { | ||||
| 	int pos = 0; | ||||
| 	int r; | ||||
| 	int target_type_is_raid = 0; | ||||
| 	char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE]; | ||||
|  | ||||
| @@ -2930,7 +2816,8 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major, | ||||
| 		break; | ||||
| 	case SEG_MIRRORED: | ||||
| 		/* Mirrors are pretty complicated - now in separate function */ | ||||
| 		if (!_mirror_emit_segment_line(dmt, seg, params, paramsize)) | ||||
| 		r = _mirror_emit_segment_line(dmt, seg, params, paramsize); | ||||
| 		if (!r) | ||||
| 			return_0; | ||||
| 		break; | ||||
| 	case SEG_SNAPSHOT: | ||||
| @@ -2951,7 +2838,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major, | ||||
| 		EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size); | ||||
| 		break; | ||||
| 	case SEG_VDO: | ||||
| 		if (!_vdo_emit_segment_line(dmt, seg, params, paramsize)) | ||||
| 		if (!(r = _vdo_emit_segment_line(dmt, seg, params, paramsize))) | ||||
| 		      return_0; | ||||
| 		break; | ||||
| 	case SEG_CRYPT: | ||||
| @@ -2980,8 +2867,9 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major, | ||||
| 	case SEG_RAID6_LA_6: | ||||
| 	case SEG_RAID6_RA_6: | ||||
| 		target_type_is_raid = 1; | ||||
| 		if (!_raid_emit_segment_line(dmt, major, minor, seg, seg_start, | ||||
| 					     params, paramsize)) | ||||
| 		r = _raid_emit_segment_line(dmt, major, minor, seg, seg_start, | ||||
| 					    params, paramsize); | ||||
| 		if (!r) | ||||
| 			return_0; | ||||
|  | ||||
| 		break; | ||||
| @@ -3001,10 +2889,6 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major, | ||||
| 		if (!_writecache_emit_segment_line(dmt, seg, params, paramsize)) | ||||
| 			return_0; | ||||
| 		break; | ||||
| 	case SEG_INTEGRITY: | ||||
| 		if (!_integrity_emit_segment_line(dmt, seg, params, paramsize)) | ||||
| 			return_0; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	switch(seg->type) { | ||||
| @@ -3017,14 +2901,14 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major, | ||||
| 	case SEG_THIN: | ||||
| 	case SEG_CACHE: | ||||
| 	case SEG_WRITECACHE: | ||||
| 	case SEG_INTEGRITY: | ||||
| 		break; | ||||
| 	case SEG_CRYPT: | ||||
| 	case SEG_LINEAR: | ||||
| 	case SEG_STRIPED: | ||||
| 		if (!_emit_areas_line(dmt, seg, params, paramsize, &pos)) | ||||
| 			return_0; | ||||
|  | ||||
| 		if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) { | ||||
| 			stack; | ||||
| 			return r; | ||||
| 		} | ||||
| 		if (!params[0]) { | ||||
| 			log_error("No parameters supplied for %s target " | ||||
| 				  "%u:%u.", _dm_segtypes[seg->type].target, | ||||
| @@ -3121,9 +3005,6 @@ static int _load_node(struct dm_tree_node *dnode) | ||||
| 	if (!dm_task_suppress_identical_reload(dmt)) | ||||
| 		log_warn("WARNING: Failed to suppress reload of identical tables."); | ||||
|  | ||||
| 	if (dnode->props.skip_reload_params_compare) | ||||
| 		dm_task_skip_reload_params_compare(dmt); | ||||
|  | ||||
| 	if ((r = dm_task_run(dmt))) { | ||||
| 		r = dm_task_get_info(dmt, &dnode->info); | ||||
| 		if (r && !dnode->info.inactive_table) | ||||
| @@ -3142,8 +3023,8 @@ static int _load_node(struct dm_tree_node *dnode) | ||||
| 			if (!existing_table_size && dnode->props.delay_resume_if_new) | ||||
| 				dnode->props.size_changed = 0; | ||||
|  | ||||
| 			log_debug_activation("Table size changed from %" PRIu64 " to %" PRIu64 " for %s.%s", | ||||
| 					     existing_table_size, | ||||
| 			log_debug_activation("Table size changed from %" PRIu64 " to %" | ||||
| 					     PRIu64 " for %s.%s", existing_table_size, | ||||
| 					     seg_start, _node_name(dnode), | ||||
| 					     dnode->props.size_changed ? "" : " (Ignoring.)"); | ||||
|  | ||||
| @@ -3169,45 +3050,32 @@ out: | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| /* Try to deactivate only nodes created during preload. */ | ||||
| static int _dm_tree_revert_activated(struct dm_tree_node *dnode) | ||||
| /* | ||||
|  * Currently try to deactivate only nodes created during preload. | ||||
|  * New node is always attached to the front of activated_list | ||||
|  */ | ||||
| static int _dm_tree_revert_activated(struct dm_tree_node *parent) | ||||
| { | ||||
| 	void *handle = NULL; | ||||
| 	struct dm_tree_node *child; | ||||
|  | ||||
| 	while ((child = dm_tree_next_child(&handle, dnode, 0))) { | ||||
| 		if (child->activated) { | ||||
| 			if (child->callback) { | ||||
| 				log_debug_activation("Dropping callback for %s.", _node_name(child)); | ||||
| 				child->callback = NULL; | ||||
| 			} | ||||
|  | ||||
| 			log_debug_activation("Reverting %s.", _node_name(child)); | ||||
| 			if (!_deactivate_node(child->name, child->info.major, child->info.minor, | ||||
| 					      &child->dtree->cookie, child->udev_flags, 0)) { | ||||
| 				log_debug_activation("Unable to deactivate %s.", _node_name(child)); | ||||
| 				return 0; | ||||
| 			} | ||||
| 	dm_list_iterate_items_gen(child, &parent->activated, activated_list) { | ||||
| 		log_debug_activation("Reverting %s.", _node_name(child)); | ||||
| 		if (child->callback) { | ||||
| 			log_debug_activation("Dropping callback for %s.", _node_name(child)); | ||||
| 			child->callback = NULL; | ||||
| 		} | ||||
|  | ||||
| 		if (dm_tree_node_num_children(child, 0) && | ||||
| 		    !_dm_tree_revert_activated(child)) | ||||
| 		if (!_deactivate_node(child->name, child->info.major, child->info.minor, | ||||
| 				      &child->dtree->cookie, child->udev_flags, 0)) { | ||||
| 			log_error("Unable to deactivate %s.", _node_name(child)); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if (!_dm_tree_revert_activated(child)) | ||||
| 			return_0; | ||||
| 	} | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int _dm_tree_wait_and_revert_activated(struct dm_tree_node *dnode) | ||||
| { | ||||
| 	if (!dm_udev_wait(dm_tree_get_cookie(dnode))) | ||||
| 		stack; | ||||
|  | ||||
| 	dm_tree_set_cookie(dnode, 0); | ||||
|  | ||||
| 	return _dm_tree_revert_activated(dnode); | ||||
| } | ||||
|  | ||||
| int dm_tree_preload_children(struct dm_tree_node *dnode, | ||||
| 			     const char *uuid_prefix, | ||||
| 			     size_t uuid_prefix_len) | ||||
| @@ -3237,7 +3105,7 @@ int dm_tree_preload_children(struct dm_tree_node *dnode, | ||||
| 				return_0; | ||||
|  | ||||
| 		/* FIXME Cope if name exists with no uuid? */ | ||||
| 		if (!child->info.exists && !(node_created = _create_node(child, dnode))) | ||||
| 		if (!child->info.exists && !(node_created = _create_node(child))) | ||||
| 			return_0; | ||||
|  | ||||
| 		/* Propagate delayed resume from exteded child node */ | ||||
| @@ -3247,22 +3115,28 @@ int dm_tree_preload_children(struct dm_tree_node *dnode, | ||||
| 		if (!child->info.inactive_table && | ||||
| 		    child->props.segment_count && | ||||
| 		    !_load_node(child)) { | ||||
| 			stack; | ||||
| 			/* | ||||
| 			 * If the table load fails, try to device in the kernel | ||||
| 			 * together with other created and preloaded devices. | ||||
| 			 * If the table load does not succeed, we remove the | ||||
| 			 * device in the kernel that would otherwise have an | ||||
| 			 * empty table.  This makes the create + load of the | ||||
| 			 * device atomic.  However, if other dependencies have | ||||
| 			 * already been created and loaded; this code is | ||||
| 			 * insufficient to remove those - only the node | ||||
| 			 * encountering the table load failure is removed. | ||||
| 			 */ | ||||
| 			if (!_dm_tree_wait_and_revert_activated(dnode)) | ||||
| 				stack; | ||||
| 			r = 0; | ||||
| 			continue; | ||||
| 			if (node_created) { | ||||
| 				if (!_remove_node(child)) | ||||
| 					return_0; | ||||
| 				if (!dm_udev_wait(dm_tree_get_cookie(dnode))) | ||||
| 					stack; | ||||
| 				dm_tree_set_cookie(dnode, 0); | ||||
| 				(void) _dm_tree_revert_activated(child); | ||||
| 			} | ||||
| 			return_0; | ||||
| 		} | ||||
|  | ||||
| 		/* No resume for a device without parents or with unchanged or smaller size */ | ||||
| 		if (!dm_tree_node_num_children(child, 1)) | ||||
| 			continue; | ||||
|  | ||||
| 		if (child->props.size_changed <= 0) | ||||
| 		if (!dm_tree_node_num_children(child, 1) || (child->props.size_changed <= 0)) | ||||
| 			continue; | ||||
|  | ||||
| 		if (!child->info.inactive_table && !child->info.suspended) | ||||
| @@ -3273,19 +3147,28 @@ int dm_tree_preload_children(struct dm_tree_node *dnode, | ||||
| 				  &child->info, &child->dtree->cookie, child->udev_flags, | ||||
| 				  child->info.suspended)) { | ||||
| 			log_error("Unable to resume %s.", _node_name(child)); | ||||
| 			if (!_dm_tree_wait_and_revert_activated(dnode)) | ||||
| 				stack; | ||||
| 			/* If the device was not previously active, we might as well remove this node. */ | ||||
| 			if (!child->info.live_table && | ||||
| 			    !_deactivate_node(child->name, child->info.major, child->info.minor, | ||||
| 					      &child->dtree->cookie, child->udev_flags, 0)) | ||||
| 				log_error("Unable to deactivate %s.", _node_name(child)); | ||||
| 			r = 0; | ||||
| 			/* Each child is handled independently */ | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (node_created) { | ||||
| 			/* Collect newly introduced devices for revert */ | ||||
| 			dm_list_add_h(&dnode->activated, &child->activated_list); | ||||
|  | ||||
| 			/* When creating new node also check transaction_id. */ | ||||
| 			if (child->props.send_messages && | ||||
| 			    !_node_send_messages(child, uuid_prefix, uuid_prefix_len, 0)) { | ||||
| 				stack; | ||||
| 				if (!_dm_tree_wait_and_revert_activated(dnode)) | ||||
| 				if (!dm_udev_wait(dm_tree_get_cookie(dnode))) | ||||
| 					stack; | ||||
| 				dm_tree_set_cookie(dnode, 0); | ||||
| 				(void) _dm_tree_revert_activated(dnode); | ||||
| 				r = 0; | ||||
| 				continue; | ||||
| 			} | ||||
| @@ -3855,48 +3738,6 @@ int dm_tree_node_add_writecache_target(struct dm_tree_node *node, | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int dm_tree_node_add_integrity_target(struct dm_tree_node *node, | ||||
| 				  uint64_t size, | ||||
| 				  const char *origin_uuid, | ||||
| 				  const char *meta_uuid, | ||||
| 				  struct integrity_settings *settings, | ||||
| 				  int recalculate) | ||||
| { | ||||
| 	struct load_segment *seg; | ||||
|  | ||||
| 	if (!(seg = _add_segment(node, SEG_INTEGRITY, size))) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (!meta_uuid) { | ||||
| 		log_error("No integrity meta uuid."); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!(seg->integrity_meta_node = dm_tree_find_node_by_uuid(node->dtree, meta_uuid))) { | ||||
| 		log_error("Missing integrity's meta uuid %s.", meta_uuid); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!_link_tree_nodes(node, seg->integrity_meta_node)) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (!(seg->origin = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) { | ||||
| 		log_error("Missing integrity's origin uuid %s.", origin_uuid); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!_link_tree_nodes(node, seg->origin)) | ||||
| 		return_0; | ||||
|  | ||||
| 	memcpy(&seg->integrity_settings, settings, sizeof(struct integrity_settings)); | ||||
|  | ||||
| 	seg->integrity_recalculate = recalculate; | ||||
|  | ||||
| 	node->props.skip_reload_params_compare = 1; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int dm_tree_node_add_replicator_target(struct dm_tree_node *node, | ||||
| 				       uint64_t size, | ||||
| 				       const char *rlog_uuid, | ||||
| @@ -3970,24 +3811,6 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node, | ||||
| 				      uint32_t data_block_size, | ||||
| 				      uint64_t low_water_mark, | ||||
| 				      unsigned skip_block_zeroing) | ||||
| { | ||||
| 	return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id, | ||||
| 						    metadata_uuid, pool_uuid, | ||||
| 						    data_block_size, | ||||
| 						    low_water_mark, | ||||
| 						    skip_block_zeroing, | ||||
| 						    1); | ||||
| } | ||||
|  | ||||
| int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node, | ||||
| 					 uint64_t size, | ||||
| 					 uint64_t transaction_id, | ||||
| 					 const char *metadata_uuid, | ||||
| 					 const char *pool_uuid, | ||||
| 					 uint32_t data_block_size, | ||||
| 					 uint64_t low_water_mark, | ||||
| 					 unsigned skip_block_zeroing, | ||||
| 					 unsigned crop_metadata) | ||||
| { | ||||
| 	struct load_segment *seg, *mseg; | ||||
| 	uint64_t devsize = 0; | ||||
| @@ -4015,18 +3838,17 @@ int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node, | ||||
| 	if (!_link_tree_nodes(node, seg->metadata)) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (crop_metadata) | ||||
| 		/* FIXME: more complex target may need more tweaks */ | ||||
| 		dm_list_iterate_items(mseg, &seg->metadata->props.segs) { | ||||
| 			devsize += mseg->size; | ||||
| 			if (devsize > DM_THIN_MAX_METADATA_SIZE) { | ||||
| 				log_debug_activation("Ignoring %" PRIu64 " of device.", | ||||
| 						     devsize - DM_THIN_MAX_METADATA_SIZE); | ||||
| 				mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE); | ||||
| 				devsize = DM_THIN_MAX_METADATA_SIZE; | ||||
| 				/* FIXME: drop remaining segs */ | ||||
| 			} | ||||
| 	/* FIXME: more complex target may need more tweaks */ | ||||
| 	dm_list_iterate_items(mseg, &seg->metadata->props.segs) { | ||||
| 		devsize += mseg->size; | ||||
| 		if (devsize > DM_THIN_MAX_METADATA_SIZE) { | ||||
| 			log_debug_activation("Ignoring %" PRIu64 " of device.", | ||||
| 					     devsize - DM_THIN_MAX_METADATA_SIZE); | ||||
| 			mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE); | ||||
| 			devsize = DM_THIN_MAX_METADATA_SIZE; | ||||
| 			/* FIXME: drop remaining segs */ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) { | ||||
| 		log_error("Missing pool uuid %s.", pool_uuid); | ||||
| @@ -4321,9 +4143,63 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode, | ||||
| 	dnode->callback_data = data; | ||||
| } | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| /* | ||||
|  * Backward compatible implementations. | ||||
|  * | ||||
|  * Keep these at the end of the file to make sure that | ||||
|  * no code in this file accidentally calls it. | ||||
|  */ | ||||
|  | ||||
| /* Backward compatible dm_tree_node_size_changed() implementations. */ | ||||
| int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode); | ||||
| int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode) | ||||
| { | ||||
| 	/* Base does not make difference between smaller and bigger */ | ||||
| 	return dm_tree_node_size_changed(dnode) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Retain ABI compatibility after adding the DM_CACHE_FEATURE_METADATA2 | ||||
|  * in version 1.02.138. | ||||
|  * | ||||
|  * Binaries compiled against version 1.02.138 onwards will use | ||||
|  * the new function dm_tree_node_add_cache_target which detects unknown | ||||
|  * feature flags and returns error for them. | ||||
|  */ | ||||
| int dm_tree_node_add_cache_target_base(struct dm_tree_node *node, | ||||
| 				       uint64_t size, | ||||
| 				       uint64_t feature_flags, /* DM_CACHE_FEATURE_* */ | ||||
| 				       const char *metadata_uuid, | ||||
| 				       const char *data_uuid, | ||||
| 				       const char *origin_uuid, | ||||
| 				       const char *policy_name, | ||||
| 				       const struct dm_config_node *policy_settings, | ||||
| 				       uint32_t data_block_size); | ||||
| int dm_tree_node_add_cache_target_base(struct dm_tree_node *node, | ||||
| 				       uint64_t size, | ||||
| 				       uint64_t feature_flags, | ||||
| 				       const char *metadata_uuid, | ||||
| 				       const char *data_uuid, | ||||
| 				       const char *origin_uuid, | ||||
| 				       const char *policy_name, | ||||
| 				       const struct dm_config_node *policy_settings, | ||||
| 				       uint32_t data_block_size) | ||||
| { | ||||
| 	/* Old version supported only these FEATURE bits, others were ignored so masked them */ | ||||
| 	static const uint64_t _mask = | ||||
| 		DM_CACHE_FEATURE_WRITEBACK | | ||||
| 		DM_CACHE_FEATURE_WRITETHROUGH | | ||||
| 		DM_CACHE_FEATURE_PASSTHROUGH; | ||||
|  | ||||
| 	return dm_tree_node_add_cache_target(node, size, feature_flags & _mask, | ||||
| 					     metadata_uuid, data_uuid, origin_uuid, | ||||
| 					     policy_name, policy_settings, 0, 0, 0, 0, data_block_size); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| int dm_tree_node_add_vdo_target(struct dm_tree_node *node, | ||||
| 				uint64_t size, | ||||
| 				const char *vdo_pool_name, | ||||
| 				const char *data_uuid, | ||||
| 				uint64_t data_size, | ||||
| 				const struct dm_vdo_target_params *vtp) | ||||
| @@ -4345,7 +4221,7 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node, | ||||
| 		return_0; | ||||
|  | ||||
| 	seg->vdo_params = *vtp; | ||||
| 	seg->vdo_name = vdo_pool_name; | ||||
| 	seg->vdo_name = node->name; | ||||
| 	seg->vdo_data_size = data_size; | ||||
|  | ||||
| 	node->props.send_messages = 2; | ||||
|   | ||||
| @@ -110,7 +110,7 @@ int dm_is_empty_dir(const char *dir) | ||||
| 	DIR *d; | ||||
|  | ||||
| 	if (!(d = opendir(dir))) { | ||||
| 		log_sys_debug("opendir", dir); | ||||
| 		log_sys_error("opendir", dir); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| @@ -119,7 +119,7 @@ int dm_is_empty_dir(const char *dir) | ||||
| 			break; | ||||
|  | ||||
| 	if (closedir(d)) | ||||
| 		log_sys_debug("closedir", dir); | ||||
| 		log_sys_error("closedir", dir); | ||||
|  | ||||
| 	return dirent ? 0 : 1; | ||||
| } | ||||
|   | ||||
| @@ -492,7 +492,7 @@ static int _report_field_string_list(struct dm_report *rh, | ||||
| 		delimiter = ","; | ||||
| 	delimiter_len = strlen(delimiter); | ||||
|  | ||||
| 	i = pos = 0; | ||||
| 	i = pos = len = 0; | ||||
| 	dm_list_iterate_items(sl, data) { | ||||
| 		arr[i].str = sl->str; | ||||
| 		if (!sort) { | ||||
| @@ -749,11 +749,10 @@ static void _display_fields_more(struct dm_report *rh, | ||||
| 			id_len = strlen(type->prefix) + 3; | ||||
|  | ||||
| 	for (f = 0; fields[f].report_fn; f++) { | ||||
| 		if (!(type = _find_type(rh, fields[f].type))) { | ||||
| 			log_debug(INTERNAL_ERROR "Field type undefined."); | ||||
| 			continue; | ||||
| 		} | ||||
| 		desc = (type->desc) ? : " "; | ||||
| 		if ((type = _find_type(rh, fields[f].type)) && type->desc) | ||||
| 			desc = type->desc; | ||||
| 		else | ||||
| 			desc = " "; | ||||
| 		if (desc != last_desc) { | ||||
| 			if (*last_desc) | ||||
| 				log_warn(" "); | ||||
| @@ -2332,7 +2331,7 @@ static const char *_reserved_name(struct dm_report *rh, | ||||
| 				  uint32_t field_num, const char *s, size_t len) | ||||
| { | ||||
| 	dm_report_reserved_handler handler; | ||||
| 	const char *canonical_name = NULL; | ||||
| 	const char *canonical_name; | ||||
| 	const char **name; | ||||
| 	char *tmp_s; | ||||
| 	char c; | ||||
| @@ -2474,7 +2473,7 @@ dm_percent_t dm_make_percent(uint64_t numerator, uint64_t denominator) | ||||
|  | ||||
| int dm_report_value_cache_set(struct dm_report *rh, const char *name, const void *data) | ||||
| { | ||||
| 	if (!rh->value_cache && (!(rh->value_cache = dm_hash_create(63)))) { | ||||
| 	if (!rh->value_cache && (!(rh->value_cache = dm_hash_create(64)))) { | ||||
| 		log_error("Failed to create cache for values used during reporting."); | ||||
| 		return 0; | ||||
| 	} | ||||
| @@ -3774,7 +3773,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh, | ||||
| 	struct field_selection *fs; | ||||
| 	struct selection_node *sn; | ||||
| 	const char *ws, *we; /* field name */ | ||||
| 	const char *vs = NULL, *ve = NULL; /* value */ | ||||
| 	const char *vs, *ve; /* value */ | ||||
| 	const char *last; | ||||
| 	uint32_t flags, field_num; | ||||
| 	int implicit; | ||||
| @@ -3910,7 +3909,7 @@ static struct selection_node *_parse_ex(struct dm_report *rh, | ||||
| 	static const char _pe_expected_msg[] = "Syntax error: right parenthesis expected at \'%s\'"; | ||||
| 	struct selection_node *sn = NULL; | ||||
| 	uint32_t t; | ||||
| 	const char *tmp = NULL; | ||||
| 	const char *tmp; | ||||
|  | ||||
| 	t = _tok_op_log(s, next, SEL_MODIFIER_NOT | SEL_PRECEDENCE_PS); | ||||
| 	if (t == SEL_MODIFIER_NOT) { | ||||
| @@ -3956,7 +3955,7 @@ static struct selection_node *_parse_and_ex(struct dm_report *rh, | ||||
| 					    struct selection_node *and_sn) | ||||
| { | ||||
| 	struct selection_node *n; | ||||
| 	const char *tmp = NULL; | ||||
| 	const char *tmp; | ||||
|  | ||||
| 	n = _parse_ex(rh, s, next); | ||||
| 	if (!n) | ||||
| @@ -3988,7 +3987,7 @@ static struct selection_node *_parse_or_ex(struct dm_report *rh, | ||||
| 					   struct selection_node *or_sn) | ||||
| { | ||||
| 	struct selection_node *n; | ||||
| 	const char *tmp = NULL; | ||||
| 	const char *tmp; | ||||
|  | ||||
| 	n = _parse_and_ex(rh, s, next, NULL); | ||||
| 	if (!n) | ||||
|   | ||||
| @@ -366,8 +366,8 @@ int dm_get_status_writecache(struct dm_pool *mem, const char *params, | ||||
| 	if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_writecache)))) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (sscanf(params, "%llu %llu %llu %llu", | ||||
| 		   (unsigned long long *)&s->error, | ||||
| 	if (sscanf(params, "%u %llu %llu %llu", | ||||
| 		   &s->error, | ||||
| 		   (unsigned long long *)&s->total_blocks, | ||||
| 		   (unsigned long long *)&s->free_blocks, | ||||
| 		   (unsigned long long *)&s->writeback_blocks) != 4) { | ||||
| @@ -380,33 +380,6 @@ int dm_get_status_writecache(struct dm_pool *mem, const char *params, | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int dm_get_status_integrity(struct dm_pool *mem, const char *params, | ||||
| 			     struct dm_status_integrity **status) | ||||
| { | ||||
| 	struct dm_status_integrity *s; | ||||
| 	char recalc_str[16] = "\0"; | ||||
|  | ||||
| 	if (!(s = dm_pool_zalloc(mem, sizeof(*s)))) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (sscanf(params, "%llu %llu %s", | ||||
| 		   (unsigned long long *)&s->number_of_mismatches, | ||||
| 		   (unsigned long long *)&s->provided_data_sectors, | ||||
| 		   recalc_str) != 3) { | ||||
| 		log_error("Failed to parse integrity params: %s.", params); | ||||
| 		dm_pool_free(mem, s); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (recalc_str[0] == '-') | ||||
| 		s->recalc_sector = 0; | ||||
| 	else | ||||
| 		s->recalc_sector = strtoull(recalc_str, NULL, 0); | ||||
|  | ||||
| 	*status = s; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int parse_thin_pool_status(const char *params, struct dm_status_thin_pool *s) | ||||
| { | ||||
| 	int pos; | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| /* SPDX-License-Identifier: LGPL-2.0+ WITH Linux-syscall-note */ | ||||
| /* | ||||
|  * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. | ||||
|  * Copyright (C) 2004 - 2021 Red Hat, Inc. All rights reserved. | ||||
|  * Copyright (C) 2004 - 2017 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is released under the LGPL. | ||||
|  */ | ||||
| @@ -195,22 +194,8 @@ struct dm_name_list { | ||||
| 	uint32_t next;		/* offset to the next record from | ||||
| 				   the _start_ of this */ | ||||
| 	char name[0]; | ||||
|  | ||||
| 	/* | ||||
| 	 * The following members can be accessed by taking a pointer that | ||||
| 	 * points immediately after the terminating zero character in "name" | ||||
| 	 * and aligning this pointer to next 8-byte boundary. | ||||
| 	 * Uuid is present if the flag DM_NAME_LIST_FLAG_HAS_UUID is set. | ||||
| 	 * | ||||
| 	 * uint32_t event_nr; | ||||
| 	 * uint32_t flags; | ||||
| 	 * char uuid[0]; | ||||
| 	 */ | ||||
| }; | ||||
|  | ||||
| #define DM_NAME_LIST_FLAG_HAS_UUID		1 | ||||
| #define DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID	2 | ||||
|  | ||||
| /* | ||||
|  * Used to retrieve the target versions | ||||
|  */ | ||||
| @@ -259,7 +244,6 @@ enum { | ||||
| 	DM_TARGET_MSG_CMD, | ||||
| 	DM_DEV_SET_GEOMETRY_CMD, | ||||
| 	DM_DEV_ARM_POLL_CMD, | ||||
| 	DM_GET_TARGET_VERSION_CMD, | ||||
| }; | ||||
|  | ||||
| #define DM_IOCTL 0xfd | ||||
| @@ -286,12 +270,10 @@ enum { | ||||
| #define DM_TARGET_MSG	 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) | ||||
| #define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) | ||||
|  | ||||
| #define DM_GET_TARGET_VERSION	_IOWR(DM_IOCTL, DM_GET_TARGET_VERSION_CMD, struct dm_ioctl) | ||||
|  | ||||
| #define DM_VERSION_MAJOR	4 | ||||
| #define DM_VERSION_MINOR	45 | ||||
| #define DM_VERSION_MINOR	36 | ||||
| #define DM_VERSION_PATCHLEVEL	0 | ||||
| #define DM_VERSION_EXTRA	"-ioctl (2021-03-22)" | ||||
| #define DM_VERSION_EXTRA	"-ioctl (2017-06-09)" | ||||
|  | ||||
| /* Status bits */ | ||||
| #define DM_READONLY_FLAG	(1 << 0) /* In/Out */ | ||||
| @@ -379,10 +361,4 @@ enum { | ||||
|  */ | ||||
| #define DM_INTERNAL_SUSPEND_FLAG	(1 << 18) /* Out */ | ||||
|  | ||||
| /* | ||||
|  * If set, returns in the in buffer passed by UM, the raw table information | ||||
|  * that would be measured by IMA subsystem on device state change. | ||||
|  */ | ||||
| #define DM_IMA_MEASUREMENT_FLAG	(1 << 19) /* In */ | ||||
|  | ||||
| #endif				/* _LINUX_DM_IOCTL_H */ | ||||
|   | ||||
| @@ -98,7 +98,7 @@ void dm_pools_check_leaks(void) | ||||
| 			  p->orig_pool, | ||||
| 			  p->name, p->stats.bytes); | ||||
| #else | ||||
| 		log_error(" [%p] %s", (void *)p, p->name); | ||||
| 		log_error(" [%p] %s", p, p->name); | ||||
| #endif | ||||
| 	} | ||||
| 	pthread_mutex_unlock(&_dm_pools_mutex); | ||||
|   | ||||
| @@ -69,13 +69,12 @@ bool dm_vdo_status_parse(struct dm_pool *mem, const char *input, | ||||
| enum dm_vdo_write_policy { | ||||
| 	DM_VDO_WRITE_POLICY_AUTO = 0, | ||||
| 	DM_VDO_WRITE_POLICY_SYNC, | ||||
| 	DM_VDO_WRITE_POLICY_ASYNC, | ||||
| 	DM_VDO_WRITE_POLICY_ASYNC_UNSAFE | ||||
| 	DM_VDO_WRITE_POLICY_ASYNC | ||||
| }; | ||||
|  | ||||
| // FIXME: review whether we should use the createParams from the userlib | ||||
| struct dm_vdo_target_params { | ||||
| 	uint32_t minimum_io_size;       // in sectors | ||||
| 	uint32_t minimum_io_size; | ||||
| 	uint32_t block_map_cache_size_mb; | ||||
| 	uint32_t block_map_era_length;	// format period | ||||
|  | ||||
|   | ||||
| @@ -23,9 +23,8 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp, | ||||
| { | ||||
| 	bool valid = true; | ||||
|  | ||||
| 	/* 512 or 4096 bytes only ATM */ | ||||
| 	if ((vtp->minimum_io_size != 1) && | ||||
| 	    (vtp->minimum_io_size != 8)) { | ||||
| 	if ((vtp->minimum_io_size != 512) && | ||||
| 	    (vtp->minimum_io_size != 4096)) { | ||||
| 		log_error("VDO minimum io size %u is unsupported.", | ||||
| 			  vtp->minimum_io_size); | ||||
| 		valid = false; | ||||
| @@ -100,7 +99,6 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp, | ||||
| 	switch (vtp->write_policy) { | ||||
| 	case DM_VDO_WRITE_POLICY_SYNC: | ||||
| 	case DM_VDO_WRITE_POLICY_ASYNC: | ||||
| 	case DM_VDO_WRITE_POLICY_ASYNC_UNSAFE: | ||||
| 	case DM_VDO_WRITE_POLICY_AUTO: | ||||
| 		break; | ||||
| 	default: | ||||
|   | ||||
| @@ -94,7 +94,7 @@ journal_watermark:number | ||||
|  | ||||
| commit_time:number | ||||
| 	Commit time in milliseconds. When this time passes, the journal is | ||||
| 	written. The journal is also written immediately if the FLUSH | ||||
| 	written. The journal is also written immediatelly if the FLUSH | ||||
| 	request is received. | ||||
|  | ||||
| internal_hash:algorithm(:key)	(the key is optional) | ||||
|   | ||||
							
								
								
									
										2
									
								
								include/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								include/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1 @@ | ||||
| *.h | ||||
| .symlinks | ||||
| .symlinks_created | ||||
|   | ||||
| @@ -1,8 +1,5 @@ | ||||
| /* include/configure.h.in.  Generated from configure.ac by autoheader.  */ | ||||
|  | ||||
| /* Define to 1 to include code that uses libsystemd machine-id apis. */ | ||||
| #undef APP_MACHINEID_SUPPORT | ||||
|  | ||||
| /* Define to 1 to use libblkid detection of signatures when wiping. */ | ||||
| #undef BLKID_WIPING_SUPPORT | ||||
|  | ||||
| @@ -90,9 +87,6 @@ | ||||
| /* Use blkid wiping by default. */ | ||||
| #undef DEFAULT_USE_BLKID_WIPING | ||||
|  | ||||
| /* Default for lvm.conf use_devicefile. */ | ||||
| #undef DEFAULT_USE_DEVICES_FILE | ||||
|  | ||||
| /* Use lvmlockd by default. */ | ||||
| #undef DEFAULT_USE_LVMLOCKD | ||||
|  | ||||
| @@ -114,6 +108,9 @@ | ||||
| /* Define to 1 to enable the device-mapper filemap daemon. */ | ||||
| #undef DMFILEMAPD | ||||
|  | ||||
| /* Define to enable compat protocol */ | ||||
| #undef DM_COMPAT | ||||
|  | ||||
| /* Define default group for device node */ | ||||
| #undef DM_DEVICE_GID | ||||
|  | ||||
| @@ -129,15 +126,9 @@ | ||||
| /* Library version */ | ||||
| #undef DM_LIB_VERSION | ||||
|  | ||||
| /* Define to 1 to include the LVM editline shell. */ | ||||
| #undef EDITLINE_SUPPORT | ||||
|  | ||||
| /* Path to fsadm binary. */ | ||||
| #undef FSADM_PATH | ||||
|  | ||||
| /* Define to use GNU versioning in the shared library. */ | ||||
| #undef GNU_SYMVER | ||||
|  | ||||
| /* Define to 1 if you have the `alarm' function. */ | ||||
| #undef HAVE_ALARM | ||||
|  | ||||
| @@ -160,9 +151,6 @@ | ||||
| /* Define to 1 if you have the `atexit' function. */ | ||||
| #undef HAVE_ATEXIT | ||||
|  | ||||
| /* Define if ioctl BLKZEROOUT can be used for device zeroing. */ | ||||
| #undef HAVE_BLKZEROOUT | ||||
|  | ||||
| /* Define to 1 if canonicalize_file_name is available. */ | ||||
| #undef HAVE_CANONICALIZE_FILE_NAME | ||||
|  | ||||
| @@ -188,18 +176,12 @@ | ||||
| /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ | ||||
| #undef HAVE_DOPRNT | ||||
|  | ||||
| /* Define to 1 if you have the <editline/readline.h> header file. */ | ||||
| #undef HAVE_EDITLINE_READLINE_H | ||||
|  | ||||
| /* Define to 1 if you have the <errno.h> header file. */ | ||||
| #undef HAVE_ERRNO_H | ||||
|  | ||||
| /* Define to 1 if you have the <fcntl.h> header file. */ | ||||
| #undef HAVE_FCNTL_H | ||||
|  | ||||
| /* Define to 1 if you have the `ffs' function. */ | ||||
| #undef HAVE_FFS | ||||
|  | ||||
| /* Define to 1 if you have the <float.h> header file. */ | ||||
| #undef HAVE_FLOAT_H | ||||
|  | ||||
| @@ -525,9 +507,6 @@ | ||||
| /* valgrind.h found */ | ||||
| #undef HAVE_VALGRIND | ||||
|  | ||||
| /* Define to 1 if you have the `versionsort' function. */ | ||||
| #undef HAVE_VERSIONSORT | ||||
|  | ||||
| /* Define to 1 if you have the `vfork' function. */ | ||||
| #undef HAVE_VFORK | ||||
|  | ||||
| @@ -552,12 +531,6 @@ | ||||
| /* Define to 1 if the system has the `__builtin_clzll' built-in function */ | ||||
| #undef HAVE___BUILTIN_CLZLL | ||||
|  | ||||
| /* Define to 1 if the system has the `__builtin_ffs' built-in function */ | ||||
| #undef HAVE___BUILTIN_FFS | ||||
|  | ||||
| /* Define to 1 to include built-in support for integrity. */ | ||||
| #undef INTEGRITY_INTERNAL | ||||
|  | ||||
| /* Internalization package */ | ||||
| #undef INTL_PACKAGE | ||||
|  | ||||
| @@ -570,9 +543,6 @@ | ||||
| /* Define to 1 to include code that uses lvmlockd dlm option. */ | ||||
| #undef LOCKDDLM_SUPPORT | ||||
|  | ||||
| /* Define to 1 to include code that uses lvmlockd IDM option. */ | ||||
| #undef LOCKDIDM_SUPPORT | ||||
|  | ||||
| /* Define to 1 to include code that uses lvmlockd sanlock option. */ | ||||
| #undef LOCKDSANLOCK_SUPPORT | ||||
|  | ||||
| @@ -583,9 +553,6 @@ | ||||
| /* Path to lvmconfig binary. */ | ||||
| #undef LVMCONFIG_PATH | ||||
|  | ||||
| /* Path to lvm_import_vdo script. */ | ||||
| #undef LVMIMPORTVDO_PATH | ||||
|  | ||||
| /* Path to lvmlockd pidfile. */ | ||||
| #undef LVMLOCKD_PIDFILE | ||||
|  | ||||
| @@ -668,9 +635,6 @@ | ||||
| /* Define to 1 if strerror_r returns char *. */ | ||||
| #undef STRERROR_R_CHAR_P | ||||
|  | ||||
| /* Define to 1 to include code that uses systemd journal. */ | ||||
| #undef SYSTEMD_JOURNAL_SUPPORT | ||||
|  | ||||
| /* Path to testsuite data */ | ||||
| #undef TESTSUITE_DATA | ||||
|  | ||||
|   | ||||
| @@ -15,13 +15,11 @@ | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| abs_srcdir = @abs_srcdir@ | ||||
|  | ||||
| SOURCES =\ | ||||
| 	activate/activate.c \ | ||||
| 	cache/lvmcache.c \ | ||||
| 	writecache/writecache.c \ | ||||
| 	integrity/integrity.c \ | ||||
| 	cache_segtype/cache.c \ | ||||
| 	commands/toolcontext.c \ | ||||
| 	config/config.c \ | ||||
| @@ -30,17 +28,14 @@ SOURCES =\ | ||||
| 	device/bcache.c \ | ||||
| 	device/bcache-utils.c \ | ||||
| 	device/dev-cache.c \ | ||||
| 	device/device_id.c \ | ||||
| 	device/dev-ext.c \ | ||||
| 	device/dev-io.c \ | ||||
| 	device/dev-md.c \ | ||||
| 	device/dev-mpath.c \ | ||||
| 	device/dev-swap.c \ | ||||
| 	device/dev-type.c \ | ||||
| 	device/dev-luks.c \ | ||||
| 	device/dev-dasd.c \ | ||||
| 	device/dev-lvm1-pool.c \ | ||||
| 	device/online.c \ | ||||
| 	display/display.c \ | ||||
| 	error/errseg.c \ | ||||
| 	unknown/unknown.c \ | ||||
| @@ -56,7 +51,6 @@ SOURCES =\ | ||||
| 	filters/filter-usable.c \ | ||||
| 	filters/filter-internal.c \ | ||||
| 	filters/filter-signature.c \ | ||||
| 	filters/filter-deviceid.c \ | ||||
| 	format_text/archive.c \ | ||||
| 	format_text/archiver.c \ | ||||
| 	format_text/export.c \ | ||||
| @@ -72,8 +66,6 @@ SOURCES =\ | ||||
| 	locking/locking.c \ | ||||
| 	log/log.c \ | ||||
| 	metadata/cache_manip.c \ | ||||
| 	metadata/writecache_manip.c \ | ||||
| 	metadata/integrity_manip.c \ | ||||
| 	metadata/lv.c \ | ||||
| 	metadata/lv_manip.c \ | ||||
| 	metadata/merge.c \ | ||||
| @@ -81,7 +73,6 @@ SOURCES =\ | ||||
| 	metadata/mirror.c \ | ||||
| 	metadata/pool_manip.c \ | ||||
| 	metadata/pv.c \ | ||||
| 	metadata/pv_list.c \ | ||||
| 	metadata/pv_manip.c \ | ||||
| 	metadata/pv_map.c \ | ||||
| 	metadata/raid_manip.c \ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -39,7 +39,6 @@ typedef enum { | ||||
| 	SEG_STATUS_THIN_POOL, | ||||
| 	SEG_STATUS_VDO_POOL, | ||||
| 	SEG_STATUS_WRITECACHE, | ||||
| 	SEG_STATUS_INTEGRITY, | ||||
| 	SEG_STATUS_UNKNOWN | ||||
| } lv_seg_status_type_t; | ||||
|  | ||||
| @@ -54,7 +53,6 @@ struct lv_seg_status { | ||||
| 		struct dm_status_thin *thin; | ||||
| 		struct dm_status_thin_pool *thin_pool; | ||||
| 		struct dm_status_writecache *writecache; | ||||
| 		struct dm_status_integrity *integrity; | ||||
| 		struct lv_status_vdo vdo_pool; | ||||
| 	}; | ||||
| }; | ||||
| @@ -106,10 +104,6 @@ int target_present(struct cmd_context *cmd, const char *target_name, | ||||
| 		   int use_modprobe); | ||||
| int target_version(const char *target_name, uint32_t *maj, | ||||
| 		   uint32_t *min, uint32_t *patchlevel); | ||||
|  | ||||
| int get_device_list(const struct volume_group *vg, struct dm_list **devs, | ||||
| 		    unsigned *devs_features); | ||||
|  | ||||
| int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype); | ||||
| int lvm_dm_prefix_check(int major, int minor, const char *prefix); | ||||
| int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg, | ||||
| @@ -150,8 +144,8 @@ int revert_lv(struct cmd_context *cmd, const struct logical_volume *lv); | ||||
|  */ | ||||
| int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_layer, | ||||
| 	    struct lvinfo *info, int with_open_count, int with_read_ahead); | ||||
| int lv_info_with_name_check(struct cmd_context *cmd, const struct logical_volume *lv, | ||||
| 			    int use_layer, struct lvinfo *info); | ||||
| int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer, | ||||
| 		    struct lvinfo *info, int with_open_count, int with_read_ahead); | ||||
|  | ||||
| /* | ||||
|  * Returns 1 if lv_info_and_seg_status structure has been populated, | ||||
| @@ -192,15 +186,16 @@ 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_raid_status(const struct logical_volume *lv, struct lv_status_raid **status); | ||||
| int lv_writecache_message(const struct logical_volume *lv, const char *msg); | ||||
| int lv_cache_status(const struct logical_volume *cache_lv, | ||||
| 		    struct lv_status_cache **status); | ||||
| int lv_thin_pool_percent(const struct logical_volume *lv, int metadata, | ||||
| 			 dm_percent_t *percent); | ||||
| int lv_thin_percent(const struct logical_volume *lv, int mapped, | ||||
| 		    dm_percent_t *percent); | ||||
| int lv_thin_pool_transaction_id(const struct logical_volume *lv, | ||||
| 				uint64_t *transaction_id); | ||||
| int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id); | ||||
| int lv_thin_status(const struct logical_volume *lv, int flush, | ||||
| 		   struct lv_status_thin **status); | ||||
| int lv_thin_pool_status(const struct logical_volume *lv, int flush, | ||||
| 			struct lv_status_thin_pool **status); | ||||
| int lv_vdo_pool_status(const struct logical_volume *lv, int flush, | ||||
| 		       struct lv_status_vdo **status); | ||||
| int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent); | ||||
| @@ -213,8 +208,6 @@ int lvs_in_vg_opened(const struct volume_group *vg); | ||||
|  | ||||
| int lv_is_active(const struct logical_volume *lv); | ||||
|  | ||||
| int lv_passes_readonly_filter(const struct logical_volume *lv); | ||||
|  | ||||
| /* Check is any component LV is active */ | ||||
| const struct logical_volume *lv_component_is_active(const struct logical_volume *lv); | ||||
| const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv); | ||||
| @@ -258,7 +251,7 @@ struct dev_usable_check_params { | ||||
|  * Returns 1 if mapped device is not suspended, blocked or | ||||
|  * is using a reserved name. | ||||
|  */ | ||||
| int device_is_usable(struct cmd_context *cmd, struct device *dev, struct dev_usable_check_params check, int *is_lv); | ||||
| int device_is_usable(struct device *dev, struct dev_usable_check_params check); | ||||
|  | ||||
| /* | ||||
|  * Declaration moved here from fs.h to keep header fs.h hidden | ||||
| @@ -267,7 +260,6 @@ void fs_unlock(void); | ||||
|  | ||||
| #define TARGET_NAME_CACHE "cache" | ||||
| #define TARGET_NAME_WRITECACHE "writecache" | ||||
| #define TARGET_NAME_INTEGRITY "integrity" | ||||
| #define TARGET_NAME_ERROR "error" | ||||
| #define TARGET_NAME_ERROR_OLD "erro"	/* Truncated in older kernels */ | ||||
| #define TARGET_NAME_LINEAR "linear" | ||||
| @@ -285,7 +277,6 @@ void fs_unlock(void); | ||||
| #define MODULE_NAME_CLUSTERED_MIRROR "clog" | ||||
| #define MODULE_NAME_CACHE TARGET_NAME_CACHE | ||||
| #define MODULE_NAME_WRITECACHE TARGET_NAME_WRITECACHE | ||||
| #define MODULE_NAME_INTEGRITY TARGET_NAME_INTEGRITY | ||||
| #define MODULE_NAME_ERROR TARGET_NAME_ERROR | ||||
| #define MODULE_NAME_LOG_CLUSTERED "log-clustered" | ||||
| #define MODULE_NAME_LOG_USERSPACE "log-userspace" | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -47,7 +47,7 @@ void dev_manager_exit(void); | ||||
|  */ | ||||
| int dev_manager_info(struct cmd_context *cmd, const struct logical_volume *lv, | ||||
| 		     const char *layer, | ||||
| 		     int with_open_count, int with_read_ahead, int with_name_check, | ||||
| 		     int with_open_count, int with_read_ahead, | ||||
| 		     struct dm_info *dminfo, uint32_t *read_ahead, | ||||
| 		     struct lv_seg_status *seg_status); | ||||
|  | ||||
| @@ -59,7 +59,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm, | ||||
| 			       dm_percent_t *percent, uint32_t *event_nr); | ||||
| int dev_manager_raid_status(struct dev_manager *dm, | ||||
| 			    const struct logical_volume *lv, | ||||
| 			    struct lv_status_raid **status, int *exists); | ||||
| 			    struct dm_status_raid **status); | ||||
| int dev_manager_raid_message(struct dev_manager *dm, | ||||
| 			     const struct logical_volume *lv, | ||||
| 			     const char *msg); | ||||
| @@ -68,19 +68,24 @@ int dev_manager_writecache_message(struct dev_manager *dm, | ||||
|                                    const char *msg); | ||||
| int dev_manager_cache_status(struct dev_manager *dm, | ||||
| 			     const struct logical_volume *lv, | ||||
| 			     struct lv_status_cache **status, int *exists); | ||||
| int dev_manager_thin_status(struct dev_manager *dm, | ||||
| 			    const struct logical_volume *lv, int flush, | ||||
| 			    struct lv_status_thin **status, int *exists); | ||||
| 			     struct lv_status_cache **status); | ||||
| int dev_manager_thin_pool_status(struct dev_manager *dm, | ||||
| 				 const struct logical_volume *lv, | ||||
| 				 struct dm_status_thin_pool **status, | ||||
| 				 int flush); | ||||
| int dev_manager_thin_pool_percent(struct dev_manager *dm, | ||||
| 				  const struct logical_volume *lv, | ||||
| 				  int metadata, dm_percent_t *percent); | ||||
| int dev_manager_thin_percent(struct dev_manager *dm, | ||||
| 			     const struct logical_volume *lv, | ||||
| 			     int mapped, dm_percent_t *percent); | ||||
| int dev_manager_thin_device_id(struct dev_manager *dm, | ||||
| 			       const struct logical_volume *lv, | ||||
| 			       uint32_t *device_id, int *exist); | ||||
| int dev_manager_thin_pool_status(struct dev_manager *dm, | ||||
| 				 const struct logical_volume *lv, int flush, | ||||
| 				 struct lv_status_thin_pool **status, int *exists); | ||||
| 			       uint32_t *device_id); | ||||
| int dev_manager_vdo_pool_status(struct dev_manager *dm, | ||||
| 				const struct logical_volume *lv, int flush, | ||||
| 				struct lv_status_vdo **status, int *exists); | ||||
| 				const struct logical_volume *lv, | ||||
| 				struct lv_status_vdo **vdo_status, | ||||
| 				int flush); | ||||
| int dev_manager_suspend(struct dev_manager *dm, const struct logical_volume *lv, | ||||
| 			struct lv_activate_opts *laopts, int lockfs, int flush_required); | ||||
| int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv, | ||||
| @@ -103,7 +108,13 @@ int dev_manager_device_uses_vg(struct device *dev, | ||||
| int dev_manager_remove_dm_major_minor(uint32_t major, uint32_t minor); | ||||
|  | ||||
| int dev_manager_check_prefix_dm_major_minor(uint32_t major, uint32_t minor, const char *prefix); | ||||
| int dev_manager_get_device_list(const char *prefix, struct dm_list **devs, | ||||
| 				unsigned *devs_features); | ||||
|  | ||||
| int get_cache_vol_meta_data(struct cmd_context *cmd, | ||||
|                                     struct logical_volume *lv, | ||||
|                                     struct logical_volume *pool_lv, | ||||
|                                     struct dm_info *info_meta, struct dm_info *info_data); | ||||
|  | ||||
| int remove_cache_vol_meta_data(struct cmd_context *cmd, | ||||
|                                        struct dm_info *info_meta, struct dm_info *info_data); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -76,7 +76,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name) | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (dir_exists(vg_path) && dm_is_empty_dir(vg_path)) { | ||||
| 	if (dir_exists(vg_path) && is_empty_dir(vg_path)) { | ||||
| 		log_very_verbose("Removing directory %s", vg_path); | ||||
| 		rmdir(vg_path); | ||||
| 	} | ||||
| @@ -93,7 +93,7 @@ static void _rm_blks(const char *dir) | ||||
| 	DIR *d; | ||||
|  | ||||
| 	if (!(d = opendir(dir))) { | ||||
| 		log_sys_debug("opendir", dir); | ||||
| 		log_sys_error("opendir", dir); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| @@ -104,7 +104,7 @@ static void _rm_blks(const char *dir) | ||||
| 			continue; | ||||
|  | ||||
| 		if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) { | ||||
| 			log_debug("Couldn't create path for %s.", name); | ||||
| 			log_error("Couldn't create path for %s", name); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| @@ -113,12 +113,12 @@ static void _rm_blks(const char *dir) | ||||
| 				continue; | ||||
| 			log_very_verbose("Removing %s", path); | ||||
| 			if (unlink(path) < 0) | ||||
| 				log_sys_debug("unlink", path); | ||||
| 				log_sys_error("unlink", path); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (closedir(d)) | ||||
| 		log_sys_debug("closedir", dir); | ||||
| 		log_sys_error("closedir", dir); | ||||
| } | ||||
|  | ||||
| static int _mk_link(const char *dev_dir, const char *vg_name, | ||||
| @@ -169,7 +169,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name, | ||||
|  | ||||
| 			log_very_verbose("Removing %s", lvm1_group_path); | ||||
| 			if (unlink(lvm1_group_path) < 0) | ||||
| 				log_sys_debug("unlink", lvm1_group_path); | ||||
| 				log_sys_error("unlink", lvm1_group_path); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
							
								
								
									
										1625
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1625
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										51
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							| @@ -41,13 +41,18 @@ struct lvmcache_vginfo; | ||||
|  | ||||
| /* | ||||
|  * vgsummary represents a summary of the VG that is read | ||||
|  * without a lock during label scan.  It's used to populate | ||||
|  * basic lvmcache vginfo/info during label scan prior to | ||||
|  * vg_read(). | ||||
|  * without a lock.  The info does not come through vg_read(), | ||||
|  * but through reading mdas.  It provides information about | ||||
|  * the VG that is needed to lock the VG and then read it fully | ||||
|  * with vg_read(), after which the VG summary should be checked | ||||
|  * against the full VG metadata to verify it was correct (since | ||||
|  * it was read without a lock.) | ||||
|  * | ||||
|  * Once read, vgsummary information is saved in lvmcache_vginfo. | ||||
|  */ | ||||
| struct lvmcache_vgsummary { | ||||
| 	const char *vgname; | ||||
| 	char vgid[ID_LEN + 1]; | ||||
| 	struct id vgid; | ||||
| 	uint64_t vgstatus; | ||||
| 	char *creation_host; | ||||
| 	const char *system_id; | ||||
| @@ -58,8 +63,6 @@ struct lvmcache_vgsummary { | ||||
| 	int mda_num; /* 1 = summary from mda1, 2 = summary from mda2 */ | ||||
| 	unsigned mda_ignored:1; | ||||
| 	unsigned zero_offset:1; | ||||
| 	unsigned mismatch:1; /* lvmcache sets if this summary differs from previous values */ | ||||
| 	struct dm_list pvsummaries; | ||||
| }; | ||||
|  | ||||
| int lvmcache_init(struct cmd_context *cmd); | ||||
| @@ -69,21 +72,21 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset); | ||||
| int lvmcache_label_scan(struct cmd_context *cmd); | ||||
| int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid); | ||||
| int lvmcache_label_rescan_vg_rw(struct cmd_context *cmd, const char *vgname, const char *vgid); | ||||
| int lvmcache_label_reopen_vg_rw(struct cmd_context *cmd, const char *vgname, const char *vgid); | ||||
|  | ||||
| /* Add/delete a device */ | ||||
| struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *labeller, const char *pvid, | ||||
| struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, | ||||
|                                    struct device *dev, uint64_t label_sector, | ||||
|                                    const char *vgname, const char *vgid, | ||||
|                                    uint32_t vgstatus, int *is_duplicate); | ||||
| int lvmcache_add_orphan_vginfo(struct cmd_context *cmd, const char *vgname, struct format_type *fmt); | ||||
| int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt); | ||||
| void lvmcache_del(struct lvmcache_info *info); | ||||
| void lvmcache_del_dev(struct device *dev); | ||||
|  | ||||
| /* Update things */ | ||||
| int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info *info, | ||||
| int lvmcache_update_vgname_and_id(struct lvmcache_info *info, | ||||
| 				  struct lvmcache_vgsummary *vgsummary); | ||||
| int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted); | ||||
| int lvmcache_update_vg_from_write(struct volume_group *vg); | ||||
|  | ||||
| void lvmcache_lock_vgname(const char *vgname, int read_only); | ||||
| void lvmcache_unlock_vgname(const char *vgname); | ||||
| @@ -95,10 +98,9 @@ struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname, | ||||
| 					   const char *vgid); | ||||
| 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); | ||||
| struct lvmcache_info *lvmcache_info_from_pv_id(const struct id *pv_id, 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_pv_id(struct cmd_context *cmd, const struct id *pv_id, uint64_t *label_sector); | ||||
| struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector); | ||||
| const char *lvmcache_vgname_from_info(struct lvmcache_info *info); | ||||
| const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info); | ||||
|  | ||||
| @@ -162,6 +164,11 @@ struct device *lvmcache_device(struct lvmcache_info *info); | ||||
| unsigned lvmcache_mda_count(struct lvmcache_info *info); | ||||
| uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info); | ||||
|  | ||||
| struct metadata_area *lvmcache_get_mda(struct cmd_context *cmd, | ||||
|                                       const char *vgname, | ||||
|                                       struct device *dev, | ||||
|                                       int use_mda_num); | ||||
|  | ||||
| bool lvmcache_has_duplicate_devs(void); | ||||
| void lvmcache_del_dev_from_duplicates(struct device *dev); | ||||
| bool lvmcache_dev_is_unused_duplicate(struct device *dev); | ||||
| @@ -170,7 +177,6 @@ int lvmcache_get_unused_duplicates(struct cmd_context *cmd, struct dm_list *head | ||||
| int vg_has_duplicate_pvs(struct volume_group *vg); | ||||
|  | ||||
| int lvmcache_found_duplicate_vgnames(void); | ||||
| bool lvmcache_has_duplicate_local_vgname(const char *vgid, const char *vgname); | ||||
|  | ||||
| int lvmcache_contains_lock_type_sanlock(struct cmd_context *cmd); | ||||
|  | ||||
| @@ -181,7 +187,7 @@ int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const ch | ||||
|  | ||||
| bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid); | ||||
|  | ||||
| int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, const char *pvid_arg); | ||||
| int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid); | ||||
|  | ||||
| uint64_t lvmcache_max_metadata_size(void); | ||||
| void lvmcache_save_metadata_size(uint64_t val); | ||||
| @@ -209,25 +215,8 @@ void lvmcache_del_outdated_devs(struct cmd_context *cmd, | ||||
|  | ||||
| void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda); | ||||
|  | ||||
| void lvmcache_del_save_bad_mda(struct lvmcache_info *info, int mda_num, int bad_mda_flag); | ||||
|  | ||||
| void lvmcache_get_bad_mdas(struct cmd_context *cmd, | ||||
|                            const char *vgname, const char *vgid, | ||||
|                            struct dm_list *bad_mda_list); | ||||
|  | ||||
| void lvmcache_get_mdas(struct cmd_context *cmd, | ||||
|                        const char *vgname, const char *vgid, | ||||
|                        struct dm_list *mda_list); | ||||
|  | ||||
| const char *dev_filtered_reason(struct device *dev); | ||||
| const char *devname_error_reason(const char *devname); | ||||
|  | ||||
| struct metadata_area *lvmcache_get_dev_mda(struct device *dev, int mda_num); | ||||
|  | ||||
| void lvmcache_extra_md_component_checks(struct cmd_context *cmd); | ||||
|  | ||||
| unsigned int lvmcache_vg_info_count(void); | ||||
|  | ||||
| int lvmcache_pvsummary_count(const char *vgname); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -335,7 +335,7 @@ static int _lookup_kallsyms(const char *symbol) | ||||
|  | ||||
| static int _target_present(struct cmd_context *cmd, | ||||
| 			   const struct lv_segment *seg __attribute__((unused)), | ||||
| 			   unsigned *attributes) | ||||
| 			   unsigned *attributes __attribute__((unused))) | ||||
| { | ||||
| 	/* List of features with their kernel target version */ | ||||
| 	static const struct feature { | ||||
| @@ -504,6 +504,9 @@ static int _cache_text_import(struct lv_segment *seg, | ||||
|  | ||||
| 	seg->lv->status |= strstr(seg->lv->name, "_corig") ? LV_PENDING_DELETE : 0; | ||||
|  | ||||
| 	if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL)) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (!_settings_text_import(seg, sn)) | ||||
| 		return_0; | ||||
|  | ||||
| @@ -525,26 +528,17 @@ static int _cache_text_import(struct lv_segment *seg, | ||||
| 		if (!dm_config_get_uint64(sn, "data_len", &seg->data_len)) | ||||
| 			return SEG_LOG_ERROR("Couldn't read data_len in"); | ||||
|  | ||||
| 		/* Will use CVOL ID, when metadata_id is not provided */ | ||||
| 		if (dm_config_has_node(sn, "metadata_id")) { | ||||
| 			if (!(seg->metadata_id = dm_pool_alloc(seg->lv->vg->vgmem, sizeof(*seg->metadata_id)))) | ||||
| 				return SEG_LOG_ERROR("Couldn't allocate metadata_id in"); | ||||
| 			if (!dm_config_get_str(sn, "metadata_id", &uuid)) | ||||
| 				return SEG_LOG_ERROR("Couldn't read metadata_id in"); | ||||
| 			if (!id_read_format(seg->metadata_id, uuid)) | ||||
| 				return SEG_LOG_ERROR("Couldn't format metadata_id in"); | ||||
| 		} | ||||
| 		if (!dm_config_get_str(sn, "metadata_id", &uuid)) | ||||
| 			return SEG_LOG_ERROR("Couldn't read metadata_id in"); | ||||
|  | ||||
| 		/* Will use CVOL ID, when data_id is not provided */ | ||||
| 		if (dm_config_has_node(sn, "data_id")) { | ||||
| 			if (!(seg->data_id = dm_pool_alloc(seg->lv->vg->vgmem, sizeof(*seg->data_id)))) | ||||
| 				return SEG_LOG_ERROR("Couldn't allocate data_id in"); | ||||
| 			if (!dm_config_get_str(sn, "data_id", &uuid)) | ||||
| 				return SEG_LOG_ERROR("Couldn't read data_id in"); | ||||
| 			if (!id_read_format(seg->data_id, uuid)) | ||||
| 				return SEG_LOG_ERROR("Couldn't format data_id in"); | ||||
| 		} | ||||
| 		pool_lv->status |= LV_CACHE_VOL; /* Mark as cachevol LV */ | ||||
| 		if (!id_read_format(&seg->metadata_id, uuid)) | ||||
| 			return SEG_LOG_ERROR("Couldn't format metadata_id in"); | ||||
|  | ||||
| 		if (!dm_config_get_str(sn, "data_id", &uuid)) | ||||
| 			return SEG_LOG_ERROR("Couldn't read data_id in"); | ||||
|  | ||||
| 		if (!id_read_format(&seg->data_id, uuid)) | ||||
| 			return SEG_LOG_ERROR("Couldn't format data_id in"); | ||||
| 	} else { | ||||
| 		/* Do not call this when LV is cache_vol. */ | ||||
| 		/* load order is unknown, could be cache origin or pool LV, so check for both */ | ||||
| @@ -552,9 +546,6 @@ static int _cache_text_import(struct lv_segment *seg, | ||||
| 			_fix_missing_defaults(first_seg(pool_lv)); | ||||
| 	} | ||||
|  | ||||
| 	if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL)) | ||||
| 		return_0; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| @@ -590,17 +581,13 @@ static int _cache_text_export(const struct lv_segment *seg, struct formatter *f) | ||||
| 		outf(f, "data_start = " FMTu64, seg->data_start); | ||||
| 		outf(f, "data_len = " FMTu64, seg->data_len); | ||||
|  | ||||
| 		if (seg->metadata_id) { | ||||
| 			if (!id_write_format(seg->metadata_id, buffer, sizeof(buffer))) | ||||
| 				return_0; | ||||
| 			outf(f, "metadata_id = \"%s\"", buffer); | ||||
| 		} | ||||
| 		if (!id_write_format(&seg->metadata_id, buffer, sizeof(buffer))) | ||||
| 			return_0; | ||||
| 		outf(f, "metadata_id = \"%s\"", buffer); | ||||
|  | ||||
| 		if (seg->data_id) { | ||||
| 			if (!id_write_format(seg->data_id, buffer, sizeof(buffer))) | ||||
| 				return_0; | ||||
| 			outf(f, "data_id = \"%s\"", buffer); | ||||
| 		} | ||||
| 		if (!id_write_format(&seg->data_id, buffer, sizeof(buffer))) | ||||
| 			return_0; | ||||
| 		outf(f, "data_id = \"%s\"", buffer); | ||||
| 	} | ||||
|  | ||||
| 	return 1; | ||||
| @@ -618,9 +605,6 @@ static int _cache_add_target_line(struct dev_manager *dm, | ||||
| { | ||||
| 	struct lv_segment *cache_pool_seg; | ||||
| 	struct lv_segment *setting_seg; | ||||
| 	struct dm_config_node *policy_settings; | ||||
| 	struct dm_config_node *cn; | ||||
| 	unsigned  i, j; | ||||
| 	union lvid metadata_lvid; | ||||
| 	union lvid data_lvid; | ||||
| 	char *metadata_uuid, *data_uuid, *origin_uuid; | ||||
| @@ -711,71 +695,16 @@ static int _cache_add_target_line(struct dev_manager *dm, | ||||
| 		memset(&metadata_lvid, 0, sizeof(metadata_lvid)); | ||||
| 		memset(&data_lvid, 0, sizeof(data_lvid)); | ||||
| 		memcpy(&metadata_lvid.id[0], &seg->lv->vg->id, sizeof(struct id)); | ||||
| 		memcpy(&metadata_lvid.id[1], (seg->metadata_id) ? : &seg->pool_lv->lvid.id[1], sizeof(struct id)); | ||||
| 		memcpy(&metadata_lvid.id[1], &seg->metadata_id, sizeof(struct id)); | ||||
| 		memcpy(&data_lvid.id[0], &seg->lv->vg->id, sizeof(struct id)); | ||||
| 		memcpy(&data_lvid.id[1], (seg->data_id) ? : &seg->pool_lv->lvid.id[1], sizeof(struct id)); | ||||
| 		memcpy(&data_lvid.id[1], &seg->data_id, sizeof(struct id)); | ||||
|  | ||||
| 		if (!(metadata_uuid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&metadata_lvid.s, "cmeta"))) | ||||
| 		if (!(metadata_uuid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&metadata_lvid.s, NULL))) | ||||
| 			return_0; | ||||
| 		if (!(data_uuid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&data_lvid.s, "cdata"))) | ||||
| 		if (!(data_uuid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&data_lvid.s, NULL))) | ||||
| 			return_0; | ||||
| 	} | ||||
|  | ||||
| 	policy_settings = seg->cleaner_policy ? NULL : setting_seg->policy_settings; | ||||
| 	if (policy_settings && cache_pool_seg->policy_name) { | ||||
| 		static const struct act { | ||||
| 			const char *name; | ||||
| 			const char *settings[20]; | ||||
| 		} _accepted[] = { | ||||
| 			{ | ||||
| 				"MQ", { | ||||
| 					"migration_threshold", "sequential_threshold", "random_threshold", | ||||
| 					"read_promote_adjustment", "write_promote_adjustment", | ||||
| 					"discard_promote_adjustment", NULL | ||||
| 				}, | ||||
| 			}, { | ||||
| 				"SMQ", { | ||||
| 					"migration_threshold", NULL | ||||
| 				} | ||||
| 			} | ||||
| 		}; | ||||
|  | ||||
|                 /* Check if cache settings are acceptable to knownm policies */ | ||||
| 		for (i = 0; i < DM_ARRAY_SIZE(_accepted); i++) { | ||||
| 			if (strcasecmp(cache_pool_seg->policy_name, _accepted[i].name)) | ||||
| 				continue; | ||||
|  | ||||
| 			for (cn = policy_settings->child; cn; cn = cn->sib) { | ||||
| 				for (j = 0; _accepted[i].settings[j]; j++) | ||||
| 					if (strcmp(cn->key, _accepted[i].settings[j]) == 0) | ||||
| 						break; /* -> Valid setting */ | ||||
|  | ||||
| 				/* Have we found 'unsupported' cache setting? */ | ||||
| 				if (!_accepted[i].settings[j]) { | ||||
| 					/* Make a copy of policy settings a remove unsupported settings and Warn */ | ||||
| 					if (!(policy_settings = dm_config_clone_node_with_mem(mem, policy_settings, 0))) | ||||
| 						return_0; | ||||
| 				restart: | ||||
| 					for (cn = policy_settings->child; cn; cn = cn->sib) { | ||||
| 						for (j = 0; _accepted[i].settings[j]; j++) { | ||||
| 							if (strcmp(cn->key, _accepted[i].settings[j]) == 0) | ||||
| 								break; /* need to be dropped */ | ||||
| 						} | ||||
| 						if (!_accepted[i].settings[j]) { | ||||
| 							log_warn("WARNING: %s cache policy does not support \"%s=" FMTu64 "\" setting, " | ||||
| 								 "remove with 'lvchange --cachesettings \"%s=default\" ...'.", | ||||
| 								 _accepted[i].name, cn->key, cn->v->v.i, cn->key); | ||||
| 							dm_config_remove_node(policy_settings, cn); | ||||
| 							goto restart; | ||||
| 						} | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!dm_tree_node_add_cache_target(node, len, | ||||
| 					   feature_flags, | ||||
| 					   metadata_uuid, | ||||
| @@ -784,7 +713,7 @@ static int _cache_add_target_line(struct dev_manager *dm, | ||||
| 					   seg->cleaner_policy ? "cleaner" : | ||||
| 						   /* undefined policy name -> likely an old "mq" */ | ||||
| 						   cache_pool_seg->policy_name ? : "mq", | ||||
| 					   policy_settings, | ||||
| 					   seg->cleaner_policy ? NULL : setting_seg->policy_settings, | ||||
| 					   seg->metadata_start, | ||||
| 					   seg->metadata_len, | ||||
| 					   seg->data_start, | ||||
|   | ||||
| @@ -32,7 +32,6 @@ | ||||
| #include "lib/cache/lvmcache.h" | ||||
| #include "lib/format_text/archiver.h" | ||||
| #include "lib/lvmpolld/lvmpolld-client.h" | ||||
| #include "lib/device/device_id.h" | ||||
|  | ||||
| #include <locale.h> | ||||
| #include <sys/stat.h> | ||||
| @@ -41,10 +40,6 @@ | ||||
| #include <syslog.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #ifdef APP_MACHINEID_SUPPORT | ||||
| #include <systemd/sd-id128.h> | ||||
| #endif | ||||
|  | ||||
| #ifdef __linux__ | ||||
| #  include <malloc.h> | ||||
| #endif | ||||
| @@ -133,12 +128,9 @@ static const char *_read_system_id_from_file(struct cmd_context *cmd, const char | ||||
| 	return system_id; | ||||
| } | ||||
|  | ||||
| /* systemd-id128 new produced: f64406832c2140e8ac5422d1089aae03 */ | ||||
| #define LVM_APPLICATION_ID SD_ID128_MAKE(f6,44,06,83,2c,21,40,e8,ac,54,22,d1,08,9a,ae,03) | ||||
|  | ||||
| static const char *_system_id_from_source(struct cmd_context *cmd, const char *source) | ||||
| { | ||||
| 	char buf[PATH_MAX]; | ||||
| 	char filebuf[PATH_MAX]; | ||||
| 	const char *file; | ||||
| 	const char *etc_str; | ||||
| 	const char *str; | ||||
| @@ -157,25 +149,10 @@ static const char *_system_id_from_source(struct cmd_context *cmd, const char *s | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| #ifdef APP_MACHINEID_SUPPORT | ||||
| 	if (!strcasecmp(source, "appmachineid")) { | ||||
| 		sd_id128_t id = { 0 }; | ||||
|  | ||||
| 		if (sd_id128_get_machine_app_specific(LVM_APPLICATION_ID, &id) != 0) | ||||
| 			log_warn("WARNING: sd_id128_get_machine_app_specific() failed %s (%d).", | ||||
| 				 strerror(errno), errno); | ||||
|  | ||||
| 		if (dm_snprintf(buf, PATH_MAX, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)) < 0) | ||||
| 			stack; | ||||
| 		system_id = system_id_from_string(cmd, buf); | ||||
| 		goto out; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	if (!strcasecmp(source, "machineid") || !strcasecmp(source, "machine-id")) { | ||||
| 		etc_str = find_config_tree_str(cmd, global_etc_CFG, NULL); | ||||
| 		if (dm_snprintf(buf, sizeof(buf), "%s/machine-id", etc_str) != -1) | ||||
| 			system_id = _read_system_id_from_file(cmd, buf); | ||||
| 		if (dm_snprintf(filebuf, sizeof(filebuf), "%s/machine-id", etc_str) != -1) | ||||
| 			system_id = _read_system_id_from_file(cmd, filebuf); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| @@ -252,7 +229,7 @@ static void _get_sysfs_dir(struct cmd_context *cmd, char *buf, size_t buf_size) | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	(void) dm_strncpy(buf, sys_mnt, buf_size); | ||||
| 	strncpy(buf, sys_mnt, buf_size); | ||||
| } | ||||
|  | ||||
| static uint32_t _parse_debug_fields(struct cmd_context *cmd, int cfg, const char *cfgname) | ||||
| @@ -342,33 +319,6 @@ static int _parse_debug_classes(struct cmd_context *cmd) | ||||
| 	return debug_classes; | ||||
| } | ||||
|  | ||||
| static uint32_t _parse_log_journal(struct cmd_context *cmd, int cfg, const char *cfgname) | ||||
| { | ||||
| 	const struct dm_config_node *cn; | ||||
| 	const struct dm_config_value *cv; | ||||
| 	uint32_t fields = 0; | ||||
| 	uint32_t val; | ||||
|  | ||||
| 	if (!(cn = find_config_tree_array(cmd, cfg, NULL))) { | ||||
| 		log_debug("Unable to find configuration for log/%s.", cfgname); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	for (cv = cn->v; cv; cv = cv->next) { | ||||
| 		if (cv->type != DM_CFG_STRING) { | ||||
| 			log_verbose("log/%s contains a value which is not a string.  Ignoring.", cfgname); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if ((val = log_journal_str_to_val(cv->v.str))) | ||||
| 			fields |= val; | ||||
| 		else | ||||
| 			log_verbose("Unrecognised value for log/%s: %s", cfgname, cv->v.str); | ||||
| 	} | ||||
|  | ||||
| 	return fields; | ||||
| } | ||||
|  | ||||
| static void _init_logging(struct cmd_context *cmd) | ||||
| { | ||||
| 	int append = 1; | ||||
| @@ -379,11 +329,12 @@ static void _init_logging(struct cmd_context *cmd) | ||||
|  | ||||
| 	/* Syslog */ | ||||
| 	cmd->default_settings.syslog = find_config_tree_bool(cmd, log_syslog_CFG, NULL); | ||||
| 	if (cmd->default_settings.syslog) | ||||
| 		init_syslog(1, DEFAULT_LOG_FACILITY); | ||||
| 	else | ||||
| 	if (cmd->default_settings.syslog != 1) | ||||
| 		fin_syslog(); | ||||
|  | ||||
| 	if (cmd->default_settings.syslog > 1) | ||||
| 		init_syslog(cmd->default_settings.syslog); | ||||
|  | ||||
| 	/* Debug level for log file output */ | ||||
| 	cmd->default_settings.debug = find_config_tree_int(cmd, log_level_CFG, NULL); | ||||
| 	init_debug(cmd->default_settings.debug); | ||||
| @@ -436,9 +387,6 @@ static void _init_logging(struct cmd_context *cmd) | ||||
| 	init_debug_file_fields(_parse_debug_fields(cmd, log_debug_file_fields_CFG, "debug_file_fields")); | ||||
| 	init_debug_output_fields(_parse_debug_fields(cmd, log_debug_output_fields_CFG, "debug_output_fields")); | ||||
|  | ||||
| 	cmd->default_settings.journal = _parse_log_journal(cmd, log_journal_CFG, "journal"); | ||||
| 	init_log_journal(cmd->default_settings.journal); | ||||
|  | ||||
| 	t = time(NULL); | ||||
| 	ctime_r(&t, &timebuf[0]); | ||||
| 	timebuf[24] = '\0'; | ||||
| @@ -453,12 +401,15 @@ static void _init_logging(struct cmd_context *cmd) | ||||
| 	reset_lvm_errno(1); | ||||
| } | ||||
|  | ||||
| static int _check_disable_udev(const char *msg) | ||||
| { | ||||
| static int _check_disable_udev(const char *msg) { | ||||
| 	if (getenv("DM_DISABLE_UDEV")) { | ||||
| 		log_very_verbose("DM_DISABLE_UDEV environment variable set."); | ||||
| 		log_very_verbose("Overriding configuration to use udev_rules=0, udev_sync=0, verify_udev_operations=1."); | ||||
| 		log_very_verbose("LVM will %s.", msg); | ||||
| 		log_very_verbose("DM_DISABLE_UDEV environment variable set. " | ||||
| 				 "Overriding configuration to use " | ||||
| 				 "udev_rules=0, udev_sync=0, verify_udev_operations=1."); | ||||
| 		if (udev_is_running()) | ||||
| 			log_warn("Udev is running and DM_DISABLE_UDEV environment variable is set. " | ||||
| 				 "Bypassing udev, LVM will %s.", msg); | ||||
|  | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| @@ -611,7 +562,7 @@ static int _init_system_id(struct cmd_context *cmd) | ||||
| static int _process_config(struct cmd_context *cmd) | ||||
| { | ||||
| 	mode_t old_umask; | ||||
| 	const char *dev_ext_info_src = NULL; | ||||
| 	const char *dev_ext_info_src; | ||||
| 	const char *read_ahead; | ||||
| 	struct stat st; | ||||
| 	const struct dm_config_node *cn; | ||||
| @@ -645,25 +596,14 @@ static int _process_config(struct cmd_context *cmd) | ||||
| #endif | ||||
|  | ||||
| 	dev_ext_info_src = find_config_tree_str(cmd, devices_external_device_info_source_CFG, NULL); | ||||
|  | ||||
| 	if (dev_ext_info_src && | ||||
| 	    strcmp(dev_ext_info_src, "none") && | ||||
| 	    strcmp(dev_ext_info_src, "udev")) { | ||||
| 		log_warn("WARNING: unknown external device info source, using none."); | ||||
| 		dev_ext_info_src = NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (dev_ext_info_src && !strcmp(dev_ext_info_src, "udev")) { | ||||
| 		if (udev_init_library_context()) { | ||||
| 			init_external_device_info_source(DEV_EXT_UDEV); | ||||
| 		} else { | ||||
| 			log_warn("WARNING: failed to init udev for external device info, using none."); | ||||
| 			dev_ext_info_src = NULL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!dev_ext_info_src || !strcmp(dev_ext_info_src, "none")) | ||||
| 	if (dev_ext_info_src && !strcmp(dev_ext_info_src, "none")) | ||||
| 		init_external_device_info_source(DEV_EXT_NONE); | ||||
| 	else if (dev_ext_info_src && !strcmp(dev_ext_info_src, "udev")) | ||||
| 		init_external_device_info_source(DEV_EXT_UDEV); | ||||
| 	else { | ||||
| 		log_error("Invalid external device info source specification."); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* proc dir */ | ||||
| 	if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s", | ||||
| @@ -720,8 +660,6 @@ static int _process_config(struct cmd_context *cmd) | ||||
| 	 */ | ||||
| 	cmd->default_settings.udev_fallback = udev_disabled ? 1 : -1; | ||||
|  | ||||
| 	cmd->default_settings.issue_discards = find_config_tree_bool(cmd, devices_issue_discards_CFG, NULL); | ||||
|  | ||||
| 	init_retry_deactivation(find_config_tree_bool(cmd, activation_retry_deactivation_CFG, NULL)); | ||||
|  | ||||
| 	init_activation_checks(find_config_tree_bool(cmd, activation_checks_CFG, NULL)); | ||||
| @@ -767,7 +705,6 @@ static int _process_config(struct cmd_context *cmd) | ||||
| 	init_pv_min_size((uint64_t)pv_min_kb * (1024 >> SECTOR_SHIFT)); | ||||
|  | ||||
| 	cmd->check_pv_dev_sizes = find_config_tree_bool(cmd, metadata_check_pv_device_sizes_CFG, NULL); | ||||
| 	cmd->event_activation = find_config_tree_bool(cmd, global_event_activation_CFG, NULL); | ||||
|  | ||||
| 	if (!process_profilable_config(cmd)) | ||||
| 		return_0; | ||||
| @@ -1026,13 +963,8 @@ static void _destroy_config(struct cmd_context *cmd) | ||||
| 	/* CONFIG_FILE/CONFIG_MERGED_FILES */ | ||||
| 	if ((cft = remove_config_tree_by_source(cmd, CONFIG_MERGED_FILES))) | ||||
| 		config_destroy(cft); | ||||
| 	else if ((cft = remove_config_tree_by_source(cmd, CONFIG_FILE))) { | ||||
| 		dm_list_iterate_items(cfl, &cmd->config_files) { | ||||
| 			if (cfl->cft == cft) | ||||
| 				dm_list_del(&cfl->list); | ||||
| 		} | ||||
| 		config_destroy(cft); | ||||
| 	} | ||||
| 	else | ||||
| 		remove_config_tree_by_source(cmd, CONFIG_FILE); | ||||
|  | ||||
| 	dm_list_iterate_items(cfl, &cmd->config_files) | ||||
| 		config_destroy(cfl->cft); | ||||
| @@ -1078,10 +1010,16 @@ static int _init_dev_cache(struct cmd_context *cmd) | ||||
| 	if (!dev_cache_init(cmd)) | ||||
| 		return_0; | ||||
|  | ||||
| 	if ((device_list_from_udev = find_config_tree_bool(cmd, devices_obtain_device_list_from_udev_CFG, NULL))) { | ||||
| 		if (!udev_init_library_context()) | ||||
| 			device_list_from_udev = 0; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * Override existing config and hardcode device_list_from_udev = 0 if: | ||||
| 	 *   - udev is not running | ||||
| 	 *   - udev is disabled using DM_DISABLE_UDEV environment variable | ||||
| 	 */ | ||||
| 	if (_check_disable_udev("obtain device list by scanning device directory")) | ||||
| 		device_list_from_udev = 0; | ||||
| 	else | ||||
| 		device_list_from_udev = udev_is_running() ? | ||||
| 			find_config_tree_bool(cmd, devices_obtain_device_list_from_udev_CFG, NULL) : 0; | ||||
|  | ||||
| 	init_obtain_device_list_from_udev(device_list_from_udev); | ||||
|  | ||||
| @@ -1128,7 +1066,7 @@ static int _init_dev_cache(struct cmd_context *cmd) | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| #define MAX_FILTERS 11 | ||||
| #define MAX_FILTERS 10 | ||||
|  | ||||
| static struct dev_filter *_init_filter_chain(struct cmd_context *cmd) | ||||
| { | ||||
| @@ -1143,6 +1081,16 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd) | ||||
| 	 * Update MAX_FILTERS definition above when adding new filters. | ||||
| 	 */ | ||||
|  | ||||
| 	/* | ||||
| 	 * sysfs filter. Only available on 2.6 kernels.  Non-critical. | ||||
| 	 * Listed first because it's very efficient at eliminating | ||||
| 	 * unavailable devices. | ||||
| 	 */ | ||||
| 	if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) { | ||||
| 		if ((filters[nr_filt] = sysfs_filter_create())) | ||||
| 			nr_filt++; | ||||
| 	} | ||||
|  | ||||
| 	/* internal filter used by command processing. */ | ||||
| 	if (!(filters[nr_filt] = internal_filter_create())) { | ||||
| 		log_error("Failed to create internal device filter"); | ||||
| @@ -1152,7 +1100,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd) | ||||
|  | ||||
| 	/* global regex filter. Optional. */ | ||||
| 	if ((cn = find_config_tree_node(cmd, devices_global_filter_CFG, NULL))) { | ||||
| 		if (!(filters[nr_filt] = regex_filter_create(cn->v, 0, 1))) { | ||||
| 		if (!(filters[nr_filt] = regex_filter_create(cn->v))) { | ||||
| 			log_error("Failed to create global regex device filter"); | ||||
| 			goto bad; | ||||
| 		} | ||||
| @@ -1161,7 +1109,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd) | ||||
|  | ||||
| 	/* regex filter. Optional. */ | ||||
| 	if ((cn = find_config_tree_node(cmd, devices_filter_CFG, NULL))) { | ||||
| 		if (!(filters[nr_filt] = regex_filter_create(cn->v, 1, 0))) { | ||||
| 		if (!(filters[nr_filt] = regex_filter_create(cn->v))) { | ||||
| 			log_error("Failed to create regex device filter"); | ||||
| 			goto bad; | ||||
| 		} | ||||
| @@ -1175,24 +1123,6 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd) | ||||
| 	} | ||||
| 	nr_filt++; | ||||
|  | ||||
| 	/* filter based on the device_ids saved in the devices file */ | ||||
| 	if (!(filters[nr_filt] = deviceid_filter_create(cmd))) { | ||||
| 		log_error("Failed to create deviceid device filter"); | ||||
| 		goto bad; | ||||
| 	} | ||||
| 	nr_filt++; | ||||
|  | ||||
| 	/* | ||||
| 	 * sysfs filter. Only available on 2.6 kernels.  Non-critical. | ||||
| 	 * Eliminates unavailable devices. | ||||
| 	 * TODO: this may be unnecessary now with device ids | ||||
| 	 * (currently not used for devs match to device id using syfs) | ||||
| 	 */ | ||||
| 	if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) { | ||||
| 		if ((filters[nr_filt] = sysfs_filter_create())) | ||||
| 			nr_filt++; | ||||
| 	} | ||||
|  | ||||
| 	/* usable device filter. Required. */ | ||||
| 	if (!(filters[nr_filt] = usable_filter_create(cmd, cmd->dev_types, FILTER_MODE_NO_LVMETAD))) { | ||||
| 		log_error("Failed to create usabled device filter"); | ||||
| @@ -1234,7 +1164,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd) | ||||
| 			nr_filt++; | ||||
| 	} | ||||
|  | ||||
| 	if (!(composite = composite_filter_create(nr_filt, filters))) | ||||
| 	if (!(composite = composite_filter_create(nr_filt, 1, filters))) | ||||
| 		goto_bad; | ||||
|  | ||||
| 	return composite; | ||||
| @@ -1346,7 +1276,7 @@ int init_lvmcache_orphans(struct cmd_context *cmd) | ||||
| 	struct format_type *fmt; | ||||
|  | ||||
| 	dm_list_iterate_items(fmt, &cmd->formats) | ||||
| 		if (!lvmcache_add_orphan_vginfo(cmd, fmt->orphan_vg_name, fmt)) | ||||
| 		if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt)) | ||||
| 			return_0; | ||||
|  | ||||
| 	return 1; | ||||
| @@ -1432,11 +1362,6 @@ static int _init_segtypes(struct cmd_context *cmd) | ||||
| 		return 0; | ||||
| #endif | ||||
|  | ||||
| #ifdef INTEGRITY_INTERNAL | ||||
| 	if (!init_integrity_segtypes(cmd, &seglib)) | ||||
| 		return 0; | ||||
| #endif | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| @@ -1555,7 +1480,6 @@ int init_run_by_dmeventd(struct cmd_context *cmd) | ||||
| 	init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE); | ||||
| 	init_ignore_suspended_devices(1); | ||||
| 	init_disable_dmeventd_monitoring(1); /* Lock settings */ | ||||
| 	cmd->run_by_dmeventd = 1; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| @@ -1603,6 +1527,7 @@ struct cmd_context *create_config_context(void) | ||||
|  | ||||
| 	dm_list_init(&cmd->config_files); | ||||
| 	dm_list_init(&cmd->tags); | ||||
| 	dm_list_init(&cmd->hints); | ||||
|  | ||||
| 	if (!_init_lvm_conf(cmd)) | ||||
| 		goto_out; | ||||
| @@ -1652,6 +1577,8 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd, | ||||
| 	bindtextdomain(INTL_PACKAGE, LOCALEDIR); | ||||
| #endif | ||||
|  | ||||
| 	init_syslog(DEFAULT_LOG_FACILITY); | ||||
|  | ||||
| 	if (!(cmd = zalloc(sizeof(*cmd)))) { | ||||
| 		log_error("Failed to allocate command context"); | ||||
| 		return NULL; | ||||
| @@ -1662,7 +1589,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd, | ||||
| 	cmd->handles_missing_pvs = 0; | ||||
| 	cmd->handles_unknown_segments = 0; | ||||
| 	cmd->hosttags = 0; | ||||
| 	cmd->check_devs_used = 1; | ||||
| 	dm_list_init(&cmd->arg_value_groups); | ||||
| 	dm_list_init(&cmd->formats); | ||||
| 	dm_list_init(&cmd->segtypes); | ||||
| @@ -1785,8 +1711,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd, | ||||
| 	if (!_init_dev_cache(cmd)) | ||||
| 		goto_out; | ||||
|  | ||||
| 	devices_file_init(cmd); | ||||
|  | ||||
| 	memlock_init(cmd); | ||||
|  | ||||
| 	if (!_init_formats(cmd)) | ||||
| @@ -1912,7 +1836,6 @@ int refresh_toolcontext(struct cmd_context *cmd) | ||||
| 	_destroy_segtypes(&cmd->segtypes); | ||||
| 	_destroy_formats(cmd, &cmd->formats); | ||||
|  | ||||
| 	devices_file_exit(cmd); | ||||
| 	if (!dev_cache_exit()) | ||||
| 		stack; | ||||
| 	_destroy_dev_types(cmd); | ||||
| @@ -1992,8 +1915,6 @@ int refresh_toolcontext(struct cmd_context *cmd) | ||||
| 	if (!_init_dev_cache(cmd)) | ||||
| 		return_0; | ||||
|  | ||||
| 	devices_file_init(cmd); | ||||
|  | ||||
| 	if (!_init_formats(cmd)) | ||||
| 		return_0; | ||||
|  | ||||
| @@ -2041,18 +1962,24 @@ void destroy_toolcontext(struct cmd_context *cmd) | ||||
| 	_destroy_segtypes(&cmd->segtypes); | ||||
| 	_destroy_formats(cmd, &cmd->formats); | ||||
| 	_destroy_filters(cmd); | ||||
| 	devices_file_exit(cmd); | ||||
| 	if (cmd->mem) | ||||
| 		dm_pool_destroy(cmd->mem); | ||||
| 	dev_cache_exit(); | ||||
| 	_destroy_dev_types(cmd); | ||||
| 	_destroy_tags(cmd); | ||||
|  | ||||
| 	if ((cft_cmdline = remove_config_tree_by_source(cmd, CONFIG_STRING))) | ||||
| 		config_destroy(cft_cmdline); | ||||
| 	_destroy_config(cmd); | ||||
|  | ||||
| 	if (cmd->cft_def_hash) | ||||
| 		dm_hash_destroy(cmd->cft_def_hash); | ||||
|  | ||||
| 	dm_device_list_destroy(&cmd->cache_dm_devs); | ||||
| 	if (cmd->libmem) | ||||
| 		dm_pool_destroy(cmd->libmem); | ||||
|  | ||||
| 	if (cmd->pending_delete_mem) | ||||
| 		dm_pool_destroy(cmd->pending_delete_mem); | ||||
| #ifndef VALGRIND_POOL | ||||
| 	if (cmd->linebuffer) { | ||||
| 		/* Reset stream buffering to defaults */ | ||||
| @@ -2077,7 +2004,7 @@ void destroy_toolcontext(struct cmd_context *cmd) | ||||
| 		free(cmd->linebuffer); | ||||
| 	} | ||||
| #endif | ||||
| 	destroy_config_context(cmd); | ||||
| 	free(cmd); | ||||
|  | ||||
| 	lvmpolld_disconnect(); | ||||
|  | ||||
|   | ||||
| @@ -29,9 +29,7 @@ struct config_info { | ||||
| 	int debug_classes; | ||||
| 	int verbose; | ||||
| 	int silent; | ||||
| 	int suppress; | ||||
| 	int test; | ||||
| 	int yes; | ||||
| 	int syslog; | ||||
| 	int activation; | ||||
| 	int suffix; | ||||
| @@ -41,8 +39,7 @@ struct config_info { | ||||
| 	int udev_rules; | ||||
| 	int udev_sync; | ||||
| 	int udev_fallback; | ||||
| 	int issue_discards; | ||||
| 	uint32_t journal; | ||||
| 	int cache_vgmetadata; | ||||
| 	const char *msg_prefix; | ||||
| 	const char *fmt_name; | ||||
| 	const char *dmeventd_executable; | ||||
| @@ -174,7 +171,7 @@ struct cmd_context { | ||||
| 	unsigned activate_component:1;		/* command activates component LV */ | ||||
| 	unsigned process_component_lvs:1;	/* command processes also component LVs */ | ||||
| 	unsigned mirror_warn_printed:1;		/* command already printed warning about non-monitored mirrors */ | ||||
| 	unsigned expect_missing_vg_device:1;	/* when reading a vg it's expected that a dev for a pv isn't found */ | ||||
| 	unsigned pvscan_cache_single:1; | ||||
| 	unsigned can_use_one_scan:1; | ||||
| 	unsigned is_clvmd:1; | ||||
| 	unsigned md_component_detection:1; | ||||
| @@ -185,37 +182,13 @@ struct cmd_context { | ||||
| 	unsigned pvscan_recreate_hints:1;	/* enable special case hint handling for pvscan --cache */ | ||||
| 	unsigned scan_lvs:1; | ||||
| 	unsigned wipe_outdated_pvs:1; | ||||
| 	unsigned enable_devices_list:1;		/* command is using --devices option */ | ||||
| 	unsigned enable_devices_file:1;		/* command is using devices file */ | ||||
| 	unsigned pending_devices_file:1;	/* command may create and enable devices file */ | ||||
| 	unsigned create_edit_devices_file:1;	/* command expects to create and/or edit devices file */ | ||||
| 	unsigned edit_devices_file:1;		/* command expects to edit devices file */ | ||||
| 	unsigned filter_deviceid_skip:1;	/* don't use filter-deviceid */ | ||||
| 	unsigned filter_regex_with_devices_file:1; /* use filter-regex even when devices file is enabled */ | ||||
| 	unsigned filter_nodata_only:1;          /* only use filters that do not require data from the dev */ | ||||
| 	unsigned run_by_dmeventd:1;		/* command is being run by dmeventd */ | ||||
| 	unsigned sysinit:1;			/* --sysinit is used */ | ||||
| 	unsigned ignorelockingfailure:1;	/* --ignorelockingfailure is used */ | ||||
| 	unsigned check_devs_used:1;		/* check devs used by LVs */ | ||||
| 	unsigned print_device_id_not_found:1;	/* print devices file entries not found */ | ||||
| 	unsigned ignore_device_name_mismatch:1; /* skip updating devices file names */ | ||||
| 	unsigned backup_disabled:1;		/* skip repeated debug message */ | ||||
| 	unsigned event_activation:1;		/* whether event_activation is set */ | ||||
| 	unsigned udevoutput:1; | ||||
| 	unsigned online_vg_file_removed:1; | ||||
| 	unsigned disable_dm_devs:1;		/* temporarily disable use of dm devs cache */ | ||||
|  | ||||
| 	/* | ||||
| 	 * Devices and filtering. | ||||
| 	 */ | ||||
| 	struct dev_filter *filter; | ||||
| 	struct dm_list use_devices;		/* struct dev_use for each entry in devices file */ | ||||
| 	struct dm_list hints; | ||||
| 	const char *md_component_checks; | ||||
| 	const char *search_for_devnames;	/* config file setting */ | ||||
| 	const char *devicesfile;                /* from --devicesfile option */ | ||||
| 	struct dm_list deviceslist;             /* from --devices option, struct dm_str_list */ | ||||
|  | ||||
| 	struct dm_list *cache_dm_devs;		/* cache with UUIDs from DM_DEVICE_LIST (when available) */ | ||||
|  | ||||
| 	/* | ||||
| 	 * Configuration. | ||||
| @@ -247,7 +220,6 @@ struct cmd_context { | ||||
| 	char system_dir[PATH_MAX]; | ||||
| 	char dev_dir[PATH_MAX]; | ||||
| 	char proc_dir[PATH_MAX]; | ||||
| 	char devices_file_path[PATH_MAX]; | ||||
|  | ||||
| 	/* | ||||
| 	 * Reporting. | ||||
|   | ||||
| @@ -501,15 +501,12 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r | ||||
| 			checksum_fn_t checksum_fn, uint32_t checksum, | ||||
| 			int checksum_only, int no_dup_node_check) | ||||
| { | ||||
| 	char namebuf[NAME_LEN + 1] __attribute__((aligned(8))); | ||||
| 	int namelen = 0; | ||||
| 	int bad_name = 0; | ||||
| 	char *fb, *fe; | ||||
| 	int r = 0; | ||||
| 	int sz, use_plain_read = 1; | ||||
| 	int use_mmap = 1; | ||||
| 	off_t mmap_offset = 0; | ||||
| 	char *buf = NULL; | ||||
| 	struct config_source *cs = dm_config_get_custom(cft); | ||||
| 	size_t rsize; | ||||
|  | ||||
| 	if (!_is_file_based_config_source(cs->type)) { | ||||
| 		log_error(INTERNAL_ERROR "config_file_read_fd: expected file, special file " | ||||
| @@ -518,30 +515,26 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Only use plain read with regular files */ | ||||
| 	/* Only use mmap with regular files */ | ||||
| 	if (!(dev->flags & DEV_REGULAR) || size2) | ||||
| 		use_plain_read = 0; | ||||
| 		use_mmap = 0; | ||||
|  | ||||
| 	/* Ensure there is extra '\0' after end of buffer since we pass | ||||
| 	 * buffer to funtions like strtoll() */ | ||||
| 	if (!(buf = zalloc(size + size2 + 1))) { | ||||
| 		log_error("Failed to allocate circular buffer."); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (use_plain_read) { | ||||
| 		/* Note: also used for lvm.conf to read all settings */ | ||||
| 		for (rsize = 0; rsize < size; rsize += sz) { | ||||
| 			do { | ||||
| 				sz = read(dev_fd(dev), buf + rsize, size - rsize); | ||||
| 			} while ((sz < 0) && ((errno == EINTR) || (errno == EAGAIN))); | ||||
|  | ||||
| 			if (sz < 0) { | ||||
| 				log_sys_error("read", dev_name(dev)); | ||||
| 				goto out; | ||||
| 			} | ||||
| 	if (use_mmap) { | ||||
| 		mmap_offset = offset % lvm_getpagesize(); | ||||
| 		/* memory map the file */ | ||||
| 		fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ, | ||||
| 			  MAP_PRIVATE, dev_fd(dev), offset - mmap_offset); | ||||
| 		if (fb == (caddr_t) (-1)) { | ||||
| 			log_sys_error("mmap", dev_name(dev)); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		fb = fb + mmap_offset; | ||||
| 	} else { | ||||
| 		if (!(buf = malloc(size + size2))) { | ||||
| 			log_error("Failed to allocate circular buffer."); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		if (!dev_read_bytes(dev, offset, size, buf)) | ||||
| 			goto out; | ||||
|  | ||||
| @@ -549,25 +542,8 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r | ||||
| 			if (!dev_read_bytes(dev, offset2, size2, buf + size)) | ||||
| 				goto out; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	fb = buf; | ||||
|  | ||||
| 	if (!(dev->flags & DEV_REGULAR)) { | ||||
| 		memcpy(namebuf, buf, NAME_LEN); | ||||
|  | ||||
| 		while (namebuf[namelen] && !isspace(namebuf[namelen]) && namebuf[namelen] != '{' && namelen < (NAME_LEN - 1)) | ||||
| 			namelen++; | ||||
| 		namebuf[namelen] = '\0'; | ||||
|  | ||||
| 		/* | ||||
| 		 * Check that the text metadata begins with a valid name. | ||||
| 		 */ | ||||
| 		if (!validate_name(namebuf)) { | ||||
| 			log_warn("WARNING: Metadata location on %s at offset %llu begins with invalid name.", | ||||
| 				 dev_name(dev), (unsigned long long)offset); | ||||
| 			bad_name = 1; | ||||
| 		} | ||||
| 		fb = buf; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| @@ -579,13 +555,10 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r | ||||
| 	if (checksum_fn && checksum != | ||||
| 	    (checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size), | ||||
| 			 (const uint8_t *)(fb + size), size2))) { | ||||
| 		log_warn("WARNING: Checksum error on %s at offset %llu.", dev_name(dev), (unsigned long long)offset); | ||||
| 		log_error("%s: Checksum error at offset %" PRIu64, dev_name(dev), (uint64_t) offset); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (bad_name) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!checksum_only) { | ||||
| 		fe = fb + size + size2; | ||||
| 		if (no_dup_node_check) { | ||||
| @@ -600,7 +573,15 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r | ||||
| 	r = 1; | ||||
|  | ||||
|       out: | ||||
| 	free(buf); | ||||
| 	if (!use_mmap) | ||||
| 		free(buf); | ||||
| 	else { | ||||
| 		/* unmap the file */ | ||||
| 		if (munmap(fb - mmap_offset, size + mmap_offset)) { | ||||
| 			log_sys_error("munmap", dev_name(dev)); | ||||
| 			r = 0; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
| @@ -735,7 +716,7 @@ static struct dm_config_value *_get_def_array_values(struct cmd_context *cmd, | ||||
| 		return array; | ||||
| 	} | ||||
|  | ||||
| 	if (!(token = enc_value = strdup(def_enc_value))) { | ||||
| 	if (!(p = token = enc_value = strdup(def_enc_value))) { | ||||
| 		log_error("_get_def_array_values: strdup failed"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| @@ -934,7 +915,7 @@ static int _check_value_differs_from_default(struct cft_check_handle *handle, | ||||
| 				} else { | ||||
| 					str = v_def ? v_def->v.str | ||||
| 						    : cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_STRING, NULL); | ||||
| 					diff = str ? strcmp(str, v->v.str) : 0; | ||||
| 					diff = strcmp(str, v->v.str); | ||||
| 				} | ||||
| 				break; | ||||
| 			case DM_CFG_EMPTY_ARRAY: | ||||
| @@ -1166,10 +1147,8 @@ int config_def_check(struct cft_check_handle *handle) | ||||
| 	 * sections and settings with full path as a key. | ||||
| 	 * If section name is variable, use '#' as a substitute. | ||||
| 	 */ | ||||
| 	*vp = 0; | ||||
| 	*rp = 0; | ||||
| 	if (!handle->cmd->cft_def_hash) { | ||||
| 		if (!(handle->cmd->cft_def_hash = dm_hash_create(500))) { | ||||
| 		if (!(handle->cmd->cft_def_hash = dm_hash_create(64))) { | ||||
| 			log_error("Failed to create configuration definition hash."); | ||||
| 			r = 0; goto out; | ||||
| 		} | ||||
| @@ -1735,7 +1714,6 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi | ||||
| 	const char *node_type_name = cn->v ? "option" : "section"; | ||||
| 	char path[CFG_PATH_MAX_LEN]; | ||||
| 	char commentline[MAX_COMMENT_LINE+1]; | ||||
| 	int is_deprecated = 0; | ||||
|  | ||||
| 	if (cn->id <= 0) | ||||
| 		return 1; | ||||
| @@ -1749,14 +1727,13 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi | ||||
|  | ||||
| 	cfg_def = cfg_def_get_item_p(cn->id); | ||||
|  | ||||
| 	is_deprecated = _def_node_is_deprecated(cfg_def, out->tree_spec); | ||||
|  | ||||
| 	if (out->tree_spec->withsummary || out->tree_spec->withcomments) { | ||||
| 		_cfg_def_make_path(path, sizeof(path), cfg_def->id, cfg_def, 1); | ||||
| 		fprintf(out->fp, "\n"); | ||||
| 		fprintf(out->fp, "%s# Configuration %s %s.\n", line, node_type_name, path); | ||||
|  | ||||
| 		if (out->tree_spec->withcomments && is_deprecated && cfg_def->deprecation_comment) | ||||
| 		if (out->tree_spec->withcomments && | ||||
| 		    _def_node_is_deprecated(cfg_def, out->tree_spec)) | ||||
| 			fprintf(out->fp, "%s# %s", line, cfg_def->deprecation_comment); | ||||
|  | ||||
| 		if (cfg_def->comment) { | ||||
| @@ -1767,14 +1744,14 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi | ||||
| 						continue; | ||||
| 					commentline[0] = '\0'; | ||||
| 				} | ||||
| 				fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline); | ||||
| 				fprintf(out->fp, "%s# %s\n", line, commentline); | ||||
| 				/* withsummary prints only the first comment line. */ | ||||
| 				if (!out->tree_spec->withcomments) | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (is_deprecated) | ||||
| 		if (_def_node_is_deprecated(cfg_def, out->tree_spec)) | ||||
| 			fprintf(out->fp, "%s# This configuration %s is deprecated.\n", line, node_type_name); | ||||
|  | ||||
| 		if (cfg_def->flags & CFG_ADVANCED) | ||||
| @@ -1802,7 +1779,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi | ||||
| 			return_0; | ||||
| 		fprintf(out->fp, "%s# Available since version %s.\n", line, version); | ||||
|  | ||||
| 		if (is_deprecated) { | ||||
| 		if (_def_node_is_deprecated(cfg_def, out->tree_spec)) { | ||||
| 			if (!_get_config_node_version(cfg_def->deprecated_since_version, version)) | ||||
| 				return_0; | ||||
| 			fprintf(out->fp, "%s# Deprecated since version %s.\n", line, version); | ||||
|   | ||||
| @@ -205,7 +205,7 @@ cfg_section(local_CFG_SECTION, "local", root_CFG_SECTION, 0, vsn(2, 2, 117), 0, | ||||
| 	"# 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, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 2, 99), NULL, 0, NULL, | ||||
| 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" | ||||
| 	"LVM and that the value of the key is the proper type. If disabled,\n" | ||||
| @@ -213,22 +213,22 @@ cfg(config_checks_CFG, "checks", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_ | ||||
| 	"without any warning (a message about the configuration key not being\n" | ||||
| 	"found is issued in verbose mode only).\n") | ||||
|  | ||||
| cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2,2,99), NULL, 0, NULL, | ||||
| cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2,2,99), NULL, 0, NULL, | ||||
| 	"Abort the LVM process if a configuration mismatch is found.\n") | ||||
|  | ||||
| cfg_runtime(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, vsn(2, 2, 99), 0, NULL, | ||||
| cfg_runtime(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, vsn(2, 2, 99), 0, NULL, | ||||
| 	"Directory where LVM looks for configuration profiles.\n") | ||||
|  | ||||
| cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Directory in which to create volume group device nodes.\n" | ||||
| 	"Commands also accept this as a prefix on volume group names.\n") | ||||
|  | ||||
| cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Directories containing device nodes to use with LVM.\n") | ||||
|  | ||||
| cfg_array(devices_loopfiles_CFG, "loopfiles", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 2, 0), NULL, vsn(2, 3, 0), NULL, NULL) | ||||
|  | ||||
| cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| 	"Obtain the list of available devices from udev.\n" | ||||
| 	"This avoids opening or using any inapplicable non-block devices or\n" | ||||
| 	"subdirectories found in the udev directory. Any device node or\n" | ||||
| @@ -237,11 +237,23 @@ cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", de | ||||
| 	"directories will be scanned fully. LVM needs to be compiled with\n" | ||||
| 	"udev support for this setting to apply.\n") | ||||
|  | ||||
| cfg(devices_external_device_info_source_CFG, "external_device_info_source", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE, vsn(2, 2, 116), NULL, 0, NULL, | ||||
| 	"Enable device information from udev.\n" | ||||
| 	"If set to \"udev\", lvm will supplement its own native device information\n" | ||||
| 	"with information from libudev. This can potentially improve the detection\n" | ||||
| 	"of MD component devices and multipath component devices.\n") | ||||
| cfg(devices_external_device_info_source_CFG, "external_device_info_source", devices_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE, vsn(2, 2, 116), NULL, 0, NULL, | ||||
| 	"Select an external device information source.\n" | ||||
| 	"Some information may already be available in the system and LVM can\n" | ||||
| 	"use this information to determine the exact type or use of devices it\n" | ||||
| 	"processes. Using an existing external device information source can\n" | ||||
| 	"speed up device processing as LVM does not need to run its own native\n" | ||||
| 	"routines to acquire this information. For example, this information\n" | ||||
| 	"is used to drive LVM filtering like MD component detection, multipath\n" | ||||
| 	"component detection, partition detection and others.\n" | ||||
| 	"#\n" | ||||
| 	"Accepted values:\n" | ||||
| 	"  none\n" | ||||
| 	"    No external device information source is used.\n" | ||||
| 	"  udev\n" | ||||
| 	"    Reuse existing udev database records. Applicable only if LVM is\n" | ||||
| 	"    compiled with udev support.\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_HINTS, vsn(2, 3, 2), NULL, 0, NULL, | ||||
| 	"Use a local file to remember which devices have PVs on them.\n" | ||||
| @@ -276,32 +288,6 @@ cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, C | ||||
| 	"preferred_names = [ \"^/dev/mpath/\", \"^/dev/mapper/mpath\", \"^/dev/[hs]d\" ]\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(devices_use_devicesfile_CFG, "use_devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_DEVICES_FILE, vsn(2, 3, 12), NULL, 0, NULL, | ||||
| 	"Enable or disable the use of a devices file.\n" | ||||
| 	"When enabled, lvm will only use devices that\n" | ||||
| 	"are lised in the devices file. A devices file will\n" | ||||
| 	"be used, regardless of this setting, when the --devicesfile\n" | ||||
| 	"option is set to a specific file name.\n") | ||||
|  | ||||
| cfg(devices_devicesfile_CFG, "devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DEVICES_FILE, vsn(2, 3, 12), NULL, 0, NULL, | ||||
| 	"The name of the system devices file, listing devices that LVM should use.\n" | ||||
| 	"This should not be used to select a non-system devices file.\n" | ||||
| 	"The --devicesfile option is intended for alternative devices files.\n") | ||||
|  | ||||
| cfg(devices_search_for_devnames_CFG, "search_for_devnames", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SEARCH_FOR_DEVNAMES, vsn(2, 3, 12), NULL, 0, NULL, | ||||
| 	"Look outside of the devices file for missing devname entries.\n" | ||||
| 	"A devname entry is used for a device that does not have a stable\n" | ||||
| 	"device id, e.g. wwid, so the unstable device name is used as\n" | ||||
| 	"the device id. After reboot, or if the device is reattached,\n" | ||||
| 	"the device name may change, in which case lvm will not find\n" | ||||
| 	"the expected PV on the device listed in the devices file.\n" | ||||
| 	"This setting controls whether lvm will search other devices,\n" | ||||
| 	"outside the devices file, to look for the missing PV on a\n" | ||||
| 	"renamed device. If \"none\", lvm will not look at other devices,\n" | ||||
| 	"and the PV may appear to be missing. If \"auto\", lvm will look\n" | ||||
| 	"at other devices, but only those that are likely to have the PV.\n" | ||||
| 	"If \"all\", lvm will look at all devices on the system.\n") | ||||
|  | ||||
| cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*|", vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Limit the block devices that are used by LVM commands.\n" | ||||
| 	"This is a list of regular expressions used to accept or reject block\n" | ||||
| @@ -340,16 +326,16 @@ cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_D | ||||
| 	"global_filter are not opened by LVM.\n") | ||||
|  | ||||
| cfg_runtime(devices_cache_CFG, "cache", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), vsn(1, 2, 19), NULL, | ||||
| 	NULL) | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg_runtime(devices_cache_dir_CFG, "cache_dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 2, 19), vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(devices_cache_file_prefix_CFG, "cache_file_prefix", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_CACHE_FILE_PREFIX, vsn(1, 2, 19), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(devices_write_cache_state_CFG, "write_cache_state", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_ADVANCED, CFG_TYPE_INT | CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"List of additional acceptable block device types.\n" | ||||
| @@ -360,12 +346,12 @@ cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | ||||
| 	"types = [ \"fd\", 16 ]\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SYSFS_SCAN, vsn(1, 0, 8), NULL, 0, NULL, | ||||
| cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SYSFS_SCAN, vsn(1, 0, 8), NULL, 0, NULL, | ||||
| 	"Restrict device scanning to block devices appearing in sysfs.\n" | ||||
| 	"This is a quick way of filtering out block devices that are not\n" | ||||
| 	"present on the system. sysfs must be part of the kernel and mounted.)\n") | ||||
|  | ||||
| cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SCAN_LVS, vsn(2, 2, 182), NULL, 0, NULL, | ||||
| cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SCAN_LVS, vsn(2, 2, 182), NULL, 0, NULL, | ||||
| 	"Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.\n" | ||||
| 	"When 1, LVM will detect PVs layered on LVs, and caution must be\n" | ||||
| 	"taken to avoid a host accessing a layered VG that may not belong\n" | ||||
| @@ -378,14 +364,10 @@ cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | ||||
| 	"an LV. The LVs are ignored using a built in device filter that\n" | ||||
| 	"identifies and excludes LVs.\n") | ||||
|  | ||||
| cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"Ignore devices that are components of DM multipath devices.\n") | ||||
|  | ||||
| cfg(devices_multipath_wwids_file_CFG, "multipath_wwids_file", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_WWIDS_FILE, vsn(2, 3, 13), NULL, 0, NULL, | ||||
| 	"The path to the multipath wwids file used for multipath component detection.\n" | ||||
| 	"Set this to an empty string to disable the use of the multipath wwids file.\n") | ||||
|  | ||||
| cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL, 0, NULL, | ||||
| cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL, 0, NULL, | ||||
| 	"Enable detection and exclusion of MD component devices.\n" | ||||
| 	"An MD component device is a block device that MD uses as part\n" | ||||
| 	"of a software RAID virtual device. When an LVM PV is created\n" | ||||
| @@ -411,26 +393,26 @@ cfg(devices_md_component_checks_CFG, "md_component_checks", devices_CFG_SECTION, | ||||
| 	"    This requires an extra read at the end of devices.\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FW_RAID_COMPONENT_DETECTION, vsn(2, 2, 112), NULL, 0, NULL, | ||||
| cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FW_RAID_COMPONENT_DETECTION, vsn(2, 2, 112), NULL, 0, NULL, | ||||
| 	"Ignore devices that are components of firmware RAID devices.\n" | ||||
| 	"LVM must use an external_device_info_source other than none for this\n" | ||||
| 	"detection to execute.\n") | ||||
|  | ||||
| cfg(devices_md_chunk_alignment_CFG, "md_chunk_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MD_CHUNK_ALIGNMENT, vsn(2, 2, 48), NULL, 0, NULL, | ||||
| cfg(devices_md_chunk_alignment_CFG, "md_chunk_alignment", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_CHUNK_ALIGNMENT, vsn(2, 2, 48), NULL, 0, NULL, | ||||
| 	"Align the start of a PV data area with md device's stripe-width.\n" | ||||
| 	"This applies if a PV is placed directly on an md device.\n" | ||||
| 	"default_data_alignment will be overridden if it is not aligned\n" | ||||
| 	"default_data_alignment will be overriden if it is not aligned\n" | ||||
| 	"with the value detected for this setting.\n" | ||||
| 	"This setting is overridden by data_alignment_detection,\n" | ||||
| 	"This setting is overriden by data_alignment_detection,\n" | ||||
| 	"data_alignment, and the --dataalignment option.\n") | ||||
|  | ||||
| cfg(devices_default_data_alignment_CFG, "default_data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, FIRST_PE_AT_ONE_MB_IN_MB, vsn(2, 2, 75), NULL, 0, NULL, | ||||
| 	"Align the start of a PV data area with this number of MiB.\n" | ||||
| 	"Set to 1 for 1MiB, 2 for 2MiB, etc. Set to 0 to disable.\n" | ||||
| 	"This setting is overridden by data_alignment and the --dataalignment\n" | ||||
| 	"This setting is overriden by data_alignment and the --dataalignment\n" | ||||
| 	"option.\n") | ||||
|  | ||||
| cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_DETECTION, vsn(2, 2, 51), NULL, 0, NULL, | ||||
| cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_DETECTION, vsn(2, 2, 51), NULL, 0, NULL, | ||||
| 	"Align the start of a PV data area with sysfs io properties.\n" | ||||
| 	"The start of a PV data area will be a multiple of minimum_io_size or\n" | ||||
| 	"optimal_io_size exposed in sysfs. minimum_io_size is the smallest\n" | ||||
| @@ -439,19 +421,19 @@ cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CF | ||||
| 	"preferred unit of receiving I/O, e.g. MD stripe width.\n" | ||||
| 	"minimum_io_size is used if optimal_io_size is undefined (0).\n" | ||||
| 	"If md_chunk_alignment is enabled, that detects the optimal_io_size.\n" | ||||
| 	"default_data_alignment and md_chunk_alignment will be overridden\n" | ||||
| 	"default_data_alignment and md_chunk_alignment will be overriden\n" | ||||
| 	"if they are not aligned with the value detected for this setting.\n" | ||||
| 	"This setting is overridden by data_alignment and the --dataalignment\n" | ||||
| 	"This setting is overriden by data_alignment and the --dataalignment\n" | ||||
| 	"option.\n") | ||||
|  | ||||
| cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 45), NULL, 0, NULL, | ||||
| cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 45), NULL, 0, NULL, | ||||
| 	"Align the start of a PV data area with this number of KiB.\n" | ||||
| 	"When non-zero, this setting overrides default_data_alignment.\n" | ||||
| 	"Set to 0 to disable, in which case default_data_alignment\n" | ||||
| 	"is used to align the first PE in units of MiB.\n" | ||||
| 	"This setting is overridden by the --dataalignment option.\n") | ||||
| 	"This setting is overriden by the --dataalignment option.\n") | ||||
|  | ||||
| cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION, vsn(2, 2, 50), NULL, 0, NULL, | ||||
| cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION, vsn(2, 2, 50), NULL, 0, NULL, | ||||
| 	"Shift the start of an aligned PV data area based on sysfs information.\n" | ||||
| 	"After a PV data area is aligned, it will be shifted by the\n" | ||||
| 	"alignment_offset exposed in sysfs. This offset is often 0, but may\n" | ||||
| @@ -459,14 +441,14 @@ cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detectio | ||||
| 	"partitioning will have an alignment_offset of 3584 bytes (sector 7\n" | ||||
| 	"is the lowest aligned logical block, the 4KiB sectors start at\n" | ||||
| 	"LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).\n" | ||||
| 	"This setting is overridden by the --dataalignmentoffset option.\n") | ||||
| 	"This setting is overriden by the --dataalignmentoffset option.\n") | ||||
|  | ||||
| cfg(devices_ignore_suspended_devices_CFG, "ignore_suspended_devices", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_IGNORE_SUSPENDED_DEVICES, vsn(1, 2, 19), NULL, 0, NULL, | ||||
| cfg(devices_ignore_suspended_devices_CFG, "ignore_suspended_devices", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_IGNORE_SUSPENDED_DEVICES, vsn(1, 2, 19), NULL, 0, NULL, | ||||
| 	"Ignore DM devices that have I/O suspended while scanning devices.\n" | ||||
| 	"Otherwise, LVM waits for a suspended device to become accessible.\n" | ||||
| 	"This should only be needed in recovery situations.\n") | ||||
|  | ||||
| cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_IGNORE_LVM_MIRRORS, vsn(2, 2, 104), NULL, 0, NULL, | ||||
| cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_IGNORE_LVM_MIRRORS, vsn(2, 2, 104), NULL, 0, NULL, | ||||
| 	"Do not scan 'mirror' LVs to avoid possible deadlocks.\n" | ||||
| 	"This avoids possible deadlocks when using the 'mirror' segment type.\n" | ||||
| 	"This setting determines whether LVs using the 'mirror' segment type\n" | ||||
| @@ -484,19 +466,19 @@ cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, C | ||||
| 	"apply to LVM RAID types like 'raid1' which handle failures in a\n" | ||||
| 	"different way, making them a better choice for VG stacking.\n") | ||||
|  | ||||
| cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(2, 3, 0), NULL, | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID, vsn(2, 2, 73), NULL, 0, NULL, | ||||
| cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID, vsn(2, 2, 73), NULL, 0, NULL, | ||||
| 	"Allow use of pvcreate --uuid without requiring --restorefile.\n") | ||||
|  | ||||
| cfg(devices_pv_min_size_CFG, "pv_min_size", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PV_MIN_SIZE_KB, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| cfg(devices_pv_min_size_CFG, "pv_min_size", devices_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_PV_MIN_SIZE_KB, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| 	"Minimum size in KiB of block devices which can be used as PVs.\n" | ||||
| 	"In a clustered environment all nodes must use the same value.\n" | ||||
| 	"Any value smaller than 512KiB is ignored. The previous built-in\n" | ||||
| 	"value was 512.\n") | ||||
|  | ||||
| cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ISSUE_DISCARDS, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ISSUE_DISCARDS, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| 	"Issue discards to PVs that are no longer used by an LV.\n" | ||||
| 	"Discards are sent to an LV's underlying physical volumes when the LV\n" | ||||
| 	"is no longer using the physical volumes' space, e.g. lvremove,\n" | ||||
| @@ -508,7 +490,7 @@ cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, CFG_DEFAU | ||||
| 	"generally do. If enabled, discards will only be issued if both the\n" | ||||
| 	"storage and kernel provide support.\n") | ||||
|  | ||||
| cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_pvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS, vsn(2, 2, 153), NULL, 0, NULL, | ||||
| cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_pvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS, vsn(2, 2, 153), NULL, 0, NULL, | ||||
| 	"Allow VG modification while a PV appears on multiple devices.\n" | ||||
| 	"When a PV appears on multiple devices, LVM attempts to choose the\n" | ||||
| 	"best device to use for the PV. If the devices represent the same\n" | ||||
| @@ -520,7 +502,7 @@ 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_allow_mixed_block_sizes_CFG, "allow_mixed_block_sizes", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 3, 6), NULL, 0, NULL, | ||||
| cfg(devices_allow_mixed_block_sizes_CFG, "allow_mixed_block_sizes", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 6), NULL, 0, NULL, | ||||
| 	"Allow PVs in the same VG with different logical block sizes.\n" | ||||
| 	"When allowed, the user is responsible to ensure that an LV is\n" | ||||
| 	"using PVs with matching block sizes when necessary.\n") | ||||
| @@ -543,14 +525,14 @@ cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTIO | ||||
| 	"cling_tag_list = [ \"@site1\", \"@site2\" ]\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(allocation_maximise_cling_CFG, "maximise_cling", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MAXIMISE_CLING, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| cfg(allocation_maximise_cling_CFG, "maximise_cling", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MAXIMISE_CLING, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| 	"Use a previous allocation algorithm.\n" | ||||
| 	"Changes made in version 2.02.85 extended the reach of the 'cling'\n" | ||||
| 	"policies to detect more situations where data can be grouped onto\n" | ||||
| 	"the same disks. This setting can be used to disable the changes\n" | ||||
| 	"and revert to the previous algorithm.\n") | ||||
|  | ||||
| cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_BLKID_WIPING, vsn(2, 2, 105), "@DEFAULT_USE_BLKID_WIPING@", 0, NULL, | ||||
| cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_BLKID_WIPING, vsn(2, 2, 105), "@DEFAULT_USE_BLKID_WIPING@", 0, NULL, | ||||
| 	"Use blkid to detect and erase existing signatures on new PVs and LVs.\n" | ||||
| 	"The blkid library can detect more signatures than the native LVM\n" | ||||
| 	"detection code, but may take longer. LVM needs to be compiled with\n" | ||||
| @@ -559,7 +541,7 @@ cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION, | ||||
| 	"swap signature, and LUKS signatures. To see the list of signatures\n" | ||||
| 	"recognized by blkid, check the output of the 'blkid -k' command.\n") | ||||
|  | ||||
| cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_zeroing_new_lvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 2, 105), NULL, 0, NULL, | ||||
| cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_zeroing_new_lvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 105), NULL, 0, NULL, | ||||
| 	"Look for and erase any signatures while zeroing a new LV.\n" | ||||
| 	"The --wipesignatures option overrides this setting.\n" | ||||
| 	"Zeroing is controlled by the -Z/--zero option, and if not specified,\n" | ||||
| @@ -575,7 +557,7 @@ cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_z | ||||
| 	"When this setting is disabled, signatures on new LVs are not detected\n" | ||||
| 	"or erased unless the --wipesignatures option is used directly.\n") | ||||
|  | ||||
| cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MIRROR_LOGS_REQUIRE_SEPARATE_PVS, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MIRROR_LOGS_REQUIRE_SEPARATE_PVS, vsn(2, 2, 85), NULL, 0, NULL, | ||||
| 	"Mirror logs and images will always use different PVs.\n" | ||||
| 	"The default setting changed in version 2.02.85.\n") | ||||
|  | ||||
| @@ -586,7 +568,7 @@ cfg(allocation_raid_stripe_all_devices_CFG, "raid_stripe_all_devices", allocatio | ||||
| 	"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_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL, | ||||
| 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, | ||||
| 	"Cache pool metadata and data will always use different PVs.\n") | ||||
|  | ||||
| cfg(allocation_cache_pool_cachemode_CFG, "cache_pool_cachemode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 113), NULL, vsn(2, 2, 128), | ||||
| @@ -643,13 +625,8 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF | ||||
| 	"For cache target v1.9 the recommended maximumm is 1000000 chunks.\n" | ||||
| 	"Using cache pool with more chunks may degrade cache performance.\n") | ||||
|  | ||||
| cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"Thin pool metadata and data will always use different PVs.\n") | ||||
|  | ||||
| cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL, | ||||
| 	"Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n" | ||||
| 	"This is slightly less then the actual maximum 15.88 GiB.\n" | ||||
| 	"For compatibility with older version and use of cropped size set to 1.\n") | ||||
| cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"Thin pool metdata and data will always use different PVs.\n") | ||||
|  | ||||
| cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL, | ||||
| 	"Thin pool data chunks are zeroed before they are first used.\n" | ||||
| @@ -680,9 +657,6 @@ cfg(allocation_thin_pool_chunk_size_policy_CFG, "thin_pool_chunk_size_policy", a | ||||
| 	"    512KiB.\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(allocation_zero_metadata_CFG, "zero_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ZERO_METADATA, vsn(2, 3, 10), NULL, 0, NULL, | ||||
| 	"Zero whole metadata area before use with thin or cache pool.\n") | ||||
|  | ||||
| cfg_runtime(allocation_thin_pool_chunk_size_CFG, "thin_pool_chunk_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(2, 2, 99), 0, NULL, | ||||
| 	"The minimal chunk size in KiB for thin pool volumes.\n" | ||||
| 	"Larger chunk sizes may improve performance for plain thin volumes,\n" | ||||
| @@ -796,12 +770,10 @@ cfg(allocation_vdo_write_policy_CFG, "vdo_write_policy", allocation_CFG_SECTION, | ||||
| 	"sync  - Writes are acknowledged only after data is stably written.\n" | ||||
| 	"        This policy is not supported if the underlying storage is not also synchronous.\n" | ||||
| 	"async - Writes are acknowledged after data has been cached for writing to stable storage.\n" | ||||
| 	"        Data which has not been flushed is not guaranteed to persist in this mode.\n" | ||||
| 	"async-unsafe - Writes are handled like 'async' but there is no guarantee of the atomicity async provides.\n" | ||||
| 	"        This mode should only be used for better performance when atomicity is not required.\n") | ||||
| 	"        Data which has not been flushed is not guaranteed to persist in this mode.\n") | ||||
|  | ||||
| cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_MAX_DISCARD, VDO_1ST_VSN, NULL, 0, NULL, | ||||
| 	"Specified the maximum size of discard bio accepted, in 4096 byte blocks.\n" | ||||
| 	"Specified te maximum size of discard bio accepted, in 4096 byte blocks.\n" | ||||
| 	"I/O requests to a VDO volume are normally split into 4096-byte blocks,\n" | ||||
| 	"and processed up to 2048 at a time. However, discard requests to a VDO volume\n" | ||||
| 	"can be automatically split to a larger size, up to <max discard> 4096-byte blocks\n" | ||||
| @@ -810,9 +782,6 @@ cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, C | ||||
| 	"increased latency for the individual discard requests.\n" | ||||
| 	"The default and minimum is 1. The maximum is UINT_MAX / 4096.\n") | ||||
|  | ||||
| cfg(allocation_vdo_pool_header_size_CFG, "vdo_pool_header_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_HEADER_SIZE_KB, vsn(2, 3, 12), NULL, 0, NULL, | ||||
| 	"Specified the emptry header size in KiB at the front and end of vdo pool device.\n") | ||||
|  | ||||
| cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL, | ||||
| 	"Enable or disable LVM log reporting.\n" | ||||
| 	"If enabled, LVM will collect a log of operations, messages,\n" | ||||
| @@ -854,10 +823,10 @@ cfg(log_command_log_selection_CFG, "command_log_selection", log_CFG_SECTION, CFG | ||||
| 	"For more information about selection criteria in general, see\n" | ||||
| 	"lvm(8) man page.\n") | ||||
|  | ||||
| cfg(log_verbose_CFG, "verbose", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VERBOSE, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(log_verbose_CFG, "verbose", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_VERBOSE, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Controls the messages sent to stdout or stderr.\n") | ||||
|  | ||||
| cfg(log_silent_CFG, "silent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SILENT, vsn(2, 2, 98), NULL, 0, NULL, | ||||
| cfg(log_silent_CFG, "silent", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SILENT, vsn(2, 2, 98), NULL, 0, NULL, | ||||
| 	"Suppress all non-essential messages from stdout.\n" | ||||
| 	"This has the same effect as -qq. When enabled, the following commands\n" | ||||
| 	"still produce output: dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck,\n" | ||||
| @@ -867,22 +836,16 @@ cfg(log_silent_CFG, "silent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_B | ||||
| 	"Any 'yes' or 'no' questions not overridden by other arguments are\n" | ||||
| 	"suppressed and default to 'no'.\n") | ||||
|  | ||||
| cfg(log_syslog_CFG, "syslog", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SYSLOG, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(log_syslog_CFG, "syslog", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SYSLOG, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Send log messages through syslog.\n") | ||||
|  | ||||
| cfg(log_file_CFG, "file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Write error and debug log messages to a file specified here.\n") | ||||
|  | ||||
| cfg_array(log_journal_CFG, "journal", log_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, NULL, vsn(2, 3, 12), NULL, 0, NULL, | ||||
| 	  "Record lvm information in the systemd journal.\n" | ||||
| 	  "command: record commands that are run.\n" | ||||
| 	  "output: record default output from commands.\n" | ||||
| 	  "debug: record debug messages from commands.\n") | ||||
|  | ||||
| cfg(log_overwrite_CFG, "overwrite", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_OVERWRITE, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(log_overwrite_CFG, "overwrite", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_OVERWRITE, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Overwrite the log file each time the program is run.\n") | ||||
|  | ||||
| cfg(log_level_CFG, "level", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LOGLEVEL, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(log_level_CFG, "level", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_LOGLEVEL, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"The level of log messages that are sent to the log file or syslog.\n" | ||||
| 	"There are 6 syslog-like log levels currently in use: 2 to 7 inclusive.\n" | ||||
| 	"7 is the most verbose (LOG_DEBUG).\n") | ||||
| @@ -890,23 +853,23 @@ cfg(log_level_CFG, "level", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT | ||||
| cfg(log_indent_CFG, "indent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_INDENT, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Indent messages according to their severity.\n") | ||||
|  | ||||
| cfg(log_command_names_CFG, "command_names", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_CMD_NAME, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(log_command_names_CFG, "command_names", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_CMD_NAME, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Display the command name on each line of output.\n") | ||||
|  | ||||
| cfg(log_prefix_CFG, "prefix", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_MSG_PREFIX, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(log_prefix_CFG, "prefix", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_MSG_PREFIX, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"A prefix to use before the log message text.\n" | ||||
| 	"(After the command name, if selected).\n" | ||||
| 	"Two spaces allows you to see/grep the severity of each message.\n" | ||||
| 	"To make the messages look similar to the original LVM tools use:\n" | ||||
| 	"indent = 0, command_names = 1, prefix = \" -- \"\n") | ||||
|  | ||||
| cfg(log_activation_CFG, "activation", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(log_activation_CFG, "activation", log_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Log messages during activation.\n" | ||||
| 	"Don't use this in low memory situations (can deadlock).\n") | ||||
|  | ||||
| cfg(log_activate_file_CFG, "activate_file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL) | ||||
|  | ||||
| cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sio#Sactivation#Sallocation#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL, | ||||
| cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sio#Sactivation#Sallocation#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL, | ||||
| 	"Select log messages by class.\n" | ||||
| 	"Some debugging messages are assigned to a class and only appear in\n" | ||||
| 	"debug output if the class is listed here. Classes currently\n" | ||||
| @@ -921,55 +884,55 @@ cfg_array(log_debug_output_fields_CFG, "debug_output_fields", log_CFG_SECTION, C | ||||
| 	  "The fields included in debug output written to stderr.\n" | ||||
| 	  "Use \"all\" to include everything (the default).\n") | ||||
|  | ||||
| cfg(backup_backup_CFG, "backup", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_BACKUP_ENABLED, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(backup_backup_CFG, "backup", backup_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_BACKUP_ENABLED, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Maintain a backup of the current metadata configuration.\n" | ||||
| 	"Think very hard before turning this off!\n") | ||||
|  | ||||
| cfg_runtime(backup_backup_dir_CFG, "backup_dir", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL, | ||||
| cfg_runtime(backup_backup_dir_CFG, "backup_dir", backup_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL, | ||||
| 	"Location of the metadata backup files.\n" | ||||
| 	"Remember to back up this directory regularly!\n") | ||||
|  | ||||
| cfg(backup_archive_CFG, "archive", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ARCHIVE_ENABLED, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(backup_archive_CFG, "archive", backup_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ARCHIVE_ENABLED, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Maintain an archive of old metadata configurations.\n" | ||||
| 	"Think very hard before turning this off.\n") | ||||
|  | ||||
| cfg_runtime(backup_archive_dir_CFG, "archive_dir", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL, | ||||
| cfg_runtime(backup_archive_dir_CFG, "archive_dir", backup_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL, | ||||
| 	"Location of the metdata archive files.\n" | ||||
| 	"Remember to back up this directory regularly!\n") | ||||
|  | ||||
| cfg(backup_retain_min_CFG, "retain_min", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_ARCHIVE_NUMBER, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(backup_retain_min_CFG, "retain_min", backup_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_ARCHIVE_NUMBER, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Minimum number of archives to keep.\n") | ||||
|  | ||||
| cfg(backup_retain_days_CFG, "retain_days", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_ARCHIVE_DAYS, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(backup_retain_days_CFG, "retain_days", backup_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_ARCHIVE_DAYS, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Minimum number of days to keep archive files.\n") | ||||
|  | ||||
| cfg(shell_history_size_CFG, "history_size", shell_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_MAX_HISTORY, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(shell_history_size_CFG, "history_size", shell_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_MAX_HISTORY, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Number of lines of history to store in ~/.lvm_history.\n") | ||||
|  | ||||
| cfg(global_umask_CFG, "umask", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_FORMAT_INT_OCTAL, CFG_TYPE_INT, DEFAULT_UMASK, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(global_umask_CFG, "umask", global_CFG_SECTION, CFG_FORMAT_INT_OCTAL, CFG_TYPE_INT, DEFAULT_UMASK, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"The file creation mask for any files and directories created.\n" | ||||
| 	"Interpreted as octal if the first digit is zero.\n") | ||||
|  | ||||
| cfg(global_test_CFG, "test", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(global_test_CFG, "test", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"No on-disk metadata changes will be made in test mode.\n" | ||||
| 	"Equivalent to having the -t option on every command.\n") | ||||
|  | ||||
| cfg(global_units_CFG, "units", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_STRING, DEFAULT_UNITS, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(global_units_CFG, "units", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_STRING, DEFAULT_UNITS, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Default value for --units argument.\n") | ||||
|  | ||||
| cfg(global_si_unit_consistency_CFG, "si_unit_consistency", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SI_UNIT_CONSISTENCY,  vsn(2, 2, 54), NULL, 0, NULL, | ||||
| cfg(global_si_unit_consistency_CFG, "si_unit_consistency", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SI_UNIT_CONSISTENCY,  vsn(2, 2, 54), NULL, 0, NULL, | ||||
| 	"Distinguish between powers of 1024 and 1000 bytes.\n" | ||||
| 	"The LVM commands distinguish between powers of 1024 bytes,\n" | ||||
| 	"e.g. KiB, MiB, GiB, and powers of 1000 bytes, e.g. KB, MB, GB.\n" | ||||
| 	"If scripts depend on the old behaviour, disable this setting\n" | ||||
| 	"temporarily until they are updated.\n") | ||||
|  | ||||
| cfg(global_suffix_CFG, "suffix", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SUFFIX, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(global_suffix_CFG, "suffix", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SUFFIX, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Display unit suffix for sizes.\n" | ||||
| 	"This setting has no effect if the units are in human-readable form\n" | ||||
| 	"(global/units = \"h\") in which case the suffix is always displayed.\n") | ||||
|  | ||||
| cfg(global_activation_CFG, "activation", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ACTIVATION, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(global_activation_CFG, "activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ACTIVATION, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Enable/disable communication with the kernel device-mapper.\n" | ||||
| 	"Disable to use the tools to manipulate LVM metadata without\n" | ||||
| 	"activating any logical volumes. If the device-mapper driver\n" | ||||
| @@ -977,69 +940,70 @@ cfg(global_activation_CFG, "activation", global_CFG_SECTION, CFG_DEFAULT_COMMENT | ||||
| 	"the error messages.\n") | ||||
|  | ||||
| cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 18), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(global_format_CFG, "format", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, | ||||
| 	  NULL) | ||||
| 	"This setting is no longer used.") | ||||
|  | ||||
| cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL, vsn(2, 3, 3), NULL, NULL) | ||||
|  | ||||
| cfg(global_proc_CFG, "proc", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_PROC_DIR, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(global_proc_CFG, "proc", global_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_PROC_DIR, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Location of proc filesystem.\n") | ||||
|  | ||||
| cfg(global_etc_CFG, "etc", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_ETC_DIR, vsn(2, 2, 117), "@CONFDIR@", 0, NULL, | ||||
| cfg(global_etc_CFG, "etc", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ETC_DIR, vsn(2, 2, 117), "@CONFDIR@", 0, NULL, | ||||
| 	"Location of /etc system configuration directory.\n") | ||||
|  | ||||
| cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, | ||||
|     NULL) | ||||
| cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, 0, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, | ||||
| 	"This setting is no longer used.") | ||||
|  | ||||
| cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL, 0, NULL, | ||||
| cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL, 0, NULL, | ||||
| 	"When disabled, fail if a lock request would block.\n") | ||||
|  | ||||
| cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL, | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL, | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(global_locking_dir_CFG, "locking_dir", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCK_DIR, vsn(1, 0, 0), "@DEFAULT_LOCK_DIR@", 0, NULL, | ||||
| cfg(global_locking_dir_CFG, "locking_dir", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_LOCK_DIR, vsn(1, 0, 0), "@DEFAULT_LOCK_DIR@", 0, NULL, | ||||
| 	"Directory to use for LVM command file locks.\n" | ||||
| 	"Local non-LV directory that holds file-based locks while commands are\n" | ||||
| 	"in progress. A directory like /tmp that may get wiped on reboot is OK.\n") | ||||
|  | ||||
| cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_PRIORITISE_WRITE_LOCKS, vsn(2, 2, 52), NULL, 0, NULL, | ||||
| cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_PRIORITISE_WRITE_LOCKS, vsn(2, 2, 52), NULL, 0, NULL, | ||||
| 	"Allow quicker VG write access during high volume read access.\n" | ||||
| 	"When there are competing read-only and read-write access requests for\n" | ||||
| 	"a volume group's metadata, instead of always granting the read-only\n" | ||||
| 	"requests immediately, delay them to allow the read-write requests to\n" | ||||
| 	"be serviced. Without this setting, write access may be stalled by a\n" | ||||
| 	"high volume of read-only requests. This option only affects file locks.\n") | ||||
| 	"high volume of read-only requests. This option only affects\n" | ||||
| 	"locking_type 1 viz. local file-based locking.\n") | ||||
|  | ||||
| cfg(global_library_dir_CFG, "library_dir", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Search this directory first for shared libraries.\n") | ||||
|  | ||||
| cfg(global_locking_library_CFG, "locking_library", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCKING_LIB, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ABORT_ON_INTERNAL_ERRORS, vsn(2, 2, 57), NULL, 0, NULL, | ||||
| cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ABORT_ON_INTERNAL_ERRORS, vsn(2, 2, 57), NULL, 0, NULL, | ||||
| 	"Abort a command that encounters an internal error.\n" | ||||
| 	"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, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 96), NULL, vsn(2, 2, 174), NULL, | ||||
| 	NULL) | ||||
| 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_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_METADATA_READ_ONLY, vsn(2, 2, 75), NULL, 0, NULL, | ||||
| 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" | ||||
| 	"Additionally, read-only commands that encounter metadata in need of\n" | ||||
| 	"repair will still be allowed to proceed exactly as if the repair had\n" | ||||
| 	"been performed (except for the unchanged vg_seqno). Inappropriate\n" | ||||
| 	"use could mess up your system, so seek advice first!\n") | ||||
|  | ||||
| cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_SEGTYPE, vsn(2, 2, 87), "@DEFAULT_MIRROR_SEGTYPE@", 0, NULL, | ||||
| cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_SEGTYPE, vsn(2, 2, 87), "@DEFAULT_MIRROR_SEGTYPE@", 0, NULL, | ||||
| 	"The segment type used by the short mirroring option -m.\n" | ||||
| 	"The --type mirror|raid1 option overrides this setting.\n" | ||||
| 	"#\n" | ||||
| @@ -1064,7 +1028,7 @@ cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECT | ||||
| 	"    fashion in a cluster.\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 3, 2), NULL, 0, NULL, | ||||
| cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 2), NULL, 0, NULL, | ||||
| 	"Enable mirrored 'mirror' log type for testing.\n" | ||||
| 	"#\n" | ||||
| 	"This type is deprecated to create or convert to but can\n" | ||||
| @@ -1074,7 +1038,7 @@ cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", globa | ||||
| 	"Not supported for regular operation!\n" | ||||
| 	"\n") | ||||
|  | ||||
| cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_RAID10_SEGTYPE, vsn(2, 2, 99), "@DEFAULT_RAID10_SEGTYPE@", 0, NULL, | ||||
| cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_RAID10_SEGTYPE, vsn(2, 2, 99), "@DEFAULT_RAID10_SEGTYPE@", 0, NULL, | ||||
| 	"The segment type used by the -i -m combination.\n" | ||||
| 	"The --type raid10|mirror option overrides this setting.\n" | ||||
| 	"The --stripes/-i and --mirrors/-m options can both be specified\n" | ||||
| @@ -1092,7 +1056,7 @@ cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECT | ||||
| 	"    in terms of providing redundancy and performance.\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(global_sparse_segtype_default_CFG, "sparse_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SPARSE_SEGTYPE, vsn(2, 2, 112), "@DEFAULT_SPARSE_SEGTYPE@", 0, NULL, | ||||
| cfg(global_sparse_segtype_default_CFG, "sparse_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_SPARSE_SEGTYPE, vsn(2, 2, 112), "@DEFAULT_SPARSE_SEGTYPE@", 0, NULL, | ||||
| 	"The segment type used by the -V -L combination.\n" | ||||
| 	"The --type snapshot|thin option overrides this setting.\n" | ||||
| 	"The combination of -V and -L options creates a sparse LV. There are\n" | ||||
| @@ -1118,23 +1082,25 @@ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_pa | ||||
| 	"Previously this was always shown as /dev/vgname/lvname even when that\n" | ||||
| 	"was never a valid path in the /dev filesystem.\n") | ||||
|  | ||||
| cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL, | ||||
| 	"Disable event based autoactivation commands.\n" | ||||
| 	"WARNING: setting this to zero may cause machine startup to fail.\n" | ||||
| 	"Previously, setting this to zero would enable static autoactivation\n" | ||||
| 	"services (via the lvm2-activation-generator), but the autoactivation\n" | ||||
| 	"services and generator have been removed.\n") | ||||
| cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL, | ||||
| 	"Activate LVs based on system-generated device events.\n" | ||||
| 	"When a device appears on the system, a system-generated event runs\n" | ||||
| 	"the pvscan command to activate LVs if the new PV completes the VG.\n" | ||||
| 	"Use auto_activation_volume_list to select which LVs should be\n" | ||||
| 	"activated from these events (the default is all.)\n" | ||||
| 	"When event_activation is disabled, the system will generally run\n" | ||||
| 	"a direct activation command to activate LVs in complete VGs.\n") | ||||
|  | ||||
| cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL, | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 151), NULL, vsn(2, 3, 0), NULL, | ||||
| 	NULL) | ||||
| 	"This setting is no longer used.\n") | ||||
|  | ||||
| cfg(global_use_aio_CFG, "use_aio", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_AIO, vsn(2, 2, 183), NULL, 0, NULL, | ||||
| 	"Use async I/O when reading and writing devices.\n") | ||||
|  | ||||
| cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL, | ||||
| cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL, | ||||
| 	"Use lvmlockd for locking among hosts using LVM on shared storage.\n" | ||||
| 	"Applicable only if LVM is compiled with lockd support in which\n" | ||||
| 	"case there is also lvmlockd(8) man page available for more\n" | ||||
| @@ -1153,15 +1119,6 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D | ||||
| 	"and can cause lvcreate to fail. Applicable only if LVM is compiled\n" | ||||
| 	"with lockd support\n") | ||||
|  | ||||
| cfg(global_lvmlockctl_kill_command_CFG, "lvmlockctl_kill_command", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "", vsn(2, 3, 12), NULL, 0, NULL, | ||||
| 	"The command that lvmlockctl --kill should use to force LVs offline.\n" | ||||
| 	"The lvmlockctl --kill command is run when a shared VG has lost\n" | ||||
| 	"access to locks (e.g. when sanlock has lost access to storage.)\n" | ||||
| 	"An empty string means that there will be no automatic attempt by\n" | ||||
| 	"lvmlockctl --kill to forcibly shut down LVs in the VG, and the user\n" | ||||
| 	"can manually intervene as described in lvmlockd(8).\n" | ||||
| 	"The VG name will be appended to the command specified here.\n") | ||||
|  | ||||
| cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL, | ||||
| 	"The full path to the thin_check command.\n" | ||||
| 	"LVM uses this command to check that a thin metadata device is in a\n" | ||||
| @@ -1247,20 +1204,11 @@ cfg(global_vdo_format_executable_CFG, "vdo_format_executable", global_CFG_SECTIO | ||||
| cfg_array(global_vdo_format_options_CFG, "vdo_format_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_FORMAT_OPTIONS_CONFIG, VDO_1ST_VSN, NULL, 0, NULL, | ||||
| 	"List of options passed added to standard vdoformat command.\n") | ||||
|  | ||||
| cfg_array(global_vdo_disabled_features_CFG, "vdo_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 3, 11), NULL, 0, NULL, | ||||
| 	"Features to not use in the vdo driver.\n" | ||||
| 	"This can be helpful for testing, or to avoid using a feature that is\n" | ||||
| 	"causing problems. Features include: online_rename\n" | ||||
| 	"#\n" | ||||
| 	"Example\n" | ||||
| 	"vdo_disabled_features = [ \"online_rename\" ]\n" | ||||
| 	"#\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, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SYSTEM_ID_SOURCE, vsn(2, 2, 117), NULL, 0, NULL, | ||||
| 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" | ||||
| 	"or vgimport.) A VG on shared storage devices is accessible only to\n" | ||||
| @@ -1276,12 +1224,10 @@ cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, CFG_DEF | ||||
| 	"  uname\n" | ||||
| 	"    Set the system ID from the hostname (uname) of the system.\n" | ||||
| 	"    System IDs beginning localhost are not permitted.\n" | ||||
| 	"  appmachineid\n" | ||||
| 	"    Use an LVM-specific derivation of the local machine-id as the\n" | ||||
| 	"    system ID. See 'man machine-id'.\n" | ||||
| 	"  machineid\n" | ||||
| 	"    Use the contents of the machine-id file to set the system ID\n" | ||||
| 	"    (appmachineid is recommended.)\n" | ||||
| 	"    Use the contents of the machine-id file to set the system ID.\n" | ||||
| 	"    Some systems create this file at installation time.\n" | ||||
| 	"    See 'man machine-id' and global/etc.\n" | ||||
| 	"  file\n" | ||||
| 	"    Use the contents of another file (system_id_file) to set the\n" | ||||
| 	"    system ID.\n" | ||||
| @@ -1292,13 +1238,13 @@ cfg(global_system_id_file_CFG, "system_id_file", global_CFG_SECTION, CFG_DEFAULT | ||||
| 	"This is used when system_id_source is set to 'file'.\n" | ||||
| 	"Comments starting with the character # are ignored.\n") | ||||
|  | ||||
| cfg(activation_checks_CFG, "checks", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ACTIVATION_CHECKS, vsn(2, 2, 86), NULL, 0, NULL, | ||||
| cfg(activation_checks_CFG, "checks", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ACTIVATION_CHECKS, vsn(2, 2, 86), NULL, 0, NULL, | ||||
| 	"Perform internal checks of libdevmapper operations.\n" | ||||
| 	"Useful for debugging problems with activation. Some of the checks may\n" | ||||
| 	"be expensive, so it's best to use this only when there seems to be a\n" | ||||
| 	"problem.\n") | ||||
|  | ||||
| cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_LVMPOLLD, vsn(2, 2, 120), "@DEFAULT_USE_LVMPOLLD@", 0, NULL, | ||||
| cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_LVMPOLLD, vsn(2, 2, 120), "@DEFAULT_USE_LVMPOLLD@", 0, NULL, | ||||
| 	"Use lvmpolld to supervise long running LVM commands.\n" | ||||
| 	"When enabled, control of long running LVM commands is transferred\n" | ||||
| 	"from the original LVM command to the lvmpolld daemon. This allows\n" | ||||
| @@ -1311,7 +1257,7 @@ cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, CFG_DEFAULT_COM | ||||
| 	"commands will supervise long running operations by forking themselves.\n" | ||||
| 	"Applicable only if LVM is compiled with lvmpolld support.\n") | ||||
|  | ||||
| cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL, | ||||
| cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL, | ||||
| 	"Enable D-Bus notification from LVM commands.\n" | ||||
| 	"When enabled, an LVM command that changes PVs, changes VG metadata,\n" | ||||
| 	"or changes the activation state of an LV will send a notification.\n") | ||||
| @@ -1324,9 +1270,9 @@ cfg(global_io_memory_size_CFG, "io_memory_size", global_CFG_SECTION, CFG_DEFAULT | ||||
| 	"This value should usually not be decreased from the default; setting\n" | ||||
| 	"it too low can result in lvm failing to read VGs.\n") | ||||
|  | ||||
| cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL, | ||||
| cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL, | ||||
| 	"Use udev notifications to synchronize udev and LVM.\n" | ||||
| 	"The --noudevsync option overrides this setting.\n" | ||||
| 	"The --nodevsync option overrides this setting.\n" | ||||
| 	"When disabled, LVM commands will not wait for notifications from\n" | ||||
| 	"udev, but continue irrespective of any possible udev processing in\n" | ||||
| 	"the background. Only use this if udev is not running or has rules\n" | ||||
| @@ -1334,25 +1280,25 @@ cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, CFG_DEFAULT_C | ||||
| 	"running, and LVM processes are waiting for udev, run the command\n" | ||||
| 	"'dmsetup udevcomplete_all' to wake them up.\n") | ||||
|  | ||||
| cfg(activation_udev_rules_CFG, "udev_rules", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_UDEV_RULES, vsn(2, 2, 57), NULL, 0, NULL, | ||||
| cfg(activation_udev_rules_CFG, "udev_rules", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_RULES, vsn(2, 2, 57), NULL, 0, NULL, | ||||
| 	"Use udev rules to manage LV device nodes and symlinks.\n" | ||||
| 	"When disabled, LVM will manage the device nodes and symlinks for\n" | ||||
| 	"active LVs itself. Manual intervention may be required if this\n" | ||||
| 	"setting is changed while LVs are active.\n") | ||||
|  | ||||
| cfg(activation_verify_udev_operations_CFG, "verify_udev_operations", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_VERIFY_UDEV_OPERATIONS, vsn(2, 2, 86), NULL, 0, NULL, | ||||
| cfg(activation_verify_udev_operations_CFG, "verify_udev_operations", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_VERIFY_UDEV_OPERATIONS, vsn(2, 2, 86), NULL, 0, NULL, | ||||
| 	"Use extra checks in LVM to verify udev operations.\n" | ||||
| 	"This enables additional checks (and if necessary, repairs) on entries\n" | ||||
| 	"in the device directory after udev has completed processing its\n" | ||||
| 	"events. Useful for diagnosing problems with LVM/udev interactions.\n") | ||||
|  | ||||
| cfg(activation_retry_deactivation_CFG, "retry_deactivation", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_RETRY_DEACTIVATION, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| cfg(activation_retry_deactivation_CFG, "retry_deactivation", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_RETRY_DEACTIVATION, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"Retry failed LV deactivation.\n" | ||||
| 	"If LV deactivation fails, LVM will retry for a few seconds before\n" | ||||
| 	"failing. This may happen because a process run from a quick udev rule\n" | ||||
| 	"temporarily opened the device.\n") | ||||
|  | ||||
| cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_STRIPE_FILLER, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_STRIPE_FILLER, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Method to fill missing stripes when activating an incomplete LV.\n" | ||||
| 	"Using 'error' will make inaccessible parts of the device return I/O\n" | ||||
| 	"errors on access. Using 'zero' will return success (and zero) on I/O\n" | ||||
| @@ -1361,21 +1307,21 @@ cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CF | ||||
| 	"other than 'error' with mirrored or snapshotted volumes is likely to\n" | ||||
| 	"result in data corruption.\n") | ||||
|  | ||||
| cfg(activation_use_linear_target_CFG, "use_linear_target", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_LINEAR_TARGET, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| cfg(activation_use_linear_target_CFG, "use_linear_target", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_LINEAR_TARGET, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"Use the linear target to optimize single stripe LVs.\n" | ||||
| 	"When disabled, the striped target is used. The linear target is an\n" | ||||
| 	"optimised version of the striped target that only handles a single\n" | ||||
| 	"stripe.\n") | ||||
|  | ||||
| cfg(activation_reserved_stack_CFG, "reserved_stack", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RESERVED_STACK, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(activation_reserved_stack_CFG, "reserved_stack", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RESERVED_STACK, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Stack size in KiB to reserve for use while devices are suspended.\n" | ||||
| 	"Insufficent reserve risks I/O deadlock during device suspension.\n") | ||||
|  | ||||
| cfg(activation_reserved_memory_CFG, "reserved_memory", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RESERVED_MEMORY, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(activation_reserved_memory_CFG, "reserved_memory", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RESERVED_MEMORY, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Memory size in KiB to reserve for use while devices are suspended.\n" | ||||
| 	"Insufficent reserve risks I/O deadlock during device suspension.\n") | ||||
|  | ||||
| cfg(activation_process_priority_CFG, "process_priority", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PROCESS_PRIORITY, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| cfg(activation_process_priority_CFG, "process_priority", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_PROCESS_PRIORITY, vsn(1, 0, 0), NULL, 0, NULL, | ||||
| 	"Nice value used while devices are suspended.\n" | ||||
| 	"Use a high priority so that LVs are suspended\n" | ||||
| 	"for the shortest possible time.\n") | ||||
| @@ -1405,22 +1351,22 @@ cfg_array(activation_volume_list_CFG, "volume_list", activation_CFG_SECTION, CFG | ||||
| 	"#\n") | ||||
|  | ||||
| cfg_array(activation_auto_activation_volume_list_CFG, "auto_activation_volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 97), NULL, 0, NULL, | ||||
| 	"A list of VGs or LVs that should be autoactivated.\n" | ||||
| 	"Autoactivation is an activation command run with -aay,\n" | ||||
| 	"i.e. vgchange -aay, lvchange -aay, or pvscan --cache -aay.\n" | ||||
| 	"When this list is defined, an autoactivation command will only\n" | ||||
| 	"activate LVs included in the list. If this list is undefined,\n" | ||||
| 	"it has no effect. If this list is defined but empty, then no\n" | ||||
| 	"LVs will be autoactivated. LVs can be included in the list by\n" | ||||
| 	"LV name, VG name (applies to all LVs in the VG), or tag name.\n" | ||||
| 	"VGs and LVs can also have an autoactivation property set in\n" | ||||
| 	"metadata, see --setautoactivation. LVs included in this list\n" | ||||
| 	"will not be autoactivated if the VG or LV autoactivation\n" | ||||
| 	"property is disabled (see vgs or lvs \"-o autoactivation\").\n" | ||||
| 	"The volume_list setting and the \"activation skip\" property\n" | ||||
| 	"also apply to autoactivation.\n" | ||||
| 	"The -aay option is meant to be used by activation commands that\n" | ||||
| 	"are run automatically by the system, e.g. from systemd services.\n" | ||||
| 	"Only LVs selected by this list are auto-activated.\n" | ||||
| 	"This list works like volume_list, but it is used only by\n" | ||||
| 	"auto-activation commands. It does not apply to direct activation\n" | ||||
| 	"commands. If this list is defined, an LV is only auto-activated\n" | ||||
| 	"if it matches an entry in this list. If this list is undefined, it\n" | ||||
| 	"imposes no limits on LV auto-activation (all are allowed.) If this\n" | ||||
| 	"list is defined and empty, i.e. \"[]\", then no LVs are selected for\n" | ||||
| 	"auto-activation. An LV that is selected by this list for\n" | ||||
| 	"auto-activation, must also be selected by volume_list (if defined)\n" | ||||
| 	"before it is activated. Auto-activation is an activation command that\n" | ||||
| 	"includes the 'a' argument: --activate ay or -a ay. The 'a' (auto)\n" | ||||
| 	"argument for auto-activation is meant to be used by activation\n" | ||||
| 	"commands that are run automatically by the system, as opposed to LVM\n" | ||||
| 	"commands run directly by a user. A user may also use the 'a' flag\n" | ||||
| 	"directly to perform auto-activation. Also see pvscan(8) for more\n" | ||||
| 	"information about auto-activation.\n" | ||||
| 	"#\n" | ||||
| 	"Accepted values:\n" | ||||
| 	"  vgname\n" | ||||
| @@ -1465,11 +1411,11 @@ cfg_array(activation_read_only_volume_list_CFG, "read_only_volume_list", activat | ||||
| 	"read_only_volume_list = [ \"vg1\", \"vg2/lvol1\", \"@tag1\", \"@*\" ]\n" | ||||
| 	"#\n") | ||||
|  | ||||
|  cfg(activation_mirror_region_size_CFG, "mirror_region_size", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(1, 0, 0), NULL, vsn(2, 2, 99), | ||||
|  cfg(activation_mirror_region_size_CFG, "mirror_region_size", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(1, 0, 0), NULL, vsn(2, 2, 99), | ||||
| 	"This has been replaced by the activation/raid_region_size setting.\n", | ||||
| 	"Size in KiB of each raid or mirror synchronization region.\n") | ||||
|  | ||||
| cfg(activation_raid_region_size_CFG, "raid_region_size", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(2, 2, 99), NULL, 0, NULL, | ||||
| cfg(activation_raid_region_size_CFG, "raid_region_size", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(2, 2, 99), NULL, 0, NULL, | ||||
| 	"Size in KiB of each raid or mirror synchronization region.\n" | ||||
| 	"The clean/dirty state of data is tracked for each region.\n" | ||||
| 	"The value is rounded down to a power of two if necessary, and\n" | ||||
| @@ -1484,7 +1430,7 @@ cfg(activation_error_when_full_CFG, "error_when_full", activation_CFG_SECTION, C | ||||
| 	"thin pool data space is extended. New thin pools are assigned the\n" | ||||
| 	"behavior defined here.\n") | ||||
|  | ||||
| cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_READ_AHEAD, vsn(1, 0, 23), NULL, 0, NULL, | ||||
| cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_READ_AHEAD, vsn(1, 0, 23), NULL, 0, NULL, | ||||
| 	"Setting to use when there is no readahead setting in metadata.\n" | ||||
| 	"#\n" | ||||
| 	"Accepted values:\n" | ||||
| @@ -1494,7 +1440,7 @@ cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, CFG_DEFAULT_C | ||||
| 	"    Use default value chosen by kernel.\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_RAID_FAULT_POLICY, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_RAID_FAULT_POLICY, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"Defines how a device failure in a RAID LV is handled.\n" | ||||
| 	"This includes LVs that have the following segment types:\n" | ||||
| 	"raid1, raid4, raid5*, and raid6*.\n" | ||||
| @@ -1515,7 +1461,7 @@ cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTIO | ||||
| 	"    replace faulty devices.\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(2, 2, 57), 0, NULL, | ||||
| cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(2, 2, 57), 0, NULL, | ||||
| 	"Defines how a device failure in a 'mirror' LV is handled.\n" | ||||
| 	"An LV with the 'mirror' segment type is composed of mirror images\n" | ||||
| 	"(copies) and a mirror log. A disk log ensures that a mirror LV does\n" | ||||
| @@ -1551,16 +1497,16 @@ cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy | ||||
| 	"    replacement.\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(activation_mirror_log_fault_policy_CFG, "mirror_log_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_LOG_FAULT_POLICY, vsn(1, 2, 18), NULL, 0, NULL, | ||||
| cfg(activation_mirror_log_fault_policy_CFG, "mirror_log_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_LOG_FAULT_POLICY, vsn(1, 2, 18), NULL, 0, NULL, | ||||
| 	"Defines how a device failure in a 'mirror' log LV is handled.\n" | ||||
| 	"The mirror_image_fault_policy description for mirrored LVs also\n" | ||||
| 	"applies to mirrored log LVs.\n") | ||||
|  | ||||
| cfg(activation_mirror_device_fault_policy_CFG, "mirror_device_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_DEVICE_FAULT_POLICY, vsn(1, 2, 10), NULL, vsn(2, 2, 57), | ||||
| cfg(activation_mirror_device_fault_policy_CFG, "mirror_device_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_DEVICE_FAULT_POLICY, vsn(1, 2, 10), NULL, vsn(2, 2, 57), | ||||
| 	"This has been replaced by the activation/mirror_image_fault_policy setting.\n", | ||||
| 	"Define how a device failure affecting a mirror is handled.\n") | ||||
|  | ||||
| cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD, vsn(2, 2, 75), NULL, 0, NULL, | ||||
| cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD, vsn(2, 2, 75), NULL, 0, NULL, | ||||
| 	"Auto-extend a snapshot when its usage exceeds this percent.\n" | ||||
| 	"Setting this to 100 disables automatic extension.\n" | ||||
| 	"The minimum value is 50 (a smaller value is treated as 50.)\n" | ||||
| @@ -1574,7 +1520,7 @@ cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold | ||||
| 	"snapshot_autoextend_threshold = 70\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT, vsn(2, 2, 75), NULL, 0, NULL, | ||||
| cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT, vsn(2, 2, 75), NULL, 0, NULL, | ||||
| 	"Auto-extending a snapshot adds this percent extra space.\n" | ||||
| 	"The amount of additional space added to a snapshot is this\n" | ||||
| 	"percent of its current size.\n" | ||||
| @@ -1586,7 +1532,7 @@ cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", a | ||||
| 	"snapshot_autoextend_percent = 20\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_threshold", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"Auto-extend a thin pool when its usage exceeds this percent.\n" | ||||
| 	"Setting this to 100 disables automatic extension.\n" | ||||
| 	"The minimum value is 50 (a smaller value is treated as 50.)\n" | ||||
| @@ -1600,7 +1546,7 @@ cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_thresho | ||||
| 	"thin_pool_autoextend_threshold = 70\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"Auto-extending a thin pool adds this percent extra space.\n" | ||||
| 	"The amount of additional space added to a thin pool is this\n" | ||||
| 	"percent of its current size.\n" | ||||
| @@ -1612,7 +1558,7 @@ cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent", | ||||
| 	"thin_pool_autoextend_percent = 20\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(activation_vdo_pool_autoextend_threshold_CFG, "vdo_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_AUTOEXTEND_THRESHOLD, VDO_1ST_VSN, NULL, 0, NULL, | ||||
| cfg(activation_vdo_pool_autoextend_threshold_CFG, "vdo_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_VDO_POOL_AUTOEXTEND_THRESHOLD, VDO_1ST_VSN, NULL, 0, NULL, | ||||
| 	"Auto-extend a VDO pool when its usage exceeds this percent.\n" | ||||
| 	"Setting this to 100 disables automatic extension.\n" | ||||
| 	"The minimum value is 50 (a smaller value is treated as 50.)\n" | ||||
| @@ -1652,17 +1598,17 @@ cfg_array(activation_mlock_filter_CFG, "mlock_filter", activation_CFG_SECTION, C | ||||
| 	"mlock_filter = [ \"locale/locale-archive\", \"gconv/gconv-modules.cache\" ]\n" | ||||
| 	"#\n") | ||||
|  | ||||
| cfg(activation_use_mlockall_CFG, "use_mlockall", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_MLOCKALL, vsn(2, 2, 62), NULL, 0, NULL, | ||||
| cfg(activation_use_mlockall_CFG, "use_mlockall", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_MLOCKALL, vsn(2, 2, 62), NULL, 0, NULL, | ||||
| 	"Use the old behavior of mlockall to pin all memory.\n" | ||||
| 	"Prior to version 2.02.62, LVM used mlockall() to pin the whole\n" | ||||
| 	"process's memory while activating devices.\n") | ||||
|  | ||||
| cfg(activation_monitoring_CFG, "monitoring", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DMEVENTD_MONITOR, vsn(2, 2, 63), NULL, 0, NULL, | ||||
| cfg(activation_monitoring_CFG, "monitoring", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DMEVENTD_MONITOR, vsn(2, 2, 63), NULL, 0, NULL, | ||||
| 	"Monitor LVs that are activated.\n" | ||||
| 	"The --ignoremonitoring option overrides this setting.\n" | ||||
| 	"When enabled, LVM will ask dmeventd to monitor activated LVs.\n") | ||||
|  | ||||
| cfg(activation_polling_interval_CFG, "polling_interval", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_INTERVAL, vsn(2, 2, 63), NULL, 0, NULL, | ||||
| cfg(activation_polling_interval_CFG, "polling_interval", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_INTERVAL, vsn(2, 2, 63), NULL, 0, NULL, | ||||
| 	"Check pvmove or lvconvert progress at this interval (seconds).\n" | ||||
| 	"When pvmove or lvconvert must wait for the kernel to finish\n" | ||||
| 	"synchronising or merging data, they check and report progress at\n" | ||||
| @@ -1679,7 +1625,7 @@ cfg(activation_auto_set_activation_skip_CFG, "auto_set_activation_skip", activat | ||||
| 	"flag set. When this setting is enabled, the activation skip flag is\n" | ||||
| 	"set on new thin snapshot LVs.\n") | ||||
|  | ||||
| cfg(activation_mode_CFG, "activation_mode", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_ACTIVATION_MODE, vsn(2,2,108), NULL, 0, NULL, | ||||
| cfg(activation_mode_CFG, "activation_mode", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ACTIVATION_MODE, vsn(2,2,108), NULL, 0, NULL, | ||||
| 	"How LVs with missing devices are activated.\n" | ||||
| 	"The --activationmode option overrides this setting.\n" | ||||
| 	"#\n" | ||||
| @@ -1776,7 +1722,7 @@ cfg(metadata_pvmetadataignore_CFG, "pvmetadataignore", metadata_CFG_SECTION, CFG | ||||
| cfg(metadata_stripesize_CFG, "stripesize", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_STRIPESIZE, vsn(1, 0, 0), NULL, 0, NULL, NULL) | ||||
|  | ||||
| cfg_array(metadata_dirs_CFG, "dirs", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, | ||||
| 	  NULL) | ||||
| 	  "This setting is no longer used.\n") | ||||
|  | ||||
| cfg_section(metadata_disk_areas_CFG_SUBSECTION, "disk_areas", metadata_CFG_SECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL) | ||||
| cfg_section(disk_area_CFG_SUBSECTION, "disk_area", metadata_disk_areas_CFG_SUBSECTION, CFG_NAME_VARIABLE | CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL) | ||||
| @@ -2101,7 +2047,7 @@ cfg(report_two_word_unknown_device_CFG, "two_word_unknown_device", report_CFG_SE | ||||
| 	"Use the two words 'unknown device' in place of '[unknown]'.\n" | ||||
| 	"This is displayed when the device for a PV is not known.\n") | ||||
|  | ||||
| cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_MIRROR_LIB, vsn(1, 2, 3), NULL, 0, NULL, | ||||
| cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_MIRROR_LIB, vsn(1, 2, 3), NULL, 0, NULL, | ||||
| 	"The library dmeventd uses when monitoring a mirror device.\n" | ||||
| 	"libdevmapper-event-lvm2mirror.so attempts to recover from\n" | ||||
| 	"failures. It removes failed devices from a volume group and\n" | ||||
| @@ -2110,13 +2056,13 @@ cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, CFG_DEF | ||||
|  | ||||
| cfg(dmeventd_raid_library_CFG, "raid_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_RAID_LIB, vsn(2, 2, 87), NULL, 0, NULL, NULL) | ||||
|  | ||||
| cfg(dmeventd_snapshot_library_CFG, "snapshot_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_SNAPSHOT_LIB, vsn(1, 2, 26), NULL, 0, NULL, | ||||
| cfg(dmeventd_snapshot_library_CFG, "snapshot_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_SNAPSHOT_LIB, vsn(1, 2, 26), NULL, 0, NULL, | ||||
| 	"The library dmeventd uses when monitoring a snapshot device.\n" | ||||
| 	"libdevmapper-event-lvm2snapshot.so monitors the filling of snapshots\n" | ||||
| 	"and emits a warning through syslog when the usage exceeds 80%. The\n" | ||||
| 	"warning is repeated when 85%, 90% and 95% of the snapshot is filled.\n") | ||||
|  | ||||
| cfg(dmeventd_thin_library_CFG, "thin_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_THIN_LIB, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| cfg(dmeventd_thin_library_CFG, "thin_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_THIN_LIB, vsn(2, 2, 89), NULL, 0, NULL, | ||||
| 	"The library dmeventd uses when monitoring a thin device.\n" | ||||
| 	"libdevmapper-event-lvm2thin.so monitors the filling of a pool\n" | ||||
| 	"and emits a warning through syslog when the usage exceeds 80%. The\n" | ||||
| @@ -2202,4 +2148,4 @@ cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_ | ||||
| 	"This must be unique among all hosts, and must be between 1 and 2000.\n" | ||||
| 	"Applicable only if LVM is compiled with lockd support\n") | ||||
|  | ||||
| cfg(CFG_COUNT, NULL, root_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL) | ||||
| cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL) | ||||
|   | ||||
| @@ -42,7 +42,7 @@ | ||||
| #define DEFAULT_DEV_DIR "/dev" | ||||
| #define DEFAULT_PROC_DIR "/proc" | ||||
| #define DEFAULT_SYSTEM_ID_SOURCE "none" | ||||
| #define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 0 | ||||
| #define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 1 | ||||
| #define DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE "none" | ||||
| #define DEFAULT_SYSFS_SCAN 1 | ||||
| #define DEFAULT_MD_COMPONENT_DETECTION 1 | ||||
| @@ -118,8 +118,6 @@ | ||||
| #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_CROP_METADATA 0 | ||||
| #define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4)  /* KB */ /* 0x3f8040 blocks */ | ||||
| #define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2)  /* KB */ | ||||
| #define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048  /* KB */ | ||||
| #define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */ | ||||
| @@ -131,7 +129,6 @@ | ||||
| #define DEFAULT_THIN_POOL_DISCARDS "passdown" | ||||
| #define DEFAULT_THIN_POOL_ZERO 1 | ||||
| #define DEFAULT_POOL_METADATA_SPARE 1 /* thin + cache */ | ||||
| #define DEFAULT_ZERO_METADATA 1		/* thin + cache */ | ||||
|  | ||||
| #ifdef CACHE_CHECK_NEEDS_CHECK | ||||
| #  define DEFAULT_CACHE_CHECK_OPTION1 "-q" | ||||
| @@ -167,7 +164,7 @@ | ||||
| #define DEFAULT_VDO_INDEX_MEMORY_SIZE_MB	(DM_VDO_INDEX_MEMORY_SIZE_MINIMUM_MB) | ||||
| #define DEFAULT_VDO_SLAB_SIZE_MB	(2 * 1024)  // 2GiB ... 19 slabbits | ||||
| #define DEFAULT_VDO_ACK_THREADS		(1) | ||||
| #define DEFAULT_VDO_BIO_THREADS		(4) | ||||
| #define DEFAULT_VDO_BIO_THREADS		(1) | ||||
| #define DEFAULT_VDO_BIO_ROTATION	(64) | ||||
| #define DEFAULT_VDO_CPU_THREADS		(2) | ||||
| #define DEFAULT_VDO_HASH_ZONE_THREADS	(1) | ||||
| @@ -181,7 +178,8 @@ | ||||
|  * VDO pool will reverve some sectors in the front and the back of pool device to avoid | ||||
|  * seeing same device twice in the system. | ||||
|  */ | ||||
| #define DEFAULT_VDO_POOL_HEADER_SIZE_KB  (512) | ||||
| #define DEFAULT_VDO_POOL_HEADER_SIZE  (1024)   // 512KiB | ||||
|  | ||||
|  | ||||
|  | ||||
| #define DEFAULT_FSADM_PATH FSADM_PATH | ||||
| @@ -221,7 +219,7 @@ | ||||
| #endif | ||||
|  | ||||
| #define DEFAULT_COMMAND_LOG_REPORT 0 | ||||
| #define DEFAULT_SYSLOG 0 | ||||
| #define DEFAULT_SYSLOG 1 | ||||
| #define DEFAULT_VERBOSE 0 | ||||
| #define DEFAULT_SILENT 0 | ||||
| #define DEFAULT_LOGLEVEL 0 | ||||
| @@ -322,14 +320,4 @@ | ||||
|  | ||||
| #define DEFAULT_MD_COMPONENT_CHECKS "auto" | ||||
|  | ||||
| #define DEFAULT_DEVICES_FILE "system.devices" | ||||
|  | ||||
| #define DEFAULT_SEARCH_FOR_DEVNAMES "auto" | ||||
|  | ||||
| #define DEFAULT_WWIDS_FILE "/etc/multipath/wwids" | ||||
|  | ||||
| #define PVS_ONLINE_DIR DEFAULT_RUN_DIR "/pvs_online" | ||||
| #define VGS_ONLINE_DIR DEFAULT_RUN_DIR "/vgs_online" | ||||
| #define PVS_LOOKUP_DIR DEFAULT_RUN_DIR "/pvs_lookup" | ||||
|  | ||||
| #endif				/* _LVM_DEFAULTS_H */ | ||||
|   | ||||
| @@ -218,7 +218,7 @@ struct dm_list *str_to_str_list(struct dm_pool *mem, const char *str, | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	p1 = str; | ||||
| 	p1 = p2 = str; | ||||
| 	while (*p1) { | ||||
| 		if (!(p2 = strstr(p1, delim))) | ||||
| 			next = p2 = str + strlen(str); | ||||
|   | ||||
| @@ -39,32 +39,32 @@ static uint64_t _min(uint64_t lhs, uint64_t rhs) | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| void bcache_prefetch_bytes(struct bcache *cache, int di, uint64_t start, size_t len) | ||||
| void bcache_prefetch_bytes(struct bcache *cache, int fd, uint64_t start, size_t len) | ||||
| { | ||||
| 	block_address bb, be; | ||||
|  | ||||
| 	byte_range_to_block_range(cache, start, len, &bb, &be); | ||||
| 	while (bb < be) { | ||||
| 		bcache_prefetch(cache, di, bb); | ||||
| 		bcache_prefetch(cache, fd, bb); | ||||
| 		bb++; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| bool bcache_read_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data) | ||||
| bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data) | ||||
| { | ||||
| 	struct block *b; | ||||
| 	block_address bb, be; | ||||
| 	uint64_t block_size = bcache_block_sectors(cache) << SECTOR_SHIFT; | ||||
| 	uint64_t block_offset = start % block_size; | ||||
|  | ||||
| 	bcache_prefetch_bytes(cache, di, start, len); | ||||
| 	bcache_prefetch_bytes(cache, fd, start, len); | ||||
|  | ||||
| 	byte_range_to_block_range(cache, start, len, &bb, &be); | ||||
|  | ||||
| 	for (; bb != be; bb++) { | ||||
|         	if (!bcache_get(cache, di, bb, 0, &b)) | ||||
|         	if (!bcache_get(cache, fd, bb, 0, &b)) | ||||
| 			return false; | ||||
|  | ||||
| 		size_t blen = _min(block_size - block_offset, len); | ||||
| @@ -79,21 +79,6 @@ bool bcache_read_bytes(struct bcache *cache, int di, uint64_t start, size_t len, | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_t len) | ||||
| { | ||||
| 	block_address bb, be; | ||||
| 	bool result = true; | ||||
|  | ||||
| 	byte_range_to_block_range(cache, start, len, &bb, &be); | ||||
|  | ||||
| 	for (; bb != be; bb++) { | ||||
| 		if (!bcache_invalidate(cache, di, bb)) | ||||
| 			result = false; | ||||
| 	} | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| // Writing bytes and zeroing bytes are very similar, so we factor out | ||||
| @@ -101,8 +86,8 @@ bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_ | ||||
|   | ||||
| struct updater; | ||||
|  | ||||
| typedef bool (*partial_update_fn)(struct updater *u, int di, block_address bb, uint64_t offset, size_t len); | ||||
| typedef bool (*whole_update_fn)(struct updater *u, int di, block_address bb, block_address be); | ||||
| typedef bool (*partial_update_fn)(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len); | ||||
| typedef bool (*whole_update_fn)(struct updater *u, int fd, block_address bb, block_address be); | ||||
|  | ||||
| struct updater { | ||||
| 	struct bcache *cache; | ||||
| @@ -111,7 +96,7 @@ struct updater { | ||||
| 	void *data; | ||||
| }; | ||||
|  | ||||
| static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len) | ||||
| static bool _update_bytes(struct updater *u, int fd, uint64_t start, size_t len) | ||||
| { | ||||
|         struct bcache *cache = u->cache; | ||||
| 	block_address bb, be; | ||||
| @@ -124,12 +109,12 @@ static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len) | ||||
| 	// If the last block is partial, we will require a read, so let's  | ||||
| 	// prefetch it. | ||||
| 	if ((start + len) % block_size) | ||||
|         	bcache_prefetch(cache, di, (start + len) / block_size); | ||||
|         	bcache_prefetch(cache, fd, (start + len) / block_size); | ||||
|  | ||||
| 	// First block may be partial | ||||
| 	if (block_offset) { | ||||
|         	size_t blen = _min(block_size - block_offset, len); | ||||
| 		if (!u->partial_fn(u, di, bb, block_offset, blen)) | ||||
| 		if (!u->partial_fn(u, fd, bb, block_offset, blen)) | ||||
|         		return false; | ||||
|  | ||||
| 		len -= blen; | ||||
| @@ -141,7 +126,7 @@ static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len) | ||||
|  | ||||
|         // Now we write out a set of whole blocks | ||||
|         nr_whole = len / block_size; | ||||
|         if (!u->whole_fn(u, di, bb, bb + nr_whole)) | ||||
|         if (!u->whole_fn(u, fd, bb, bb + nr_whole)) | ||||
|                 return false; | ||||
|  | ||||
| 	bb += nr_whole; | ||||
| @@ -151,29 +136,27 @@ static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len) | ||||
|         	return true; | ||||
|  | ||||
|         // Finally we write a partial end block | ||||
|         return u->partial_fn(u, di, bb, 0, len); | ||||
|         return u->partial_fn(u, fd, bb, 0, len); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| static bool _write_partial(struct updater *u, int di, block_address bb, | ||||
| static bool _write_partial(struct updater *u, int fd, block_address bb, | ||||
|                            uint64_t offset, size_t len) | ||||
| { | ||||
| 	struct block *b; | ||||
|  | ||||
| 	if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b)) | ||||
| 	if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b)) | ||||
| 		return false; | ||||
|  | ||||
| 	if (u->data) { | ||||
| 		memcpy(((unsigned char *) b->data) + offset, u->data, len); | ||||
| 		u->data = ((unsigned char *) u->data) + len; | ||||
| 	} | ||||
| 	memcpy(((unsigned char *) b->data) + offset, u->data, len); | ||||
| 	u->data = ((unsigned char *) u->data) + len; | ||||
|  | ||||
| 	bcache_put(b); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| static bool _write_whole(struct updater *u, int di, block_address bb, block_address be) | ||||
| static bool _write_whole(struct updater *u, int fd, block_address bb, block_address be) | ||||
| { | ||||
| 	struct block *b; | ||||
| 	uint64_t block_size = bcache_block_sectors(u->cache) << SECTOR_SHIFT; | ||||
| @@ -181,7 +164,7 @@ static bool _write_whole(struct updater *u, int di, block_address bb, block_addr | ||||
| 	for (; bb != be; bb++) { | ||||
|         	// We don't need to read the block since we are overwriting | ||||
|         	// it completely. | ||||
| 		if (!bcache_get(u->cache, di, bb, GF_ZERO, &b)) | ||||
| 		if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b)) | ||||
|         		return false; | ||||
| 		memcpy(b->data, u->data, block_size); | ||||
| 		u->data = ((unsigned char *) u->data) + block_size; | ||||
| @@ -191,7 +174,7 @@ static bool _write_whole(struct updater *u, int di, block_address bb, block_addr | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool bcache_write_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data) | ||||
| bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data) | ||||
| { | ||||
|         struct updater u; | ||||
|  | ||||
| @@ -200,16 +183,16 @@ bool bcache_write_bytes(struct bcache *cache, int di, uint64_t start, size_t len | ||||
|         u.whole_fn = _write_whole; | ||||
|         u.data = data; | ||||
|  | ||||
| 	return _update_bytes(&u, di, start, len); | ||||
| 	return _update_bytes(&u, fd, start, len); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| static bool _zero_partial(struct updater *u, int di, block_address bb, uint64_t offset, size_t len) | ||||
| static bool _zero_partial(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len) | ||||
| { | ||||
| 	struct block *b; | ||||
|  | ||||
| 	if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b)) | ||||
| 	if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b)) | ||||
| 		return false; | ||||
|  | ||||
| 	memset(((unsigned char *) b->data) + offset, 0, len); | ||||
| @@ -218,12 +201,12 @@ static bool _zero_partial(struct updater *u, int di, block_address bb, uint64_t | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| static bool _zero_whole(struct updater *u, int di, block_address bb, block_address be) | ||||
| static bool _zero_whole(struct updater *u, int fd, block_address bb, block_address be) | ||||
| { | ||||
| 	struct block *b; | ||||
|  | ||||
| 	for (; bb != be; bb++) { | ||||
| 		if (!bcache_get(u->cache, di, bb, GF_ZERO, &b)) | ||||
| 		if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b)) | ||||
|         		return false; | ||||
|         	bcache_put(b); | ||||
| 	} | ||||
| @@ -231,7 +214,7 @@ static bool _zero_whole(struct updater *u, int di, block_address bb, block_addre | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool bcache_zero_bytes(struct bcache *cache, int di, uint64_t start, size_t len) | ||||
| bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len) | ||||
| { | ||||
|         struct updater u; | ||||
|  | ||||
| @@ -240,17 +223,17 @@ bool bcache_zero_bytes(struct bcache *cache, int di, uint64_t start, size_t len) | ||||
|         u.whole_fn = _zero_whole; | ||||
|         u.data = NULL; | ||||
|  | ||||
| 	return _update_bytes(&u, di, start, len); | ||||
| 	return _update_bytes(&u, fd, start, len); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| static bool _set_partial(struct updater *u, int di, block_address bb, uint64_t offset, size_t len) | ||||
| static bool _set_partial(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len) | ||||
| { | ||||
| 	struct block *b; | ||||
| 	uint8_t val = (u->data) ? *((uint8_t *) u->data) : 0; | ||||
| 	uint8_t val = *((uint8_t *) u->data); | ||||
|  | ||||
| 	if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b)) | ||||
| 	if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b)) | ||||
| 		return false; | ||||
|  | ||||
| 	memset(((unsigned char *) b->data) + offset, val, len); | ||||
| @@ -259,14 +242,14 @@ static bool _set_partial(struct updater *u, int di, block_address bb, uint64_t o | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| static bool _set_whole(struct updater *u, int di, block_address bb, block_address be) | ||||
| static bool _set_whole(struct updater *u, int fd, block_address bb, block_address be) | ||||
| { | ||||
| 	struct block *b; | ||||
| 	uint8_t val = (u->data) ? *((uint8_t *) u->data) : 0; | ||||
| 	uint8_t val = *((uint8_t *) u->data); | ||||
|         uint64_t len = bcache_block_sectors(u->cache) * 512; | ||||
|  | ||||
| 	for (; bb != be; bb++) { | ||||
| 		if (!bcache_get(u->cache, di, bb, GF_ZERO, &b)) | ||||
| 		if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b)) | ||||
|         		return false; | ||||
|         	memset((unsigned char *) b->data, val, len); | ||||
|         	bcache_put(b); | ||||
| @@ -275,7 +258,7 @@ static bool _set_whole(struct updater *u, int di, block_address bb, block_addres | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool bcache_set_bytes(struct bcache *cache, int di, uint64_t start, size_t len, uint8_t val) | ||||
| bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val) | ||||
| { | ||||
|         struct updater u; | ||||
|  | ||||
| @@ -284,6 +267,6 @@ bool bcache_set_bytes(struct bcache *cache, int di, uint64_t start, size_t len, | ||||
|         u.whole_fn = _set_whole; | ||||
|         u.data = &val; | ||||
|  | ||||
| 	return _update_bytes(&u, di, start, len); | ||||
| 	return _update_bytes(&u, fd, start, len); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -33,16 +33,11 @@ | ||||
|  | ||||
| #define SECTOR_SHIFT 9L | ||||
|  | ||||
| #define FD_TABLE_INC 1024 | ||||
| static int _fd_table_size; | ||||
| static int *_fd_table; | ||||
|  | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| static void log_sys_warn(const char *call) | ||||
| { | ||||
| 	log_warn("WARNING: %s failed: %s.", call, strerror(errno)); | ||||
| 	log_warn("%s failed: %s", call, strerror(errno)); | ||||
| } | ||||
|  | ||||
| // Assumes the list is not empty. | ||||
| @@ -66,17 +61,23 @@ struct control_block { | ||||
| struct cb_set { | ||||
| 	struct dm_list free; | ||||
| 	struct dm_list allocated; | ||||
| 	struct control_block vec[]; | ||||
| 	struct control_block *vec; | ||||
| } control_block_set; | ||||
|  | ||||
| static struct cb_set *_cb_set_create(unsigned nr) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	struct cb_set *cbs = malloc(sizeof(*cbs) + nr * sizeof(*cbs->vec)); | ||||
| 	int i; | ||||
| 	struct cb_set *cbs = malloc(sizeof(*cbs)); | ||||
|  | ||||
| 	if (!cbs) | ||||
| 		return NULL; | ||||
|  | ||||
| 	cbs->vec = malloc(nr * sizeof(*cbs->vec)); | ||||
| 	if (!cbs->vec) { | ||||
| 		free(cbs); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	dm_list_init(&cbs->free); | ||||
| 	dm_list_init(&cbs->allocated); | ||||
|  | ||||
| @@ -92,10 +93,11 @@ static void _cb_set_destroy(struct cb_set *cbs) | ||||
| 	// never be in flight IO. | ||||
| 	if (!dm_list_empty(&cbs->allocated)) { | ||||
| 		// bail out | ||||
| 		log_warn("WARNING: async io still in flight."); | ||||
| 		log_error("async io still in flight"); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	free(cbs->vec); | ||||
| 	free(cbs); | ||||
| } | ||||
|  | ||||
| @@ -153,11 +155,11 @@ static void _async_destroy(struct io_engine *ioe) | ||||
| 	free(e); | ||||
| } | ||||
|  | ||||
| static int _last_byte_di; | ||||
| static int _last_byte_fd; | ||||
| static uint64_t _last_byte_offset; | ||||
| static int _last_byte_sector_size; | ||||
|  | ||||
| static bool _async_issue(struct io_engine *ioe, enum dir d, int di, | ||||
| static bool _async_issue(struct io_engine *ioe, enum dir d, int fd, | ||||
| 			 sector_t sb, sector_t se, void *data, void *context) | ||||
| { | ||||
| 	int r; | ||||
| @@ -181,7 +183,7 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int di, | ||||
| 	/* | ||||
| 	 * If bcache block goes past where lvm wants to write, then clamp it. | ||||
| 	 */ | ||||
| 	if ((d == DIR_WRITE) && _last_byte_offset && (di == _last_byte_di)) { | ||||
| 	if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) { | ||||
| 		if (offset > _last_byte_offset) { | ||||
| 			log_error("Limit write at %llu len %llu beyond last byte %llu", | ||||
| 				  (unsigned long long)offset, | ||||
| @@ -266,7 +268,7 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int di, | ||||
|  | ||||
| 	memset(&cb->cb, 0, sizeof(cb->cb)); | ||||
|  | ||||
| 	cb->cb.aio_fildes = (int) _fd_table[di]; | ||||
| 	cb->cb.aio_fildes = (int) fd; | ||||
| 	cb->cb.u.c.buf = data; | ||||
| 	cb->cb.u.c.offset = offset; | ||||
| 	cb->cb.u.c.nbytes = nbytes; | ||||
| @@ -274,15 +276,13 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int di, | ||||
|  | ||||
| #if 0 | ||||
| 	if (d == DIR_READ) { | ||||
| 		log_debug("io R off %llu bytes %llu di %d fd %d", | ||||
| 		log_debug("io R off %llu bytes %llu", | ||||
| 			  (unsigned long long)cb->cb.u.c.offset, | ||||
| 			  (unsigned long long)cb->cb.u.c.nbytes, | ||||
| 			  di, _fd_table[di]); | ||||
| 			  (unsigned long long)cb->cb.u.c.nbytes); | ||||
| 	} else { | ||||
| 		log_debug("io W off %llu bytes %llu di %d fd %d", | ||||
| 		log_debug("io W off %llu bytes %llu", | ||||
| 			  (unsigned long long)cb->cb.u.c.offset, | ||||
| 			  (unsigned long long)cb->cb.u.c.nbytes, | ||||
| 			  di, _fd_table[di]); | ||||
| 			  (unsigned long long)cb->cb.u.c.nbytes); | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| @@ -318,7 +318,9 @@ static bool _async_wait(struct io_engine *ioe, io_complete_fn fn) | ||||
| 	struct async_engine *e = _to_async(ioe); | ||||
|  | ||||
| 	memset(&event, 0, sizeof(event)); | ||||
| 	r = io_getevents(e->aio_context, 1, MAX_EVENT, event, NULL); | ||||
| 	do { | ||||
| 		r = io_getevents(e->aio_context, 1, MAX_EVENT, event, NULL); | ||||
| 	} while (r == -EINTR); | ||||
|  | ||||
| 	if (r < 0) { | ||||
| 		log_sys_warn("io_getevents"); | ||||
| @@ -358,16 +360,10 @@ static unsigned _async_max_io(struct io_engine *e) | ||||
|  | ||||
| struct io_engine *create_async_io_engine(void) | ||||
| { | ||||
| 	static int _pagesize = 0; | ||||
| 	int r; | ||||
| 	struct async_engine *e; | ||||
| 	struct async_engine *e = malloc(sizeof(*e)); | ||||
|  | ||||
| 	if ((_pagesize <= 0) && (_pagesize = sysconf(_SC_PAGESIZE)) < 0) { | ||||
| 		log_warn("_SC_PAGESIZE returns negative value."); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (!(e = malloc(sizeof(*e)))) | ||||
| 	if (!e) | ||||
| 		return NULL; | ||||
|  | ||||
| 	e->e.destroy = _async_destroy; | ||||
| @@ -390,9 +386,8 @@ struct io_engine *create_async_io_engine(void) | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	e->page_mask = (unsigned) _pagesize - 1; | ||||
| 	e->page_mask = sysconf(_SC_PAGESIZE) - 1; | ||||
|  | ||||
| 	/* coverity[leaked_storage] 'e' is not leaking */ | ||||
| 	return &e->e; | ||||
| } | ||||
|  | ||||
| @@ -419,7 +414,7 @@ static void _sync_destroy(struct io_engine *ioe) | ||||
|         free(e); | ||||
| } | ||||
|  | ||||
| static bool _sync_issue(struct io_engine *ioe, enum dir d, int di, | ||||
| static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd, | ||||
|                         sector_t sb, sector_t se, void *data, void *context) | ||||
| { | ||||
| 	int rv; | ||||
| @@ -435,7 +430,7 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int di, | ||||
| 	} | ||||
|  | ||||
| 	where = sb * 512; | ||||
| 	off = lseek(_fd_table[di], where, SEEK_SET); | ||||
| 	off = lseek(fd, where, SEEK_SET); | ||||
| 	if (off == (off_t) -1) { | ||||
| 		log_warn("Device seek error %d for offset %llu", errno, (unsigned long long)where); | ||||
| 		free(io); | ||||
| @@ -450,7 +445,7 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int di, | ||||
| 	/* | ||||
| 	 * If bcache block goes past where lvm wants to write, then clamp it. | ||||
| 	 */ | ||||
| 	if ((d == DIR_WRITE) && _last_byte_offset && (di == _last_byte_di)) { | ||||
| 	if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) { | ||||
| 		uint64_t offset = where; | ||||
| 		uint64_t nbytes = len; | ||||
| 		sector_t limit_nbytes = 0; | ||||
| @@ -520,7 +515,6 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int di, | ||||
| 					  (unsigned long long)limit_nbytes, | ||||
| 					  (unsigned long long)extra_nbytes, | ||||
| 					  (unsigned long long)_last_byte_sector_size); | ||||
| 				free(io); | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| @@ -531,9 +525,9 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int di, | ||||
|  | ||||
| 	while (pos < len) { | ||||
| 		if (d == DIR_READ) | ||||
| 			rv = read(_fd_table[di], (char *)data + pos, len - pos); | ||||
| 			rv = read(fd, (char *)data + pos, len - pos); | ||||
| 		else | ||||
| 			rv = write(_fd_table[di], (char *)data + pos, len - pos); | ||||
| 			rv = write(fd, (char *)data + pos, len - pos); | ||||
|  | ||||
| 		if (rv == -1 && errno == EINTR) | ||||
| 			continue; | ||||
| @@ -607,8 +601,7 @@ struct io_engine *create_sync_io_engine(void) | ||||
|         e->e.wait = _sync_wait; | ||||
|         e->e.max_io = _sync_max_io; | ||||
|  | ||||
| 	dm_list_init(&e->complete); | ||||
| 	/* coverity[leaked_storage] 'e' is not leaking */ | ||||
|         dm_list_init(&e->complete); | ||||
|         return &e->e; | ||||
| } | ||||
|  | ||||
| @@ -694,7 +687,7 @@ struct bcache { | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| struct key_parts { | ||||
| 	uint32_t di; | ||||
| 	uint32_t fd; | ||||
| 	uint64_t b; | ||||
| } __attribute__ ((packed)); | ||||
|  | ||||
| @@ -703,12 +696,12 @@ union key { | ||||
|         uint8_t bytes[12]; | ||||
| }; | ||||
|  | ||||
| static struct block *_block_lookup(struct bcache *cache, int di, uint64_t i) | ||||
| static struct block *_block_lookup(struct bcache *cache, int fd, uint64_t i) | ||||
| { | ||||
| 	union key k; | ||||
| 	union radix_value v; | ||||
|  | ||||
| 	k.parts.di = di; | ||||
| 	k.parts.fd = fd; | ||||
| 	k.parts.b = i; | ||||
|  | ||||
| 	if (radix_tree_lookup(cache->rtree, k.bytes, k.bytes + sizeof(k.bytes), &v)) | ||||
| @@ -722,7 +715,7 @@ static bool _block_insert(struct block *b) | ||||
|         union key k; | ||||
|         union radix_value v; | ||||
|  | ||||
|         k.parts.di = b->di; | ||||
|         k.parts.fd = b->fd; | ||||
|         k.parts.b = b->index; | ||||
|         v.ptr = b; | ||||
|  | ||||
| @@ -733,10 +726,10 @@ static void _block_remove(struct block *b) | ||||
| { | ||||
|         union key k; | ||||
|  | ||||
|         k.parts.di = b->di; | ||||
|         k.parts.fd = b->fd; | ||||
|         k.parts.b = b->index; | ||||
|  | ||||
| 	(void) radix_tree_remove(b->cache->rtree, k.bytes, k.bytes + sizeof(k.bytes)); | ||||
| 	radix_tree_remove(b->cache->rtree, k.bytes, k.bytes + sizeof(k.bytes)); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
| @@ -875,7 +868,7 @@ static void _issue_low_level(struct block *b, enum dir d) | ||||
|  | ||||
| 	dm_list_move(&cache->io_pending, &b->list); | ||||
|  | ||||
| 	if (!cache->engine->issue(cache->engine, d, b->di, sb, se, b->data, b)) { | ||||
| 	if (!cache->engine->issue(cache->engine, d, b->fd, sb, se, b->data, b)) { | ||||
| 		/* FIXME: if io_submit() set an errno, return that instead of EIO? */ | ||||
| 		_complete_io(b, -EIO); | ||||
| 		return; | ||||
| @@ -951,26 +944,21 @@ static struct block *_find_unused_clean_block(struct bcache *cache) | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static struct block *_new_block(struct bcache *cache, int di, block_address i, bool can_wait) | ||||
| static struct block *_new_block(struct bcache *cache, int fd, block_address i, bool can_wait) | ||||
| { | ||||
| 	struct block *b; | ||||
|  | ||||
| 	b = _alloc_block(cache); | ||||
| 	while (!b) { | ||||
| 	while (!b && !dm_list_empty(&cache->clean)) { | ||||
| 		b = _find_unused_clean_block(cache); | ||||
| 		if (!b) { | ||||
| 			if (can_wait) { | ||||
| 				if (dm_list_empty(&cache->io_pending)) | ||||
| 					_writeback(cache, 16);  // FIXME: magic number | ||||
| 				_wait_all(cache); | ||||
| 				if (dm_list_size(&cache->errored) >= cache->max_io) { | ||||
| 					log_debug("bcache no new blocks for di %d index %u with >%d errors.", | ||||
| 						  di, (uint32_t) i, cache->max_io); | ||||
| 					return NULL; | ||||
| 				} | ||||
| 				_wait_io(cache); | ||||
| 			} else { | ||||
| 				log_debug("bcache no new blocks for di %d index %u", | ||||
| 					  di, (uint32_t) i); | ||||
| 				log_debug("bcache no new blocks for fd %d index %u", | ||||
| 					  fd, (uint32_t) i); | ||||
| 				return NULL; | ||||
| 			} | ||||
| 		} | ||||
| @@ -979,7 +967,7 @@ static struct block *_new_block(struct bcache *cache, int di, block_address i, b | ||||
| 	if (b) { | ||||
| 		dm_list_init(&b->list); | ||||
| 		b->flags = 0; | ||||
| 		b->di = di; | ||||
| 		b->fd = fd; | ||||
| 		b->index = i; | ||||
| 		b->ref_count = 0; | ||||
| 		b->error = 0; | ||||
| @@ -1025,10 +1013,10 @@ static void _miss(struct bcache *cache, unsigned flags) | ||||
| } | ||||
|  | ||||
| static struct block *_lookup_or_read_block(struct bcache *cache, | ||||
| 				  	   int di, block_address i, | ||||
| 				  	   int fd, block_address i, | ||||
| 					   unsigned flags) | ||||
| { | ||||
| 	struct block *b = _block_lookup(cache, di, i); | ||||
| 	struct block *b = _block_lookup(cache, fd, i); | ||||
|  | ||||
| 	if (b) { | ||||
| 		// FIXME: this is insufficient.  We need to also catch a read | ||||
| @@ -1053,7 +1041,7 @@ static struct block *_lookup_or_read_block(struct bcache *cache, | ||||
| 	} else { | ||||
| 		_miss(cache, flags); | ||||
|  | ||||
| 		b = _new_block(cache, di, i, true); | ||||
| 		b = _new_block(cache, fd, i, true); | ||||
| 		if (b) { | ||||
| 			if (flags & GF_ZERO) | ||||
| 				_zero_block(b); | ||||
| @@ -1095,12 +1083,11 @@ static void _preemptive_writeback(struct bcache *cache) | ||||
| struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks, | ||||
| 			     struct io_engine *engine) | ||||
| { | ||||
| 	static long _pagesize = 0; | ||||
| 	struct bcache *cache; | ||||
| 	unsigned max_io = engine->max_io(engine); | ||||
| 	int i; | ||||
| 	long pgsize = sysconf(_SC_PAGESIZE); | ||||
|  | ||||
| 	if ((_pagesize <= 0) && ((_pagesize = sysconf(_SC_PAGESIZE)) < 0)) { | ||||
| 	if (pgsize < 0) { | ||||
| 		log_warn("WARNING: _SC_PAGESIZE returns negative value."); | ||||
| 		return NULL; | ||||
| 	} | ||||
| @@ -1115,7 +1102,7 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks, | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (block_sectors & ((_pagesize >> SECTOR_SHIFT) - 1)) { | ||||
| 	if (block_sectors & ((pgsize >> SECTOR_SHIFT) - 1)) { | ||||
| 		log_warn("bcache block size must be a multiple of page size"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| @@ -1152,25 +1139,13 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks, | ||||
| 	cache->write_misses = 0; | ||||
| 	cache->prefetches = 0; | ||||
|  | ||||
| 	if (!_init_free_list(cache, nr_cache_blocks, _pagesize)) { | ||||
| 	if (!_init_free_list(cache, nr_cache_blocks, pgsize)) { | ||||
| 		cache->engine->destroy(cache->engine); | ||||
| 		radix_tree_destroy(cache->rtree); | ||||
| 		free(cache); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	_fd_table_size = FD_TABLE_INC; | ||||
|  | ||||
| 	if (!(_fd_table = malloc(sizeof(int) * _fd_table_size))) { | ||||
| 		cache->engine->destroy(cache->engine); | ||||
| 		radix_tree_destroy(cache->rtree); | ||||
| 		free(cache); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < _fd_table_size; i++) | ||||
| 		_fd_table[i] = -1; | ||||
|  | ||||
| 	return cache; | ||||
| } | ||||
|  | ||||
| @@ -1186,9 +1161,6 @@ void bcache_destroy(struct bcache *cache) | ||||
| 	radix_tree_destroy(cache->rtree); | ||||
| 	cache->engine->destroy(cache->engine); | ||||
| 	free(cache); | ||||
| 	free(_fd_table); | ||||
| 	_fd_table = NULL; | ||||
| 	_fd_table_size = 0; | ||||
| } | ||||
|  | ||||
| sector_t bcache_block_sectors(struct bcache *cache) | ||||
| @@ -1206,13 +1178,13 @@ unsigned bcache_max_prefetches(struct bcache *cache) | ||||
| 	return cache->max_io; | ||||
| } | ||||
|  | ||||
| void bcache_prefetch(struct bcache *cache, int di, block_address i) | ||||
| void bcache_prefetch(struct bcache *cache, int fd, block_address i) | ||||
| { | ||||
| 	struct block *b = _block_lookup(cache, di, i); | ||||
| 	struct block *b = _block_lookup(cache, fd, i); | ||||
|  | ||||
| 	if (!b) { | ||||
| 		if (cache->nr_io_pending < cache->max_io) { | ||||
| 			b = _new_block(cache, di, i, false); | ||||
| 			b = _new_block(cache, fd, i, false); | ||||
| 			if (b) { | ||||
| 				cache->prefetches++; | ||||
| 				_issue_read(b); | ||||
| @@ -1230,15 +1202,12 @@ static void _recycle_block(struct bcache *cache, struct block *b) | ||||
| 	_free_block(b); | ||||
| } | ||||
|  | ||||
| bool bcache_get(struct bcache *cache, int di, block_address i, | ||||
| bool bcache_get(struct bcache *cache, int fd, block_address i, | ||||
| 	        unsigned flags, struct block **result) | ||||
| { | ||||
| 	struct block *b; | ||||
|  | ||||
| 	if (di >= _fd_table_size) | ||||
| 		goto bad; | ||||
|  | ||||
| 	b = _lookup_or_read_block(cache, di, i, flags); | ||||
| 	b = _lookup_or_read_block(cache, fd, i, flags); | ||||
| 	if (b) { | ||||
| 		if (b->error) { | ||||
| 			if (b->io_dir == DIR_READ) { | ||||
| @@ -1257,10 +1226,10 @@ bool bcache_get(struct bcache *cache, int di, block_address i, | ||||
| 		*result = b; | ||||
| 		return true; | ||||
| 	} | ||||
| bad: | ||||
|  | ||||
| 	*result = NULL; | ||||
|  | ||||
| 	log_error("bcache failed to get block %u di %d", (uint32_t) i, di); | ||||
| 	log_error("bcache failed to get block %u fd %d", (uint32_t) i, fd); | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| @@ -1324,7 +1293,7 @@ static bool _invalidate_block(struct bcache *cache, struct block *b) | ||||
|  | ||||
| 	if (b->ref_count) { | ||||
| 		log_warn("bcache_invalidate: block (%d, %llu) still held", | ||||
| 			 b->di, (unsigned long long) b->index); | ||||
| 			 b->fd, (unsigned long long) b->index); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| @@ -1341,9 +1310,9 @@ static bool _invalidate_block(struct bcache *cache, struct block *b) | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool bcache_invalidate(struct bcache *cache, int di, block_address i) | ||||
| bool bcache_invalidate(struct bcache *cache, int fd, block_address i) | ||||
| { | ||||
| 	return _invalidate_block(cache, _block_lookup(cache, di, i)); | ||||
| 	return _invalidate_block(cache, _block_lookup(cache, fd, i)); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
| @@ -1359,27 +1328,27 @@ static bool _writeback_v(struct radix_tree_iterator *it, | ||||
| 	struct block *b = v.ptr; | ||||
|  | ||||
| 	if (_test_flags(b, BF_DIRTY)) | ||||
| 		_issue_write(b); | ||||
|         	_issue_write(b); | ||||
|  | ||||
| 	return true; | ||||
|         return true; | ||||
| } | ||||
|  | ||||
| static bool _invalidate_v(struct radix_tree_iterator *it, | ||||
|                           uint8_t *kb, uint8_t *ke, union radix_value v) | ||||
| { | ||||
| 	struct block *b = v.ptr; | ||||
| 	struct invalidate_iterator *iit = container_of(it, struct invalidate_iterator, it); | ||||
|         struct invalidate_iterator *iit = container_of(it, struct invalidate_iterator, it); | ||||
|  | ||||
| 	if (b->error || _test_flags(b, BF_DIRTY)) { | ||||
| 		log_warn("WARNING: bcache_invalidate: block (%d, %llu) still dirty.", | ||||
| 			 b->di, (unsigned long long) b->index); | ||||
| 		iit->success = false; | ||||
| 		return true; | ||||
|         	log_warn("bcache_invalidate: block (%d, %llu) still dirty", | ||||
|                          b->fd, (unsigned long long) b->index); | ||||
|         	iit->success = false; | ||||
|         	return true; | ||||
| 	} | ||||
|  | ||||
| 	if (b->ref_count) { | ||||
| 		log_warn("WARNING: bcache_invalidate: block (%d, %llu) still held.", | ||||
| 			 b->di, (unsigned long long) b->index); | ||||
| 		log_warn("bcache_invalidate: block (%d, %llu) still held", | ||||
| 			 b->fd, (unsigned long long) b->index); | ||||
| 		iit->success = false; | ||||
| 		return true; | ||||
| 	} | ||||
| @@ -1392,137 +1361,42 @@ static bool _invalidate_v(struct radix_tree_iterator *it, | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool bcache_invalidate_di(struct bcache *cache, int di) | ||||
| bool bcache_invalidate_fd(struct bcache *cache, int fd) | ||||
| { | ||||
| 	union key k; | ||||
|         union key k; | ||||
| 	struct invalidate_iterator it; | ||||
|  | ||||
| 	k.parts.di = di; | ||||
| 	k.parts.fd = fd; | ||||
|  | ||||
| 	it.it.visit = _writeback_v; | ||||
| 	radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it.it); | ||||
| 	radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), &it.it); | ||||
|  | ||||
| 	_wait_all(cache); | ||||
|  | ||||
| 	it.success = true; | ||||
| 	it.it.visit = _invalidate_v; | ||||
| 	radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it.it); | ||||
|  | ||||
| 	if (it.success) | ||||
| 		(void) radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di)); | ||||
|  | ||||
| 	radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), &it.it); | ||||
| 	radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd)); | ||||
| 	return it.success; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| static bool _abort_v(struct radix_tree_iterator *it, | ||||
|                      uint8_t *kb, uint8_t *ke, union radix_value v) | ||||
| void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size) | ||||
| { | ||||
| 	struct block *b = v.ptr; | ||||
|  | ||||
| 	if (b->ref_count) { | ||||
| 		log_fatal("bcache_abort: block (%d, %llu) still held", | ||||
| 			 b->di, (unsigned long long) b->index); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	_unlink_block(b); | ||||
| 	_free_block(b); | ||||
|  | ||||
| 	// We can't remove the block from the radix tree yet because | ||||
| 	// we're in the middle of an iteration. | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void bcache_abort_di(struct bcache *cache, int di) | ||||
| { | ||||
| 	union key k; | ||||
| 	struct radix_tree_iterator it; | ||||
|  | ||||
| 	k.parts.di = di; | ||||
|  | ||||
| 	it.visit = _abort_v; | ||||
| 	radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it); | ||||
| 	(void) radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di)); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| void bcache_set_last_byte(struct bcache *cache, int di, uint64_t offset, int sector_size) | ||||
| { | ||||
| 	_last_byte_di = di; | ||||
| 	_last_byte_fd = fd; | ||||
| 	_last_byte_offset = offset; | ||||
| 	_last_byte_sector_size = sector_size; | ||||
| 	if (!sector_size) | ||||
| 		_last_byte_sector_size = 512; | ||||
| } | ||||
|  | ||||
| void bcache_unset_last_byte(struct bcache *cache, int di) | ||||
| void bcache_unset_last_byte(struct bcache *cache, int fd) | ||||
| { | ||||
| 	if (_last_byte_di == di) { | ||||
| 		_last_byte_di = 0; | ||||
| 	if (_last_byte_fd == fd) { | ||||
| 		_last_byte_fd = 0; | ||||
| 		_last_byte_offset = 0; | ||||
| 		_last_byte_sector_size = 0; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int bcache_set_fd(int fd) | ||||
| { | ||||
| 	int *new_table = NULL; | ||||
| 	int new_size = 0; | ||||
| 	int i; | ||||
|  | ||||
|  retry: | ||||
| 	for (i = 0; i < _fd_table_size; i++) { | ||||
| 		if (_fd_table[i] == -1) { | ||||
| 			_fd_table[i] = fd; | ||||
| 			return i; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* already tried once, shouldn't happen */ | ||||
| 	if (new_size) | ||||
| 		return -1; | ||||
|  | ||||
| 	new_size = _fd_table_size + FD_TABLE_INC; | ||||
|  | ||||
| 	new_table = realloc(_fd_table, sizeof(int) * new_size); | ||||
| 	if (!new_table) { | ||||
| 		log_error("Cannot extend bcache fd table"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	for (i = _fd_table_size; i < new_size; i++) | ||||
| 		new_table[i] = -1; | ||||
|  | ||||
| 	_fd_table = new_table; | ||||
| 	_fd_table_size = new_size; | ||||
|  | ||||
| 	goto retry; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Should we check for unflushed or inprogress io on an fd | ||||
|  * prior to doing clear_fd or change_fd?  (To catch mistakes; | ||||
|  * the caller should be smart enough to not do that.) | ||||
|  */ | ||||
|  | ||||
| void bcache_clear_fd(int di) | ||||
| { | ||||
| 	if (di >= _fd_table_size) | ||||
| 		return; | ||||
| 	_fd_table[di] = -1; | ||||
| } | ||||
|  | ||||
| int bcache_change_fd(int di, int fd) | ||||
| { | ||||
| 	if (di >= _fd_table_size) | ||||
| 		return 0; | ||||
| 	if (di < 0) { | ||||
| 		log_error(INTERNAL_ERROR "Cannot change not opened DI with FD:%d", fd); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	_fd_table[di] = fd; | ||||
| 	return 1; | ||||
| } | ||||
|   | ||||
| @@ -16,12 +16,19 @@ | ||||
| #define BCACHE_H | ||||
|  | ||||
| #include "device_mapper/all.h" | ||||
| #include "base/memory/container_of.h" | ||||
|  | ||||
| #include <linux/fs.h> | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
|  | ||||
| /*----------------------------------------------------------------*/ | ||||
|  | ||||
| // FIXME: move somewhere more sensible | ||||
| #define container_of(v, t, head) \ | ||||
|     ((t *)((const char *)(v) - (const char *)&((t *) 0)->head)) | ||||
|  | ||||
| /*----------------------------------------------------------------*/ | ||||
|  | ||||
| enum dir { | ||||
| 	DIR_READ, | ||||
| 	DIR_WRITE | ||||
| @@ -34,7 +41,7 @@ typedef void io_complete_fn(void *context, int io_error); | ||||
|  | ||||
| struct io_engine { | ||||
| 	void (*destroy)(struct io_engine *e); | ||||
| 	bool (*issue)(struct io_engine *e, enum dir d, int di, | ||||
| 	bool (*issue)(struct io_engine *e, enum dir d, int fd, | ||||
| 		      sector_t sb, sector_t se, void *data, void *context); | ||||
| 	bool (*wait)(struct io_engine *e, io_complete_fn fn); | ||||
| 	unsigned (*max_io)(struct io_engine *e); | ||||
| @@ -48,7 +55,7 @@ struct io_engine *create_sync_io_engine(void); | ||||
| struct bcache; | ||||
| struct block { | ||||
| 	/* clients may only access these three fields */ | ||||
| 	int di; | ||||
| 	int fd; | ||||
| 	uint64_t index; | ||||
| 	void *data; | ||||
|  | ||||
| @@ -106,12 +113,12 @@ unsigned bcache_max_prefetches(struct bcache *cache); | ||||
|  * they complete.  But we're talking a very small difference, and it's worth it | ||||
|  * to keep callbacks out of this interface. | ||||
|  */ | ||||
| void bcache_prefetch(struct bcache *cache, int di, block_address index); | ||||
| void bcache_prefetch(struct bcache *cache, int fd, block_address index); | ||||
|  | ||||
| /* | ||||
|  * Returns true on success. | ||||
|  */ | ||||
| bool bcache_get(struct bcache *cache, int di, block_address index, | ||||
| bool bcache_get(struct bcache *cache, int fd, block_address index, | ||||
| 	        unsigned flags, struct block **result); | ||||
| void bcache_put(struct block *b); | ||||
|  | ||||
| @@ -129,42 +136,30 @@ bool bcache_flush(struct bcache *cache); | ||||
|  *  | ||||
|  * If the block is currently held false will be returned. | ||||
|  */ | ||||
| bool bcache_invalidate(struct bcache *cache, int di, block_address index); | ||||
| bool bcache_invalidate(struct bcache *cache, int fd, block_address index); | ||||
|  | ||||
| /* | ||||
|  * Invalidates all blocks on the given descriptor.  Call this before closing | ||||
|  * the descriptor to make sure everything is written back. | ||||
|  */ | ||||
| bool bcache_invalidate_di(struct bcache *cache, int di); | ||||
| bool bcache_invalidate_fd(struct bcache *cache, int fd); | ||||
|  | ||||
| /* | ||||
|  * Call this function if flush, or invalidate fail and you do not | ||||
|  * wish to retry the writes.  This will throw away any dirty data | ||||
|  * not written.  If any blocks for di are held, then it will call | ||||
|  * abort(). | ||||
|  */ | ||||
| void bcache_abort_di(struct bcache *cache, int di); | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
| // The next four functions are utilities written in terms of the above api. | ||||
|   | ||||
| // Prefetches the blocks neccessary to satisfy a byte range. | ||||
| void bcache_prefetch_bytes(struct bcache *cache, int di, uint64_t start, size_t len); | ||||
| void bcache_prefetch_bytes(struct bcache *cache, int fd, uint64_t start, size_t len); | ||||
|  | ||||
| // Reads, writes and zeroes bytes.  Returns false if errors occur. | ||||
| bool bcache_read_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data); | ||||
| bool bcache_write_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data); | ||||
| bool bcache_zero_bytes(struct bcache *cache, int di, uint64_t start, size_t len); | ||||
| bool bcache_set_bytes(struct bcache *cache, int di, uint64_t start, size_t len, uint8_t val); | ||||
| bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_t len); | ||||
| bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data); | ||||
| bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data); | ||||
| bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len); | ||||
| bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val); | ||||
|  | ||||
| void bcache_set_last_byte(struct bcache *cache, int di, uint64_t offset, int sector_size); | ||||
| void bcache_unset_last_byte(struct bcache *cache, int di); | ||||
| void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size); | ||||
| void bcache_unset_last_byte(struct bcache *cache, int fd); | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| int bcache_set_fd(int fd); /* returns di */ | ||||
| void bcache_clear_fd(int di); | ||||
| int bcache_change_fd(int di, int fd); | ||||
|  | ||||
| #endif | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -28,12 +28,13 @@ struct cmd_context; | ||||
| struct dev_filter { | ||||
| 	int (*passes_filter) (struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name); | ||||
| 	void (*destroy) (struct dev_filter *f); | ||||
| 	void (*wipe) (struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name); | ||||
| 	void (*wipe) (struct dev_filter *f); | ||||
| 	void *private; | ||||
| 	unsigned use_count; | ||||
| 	const char *name; | ||||
| }; | ||||
|  | ||||
| int dev_cache_index_devs(void); | ||||
| struct dm_list *dev_cache_get_dev_list_for_vgid(const char *vgid); | ||||
| struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid); | ||||
|  | ||||
| @@ -48,15 +49,14 @@ int dev_cache_exit(void); | ||||
|  */ | ||||
| int dev_cache_check_for_open_devices(void); | ||||
|  | ||||
| void dev_cache_scan(struct cmd_context *cmd); | ||||
| void dev_cache_scan(void); | ||||
| int dev_cache_has_scanned(void); | ||||
|  | ||||
| int dev_cache_add_dir(const char *path); | ||||
| struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f); | ||||
| struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f); | ||||
| struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt); | ||||
| const char *dev_cache_filtered_reason(const char *name); | ||||
|  | ||||
| struct device *dev_hash_get(const char *name); | ||||
| struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t device, struct dev_filter *f, int *filtered); | ||||
|  | ||||
| void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev); | ||||
|  | ||||
| @@ -68,20 +68,10 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int unused); | ||||
| void dev_iter_destroy(struct dev_iter *iter); | ||||
| struct device *dev_iter_get(struct cmd_context *cmd, struct dev_iter *iter); | ||||
|  | ||||
| void dev_reset_error_count(struct cmd_context *cmd); | ||||
|  | ||||
| void dev_cache_failed_path(struct device *dev, const char *path); | ||||
|  | ||||
| bool dev_cache_has_md_with_end_superblock(struct dev_types *dt); | ||||
|  | ||||
| int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value); | ||||
| int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor); | ||||
|  | ||||
| int setup_devices_file(struct cmd_context *cmd); | ||||
| int setup_devices(struct cmd_context *cmd); | ||||
| int setup_device(struct cmd_context *cmd, const char *devname); | ||||
|  | ||||
| int setup_devices_for_online_autoactivation(struct cmd_context *cmd); | ||||
| int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname); | ||||
| int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno); | ||||
| struct device *setup_dev_in_dev_cache(struct cmd_context *cmd, dev_t devno, const char *devname); | ||||
|  | ||||
| #endif | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user