mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-03 08:23:48 +03:00 
			
		
		
		
	Compare commits
	
		
			288 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					45abade7fc | ||
| 
						 | 
					5372fc4b43 | ||
| 
						 | 
					4e2f240c98 | ||
| 
						 | 
					bb3605518d | ||
| 
						 | 
					3ef6d37f27 | ||
| 
						 | 
					88e9f2f7f4 | ||
| 
						 | 
					704a447df9 | ||
| 
						 | 
					a5fcb26a33 | ||
| 
						 | 
					2491a61481 | ||
| 
						 | 
					91831d51ed | ||
| 
						 | 
					174f0c19f7 | ||
| 
						 | 
					de6fadfb4f | ||
| 
						 | 
					f946db3e00 | ||
| 
						 | 
					8d05e5bc31 | ||
| 
						 | 
					cfb46820e4 | ||
| 
						 | 
					081f1cbcc2 | ||
| 
						 | 
					7bc6da326f | ||
| 
						 | 
					cd95a0df7b | ||
| 
						 | 
					82fa497c16 | ||
| 
						 | 
					44fd345206 | ||
| 
						 | 
					088e1c9db4 | ||
| 
						 | 
					d4f16e666e | ||
| 
						 | 
					8233cfd371 | ||
| 
						 | 
					ff05e2e30d | ||
| 
						 | 
					a8ea7dd3fb | ||
| 
						 | 
					96f70a5303 | ||
| 
						 | 
					f1604c3e69 | ||
| 
						 | 
					c42c8c5192 | ||
| 
						 | 
					5facb53a41 | ||
| 
						 | 
					d039ce89af | ||
| 
						 | 
					bc7605103f | ||
| 
						 | 
					d305d655d4 | ||
| 
						 | 
					4ef1220b16 | ||
| 
						 | 
					a4fef143cd | ||
| 
						 | 
					74ecb724a9 | ||
| 
						 | 
					af235897ab | ||
| 
						 | 
					5ec4e458b5 | ||
| 
						 | 
					2dae63ce21 | ||
| 
						 | 
					be748fe33b | ||
| 
						 | 
					7408340b6a | ||
| 
						 | 
					29eb92446e | ||
| 
						 | 
					ae6918742e | ||
| 
						 | 
					863484bb65 | ||
| 
						 | 
					1cd7ebce4c | ||
| 
						 | 
					eef8c7862e | ||
| 
						 | 
					b52375d446 | ||
| 
						 | 
					6e2babc2ce | ||
| 
						 | 
					08e253bed1 | ||
| 
						 | 
					c6661477a2 | ||
| 
						 | 
					415cfd99a0 | ||
| 
						 | 
					8c2e37381a | ||
| 
						 | 
					45df79feba | ||
| 
						 | 
					5824f992b7 | ||
| 
						 | 
					b0b60fafd5 | ||
| 
						 | 
					8d98b02ba2 | ||
| 
						 | 
					a93fe79bc4 | ||
| 
						 | 
					4aebd7be37 | ||
| 
						 | 
					3170a5db32 | ||
| 
						 | 
					3605b9eef6 | ||
| 
						 | 
					a945f1fde2 | ||
| 
						 | 
					461a997b5b | ||
| 
						 | 
					a80afd7b4e | ||
| 
						 | 
					aad2b51d85 | ||
| 
						 | 
					36a9a81ff1 | ||
| 
						 | 
					42c88546ae | ||
| 
						 | 
					0f0e86ef9b | ||
| 
						 | 
					98efd9a857 | ||
| 
						 | 
					a0c27d95b7 | ||
| 
						 | 
					984651d99d | ||
| 
						 | 
					c6f7370b30 | ||
| 
						 | 
					3e4b8e8985 | ||
| 
						 | 
					73f08b98d2 | ||
| 
						 | 
					8607a74206 | ||
| 
						 | 
					8339f3ceb3 | ||
| 
						 | 
					c0c9f3cc19 | ||
| 
						 | 
					81f4813c29 | ||
| 
						 | 
					94f57745b9 | ||
| 
						 | 
					54fb2ebbe0 | ||
| 
						 | 
					02d122b65b | ||
| 
						 | 
					df0a5561a1 | ||
| 
						 | 
					f7c55da7d0 | ||
| 
						 | 
					b385f701ce | ||
| 
						 | 
					05dd42f443 | ||
| 
						 | 
					36d816d5cb | ||
| 
						 | 
					92a6746e70 | ||
| 
						 | 
					1728848a39 | ||
| 
						 | 
					f9eb4e7487 | ||
| 
						 | 
					d0b9f33aeb | ||
| 
						 | 
					718583b241 | ||
| 
						 | 
					6737127e9a | ||
| 
						 | 
					19a7b4479b | ||
| 
						 | 
					c340647502 | ||
| 
						 | 
					0f987d2982 | ||
| 
						 | 
					52bcaed169 | ||
| 
						 | 
					177bd565ac | ||
| 
						 | 
					c801c32fc5 | ||
| 
						 | 
					d090cf3058 | ||
| 
						 | 
					1e4b82cc94 | ||
| 
						 | 
					3426f31184 | ||
| 
						 | 
					b4fb7af1df | ||
| 
						 | 
					b36647598b | ||
| 
						 | 
					fd6b94f20e | ||
| 
						 | 
					296dc0ed8a | ||
| 
						 | 
					4f869e14d6 | ||
| 
						 | 
					5704270e9d | ||
| 
						 | 
					505b381e85 | ||
| 
						 | 
					da6cb15393 | ||
| 
						 | 
					16843f6cc8 | ||
| 
						 | 
					64f3ad1fd4 | ||
| 
						 | 
					ff4c4f99b3 | ||
| 
						 | 
					f5d2e09569 | ||
| 
						 | 
					f2bdbe0d4d | ||
| 
						 | 
					c51a13caa6 | ||
| 
						 | 
					7840c78a23 | ||
| 
						 | 
					c706f3246b | ||
| 
						 | 
					608eedf88d | ||
| 
						 | 
					a564ca82be | ||
| 
						 | 
					c868b1fee2 | ||
| 
						 | 
					22374f718f | ||
| 
						 | 
					abe3cfcf41 | ||
| 
						 | 
					59db4b50cd | ||
| 
						 | 
					bdae38765d | ||
| 
						 | 
					66d3ceeb61 | ||
| 
						 | 
					445dd17db3 | ||
| 
						 | 
					cff78a2577 | ||
| 
						 | 
					6a09e64195 | ||
| 
						 | 
					22eabe5eab | ||
| 
						 | 
					b69ba36c2d | ||
| 
						 | 
					5240aad22b | ||
| 
						 | 
					2897eb3cb3 | ||
| 
						 | 
					d3f2f00c25 | ||
| 
						 | 
					bacfb913a0 | ||
| 
						 | 
					c99d0236a0 | ||
| 
						 | 
					aac2b655f7 | ||
| 
						 | 
					126c41e73a | ||
| 
						 | 
					359ee54f0d | ||
| 
						 | 
					28ab560907 | ||
| 
						 | 
					ead252fee4 | ||
| 
						 | 
					abf67914c4 | ||
| 
						 | 
					127884e9dd | ||
| 
						 | 
					654f5049eb | ||
| 
						 | 
					979ca34259 | ||
| 
						 | 
					4dd1086805 | ||
| 
						 | 
					3503d4b72c | ||
| 
						 | 
					b8d32a0d33 | ||
| 
						 | 
					45dca55fc8 | ||
| 
						 | 
					445d8ecd9f | ||
| 
						 | 
					c980add503 | ||
| 
						 | 
					133842392a | ||
| 
						 | 
					8baf2ef155 | ||
| 
						 | 
					20b71340bc | ||
| 
						 | 
					61d8baf8b1 | ||
| 
						 | 
					56a9645aa5 | ||
| 
						 | 
					85877000a6 | ||
| 
						 | 
					2f7d2477b6 | ||
| 
						 | 
					21ea3f05f4 | ||
| 
						 | 
					79d3492e90 | ||
| 
						 | 
					5972777abe | ||
| 
						 | 
					8e373ff868 | ||
| 
						 | 
					a4db92da3a | ||
| 
						 | 
					9b777eb281 | ||
| 
						 | 
					bd3c652184 | ||
| 
						 | 
					800f747570 | ||
| 
						 | 
					2b8423437e | ||
| 
						 | 
					8b4b6945f8 | ||
| 
						 | 
					e5ecfec5c4 | ||
| 
						 | 
					f95dbff71f | ||
| 
						 | 
					098f6830a6 | ||
| 
						 | 
					d1ecebdb52 | ||
| 
						 | 
					590b654251 | ||
| 
						 | 
					3bf190c8ab | ||
| 
						 | 
					dcca7638e0 | ||
| 
						 | 
					70e45ad37b | ||
| 
						 | 
					db88210289 | ||
| 
						 | 
					d2e0d96cc3 | ||
| 
						 | 
					3feba82ccc | ||
| 
						 | 
					db924da231 | ||
| 
						 | 
					fc55ae7e6d | ||
| 
						 | 
					86e757a6ad | ||
| 
						 | 
					4790715cd3 | ||
| 
						 | 
					e7e9c60042 | ||
| 
						 | 
					1c3bc52cc4 | ||
| 
						 | 
					5227dff0e1 | ||
| 
						 | 
					33f0b5b7c2 | ||
| 
						 | 
					0a02968303 | ||
| 
						 | 
					f7bf658c07 | ||
| 
						 | 
					8d16a0abad | ||
| 
						 | 
					c974b97ca3 | ||
| 
						 | 
					b8025bfebd | ||
| 
						 | 
					30323b253f | ||
| 
						 | 
					535c3ede96 | ||
| 
						 | 
					89fed8ca33 | ||
| 
						 | 
					f43c77aaed | ||
| 
						 | 
					96c676b371 | ||
| 
						 | 
					113047e1a2 | ||
| 
						 | 
					abed57cb53 | ||
| 
						 | 
					c01a800a6b | ||
| 
						 | 
					d648832a2d | ||
| 
						 | 
					f06833fbd2 | ||
| 
						 | 
					c561addc94 | ||
| 
						 | 
					702f5f1f4c | ||
| 
						 | 
					1273f179e8 | ||
| 
						 | 
					5d02f60bde | ||
| 
						 | 
					4cf7a108e8 | ||
| 
						 | 
					42635c3938 | ||
| 
						 | 
					ed43dc842b | ||
| 
						 | 
					49d4db6cd2 | ||
| 
						 | 
					ea80ab2cae | ||
| 
						 | 
					382e808b8d | ||
| 
						 | 
					846befa7e0 | ||
| 
						 | 
					74dd29f843 | ||
| 
						 | 
					b0473bffcb | ||
| 
						 | 
					24dd9ab1a7 | ||
| 
						 | 
					49d3037e87 | ||
| 
						 | 
					37ad2bd4e8 | ||
| 
						 | 
					7d7b332b02 | ||
| 
						 | 
					ac033b8612 | ||
| 
						 | 
					a7b98dfe25 | ||
| 
						 | 
					7fb7c86c46 | ||
| 
						 | 
					ed036598a9 | ||
| 
						 | 
					160bb70cdf | ||
| 
						 | 
					c2e61f3c21 | ||
| 
						 | 
					18218467f3 | ||
| 
						 | 
					17e298ad2a | ||
| 
						 | 
					d031a374f9 | ||
| 
						 | 
					55f69c98cb | ||
| 
						 | 
					71f2e4306d | ||
| 
						 | 
					f8af23a025 | ||
| 
						 | 
					4ef55a6cd3 | ||
| 
						 | 
					312f866723 | ||
| 
						 | 
					0ebe1f6dec | ||
| 
						 | 
					2ad92e0e6e | ||
| 
						 | 
					ac8823cdcf | ||
| 
						 | 
					77565f7ee4 | ||
| 
						 | 
					d656d90fa8 | ||
| 
						 | 
					175b3b0834 | ||
| 
						 | 
					7477e6b714 | ||
| 
						 | 
					cd6568db69 | ||
| 
						 | 
					6aff325fb2 | ||
| 
						 | 
					0d603cfe9c | ||
| 
						 | 
					34a1f14a17 | ||
| 
						 | 
					efe1c8a070 | ||
| 
						 | 
					1575844344 | ||
| 
						 | 
					221ac1c208 | ||
| 
						 | 
					57442db759 | ||
| 
						 | 
					5fdb3e7cd6 | ||
| 
						 | 
					96f259726c | ||
| 
						 | 
					4936efba5e | ||
| 
						 | 
					d5a3559a2f | ||
| 
						 | 
					114a1c7f52 | ||
| 
						 | 
					ce5265c203 | ||
| 
						 | 
					1a575d926f | ||
| 
						 | 
					85c818a39e | ||
| 
						 | 
					4ffa2defe4 | ||
| 
						 | 
					8825157fbb | ||
| 
						 | 
					966d608dc5 | ||
| 
						 | 
					b808c89471 | ||
| 
						 | 
					75d4e6490f | ||
| 
						 | 
					a82775f544 | ||
| 
						 | 
					6a22ad0171 | ||
| 
						 | 
					c854e88186 | ||
| 
						 | 
					d02203060c | ||
| 
						 | 
					cf703b0433 | ||
| 
						 | 
					c0197a72d3 | ||
| 
						 | 
					e5a543e283 | ||
| 
						 | 
					b8b029b7d3 | ||
| 
						 | 
					370f368b1a | ||
| 
						 | 
					8288b45b4f | ||
| 
						 | 
					fe529faf8e | ||
| 
						 | 
					ab931b177d | ||
| 
						 | 
					9aa3465513 | ||
| 
						 | 
					6c70fc1a6c | ||
| 
						 | 
					1ccc39962a | ||
| 
						 | 
					99c941fc85 | ||
| 
						 | 
					19729fdcc2 | ||
| 
						 | 
					02e17998ce | ||
| 
						 | 
					459e00c67a | ||
| 
						 | 
					292f665650 | ||
| 
						 | 
					93bbb79569 | ||
| 
						 | 
					273e724f2b | ||
| 
						 | 
					5d2615c56f | ||
| 
						 | 
					bfaaf21330 | ||
| 
						 | 
					dcb8415b7a | ||
| 
						 | 
					699e1c75ce | ||
| 
						 | 
					465b6e613e | ||
| 
						 | 
					05fa105855 | ||
| 
						 | 
					d7a0cdebe5 | ||
| 
						 | 
					b049ab31eb | 
							
								
								
									
										22
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								Makefile.in
									
									
									
									
									
								
							@@ -24,8 +24,13 @@ endif
 | 
			
		||||
 | 
			
		||||
SUBDIRS += lib tools daemons
 | 
			
		||||
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
  SUBDIRS += dmeventd
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
  SUBDIRS += daemons/clvmd \
 | 
			
		||||
	     dmeventd \
 | 
			
		||||
	     lib/format1 \
 | 
			
		||||
	     lib/format_pool \
 | 
			
		||||
	     lib/locking \
 | 
			
		||||
@@ -33,6 +38,7 @@ ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
	     lib/snapshot \
 | 
			
		||||
	     po \
 | 
			
		||||
	     test/mm test/device test/format1 test/regex test/filters
 | 
			
		||||
  DISTCLEAN_TARGETS += lib/misc/configure.h
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include make.tmpl
 | 
			
		||||
@@ -40,13 +46,25 @@ include make.tmpl
 | 
			
		||||
daemons: lib
 | 
			
		||||
lib: include
 | 
			
		||||
tools: lib
 | 
			
		||||
po: tools daemons
 | 
			
		||||
dmeventd: tools
 | 
			
		||||
po: tools daemons dmeventd
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
lib.pofile: include.pofile
 | 
			
		||||
tools.pofile: lib.pofile
 | 
			
		||||
daemons.pofile: lib.pofile
 | 
			
		||||
po.pofile: tools.pofile daemons.pofile
 | 
			
		||||
dmeventd.pofile: tools.pofile
 | 
			
		||||
po.pofile: tools.pofile daemons.pofile dmeventd.pofile
 | 
			
		||||
pofile: po.pofile
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@CFLOW_CMD@", "")
 | 
			
		||||
tools.cflow: lib.cflow
 | 
			
		||||
cflow: tools.cflow
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@CSCOPE_CMD@", "")
 | 
			
		||||
cscope.out: tools
 | 
			
		||||
	@CSCOPE_CMD@ -b -R
 | 
			
		||||
all: cscope.out
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										186
									
								
								WHATS_NEW
									
									
									
									
									
								
							
							
						
						
									
										186
									
								
								WHATS_NEW
									
									
									
									
									
								
							@@ -1,5 +1,189 @@
 | 
			
		||||
Version 2.02.01 -
 | 
			
		||||
Version 2.02.11 -  
 | 
			
		||||
=====================================
 | 
			
		||||
  Add clvmd function to return the cluster name. not used by LVM yet.
 | 
			
		||||
  Add cling allocation policy.
 | 
			
		||||
  Change _check_contiguous() to use _for_each_pv().
 | 
			
		||||
  Extend _for_each_pv() to allow termination without error.
 | 
			
		||||
  Abstract _is_contiguous().
 | 
			
		||||
  Remove duplicated pv arg from _check_contiguous().
 | 
			
		||||
  Accept regionsize with lvconvert.
 | 
			
		||||
  Add report columns with underscore before field names ending 'size'.
 | 
			
		||||
  Correct regionsize default on lvcreate man page (MB).
 | 
			
		||||
  Fix clvmd bug that could cause it to die when a node with a long name crashed.
 | 
			
		||||
  Add device size to text metadata.
 | 
			
		||||
  Fix format_text mda_setup pv->size and pv_setup pe_count calculations.
 | 
			
		||||
  Fix _for_each_pv() for mirror with core log.
 | 
			
		||||
  Add lvm_dump.sh script to create a tarball of debugging info from a system.
 | 
			
		||||
  Capture error messages in clvmd and pass them back to the user.
 | 
			
		||||
  Remove unused #defines from filter-md.c.
 | 
			
		||||
  Make clvmd restart init script wait until clvmd has died before starting it.
 | 
			
		||||
  Add -R to clvmd which tells running clvmds to reload their device cache.
 | 
			
		||||
  Add LV column to reports listing kernel modules needed for activation.
 | 
			
		||||
  Show available fields if report given invalid field. (e.g. lvs -o list)
 | 
			
		||||
  Add timestamp functions with --disable-realtime configure option.
 | 
			
		||||
  Add %VG, %LV and %FREE suffices to lvcreate/lvresize --extents arg.
 | 
			
		||||
  Fix two potential NULL pointer derefs in error cases in vg_read().
 | 
			
		||||
  Separate --enable-cluster from locking lib options in lvmconf.sh.
 | 
			
		||||
  Add a missing comma in lvcreate man page.
 | 
			
		||||
 | 
			
		||||
Version 2.02.10 - 19th September 2006
 | 
			
		||||
=====================================
 | 
			
		||||
  Fix lvconvert mirror change case detection logic.
 | 
			
		||||
  Fix mirror log detachment so it correctly becomes a standalone LV.
 | 
			
		||||
  Extend _check_contiguous() to detect single-area LVs.
 | 
			
		||||
  Include mirror log (untested) in _for_each_pv() processing.
 | 
			
		||||
  Use MIRROR_LOG_SIZE constant.
 | 
			
		||||
  Remove struct seg_pvs from _for_each_pv() to generalise.
 | 
			
		||||
  Avoid adding duplicates to list of parallel PVs to avoid.
 | 
			
		||||
  Fix several incorrect comparisons in parallel area avoidance code.
 | 
			
		||||
  Fix segment lengths when flattening existing parallel areas.
 | 
			
		||||
  Log existing parallel areas prior to allocation.
 | 
			
		||||
  Fix mirror log creation when activation disabled.
 | 
			
		||||
  Don't attempt automatic recovery without proper locking.
 | 
			
		||||
  When using local file locking, skip clustered VGs.
 | 
			
		||||
  Add fallback_to_clustered_locking and fallback_to_local_locking parameters.
 | 
			
		||||
  lvm.static uses built-in cluster locking instead of external locking.
 | 
			
		||||
  Don't attempt to load shared libraries if built statically.
 | 
			
		||||
  Change default locking_lib to liblvm2clusterlock.so.
 | 
			
		||||
  Add skip_dev_dir() to process command line VGs.
 | 
			
		||||
  Stop clvmd complaining about nodes that have left the cluster.
 | 
			
		||||
  Move lvm_snprintf(), split_words() and split_dm_name() into libdevmapper.
 | 
			
		||||
  Add lvconvert man page.
 | 
			
		||||
  Add mirror options to man pages.
 | 
			
		||||
  Prevent mirror renames.
 | 
			
		||||
  Move CMDLIB code into separate file and record whether static build.
 | 
			
		||||
 | 
			
		||||
Version 2.02.09 - 17th August 2006
 | 
			
		||||
==================================
 | 
			
		||||
  Fix PE_ALIGN for pagesize over 32KB.
 | 
			
		||||
  Separate out LVM1_PE_ALIGN and pe_align().
 | 
			
		||||
  Add lvm_getpagesize wrapper.
 | 
			
		||||
  Add --maxphysicalvolumes to vgchange.
 | 
			
		||||
 | 
			
		||||
Version 2.02.08 - 15th August 2006
 | 
			
		||||
==================================
 | 
			
		||||
  Add checks for duplicate LV name, lvid and PV id before writing metadata.
 | 
			
		||||
  Report all sanity check failures, not just the first.
 | 
			
		||||
  Fix missing lockfs on first snapshot creation.
 | 
			
		||||
  Add unreliable --trustcache option to reporting commands.
 | 
			
		||||
  Fix locking for mimage removal.
 | 
			
		||||
  Fix clvmd_init_rhel4 'status' exit code.
 | 
			
		||||
 | 
			
		||||
Version 2.02.07 - 17th July 2006
 | 
			
		||||
================================
 | 
			
		||||
  Fix activation logic in lvchange --persistent.
 | 
			
		||||
  Don't ignore persistent minor numbers when activating.
 | 
			
		||||
  Use RTLD_GLOBAL when loading shared libraries.
 | 
			
		||||
  Add some forgotten memlock checks to _vg_read to protect against full scans.
 | 
			
		||||
  Add mutex to dmeventd_mirror to avoid concurrent execution.
 | 
			
		||||
  Fix vgreduce --removemissing to return success if VG is already consistent.
 | 
			
		||||
  Fix return code if VG specified on command line is not found.
 | 
			
		||||
  Fix PV tools to include orphaned PVs in default output again.
 | 
			
		||||
  Fixed unaligned access when using clvm.
 | 
			
		||||
  Fix an extra dev_close in a label_read error path.
 | 
			
		||||
  Append patches to commit emails.
 | 
			
		||||
  Fix target_register_events args.
 | 
			
		||||
  Prevent snapshots of mirrors.
 | 
			
		||||
  Add DISTCLEAN_TARGETS to make template for configure.h.
 | 
			
		||||
  More fixes to error paths.
 | 
			
		||||
  Fix lvcreate corelog validation.
 | 
			
		||||
  Add --config for overriding most config file settings from cmdline.
 | 
			
		||||
  Quote arguments when printing command line.
 | 
			
		||||
  Remove linefeed from 'initialising logging' message.
 | 
			
		||||
  Add 'Completed' debug message.
 | 
			
		||||
  Don't attempt library exit after reloading config files.
 | 
			
		||||
  Always compile with libdevmapper, even if device-mapper is disabled.
 | 
			
		||||
 | 
			
		||||
Version 2.02.06 - 12th May 2006
 | 
			
		||||
===============================
 | 
			
		||||
  Propagate --monitor around cluster.
 | 
			
		||||
  Add --monitor to vgcreate and lvcreate to control dmeventd registration.
 | 
			
		||||
  Filter LCK_NONBLOCK in clvmd lock_vg.
 | 
			
		||||
  Add --nosync to lvcreate with LV flag NOTSYNCED.
 | 
			
		||||
  Use mirror's uuid for a core log.
 | 
			
		||||
  Add mirror log fault-handling policy.
 | 
			
		||||
  Improve mirror warning messages and tidy dmeventd syslog output.
 | 
			
		||||
  Propagate nosync flag around cluster.
 | 
			
		||||
  Allow vgreduce to handle mirror log failures.
 | 
			
		||||
  Add --corelog to lvcreate and lvconvert.
 | 
			
		||||
  Create a log header for replacement in-sync mirror log.
 | 
			
		||||
  Use set_lv() and dev_set() to wipe sections of devices.
 | 
			
		||||
  Add mirror_in_sync() flag to avoid unnecessary resync on activation.
 | 
			
		||||
  Add mirror_library description to example.conf.
 | 
			
		||||
  Fix uuid_from_num() buffer overrun.
 | 
			
		||||
  Make SIZE_SHORT the default for display_size().
 | 
			
		||||
  Fix some memory leaks in error paths found by coverity.
 | 
			
		||||
  Use C99 struct initialisers.
 | 
			
		||||
  Move DEFS into configure.h.
 | 
			
		||||
  Clean-ups to remove miscellaneous compiler warnings.
 | 
			
		||||
  Improve stripe size validation.
 | 
			
		||||
  Increase maximum stripe size limit to physical extent size for lvm2 metadata.
 | 
			
		||||
  Fix activation code to check for pre-existing mirror logs.
 | 
			
		||||
  Tighten region size validation.
 | 
			
		||||
  Ignore empty strings in config files.
 | 
			
		||||
  Require non-zero regionsize and document parameter on lvcreate man page.
 | 
			
		||||
  Invalidate cache if composition of VG changed externally.
 | 
			
		||||
 | 
			
		||||
Version 2.02.05 - 21st April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  Fix vgid string termination in recent cache code.
 | 
			
		||||
 | 
			
		||||
Version 2.02.04 - 19th April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  Check for libsepol.
 | 
			
		||||
  Add some cflow & scope support.
 | 
			
		||||
  Separate out DEFS from CFLAGS.
 | 
			
		||||
  Remove inlines and use unique function names.
 | 
			
		||||
 | 
			
		||||
Version 2.02.03 - 14th April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  vgrename accepts vgid and exported VG.
 | 
			
		||||
  Add --partial to pvs.
 | 
			
		||||
  When choosing between identically-named VGs, also consider creation_host.
 | 
			
		||||
  Provide total log suppression with 2.
 | 
			
		||||
  Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
 | 
			
		||||
  Add vgid to struct physical_volume and pass with vg_name to some functions.
 | 
			
		||||
  If two or more VGs are found with the same name, use one that is not exported.
 | 
			
		||||
  Whenever vgname is captured, also capture vgid and whether exported.
 | 
			
		||||
  Remove an incorrect unlock_vg() from process_each_lv().
 | 
			
		||||
  Update extent size information in vgchange and vgcreate man pages.
 | 
			
		||||
  Introduce origin_from_cow() and lv_is_visible().
 | 
			
		||||
  pvremove without -f now fails if there's no PV label.
 | 
			
		||||
  Support lvconvert -s.
 | 
			
		||||
  Suppress locking library load failure message if --ignorelockingfailure.
 | 
			
		||||
  Propagate partial mode around cluster.
 | 
			
		||||
  Fix archive file expiration.
 | 
			
		||||
  Fix dmeventd build.
 | 
			
		||||
  clvmd now uses libcman rather than cman ioctls.
 | 
			
		||||
  clvmd will allow new cman to shutdown on request.
 | 
			
		||||
 | 
			
		||||
Version 2.02.02 - 7th February 2006
 | 
			
		||||
===================================
 | 
			
		||||
  Add %.so: %.a make template rule.
 | 
			
		||||
  Switchover library building to use LIB_SUFFIX.
 | 
			
		||||
  Only do lockfs filesystem sync when suspending snapshots.
 | 
			
		||||
  Always print warning if activation is disabled.
 | 
			
		||||
  vgreduce removes mirror images.
 | 
			
		||||
  Add --mirrorsonly to vgreduce.
 | 
			
		||||
  vgreduce replaces active LVs with error segment before removing them.
 | 
			
		||||
  Set block_on_error parameter if available.
 | 
			
		||||
  Add target_version.
 | 
			
		||||
  Add details to format1 'Invalid LV in extent map' error message.
 | 
			
		||||
  Fix lvscan snapshot full display.
 | 
			
		||||
  Bring lvdisplay man page example into line.
 | 
			
		||||
  Add mirror dmeventd library.
 | 
			
		||||
  Add some activation logic to remove_mirror_images().
 | 
			
		||||
  lvconvert can remove specified PVs from a mirror.
 | 
			
		||||
  lvconvert turns an existing LV into a mirror.
 | 
			
		||||
  Allow signed mirrors arguments.
 | 
			
		||||
  Move create_mirror_log() into toollib.
 | 
			
		||||
  Determine parallel PVs to avoid with ALLOC_NORMAL allocation.
 | 
			
		||||
  Fix lv_empty.
 | 
			
		||||
 | 
			
		||||
Version 2.02.01 - 23rd November 2005
 | 
			
		||||
====================================
 | 
			
		||||
  Fix lvdisplay cmdline to accept snapshots.
 | 
			
		||||
  Fix open RO->RW promotion.
 | 
			
		||||
  Fix missing vg_revert in lvcreate error path.
 | 
			
		||||
 | 
			
		||||
Version 2.02.00 - 10th November 2005
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							@@ -1,5 +1,81 @@
 | 
			
		||||
Version 1.02.01 - 
 | 
			
		||||
Version 1.02.11 -  
 | 
			
		||||
=============================
 | 
			
		||||
  Add suspend noflush support.
 | 
			
		||||
  Add basic dmsetup loop support.
 | 
			
		||||
 | 
			
		||||
Version 1.02.10 - 19 Sep 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
 | 
			
		||||
  Reorder mm bounds_check code to reduce window for a dmeventd race.
 | 
			
		||||
 | 
			
		||||
Version 1.02.09 - 15 Aug 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Add --table argument to dmsetup for a one-line table.
 | 
			
		||||
  Abort if errors are found during cmdline option processing.
 | 
			
		||||
  Add lockfs indicator to debug output.
 | 
			
		||||
 | 
			
		||||
Version 1.02.08 - 17 July 2006
 | 
			
		||||
==============================
 | 
			
		||||
  Append full patch to check in emails.
 | 
			
		||||
  Avoid duplicate dmeventd subdir with 'make distclean'.
 | 
			
		||||
  Update dmsetup man page.
 | 
			
		||||
  Add --force to dmsetup remove* to load error target.
 | 
			
		||||
  dmsetup remove_all also performs mknodes.
 | 
			
		||||
  Don't suppress identical table reloads if permission changes.
 | 
			
		||||
  Fix corelog segment line.
 | 
			
		||||
  Suppress some compiler warnings.
 | 
			
		||||
 | 
			
		||||
Version 1.02.07 - 11 May 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
 | 
			
		||||
  Avoid a dmeventd compiler warning.
 | 
			
		||||
 | 
			
		||||
Version 1.02.06 - 10 May 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Move DEFS into configure.h.
 | 
			
		||||
  Fix leaks in error paths found by coverity.
 | 
			
		||||
  Remove dmsetup line buffer limitation.
 | 
			
		||||
 | 
			
		||||
Version 1.02.05 - 19 Apr 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Separate install_include target in makefiles.
 | 
			
		||||
  Separate out DEFS from CFLAGS.
 | 
			
		||||
  Support pkg-config.
 | 
			
		||||
  Check for libsepol.
 | 
			
		||||
 | 
			
		||||
Version 1.02.04 - 14 Apr 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Bring dmsetup man page up-to-date.
 | 
			
		||||
  Use name-based device refs if kernel doesn't support device number refs.
 | 
			
		||||
  Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
 | 
			
		||||
  If _create_and_load_v4 fails part way through, revert the creation.
 | 
			
		||||
  dmeventd thread/fifo fixes.
 | 
			
		||||
  Add file & line to dm_strdup_aux().
 | 
			
		||||
  Add setgeometry.
 | 
			
		||||
 | 
			
		||||
Version 1.02.03 - 7 Feb 2006
 | 
			
		||||
============================
 | 
			
		||||
  Add exported functions to set uid, gid and mode.
 | 
			
		||||
  Rename _log to dm_log and export.
 | 
			
		||||
  Add dm_tree_skip_lockfs.
 | 
			
		||||
  Fix dm_strdup debug definition.
 | 
			
		||||
  Fix hash function to avoid using a negative array offset.
 | 
			
		||||
  Don't inline _find in hash.c and tidy signed/unsigned etc.
 | 
			
		||||
  Fix libdevmapper.h #endif.
 | 
			
		||||
  Fix dmsetup version driver version.
 | 
			
		||||
  Add sync, nosync and block_on_error mirror log parameters.
 | 
			
		||||
  Add hweight32.
 | 
			
		||||
  Fix dmeventd build.
 | 
			
		||||
 | 
			
		||||
Version 1.02.02 - 2 Dec 2005
 | 
			
		||||
============================
 | 
			
		||||
  dmeventd added.
 | 
			
		||||
  Export dm_task_update_nodes.
 | 
			
		||||
  Use names instead of numbers in messages when ioctls fail.
 | 
			
		||||
 | 
			
		||||
Version 1.02.01 - 23 Nov 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Resume snapshot-origins last.
 | 
			
		||||
  Drop leading zeros from dm_format_dev.
 | 
			
		||||
  Suppress attempt to reload identical table.
 | 
			
		||||
  Additional LVM- prefix matching for transitional period.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										673
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										673
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@@ -310,7 +310,7 @@ ac_includes_default="\
 | 
			
		||||
#endif"
 | 
			
		||||
 | 
			
		||||
ac_default_prefix=/usr
 | 
			
		||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM LTLIBOBJS'
 | 
			
		||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CFLOW_CMD CSCOPE_CMD CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS LIB_SUFFIX LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX HAVE_REALTIME CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM DMEVENTD LTLIBOBJS'
 | 
			
		||||
ac_subst_files=''
 | 
			
		||||
 | 
			
		||||
# Initialize some variables set by options.
 | 
			
		||||
@@ -853,11 +853,13 @@ Optional Features:
 | 
			
		||||
                          statically.  Default is dynamic linking
 | 
			
		||||
  --enable-readline       Enable readline support
 | 
			
		||||
  --disable-selinux       Disable selinux support
 | 
			
		||||
  --disable-realtime       Disable realtime clock support
 | 
			
		||||
  --enable-debug          Enable debugging
 | 
			
		||||
  --disable-devmapper     Disable device-mapper interaction
 | 
			
		||||
  --disable-o_direct      Disable O_DIRECT
 | 
			
		||||
  --enable-cmdlib         Build shared command library
 | 
			
		||||
  --enable-fsadm          Enable fsadm
 | 
			
		||||
  --enable-dmeventd       Enable the device-mapper event daemon
 | 
			
		||||
  --enable-nls            Enable Native Language Support
 | 
			
		||||
 | 
			
		||||
Optional Packages:
 | 
			
		||||
@@ -1330,6 +1332,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
          ac_config_headers="$ac_config_headers lib/misc/configure.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
ac_aux_dir=
 | 
			
		||||
for ac_dir in autoconf $srcdir/autoconf; do
 | 
			
		||||
@@ -1450,10 +1456,11 @@ case "$host_os" in
 | 
			
		||||
		CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
 | 
			
		||||
		LDDEPS="$LDDEPS .export.sym"
 | 
			
		||||
		LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
 | 
			
		||||
		SOFLAG="-shared"
 | 
			
		||||
		LIB_SUFFIX="so"
 | 
			
		||||
		DEVMAPPER=yes
 | 
			
		||||
		ODIRECT=yes
 | 
			
		||||
		SELINUX=yes
 | 
			
		||||
		REALTIME=yes
 | 
			
		||||
		CLUSTER=internal
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
	darwin*)
 | 
			
		||||
@@ -1464,10 +1471,11 @@ case "$host_os" in
 | 
			
		||||
		CLDNOWHOLEARCHIVE=
 | 
			
		||||
		LDDEPS="$LDDEPS"
 | 
			
		||||
		LDFLAGS="$LDFLAGS"
 | 
			
		||||
		SOFLAG="-dynamiclib"
 | 
			
		||||
		LIB_SUFFIX="dylib"
 | 
			
		||||
		DEVMAPPER=yes
 | 
			
		||||
		ODIRECT=no
 | 
			
		||||
		SELINUX=no
 | 
			
		||||
		REALTIME=no
 | 
			
		||||
		CLUSTER=none
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
esac
 | 
			
		||||
@@ -2642,6 +2650,84 @@ else
 | 
			
		||||
  RANLIB="$ac_cv_prog_RANLIB"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Extract the first word of "cflow", so it can be a program name with args.
 | 
			
		||||
set dummy cflow; ac_word=$2
 | 
			
		||||
echo "$as_me:$LINENO: checking for $ac_word" >&5
 | 
			
		||||
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 | 
			
		||||
if test "${ac_cv_path_CFLOW_CMD+set}" = set; then
 | 
			
		||||
  echo $ECHO_N "(cached) $ECHO_C" >&6
 | 
			
		||||
else
 | 
			
		||||
  case $CFLOW_CMD in
 | 
			
		||||
  [\\/]* | ?:[\\/]*)
 | 
			
		||||
  ac_cv_path_CFLOW_CMD="$CFLOW_CMD" # Let the user override the test with a path.
 | 
			
		||||
  ;;
 | 
			
		||||
  *)
 | 
			
		||||
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 | 
			
		||||
for as_dir in $PATH
 | 
			
		||||
do
 | 
			
		||||
  IFS=$as_save_IFS
 | 
			
		||||
  test -z "$as_dir" && as_dir=.
 | 
			
		||||
  for ac_exec_ext in '' $ac_executable_extensions; do
 | 
			
		||||
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
 | 
			
		||||
    ac_cv_path_CFLOW_CMD="$as_dir/$ac_word$ac_exec_ext"
 | 
			
		||||
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
 | 
			
		||||
    break 2
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
  ;;
 | 
			
		||||
esac
 | 
			
		||||
fi
 | 
			
		||||
CFLOW_CMD=$ac_cv_path_CFLOW_CMD
 | 
			
		||||
 | 
			
		||||
if test -n "$CFLOW_CMD"; then
 | 
			
		||||
  echo "$as_me:$LINENO: result: $CFLOW_CMD" >&5
 | 
			
		||||
echo "${ECHO_T}$CFLOW_CMD" >&6
 | 
			
		||||
else
 | 
			
		||||
  echo "$as_me:$LINENO: result: no" >&5
 | 
			
		||||
echo "${ECHO_T}no" >&6
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Extract the first word of "cscope", so it can be a program name with args.
 | 
			
		||||
set dummy cscope; ac_word=$2
 | 
			
		||||
echo "$as_me:$LINENO: checking for $ac_word" >&5
 | 
			
		||||
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 | 
			
		||||
if test "${ac_cv_path_CSCOPE_CMD+set}" = set; then
 | 
			
		||||
  echo $ECHO_N "(cached) $ECHO_C" >&6
 | 
			
		||||
else
 | 
			
		||||
  case $CSCOPE_CMD in
 | 
			
		||||
  [\\/]* | ?:[\\/]*)
 | 
			
		||||
  ac_cv_path_CSCOPE_CMD="$CSCOPE_CMD" # Let the user override the test with a path.
 | 
			
		||||
  ;;
 | 
			
		||||
  *)
 | 
			
		||||
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 | 
			
		||||
for as_dir in $PATH
 | 
			
		||||
do
 | 
			
		||||
  IFS=$as_save_IFS
 | 
			
		||||
  test -z "$as_dir" && as_dir=.
 | 
			
		||||
  for ac_exec_ext in '' $ac_executable_extensions; do
 | 
			
		||||
  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
 | 
			
		||||
    ac_cv_path_CSCOPE_CMD="$as_dir/$ac_word$ac_exec_ext"
 | 
			
		||||
    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
 | 
			
		||||
    break 2
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
  ;;
 | 
			
		||||
esac
 | 
			
		||||
fi
 | 
			
		||||
CSCOPE_CMD=$ac_cv_path_CSCOPE_CMD
 | 
			
		||||
 | 
			
		||||
if test -n "$CSCOPE_CMD"; then
 | 
			
		||||
  echo "$as_me:$LINENO: result: $CSCOPE_CMD" >&5
 | 
			
		||||
echo "${ECHO_T}$CSCOPE_CMD" >&6
 | 
			
		||||
else
 | 
			
		||||
  echo "$as_me:$LINENO: result: no" >&5
 | 
			
		||||
echo "${ECHO_T}no" >&6
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
@@ -7148,7 +7234,11 @@ echo "$as_me:$LINENO: result: $LVM1_FALLBACK" >&5
 | 
			
		||||
echo "${ECHO_T}$LVM1_FALLBACK" >&6
 | 
			
		||||
 | 
			
		||||
if test x$LVM1_FALLBACK = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DLVM1_FALLBACK"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define LVM1_FALLBACK 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7174,7 +7264,11 @@ echo "$as_me: error: --with-lvm1 parameter invalid
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$LVM1 = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DLVM1_INTERNAL"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define LVM1_INTERNAL 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7200,7 +7294,11 @@ echo "$as_me: error: --with-pool parameter invalid
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$POOL = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DPOOL_INTERNAL"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define POOL_INTERNAL 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7224,7 +7322,11 @@ echo "$as_me: error: --with-cluster parameter invalid
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$CLUSTER = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define CLUSTER_LOCKING_INTERNAL 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7250,7 +7352,11 @@ echo "$as_me: error: --with-snapshots parameter invalid
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$SNAPSHOTS = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define SNAPSHOT_INTERNAL 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7276,7 +7382,11 @@ echo "$as_me: error: --with-mirrors parameter invalid
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$MIRRORS = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define MIRRORED_INTERNAL 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7306,7 +7416,11 @@ echo "$as_me:$LINENO: result: $READLINE" >&5
 | 
			
		||||
echo "${ECHO_T}$READLINE" >&6
 | 
			
		||||
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define READLINE_SUPPORT 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7320,6 +7434,17 @@ fi;
 | 
			
		||||
echo "$as_me:$LINENO: result: $SELINUX" >&5
 | 
			
		||||
echo "${ECHO_T}$SELINUX" >&6
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
echo "$as_me:$LINENO: checking whether to enable realtime support" >&5
 | 
			
		||||
echo $ECHO_N "checking whether to enable realtime support... $ECHO_C" >&6
 | 
			
		||||
# Check whether --enable-realtime or --disable-realtime was given.
 | 
			
		||||
if test "${enable_realtime+set}" = set; then
 | 
			
		||||
  enableval="$enable_realtime"
 | 
			
		||||
  REALTIME=$enableval
 | 
			
		||||
fi;
 | 
			
		||||
echo "$as_me:$LINENO: result: $REALTIME" >&5
 | 
			
		||||
echo "${ECHO_T}$REALTIME" >&6
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
echo "$as_me:$LINENO: checking whether to build cluster LVM daemon" >&5
 | 
			
		||||
echo $ECHO_N "checking whether to build cluster LVM daemon... $ECHO_C" >&6
 | 
			
		||||
@@ -7356,6 +7481,8 @@ echo "${ECHO_T}$DEBUG" >&6
 | 
			
		||||
 | 
			
		||||
if test x$DEBUG = xyes; then
 | 
			
		||||
	COPTIMISE_FLAG=
 | 
			
		||||
else
 | 
			
		||||
	CSCOPE_CMD=
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7382,7 +7509,11 @@ echo "$as_me:$LINENO: result: $DEVMAPPER" >&5
 | 
			
		||||
echo "${ECHO_T}$DEVMAPPER" >&6
 | 
			
		||||
 | 
			
		||||
if test x$DEVMAPPER = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define DEVMAPPER_SUPPORT 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7397,7 +7528,11 @@ echo "$as_me:$LINENO: result: $ODIRECT" >&5
 | 
			
		||||
echo "${ECHO_T}$ODIRECT" >&6
 | 
			
		||||
 | 
			
		||||
if test x$ODIRECT = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define O_DIRECT_SUPPORT 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -7413,10 +7548,6 @@ fi;
 | 
			
		||||
echo "$as_me:$LINENO: result: $CMDLIB" >&5
 | 
			
		||||
echo "${ECHO_T}$CMDLIB" >&6
 | 
			
		||||
 | 
			
		||||
if test x$CMDLIB = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DCMDLIB"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
echo "$as_me:$LINENO: checking whether to build fsadm" >&5
 | 
			
		||||
echo $ECHO_N "checking whether to build fsadm... $ECHO_C" >&6
 | 
			
		||||
@@ -7428,6 +7559,32 @@ fi;
 | 
			
		||||
echo "$as_me:$LINENO: result: $FSADM" >&5
 | 
			
		||||
echo "${ECHO_T}$FSADM" >&6
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
echo "$as_me:$LINENO: checking whether to use dmeventd" >&5
 | 
			
		||||
echo $ECHO_N "checking whether to use dmeventd... $ECHO_C" >&6
 | 
			
		||||
# Check whether --enable-dmeventd or --disable-dmeventd was given.
 | 
			
		||||
if test "${enable_dmeventd+set}" = set; then
 | 
			
		||||
  enableval="$enable_dmeventd"
 | 
			
		||||
  DMEVENTD=$enableval
 | 
			
		||||
fi;
 | 
			
		||||
echo "$as_me:$LINENO: result: $DMEVENTD" >&5
 | 
			
		||||
echo "${ECHO_T}$DMEVENTD" >&6
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
 | 
			
		||||
{ { echo "$as_me:$LINENO: error: --enable-dmeventd currently requires --with-mirrors=internal
 | 
			
		||||
" >&5
 | 
			
		||||
echo "$as_me: error: --enable-dmeventd currently requires --with-mirrors=internal
 | 
			
		||||
" >&2;}
 | 
			
		||||
   { (exit 1); exit 1; }; }
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD = xyes; then
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define DMEVENTD 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
################################################################################
 | 
			
		||||
if [ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ];
 | 
			
		||||
 then  exec_prefix="";
 | 
			
		||||
@@ -8087,7 +8244,11 @@ fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if [ "x$HAVE_LIBDL" = xyes ]; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DHAVE_LIBDL"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define HAVE_LIBDL 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
	LIBS="-ldl $LIBS"
 | 
			
		||||
else
 | 
			
		||||
	HAVE_LIBDL=no
 | 
			
		||||
@@ -8106,6 +8267,85 @@ fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
if test x$SELINUX = xyes; then
 | 
			
		||||
	echo "$as_me:$LINENO: checking for sepol_check_context function" >&5
 | 
			
		||||
echo $ECHO_N "checking for sepol_check_context function... $ECHO_C" >&6
 | 
			
		||||
	echo "$as_me:$LINENO: checking for sepol_check_context in -lsepol" >&5
 | 
			
		||||
echo $ECHO_N "checking for sepol_check_context in -lsepol... $ECHO_C" >&6
 | 
			
		||||
if test "${ac_cv_lib_sepol_sepol_check_context+set}" = set; then
 | 
			
		||||
  echo $ECHO_N "(cached) $ECHO_C" >&6
 | 
			
		||||
else
 | 
			
		||||
  ac_check_lib_save_LIBS=$LIBS
 | 
			
		||||
LIBS="-lsepol  $LIBS"
 | 
			
		||||
cat >conftest.$ac_ext <<_ACEOF
 | 
			
		||||
/* confdefs.h.  */
 | 
			
		||||
_ACEOF
 | 
			
		||||
cat confdefs.h >>conftest.$ac_ext
 | 
			
		||||
cat >>conftest.$ac_ext <<_ACEOF
 | 
			
		||||
/* end confdefs.h.  */
 | 
			
		||||
 | 
			
		||||
/* Override any gcc2 internal prototype to avoid an error.  */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
/* We use char because int might match the return type of a gcc2
 | 
			
		||||
   builtin and then its argument prototype would still apply.  */
 | 
			
		||||
char sepol_check_context ();
 | 
			
		||||
int
 | 
			
		||||
main ()
 | 
			
		||||
{
 | 
			
		||||
sepol_check_context ();
 | 
			
		||||
  ;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
_ACEOF
 | 
			
		||||
rm -f conftest.$ac_objext conftest$ac_exeext
 | 
			
		||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
 | 
			
		||||
  (eval $ac_link) 2>conftest.er1
 | 
			
		||||
  ac_status=$?
 | 
			
		||||
  grep -v '^ *+' conftest.er1 >conftest.err
 | 
			
		||||
  rm -f conftest.er1
 | 
			
		||||
  cat conftest.err >&5
 | 
			
		||||
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
 | 
			
		||||
  (exit $ac_status); } &&
 | 
			
		||||
	 { ac_try='test -z "$ac_c_werror_flag"
 | 
			
		||||
			 || test ! -s conftest.err'
 | 
			
		||||
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
 | 
			
		||||
  (eval $ac_try) 2>&5
 | 
			
		||||
  ac_status=$?
 | 
			
		||||
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
 | 
			
		||||
  (exit $ac_status); }; } &&
 | 
			
		||||
	 { ac_try='test -s conftest$ac_exeext'
 | 
			
		||||
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
 | 
			
		||||
  (eval $ac_try) 2>&5
 | 
			
		||||
  ac_status=$?
 | 
			
		||||
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
 | 
			
		||||
  (exit $ac_status); }; }; then
 | 
			
		||||
  ac_cv_lib_sepol_sepol_check_context=yes
 | 
			
		||||
else
 | 
			
		||||
  echo "$as_me: failed program was:" >&5
 | 
			
		||||
sed 's/^/| /' conftest.$ac_ext >&5
 | 
			
		||||
 | 
			
		||||
ac_cv_lib_sepol_sepol_check_context=no
 | 
			
		||||
fi
 | 
			
		||||
rm -f conftest.err conftest.$ac_objext \
 | 
			
		||||
      conftest$ac_exeext conftest.$ac_ext
 | 
			
		||||
LIBS=$ac_check_lib_save_LIBS
 | 
			
		||||
fi
 | 
			
		||||
echo "$as_me:$LINENO: result: $ac_cv_lib_sepol_sepol_check_context" >&5
 | 
			
		||||
echo "${ECHO_T}$ac_cv_lib_sepol_sepol_check_context" >&6
 | 
			
		||||
if test $ac_cv_lib_sepol_sepol_check_context = yes; then
 | 
			
		||||
  HAVE_SEPOL=yes
 | 
			
		||||
else
 | 
			
		||||
  HAVE_SEPOL=no
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
	echo "$as_me:$LINENO: result: $HAVE_SEPOL" >&5
 | 
			
		||||
echo "${ECHO_T}$HAVE_SEPOL" >&6
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_SEPOL = xyes; then
 | 
			
		||||
		LIBS="-lsepol $LIBS"
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	echo "$as_me:$LINENO: checking for is_selinux_enabled function" >&5
 | 
			
		||||
echo $ECHO_N "checking for is_selinux_enabled function... $ECHO_C" >&6
 | 
			
		||||
	echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5
 | 
			
		||||
@@ -8182,7 +8422,11 @@ fi
 | 
			
		||||
echo "${ECHO_T}$HAVE_SELINUX" >&6
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
		CFLAGS="$CFLAGS -DHAVE_SELINUX"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define HAVE_SELINUX 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
		LIBS="-lselinux $LIBS"
 | 
			
		||||
	else
 | 
			
		||||
		{ echo "$as_me:$LINENO: WARNING: Disabling selinux" >&5
 | 
			
		||||
@@ -8190,6 +8434,96 @@ echo "$as_me: WARNING: Disabling selinux" >&2;}
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
if test x$REALTIME = xyes; then
 | 
			
		||||
	echo "$as_me:$LINENO: checking for clock_gettime function" >&5
 | 
			
		||||
echo $ECHO_N "checking for clock_gettime function... $ECHO_C" >&6
 | 
			
		||||
	echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5
 | 
			
		||||
echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6
 | 
			
		||||
if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then
 | 
			
		||||
  echo $ECHO_N "(cached) $ECHO_C" >&6
 | 
			
		||||
else
 | 
			
		||||
  ac_check_lib_save_LIBS=$LIBS
 | 
			
		||||
LIBS="-lrt  $LIBS"
 | 
			
		||||
cat >conftest.$ac_ext <<_ACEOF
 | 
			
		||||
/* confdefs.h.  */
 | 
			
		||||
_ACEOF
 | 
			
		||||
cat confdefs.h >>conftest.$ac_ext
 | 
			
		||||
cat >>conftest.$ac_ext <<_ACEOF
 | 
			
		||||
/* end confdefs.h.  */
 | 
			
		||||
 | 
			
		||||
/* Override any gcc2 internal prototype to avoid an error.  */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
/* We use char because int might match the return type of a gcc2
 | 
			
		||||
   builtin and then its argument prototype would still apply.  */
 | 
			
		||||
char clock_gettime ();
 | 
			
		||||
int
 | 
			
		||||
main ()
 | 
			
		||||
{
 | 
			
		||||
clock_gettime ();
 | 
			
		||||
  ;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
_ACEOF
 | 
			
		||||
rm -f conftest.$ac_objext conftest$ac_exeext
 | 
			
		||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
 | 
			
		||||
  (eval $ac_link) 2>conftest.er1
 | 
			
		||||
  ac_status=$?
 | 
			
		||||
  grep -v '^ *+' conftest.er1 >conftest.err
 | 
			
		||||
  rm -f conftest.er1
 | 
			
		||||
  cat conftest.err >&5
 | 
			
		||||
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
 | 
			
		||||
  (exit $ac_status); } &&
 | 
			
		||||
	 { ac_try='test -z "$ac_c_werror_flag"
 | 
			
		||||
			 || test ! -s conftest.err'
 | 
			
		||||
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
 | 
			
		||||
  (eval $ac_try) 2>&5
 | 
			
		||||
  ac_status=$?
 | 
			
		||||
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
 | 
			
		||||
  (exit $ac_status); }; } &&
 | 
			
		||||
	 { ac_try='test -s conftest$ac_exeext'
 | 
			
		||||
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
 | 
			
		||||
  (eval $ac_try) 2>&5
 | 
			
		||||
  ac_status=$?
 | 
			
		||||
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
 | 
			
		||||
  (exit $ac_status); }; }; then
 | 
			
		||||
  ac_cv_lib_rt_clock_gettime=yes
 | 
			
		||||
else
 | 
			
		||||
  echo "$as_me: failed program was:" >&5
 | 
			
		||||
sed 's/^/| /' conftest.$ac_ext >&5
 | 
			
		||||
 | 
			
		||||
ac_cv_lib_rt_clock_gettime=no
 | 
			
		||||
fi
 | 
			
		||||
rm -f conftest.err conftest.$ac_objext \
 | 
			
		||||
      conftest$ac_exeext conftest.$ac_ext
 | 
			
		||||
LIBS=$ac_check_lib_save_LIBS
 | 
			
		||||
fi
 | 
			
		||||
echo "$as_me:$LINENO: result: $ac_cv_lib_rt_clock_gettime" >&5
 | 
			
		||||
echo "${ECHO_T}$ac_cv_lib_rt_clock_gettime" >&6
 | 
			
		||||
if test $ac_cv_lib_rt_clock_gettime = yes; then
 | 
			
		||||
  HAVE_REALTIME=yes
 | 
			
		||||
else
 | 
			
		||||
  HAVE_REALTIME=no
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
	echo "$as_me:$LINENO: result: $HAVE_REALTIME" >&5
 | 
			
		||||
echo "${ECHO_T}$HAVE_REALTIME" >&6
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_REALTIME = xyes; then
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define HAVE_REALTIME 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
		LIBS="-lrt $LIBS"
 | 
			
		||||
	else
 | 
			
		||||
		{ echo "$as_me:$LINENO: WARNING: Disabling realtime clock" >&5
 | 
			
		||||
echo "$as_me: WARNING: Disabling realtime clock" >&2;}
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
for ac_header in getopt.h
 | 
			
		||||
@@ -8336,7 +8670,11 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then
 | 
			
		||||
  cat >>confdefs.h <<_ACEOF
 | 
			
		||||
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 CFLAGS="$CFLAGS -DHAVE_GETOPTLONG"
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define HAVE_GETOPTLONG 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
done
 | 
			
		||||
@@ -8526,9 +8864,12 @@ fi
 | 
			
		||||
echo "$as_me:$LINENO: result: $ac_cv_func_rl_completion_matches" >&5
 | 
			
		||||
echo "${ECHO_T}$ac_cv_func_rl_completion_matches" >&6
 | 
			
		||||
if test $ac_cv_func_rl_completion_matches = yes; then
 | 
			
		||||
  CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<\_ACEOF
 | 
			
		||||
#define HAVE_RL_COMPLETION_MATCHES 1
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
@@ -10454,7 +10795,6 @@ done
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DEVMAPPER = xyes; then
 | 
			
		||||
 | 
			
		||||
for ac_header in libdevmapper.h
 | 
			
		||||
do
 | 
			
		||||
@@ -10609,7 +10949,6 @@ fi
 | 
			
		||||
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
 | 
			
		||||
@@ -10810,7 +11149,11 @@ fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if test x$MODPROBE_CMD != x; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
 | 
			
		||||
 | 
			
		||||
cat >>confdefs.h <<_ACEOF
 | 
			
		||||
#define MODPROBE_CMD "$MODPROBE_CMD"
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -10850,13 +11193,17 @@ fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
                                                                                                                                                                                                                            ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
 | 
			
		||||
                                                                                                                                                                                                                                                ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
 | 
			
		||||
cat >confcache <<\_ACEOF
 | 
			
		||||
# This file is a shell script that caches the results of configure
 | 
			
		||||
# tests run on this system so they can be shared between configure
 | 
			
		||||
@@ -10931,38 +11278,7 @@ s/^[^=]*=[	 ]*$//;
 | 
			
		||||
}'
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Transform confdefs.h into DEFS.
 | 
			
		||||
# Protect against shell expansion while executing Makefile rules.
 | 
			
		||||
# Protect against Makefile macro expansion.
 | 
			
		||||
#
 | 
			
		||||
# If the first sed substitution is executed (which looks for macros that
 | 
			
		||||
# take arguments), then we branch to the quote section.  Otherwise,
 | 
			
		||||
# look for a macro that doesn't take arguments.
 | 
			
		||||
cat >confdef2opt.sed <<\_ACEOF
 | 
			
		||||
t clear
 | 
			
		||||
: clear
 | 
			
		||||
s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\),-D\1=\2,g
 | 
			
		||||
t quote
 | 
			
		||||
s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\),-D\1=\2,g
 | 
			
		||||
t quote
 | 
			
		||||
d
 | 
			
		||||
: quote
 | 
			
		||||
s,[	 `~#$^&*(){}\\|;'"<>?],\\&,g
 | 
			
		||||
s,\[,\\&,g
 | 
			
		||||
s,\],\\&,g
 | 
			
		||||
s,\$,$$,g
 | 
			
		||||
p
 | 
			
		||||
_ACEOF
 | 
			
		||||
# We use echo to avoid assuming a particular line-breaking character.
 | 
			
		||||
# The extra dot is to prevent the shell from consuming trailing
 | 
			
		||||
# line-breaks from the sub-command output.  A line-break within
 | 
			
		||||
# single-quotes doesn't work because, if this script is created in a
 | 
			
		||||
# platform that uses two characters for line-breaks (e.g., DOS), tr
 | 
			
		||||
# would break.
 | 
			
		||||
ac_LF_and_DOT=`echo; echo .`
 | 
			
		||||
DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
 | 
			
		||||
rm -f confdef2opt.sed
 | 
			
		||||
 | 
			
		||||
DEFS=-DHAVE_CONFIG_H
 | 
			
		||||
 | 
			
		||||
ac_libobjs=
 | 
			
		||||
ac_ltlibobjs=
 | 
			
		||||
@@ -11296,10 +11612,15 @@ Usage: $0 [OPTIONS] [FILE]...
 | 
			
		||||
      --recheck    update $as_me by reconfiguring in the same conditions
 | 
			
		||||
  --file=FILE[:TEMPLATE]
 | 
			
		||||
		   instantiate the configuration file FILE
 | 
			
		||||
  --header=FILE[:TEMPLATE]
 | 
			
		||||
		   instantiate the configuration header FILE
 | 
			
		||||
 | 
			
		||||
Configuration files:
 | 
			
		||||
$config_files
 | 
			
		||||
 | 
			
		||||
Configuration headers:
 | 
			
		||||
$config_headers
 | 
			
		||||
 | 
			
		||||
Report bugs to <bug-autoconf@gnu.org>."
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
@@ -11412,6 +11733,8 @@ do
 | 
			
		||||
  "make.tmpl" ) CONFIG_FILES="$CONFIG_FILES make.tmpl" ;;
 | 
			
		||||
  "daemons/Makefile" ) CONFIG_FILES="$CONFIG_FILES daemons/Makefile" ;;
 | 
			
		||||
  "daemons/clvmd/Makefile" ) CONFIG_FILES="$CONFIG_FILES daemons/clvmd/Makefile" ;;
 | 
			
		||||
  "dmeventd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/Makefile" ;;
 | 
			
		||||
  "dmeventd/mirror/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/mirror/Makefile" ;;
 | 
			
		||||
  "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
 | 
			
		||||
  "include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
 | 
			
		||||
  "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
 | 
			
		||||
@@ -11430,6 +11753,7 @@ do
 | 
			
		||||
  "test/format1/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/format1/Makefile" ;;
 | 
			
		||||
  "test/regex/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/regex/Makefile" ;;
 | 
			
		||||
  "test/filters/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/filters/Makefile" ;;
 | 
			
		||||
  "lib/misc/configure.h" ) CONFIG_HEADERS="$CONFIG_HEADERS lib/misc/configure.h" ;;
 | 
			
		||||
  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
 | 
			
		||||
echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
 | 
			
		||||
   { (exit 1); exit 1; }; };;
 | 
			
		||||
@@ -11442,6 +11766,7 @@ done
 | 
			
		||||
# bizarre bug on SunOS 4.1.3.
 | 
			
		||||
if $ac_need_defaults; then
 | 
			
		||||
  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
 | 
			
		||||
  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Have a temporary directory for convenience.  Make it in the build tree
 | 
			
		||||
@@ -11540,6 +11865,8 @@ s,@LN_S@,$LN_S,;t t
 | 
			
		||||
s,@SET_MAKE@,$SET_MAKE,;t t
 | 
			
		||||
s,@RANLIB@,$RANLIB,;t t
 | 
			
		||||
s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
 | 
			
		||||
s,@CFLOW_CMD@,$CFLOW_CMD,;t t
 | 
			
		||||
s,@CSCOPE_CMD@,$CSCOPE_CMD,;t t
 | 
			
		||||
s,@CPP@,$CPP,;t t
 | 
			
		||||
s,@EGREP@,$EGREP,;t t
 | 
			
		||||
s,@ALLOCA@,$ALLOCA,;t t
 | 
			
		||||
@@ -11560,13 +11887,14 @@ s,@CLDFLAGS@,$CLDFLAGS,;t t
 | 
			
		||||
s,@CLDWHOLEARCHIVE@,$CLDWHOLEARCHIVE,;t t
 | 
			
		||||
s,@CLDNOWHOLEARCHIVE@,$CLDNOWHOLEARCHIVE,;t t
 | 
			
		||||
s,@LDDEPS@,$LDDEPS,;t t
 | 
			
		||||
s,@SOFLAG@,$SOFLAG,;t t
 | 
			
		||||
s,@LIB_SUFFIX@,$LIB_SUFFIX,;t t
 | 
			
		||||
s,@LVM_VERSION@,$LVM_VERSION,;t t
 | 
			
		||||
s,@LVM1_FALLBACK@,$LVM1_FALLBACK,;t t
 | 
			
		||||
s,@DEBUG@,$DEBUG,;t t
 | 
			
		||||
s,@DEVMAPPER@,$DEVMAPPER,;t t
 | 
			
		||||
s,@HAVE_LIBDL@,$HAVE_LIBDL,;t t
 | 
			
		||||
s,@HAVE_SELINUX@,$HAVE_SELINUX,;t t
 | 
			
		||||
s,@HAVE_REALTIME@,$HAVE_REALTIME,;t t
 | 
			
		||||
s,@CMDLIB@,$CMDLIB,;t t
 | 
			
		||||
s,@LOCALEDIR@,$LOCALEDIR,;t t
 | 
			
		||||
s,@CONFDIR@,$CONFDIR,;t t
 | 
			
		||||
@@ -11576,6 +11904,7 @@ s,@INTL@,$INTL,;t t
 | 
			
		||||
s,@CLVMD@,$CLVMD,;t t
 | 
			
		||||
s,@CLUSTER@,$CLUSTER,;t t
 | 
			
		||||
s,@FSADM@,$FSADM,;t t
 | 
			
		||||
s,@DMEVENTD@,$DMEVENTD,;t t
 | 
			
		||||
s,@LTLIBOBJS@,$LTLIBOBJS,;t t
 | 
			
		||||
CEOF
 | 
			
		||||
 | 
			
		||||
@@ -11815,6 +12144,229 @@ s,@INSTALL@,$ac_INSTALL,;t t
 | 
			
		||||
 | 
			
		||||
done
 | 
			
		||||
_ACEOF
 | 
			
		||||
cat >>$CONFIG_STATUS <<\_ACEOF
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# CONFIG_HEADER section.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
 | 
			
		||||
# NAME is the cpp macro being defined and VALUE is the value it is being given.
 | 
			
		||||
#
 | 
			
		||||
# ac_d sets the value in "#define NAME VALUE" lines.
 | 
			
		||||
ac_dA='s,^\([	 ]*\)#\([	 ]*define[	 ][	 ]*\)'
 | 
			
		||||
ac_dB='[	 ].*$,\1#\2'
 | 
			
		||||
ac_dC=' '
 | 
			
		||||
ac_dD=',;t'
 | 
			
		||||
# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
 | 
			
		||||
ac_uA='s,^\([	 ]*\)#\([	 ]*\)undef\([	 ][	 ]*\)'
 | 
			
		||||
ac_uB='$,\1#\2define\3'
 | 
			
		||||
ac_uC=' '
 | 
			
		||||
ac_uD=',;t'
 | 
			
		||||
 | 
			
		||||
for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
 | 
			
		||||
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
 | 
			
		||||
  case $ac_file in
 | 
			
		||||
  - | *:- | *:-:* ) # input from stdin
 | 
			
		||||
	cat >$tmp/stdin
 | 
			
		||||
	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
 | 
			
		||||
	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
 | 
			
		||||
  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
 | 
			
		||||
	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
 | 
			
		||||
  * )   ac_file_in=$ac_file.in ;;
 | 
			
		||||
  esac
 | 
			
		||||
 | 
			
		||||
  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
 | 
			
		||||
echo "$as_me: creating $ac_file" >&6;}
 | 
			
		||||
 | 
			
		||||
  # First look for the input files in the build tree, otherwise in the
 | 
			
		||||
  # src tree.
 | 
			
		||||
  ac_file_inputs=`IFS=:
 | 
			
		||||
    for f in $ac_file_in; do
 | 
			
		||||
      case $f in
 | 
			
		||||
      -) echo $tmp/stdin ;;
 | 
			
		||||
      [\\/$]*)
 | 
			
		||||
	 # Absolute (can't be DOS-style, as IFS=:)
 | 
			
		||||
	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
 | 
			
		||||
echo "$as_me: error: cannot find input file: $f" >&2;}
 | 
			
		||||
   { (exit 1); exit 1; }; }
 | 
			
		||||
	 # Do quote $f, to prevent DOS paths from being IFS'd.
 | 
			
		||||
	 echo "$f";;
 | 
			
		||||
      *) # Relative
 | 
			
		||||
	 if test -f "$f"; then
 | 
			
		||||
	   # Build tree
 | 
			
		||||
	   echo "$f"
 | 
			
		||||
	 elif test -f "$srcdir/$f"; then
 | 
			
		||||
	   # Source tree
 | 
			
		||||
	   echo "$srcdir/$f"
 | 
			
		||||
	 else
 | 
			
		||||
	   # /dev/null tree
 | 
			
		||||
	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
 | 
			
		||||
echo "$as_me: error: cannot find input file: $f" >&2;}
 | 
			
		||||
   { (exit 1); exit 1; }; }
 | 
			
		||||
	 fi;;
 | 
			
		||||
      esac
 | 
			
		||||
    done` || { (exit 1); exit 1; }
 | 
			
		||||
  # Remove the trailing spaces.
 | 
			
		||||
  sed 's/[	 ]*$//' $ac_file_inputs >$tmp/in
 | 
			
		||||
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
# Transform confdefs.h into two sed scripts, `conftest.defines' and
 | 
			
		||||
# `conftest.undefs', that substitutes the proper values into
 | 
			
		||||
# config.h.in to produce config.h.  The first handles `#define'
 | 
			
		||||
# templates, and the second `#undef' templates.
 | 
			
		||||
# And first: Protect against being on the right side of a sed subst in
 | 
			
		||||
# config.status.  Protect against being in an unquoted here document
 | 
			
		||||
# in config.status.
 | 
			
		||||
rm -f conftest.defines conftest.undefs
 | 
			
		||||
# Using a here document instead of a string reduces the quoting nightmare.
 | 
			
		||||
# Putting comments in sed scripts is not portable.
 | 
			
		||||
#
 | 
			
		||||
# `end' is used to avoid that the second main sed command (meant for
 | 
			
		||||
# 0-ary CPP macros) applies to n-ary macro definitions.
 | 
			
		||||
# See the Autoconf documentation for `clear'.
 | 
			
		||||
cat >confdef2sed.sed <<\_ACEOF
 | 
			
		||||
s/[\\&,]/\\&/g
 | 
			
		||||
s,[\\$`],\\&,g
 | 
			
		||||
t clear
 | 
			
		||||
: clear
 | 
			
		||||
s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*\)\(([^)]*)\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
 | 
			
		||||
t end
 | 
			
		||||
s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
 | 
			
		||||
: end
 | 
			
		||||
_ACEOF
 | 
			
		||||
# If some macros were called several times there might be several times
 | 
			
		||||
# the same #defines, which is useless.  Nevertheless, we may not want to
 | 
			
		||||
# sort them, since we want the *last* AC-DEFINE to be honored.
 | 
			
		||||
uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
 | 
			
		||||
sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
 | 
			
		||||
rm -f confdef2sed.sed
 | 
			
		||||
 | 
			
		||||
# This sed command replaces #undef with comments.  This is necessary, for
 | 
			
		||||
# example, in the case of _POSIX_SOURCE, which is predefined and required
 | 
			
		||||
# on some systems where configure will not decide to define it.
 | 
			
		||||
cat >>conftest.undefs <<\_ACEOF
 | 
			
		||||
s,^[	 ]*#[	 ]*undef[	 ][	 ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
# Break up conftest.defines because some shells have a limit on the size
 | 
			
		||||
# of here documents, and old seds have small limits too (100 cmds).
 | 
			
		||||
echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
 | 
			
		||||
echo '  if grep "^[	 ]*#[	 ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
 | 
			
		||||
echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
 | 
			
		||||
echo '  :' >>$CONFIG_STATUS
 | 
			
		||||
rm -f conftest.tail
 | 
			
		||||
while grep . conftest.defines >/dev/null
 | 
			
		||||
do
 | 
			
		||||
  # Write a limited-size here document to $tmp/defines.sed.
 | 
			
		||||
  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
 | 
			
		||||
  # Speed up: don't consider the non `#define' lines.
 | 
			
		||||
  echo '/^[	 ]*#[	 ]*define/!b' >>$CONFIG_STATUS
 | 
			
		||||
  # Work around the forget-to-reset-the-flag bug.
 | 
			
		||||
  echo 't clr' >>$CONFIG_STATUS
 | 
			
		||||
  echo ': clr' >>$CONFIG_STATUS
 | 
			
		||||
  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
 | 
			
		||||
  echo 'CEOF
 | 
			
		||||
  sed -f $tmp/defines.sed $tmp/in >$tmp/out
 | 
			
		||||
  rm -f $tmp/in
 | 
			
		||||
  mv $tmp/out $tmp/in
 | 
			
		||||
' >>$CONFIG_STATUS
 | 
			
		||||
  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
 | 
			
		||||
  rm -f conftest.defines
 | 
			
		||||
  mv conftest.tail conftest.defines
 | 
			
		||||
done
 | 
			
		||||
rm -f conftest.defines
 | 
			
		||||
echo '  fi # grep' >>$CONFIG_STATUS
 | 
			
		||||
echo >>$CONFIG_STATUS
 | 
			
		||||
 | 
			
		||||
# Break up conftest.undefs because some shells have a limit on the size
 | 
			
		||||
# of here documents, and old seds have small limits too (100 cmds).
 | 
			
		||||
echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
 | 
			
		||||
rm -f conftest.tail
 | 
			
		||||
while grep . conftest.undefs >/dev/null
 | 
			
		||||
do
 | 
			
		||||
  # Write a limited-size here document to $tmp/undefs.sed.
 | 
			
		||||
  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
 | 
			
		||||
  # Speed up: don't consider the non `#undef'
 | 
			
		||||
  echo '/^[	 ]*#[	 ]*undef/!b' >>$CONFIG_STATUS
 | 
			
		||||
  # Work around the forget-to-reset-the-flag bug.
 | 
			
		||||
  echo 't clr' >>$CONFIG_STATUS
 | 
			
		||||
  echo ': clr' >>$CONFIG_STATUS
 | 
			
		||||
  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
 | 
			
		||||
  echo 'CEOF
 | 
			
		||||
  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
 | 
			
		||||
  rm -f $tmp/in
 | 
			
		||||
  mv $tmp/out $tmp/in
 | 
			
		||||
' >>$CONFIG_STATUS
 | 
			
		||||
  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
 | 
			
		||||
  rm -f conftest.undefs
 | 
			
		||||
  mv conftest.tail conftest.undefs
 | 
			
		||||
done
 | 
			
		||||
rm -f conftest.undefs
 | 
			
		||||
 | 
			
		||||
cat >>$CONFIG_STATUS <<\_ACEOF
 | 
			
		||||
  # Let's still pretend it is `configure' which instantiates (i.e., don't
 | 
			
		||||
  # use $as_me), people would be surprised to read:
 | 
			
		||||
  #    /* config.h.  Generated by config.status.  */
 | 
			
		||||
  if test x"$ac_file" = x-; then
 | 
			
		||||
    echo "/* Generated by configure.  */" >$tmp/config.h
 | 
			
		||||
  else
 | 
			
		||||
    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
 | 
			
		||||
  fi
 | 
			
		||||
  cat $tmp/in >>$tmp/config.h
 | 
			
		||||
  rm -f $tmp/in
 | 
			
		||||
  if test x"$ac_file" != x-; then
 | 
			
		||||
    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
 | 
			
		||||
      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
 | 
			
		||||
echo "$as_me: $ac_file is unchanged" >&6;}
 | 
			
		||||
    else
 | 
			
		||||
      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
 | 
			
		||||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
 | 
			
		||||
	 X"$ac_file" : 'X\(//\)[^/]' \| \
 | 
			
		||||
	 X"$ac_file" : 'X\(//\)$' \| \
 | 
			
		||||
	 X"$ac_file" : 'X\(/\)' \| \
 | 
			
		||||
	 .     : '\(.\)' 2>/dev/null ||
 | 
			
		||||
echo X"$ac_file" |
 | 
			
		||||
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
 | 
			
		||||
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
 | 
			
		||||
  	  /^X\(\/\/\)$/{ s//\1/; q; }
 | 
			
		||||
  	  /^X\(\/\).*/{ s//\1/; q; }
 | 
			
		||||
  	  s/.*/./; q'`
 | 
			
		||||
      { if $as_mkdir_p; then
 | 
			
		||||
    mkdir -p "$ac_dir"
 | 
			
		||||
  else
 | 
			
		||||
    as_dir="$ac_dir"
 | 
			
		||||
    as_dirs=
 | 
			
		||||
    while test ! -d "$as_dir"; do
 | 
			
		||||
      as_dirs="$as_dir $as_dirs"
 | 
			
		||||
      as_dir=`(dirname "$as_dir") 2>/dev/null ||
 | 
			
		||||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
 | 
			
		||||
	 X"$as_dir" : 'X\(//\)[^/]' \| \
 | 
			
		||||
	 X"$as_dir" : 'X\(//\)$' \| \
 | 
			
		||||
	 X"$as_dir" : 'X\(/\)' \| \
 | 
			
		||||
	 .     : '\(.\)' 2>/dev/null ||
 | 
			
		||||
echo X"$as_dir" |
 | 
			
		||||
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
 | 
			
		||||
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
 | 
			
		||||
  	  /^X\(\/\/\)$/{ s//\1/; q; }
 | 
			
		||||
  	  /^X\(\/\).*/{ s//\1/; q; }
 | 
			
		||||
  	  s/.*/./; q'`
 | 
			
		||||
    done
 | 
			
		||||
    test ! -n "$as_dirs" || mkdir $as_dirs
 | 
			
		||||
  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
 | 
			
		||||
echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
 | 
			
		||||
   { (exit 1); exit 1; }; }; }
 | 
			
		||||
 | 
			
		||||
      rm -f $ac_file
 | 
			
		||||
      mv $tmp/config.h $ac_file
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    cat $tmp/config.h
 | 
			
		||||
    rm -f $tmp/config.h
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
_ACEOF
 | 
			
		||||
 | 
			
		||||
cat >>$CONFIG_STATUS <<\_ACEOF
 | 
			
		||||
 | 
			
		||||
@@ -11855,3 +12407,8 @@ if test x$FSADM == xyes; then
 | 
			
		||||
  { echo "$as_me:$LINENO: WARNING: fsadm support is untested" >&5
 | 
			
		||||
echo "$as_me: WARNING: fsadm support is untested" >&2;}
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD == xyes; then
 | 
			
		||||
  { echo "$as_me:$LINENO: WARNING: dmeventd support is untested" >&5
 | 
			
		||||
echo "$as_me: WARNING: dmeventd support is untested" >&2;}
 | 
			
		||||
fi
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										111
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								configure.in
									
									
									
									
									
								
							@@ -18,6 +18,9 @@ AC_PREREQ(2.53)
 | 
			
		||||
dnl -- Process this file with autoconf to produce a configure script.
 | 
			
		||||
AC_INIT(lib/device/dev-cache.h)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
AC_CONFIG_HEADERS(lib/misc/configure.h)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Setup the directory where autoconf has auxilary files
 | 
			
		||||
AC_CONFIG_AUX_DIR(autoconf) 
 | 
			
		||||
@@ -35,10 +38,11 @@ case "$host_os" in
 | 
			
		||||
		CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
 | 
			
		||||
		LDDEPS="$LDDEPS .export.sym"
 | 
			
		||||
		LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
 | 
			
		||||
		SOFLAG="-shared"
 | 
			
		||||
		LIB_SUFFIX="so"
 | 
			
		||||
		DEVMAPPER=yes
 | 
			
		||||
		ODIRECT=yes
 | 
			
		||||
		SELINUX=yes
 | 
			
		||||
		REALTIME=yes
 | 
			
		||||
		CLUSTER=internal
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
	darwin*)
 | 
			
		||||
@@ -49,10 +53,11 @@ case "$host_os" in
 | 
			
		||||
		CLDNOWHOLEARCHIVE=
 | 
			
		||||
		LDDEPS="$LDDEPS"
 | 
			
		||||
		LDFLAGS="$LDFLAGS"
 | 
			
		||||
		SOFLAG="-dynamiclib"
 | 
			
		||||
		LIB_SUFFIX="dylib"
 | 
			
		||||
		DEVMAPPER=yes
 | 
			
		||||
		ODIRECT=no
 | 
			
		||||
		SELINUX=no
 | 
			
		||||
		REALTIME=no
 | 
			
		||||
		CLUSTER=none
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
esac
 | 
			
		||||
@@ -65,6 +70,8 @@ AC_PROG_INSTALL
 | 
			
		||||
AC_PROG_LN_S
 | 
			
		||||
AC_PROG_MAKE_SET
 | 
			
		||||
AC_PROG_RANLIB
 | 
			
		||||
AC_PATH_PROG(CFLOW_CMD, cflow)
 | 
			
		||||
AC_PATH_PROG(CSCOPE_CMD, cscope)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Checks for header files.
 | 
			
		||||
@@ -150,7 +157,7 @@ AC_ARG_ENABLE(lvm1_fallback, [  --enable-lvm1_fallback  Use this to fall back an
 | 
			
		||||
AC_MSG_RESULT($LVM1_FALLBACK)
 | 
			
		||||
 | 
			
		||||
if test x$LVM1_FALLBACK = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DLVM1_FALLBACK"
 | 
			
		||||
	AC_DEFINE([LVM1_FALLBACK], 1, [Define to 1 if 'lvm' should fall back to using LVM1 binaries if device-mapper is missing from the kernel])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -170,7 +177,7 @@ if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$LVM1 = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DLVM1_INTERNAL"
 | 
			
		||||
	AC_DEFINE([LVM1_INTERNAL], 1, [Define to 1 to include built-in support for LVM1 metadata.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -190,7 +197,7 @@ if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$POOL = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DPOOL_INTERNAL"
 | 
			
		||||
	AC_DEFINE([POOL_INTERNAL], 1, [Define to 1 to include built-in support for GFS pool metadata.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -209,7 +216,7 @@ if [[ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$CLUSTER = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
 | 
			
		||||
	AC_DEFINE([CLUSTER_LOCKING_INTERNAL], 1, [Define to 1 to include built-in support for clustered LVM locking.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -229,7 +236,7 @@ if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != x
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$SNAPSHOTS = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
 | 
			
		||||
	AC_DEFINE([SNAPSHOT_INTERNAL], 1, [Define to 1 to include built-in support for snapshots.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -249,7 +256,7 @@ if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$MIRRORS = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
 | 
			
		||||
	AC_DEFINE([MIRRORED_INTERNAL], 1, [Define to 1 to include built-in support for mirrors.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -267,7 +274,7 @@ READLINE=$enableval, READLINE=no)
 | 
			
		||||
AC_MSG_RESULT($READLINE)
 | 
			
		||||
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
 | 
			
		||||
	AC_DEFINE([READLINE_SUPPORT], 1, [Define to 1 to include the LVM readline shell.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -277,6 +284,13 @@ AC_ARG_ENABLE(selinux, [  --disable-selinux       Disable selinux support],
 | 
			
		||||
SELINUX=$enableval)
 | 
			
		||||
AC_MSG_RESULT($SELINUX)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Disable realtime clock support
 | 
			
		||||
AC_MSG_CHECKING(whether to enable realtime support)
 | 
			
		||||
AC_ARG_ENABLE(realtime, [  --disable-realtime       Disable realtime clock support],
 | 
			
		||||
REALTIME=$enableval)
 | 
			
		||||
AC_MSG_RESULT($REALTIME)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Build cluster LVM daemon
 | 
			
		||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
 | 
			
		||||
@@ -305,6 +319,8 @@ AC_MSG_RESULT($DEBUG)
 | 
			
		||||
dnl -- Normally turn off optimisation for debug builds
 | 
			
		||||
if test x$DEBUG = xyes; then
 | 
			
		||||
	COPTIMISE_FLAG=
 | 
			
		||||
else
 | 
			
		||||
	CSCOPE_CMD=
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -323,7 +339,7 @@ DEVMAPPER=$enableval)
 | 
			
		||||
AC_MSG_RESULT($DEVMAPPER)
 | 
			
		||||
 | 
			
		||||
if test x$DEVMAPPER = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
 | 
			
		||||
	AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable device-mapper interaction.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -334,7 +350,7 @@ ODIRECT=$enableval)
 | 
			
		||||
AC_MSG_RESULT($ODIRECT)
 | 
			
		||||
 | 
			
		||||
if test x$ODIRECT = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
 | 
			
		||||
	AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -344,10 +360,6 @@ AC_ARG_ENABLE(cmdlib, [  --enable-cmdlib         Build shared command library],
 | 
			
		||||
CMDLIB=$enableval, CMDLIB=no)
 | 
			
		||||
AC_MSG_RESULT($CMDLIB)
 | 
			
		||||
 | 
			
		||||
if test x$CMDLIB = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DCMDLIB"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Enable fsadm
 | 
			
		||||
AC_MSG_CHECKING(whether to build fsadm)
 | 
			
		||||
@@ -355,6 +367,23 @@ AC_ARG_ENABLE(fsadm, [  --enable-fsadm          Enable fsadm],
 | 
			
		||||
FSADM=$enableval)
 | 
			
		||||
AC_MSG_RESULT($FSADM)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- enable dmeventd handling
 | 
			
		||||
AC_MSG_CHECKING(whether to use dmeventd)
 | 
			
		||||
AC_ARG_ENABLE(dmeventd, [  --enable-dmeventd       Enable the device-mapper event daemon],
 | 
			
		||||
DMEVENTD=$enableval)
 | 
			
		||||
AC_MSG_RESULT($DMEVENTD)
 | 
			
		||||
 | 
			
		||||
dnl -- dmeventd currently requires internal mirror support
 | 
			
		||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
 | 
			
		||||
AC_MSG_ERROR(
 | 
			
		||||
--enable-dmeventd currently requires --with-mirrors=internal
 | 
			
		||||
)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD = xyes; then
 | 
			
		||||
	AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
 | 
			
		||||
fi
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Mess with default exec_prefix
 | 
			
		||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
 | 
			
		||||
@@ -390,7 +419,7 @@ dnl -- Check for dlopen
 | 
			
		||||
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
 | 
			
		||||
 | 
			
		||||
if [[ "x$HAVE_LIBDL" = xyes ]]; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DHAVE_LIBDL"
 | 
			
		||||
	AC_DEFINE([HAVE_LIBDL], 1, [Define to 1 if dynamic libraries are available.])
 | 
			
		||||
	LIBS="-ldl $LIBS"
 | 
			
		||||
else
 | 
			
		||||
	HAVE_LIBDL=no
 | 
			
		||||
@@ -407,23 +436,46 @@ Features cannot be 'shared' when building statically
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for is_selinux_enabled
 | 
			
		||||
dnl -- Check for selinux
 | 
			
		||||
if test x$SELINUX = xyes; then
 | 
			
		||||
	AC_MSG_CHECKING(for sepol_check_context function)
 | 
			
		||||
	AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
 | 
			
		||||
	AC_MSG_RESULT($HAVE_SEPOL)
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_SEPOL = xyes; then
 | 
			
		||||
		LIBS="-lsepol $LIBS"
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	AC_MSG_CHECKING(for is_selinux_enabled function)
 | 
			
		||||
	AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
 | 
			
		||||
	AC_MSG_RESULT($HAVE_SELINUX)
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
		CFLAGS="$CFLAGS -DHAVE_SELINUX"
 | 
			
		||||
		AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.])
 | 
			
		||||
		LIBS="-lselinux $LIBS"
 | 
			
		||||
	else
 | 
			
		||||
		AC_MSG_WARN(Disabling selinux)
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for realtime clock support
 | 
			
		||||
if test x$REALTIME = xyes; then
 | 
			
		||||
	AC_MSG_CHECKING(for clock_gettime function)
 | 
			
		||||
	AC_CHECK_LIB(rt, clock_gettime, HAVE_REALTIME=yes, HAVE_REALTIME=no)
 | 
			
		||||
	AC_MSG_RESULT($HAVE_REALTIME)
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_REALTIME = xyes; then
 | 
			
		||||
		AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
 | 
			
		||||
		LIBS="-lrt $LIBS"
 | 
			
		||||
	else
 | 
			
		||||
		AC_MSG_WARN(Disabling realtime clock)
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for getopt
 | 
			
		||||
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
 | 
			
		||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 to if getopt_long is available.]))
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
 | 
			
		||||
@@ -438,8 +490,7 @@ Note: if you are using precompiled packages you will also need the development
 | 
			
		||||
package as well (which may be called readline-devel or something similar).
 | 
			
		||||
)
 | 
			
		||||
	)
 | 
			
		||||
	AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
 | 
			
		||||
		
 | 
			
		||||
	AC_CHECK_FUNC(rl_completion_matches, AC_DEFINE([HAVE_RL_COMPLETION_MATCHES], 1, [Define to 1 if rl_completion_matches() is available.]))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -507,9 +558,7 @@ if test x$INTL = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(libintl.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DEVMAPPER = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
 | 
			
		||||
if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(selinux/selinux.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
@@ -519,7 +568,7 @@ fi
 | 
			
		||||
AC_PATH_PROG(MODPROBE_CMD, modprobe)
 | 
			
		||||
 | 
			
		||||
if test x$MODPROBE_CMD != x; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
 | 
			
		||||
	AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -545,7 +594,7 @@ AC_SUBST(CLDWHOLEARCHIVE)
 | 
			
		||||
AC_SUBST(CLDNOWHOLEARCHIVE)
 | 
			
		||||
AC_SUBST(LDDEPS)
 | 
			
		||||
AC_SUBST(LDFLAGS)
 | 
			
		||||
AC_SUBST(SOFLAG)
 | 
			
		||||
AC_SUBST(LIB_SUFFIX)
 | 
			
		||||
AC_SUBST(LIBS)
 | 
			
		||||
AC_SUBST(LVM_VERSION)
 | 
			
		||||
AC_SUBST(LVM1_FALLBACK)
 | 
			
		||||
@@ -553,6 +602,7 @@ AC_SUBST(DEBUG)
 | 
			
		||||
AC_SUBST(DEVMAPPER)
 | 
			
		||||
AC_SUBST(HAVE_LIBDL)
 | 
			
		||||
AC_SUBST(HAVE_SELINUX)
 | 
			
		||||
AC_SUBST(HAVE_REALTIME)
 | 
			
		||||
AC_SUBST(CMDLIB)
 | 
			
		||||
AC_SUBST(MSGFMT)
 | 
			
		||||
AC_SUBST(LOCALEDIR)
 | 
			
		||||
@@ -563,6 +613,9 @@ AC_SUBST(INTL)
 | 
			
		||||
AC_SUBST(CLVMD)
 | 
			
		||||
AC_SUBST(CLUSTER)
 | 
			
		||||
AC_SUBST(FSADM)
 | 
			
		||||
AC_SUBST(DMEVENTD)
 | 
			
		||||
AC_SUBST(CFLOW_CMD)
 | 
			
		||||
AC_SUBST(CSCOPE_CMD)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- First and last lines should not contain files to generate in order to 
 | 
			
		||||
@@ -572,6 +625,8 @@ Makefile								\
 | 
			
		||||
make.tmpl								\
 | 
			
		||||
daemons/Makefile							\
 | 
			
		||||
daemons/clvmd/Makefile							\
 | 
			
		||||
dmeventd/Makefile							\
 | 
			
		||||
dmeventd/mirror/Makefile						\
 | 
			
		||||
doc/Makefile								\
 | 
			
		||||
include/Makefile						 	\
 | 
			
		||||
lib/Makefile							 	\
 | 
			
		||||
@@ -599,3 +654,7 @@ fi
 | 
			
		||||
if test x$FSADM == xyes; then
 | 
			
		||||
  AC_MSG_WARN(fsadm support is untested)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD == xyes; then
 | 
			
		||||
  AC_MSG_WARN(dmeventd support is untested)
 | 
			
		||||
fi
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ SOURCES = \
 | 
			
		||||
	clvmd-command.c  \
 | 
			
		||||
	clvmd.c          \
 | 
			
		||||
	lvm-functions.c  \
 | 
			
		||||
	refresh_clvmd.c \
 | 
			
		||||
	system-lv.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "gulm")
 | 
			
		||||
@@ -35,28 +36,36 @@ ifeq ("@CLVMD@", "all")
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@DEBUG@", "yes")
 | 
			
		||||
	CFLAGS += -DDEBUG
 | 
			
		||||
	DEFS += -DDEBUG
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("$(GULM)", "yes")
 | 
			
		||||
	SOURCES += clvmd-gulm.c tcp-comms.c
 | 
			
		||||
	LMLIBS += -lccs -lgulm
 | 
			
		||||
	CFLAGS += -DUSE_GULM
 | 
			
		||||
	DEFS += -DUSE_GULM
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("$(CMAN)", "yes")
 | 
			
		||||
	SOURCES += clvmd-cman.c
 | 
			
		||||
	LMLIBS += -ldlm
 | 
			
		||||
	CFLAGS += -DUSE_CMAN
 | 
			
		||||
	LMLIBS += -ldlm -lcman
 | 
			
		||||
	DEFS += -DUSE_CMAN
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
TARGETS = \
 | 
			
		||||
	clvmd
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
LVMLIBS = -llvm -lpthread
 | 
			
		||||
 | 
			
		||||
CFLAGS += -D_REENTRANT -fno-strict-aliasing
 | 
			
		||||
LIBS += -ldevmapper -llvm -lpthread
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
	LVMLIBS += -ldevmapper-event
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
LVMLIBS += -ldevmapper
 | 
			
		||||
 | 
			
		||||
DEFS += -D_REENTRANT
 | 
			
		||||
CFLAGS += -fno-strict-aliasing
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
INSTALL_TARGETS = \
 | 
			
		||||
	install_clvmd
 | 
			
		||||
 
 | 
			
		||||
@@ -63,4 +63,8 @@ static const char CLVMD_SOCKNAME[] = "\0clvmd";
 | 
			
		||||
#define CLVMD_CMD_LOCK_LV           50
 | 
			
		||||
#define CLVMD_CMD_LOCK_VG           51
 | 
			
		||||
 | 
			
		||||
/* Misc functions */
 | 
			
		||||
#define CLVMD_CMD_REFRESH	    40
 | 
			
		||||
#define CLVMD_CMD_GET_CLUSTERNAME   41
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -46,19 +46,23 @@
 | 
			
		||||
 | 
			
		||||
#define LOCKSPACE_NAME "clvmd"
 | 
			
		||||
 | 
			
		||||
static int cluster_sock;
 | 
			
		||||
static int num_nodes;
 | 
			
		||||
static struct cl_cluster_node *nodes = NULL;
 | 
			
		||||
static struct cman_node *nodes = NULL;
 | 
			
		||||
static struct cman_node this_node;
 | 
			
		||||
static int count_nodes; /* size of allocated nodes array */
 | 
			
		||||
static int max_updown_nodes = 50;	/* Current size of the allocated array */
 | 
			
		||||
/* Node up/down status, indexed by nodeid */
 | 
			
		||||
static int *node_updown = NULL;
 | 
			
		||||
static dlm_lshandle_t *lockspace;
 | 
			
		||||
static cman_handle_t c_handle;
 | 
			
		||||
 | 
			
		||||
static void count_clvmds_running(void);
 | 
			
		||||
static void get_members(void);
 | 
			
		||||
static int nodeid_from_csid(char *csid);
 | 
			
		||||
static int name_from_nodeid(int nodeid, char *name);
 | 
			
		||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
 | 
			
		||||
static void data_callback(cman_handle_t handle, void *private,
 | 
			
		||||
			  char *buf, int len, uint8_t port, int nodeid);
 | 
			
		||||
 | 
			
		||||
struct lock_wait {
 | 
			
		||||
	pthread_cond_t cond;
 | 
			
		||||
@@ -68,30 +72,23 @@ struct lock_wait {
 | 
			
		||||
 | 
			
		||||
static int _init_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_cl saddr;
 | 
			
		||||
	int port = CLUSTER_PORT_CLVMD;
 | 
			
		||||
 | 
			
		||||
	/* Open the cluster communication socket */
 | 
			
		||||
	cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT);
 | 
			
		||||
	if (cluster_sock == -1) {
 | 
			
		||||
		/* Don't print an error here because we could be just probing for CMAN */
 | 
			
		||||
	c_handle = cman_init(NULL);
 | 
			
		||||
	if (!c_handle) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't open cluster manager socket: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	/* Set Close-on-exec */
 | 
			
		||||
	fcntl(cluster_sock, F_SETFD, 1);
 | 
			
		||||
 | 
			
		||||
	/* Bind to our port number on the cluster.
 | 
			
		||||
	   Writes to this will block if the cluster loses quorum */
 | 
			
		||||
	saddr.scl_family = AF_CLUSTER;
 | 
			
		||||
	saddr.scl_port = port;
 | 
			
		||||
 | 
			
		||||
	if (bind
 | 
			
		||||
	    (cluster_sock, (struct sockaddr *) &saddr,
 | 
			
		||||
	     sizeof(struct sockaddr_cl))) {
 | 
			
		||||
	if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't bind cluster socket: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cman_start_notification(c_handle, event_callback)) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't start cluster event listening");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the cluster members list */
 | 
			
		||||
	get_members();
 | 
			
		||||
	count_clvmds_running();
 | 
			
		||||
@@ -114,152 +111,122 @@ static void _cluster_init_completed(void)
 | 
			
		||||
 | 
			
		||||
static int _get_main_cluster_fd()
 | 
			
		||||
{
 | 
			
		||||
	return cluster_sock;
 | 
			
		||||
	return cman_get_fd(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_num_nodes()
 | 
			
		||||
{
 | 
			
		||||
	return num_nodes;
 | 
			
		||||
	int i;
 | 
			
		||||
	int nnodes = 0;
 | 
			
		||||
 | 
			
		||||
	/* return number of ACTIVE nodes */
 | 
			
		||||
	for (i=0; i<num_nodes; i++) {
 | 
			
		||||
		if (nodes[i].cn_member)
 | 
			
		||||
			nnodes++;
 | 
			
		||||
	}
 | 
			
		||||
	return nnodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send_message with the fd check removed */
 | 
			
		||||
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	struct iovec iov[2];
 | 
			
		||||
	struct msghdr msg;
 | 
			
		||||
	struct sockaddr_cl saddr;
 | 
			
		||||
	int len = 0;
 | 
			
		||||
	int nodeid = 0;
 | 
			
		||||
 | 
			
		||||
	msg.msg_control = NULL;
 | 
			
		||||
	msg.msg_controllen = 0;
 | 
			
		||||
	msg.msg_iovlen = 1;
 | 
			
		||||
	msg.msg_iov = iov;
 | 
			
		||||
	msg.msg_flags = 0;
 | 
			
		||||
	iov[0].iov_len = msglen;
 | 
			
		||||
	iov[0].iov_base = buf;
 | 
			
		||||
	if (csid)
 | 
			
		||||
		memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	saddr.scl_family = AF_CLUSTER;
 | 
			
		||||
	saddr.scl_port = CLUSTER_PORT_CLVMD;
 | 
			
		||||
	if (csid) {
 | 
			
		||||
		msg.msg_name = &saddr;
 | 
			
		||||
		msg.msg_namelen = sizeof(saddr);
 | 
			
		||||
		memcpy(&saddr.scl_nodeid, csid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
	} else {		/* Cluster broadcast */
 | 
			
		||||
 | 
			
		||||
		msg.msg_name = NULL;
 | 
			
		||||
		msg.msg_namelen = 0;
 | 
			
		||||
	if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
 | 
			
		||||
	{
 | 
			
		||||
		log_error(errtext);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		len = sendmsg(cluster_sock, &msg, 0);
 | 
			
		||||
		if (len < 0 && errno != EAGAIN)
 | 
			
		||||
			log_error(errtext);
 | 
			
		||||
 | 
			
		||||
	} while (len == -1 && errno == EAGAIN);
 | 
			
		||||
	return len;
 | 
			
		||||
	return msglen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	memset(csid, 0, CMAN_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (nodes[i].us)
 | 
			
		||||
			memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
 | 
			
		||||
	if (this_node.cn_nodeid == 0) {
 | 
			
		||||
		cman_get_node(c_handle, 0, &this_node);
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Call a callback routine for each node that known (down mean not running a clvmd) */
 | 
			
		||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
 | 
			
		||||
static int _cluster_do_node_callback(struct local_client *client,
 | 
			
		||||
			     void (*callback) (struct local_client *, char *,
 | 
			
		||||
					       int))
 | 
			
		||||
				     void (*callback) (struct local_client *, char *,
 | 
			
		||||
						       int))
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int somedown = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < _get_num_nodes(); i++) {
 | 
			
		||||
		callback(client, (char *)&nodes[i].node_id, node_updown[nodes[i].node_id]);
 | 
			
		||||
		if (!node_updown[nodes[i].node_id])
 | 
			
		||||
			somedown = -1;
 | 
			
		||||
		if (nodes[i].cn_member) {
 | 
			
		||||
			callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
 | 
			
		||||
			if (!node_updown[nodes[i].cn_nodeid])
 | 
			
		||||
				somedown = -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return somedown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Process OOB message from the cluster socket,
 | 
			
		||||
   this currently just means that a node has stopped listening on our port */
 | 
			
		||||
static void process_oob_msg(char *buf, int len, int nodeid)
 | 
			
		||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
 | 
			
		||||
{
 | 
			
		||||
	char namebuf[256];
 | 
			
		||||
	switch (buf[0]) {
 | 
			
		||||
        case CLUSTER_OOB_MSG_PORTCLOSED:
 | 
			
		||||
		name_from_nodeid(nodeid, namebuf);
 | 
			
		||||
		log_notice("clvmd on node %s has died\n", namebuf);
 | 
			
		||||
		DEBUGLOG("Got OOB message, removing node %s\n", namebuf);
 | 
			
		||||
	char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
 | 
			
		||||
 | 
			
		||||
		node_updown[nodeid] = 0;
 | 
			
		||||
	switch (reason) {
 | 
			
		||||
        case CMAN_REASON_PORTCLOSED:
 | 
			
		||||
		name_from_nodeid(arg, namebuf);
 | 
			
		||||
		log_notice("clvmd on node %s has died\n", namebuf);
 | 
			
		||||
		DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
 | 
			
		||||
 | 
			
		||||
		node_updown[arg] = 0;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLUSTER_OOB_MSG_STATECHANGE:
 | 
			
		||||
		DEBUGLOG("Got OOB message, Cluster state change\n");
 | 
			
		||||
	case CMAN_REASON_STATECHANGE:
 | 
			
		||||
		DEBUGLOG("Got state change message, re-reading members list\n");
 | 
			
		||||
		get_members();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
 | 
			
		||||
	case CMAN_REASON_PORTOPENED:
 | 
			
		||||
		/* Ignore this, wait for startup message from clvmd itself */
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CMAN_REASON_TRY_SHUTDOWN:
 | 
			
		||||
		DEBUGLOG("Got try shutdown, sending OK\n");
 | 
			
		||||
		cman_replyto_shutdown(c_handle, 1);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		/* ERROR */
 | 
			
		||||
		DEBUGLOG("Got unknown OOB message: %d\n", buf[0]);
 | 
			
		||||
		DEBUGLOG("Got unknown event callback message: %d\n", reason);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
			struct local_client **new_client)
 | 
			
		||||
static struct local_client *cman_client;
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
 | 
			
		||||
				struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	struct iovec iov[2];
 | 
			
		||||
	struct msghdr msg;
 | 
			
		||||
	struct sockaddr_cl saddr;
 | 
			
		||||
 | 
			
		||||
	/* Save this for data_callback */
 | 
			
		||||
	cman_client = fd;
 | 
			
		||||
 | 
			
		||||
	/* We never return a new client */
 | 
			
		||||
	*new_client = NULL;
 | 
			
		||||
 | 
			
		||||
	msg.msg_control = NULL;
 | 
			
		||||
	msg.msg_controllen = 0;
 | 
			
		||||
	msg.msg_iovlen = 1;
 | 
			
		||||
	msg.msg_iov = iov;
 | 
			
		||||
	msg.msg_name = &saddr;
 | 
			
		||||
	msg.msg_flags = 0;
 | 
			
		||||
	msg.msg_namelen = sizeof(saddr);
 | 
			
		||||
	iov[0].iov_len = len;
 | 
			
		||||
	iov[0].iov_base = buf;
 | 
			
		||||
	return cman_dispatch(c_handle, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	len = recvmsg(cluster_sock, &msg, MSG_OOB | O_NONBLOCK);
 | 
			
		||||
	if (len < 0 && errno == EAGAIN)
 | 
			
		||||
		return len;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Read on cluster socket, len = %d\n", len);
 | 
			
		||||
 | 
			
		||||
	/* A real error */
 | 
			
		||||
	if (len < 0) {
 | 
			
		||||
		log_error("read error on cluster socket: %m");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* EOF - we have left the cluster */
 | 
			
		||||
	if (len == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* Is it OOB? probably a node gone down */
 | 
			
		||||
	if (msg.msg_flags & MSG_OOB) {
 | 
			
		||||
		process_oob_msg(iov[0].iov_base, len, saddr.scl_nodeid);
 | 
			
		||||
 | 
			
		||||
		/* Tell the upper layer to ignore this message */
 | 
			
		||||
		len = -1;
 | 
			
		||||
		errno = EAGAIN;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		memcpy(csid, &saddr.scl_nodeid, sizeof(saddr.scl_nodeid));
 | 
			
		||||
		/* Send it back to clvmd */
 | 
			
		||||
		process_message(client, buf, len, csid);
 | 
			
		||||
	}
 | 
			
		||||
	return len;
 | 
			
		||||
static void data_callback(cman_handle_t handle, void *private,
 | 
			
		||||
			  char *buf, int len, uint8_t port, int nodeid)
 | 
			
		||||
{
 | 
			
		||||
	/* Ignore looped back messages */
 | 
			
		||||
	if (nodeid == this_node.cn_nodeid)
 | 
			
		||||
		return;
 | 
			
		||||
	process_message(cman_client, buf, len, (char *)&nodeid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _add_up_node(char *csid)
 | 
			
		||||
@@ -278,7 +245,7 @@ static void _add_up_node(char *csid)
 | 
			
		||||
				 max_updown_nodes);
 | 
			
		||||
		} else {
 | 
			
		||||
			log_error
 | 
			
		||||
			    ("Realloc failed. Node status for clvmd will be wrong. quitting\n");
 | 
			
		||||
				("Realloc failed. Node status for clvmd will be wrong. quitting\n");
 | 
			
		||||
			exit(999);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -290,19 +257,15 @@ static void _cluster_closedown()
 | 
			
		||||
{
 | 
			
		||||
	unlock_all();
 | 
			
		||||
	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
 | 
			
		||||
	close(cluster_sock);
 | 
			
		||||
	cman_finish(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_listening(int nodeid)
 | 
			
		||||
{
 | 
			
		||||
	struct cl_listen_request rq;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	rq.port = CLUSTER_PORT_CLVMD;
 | 
			
		||||
	rq.nodeid = nodeid;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		status = ioctl(cluster_sock, SIOCCLUSTER_ISLISTENING, &rq);
 | 
			
		||||
		status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
 | 
			
		||||
		if (status < 0 && errno == EBUSY) {	/* Don't busywait */
 | 
			
		||||
			sleep(1);
 | 
			
		||||
			errno = EBUSY;	/* In case sleep trashes it */
 | 
			
		||||
@@ -320,67 +283,61 @@ static void count_clvmds_running(void)
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		node_updown[nodes[i].node_id] = is_listening(nodes[i].node_id);
 | 
			
		||||
		node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get a list of active cluster members */
 | 
			
		||||
static void get_members()
 | 
			
		||||
{
 | 
			
		||||
	struct cl_cluster_nodelist nodelist;
 | 
			
		||||
	int retnodes;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
 | 
			
		||||
	num_nodes = cman_get_node_count(c_handle);
 | 
			
		||||
	if (num_nodes == -1) {
 | 
			
		||||
		log_error("Unable to get node count");
 | 
			
		||||
	} else {
 | 
			
		||||
	        /* Not enough room for new nodes list ? */
 | 
			
		||||
	        if (num_nodes > count_nodes && nodes) {
 | 
			
		||||
			free(nodes);
 | 
			
		||||
			nodes = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		if (nodes == NULL) {
 | 
			
		||||
		        count_nodes = num_nodes + 10; /* Overallocate a little */
 | 
			
		||||
		        nodes = malloc(count_nodes * sizeof(struct cl_cluster_node));
 | 
			
		||||
			if (!nodes) {
 | 
			
		||||
			        log_error("Unable to allocate nodes array\n");
 | 
			
		||||
				exit(5);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		nodelist.max_members = count_nodes;
 | 
			
		||||
		nodelist.nodes = nodes;
 | 
			
		||||
	/* Not enough room for new nodes list ? */
 | 
			
		||||
	if (num_nodes > count_nodes && nodes) {
 | 
			
		||||
		free(nodes);
 | 
			
		||||
		nodes = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
 | 
			
		||||
		if (num_nodes <= 0) {
 | 
			
		||||
		        log_error("Unable to get node details");
 | 
			
		||||
			exit(6);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Sanity check struct */
 | 
			
		||||
		if (nodes[0].size != sizeof(struct cl_cluster_node)) {
 | 
			
		||||
			log_error
 | 
			
		||||
			    ("sizeof(cl_cluster_node) does not match size returned from the kernel: aborting\n");
 | 
			
		||||
			exit(10);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (node_updown == NULL) {
 | 
			
		||||
			node_updown =
 | 
			
		||||
			    (int *) malloc(sizeof(int) *
 | 
			
		||||
					   max(num_nodes, max_updown_nodes));
 | 
			
		||||
			memset(node_updown, 0,
 | 
			
		||||
			       sizeof(int) * max(num_nodes, max_updown_nodes));
 | 
			
		||||
	if (nodes == NULL) {
 | 
			
		||||
		count_nodes = num_nodes + 10; /* Overallocate a little */
 | 
			
		||||
		nodes = malloc(count_nodes * sizeof(struct cman_node));
 | 
			
		||||
		if (!nodes) {
 | 
			
		||||
			log_error("Unable to allocate nodes array\n");
 | 
			
		||||
			exit(5);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
 | 
			
		||||
	if (status < 0) {
 | 
			
		||||
		log_error("Unable to get node details");
 | 
			
		||||
		exit(6);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (node_updown == NULL) {
 | 
			
		||||
		node_updown =
 | 
			
		||||
			(int *) malloc(sizeof(int) *
 | 
			
		||||
				       max(num_nodes, max_updown_nodes));
 | 
			
		||||
		memset(node_updown, 0,
 | 
			
		||||
		       sizeof(int) * max(num_nodes, max_updown_nodes));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Convert a node name to a CSID */
 | 
			
		||||
static int _csid_from_name(char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (strcmp(name, nodes[i].name) == 0) {
 | 
			
		||||
			memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
 | 
			
		||||
		if (strcmp(name, nodes[i].cn_name) == 0) {
 | 
			
		||||
			memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -393,8 +350,8 @@ static int _name_from_csid(char *csid, char *name)
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (memcmp(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN) == 0) {
 | 
			
		||||
			strcpy(name, nodes[i].name);
 | 
			
		||||
		if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
 | 
			
		||||
			strcpy(name, nodes[i].cn_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -409,8 +366,8 @@ static int name_from_nodeid(int nodeid, char *name)
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (nodeid == nodes[i].node_id) {
 | 
			
		||||
			strcpy(name, nodes[i].name);
 | 
			
		||||
		if (nodeid == nodes[i].cn_nodeid) {
 | 
			
		||||
			strcpy(name, nodes[i].cn_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -431,7 +388,7 @@ static int nodeid_from_csid(char *csid)
 | 
			
		||||
 | 
			
		||||
static int _is_quorate()
 | 
			
		||||
{
 | 
			
		||||
	return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
 | 
			
		||||
	return cman_is_quorate(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sync_ast_routine(void *arg)
 | 
			
		||||
@@ -514,6 +471,18 @@ static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_cluster_name(char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	cman_cluster_t cluster_info;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	status = cman_get_cluster(c_handle, &cluster_info);
 | 
			
		||||
	if (!status) {
 | 
			
		||||
		strncpy(buf, cluster_info.ci_name, buflen);
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops _cluster_cman_ops = {
 | 
			
		||||
	.cluster_init_completed   = _cluster_init_completed,
 | 
			
		||||
	.cluster_send_message     = _cluster_send_message,
 | 
			
		||||
@@ -527,6 +496,7 @@ static struct cluster_ops _cluster_cman_ops = {
 | 
			
		||||
	.get_our_csid             = _get_our_csid,
 | 
			
		||||
	.add_up_node              = _add_up_node,
 | 
			
		||||
	.cluster_closedown        = _cluster_closedown,
 | 
			
		||||
	.get_cluster_name         = _get_cluster_name,
 | 
			
		||||
	.sync_lock                = _sync_lock,
 | 
			
		||||
	.sync_unlock              = _sync_unlock,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -75,6 +75,8 @@
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
 | 
			
		||||
extern struct cluster_ops *clops;
 | 
			
		||||
 | 
			
		||||
/* This is where all the real work happens:
 | 
			
		||||
   NOTE: client will be NULL when this is executed on a remote node */
 | 
			
		||||
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
 | 
			
		||||
@@ -117,11 +119,21 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
 | 
			
		||||
		if (status == EIO) {
 | 
			
		||||
			*retlen =
 | 
			
		||||
			    1 + snprintf(*buf, buflen,
 | 
			
		||||
					 "Internal lvm error, check syslog");
 | 
			
		||||
					 get_last_lvm_error());
 | 
			
		||||
			return EIO;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_REFRESH:
 | 
			
		||||
		do_refresh_cache();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_GET_CLUSTERNAME:
 | 
			
		||||
		status = clops->get_cluster_name(*buf, buflen);
 | 
			
		||||
		if (!status)
 | 
			
		||||
			*retlen = strlen(*buf);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		/* Won't get here because command is validated in pre_command */
 | 
			
		||||
		break;
 | 
			
		||||
@@ -180,7 +192,7 @@ static int lock_vg(struct local_client *client)
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
 | 
			
		||||
	status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
 | 
			
		||||
	status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    status = errno;
 | 
			
		||||
	else
 | 
			
		||||
@@ -222,6 +234,10 @@ int do_pre_command(struct local_client *client)
 | 
			
		||||
		status = pre_lock_lv(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_REFRESH:
 | 
			
		||||
	case CLVMD_CMD_GET_CLUSTERNAME:
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("Unknown command %d received\n", header->cmd);
 | 
			
		||||
		status = EINVAL;
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,8 @@ struct cluster_ops {
 | 
			
		||||
	void (*reread_config) (void);
 | 
			
		||||
	void (*cluster_closedown) (void);
 | 
			
		||||
 | 
			
		||||
	int (*get_cluster_name)(char *buf, int buflen);
 | 
			
		||||
 | 
			
		||||
	int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
 | 
			
		||||
	int (*sync_unlock) (const char *resource, int lockid);
 | 
			
		||||
 | 
			
		||||
@@ -56,15 +58,19 @@ struct cluster_ops *init_gulm_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CMAN
 | 
			
		||||
#  include "cnxman-socket.h"
 | 
			
		||||
#  include <netinet/in.h>
 | 
			
		||||
#  include "libcman.h"
 | 
			
		||||
#  define CMAN_MAX_CSID_LEN 4
 | 
			
		||||
#  ifndef MAX_CSID_LEN
 | 
			
		||||
#    define MAX_CSID_LEN CMAN_MAX_CSID_LEN
 | 
			
		||||
#  endif
 | 
			
		||||
#  undef MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#  define MAX_CLUSTER_MEMBER_NAME_LEN	CMAN_MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#  define MAX_CLUSTER_MEMBER_NAME_LEN   CMAN_MAX_NODENAME_LEN
 | 
			
		||||
#  define CMAN_MAX_CLUSTER_MESSAGE 1500
 | 
			
		||||
#  define CLUSTER_PORT_CLVMD 11
 | 
			
		||||
struct cluster_ops *init_cman_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -973,6 +973,12 @@ static int _cluster_send_message(void *buf, int msglen, char *csid, const char *
 | 
			
		||||
	return gulm_cluster_send_message(buf, msglen, csid, errtext);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_cluster_name(char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	strncpy(buf, cluster_name, buflen);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops _cluster_gulm_ops = {
 | 
			
		||||
	.cluster_init_completed   = NULL,
 | 
			
		||||
	.cluster_send_message     = _cluster_send_message,
 | 
			
		||||
@@ -987,6 +993,7 @@ static struct cluster_ops _cluster_gulm_ops = {
 | 
			
		||||
	.add_up_node              = gulm_add_up_node,
 | 
			
		||||
	.reread_config            = _reread_config,
 | 
			
		||||
	.cluster_closedown        = _cluster_closedown,
 | 
			
		||||
	.get_cluster_name         = _get_cluster_name,
 | 
			
		||||
	.sync_lock                = _sync_lock,
 | 
			
		||||
	.sync_unlock              = _sync_unlock,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,7 @@
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "version.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "refresh_clvmd.h"
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
#include "system-lv.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
@@ -66,7 +67,7 @@ static struct local_client local_client_head;
 | 
			
		||||
 | 
			
		||||
static unsigned short global_xid = 0;	/* Last transaction ID issued */
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops *clops = NULL;
 | 
			
		||||
struct cluster_ops *clops = NULL;
 | 
			
		||||
 | 
			
		||||
static char our_csid[MAX_CSID_LEN];
 | 
			
		||||
static unsigned max_csid_len;
 | 
			
		||||
@@ -143,6 +144,7 @@ static void usage(char *prog, FILE *file)
 | 
			
		||||
	fprintf(file, "   -V       Show version of clvmd\n");
 | 
			
		||||
	fprintf(file, "   -h       Show this help information\n");
 | 
			
		||||
	fprintf(file, "   -d       Don't fork, run in the foreground\n");
 | 
			
		||||
	fprintf(file, "   -R       Tell all running clvmds in the cluster to reload their device cache\n");
 | 
			
		||||
	fprintf(file, "   -t<secs> Command timeout (default 60 seconds)\n");
 | 
			
		||||
	fprintf(file, "\n");
 | 
			
		||||
}
 | 
			
		||||
@@ -173,7 +175,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
	/* Deal with command-line arguments */
 | 
			
		||||
	opterr = 0;
 | 
			
		||||
	optind = 0;
 | 
			
		||||
	while ((opt = getopt(argc, argv, "?vVhdt:")) != EOF) {
 | 
			
		||||
	while ((opt = getopt(argc, argv, "?vVhdt:R")) != EOF) {
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
		case 'h':
 | 
			
		||||
			usage(argv[0], stdout);
 | 
			
		||||
@@ -183,6 +185,9 @@ int main(int argc, char *argv[])
 | 
			
		||||
			usage(argv[0], stderr);
 | 
			
		||||
			exit(0);
 | 
			
		||||
 | 
			
		||||
		case 'R':
 | 
			
		||||
			return refresh_clvmd();
 | 
			
		||||
 | 
			
		||||
		case 'd':
 | 
			
		||||
			debug++;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -247,7 +252,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
	if ((clops = init_cman_cluster())) {
 | 
			
		||||
		max_csid_len = CMAN_MAX_CSID_LEN;
 | 
			
		||||
		max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
 | 
			
		||||
		max_cluster_member_name_len = CMAN_MAX_CLUSTER_MEMBER_NAME_LEN;
 | 
			
		||||
		max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
 | 
			
		||||
		syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -509,6 +514,7 @@ static void main_loop(int local_sock, int cmd_timeout)
 | 
			
		||||
		int quorate = clops->is_quorate();
 | 
			
		||||
 | 
			
		||||
		/* Wait on the cluster FD and all local sockets/pipes */
 | 
			
		||||
		local_client_head.fd = clops->get_main_cluster_fd();
 | 
			
		||||
		FD_ZERO(&in);
 | 
			
		||||
		for (thisfd = &local_client_head; thisfd != NULL;
 | 
			
		||||
		     thisfd = thisfd->next) {
 | 
			
		||||
@@ -1683,6 +1689,7 @@ static void *lvm_thread_fn(void *arg)
 | 
			
		||||
		}
 | 
			
		||||
		pthread_mutex_unlock(&lvm_thread_mutex);
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Pass down some work to the LVM thread */
 | 
			
		||||
 
 | 
			
		||||
@@ -45,16 +45,23 @@
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
#include "defaults.h"
 | 
			
		||||
 | 
			
		||||
static struct cmd_context *cmd = NULL;
 | 
			
		||||
static struct dm_hash_table *lv_hash = NULL;
 | 
			
		||||
static pthread_mutex_t lv_hash_lock;
 | 
			
		||||
static char last_error[1024];
 | 
			
		||||
 | 
			
		||||
struct lv_info {
 | 
			
		||||
	int lock_id;
 | 
			
		||||
	int lock_mode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
char *get_last_lvm_error()
 | 
			
		||||
{
 | 
			
		||||
	return last_error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return the mode a lock is currently held at (or -1 if not held) */
 | 
			
		||||
static int get_current_lock(char *resource)
 | 
			
		||||
{
 | 
			
		||||
@@ -200,8 +207,17 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
 | 
			
		||||
	/* Try to get the lock if it's a clustered volume group */
 | 
			
		||||
	if (lock_flags & LCK_CLUSTER_VG) {
 | 
			
		||||
		status = hold_lock(resource, mode, LKF_NOQUEUE);
 | 
			
		||||
		if (status)
 | 
			
		||||
		if (status) {
 | 
			
		||||
			/* Return an LVM-sensible error for this.
 | 
			
		||||
			 * Forcing EIO makes the upper level return this text
 | 
			
		||||
			 * rather than the strerror text for EAGAIN.
 | 
			
		||||
			 */
 | 
			
		||||
			if (errno == EAGAIN) {
 | 
			
		||||
				sprintf(last_error, "Volume is busy on another node");
 | 
			
		||||
				errno = EIO;
 | 
			
		||||
			}
 | 
			
		||||
			return errno;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If it's suspended then resume it */
 | 
			
		||||
@@ -303,6 +319,15 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_PARTIAL_MODE)
 | 
			
		||||
		init_partial(1);
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
 | 
			
		||||
		init_mirror_in_sync(1);
 | 
			
		||||
 | 
			
		||||
	if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
 | 
			
		||||
		init_dmeventd_register(0);
 | 
			
		||||
 | 
			
		||||
	switch (command) {
 | 
			
		||||
	case LCK_LV_EXCLUSIVE:
 | 
			
		||||
		status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
 | 
			
		||||
@@ -331,6 +356,15 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_PARTIAL_MODE)
 | 
			
		||||
		init_partial(0);
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
 | 
			
		||||
		init_mirror_in_sync(0);
 | 
			
		||||
 | 
			
		||||
	if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
 | 
			
		||||
		init_dmeventd_register(DEFAULT_DMEVENTD_MONITOR);
 | 
			
		||||
 | 
			
		||||
	/* clean the pool for another command */
 | 
			
		||||
	dm_pool_empty(cmd->mem);
 | 
			
		||||
 | 
			
		||||
@@ -397,6 +431,13 @@ int do_check_lvm1(char *vgname)
 | 
			
		||||
	return status == 1 ? 0 : EBUSY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int do_refresh_cache()
 | 
			
		||||
{
 | 
			
		||||
	DEBUGLOG("Refreshing context\n");
 | 
			
		||||
	log_notice("Refreshing context");
 | 
			
		||||
	return refresh_toolcontext(cmd)==1?0:-1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
 | 
			
		||||
   that might be hanging around if we died for any reason
 | 
			
		||||
@@ -486,12 +527,26 @@ static void *get_initial_state()
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void lvm2_log_fn(int level, const char *file, int line,
 | 
			
		||||
			const char *message)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * Ignore non-error messages, but store the latest one for returning 
 | 
			
		||||
	 * to the user.
 | 
			
		||||
	 */
 | 
			
		||||
	if (level != _LOG_ERR && level != _LOG_FATAL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	strncpy(last_error, message, sizeof(last_error));
 | 
			
		||||
	last_error[sizeof(last_error)-1] = '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This checks some basic cluster-LVM configuration stuff */
 | 
			
		||||
static void check_config()
 | 
			
		||||
{
 | 
			
		||||
	int locking_type;
 | 
			
		||||
 | 
			
		||||
	locking_type = find_config_int(cmd->cft->root, "global/locking_type", 1);
 | 
			
		||||
	locking_type = find_config_tree_int(cmd, "global/locking_type", 1);
 | 
			
		||||
 | 
			
		||||
	if (locking_type == 3) /* compiled-in cluster support */
 | 
			
		||||
		return;
 | 
			
		||||
@@ -499,7 +554,7 @@ static void check_config()
 | 
			
		||||
	if (locking_type == 2) { /* External library, check name */
 | 
			
		||||
		const char *libname;
 | 
			
		||||
 | 
			
		||||
		libname = find_config_str(cmd->cft->root, "global/locking_library",
 | 
			
		||||
		libname = find_config_tree_str(cmd, "global/locking_library",
 | 
			
		||||
					  "");
 | 
			
		||||
		if (strstr(libname, "liblvm2clusterlock.so"))
 | 
			
		||||
			return;
 | 
			
		||||
@@ -520,7 +575,7 @@ void init_lvhash()
 | 
			
		||||
/* Called to initialise the LVM context of the daemon */
 | 
			
		||||
int init_lvm(int using_gulm)
 | 
			
		||||
{
 | 
			
		||||
	if (!(cmd = create_toolcontext(NULL))) {
 | 
			
		||||
	if (!(cmd = create_toolcontext(NULL, 0))) {
 | 
			
		||||
		log_error("Failed to allocate command context");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -538,5 +593,8 @@ int init_lvm(int using_gulm)
 | 
			
		||||
 | 
			
		||||
	get_initial_state();
 | 
			
		||||
 | 
			
		||||
	/* Trap log messages so we can pass them back to the user */
 | 
			
		||||
	init_log_fn(lvm2_log_fn);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,11 +25,13 @@ extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
 | 
			
		||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
 | 
			
		||||
			char *resource);
 | 
			
		||||
extern int do_check_lvm1(char *vgname);
 | 
			
		||||
extern int do_refresh_cache(void);
 | 
			
		||||
extern int init_lvm(int using_gulm);
 | 
			
		||||
extern void init_lvhash(void);
 | 
			
		||||
 | 
			
		||||
extern int hold_unlock(char *resource);
 | 
			
		||||
extern int hold_lock(char *resource, int mode, int flags);
 | 
			
		||||
extern void unlock_all(void);
 | 
			
		||||
extern char *get_last_lvm_error(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										334
									
								
								daemons/clvmd/refresh_clvmd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								daemons/clvmd/refresh_clvmd.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,334 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Tell all clvmds in a cluster to refresh their toolcontext
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "refresh_clvmd.h"
 | 
			
		||||
 | 
			
		||||
typedef struct lvm_response {
 | 
			
		||||
	char node[255];
 | 
			
		||||
	char *response;
 | 
			
		||||
	int status;
 | 
			
		||||
	int len;
 | 
			
		||||
} lvm_response_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This gets stuck at the start of memory we allocate so we
 | 
			
		||||
 * can sanity-check it at deallocation time
 | 
			
		||||
 */
 | 
			
		||||
#define LVM_SIGNATURE 0x434C564D
 | 
			
		||||
 | 
			
		||||
static int _clvmd_sock = -1;
 | 
			
		||||
 | 
			
		||||
/* Open connection to the Cluster Manager daemon */
 | 
			
		||||
static int _open_local_sock(void)
 | 
			
		||||
{
 | 
			
		||||
	int local_socket;
 | 
			
		||||
	struct sockaddr_un sockaddr;
 | 
			
		||||
 | 
			
		||||
	/* Open local socket */
 | 
			
		||||
	if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
 | 
			
		||||
		fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&sockaddr, 0, sizeof(sockaddr));
 | 
			
		||||
	memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
 | 
			
		||||
 | 
			
		||||
	sockaddr.sun_family = AF_UNIX;
 | 
			
		||||
 | 
			
		||||
	if (connect(local_socket,(struct sockaddr *) &sockaddr,
 | 
			
		||||
		    sizeof(sockaddr))) {
 | 
			
		||||
		int saved_errno = errno;
 | 
			
		||||
 | 
			
		||||
		fprintf(stderr, "connect() failed on local socket: %s\n",
 | 
			
		||||
			  strerror(errno));
 | 
			
		||||
		if (close(local_socket))
 | 
			
		||||
			return -1;
 | 
			
		||||
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return local_socket;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Send a request and return the status */
 | 
			
		||||
static int _send_request(char *inbuf, int inlen, char **retbuf)
 | 
			
		||||
{
 | 
			
		||||
	char outbuf[PIPE_BUF];
 | 
			
		||||
	struct clvm_header *outheader = (struct clvm_header *) outbuf;
 | 
			
		||||
	int len;
 | 
			
		||||
	int off;
 | 
			
		||||
	int buflen;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	/* Send it to CLVMD */
 | 
			
		||||
 rewrite:
 | 
			
		||||
	if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
 | 
			
		||||
	        if (err == -1 && errno == EINTR)
 | 
			
		||||
		        goto rewrite;
 | 
			
		||||
		fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the response */
 | 
			
		||||
 reread:
 | 
			
		||||
	if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
 | 
			
		||||
	        if (errno == EINTR)
 | 
			
		||||
		        goto reread;
 | 
			
		||||
		fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (len == 0) {
 | 
			
		||||
		fprintf(stderr, "EOF reading CLVMD");
 | 
			
		||||
		errno = ENOTCONN;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Allocate buffer */
 | 
			
		||||
	buflen = len + outheader->arglen;
 | 
			
		||||
	*retbuf = dm_malloc(buflen);
 | 
			
		||||
	if (!*retbuf) {
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Copy the header */
 | 
			
		||||
	memcpy(*retbuf, outbuf, len);
 | 
			
		||||
	outheader = (struct clvm_header *) *retbuf;
 | 
			
		||||
 | 
			
		||||
	/* Read the returned values */
 | 
			
		||||
	off = 1;		/* we've already read the first byte */
 | 
			
		||||
	while (off <= outheader->arglen && len > 0) {
 | 
			
		||||
		len = read(_clvmd_sock, outheader->args + off,
 | 
			
		||||
			   buflen - off - offsetof(struct clvm_header, args));
 | 
			
		||||
		if (len > 0)
 | 
			
		||||
			off += len;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Was it an error ? */
 | 
			
		||||
	if (outheader->status != 0) {
 | 
			
		||||
		errno = outheader->status;
 | 
			
		||||
 | 
			
		||||
		/* Only return an error here if there are no node-specific
 | 
			
		||||
		   errors present in the message that might have more detail */
 | 
			
		||||
		if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
 | 
			
		||||
			fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Build the structure header and parse-out wildcard node names */
 | 
			
		||||
static void _build_header(struct clvm_header *head, int cmd, const char *node,
 | 
			
		||||
			  int len)
 | 
			
		||||
{
 | 
			
		||||
	head->cmd = cmd;
 | 
			
		||||
	head->status = 0;
 | 
			
		||||
	head->flags = 0;
 | 
			
		||||
	head->clientid = 0;
 | 
			
		||||
	head->arglen = len;
 | 
			
		||||
 | 
			
		||||
	if (node) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Allow a couple of special node names:
 | 
			
		||||
		 * "*" for all nodes,
 | 
			
		||||
		 * "." for the local node only
 | 
			
		||||
		 */
 | 
			
		||||
		if (strcmp(node, "*") == 0) {
 | 
			
		||||
			head->node[0] = '\0';
 | 
			
		||||
		} else if (strcmp(node, ".") == 0) {
 | 
			
		||||
			head->node[0] = '\0';
 | 
			
		||||
			head->flags = CLVMD_FLAG_LOCAL;
 | 
			
		||||
		} else
 | 
			
		||||
			strcpy(head->node, node);
 | 
			
		||||
	} else
 | 
			
		||||
		head->node[0] = '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Send a message to a(or all) node(s) in the cluster and wait for replies
 | 
			
		||||
 */
 | 
			
		||||
static int _cluster_request(char cmd, const char *node, void *data, int len,
 | 
			
		||||
			   lvm_response_t ** response, int *num)
 | 
			
		||||
{
 | 
			
		||||
	char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
 | 
			
		||||
	int *outptr;
 | 
			
		||||
	char *inptr;
 | 
			
		||||
	char *retbuf = NULL;
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
	int num_responses = 0;
 | 
			
		||||
	struct clvm_header *head = (struct clvm_header *) outbuf;
 | 
			
		||||
	lvm_response_t *rarray;
 | 
			
		||||
 | 
			
		||||
	*num = 0;
 | 
			
		||||
 | 
			
		||||
	if (_clvmd_sock == -1)
 | 
			
		||||
		_clvmd_sock = _open_local_sock();
 | 
			
		||||
 | 
			
		||||
	if (_clvmd_sock == -1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	_build_header(head, cmd, node, len);
 | 
			
		||||
	memcpy(head->node + strlen(head->node) + 1, data, len);
 | 
			
		||||
 | 
			
		||||
	status = _send_request(outbuf, sizeof(struct clvm_header) +
 | 
			
		||||
			      strlen(head->node) + len, &retbuf);
 | 
			
		||||
	if (!status)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	/* Count the number of responses we got */
 | 
			
		||||
	head = (struct clvm_header *) retbuf;
 | 
			
		||||
	inptr = head->args;
 | 
			
		||||
	while (inptr[0]) {
 | 
			
		||||
		num_responses++;
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
		inptr += sizeof(int);
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Allocate response array.
 | 
			
		||||
	 * With an extra pair of INTs on the front to sanity
 | 
			
		||||
	 * check the pointer when we are given it back to free
 | 
			
		||||
	 */
 | 
			
		||||
	outptr = dm_malloc(sizeof(lvm_response_t) * num_responses +
 | 
			
		||||
			    sizeof(int) * 2);
 | 
			
		||||
	if (!outptr) {
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		status = 0;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*response = (lvm_response_t *) (outptr + 2);
 | 
			
		||||
	outptr[0] = LVM_SIGNATURE;
 | 
			
		||||
	outptr[1] = num_responses;
 | 
			
		||||
	rarray = *response;
 | 
			
		||||
 | 
			
		||||
	/* Unpack the response into an lvm_response_t array */
 | 
			
		||||
	inptr = head->args;
 | 
			
		||||
	i = 0;
 | 
			
		||||
	while (inptr[0]) {
 | 
			
		||||
		strcpy(rarray[i].node, inptr);
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
 | 
			
		||||
		memcpy(&rarray[i].status, inptr, sizeof(int));
 | 
			
		||||
		inptr += sizeof(int);
 | 
			
		||||
 | 
			
		||||
		rarray[i].response = dm_malloc(strlen(inptr) + 1);
 | 
			
		||||
		if (rarray[i].response == NULL) {
 | 
			
		||||
			/* Free up everything else and return error */
 | 
			
		||||
			int j;
 | 
			
		||||
			for (j = 0; j < i; j++)
 | 
			
		||||
				dm_free(rarray[i].response);
 | 
			
		||||
			free(outptr);
 | 
			
		||||
			errno = ENOMEM;
 | 
			
		||||
			status = -1;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		strcpy(rarray[i].response, inptr);
 | 
			
		||||
		rarray[i].len = strlen(inptr);
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
		i++;
 | 
			
		||||
	}
 | 
			
		||||
	*num = num_responses;
 | 
			
		||||
	*response = rarray;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (retbuf)
 | 
			
		||||
		dm_free(retbuf);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Free reply array */
 | 
			
		||||
static int _cluster_free_request(lvm_response_t * response)
 | 
			
		||||
{
 | 
			
		||||
	int *ptr = (int *) response - 2;
 | 
			
		||||
	int i;
 | 
			
		||||
	int num;
 | 
			
		||||
 | 
			
		||||
	/* Check it's ours to free */
 | 
			
		||||
	if (response == NULL || *ptr != LVM_SIGNATURE) {
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	num = ptr[1];
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num; i++) {
 | 
			
		||||
		dm_free(response[i].response);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_free(ptr);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int refresh_clvmd()
 | 
			
		||||
{
 | 
			
		||||
	int num_responses;
 | 
			
		||||
	char args[1]; // No args really.
 | 
			
		||||
	lvm_response_t *response;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	status = _cluster_request(CLVMD_CMD_REFRESH, "*", args, 0, &response, &num_responses);
 | 
			
		||||
 | 
			
		||||
	/* If any nodes were down then display them and return an error */
 | 
			
		||||
	for (i = 0; i < num_responses; i++) {
 | 
			
		||||
		if (response[i].status == EHOSTDOWN) {
 | 
			
		||||
			fprintf(stderr, "clvmd not running on node %s",
 | 
			
		||||
				  response[i].node);
 | 
			
		||||
			status = 0;
 | 
			
		||||
			errno = response[i].status;
 | 
			
		||||
		} else if (response[i].status) {
 | 
			
		||||
			fprintf(stderr, "Error resetting node %s: %s",
 | 
			
		||||
				  response[i].node,
 | 
			
		||||
				  response[i].response[0] ?
 | 
			
		||||
				  	response[i].response :
 | 
			
		||||
				  	strerror(response[i].status));
 | 
			
		||||
			status = 0;
 | 
			
		||||
			errno = response[i].status;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	saved_errno = errno;
 | 
			
		||||
	_cluster_free_request(response);
 | 
			
		||||
	errno = saved_errno;
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								daemons/clvmd/refresh_clvmd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								daemons/clvmd/refresh_clvmd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
int refresh_clvmd(void);
 | 
			
		||||
 | 
			
		||||
@@ -57,7 +57,7 @@ int init_comms(unsigned short port)
 | 
			
		||||
    struct sockaddr_in6 addr;
 | 
			
		||||
 | 
			
		||||
    sock_hash = dm_hash_create(100);
 | 
			
		||||
    tcp_port = port ? port : DEFAULT_TCP_PORT;
 | 
			
		||||
    tcp_port = port ? : DEFAULT_TCP_PORT;
 | 
			
		||||
 | 
			
		||||
    listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
dm_event_register
 | 
			
		||||
dm_event_unregister
 | 
			
		||||
dm_event_get_registered_device
 | 
			
		||||
dm_event_set_timeout
 | 
			
		||||
dm_event_get_timeout
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,13 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the device-mapper userspace tools.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU General Public License v.2.
 | 
			
		||||
# of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
@@ -16,36 +15,59 @@ srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
TARGETS = dmevent dmeventd
 | 
			
		||||
INSTALL_TYPE = install_dynamic
 | 
			
		||||
SOURCES = libdevmapper-event.c \
 | 
			
		||||
	  dmeventd.c
 | 
			
		||||
 | 
			
		||||
SOURCES = noop.c
 | 
			
		||||
CLEAN_TARGETS = dmevent.o dmeventd.o
 | 
			
		||||
LIB_STATIC = libdevmapper-event.a
 | 
			
		||||
 | 
			
		||||
ifeq ("@LIB_SUFFIX@","dylib")
 | 
			
		||||
  LIB_SHARED = libdmeventdnoop.dylib
 | 
			
		||||
  LIB_SHARED = libdevmapper-event.dylib
 | 
			
		||||
else
 | 
			
		||||
  LIB_SHARED = libdmeventdnoop.so
 | 
			
		||||
  LIB_SHARED = libdevmapper-event.so
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
LDFLAGS += -ldl -ldevmapper -lmultilog
 | 
			
		||||
 | 
			
		||||
include ../make.tmpl
 | 
			
		||||
 | 
			
		||||
libdmeventdnoop.so: noop.o
 | 
			
		||||
CLDFLAGS += -ldl -ldevmapper -lpthread
 | 
			
		||||
 | 
			
		||||
dmevent: dmevent.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
 | 
			
		||||
	$(CC) -o $@ dmevent.o $(LDFLAGS) \
 | 
			
		||||
	      -L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog $(LIBS)
 | 
			
		||||
.PHONY: install_dynamic install_static install_include \
 | 
			
		||||
	install_pkgconfig
 | 
			
		||||
 | 
			
		||||
dmeventd: dmeventd.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
 | 
			
		||||
	$(CC) -o $@ dmeventd.o $(LDFLAGS) \
 | 
			
		||||
	      -L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -lpthread -ldmevent $(LIBS)
 | 
			
		||||
INSTALL_TYPE = install_dynamic
 | 
			
		||||
 | 
			
		||||
install: $(INSTALL_TYPE)
 | 
			
		||||
ifeq ("@STATIC_LINK@", "yes")
 | 
			
		||||
  INSTALL_TYPE += install_static
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
.PHONY: install_dynamic
 | 
			
		||||
ifeq ("@PKGCONFIG@", "yes")
 | 
			
		||||
  INSTALL_TYPE += install_pkgconfig
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
install_dynamic: dmeventd
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) dmeventd $(sbindir)/dmeventd
 | 
			
		||||
install: $(INSTALL_TYPE) install_include
 | 
			
		||||
 | 
			
		||||
install_include:
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \
 | 
			
		||||
		$(includedir)/libdevmapper-event.h
 | 
			
		||||
 | 
			
		||||
install_dynamic: libdevmapper-event.$(LIB_SUFFIX)
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \
 | 
			
		||||
		$(libdir)/libdevmapper-event.$(LIB_SUFFIX)
 | 
			
		||||
 | 
			
		||||
install_pkgconfig:
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \
 | 
			
		||||
		$(usrlibdir)/pkgconfig/devmapper-event.pc
 | 
			
		||||
 | 
			
		||||
install_static: libdevmapper-event.a
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
 | 
			
		||||
 | 
			
		||||
.PHONY: distclean_lib distclean
 | 
			
		||||
 | 
			
		||||
distclean_lib: 
 | 
			
		||||
	$(RM) libdevmapper-event.pc
 | 
			
		||||
 | 
			
		||||
distclean: distclean_lib
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,240 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the device-mapper userspace tools.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "libdm-event.h"
 | 
			
		||||
#include "libmultilog.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/file.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
static enum event_type events = ALL_ERRORS; /* All until we can distinguish. */
 | 
			
		||||
static char default_dso_name[] = "noop";  /* default DSO is noop */
 | 
			
		||||
static int default_reg = 1;		 /* default action is register */
 | 
			
		||||
static uint32_t timeout;
 | 
			
		||||
 | 
			
		||||
struct event_ops {
 | 
			
		||||
int (*dm_register_for_event)(char *dso_name, char *device,
 | 
			
		||||
			     enum event_type event_types);
 | 
			
		||||
int (*dm_unregister_for_event)(char *dso_name, char *device,
 | 
			
		||||
			       enum event_type event_types);
 | 
			
		||||
int (*dm_get_registered_device)(char **dso_name, char **device,
 | 
			
		||||
				enum event_type *event_types, int next);
 | 
			
		||||
int (*dm_set_event_timeout)(char *device, uint32_t time);
 | 
			
		||||
int (*dm_get_event_timeout)(char *device, uint32_t *time);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Display help. */
 | 
			
		||||
static void print_usage(char *name)
 | 
			
		||||
{
 | 
			
		||||
	char *cmd = strrchr(name, '/');
 | 
			
		||||
 | 
			
		||||
	cmd = cmd ? cmd + 1 : name;
 | 
			
		||||
	printf("Usage::\n"
 | 
			
		||||
	       "%s [options] <device>\n"
 | 
			
		||||
	       "\n"
 | 
			
		||||
	       "Options:\n"
 | 
			
		||||
	       "  -d <dso>           Specify the DSO to use.\n"
 | 
			
		||||
	       "  -h                 Print this usage.\n"
 | 
			
		||||
	       "  -l                 List registered devices.\n"
 | 
			
		||||
	       "  -r                 Register for event (default).\n"
 | 
			
		||||
	       "  -t <timeout>       (un)register for timeout event.\n"
 | 
			
		||||
	       "  -u                 Unregister for event.\n"
 | 
			
		||||
	       "\n", cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Parse command line arguments. */
 | 
			
		||||
static int parse_argv(int argc, char **argv, char **dso_name_arg,
 | 
			
		||||
		      char **device_arg, int *reg, int *list)
 | 
			
		||||
{
 | 
			
		||||
	int c;
 | 
			
		||||
	const char *options = "d:hlrt:u";
 | 
			
		||||
 | 
			
		||||
	while ((c = getopt(argc, argv, options)) != -1) {
 | 
			
		||||
		switch (c) {
 | 
			
		||||
		case 'd':
 | 
			
		||||
			*dso_name_arg = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'h':
 | 
			
		||||
			print_usage(argv[0]);
 | 
			
		||||
			exit(EXIT_SUCCESS);
 | 
			
		||||
		case 'l':
 | 
			
		||||
			*list = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'r':
 | 
			
		||||
			*reg = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 't':
 | 
			
		||||
			events = TIMEOUT;
 | 
			
		||||
			if (sscanf(optarg, "%"SCNu32, &timeout) != 1){
 | 
			
		||||
				fprintf(stderr, "invalid timeout '%s'\n",
 | 
			
		||||
					optarg);
 | 
			
		||||
				timeout = 0;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 'u':
 | 
			
		||||
			*reg = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			fprintf(stderr, "Unknown option '%c'.\n"
 | 
			
		||||
				"Try '-h' for help.\n", c);
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (optind >= argc) {
 | 
			
		||||
		if (!*list) {
 | 
			
		||||
			fprintf(stderr, "You need to specify a device.\n");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	} else 
 | 
			
		||||
		*device_arg = argv[optind];
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int lookup_symbol(void *dl, void **symbol, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	if ((*symbol = dlsym(dl, name)))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	fprintf(stderr, "error looking up %s symbol: %s\n", name, dlerror());
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int lookup_symbols(void *dl, struct event_ops *e)
 | 
			
		||||
{
 | 
			
		||||
	return lookup_symbol(dl, (void *) &e->dm_register_for_event,
 | 
			
		||||
			     "dm_register_for_event") &&
 | 
			
		||||
	       lookup_symbol(dl, (void *) &e->dm_unregister_for_event,
 | 
			
		||||
			     "dm_unregister_for_event") &&
 | 
			
		||||
	       lookup_symbol(dl, (void *) &e->dm_get_registered_device,
 | 
			
		||||
			     "dm_get_registered_device") &&
 | 
			
		||||
	       lookup_symbol(dl, (void *) &e->dm_set_event_timeout,
 | 
			
		||||
			     "dm_set_event_timeout") &&
 | 
			
		||||
	       lookup_symbol(dl, (void *) &e->dm_get_event_timeout,
 | 
			
		||||
			     "dm_get_event_timeout");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	void *dl;
 | 
			
		||||
	struct event_ops e;
 | 
			
		||||
	int list = 0, next = 0, ret, reg = default_reg;
 | 
			
		||||
	char *device, *device_arg = NULL, *dso_name, *dso_name_arg = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!parse_argv(argc, argv, &dso_name_arg, &device_arg, ®, &list))
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
	if (device_arg) {
 | 
			
		||||
		if (!(device = strdup(device_arg)))
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
	} else
 | 
			
		||||
		device = NULL;
 | 
			
		||||
 | 
			
		||||
	if (dso_name_arg) {
 | 
			
		||||
		if (!(dso_name = strdup(dso_name_arg)))
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!(dso_name = strdup(default_dso_name)))
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME: use -v/-q options to set this */
 | 
			
		||||
	multilog_add_type(standard, NULL);
 | 
			
		||||
	multilog_init_verbose(standard, _LOG_DEBUG);
 | 
			
		||||
 | 
			
		||||
	if (!(dl = dlopen("libdmevent.so", RTLD_NOW))){
 | 
			
		||||
		fprintf(stderr, "Cannot dlopen libdmevent.so: %s\n", dlerror());
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(lookup_symbols(dl, &e)))
 | 
			
		||||
		goto out;
 | 
			
		||||
	if (list) {
 | 
			
		||||
		while (1) {
 | 
			
		||||
			if ((ret= e.dm_get_registered_device(&dso_name,
 | 
			
		||||
							     &device,
 | 
			
		||||
							     &events, next)))
 | 
			
		||||
				break;
 | 
			
		||||
			printf("%s %s 0x%x", dso_name, device, events);
 | 
			
		||||
			if (events & TIMEOUT){
 | 
			
		||||
				if ((ret = e.dm_get_event_timeout(device,
 | 
			
		||||
							  	  &timeout))) {
 | 
			
		||||
					ret = EXIT_FAILURE;
 | 
			
		||||
					goto out;
 | 
			
		||||
				}
 | 
			
		||||
				printf(" %"PRIu32"\n", timeout);
 | 
			
		||||
			} else
 | 
			
		||||
				printf("\n");
 | 
			
		||||
			if (device_arg)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			next = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = (ret && device_arg) ? EXIT_FAILURE : EXIT_SUCCESS;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ret = reg ? e.dm_register_for_event(dso_name, device, events) :
 | 
			
		||||
			 e.dm_unregister_for_event(dso_name, device, events))) {
 | 
			
		||||
		fprintf(stderr, "Failed to %sregister %s: %s\n",
 | 
			
		||||
			reg ? "": "un", device, strerror(-ret));
 | 
			
		||||
		ret = EXIT_FAILURE;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (reg && (events & TIMEOUT) &&
 | 
			
		||||
		    ((ret = e.dm_set_event_timeout(device, timeout)))){
 | 
			
		||||
			fprintf(stderr, "Failed to set timeout for %s: %s\n",
 | 
			
		||||
				device, strerror(-ret));
 | 
			
		||||
			ret = EXIT_FAILURE;
 | 
			
		||||
		} else {
 | 
			
		||||
			printf("%s %sregistered successfully.\n",
 | 
			
		||||
			       device, reg ? "" : "un");
 | 
			
		||||
			ret = EXIT_SUCCESS;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
   out:
 | 
			
		||||
	multilog_del_type(standard);
 | 
			
		||||
 | 
			
		||||
	if (device)
 | 
			
		||||
		free(device);
 | 
			
		||||
	if (dso_name)
 | 
			
		||||
		free(dso_name);
 | 
			
		||||
 | 
			
		||||
	exit(ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Overrides for Emacs so that we follow Linus's tabbing style.
 | 
			
		||||
 * Emacs will notice this stuff at the end of the file and automatically
 | 
			
		||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
			
		||||
 * of the file.
 | 
			
		||||
 * ---------------------------------------------------------------------------
 | 
			
		||||
 * Local variables:
 | 
			
		||||
 * c-file-style: "linux"
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										13
									
								
								daemons/dmeventd/dmeventd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								daemons/dmeventd/dmeventd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#ifndef __DMEVENTD_DOT_H__
 | 
			
		||||
#define __DMEVENTD_DOT_H__
 | 
			
		||||
 | 
			
		||||
#define EXIT_LOCKFILE_INUSE      2
 | 
			
		||||
#define EXIT_DESC_CLOSE_FAILURE  3
 | 
			
		||||
#define EXIT_OPEN_PID_FAILURE    4
 | 
			
		||||
#define EXIT_FIFO_FAILURE        5
 | 
			
		||||
#define EXIT_CHDIR_FAILURE       6
 | 
			
		||||
 | 
			
		||||
void dmeventd(void)
 | 
			
		||||
    __attribute((noreturn));
 | 
			
		||||
 | 
			
		||||
#endif /* __DMEVENTD_DOT_H__ */
 | 
			
		||||
							
								
								
									
										510
									
								
								daemons/dmeventd/libdevmapper-event.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								daemons/dmeventd/libdevmapper-event.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,510 @@
 | 
			
		||||
 /*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the device-mapper userspace tools.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
//#include "libmultilog.h"
 | 
			
		||||
#include "dmeventd.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/file.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
/* Set by any of the external fxns the first time one of them is called */
 | 
			
		||||
/* FIXME Unused */
 | 
			
		||||
// static int _logging = 0;
 | 
			
		||||
 | 
			
		||||
/* Fetch a string off src and duplicate it into *dest. */
 | 
			
		||||
/* FIXME: move to seperate module to share with the daemon. */
 | 
			
		||||
static const char delimiter = ' ';
 | 
			
		||||
static char *fetch_string(char **src)
 | 
			
		||||
{
 | 
			
		||||
	char *p, *ret;
 | 
			
		||||
 | 
			
		||||
	if ((p = strchr(*src, delimiter)))
 | 
			
		||||
		*p = 0;
 | 
			
		||||
 | 
			
		||||
	if ((ret = dm_strdup(*src)))
 | 
			
		||||
		*src += strlen(ret) + 1;
 | 
			
		||||
 | 
			
		||||
	if (p)
 | 
			
		||||
		*p = delimiter;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Parse a device message from the daemon. */
 | 
			
		||||
static int parse_message(struct dm_event_daemon_message *msg, char **dso_name,
 | 
			
		||||
			 char **device, enum dm_event_type *events)
 | 
			
		||||
{
 | 
			
		||||
	char *p = msg->msg;
 | 
			
		||||
 | 
			
		||||
	if ((*dso_name = fetch_string(&p)) &&
 | 
			
		||||
	    (*device   = fetch_string(&p))) {
 | 
			
		||||
		*events = atoi(p);
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -ENOMEM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * daemon_read
 | 
			
		||||
 * @fifos
 | 
			
		||||
 * @msg
 | 
			
		||||
 *
 | 
			
		||||
 * Read message from daemon.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 0 on failure, 1 on success
 | 
			
		||||
 */
 | 
			
		||||
static int daemon_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	unsigned bytes = 0;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	fd_set fds;
 | 
			
		||||
 | 
			
		||||
	memset(msg, 0, sizeof(*msg));
 | 
			
		||||
	while (bytes < sizeof(*msg)) {
 | 
			
		||||
		do {
 | 
			
		||||
			/* Watch daemon read FIFO for input. */
 | 
			
		||||
			FD_ZERO(&fds);
 | 
			
		||||
			FD_SET(fifos->server, &fds);
 | 
			
		||||
			ret = select(fifos->server+1, &fds, NULL, NULL, NULL);
 | 
			
		||||
			if (ret < 0 && errno != EINTR) {
 | 
			
		||||
				/* FIXME Log error */
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} while (ret < 1);
 | 
			
		||||
 | 
			
		||||
		ret = read(fifos->server, msg, sizeof(*msg) - bytes);
 | 
			
		||||
		if (ret < 0) {
 | 
			
		||||
			if ((errno == EINTR) || (errno == EAGAIN))
 | 
			
		||||
				continue;
 | 
			
		||||
			else {
 | 
			
		||||
				/* FIXME Log error */
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bytes += ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytes == sizeof(*msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Write message to daemon. */
 | 
			
		||||
static int daemon_write(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	unsigned bytes = 0;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	fd_set fds;
 | 
			
		||||
 | 
			
		||||
	while (bytes < sizeof(*msg)) {
 | 
			
		||||
		do {
 | 
			
		||||
			/* Watch daemon write FIFO to be ready for output. */
 | 
			
		||||
			FD_ZERO(&fds);
 | 
			
		||||
			FD_SET(fifos->client, &fds);
 | 
			
		||||
			ret = select(fifos->client +1, NULL, &fds, NULL, NULL);
 | 
			
		||||
			if ((ret < 0) && (errno != EINTR)) {
 | 
			
		||||
				/* FIXME Log error */
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} while (ret < 1);
 | 
			
		||||
 | 
			
		||||
		ret = write(fifos->client, msg, sizeof(*msg) - bytes);
 | 
			
		||||
		if (ret < 0) {
 | 
			
		||||
			if ((errno == EINTR) || (errno == EAGAIN))
 | 
			
		||||
				continue;
 | 
			
		||||
			else {
 | 
			
		||||
				/* fixme: log error */
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bytes += ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytes == sizeof(*msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int daemon_talk(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg,
 | 
			
		||||
		       int cmd, char *dso_name, char *device,
 | 
			
		||||
		       enum dm_event_type events, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	memset(msg, 0, sizeof(*msg));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Set command and pack the arguments
 | 
			
		||||
	 * into ASCII message string.
 | 
			
		||||
	 */
 | 
			
		||||
	msg->opcode.cmd = cmd;
 | 
			
		||||
 | 
			
		||||
	if (sizeof(msg->msg) <= (unsigned) snprintf(msg->msg, sizeof(msg->msg),
 | 
			
		||||
						    "%s %s %u %"PRIu32,
 | 
			
		||||
						    dso_name ? dso_name : "",
 | 
			
		||||
						    device ? device : "",
 | 
			
		||||
						    events, timeout)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Write command and message to and
 | 
			
		||||
	 * read status return code from daemon.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!daemon_write(fifos, msg)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!daemon_read(fifos, msg)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return msg->opcode.status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static volatile sig_atomic_t daemon_running = 0;
 | 
			
		||||
 | 
			
		||||
static void daemon_running_signal_handler(int sig)
 | 
			
		||||
{
 | 
			
		||||
	daemon_running = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * start_daemon
 | 
			
		||||
 *
 | 
			
		||||
 * This function forks off a process (dmeventd) that will handle
 | 
			
		||||
 * the events.  A signal must be returned from the child to
 | 
			
		||||
 * indicate when it is ready to handle requests.  The parent
 | 
			
		||||
 * (this function) returns 1 if there is a daemon running. 
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 1 on success, 0 otherwise
 | 
			
		||||
 */
 | 
			
		||||
static int start_daemon(void)
 | 
			
		||||
{
 | 
			
		||||
	int pid, ret=0;
 | 
			
		||||
	void *old_hand;
 | 
			
		||||
	sigset_t set, oset;
 | 
			
		||||
 | 
			
		||||
	/* Must be able to acquire signal */
 | 
			
		||||
	old_hand = signal(SIGUSR1, &daemon_running_signal_handler);
 | 
			
		||||
	if (old_hand == SIG_ERR) {
 | 
			
		||||
		log_error("Unable to setup signal handler.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sigemptyset(&set) || sigaddset(&set, SIGUSR1)) {
 | 
			
		||||
		log_error("Unable to fill signal set.");
 | 
			
		||||
	} else if (sigprocmask(SIG_UNBLOCK, &set, &oset)) {
 | 
			
		||||
		log_error("Can't unblock the potentially blocked signal SIGUSR1");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	pid = fork();
 | 
			
		||||
 | 
			
		||||
	if (pid < 0)
 | 
			
		||||
		log_error("Unable to fork.\n");
 | 
			
		||||
	else if (pid) { /* parent waits for child to get ready for requests */
 | 
			
		||||
		int status;
 | 
			
		||||
 | 
			
		||||
		/* FIXME Better way to do this? */
 | 
			
		||||
		while (!waitpid(pid, &status, WNOHANG) && !daemon_running)
 | 
			
		||||
			sleep(1);
 | 
			
		||||
 | 
			
		||||
		if (daemon_running) {
 | 
			
		||||
			ret = 1;
 | 
			
		||||
		} else {
 | 
			
		||||
			switch (WEXITSTATUS(status)) {
 | 
			
		||||
			case EXIT_LOCKFILE_INUSE:
 | 
			
		||||
				/*
 | 
			
		||||
				 * Note, this is ok... we still have daemon
 | 
			
		||||
				 * that we can communicate with...
 | 
			
		||||
				 */
 | 
			
		||||
				log_print("Starting dmeventd failed: "
 | 
			
		||||
					  "dmeventd already running.\n");
 | 
			
		||||
				ret = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				log_error("Unable to start dmeventd.\n");
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * Sometimes, a single process may perform multiple calls
 | 
			
		||||
		 * that result in a daemon starting and exiting.  If we
 | 
			
		||||
		 * don't reset this, the second (or greater) time the daemon
 | 
			
		||||
		 * is started will cause this logic not to work.
 | 
			
		||||
		 */
 | 
			
		||||
		daemon_running = 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		signal(SIGUSR1, SIG_IGN); /* don't care about error */
 | 
			
		||||
 | 
			
		||||
		/* dmeventd function is responsible for properly setting **
 | 
			
		||||
		** itself up.  It must never return - only exit.  This is**
 | 
			
		||||
		** why it is followed by an EXIT_FAILURE                 */
 | 
			
		||||
		dmeventd();
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME What if old_hand is SIG_ERR? */
 | 
			
		||||
	if (signal(SIGUSR1, old_hand) == SIG_ERR)
 | 
			
		||||
		log_error("Unable to reset signal handler.");
 | 
			
		||||
 | 
			
		||||
	if (sigprocmask(SIG_SETMASK, &oset, NULL))
 | 
			
		||||
		log_error("Unable to reset signal mask.");
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Initialize client. */
 | 
			
		||||
static int init_client(struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME Is fifo the most suitable method? */
 | 
			
		||||
	/* FIXME Why not share comms/daemon code with something else e.g. multipath? */
 | 
			
		||||
 | 
			
		||||
	/* init fifos */
 | 
			
		||||
	memset(fifos, 0, sizeof(*fifos));
 | 
			
		||||
	fifos->client_path = DM_EVENT_FIFO_CLIENT;
 | 
			
		||||
	fifos->server_path = DM_EVENT_FIFO_SERVER;
 | 
			
		||||
 | 
			
		||||
	/* FIXME The server should be responsible for these, not the client. */
 | 
			
		||||
	/* Create fifos */
 | 
			
		||||
	if (((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) ||
 | 
			
		||||
	    ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST)) {
 | 
			
		||||
		log_error("%s: Failed to create a fifo.\n", __func__);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Warn/abort if perms are wrong - not something to fix silently. */
 | 
			
		||||
	/* If they were already there, make sure permissions are ok. */
 | 
			
		||||
	if (chmod(fifos->client_path, 0600)) {
 | 
			
		||||
		log_error("Unable to set correct file permissions on %s",
 | 
			
		||||
			fifos->client_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (chmod(fifos->server_path, 0600)) {
 | 
			
		||||
		log_error("Unable to set correct file permissions on %s",
 | 
			
		||||
			fifos->server_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Open the fifo used to read from the daemon.
 | 
			
		||||
	 * Allows daemon to create its write fifo...
 | 
			
		||||
	 */
 | 
			
		||||
	if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
 | 
			
		||||
		log_error("%s: open server fifo %s\n",
 | 
			
		||||
			__func__, fifos->server_path);
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Lock out anyone else trying to do communication with the daemon. */
 | 
			
		||||
	/* FIXME Why failure not retry?  How do multiple processes communicate? */
 | 
			
		||||
	if (flock(fifos->server, LOCK_EX) < 0){
 | 
			
		||||
		log_error("%s: flock %s\n", __func__, fifos->server_path);
 | 
			
		||||
		close(fifos->server);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Anyone listening?  If not, errno will be ENXIO */
 | 
			
		||||
	while ((fifos->client = open(fifos->client_path,
 | 
			
		||||
				  O_WRONLY | O_NONBLOCK)) < 0) {
 | 
			
		||||
		if (errno != ENXIO) {
 | 
			
		||||
			log_error("%s: Can't open client fifo %s: %s\n",
 | 
			
		||||
				  __func__, fifos->client_path, strerror(errno));
 | 
			
		||||
			close(fifos->server);
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* FIXME Unnecessary if daemon was started before calling this */
 | 
			
		||||
		if (!start_daemon()) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dtr_client(struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	if (flock(fifos->server, LOCK_UN))
 | 
			
		||||
		log_error("flock unlock %s\n", fifos->server_path);
 | 
			
		||||
 | 
			
		||||
	close(fifos->client);
 | 
			
		||||
	close(fifos->server);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check, if a block device exists. */
 | 
			
		||||
static int device_exists(char *device)
 | 
			
		||||
{
 | 
			
		||||
	struct stat st_buf;
 | 
			
		||||
	char path2[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (!device)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (device[0] == '/') /* absolute path */
 | 
			
		||||
		return !stat(device, &st_buf) && S_ISBLK(st_buf.st_mode);
 | 
			
		||||
 | 
			
		||||
	if (PATH_MAX <= snprintf(path2, PATH_MAX, "%s/%s", dm_dir(), device))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return !stat(path2, &st_buf) && S_ISBLK(st_buf.st_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle the event (de)registration call and return negative error codes. */
 | 
			
		||||
static int do_event(int cmd, struct dm_event_daemon_message *msg,
 | 
			
		||||
		    char *dso_name, char *device, enum dm_event_type events,
 | 
			
		||||
		    uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_fifos fifos;
 | 
			
		||||
 | 
			
		||||
	/* FIXME Start the daemon here if it's not running e.g. exclusive lock file */
 | 
			
		||||
	/* FIXME Move this to separate 'dm_event_register_handler' - if no daemon here, fail */
 | 
			
		||||
	if (!init_client(&fifos)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -ESRCH;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Use separate 'dm_event_register_handler' function to pass in dso? */
 | 
			
		||||
	ret = daemon_talk(&fifos, msg, cmd, dso_name, device, events, timeout);
 | 
			
		||||
 | 
			
		||||
	/* what is the opposite of init? */
 | 
			
		||||
	dtr_client(&fifos);
 | 
			
		||||
	
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME remove dso_name - use handle instead */
 | 
			
		||||
/* FIXME Use uuid not path! */
 | 
			
		||||
/* External library interface. */
 | 
			
		||||
int dm_event_register(char *dso_name, char *device_path,
 | 
			
		||||
		      enum dm_event_type events)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path)) {
 | 
			
		||||
		log_error("%s: device not found", device_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ret = do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
 | 
			
		||||
			    dso_name, device_path, events, 0)) < 0) {
 | 
			
		||||
		log_error("%s: event registration failed: %s", device_path,
 | 
			
		||||
			  strerror(-ret));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_unregister(char *dso_name, char *device_path,
 | 
			
		||||
			enum dm_event_type events)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path)) {
 | 
			
		||||
		log_error("%s: device not found", device_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ret = do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
 | 
			
		||||
			    dso_name, device_path, events, 0)) < 0) {
 | 
			
		||||
		log_error("%s: event deregistration failed: %s", device_path,
 | 
			
		||||
			  strerror(-ret));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_get_registered_device(char **dso_name, char **device_path,
 | 
			
		||||
			     enum dm_event_type *events, int next)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	char *dso_name_arg = NULL, *device_path_arg = NULL;
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!(ret = do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
 | 
			
		||||
				    DM_EVENT_CMD_GET_REGISTERED_DEVICE,
 | 
			
		||||
			     &msg, *dso_name, *device_path, *events, 0)))
 | 
			
		||||
		ret = parse_message(&msg, &dso_name_arg, &device_path_arg,
 | 
			
		||||
				    events);
 | 
			
		||||
 | 
			
		||||
	if (next){
 | 
			
		||||
		if (*dso_name)
 | 
			
		||||
			dm_free(*dso_name);
 | 
			
		||||
		if (*device_path)
 | 
			
		||||
			dm_free(*device_path);
 | 
			
		||||
		*dso_name = dso_name_arg;
 | 
			
		||||
		*device_path = device_path_arg;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!(*dso_name))
 | 
			
		||||
			*dso_name = dso_name_arg;
 | 
			
		||||
		if (!(*device_path))
 | 
			
		||||
			*device_path = device_path_arg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_set_timeout(char *device_path, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path))
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	return do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
 | 
			
		||||
			NULL, device_path, 0, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_get_timeout(char *device_path, uint32_t *timeout)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path))
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	if (!(ret = do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path, 0, 0)))
 | 
			
		||||
		*timeout = atoi(msg.msg);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Overrides for Emacs so that we follow Linus's tabbing style.
 | 
			
		||||
 * Emacs will notice this stuff at the end of the file and automatically
 | 
			
		||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
			
		||||
 * of the file.
 | 
			
		||||
 * ---------------------------------------------------------------------------
 | 
			
		||||
 * Local variables:
 | 
			
		||||
 * c-file-style: "linux"
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										108
									
								
								daemons/dmeventd/libdevmapper-event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								daemons/dmeventd/libdevmapper-event.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the device-mapper userspace tools.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Note that this file is released only as part of a technology preview
 | 
			
		||||
 * and its contents may change in future updates in ways that do not
 | 
			
		||||
 * preserve compatibility.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LIB_DMEVENT_H
 | 
			
		||||
#define LIB_DMEVENT_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* FIXME This stuff must be configurable. */
 | 
			
		||||
 | 
			
		||||
#define	DM_EVENT_DAEMON		"/sbin/dmeventd"
 | 
			
		||||
#define DM_EVENT_LOCKFILE	"/var/lock/dmeventd"
 | 
			
		||||
#define	DM_EVENT_FIFO_CLIENT	"/var/run/dmeventd-client"
 | 
			
		||||
#define	DM_EVENT_FIFO_SERVER	"/var/run/dmeventd-server"
 | 
			
		||||
#define DM_EVENT_PIDFILE	"/var/run/dmeventd.pid"
 | 
			
		||||
 | 
			
		||||
#define DM_EVENT_DEFAULT_TIMEOUT 10
 | 
			
		||||
 | 
			
		||||
/* Commands for the daemon passed in the message below. */
 | 
			
		||||
enum dm_event_command {
 | 
			
		||||
	DM_EVENT_CMD_ACTIVE = 1,
 | 
			
		||||
	DM_EVENT_CMD_REGISTER_FOR_EVENT,
 | 
			
		||||
	DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
 | 
			
		||||
	DM_EVENT_CMD_GET_REGISTERED_DEVICE,
 | 
			
		||||
	DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
 | 
			
		||||
	DM_EVENT_CMD_SET_TIMEOUT,
 | 
			
		||||
	DM_EVENT_CMD_GET_TIMEOUT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Message passed between client and daemon. */
 | 
			
		||||
struct dm_event_daemon_message {
 | 
			
		||||
	union {
 | 
			
		||||
		unsigned int cmd;	/* FIXME Use fixed size. */
 | 
			
		||||
		int	 status;	/* FIXME Use fixed size. */
 | 
			
		||||
	} opcode;
 | 
			
		||||
	char msg[252];		/* FIXME Why is this 252 ? */
 | 
			
		||||
} __attribute__((packed));	/* FIXME Do this properly! */
 | 
			
		||||
 | 
			
		||||
/* FIXME Is this meant to be exported?  I can't see where the interface uses it. */
 | 
			
		||||
/* Fifos for client/daemon communication. */
 | 
			
		||||
struct dm_event_fifos {
 | 
			
		||||
	int client;
 | 
			
		||||
	int server;
 | 
			
		||||
	const char *client_path;
 | 
			
		||||
	const char *server_path;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Event type definitions. */
 | 
			
		||||
/* FIXME Use masks to separate the types and provide for extension. */
 | 
			
		||||
enum dm_event_type {
 | 
			
		||||
	DM_EVENT_SINGLE		= 0x01, /* Report multiple errors just once. */
 | 
			
		||||
	DM_EVENT_MULTI		= 0x02, /* Report all of them. */
 | 
			
		||||
 | 
			
		||||
	DM_EVENT_SECTOR_ERROR	= 0x04, /* Failure on a particular sector. */
 | 
			
		||||
	DM_EVENT_DEVICE_ERROR	= 0x08, /* Device failure. */
 | 
			
		||||
	DM_EVENT_PATH_ERROR	= 0x10, /* Failure on an io path. */
 | 
			
		||||
	DM_EVENT_ADAPTOR_ERROR	= 0x20, /* Failure off a host adaptor. */
 | 
			
		||||
 | 
			
		||||
	DM_EVENT_SYNC_STATUS	= 0x40, /* Mirror synchronization completed/failed. */
 | 
			
		||||
	DM_EVENT_TIMEOUT	= 0x80, /* Timeout has occured */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* FIXME Use a mask. */
 | 
			
		||||
#define	DM_EVENT_ALL_ERRORS (DM_EVENT_SECTOR_ERROR | DM_EVENT_DEVICE_ERROR | \
 | 
			
		||||
			     DM_EVENT_PATH_ERROR | DM_EVENT_ADAPTOR_ERROR)
 | 
			
		||||
 | 
			
		||||
/* Prototypes for event lib interface. */
 | 
			
		||||
 | 
			
		||||
/* FIXME Replace device with standard name/uuid/devno choice */
 | 
			
		||||
/* Interface changes: 
 | 
			
		||||
   First register a handler, passing in a unique ref for the device. */
 | 
			
		||||
//  int dm_event_register_handler(const char *dso_name, const char *device);
 | 
			
		||||
//  int dm_event_register(const char *dso_name, const char *name, const char *uuid, uint32_t major, uint32_t minor, enum dm_event_type events);
 | 
			
		||||
/* Or (better?) add to task structure and use existing functions - run a task to register/unregister events - we may need to run task withe that with the new event mechanism anyway, then the dso calls just hook in.
 | 
			
		||||
*/
 | 
			
		||||
 
 | 
			
		||||
/* FIXME Missing consts? */
 | 
			
		||||
int dm_event_register(char *dso_name, char *device, enum dm_event_type events);
 | 
			
		||||
int dm_event_unregister(char *dso_name, char *device,
 | 
			
		||||
			enum dm_event_type events);
 | 
			
		||||
int dm_event_get_registered_device(char **dso_name, char **device,
 | 
			
		||||
				   enum dm_event_type *events, int next);
 | 
			
		||||
int dm_event_set_timeout(char *device, uint32_t timeout);
 | 
			
		||||
int dm_event_get_timeout(char *device, uint32_t *timeout);
 | 
			
		||||
 | 
			
		||||
/* Prototypes for DSO interface. */
 | 
			
		||||
void process_event(const char *device, enum dm_event_type event);
 | 
			
		||||
int register_device(const char *device);
 | 
			
		||||
int unregister_device(const char *device);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										12
									
								
								daemons/dmeventd/libdevmapper-event.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								daemons/dmeventd/libdevmapper-event.pc.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
prefix=@prefix@
 | 
			
		||||
exec_prefix=@exec_prefix@
 | 
			
		||||
libdir=@libdir@
 | 
			
		||||
includedir=@includedir@
 | 
			
		||||
 | 
			
		||||
Name: devmapper-event
 | 
			
		||||
Description: device-mapper event library
 | 
			
		||||
Version: @DM_LIB_VERSION@
 | 
			
		||||
Requires: devmapper
 | 
			
		||||
Cflags: -I${includedir}
 | 
			
		||||
Libs: -L${libdir} -ldevmapper-event
 | 
			
		||||
Libs.private: -lpthread -ldl
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
#
 | 
			
		||||
# Create test devices for dmeventd
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
trap "rm -f /tmp/tmp.$$" 0 1 2 3 15
 | 
			
		||||
 | 
			
		||||
echo "0 1024 zero" > /tmp/tmp.$$
 | 
			
		||||
dmsetup create test /tmp/tmp.$$
 | 
			
		||||
dmsetup create test1 /tmp/tmp.$$
 | 
			
		||||
 | 
			
		||||
kill -15 $$
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the device-mapper userspace tools.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdm-event.h"
 | 
			
		||||
#include "libmultilog.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void process_event(char *device, enum event_type event)
 | 
			
		||||
{
 | 
			
		||||
	log_err("[%s] %s(%d) - Device: %s, Event %d\n",
 | 
			
		||||
		__FILE__, __func__, __LINE__, device, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(char *device)
 | 
			
		||||
{
 | 
			
		||||
	log_err("[%s] %s(%d) - Device: %s\n",
 | 
			
		||||
		__FILE__, __func__, __LINE__, device);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(char *device)
 | 
			
		||||
{
 | 
			
		||||
	log_err("[%s] %s(%d) - Device: %s\n",
 | 
			
		||||
		__FILE__, __func__, __LINE__, device);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								daemons/dmeventd/plugins/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								daemons/dmeventd/plugins/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the 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 General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
SUBDIRS += mirror
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								daemons/dmeventd/plugins/mirror/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								daemons/dmeventd/plugins/mirror/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
							
								
								
									
										36
									
								
								daemons/dmeventd/plugins/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								daemons/dmeventd/plugins/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the 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 General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I${top_srcdir}/tools
 | 
			
		||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_mirror.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@LIB_SUFFIX@","dylib")
 | 
			
		||||
  LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
 | 
			
		||||
else
 | 
			
		||||
  LIB_SHARED = libdevmapper-event-lvm2mirror.so
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/$<.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										254
									
								
								daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
 | 
			
		||||
 | 
			
		||||
#define ME_IGNORE    0
 | 
			
		||||
#define ME_INSYNC    1
 | 
			
		||||
#define ME_FAILURE   2
 | 
			
		||||
 | 
			
		||||
static pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
/* FIXME: We may need to lock around operations to these */
 | 
			
		||||
static int register_count = 0;
 | 
			
		||||
static struct dm_pool *mem_pool = NULL;
 | 
			
		||||
 | 
			
		||||
static int _get_mirror_event(char *params)
 | 
			
		||||
{
 | 
			
		||||
	int i, rtn = ME_INSYNC;
 | 
			
		||||
	int max_args = 30;  /* should support at least 8-way mirrors */
 | 
			
		||||
	char *args[max_args];
 | 
			
		||||
	char *dev_status_str;
 | 
			
		||||
	char *log_status_str;
 | 
			
		||||
	char *sync_str;
 | 
			
		||||
	char *p;
 | 
			
		||||
	int log_argc, num_devs, num_failures=0;
 | 
			
		||||
 | 
			
		||||
	if (max_args <= dm_split_words(params, max_args, 0, args)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
 | 
			
		||||
		return -E2BIG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Unused:  0 409600 mirror
 | 
			
		||||
	 * Used  :  2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
 | 
			
		||||
	*/
 | 
			
		||||
	num_devs = atoi(args[0]);
 | 
			
		||||
	dev_status_str = args[3 + num_devs];
 | 
			
		||||
	log_argc = atoi(args[4 + num_devs]);
 | 
			
		||||
	log_status_str = args[4 + num_devs + log_argc];
 | 
			
		||||
	sync_str = args[1 + num_devs];
 | 
			
		||||
 | 
			
		||||
	/* Check for bad mirror devices */
 | 
			
		||||
	for (i = 0; i < num_devs; i++) {
 | 
			
		||||
		if (dev_status_str[i] == 'D') {
 | 
			
		||||
			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
 | 
			
		||||
			num_failures++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check for bad log device */
 | 
			
		||||
	if (log_status_str[0] == 'D') {
 | 
			
		||||
		syslog(LOG_ERR, "Log device, %s, has failed.\n",
 | 
			
		||||
		       args[3 + num_devs + log_argc]);
 | 
			
		||||
		num_failures++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (num_failures) {
 | 
			
		||||
		rtn = ME_FAILURE;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p = strstr(sync_str, "/");
 | 
			
		||||
	if (p) {
 | 
			
		||||
		p[0] = '\0';
 | 
			
		||||
		if (strcmp(sync_str, p+1))
 | 
			
		||||
			rtn = ME_IGNORE;
 | 
			
		||||
		p[0] = '/';
 | 
			
		||||
	} else {
 | 
			
		||||
		/*
 | 
			
		||||
		 * How the hell did we get this?
 | 
			
		||||
		 * Might mean all our parameters are screwed.
 | 
			
		||||
		 */
 | 
			
		||||
		syslog(LOG_ERR, "Unable to parse sync string.");
 | 
			
		||||
		rtn = ME_IGNORE;
 | 
			
		||||
	}
 | 
			
		||||
 out:
 | 
			
		||||
	return rtn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _temporary_log_fn(int level, const char *file,
 | 
			
		||||
			      int line, const char *format)
 | 
			
		||||
{
 | 
			
		||||
	if (!strncmp(format, "WARNING: ", 9) && (level < 5))
 | 
			
		||||
		syslog(LOG_CRIT, "%s", format);
 | 
			
		||||
	else
 | 
			
		||||
		syslog(LOG_DEBUG, "%s", format);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _remove_failed_devices(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	void *handle;
 | 
			
		||||
	int cmd_size = 256;	/* FIXME Use system restriction */
 | 
			
		||||
	char cmd_str[cmd_size];
 | 
			
		||||
	char *vg = NULL, *lv = NULL, *layer = NULL;
 | 
			
		||||
 | 
			
		||||
	if (strlen(device) > 200)
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
 | 
			
		||||
	if (!dm_split_lvm_name(mem_pool, device, &vg, &lv, &layer)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to determine VG name from %s",
 | 
			
		||||
		       device);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Is any sanity-checking required on %s? */
 | 
			
		||||
	if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
 | 
			
		||||
		/* this error should be caught above, but doesn't hurt to check again */
 | 
			
		||||
		syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
 | 
			
		||||
		dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lvm2_log_fn(_temporary_log_fn);
 | 
			
		||||
	handle = lvm2_init();
 | 
			
		||||
	lvm2_log_level(handle, 1);
 | 
			
		||||
	r = lvm2_run(handle, cmd_str);
 | 
			
		||||
 | 
			
		||||
	dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
	return (r == 1)? 0: -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(const char *device, enum dm_event_type event)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *target_type = NULL;
 | 
			
		||||
	char *params;
 | 
			
		||||
 | 
			
		||||
	if (pthread_mutex_trylock(&_lock)) {
 | 
			
		||||
		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting...");
 | 
			
		||||
		pthread_mutex_lock(&_lock);
 | 
			
		||||
	}
 | 
			
		||||
	/* FIXME Move inside libdevmapper */
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to create dm_task.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_set_name(dmt, device)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to set device name.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_run(dmt)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to run task.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
					  &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
		if (strcmp(target_type, "mirror")) {
 | 
			
		||||
			syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch(_get_mirror_event(params)) {
 | 
			
		||||
		case ME_INSYNC:
 | 
			
		||||
			/* FIXME: all we really know is that this
 | 
			
		||||
			   _part_ of the device is in sync
 | 
			
		||||
			   Also, this is not an error
 | 
			
		||||
			*/
 | 
			
		||||
			syslog(LOG_NOTICE, "%s is now in-sync\n", device);
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_FAILURE:
 | 
			
		||||
			syslog(LOG_ERR, "Device failure in %s\n", device);
 | 
			
		||||
			if (_remove_failed_devices(device))
 | 
			
		||||
				syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
 | 
			
		||||
				       device);
 | 
			
		||||
			/* Should check before warning user that device is now linear
 | 
			
		||||
			else
 | 
			
		||||
				syslog(LOG_NOTICE, "%s is now a linear device.\n",
 | 
			
		||||
					device);
 | 
			
		||||
			*/
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_IGNORE:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			syslog(LOG_INFO, "Unknown event received.\n");
 | 
			
		||||
		}
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
	if (dmt)
 | 
			
		||||
		dm_task_destroy(dmt);
 | 
			
		||||
	pthread_mutex_unlock(&_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	syslog(LOG_INFO, "Monitoring mirror device, %s for events\n", device);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Need some space for allocations.  1024 should be more
 | 
			
		||||
	 * than enough for what we need (device mapper name splitting)
 | 
			
		||||
	 */
 | 
			
		||||
	if (!mem_pool)
 | 
			
		||||
		mem_pool = dm_pool_create("mirror_dso", 1024);
 | 
			
		||||
 | 
			
		||||
	if (!mem_pool)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	register_count++;
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	if (!(--register_count)) {
 | 
			
		||||
		dm_pool_destroy(mem_pool);
 | 
			
		||||
		mem_pool = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Overrides for Emacs so that we follow Linus's tabbing style.
 | 
			
		||||
 * Emacs will notice this stuff at the end of the file and automatically
 | 
			
		||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
			
		||||
 * of the file.
 | 
			
		||||
 * ---------------------------------------------------------------------------
 | 
			
		||||
 * Local variables:
 | 
			
		||||
 * c-file-style: "linux"
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										22
									
								
								dmeventd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								dmeventd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the 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 General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
SUBDIRS += mirror
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								dmeventd/mirror/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								dmeventd/mirror/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
							
								
								
									
										36
									
								
								dmeventd/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								dmeventd/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the 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 General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I${top_srcdir}/tools
 | 
			
		||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_mirror.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@LIB_SUFFIX@","dylib")
 | 
			
		||||
  LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
 | 
			
		||||
else
 | 
			
		||||
  LIB_SHARED = libdevmapper-event-lvm2mirror.so
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/$<.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										254
									
								
								dmeventd/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								dmeventd/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
 | 
			
		||||
 | 
			
		||||
#define ME_IGNORE    0
 | 
			
		||||
#define ME_INSYNC    1
 | 
			
		||||
#define ME_FAILURE   2
 | 
			
		||||
 | 
			
		||||
static pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
/* FIXME: We may need to lock around operations to these */
 | 
			
		||||
static int register_count = 0;
 | 
			
		||||
static struct dm_pool *mem_pool = NULL;
 | 
			
		||||
 | 
			
		||||
static int _get_mirror_event(char *params)
 | 
			
		||||
{
 | 
			
		||||
	int i, rtn = ME_INSYNC;
 | 
			
		||||
	int max_args = 30;  /* should support at least 8-way mirrors */
 | 
			
		||||
	char *args[max_args];
 | 
			
		||||
	char *dev_status_str;
 | 
			
		||||
	char *log_status_str;
 | 
			
		||||
	char *sync_str;
 | 
			
		||||
	char *p;
 | 
			
		||||
	int log_argc, num_devs, num_failures=0;
 | 
			
		||||
 | 
			
		||||
	if (max_args <= dm_split_words(params, max_args, 0, args)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
 | 
			
		||||
		return -E2BIG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Unused:  0 409600 mirror
 | 
			
		||||
	 * Used  :  2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
 | 
			
		||||
	*/
 | 
			
		||||
	num_devs = atoi(args[0]);
 | 
			
		||||
	dev_status_str = args[3 + num_devs];
 | 
			
		||||
	log_argc = atoi(args[4 + num_devs]);
 | 
			
		||||
	log_status_str = args[4 + num_devs + log_argc];
 | 
			
		||||
	sync_str = args[1 + num_devs];
 | 
			
		||||
 | 
			
		||||
	/* Check for bad mirror devices */
 | 
			
		||||
	for (i = 0; i < num_devs; i++) {
 | 
			
		||||
		if (dev_status_str[i] == 'D') {
 | 
			
		||||
			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
 | 
			
		||||
			num_failures++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check for bad log device */
 | 
			
		||||
	if (log_status_str[0] == 'D') {
 | 
			
		||||
		syslog(LOG_ERR, "Log device, %s, has failed.\n",
 | 
			
		||||
		       args[3 + num_devs + log_argc]);
 | 
			
		||||
		num_failures++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (num_failures) {
 | 
			
		||||
		rtn = ME_FAILURE;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p = strstr(sync_str, "/");
 | 
			
		||||
	if (p) {
 | 
			
		||||
		p[0] = '\0';
 | 
			
		||||
		if (strcmp(sync_str, p+1))
 | 
			
		||||
			rtn = ME_IGNORE;
 | 
			
		||||
		p[0] = '/';
 | 
			
		||||
	} else {
 | 
			
		||||
		/*
 | 
			
		||||
		 * How the hell did we get this?
 | 
			
		||||
		 * Might mean all our parameters are screwed.
 | 
			
		||||
		 */
 | 
			
		||||
		syslog(LOG_ERR, "Unable to parse sync string.");
 | 
			
		||||
		rtn = ME_IGNORE;
 | 
			
		||||
	}
 | 
			
		||||
 out:
 | 
			
		||||
	return rtn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _temporary_log_fn(int level, const char *file,
 | 
			
		||||
			      int line, const char *format)
 | 
			
		||||
{
 | 
			
		||||
	if (!strncmp(format, "WARNING: ", 9) && (level < 5))
 | 
			
		||||
		syslog(LOG_CRIT, "%s", format);
 | 
			
		||||
	else
 | 
			
		||||
		syslog(LOG_DEBUG, "%s", format);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _remove_failed_devices(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	void *handle;
 | 
			
		||||
	int cmd_size = 256;	/* FIXME Use system restriction */
 | 
			
		||||
	char cmd_str[cmd_size];
 | 
			
		||||
	char *vg = NULL, *lv = NULL, *layer = NULL;
 | 
			
		||||
 | 
			
		||||
	if (strlen(device) > 200)
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
 | 
			
		||||
	if (!dm_split_lvm_name(mem_pool, device, &vg, &lv, &layer)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to determine VG name from %s",
 | 
			
		||||
		       device);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Is any sanity-checking required on %s? */
 | 
			
		||||
	if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
 | 
			
		||||
		/* this error should be caught above, but doesn't hurt to check again */
 | 
			
		||||
		syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
 | 
			
		||||
		dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lvm2_log_fn(_temporary_log_fn);
 | 
			
		||||
	handle = lvm2_init();
 | 
			
		||||
	lvm2_log_level(handle, 1);
 | 
			
		||||
	r = lvm2_run(handle, cmd_str);
 | 
			
		||||
 | 
			
		||||
	dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
	return (r == 1)? 0: -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(const char *device, enum dm_event_type event)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *target_type = NULL;
 | 
			
		||||
	char *params;
 | 
			
		||||
 | 
			
		||||
	if (pthread_mutex_trylock(&_lock)) {
 | 
			
		||||
		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting...");
 | 
			
		||||
		pthread_mutex_lock(&_lock);
 | 
			
		||||
	}
 | 
			
		||||
	/* FIXME Move inside libdevmapper */
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to create dm_task.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_set_name(dmt, device)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to set device name.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_run(dmt)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to run task.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
					  &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
		if (strcmp(target_type, "mirror")) {
 | 
			
		||||
			syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch(_get_mirror_event(params)) {
 | 
			
		||||
		case ME_INSYNC:
 | 
			
		||||
			/* FIXME: all we really know is that this
 | 
			
		||||
			   _part_ of the device is in sync
 | 
			
		||||
			   Also, this is not an error
 | 
			
		||||
			*/
 | 
			
		||||
			syslog(LOG_NOTICE, "%s is now in-sync\n", device);
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_FAILURE:
 | 
			
		||||
			syslog(LOG_ERR, "Device failure in %s\n", device);
 | 
			
		||||
			if (_remove_failed_devices(device))
 | 
			
		||||
				syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
 | 
			
		||||
				       device);
 | 
			
		||||
			/* Should check before warning user that device is now linear
 | 
			
		||||
			else
 | 
			
		||||
				syslog(LOG_NOTICE, "%s is now a linear device.\n",
 | 
			
		||||
					device);
 | 
			
		||||
			*/
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_IGNORE:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			syslog(LOG_INFO, "Unknown event received.\n");
 | 
			
		||||
		}
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
	if (dmt)
 | 
			
		||||
		dm_task_destroy(dmt);
 | 
			
		||||
	pthread_mutex_unlock(&_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	syslog(LOG_INFO, "Monitoring mirror device, %s for events\n", device);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Need some space for allocations.  1024 should be more
 | 
			
		||||
	 * than enough for what we need (device mapper name splitting)
 | 
			
		||||
	 */
 | 
			
		||||
	if (!mem_pool)
 | 
			
		||||
		mem_pool = dm_pool_create("mirror_dso", 1024);
 | 
			
		||||
 | 
			
		||||
	if (!mem_pool)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	register_count++;
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	if (!(--register_count)) {
 | 
			
		||||
		dm_pool_destroy(mem_pool);
 | 
			
		||||
		mem_pool = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Overrides for Emacs so that we follow Linus's tabbing style.
 | 
			
		||||
 * Emacs will notice this stuff at the end of the file and automatically
 | 
			
		||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
			
		||||
 * of the file.
 | 
			
		||||
 * ---------------------------------------------------------------------------
 | 
			
		||||
 * Local variables:
 | 
			
		||||
 * c-file-style: "linux"
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -207,11 +207,26 @@ global {
 | 
			
		||||
    # Location of proc filesystem
 | 
			
		||||
    proc = "/proc"
 | 
			
		||||
 | 
			
		||||
    # Type of locking to use. Defaults to file-based locking (1).
 | 
			
		||||
    # Type of locking to use. Defaults to local file-based locking (1).
 | 
			
		||||
    # Turn locking off by setting to 0 (dangerous: risks metadata corruption
 | 
			
		||||
    # if LVM2 commands get run concurrently).
 | 
			
		||||
    # Type 2 uses the external shared library locking_library.
 | 
			
		||||
    # Type 3 uses built-in clustered locking.
 | 
			
		||||
    locking_type = 1
 | 
			
		||||
 | 
			
		||||
    # If using external locking (type 2) and initialisation fails,
 | 
			
		||||
    # with this set to 1 an attempt will be made to use the built-in
 | 
			
		||||
    # clustered locking.
 | 
			
		||||
    # If you are using a customised locking_library you should set this to 0.
 | 
			
		||||
    fallback_to_clustered_locking = 1
 | 
			
		||||
 | 
			
		||||
    # If an attempt to initialise type 2 or type 3 locking failed, perhaps
 | 
			
		||||
    # because cluster components such as clvmd are not running, with this set
 | 
			
		||||
    # to 1 an attempt will be made to use local file-based locking (type 1).
 | 
			
		||||
    # If this succeeds, only commands against local volume groups will proceed.
 | 
			
		||||
    # Volume Groups marked as clustered will be ignored.
 | 
			
		||||
    fallback_to_local_locking = 1
 | 
			
		||||
 | 
			
		||||
    # Local non-LV directory that holds file-based locks while commands are
 | 
			
		||||
    # in progress.  A directory like /tmp that may get wiped on reboot is OK.
 | 
			
		||||
    locking_dir = "/var/lock/lvm"
 | 
			
		||||
@@ -223,6 +238,9 @@ global {
 | 
			
		||||
 | 
			
		||||
    # Search this directory first for shared libraries.
 | 
			
		||||
    #   library_dir = "/lib"
 | 
			
		||||
 | 
			
		||||
    # The external locking library to load if locking_type is set to 2.
 | 
			
		||||
    #   locking_library = "liblvm2clusterlock.so"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
activation {
 | 
			
		||||
@@ -232,9 +250,6 @@ activation {
 | 
			
		||||
    # target or make it return zeros.
 | 
			
		||||
    missing_stripe_filler = "/dev/ioerror"
 | 
			
		||||
 | 
			
		||||
    # Size (in KB) of each copy operation when mirroring
 | 
			
		||||
    mirror_region_size = 512
 | 
			
		||||
 | 
			
		||||
    # How much stack (in KB) to reserve for use while devices suspended
 | 
			
		||||
    reserved_stack = 256
 | 
			
		||||
 | 
			
		||||
@@ -251,6 +266,54 @@ activation {
 | 
			
		||||
    #   "@*" matches if any tag defined on the host is also set in the LV or VG
 | 
			
		||||
    #
 | 
			
		||||
    # volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
 | 
			
		||||
 | 
			
		||||
    # Size (in KB) of each copy operation when mirroring
 | 
			
		||||
    mirror_region_size = 512
 | 
			
		||||
 | 
			
		||||
    # 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
 | 
			
		||||
    # how a device failure affecting a mirror is handled.
 | 
			
		||||
    # A mirror is composed of mirror images (copies) and a log.
 | 
			
		||||
    # A disk log ensures that a mirror does not need to be re-synced
 | 
			
		||||
    # (all copies made the same) every time a machine reboots or crashes.
 | 
			
		||||
    #
 | 
			
		||||
    # In the event of a failure, the specified policy will be used to
 | 
			
		||||
    # determine what happens:
 | 
			
		||||
    #
 | 
			
		||||
    # "remove" - Simply remove the faulty device and run without it.  If
 | 
			
		||||
    #            the log device fails, the mirror would convert to using
 | 
			
		||||
    #            an in-memory log.  This means the mirror will not
 | 
			
		||||
    #            remember its sync status across crashes/reboots and
 | 
			
		||||
    #            the entire mirror will be re-synced.  If a
 | 
			
		||||
    #            mirror image fails, the mirror will convert to a
 | 
			
		||||
    #            non-mirrored device if there is only one remaining good
 | 
			
		||||
    #            copy.
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate" - Remove the faulty device and try to allocate space on
 | 
			
		||||
    #            a new device to be a replacement for the failed device.
 | 
			
		||||
    #            Using this policy for the log is fast and maintains the
 | 
			
		||||
    #            ability to remember sync state through crashes/reboots.
 | 
			
		||||
    #            Using this policy for a mirror device is slow, as it
 | 
			
		||||
    #            requires the mirror to resynchronize the devices, but it
 | 
			
		||||
    #            will preserve the mirror characteristic of the device.
 | 
			
		||||
    #            This policy acts like "remove" if no suitable device and
 | 
			
		||||
    #            space can be allocated for the replacement.
 | 
			
		||||
    #            Currently this is not implemented properly and behaves
 | 
			
		||||
    #            similarly to:
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate_anywhere" - Operates like "allocate", but it does not
 | 
			
		||||
    #            require that the new space being allocated be on a
 | 
			
		||||
    #            device is not part of the mirror.  For a log device
 | 
			
		||||
    #            failure, this could mean that the log is allocated on
 | 
			
		||||
    #            the same device as a mirror device.  For a mirror
 | 
			
		||||
    #            device, this could mean that the mirror device is
 | 
			
		||||
    #            allocated on the same device as another mirror device.
 | 
			
		||||
    #            This policy would not be wise for mirror devices
 | 
			
		||||
    #            because it would break the redundant nature of the
 | 
			
		||||
    #            mirror.  This policy acts like "remove" if no suitable
 | 
			
		||||
    #            device and space can be allocated for the replacement.
 | 
			
		||||
 | 
			
		||||
    mirror_log_fault_policy = "allocate"
 | 
			
		||||
    mirror_device_fault_policy = "remove"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -289,4 +352,15 @@ activation {
 | 
			
		||||
    # dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
 | 
			
		||||
#}
 | 
			
		||||
 | 
			
		||||
# Event daemon
 | 
			
		||||
#
 | 
			
		||||
# dmeventd {
 | 
			
		||||
    # mirror_library is the library used when monitoring a mirror device.
 | 
			
		||||
    #
 | 
			
		||||
    # "libdevmapper-event-lvm2mirror.so" attempts to recover from failures.
 | 
			
		||||
    # It removes failed devices from a volume group and reconfigures a
 | 
			
		||||
    # mirror as necessary.
 | 
			
		||||
    #
 | 
			
		||||
    # mirror_library = "libdevmapper-event-lvm2mirror.so"
 | 
			
		||||
#}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,12 +34,14 @@
 | 
			
		||||
../lib/metadata/segtype.h
 | 
			
		||||
../lib/mm/memlock.h
 | 
			
		||||
../lib/mm/xlate.h
 | 
			
		||||
../lib/misc/configure.h
 | 
			
		||||
../lib/misc/crc.h
 | 
			
		||||
../lib/misc/intl.h
 | 
			
		||||
../lib/misc/lib.h
 | 
			
		||||
../lib/misc/lvm-exec.h
 | 
			
		||||
../lib/misc/lvm-file.h
 | 
			
		||||
../lib/misc/lvm-string.h
 | 
			
		||||
../lib/misc/lvm-wrappers.h
 | 
			
		||||
../lib/misc/sharedlib.h
 | 
			
		||||
../lib/regex/matcher.h
 | 
			
		||||
../lib/report/report.h
 | 
			
		||||
 
 | 
			
		||||
@@ -41,3 +41,5 @@ install:
 | 
			
		||||
 | 
			
		||||
install_cluster:
 | 
			
		||||
 | 
			
		||||
cflow:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,7 @@ SOURCES =\
 | 
			
		||||
	commands/toolcontext.c \
 | 
			
		||||
	config/config.c \
 | 
			
		||||
	datastruct/btree.c \
 | 
			
		||||
	datastruct/list.c \
 | 
			
		||||
	datastruct/str_list.c \
 | 
			
		||||
	device/dev-cache.c \
 | 
			
		||||
	device/dev-io.c \
 | 
			
		||||
@@ -77,6 +78,8 @@ SOURCES =\
 | 
			
		||||
	misc/lvm-exec.c \
 | 
			
		||||
	misc/lvm-file.c \
 | 
			
		||||
	misc/lvm-string.c \
 | 
			
		||||
	misc/lvm-wrappers.c \
 | 
			
		||||
	misc/timestamp.c \
 | 
			
		||||
	mm/memlock.c \
 | 
			
		||||
	regex/matcher.c \
 | 
			
		||||
	regex/parse_rx.c \
 | 
			
		||||
@@ -133,9 +136,22 @@ ifeq ("@HAVE_LIBDL@", "yes")
 | 
			
		||||
	misc/sharedlib.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
  CLDFLAGS += -ldevmapper-event
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
LIB_STATIC = liblvm.a
 | 
			
		||||
 | 
			
		||||
$(SUBDIRS): $(LIB_STATIC)
 | 
			
		||||
 | 
			
		||||
CLEAN_TARGETS += liblvm.cflow
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
liblvm.cflow: $(SOURCES)
 | 
			
		||||
	set -e; (echo -n "SOURCES += "; \
 | 
			
		||||
		 echo $(SOURCES) | \
 | 
			
		||||
		 sed "s/^/ /;s/ / $(top_srcdir)\/lib\//g;s/$$//"; \
 | 
			
		||||
		 ) > $@
 | 
			
		||||
 | 
			
		||||
cflow: liblvm.cflow
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -38,7 +39,7 @@ int lvm1_present(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
 | 
			
		||||
	if (dm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
 | 
			
		||||
	    < 0) {
 | 
			
		||||
		log_error("LVM1 proc global snprintf failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -50,6 +51,66 @@ int lvm1_present(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
 | 
			
		||||
			 struct list *modules)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s;
 | 
			
		||||
	struct lv_segment *seg2, *snap_seg;
 | 
			
		||||
	struct list *snh;
 | 
			
		||||
 | 
			
		||||
	if (seg->segtype->ops->modules_needed &&
 | 
			
		||||
	    !seg->segtype->ops->modules_needed(mem, seg, modules)) {
 | 
			
		||||
		log_error("module string allocation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lv_is_origin(seg->lv))
 | 
			
		||||
		list_iterate(snh, &seg->lv->snapshot_segs)
 | 
			
		||||
			if (!list_lv_modules(mem,
 | 
			
		||||
					     list_struct_base(snh,
 | 
			
		||||
							      struct lv_segment,
 | 
			
		||||
							      origin_list)->cow,
 | 
			
		||||
					     modules))
 | 
			
		||||
				return_0;
 | 
			
		||||
 | 
			
		||||
	if (lv_is_cow(seg->lv)) {
 | 
			
		||||
		snap_seg = find_cow(seg->lv);
 | 
			
		||||
		if (snap_seg->segtype->ops->modules_needed &&
 | 
			
		||||
		    !snap_seg->segtype->ops->modules_needed(mem, snap_seg,
 | 
			
		||||
							    modules)) {
 | 
			
		||||
			log_error("snap_seg module string allocation failed");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
		switch (seg_type(seg, s)) {
 | 
			
		||||
		case AREA_LV:
 | 
			
		||||
			seg2 = find_seg_by_le(seg_lv(seg, s), seg_le(seg, s));
 | 
			
		||||
			if (seg2 && !list_segment_modules(mem, seg2, modules))
 | 
			
		||||
				return_0;
 | 
			
		||||
			break;
 | 
			
		||||
		case AREA_PV:
 | 
			
		||||
		case AREA_UNASSIGNED:
 | 
			
		||||
			;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
 | 
			
		||||
		    struct list *modules)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(seg, &lv->segments)
 | 
			
		||||
		if (!list_segment_modules(mem, seg, modules))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef DEVMAPPER_SUPPORT
 | 
			
		||||
void set_activation(int act)
 | 
			
		||||
{
 | 
			
		||||
@@ -75,6 +136,11 @@ int driver_version(char *version, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
		   uint32_t *min, uint32_t *patchlevel)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int target_present(const char *target_name)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -89,12 +155,12 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr)
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -146,11 +212,16 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
               struct volume_group *vg)
 | 
			
		||||
	       struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_release(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
@@ -170,8 +241,8 @@ void set_activation(int act)
 | 
			
		||||
		log_verbose("Activation enabled. Device-mapper kernel "
 | 
			
		||||
			    "driver will be used.");
 | 
			
		||||
	else
 | 
			
		||||
		log_verbose("Activation disabled. No device-mapper "
 | 
			
		||||
			    "interaction will be attempted.");
 | 
			
		||||
		log_print("WARNING: Activation disabled. No device-mapper "
 | 
			
		||||
			  "interaction will be attempted.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int activation(void)
 | 
			
		||||
@@ -187,7 +258,7 @@ static int _passes_activation_filter(struct cmd_context *cmd,
 | 
			
		||||
	char *str;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "activation/volume_list"))) {
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "activation/volume_list"))) {
 | 
			
		||||
		/* If no host tags defined, activate */
 | 
			
		||||
		if (list_empty(&cmd->tags))
 | 
			
		||||
			return 1;
 | 
			
		||||
@@ -246,9 +317,9 @@ static int _passes_activation_filter(struct cmd_context *cmd,
 | 
			
		||||
				continue;
 | 
			
		||||
		}
 | 
			
		||||
		/* vgname/lvname */
 | 
			
		||||
		if (lvm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
 | 
			
		||||
		if (dm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
 | 
			
		||||
				 lv->name) < 0) {
 | 
			
		||||
			log_error("lvm_snprintf error from %s/%s", lv->vg->name,
 | 
			
		||||
			log_error("dm_snprintf error from %s/%s", lv->vg->name,
 | 
			
		||||
				  lv->name);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
@@ -277,7 +348,8 @@ int driver_version(char *version, size_t size)
 | 
			
		||||
	return dm_driver_version(version, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _target_present(const char *target_name)
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
		   uint32_t *min, uint32_t *patchlevel)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
@@ -300,6 +372,9 @@ static int _target_present(const char *target_name)
 | 
			
		||||
 | 
			
		||||
		if (!strcmp(target_name, target->name)) {
 | 
			
		||||
			r = 1;
 | 
			
		||||
			*maj = target->version[0];
 | 
			
		||||
			*min = target->version[1];
 | 
			
		||||
			*patchlevel = target->version[2];
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -314,6 +389,7 @@ static int _target_present(const char *target_name)
 | 
			
		||||
 | 
			
		||||
int target_present(const char *target_name, int use_modprobe)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t maj, min, patchlevel;
 | 
			
		||||
#ifdef MODPROBE_CMD
 | 
			
		||||
	char module[128];
 | 
			
		||||
#endif
 | 
			
		||||
@@ -323,10 +399,10 @@ int target_present(const char *target_name, int use_modprobe)
 | 
			
		||||
 | 
			
		||||
#ifdef MODPROBE_CMD
 | 
			
		||||
	if (use_modprobe) {
 | 
			
		||||
		if (_target_present(target_name))
 | 
			
		||||
		if (target_version(target_name, &maj, &min, &patchlevel))
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
 | 
			
		||||
		if (dm_snprintf(module, sizeof(module), "dm-%s", target_name)
 | 
			
		||||
		    < 0) {
 | 
			
		||||
			log_error("target_present module name too long: %s",
 | 
			
		||||
				  target_name);
 | 
			
		||||
@@ -338,7 +414,7 @@ int target_present(const char *target_name, int use_modprobe)
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return _target_present(target_name);
 | 
			
		||||
	return target_version(target_name, &maj, &min, &patchlevel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -396,7 +472,7 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if percent set, else 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
@@ -416,8 +492,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Merge with snapshot_percent */
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr)
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
@@ -512,7 +588,7 @@ static int _lv_deactivate(struct logical_volume *lv)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_suspend_lv(struct logical_volume *lv)
 | 
			
		||||
static int _lv_suspend_lv(struct logical_volume *lv, int lockfs)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
@@ -520,7 +596,7 @@ static int _lv_suspend_lv(struct logical_volume *lv)
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_suspend(dm, lv)))
 | 
			
		||||
	if (!(r = dev_manager_suspend(dm, lv, lockfs)))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	dev_manager_destroy(dm);
 | 
			
		||||
@@ -563,18 +639,75 @@ int lvs_in_vg_opened(struct volume_group *vg)
 | 
			
		||||
	return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * register_dev_for_events
 | 
			
		||||
 *
 | 
			
		||||
 * This function uses proper error codes (but breaks convention)
 | 
			
		||||
 * to return:
 | 
			
		||||
 *      -1 on error
 | 
			
		||||
 *       0 if the lv's targets don't do event [un]registration
 | 
			
		||||
 *       0 if the lv is already [un]registered -- FIXME: not implemented
 | 
			
		||||
 *       1 if the lv had a segment which was [un]registered
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: -1 on error
 | 
			
		||||
 */
 | 
			
		||||
int register_dev_for_events(struct cmd_context *cmd,
 | 
			
		||||
			    struct logical_volume *lv, int do_reg)
 | 
			
		||||
{
 | 
			
		||||
#ifdef DMEVENTD
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct list *tmp;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	int (*reg) (struct lv_segment *, int events);
 | 
			
		||||
 | 
			
		||||
	if (do_reg && !dmeventd_register_mode())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	list_iterate(tmp, &lv->segments) {
 | 
			
		||||
		seg = list_item(tmp, struct lv_segment);
 | 
			
		||||
 | 
			
		||||
		reg = NULL;
 | 
			
		||||
 | 
			
		||||
		if (do_reg) {
 | 
			
		||||
			if (seg->segtype->ops->target_register_events)
 | 
			
		||||
				reg = seg->segtype->ops->target_register_events;
 | 
			
		||||
		} else if (seg->segtype->ops->target_unregister_events)
 | 
			
		||||
			reg = seg->segtype->ops->target_unregister_events;
 | 
			
		||||
 | 
			
		||||
		if (!reg)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* FIXME specify events */
 | 
			
		||||
		if (!reg(seg, 0)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		r = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
#else
 | 
			
		||||
	return 1;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		       int error_if_not_suspended)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct logical_volume *lv, *lv_pre;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int lockfs = 0;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	/* Use precommitted metadata if present */
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 1)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
		_skip("Suspending '%s'.", lv->name);
 | 
			
		||||
@@ -588,15 +721,23 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		return error_if_not_suspended ? 0 : 1;
 | 
			
		||||
 | 
			
		||||
	/* If VG was precommitted, preload devices for the LV */
 | 
			
		||||
	if ((lv->vg->status & PRECOMMITTED)) {
 | 
			
		||||
		if (!_lv_preload(lv)) {
 | 
			
		||||
	if ((lv_pre->vg->status & PRECOMMITTED)) {
 | 
			
		||||
		if (!_lv_preload(lv_pre)) {
 | 
			
		||||
			/* FIXME Revert preloading */
 | 
			
		||||
			return_0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (register_dev_for_events(cmd, lv, 0) != 1)
 | 
			
		||||
		/* FIXME Consider aborting here */
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	if (!_lv_suspend_lv(lv)) {
 | 
			
		||||
 | 
			
		||||
	if (lv_is_origin(lv_pre) || lv_is_cow(lv_pre))
 | 
			
		||||
		lockfs = 1;
 | 
			
		||||
 | 
			
		||||
	if (!_lv_suspend_lv(lv, lockfs)) {
 | 
			
		||||
		memlock_dec();
 | 
			
		||||
		fs_unlock();
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -645,6 +786,9 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	if (register_dev_for_events(cmd, lv, 1) != 1)
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -688,6 +832,9 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (register_dev_for_events(cmd, lv, 0) != 1)
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	r = _lv_deactivate(lv);
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
@@ -758,6 +905,9 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	if (!register_dev_for_events(cmd, lv, 1) != 1)
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -801,28 +951,21 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
 | 
			
		||||
 * Does PV use VG somewhere in its construction?
 | 
			
		||||
 * Returns 1 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
               struct volume_group *vg)
 | 
			
		||||
int pv_uses_vg(struct physical_volume *pv,
 | 
			
		||||
	       struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(cmd, vg->name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	return dev_manager_device_uses_vg(pv->dev, vg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	r = dev_manager_device_uses_vg(dm, pv->dev, vg);
 | 
			
		||||
 | 
			
		||||
	dev_manager_destroy(dm);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
void activation_release(void)
 | 
			
		||||
{
 | 
			
		||||
	dev_manager_release();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_exit(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,14 @@ int library_version(char *version, size_t size);
 | 
			
		||||
int lvm1_present(struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
int target_present(const char *target_name, int use_modprobe);
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
                   uint32_t *min, uint32_t *patchlevel);
 | 
			
		||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
 | 
			
		||||
			 struct list *modules);
 | 
			
		||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
 | 
			
		||||
		    struct list *modules);
 | 
			
		||||
 | 
			
		||||
void activation_release(void);
 | 
			
		||||
void activation_exit(void);
 | 
			
		||||
 | 
			
		||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
@@ -68,9 +75,9 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if percent has been set, else 0.
 | 
			
		||||
 */
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr);
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return number of LVs in the VG that are active.
 | 
			
		||||
@@ -78,10 +85,14 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wa
 | 
			
		||||
int lvs_in_vg_activated(struct volume_group *vg);
 | 
			
		||||
int lvs_in_vg_opened(struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int register_dev_for_events(struct cmd_context *cmd,
 | 
			
		||||
			    struct logical_volume *lv, int do_reg);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if PV has a dependency tree that uses anything in VG.
 | 
			
		||||
 */
 | 
			
		||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
int pv_uses_vg(struct physical_volume *pv,
 | 
			
		||||
	       struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@ typedef enum {
 | 
			
		||||
	ACTIVATE,
 | 
			
		||||
	DEACTIVATE,
 | 
			
		||||
	SUSPEND,
 | 
			
		||||
	SUSPEND_WITH_LOCKFS,
 | 
			
		||||
	CLEAN
 | 
			
		||||
} action_t;
 | 
			
		||||
 | 
			
		||||
@@ -85,7 +86,7 @@ char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer)
 | 
			
		||||
	return _build_dlid(dm->mem, lvid, layer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int _read_only_lv(struct logical_volume *lv)
 | 
			
		||||
static int _read_only_lv(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	return (!(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
 | 
			
		||||
}
 | 
			
		||||
@@ -329,7 +330,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
 | 
			
		||||
 | 
			
		||||
		if (segtype->ops->target_percent &&
 | 
			
		||||
		    !segtype->ops->target_percent(&dm->target_state, dm->mem,
 | 
			
		||||
						  dm->cmd->cft, seg, params,
 | 
			
		||||
						  dm->cmd, seg, params,
 | 
			
		||||
						  &total_numerator,
 | 
			
		||||
						  &total_denominator,
 | 
			
		||||
						  percent))
 | 
			
		||||
@@ -401,7 +402,7 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
 | 
			
		||||
	dm->mem = mem;
 | 
			
		||||
 | 
			
		||||
	if (!stripe_filler) {
 | 
			
		||||
		stripe_filler = find_config_str(cmd->cft->root,
 | 
			
		||||
		stripe_filler = find_config_tree_str(cmd,
 | 
			
		||||
						"activation/missing_stripe_filler",
 | 
			
		||||
						DEFAULT_STRIPE_FILLER);
 | 
			
		||||
	}
 | 
			
		||||
@@ -426,13 +427,19 @@ void dev_manager_destroy(struct dev_manager *dm)
 | 
			
		||||
	dm_pool_destroy(dm->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dev_manager_release(void)
 | 
			
		||||
{
 | 
			
		||||
	dm_lib_release();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dev_manager_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	dm_lib_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
 | 
			
		||||
				 struct logical_volume *lv, float *percent)
 | 
			
		||||
				 const struct logical_volume *lv,
 | 
			
		||||
				 float *percent)
 | 
			
		||||
{
 | 
			
		||||
	char *name;
 | 
			
		||||
	const char *dlid;
 | 
			
		||||
@@ -615,6 +622,9 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struc
 | 
			
		||||
	if (!_add_dev_to_dtree(dm, dtree, lv, "cow"))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!_add_dev_to_dtree(dm, dtree, lv, "_mlog"))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -660,7 +670,8 @@ fail:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
		   struct dm_tree_node *node, int start_area, int areas)
 | 
			
		||||
		   struct dm_tree_node *node, uint32_t start_area,
 | 
			
		||||
		   uint32_t areas)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t extent_size = seg->lv->vg->extent_size;
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
@@ -674,7 +685,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
		    (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
 | 
			
		||||
			dm_tree_node_add_target_area(node,
 | 
			
		||||
							dm->stripe_filler,
 | 
			
		||||
							NULL, 0);
 | 
			
		||||
							NULL, UINT64_C(0));
 | 
			
		||||
		else if (seg_type(seg, s) == AREA_PV)
 | 
			
		||||
			dm_tree_node_add_target_area(node,
 | 
			
		||||
							dev_name(seg_dev(seg, s)),
 | 
			
		||||
@@ -699,7 +710,6 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_origin_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
					 struct dm_tree *dtree,
 | 
			
		||||
					 struct dm_tree_node *dnode,
 | 
			
		||||
					 struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
@@ -715,7 +725,6 @@ static int _add_origin_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
					   struct dm_tree *dtree,
 | 
			
		||||
					   struct dm_tree_node *dnode,
 | 
			
		||||
					   struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
@@ -744,7 +753,6 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
				  struct dm_tree *dtree,
 | 
			
		||||
				  struct dm_tree_node *dnode,
 | 
			
		||||
				  struct lv_segment *seg)
 | 
			
		||||
{
 | 
			
		||||
@@ -756,7 +764,7 @@ static int _add_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd->cft,
 | 
			
		||||
	return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
 | 
			
		||||
						  &dm->target_state, seg,
 | 
			
		||||
						  dnode,
 | 
			
		||||
						  extent_size * seg->len,
 | 
			
		||||
@@ -809,12 +817,12 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
 | 
			
		||||
 | 
			
		||||
	/* Now we've added its dependencies, we can add the target itself */
 | 
			
		||||
	if (lv_is_origin(seg->lv) && !layer) {
 | 
			
		||||
		if (!_add_origin_target_to_dtree(dm, dtree, dnode, seg->lv))
 | 
			
		||||
		if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
 | 
			
		||||
			return_0;
 | 
			
		||||
	} else if (lv_is_cow(seg->lv) && !layer) {
 | 
			
		||||
		if (!_add_snapshot_target_to_dtree(dm, dtree, dnode, seg->lv))
 | 
			
		||||
		if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv))
 | 
			
		||||
			return_0;
 | 
			
		||||
	} else if (!_add_target_to_dtree(dm, dtree, dnode, seg))
 | 
			
		||||
	} else if (!_add_target_to_dtree(dm, dnode, seg))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (lv_is_origin(seg->lv) && !layer)
 | 
			
		||||
@@ -845,7 +853,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 | 
			
		||||
	    dm_tree_node_get_context(dnode))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/* FIXME How do we determine whether a pre-existing node need reloading or not? */
 | 
			
		||||
	if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
 | 
			
		||||
		log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.", lv->name, layer);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -860,10 +867,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 | 
			
		||||
	 * Major/minor settings only apply to the visible layer.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(dnode = dm_tree_add_new_dev(dtree, name, dlid,
 | 
			
		||||
					     layer ? lv->major : 0,
 | 
			
		||||
					     layer ? lv->minor : 0,
 | 
			
		||||
					     layer ? UINT32_C(0) : (uint32_t) lv->major,
 | 
			
		||||
					     layer ? UINT32_C(0) : (uint32_t) lv->minor,
 | 
			
		||||
					     _read_only_lv(lv),
 | 
			
		||||
					     lv->vg->status & PRECOMMITTED,
 | 
			
		||||
					     (lv->vg->status & PRECOMMITTED) ? 1 : 0,
 | 
			
		||||
					     lvlayer)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
@@ -905,7 +912,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
 | 
			
		||||
		name = dm_tree_node_get_name(child);
 | 
			
		||||
 | 
			
		||||
		if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
 | 
			
		||||
	        	if (!split_dm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
 | 
			
		||||
	        	if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
 | 
			
		||||
                		log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
 | 
			
		||||
                		return 0;
 | 
			
		||||
        		}
 | 
			
		||||
@@ -917,7 +924,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _clean_tree(struct dev_manager *dm, struct logical_volume *lv, struct dm_tree_node *root)
 | 
			
		||||
static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
 | 
			
		||||
{
 | 
			
		||||
	void *handle = NULL;
 | 
			
		||||
	struct dm_tree_node *child;
 | 
			
		||||
@@ -931,7 +938,7 @@ static int _clean_tree(struct dev_manager *dm, struct logical_volume *lv, struct
 | 
			
		||||
		if (!(uuid = dm_tree_node_get_uuid(child)))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
        	if (!split_dm_name(dm->mem, name, &vgname, &lvname, &layer)) {
 | 
			
		||||
        	if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
 | 
			
		||||
                	log_error("_clean_tree: Couldn't split up device name %s.", name);
 | 
			
		||||
                	return 0;
 | 
			
		||||
        	}
 | 
			
		||||
@@ -969,7 +976,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
 | 
			
		||||
	switch(action) {
 | 
			
		||||
	case CLEAN:
 | 
			
		||||
		/* Deactivate any unused non-toplevel nodes */
 | 
			
		||||
		if (!_clean_tree(dm, lv, root))
 | 
			
		||||
		if (!_clean_tree(dm, root))
 | 
			
		||||
			goto_out;
 | 
			
		||||
		break;
 | 
			
		||||
	case DEACTIVATE:
 | 
			
		||||
@@ -978,6 +985,8 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
 | 
			
		||||
			goto_out;
 | 
			
		||||
		break;
 | 
			
		||||
	case SUSPEND:
 | 
			
		||||
		dm_tree_skip_lockfs(root);
 | 
			
		||||
	case SUSPEND_WITH_LOCKFS:
 | 
			
		||||
		if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
 | 
			
		||||
			goto_out;
 | 
			
		||||
		break;
 | 
			
		||||
@@ -1041,16 +1050,17 @@ int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv)
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
 | 
			
		||||
			int lockfs)
 | 
			
		||||
{
 | 
			
		||||
	return _tree_action(dm, lv, SUSPEND);
 | 
			
		||||
	return _tree_action(dm, lv, lockfs ? SUSPEND_WITH_LOCKFS : SUSPEND);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Does device use VG somewhere in its construction?
 | 
			
		||||
 * Returns 1 if uncertain.
 | 
			
		||||
 */
 | 
			
		||||
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
 | 
			
		||||
int dev_manager_device_uses_vg(struct device *dev,
 | 
			
		||||
			       struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_tree *dtree;
 | 
			
		||||
@@ -1063,7 +1073,7 @@ int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_tree_add_dev(dtree, MAJOR(dev->dev), MINOR(dev->dev))) {
 | 
			
		||||
	if (!dm_tree_add_dev(dtree, (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev))) {
 | 
			
		||||
		log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to dtree",
 | 
			
		||||
			  dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));
 | 
			
		||||
		goto out;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ struct device;
 | 
			
		||||
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
 | 
			
		||||
				       const char *vg_name);
 | 
			
		||||
void dev_manager_destroy(struct dev_manager *dm);
 | 
			
		||||
void dev_manager_release(void);
 | 
			
		||||
void dev_manager_exit(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -41,11 +42,13 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
 | 
			
		||||
		     const struct logical_volume *lv,
 | 
			
		||||
		     int mknodes, int with_open_count, struct dm_info *info);
 | 
			
		||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
 | 
			
		||||
				 struct logical_volume *lv, float *percent);
 | 
			
		||||
				 const struct logical_volume *lv,
 | 
			
		||||
				 float *percent);
 | 
			
		||||
int dev_manager_mirror_percent(struct dev_manager *dm,
 | 
			
		||||
			       struct logical_volume *lv, int wait,
 | 
			
		||||
			       float *percent, uint32_t *event_nr);
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
 | 
			
		||||
			int lockfs);
 | 
			
		||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
@@ -58,7 +61,7 @@ int dev_manager_lv_rmnodes(const struct logical_volume *lv);
 | 
			
		||||
 */
 | 
			
		||||
int dev_manager_execute(struct dev_manager *dm);
 | 
			
		||||
 | 
			
		||||
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
 | 
			
		||||
int dev_manager_device_uses_vg(struct device *dev,
 | 
			
		||||
			       struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't construct name of volume "
 | 
			
		||||
			  "group directory.");
 | 
			
		||||
@@ -53,7 +53,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't construct name of volume "
 | 
			
		||||
			  "group directory.");
 | 
			
		||||
@@ -87,7 +87,7 @@ static void _rm_blks(const char *dir)
 | 
			
		||||
		if (!strcmp(name, ".") || !strcmp(name, ".."))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (lvm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
 | 
			
		||||
		if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
 | 
			
		||||
			log_error("Couldn't create path for %s", name);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
@@ -109,28 +109,28 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't create path for volume group dir %s",
 | 
			
		||||
			  vg_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
 | 
			
		||||
	if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
 | 
			
		||||
			 lv_name) == -1) {
 | 
			
		||||
		log_error("Couldn't create source pathname for "
 | 
			
		||||
			  "logical volume link %s", lv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
 | 
			
		||||
	if (dm_snprintf(link_path, sizeof(link_path), "%s/%s",
 | 
			
		||||
			 dm_dir(), dev) == -1) {
 | 
			
		||||
		log_error("Couldn't create destination pathname for "
 | 
			
		||||
			  "logical volume link for %s", lv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
 | 
			
		||||
	if (dm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
 | 
			
		||||
			 vg_path) == -1) {
 | 
			
		||||
		log_error("Couldn't create pathname for LVM1 group file for %s",
 | 
			
		||||
			  vg_name);
 | 
			
		||||
@@ -190,7 +190,7 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	char lv_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
 | 
			
		||||
	if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
 | 
			
		||||
			 dev_dir, vg_name, lv_name) == -1) {
 | 
			
		||||
		log_error("Couldn't determine link pathname.");
 | 
			
		||||
		return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
		       int start_area, int areas);
 | 
			
		||||
 | 
			
		||||
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
                   struct dm_tree_node *node, int start_area, int areas);
 | 
			
		||||
                   struct dm_tree_node *node, uint32_t start_area, uint32_t areas);
 | 
			
		||||
 | 
			
		||||
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
 | 
			
		||||
		     size_t bufsize, const char *desc);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										364
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										364
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							@@ -50,7 +50,7 @@ int lvmcache_init(void)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only)
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	if (!_lock_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
@@ -86,7 +86,8 @@ int vgs_locked(void)
 | 
			
		||||
	return _vgs_locked;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
 | 
			
		||||
/* If vgid supplied, require a match. */
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
@@ -96,10 +97,16 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
 | 
			
		||||
	if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (vgid)
 | 
			
		||||
		do 
 | 
			
		||||
			if (!strncmp(vgid, vginfo->vgid, ID_LEN))
 | 
			
		||||
				return vginfo;
 | 
			
		||||
		while ((vginfo = vginfo->next));
 | 
			
		||||
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname)
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
@@ -107,19 +114,25 @@ const struct format_type *fmt_from_vgname(const char *vgname)
 | 
			
		||||
	struct list *devh, *tmp;
 | 
			
		||||
	struct list devs;
 | 
			
		||||
	struct device_list *devl;
 | 
			
		||||
	char vgid_found[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname)))
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	/* This function is normally called before reading metadata so
 | 
			
		||||
 	 * we check cached labels here. Unfortunately vginfo is volatile. */
 | 
			
		||||
	list_init(&devs);
 | 
			
		||||
	list_iterate_items(info, &vginfo->infos) {
 | 
			
		||||
		devl = dm_malloc(sizeof(*devl));
 | 
			
		||||
		if (!(devl = dm_malloc(sizeof(*devl)))) {
 | 
			
		||||
			log_error("device_list element allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		devl->dev = info->dev;
 | 
			
		||||
		list_add(&devs, &devl->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
 | 
			
		||||
 | 
			
		||||
	list_iterate_safe(devh, tmp, &devs) {
 | 
			
		||||
		devl = list_item(devh, struct device_list);
 | 
			
		||||
		label_read(devl->dev, &label);
 | 
			
		||||
@@ -127,6 +140,11 @@ const struct format_type *fmt_from_vgname(const char *vgname)
 | 
			
		||||
		dm_free(devl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If vginfo changed, caller needs to rescan */
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
 | 
			
		||||
	    strncmp(vginfo->vgid, vgid_found, ID_LEN))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return vginfo->fmt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -148,6 +166,23 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	const char *vgname = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!*vgid)
 | 
			
		||||
		vgname = ORPHAN;
 | 
			
		||||
 | 
			
		||||
	if ((vginfo = vginfo_from_vgid(vgid)))
 | 
			
		||||
		vgname = vginfo->vgname;
 | 
			
		||||
 | 
			
		||||
	if (mem && vgname)
 | 
			
		||||
		return dm_pool_strdup(mem, vgname);
 | 
			
		||||
 | 
			
		||||
	return vgname;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lvmcache_info *info_from_pvid(const char *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
@@ -206,7 +241,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1: 0))) {
 | 
			
		||||
	if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
 | 
			
		||||
		log_error("dev_iter creation failed");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -232,10 +267,33 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *vgids;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
	if (!(vgids = str_list_create(cmd->mem))) {
 | 
			
		||||
		log_error("vgids list allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(vginfo, &_vginfos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, vgids, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, vginfo->vgid))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vgids;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *vgnames;
 | 
			
		||||
	struct lvmcache_vginfo *vgi;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
@@ -244,9 +302,9 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(vgi, &_vginfos) {
 | 
			
		||||
	list_iterate_items(vginfo, &_vginfos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, vgnames, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, vgi->vgname))) {
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, vginfo->vgname))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
@@ -255,6 +313,32 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
	return vgnames;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
				const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct list *pvids;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(pvids = str_list_create(cmd->mem))) {
 | 
			
		||||
		log_error("pvids list allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
 | 
			
		||||
		return pvids;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(info, &vginfo->infos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, pvids, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, info->dev->pvid))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pvids;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
@@ -297,7 +381,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
static int _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!list_empty(&info->list)) {
 | 
			
		||||
		list_del(&info->list);
 | 
			
		||||
@@ -306,8 +390,18 @@ static void _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && list_empty(&info->vginfo->infos)) {
 | 
			
		||||
		dm_hash_remove(_vgname_hash, info->vginfo->vgname);
 | 
			
		||||
		if (info->vginfo->next) {
 | 
			
		||||
                	if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
 | 
			
		||||
                        	log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
					  info->vginfo->vgname);
 | 
			
		||||
                        	return 0;
 | 
			
		||||
			}
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
		if (info->vginfo->vgname)
 | 
			
		||||
			dm_free(info->vginfo->vgname);
 | 
			
		||||
		if (info->vginfo->creation_host)
 | 
			
		||||
			dm_free(info->vginfo->creation_host);
 | 
			
		||||
		if (*info->vginfo->vgid)
 | 
			
		||||
			dm_hash_remove(_vgid_hash, info->vginfo->vgid);
 | 
			
		||||
		list_del(&info->vginfo->list);
 | 
			
		||||
@@ -315,6 +409,8 @@ static void _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->vginfo = NULL;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unused
 | 
			
		||||
@@ -350,36 +446,129 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid,
 | 
			
		||||
					       sizeof(info->vginfo->vgid)))
 | 
			
		||||
	if (!vgid || !info->vginfo ||
 | 
			
		||||
	    !strncmp(info->vginfo->vgid, vgid, ID_LEN))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && *info->vginfo->vgid)
 | 
			
		||||
		dm_hash_remove(_vgid_hash, info->vginfo->vgid);
 | 
			
		||||
	if (!vgid)
 | 
			
		||||
	if (!vgid) {
 | 
			
		||||
		log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
 | 
			
		||||
	info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
 | 
			
		||||
	strncpy(info->vginfo->vgid, vgid, ID_LEN);
 | 
			
		||||
	info->vginfo->vgid[ID_LEN] = '\0';
 | 
			
		||||
	if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
 | 
			
		||||
		log_error("_lvmcache_update: vgid hash insertion failed: %s",
 | 
			
		||||
			  info->vginfo->vgid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
 | 
			
		||||
		  info->vginfo->vgname, info->vginfo->vgid);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
 | 
			
		||||
			  uint32_t vgstatus, const char *creation_host,
 | 
			
		||||
			  struct lvmcache_vginfo *primary_vginfo)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *last_vginfo = primary_vginfo;
 | 
			
		||||
	char uuid_primary[64], uuid_new[64];
 | 
			
		||||
	int use_new = 0;
 | 
			
		||||
	
 | 
			
		||||
	/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
 | 
			
		||||
	if (primary_vginfo) {
 | 
			
		||||
		if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
 | 
			
		||||
				     sizeof(uuid_primary)))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * If   Primary not exported, new exported => keep
 | 
			
		||||
		 * Else Primary exported, new not exported => change
 | 
			
		||||
		 * Else Primary has hostname for this machine => keep
 | 
			
		||||
		 * Else Primary has no hostname, new has one => change
 | 
			
		||||
		 * Else New has hostname for this machine => change
 | 
			
		||||
		 * Else Keep primary.
 | 
			
		||||
		 */
 | 
			
		||||
		if (!(primary_vginfo->status & EXPORTED_VG) &&
 | 
			
		||||
		    (vgstatus & EXPORTED_VG))
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "Existing %s takes precedence over "
 | 
			
		||||
				  "exported %s", new_vginfo->vgname,
 | 
			
		||||
				  uuid_primary, uuid_new);
 | 
			
		||||
		else if ((primary_vginfo->status & EXPORTED_VG) &&
 | 
			
		||||
			   !(vgstatus & EXPORTED_VG)) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s takes precedence over exported %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		} else if (primary_vginfo->creation_host &&
 | 
			
		||||
			   !strcmp(primary_vginfo->creation_host,
 | 
			
		||||
				   primary_vginfo->fmt->cmd->hostname))
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "Existing %s (created here) takes precedence "
 | 
			
		||||
				  "over %s", new_vginfo->vgname, uuid_primary,
 | 
			
		||||
				  uuid_new);
 | 
			
		||||
		else if (!primary_vginfo->creation_host && creation_host) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s (with creation_host) takes precedence over %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		} else if (creation_host &&
 | 
			
		||||
			   !strcmp(creation_host,
 | 
			
		||||
				   primary_vginfo->fmt->cmd->hostname)) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s (created here) takes precedence over %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!use_new) {
 | 
			
		||||
			while (last_vginfo->next)
 | 
			
		||||
				last_vginfo = last_vginfo->next;
 | 
			
		||||
			last_vginfo->next = new_vginfo;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
 | 
			
		||||
		log_error("cache_update: vg hash insertion failed: %s",
 | 
			
		||||
		  	new_vginfo->vgname);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (primary_vginfo)
 | 
			
		||||
		new_vginfo->next = primary_vginfo;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_vgname(struct lvmcache_info *info,
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus, const char *creation_host)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo, *primary_vginfo;
 | 
			
		||||
	// struct lvmcache_vginfo  *old_vginfo, *next;
 | 
			
		||||
 | 
			
		||||
	/* If vgname is NULL and we don't already have a vgname, 
 | 
			
		||||
	 * assume ORPHAN - we want every entry to have a vginfo
 | 
			
		||||
	 * attached for scanning reasons.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!vgname && !info->vginfo)
 | 
			
		||||
	if (!vgname && !info->vginfo) {
 | 
			
		||||
		vgname = ORPHAN;
 | 
			
		||||
		vgid = ORPHAN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
 | 
			
		||||
		return 1;
 | 
			
		||||
@@ -388,7 +577,43 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
	_drop_vginfo(info);
 | 
			
		||||
 | 
			
		||||
	/* Get existing vginfo or create new one */
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname))) {
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
 | 
			
		||||
/*** FIXME - vginfo ends up duplicated instead of renamed.
 | 
			
		||||
		// Renaming?  This lookup fails.
 | 
			
		||||
		if ((vginfo = vginfo_from_vgid(vgid))) {
 | 
			
		||||
			next = vginfo->next;
 | 
			
		||||
			old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
 | 
			
		||||
			if (old_vginfo == vginfo) {
 | 
			
		||||
				dm_hash_remove(_vgname_hash, old_vginfo->vgname);
 | 
			
		||||
				if (old_vginfo->next) {
 | 
			
		||||
					if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
 | 
			
		||||
                        			log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
							  old_vginfo->vgname);
 | 
			
		||||
                        			return 0;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else do {
 | 
			
		||||
				if (old_vginfo->next == vginfo) {
 | 
			
		||||
					old_vginfo->next = vginfo->next;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			} while ((old_vginfo = old_vginfo->next));
 | 
			
		||||
			vginfo->next = NULL;
 | 
			
		||||
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
			if (!(vginfo->vgname = dm_strdup(vgname))) {
 | 
			
		||||
				log_error("cache vgname alloc failed for %s", vgname);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Rename so can assume new name does not already exist 
 | 
			
		||||
			if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
 | 
			
		||||
				log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
					  vginfo->vgname);
 | 
			
		||||
                      		return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
***/
 | 
			
		||||
		if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
 | 
			
		||||
			log_error("lvmcache_update_vgname: list alloc failed");
 | 
			
		||||
			return 0;
 | 
			
		||||
@@ -400,9 +625,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		list_init(&vginfo->infos);
 | 
			
		||||
		if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
 | 
			
		||||
			log_error("cache_update: vg hash insertion failed: %s",
 | 
			
		||||
				  vginfo->vgname);
 | 
			
		||||
			primary_vginfo = vginfo_from_vgname(vgname, NULL);
 | 
			
		||||
		if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
 | 
			
		||||
				    primary_vginfo)) {
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
			dm_free(vginfo);
 | 
			
		||||
			return 0;
 | 
			
		||||
@@ -412,6 +637,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
			list_add(&_vginfos, &vginfo->list);
 | 
			
		||||
		else
 | 
			
		||||
			list_add_h(&_vginfos, &vginfo->list);
 | 
			
		||||
/***
 | 
			
		||||
		}
 | 
			
		||||
***/
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->vginfo = vginfo;
 | 
			
		||||
@@ -420,8 +648,59 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
	/* FIXME Check consistency of list! */
 | 
			
		||||
	vginfo->fmt = info->fmt;
 | 
			
		||||
 | 
			
		||||
	log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
 | 
			
		||||
		  *vgname ? "in VG " : "orphaned", vgname);
 | 
			
		||||
	log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
 | 
			
		||||
		  *vgname ? "in VG " : "orphaned", vgname,
 | 
			
		||||
		  vginfo->vgid[0] ? " (" : "",
 | 
			
		||||
		  vginfo->vgid[0] ? vginfo->vgid : "",
 | 
			
		||||
		  vginfo->vgid[0] ? ")" : "");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
 | 
			
		||||
				     const char *creation_host)
 | 
			
		||||
{
 | 
			
		||||
	if (!info || !info->vginfo)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
 | 
			
		||||
		log_debug("lvmcache: %s: VG %s %s exported",
 | 
			
		||||
			  dev_name(info->dev), info->vginfo->vgname,
 | 
			
		||||
			  vgstatus & EXPORTED_VG ? "now" : "no longer");
 | 
			
		||||
 | 
			
		||||
	info->vginfo->status = vgstatus;
 | 
			
		||||
 | 
			
		||||
	if (!creation_host)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo->creation_host && !strcmp(creation_host,
 | 
			
		||||
						   info->vginfo->creation_host))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo->creation_host)
 | 
			
		||||
		dm_free(info->vginfo->creation_host);
 | 
			
		||||
 | 
			
		||||
	if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
 | 
			
		||||
		log_error("cache creation host alloc failed for %s",
 | 
			
		||||
			  creation_host);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
 | 
			
		||||
		  dev_name(info->dev), info->vginfo->vgname, creation_host);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
 | 
			
		||||
				  const char *vgname, const char *vgid,
 | 
			
		||||
				  uint32_t vgstatus, const char *creation_host)
 | 
			
		||||
{
 | 
			
		||||
	if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
 | 
			
		||||
				     creation_host) ||
 | 
			
		||||
	    !_lvmcache_update_vgid(info, vgid) ||
 | 
			
		||||
	    !_lvmcache_update_vgstatus(info, vgstatus, creation_host))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -431,20 +710,17 @@ int lvmcache_update_vg(struct volume_group *vg)
 | 
			
		||||
	struct pv_list *pvl;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
	int vgid_updated = 0;
 | 
			
		||||
 | 
			
		||||
	pvid_s[sizeof(pvid_s) - 1] = '\0';
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(pvl, &vg->pvs) {
 | 
			
		||||
		strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
 | 
			
		||||
		/* FIXME Could pvl->pv->dev->pvid ever be different? */
 | 
			
		||||
		if ((info = info_from_pvid(pvid_s))) {
 | 
			
		||||
			lvmcache_update_vgname(info, vg->name);
 | 
			
		||||
			if (!vgid_updated) {
 | 
			
		||||
				_lvmcache_update_vgid(info, (char *) &vg->id);
 | 
			
		||||
				vgid_updated = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if ((info = info_from_pvid(pvid_s)) &&
 | 
			
		||||
		    !lvmcache_update_vgname_and_id(info, vg->name,
 | 
			
		||||
						   (char *) &vg->id,
 | 
			
		||||
						   vg->status, NULL))
 | 
			
		||||
			return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -452,7 +728,8 @@ int lvmcache_update_vg(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
				   struct device *dev,
 | 
			
		||||
				   const char *vgname, const char *vgid)
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct lvmcache_info *existing, *info;
 | 
			
		||||
@@ -548,7 +825,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lvmcache_update_vgname(info, vgname)) {
 | 
			
		||||
	if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
 | 
			
		||||
		if (!existing) {
 | 
			
		||||
			dm_hash_remove(_pvid_hash, pvid_s);
 | 
			
		||||
			strcpy(info->dev->pvid, "");
 | 
			
		||||
@@ -558,10 +835,6 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_lvmcache_update_vgid(info, vgid))
 | 
			
		||||
		/* Non-critical */
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -576,12 +849,19 @@ static void _lvmcache_destroy_entry(struct lvmcache_info *info)
 | 
			
		||||
 | 
			
		||||
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
 | 
			
		||||
{
 | 
			
		||||
	if (vginfo->vgname)
 | 
			
		||||
		dm_free(vginfo->vgname);
 | 
			
		||||
	dm_free(vginfo);
 | 
			
		||||
	struct lvmcache_vginfo *next;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = vginfo->next;
 | 
			
		||||
		if (vginfo->vgname)
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
		if (vginfo->creation_host)
 | 
			
		||||
			dm_free(vginfo->creation_host);
 | 
			
		||||
		dm_free(vginfo);
 | 
			
		||||
	} while ((vginfo = next));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _lvmcache_destroy_lockname(int present)
 | 
			
		||||
static void _lvmcache_destroy_lockname(int present __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	/* Nothing to do */
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							@@ -33,15 +33,20 @@ struct cmd_context;
 | 
			
		||||
struct format_type;
 | 
			
		||||
struct volume_group;
 | 
			
		||||
 | 
			
		||||
/* One per VG */
 | 
			
		||||
struct lvmcache_vginfo {
 | 
			
		||||
	struct list list;	/* Join these vginfos together */
 | 
			
		||||
	struct list infos;	/* List head for lvmcache_infos */
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
	char *vgname;		/* "" == orphan */
 | 
			
		||||
	uint32_t status;
 | 
			
		||||
	char vgid[ID_LEN + 1];
 | 
			
		||||
	char _padding[7];
 | 
			
		||||
	struct lvmcache_vginfo *next; /* Another VG with same name? */
 | 
			
		||||
	char *creation_host;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* One per device */
 | 
			
		||||
struct lvmcache_info {
 | 
			
		||||
	struct list list;	/* Join VG members together */
 | 
			
		||||
	struct list mdas;	/* list head for metadata areas */
 | 
			
		||||
@@ -64,21 +69,26 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
/* Add/delete a device */
 | 
			
		||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
				   struct device *dev,
 | 
			
		||||
				   const char *vgname, const char *vgid);
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus);
 | 
			
		||||
void lvmcache_del(struct lvmcache_info *info);
 | 
			
		||||
 | 
			
		||||
/* Update things */
 | 
			
		||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname);
 | 
			
		||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
 | 
			
		||||
				  const char *vgname, const char *vgid,
 | 
			
		||||
				  uint32_t vgstatus, const char *hostname);
 | 
			
		||||
int lvmcache_update_vg(struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
 | 
			
		||||
void lvmcache_unlock_vgname(const char *vgname);
 | 
			
		||||
 | 
			
		||||
/* Queries */
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname);
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
 | 
			
		||||
					   const char *vgid);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
 | 
			
		||||
struct lvmcache_info *info_from_pvid(const char *pvid);
 | 
			
		||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
 | 
			
		||||
int vgs_locked(void);
 | 
			
		||||
int vgname_is_locked(const char *vgname);
 | 
			
		||||
@@ -87,4 +97,12 @@ int vgname_is_locked(const char *vgname);
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of vgids */
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of pvids */
 | 
			
		||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
				const char *vgid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ static int _get_env_vars(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* Set to "" to avoid using any system directory */
 | 
			
		||||
	if ((e = getenv("LVM_SYSTEM_DIR"))) {
 | 
			
		||||
		if (lvm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
 | 
			
		||||
		if (dm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
 | 
			
		||||
				 "%s", e) < 0) {
 | 
			
		||||
			log_error("LVM_SYSTEM_DIR environment variable "
 | 
			
		||||
				  "is too long.");
 | 
			
		||||
@@ -84,10 +84,11 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
	time_t t;
 | 
			
		||||
 | 
			
		||||
	const char *log_file;
 | 
			
		||||
	char timebuf[26];
 | 
			
		||||
 | 
			
		||||
	/* Syslog */
 | 
			
		||||
	cmd->default_settings.syslog =
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/syslog", DEFAULT_SYSLOG);
 | 
			
		||||
	    find_config_tree_int(cmd, "log/syslog", DEFAULT_SYSLOG);
 | 
			
		||||
	if (cmd->default_settings.syslog != 1)
 | 
			
		||||
		fin_syslog();
 | 
			
		||||
 | 
			
		||||
@@ -96,37 +97,37 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* Debug level for log file output */
 | 
			
		||||
	cmd->default_settings.debug =
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/level", DEFAULT_LOGLEVEL);
 | 
			
		||||
	    find_config_tree_int(cmd, "log/level", DEFAULT_LOGLEVEL);
 | 
			
		||||
	init_debug(cmd->default_settings.debug);
 | 
			
		||||
 | 
			
		||||
	/* Verbose level for tty output */
 | 
			
		||||
	cmd->default_settings.verbose =
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/verbose", DEFAULT_VERBOSE);
 | 
			
		||||
	    find_config_tree_int(cmd, "log/verbose", DEFAULT_VERBOSE);
 | 
			
		||||
	init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
 | 
			
		||||
 | 
			
		||||
	/* Log message formatting */
 | 
			
		||||
	init_indent(find_config_int(cmd->cft->root, "log/indent",
 | 
			
		||||
	init_indent(find_config_tree_int(cmd, "log/indent",
 | 
			
		||||
				    DEFAULT_INDENT));
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.msg_prefix = find_config_str(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.msg_prefix = find_config_tree_str(cmd,
 | 
			
		||||
							   "log/prefix",
 | 
			
		||||
							   DEFAULT_MSG_PREFIX);
 | 
			
		||||
	init_msg_prefix(cmd->default_settings.msg_prefix);
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.cmd_name = find_config_int(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.cmd_name = find_config_tree_int(cmd,
 | 
			
		||||
							 "log/command_names",
 | 
			
		||||
							 DEFAULT_CMD_NAME);
 | 
			
		||||
	init_cmd_name(cmd->default_settings.cmd_name);
 | 
			
		||||
 | 
			
		||||
	/* Test mode */
 | 
			
		||||
	cmd->default_settings.test =
 | 
			
		||||
	    find_config_int(cmd->cft->root, "global/test", 0);
 | 
			
		||||
	    find_config_tree_int(cmd, "global/test", 0);
 | 
			
		||||
 | 
			
		||||
	/* Settings for logging to file */
 | 
			
		||||
	if (find_config_int(cmd->cft->root, "log/overwrite", DEFAULT_OVERWRITE))
 | 
			
		||||
	if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE))
 | 
			
		||||
		append = 0;
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cft->root, "log/file", 0);
 | 
			
		||||
	log_file = find_config_tree_str(cmd, "log/file", 0);
 | 
			
		||||
 | 
			
		||||
	if (log_file) {
 | 
			
		||||
		release_log_memory();
 | 
			
		||||
@@ -134,15 +135,17 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
		init_log_file(log_file, append);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cft->root, "log/activate_file", 0);
 | 
			
		||||
	log_file = find_config_tree_str(cmd, "log/activate_file", 0);
 | 
			
		||||
	if (log_file)
 | 
			
		||||
		init_log_direct(log_file, append);
 | 
			
		||||
 | 
			
		||||
	init_log_while_suspended(find_config_int(cmd->cft->root,
 | 
			
		||||
	init_log_while_suspended(find_config_tree_int(cmd,
 | 
			
		||||
						 "log/activation", 0));
 | 
			
		||||
 | 
			
		||||
	t = time(NULL);
 | 
			
		||||
	log_verbose("Logging initialised at %s", ctime(&t));
 | 
			
		||||
	ctime_r(&t, &timebuf[0]);
 | 
			
		||||
	timebuf[24] = '\0';
 | 
			
		||||
	log_verbose("Logging initialised at %s", timebuf);
 | 
			
		||||
 | 
			
		||||
	/* Tell device-mapper about our logging */
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
@@ -155,7 +158,7 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
	mode_t old_umask;
 | 
			
		||||
 | 
			
		||||
	/* umask */
 | 
			
		||||
	cmd->default_settings.umask = find_config_int(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.umask = find_config_tree_int(cmd,
 | 
			
		||||
						      "global/umask",
 | 
			
		||||
						      DEFAULT_UMASK);
 | 
			
		||||
 | 
			
		||||
@@ -164,8 +167,8 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
		log_verbose("Set umask to %04o", cmd->default_settings.umask);
 | 
			
		||||
 | 
			
		||||
	/* dev dir */
 | 
			
		||||
	if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
 | 
			
		||||
			 find_config_str(cmd->cft->root, "devices/dir",
 | 
			
		||||
	if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
 | 
			
		||||
			 find_config_tree_str(cmd, "devices/dir",
 | 
			
		||||
					 DEFAULT_DEV_DIR)) < 0) {
 | 
			
		||||
		log_error("Device directory given in config file too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -175,8 +178,8 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* proc dir */
 | 
			
		||||
	if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
 | 
			
		||||
			 find_config_str(cmd->cft->root, "global/proc",
 | 
			
		||||
	if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
 | 
			
		||||
			 find_config_tree_str(cmd, "global/proc",
 | 
			
		||||
					 DEFAULT_PROC_DIR)) < 0) {
 | 
			
		||||
		log_error("Device directory given in config file too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -189,17 +192,17 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* activation? */
 | 
			
		||||
	cmd->default_settings.activation = find_config_int(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.activation = find_config_tree_int(cmd,
 | 
			
		||||
							   "global/activation",
 | 
			
		||||
							   DEFAULT_ACTIVATION);
 | 
			
		||||
	set_activation(cmd->default_settings.activation);
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.suffix = find_config_int(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.suffix = find_config_tree_int(cmd,
 | 
			
		||||
						       "global/suffix",
 | 
			
		||||
						       DEFAULT_SUFFIX);
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->default_settings.unit_factor =
 | 
			
		||||
	      units_to_bytes(find_config_str(cmd->cft->root,
 | 
			
		||||
	      units_to_bytes(find_config_tree_str(cmd,
 | 
			
		||||
					     "global/units",
 | 
			
		||||
					     DEFAULT_UNITS),
 | 
			
		||||
			     &cmd->default_settings.unit_type))) {
 | 
			
		||||
@@ -316,7 +319,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
 | 
			
		||||
	if (*tag)
 | 
			
		||||
		filler = "_";
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
 | 
			
		||||
	if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
 | 
			
		||||
			 cmd->sys_dir, filler, tag) < 0) {
 | 
			
		||||
		log_error("LVM_SYSTEM_DIR or tag was too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -469,7 +472,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "devices/scan"))) {
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
 | 
			
		||||
		if (!dev_cache_add_dir("/dev")) {
 | 
			
		||||
			log_error("Failed to add /dev to internal "
 | 
			
		||||
				  "device cache");
 | 
			
		||||
@@ -494,7 +497,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "devices/loopfiles")))
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "devices/loopfiles")))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
@@ -536,14 +539,14 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
 | 
			
		||||
	 * Listed first because it's very efficient at eliminating 
 | 
			
		||||
	 * unavailable devices.
 | 
			
		||||
	 */
 | 
			
		||||
	if (find_config_bool(cmd->cft->root, "devices/sysfs_scan",
 | 
			
		||||
	if (find_config_tree_bool(cmd, "devices/sysfs_scan",
 | 
			
		||||
			     DEFAULT_SYSFS_SCAN)) {
 | 
			
		||||
		if ((filters[nr_filt] = sysfs_filter_create(cmd->proc_dir)))
 | 
			
		||||
			nr_filt++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* regex filter. Optional. */
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "devices/filter")))
 | 
			
		||||
		log_very_verbose("devices/filter not found in config file: "
 | 
			
		||||
				 "no regex filter installed");
 | 
			
		||||
 | 
			
		||||
@@ -553,14 +556,14 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* device type filter. Required. */
 | 
			
		||||
	cn = find_config_node(cmd->cft->root, "devices/types");
 | 
			
		||||
	cn = find_config_tree_node(cmd, "devices/types");
 | 
			
		||||
	if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
 | 
			
		||||
		log_error("Failed to create lvm type filter");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* md component filter. Optional, non-critical. */
 | 
			
		||||
	if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
 | 
			
		||||
	if (find_config_tree_bool(cmd, "devices/md_component_detection",
 | 
			
		||||
			     DEFAULT_MD_COMPONENT_DETECTION)) {
 | 
			
		||||
		init_md_filtering(1);
 | 
			
		||||
		if ((filters[nr_filt] = md_filter_create()))
 | 
			
		||||
@@ -584,14 +587,14 @@ static int _init_filters(struct cmd_context *cmd)
 | 
			
		||||
	if (!(f3 = _init_filter_components(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(cache_file, sizeof(cache_file),
 | 
			
		||||
	if (dm_snprintf(cache_file, sizeof(cache_file),
 | 
			
		||||
			 "%s/.cache", cmd->sys_dir) < 0) {
 | 
			
		||||
		log_error("Persistent cache filename too long ('%s/.cache').",
 | 
			
		||||
			  cmd->sys_dir);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev_cache = find_config_str(cmd->cft->root, "devices/cache",
 | 
			
		||||
	dev_cache = find_config_tree_str(cmd, "devices/cache",
 | 
			
		||||
				    cache_file);
 | 
			
		||||
	if (!(f4 = persistent_filter_create(f3, dev_cache))) {
 | 
			
		||||
		log_error("Failed to create persistent device filter");
 | 
			
		||||
@@ -599,7 +602,7 @@ static int _init_filters(struct cmd_context *cmd)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Should we ever dump persistent filter state? */
 | 
			
		||||
	if (find_config_int(cmd->cft->root, "devices/write_cache_state", 1))
 | 
			
		||||
	if (find_config_tree_int(cmd, "devices/write_cache_state", 1))
 | 
			
		||||
		cmd->dump_filter = 1;
 | 
			
		||||
 | 
			
		||||
	if (!*cmd->sys_dir)
 | 
			
		||||
@@ -643,8 +646,9 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	/* Load any formats in shared libs */
 | 
			
		||||
	if ((cn = find_config_node(cmd->cft->root, "global/format_libraries"))) {
 | 
			
		||||
	/* Load any formats in shared libs if not static */
 | 
			
		||||
	if (!cmd->is_static &&
 | 
			
		||||
	    (cn = find_config_tree_node(cmd, "global/format_libraries"))) {
 | 
			
		||||
 | 
			
		||||
		struct config_value *cv;
 | 
			
		||||
		struct format_type *(*init_format_fn) (struct cmd_context *);
 | 
			
		||||
@@ -656,8 +660,8 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
					  "global/format_libraries");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(lib = load_shared_library(cmd->cft, cv->v.str,
 | 
			
		||||
							"format"))) {
 | 
			
		||||
			if (!(lib = load_shared_library(cmd, cv->v.str,
 | 
			
		||||
							"format", 0))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -684,7 +688,7 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	cmd->fmt_backup = fmt;
 | 
			
		||||
 | 
			
		||||
	format = find_config_str(cmd->cft->root, "global/format",
 | 
			
		||||
	format = find_config_tree_str(cmd, "global/format",
 | 
			
		||||
				 DEFAULT_FORMAT);
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(fmt, &cmd->formats) {
 | 
			
		||||
@@ -737,8 +741,9 @@ static int _init_segtypes(struct cmd_context *cmd)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	/* Load any formats in shared libs */
 | 
			
		||||
	if ((cn = find_config_node(cmd->cft->root, "global/segment_libraries"))) {
 | 
			
		||||
	/* Load any formats in shared libs unless static */
 | 
			
		||||
	if (!cmd->is_static &&
 | 
			
		||||
	    (cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
 | 
			
		||||
 | 
			
		||||
		struct config_value *cv;
 | 
			
		||||
		struct segment_type *(*init_segtype_fn) (struct cmd_context *);
 | 
			
		||||
@@ -752,8 +757,8 @@ static int _init_segtypes(struct cmd_context *cmd)
 | 
			
		||||
					  "global/segment_libraries");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(lib = load_shared_library(cmd->cft, cv->v.str,
 | 
			
		||||
							"segment type"))) {
 | 
			
		||||
			if (!(lib = load_shared_library(cmd, cv->v.str,
 | 
			
		||||
							"segment type", 0))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -827,16 +832,16 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* set up archiving */
 | 
			
		||||
	cmd->default_settings.archive =
 | 
			
		||||
	    find_config_bool(cmd->cft->root, "backup/archive",
 | 
			
		||||
	    find_config_tree_bool(cmd, "backup/archive",
 | 
			
		||||
			     DEFAULT_ARCHIVE_ENABLED);
 | 
			
		||||
 | 
			
		||||
	days = (uint32_t) find_config_int(cmd->cft->root, "backup/retain_days",
 | 
			
		||||
	days = (uint32_t) find_config_tree_int(cmd, "backup/retain_days",
 | 
			
		||||
					  DEFAULT_ARCHIVE_DAYS);
 | 
			
		||||
 | 
			
		||||
	min = (uint32_t) find_config_int(cmd->cft->root, "backup/retain_min",
 | 
			
		||||
	min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min",
 | 
			
		||||
					 DEFAULT_ARCHIVE_NUMBER);
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf
 | 
			
		||||
	if (dm_snprintf
 | 
			
		||||
	    (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
 | 
			
		||||
	     DEFAULT_ARCHIVE_SUBDIR) == -1) {
 | 
			
		||||
		log_err("Couldn't create default archive path '%s/%s'.",
 | 
			
		||||
@@ -844,7 +849,7 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dir = find_config_str(cmd->cft->root, "backup/archive_dir",
 | 
			
		||||
	dir = find_config_tree_str(cmd, "backup/archive_dir",
 | 
			
		||||
			      default_dir);
 | 
			
		||||
 | 
			
		||||
	if (!archive_init(cmd, dir, days, min)) {
 | 
			
		||||
@@ -854,10 +859,10 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* set up the backup */
 | 
			
		||||
	cmd->default_settings.backup =
 | 
			
		||||
	    find_config_bool(cmd->cft->root, "backup/backup",
 | 
			
		||||
	    find_config_tree_bool(cmd, "backup/backup",
 | 
			
		||||
			     DEFAULT_BACKUP_ENABLED);
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf
 | 
			
		||||
	if (dm_snprintf
 | 
			
		||||
	    (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
 | 
			
		||||
	     DEFAULT_BACKUP_SUBDIR) == -1) {
 | 
			
		||||
		log_err("Couldn't create default backup path '%s/%s'.",
 | 
			
		||||
@@ -865,7 +870,7 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dir = find_config_str(cmd->cft->root, "backup/backup_dir", default_dir);
 | 
			
		||||
	dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir);
 | 
			
		||||
 | 
			
		||||
	if (!backup_init(cmd, dir)) {
 | 
			
		||||
		log_debug("backup_init failed.");
 | 
			
		||||
@@ -876,7 +881,7 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Entry point */
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_context *cmd;
 | 
			
		||||
 | 
			
		||||
@@ -899,6 +904,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
	}
 | 
			
		||||
	memset(cmd, 0, sizeof(*cmd));
 | 
			
		||||
	cmd->args = the_args;
 | 
			
		||||
	cmd->is_static = is_static;
 | 
			
		||||
	cmd->hosttags = 0;
 | 
			
		||||
	list_init(&cmd->formats);
 | 
			
		||||
	list_init(&cmd->segtypes);
 | 
			
		||||
@@ -921,7 +927,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) {
 | 
			
		||||
		log_error("Library memory pool creation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_init_lvm_conf(cmd))
 | 
			
		||||
@@ -952,7 +958,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
 | 
			
		||||
		log_error("Command memory pool creation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memlock_init(cmd);
 | 
			
		||||
@@ -1021,7 +1027,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
			persistent_filter_dump(cmd->filter);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	activation_exit();
 | 
			
		||||
	activation_release();
 | 
			
		||||
	lvmcache_destroy();
 | 
			
		||||
	label_exit();
 | 
			
		||||
	_destroy_segtypes(&cmd->segtypes);
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,7 @@ struct cmd_context {
 | 
			
		||||
	struct command *command;
 | 
			
		||||
	struct arg *args;
 | 
			
		||||
	char **argv;
 | 
			
		||||
	unsigned is_static;	/* Static binary? */
 | 
			
		||||
 | 
			
		||||
	struct dev_filter *filter;
 | 
			
		||||
	int dump_filter;	/* Dump filter when exiting? */
 | 
			
		||||
@@ -71,6 +72,7 @@ struct cmd_context {
 | 
			
		||||
	struct list config_files;
 | 
			
		||||
	int config_valid;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
	struct config_tree *cft_override;
 | 
			
		||||
	struct config_info default_settings;
 | 
			
		||||
	struct config_info current_settings;
 | 
			
		||||
 | 
			
		||||
@@ -86,7 +88,7 @@ struct cmd_context {
 | 
			
		||||
	char proc_dir[PATH_MAX];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args);
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static);
 | 
			
		||||
void destroy_toolcontext(struct cmd_context *cmd);
 | 
			
		||||
int refresh_toolcontext(struct cmd_context *cmd);
 | 
			
		||||
int config_files_changed(struct cmd_context *cmd);
 | 
			
		||||
 
 | 
			
		||||
@@ -41,10 +41,10 @@ enum {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct parser {
 | 
			
		||||
	char *fb, *fe;		/* file limits */
 | 
			
		||||
	const char *fb, *fe;		/* file limits */
 | 
			
		||||
 | 
			
		||||
	int t;			/* token limits and type */
 | 
			
		||||
	char *tb, *te;
 | 
			
		||||
	const char *tb, *te;
 | 
			
		||||
 | 
			
		||||
	int fd;			/* descriptor for file being parsed */
 | 
			
		||||
	int line;		/* line number we are on */
 | 
			
		||||
@@ -77,7 +77,7 @@ static const int sep = '/';
 | 
			
		||||
 | 
			
		||||
#define match(t) do {\
 | 
			
		||||
   if (!_match_aux(p, (t))) {\
 | 
			
		||||
	log_error("Parse error at line %d: unexpected token", p->line); \
 | 
			
		||||
	log_error("Parse error at byte %d (line %d): unexpected token", p->tb - p->fb + 1, p->line); \
 | 
			
		||||
      return 0;\
 | 
			
		||||
   } \
 | 
			
		||||
} while(0);
 | 
			
		||||
@@ -101,12 +101,12 @@ struct config_tree *create_config_tree(const char *filename)
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
 | 
			
		||||
 | 
			
		||||
	if (!mem) {
 | 
			
		||||
		stack;
 | 
			
		||||
		log_error("Failed to allocate config pool.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		log_error("Failed to allocate config tree.");
 | 
			
		||||
		dm_pool_destroy(mem);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -125,6 +125,46 @@ void destroy_config_tree(struct config_tree *cft)
 | 
			
		||||
	dm_pool_destroy(((struct cs *) cft)->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _parse_config_file(struct parser *p, struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	p->tb = p->te = p->fb;
 | 
			
		||||
	p->line = 1;
 | 
			
		||||
	_get_token(p, TOK_SECTION_E);
 | 
			
		||||
	if (!(cft->root = _file(p)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
 | 
			
		||||
						   const char *config_settings)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
	struct parser *p;
 | 
			
		||||
 | 
			
		||||
	if (!(cft = create_config_tree(NULL)))
 | 
			
		||||
		return_NULL;
 | 
			
		||||
 | 
			
		||||
	c = (struct cs *) cft;
 | 
			
		||||
	if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
 | 
			
		||||
		log_error("Failed to allocate config tree parser.");
 | 
			
		||||
		destroy_config_tree(cft);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p->mem = c->mem;
 | 
			
		||||
	p->fb = config_settings;
 | 
			
		||||
	p->fe = config_settings + strlen(config_settings);
 | 
			
		||||
 | 
			
		||||
	if (!_parse_config_file(p, cft)) {
 | 
			
		||||
		destroy_config_tree(cft);
 | 
			
		||||
		return_NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cft;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		   off_t offset, size_t size, off_t offset2, size_t size2,
 | 
			
		||||
		   checksum_fn_t checksum_fn, uint32_t checksum)
 | 
			
		||||
@@ -134,6 +174,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	int use_mmap = 1;
 | 
			
		||||
	off_t mmap_offset = 0;
 | 
			
		||||
	char *buf;
 | 
			
		||||
 | 
			
		||||
	if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -146,7 +187,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		use_mmap = 0;
 | 
			
		||||
 | 
			
		||||
	if (use_mmap) {
 | 
			
		||||
		mmap_offset = offset % getpagesize();
 | 
			
		||||
		mmap_offset = offset % lvm_getpagesize();
 | 
			
		||||
		/* memory map the file */
 | 
			
		||||
		p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
 | 
			
		||||
			     MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
 | 
			
		||||
@@ -156,22 +197,23 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		}
 | 
			
		||||
		p->fb = p->fb + mmap_offset;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!(p->fb = dm_malloc(size + size2))) {
 | 
			
		||||
		if (!(buf = dm_malloc(size + size2))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (!dev_read(dev, (uint64_t) offset, size, p->fb)) {
 | 
			
		||||
		if (!dev_read(dev, (uint64_t) offset, size, buf)) {
 | 
			
		||||
			log_error("Read from %s failed", dev_name(dev));
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (size2) {
 | 
			
		||||
			if (!dev_read(dev, (uint64_t) offset2, size2,
 | 
			
		||||
				      p->fb + size)) {
 | 
			
		||||
				      buf + size)) {
 | 
			
		||||
				log_error("Circular read from %s failed",
 | 
			
		||||
					  dev_name(dev));
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		p->fb = buf;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (checksum_fn && checksum !=
 | 
			
		||||
@@ -183,11 +225,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
 | 
			
		||||
	p->fe = p->fb + size + size2;
 | 
			
		||||
 | 
			
		||||
	/* parse */
 | 
			
		||||
	p->tb = p->te = p->fb;
 | 
			
		||||
	p->line = 1;
 | 
			
		||||
	_get_token(p, TOK_SECTION_E);
 | 
			
		||||
	if (!(cft->root = _file(p))) {
 | 
			
		||||
	if (!_parse_config_file(p, cft)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -196,7 +234,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!use_mmap)
 | 
			
		||||
		dm_free(p->fb);
 | 
			
		||||
		dm_free(buf);
 | 
			
		||||
	else {
 | 
			
		||||
		/* unmap the file */
 | 
			
		||||
		if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
 | 
			
		||||
@@ -529,7 +567,7 @@ static struct config_value *_type(struct parser *p)
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("Parse error at line %d: expected a value", p->line);
 | 
			
		||||
		log_error("Parse error at byte %d (line %d): expected a value", p->tb - p->fb + 1, p->line);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return v;
 | 
			
		||||
@@ -688,14 +726,20 @@ static void _eat_space(struct parser *p)
 | 
			
		||||
static struct config_value *_create_value(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
 | 
			
		||||
	memset(v, 0, sizeof(*v));
 | 
			
		||||
 | 
			
		||||
	if (v)
 | 
			
		||||
		memset(v, 0, sizeof(*v));
 | 
			
		||||
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct config_node *_create_node(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
 | 
			
		||||
	memset(n, 0, sizeof(*n));
 | 
			
		||||
 | 
			
		||||
	if (n)
 | 
			
		||||
		memset(n, 0, sizeof(*n));
 | 
			
		||||
 | 
			
		||||
	return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -715,8 +759,8 @@ static char *_dup_tok(struct parser *p)
 | 
			
		||||
/*
 | 
			
		||||
 * utility functions
 | 
			
		||||
 */
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path)
 | 
			
		||||
static struct config_node *_find_config_node(const struct config_node *cn,
 | 
			
		||||
					     const char *path)
 | 
			
		||||
{
 | 
			
		||||
	const char *e;
 | 
			
		||||
 | 
			
		||||
@@ -747,14 +791,36 @@ struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
	return (struct config_node *) cn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *find_config_str(const struct config_node *cn,
 | 
			
		||||
			    const char *path, const char *fail)
 | 
			
		||||
static struct config_node *_find_first_config_node(const struct config_node *cn1,
 | 
			
		||||
						   const struct config_node *cn2,
 | 
			
		||||
						   const char *path)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_STRING) {
 | 
			
		||||
		if (*n->v->v.str)
 | 
			
		||||
			log_very_verbose("Setting %s to %s", path, n->v->v.str);
 | 
			
		||||
	if (cn1 && (cn = _find_config_node(cn1, path)))
 | 
			
		||||
		return cn;
 | 
			
		||||
 | 
			
		||||
	if (cn2 && (cn = _find_config_node(cn2, path)))
 | 
			
		||||
		return cn;
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_node(cn, path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *_find_config_str(const struct config_node *cn1,
 | 
			
		||||
				    const struct config_node *cn2,
 | 
			
		||||
				    const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
 | 
			
		||||
	/* Empty strings are ignored */
 | 
			
		||||
	if ((n && n->v->type == CFG_STRING) && (*n->v->v.str)) {
 | 
			
		||||
		log_very_verbose("Setting %s to %s", path, n->v->v.str);
 | 
			
		||||
		return n->v->v.str;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -764,9 +830,17 @@ const char *find_config_str(const struct config_node *cn,
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
const char *find_config_str(const struct config_node *cn,
 | 
			
		||||
			    const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	return _find_config_str(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _find_config_int(const struct config_node *cn1,
 | 
			
		||||
			    const struct config_node *cn2,
 | 
			
		||||
			    const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_INT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %d", path, n->v->v.i);
 | 
			
		||||
@@ -778,10 +852,16 @@ int find_config_int(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail)
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	return _find_config_int(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static float _find_config_float(const struct config_node *cn1,
 | 
			
		||||
				const struct config_node *cn2,
 | 
			
		||||
				const char *path, float fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_FLOAT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %f", path, n->v->v.r);
 | 
			
		||||
@@ -795,6 +875,36 @@ float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_float(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_tree_node(struct cmd_context *cmd,
 | 
			
		||||
                                          const char *path)
 | 
			
		||||
{
 | 
			
		||||
	return _find_first_config_node(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *find_config_tree_str(struct cmd_context *cmd,
 | 
			
		||||
                                 const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_str(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_tree_int(struct cmd_context *cmd, const char *path,
 | 
			
		||||
                         int fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_int(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_tree_float(struct cmd_context *cmd, const char *path,
 | 
			
		||||
                             float fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _str_in_array(const char *str, const char *values[])
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
@@ -821,9 +931,11 @@ static int _str_to_bool(const char *str, int fail)
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_bool(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
static int _find_config_bool(const struct config_node *cn1,
 | 
			
		||||
			     const struct config_node *cn2,
 | 
			
		||||
			     const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
	struct config_value *v;
 | 
			
		||||
 | 
			
		||||
	if (!n)
 | 
			
		||||
@@ -842,6 +954,16 @@ int find_config_bool(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_bool(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_bool(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_bool(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_config_uint32(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint32_t *result)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -54,9 +54,11 @@ struct config_tree_list {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct config_tree *create_config_tree(const char *filename);
 | 
			
		||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
 | 
			
		||||
						   const char *config_settings);
 | 
			
		||||
void destroy_config_tree(struct config_tree *cft);
 | 
			
		||||
 | 
			
		||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
 | 
			
		||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const void *buf, uint32_t size);
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		   off_t offset, size_t size, off_t offset2, size_t size2,
 | 
			
		||||
@@ -71,20 +73,30 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path);
 | 
			
		||||
 | 
			
		||||
const char *find_config_str(const struct config_node *cn, const char *path,
 | 
			
		||||
			    const char *fail);
 | 
			
		||||
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail);
 | 
			
		||||
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * These versions check an override tree, if present, first.
 | 
			
		||||
 */
 | 
			
		||||
struct config_node *find_config_tree_node(struct cmd_context *cmd,
 | 
			
		||||
					  const char *path);
 | 
			
		||||
const char *find_config_tree_str(struct cmd_context *cmd,
 | 
			
		||||
				 const char *path, const char *fail);
 | 
			
		||||
int find_config_tree_int(struct cmd_context *cmd, const char *path,
 | 
			
		||||
			 int fail);
 | 
			
		||||
float find_config_tree_float(struct cmd_context *cmd, const char *path,
 | 
			
		||||
			     float fail);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Understands (0, ~0), (y, n), (yes, no), (on,
 | 
			
		||||
 * off), (true, false).
 | 
			
		||||
 */
 | 
			
		||||
int find_config_bool(const struct config_node *cn, const char *path, int fail);
 | 
			
		||||
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail);
 | 
			
		||||
 | 
			
		||||
int get_config_uint32(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint32_t *result);
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,14 @@
 | 
			
		||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
 | 
			
		||||
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
 | 
			
		||||
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
 | 
			
		||||
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
 | 
			
		||||
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
 | 
			
		||||
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
 | 
			
		||||
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
 | 
			
		||||
#define DEFAULT_DMEVENTD_MONITOR 1
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_UMASK 0077
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -107,7 +107,7 @@ void *btree_get_data(struct btree_iter *it)
 | 
			
		||||
	return ((struct node *) it)->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct node *_left(struct node *n)
 | 
			
		||||
static struct node *_left(struct node *n)
 | 
			
		||||
{
 | 
			
		||||
	while (n->l)
 | 
			
		||||
		n = n->l;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										136
									
								
								lib/datastruct/list.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								lib/datastruct/list.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,136 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initialise a list before use.
 | 
			
		||||
 * The list head's next and previous pointers point back to itself.
 | 
			
		||||
 */
 | 
			
		||||
void list_init(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	head->n = head->p = head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element before 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the end of the list.
 | 
			
		||||
 */
 | 
			
		||||
void list_add(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
 | 
			
		||||
	elem->n = head;
 | 
			
		||||
	elem->p = head->p;
 | 
			
		||||
 | 
			
		||||
	head->p->n = elem;
 | 
			
		||||
	head->p = elem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element after 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the front of the list.
 | 
			
		||||
 */
 | 
			
		||||
void list_add_h(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
 | 
			
		||||
	elem->n = head->n;
 | 
			
		||||
	elem->p = head;
 | 
			
		||||
 | 
			
		||||
	head->n->p = elem;
 | 
			
		||||
	head->n = elem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Delete an element from its list.
 | 
			
		||||
 * Note that this doesn't change the element itself - it may still be safe
 | 
			
		||||
 * to follow its pointers.
 | 
			
		||||
 */
 | 
			
		||||
void list_del(struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	elem->n->p = elem->p;
 | 
			
		||||
	elem->p->n = elem->n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is the list empty?
 | 
			
		||||
 */
 | 
			
		||||
int list_empty(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return head->n == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the first element of the list?
 | 
			
		||||
 */
 | 
			
		||||
int list_start(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->p == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the last element of the list?
 | 
			
		||||
 */
 | 
			
		||||
int list_end(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->n == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return first element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_first(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return last element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_last(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the previous element of the list, or NULL if we've reached the start.
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_prev(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_start(head, elem) ? NULL : elem->p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the next element of the list, or NULL if we've reached the end.
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_end(head, elem) ? NULL : elem->n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the number of elements in a list by walking it.
 | 
			
		||||
 */
 | 
			
		||||
unsigned int list_size(const struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s = 0;
 | 
			
		||||
	const struct list *v;
 | 
			
		||||
 | 
			
		||||
	list_iterate(v, head)
 | 
			
		||||
	    s++;
 | 
			
		||||
 | 
			
		||||
	return s;
 | 
			
		||||
}
 | 
			
		||||
@@ -33,107 +33,61 @@ struct list {
 | 
			
		||||
 * The list head's next and previous pointers point back to itself.
 | 
			
		||||
 */
 | 
			
		||||
#define LIST_INIT(name)	struct list name = { &(name), &(name) }
 | 
			
		||||
static inline void list_init(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	head->n = head->p = head;
 | 
			
		||||
}
 | 
			
		||||
void list_init(struct list *head);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element before 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the end of the list.
 | 
			
		||||
 */
 | 
			
		||||
static inline void list_add(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
 | 
			
		||||
	elem->n = head;
 | 
			
		||||
	elem->p = head->p;
 | 
			
		||||
 | 
			
		||||
	head->p->n = elem;
 | 
			
		||||
	head->p = elem;
 | 
			
		||||
}
 | 
			
		||||
void list_add(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element after 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the front of the list.
 | 
			
		||||
 */
 | 
			
		||||
static inline void list_add_h(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
 | 
			
		||||
	elem->n = head->n;
 | 
			
		||||
	elem->p = head;
 | 
			
		||||
 | 
			
		||||
	head->n->p = elem;
 | 
			
		||||
	head->n = elem;
 | 
			
		||||
}
 | 
			
		||||
void list_add_h(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Delete an element from its list.
 | 
			
		||||
 * Note that this doesn't change the element itself - it may still be safe
 | 
			
		||||
 * to follow its pointers.
 | 
			
		||||
 */
 | 
			
		||||
static inline void list_del(struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	elem->n->p = elem->p;
 | 
			
		||||
	elem->p->n = elem->n;
 | 
			
		||||
}
 | 
			
		||||
void list_del(struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is the list empty?
 | 
			
		||||
 */
 | 
			
		||||
static inline int list_empty(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return head->n == head;
 | 
			
		||||
}
 | 
			
		||||
int list_empty(struct list *head);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the first element of the list?
 | 
			
		||||
 */
 | 
			
		||||
static inline int list_start(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->p == head;
 | 
			
		||||
}
 | 
			
		||||
int list_start(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the last element of the list?
 | 
			
		||||
 */
 | 
			
		||||
static inline int list_end(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->n == head;
 | 
			
		||||
}
 | 
			
		||||
int list_end(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return first element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
static inline struct list *list_first(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->n);
 | 
			
		||||
}
 | 
			
		||||
struct list *list_first(struct list *head);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return last element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
static inline struct list *list_last(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->p);
 | 
			
		||||
}
 | 
			
		||||
struct list *list_last(struct list *head);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the previous element of the list, or NULL if we've reached the start.
 | 
			
		||||
 */
 | 
			
		||||
static inline struct list *list_prev(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_start(head, elem) ? NULL : elem->p);
 | 
			
		||||
}
 | 
			
		||||
struct list *list_prev(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the next element of the list, or NULL if we've reached the end.
 | 
			
		||||
 */
 | 
			
		||||
static inline struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_end(head, elem) ? NULL : elem->n);
 | 
			
		||||
}
 | 
			
		||||
struct list *list_next(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Given the address v of an instance of 'struct list' called 'head' 
 | 
			
		||||
@@ -244,15 +198,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
/*
 | 
			
		||||
 * Return the number of elements in a list by walking it.
 | 
			
		||||
 */
 | 
			
		||||
static inline unsigned int list_size(const struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s = 0;
 | 
			
		||||
	const struct list *v;
 | 
			
		||||
 | 
			
		||||
	list_iterate(v, head)
 | 
			
		||||
	    s++;
 | 
			
		||||
 | 
			
		||||
	return s;
 | 
			
		||||
}
 | 
			
		||||
unsigned int list_size(const struct list *head);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -479,7 +479,7 @@ static void _check_closed(struct device *dev)
 | 
			
		||||
		log_err("Device '%s' has been left open.", dev_name(dev));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void _check_for_open_devices(void)
 | 
			
		||||
static void _check_for_open_devices(void)
 | 
			
		||||
{
 | 
			
		||||
	dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
 | 
			
		||||
}
 | 
			
		||||
@@ -645,8 +645,7 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (dev_scan) {
 | 
			
		||||
	if (dev_scan && !trust_cache()) {
 | 
			
		||||
		/* Flag gets reset between each command */
 | 
			
		||||
		if (!full_scan_done())
 | 
			
		||||
			persistent_filter_wipe(f); /* Calls _full_scan(1) */
 | 
			
		||||
@@ -664,7 +663,7 @@ void dev_iter_destroy(struct dev_iter *iter)
 | 
			
		||||
	dm_free(iter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct device *_iter_next(struct dev_iter *iter)
 | 
			
		||||
static struct device *_iter_next(struct dev_iter *iter)
 | 
			
		||||
{
 | 
			
		||||
	struct device *d = btree_get_data(iter->current);
 | 
			
		||||
	iter->current = btree_next(iter->current);
 | 
			
		||||
@@ -682,3 +681,14 @@ struct device *dev_iter_get(struct dev_iter *iter)
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_fd(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dev_name(const struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
 | 
			
		||||
	    "unknown device";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -176,7 +176,7 @@ static int _aligned_io(struct device_area *where, void *buffer,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!block_size)
 | 
			
		||||
		block_size = getpagesize();
 | 
			
		||||
		block_size = lvm_getpagesize();
 | 
			
		||||
 | 
			
		||||
	_widen_region(block_size, where, &widened);
 | 
			
		||||
 | 
			
		||||
@@ -418,7 +418,6 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
 | 
			
		||||
	    ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
 | 
			
		||||
		log_error("%s: fstat failed: Has device name changed?", name);
 | 
			
		||||
		dev_close_immediate(dev);
 | 
			
		||||
		dev->open_count = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -509,11 +508,9 @@ static int _dev_close(struct device *dev, int immediate)
 | 
			
		||||
	if (dev->open_count > 0)
 | 
			
		||||
		dev->open_count--;
 | 
			
		||||
 | 
			
		||||
	if (immediate && dev->open_count) {
 | 
			
		||||
	if (immediate && dev->open_count)
 | 
			
		||||
		log_debug("%s: Immediate close attempt while still referenced",
 | 
			
		||||
			  dev_name(dev));
 | 
			
		||||
		dev->open_count = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Close unless device is known to belong to a locked VG */
 | 
			
		||||
	if (immediate ||
 | 
			
		||||
@@ -605,7 +602,7 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
	return _aligned_io(&where, buffer, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
 | 
			
		||||
{
 | 
			
		||||
	size_t s;
 | 
			
		||||
	char buffer[4096];
 | 
			
		||||
@@ -623,7 +620,7 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
			  " sectors", dev_name(dev), offset >> SECTOR_SHIFT,
 | 
			
		||||
			  len >> SECTOR_SHIFT);
 | 
			
		||||
 | 
			
		||||
	memset(buffer, 0, sizeof(buffer));
 | 
			
		||||
	memset(buffer, value, sizeof(buffer));
 | 
			
		||||
	while (1) {
 | 
			
		||||
		s = len > sizeof(buffer) ? sizeof(buffer) : len;
 | 
			
		||||
		if (!dev_write(dev, offset, s, buffer))
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ static int _has_partition_table(struct device *dev)
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_read(dev, 0, sizeof(buf), &buf)) {
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -74,26 +74,18 @@ int dev_close_immediate(struct device *dev);
 | 
			
		||||
void dev_close_all(void);
 | 
			
		||||
int dev_test_excl(struct device *dev);
 | 
			
		||||
 | 
			
		||||
static inline int dev_fd(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd;
 | 
			
		||||
}
 | 
			
		||||
int dev_fd(struct device *dev);
 | 
			
		||||
const char *dev_name(const struct device *dev);
 | 
			
		||||
 | 
			
		||||
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int dev_append(struct device *dev, size_t len, void *buffer);
 | 
			
		||||
int dev_zero(struct device *dev, uint64_t offset, size_t len);
 | 
			
		||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);
 | 
			
		||||
void dev_flush(struct device *dev);
 | 
			
		||||
 | 
			
		||||
struct device *dev_create_file(const char *filename, struct device *dev,
 | 
			
		||||
			       struct str_list *alias, int use_malloc);
 | 
			
		||||
 | 
			
		||||
static inline const char *dev_name(const struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
 | 
			
		||||
	    "unknown device";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return a valid device name from the alias list; NULL otherwise */
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev, int quiet);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,12 +22,15 @@
 | 
			
		||||
 | 
			
		||||
#define SIZE_BUF 128
 | 
			
		||||
 | 
			
		||||
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
	alloc_policy_t alloc;
 | 
			
		||||
	const char *str;
 | 
			
		||||
} _policies[] = {
 | 
			
		||||
	{
 | 
			
		||||
	ALLOC_CONTIGUOUS, "contiguous"}, {
 | 
			
		||||
	ALLOC_CLING, "cling"}, {
 | 
			
		||||
	ALLOC_NORMAL, "normal"}, {
 | 
			
		||||
	ALLOC_ANYWHERE, "anywhere"}, {
 | 
			
		||||
	ALLOC_INHERIT, "inherit"}
 | 
			
		||||
@@ -132,7 +135,7 @@ alloc_policy_t get_alloc_from_string(const char *str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Size supplied in sectors */
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
{
 | 
			
		||||
	int s;
 | 
			
		||||
	int suffix = 1, precision;
 | 
			
		||||
@@ -200,6 +203,21 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
	return size_buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size_long(struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _display_size(cmd, size, SIZE_LONG);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size_units(struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _display_size(cmd, size, SIZE_UNIT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _display_size(cmd, size, SIZE_SHORT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pvdisplay_colons(struct physical_volume *pv)
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
@@ -228,7 +246,7 @@ void pvdisplay_colons(struct physical_volume *pv)
 | 
			
		||||
 | 
			
		||||
/* FIXME Include label fields */
 | 
			
		||||
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
		    void *handle)
 | 
			
		||||
		    void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	const char *size;
 | 
			
		||||
@@ -248,18 +266,17 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
	log_print("VG Name               %s%s", pv->vg_name,
 | 
			
		||||
		  pv->status & EXPORTED_VG ? " (exported)" : "");
 | 
			
		||||
 | 
			
		||||
	size = display_size(cmd, (uint64_t) pv->size, SIZE_SHORT);
 | 
			
		||||
	size = display_size(cmd, (uint64_t) pv->size);
 | 
			
		||||
	if (pv->pe_size && pv->pe_count) {
 | 
			
		||||
 | 
			
		||||
/******** FIXME display LVM on-disk data size
 | 
			
		||||
		size2 = display_size(pv->size, SIZE_SHORT);
 | 
			
		||||
		size2 = display_size(cmd, pv->size);
 | 
			
		||||
********/
 | 
			
		||||
 | 
			
		||||
		log_print("PV Size               %s" " / not usable %s",	/*  [LVM: %s]", */
 | 
			
		||||
			  size,
 | 
			
		||||
			  display_size(cmd, (pv->size -
 | 
			
		||||
				       (uint64_t) pv->pe_count * pv->pe_size),
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
				       (uint64_t) pv->pe_count * pv->pe_size)));
 | 
			
		||||
 | 
			
		||||
	} else
 | 
			
		||||
		log_print("PV Size               %s", size);
 | 
			
		||||
@@ -288,8 +305,10 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
		    struct physical_volume *pv, void *handle)
 | 
			
		||||
int pvdisplay_short(struct cmd_context *cmd __attribute((unused)),
 | 
			
		||||
		    struct volume_group *vg __attribute((unused)),
 | 
			
		||||
		    struct physical_volume *pv,
 | 
			
		||||
		    void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
 | 
			
		||||
@@ -334,7 +353,7 @@ void lvdisplay_colons(struct logical_volume *lv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		   void *handle)
 | 
			
		||||
		   void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int inkernel, snap_active = 0;
 | 
			
		||||
@@ -404,23 +423,21 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
 | 
			
		||||
	log_print("LV Size                %s",
 | 
			
		||||
		  display_size(cmd,
 | 
			
		||||
			       snap_seg ? snap_seg->origin->size : lv->size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       snap_seg ? snap_seg->origin->size : lv->size));
 | 
			
		||||
 | 
			
		||||
	log_print("Current LE             %u",
 | 
			
		||||
		  snap_seg ? snap_seg->origin->le_count : lv->le_count);
 | 
			
		||||
 | 
			
		||||
	if (snap_seg) {
 | 
			
		||||
		log_print("COW-table size         %s",
 | 
			
		||||
			  display_size(cmd, (uint64_t) lv->size, SIZE_SHORT));
 | 
			
		||||
			  display_size(cmd, (uint64_t) lv->size));
 | 
			
		||||
		log_print("COW-table LE           %u", lv->le_count);
 | 
			
		||||
 | 
			
		||||
		if (snap_active)
 | 
			
		||||
			log_print("Allocated to snapshot  %.2f%% ", snap_percent);	
 | 
			
		||||
 | 
			
		||||
		log_print("Snapshot chunk size    %s",
 | 
			
		||||
			  display_size(cmd, (uint64_t) snap_seg->chunk_size,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(cmd, (uint64_t) snap_seg->chunk_size));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print("Segments               %u", list_size(&lv->segments));
 | 
			
		||||
@@ -497,7 +514,7 @@ int lvdisplay_segments(struct logical_volume *lv)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vgdisplay_extents(struct volume_group *vg)
 | 
			
		||||
void vgdisplay_extents(struct volume_group *vg __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
@@ -544,7 +561,7 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
	log_print("Open LV               %u", lvs_in_vg_opened(vg));
 | 
			
		||||
/****** FIXME Max LV Size
 | 
			
		||||
      log_print ( "MAX LV Size           %s",
 | 
			
		||||
               ( s1 = display_size ( LVM_LV_SIZE_MAX(vg), SIZE_SHORT)));
 | 
			
		||||
               ( s1 = display_size ( LVM_LV_SIZE_MAX(vg))));
 | 
			
		||||
      free ( s1);
 | 
			
		||||
*********/
 | 
			
		||||
	log_print("Max PV                %u", vg->max_pv);
 | 
			
		||||
@@ -553,12 +570,10 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	log_print("VG Size               %s",
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	log_print("PE Size               %s",
 | 
			
		||||
		  display_size(vg->cmd, (uint64_t) vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
		  display_size(vg->cmd, (uint64_t) vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	log_print("Total PE              %u", vg->extent_count);
 | 
			
		||||
 | 
			
		||||
@@ -566,12 +581,11 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
		  vg->extent_count - vg->free_count,
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       ((uint64_t) vg->extent_count - vg->free_count) *
 | 
			
		||||
			       vg->extent_size, SIZE_SHORT));
 | 
			
		||||
			       vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	log_print("Free  PE / Size       %u / %s", vg->free_count,
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -641,15 +655,12 @@ void vgdisplay_short(struct volume_group *vg)
 | 
			
		||||
	log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
 | 
			
		||||
/********* FIXME if "open" print "/used" else print "/idle"???  ******/
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT),
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size),
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       ((uint64_t) vg->extent_count -
 | 
			
		||||
				vg->free_count) * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT),
 | 
			
		||||
				vg->free_count) * vg->extent_size),
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size));
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,12 +20,13 @@
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
 | 
			
		||||
 | 
			
		||||
uint64_t units_to_bytes(const char *units, char *unit_type);
 | 
			
		||||
 | 
			
		||||
/* Specify size in KB */
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl);
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size);
 | 
			
		||||
const char *display_size_long(struct cmd_context *cmd, uint64_t size);
 | 
			
		||||
const char *display_size_units(struct cmd_context *cmd, uint64_t size);
 | 
			
		||||
 | 
			
		||||
char *display_uuid(char *uuidstr);
 | 
			
		||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,13 +23,14 @@
 | 
			
		||||
#include "targets.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
 | 
			
		||||
static const char *_name(const struct lv_segment *seg)
 | 
			
		||||
static const char *_errseg_name(const struct lv_segment *seg)
 | 
			
		||||
{
 | 
			
		||||
	return seg->segtype->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 | 
			
		||||
static int _errseg_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 | 
			
		||||
{
 | 
			
		||||
	seg1->len += seg2->len;
 | 
			
		||||
	seg1->area_len += seg2->area_len;
 | 
			
		||||
@@ -38,43 +39,58 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
 | 
			
		||||
				struct config_tree *cft, void **target_state,
 | 
			
		||||
				struct lv_segment *seg,
 | 
			
		||||
static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
 | 
			
		||||
				struct dm_pool *mem __attribute((unused)),
 | 
			
		||||
				struct cmd_context *cmd __attribute((unused)),
 | 
			
		||||
				void **target_state __attribute((unused)),
 | 
			
		||||
				struct lv_segment *seg __attribute((unused)),
 | 
			
		||||
				struct dm_tree_node *node, uint64_t len,
 | 
			
		||||
				uint32_t *pvmove_mirror_count)
 | 
			
		||||
				uint32_t *pvmove_mirror_count __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return dm_tree_node_add_error_target(node, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _target_present(void)
 | 
			
		||||
static int _errseg_target_present(void)
 | 
			
		||||
{
 | 
			
		||||
	static int checked = 0;
 | 
			
		||||
	static int present = 0;
 | 
			
		||||
	static int _errseg_checked = 0;
 | 
			
		||||
	static int _errseg_present = 0;
 | 
			
		||||
 | 
			
		||||
	/* Reported truncated in older kernels */
 | 
			
		||||
	if (!checked &&
 | 
			
		||||
	if (!_errseg_checked &&
 | 
			
		||||
	    (target_present("error", 0) || target_present("erro", 0)))
 | 
			
		||||
		present = 1;
 | 
			
		||||
		_errseg_present = 1;
 | 
			
		||||
 | 
			
		||||
	checked = 1;
 | 
			
		||||
	return present;
 | 
			
		||||
	_errseg_checked = 1;
 | 
			
		||||
	return _errseg_present;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void _destroy(const struct segment_type *segtype)
 | 
			
		||||
static int _errseg_modules_needed(struct dm_pool *mem,
 | 
			
		||||
				  const struct lv_segment *seg,
 | 
			
		||||
				  struct list *modules)
 | 
			
		||||
{
 | 
			
		||||
	dm_free((void *) segtype);
 | 
			
		||||
	if (!str_list_add(mem, modules, "error")) {
 | 
			
		||||
		log_error("error module string list allocation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
static void _errseg_destroy(const struct segment_type *segtype)
 | 
			
		||||
{
 | 
			
		||||
	dm_free((void *)segtype);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct segtype_handler _error_ops = {
 | 
			
		||||
	name:_name,
 | 
			
		||||
	merge_segments:_merge_segments,
 | 
			
		||||
	.name = _errseg_name,
 | 
			
		||||
	.merge_segments = _errseg_merge_segments,
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
	add_target_line:_add_target_line,
 | 
			
		||||
	target_present:_target_present,
 | 
			
		||||
	.add_target_line = _errseg_add_target_line,
 | 
			
		||||
	.target_present = _errseg_target_present,
 | 
			
		||||
#endif
 | 
			
		||||
	destroy:_destroy,
 | 
			
		||||
	.modules_needed = _errseg_modules_needed,
 | 
			
		||||
	.destroy = _errseg_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct segment_type *init_error_segtype(struct cmd_context *cmd)
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ static int _and_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _composite_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_filter **filters = (struct dev_filter **) f->private;
 | 
			
		||||
 | 
			
		||||
@@ -70,7 +70,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cft->passes_filter = _and_p;
 | 
			
		||||
	cft->destroy = _destroy;
 | 
			
		||||
	cft->destroy = _composite_destroy;
 | 
			
		||||
	cft->private = filters_copy;
 | 
			
		||||
 | 
			
		||||
	return cft;
 | 
			
		||||
 
 | 
			
		||||
@@ -18,14 +18,6 @@
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
 | 
			
		||||
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
 | 
			
		||||
 | 
			
		||||
#define MD_SB_MAGIC 0xa92b4efc
 | 
			
		||||
#define MD_RESERVED_BYTES (64 * 1024)
 | 
			
		||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
 | 
			
		||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
 | 
			
		||||
				- MD_RESERVED_SECTORS)
 | 
			
		||||
 | 
			
		||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -217,7 +217,7 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	return (l == PF_BAD_DEVICE) ? 0 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _persistent_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct pfilter *pf = (struct pfilter *) f->private;
 | 
			
		||||
 | 
			
		||||
@@ -258,7 +258,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _lookup_p;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
	f->destroy = _persistent_destroy;
 | 
			
		||||
	f->private = pf;
 | 
			
		||||
 | 
			
		||||
	return f;
 | 
			
		||||
 
 | 
			
		||||
@@ -191,7 +191,7 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	return !rejected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _regex_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct rfilter *rf = (struct rfilter *) f->private;
 | 
			
		||||
	dm_pool_destroy(rf->mem);
 | 
			
		||||
@@ -226,7 +226,7 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _accept_p;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
	f->destroy = _regex_destroy;
 | 
			
		||||
	f->private = rf;
 | 
			
		||||
	return f;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	if (lvm_snprintf(proc_mounts, sizeof(proc_mounts),
 | 
			
		||||
	if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
 | 
			
		||||
			 "%s/mounts", proc) < 0) {
 | 
			
		||||
		log_error("Failed to create /proc/mounts string");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -44,9 +44,9 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (fgets(buffer, sizeof(buffer), fp)) {
 | 
			
		||||
		if (split_words(buffer, 4, split) == 4 &&
 | 
			
		||||
		if (dm_split_words(buffer, 4, 0, split) == 4 &&
 | 
			
		||||
		    !strcmp(split[2], "sysfs")) {
 | 
			
		||||
			if (lvm_snprintf(path, len, "%s/%s", split[1],
 | 
			
		||||
			if (dm_snprintf(path, len, "%s/%s", split[1],
 | 
			
		||||
					 "block") >= 0) {
 | 
			
		||||
				r = 1;
 | 
			
		||||
			}
 | 
			
		||||
@@ -88,7 +88,7 @@ static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_bloc
 | 
			
		||||
	return ds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline unsigned _hash_dev(dev_t dev)
 | 
			
		||||
static unsigned _hash_dev(dev_t dev)
 | 
			
		||||
{
 | 
			
		||||
	return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1);
 | 
			
		||||
}
 | 
			
		||||
@@ -183,7 +183,7 @@ static int _read_devs(struct dev_set *ds, const char *dir)
 | 
			
		||||
                if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (lvm_snprintf(path, sizeof(path), "%s/%s", dir,
 | 
			
		||||
		if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
 | 
			
		||||
				 d->d_name) < 0) {
 | 
			
		||||
			log_error("sysfs path name too long: %s in %s",
 | 
			
		||||
				  d->d_name, dir);
 | 
			
		||||
 
 | 
			
		||||
@@ -145,7 +145,7 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
	/* All types unrecognised initially */
 | 
			
		||||
	memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(proc_devices, sizeof(proc_devices),
 | 
			
		||||
	if (dm_snprintf(proc_devices, sizeof(proc_devices),
 | 
			
		||||
			 "%s/devices", proc) < 0) {
 | 
			
		||||
		log_error("Failed to create /proc/devices string");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -204,6 +204,7 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
			if (cv->type != CFG_STRING) {
 | 
			
		||||
				log_error("Expecting string in devices/types "
 | 
			
		||||
					  "in config file");
 | 
			
		||||
				fclose(pd);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			dev_len = strlen(cv->v.str);
 | 
			
		||||
@@ -213,12 +214,14 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
				log_error("Max partition count missing for %s "
 | 
			
		||||
					  "in devices/types in config file",
 | 
			
		||||
					  name);
 | 
			
		||||
				fclose(pd);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!cv->v.i) {
 | 
			
		||||
				log_error("Zero partition count invalid for "
 | 
			
		||||
					  "%s in devices/types in config file",
 | 
			
		||||
					  name);
 | 
			
		||||
				fclose(pd);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (dev_len <= strlen(line + i) &&
 | 
			
		||||
@@ -254,6 +257,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
 | 
			
		||||
 | 
			
		||||
	if (!_scan_proc_dev(proc, cn)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		dm_free(f);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ static void _xlate_vgd(struct vg_disk *disk)
 | 
			
		||||
 | 
			
		||||
static void _xlate_extents(struct pe_disk *extents, uint32_t count)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < count; i++) {
 | 
			
		||||
		extents[i].lv_num = xlate16(extents[i].lv_num);
 | 
			
		||||
@@ -116,7 +116,7 @@ static void _xlate_extents(struct pe_disk *extents, uint32_t count)
 | 
			
		||||
static int _munge_formats(struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t pe_start;
 | 
			
		||||
	int b, e;
 | 
			
		||||
	unsigned b, e;
 | 
			
		||||
 | 
			
		||||
	switch (pvd->version) {
 | 
			
		||||
	case 1:
 | 
			
		||||
@@ -153,8 +153,10 @@ static int _munge_formats(struct pv_disk *pvd)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	/* If UUID is missing, create one */
 | 
			
		||||
	if (pvd->pv_uuid[0] == '\0')
 | 
			
		||||
		uuid_from_num(pvd->pv_uuid, pvd->pv_number);
 | 
			
		||||
	if (pvd->pv_uuid[0] == '\0') {
 | 
			
		||||
		uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
 | 
			
		||||
		pvd->pv_uuid[ID_LEN] = '\0';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -172,9 +174,9 @@ static void _munge_exported_vg(struct pv_disk *pvd)
 | 
			
		||||
		return;
 | 
			
		||||
	/* FIXME also check vgd->status & VG_EXPORTED? */
 | 
			
		||||
 | 
			
		||||
	l = strlen(pvd->vg_name);
 | 
			
		||||
	l = strlen((char *)pvd->vg_name);
 | 
			
		||||
	s = sizeof(EXPORTED_TAG);
 | 
			
		||||
	if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
 | 
			
		||||
	if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
 | 
			
		||||
		pvd->vg_name[l - s + 1] = '\0';
 | 
			
		||||
                pvd->pv_status |= VG_EXPORTED;
 | 
			
		||||
        }
 | 
			
		||||
@@ -223,11 +225,11 @@ static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_vgd(struct disk_list *data)
 | 
			
		||||
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	struct vg_disk *vgd = &data->vgd;
 | 
			
		||||
	uint64_t pos = data->pvd.vg_on_disk.base;
 | 
			
		||||
	if (!dev_read(data->dev, pos, sizeof(*vgd), vgd))
 | 
			
		||||
	uint64_t pos = pvd->vg_on_disk.base;
 | 
			
		||||
 | 
			
		||||
	if (!dev_read(dev, pos, sizeof(*vgd), vgd))
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	_xlate_vgd(vgd);
 | 
			
		||||
@@ -237,14 +239,14 @@ static int _read_vgd(struct disk_list *data)
 | 
			
		||||
		
 | 
			
		||||
	/* If UUID is missing, create one */
 | 
			
		||||
	if (vgd->vg_uuid[0] == '\0')
 | 
			
		||||
		uuid_from_num(vgd->vg_uuid, vgd->vg_number);
 | 
			
		||||
		uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_uuids(struct disk_list *data)
 | 
			
		||||
{
 | 
			
		||||
	int num_read = 0;
 | 
			
		||||
	unsigned num_read = 0;
 | 
			
		||||
	struct uuid_list *ul;
 | 
			
		||||
	char buffer[NAME_LEN];
 | 
			
		||||
	uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
 | 
			
		||||
@@ -269,7 +271,7 @@ static int _read_uuids(struct disk_list *data)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int _check_lvd(struct lv_disk *lvd)
 | 
			
		||||
static int _check_lvd(struct lv_disk *lvd)
 | 
			
		||||
{
 | 
			
		||||
	return !(lvd->lv_name[0] == '\0');
 | 
			
		||||
}
 | 
			
		||||
@@ -319,13 +321,31 @@ static int _read_extents(struct disk_list *data)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __update_lvmcache(const struct format_type *fmt,
 | 
			
		||||
			      struct disk_list *dl,
 | 
			
		||||
			      struct device *dev, const char *vgid,
 | 
			
		||||
			      unsigned exported)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
 | 
			
		||||
				  (char *)dl->pvd.vg_name, vgid,
 | 
			
		||||
				  exported ? EXPORTED_VG : 0))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
 | 
			
		||||
	list_init(&info->mdas);
 | 
			
		||||
	info->status &= ~CACHE_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
				     struct device *dev, struct dm_pool *mem,
 | 
			
		||||
				     const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
 | 
			
		||||
	struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!dl) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -342,41 +362,32 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
 | 
			
		||||
				  dl->pvd.vg_name, NULL)))
 | 
			
		||||
		stack;
 | 
			
		||||
	else {
 | 
			
		||||
		info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
 | 
			
		||||
		list_init(&info->mdas);
 | 
			
		||||
		info->status &= ~CACHE_INVALID;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * is it an orphan ?
 | 
			
		||||
	 */
 | 
			
		||||
	if (!*dl->pvd.vg_name) {
 | 
			
		||||
		log_very_verbose("%s is not a member of any format1 VG", name);
 | 
			
		||||
 | 
			
		||||
		/* Update VG cache */
 | 
			
		||||
		/* vgcache_add(dl->pvd.vg_name, NULL, dev, fmt); */
 | 
			
		||||
 | 
			
		||||
		__update_lvmcache(fmt, dl, dev, NULL, 0);
 | 
			
		||||
		return (vg_name) ? NULL : dl;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_read_vgd(dl)) {
 | 
			
		||||
	if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
 | 
			
		||||
		log_error("Failed to read VG data from PV (%s)", name);
 | 
			
		||||
		__update_lvmcache(fmt, dl, dev, NULL, 0);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Update VG cache with what we found */
 | 
			
		||||
	/* vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt); */
 | 
			
		||||
 | 
			
		||||
	if (vg_name && strcmp(vg_name, dl->pvd.vg_name)) {
 | 
			
		||||
	if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
 | 
			
		||||
		log_very_verbose("%s is not a member of the VG %s",
 | 
			
		||||
				 name, vg_name);
 | 
			
		||||
		__update_lvmcache(fmt, dl, dev, NULL, 0);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	__update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
 | 
			
		||||
			  dl->vgd.vg_status & VG_EXPORTED);
 | 
			
		||||
 | 
			
		||||
	if (!_read_uuids(dl)) {
 | 
			
		||||
		log_error("Failed to read PV uuid list from %s", name);
 | 
			
		||||
		goto bad;
 | 
			
		||||
@@ -428,7 +439,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(diskl, head) {
 | 
			
		||||
		pvd = &diskl->pvd;
 | 
			
		||||
		if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
 | 
			
		||||
		if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
 | 
			
		||||
			     sizeof(pvd->pv_uuid))) {
 | 
			
		||||
			if (MAJOR(data->dev->dev) != md_major()) {
 | 
			
		||||
				log_very_verbose("Ignoring duplicate PV %s on "
 | 
			
		||||
@@ -447,7 +458,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Build a list of pv_d's structures, allocated from mem.
 | 
			
		||||
 * We keep track of the first object allocated form the pool
 | 
			
		||||
 * We keep track of the first object allocated from the pool
 | 
			
		||||
 * so we can free off all the memory if something goes wrong.
 | 
			
		||||
 */
 | 
			
		||||
int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
 | 
			
		||||
@@ -461,7 +472,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	/* Fast path if we already saw this VG and cached the list of PVs */
 | 
			
		||||
	if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
 | 
			
		||||
	if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
 | 
			
		||||
	    vginfo->infos.n) {
 | 
			
		||||
		list_iterate_items(info, &vginfo->infos) {
 | 
			
		||||
			dev = info->dev;
 | 
			
		||||
@@ -565,7 +576,7 @@ static int _write_lvs(struct disk_list *data)
 | 
			
		||||
 | 
			
		||||
	pos = data->pvd.lv_on_disk.base;
 | 
			
		||||
 | 
			
		||||
	if (!dev_zero(data->dev, pos, data->pvd.lv_on_disk.size)) {
 | 
			
		||||
	if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
 | 
			
		||||
		log_error("Couldn't zero lv area on device '%s'",
 | 
			
		||||
			  dev_name(data->dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -73,16 +73,16 @@ struct data_area {
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct pv_disk {
 | 
			
		||||
	uint8_t id[2];
 | 
			
		||||
	int8_t id[2];
 | 
			
		||||
	uint16_t version;	/* lvm version */
 | 
			
		||||
	struct data_area pv_on_disk;
 | 
			
		||||
	struct data_area vg_on_disk;
 | 
			
		||||
	struct data_area pv_uuidlist_on_disk;
 | 
			
		||||
	struct data_area lv_on_disk;
 | 
			
		||||
	struct data_area pe_on_disk;
 | 
			
		||||
	uint8_t pv_uuid[NAME_LEN];
 | 
			
		||||
	uint8_t vg_name[NAME_LEN];
 | 
			
		||||
	uint8_t system_id[NAME_LEN];	/* for vgexport/vgimport */
 | 
			
		||||
	int8_t pv_uuid[NAME_LEN];
 | 
			
		||||
	int8_t vg_name[NAME_LEN];
 | 
			
		||||
	int8_t system_id[NAME_LEN];	/* for vgexport/vgimport */
 | 
			
		||||
	uint32_t pv_major;
 | 
			
		||||
	uint32_t pv_number;
 | 
			
		||||
	uint32_t pv_status;
 | 
			
		||||
@@ -98,8 +98,8 @@ struct pv_disk {
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct lv_disk {
 | 
			
		||||
	uint8_t lv_name[NAME_LEN];
 | 
			
		||||
	uint8_t vg_name[NAME_LEN];
 | 
			
		||||
	int8_t lv_name[NAME_LEN];
 | 
			
		||||
	int8_t vg_name[NAME_LEN];
 | 
			
		||||
	uint32_t lv_access;
 | 
			
		||||
	uint32_t lv_status;
 | 
			
		||||
	uint32_t lv_open;
 | 
			
		||||
@@ -122,8 +122,8 @@ struct lv_disk {
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct vg_disk {
 | 
			
		||||
	uint8_t vg_uuid[ID_LEN];	/* volume group UUID */
 | 
			
		||||
	uint8_t vg_name_dummy[NAME_LEN - ID_LEN];	/* rest of v1 VG name */
 | 
			
		||||
	int8_t vg_uuid[ID_LEN];	/* volume group UUID */
 | 
			
		||||
	int8_t vg_name_dummy[NAME_LEN - ID_LEN];	/* rest of v1 VG name */
 | 
			
		||||
	uint32_t vg_number;	/* volume group number */
 | 
			
		||||
	uint32_t vg_access;	/* read/write */
 | 
			
		||||
	uint32_t vg_status;	/* active or not */
 | 
			
		||||
@@ -172,6 +172,7 @@ struct disk_list {
 | 
			
		||||
 * Layout constants.
 | 
			
		||||
 */
 | 
			
		||||
#define METADATA_ALIGN 4096UL
 | 
			
		||||
#define LVM1_PE_ALIGN (65536UL >> SECTOR_SHIFT)      /* PE alignment */
 | 
			
		||||
 | 
			
		||||
#define	METADATA_BASE 0UL
 | 
			
		||||
#define	PV_SIZE 1024UL
 | 
			
		||||
@@ -204,7 +205,8 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
 | 
			
		||||
 */
 | 
			
		||||
int import_pv(struct dm_pool *mem, struct device *dev,
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
	      struct physical_volume *pv, struct pv_disk *pvd);
 | 
			
		||||
	      struct physical_volume *pv, struct pv_disk *pvd,
 | 
			
		||||
	      struct vg_disk *vgd);
 | 
			
		||||
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
	      struct pv_disk *pvd, struct physical_volume *pv);
 | 
			
		||||
@@ -222,7 +224,7 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
 | 
			
		||||
 | 
			
		||||
int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
 | 
			
		||||
	       struct volume_group *vg,
 | 
			
		||||
	       struct list *pvds, struct list *results, int *count);
 | 
			
		||||
	       struct list *pvds, struct list *results, uint32_t *count);
 | 
			
		||||
 | 
			
		||||
int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds);
 | 
			
		||||
int export_lvs(struct disk_list *dl, struct volume_group *vg,
 | 
			
		||||
@@ -237,6 +239,7 @@ void export_numbers(struct list *pvds, struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void export_pv_act(struct list *pvds);
 | 
			
		||||
int munge_pvd(struct device *dev, struct pv_disk *pvd);
 | 
			
		||||
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd);
 | 
			
		||||
 | 
			
		||||
/* blech */
 | 
			
		||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
 | 
			
		||||
 
 | 
			
		||||
@@ -173,7 +173,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct volume_group *_vg_read(struct format_instance *fid,
 | 
			
		||||
static struct volume_group *_format1_vg_read(struct format_instance *fid,
 | 
			
		||||
				     const char *vg_name,
 | 
			
		||||
				     struct metadata_area *mda)
 | 
			
		||||
{
 | 
			
		||||
@@ -264,7 +264,7 @@ static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
static int _format1_vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
		     struct metadata_area *mda)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("lvm1 vg_write", 1024 * 10);
 | 
			
		||||
@@ -287,7 +287,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		    struct physical_volume *pv, struct list *mdas)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
 | 
			
		||||
@@ -312,7 +312,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd)) {
 | 
			
		||||
	if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -326,7 +326,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
static int _format1_pv_setup(const struct format_type *fmt,
 | 
			
		||||
		     uint64_t pe_start, uint32_t extent_count,
 | 
			
		||||
		     uint32_t extent_size,
 | 
			
		||||
		     int pvmetadatacopies,
 | 
			
		||||
@@ -337,8 +337,7 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
		pv->size--;
 | 
			
		||||
	if (pv->size > MAX_PV_SIZE) {
 | 
			
		||||
		log_error("Physical volumes cannot be bigger than %s",
 | 
			
		||||
			  display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -364,7 +363,7 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
 | 
			
		||||
static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t max_size = UINT_MAX;
 | 
			
		||||
 | 
			
		||||
@@ -378,15 +377,14 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
 | 
			
		||||
	}
 | 
			
		||||
	if (lv->size > max_size) {
 | 
			
		||||
		log_error("logical volumes cannot be larger than %s",
 | 
			
		||||
			  display_size(fid->fmt->cmd, max_size,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(fid->fmt->cmd, max_size));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
		     struct list *mdas, int64_t sector)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
@@ -396,7 +394,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
 | 
			
		||||
				  pv->vg_name, NULL))) {
 | 
			
		||||
				  pv->vg_name, NULL, 0))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -410,7 +408,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
 | 
			
		||||
	/* Ensure any residual PE structure is gone */
 | 
			
		||||
	pv->pe_size = pv->pe_count = 0;
 | 
			
		||||
	pv->pe_start = PE_ALIGN;
 | 
			
		||||
	pv->pe_start = LVM1_PE_ALIGN;
 | 
			
		||||
 | 
			
		||||
	if (!(mem = dm_pool_create("lvm1 pv_write", 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -433,7 +431,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	   dev_write in order to make other disk tools happy */
 | 
			
		||||
	dl->pvd.pv_on_disk.base = METADATA_BASE;
 | 
			
		||||
	dl->pvd.pv_on_disk.size = PV_SIZE;
 | 
			
		||||
	dl->pvd.pe_on_disk.base = PE_ALIGN << SECTOR_SHIFT;
 | 
			
		||||
	dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
 | 
			
		||||
 | 
			
		||||
	list_add(&pvs, &dl->list);
 | 
			
		||||
	if (!write_disks(fmt, &pvs)) {
 | 
			
		||||
@@ -449,7 +447,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
static int _format1_vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	/* just check max_pv and max_lv */
 | 
			
		||||
	if (!vg->max_lv || vg->max_lv >= MAX_LV)
 | 
			
		||||
@@ -460,18 +458,15 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	if (vg->extent_size > MAX_PE_SIZE || vg->extent_size < MIN_PE_SIZE) {
 | 
			
		||||
		log_error("Extent size must be between %s and %s",
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT),
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE),
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE));
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (vg->extent_size % MIN_PE_SIZE) {
 | 
			
		||||
		log_error("Extent size must be multiple of %s",
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -484,8 +479,8 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _segtype_supported (struct format_instance *fid, 
 | 
			
		||||
			       struct segment_type *segtype)
 | 
			
		||||
static int _format1_segtype_supported(struct format_instance *fid, 
 | 
			
		||||
				      const struct segment_type *segtype)
 | 
			
		||||
{
 | 
			
		||||
	if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -496,12 +491,13 @@ static int _segtype_supported (struct format_instance *fid,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct metadata_area_ops _metadata_format1_ops = {
 | 
			
		||||
	vg_read:_vg_read,
 | 
			
		||||
	vg_write:_vg_write,
 | 
			
		||||
	.vg_read = _format1_vg_read,
 | 
			
		||||
	.vg_write = _format1_vg_write,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct format_instance *_create_instance(const struct format_type *fmt,
 | 
			
		||||
static struct format_instance *_format1_create_instance(const struct format_type *fmt,
 | 
			
		||||
						const char *vgname,
 | 
			
		||||
						const char *vgid,
 | 
			
		||||
						void *private)
 | 
			
		||||
{
 | 
			
		||||
	struct format_instance *fid;
 | 
			
		||||
@@ -529,26 +525,26 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
 | 
			
		||||
	return fid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_instance(struct format_instance *fid)
 | 
			
		||||
static void _format1_destroy_instance(struct format_instance *fid)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(const struct format_type *fmt)
 | 
			
		||||
static void _format1_destroy(const struct format_type *fmt)
 | 
			
		||||
{
 | 
			
		||||
	dm_free((void *) fmt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct format_handler _format1_ops = {
 | 
			
		||||
	pv_read:_pv_read,
 | 
			
		||||
	pv_setup:_pv_setup,
 | 
			
		||||
	pv_write:_pv_write,
 | 
			
		||||
	lv_setup:_lv_setup,
 | 
			
		||||
	vg_setup:_vg_setup,
 | 
			
		||||
	segtype_supported:_segtype_supported,
 | 
			
		||||
	create_instance:_create_instance,
 | 
			
		||||
	destroy_instance:_destroy_instance,
 | 
			
		||||
	destroy:_destroy,
 | 
			
		||||
	.pv_read = _format1_pv_read,
 | 
			
		||||
	.pv_setup = _format1_pv_setup,
 | 
			
		||||
	.pv_write = _format1_pv_write,
 | 
			
		||||
	.lv_setup = _format1_lv_setup,
 | 
			
		||||
	.vg_setup = _format1_vg_setup,
 | 
			
		||||
	.segtype_supported = _format1_segtype_supported,
 | 
			
		||||
	.create_instance = _format1_create_instance,
 | 
			
		||||
	.destroy_instance = _format1_destroy_instance,
 | 
			
		||||
	.destroy = _format1_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef LVM1_INTERNAL
 | 
			
		||||
 
 | 
			
		||||
@@ -49,23 +49,26 @@ static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
 | 
			
		||||
 | 
			
		||||
int import_pv(struct dm_pool *mem, struct device *dev,
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
	      struct physical_volume *pv, struct pv_disk *pvd)
 | 
			
		||||
	      struct physical_volume *pv, struct pv_disk *pvd,
 | 
			
		||||
	      struct vg_disk *vgd)
 | 
			
		||||
{
 | 
			
		||||
	memset(pv, 0, sizeof(*pv));
 | 
			
		||||
	memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
 | 
			
		||||
 | 
			
		||||
	pv->dev = dev;
 | 
			
		||||
	if (!(pv->vg_name = dm_pool_strdup(mem, pvd->vg_name))) {
 | 
			
		||||
	if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
 | 
			
		||||
 | 
			
		||||
	/* Store system_id from first PV if PV belongs to a VG */
 | 
			
		||||
	if (vg && !*vg->system_id)
 | 
			
		||||
		strncpy(vg->system_id, pvd->system_id, NAME_LEN);
 | 
			
		||||
		strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
 | 
			
		||||
 | 
			
		||||
	if (vg &&
 | 
			
		||||
	    strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id)))
 | 
			
		||||
	    strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
 | 
			
		||||
		    log_very_verbose("System ID %s on %s differs from %s for "
 | 
			
		||||
				     "volume group", pvd->system_id,
 | 
			
		||||
				     dev_name(pv->dev), vg->system_id);
 | 
			
		||||
@@ -100,7 +103,7 @@ int import_pv(struct dm_pool *mem, struct device *dev,
 | 
			
		||||
static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(s, NAME_LEN, "%s%s%lu",
 | 
			
		||||
	if (dm_snprintf(s, NAME_LEN, "%s%s%lu",
 | 
			
		||||
			 prefix, cmd->hostname, time(NULL)) < 0) {
 | 
			
		||||
		log_error("Generated system_id too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -121,19 +124,17 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
 | 
			
		||||
 | 
			
		||||
	memcpy(pvd->pv_uuid, pv->id.uuid, ID_LEN);
 | 
			
		||||
 | 
			
		||||
	if (!_check_vg_name(pv->vg_name)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (pv->vg_name) {
 | 
			
		||||
		if (!_check_vg_name(pv->vg_name)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		strncpy((char *)pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(pvd->vg_name, 0, sizeof(pvd->vg_name));
 | 
			
		||||
 | 
			
		||||
	if (pv->vg_name)
 | 
			
		||||
		strncpy(pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
 | 
			
		||||
 | 
			
		||||
	/* Preserve existing system_id if it exists */
 | 
			
		||||
	if (vg && *vg->system_id)
 | 
			
		||||
		strncpy(pvd->system_id, vg->system_id, sizeof(pvd->system_id));
 | 
			
		||||
		strncpy((char *)pvd->system_id, vg->system_id, sizeof(pvd->system_id));
 | 
			
		||||
 | 
			
		||||
	/* Is VG already exported or being exported? */
 | 
			
		||||
	if (vg && (vg->status & EXPORTED_VG)) {
 | 
			
		||||
@@ -141,24 +142,24 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
 | 
			
		||||
		if (!*vg->system_id ||
 | 
			
		||||
		    strncmp(vg->system_id, EXPORTED_TAG,
 | 
			
		||||
			    sizeof(EXPORTED_TAG) - 1)) {
 | 
			
		||||
			if (!_system_id(cmd, pvd->system_id, EXPORTED_TAG)) {
 | 
			
		||||
			if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG)) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (strlen(pvd->vg_name) + sizeof(EXPORTED_TAG) >
 | 
			
		||||
		if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
 | 
			
		||||
		    sizeof(pvd->vg_name)) {
 | 
			
		||||
			log_error("Volume group name %s too long to export",
 | 
			
		||||
				  pvd->vg_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		strcat(pvd->vg_name, EXPORTED_TAG);
 | 
			
		||||
		strcat((char *)pvd->vg_name, EXPORTED_TAG);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is VG being imported? */
 | 
			
		||||
	if (vg && !(vg->status & EXPORTED_VG) && *vg->system_id &&
 | 
			
		||||
	    !strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
 | 
			
		||||
		if (!_system_id(cmd, pvd->system_id, IMPORTED_TAG)) {
 | 
			
		||||
		if (!_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -166,7 +167,7 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
 | 
			
		||||
 | 
			
		||||
	/* Generate system_id if PV is in VG */
 | 
			
		||||
	if (!pvd->system_id || !*pvd->system_id)
 | 
			
		||||
		if (!_system_id(cmd, pvd->system_id, "")) {
 | 
			
		||||
		if (!_system_id(cmd, (char *)pvd->system_id, "")) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -174,8 +175,8 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
 | 
			
		||||
	/* Update internal system_id if we changed it */
 | 
			
		||||
	if (vg &&
 | 
			
		||||
	    (!*vg->system_id ||
 | 
			
		||||
	     strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id))))
 | 
			
		||||
		    strncpy(vg->system_id, pvd->system_id, NAME_LEN);
 | 
			
		||||
	     strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
 | 
			
		||||
		    strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
 | 
			
		||||
 | 
			
		||||
	//pvd->pv_major = MAJOR(pv->dev);
 | 
			
		||||
 | 
			
		||||
@@ -201,12 +202,12 @@ int import_vg(struct dm_pool *mem,
 | 
			
		||||
	struct vg_disk *vgd = &dl->vgd;
 | 
			
		||||
	memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
 | 
			
		||||
 | 
			
		||||
	if (!_check_vg_name(dl->pvd.vg_name)) {
 | 
			
		||||
	if (!_check_vg_name((char *)dl->pvd.vg_name)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(vg->name = dm_pool_strdup(mem, dl->pvd.vg_name))) {
 | 
			
		||||
	if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -289,7 +290,7 @@ int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lv
 | 
			
		||||
{
 | 
			
		||||
	lvid_from_lvnum(&lv->lvid, &lv->vg->id, lvd->lv_number);
 | 
			
		||||
 | 
			
		||||
	if (!(lv->name = _create_lv_name(mem, lvd->lv_name))) {
 | 
			
		||||
	if (!(lv->name = _create_lv_name(mem, (char *)lvd->lv_name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -339,10 +340,10 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
 | 
			
		||||
		       struct logical_volume *lv, const char *dev_dir)
 | 
			
		||||
{
 | 
			
		||||
	memset(lvd, 0, sizeof(*lvd));
 | 
			
		||||
	snprintf(lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s",
 | 
			
		||||
	snprintf((char *)lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s",
 | 
			
		||||
		 dev_dir, vg->name, lv->name);
 | 
			
		||||
 | 
			
		||||
	strcpy(lvd->vg_name, vg->name);
 | 
			
		||||
	strcpy((char *)lvd->vg_name, vg->name);
 | 
			
		||||
 | 
			
		||||
	if (lv->status & LVM_READ)
 | 
			
		||||
		lvd->lv_access |= LV_READ;
 | 
			
		||||
@@ -413,7 +414,7 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
 | 
			
		||||
 | 
			
		||||
int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
 | 
			
		||||
	       struct volume_group *vg,
 | 
			
		||||
	       struct list *pvds, struct list *results, int *count)
 | 
			
		||||
	       struct list *pvds, struct list *results, uint32_t *count)
 | 
			
		||||
{
 | 
			
		||||
	struct disk_list *dl;
 | 
			
		||||
	struct pv_list *pvl;
 | 
			
		||||
@@ -426,7 +427,7 @@ int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd)) {
 | 
			
		||||
		if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -475,7 +476,7 @@ int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds)
 | 
			
		||||
		list_iterate_items(ll, &dl->lvds) {
 | 
			
		||||
			lvd = &ll->lvd;
 | 
			
		||||
 | 
			
		||||
			if (!find_lv(vg, lvd->lv_name) &&
 | 
			
		||||
			if (!find_lv(vg, (char *)lvd->lv_name) &&
 | 
			
		||||
			    !_add_lv(mem, vg, lvd)) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
@@ -583,14 +584,14 @@ int import_snapshots(struct dm_pool *mem, struct volume_group *vg,
 | 
			
		||||
 | 
			
		||||
			lvnum = lvd->lv_number;
 | 
			
		||||
 | 
			
		||||
			if (lvnum > MAX_LV) {
 | 
			
		||||
			if (lvnum >= MAX_LV) {
 | 
			
		||||
				log_err("Logical volume number "
 | 
			
		||||
					"out of bounds.");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!lvs[lvnum] &&
 | 
			
		||||
			    !(lvs[lvnum] = find_lv(vg, lvd->lv_name))) {
 | 
			
		||||
			    !(lvs[lvnum] = find_lv(vg, (char *)lvd->lv_name))) {
 | 
			
		||||
				log_err("Couldn't find logical volume '%s'.",
 | 
			
		||||
					lvd->lv_name);
 | 
			
		||||
				return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -93,7 +93,7 @@ static int _fill_lv_array(struct lv_map **lvs,
 | 
			
		||||
	memset(lvs, 0, sizeof(*lvs) * MAX_LV);
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(ll, &dl->lvds) {
 | 
			
		||||
		if (!(lvm = dm_hash_lookup(maps, strrchr(ll->lvd.lv_name, '/')
 | 
			
		||||
		if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/')
 | 
			
		||||
					+ 1))) {
 | 
			
		||||
			log_err("Physical volume (%s) contains an "
 | 
			
		||||
				"unknown logical volume (%s).",
 | 
			
		||||
@@ -140,7 +140,12 @@ static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
 | 
			
		||||
				lvm = lvms[lv_num];
 | 
			
		||||
 | 
			
		||||
				if (!lvm) {
 | 
			
		||||
					log_err("invalid lv in extent map");
 | 
			
		||||
					log_error("Invalid LV in extent map "
 | 
			
		||||
						  "(PV %s, PE %" PRIu32
 | 
			
		||||
						  ", LV %" PRIu32
 | 
			
		||||
						  ", LE %" PRIu32 ")",
 | 
			
		||||
						  dev_name(pv->dev), i,
 | 
			
		||||
						  lv_num, e[i].le_num);
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,16 +19,18 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Only works with powers of 2.
 | 
			
		||||
 */
 | 
			
		||||
static inline uint32_t _round_up(uint32_t n, uint32_t size)
 | 
			
		||||
static uint32_t _round_up(uint32_t n, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
	size--;
 | 
			
		||||
	return (n + size) & ~size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint32_t _div_up(uint32_t n, uint32_t size)
 | 
			
		||||
/* Unused.
 | 
			
		||||
static uint32_t _div_up(uint32_t n, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _round_up(n, size) / size;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Each chunk of metadata should be aligned to
 | 
			
		||||
@@ -151,7 +153,7 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
 | 
			
		||||
		if (pe_start && end < pe_start)
 | 
			
		||||
			end = pe_start;
 | 
			
		||||
 | 
			
		||||
		pvd->pe_start = _round_up(end, PE_ALIGN);
 | 
			
		||||
		pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
 | 
			
		||||
 | 
			
		||||
	} while ((pvd->pe_start + (pvd->pe_total * extent_size))
 | 
			
		||||
		 > pv->size);
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ static void _not_supported(const char *op)
 | 
			
		||||
		op);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
 | 
			
		||||
static int _lvm1_can_handle(struct labeller *l, char *buf, uint64_t sector)
 | 
			
		||||
{
 | 
			
		||||
	struct pv_disk *pvd = (struct pv_disk *) buf;
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
@@ -48,21 +48,30 @@ static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _write(struct label *label, char *buf)
 | 
			
		||||
static int _lvm1_write(struct label *label, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	_not_supported("write");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
static int _lvm1_read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
		 struct label **label)
 | 
			
		||||
{
 | 
			
		||||
	struct pv_disk *pvd = (struct pv_disk *) buf;
 | 
			
		||||
	struct vg_disk vgd;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	const char *vgid = NULL;
 | 
			
		||||
	unsigned exported = 0;
 | 
			
		||||
 | 
			
		||||
	munge_pvd(dev, pvd);
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) {
 | 
			
		||||
	if (*pvd->vg_name && read_vgd(dev, &vgd, pvd)) {
 | 
			
		||||
		vgid = (char *) vgd.vg_uuid;
 | 
			
		||||
		exported = pvd->pv_status & VG_EXPORTED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, (char *)pvd->vg_name, vgid,
 | 
			
		||||
				  exported))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -76,31 +85,31 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _initialise_label(struct labeller *l, struct label *label)
 | 
			
		||||
static int _lvm1_initialise_label(struct labeller *l, struct label *label)
 | 
			
		||||
{
 | 
			
		||||
	strcpy(label->type, "LVM1");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_label(struct labeller *l, struct label *label)
 | 
			
		||||
static void _lvm1_destroy_label(struct labeller *l, struct label *label)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct labeller *l)
 | 
			
		||||
static void _lvm1_destroy(struct labeller *l)
 | 
			
		||||
{
 | 
			
		||||
	dm_free(l);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct label_ops _lvm1_ops = {
 | 
			
		||||
	can_handle:_can_handle,
 | 
			
		||||
	write:_write,
 | 
			
		||||
	read:_read,
 | 
			
		||||
	verify:_can_handle,
 | 
			
		||||
	initialise_label:_initialise_label,
 | 
			
		||||
	destroy_label:_destroy_label,
 | 
			
		||||
	destroy:_destroy
 | 
			
		||||
	.can_handle = _lvm1_can_handle,
 | 
			
		||||
	.write = _lvm1_write,
 | 
			
		||||
	.read = _lvm1_read,
 | 
			
		||||
	.verify = _lvm1_can_handle,
 | 
			
		||||
	.initialise_label = _lvm1_initialise_label,
 | 
			
		||||
	.destroy_label = _lvm1_destroy_label,
 | 
			
		||||
	.destroy = _lvm1_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct labeller *lvm1_labeller_create(struct format_type *fmt)
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
 | 
			
		||||
	memset(numbers, 0, sizeof(numbers));
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(dl, &all_pvs) {
 | 
			
		||||
		if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
 | 
			
		||||
		if (!*dl->pvd.vg_name || !strcmp((char *)dl->pvd.vg_name, candidate_vg))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		numbers[dl->vgd.vg_number] = 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -98,7 +98,7 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
 | 
			
		||||
	log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
 | 
			
		||||
				  (char *) &vgid))) {
 | 
			
		||||
				  (char *) &vgid, 0))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -248,7 +248,7 @@ static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
 | 
			
		||||
 | 
			
		||||
	uint32_t sp_count = 0;
 | 
			
		||||
	uint32_t *sp_devs = NULL;
 | 
			
		||||
	int i;
 | 
			
		||||
	uint32_t i;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: maybe should return a different error in memory
 | 
			
		||||
	 * allocation failure */
 | 
			
		||||
@@ -314,7 +314,7 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
 | 
			
		||||
		/*
 | 
			
		||||
		 * If the cache scanning doesn't work, this will never work
 | 
			
		||||
		 */
 | 
			
		||||
		if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
 | 
			
		||||
		if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
 | 
			
		||||
		    vginfo->infos.n) {
 | 
			
		||||
 | 
			
		||||
			if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,8 @@ static struct user_subpool *_build_usp(struct list *pls, struct dm_pool *mem,
 | 
			
		||||
 | 
			
		||||
static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
 | 
			
		||||
{
 | 
			
		||||
	int i, j;
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned j;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sp_count; i++) {
 | 
			
		||||
		if (!usp[i].initialized) {
 | 
			
		||||
@@ -88,7 +89,7 @@ static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
 | 
			
		||||
		}
 | 
			
		||||
		for (j = 0; j < usp[i].num_devs; j++) {
 | 
			
		||||
			if (!usp[i].devs[j].initialized) {
 | 
			
		||||
				log_error("Missing device %d for subpool %d"
 | 
			
		||||
				log_error("Missing device %u for subpool %d"
 | 
			
		||||
					  " in pool %s", j, i, vgname);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -169,7 +170,7 @@ static struct volume_group *_build_vg_from_pds(struct format_instance
 | 
			
		||||
	return vg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct volume_group *_vg_read(struct format_instance *fid,
 | 
			
		||||
static struct volume_group *_pool_vg_read(struct format_instance *fid,
 | 
			
		||||
				     const char *vg_name,
 | 
			
		||||
				     struct metadata_area *mda)
 | 
			
		||||
{
 | 
			
		||||
@@ -206,7 +207,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
 | 
			
		||||
	return vg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
static int _pool_pv_setup(const struct format_type *fmt,
 | 
			
		||||
		     uint64_t pe_start, uint32_t extent_count,
 | 
			
		||||
		     uint32_t extent_size,
 | 
			
		||||
		     int pvmetadatacopies,
 | 
			
		||||
@@ -216,7 +217,7 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		    struct physical_volume *pv, struct list *mdas)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
 | 
			
		||||
@@ -262,12 +263,13 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
 | 
			
		||||
/* *INDENT-OFF* */
 | 
			
		||||
static struct metadata_area_ops _metadata_format_pool_ops = {
 | 
			
		||||
	vg_read:_vg_read,
 | 
			
		||||
	.vg_read = _pool_vg_read,
 | 
			
		||||
};
 | 
			
		||||
/* *INDENT-ON* */
 | 
			
		||||
 | 
			
		||||
static struct format_instance *_create_instance(const struct format_type *fmt,
 | 
			
		||||
static struct format_instance *_pool_create_instance(const struct format_type *fmt,
 | 
			
		||||
						const char *vgname,
 | 
			
		||||
						const char *vgid,
 | 
			
		||||
						void *private)
 | 
			
		||||
{
 | 
			
		||||
	struct format_instance *fid;
 | 
			
		||||
@@ -297,23 +299,23 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
 | 
			
		||||
	return fid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_instance(struct format_instance *fid)
 | 
			
		||||
static void _pool_destroy_instance(struct format_instance *fid)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(const struct format_type *fmt)
 | 
			
		||||
static void _pool_destroy(const struct format_type *fmt)
 | 
			
		||||
{
 | 
			
		||||
	dm_free((void *) fmt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* *INDENT-OFF* */
 | 
			
		||||
static struct format_handler _format_pool_ops = {
 | 
			
		||||
	pv_read:_pv_read,
 | 
			
		||||
	pv_setup:_pv_setup,
 | 
			
		||||
	create_instance:_create_instance,
 | 
			
		||||
	destroy_instance:_destroy_instance,
 | 
			
		||||
	destroy:_destroy,
 | 
			
		||||
	.pv_read = _pool_pv_read,
 | 
			
		||||
	.pv_setup = _pool_pv_setup,
 | 
			
		||||
	.create_instance = _pool_create_instance,
 | 
			
		||||
	.destroy_instance = _pool_destroy_instance,
 | 
			
		||||
	.destroy = _pool_destroy,
 | 
			
		||||
};
 | 
			
		||||
/* *INDENT-ON */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -165,6 +165,7 @@ int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
 | 
			
		||||
		log_error("Unable to duplicate vg_name string");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
 | 
			
		||||
	pv->status = 0;
 | 
			
		||||
	pv->size = pd->pl_blocks;
 | 
			
		||||
	pv->pe_size = POOL_PE_SIZE;
 | 
			
		||||
@@ -202,7 +203,7 @@ static int _add_stripe_seg(struct dm_pool *mem,
 | 
			
		||||
{
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	struct segment_type *segtype;
 | 
			
		||||
	int j;
 | 
			
		||||
	unsigned j;
 | 
			
		||||
	uint32_t area_len;
 | 
			
		||||
 | 
			
		||||
	if (usp->striping & (usp->striping - 1)) {
 | 
			
		||||
@@ -248,7 +249,7 @@ static int _add_linear_seg(struct dm_pool *mem,
 | 
			
		||||
{
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	struct segment_type *segtype;
 | 
			
		||||
	int j;
 | 
			
		||||
	unsigned j;
 | 
			
		||||
	uint32_t area_len;
 | 
			
		||||
 | 
			
		||||
	if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped"))) {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,13 +23,13 @@
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
static void _not_supported(const char *op)
 | 
			
		||||
static void _pool_not_supported(const char *op)
 | 
			
		||||
{
 | 
			
		||||
	log_error("The '%s' operation is not supported for the pool labeller.",
 | 
			
		||||
		  op);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
 | 
			
		||||
static int _pool_can_handle(struct labeller *l, char *buf, uint64_t sector)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	struct pool_disk pd;
 | 
			
		||||
@@ -50,13 +50,13 @@ static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _write(struct label *label, char *buf)
 | 
			
		||||
static int _pool_write(struct label *label, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	_not_supported("write");
 | 
			
		||||
	_pool_not_supported("write");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
static int _pool_read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
		 struct label **label)
 | 
			
		||||
{
 | 
			
		||||
	struct pool_list pl;
 | 
			
		||||
@@ -64,31 +64,31 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
	return read_pool_label(&pl, l, dev, buf, label);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _initialise_label(struct labeller *l, struct label *label)
 | 
			
		||||
static int _pool_initialise_label(struct labeller *l, struct label *label)
 | 
			
		||||
{
 | 
			
		||||
	strcpy(label->type, "POOL");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_label(struct labeller *l, struct label *label)
 | 
			
		||||
static void _pool_destroy_label(struct labeller *l, struct label *label)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct labeller *l)
 | 
			
		||||
static void _label_pool_destroy(struct labeller *l)
 | 
			
		||||
{
 | 
			
		||||
	dm_free(l);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct label_ops _pool_ops = {
 | 
			
		||||
      can_handle:_can_handle,
 | 
			
		||||
      write:_write,
 | 
			
		||||
      read:_read,
 | 
			
		||||
      verify:_can_handle,
 | 
			
		||||
      initialise_label:_initialise_label,
 | 
			
		||||
      destroy_label:_destroy_label,
 | 
			
		||||
      destroy:_destroy
 | 
			
		||||
      .can_handle = _pool_can_handle,
 | 
			
		||||
      .write = _pool_write,
 | 
			
		||||
      .read = _pool_read,
 | 
			
		||||
      .verify = _pool_can_handle,
 | 
			
		||||
      .initialise_label = _pool_initialise_label,
 | 
			
		||||
      .destroy_label = _pool_destroy_label,
 | 
			
		||||
      .destroy = _label_pool_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct labeller *pool_labeller_create(struct format_type *fmt)
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,7 @@ static int _split_vg(const char *filename, char *vgname, size_t vg_size,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _insert_file(struct list *head, struct archive_file *b)
 | 
			
		||||
static void _insert_archive_file(struct list *head, struct archive_file *b)
 | 
			
		||||
{
 | 
			
		||||
	struct archive_file *bf = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -107,7 +107,7 @@ static void _insert_file(struct list *head, struct archive_file *b)
 | 
			
		||||
	list_add_h(&bf->list, &b->list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *_join(struct dm_pool *mem, const char *dir, const char *name)
 | 
			
		||||
static char *_join_file_to_dir(struct dm_pool *mem, const char *dir, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	if (!dm_pool_begin_object(mem, 32) ||
 | 
			
		||||
	    !dm_pool_grow_object(mem, dir, strlen(dir)) ||
 | 
			
		||||
@@ -161,7 +161,7 @@ static struct list *_scan_archive(struct dm_pool *mem,
 | 
			
		||||
		if (strcmp(vgname, vgname_found))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (!(path = _join(mem, dir, dirent[i]->d_name))) {
 | 
			
		||||
		if (!(path = _join_file_to_dir(mem, dir, dirent[i]->d_name))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
@@ -181,7 +181,7 @@ static struct list *_scan_archive(struct dm_pool *mem,
 | 
			
		||||
		/*
 | 
			
		||||
		 * Insert it to the correct part of the list.
 | 
			
		||||
		 */
 | 
			
		||||
		_insert_file(results, af);
 | 
			
		||||
		_insert_archive_file(results, af);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
@@ -207,8 +207,8 @@ static void _remove_expired(struct list *archives, uint32_t archives_size,
 | 
			
		||||
	/* Convert retain_days into the time after which we must retain */
 | 
			
		||||
	retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
 | 
			
		||||
 | 
			
		||||
	/* Assume list is ordered oldest first (by index) */
 | 
			
		||||
	list_iterate_items(bf, archives) {
 | 
			
		||||
	/* Assume list is ordered newest first (by index) */
 | 
			
		||||
	list_iterate_back_items(bf, archives) {
 | 
			
		||||
		/* Get the mtime of the file and unlink if too old */
 | 
			
		||||
		if (stat(bf->path, &sb)) {
 | 
			
		||||
			log_sys_error("stat", bf->path);
 | 
			
		||||
@@ -277,7 +277,7 @@ int archive_vg(struct volume_group *vg,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 10; i++) {
 | 
			
		||||
		if (lvm_snprintf(archive_name, sizeof(archive_name),
 | 
			
		||||
		if (dm_snprintf(archive_name, sizeof(archive_name),
 | 
			
		||||
				 "%s/%s_%05u.vg", dir, vg->name, ix) < 0) {
 | 
			
		||||
			log_error("Archive file name too long.");
 | 
			
		||||
			return 0;
 | 
			
		||||
@@ -311,7 +311,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
 | 
			
		||||
 | 
			
		||||
	if (!(context = create_text_context(cmd, af->path, NULL)) ||
 | 
			
		||||
	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
 | 
			
		||||
							 context))) {
 | 
			
		||||
							 NULL, context))) {
 | 
			
		||||
		log_error("Couldn't create text instance object.");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
@@ -328,7 +328,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print("VG name:    \t%s", vg->name);
 | 
			
		||||
	log_print("Description:\t%s", desc ? desc : "<No description>");
 | 
			
		||||
	log_print("Description:\t%s", desc ? : "<No description>");
 | 
			
		||||
	log_print("Backup Time:\t%s", ctime(&when));
 | 
			
		||||
 | 
			
		||||
	dm_pool_free(cmd->mem, vg);
 | 
			
		||||
@@ -360,7 +360,7 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	struct archive_file af;
 | 
			
		||||
 | 
			
		||||
	if (!(af.path = _join(cmd->mem, dir, vgname))) {
 | 
			
		||||
	if (!(af.path = _join_file_to_dir(cmd->mem, dir, vgname))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -190,7 +190,7 @@ static int __backup(struct volume_group *vg)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(name, sizeof(name), "%s/%s",
 | 
			
		||||
	if (dm_snprintf(name, sizeof(name), "%s/%s",
 | 
			
		||||
			 vg->cmd->backup_params->dir, vg->name) < 0) {
 | 
			
		||||
		log_error("Failed to generate volume group metadata backup "
 | 
			
		||||
			  "filename.");
 | 
			
		||||
@@ -233,7 +233,7 @@ int backup_remove(struct cmd_context *cmd, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(path, sizeof(path), "%s/%s",
 | 
			
		||||
	if (dm_snprintf(path, sizeof(path), "%s/%s",
 | 
			
		||||
			 cmd->backup_params->dir, vg_name) < 0) {
 | 
			
		||||
		log_err("Failed to generate backup filename (for removal).");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -257,7 +257,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
 | 
			
		||||
	if (!(context = create_text_context(cmd, file,
 | 
			
		||||
					    cmd->cmd_line)) ||
 | 
			
		||||
	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
 | 
			
		||||
							 context))) {
 | 
			
		||||
							 NULL, context))) {
 | 
			
		||||
		log_error("Couldn't create text format object.");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -286,7 +286,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	/* Attempt to write out using currently active format */
 | 
			
		||||
	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
 | 
			
		||||
						       NULL))) {
 | 
			
		||||
						       NULL, NULL))) {
 | 
			
		||||
		log_error("Failed to allocate format instance");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -342,7 +342,7 @@ int backup_restore(struct cmd_context *cmd, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(path, sizeof(path), "%s/%s",
 | 
			
		||||
	if (dm_snprintf(path, sizeof(path), "%s/%s",
 | 
			
		||||
			 cmd->backup_params->dir, vg_name) < 0) {
 | 
			
		||||
		log_err("Failed to generate backup filename (for restore).");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -365,7 +365,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	if (!(context = create_text_context(cmd, file, desc)) ||
 | 
			
		||||
	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
 | 
			
		||||
							 context))) {
 | 
			
		||||
							 NULL, context))) {
 | 
			
		||||
		log_error("Couldn't create backup object.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -397,7 +397,7 @@ void check_current_backup(struct volume_group *vg)
 | 
			
		||||
	if ((vg->status & PARTIAL_VG) || (vg->status & EXPORTED_VG))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(path, sizeof(path), "%s/%s",
 | 
			
		||||
	if (dm_snprintf(path, sizeof(path), "%s/%s",
 | 
			
		||||
			 vg->cmd->backup_params->dir, vg->name) < 0) {
 | 
			
		||||
		log_debug("Failed to generate backup filename.");
 | 
			
		||||
		return;
 | 
			
		||||
 
 | 
			
		||||
@@ -183,7 +183,8 @@ static int _out_with_comment_file(struct formatter *f, const char *comment,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _out_with_comment_raw(struct formatter *f, const char *comment,
 | 
			
		||||
static int _out_with_comment_raw(struct formatter *f,
 | 
			
		||||
				 const char *comment __attribute((unused)),
 | 
			
		||||
				 const char *fmt, va_list ap)
 | 
			
		||||
{
 | 
			
		||||
	int n;
 | 
			
		||||
@@ -232,7 +233,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
 | 
			
		||||
	for (i = 0; (d > 1024.0) && _units[i]; i++)
 | 
			
		||||
		d /= 1024.0;
 | 
			
		||||
 | 
			
		||||
	return lvm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
 | 
			
		||||
	return dm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -281,7 +282,7 @@ int out_text(struct formatter *f, const char *fmt, ...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _print_header(struct formatter *f,
 | 
			
		||||
			 struct volume_group *vg, const char *desc)
 | 
			
		||||
			 const char *desc)
 | 
			
		||||
{
 | 
			
		||||
	time_t t;
 | 
			
		||||
 | 
			
		||||
@@ -354,8 +355,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
 | 
			
		||||
 * Get the pv%d name from the formatters hash
 | 
			
		||||
 * table.
 | 
			
		||||
 */
 | 
			
		||||
static inline const char *_get_pv_name(struct formatter *f,
 | 
			
		||||
				       struct physical_volume *pv)
 | 
			
		||||
static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv)
 | 
			
		||||
{
 | 
			
		||||
	return (pv) ? (const char *)
 | 
			
		||||
	    dm_hash_lookup(f->pv_names, dev_name(pv->dev)) : "Missing";
 | 
			
		||||
@@ -409,6 +409,11 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
 | 
			
		||||
			outf(f, "tags = %s", buffer);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!out_size(f, pv->size, "dev_size = %" PRIu64, pv->size)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		outf(f, "pe_start = %" PRIu64, pv->pe_start);
 | 
			
		||||
		if (!out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
 | 
			
		||||
			      "pe_count = %u", pv->pe_count)) {
 | 
			
		||||
@@ -613,46 +618,27 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
	char buffer[32], *name;
 | 
			
		||||
 | 
			
		||||
	if (!(f->mem = dm_pool_create("text pv_names", 512))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(f->mem = dm_pool_create("text pv_names", 512)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(f->pv_names = dm_hash_create(128))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(f->pv_names = dm_hash_create(128)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(pvl, &vg->pvs) {
 | 
			
		||||
		pv = pvl->pv;
 | 
			
		||||
 | 
			
		||||
		/* FIXME But skip if there's already an LV called pv%d ! */
 | 
			
		||||
		if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto bad;
 | 
			
		||||
		}
 | 
			
		||||
		if (dm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0)
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		if (!(name = dm_pool_strdup(f->mem, buffer))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto bad;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(name = dm_pool_strdup(f->mem, buffer)))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		if (!dm_hash_insert(f->pv_names, dev_name(pv->dev), name)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto bad;
 | 
			
		||||
		}
 | 
			
		||||
		if (!dm_hash_insert(f->pv_names, dev_name(pv->dev), name))
 | 
			
		||||
			return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	if (f->mem)
 | 
			
		||||
		dm_pool_destroy(f->mem);
 | 
			
		||||
 | 
			
		||||
	if (f->pv_names)
 | 
			
		||||
		dm_hash_destroy(f->pv_names);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _text_vg_export(struct formatter *f,
 | 
			
		||||
@@ -664,35 +650,33 @@ static int _text_vg_export(struct formatter *f,
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
#define fail do {stack; goto out;} while(0)
 | 
			
		||||
 | 
			
		||||
	if (f->header && !_print_header(f, vg, desc))
 | 
			
		||||
		fail;
 | 
			
		||||
	if (f->header && !_print_header(f, desc))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if (!out_text(f, "%s {", vg->name))
 | 
			
		||||
		fail;
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	_inc_indent(f);
 | 
			
		||||
 | 
			
		||||
	if (!_print_vg(f, vg))
 | 
			
		||||
		fail;
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	outnl(f);
 | 
			
		||||
	if (!_print_pvs(f, vg))
 | 
			
		||||
		fail;
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	outnl(f);
 | 
			
		||||
	if (!_print_lvs(f, vg))
 | 
			
		||||
		fail;
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	_dec_indent(f);
 | 
			
		||||
	if (!out_text(f, "}"))
 | 
			
		||||
		fail;
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if (!f->header && !_print_header(f, vg, desc))
 | 
			
		||||
		fail;
 | 
			
		||||
	if (!f->header && !_print_header(f, desc))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
#undef fail
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,7 @@ static struct flag _lv_flags[] = {
 | 
			
		||||
	{VISIBLE_LV, "VISIBLE"},
 | 
			
		||||
	{PVMOVE, "PVMOVE"},
 | 
			
		||||
	{LOCKED, "LOCKED"},
 | 
			
		||||
	{MIRROR_NOTSYNCED, "NOTSYNCED"},
 | 
			
		||||
	{MIRROR_IMAGE, NULL},
 | 
			
		||||
	{MIRROR_LOG, NULL},
 | 
			
		||||
	{MIRRORED, NULL},
 | 
			
		||||
 
 | 
			
		||||
@@ -39,8 +39,9 @@
 | 
			
		||||
#define FMT_TEXT_NAME "lvm2"
 | 
			
		||||
#define FMT_TEXT_ALIAS "text"
 | 
			
		||||
 | 
			
		||||
static struct format_instance *_create_text_instance(const struct format_type
 | 
			
		||||
static struct format_instance *_text_create_text_instance(const struct format_type
 | 
			
		||||
						     *fmt, const char *vgname,
 | 
			
		||||
						     const char *vgid,
 | 
			
		||||
						     void *context);
 | 
			
		||||
 | 
			
		||||
struct text_fid_context {
 | 
			
		||||
@@ -68,7 +69,8 @@ struct text_context {
 | 
			
		||||
 * NOTE: Currently there can be only one vg per text file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
static int _text_vg_setup(struct format_instance *fid __attribute((unused)),
 | 
			
		||||
			  struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	if (vg->extent_size & (vg->extent_size - 1)) {
 | 
			
		||||
		log_error("Extent size must be power of 2");
 | 
			
		||||
@@ -78,13 +80,14 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
 | 
			
		||||
static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
 | 
			
		||||
			  struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
/******** FIXME Any LV size restriction? 
 | 
			
		||||
	uint64_t max_size = UINT_MAX;
 | 
			
		||||
 | 
			
		||||
	if (lv->size > max_size) {
 | 
			
		||||
		char *dummy = display_size(max_size, SIZE_SHORT);
 | 
			
		||||
		char *dummy = display_size(max_size);
 | 
			
		||||
		log_error("logical volumes cannot be larger than %s", dummy);
 | 
			
		||||
		dm_free(dummy);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -142,7 +145,7 @@ static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
 | 
			
		||||
 | 
			
		||||
	_xlate_mdah(mdah);
 | 
			
		||||
 | 
			
		||||
	if (strncmp(mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
 | 
			
		||||
	if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
 | 
			
		||||
		log_error("Wrong magic number in metadata area header");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -166,7 +169,7 @@ static int _raw_write_mda_header(const struct format_type *fmt,
 | 
			
		||||
				 struct device *dev,
 | 
			
		||||
				 uint64_t start_byte, struct mda_header *mdah)
 | 
			
		||||
{
 | 
			
		||||
	strncpy(mdah->magic, FMTT_MAGIC, sizeof(mdah->magic));
 | 
			
		||||
	strncpy((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic));
 | 
			
		||||
	mdah->version = FMTT_VERSION;
 | 
			
		||||
	mdah->start = start_byte;
 | 
			
		||||
 | 
			
		||||
@@ -219,7 +222,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
 | 
			
		||||
 | 
			
		||||
      error:
 | 
			
		||||
	if ((info = info_from_pvid(dev_area->dev->pvid)))
 | 
			
		||||
		lvmcache_update_vgname(info, ORPHAN);
 | 
			
		||||
		lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL);
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
@@ -850,7 +853,7 @@ static int _scan_file(const struct format_type *fmt)
 | 
			
		||||
			     tmp != dirent->d_name + strlen(dirent->d_name)
 | 
			
		||||
			     - 4)) {
 | 
			
		||||
				vgname = dirent->d_name;
 | 
			
		||||
				if (lvm_snprintf(path, PATH_MAX, "%s/%s",
 | 
			
		||||
				if (dm_snprintf(path, PATH_MAX, "%s/%s",
 | 
			
		||||
						 dl->dir, vgname) < 0) {
 | 
			
		||||
					log_error("Name too long %s/%s",
 | 
			
		||||
						  dl->dir, vgname);
 | 
			
		||||
@@ -858,9 +861,11 @@ static int _scan_file(const struct format_type *fmt)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				/* FIXME stat file to see if it's changed */
 | 
			
		||||
				fid = _create_text_instance(fmt, NULL, NULL);
 | 
			
		||||
				fid = _text_create_text_instance(fmt, NULL, NULL,
 | 
			
		||||
							    NULL);
 | 
			
		||||
				if ((vg = _vg_read_file_name(fid, vgname,
 | 
			
		||||
							     path)))
 | 
			
		||||
					/* FIXME Store creation host in vg */
 | 
			
		||||
					lvmcache_update_vg(vg);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -871,65 +876,99 @@ static int _scan_file(const struct format_type *fmt)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
 | 
			
		||||
		    char *buf, uint32_t size)
 | 
			
		||||
const char *vgname_from_mda(const struct format_type *fmt,
 | 
			
		||||
			    struct device_area *dev_area, struct id *vgid,
 | 
			
		||||
			    uint32_t *vgstatus, char **creation_host)
 | 
			
		||||
{
 | 
			
		||||
	struct raw_locn *rlocn;
 | 
			
		||||
	struct mda_header *mdah;
 | 
			
		||||
	unsigned int len;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	uint32_t wrap = 0;
 | 
			
		||||
	const char *vgname = NULL;
 | 
			
		||||
	unsigned int len = 0;
 | 
			
		||||
	char buf[NAME_LEN + 1];
 | 
			
		||||
        char uuid[64];
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev_area->dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(mdah = _raw_read_mda_header(fmt, dev_area))) {
 | 
			
		||||
		stack;
 | 
			
		||||
	if (!(mdah = _raw_read_mda_header(fmt, dev_area)))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	/* FIXME Cope with returning a list */
 | 
			
		||||
	rlocn = mdah->raw_locns;
 | 
			
		||||
 | 
			
		||||
	/* Do quick check for a vgname */
 | 
			
		||||
	if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
 | 
			
		||||
		      NAME_LEN, buf))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
 | 
			
		||||
	       len < (NAME_LEN - 1))
 | 
			
		||||
		len++;
 | 
			
		||||
 | 
			
		||||
	buf[len] = '\0';
 | 
			
		||||
 | 
			
		||||
	/* Ignore this entry if the characters aren't permissible */
 | 
			
		||||
	if (!validate_name(buf))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	/* We found a VG - now check the metadata */
 | 
			
		||||
	if (rlocn->offset + rlocn->size > mdah->size)
 | 
			
		||||
		wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
 | 
			
		||||
 | 
			
		||||
	if (wrap > rlocn->offset) {
 | 
			
		||||
		log_error("%s: metadata too large for circular buffer",
 | 
			
		||||
			  dev_name(dev_area->dev));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rlocn = mdah->raw_locns;
 | 
			
		||||
	/* FIXME 64-bit */
 | 
			
		||||
	if (!(vgname = text_vgname_import(fmt, dev_area->dev,
 | 
			
		||||
					  (off_t) (dev_area->start +
 | 
			
		||||
						   rlocn->offset),
 | 
			
		||||
					  (uint32_t) (rlocn->size - wrap),
 | 
			
		||||
					  (off_t) (dev_area->start +
 | 
			
		||||
						   MDA_HEADER_SIZE),
 | 
			
		||||
					  wrap, calc_crc, rlocn->checksum,
 | 
			
		||||
					  vgid, vgstatus, creation_host)))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	while (rlocn->offset) {
 | 
			
		||||
		if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
 | 
			
		||||
			      size, buf)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		len = 0;
 | 
			
		||||
		while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
 | 
			
		||||
		       len < (size - 1))
 | 
			
		||||
			len++;
 | 
			
		||||
		buf[len] = '\0';
 | 
			
		||||
 | 
			
		||||
		/* Ignore this entry if the characters aren't permissible */
 | 
			
		||||
		if (!validate_name(buf)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		r = 1;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
		/* FIXME Cope with returning a list */
 | 
			
		||||
		rlocn++;
 | 
			
		||||
	/* Ignore this entry if the characters aren't permissible */
 | 
			
		||||
	if (!validate_name(vgname)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		vgname = NULL;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!id_write_format(vgid, uuid, sizeof(uuid))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		vgname = NULL;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64
 | 
			
		||||
		  " for %s (%s)", 
 | 
			
		||||
		  dev_name(dev_area->dev), dev_area->start + rlocn->offset,
 | 
			
		||||
		  rlocn->size, vgname, uuid);
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!dev_close(dev_area->dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
	return vgname;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _scan_raw(const struct format_type *fmt)
 | 
			
		||||
{
 | 
			
		||||
	struct raw_list *rl;
 | 
			
		||||
	struct list *raw_list;
 | 
			
		||||
	char vgnamebuf[NAME_LEN + 2];
 | 
			
		||||
	const char *vgname;
 | 
			
		||||
	struct volume_group *vg;
 | 
			
		||||
	struct format_instance fid;
 | 
			
		||||
	struct id vgid;
 | 
			
		||||
	uint32_t vgstatus;
 | 
			
		||||
 | 
			
		||||
	raw_list = &((struct mda_lists *) fmt->private)->raws;
 | 
			
		||||
 | 
			
		||||
@@ -938,9 +977,9 @@ static int _scan_raw(const struct format_type *fmt)
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(rl, raw_list) {
 | 
			
		||||
		/* FIXME We're reading mdah twice here... */
 | 
			
		||||
		if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf,
 | 
			
		||||
				    sizeof(vgnamebuf))) {
 | 
			
		||||
			if ((vg = _vg_read_raw_area(&fid, vgnamebuf,
 | 
			
		||||
		if ((vgname = vgname_from_mda(fmt, &rl->dev_area, &vgid, &vgstatus,
 | 
			
		||||
					      NULL))) {
 | 
			
		||||
			if ((vg = _vg_read_raw_area(&fid, vgname,
 | 
			
		||||
						    &rl->dev_area, 0)))
 | 
			
		||||
				lvmcache_update_vg(vg);
 | 
			
		||||
		}
 | 
			
		||||
@@ -949,13 +988,13 @@ static int _scan_raw(const struct format_type *fmt)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _scan(const struct format_type *fmt)
 | 
			
		||||
static int _text_scan(const struct format_type *fmt)
 | 
			
		||||
{
 | 
			
		||||
	return (_scan_file(fmt) & _scan_raw(fmt));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* For orphan, creates new mdas according to policy.
 | 
			
		||||
   Always have an mda between end-of-label and PE_ALIGN boundary */
 | 
			
		||||
   Always have an mda between end-of-label and pe_align() boundary */
 | 
			
		||||
static int _mda_setup(const struct format_type *fmt,
 | 
			
		||||
		      uint64_t pe_start, uint64_t pe_end,
 | 
			
		||||
		      int pvmetadatacopies,
 | 
			
		||||
@@ -966,15 +1005,12 @@ static int _mda_setup(const struct format_type *fmt,
 | 
			
		||||
	uint64_t start1, mda_size1;	/* First area - start of disk */
 | 
			
		||||
	uint64_t start2, mda_size2;	/* Second area - end of disk */
 | 
			
		||||
	uint64_t wipe_size = 8 << SECTOR_SHIFT;
 | 
			
		||||
	size_t pagesize = getpagesize();
 | 
			
		||||
	size_t pagesize = lvm_getpagesize();
 | 
			
		||||
 | 
			
		||||
	if (!pvmetadatacopies) {
 | 
			
		||||
		/* Space available for PEs */
 | 
			
		||||
		pv->size -= PE_ALIGN;
 | 
			
		||||
	if (!pvmetadatacopies)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	alignment = PE_ALIGN << SECTOR_SHIFT;
 | 
			
		||||
	alignment = pe_align() << SECTOR_SHIFT;
 | 
			
		||||
	disk_size = pv->size << SECTOR_SHIFT;
 | 
			
		||||
	pe_start <<= SECTOR_SHIFT;
 | 
			
		||||
	pe_end <<= SECTOR_SHIFT;
 | 
			
		||||
@@ -988,9 +1024,6 @@ static int _mda_setup(const struct format_type *fmt,
 | 
			
		||||
	/* Requested metadatasize */
 | 
			
		||||
	mda_size1 = pvmetadatasize << SECTOR_SHIFT;
 | 
			
		||||
 | 
			
		||||
	/* Space available for PEs (before any mdas created) */
 | 
			
		||||
	pv->size -= LABEL_SCAN_SECTORS;
 | 
			
		||||
 | 
			
		||||
	/* Place mda straight after label area at start of disk */
 | 
			
		||||
	start1 = LABEL_SCAN_SIZE;
 | 
			
		||||
 | 
			
		||||
@@ -998,11 +1031,8 @@ static int _mda_setup(const struct format_type *fmt,
 | 
			
		||||
	if ((!pe_start && !pe_end) ||
 | 
			
		||||
	    ((pe_start > start1) && (pe_start - start1 >= MDA_SIZE_MIN))) {
 | 
			
		||||
		mda_adjustment = start1 % pagesize;
 | 
			
		||||
		if (mda_adjustment) {
 | 
			
		||||
		if (mda_adjustment)
 | 
			
		||||
			start1 += (pagesize - mda_adjustment);
 | 
			
		||||
			pv->size -= ((pagesize - mda_adjustment) >>
 | 
			
		||||
				     SECTOR_SHIFT);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Ensure it's not going to be bigger than the disk! */
 | 
			
		||||
@@ -1016,7 +1046,7 @@ static int _mda_setup(const struct format_type *fmt,
 | 
			
		||||
		pvmetadatacopies = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Round up to PE_ALIGN boundary */
 | 
			
		||||
	/* Round up to pe_align() boundary */
 | 
			
		||||
	mda_adjustment = (mda_size1 + start1) % alignment;
 | 
			
		||||
	if (mda_adjustment)
 | 
			
		||||
		mda_size1 += (alignment - mda_adjustment);
 | 
			
		||||
@@ -1032,16 +1062,16 @@ static int _mda_setup(const struct format_type *fmt,
 | 
			
		||||
	/* FIXME If creating new mdas, wipe them! */
 | 
			
		||||
	if (mda_size1) {
 | 
			
		||||
		if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
 | 
			
		||||
			     mda_size1)) return 0;
 | 
			
		||||
			     mda_size1))
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		if (!dev_zero((struct device *) pv->dev, start1,
 | 
			
		||||
			      (size_t) (mda_size1 >
 | 
			
		||||
					wipe_size ? wipe_size : mda_size1))) {
 | 
			
		||||
		if (!dev_set((struct device *) pv->dev, start1,
 | 
			
		||||
			     (size_t) (mda_size1 >
 | 
			
		||||
				       wipe_size ? : mda_size1), 0)) {
 | 
			
		||||
			log_error("Failed to wipe new metadata area");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pv->size -= mda_size1 >> SECTOR_SHIFT;
 | 
			
		||||
		if (pvmetadatacopies == 1)
 | 
			
		||||
			return 1;
 | 
			
		||||
	} else
 | 
			
		||||
@@ -1080,13 +1110,12 @@ static int _mda_setup(const struct format_type *fmt,
 | 
			
		||||
	if (mda_size2) {
 | 
			
		||||
		if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
 | 
			
		||||
			     mda_size2)) return 0;
 | 
			
		||||
		if (!dev_zero(pv->dev, start2,
 | 
			
		||||
			      (size_t) (mda_size1 >
 | 
			
		||||
					wipe_size ? wipe_size : mda_size1))) {
 | 
			
		||||
		if (!dev_set(pv->dev, start2,
 | 
			
		||||
			     (size_t) (mda_size1 >
 | 
			
		||||
				       wipe_size ? : mda_size1), 0)) {
 | 
			
		||||
			log_error("Failed to wipe new metadata area");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		pv->size -= mda_size2 >> SECTOR_SHIFT;
 | 
			
		||||
	} else
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
@@ -1095,7 +1124,7 @@ static int _mda_setup(const struct format_type *fmt,
 | 
			
		||||
 | 
			
		||||
/* Only for orphans */
 | 
			
		||||
/* Set label_sector to -1 if rewriting existing label into same sector */
 | 
			
		||||
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
		     struct list *mdas, int64_t label_sector)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
@@ -1109,7 +1138,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	/* FIXME Test mode don't update cache? */
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
 | 
			
		||||
				  ORPHAN, NULL))) {
 | 
			
		||||
				  ORPHAN, NULL, 0))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1150,22 +1179,22 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
 | 
			
		||||
	/* Set pe_start to first aligned sector after any metadata 
 | 
			
		||||
	 * areas that begin before pe_start */
 | 
			
		||||
	pv->pe_start = PE_ALIGN;
 | 
			
		||||
	pv->pe_start = pe_align();
 | 
			
		||||
	list_iterate_items(mda, &info->mdas) {
 | 
			
		||||
		mdac = (struct mda_context *) mda->metadata_locn;
 | 
			
		||||
		if (pv->dev == mdac->area.dev &&
 | 
			
		||||
		    (mdac->area.start < (pv->pe_start << SECTOR_SHIFT)) &&
 | 
			
		||||
		    (mdac->area.start <= (pv->pe_start << SECTOR_SHIFT)) &&
 | 
			
		||||
		    (mdac->area.start + mdac->area.size >
 | 
			
		||||
		     (pv->pe_start << SECTOR_SHIFT))) {
 | 
			
		||||
			pv->pe_start = (mdac->area.start + mdac->area.size)
 | 
			
		||||
			    >> SECTOR_SHIFT;
 | 
			
		||||
			adjustment = pv->pe_start % PE_ALIGN;
 | 
			
		||||
			adjustment = pv->pe_start % pe_align();
 | 
			
		||||
			if (adjustment)
 | 
			
		||||
				pv->pe_start += (PE_ALIGN - adjustment);
 | 
			
		||||
				pv->pe_start += (pe_align() - adjustment);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (!add_da
 | 
			
		||||
	    (fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
 | 
			
		||||
	    (NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1220,7 +1249,7 @@ static int _add_raw(struct list *raw_list, struct device_area *dev_area)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		    struct physical_volume *pv, struct list *mdas)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
@@ -1245,7 +1274,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
	/* Have we already cached vgname? */
 | 
			
		||||
	if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
 | 
			
		||||
	    get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
 | 
			
		||||
				 info->dev->pvid, pv)) {
 | 
			
		||||
				 info->vginfo->vgid, info->dev->pvid, pv)) {
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1256,6 +1285,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		if (info->vginfo && info->vginfo->vgname &&
 | 
			
		||||
		    *info->vginfo->vgname &&
 | 
			
		||||
		    get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
 | 
			
		||||
					 info->vginfo->vgid,
 | 
			
		||||
					 info->dev->pvid, pv)) {
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
@@ -1301,7 +1331,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_instance(struct format_instance *fid)
 | 
			
		||||
static void _text_destroy_instance(struct format_instance *fid __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
@@ -1326,7 +1356,7 @@ static void _free_raws(struct list *raw_list)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(const struct format_type *fmt)
 | 
			
		||||
static void _text_destroy(const struct format_type *fmt)
 | 
			
		||||
{
 | 
			
		||||
	if (fmt->private) {
 | 
			
		||||
		_free_dirs(&((struct mda_lists *) fmt->private)->dirs);
 | 
			
		||||
@@ -1334,36 +1364,36 @@ static void _destroy(const struct format_type *fmt)
 | 
			
		||||
		dm_free(fmt->private);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_free((void *) fmt);
 | 
			
		||||
	dm_free((void *)fmt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct metadata_area_ops _metadata_text_file_ops = {
 | 
			
		||||
	vg_read:_vg_read_file,
 | 
			
		||||
	vg_read_precommit:_vg_read_precommit_file,
 | 
			
		||||
	vg_write:_vg_write_file,
 | 
			
		||||
	vg_remove:_vg_remove_file,
 | 
			
		||||
	vg_commit:_vg_commit_file
 | 
			
		||||
	.vg_read = _vg_read_file,
 | 
			
		||||
	.vg_read_precommit = _vg_read_precommit_file,
 | 
			
		||||
	.vg_write = _vg_write_file,
 | 
			
		||||
	.vg_remove = _vg_remove_file,
 | 
			
		||||
	.vg_commit = _vg_commit_file
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct metadata_area_ops _metadata_text_file_backup_ops = {
 | 
			
		||||
	vg_read:_vg_read_file,
 | 
			
		||||
	vg_write:_vg_write_file,
 | 
			
		||||
	vg_remove:_vg_remove_file,
 | 
			
		||||
	vg_commit:_vg_commit_file_backup
 | 
			
		||||
	.vg_read = _vg_read_file,
 | 
			
		||||
	.vg_write = _vg_write_file,
 | 
			
		||||
	.vg_remove = _vg_remove_file,
 | 
			
		||||
	.vg_commit = _vg_commit_file_backup
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct metadata_area_ops _metadata_text_raw_ops = {
 | 
			
		||||
	vg_read:_vg_read_raw,
 | 
			
		||||
	vg_read_precommit:_vg_read_precommit_raw,
 | 
			
		||||
	vg_write:_vg_write_raw,
 | 
			
		||||
	vg_remove:_vg_remove_raw,
 | 
			
		||||
	vg_precommit:_vg_precommit_raw,
 | 
			
		||||
	vg_commit:_vg_commit_raw,
 | 
			
		||||
	vg_revert:_vg_revert_raw
 | 
			
		||||
	.vg_read = _vg_read_raw,
 | 
			
		||||
	.vg_read_precommit = _vg_read_precommit_raw,
 | 
			
		||||
	.vg_write = _vg_write_raw,
 | 
			
		||||
	.vg_remove = _vg_remove_raw,
 | 
			
		||||
	.vg_precommit = _vg_precommit_raw,
 | 
			
		||||
	.vg_commit = _vg_commit_raw,
 | 
			
		||||
	.vg_revert = _vg_revert_raw
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* pvmetadatasize in sectors */
 | 
			
		||||
static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
static int _text_pv_setup(const struct format_type *fmt,
 | 
			
		||||
		     uint64_t pe_start, uint32_t extent_count,
 | 
			
		||||
		     uint32_t extent_size,
 | 
			
		||||
		     int pvmetadatacopies,
 | 
			
		||||
@@ -1376,11 +1406,11 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	int found;
 | 
			
		||||
	uint64_t pe_end = 0;
 | 
			
		||||
 | 
			
		||||
	/* FIXME if vg, adjust start/end of pe area to avoid mdas! */
 | 
			
		||||
	unsigned mda_count = 0;
 | 
			
		||||
	uint64_t mda_size2 = 0;
 | 
			
		||||
 | 
			
		||||
	/* FIXME Cope with pvchange */
 | 
			
		||||
	/* FIXME Merge code with _create_text_instance */
 | 
			
		||||
	/* FIXME Merge code with _text_create_text_instance */
 | 
			
		||||
 | 
			
		||||
	/* If new vg, add any further mdas on this PV to the fid's mda list */
 | 
			
		||||
	if (vg) {
 | 
			
		||||
@@ -1388,11 +1418,16 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
		if ((info = info_from_pvid(pv->dev->pvid))) {
 | 
			
		||||
			pvmdas = &info->mdas;
 | 
			
		||||
			list_iterate_items(mda, pvmdas) {
 | 
			
		||||
				mda_count++;
 | 
			
		||||
				mdac =
 | 
			
		||||
				    (struct mda_context *) mda->metadata_locn;
 | 
			
		||||
 | 
			
		||||
				/* FIXME Check it isn't already in use */
 | 
			
		||||
 | 
			
		||||
				/* Reduce usable device size */
 | 
			
		||||
				if (mda_count > 1)
 | 
			
		||||
					mda_size2 = mdac->area.size >> SECTOR_SHIFT;
 | 
			
		||||
 | 
			
		||||
				/* Ensure it isn't already on list */
 | 
			
		||||
				found = 0;
 | 
			
		||||
				list_iterate_items(mda2, mdas) {
 | 
			
		||||
@@ -1430,6 +1465,17 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* FIXME Cope with genuine pe_count 0 */
 | 
			
		||||
 | 
			
		||||
		/* If missing, estimate pv->size from file-based metadata */
 | 
			
		||||
		if (!pv->size && pv->pe_count)
 | 
			
		||||
			pv->size = pv->pe_count * (uint64_t) vg->extent_size +
 | 
			
		||||
				   pv->pe_start + mda_size2;
 | 
			
		||||
 | 
			
		||||
		/* Recalculate number of extents that will fit */
 | 
			
		||||
		if (!pv->pe_count)
 | 
			
		||||
			pv->pe_count = (pv->size - pv->pe_start - mda_size2) / vg->extent_size;
 | 
			
		||||
 | 
			
		||||
		/* Unlike LVM1, we don't store this outside a VG */
 | 
			
		||||
		/* FIXME Default from config file? vgextend cmdline flag? */
 | 
			
		||||
		pv->status |= ALLOCATABLE_PV;
 | 
			
		||||
@@ -1448,8 +1494,9 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* NULL vgname means use only the supplied context e.g. an archive file */
 | 
			
		||||
static struct format_instance *_create_text_instance(const struct format_type
 | 
			
		||||
static struct format_instance *_text_create_text_instance(const struct format_type
 | 
			
		||||
						     *fmt, const char *vgname,
 | 
			
		||||
						     const char *vgid,
 | 
			
		||||
						     void *context)
 | 
			
		||||
{
 | 
			
		||||
	struct format_instance *fid;
 | 
			
		||||
@@ -1492,7 +1539,7 @@ static struct format_instance *_create_text_instance(const struct format_type
 | 
			
		||||
		dir_list = &((struct mda_lists *) fmt->private)->dirs;
 | 
			
		||||
 | 
			
		||||
		list_iterate_items(dl, dir_list) {
 | 
			
		||||
			if (lvm_snprintf(path, PATH_MAX, "%s/%s",
 | 
			
		||||
			if (dm_snprintf(path, PATH_MAX, "%s/%s",
 | 
			
		||||
					 dl->dir, vgname) < 0) {
 | 
			
		||||
				log_error("Name too long %s/%s", dl->dir,
 | 
			
		||||
					  vgname);
 | 
			
		||||
@@ -1535,7 +1582,7 @@ static struct format_instance *_create_text_instance(const struct format_type
 | 
			
		||||
 | 
			
		||||
		/* Scan PVs in VG for any further MDAs */
 | 
			
		||||
		lvmcache_label_scan(fmt->cmd, 0);
 | 
			
		||||
		if (!(vginfo = vginfo_from_vgname(vgname))) {
 | 
			
		||||
		if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
@@ -1569,7 +1616,6 @@ static struct format_instance *_create_text_instance(const struct format_type
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	return fid;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *create_text_context(struct cmd_context *cmd, const char *path,
 | 
			
		||||
@@ -1618,15 +1664,15 @@ void *create_text_context(struct cmd_context *cmd, const char *path,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct format_handler _text_handler = {
 | 
			
		||||
	scan:_scan,
 | 
			
		||||
	pv_read:_pv_read,
 | 
			
		||||
	pv_setup:_pv_setup,
 | 
			
		||||
	pv_write:_pv_write,
 | 
			
		||||
	vg_setup:_vg_setup,
 | 
			
		||||
	lv_setup:_lv_setup,
 | 
			
		||||
	create_instance:_create_text_instance,
 | 
			
		||||
	destroy_instance:_destroy_instance,
 | 
			
		||||
	destroy:_destroy
 | 
			
		||||
	.scan = _text_scan,
 | 
			
		||||
	.pv_read = _text_pv_read,
 | 
			
		||||
	.pv_setup = _text_pv_setup,
 | 
			
		||||
	.pv_write = _text_pv_write,
 | 
			
		||||
	.vg_setup = _text_vg_setup,
 | 
			
		||||
	.lv_setup = _text_lv_setup,
 | 
			
		||||
	.create_instance = _text_create_text_instance,
 | 
			
		||||
	.destroy_instance = _text_destroy_instance,
 | 
			
		||||
	.destroy = _text_destroy
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _add_dir(const char *dir, struct list *dir_list)
 | 
			
		||||
@@ -1716,10 +1762,12 @@ struct format_type *create_text_format(struct cmd_context *cmd)
 | 
			
		||||
	fmt->name = FMT_TEXT_NAME;
 | 
			
		||||
	fmt->alias = FMT_TEXT_ALIAS;
 | 
			
		||||
	fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
 | 
			
		||||
			FMT_UNLIMITED_VOLS | FMT_RESIZE_PV;
 | 
			
		||||
			FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
 | 
			
		||||
			FMT_UNLIMITED_STRIPESIZE;
 | 
			
		||||
 | 
			
		||||
	if (!(mda_lists = dm_malloc(sizeof(struct mda_lists)))) {
 | 
			
		||||
		log_error("Failed to allocate dir_list");
 | 
			
		||||
		dm_free(fmt);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1731,15 +1779,17 @@ struct format_type *create_text_format(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	if (!(fmt->labeller = text_labeller_create(fmt))) {
 | 
			
		||||
		log_error("Couldn't create text label handler.");
 | 
			
		||||
		dm_free(fmt);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(label_register_handler(FMT_TEXT_NAME, fmt->labeller))) {
 | 
			
		||||
		log_error("Couldn't register text label handler.");
 | 
			
		||||
		dm_free(fmt);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((cn = find_config_node(cmd->cft->root, "metadata/dirs"))) {
 | 
			
		||||
	if ((cn = find_config_tree_node(cmd, "metadata/dirs"))) {
 | 
			
		||||
		for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
			if (cv->type != CFG_STRING) {
 | 
			
		||||
				log_error("Invalid string in config file: "
 | 
			
		||||
@@ -1755,7 +1805,7 @@ struct format_type *create_text_format(struct cmd_context *cmd)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((cn = find_config_node(cmd->cft->root, "metadata/disk_areas"))) {
 | 
			
		||||
	if ((cn = find_config_tree_node(cmd, "metadata/disk_areas"))) {
 | 
			
		||||
		for (cn = cn->child; cn; cn = cn->sib) {
 | 
			
		||||
			if (!_get_config_disk_area(cmd, cn, &mda_lists->raws))
 | 
			
		||||
				goto err;
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ struct labeller *text_labeller_create(const struct format_type *fmt);
 | 
			
		||||
 | 
			
		||||
int pvhdr_read(struct device *dev, char *buf);
 | 
			
		||||
 | 
			
		||||
int add_da(const struct format_type *fmt, struct dm_pool *mem, struct list *das,
 | 
			
		||||
int add_da(struct dm_pool *mem, struct list *das,
 | 
			
		||||
	   uint64_t start, uint64_t size);
 | 
			
		||||
void del_das(struct list *das);
 | 
			
		||||
 | 
			
		||||
@@ -54,7 +54,8 @@ int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct list *mda
 | 
			
		||||
	    struct device *dev, uint64_t start, uint64_t size);
 | 
			
		||||
void del_mdas(struct list *mdas);
 | 
			
		||||
 | 
			
		||||
int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
 | 
			
		||||
		    char *buf, uint32_t size);
 | 
			
		||||
const char *vgname_from_mda(const struct format_type *fmt,
 | 
			
		||||
			    struct device_area *dev_area, struct id *vgid,
 | 
			
		||||
			    uint32_t *vgstatus, char **creation_host);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,10 @@ struct text_vg_version_ops {
 | 
			
		||||
					 struct config_tree * cf);
 | 
			
		||||
	void (*read_desc) (struct dm_pool * mem, struct config_tree * cf,
 | 
			
		||||
			   time_t *when, char **desc);
 | 
			
		||||
	const char *(*read_vgname) (const struct format_type *fmt,
 | 
			
		||||
				    struct config_tree *cft,
 | 
			
		||||
				    struct id *vgid, uint32_t *vgstatus,
 | 
			
		||||
				    char **creation_host);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct text_vg_version_ops *text_vg_vsn1_init(void);
 | 
			
		||||
@@ -70,5 +74,12 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
 | 
			
		||||
				       checksum_fn_t checksum_fn,
 | 
			
		||||
				       uint32_t checksum,
 | 
			
		||||
				       time_t *when, char **desc);
 | 
			
		||||
const char *text_vgname_import(const struct format_type *fmt,
 | 
			
		||||
			       struct device *dev,
 | 
			
		||||
                               off_t offset, uint32_t size,
 | 
			
		||||
                               off_t offset2, uint32_t size2,
 | 
			
		||||
                               checksum_fn_t checksum_fn, uint32_t checksum,
 | 
			
		||||
                               struct id *vgid, uint32_t *vgstatus,
 | 
			
		||||
			       char **creation_host);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,53 @@
 | 
			
		||||
/* FIXME Use tidier inclusion method */
 | 
			
		||||
static struct text_vg_version_ops *(_text_vsn_list[2]);
 | 
			
		||||
 | 
			
		||||
const char *text_vgname_import(const struct format_type *fmt,
 | 
			
		||||
			       struct device *dev,
 | 
			
		||||
			       off_t offset, uint32_t size,
 | 
			
		||||
			       off_t offset2, uint32_t size2,
 | 
			
		||||
			       checksum_fn_t checksum_fn, uint32_t checksum,
 | 
			
		||||
			       struct id *vgid, uint32_t *vgstatus,
 | 
			
		||||
			       char **creation_host)
 | 
			
		||||
{
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
	struct text_vg_version_ops **vsn;
 | 
			
		||||
	const char *vgname = NULL;
 | 
			
		||||
 | 
			
		||||
	static int _text_import_initialised = 0;
 | 
			
		||||
 | 
			
		||||
	if (!_text_import_initialised) {
 | 
			
		||||
		_text_vsn_list[0] = text_vg_vsn1_init();
 | 
			
		||||
		_text_vsn_list[1] = NULL;
 | 
			
		||||
		_text_import_initialised = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cft = create_config_tree(NULL)))
 | 
			
		||||
		return_NULL;
 | 
			
		||||
 | 
			
		||||
	if ((!dev && !read_config_file(cft)) ||
 | 
			
		||||
	    (dev && !read_config_fd(cft, dev, offset, size,
 | 
			
		||||
				    offset2, size2, checksum_fn, checksum)))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	/* 
 | 
			
		||||
	 * Find a set of version functions that can read this file
 | 
			
		||||
	 */
 | 
			
		||||
	for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
 | 
			
		||||
		if (!(*vsn)->check_version(cft))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid, vgstatus,
 | 
			
		||||
						   creation_host)))
 | 
			
		||||
			goto_out;
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	destroy_config_tree(cft);
 | 
			
		||||
	return vgname;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct volume_group *text_vg_import_fd(struct format_instance *fid,
 | 
			
		||||
				       const char *file,
 | 
			
		||||
				       struct device *dev,
 | 
			
		||||
@@ -36,21 +83,19 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
	struct text_vg_version_ops **vsn;
 | 
			
		||||
 | 
			
		||||
	static int _initialised = 0;
 | 
			
		||||
	static int _text_vg_import_initialised = 0;
 | 
			
		||||
 | 
			
		||||
	if (!_initialised) {
 | 
			
		||||
	if (!_text_vg_import_initialised) {
 | 
			
		||||
		_text_vsn_list[0] = text_vg_vsn1_init();
 | 
			
		||||
		_text_vsn_list[1] = NULL;
 | 
			
		||||
		_initialised = 1;
 | 
			
		||||
		_text_vg_import_initialised = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*desc = NULL;
 | 
			
		||||
	*when = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(cft = create_config_tree(file))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(cft = create_config_tree(file)))
 | 
			
		||||
		return_NULL;
 | 
			
		||||
 | 
			
		||||
	if ((!dev && !read_config_file(cft)) ||
 | 
			
		||||
	    (dev && !read_config_fd(cft, dev, offset, size,
 | 
			
		||||
@@ -84,6 +129,6 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
 | 
			
		||||
					 const char *file,
 | 
			
		||||
					 time_t *when, char **desc)
 | 
			
		||||
{
 | 
			
		||||
	return text_vg_import_fd(fid, file, NULL, 0, 0, 0, 0, NULL, 0,
 | 
			
		||||
	return text_vg_import_fd(fid, file, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
 | 
			
		||||
				 when, desc);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -167,6 +167,8 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(pvn, "status"))) {
 | 
			
		||||
		log_error("Couldn't find status flags for physical volume.");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -177,6 +179,9 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Late addition */
 | 
			
		||||
	_read_int64(pvn, "dev_size", &pv->size);
 | 
			
		||||
 | 
			
		||||
	if (!_read_int64(pvn, "pe_start", &pv->pe_start)) {
 | 
			
		||||
		log_error("Couldn't read extent size for volume group.");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -204,7 +209,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
 | 
			
		||||
	vg->free_count += pv->pe_count;
 | 
			
		||||
 | 
			
		||||
	pv->pe_size = vg->extent_size;
 | 
			
		||||
	pv->size = vg->extent_size * (uint64_t) pv->pe_count;
 | 
			
		||||
 | 
			
		||||
	pv->pe_alloc_count = 0;
 | 
			
		||||
	pv->fmt = fid->fmt;
 | 
			
		||||
 | 
			
		||||
@@ -368,7 +373,7 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
 | 
			
		||||
		} else {
 | 
			
		||||
			log_error("Couldn't find volume '%s' "
 | 
			
		||||
				  "for segment '%s'.",
 | 
			
		||||
				  cv->v.str ? cv->v.str : "NULL", seg_name);
 | 
			
		||||
				  cv->v.str ? : "NULL", seg_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -798,13 +803,62 @@ static void _read_desc(struct dm_pool *mem,
 | 
			
		||||
	*when = u;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *_read_vgname(const struct format_type *fmt,
 | 
			
		||||
				struct config_tree *cft, struct id *vgid,
 | 
			
		||||
				uint32_t *vgstatus, char **creation_host)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *vgn, *cn;
 | 
			
		||||
	struct dm_pool *mem = fmt->cmd->mem;
 | 
			
		||||
	char *vgname;
 | 
			
		||||
	int old_suppress;
 | 
			
		||||
 | 
			
		||||
	old_suppress = log_suppress(2);
 | 
			
		||||
	*creation_host = dm_pool_strdup(mem,
 | 
			
		||||
					find_config_str(cft->root,
 | 
			
		||||
						        "creation_host", ""));
 | 
			
		||||
	log_suppress(old_suppress);
 | 
			
		||||
 | 
			
		||||
	/* skip any top-level values */
 | 
			
		||||
	for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
 | 
			
		||||
 | 
			
		||||
	if (!vgn) {
 | 
			
		||||
		log_error("Couldn't find volume group in file.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(vgname = dm_pool_strdup(mem, vgn->key)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	vgn = vgn->child;
 | 
			
		||||
 | 
			
		||||
	if (!_read_id(vgid, vgn, "id")) {
 | 
			
		||||
		log_error("Couldn't read uuid for volume group %s.", vgname);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(vgn, "status"))) {
 | 
			
		||||
		log_error("Couldn't find status flags for volume group %s.",
 | 
			
		||||
			  vgname);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(read_flags(vgstatus, VG_FLAGS, cn->v))) {
 | 
			
		||||
		log_error("Couldn't read status flags for volume group %s.",
 | 
			
		||||
			  vgname);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vgname;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct text_vg_version_ops _vsn1_ops = {
 | 
			
		||||
	check_version:_check_version,
 | 
			
		||||
	read_vg:_read_vg,
 | 
			
		||||
	read_desc:_read_desc
 | 
			
		||||
	.check_version = _check_version,
 | 
			
		||||
	.read_vg = _read_vg,
 | 
			
		||||
	.read_desc = _read_desc,
 | 
			
		||||
	.read_vgname = _read_vgname,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct text_vg_version_ops *text_vg_vsn1_init(void)
 | 
			
		||||
{
 | 
			
		||||
	return &_vsn1_ops;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ struct data_area_list {
 | 
			
		||||
/* Fields with the suffix _xl should be xlate'd wherever they appear */
 | 
			
		||||
/* On disk */
 | 
			
		||||
struct pv_header {
 | 
			
		||||
	uint8_t pv_uuid[ID_LEN];
 | 
			
		||||
	int8_t pv_uuid[ID_LEN];
 | 
			
		||||
 | 
			
		||||
	/* This size can be overridden if PV belongs to a VG */
 | 
			
		||||
	uint64_t device_size_xl;	/* Bytes */
 | 
			
		||||
@@ -58,7 +58,7 @@ struct raw_locn {
 | 
			
		||||
/* Structure size limited to one sector */
 | 
			
		||||
struct mda_header {
 | 
			
		||||
	uint32_t checksum_xl;	/* Checksum of rest of mda_header */
 | 
			
		||||
	uint8_t magic[16];	/* To aid scans for metadata */
 | 
			
		||||
	int8_t magic[16];	/* To aid scans for metadata */
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
	uint64_t start;		/* Absolute start byte of mda_header */
 | 
			
		||||
	uint64_t size;		/* Size of metadata area */
 | 
			
		||||
@@ -83,6 +83,6 @@ struct mda_context {
 | 
			
		||||
#define FMTT_VERSION 1
 | 
			
		||||
#define MDA_HEADER_SIZE 512
 | 
			
		||||
#define LVM2_LABEL "LVM2 001"
 | 
			
		||||
#define MDA_SIZE_MIN (8 * getpagesize())
 | 
			
		||||
#define MDA_SIZE_MIN (8 * (unsigned) lvm_getpagesize())
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -23,17 +23,19 @@
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
 | 
			
		||||
static int _text_can_handle(struct labeller *l __attribute((unused)),
 | 
			
		||||
			    char *buf,
 | 
			
		||||
			    uint64_t sector __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct label_header *lh = (struct label_header *) buf;
 | 
			
		||||
 | 
			
		||||
	if (!strncmp(lh->type, LVM2_LABEL, sizeof(lh->type)))
 | 
			
		||||
	if (!strncmp((char *)lh->type, LVM2_LABEL, sizeof(lh->type)))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _write(struct label *label, char *buf)
 | 
			
		||||
static int _text_write(struct label *label, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct label_header *lh = (struct label_header *) buf;
 | 
			
		||||
	struct pv_header *pvhdr;
 | 
			
		||||
@@ -46,7 +48,7 @@ static int _write(struct label *label, char *buf)
 | 
			
		||||
	/* FIXME Move to where label is created */
 | 
			
		||||
	strncpy(label->type, LVM2_LABEL, sizeof(label->type));
 | 
			
		||||
 | 
			
		||||
	strncpy(lh->type, label->type, sizeof(label->type));
 | 
			
		||||
	strncpy((char *)lh->type, label->type, sizeof(label->type));
 | 
			
		||||
 | 
			
		||||
	pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
 | 
			
		||||
	info = (struct lvmcache_info *) label->info;
 | 
			
		||||
@@ -86,7 +88,7 @@ static int _write(struct label *label, char *buf)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int add_da(const struct format_type *fmt, struct dm_pool *mem, struct list *das,
 | 
			
		||||
int add_da(struct dm_pool *mem, struct list *das,
 | 
			
		||||
	   uint64_t start, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct data_area_list *dal;
 | 
			
		||||
@@ -179,14 +181,15 @@ void del_mdas(struct list *mdas)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _initialise_label(struct labeller *l, struct label *label)
 | 
			
		||||
static int _text_initialise_label(struct labeller *l __attribute((unused)),
 | 
			
		||||
				  struct label *label)
 | 
			
		||||
{
 | 
			
		||||
	strncpy(label->type, LVM2_LABEL, sizeof(label->type));
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
static int _text_read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
		 struct label **label)
 | 
			
		||||
{
 | 
			
		||||
	struct label_header *lh = (struct label_header *) buf;
 | 
			
		||||
@@ -195,13 +198,16 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
	struct disk_locn *dlocn_xl;
 | 
			
		||||
	uint64_t offset;
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
	char vgnamebuf[NAME_LEN + 2];
 | 
			
		||||
	struct id vgid;
 | 
			
		||||
	struct mda_context *mdac;
 | 
			
		||||
	const char *vgname;
 | 
			
		||||
	uint32_t vgstatus;
 | 
			
		||||
	char *creation_host;
 | 
			
		||||
 | 
			
		||||
	pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev, NULL, NULL, 0)))
 | 
			
		||||
		return_0;
 | 
			
		||||
	*label = info->label;
 | 
			
		||||
 | 
			
		||||
	info->device_size = xlate64(pvhdr->device_size_xl);
 | 
			
		||||
@@ -217,7 +223,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
	/* Data areas holding the PEs */
 | 
			
		||||
	dlocn_xl = pvhdr->disk_areas_xl;
 | 
			
		||||
	while ((offset = xlate64(dlocn_xl->offset))) {
 | 
			
		||||
		add_da(info->fmt, NULL, &info->das, offset,
 | 
			
		||||
		add_da(NULL, &info->das, offset,
 | 
			
		||||
		       xlate64(dlocn_xl->size));
 | 
			
		||||
		dlocn_xl++;
 | 
			
		||||
	}
 | 
			
		||||
@@ -232,10 +238,12 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(mda, &info->mdas) {
 | 
			
		||||
		mdac = (struct mda_context *) mda->metadata_locn;
 | 
			
		||||
		if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
 | 
			
		||||
				    sizeof(vgnamebuf))) {
 | 
			
		||||
			lvmcache_update_vgname(info, vgnamebuf);
 | 
			
		||||
		}
 | 
			
		||||
		if ((vgname = vgname_from_mda(info->fmt, &mdac->area, 
 | 
			
		||||
					      &vgid, &vgstatus, &creation_host)) &&
 | 
			
		||||
		    !lvmcache_update_vgname_and_id(info, vgname,
 | 
			
		||||
						   (char *) &vgid, vgstatus,
 | 
			
		||||
						   creation_host))
 | 
			
		||||
			return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->status &= ~CACHE_INVALID;
 | 
			
		||||
@@ -243,7 +251,8 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_label(struct labeller *l, struct label *label)
 | 
			
		||||
static void _text_destroy_label(struct labeller *l __attribute((unused)),
 | 
			
		||||
				struct label *label)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_info *info = (struct lvmcache_info *) label->info;
 | 
			
		||||
 | 
			
		||||
@@ -253,19 +262,19 @@ static void _destroy_label(struct labeller *l, struct label *label)
 | 
			
		||||
		del_das(&info->das);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct labeller *l)
 | 
			
		||||
static void _fmt_text_destroy(struct labeller *l)
 | 
			
		||||
{
 | 
			
		||||
	dm_free(l);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct label_ops _text_ops = {
 | 
			
		||||
	can_handle:_can_handle,
 | 
			
		||||
	write:_write,
 | 
			
		||||
	read:_read,
 | 
			
		||||
	verify:_can_handle,
 | 
			
		||||
	initialise_label:_initialise_label,
 | 
			
		||||
	destroy_label:_destroy_label,
 | 
			
		||||
	destroy:_destroy
 | 
			
		||||
	.can_handle = _text_can_handle,
 | 
			
		||||
	.write = _text_write,
 | 
			
		||||
	.read = _text_read,
 | 
			
		||||
	.verify = _text_can_handle,
 | 
			
		||||
	.initialise_label = _text_initialise_label,
 | 
			
		||||
	.destroy_label = _text_destroy_label,
 | 
			
		||||
	.destroy = _fmt_text_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct labeller *text_labeller_create(const struct format_type *fmt)
 | 
			
		||||
 
 | 
			
		||||
@@ -117,15 +117,6 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
 | 
			
		||||
	int found = 0;
 | 
			
		||||
	char readbuf[LABEL_SCAN_SIZE];
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
		if ((info = info_from_pvid(dev->pvid)))
 | 
			
		||||
			lvmcache_update_vgname(info, ORPHAN);
 | 
			
		||||
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
 | 
			
		||||
		log_debug("%s: Failed to read label area", dev_name(dev));
 | 
			
		||||
		goto out;
 | 
			
		||||
@@ -137,7 +128,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
 | 
			
		||||
		lh = (struct label_header *) (readbuf +
 | 
			
		||||
					      (sector << SECTOR_SHIFT));
 | 
			
		||||
 | 
			
		||||
		if (!strncmp(lh->id, LABEL_ID, sizeof(lh->id))) {
 | 
			
		||||
		if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
 | 
			
		||||
			if (found) {
 | 
			
		||||
				log_error("Ignoring additional label on %s at "
 | 
			
		||||
					  "sector %" PRIu64, dev_name(dev),
 | 
			
		||||
@@ -184,13 +175,11 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
 | 
			
		||||
      out:
 | 
			
		||||
	if (!found) {
 | 
			
		||||
		if ((info = info_from_pvid(dev->pvid)))
 | 
			
		||||
			lvmcache_update_vgname(info, ORPHAN);
 | 
			
		||||
			lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
 | 
			
		||||
						      0, NULL);
 | 
			
		||||
		log_very_verbose("%s: No label detected", dev_name(dev));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -233,7 +222,7 @@ int label_remove(struct device *dev)
 | 
			
		||||
 | 
			
		||||
		wipe = 0;
 | 
			
		||||
 | 
			
		||||
		if (!strncmp(lh->id, LABEL_ID, sizeof(lh->id))) {
 | 
			
		||||
		if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
 | 
			
		||||
			if (xlate64(lh->sector_xl) == sector)
 | 
			
		||||
				wipe = 1;
 | 
			
		||||
		} else {
 | 
			
		||||
@@ -272,16 +261,29 @@ int label_read(struct device *dev, struct label **result)
 | 
			
		||||
	char buf[LABEL_SIZE];
 | 
			
		||||
	struct labeller *l;
 | 
			
		||||
	uint64_t sector;
 | 
			
		||||
	int r;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(l = _find_labeller(dev, buf, §or))) {
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
		if ((info = info_from_pvid(dev->pvid)))
 | 
			
		||||
			lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
 | 
			
		||||
						      0, NULL);
 | 
			
		||||
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(l = _find_labeller(dev, buf, §or)))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
 | 
			
		||||
		(*result)->sector = sector;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -305,7 +307,7 @@ int label_write(struct device *dev, struct label *label)
 | 
			
		||||
 | 
			
		||||
	memset(buf, 0, LABEL_SIZE);
 | 
			
		||||
 | 
			
		||||
	strncpy(lh->id, LABEL_ID, sizeof(lh->id));
 | 
			
		||||
	strncpy((char *)lh->id, LABEL_ID, sizeof(lh->id));
 | 
			
		||||
	lh->sector_xl = xlate64(label->sector);
 | 
			
		||||
	lh->offset_xl = xlate32(sizeof(*lh));
 | 
			
		||||
 | 
			
		||||
@@ -335,18 +337,35 @@ int label_write(struct device *dev, struct label *label)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unused */
 | 
			
		||||
int label_verify(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct labeller *l;
 | 
			
		||||
	char buf[LABEL_SIZE];
 | 
			
		||||
	uint64_t sector;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(l = _find_labeller(dev, buf, §or))) {
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
		if ((info = info_from_pvid(dev->pvid)))
 | 
			
		||||
			lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
 | 
			
		||||
						      0, NULL);
 | 
			
		||||
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ((l->ops->verify) ? l->ops->verify(l, buf, sector) : 1);
 | 
			
		||||
	if (!(l = _find_labeller(dev, buf, §or)))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void label_destroy(struct label *label)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,11 +28,11 @@ struct labeller;
 | 
			
		||||
 | 
			
		||||
/* On disk - 32 bytes */
 | 
			
		||||
struct label_header {
 | 
			
		||||
	uint8_t id[8];		/* LABELONE */
 | 
			
		||||
	int8_t id[8];		/* LABELONE */
 | 
			
		||||
	uint64_t sector_xl;	/* Sector number of this label */
 | 
			
		||||
	uint32_t crc_xl;	/* From next field to end of sector */
 | 
			
		||||
	uint32_t offset_xl;	/* Offset from start of struct to contents */
 | 
			
		||||
	uint8_t type[8];	/* LVM2 001 */
 | 
			
		||||
	int8_t type[8];		/* LVM2 001 */
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
/* In core */
 | 
			
		||||
 
 | 
			
		||||
@@ -256,7 +256,7 @@ static int _cluster_request(char cmd, const char *node, void *data, int len,
 | 
			
		||||
		strcpy(rarray[i].node, inptr);
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
 | 
			
		||||
		rarray[i].status = *(int *) inptr;
 | 
			
		||||
		memcpy(&rarray[i].status, inptr, sizeof(int));
 | 
			
		||||
		inptr += sizeof(int);
 | 
			
		||||
 | 
			
		||||
		rarray[i].response = dm_malloc(strlen(inptr) + 1);
 | 
			
		||||
@@ -330,6 +330,15 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
 | 
			
		||||
	args[0] = flags & 0x7F; /* Maskoff lock flags */
 | 
			
		||||
	args[1] = flags & 0xC0; /* Bitmap flags */
 | 
			
		||||
 | 
			
		||||
	if (partial_mode())
 | 
			
		||||
		args[1] |= LCK_PARTIAL_MODE;
 | 
			
		||||
 | 
			
		||||
	if (mirror_in_sync())
 | 
			
		||||
		args[1] |= LCK_MIRROR_NOSYNC_MODE;
 | 
			
		||||
 | 
			
		||||
	if (dmeventd_register_mode())
 | 
			
		||||
		args[1] |= LCK_DMEVENTD_REGISTER_MODE;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * VG locks are just that: locks, and have no side effects
 | 
			
		||||
	 * so we only need to do them on the local node because all
 | 
			
		||||
@@ -383,14 +392,15 @@ int lock_resource(struct cmd_context *cmd, const char *resource, int flags)
 | 
			
		||||
	int cluster_cmd = 0;
 | 
			
		||||
 | 
			
		||||
	assert(strlen(resource) < sizeof(lockname));
 | 
			
		||||
	assert(resource);
 | 
			
		||||
 | 
			
		||||
	switch (flags & LCK_SCOPE_MASK) {
 | 
			
		||||
	case LCK_VG:
 | 
			
		||||
		/* If the VG name is empty then lock the unused PVs */
 | 
			
		||||
		if (!resource || !*resource)
 | 
			
		||||
			lvm_snprintf(lockname, sizeof(lockname), "P_orphans");
 | 
			
		||||
		if (!*resource)
 | 
			
		||||
			dm_snprintf(lockname, sizeof(lockname), "P_orphans");
 | 
			
		||||
		else
 | 
			
		||||
			lvm_snprintf(lockname, sizeof(lockname), "V_%s",
 | 
			
		||||
			dm_snprintf(lockname, sizeof(lockname), "V_%s",
 | 
			
		||||
				     resource);
 | 
			
		||||
 | 
			
		||||
		cluster_cmd = CLVMD_CMD_LOCK_VG;
 | 
			
		||||
@@ -442,7 +452,7 @@ void reset_locking(void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CLUSTER_LOCKING_INTERNAL
 | 
			
		||||
int init_cluster_locking(struct locking_type *locking, struct config_tree *cft)
 | 
			
		||||
int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	locking->lock_resource = _lock_resource;
 | 
			
		||||
	locking->fin_locking = _locking_end;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
#include "locking_types.h"
 | 
			
		||||
#include "defaults.h"
 | 
			
		||||
#include "sharedlib.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
 | 
			
		||||
static void *_locking_lib = NULL;
 | 
			
		||||
static void (*_reset_fn) (void) = NULL;
 | 
			
		||||
@@ -55,7 +56,7 @@ static void _reset_external_locking(void)
 | 
			
		||||
		_reset_fn();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int init_external_locking(struct locking_type *locking, struct config_tree *cft)
 | 
			
		||||
int init_external_locking(struct locking_type *locking, struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	const char *libname;
 | 
			
		||||
 | 
			
		||||
@@ -69,10 +70,10 @@ int init_external_locking(struct locking_type *locking, struct config_tree *cft)
 | 
			
		||||
	locking->reset_locking = _reset_external_locking;
 | 
			
		||||
	locking->flags = 0;
 | 
			
		||||
 | 
			
		||||
	libname = find_config_str(cft->root, "global/locking_library",
 | 
			
		||||
				  DEFAULT_LOCKING_LIB);
 | 
			
		||||
	libname = find_config_tree_str(cmd, "global/locking_library",
 | 
			
		||||
				       DEFAULT_LOCKING_LIB);
 | 
			
		||||
 | 
			
		||||
	if (!(_locking_lib = load_shared_library(cft, libname, "locking"))) {
 | 
			
		||||
	if (!(_locking_lib = load_shared_library(cmd, libname, "locking", 1))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -90,5 +91,5 @@ int init_external_locking(struct locking_type *locking, struct config_tree *cft)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_verbose("Loaded external locking library %s", libname);
 | 
			
		||||
	return _init_fn(2, cft, &locking->flags);
 | 
			
		||||
	return _init_fn(2, cmd->cft, &locking->flags);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -105,7 +105,7 @@ static void _remove_ctrl_c_handler()
 | 
			
		||||
		log_sys_error("signal", "_remove_ctrl_c_handler");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _trap_ctrl_c(int sig)
 | 
			
		||||
static void _trap_ctrl_c(int sig __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	_remove_ctrl_c_handler();
 | 
			
		||||
	log_error("CTRL-c detected: giving up waiting for lock");
 | 
			
		||||
@@ -207,13 +207,15 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
 | 
			
		||||
{
 | 
			
		||||
	char lockfile[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	assert(resource);
 | 
			
		||||
 | 
			
		||||
	switch (flags & LCK_SCOPE_MASK) {
 | 
			
		||||
	case LCK_VG:
 | 
			
		||||
		if (!resource || !*resource)
 | 
			
		||||
			lvm_snprintf(lockfile, sizeof(lockfile),
 | 
			
		||||
		if (!*resource)
 | 
			
		||||
			dm_snprintf(lockfile, sizeof(lockfile),
 | 
			
		||||
				     "%s/P_orphans", _lock_dir);
 | 
			
		||||
		else
 | 
			
		||||
			lvm_snprintf(lockfile, sizeof(lockfile),
 | 
			
		||||
			dm_snprintf(lockfile, sizeof(lockfile),
 | 
			
		||||
				     "%s/V_%s", _lock_dir, resource);
 | 
			
		||||
 | 
			
		||||
		if (!_lock_file(lockfile, flags))
 | 
			
		||||
@@ -269,7 +271,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int init_file_locking(struct locking_type *locking, struct config_tree *cft)
 | 
			
		||||
int init_file_locking(struct locking_type *locking, struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	locking->lock_resource = _file_lock_resource;
 | 
			
		||||
	locking->reset_locking = _reset_file_locking;
 | 
			
		||||
@@ -277,8 +279,8 @@ int init_file_locking(struct locking_type *locking, struct config_tree *cft)
 | 
			
		||||
	locking->flags = 0;
 | 
			
		||||
 | 
			
		||||
	/* Get lockfile directory from config file */
 | 
			
		||||
	strncpy(_lock_dir, find_config_str(cft->root, "global/locking_dir",
 | 
			
		||||
					   DEFAULT_LOCK_DIR),
 | 
			
		||||
	strncpy(_lock_dir, find_config_tree_str(cmd, "global/locking_dir",
 | 
			
		||||
						DEFAULT_LOCK_DIR),
 | 
			
		||||
		sizeof(_lock_dir));
 | 
			
		||||
 | 
			
		||||
	if (!create_dir(_lock_dir))
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "defaults.h"
 | 
			
		||||
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
@@ -33,7 +34,7 @@ static int _vg_lock_count = 0;		/* Number of locks held */
 | 
			
		||||
static int _vg_write_lock_held = 0;	/* VG write lock held? */
 | 
			
		||||
static int _signals_blocked = 0;
 | 
			
		||||
 | 
			
		||||
static void _block_signals(int flags)
 | 
			
		||||
static void _block_signals(int flags __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	sigset_t set;
 | 
			
		||||
 | 
			
		||||
@@ -102,7 +103,7 @@ void reset_locking(void)
 | 
			
		||||
		_unblock_signals();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void _update_vg_lock_count(int flags)
 | 
			
		||||
static void _update_vg_lock_count(int flags)
 | 
			
		||||
{
 | 
			
		||||
	if ((flags & LCK_SCOPE_MASK) != LCK_VG)
 | 
			
		||||
		return;
 | 
			
		||||
@@ -122,36 +123,43 @@ static inline void _update_vg_lock_count(int flags)
 | 
			
		||||
/*
 | 
			
		||||
 * Select a locking type
 | 
			
		||||
 */
 | 
			
		||||
int init_locking(int type, struct config_tree *cft)
 | 
			
		||||
int init_locking(int type, struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	init_lockingfailed(0);
 | 
			
		||||
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		init_no_locking(&_locking, cft);
 | 
			
		||||
		init_no_locking(&_locking, cmd);
 | 
			
		||||
		log_print("WARNING: Locking disabled. Be careful! "
 | 
			
		||||
			  "This could corrupt your metadata.");
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	case 1:
 | 
			
		||||
		if (!init_file_locking(&_locking, cft))
 | 
			
		||||
		log_very_verbose("File-based locking selected.");
 | 
			
		||||
		if (!init_file_locking(&_locking, cmd))
 | 
			
		||||
			break;
 | 
			
		||||
		log_very_verbose("File-based locking enabled.");
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	case 2:
 | 
			
		||||
		if (!init_external_locking(&_locking, cft))
 | 
			
		||||
		if (!cmd->is_static) {
 | 
			
		||||
			log_very_verbose("External locking selected.");
 | 
			
		||||
			if (!init_external_locking(&_locking, cmd))
 | 
			
		||||
				break;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
		if (!find_config_tree_int(cmd, "locking/fallback_to_clustered_locking",
 | 
			
		||||
					  DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING))
 | 
			
		||||
			break;
 | 
			
		||||
		log_very_verbose("External locking enabled.");
 | 
			
		||||
		return 1;
 | 
			
		||||
		log_very_verbose("Falling back to clustered locking.");
 | 
			
		||||
		/* Fall through */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CLUSTER_LOCKING_INTERNAL
 | 
			
		||||
	case 3:
 | 
			
		||||
		if (!init_cluster_locking(&_locking, cft))
 | 
			
		||||
		log_very_verbose("Cluster locking selected.");
 | 
			
		||||
		if (!init_cluster_locking(&_locking, cmd))
 | 
			
		||||
			break;
 | 
			
		||||
		log_very_verbose("Cluster locking enabled.");
 | 
			
		||||
		return 1;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -160,13 +168,23 @@ int init_locking(int type, struct config_tree *cft)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((type == 2 || type == 3) &&
 | 
			
		||||
            find_config_tree_int(cmd, "locking/fallback_to_local_locking",
 | 
			
		||||
				 DEFAULT_FALLBACK_TO_LOCAL_LOCKING)) {
 | 
			
		||||
		log_print("WARNING: Falling back to local file-based locking.");
 | 
			
		||||
		log_print("Volume Groups with the clustered attribute will "
 | 
			
		||||
			  "be inaccessible.");
 | 
			
		||||
		if (init_file_locking(&_locking, cmd))
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!ignorelockingfailure())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* FIXME Ensure only read ops are permitted */
 | 
			
		||||
	log_verbose("Locking disabled - only read operations permitted.");
 | 
			
		||||
 | 
			
		||||
	init_no_locking(&_locking, cft);
 | 
			
		||||
	init_no_locking(&_locking, cmd);
 | 
			
		||||
	init_lockingfailed(1);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -189,7 +207,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
 | 
			
		||||
	if (!*vgname)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
 | 
			
		||||
	if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
 | 
			
		||||
			 vgname) < 0) {
 | 
			
		||||
		log_error("LVM1 proc VG pathname too long for %s", vgname);
 | 
			
		||||
		return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,10 +13,13 @@
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_LOCKING_H
 | 
			
		||||
#define _LVM_LOCKING_H
 | 
			
		||||
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
int init_locking(int type, struct config_tree *cf);
 | 
			
		||||
int init_locking(int type, struct cmd_context *cmd);
 | 
			
		||||
void fin_locking(void);
 | 
			
		||||
void reset_locking(void);
 | 
			
		||||
int vg_write_lock_held(void);
 | 
			
		||||
@@ -67,6 +70,14 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
 | 
			
		||||
#define LCK_LOCAL	0x00000040	/* Don't propagate to other nodes */
 | 
			
		||||
#define LCK_CLUSTER_VG	0x00000080	/* VG is clustered */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Additional lock bits for cluster communication
 | 
			
		||||
 */
 | 
			
		||||
#define LCK_PARTIAL_MODE	0x00000001	/* Running in partial mode */
 | 
			
		||||
#define LCK_MIRROR_NOSYNC_MODE	0x00000002	/* Mirrors don't require sync */
 | 
			
		||||
#define LCK_DMEVENTD_REGISTER_MODE	0x00000004	/* Register with dmeventd */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Common combinations
 | 
			
		||||
 */
 | 
			
		||||
@@ -104,3 +115,4 @@ int suspend_lvs(struct cmd_context *cmd, struct list *lvs);
 | 
			
		||||
int resume_lvs(struct cmd_context *cmd, struct list *lvs);
 | 
			
		||||
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -36,10 +36,10 @@ struct locking_type {
 | 
			
		||||
/*
 | 
			
		||||
 * Locking types
 | 
			
		||||
 */
 | 
			
		||||
int init_no_locking(struct locking_type *locking, struct config_tree *cf);
 | 
			
		||||
int init_no_locking(struct locking_type *locking, struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
int init_file_locking(struct locking_type *locking, struct config_tree *cf);
 | 
			
		||||
int init_file_locking(struct locking_type *locking, struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
int init_external_locking(struct locking_type *locking, struct config_tree *cf);
 | 
			
		||||
int init_external_locking(struct locking_type *locking, struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
int init_cluster_locking(struct locking_type *locking, struct config_tree *cf);
 | 
			
		||||
int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd);
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user