mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-03 08:23:48 +03:00 
			
		
		
		
	Compare commits
	
		
			279 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					14dbd220c2 | ||
| 
						 | 
					babc890c59 | ||
| 
						 | 
					6f7b47ff40 | ||
| 
						 | 
					3991f03202 | ||
| 
						 | 
					27271d5da7 | ||
| 
						 | 
					627312e1de | ||
| 
						 | 
					bfc9550e4e | ||
| 
						 | 
					2b9c21268b | ||
| 
						 | 
					3dce4ed6f1 | ||
| 
						 | 
					0f16c2ea87 | ||
| 
						 | 
					9a635f0686 | ||
| 
						 | 
					6a0d4b2baa | ||
| 
						 | 
					ac017098ad | ||
| 
						 | 
					98fef2640d | ||
| 
						 | 
					8bb66e133a | ||
| 
						 | 
					68a582901d | ||
| 
						 | 
					c094f4c06e | ||
| 
						 | 
					f7ca545544 | ||
| 
						 | 
					69b4716894 | ||
| 
						 | 
					7e44dcc5bf | ||
| 
						 | 
					ab9843e183 | ||
| 
						 | 
					01af706ade | ||
| 
						 | 
					9ebdb08e99 | ||
| 
						 | 
					a74ffe25d9 | ||
| 
						 | 
					7f95e27707 | ||
| 
						 | 
					1facf5bba3 | ||
| 
						 | 
					03d77009eb | ||
| 
						 | 
					8afd6812b5 | ||
| 
						 | 
					ec9ad78fcf | ||
| 
						 | 
					6f4e93dc90 | ||
| 
						 | 
					a38e43862d | ||
| 
						 | 
					39294bb037 | ||
| 
						 | 
					edc5e59b78 | ||
| 
						 | 
					c00fd9fd37 | ||
| 
						 | 
					b3e621dd9f | ||
| 
						 | 
					6e8c49b978 | ||
| 
						 | 
					398d57133d | ||
| 
						 | 
					16521a6feb | ||
| 
						 | 
					3ca0b37a3e | ||
| 
						 | 
					cf2ec1229d | ||
| 
						 | 
					fe9b1e5f9b | ||
| 
						 | 
					f5b96ddf01 | ||
| 
						 | 
					2fe076fb27 | ||
| 
						 | 
					99249cff04 | ||
| 
						 | 
					0cdf7b0613 | ||
| 
						 | 
					90bcf4f157 | ||
| 
						 | 
					03c3ec4e12 | ||
| 
						 | 
					ca9bb20d64 | ||
| 
						 | 
					c6bc078fd9 | ||
| 
						 | 
					2f4bd6e52c | ||
| 
						 | 
					2affe53727 | ||
| 
						 | 
					09654d7dd8 | ||
| 
						 | 
					90a4e37815 | ||
| 
						 | 
					60889c0c79 | ||
| 
						 | 
					20f3408d96 | ||
| 
						 | 
					e9d86789db | ||
| 
						 | 
					5152b7c66c | ||
| 
						 | 
					c494c4e12c | ||
| 
						 | 
					54d58ccb7e | ||
| 
						 | 
					714a77bfbe | ||
| 
						 | 
					d48f8bf5cc | ||
| 
						 | 
					99d97754a6 | ||
| 
						 | 
					b9d437de2a | ||
| 
						 | 
					11403f2019 | ||
| 
						 | 
					1ca102d639 | ||
| 
						 | 
					339ba55111 | ||
| 
						 | 
					14ae59885a | ||
| 
						 | 
					e3ef54f99b | ||
| 
						 | 
					001901f9a9 | ||
| 
						 | 
					6a98f60e2e | ||
| 
						 | 
					6f2e24c47d | ||
| 
						 | 
					aafa368923 | ||
| 
						 | 
					eb783cab4c | ||
| 
						 | 
					6533aa865a | ||
| 
						 | 
					f1a1e1bc07 | ||
| 
						 | 
					953f4838dd | ||
| 
						 | 
					130b892d34 | ||
| 
						 | 
					6ad525c77e | ||
| 
						 | 
					d0ca74ad27 | ||
| 
						 | 
					9806f69b4d | ||
| 
						 | 
					34d9b5e3d7 | ||
| 
						 | 
					3bf5189d86 | ||
| 
						 | 
					12e5b0681b | ||
| 
						 | 
					8c0285d608 | ||
| 
						 | 
					36558fa3b8 | ||
| 
						 | 
					235f940cde | ||
| 
						 | 
					803d61fcbc | ||
| 
						 | 
					ffbd7d8de4 | ||
| 
						 | 
					4ed924d7c7 | ||
| 
						 | 
					798dc9948b | ||
| 
						 | 
					13515f7ee4 | ||
| 
						 | 
					ef80824c26 | ||
| 
						 | 
					c8503fd65e | ||
| 
						 | 
					b3c454fb1c | ||
| 
						 | 
					1d7723e873 | ||
| 
						 | 
					77100b2365 | ||
| 
						 | 
					259a788134 | ||
| 
						 | 
					39511455cb | ||
| 
						 | 
					b04c16178e | ||
| 
						 | 
					49a959c06e | ||
| 
						 | 
					096a8932b4 | ||
| 
						 | 
					e39e66df93 | ||
| 
						 | 
					513633f49a | ||
| 
						 | 
					eb3740daaf | ||
| 
						 | 
					f7947b148a | ||
| 
						 | 
					9a2a702f3f | ||
| 
						 | 
					c65d95bf29 | ||
| 
						 | 
					753a5edc4f | ||
| 
						 | 
					0b3f853c2d | ||
| 
						 | 
					3527fcf1d5 | ||
| 
						 | 
					4544a89c7a | ||
| 
						 | 
					ffeae9005e | ||
| 
						 | 
					47217bcfb7 | ||
| 
						 | 
					80ff58b57a | ||
| 
						 | 
					d15dd368f1 | ||
| 
						 | 
					8a2ec32bd8 | ||
| 
						 | 
					410496ed52 | ||
| 
						 | 
					b7b07552e5 | ||
| 
						 | 
					44486e80d9 | ||
| 
						 | 
					7890c527d8 | ||
| 
						 | 
					2c82ab79a7 | ||
| 
						 | 
					e3ebe5fc53 | ||
| 
						 | 
					0ac430892e | ||
| 
						 | 
					a7739c942c | ||
| 
						 | 
					24581482d0 | ||
| 
						 | 
					0571c3b453 | ||
| 
						 | 
					73e7f5a0b0 | ||
| 
						 | 
					20c0adb961 | ||
| 
						 | 
					a01e03562f | ||
| 
						 | 
					d184ed0130 | ||
| 
						 | 
					089e1c2aee | ||
| 
						 | 
					ebab0e91ee | ||
| 
						 | 
					858a2b1b88 | ||
| 
						 | 
					02bd59827c | ||
| 
						 | 
					4991428510 | ||
| 
						 | 
					3b245f5dc1 | ||
| 
						 | 
					c9c81da901 | ||
| 
						 | 
					4919cdc3fb | ||
| 
						 | 
					e90e1f577d | ||
| 
						 | 
					afd4284403 | ||
| 
						 | 
					150b350d31 | ||
| 
						 | 
					2818520bd1 | ||
| 
						 | 
					2819952292 | ||
| 
						 | 
					5af71af51c | ||
| 
						 | 
					07a55b51df | ||
| 
						 | 
					66dd68b49d | ||
| 
						 | 
					9812657777 | ||
| 
						 | 
					0b09312fc6 | ||
| 
						 | 
					d0a7ac6b74 | ||
| 
						 | 
					ff9a238fbd | ||
| 
						 | 
					359fffa5f1 | ||
| 
						 | 
					5bf92ced1a | ||
| 
						 | 
					340bcc7b45 | ||
| 
						 | 
					ef03742bd4 | ||
| 
						 | 
					20431ec16d | ||
| 
						 | 
					becba8157b | ||
| 
						 | 
					51fd3bb0eb | ||
| 
						 | 
					4bbd3acb4e | ||
| 
						 | 
					3bc930ea7b | ||
| 
						 | 
					d1b26f8e86 | ||
| 
						 | 
					fdf15caaff | ||
| 
						 | 
					c7b4a53c0b | ||
| 
						 | 
					af78dc0308 | ||
| 
						 | 
					5ad39493c4 | ||
| 
						 | 
					61f597b408 | ||
| 
						 | 
					2162825240 | ||
| 
						 | 
					2b780e70d1 | ||
| 
						 | 
					a3823f818e | ||
| 
						 | 
					1f7c47bcaf | ||
| 
						 | 
					ec53c365a2 | ||
| 
						 | 
					793ad1f2d4 | ||
| 
						 | 
					9bc733b76c | ||
| 
						 | 
					21b28f0217 | ||
| 
						 | 
					d3e23caa52 | ||
| 
						 | 
					9e7518de67 | ||
| 
						 | 
					679f0047aa | ||
| 
						 | 
					d77d5ce14b | ||
| 
						 | 
					33ec22a2af | ||
| 
						 | 
					353053225f | ||
| 
						 | 
					b7f3d6f7f7 | ||
| 
						 | 
					e34577499d | ||
| 
						 | 
					4cf8960c0c | ||
| 
						 | 
					1f93ea0675 | ||
| 
						 | 
					25b705c3a8 | ||
| 
						 | 
					0725588731 | ||
| 
						 | 
					fc5c61cc8b | ||
| 
						 | 
					ac282e63c6 | ||
| 
						 | 
					c3941941ce | ||
| 
						 | 
					46cdd53323 | ||
| 
						 | 
					3ff3e302c3 | ||
| 
						 | 
					f2ceecf95c | ||
| 
						 | 
					9314c7c881 | ||
| 
						 | 
					54abb2c572 | ||
| 
						 | 
					8fa3bdd025 | ||
| 
						 | 
					5e7a308528 | ||
| 
						 | 
					7952177786 | ||
| 
						 | 
					9afbe49c84 | ||
| 
						 | 
					9f06ba2db3 | ||
| 
						 | 
					fe55bfddcf | ||
| 
						 | 
					c0842e6444 | ||
| 
						 | 
					3fed20d06a | ||
| 
						 | 
					5e8f2e2c04 | ||
| 
						 | 
					e4df99ea84 | ||
| 
						 | 
					b3276f5f11 | ||
| 
						 | 
					32667ca256 | ||
| 
						 | 
					bed122a170 | ||
| 
						 | 
					14adc9b875 | ||
| 
						 | 
					a8778bbc5a | ||
| 
						 | 
					a54e641f44 | ||
| 
						 | 
					5c99efe87a | ||
| 
						 | 
					7da1d731ff | ||
| 
						 | 
					af9828e819 | ||
| 
						 | 
					7a27136142 | ||
| 
						 | 
					012ad2d423 | ||
| 
						 | 
					ef3bdbf4da | ||
| 
						 | 
					b3bb698f7b | ||
| 
						 | 
					1ed5d1e4c1 | ||
| 
						 | 
					bdee01a03d | ||
| 
						 | 
					458f7376d7 | ||
| 
						 | 
					cb3a00e027 | ||
| 
						 | 
					482eb1f3fb | ||
| 
						 | 
					6e0f638f5e | ||
| 
						 | 
					bab349047d | ||
| 
						 | 
					28ea6b8de8 | ||
| 
						 | 
					9d51bbdae8 | ||
| 
						 | 
					d622f79533 | ||
| 
						 | 
					04c8515ad1 | ||
| 
						 | 
					53bc4251d1 | ||
| 
						 | 
					a5a751f02f | ||
| 
						 | 
					66ed5f82c4 | ||
| 
						 | 
					c802a9e6aa | ||
| 
						 | 
					880f210946 | ||
| 
						 | 
					4f9f7eb6a6 | ||
| 
						 | 
					f910c4a8e7 | ||
| 
						 | 
					529686d965 | ||
| 
						 | 
					84dfd1536f | ||
| 
						 | 
					85dedc324c | ||
| 
						 | 
					d639237411 | ||
| 
						 | 
					449aaf75f1 | ||
| 
						 | 
					b1fda66caa | ||
| 
						 | 
					66a8e90fd9 | ||
| 
						 | 
					37b487d191 | ||
| 
						 | 
					6c59fe3577 | ||
| 
						 | 
					1cbb70c992 | ||
| 
						 | 
					e06b39f882 | ||
| 
						 | 
					2602b1493e | ||
| 
						 | 
					989d14502d | ||
| 
						 | 
					f78a550282 | ||
| 
						 | 
					54a1abb284 | ||
| 
						 | 
					97b492a8e2 | ||
| 
						 | 
					0873bd14a9 | ||
| 
						 | 
					eff6ba429a | ||
| 
						 | 
					8c18064be4 | ||
| 
						 | 
					44a1ac0cf3 | ||
| 
						 | 
					28dc8d88dd | ||
| 
						 | 
					2c0c2b64ba | ||
| 
						 | 
					bd3e0f5248 | ||
| 
						 | 
					cd52d98938 | ||
| 
						 | 
					894c70e7f8 | ||
| 
						 | 
					51d70c2edd | ||
| 
						 | 
					7d4b355240 | ||
| 
						 | 
					3b56193b98 | ||
| 
						 | 
					b16045b57d | ||
| 
						 | 
					9e8b0fca5b | ||
| 
						 | 
					35cf1b3b5b | ||
| 
						 | 
					83f788af57 | ||
| 
						 | 
					2ffe378d3f | ||
| 
						 | 
					38b33a4a5e | ||
| 
						 | 
					60bf9ed0a0 | ||
| 
						 | 
					16adf4de1b | ||
| 
						 | 
					80de983023 | ||
| 
						 | 
					8703ca623f | ||
| 
						 | 
					286253a73f | ||
| 
						 | 
					bd806a41df | ||
| 
						 | 
					b89c4e9002 | ||
| 
						 | 
					6dbf31c0c3 | ||
| 
						 | 
					060c45d8a1 | ||
| 
						 | 
					33d3e82e4d | ||
| 
						 | 
					4bb074514d | 
							
								
								
									
										0
									
								
								CONTRIBUTORS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								CONTRIBUTORS
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										39
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								Makefile.in
									
									
									
									
									
								
							@@ -1,49 +1,52 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001 Sistina Software
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This LVM library is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the terms of the GNU Library General Public
 | 
			
		||||
# License as published by the Free Software Foundation; either
 | 
			
		||||
# version 2 of the License, or (at your option) any later version.
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
#
 | 
			
		||||
# This LVM library is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
# Library General Public License for more details.
 | 
			
		||||
# 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 Library General Public
 | 
			
		||||
# License along with this LVM library; if not, write to the Free
 | 
			
		||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 | 
			
		||||
# MA 02111-1307, USA
 | 
			
		||||
# 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 = include man 
 | 
			
		||||
SUBDIRS = doc include man 
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
  SUBDIRS += po
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
SUBDIRS += lib tools
 | 
			
		||||
SUBDIRS += lib tools daemons
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
  SUBDIRS += lib/format1 \
 | 
			
		||||
  SUBDIRS += daemons/clvmd \
 | 
			
		||||
	     lib/format1 \
 | 
			
		||||
	     lib/format_pool \
 | 
			
		||||
	     lib/locking \
 | 
			
		||||
	     lib/mirror \
 | 
			
		||||
	     lib/snapshot \
 | 
			
		||||
	     po \
 | 
			
		||||
	     test/mm test/device test/format1 test/regex test/filters
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include make.tmpl
 | 
			
		||||
 | 
			
		||||
daemons: lib
 | 
			
		||||
lib: include
 | 
			
		||||
tools: lib
 | 
			
		||||
po: lib tools
 | 
			
		||||
po: tools daemons
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
lib.pofile: include.pofile
 | 
			
		||||
tools.pofile: lib.pofile
 | 
			
		||||
po.pofile: lib.pofile tools.pofile
 | 
			
		||||
daemons.pofile: lib.pofile
 | 
			
		||||
po.pofile: tools.pofile daemons.pofile
 | 
			
		||||
pofile: po.pofile
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								README
									
									
									
									
									
								
							@@ -9,8 +9,8 @@ Installation instructions are in INSTALL.
 | 
			
		||||
There is no warranty - see COPYING and COPYING.LIB.
 | 
			
		||||
 | 
			
		||||
Tarballs are available from:
 | 
			
		||||
  ftp://ftp.sistina.com/pub/LVM2/tools/
 | 
			
		||||
  ftp://ftp.sistina.com/pub/LVM2/device-mapper/
 | 
			
		||||
  ftp://sources.redhat.com/pub/lvm2/
 | 
			
		||||
  ftp://sources.redhat.com/pub/dm/
 | 
			
		||||
 | 
			
		||||
To access the CVS tree use:
 | 
			
		||||
  cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										253
									
								
								WHATS_NEW
									
									
									
									
									
								
							
							
						
						
									
										253
									
								
								WHATS_NEW
									
									
									
									
									
								
							@@ -1,3 +1,256 @@
 | 
			
		||||
Version 2.00.32 - 22nd December 2004
 | 
			
		||||
====================================
 | 
			
		||||
  Drop static/dl restriction for now.
 | 
			
		||||
  Fix an error fprintf.
 | 
			
		||||
  Fix vgdisplay -s. Breaks (undocumented) lvs/pvs/vgs -s instead for now.
 | 
			
		||||
  Fix device reference counting on re-opens.
 | 
			
		||||
  Ignore sysfs symlinks when DT_UNKNOWN.
 | 
			
		||||
  Add clvmd init script for RHEL4.
 | 
			
		||||
  Skip devices that are too small to be PVs.
 | 
			
		||||
  Fix pvchange -x segfault with lvm2-format orphan.
 | 
			
		||||
  Cope with empty msdos partition tables.
 | 
			
		||||
  Add CONTRIBUTORS file.
 | 
			
		||||
 | 
			
		||||
Version 2.00.31 - 12th December 2004
 | 
			
		||||
====================================
 | 
			
		||||
  Reopen RO file descriptors RW if necessary.
 | 
			
		||||
 | 
			
		||||
Version 2.00.30 - 10th December 2004
 | 
			
		||||
====================================
 | 
			
		||||
  Additional device-handling debug messages.
 | 
			
		||||
  Additional verbosity level -vvvv includes line numbers and backtraces.
 | 
			
		||||
  Verbose messages now go to stderr not stdout.
 | 
			
		||||
  Close any stray file descriptors before starting.
 | 
			
		||||
  Refine partitionable checks for certain device types.
 | 
			
		||||
  Allow devices/types to override built-ins.
 | 
			
		||||
  Fix lvreduce man page .i->.I
 | 
			
		||||
  Fix vgsplit man page title.
 | 
			
		||||
  Fix clvmd man makefile.
 | 
			
		||||
  Extend dev_open logging.
 | 
			
		||||
  Make clvmd_fix_conf.sh UNDOable.
 | 
			
		||||
 | 
			
		||||
Version 2.00.29 - 27th November 2004
 | 
			
		||||
====================================
 | 
			
		||||
  xlate compilation fix.
 | 
			
		||||
 | 
			
		||||
Version 2.00.28 - 27th November 2004
 | 
			
		||||
====================================
 | 
			
		||||
  Fix partition table & md signature detection.
 | 
			
		||||
  Minor configure/makefile tidy.
 | 
			
		||||
  Export version.h from tools for clvmd.
 | 
			
		||||
 | 
			
		||||
Version 2.00.27 - 24th November 2004
 | 
			
		||||
====================================
 | 
			
		||||
  Trap large memory allocation requests.
 | 
			
		||||
  Fix to partition table detection code.
 | 
			
		||||
  Improve filter debug mesgs.
 | 
			
		||||
  Make clvmd_fix_conf.sh UNDOable
 | 
			
		||||
 | 
			
		||||
Version 2.00.26 - 23rd November 2004
 | 
			
		||||
====================================
 | 
			
		||||
  Improve pool debugging stats.
 | 
			
		||||
  Detect partition table signature.
 | 
			
		||||
  pvcreate wipes md superblocks. (With --uuid or --restorefile it prompts.)
 | 
			
		||||
  Separate out md superblock detection code.
 | 
			
		||||
  Prevent snapshot origin resizing.
 | 
			
		||||
  Improve a vgremove error message.
 | 
			
		||||
  Update some man pages.
 | 
			
		||||
  Allow y/n with -ae args (exclusive activation).
 | 
			
		||||
  Fixes to lvcreate vgname parsing.
 | 
			
		||||
  Fix dm_name string size calculation.
 | 
			
		||||
  Improve clvmd error reporting during startup.
 | 
			
		||||
  Make clvmd cope with large gaps in node numbers IDs.
 | 
			
		||||
  Make clvmd initialisation cope better with debugging output.
 | 
			
		||||
  Tidy clvmd socket callbacks so all work happens outside main loop.
 | 
			
		||||
  clvmd -V now displays lvm version too.
 | 
			
		||||
  Add optional gulm build for clvmd
 | 
			
		||||
 | 
			
		||||
Version 2.00.25 - 29th September 2004
 | 
			
		||||
=====================================
 | 
			
		||||
  Fix return code from rm_link for vgmknodes.
 | 
			
		||||
  Make clvmd LV hash table thread-safe.
 | 
			
		||||
  Fix clvmd locking so it will lock out multiple users on the same node.
 | 
			
		||||
  Fix clvmd VG locking to it can cope with multiple VG locks.
 | 
			
		||||
  Remove spurious trailing dot in lvreduce man page.
 | 
			
		||||
  Fix vgremove locking.
 | 
			
		||||
 | 
			
		||||
Version 2.00.24 - 16th September 2004
 | 
			
		||||
=====================================
 | 
			
		||||
  Fix pool_empty so it really does empty the memory pool.
 | 
			
		||||
  Rename old segtypes files to segtype.
 | 
			
		||||
  Some fixes to memory debugging code.
 | 
			
		||||
  Exclude internal commands formats & segtypes from install.
 | 
			
		||||
 | 
			
		||||
Version 2.00.23 - 15th September 2004
 | 
			
		||||
=====================================
 | 
			
		||||
  Export dm name build & split functions.
 | 
			
		||||
  Use O_NOATIME on devices if available.
 | 
			
		||||
  Write log message when each segtype/format gets initialised.
 | 
			
		||||
  New commands 'segtypes' and 'formats'.
 | 
			
		||||
  Suppress pvmove abort message in test mode.
 | 
			
		||||
  Improve pvcreate/remove device not found error message.
 | 
			
		||||
  Allow pvmove to move data within the same PV.
 | 
			
		||||
  Describe how pvmove works on man page.
 | 
			
		||||
  Test for incompatible format/segtype combinations in lv_extend.
 | 
			
		||||
  Fix lvchange example on man page.
 | 
			
		||||
 | 
			
		||||
Version 2.00.22 - 3rd September 2004
 | 
			
		||||
====================================
 | 
			
		||||
  Fix /dev/vgname perms.
 | 
			
		||||
  Restructure xlate.h.
 | 
			
		||||
  Add clvmd man page.
 | 
			
		||||
 | 
			
		||||
Version 2.00.21 - 19th August 2004
 | 
			
		||||
==================================
 | 
			
		||||
  Update cnxman-socket.h from cman.
 | 
			
		||||
  Recognise iseries/vd devices.
 | 
			
		||||
  Use 'make install_cluster' to install cluster extensions only.
 | 
			
		||||
  Cope with DT_UNKNOWN in sysfs.
 | 
			
		||||
  Fix extents_moved metadata size comment.
 | 
			
		||||
  Remove duplicate line in pvremove help text.
 | 
			
		||||
  Support variable mirror region size.
 | 
			
		||||
  Support PE ranges in pvmove source PV.
 | 
			
		||||
  Fixes to as-yet-unused LV segment splitting code.
 | 
			
		||||
  Change alloc_areas to pe_ranges and allow suppression of availability checks.
 | 
			
		||||
  Add dev_size column to pvs.
 | 
			
		||||
  Add report columns for in-kernel device number.
 | 
			
		||||
 | 
			
		||||
Version 2.00.20 - 3 July 2004
 | 
			
		||||
=============================
 | 
			
		||||
  More autoconf fixes.
 | 
			
		||||
  Fix device number handling for 2.6 kernels.
 | 
			
		||||
 | 
			
		||||
Version 2.00.19 - 29 June 2004
 | 
			
		||||
==============================
 | 
			
		||||
  Reduce severity of setlocale failure message.
 | 
			
		||||
  Recognise argv[0] "initrd-lvm" (pld-linux).
 | 
			
		||||
  Make -O2 configurable.
 | 
			
		||||
  Added --disable-selinux to configure script.
 | 
			
		||||
  LD_FLAGS->LDFLAGS & LD_DEPS->LDDEPS in configure script.
 | 
			
		||||
  Add init_debug to clvmd.
 | 
			
		||||
 | 
			
		||||
Version 2.00.18 - 24 June 2004
 | 
			
		||||
==============================
 | 
			
		||||
  Fix vgchange activation.
 | 
			
		||||
  Add cluster support.
 | 
			
		||||
 | 
			
		||||
Version 2.00.17 - 20 June 2004
 | 
			
		||||
==============================
 | 
			
		||||
  configure --enable-fsadm to try out fsadm.  fsadm is not tested yet.
 | 
			
		||||
  Display all filtered devices, not just PVs, with pvs -a.
 | 
			
		||||
  Fix sync_dir() when no / in filename
 | 
			
		||||
  vgcfgbackup -f accepts template with %s for VG name.
 | 
			
		||||
  Extend hash functions to handle non-null-terminated data.
 | 
			
		||||
  Add local activation support.
 | 
			
		||||
  Tidy relative paths in makefile includes.
 | 
			
		||||
  fsadm support for fsck and resizing - needs testing.
 | 
			
		||||
  Add read-only GFS pool support.
 | 
			
		||||
  Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
 | 
			
		||||
  Fix rounding of large diplayed sizes.
 | 
			
		||||
  Suppress decimal point when using units of sectors/bytes.
 | 
			
		||||
  Additional kernel target checks before pvmove & snapshot creation.
 | 
			
		||||
  Add i2o_block.
 | 
			
		||||
 | 
			
		||||
Version 2.00.16 - 24 May 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Set area_count within alloc_lv_segment.
 | 
			
		||||
  Remove error labels from lvresize.
 | 
			
		||||
  Fix a pvs error path.
 | 
			
		||||
  xxchange -ae for exclusive activation.
 | 
			
		||||
  Don't return non-zero status if there aren't any volume groups.
 | 
			
		||||
  Add --alloc argument to tools.
 | 
			
		||||
  Rename allocation policies to contiguous, normal, anywhere, inherit.
 | 
			
		||||
  nextfree becomes normal; anywhere isn't implemented yet.
 | 
			
		||||
  LV inherits allocation policy from VG. Defaults: LV - inherit; VG - normal
 | 
			
		||||
  Additional status character added to vgs to indicate allocation policy.
 | 
			
		||||
  Add reset_fn to external_locking.
 | 
			
		||||
  Ensure presence of virtual targets before attempting activating.
 | 
			
		||||
  Attempt to fix resizing of snapshot origins.
 | 
			
		||||
  Restructure lvresize, bringing it closer to lvcreate.
 | 
			
		||||
  A quick sanity check on vg_disk struct when read in.  More checks needed.
 | 
			
		||||
  Only include visible LVs in active/open counts.
 | 
			
		||||
  Add virtual segment types, zero and error.  A large sparse device can be
 | 
			
		||||
constructed as a writeable snapshot of a large zero segment.
 | 
			
		||||
  Add --type to lvcreate/resize.
 | 
			
		||||
  Push lv_create & alloc policy up to tool level.
 | 
			
		||||
  Fix pvdisplay return code.
 | 
			
		||||
  Detect invalid LV names in arg lists.
 | 
			
		||||
  Reporting uses line-at-a-time output.
 | 
			
		||||
  lvm2 format sets unlimited_vols format flag.
 | 
			
		||||
  Internal-only metadata flag support.
 | 
			
		||||
  Basic checking for presence of device-mapper targets.
 | 
			
		||||
  Separate out polldaemon.
 | 
			
		||||
  Revise internal locking semantics.
 | 
			
		||||
  Move find_pv_by_name to library.
 | 
			
		||||
  Rename move->copy.
 | 
			
		||||
  Add devices to segments report.
 | 
			
		||||
  Begin separating out segment code. There's a lot of change here.
 | 
			
		||||
  Compress any (obsolete) long LVM1 pvids encountered.
 | 
			
		||||
  Support for tagged config files.
 | 
			
		||||
  Don't abort operations if selinux present but disabled.
 | 
			
		||||
  Fix typo in configure which left HAVE_LIBDL unset.
 | 
			
		||||
 | 
			
		||||
Version 2.00.15 - 19 Apr 2004
 | 
			
		||||
=============================
 | 
			
		||||
  configure --with-owner= --with-group= to avoid -o and -g args to 'install'
 | 
			
		||||
 | 
			
		||||
Version 2.00.14 - 16 Apr 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Use 64-bit file functions by default.
 | 
			
		||||
 | 
			
		||||
Version 2.00.13 - 16 Apr 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Set devices/md_component_detection = 1 to ignore devices containing md
 | 
			
		||||
  superblocks. [Luca Berra]
 | 
			
		||||
  Ignore error setting selinux file context if fs doesn't support it.
 | 
			
		||||
 | 
			
		||||
Version 2.00.12 - 14 Apr 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Install a default lvm.conf into /etc/lvm if there isn't one already.
 | 
			
		||||
  Allow different installation dir for lvm.static (configure --staticdir=)
 | 
			
		||||
  Fix inverted selinux error check.
 | 
			
		||||
  Recognise power2 in /proc/devices.
 | 
			
		||||
  Fix counting in lvs_in_vg_opened. [It ignored devices open more than once.]
 | 
			
		||||
 | 
			
		||||
Version 2.00.11 - 8 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Set fallback_to_lvm1 in lvm.conf (or configure --enable-lvm1_fallback)
 | 
			
		||||
  to run lvm1 binaries if running a 2.4 kernel without device-mapper.
 | 
			
		||||
 | 
			
		||||
Version 2.00.10 - 7 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  More fixes for static build.
 | 
			
		||||
  Add basic selinux support.
 | 
			
		||||
  Fix sysfs detection.
 | 
			
		||||
 | 
			
		||||
Version 2.00.09 - 31 Mar 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Update copyright notices for Red Hat.
 | 
			
		||||
  Fix vgmknodes to remove dud /dev/mapper entries. (libdevmapper update reqd).
 | 
			
		||||
  Add LVM1-style colon output to vgdisplay.
 | 
			
		||||
  lvchange --refresh to reload active LVs.
 | 
			
		||||
  Add string display to memory leak dump.
 | 
			
		||||
  Add locking flags & memlock option.
 | 
			
		||||
  Add list_versions to library.
 | 
			
		||||
  Ignore open hidden LVs when checking if deactivation is OK.
 | 
			
		||||
  Suppress move percentage when device inactive.
 | 
			
		||||
  Add lv_info_by_lvid.
 | 
			
		||||
  Various tidy-ups to the build process.
 | 
			
		||||
  Rebaseline internal verbose level.
 | 
			
		||||
  Add --nolocking option for read operations if locking is failing.
 | 
			
		||||
  Add option to compile into a library.
 | 
			
		||||
  When compiled without libdevmapper, only print warning message once.
 | 
			
		||||
  Fix lvreduce PV extent calculations.
 | 
			
		||||
  Fix DESTDIR to work with configure path overrides.
 | 
			
		||||
  Always use / as config file separator & rename internal config file variables.
 | 
			
		||||
  Add support for tagging PV/VG/LVs and hosts.
 | 
			
		||||
  Fix rare bug in recognition of long cmdline argument forms.
 | 
			
		||||
  Add basic internationalisation infrastructure.
 | 
			
		||||
  Don't recurse symlinked dirs such as /dev/fd on 2.6 kernels.
 | 
			
		||||
  Update autoconf files.
 | 
			
		||||
  Add sysfs block device filtering for 2.6 kernels.
 | 
			
		||||
  Update refs for move to sources.redhat.com.
 | 
			
		||||
 | 
			
		||||
Friday 14th November 2003
 | 
			
		||||
=========================
 | 
			
		||||
Some bug fixes & minor enhancements, including:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										80
									
								
								WHATS_NEW_DM
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								WHATS_NEW_DM
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
Version 1.00.20 -
 | 
			
		||||
=============================
 | 
			
		||||
  Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
 | 
			
		||||
  Add --noheadings columns option for colon-separated dmsetup output.
 | 
			
		||||
  Support device referencing by uuid or major/minor.
 | 
			
		||||
  Warn if kernel data didn't fit in buffer.
 | 
			
		||||
  Fix a printf.
 | 
			
		||||
 | 
			
		||||
Version 1.00.19 - 3 July 2004
 | 
			
		||||
=============================
 | 
			
		||||
  More autoconf fixes.
 | 
			
		||||
  Fix a dmsetup newline.
 | 
			
		||||
  Fix device number handling for 2.6 kernels.
 | 
			
		||||
 | 
			
		||||
Version 1.00.18 - 20 Jun 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Fix a uuid free in libdm-iface.
 | 
			
		||||
  Fix a targets string size calc in driver.
 | 
			
		||||
  Add -c to dmsetup for column-based output.
 | 
			
		||||
  Add target message-passing ioctl.
 | 
			
		||||
 | 
			
		||||
Version 1.00.17 - 17 Apr 2004
 | 
			
		||||
=============================
 | 
			
		||||
  configure --with-owner= --with-group= to avoid -o and -g args to 'install'
 | 
			
		||||
  Fix library selinux linking.
 | 
			
		||||
 | 
			
		||||
Version 1.00.16 - 16 Apr 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Ignore error setting selinux file context if fs doesn't support it.
 | 
			
		||||
 | 
			
		||||
Version 1.00.15 - 7 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Fix status overflow check in kernel patches.
 | 
			
		||||
 | 
			
		||||
Version 1.00.14 - 6 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Fix static selinux build.
 | 
			
		||||
 | 
			
		||||
Version 1.00.13 - 6 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Add some basic selinux support.
 | 
			
		||||
 | 
			
		||||
Version 1.00.12 - 6 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Fix dmsetup.static install.
 | 
			
		||||
 | 
			
		||||
Version 1.00.11 - 5 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  configure --enable-static_link does static build in addition to dynamic.
 | 
			
		||||
  Moved Makefile library targets definition into template.
 | 
			
		||||
 | 
			
		||||
Version 1.00.10 - 2 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Fix DESTDIR handling.
 | 
			
		||||
  Static build installs to dmsetup.static.
 | 
			
		||||
  Basic support for internationalisation.
 | 
			
		||||
  Minor Makefile tidy-ups/fixes.
 | 
			
		||||
 | 
			
		||||
Version 1.00.09 - 31 Mar 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Update copyright notices to Red Hat.
 | 
			
		||||
  Move full mknodes functionality from dmsetup into libdevmapper.
 | 
			
		||||
  Avoid sscanf %as for uClibc compatibility.
 | 
			
		||||
  Cope if DM_LIST_VERSIONS is not defined.
 | 
			
		||||
  Add DM_LIST_VERSIONS functionality to kernel patches.
 | 
			
		||||
  Generate new kernel patches for 2.4.26-rc1.
 | 
			
		||||
 | 
			
		||||
Version 1.00.08 - 27 Feb 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Added 'dmsetup targets'.
 | 
			
		||||
  Added event_nr support to 'dmsetup wait'.
 | 
			
		||||
  Updated dmsetup man page.
 | 
			
		||||
  Allow logging function to be reset to use internal one.
 | 
			
		||||
  Bring log macros in line with LVM2 ones.
 | 
			
		||||
  Added 'make install_static_lib' which installs libdevmapper.a.
 | 
			
		||||
  Made configure/makefiles closer to LVM2 versions.
 | 
			
		||||
  Fixed DESTDIR for make install/install_static_lib.
 | 
			
		||||
  Updated README/INSTALL to reflect move to sources.redhat.com.
 | 
			
		||||
  Updated autoconf files to 2003-06-17.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										499
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										499
									
								
								configure.in
									
									
									
									
									
								
							@@ -1,30 +1,64 @@
 | 
			
		||||
################################################################################
 | 
			
		||||
##
 | 
			
		||||
##    Copyright 1999-2000 Sistina Software, Inc.
 | 
			
		||||
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
## Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
##
 | 
			
		||||
##    This is free software released under the GNU General Public License.
 | 
			
		||||
##    There is no warranty for this software.  See the file COPYING for
 | 
			
		||||
##    details.
 | 
			
		||||
## This file is part of the LVM2.
 | 
			
		||||
##
 | 
			
		||||
##    See the file CONTRIBUTORS for a list of contributors.
 | 
			
		||||
## 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.
 | 
			
		||||
##
 | 
			
		||||
##    This file is maintained by:
 | 
			
		||||
##      AJ Lewis <lewis@sistina.com>
 | 
			
		||||
## 
 | 
			
		||||
##    File name: configure.in
 | 
			
		||||
##
 | 
			
		||||
##    Description: Input file for autoconf.  Generates the configure script 
 | 
			
		||||
##                 that tries to keep everything nice and portable.  It also
 | 
			
		||||
##                 simplifies distribution package building considerably.
 | 
			
		||||
## 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
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
dnl Process this file with autoconf to produce a configure script.
 | 
			
		||||
AC_PREREQ(2.53)
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Process this file with autoconf to produce a configure script.
 | 
			
		||||
AC_INIT(lib/device/dev-cache.h)
 | 
			
		||||
 | 
			
		||||
dnl setup the directory where autoconf has auxilary files
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Setup the directory where autoconf has auxilary files
 | 
			
		||||
AC_CONFIG_AUX_DIR(autoconf) 
 | 
			
		||||
 | 
			
		||||
dnl Checks for programs.
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Get system type
 | 
			
		||||
AC_CANONICAL_SYSTEM
 | 
			
		||||
 | 
			
		||||
case "$host_os" in
 | 
			
		||||
	linux*)
 | 
			
		||||
		CFLAGS="$CFLAGS"
 | 
			
		||||
		COPTIMISE_FLAG="-O2"
 | 
			
		||||
		CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
 | 
			
		||||
		CLDWHOLEARCHIVE="-Wl,-whole-archive"
 | 
			
		||||
		CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
 | 
			
		||||
		LDDEPS="$LDDEPS .export.sym"
 | 
			
		||||
		LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
 | 
			
		||||
		SOFLAG="-shared"
 | 
			
		||||
		DEVMAPPER=yes
 | 
			
		||||
		ODIRECT=yes
 | 
			
		||||
		SELINUX=yes
 | 
			
		||||
		CLUSTER=internal
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
	darwin*)
 | 
			
		||||
		CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
 | 
			
		||||
		COPTIMISE_FLAG="-O2"
 | 
			
		||||
		CLDFLAGS="$CLDFLAGS"
 | 
			
		||||
		CLDWHOLEARCHIVE="-all_load"
 | 
			
		||||
		CLDNOWHOLEARCHIVE=
 | 
			
		||||
		LDDEPS="$LDDEPS"
 | 
			
		||||
		LDFLAGS="$LDFLAGS"
 | 
			
		||||
		SOFLAG="-dynamiclib"
 | 
			
		||||
		DEVMAPPER=no
 | 
			
		||||
		ODIRECT=no
 | 
			
		||||
		SELINUX=no
 | 
			
		||||
		CLUSTER=none
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Checks for programs.
 | 
			
		||||
AC_PROG_AWK
 | 
			
		||||
AC_PROG_CC
 | 
			
		||||
AC_PROG_INSTALL
 | 
			
		||||
@@ -32,113 +66,310 @@ AC_PROG_LN_S
 | 
			
		||||
AC_PROG_MAKE_SET
 | 
			
		||||
AC_PROG_RANLIB
 | 
			
		||||
 | 
			
		||||
dnl Checks for header files.
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Checks for header files.
 | 
			
		||||
AC_HEADER_DIRENT
 | 
			
		||||
AC_HEADER_STDC
 | 
			
		||||
AC_CHECK_HEADERS(fcntl.h malloc.h sys/ioctl.h unistd.h)
 | 
			
		||||
AC_HEADER_SYS_WAIT
 | 
			
		||||
AC_HEADER_TIME
 | 
			
		||||
 | 
			
		||||
dnl Checks for typedefs, structures, and compiler characteristics.
 | 
			
		||||
AC_CHECK_HEADERS(fcntl.h limits.h locale.h stddef.h syslog.h sys/file.h sys/ioctl.h sys/param.h sys/time.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
AC_CHECK_HEADERS(assert.h ctype.h libgen.h signal.h stdio.h sys/mman.h sys/resource.h sys/stat.h sys/types.h sys/utsname.h sys/wait.h time.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
 | 
			
		||||
case "$host_os" in
 | 
			
		||||
	linux*)
 | 
			
		||||
		AC_CHECK_HEADERS(asm/byteorder.h linux/fs.h malloc.h,,AC_MSG_ERROR(bailing out)) ;;
 | 
			
		||||
	darwin*)
 | 
			
		||||
		AC_CHECK_HEADERS(machine/endian.h sys/disk.h,,AC_MSG_ERROR(bailing out)) ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Checks for typedefs, structures, and compiler characteristics.
 | 
			
		||||
AC_C_CONST
 | 
			
		||||
AC_C_INLINE
 | 
			
		||||
AC_TYPE_OFF_T
 | 
			
		||||
AC_TYPE_PID_T
 | 
			
		||||
AC_TYPE_SIZE_T
 | 
			
		||||
AC_TYPE_MODE_T
 | 
			
		||||
AC_STRUCT_ST_RDEV
 | 
			
		||||
AC_HEADER_TIME
 | 
			
		||||
AC_STRUCT_TM
 | 
			
		||||
 | 
			
		||||
dnl Get system type
 | 
			
		||||
AC_CANONICAL_SYSTEM
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for functions
 | 
			
		||||
AC_CHECK_FUNCS(gethostname getpagesize memset munmap setlocale strcasecmp strchr strdup strncasecmp strerror strrchr strstr strtol strtoul,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
AC_FUNC_ALLOCA
 | 
			
		||||
AC_FUNC_CLOSEDIR_VOID
 | 
			
		||||
AC_FUNC_FORK
 | 
			
		||||
AC_FUNC_LSTAT
 | 
			
		||||
AC_FUNC_MALLOC
 | 
			
		||||
AC_FUNC_MEMCMP
 | 
			
		||||
AC_FUNC_MMAP
 | 
			
		||||
AC_FUNC_STAT
 | 
			
		||||
AC_FUNC_STRTOD
 | 
			
		||||
 | 
			
		||||
case "$host_os" in
 | 
			
		||||
	linux*)
 | 
			
		||||
		CFLAGS= ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
dnl -- prefix is /usr by default, the exec_prefix default is setup later
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Prefix is /usr by default, the exec_prefix default is setup later
 | 
			
		||||
AC_PREFIX_DEFAULT(/usr)
 | 
			
		||||
 | 
			
		||||
dnl -- setup the ownership of the files
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Parallel make jobs?
 | 
			
		||||
AC_ARG_ENABLE(jobs, [  --enable-jobs=NUM       Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Setup the ownership of the files
 | 
			
		||||
AC_MSG_CHECKING(file owner)
 | 
			
		||||
OWNER="root"
 | 
			
		||||
 | 
			
		||||
AC_ARG_WITH(user,
 | 
			
		||||
  [  --with-user=USER        Set the owner of installed files ],
 | 
			
		||||
  [ OWNER="$withval" ],
 | 
			
		||||
  [ OWNER="root" ])
 | 
			
		||||
  [ OWNER="$withval" ])
 | 
			
		||||
AC_MSG_RESULT($OWNER)
 | 
			
		||||
 | 
			
		||||
dnl -- setup the group ownership of the files
 | 
			
		||||
if test x$OWNER != x; then
 | 
			
		||||
	OWNER="-o $OWNER"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Setup the group ownership of the files
 | 
			
		||||
AC_MSG_CHECKING(group owner)
 | 
			
		||||
GROUP="root"
 | 
			
		||||
AC_ARG_WITH(group,
 | 
			
		||||
  [  --with-group=GROUP      Set the group owner of installed files ],
 | 
			
		||||
  [ GROUP="$withval" ],
 | 
			
		||||
  [ GROUP="root" ])
 | 
			
		||||
  [ GROUP="$withval" ])
 | 
			
		||||
AC_MSG_RESULT($GROUP)
 | 
			
		||||
 | 
			
		||||
if test x$GROUP != x; then
 | 
			
		||||
	GROUP="-g $GROUP"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- LVM1 tool fallback option
 | 
			
		||||
AC_MSG_CHECKING(whether to enable lvm1 fallback)
 | 
			
		||||
AC_ARG_ENABLE(lvm1_fallback, [  --enable-lvm1_fallback  Use this to fall back and use LVM1 binaries if
 | 
			
		||||
                          device-mapper is missing from the kernel],  LVM1_FALLBACK=$enableval, LVM1_FALLBACK=no)
 | 
			
		||||
AC_MSG_RESULT($LVM1_FALLBACK)
 | 
			
		||||
 | 
			
		||||
if test x$LVM1_FALLBACK = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DLVM1_FALLBACK"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- format1 inclusion type
 | 
			
		||||
AC_MSG_CHECKING(whether to include support for lvm1 metadata)
 | 
			
		||||
AC_ARG_WITH(lvm1,
 | 
			
		||||
  [  --with-lvm1=TYPE        LVM1 metadata support: internal/shared/none
 | 
			
		||||
                          [TYPE=internal] ],
 | 
			
		||||
  [ LVM1="$withval" ],
 | 
			
		||||
  [ LVM1="internal" ])
 | 
			
		||||
AC_MSG_RESULT($LVM1)
 | 
			
		||||
 | 
			
		||||
if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
 | 
			
		||||
 then  AC_MSG_ERROR(
 | 
			
		||||
--with-lvm1 parameter invalid
 | 
			
		||||
)
 | 
			
		||||
 exit
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$LVM1 = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DLVM1_INTERNAL"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(jobs, [  --enable-jobs=NUM       Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- format_pool inclusion type
 | 
			
		||||
AC_MSG_CHECKING(whether to include support for GFS pool metadata)
 | 
			
		||||
AC_ARG_WITH(pool,
 | 
			
		||||
  [  --with-pool=TYPE        GFS pool read-only support: internal/shared/none
 | 
			
		||||
                          [TYPE=internal] ],
 | 
			
		||||
  [ POOL="$withval" ],
 | 
			
		||||
  [ POOL="internal" ])
 | 
			
		||||
AC_MSG_RESULT($POOL)
 | 
			
		||||
 | 
			
		||||
dnl Enables staticly linked tools
 | 
			
		||||
AC_ARG_ENABLE(static_link, [  --enable-static_link    Use this to link the tools to the liblvm library
 | 
			
		||||
if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
 | 
			
		||||
 then  AC_MSG_ERROR(
 | 
			
		||||
--with-pool parameter invalid
 | 
			
		||||
)
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$POOL = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DPOOL_INTERNAL"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- cluster_locking inclusion type
 | 
			
		||||
AC_MSG_CHECKING(whether to include support for cluster locking)
 | 
			
		||||
AC_ARG_WITH(cluster,
 | 
			
		||||
  [  --with-cluster=TYPE     Cluster LVM locking support: internal/shared/none
 | 
			
		||||
                          [TYPE=internal] ],
 | 
			
		||||
  [ CLUSTER="$withval" ])
 | 
			
		||||
AC_MSG_RESULT($CLUSTER)
 | 
			
		||||
 | 
			
		||||
if [[ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared ]];
 | 
			
		||||
 then  AC_MSG_ERROR(
 | 
			
		||||
--with-cluster parameter invalid
 | 
			
		||||
)
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$CLUSTER = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- snapshots inclusion type
 | 
			
		||||
AC_MSG_CHECKING(whether to include snapshots)
 | 
			
		||||
AC_ARG_WITH(snapshots,
 | 
			
		||||
  [  --with-snapshots=TYPE   Snapshot support: internal/shared/none
 | 
			
		||||
                          [TYPE=internal] ],
 | 
			
		||||
  [ SNAPSHOTS="$withval" ],
 | 
			
		||||
  [ SNAPSHOTS="internal" ])
 | 
			
		||||
AC_MSG_RESULT($SNAPSHOTS)
 | 
			
		||||
 | 
			
		||||
if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
 | 
			
		||||
 then  AC_MSG_ERROR(
 | 
			
		||||
--with-snapshots parameter invalid
 | 
			
		||||
)
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$SNAPSHOTS = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- mirrors inclusion type
 | 
			
		||||
AC_MSG_CHECKING(whether to include mirrors)
 | 
			
		||||
AC_ARG_WITH(mirrors,
 | 
			
		||||
  [  --with-mirrors=TYPE     Mirror support: internal/shared/none
 | 
			
		||||
                          [TYPE=internal] ],
 | 
			
		||||
  [ MIRRORS="$withval" ],
 | 
			
		||||
  [ MIRRORS="internal" ])
 | 
			
		||||
AC_MSG_RESULT($MIRRORS)
 | 
			
		||||
 | 
			
		||||
if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
 | 
			
		||||
 then  AC_MSG_ERROR(
 | 
			
		||||
--with-mirrors parameter invalid
 | 
			
		||||
)
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$MIRRORS = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Enables staticly-linked tools
 | 
			
		||||
AC_MSG_CHECKING(whether to use static linking)
 | 
			
		||||
AC_ARG_ENABLE(static_link, [  --enable-static_link    Use this to link the tools to their libraries
 | 
			
		||||
                          statically.  Default is dynamic linking],  STATIC_LINK=$enableval, STATIC_LINK=no)
 | 
			
		||||
AC_MSG_RESULT($STATIC_LINK)
 | 
			
		||||
 | 
			
		||||
dnl Enable readline
 | 
			
		||||
AC_ARG_ENABLE(readline, [  --enable-readline       Enable readline support],  \
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Enable readline
 | 
			
		||||
AC_MSG_CHECKING(whether to enable readline)
 | 
			
		||||
AC_ARG_ENABLE(readline, [  --enable-readline       Enable readline support],
 | 
			
		||||
READLINE=$enableval, READLINE=no)
 | 
			
		||||
AC_MSG_RESULT($READLINE)
 | 
			
		||||
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo $ac_n "checking whether to enable debugging""... $ac_c" 1>&6
 | 
			
		||||
dnl Enable Debugging
 | 
			
		||||
AC_ARG_ENABLE(debug,    [  --enable-debug          Enable debugging],  \
 | 
			
		||||
DEBUG=yes, DEBUG=no)
 | 
			
		||||
echo "$ac_t""$DEBUG" 1>&6
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Disable selinux
 | 
			
		||||
AC_MSG_CHECKING(whether to enable selinux support)
 | 
			
		||||
AC_ARG_ENABLE(selinux, [  --disable-selinux       Disable selinux support],
 | 
			
		||||
SELINUX=$enableval)
 | 
			
		||||
AC_MSG_RESULT($SELINUX)
 | 
			
		||||
 | 
			
		||||
echo $ac_n "checking whether to enable device-mapper""... $ac_c" 1>&6
 | 
			
		||||
dnl Disable devmapper
 | 
			
		||||
AC_ARG_ENABLE(devmapper, [  --disable-devmapper     Disable device-mapper interaction],  \
 | 
			
		||||
DEVMAPPER=no, DEVMAPPER=yes)
 | 
			
		||||
echo "$ac_t""$DEVMAPPER" 1>&6
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Build cluster LVM daemon
 | 
			
		||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
 | 
			
		||||
AC_ARG_WITH(clvmd,
 | 
			
		||||
  [  --with-clvmd=TYPE       Build cluster LVM Daemon: cman/gulm/none
 | 
			
		||||
                          [TYPE=none] ],
 | 
			
		||||
  [ CLVMD="$withval" ],
 | 
			
		||||
  [ CLVMD="none" ])
 | 
			
		||||
if test x$CLVMD = xyes; then
 | 
			
		||||
	CLVMD=cman
 | 
			
		||||
fi
 | 
			
		||||
AC_MSG_RESULT($CLVMD)
 | 
			
		||||
 | 
			
		||||
dnl -- If clvmd enabled without cluster locking, automagically include it
 | 
			
		||||
if  test x$CLVMD != xnone && test x$CLUSTER = xnone; then
 | 
			
		||||
	CLUSTER=internal
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Enable debugging
 | 
			
		||||
AC_MSG_CHECKING(whether to enable debugging)
 | 
			
		||||
AC_ARG_ENABLE(debug,    [  --enable-debug          Enable debugging],
 | 
			
		||||
DEBUG=$enableval, DEBUG=no)
 | 
			
		||||
AC_MSG_RESULT($DEBUG)
 | 
			
		||||
 | 
			
		||||
dnl -- Normally turn off optimisation for debug builds
 | 
			
		||||
if test x$DEBUG = xyes; then
 | 
			
		||||
	COPTIMISE_FLAG=
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Override optimisation
 | 
			
		||||
AC_MSG_CHECKING(for C optimisation flag)
 | 
			
		||||
AC_ARG_WITH(optimisation,
 | 
			
		||||
  [  --with-optimisation=OPT C optimisation flag [OPT=-O2] ],
 | 
			
		||||
  [ COPTIMISE_FLAG="$withval" ])
 | 
			
		||||
AC_MSG_RESULT($COPTIMISE_FLAG)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Disable devmapper
 | 
			
		||||
AC_MSG_CHECKING(whether to use device-mapper)
 | 
			
		||||
AC_ARG_ENABLE(devmapper, [  --disable-devmapper     Disable device-mapper interaction],
 | 
			
		||||
DEVMAPPER=$enableval)
 | 
			
		||||
AC_MSG_RESULT($DEVMAPPER)
 | 
			
		||||
 | 
			
		||||
if test x$DEVMAPPER = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo $ac_n "checking whether to enable O_DIRECT""... $ac_c" 1>&6
 | 
			
		||||
dnl Disable O_DIRECT
 | 
			
		||||
AC_ARG_ENABLE(o_direct, [  --disable-o_direct      Disable O_DIRECT],  \
 | 
			
		||||
ODIRECT=no, ODIRECT=yes)
 | 
			
		||||
echo "$ac_t""$ODIRECT" 1>&6
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Disable O_DIRECT
 | 
			
		||||
AC_MSG_CHECKING(whether to enable O_DIRECT)
 | 
			
		||||
AC_ARG_ENABLE(o_direct, [  --disable-o_direct      Disable O_DIRECT],
 | 
			
		||||
ODIRECT=$enableval)
 | 
			
		||||
AC_MSG_RESULT($ODIRECT)
 | 
			
		||||
 | 
			
		||||
if test x$ODIRECT = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
dnl Mess with default exec_prefix
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Enable cmdlib
 | 
			
		||||
AC_MSG_CHECKING(whether to compile liblvm2cmd.so)
 | 
			
		||||
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)
 | 
			
		||||
AC_ARG_ENABLE(fsadm, [  --enable-fsadm          Enable fsadm],
 | 
			
		||||
FSADM=$enableval)
 | 
			
		||||
AC_MSG_RESULT($FSADM)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Mess with default exec_prefix
 | 
			
		||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
 | 
			
		||||
 then  exec_prefix="";
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
dnl Checks for library functions.
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Checks for library functions.
 | 
			
		||||
AC_PROG_GCC_TRADITIONAL
 | 
			
		||||
AC_TYPE_SIGNAL
 | 
			
		||||
AC_FUNC_VPRINTF
 | 
			
		||||
AC_CHECK_FUNCS(mkdir rmdir uname)
 | 
			
		||||
AC_CHECK_FUNCS(mkdir rmdir uname,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
 | 
			
		||||
dnl check for termcap (Shamelessly copied from parted 1.4.17)
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for termcap (Shamelessly copied from parted 1.4.17)
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	AC_SEARCH_LIBS(tgetent, ncurses curses termcap termlib, ,
 | 
			
		||||
		AC_MSG_ERROR(
 | 
			
		||||
@@ -151,22 +382,51 @@ Note: if you are using precompiled packages you will also need the development
 | 
			
		||||
Note: (n)curses also seems to work as a substitute for termcap.  This was
 | 
			
		||||
  not found either - but you could try installing that as well.
 | 
			
		||||
)
 | 
			
		||||
	exit
 | 
			
		||||
	)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
dnl Check for dlopen
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for dlopen
 | 
			
		||||
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
 | 
			
		||||
 | 
			
		||||
if test x$HAVE_LIBDL = xyes; then
 | 
			
		||||
if [[ "x$HAVE_LIBDL" = xyes ]]; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DHAVE_LIBDL"
 | 
			
		||||
	LIBS="-ldl $LIBS"
 | 
			
		||||
else
 | 
			
		||||
	HAVE_LIBDL=no
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
dnl Check for getopt
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for shared/static conflicts
 | 
			
		||||
if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \
 | 
			
		||||
      -o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
 | 
			
		||||
      \) -a "x$STATIC_LINK" = xyes ]];
 | 
			
		||||
 then  AC_MSG_ERROR(
 | 
			
		||||
Features cannot be 'shared' when building statically
 | 
			
		||||
)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for is_selinux_enabled
 | 
			
		||||
if test x$SELINUX = xyes; then
 | 
			
		||||
	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"
 | 
			
		||||
		LIBS="-lselinux $LIBS"
 | 
			
		||||
	else
 | 
			
		||||
		AC_MSG_WARN(Disabling selinux)
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for getopt
 | 
			
		||||
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
 | 
			
		||||
 | 
			
		||||
dnl Check for readline (Shamelessly copied from parted 1.4.17)
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	AC_CHECK_LIB(readline, readline, ,
 | 
			
		||||
		AC_MSG_ERROR(
 | 
			
		||||
@@ -177,17 +437,17 @@ support with --disable-readline or download and install readline from:
 | 
			
		||||
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).
 | 
			
		||||
)
 | 
			
		||||
		exit
 | 
			
		||||
	)
 | 
			
		||||
	AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
 | 
			
		||||
		
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo $ac_n "checking whether to enable internationalisation""... $ac_c" 1>&6
 | 
			
		||||
dnl Internationalisation stuff
 | 
			
		||||
AC_ARG_ENABLE(nls, [  --enable-nls            Enable Native Language Support],\
 | 
			
		||||
		INTL=yes, INTL=no)
 | 
			
		||||
echo "$ac_t""$INTL" 1>&6
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Internationalisation stuff
 | 
			
		||||
AC_MSG_CHECKING(whether to enable internationalisation)
 | 
			
		||||
AC_ARG_ENABLE(nls, [  --enable-nls            Enable Native Language Support],
 | 
			
		||||
		INTL=$enableval, INTL=no)
 | 
			
		||||
AC_MSG_RESULT($INTL)
 | 
			
		||||
 | 
			
		||||
if test x$INTL = xyes; then
 | 
			
		||||
	INTL_PACKAGE="lvm2"
 | 
			
		||||
@@ -196,7 +456,6 @@ if test x$INTL = xyes; then
 | 
			
		||||
		then  AC_MSG_ERROR(
 | 
			
		||||
		msgfmt not found in path $PATH
 | 
			
		||||
		)
 | 
			
		||||
		exit  
 | 
			
		||||
	fi;
 | 
			
		||||
 | 
			
		||||
	AC_ARG_WITH(localedir,
 | 
			
		||||
@@ -205,39 +464,120 @@ if test x$INTL = xyes; then
 | 
			
		||||
  		    [ LOCALEDIR='${prefix}/share/locale' ])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
AC_ARG_WITH(confdir,
 | 
			
		||||
	    [  --with-confdir=DIR      Configuration files in DIR [/etc]],
 | 
			
		||||
  	    [ CONFDIR="$withval" ],
 | 
			
		||||
 	    [ CONFDIR='/etc' ])
 | 
			
		||||
 | 
			
		||||
AC_ARG_WITH(staticdir,
 | 
			
		||||
	    [  --with-staticdir=DIR    Static binary in DIR [EXEC_PREFIX/sbin]],
 | 
			
		||||
  	    [ STATICDIR="$withval" ],
 | 
			
		||||
 	    [ STATICDIR='${exec_prefix}/sbin' ])
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Ensure additional headers required
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(readline/readline.h readline/history.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$CLVMD = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
	AC_CHECK_FUNCS(dup2 getmntent memmove select socket,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
	AC_FUNC_GETMNTENT
 | 
			
		||||
#	AC_FUNC_REALLOC
 | 
			
		||||
	AC_FUNC_SELECT_ARGTYPES
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$FSADM = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(fstab.h sys/mount.h sys/vfs.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
	AC_CHECK_FUNCS(memmove,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$CLUSTER != xnone; then
 | 
			
		||||
	AC_CHECK_HEADERS(sys/socket.h sys/un.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
	AC_CHECK_FUNCS(socket,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$HAVE_LIBDL = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(dlfcn.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(selinux/selinux.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
if test "-f VERSION"; then
 | 
			
		||||
  LVM_VERSION="\"`cat VERSION`\""
 | 
			
		||||
else
 | 
			
		||||
  LVM_VERSION="Unknown"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
AC_SUBST(JOBS)
 | 
			
		||||
AC_SUBST(STATIC_LINK)
 | 
			
		||||
AC_SUBST(LVM1)
 | 
			
		||||
AC_SUBST(POOL)
 | 
			
		||||
AC_SUBST(SNAPSHOTS)
 | 
			
		||||
AC_SUBST(MIRRORS)
 | 
			
		||||
AC_SUBST(OWNER)
 | 
			
		||||
AC_SUBST(GROUP)
 | 
			
		||||
AC_SUBST(CFLAGS)
 | 
			
		||||
AC_SUBST(COPTIMISE_FLAG)
 | 
			
		||||
AC_SUBST(CLDFLAGS)
 | 
			
		||||
AC_SUBST(CLDWHOLEARCHIVE)
 | 
			
		||||
AC_SUBST(CLDNOWHOLEARCHIVE)
 | 
			
		||||
AC_SUBST(LDDEPS)
 | 
			
		||||
AC_SUBST(LDFLAGS)
 | 
			
		||||
AC_SUBST(SOFLAG)
 | 
			
		||||
AC_SUBST(LIBS)
 | 
			
		||||
AC_SUBST(LVM_VERSION)
 | 
			
		||||
AC_SUBST(LVM1_FALLBACK)
 | 
			
		||||
AC_SUBST(DEBUG)
 | 
			
		||||
AC_SUBST(DEVMAPPER)
 | 
			
		||||
AC_SUBST(HAVE_LIBDL)
 | 
			
		||||
AC_SUBST(HAVE_SELINUX)
 | 
			
		||||
AC_SUBST(CMDLIB)
 | 
			
		||||
AC_SUBST(MSGFMT)
 | 
			
		||||
AC_SUBST(LOCALEDIR)
 | 
			
		||||
AC_SUBST(CONFDIR)
 | 
			
		||||
AC_SUBST(STATICDIR)
 | 
			
		||||
AC_SUBST(INTL_PACKAGE)
 | 
			
		||||
AC_SUBST(INTL)
 | 
			
		||||
dnl First and last lines should not contain files to generate in order to 
 | 
			
		||||
dnl keep utility scripts running properly
 | 
			
		||||
AC_SUBST(CLVMD)
 | 
			
		||||
AC_SUBST(CLUSTER)
 | 
			
		||||
AC_SUBST(FSADM)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- First and last lines should not contain files to generate in order to 
 | 
			
		||||
dnl -- keep utility scripts running properly
 | 
			
		||||
AC_OUTPUT( 								\
 | 
			
		||||
Makefile								\
 | 
			
		||||
make.tmpl                                                               \
 | 
			
		||||
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							\
 | 
			
		||||
@@ -246,8 +586,9 @@ test/filters/Makefile                                                   \
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if test x$ODIRECT != xyes; then
 | 
			
		||||
  echo
 | 
			
		||||
  echo Warning: O_DIRECT disabled.
 | 
			
		||||
  echo Use of pvmove may cause machine to lock up under low memory conditions.
 | 
			
		||||
  echo
 | 
			
		||||
  AC_MSG_WARN(Warning: O_DIRECT disabled: low-memory pvmove may lock up)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$FSADM == xyes; then
 | 
			
		||||
  AC_MSG_WARN(fsadm support is untested)
 | 
			
		||||
fi
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								daemons/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								daemons/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2004 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@
 | 
			
		||||
 | 
			
		||||
ifneq ("@CLVMD@", "none")
 | 
			
		||||
  SUBDIRS = clvmd
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										59
									
								
								daemons/clvmd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								daemons/clvmd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2004 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@
 | 
			
		||||
 | 
			
		||||
SOURCES = \
 | 
			
		||||
	clvmd-command.c  \
 | 
			
		||||
	clvmd.c          \
 | 
			
		||||
	libclvm.c        \
 | 
			
		||||
	lvm-functions.c  \
 | 
			
		||||
	system-lv.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "gulm")
 | 
			
		||||
	SOURCES += clvmd-gulm.c tcp-comms.c
 | 
			
		||||
	LMLIBS += -lccs -lgulm
 | 
			
		||||
	CFLAGS += -DUSE_GULM
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "cman")
 | 
			
		||||
	SOURCES += clvmd-cman.c
 | 
			
		||||
	LMLIBS += -ldlm
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
TARGETS = \
 | 
			
		||||
	clvmd
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
CFLAGS += -D_REENTRANT -fno-strict-aliasing
 | 
			
		||||
LIBS += -ldevmapper -llvm -lpthread
 | 
			
		||||
 | 
			
		||||
INSTALL_TARGETS = \
 | 
			
		||||
	install_clvmd
 | 
			
		||||
 | 
			
		||||
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
 | 
			
		||||
	$(CC) -o clvmd $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(LMLIBS) $(LIBS)
 | 
			
		||||
 | 
			
		||||
.PHONY: install_clvmd
 | 
			
		||||
 | 
			
		||||
install_clvmd: $(TARGETS)
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) clvmd \
 | 
			
		||||
		$(sbindir)/clvmd
 | 
			
		||||
 | 
			
		||||
install: $(INSTALL_TARGETS)
 | 
			
		||||
 | 
			
		||||
install_cluster: $(INSTALL_TARGETS)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										65
									
								
								daemons/clvmd/clvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								daemons/clvmd/clvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Definitions for CLVMD server and clients */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The protocol spoken over the cluster and across the local socket.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _CLVM_H
 | 
			
		||||
#define _CLVM_H
 | 
			
		||||
 | 
			
		||||
struct clvm_header {
 | 
			
		||||
	uint8_t  cmd;	        /* See below */
 | 
			
		||||
	uint8_t  flags;	        /* See below */
 | 
			
		||||
	uint16_t xid;	        /* Transaction ID */
 | 
			
		||||
	uint32_t clientid;	/* Only used in Daemon->Daemon comms */
 | 
			
		||||
	int32_t  status;	/* For replies, whether request succeeded */
 | 
			
		||||
	uint32_t arglen;	/* Length of argument below. 
 | 
			
		||||
				   If >1500 then it will be passed 
 | 
			
		||||
				   around the cluster in the system LV */
 | 
			
		||||
	char node[1];		/* Actually a NUL-terminated string, node name.
 | 
			
		||||
				   If this is empty then the command is 
 | 
			
		||||
				   forwarded to all cluster nodes unless 
 | 
			
		||||
				   FLAG_LOCAL is also set. */
 | 
			
		||||
	char args[1];		/* Arguments for the command follow the 
 | 
			
		||||
				   node name, This member is only
 | 
			
		||||
				   valid if the node name is empty */
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
/* Flags */
 | 
			
		||||
#define CLVMD_FLAG_LOCAL        1	/* Only do this on the local node */
 | 
			
		||||
#define CLVMD_FLAG_SYSTEMLV     2	/* Data in system LV under my node name */
 | 
			
		||||
 | 
			
		||||
/* Name of the local socket to communicate between libclvm and clvmd */
 | 
			
		||||
//static const char CLVMD_SOCKNAME[]="/var/run/clvmd";
 | 
			
		||||
static const char CLVMD_SOCKNAME[] = "\0clvmd";
 | 
			
		||||
 | 
			
		||||
/* Internal commands & replies */
 | 
			
		||||
#define CLVMD_CMD_REPLY    1
 | 
			
		||||
#define CLVMD_CMD_VERSION  2	/* Send version around cluster when we start */
 | 
			
		||||
#define CLVMD_CMD_GOAWAY   3	/* Die if received this - we are running 
 | 
			
		||||
				   an incompatible version */
 | 
			
		||||
#define CLVMD_CMD_TEST     4	/* Just for mucking about */
 | 
			
		||||
 | 
			
		||||
#define CLVMD_CMD_LOCK              30
 | 
			
		||||
#define CLVMD_CMD_UNLOCK            31
 | 
			
		||||
 | 
			
		||||
/* Lock/Unlock commands */
 | 
			
		||||
#define CLVMD_CMD_LOCK_LV           50
 | 
			
		||||
#define CLVMD_CMD_LOCK_VG           51
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										507
									
								
								daemons/clvmd/clvmd-cman.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										507
									
								
								daemons/clvmd/clvmd-cman.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,507 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * CMAN communication layer for clvmd.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/uio.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
 | 
			
		||||
#define LOCKSPACE_NAME "clvmd"
 | 
			
		||||
 | 
			
		||||
static int cluster_sock;
 | 
			
		||||
static int num_nodes;
 | 
			
		||||
static struct cl_cluster_node *nodes = NULL;
 | 
			
		||||
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 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);
 | 
			
		||||
 | 
			
		||||
struct lock_wait {
 | 
			
		||||
	pthread_cond_t cond;
 | 
			
		||||
	pthread_mutex_t mutex;
 | 
			
		||||
	struct dlm_lksb lksb;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int init_cluster()
 | 
			
		||||
{
 | 
			
		||||
	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) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't open cluster manager socket: %m");
 | 
			
		||||
		return -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))) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't bind cluster socket: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the cluster members list */
 | 
			
		||||
	get_members();
 | 
			
		||||
	count_clvmds_running();
 | 
			
		||||
 | 
			
		||||
	/* Create a lockspace for LV & VG locks to live in */
 | 
			
		||||
	lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
 | 
			
		||||
	if (!lockspace) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	dlm_ls_pthread_init(lockspace);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_main_cluster_fd()
 | 
			
		||||
{
 | 
			
		||||
	return cluster_sock;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_num_nodes()
 | 
			
		||||
{
 | 
			
		||||
	return num_nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send_message with the fd check removed */
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	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, MAX_CSID_LEN);
 | 
			
		||||
	} else {		/* Cluster broadcast */
 | 
			
		||||
 | 
			
		||||
		msg.msg_name = NULL;
 | 
			
		||||
		msg.msg_namelen = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		len = sendmsg(cluster_sock, &msg, 0);
 | 
			
		||||
		if (len < 0 && errno != EAGAIN)
 | 
			
		||||
			log_error(errtext);
 | 
			
		||||
 | 
			
		||||
	} while (len == -1 && errno == EAGAIN);
 | 
			
		||||
	return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	memset(csid, 0, MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (nodes[i].us)
 | 
			
		||||
			memcpy(csid, &nodes[i].node_id, MAX_CSID_LEN);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Call a callback routine for each node that known (down mean not running a clvmd) */
 | 
			
		||||
int cluster_do_node_callback(struct local_client *client,
 | 
			
		||||
			     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;
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
		node_updown[nodeid] = 0;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLUSTER_OOB_MSG_STATECHANGE:
 | 
			
		||||
		DEBUGLOG("Got OOB message, Cluster state change\n");
 | 
			
		||||
		get_members();
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		/* ERROR */
 | 
			
		||||
		DEBUGLOG("Got unknown OOB message: %d\n", buf[0]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
			struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	struct iovec iov[2];
 | 
			
		||||
	struct msghdr msg;
 | 
			
		||||
	struct sockaddr_cl saddr;
 | 
			
		||||
 | 
			
		||||
	/* 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;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void add_up_node(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	/* It's up ! */
 | 
			
		||||
	int nodeid = nodeid_from_csid(csid);
 | 
			
		||||
 | 
			
		||||
	if (nodeid >= max_updown_nodes) {
 | 
			
		||||
	        int new_size = nodeid + 10;
 | 
			
		||||
		int *new_updown = realloc(node_updown, new_size);
 | 
			
		||||
 | 
			
		||||
		if (new_updown) {
 | 
			
		||||
			node_updown = new_updown;
 | 
			
		||||
			max_updown_nodes = new_size;
 | 
			
		||||
			DEBUGLOG("realloced more space for nodes. now %d\n",
 | 
			
		||||
				 max_updown_nodes);
 | 
			
		||||
		} else {
 | 
			
		||||
			log_error
 | 
			
		||||
			    ("Realloc failed. Node status for clvmd will be wrong. quitting\n");
 | 
			
		||||
			exit(999);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	node_updown[nodeid] = 1;
 | 
			
		||||
	DEBUGLOG("Added new node %d to updown list\n", nodeid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cluster_closedown()
 | 
			
		||||
{
 | 
			
		||||
	unlock_all();
 | 
			
		||||
	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
 | 
			
		||||
	close(cluster_sock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
		if (status < 0 && errno == EBUSY) {	/* Don't busywait */
 | 
			
		||||
			sleep(1);
 | 
			
		||||
			errno = EBUSY;	/* In case sleep trashes it */
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	while (status < 0 && errno == EBUSY);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Populate the list of CLVMDs running.
 | 
			
		||||
   called only at startup time */
 | 
			
		||||
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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get a list of active cluster members */
 | 
			
		||||
static void get_members()
 | 
			
		||||
{
 | 
			
		||||
	struct cl_cluster_nodelist nodelist;
 | 
			
		||||
 | 
			
		||||
	num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
 | 
			
		||||
	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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
		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));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a node name to a CSID */
 | 
			
		||||
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, MAX_CSID_LEN);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a CSID to a node name */
 | 
			
		||||
int name_from_csid(char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (memcmp(csid, &nodes[i].node_id, MAX_CSID_LEN) == 0) {
 | 
			
		||||
			strcpy(name, nodes[i].name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/* Who?? */
 | 
			
		||||
	strcpy(name, "Unknown");
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a node ID to a node name */
 | 
			
		||||
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);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/* Who?? */
 | 
			
		||||
	strcpy(name, "Unknown");
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a CSID to a node ID */
 | 
			
		||||
static int nodeid_from_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
        int nodeid;
 | 
			
		||||
 | 
			
		||||
	memcpy(&nodeid, csid, MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	return nodeid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int is_quorate()
 | 
			
		||||
{
 | 
			
		||||
	return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sync_ast_routine(void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct lock_wait *lwait = arg;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lwait->mutex);
 | 
			
		||||
	pthread_cond_signal(&lwait->cond);
 | 
			
		||||
	pthread_mutex_unlock(&lwait->mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sync_lock(const char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	struct lock_wait lwait;
 | 
			
		||||
 | 
			
		||||
	if (!lockid) {
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
 | 
			
		||||
	/* Conversions need the lockid in the LKSB */
 | 
			
		||||
	if (flags & LKF_CONVERT)
 | 
			
		||||
		lwait.lksb.sb_lkid = *lockid;
 | 
			
		||||
 | 
			
		||||
	pthread_cond_init(&lwait.cond, NULL);
 | 
			
		||||
	pthread_mutex_init(&lwait.mutex, NULL);
 | 
			
		||||
	pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	status = dlm_ls_lock(lockspace,
 | 
			
		||||
			     mode,
 | 
			
		||||
			     &lwait.lksb,
 | 
			
		||||
			     flags,
 | 
			
		||||
			     resource,
 | 
			
		||||
			     strlen(resource),
 | 
			
		||||
			     0, sync_ast_routine, &lwait, NULL, NULL);
 | 
			
		||||
	if (status)
 | 
			
		||||
		return status;
 | 
			
		||||
 | 
			
		||||
	/* Wait for it to complete */
 | 
			
		||||
	pthread_cond_wait(&lwait.cond, &lwait.mutex);
 | 
			
		||||
	pthread_mutex_unlock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	*lockid = lwait.lksb.sb_lkid;
 | 
			
		||||
 | 
			
		||||
	errno = lwait.lksb.sb_status;
 | 
			
		||||
	DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
 | 
			
		||||
	if (lwait.lksb.sb_status)
 | 
			
		||||
		return -1;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sync_unlock(const char *resource /* UNUSED */, int lockid)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	struct lock_wait lwait;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
 | 
			
		||||
 | 
			
		||||
	pthread_cond_init(&lwait.cond, NULL);
 | 
			
		||||
	pthread_mutex_init(&lwait.mutex, NULL);
 | 
			
		||||
	pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
 | 
			
		||||
 | 
			
		||||
	if (status)
 | 
			
		||||
		return status;
 | 
			
		||||
 | 
			
		||||
	/* Wait for it to complete */
 | 
			
		||||
	pthread_cond_wait(&lwait.cond, &lwait.mutex);
 | 
			
		||||
	pthread_mutex_unlock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	errno = lwait.lksb.sb_status;
 | 
			
		||||
	if (lwait.lksb.sb_status != EUNLOCK)
 | 
			
		||||
		return -1;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										285
									
								
								daemons/clvmd/clvmd-command.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								daemons/clvmd/clvmd-command.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,285 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  CLVMD Cluster LVM daemon command processor.
 | 
			
		||||
 | 
			
		||||
  To add commands to the daemon simply add a processor in do_command and return
 | 
			
		||||
  and messages back in buf and the length in *retlen. The initial value of
 | 
			
		||||
  buflen is the maximum size of the buffer. if buf is not large enough then it
 | 
			
		||||
  may be reallocated by the functions in here to a suitable size bearing in
 | 
			
		||||
  mind that anything larger than the passed-in size will have to be returned
 | 
			
		||||
  using the system LV and so performance will suffer.
 | 
			
		||||
 | 
			
		||||
  The status return will be negated and passed back to the originating node.
 | 
			
		||||
 | 
			
		||||
  pre- and post- command routines are called only on the local node. The
 | 
			
		||||
  purpose is primarily to get and release locks, though the pre- routine should
 | 
			
		||||
  also do any other local setups required by the command (if any) and can
 | 
			
		||||
  return a failure code that prevents the command from being distributed around
 | 
			
		||||
  the cluster
 | 
			
		||||
 | 
			
		||||
  The pre- and post- routines are run in their own thread so can block as long
 | 
			
		||||
  they like, do_command is run in the main clvmd thread so should not block for
 | 
			
		||||
  too long. If the pre-command returns an error code (!=0) then the command
 | 
			
		||||
  will not be propogated around the cluster but the post-command WILL be called
 | 
			
		||||
 | 
			
		||||
  Also note that the pre and post routine are *always* called on the local
 | 
			
		||||
  node, even if the command to be executed was only requested to run on a
 | 
			
		||||
  remote node. It may peek inside the client structure to check the status of
 | 
			
		||||
  the command.
 | 
			
		||||
 | 
			
		||||
  The clients of the daemon must, naturally, understand the return messages and
 | 
			
		||||
  codes.
 | 
			
		||||
 | 
			
		||||
  Routines in here may only READ the values in the client structure passed in
 | 
			
		||||
  apart from client->private which they are free to do what they like with.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
 | 
			
		||||
/* 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,
 | 
			
		||||
	       char **buf, int buflen, int *retlen)
 | 
			
		||||
{
 | 
			
		||||
	char *args = msg->node + strlen(msg->node) + 1;
 | 
			
		||||
	int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	char *lockname;
 | 
			
		||||
	struct utsname nodeinfo;
 | 
			
		||||
	unsigned char lock_cmd;
 | 
			
		||||
	unsigned char lock_flags;
 | 
			
		||||
 | 
			
		||||
	/* Do the command */
 | 
			
		||||
	switch (msg->cmd) {
 | 
			
		||||
		/* Just a test message */
 | 
			
		||||
	case CLVMD_CMD_TEST:
 | 
			
		||||
		if (arglen > buflen) {
 | 
			
		||||
			buflen = arglen + 200;
 | 
			
		||||
			*buf = realloc(*buf, buflen);
 | 
			
		||||
		}
 | 
			
		||||
		uname(&nodeinfo);
 | 
			
		||||
		*retlen = 1 + snprintf(*buf, buflen, "TEST from %s: %s v%s",
 | 
			
		||||
				       nodeinfo.nodename, args,
 | 
			
		||||
				       nodeinfo.release);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_VG:
 | 
			
		||||
		/* Check to see if the VG is in use by LVM1 */
 | 
			
		||||
		status = do_check_lvm1(&args[2]);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_LV:
 | 
			
		||||
		/* This is the biggie */
 | 
			
		||||
		lock_cmd = args[0];
 | 
			
		||||
		lock_flags = args[1];
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		status = do_lock_lv(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		/* Replace EIO with something less scary */
 | 
			
		||||
		if (status == EIO) {
 | 
			
		||||
			*retlen =
 | 
			
		||||
			    1 + snprintf(*buf, buflen,
 | 
			
		||||
					 "Internal lvm error, check syslog");
 | 
			
		||||
			return EIO;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		/* Won't get here because command is validated in pre_command */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check the status of the command and return the error text */
 | 
			
		||||
	if (status) {
 | 
			
		||||
		*retlen = 1 + snprintf(*buf, buflen, strerror(status));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int lock_vg(struct local_client *client)
 | 
			
		||||
{
 | 
			
		||||
    struct hash_table *lock_hash;
 | 
			
		||||
    struct clvm_header *header =
 | 
			
		||||
	(struct clvm_header *) client->bits.localsock.cmd;
 | 
			
		||||
    unsigned char lock_cmd;
 | 
			
		||||
    unsigned char lock_flags;
 | 
			
		||||
    char *args = header->node + strlen(header->node) + 1;
 | 
			
		||||
    int lkid;
 | 
			
		||||
    int status = 0;
 | 
			
		||||
    char *lockname;
 | 
			
		||||
 | 
			
		||||
    /* Keep a track of VG locks in our own hash table. In current
 | 
			
		||||
       practice there should only ever be more than two VGs locked
 | 
			
		||||
       if a user tries to merge lots of them at once */
 | 
			
		||||
    if (client->bits.localsock.private) {
 | 
			
		||||
	lock_hash = (struct hash_table *)client->bits.localsock.private;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	lock_hash = hash_create(3);
 | 
			
		||||
	if (!lock_hash)
 | 
			
		||||
	    return ENOMEM;
 | 
			
		||||
	client->bits.localsock.private = (void *)lock_hash;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lock_cmd = args[0];
 | 
			
		||||
    lock_flags = args[1];
 | 
			
		||||
    lockname = &args[2];
 | 
			
		||||
    DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
 | 
			
		||||
 | 
			
		||||
    if (lock_cmd == LCK_UNLOCK) {
 | 
			
		||||
 | 
			
		||||
	lkid = (int)(long)hash_lookup(lock_hash, lockname);
 | 
			
		||||
	if (lkid == 0)
 | 
			
		||||
	    return EINVAL;
 | 
			
		||||
 | 
			
		||||
	status = sync_unlock(lockname, lkid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    status = errno;
 | 
			
		||||
	else
 | 
			
		||||
	    hash_remove(lock_hash, lockname);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
 | 
			
		||||
	status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    status = errno;
 | 
			
		||||
	else
 | 
			
		||||
	    hash_insert(lock_hash, lockname, (void *)lkid);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Pre-command is a good place to get locks that are needed only for the duration
 | 
			
		||||
   of the commands around the cluster (don't forget to free them in post-command),
 | 
			
		||||
   and to sanity check the command arguments */
 | 
			
		||||
int do_pre_command(struct local_client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct clvm_header *header =
 | 
			
		||||
	    (struct clvm_header *) client->bits.localsock.cmd;
 | 
			
		||||
	unsigned char lock_cmd;
 | 
			
		||||
	unsigned char lock_flags;
 | 
			
		||||
	char *args = header->node + strlen(header->node) + 1;
 | 
			
		||||
	int lockid;
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	char *lockname;
 | 
			
		||||
 | 
			
		||||
	switch (header->cmd) {
 | 
			
		||||
	case CLVMD_CMD_TEST:
 | 
			
		||||
		status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid);
 | 
			
		||||
		client->bits.localsock.private = (void *) lockid;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_VG:
 | 
			
		||||
       	        status = lock_vg(client);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_LV:
 | 
			
		||||
		lock_cmd = args[0];
 | 
			
		||||
		lock_flags = args[1];
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		status = pre_lock_lv(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("Unknown command %d received\n", header->cmd);
 | 
			
		||||
		status = EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Note that the post-command routine is called even if the pre-command or the real command
 | 
			
		||||
   failed */
 | 
			
		||||
int do_post_command(struct local_client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct clvm_header *header =
 | 
			
		||||
	    (struct clvm_header *) client->bits.localsock.cmd;
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	unsigned char lock_cmd;
 | 
			
		||||
	unsigned char lock_flags;
 | 
			
		||||
	char *args = header->node + strlen(header->node) + 1;
 | 
			
		||||
	char *lockname;
 | 
			
		||||
 | 
			
		||||
	switch (header->cmd) {
 | 
			
		||||
	case CLVMD_CMD_TEST:
 | 
			
		||||
		status =
 | 
			
		||||
		    sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
 | 
			
		||||
		client->bits.localsock.private = 0;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_VG:
 | 
			
		||||
		/* Nothing to do here */
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_LV:
 | 
			
		||||
		lock_cmd = args[0];
 | 
			
		||||
		lock_flags = args[1];
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		status = post_lock_lv(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Called when the client is about to be deleted */
 | 
			
		||||
void cmd_client_cleanup(struct local_client *client)
 | 
			
		||||
{
 | 
			
		||||
    if (client->bits.localsock.private) {
 | 
			
		||||
 | 
			
		||||
	struct hash_node *v;
 | 
			
		||||
	struct hash_table *lock_hash =
 | 
			
		||||
	    (struct hash_table *)client->bits.localsock.private;
 | 
			
		||||
 | 
			
		||||
	hash_iterate(v, lock_hash) {
 | 
			
		||||
		int lkid = (int)(long)hash_get_data(lock_hash, v);
 | 
			
		||||
 | 
			
		||||
		DEBUGLOG("cleanup: Unlocking lkid %x\n", lkid);
 | 
			
		||||
		sync_unlock("DUMMY", lkid);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hash_destroy(lock_hash);
 | 
			
		||||
	client->bits.localsock.private = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								daemons/clvmd/clvmd-comms.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								daemons/clvmd/clvmd-comms.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Abstraction layer for clvmd cluster communications
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _CLVMD_COMMS_H
 | 
			
		||||
#define _CLVMD_COMMS_H
 | 
			
		||||
 | 
			
		||||
struct local_client;
 | 
			
		||||
 | 
			
		||||
extern int cluster_send_message(void *buf, int msglen, char *csid,
 | 
			
		||||
				const char *errtext);
 | 
			
		||||
extern int name_from_csid(char *csid, char *name);
 | 
			
		||||
extern int csid_from_name(char *csid, char *name);
 | 
			
		||||
extern int get_num_nodes(void);
 | 
			
		||||
extern int cluster_fd_callback(struct local_client *fd, char *buf, int len,
 | 
			
		||||
			       char *csid, struct local_client **new_client);
 | 
			
		||||
extern int init_cluster(void);
 | 
			
		||||
extern int get_main_cluster_fd(void);	/* gets accept FD or cman cluster socket */
 | 
			
		||||
extern int cluster_do_node_callback(struct local_client *client,
 | 
			
		||||
				    void (*callback) (struct local_client *,
 | 
			
		||||
						      char *csid, int node_up));
 | 
			
		||||
extern int is_quorate(void);
 | 
			
		||||
 | 
			
		||||
extern void get_our_csid(char *csid);
 | 
			
		||||
extern void add_up_node(char *csid);
 | 
			
		||||
extern void cluster_closedown(void);
 | 
			
		||||
 | 
			
		||||
extern int sync_lock(const char *resource, int mode, int flags, int *lockid);
 | 
			
		||||
extern int sync_unlock(const char *resource, int lockid);
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GULM
 | 
			
		||||
#include "tcp-comms.h"
 | 
			
		||||
#else
 | 
			
		||||
/* cman */
 | 
			
		||||
#include "cnxman-socket.h"
 | 
			
		||||
#define MAX_CSID_LEN 4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										912
									
								
								daemons/clvmd/clvmd-gulm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										912
									
								
								daemons/clvmd/clvmd-gulm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,912 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
**
 | 
			
		||||
**  Copyright (C) Sistina Software, Inc.  2002-2003  All rights reserved.
 | 
			
		||||
**
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* This provides the interface between clvmd and gulm as the cluster
 | 
			
		||||
 * and lock manager.
 | 
			
		||||
 *
 | 
			
		||||
 * It also provides the "liblm" functions too as it's hard (and pointless)
 | 
			
		||||
 * to seperate them out when using gulm.
 | 
			
		||||
 *
 | 
			
		||||
 * What it does /not/ provide is the communications between clvmd daemons
 | 
			
		||||
 * on the cluster nodes. That is done in tcp-comms.c
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/file.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <utmpx.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include "ccs.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "clvmd-gulm.h"
 | 
			
		||||
#include "libgulm.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
 | 
			
		||||
/* Hash list of nodes in the cluster */
 | 
			
		||||
static struct hash_table *node_hash;
 | 
			
		||||
 | 
			
		||||
/* hash list of outstanding lock requests */
 | 
			
		||||
static struct hash_table *lock_hash;
 | 
			
		||||
 | 
			
		||||
/* Copy of the current core state */
 | 
			
		||||
static uint8_t current_corestate;
 | 
			
		||||
 | 
			
		||||
/* Number of active nodes */
 | 
			
		||||
static int num_nodes;
 | 
			
		||||
 | 
			
		||||
static char *cluster_name;
 | 
			
		||||
 | 
			
		||||
static pthread_mutex_t lock_start_mutex;
 | 
			
		||||
static volatile int lock_start_flag;
 | 
			
		||||
 | 
			
		||||
struct node_info
 | 
			
		||||
{
 | 
			
		||||
    enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
 | 
			
		||||
    char name[MAX_CLUSTER_MEMBER_NAME_LEN];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct lock_wait
 | 
			
		||||
{
 | 
			
		||||
    pthread_cond_t cond;
 | 
			
		||||
    pthread_mutex_t mutex;
 | 
			
		||||
    int status;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Forward */
 | 
			
		||||
static int read_from_core_sock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
			       struct local_client **new_client);
 | 
			
		||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
			       struct local_client **new_client);
 | 
			
		||||
static int get_all_cluster_nodes(void);
 | 
			
		||||
 | 
			
		||||
/* In tcp-comms.c */
 | 
			
		||||
extern struct hash_table *sock_hash;
 | 
			
		||||
 | 
			
		||||
static int add_internal_client(int fd, fd_callback_t callback)
 | 
			
		||||
{
 | 
			
		||||
    struct local_client *client;
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("Add_internal_client, fd = %d\n", fd);
 | 
			
		||||
 | 
			
		||||
    /* Add a GULM file descriptor it to the main loop */
 | 
			
		||||
    client = malloc(sizeof(struct local_client));
 | 
			
		||||
    if (!client)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("malloc failed\n");
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(client, 0, sizeof(struct local_client));
 | 
			
		||||
    client->fd = fd;
 | 
			
		||||
    client->type = CLUSTER_INTERNAL;
 | 
			
		||||
    client->callback = callback;
 | 
			
		||||
    add_client(client);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Gulm library handle */
 | 
			
		||||
static gulm_interface_p gulm_if;
 | 
			
		||||
static lg_core_callbacks_t core_callbacks;
 | 
			
		||||
static lg_lockspace_callbacks_t lock_callbacks;
 | 
			
		||||
 | 
			
		||||
static void badsig_handler(int sig)
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("got sig %d\n", sig);
 | 
			
		||||
    cluster_closedown();
 | 
			
		||||
    exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sighup_handler(int sig)
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("got SIGHUP\n");
 | 
			
		||||
 | 
			
		||||
    /* Re-read CCS node list */
 | 
			
		||||
    get_all_cluster_nodes();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int init_cluster()
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
    int ccs_h;
 | 
			
		||||
    int port = 0;
 | 
			
		||||
    char *portstr;
 | 
			
		||||
 | 
			
		||||
    /* Get cluster name from CCS */
 | 
			
		||||
    /* TODO: is this right? */
 | 
			
		||||
    ccs_h = ccs_force_connect(NULL, 1); // PJC
 | 
			
		||||
    if (!ccs_h)
 | 
			
		||||
	return -1;
 | 
			
		||||
 | 
			
		||||
    ccs_get(ccs_h, "//cluster/@name", &cluster_name);
 | 
			
		||||
    DEBUGLOG("got cluster name %s\n", cluster_name);
 | 
			
		||||
 | 
			
		||||
    if (!ccs_get(ccs_h, "//clvm/@port", &portstr))
 | 
			
		||||
    {
 | 
			
		||||
	port = atoi(portstr);
 | 
			
		||||
	free(portstr);
 | 
			
		||||
	DEBUGLOG("got port number %d\n", port);
 | 
			
		||||
 | 
			
		||||
	if (port <= 0 && port >= 65536)
 | 
			
		||||
	    port = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ccs_disconnect(ccs_h);
 | 
			
		||||
 | 
			
		||||
    /* Block locking until we are logged in */
 | 
			
		||||
    pthread_mutex_init(&lock_start_mutex, NULL);
 | 
			
		||||
    pthread_mutex_lock(&lock_start_mutex);
 | 
			
		||||
    lock_start_flag = 1;
 | 
			
		||||
 | 
			
		||||
    node_hash = hash_create(100);
 | 
			
		||||
    lock_hash = hash_create(10);
 | 
			
		||||
 | 
			
		||||
    /* Get all nodes from CCS */
 | 
			
		||||
    if (get_all_cluster_nodes())
 | 
			
		||||
	return -1;
 | 
			
		||||
 | 
			
		||||
    /* Initialise GULM library */
 | 
			
		||||
    status = lg_initialize(&gulm_if, cluster_name, "clvmd");
 | 
			
		||||
    if (status)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("lg_initialize failed: %d\n", status);
 | 
			
		||||
	return status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Connect to core - we are not "important" :-) */
 | 
			
		||||
    status = lg_core_login(gulm_if, 0);
 | 
			
		||||
    if (status)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("lg_core_login failed: %d\n", status);
 | 
			
		||||
	return status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Initialise the inter-node comms */
 | 
			
		||||
    status = init_comms(port);
 | 
			
		||||
    if (status)
 | 
			
		||||
	return status;
 | 
			
		||||
 | 
			
		||||
    /* Add core FD to the list */
 | 
			
		||||
    status = add_internal_client(lg_core_selector(gulm_if), read_from_core_sock);
 | 
			
		||||
    if (status)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("can't allocate client space\n");
 | 
			
		||||
	return status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Connect to the lock server */
 | 
			
		||||
    if (lg_lock_login(gulm_if, "CLVM"))
 | 
			
		||||
    {
 | 
			
		||||
	syslog(LOG_ERR, "Cannot login in to LOCK server\n");
 | 
			
		||||
	DEBUGLOG("Cannot login in to LOCK server\n");
 | 
			
		||||
	exit(88);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Add lockspace FD to the list */
 | 
			
		||||
    status = add_internal_client(lg_lock_selector(gulm_if), read_from_lock_sock);
 | 
			
		||||
    if (status)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("can't allocate client space\n");
 | 
			
		||||
	exit(status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Request a list of nodes, we can;t really do anything until
 | 
			
		||||
       this comes back */
 | 
			
		||||
    status = lg_core_nodelist(gulm_if);
 | 
			
		||||
    if (status)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("lg_core_nodelist failed: %d\n", status);
 | 
			
		||||
	return status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* So I can kill it without taking GULM down too */
 | 
			
		||||
    signal(SIGINT, badsig_handler);
 | 
			
		||||
    signal(SIGTERM, badsig_handler);
 | 
			
		||||
 | 
			
		||||
    /* Re-read the node list on SIGHUP */
 | 
			
		||||
    signal(SIGHUP, sighup_handler);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cluster_closedown()
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("cluster_closedown\n");
 | 
			
		||||
    lg_lock_logout(gulm_if);
 | 
			
		||||
    lg_core_logout(gulm_if);
 | 
			
		||||
    lg_core_shutdown(gulm_if);
 | 
			
		||||
    lg_release(gulm_if);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Expire locks for a named node, or us */
 | 
			
		||||
#define GIO_KEY_SIZE 46
 | 
			
		||||
static void drop_expired_locks(char *nodename)
 | 
			
		||||
{
 | 
			
		||||
    struct utsname nodeinfo;
 | 
			
		||||
    uint8_t mask[GIO_KEY_SIZE];
 | 
			
		||||
 | 
			
		||||
    memset(mask, 0xff, GIO_KEY_SIZE);
 | 
			
		||||
 | 
			
		||||
    if (!nodename)
 | 
			
		||||
    {
 | 
			
		||||
	uname(&nodeinfo);
 | 
			
		||||
	nodename = nodeinfo.nodename;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (lg_lock_drop_exp(gulm_if, nodename, mask, GIO_KEY_SIZE))
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("Error calling lg_lock_drop_exp()\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int read_from_core_sock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
			       struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
 | 
			
		||||
    *new_client = NULL;
 | 
			
		||||
    status = lg_core_handle_messages(gulm_if, &core_callbacks, NULL);
 | 
			
		||||
    return status<0 ? status : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
			       struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
 | 
			
		||||
    *new_client = NULL;
 | 
			
		||||
    status = lg_lock_handle_messages(gulm_if, &lock_callbacks, NULL);
 | 
			
		||||
    return status<0 ? status : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* CORE callback routines */
 | 
			
		||||
static int core_login_reply(void *misc, uint64_t gen, uint32_t error, uint32_t rank, uint8_t corestate)
 | 
			
		||||
{
 | 
			
		||||
   DEBUGLOG("CORE Got a Login reply.  gen:%lld err:%d rank:%d corestate:%d\n",
 | 
			
		||||
         gen, error, rank, corestate);
 | 
			
		||||
 | 
			
		||||
   if (error)
 | 
			
		||||
       exit(error);
 | 
			
		||||
 | 
			
		||||
   current_corestate = corestate;
 | 
			
		||||
   return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_node_state(struct node_info *ninfo, char *csid, uint8_t nodestate)
 | 
			
		||||
{
 | 
			
		||||
    if (nodestate == lg_core_Logged_in)
 | 
			
		||||
    {
 | 
			
		||||
	/* Don't clobber NODE_CLVMD state */
 | 
			
		||||
	if (ninfo->state != NODE_CLVMD)
 | 
			
		||||
	{
 | 
			
		||||
	    if (ninfo->state == NODE_UNKNOWN ||
 | 
			
		||||
		ninfo->state == NODE_DOWN)
 | 
			
		||||
		num_nodes++;
 | 
			
		||||
 | 
			
		||||
	    ninfo->state = NODE_UP;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	if (nodestate == lg_core_Expired ||
 | 
			
		||||
	    nodestate == lg_core_Fenced ||
 | 
			
		||||
	    nodestate == lg_core_Logged_out)
 | 
			
		||||
	{
 | 
			
		||||
	    if (ninfo->state != NODE_DOWN)
 | 
			
		||||
		num_nodes--;
 | 
			
		||||
	    ninfo->state = NODE_DOWN;
 | 
			
		||||
	    tcp_remove_client(csid);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    DEBUGLOG("set_node_state, '%s' state = %d, num_nodes=%d\n",
 | 
			
		||||
	     ninfo->name, ninfo->state, num_nodes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_t state)
 | 
			
		||||
{
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
    ninfo = hash_lookup_binary(node_hash, (char *)ip, MAX_CSID_LEN);
 | 
			
		||||
    if (!ninfo)
 | 
			
		||||
    {
 | 
			
		||||
	/* If we can't find that node then re-read the config file in case it
 | 
			
		||||
	   was added after we were started */
 | 
			
		||||
	DEBUGLOG("Node %s not found, re-reading config file\n", name);
 | 
			
		||||
	get_all_cluster_nodes();
 | 
			
		||||
 | 
			
		||||
	/* Now try again */
 | 
			
		||||
	ninfo = hash_lookup_binary(node_hash, (char *)ip, MAX_CSID_LEN);
 | 
			
		||||
	if (!ninfo)
 | 
			
		||||
	{
 | 
			
		||||
	    DEBUGLOG("Ignoring node %s, not part of the SAN cluster\n", name);
 | 
			
		||||
	    return NULL;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set_node_state(ninfo, (char *)&ip, state);
 | 
			
		||||
 | 
			
		||||
    return ninfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int core_nodelist(void *misc, lglcb_t type, char *name, struct in6_addr *ip, uint8_t state)
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("CORE nodelist\n");
 | 
			
		||||
 | 
			
		||||
    if (type == lglcb_start)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("Got Nodelist, start\n");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	if (type == lglcb_item)
 | 
			
		||||
	{
 | 
			
		||||
	    DEBUGLOG("Got nodelist, item: %s, %#x\n", name, state);
 | 
			
		||||
 | 
			
		||||
	    add_or_set_node(name, ip, state);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	    if (type == lglcb_stop)
 | 
			
		||||
	    {
 | 
			
		||||
		char ourcsid[MAX_CSID_LEN];
 | 
			
		||||
 | 
			
		||||
		DEBUGLOG("Got Nodelist, stop\n");
 | 
			
		||||
		clvmd_cluster_init_completed();
 | 
			
		||||
 | 
			
		||||
		/* Mark ourself as up */
 | 
			
		||||
		get_our_csid(ourcsid);
 | 
			
		||||
		add_up_node(ourcsid);
 | 
			
		||||
	    }
 | 
			
		||||
	    else
 | 
			
		||||
	    {
 | 
			
		||||
		DEBUGLOG("Unknown lglcb_t %#x\n", type);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int core_statechange(void *misc, uint8_t corestate, uint8_t quorate, struct in6_addr *masterip, char *mastername)
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("CORE Got statechange  corestate:%#x mastername:%s\n",
 | 
			
		||||
	     corestate, mastername);
 | 
			
		||||
 | 
			
		||||
    current_corestate = corestate;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int core_nodechange(void *misc, char *nodename, struct in6_addr *nodeip, uint8_t nodestate)
 | 
			
		||||
{
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("CORE node change, name=%s, state = %d\n", nodename, nodestate);
 | 
			
		||||
 | 
			
		||||
    /* If we don't get nodeip here, try a lookup by name */
 | 
			
		||||
    if (!nodeip)
 | 
			
		||||
	csid_from_name((char *)nodeip, nodename);
 | 
			
		||||
    if (!nodeip)
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
    ninfo = add_or_set_node(nodename, nodeip, nodestate);
 | 
			
		||||
    if (!ninfo)
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
    /* Check if we need to drop any expired locks */
 | 
			
		||||
    if (ninfo->state == NODE_DOWN)
 | 
			
		||||
    {
 | 
			
		||||
	drop_expired_locks(nodename);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
static int core_error(void *misc, uint32_t err)
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("CORE error: %d\n", err);
 | 
			
		||||
    // Not sure what happens here
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* LOCK callback routines */
 | 
			
		||||
static int lock_login_reply(void *misc, uint32_t error, uint8_t which)
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("LOCK Got a Login reply.  err:%d which:%d\n",
 | 
			
		||||
	     error, which);
 | 
			
		||||
 | 
			
		||||
    if (error)
 | 
			
		||||
	exit(error);
 | 
			
		||||
 | 
			
		||||
    /* Drop any expired locks for us that might be hanging around */
 | 
			
		||||
    drop_expired_locks(NULL);
 | 
			
		||||
 | 
			
		||||
    /* Enable locking operations in other threads */
 | 
			
		||||
    if (lock_start_flag)
 | 
			
		||||
    {
 | 
			
		||||
	lock_start_flag = 0;
 | 
			
		||||
	pthread_mutex_unlock(&lock_start_mutex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int lock_lock_state(void *misc, uint8_t *key, uint16_t keylen,
 | 
			
		||||
			   uint64_t subid, uint64_t start, uint64_t stop,
 | 
			
		||||
			   uint8_t state, uint32_t flags, uint32_t error,
 | 
			
		||||
			   uint8_t *LVB, uint16_t LVBlen)
 | 
			
		||||
{
 | 
			
		||||
    struct lock_wait *lwait;
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("LOCK lock state: %s, error = %d\n", key, error);
 | 
			
		||||
 | 
			
		||||
    lwait = hash_lookup(lock_hash, key);
 | 
			
		||||
    if (!lwait)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("Can't find hash entry for resource %s\n", key);
 | 
			
		||||
	return 0;
 | 
			
		||||
    }
 | 
			
		||||
    lwait->status = error;
 | 
			
		||||
    pthread_mutex_lock(&lwait->mutex);
 | 
			
		||||
    pthread_cond_signal(&lwait->cond);
 | 
			
		||||
    pthread_mutex_unlock(&lwait->mutex);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
static int lock_error(void *misc, uint32_t err)
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("LOCK error: %d\n", err);
 | 
			
		||||
    // Not sure what happens here
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* CORE callbacks */
 | 
			
		||||
static lg_core_callbacks_t core_callbacks = {
 | 
			
		||||
    .login_reply  = core_login_reply,
 | 
			
		||||
    .nodelist     = core_nodelist,
 | 
			
		||||
    .statechange  = core_statechange,
 | 
			
		||||
    .nodechange   = core_nodechange,
 | 
			
		||||
    .error        = core_error,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* LOCK callbacks */
 | 
			
		||||
static lg_lockspace_callbacks_t lock_callbacks = {
 | 
			
		||||
    .login_reply   = lock_login_reply,
 | 
			
		||||
    .lock_state    = lock_lock_state,
 | 
			
		||||
    .error         = lock_error,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Allow tcp-comms to loop round the list of active nodes */
 | 
			
		||||
int get_next_node_csid(void **context, char *csid)
 | 
			
		||||
{
 | 
			
		||||
    struct node_info *ninfo = NULL;
 | 
			
		||||
 | 
			
		||||
    /* First node */
 | 
			
		||||
    if (!*context)
 | 
			
		||||
    {
 | 
			
		||||
	*context = hash_get_first(node_hash);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	*context = hash_get_next(node_hash, *context);
 | 
			
		||||
    }
 | 
			
		||||
    if (*context)
 | 
			
		||||
	ninfo = hash_get_data(node_hash, *context);
 | 
			
		||||
 | 
			
		||||
    /* Find a node that is UP */
 | 
			
		||||
    while (*context && ninfo->state == NODE_DOWN)
 | 
			
		||||
    {
 | 
			
		||||
	*context = hash_get_next(node_hash, *context);
 | 
			
		||||
	if (*context)
 | 
			
		||||
	{
 | 
			
		||||
	    ninfo = hash_get_data(node_hash, *context);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!*context || ninfo->state == NODE_DOWN)
 | 
			
		||||
    {
 | 
			
		||||
	return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(csid, hash_get_key(node_hash, *context), MAX_CSID_LEN);
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int name_from_csid(char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
    ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
    if (!ninfo)
 | 
			
		||||
    {
 | 
			
		||||
        sprintf(name, "UNKNOWN %s", print_csid(csid));
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    strcpy(name, ninfo->name);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int csid_from_name(char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
    struct hash_node *hn;
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
    hash_iterate(hn, node_hash)
 | 
			
		||||
    {
 | 
			
		||||
	ninfo = hash_get_data(node_hash, hn);
 | 
			
		||||
	if (strcmp(ninfo->name, name) == 0)
 | 
			
		||||
	{
 | 
			
		||||
	    memcpy(csid, hash_get_key(node_hash, hn), MAX_CSID_LEN);
 | 
			
		||||
	    return 0;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_num_nodes()
 | 
			
		||||
{
 | 
			
		||||
    DEBUGLOG("num_nodes = %d\n", num_nodes);
 | 
			
		||||
    return num_nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Node is now known to be running a clvmd */
 | 
			
		||||
void add_up_node(char *csid)
 | 
			
		||||
{
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
    ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
    if (!ninfo)
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
    ninfo->state = NODE_CLVMD;
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/* Node is now known to be NOT running a clvmd */
 | 
			
		||||
void add_down_node(char *csid)
 | 
			
		||||
{
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
    ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
    if (!ninfo)
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
    /* Only set it to UP if it was previously known to be
 | 
			
		||||
       running clvmd - gulm may set it DOWN quite soon */
 | 
			
		||||
    if (ninfo->state == NODE_CLVMD)
 | 
			
		||||
	ninfo->state = NODE_UP;
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Call a callback for each node, so the caller knows whether it's up or down */
 | 
			
		||||
int cluster_do_node_callback(struct local_client *master_client,
 | 
			
		||||
			     void (*callback)(struct local_client *, char *csid, int node_up))
 | 
			
		||||
{
 | 
			
		||||
    struct hash_node *hn;
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
    hash_iterate(hn, node_hash)
 | 
			
		||||
    {
 | 
			
		||||
	char csid[MAX_CSID_LEN];
 | 
			
		||||
	struct local_client *client;
 | 
			
		||||
 | 
			
		||||
	ninfo = hash_get_data(node_hash, hn);
 | 
			
		||||
	memcpy(csid, hash_get_key(node_hash, hn), MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("down_callback. node %s, state = %d\n", ninfo->name, ninfo->state);
 | 
			
		||||
 | 
			
		||||
	client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
	if (client)
 | 
			
		||||
	    callback(master_client, csid, ninfo->state == NODE_CLVMD);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert gulm error codes to unix errno numbers */
 | 
			
		||||
static int gulm_to_errno(int gulm_ret)
 | 
			
		||||
{
 | 
			
		||||
    switch (gulm_ret)
 | 
			
		||||
    {
 | 
			
		||||
    case lg_err_TryFailed:
 | 
			
		||||
	errno = EAGAIN;
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case lg_err_AlreadyPend:
 | 
			
		||||
	errno = EBUSY;
 | 
			
		||||
 | 
			
		||||
	/* More?? */
 | 
			
		||||
    default:
 | 
			
		||||
	errno = EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return gulm_ret ? -1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Real locking */
 | 
			
		||||
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
    struct lock_wait lwait;
 | 
			
		||||
 | 
			
		||||
    /* Wait until the lock module is ready */
 | 
			
		||||
    if (lock_start_flag)
 | 
			
		||||
    {
 | 
			
		||||
	pthread_mutex_lock(&lock_start_mutex);
 | 
			
		||||
	pthread_mutex_unlock(&lock_start_mutex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pthread_cond_init(&lwait.cond, NULL);
 | 
			
		||||
    pthread_mutex_init(&lwait.mutex, NULL);
 | 
			
		||||
    pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
    /* This needs to be converted from DLM/LVM2 value for GULM */
 | 
			
		||||
    if (flags == LCK_NONBLOCK) flags = lg_lock_flag_Try;
 | 
			
		||||
 | 
			
		||||
    hash_insert(lock_hash, resource, &lwait);
 | 
			
		||||
    DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
 | 
			
		||||
 | 
			
		||||
    status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
 | 
			
		||||
			       0, 0, 0,
 | 
			
		||||
			       mode, flags, NULL, 0);
 | 
			
		||||
    if (status)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("lg_lock_state returned %d\n", status);
 | 
			
		||||
	return status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Wait for it to complete */
 | 
			
		||||
    pthread_cond_wait(&lwait.cond, &lwait.mutex);
 | 
			
		||||
    pthread_mutex_unlock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
    hash_remove(lock_hash, resource);
 | 
			
		||||
    DEBUGLOG("lock-resource returning %d\n", lwait.status);
 | 
			
		||||
 | 
			
		||||
    return gulm_to_errno(lwait.status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int _unlock_resource(char *resource, int lockid)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
    struct lock_wait lwait;
 | 
			
		||||
 | 
			
		||||
    pthread_cond_init(&lwait.cond, NULL);
 | 
			
		||||
    pthread_mutex_init(&lwait.mutex, NULL);
 | 
			
		||||
    pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
    hash_insert(lock_hash, resource, &lwait);
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("unlock_resource %s\n", resource);
 | 
			
		||||
    status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
 | 
			
		||||
			       0, 0, 0,
 | 
			
		||||
			       lg_lock_state_Unlock, 0, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    if (status)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("lg_lock_state(unlock) returned %d\n", status);
 | 
			
		||||
	return status;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Wait for it to complete */
 | 
			
		||||
 | 
			
		||||
    pthread_cond_wait(&lwait.cond, &lwait.mutex);
 | 
			
		||||
    pthread_mutex_unlock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
    hash_remove(lock_hash, resource);
 | 
			
		||||
 | 
			
		||||
    return gulm_to_errno(lwait.status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* These two locking functions MUST be called in a seperate thread from
 | 
			
		||||
   the clvmd main loop because they expect to be woken up by it.
 | 
			
		||||
 | 
			
		||||
   These are abstractions around the real locking functions (above)
 | 
			
		||||
   as we need to emulate the DLM's EX/PW/CW interaction with GULM using
 | 
			
		||||
   two locks.
 | 
			
		||||
   To aid unlocking, we store the lock mode in the lockid (as GULM
 | 
			
		||||
   doesn't use this).
 | 
			
		||||
*/
 | 
			
		||||
int sync_lock(const char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
    char lock1[strlen(resource)+3];
 | 
			
		||||
    char lock2[strlen(resource)+3];
 | 
			
		||||
 | 
			
		||||
    snprintf(lock1, sizeof(lock1), "%s-1", resource);
 | 
			
		||||
    snprintf(lock2, sizeof(lock2), "%s-2", resource);
 | 
			
		||||
 | 
			
		||||
    switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
    case LCK_EXCL:
 | 
			
		||||
	status = _lock_resource(lock1, lg_lock_state_Exclusive, flags, lockid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    goto out;
 | 
			
		||||
 | 
			
		||||
	/* If we can't get this lock then bail out */
 | 
			
		||||
	status = _lock_resource(lock2, lg_lock_state_Exclusive, LCK_NONBLOCK, lockid);
 | 
			
		||||
        if (status == lg_err_TryFailed)
 | 
			
		||||
        {
 | 
			
		||||
           _unlock_resource(lock1, *lockid);
 | 
			
		||||
           status = -1;
 | 
			
		||||
           errno = EAGAIN;
 | 
			
		||||
        }
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case LCK_READ:
 | 
			
		||||
	status = _lock_resource(lock1, lg_lock_state_Shared, flags, lockid);
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case LCK_WRITE:
 | 
			
		||||
	status = _lock_resource(lock2, lg_lock_state_Exclusive, flags, lockid);
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
	status = -1;
 | 
			
		||||
	errno = EINVAL;
 | 
			
		||||
	break;
 | 
			
		||||
    }
 | 
			
		||||
 out:
 | 
			
		||||
    *lockid = mode;
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sync_unlock(const char *resource, int lockid)
 | 
			
		||||
{
 | 
			
		||||
    int status = 0;
 | 
			
		||||
    char lock1[strlen(resource)+3];
 | 
			
		||||
    char lock2[strlen(resource)+3];
 | 
			
		||||
 | 
			
		||||
    snprintf(lock1, sizeof(lock1), "%s-1", resource);
 | 
			
		||||
    snprintf(lock2, sizeof(lock2), "%s-2", resource);
 | 
			
		||||
 | 
			
		||||
    /* The held lock mode is in the lock id */
 | 
			
		||||
    assert(lockid == LCK_EXCL ||
 | 
			
		||||
	   lockid == LCK_READ ||
 | 
			
		||||
	   lockid == LCK_WRITE);
 | 
			
		||||
 | 
			
		||||
    switch (lockid)
 | 
			
		||||
    {
 | 
			
		||||
    case LCK_EXCL:
 | 
			
		||||
	status = _unlock_resource(lock1, lockid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    goto out;
 | 
			
		||||
	status = _unlock_resource(lock2, lockid);
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case LCK_READ:
 | 
			
		||||
	status = _unlock_resource(lock1, lockid);
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case LCK_WRITE:
 | 
			
		||||
	status = _unlock_resource(lock2, lockid);
 | 
			
		||||
	break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int is_quorate()
 | 
			
		||||
{
 | 
			
		||||
    if (current_corestate == lg_core_Slave ||
 | 
			
		||||
	current_corestate == lg_core_Master ||
 | 
			
		||||
	current_corestate == lg_core_Client)
 | 
			
		||||
	return 1;
 | 
			
		||||
    else
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get all the cluster node names & IPs from CCS and
 | 
			
		||||
   add them to our node list so we know who to talk to.
 | 
			
		||||
   Called when we start up and if we get sent SIGHUP.
 | 
			
		||||
*/
 | 
			
		||||
static int get_all_cluster_nodes()
 | 
			
		||||
{
 | 
			
		||||
    int ctree;
 | 
			
		||||
    char *nodename;
 | 
			
		||||
    int error;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    /* Open the config file */
 | 
			
		||||
    ctree = ccs_force_connect(NULL, 1);
 | 
			
		||||
    if (ctree <= 0)
 | 
			
		||||
    {
 | 
			
		||||
	log_error("Error connecting to CCS");
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i=1; i++;)
 | 
			
		||||
    {
 | 
			
		||||
	char nodekey[256];
 | 
			
		||||
	char nodeip[MAX_CSID_LEN];
 | 
			
		||||
	int  clvmflag = 1;
 | 
			
		||||
	char *clvmflagstr;
 | 
			
		||||
	char key[256];
 | 
			
		||||
 | 
			
		||||
	sprintf(nodekey, "//cluster/nodes/node[%d]/@name", i);
 | 
			
		||||
	error = ccs_get(ctree, nodekey, &nodename);
 | 
			
		||||
	if (error)
 | 
			
		||||
	    break;
 | 
			
		||||
 | 
			
		||||
	sprintf(key, "//nodes/node[@name=\"%s\"]/clvm", nodename);
 | 
			
		||||
	if (!ccs_get(ctree, key, &clvmflagstr))
 | 
			
		||||
	{
 | 
			
		||||
	    clvmflag = atoi(clvmflagstr);
 | 
			
		||||
	    free(clvmflagstr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Got node %s from ccs(clvmflag = %d)\n", nodename, clvmflag);
 | 
			
		||||
	if ((get_ip_address(nodename, nodeip) == 0) && clvmflag)
 | 
			
		||||
	{
 | 
			
		||||
	    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
	    /* If it's not in the list, then add it */
 | 
			
		||||
	    ninfo = hash_lookup_binary(node_hash, nodeip, MAX_CSID_LEN);
 | 
			
		||||
	    if (!ninfo)
 | 
			
		||||
	    {
 | 
			
		||||
		ninfo = malloc(sizeof(struct node_info));
 | 
			
		||||
		if (!ninfo)
 | 
			
		||||
		{
 | 
			
		||||
		    syslog(LOG_ERR, "Cannot alloc memory for node info\n");
 | 
			
		||||
		    ccs_disconnect(ctree);
 | 
			
		||||
		    return -1;
 | 
			
		||||
		}
 | 
			
		||||
		strcpy(ninfo->name, nodename);
 | 
			
		||||
 | 
			
		||||
		ninfo->state = NODE_DOWN;
 | 
			
		||||
		hash_insert_binary(node_hash, nodeip, MAX_CSID_LEN, ninfo);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	    DEBUGLOG("node %s has clvm disabled\n", nodename);
 | 
			
		||||
	}
 | 
			
		||||
	free(nodename);
 | 
			
		||||
	error = ccs_get(ctree, "//nodes/node/@name", &nodename);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Finished with config file */
 | 
			
		||||
    ccs_disconnect(ctree);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int gulm_fd(void)
 | 
			
		||||
{
 | 
			
		||||
    return lg_core_selector(gulm_if);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								daemons/clvmd/clvmd-gulm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								daemons/clvmd/clvmd-gulm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern int get_next_node_csid(void **context, char *csid);
 | 
			
		||||
extern void add_down_node(char *csid);
 | 
			
		||||
extern int gulm_fd(void);
 | 
			
		||||
extern int get_ip_address(char *node, char *addr);
 | 
			
		||||
extern void tcp_remove_client(char *csid);
 | 
			
		||||
extern int alloc_client(int fd, char *csid, struct local_client **new_client);
 | 
			
		||||
							
								
								
									
										1743
									
								
								daemons/clvmd/clvmd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1743
									
								
								daemons/clvmd/clvmd.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										119
									
								
								daemons/clvmd/clvmd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								daemons/clvmd/clvmd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _CLVMD_H
 | 
			
		||||
#define _CLVMD_H
 | 
			
		||||
 | 
			
		||||
#define CLVMD_MAJOR_VERSION 0
 | 
			
		||||
#define CLVMD_MINOR_VERSION 2
 | 
			
		||||
#define CLVMD_PATCH_VERSION 1
 | 
			
		||||
 | 
			
		||||
/* Name of the cluster LVM admin lock */
 | 
			
		||||
#define ADMIN_LOCK_NAME "CLVMD_ADMIN"
 | 
			
		||||
 | 
			
		||||
/* Default time (in seconds) we will wait for all remote commands to execute
 | 
			
		||||
   before declaring them dead */
 | 
			
		||||
#define DEFAULT_CMD_TIMEOUT 60
 | 
			
		||||
 | 
			
		||||
/* One of these for each reply we get from command execution on a node */
 | 
			
		||||
struct node_reply {
 | 
			
		||||
	char node[MAX_CLUSTER_MEMBER_NAME_LEN];
 | 
			
		||||
	char *replymsg;
 | 
			
		||||
	int status;
 | 
			
		||||
	struct node_reply *next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * These exist for the use of local sockets only when we are
 | 
			
		||||
 * collecting responses from all cluster nodes
 | 
			
		||||
 */
 | 
			
		||||
struct localsock_bits {
 | 
			
		||||
	struct node_reply *replies;
 | 
			
		||||
	int num_replies;
 | 
			
		||||
	int expected_replies;
 | 
			
		||||
	time_t sent_time;	/* So we can check for timeouts */
 | 
			
		||||
	int in_progress;	/* Only execute one cmd at a time per client */
 | 
			
		||||
	int sent_out;		/* Flag to indicate that a command was sent
 | 
			
		||||
				   to remote nodes */
 | 
			
		||||
	void *private;		/* Private area for command processor use */
 | 
			
		||||
	void *cmd;		/* Whole command as passed down local socket */
 | 
			
		||||
	int cmd_len;		/* Length of above */
 | 
			
		||||
	int pipe;		/* Pipe to send PRE completion status down */
 | 
			
		||||
	int finished;		/* Flag to tell subthread to exit */
 | 
			
		||||
	int all_success;	/* Set to 0 if any node (or the pre_command)
 | 
			
		||||
				   failed */
 | 
			
		||||
	struct local_client *pipe_client;
 | 
			
		||||
	pthread_t threadid;
 | 
			
		||||
	enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
 | 
			
		||||
	pthread_mutex_t mutex;	/* Main thread and worker synchronisation */
 | 
			
		||||
	pthread_cond_t cond;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_t reply_mutex;	/* Protect reply structure */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Entries for PIPE clients */
 | 
			
		||||
struct pipe_bits {
 | 
			
		||||
	struct local_client *client;	/* Actual (localsock) client */
 | 
			
		||||
	pthread_t threadid;		/* Our own copy of the thread id */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Entries for Network socket clients */
 | 
			
		||||
struct netsock_bits {
 | 
			
		||||
	void *private;
 | 
			
		||||
	int flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
 | 
			
		||||
			      char *csid, struct local_client ** new_client);
 | 
			
		||||
 | 
			
		||||
/* One of these for each fd we are listening on */
 | 
			
		||||
struct local_client {
 | 
			
		||||
	int fd;
 | 
			
		||||
	enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
 | 
			
		||||
		    LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
 | 
			
		||||
	struct local_client *next;
 | 
			
		||||
	unsigned short xid;
 | 
			
		||||
	fd_callback_t callback;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct localsock_bits localsock;
 | 
			
		||||
		struct pipe_bits pipe;
 | 
			
		||||
		struct netsock_bits net;
 | 
			
		||||
	} bits;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#define DEBUGLOG(fmt, args...) fprintf(stderr, "CLVMD[%d]: %ld ", getpid(), time(NULL) ); fprintf(stderr, fmt, ## args)
 | 
			
		||||
#else
 | 
			
		||||
#define DEBUGLOG(fmt, args...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef max
 | 
			
		||||
#define max(a,b) ((a)>(b)?(a):(b))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The real command processor is in clvmd-command.c */
 | 
			
		||||
extern int do_command(struct local_client *client, struct clvm_header *msg,
 | 
			
		||||
		      int msglen, char **buf, int buflen, int *retlen);
 | 
			
		||||
 | 
			
		||||
/* Pre and post command routines are called only on the local node */
 | 
			
		||||
extern int do_pre_command(struct local_client *client);
 | 
			
		||||
extern int do_post_command(struct local_client *client);
 | 
			
		||||
extern void cmd_client_cleanup(struct local_client *client);
 | 
			
		||||
extern int add_client(struct local_client *new_client);
 | 
			
		||||
 | 
			
		||||
extern void clvmd_cluster_init_completed(void);
 | 
			
		||||
extern void process_message(struct local_client *client, char *buf, int len, char *csid);
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										226
									
								
								daemons/clvmd/cnxman-socket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								daemons/clvmd/cnxman-socket.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,226 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
**
 | 
			
		||||
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
 | 
			
		||||
**  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
 | 
			
		||||
**
 | 
			
		||||
**  This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
**  modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
**  of the GNU General Public License v.2.
 | 
			
		||||
**
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* CMAN socket interface header,
 | 
			
		||||
   may be include by user or kernel code */
 | 
			
		||||
 | 
			
		||||
#ifndef __CNXMAN_SOCKET_H
 | 
			
		||||
#define __CNXMAN_SOCKET_H
 | 
			
		||||
 | 
			
		||||
/* A currently unused number. TIPC also uses this number and you're unlikely
 | 
			
		||||
   to be using both.
 | 
			
		||||
 */
 | 
			
		||||
#define AF_CLUSTER 30
 | 
			
		||||
#define PF_CLUSTER AF_CLUSTER
 | 
			
		||||
 | 
			
		||||
/* Protocol(socket) types */
 | 
			
		||||
#define CLPROTO_MASTER 2
 | 
			
		||||
#define CLPROTO_CLIENT 3
 | 
			
		||||
 | 
			
		||||
/* ioctls -- should register these properly */
 | 
			
		||||
#define SIOCCLUSTER_NOTIFY            _IOW('x', 0x01, int)
 | 
			
		||||
#define SIOCCLUSTER_REMOVENOTIFY      _IO( 'x', 0x02)
 | 
			
		||||
#define SIOCCLUSTER_GETMEMBERS        _IOR('x', 0x03, struct cl_cluster_nodelist)
 | 
			
		||||
#define SIOCCLUSTER_SETEXPECTED_VOTES _IOW('x', 0x04, int)
 | 
			
		||||
#define SIOCCLUSTER_ISQUORATE         _IO( 'x', 0x05)
 | 
			
		||||
#define SIOCCLUSTER_ISLISTENING       _IOW('x', 0x06, struct cl_listen_request)
 | 
			
		||||
#define SIOCCLUSTER_GETALLMEMBERS     _IOR('x', 0x07, struct cl_cluster_nodelist)
 | 
			
		||||
#define SIOCCLUSTER_SET_VOTES         _IOW('x', 0x08, int)
 | 
			
		||||
#define SIOCCLUSTER_GET_VERSION       _IOR('x', 0x09, struct cl_version)
 | 
			
		||||
#define SIOCCLUSTER_SET_VERSION       _IOW('x', 0x0a, struct cl_version)
 | 
			
		||||
#define SIOCCLUSTER_ISACTIVE          _IO( 'x', 0x0b)
 | 
			
		||||
#define SIOCCLUSTER_KILLNODE          _IOW('x', 0x0c, int)
 | 
			
		||||
#define SIOCCLUSTER_GET_JOINCOUNT     _IO( 'x', 0x0d)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_REGISTER  _IOW('x', 0x0e, char)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_UNREGISTER _IO('x', 0x0f)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_JOIN      _IO( 'x', 0x10)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_LEAVE     _IO( 'x', 0x20)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_SETSIGNAL _IOW('x', 0x30, int)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_STARTDONE _IOW('x', 0x40, unsigned int)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_GETEVENT  _IOR('x', 0x50, struct cl_service_event)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_GETMEMBERS _IOR('x', 0x60, struct cl_cluster_nodelist)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_GLOBALID  _IOR('x', 0x70, uint32_t)
 | 
			
		||||
#define SIOCCLUSTER_SERVICE_SETLEVEL  _IOR('x', 0x80, int)
 | 
			
		||||
#define SIOCCLUSTER_GETNODE	      _IOWR('x', 0x90, struct cl_cluster_node)
 | 
			
		||||
#define SIOCCLUSTER_BARRIER           _IOW('x', 0x0a0, struct cl_barrier_info)
 | 
			
		||||
 | 
			
		||||
/* These were setsockopts */
 | 
			
		||||
#define SIOCCLUSTER_PASS_SOCKET       _IOW('x', 0x0b0, struct cl_passed_sock)
 | 
			
		||||
#define SIOCCLUSTER_SET_NODENAME      _IOW('x', 0x0b1, char *)
 | 
			
		||||
#define SIOCCLUSTER_SET_NODEID        _IOW('x', 0x0b2, int)
 | 
			
		||||
#define SIOCCLUSTER_JOIN_CLUSTER      _IOW('x', 0x0b3, struct cl_join_cluster_info)
 | 
			
		||||
#define SIOCCLUSTER_LEAVE_CLUSTER     _IOW('x', 0x0b4, int)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Maximum size of a cluster message */
 | 
			
		||||
#define MAX_CLUSTER_MESSAGE          1500
 | 
			
		||||
#define MAX_CLUSTER_MEMBER_NAME_LEN   255
 | 
			
		||||
#define MAX_BARRIER_NAME_LEN           33
 | 
			
		||||
#define MAX_SA_ADDR_LEN                12
 | 
			
		||||
#define MAX_CLUSTER_NAME_LEN           16
 | 
			
		||||
 | 
			
		||||
/* Well-known cluster port numbers */
 | 
			
		||||
#define CLUSTER_PORT_MEMBERSHIP  1	/* Mustn't block during cluster
 | 
			
		||||
					 * transitions! */
 | 
			
		||||
#define CLUSTER_PORT_SERVICES    2
 | 
			
		||||
#define CLUSTER_PORT_SYSMAN      10	/* Remote execution daemon */
 | 
			
		||||
#define CLUSTER_PORT_CLVMD       11	/* Cluster LVM daemon */
 | 
			
		||||
#define CLUSTER_PORT_SLM         12	/* LVM SLM (simple lock manager) */
 | 
			
		||||
 | 
			
		||||
/* Port numbers above this will be blocked when the cluster is inquorate or in
 | 
			
		||||
 * transition */
 | 
			
		||||
#define HIGH_PROTECTED_PORT      9
 | 
			
		||||
 | 
			
		||||
/* Reasons for leaving the cluster */
 | 
			
		||||
#define CLUSTER_LEAVEFLAG_DOWN     0	/* Normal shutdown */
 | 
			
		||||
#define CLUSTER_LEAVEFLAG_KILLED   1
 | 
			
		||||
#define CLUSTER_LEAVEFLAG_PANIC    2
 | 
			
		||||
#define CLUSTER_LEAVEFLAG_REMOVED  3	/* This one can reduce quorum */
 | 
			
		||||
#define CLUSTER_LEAVEFLAG_REJECTED 4	/* Not allowed into the cluster in the
 | 
			
		||||
					 * first place */
 | 
			
		||||
#define CLUSTER_LEAVEFLAG_INCONSISTENT 5	/* Our view of the cluster is
 | 
			
		||||
						 * in a minority */
 | 
			
		||||
#define CLUSTER_LEAVEFLAG_DEAD         6	/* Discovered to be dead */
 | 
			
		||||
#define CLUSTER_LEAVEFLAG_FORCE     0x10	/* Forced by command-line */
 | 
			
		||||
 | 
			
		||||
/* OOB messages sent to a local socket */
 | 
			
		||||
#define CLUSTER_OOB_MSG_PORTCLOSED  1
 | 
			
		||||
#define CLUSTER_OOB_MSG_STATECHANGE 2
 | 
			
		||||
#define CLUSTER_OOB_MSG_SERVICEEVENT 3
 | 
			
		||||
 | 
			
		||||
/* Sendmsg flags, these are above the normal sendmsg flags so they don't
 | 
			
		||||
 * interfere */
 | 
			
		||||
#define MSG_NOACK     0x010000	/* Don't need an ACK for this message */
 | 
			
		||||
#define MSG_QUEUE     0x020000	/* Queue the message for sending later */
 | 
			
		||||
#define MSG_MULTICAST 0x080000	/* Message was sent to all nodes in the cluster
 | 
			
		||||
				 */
 | 
			
		||||
#define MSG_ALLINT    0x100000	/* Send out of all interfaces */
 | 
			
		||||
#define MSG_REPLYEXP  0x200000	/* Reply is expected */
 | 
			
		||||
 | 
			
		||||
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
 | 
			
		||||
	       NODESTATE_DEAD } nodestate_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct sockaddr_cl {
 | 
			
		||||
	unsigned short scl_family;
 | 
			
		||||
	unsigned char scl_flags;
 | 
			
		||||
	unsigned char scl_port;
 | 
			
		||||
	int           scl_nodeid;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is how we pass the multicast & receive sockets into kernel space.
 | 
			
		||||
 */
 | 
			
		||||
struct cl_passed_sock {
 | 
			
		||||
	int fd;			/* FD of master socket to do multicast on */
 | 
			
		||||
	int number;		/* Socket number, to match up recvonly & bcast
 | 
			
		||||
				 * sockets */
 | 
			
		||||
        int multicast;          /* Is it multicast or receive ? */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Cluster configuration info passed when we join the cluster */
 | 
			
		||||
struct cl_join_cluster_info {
 | 
			
		||||
	unsigned char votes;
 | 
			
		||||
	unsigned int expected_votes;
 | 
			
		||||
	unsigned int two_node;
 | 
			
		||||
	unsigned int config_version;
 | 
			
		||||
 | 
			
		||||
        char cluster_name[17];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* This is the structure, per node, returned from the membership ioctl */
 | 
			
		||||
struct cl_cluster_node {
 | 
			
		||||
	unsigned int size;
 | 
			
		||||
	unsigned int node_id;
 | 
			
		||||
	unsigned int us;
 | 
			
		||||
	unsigned int leave_reason;
 | 
			
		||||
	unsigned int incarnation;
 | 
			
		||||
	nodestate_t state;
 | 
			
		||||
	char name[MAX_CLUSTER_MEMBER_NAME_LEN];
 | 
			
		||||
	unsigned char votes;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* The struct passed to the membership ioctls */
 | 
			
		||||
struct cl_cluster_nodelist {
 | 
			
		||||
        uint32_t max_members;
 | 
			
		||||
        struct cl_cluster_node *nodes;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Structure passed to SIOCCLUSTER_ISLISTENING */
 | 
			
		||||
struct cl_listen_request {
 | 
			
		||||
	unsigned char port;
 | 
			
		||||
        int           nodeid;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* A Cluster PORTCLOSED message - received by a local user as an OOB message */
 | 
			
		||||
struct cl_portclosed_oob {
 | 
			
		||||
	unsigned char cmd;	/* CLUSTER_OOB_MSG_PORTCLOSED */
 | 
			
		||||
	unsigned char port;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Get all version numbers or set the config version */
 | 
			
		||||
struct cl_version {
 | 
			
		||||
	unsigned int major;
 | 
			
		||||
	unsigned int minor;
 | 
			
		||||
	unsigned int patch;
 | 
			
		||||
	unsigned int config;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* structure passed to barrier ioctls */
 | 
			
		||||
struct cl_barrier_info {
 | 
			
		||||
	char cmd;
 | 
			
		||||
	char name[MAX_BARRIER_NAME_LEN];
 | 
			
		||||
	unsigned int flags;
 | 
			
		||||
	unsigned long arg;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef enum { SERVICE_EVENT_STOP, SERVICE_EVENT_START, SERVICE_EVENT_FINISH,
 | 
			
		||||
		SERVICE_EVENT_LEAVEDONE } service_event_t;
 | 
			
		||||
 | 
			
		||||
typedef enum { SERVICE_START_FAILED, SERVICE_START_JOIN, SERVICE_START_LEAVE }
 | 
			
		||||
		service_start_t;
 | 
			
		||||
 | 
			
		||||
struct cl_service_event {
 | 
			
		||||
	service_event_t type;
 | 
			
		||||
	service_start_t start_type;
 | 
			
		||||
	unsigned int event_id;
 | 
			
		||||
	unsigned int last_stop;
 | 
			
		||||
	unsigned int last_start;
 | 
			
		||||
	unsigned int last_finish;
 | 
			
		||||
	unsigned int node_count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Commands to the barrier ioctl */
 | 
			
		||||
#define BARRIER_IOCTL_REGISTER 1
 | 
			
		||||
#define BARRIER_IOCTL_CHANGE   2
 | 
			
		||||
#define BARRIER_IOCTL_DELETE   3
 | 
			
		||||
#define BARRIER_IOCTL_WAIT     4
 | 
			
		||||
 | 
			
		||||
/* Attributes of a barrier - bitmask */
 | 
			
		||||
#define BARRIER_ATTR_AUTODELETE 1
 | 
			
		||||
#define BARRIER_ATTR_MULTISTEP  2
 | 
			
		||||
#define BARRIER_ATTR_MANUAL     4
 | 
			
		||||
#define BARRIER_ATTR_ENABLED    8
 | 
			
		||||
#define BARRIER_ATTR_CALLBACK  16
 | 
			
		||||
 | 
			
		||||
/* Attribute setting commands */
 | 
			
		||||
#define BARRIER_SETATTR_AUTODELETE 1
 | 
			
		||||
#define BARRIER_SETATTR_MULTISTEP  2
 | 
			
		||||
#define BARRIER_SETATTR_ENABLED    3
 | 
			
		||||
#define BARRIER_SETATTR_NODES      4
 | 
			
		||||
#define BARRIER_SETATTR_CALLBACK   5
 | 
			
		||||
#define BARRIER_SETATTR_TIMEOUT    6
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										446
									
								
								daemons/clvmd/libclvm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										446
									
								
								daemons/clvmd/libclvm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,446 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1997-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* library functions for Cluster LVM Daemon */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/uio.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <search.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "libclvm.h"
 | 
			
		||||
 | 
			
		||||
/* CLVM in hex! */
 | 
			
		||||
#define LVM_SIGNATURE 0x434C564D
 | 
			
		||||
 | 
			
		||||
#define MAX_CLUSTER_MEMBER_NAME_LEN 255
 | 
			
		||||
 | 
			
		||||
/* NOTE: the LVMD uses the socket FD as the client ID, this means
 | 
			
		||||
   that any client that calls fork() will inherit the context of
 | 
			
		||||
   it's parent. */
 | 
			
		||||
static int clvmd_sock = -1;
 | 
			
		||||
 | 
			
		||||
static int open_local_sock(void)
 | 
			
		||||
{
 | 
			
		||||
	int local_socket;
 | 
			
		||||
	struct sockaddr_un sockaddr;
 | 
			
		||||
 | 
			
		||||
	/* Open local socket */
 | 
			
		||||
	local_socket = socket(PF_UNIX, SOCK_STREAM, 0);
 | 
			
		||||
	if (local_socket < 0) {
 | 
			
		||||
		perror("Can't create local socket");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fcntl(local_socket, F_SETFD, !FD_CLOEXEC);
 | 
			
		||||
 | 
			
		||||
	strcpy(sockaddr.sun_path, CLVMD_SOCKNAME);
 | 
			
		||||
	sockaddr.sun_family = AF_UNIX;
 | 
			
		||||
	if (connect
 | 
			
		||||
	    (local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
 | 
			
		||||
		int saved_errno = errno;
 | 
			
		||||
 | 
			
		||||
		close(local_socket);
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
	fd_set fds;
 | 
			
		||||
 | 
			
		||||
	FD_ZERO(&fds);
 | 
			
		||||
	FD_SET(clvmd_sock, &fds);
 | 
			
		||||
 | 
			
		||||
	/* Send it to CLVMD */
 | 
			
		||||
	if (write(clvmd_sock, inbuf, inlen) != inlen) {
 | 
			
		||||
		perror("Error writing to CLVMD");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the response */
 | 
			
		||||
	if ((len = read(clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
 | 
			
		||||
		perror("Error reading CLVMD");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	if (len == 0) {
 | 
			
		||||
		fprintf(stderr, "EOF reading CLVMD");
 | 
			
		||||
		errno = ENOTCONN;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Allocate buffer */
 | 
			
		||||
	*retbuf = malloc(len + outheader->arglen);
 | 
			
		||||
	if (!*retbuf) {
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* 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, PIPE_BUF);
 | 
			
		||||
		if (len > 0)
 | 
			
		||||
			off += len;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Was it an error ? */
 | 
			
		||||
	if (outheader->status < 0) {
 | 
			
		||||
		errno = -outheader->status;
 | 
			
		||||
		return -2;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Build the structure header and parse-out wildcard node names */
 | 
			
		||||
static void build_header(struct clvm_header *head, int cmd, const char *node,
 | 
			
		||||
			 void *data, 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 */
 | 
			
		||||
int lvm_cluster_write(char cmd, char *node, void *data, int len)
 | 
			
		||||
{
 | 
			
		||||
	char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
 | 
			
		||||
	char *retbuf = NULL;
 | 
			
		||||
	int status;
 | 
			
		||||
	struct clvm_header *head = (struct clvm_header *) outbuf;
 | 
			
		||||
 | 
			
		||||
	if (clvmd_sock == -1)
 | 
			
		||||
		clvmd_sock = open_local_sock();
 | 
			
		||||
	if (clvmd_sock == -1)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	build_header(head, cmd, node, data, len);
 | 
			
		||||
	memcpy(head->node + strlen(head->node) + 1, data, len);
 | 
			
		||||
 | 
			
		||||
	status =
 | 
			
		||||
	    send_request(outbuf,
 | 
			
		||||
			 sizeof(struct clvm_header) + strlen(head->node) + len,
 | 
			
		||||
			 &retbuf);
 | 
			
		||||
	if (retbuf)
 | 
			
		||||
		free(retbuf);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* API: Send a message to a(or all) node(s) in the cluster
 | 
			
		||||
   and wait for replies */
 | 
			
		||||
int lvm_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 -1;
 | 
			
		||||
 | 
			
		||||
	build_header(head, cmd, node, data, 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 == 0 || status == -2) {
 | 
			
		||||
		/* 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 =
 | 
			
		||||
		    malloc(sizeof(lvm_response_t) * num_responses +
 | 
			
		||||
			   sizeof(int) * 2);
 | 
			
		||||
		if (!outptr) {
 | 
			
		||||
			if (retbuf)
 | 
			
		||||
				free(retbuf);
 | 
			
		||||
			errno = ENOMEM;
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		*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;
 | 
			
		||||
 | 
			
		||||
			rarray[i].status = *(int *) inptr;
 | 
			
		||||
			inptr += sizeof(int);
 | 
			
		||||
 | 
			
		||||
			rarray[i].response = malloc(strlen(inptr) + 1);
 | 
			
		||||
			if (rarray[i].response == NULL) {
 | 
			
		||||
				/* Free up everything else and return error */
 | 
			
		||||
				int j;
 | 
			
		||||
				for (j = 0; j < i; j++)
 | 
			
		||||
					free(rarray[i].response);
 | 
			
		||||
				free(outptr);
 | 
			
		||||
				errno = ENOMEM;
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			strcpy(rarray[i].response, inptr);
 | 
			
		||||
			rarray[i].len = strlen(inptr);
 | 
			
		||||
			inptr += strlen(inptr) + 1;
 | 
			
		||||
			i++;
 | 
			
		||||
		}
 | 
			
		||||
		*num = num_responses;
 | 
			
		||||
		*response = rarray;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (retbuf)
 | 
			
		||||
		free(retbuf);
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* API: Free reply array */
 | 
			
		||||
int lvm_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 -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	num = ptr[1];
 | 
			
		||||
	for (i = 0; i < num; i++) {
 | 
			
		||||
		free(response[i].response);
 | 
			
		||||
	}
 | 
			
		||||
	free(ptr);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* These are a "higher-level" API providing black-box lock/unlock
 | 
			
		||||
   functions for cluster LVM...maybe */
 | 
			
		||||
 | 
			
		||||
/* Set by lock(), used by unlock() */
 | 
			
		||||
static int num_responses;
 | 
			
		||||
static lvm_response_t *response;
 | 
			
		||||
 | 
			
		||||
int lvm_lock_for_cluster(char scope, char *name, int verbosity)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
	char *args;
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	if (name) {
 | 
			
		||||
		len = strlen(name) + 2;
 | 
			
		||||
		args = alloca(len);
 | 
			
		||||
		strcpy(args + 1, name);
 | 
			
		||||
	} else {
 | 
			
		||||
		len = 2;
 | 
			
		||||
		args = alloca(len);
 | 
			
		||||
		args[1] = '\0';
 | 
			
		||||
	}
 | 
			
		||||
	args[0] = scope;
 | 
			
		||||
 | 
			
		||||
	status = lvm_cluster_request(CLVMD_CMD_LOCK,
 | 
			
		||||
				     "", args, len, &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) {
 | 
			
		||||
			if (verbosity)
 | 
			
		||||
				fprintf(stderr,
 | 
			
		||||
					"clvmd not running on node %s\n",
 | 
			
		||||
					response[i].node);
 | 
			
		||||
			status = -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If there was an error then free the memory now as the caller won't
 | 
			
		||||
	   want to do the unlock */
 | 
			
		||||
	if (status) {
 | 
			
		||||
		int saved_errno = errno;
 | 
			
		||||
		lvm_cluster_free_request(response);
 | 
			
		||||
		num_responses = 0;
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvm_unlock_for_cluster(char scope, char *name, int verbosity)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
	int len;
 | 
			
		||||
	int failed;
 | 
			
		||||
	int num_unlock_responses;
 | 
			
		||||
	char *args;
 | 
			
		||||
	lvm_response_t *unlock_response;
 | 
			
		||||
 | 
			
		||||
	/* We failed - this should not have been called */
 | 
			
		||||
	if (num_responses == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (name) {
 | 
			
		||||
		len = strlen(name) + 2;
 | 
			
		||||
		args = alloca(len);
 | 
			
		||||
		strcpy(args + 1, name);
 | 
			
		||||
	} else {
 | 
			
		||||
		len = 2;
 | 
			
		||||
		args = alloca(len);
 | 
			
		||||
		args[1] = '\0';
 | 
			
		||||
	}
 | 
			
		||||
	args[0] = scope;
 | 
			
		||||
 | 
			
		||||
	/* See if it failed anywhere */
 | 
			
		||||
	failed = 0;
 | 
			
		||||
	for (i = 0; i < num_responses; i++) {
 | 
			
		||||
		if (response[i].status != 0)
 | 
			
		||||
			failed++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If it failed on any nodes then we only unlock on
 | 
			
		||||
	   the nodes that succeeded */
 | 
			
		||||
	if (failed) {
 | 
			
		||||
		for (i = 0; i < num_responses; i++) {
 | 
			
		||||
			/* Unlock the ones that succeeded */
 | 
			
		||||
			if (response[i].status == 0) {
 | 
			
		||||
				status = lvm_cluster_request(CLVMD_CMD_UNLOCK,
 | 
			
		||||
							     response[i].node,
 | 
			
		||||
							     args, len,
 | 
			
		||||
							     &unlock_response,
 | 
			
		||||
							     &num_unlock_responses);
 | 
			
		||||
				if (status) {
 | 
			
		||||
					if (verbosity)
 | 
			
		||||
						fprintf(stderr,
 | 
			
		||||
							"cluster command to node %s failed: %s\n",
 | 
			
		||||
							response[i].node,
 | 
			
		||||
							strerror(errno));
 | 
			
		||||
				} else if (unlock_response[0].status != 0) {
 | 
			
		||||
					if (verbosity > 1)
 | 
			
		||||
						fprintf(stderr,
 | 
			
		||||
							"unlock on node %s failed: %s\n",
 | 
			
		||||
							response[i].node,
 | 
			
		||||
							strerror(unlock_response
 | 
			
		||||
								 [0].status));
 | 
			
		||||
				}
 | 
			
		||||
				lvm_cluster_free_request(unlock_response);
 | 
			
		||||
			} else {
 | 
			
		||||
				if (verbosity)
 | 
			
		||||
					fprintf(stderr,
 | 
			
		||||
						"command on node %s failed: '%s' - will be left locked\n",
 | 
			
		||||
						response[i].node,
 | 
			
		||||
						strerror(response[i].status));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* All OK, we can do a full cluster unlock */
 | 
			
		||||
		status = lvm_cluster_request(CLVMD_CMD_UNLOCK,
 | 
			
		||||
					     "",
 | 
			
		||||
					     args, len,
 | 
			
		||||
					     &unlock_response,
 | 
			
		||||
					     &num_unlock_responses);
 | 
			
		||||
		if (status) {
 | 
			
		||||
			if (verbosity > 1)
 | 
			
		||||
				fprintf(stderr, "cluster command failed: %s\n",
 | 
			
		||||
					strerror(errno));
 | 
			
		||||
		} else {
 | 
			
		||||
			for (i = 0; i < num_unlock_responses; i++) {
 | 
			
		||||
				if (unlock_response[i].status != 0) {
 | 
			
		||||
					if (verbosity > 1)
 | 
			
		||||
						fprintf(stderr,
 | 
			
		||||
							"unlock on node %s failed: %s\n",
 | 
			
		||||
							response[i].node,
 | 
			
		||||
							strerror(unlock_response
 | 
			
		||||
								 [0].status));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		lvm_cluster_free_request(unlock_response);
 | 
			
		||||
	}
 | 
			
		||||
	lvm_cluster_free_request(response);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								daemons/clvmd/libclvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								daemons/clvmd/libclvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1997-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LIBCLVM_H
 | 
			
		||||
#define _LIBCLVM_H
 | 
			
		||||
 | 
			
		||||
typedef struct lvm_response {
 | 
			
		||||
	char node[255];
 | 
			
		||||
	char *response;
 | 
			
		||||
	int status;
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
} lvm_response_t;
 | 
			
		||||
 | 
			
		||||
extern int lvm_cluster_request(char cmd, const char *node, void *data, int len,
 | 
			
		||||
			       lvm_response_t ** response, int *num);
 | 
			
		||||
extern int lvm_cluster_write(char cmd, char *node, void *data, int len);
 | 
			
		||||
extern int lvm_cluster_free_request(lvm_response_t * response);
 | 
			
		||||
 | 
			
		||||
/* The "high-level" API */
 | 
			
		||||
extern int lvm_lock_for_cluster(char scope, char *name, int verbosity);
 | 
			
		||||
extern int lvm_unlock_for_cluster(char scope, char *name, int verbosity);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										463
									
								
								daemons/clvmd/lvm-functions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										463
									
								
								daemons/clvmd/lvm-functions.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,463 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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 <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
 | 
			
		||||
/* LVM2 headers */
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
 | 
			
		||||
static struct cmd_context *cmd = NULL;
 | 
			
		||||
static struct hash_table *lv_hash = NULL;
 | 
			
		||||
static pthread_mutex_t lv_hash_lock;
 | 
			
		||||
 | 
			
		||||
struct lv_info {
 | 
			
		||||
	int lock_id;
 | 
			
		||||
	int lock_mode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Return the mode a lock is currently held at (or -1 if not held) */
 | 
			
		||||
static int get_current_lock(char *resource)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
	lvi = hash_lookup(lv_hash, resource);
 | 
			
		||||
	pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
	if (lvi) {
 | 
			
		||||
		return lvi->lock_mode;
 | 
			
		||||
	} else {
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called at shutdown to tidy the lockspace */
 | 
			
		||||
void unlock_all()
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node *v;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
	hash_iterate(v, lv_hash) {
 | 
			
		||||
		struct lv_info *lvi = hash_get_data(lv_hash, v);
 | 
			
		||||
 | 
			
		||||
		sync_unlock(hash_get_key(lv_hash, v), lvi->lock_id);
 | 
			
		||||
	}
 | 
			
		||||
	pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Gets a real lock and keeps the info in the hash table */
 | 
			
		||||
int hold_lock(char *resource, int mode, int flags)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
 | 
			
		||||
	flags &= LKF_NOQUEUE;	/* Only LKF_NOQUEUE is valid here */
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
	lvi = hash_lookup(lv_hash, resource);
 | 
			
		||||
	pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
	if (lvi) {
 | 
			
		||||
		/* Already exists - convert it */
 | 
			
		||||
		status =
 | 
			
		||||
		    sync_lock(resource, mode, LKF_CONVERT | flags,
 | 
			
		||||
			      &lvi->lock_id);
 | 
			
		||||
		saved_errno = errno;
 | 
			
		||||
		if (!status)
 | 
			
		||||
			lvi->lock_mode = mode;
 | 
			
		||||
 | 
			
		||||
		if (status) {
 | 
			
		||||
			DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
 | 
			
		||||
				 strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
	} else {
 | 
			
		||||
		lvi = malloc(sizeof(struct lv_info));
 | 
			
		||||
		if (!lvi)
 | 
			
		||||
			return -1;
 | 
			
		||||
 | 
			
		||||
		lvi->lock_mode = mode;
 | 
			
		||||
		status = sync_lock(resource, mode, flags, &lvi->lock_id);
 | 
			
		||||
		saved_errno = errno;
 | 
			
		||||
		if (status) {
 | 
			
		||||
			free(lvi);
 | 
			
		||||
			DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
 | 
			
		||||
				 strerror(errno));
 | 
			
		||||
		} else {
 | 
			
		||||
		        pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
			hash_insert(lv_hash, resource, lvi);
 | 
			
		||||
			pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
		}
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unlock and remove it from the hash table */
 | 
			
		||||
int hold_unlock(char *resource)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
	int status;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
	lvi = hash_lookup(lv_hash, resource);
 | 
			
		||||
	pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
	if (!lvi) {
 | 
			
		||||
		DEBUGLOG("hold_unlock, lock not already held\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	status = sync_unlock(resource, lvi->lock_id);
 | 
			
		||||
	saved_errno = errno;
 | 
			
		||||
	if (!status) {
 | 
			
		||||
	    	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
		hash_remove(lv_hash, resource);
 | 
			
		||||
		pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
		free(lvi);
 | 
			
		||||
	} else {
 | 
			
		||||
		DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
 | 
			
		||||
			 strerror(errno));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	errno = saved_errno;
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Watch the return codes here.
 | 
			
		||||
   liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
 | 
			
		||||
   libdlm API functions return 0 for success, -1 for failure and do set errno.
 | 
			
		||||
   These functions here return 0 for success or >0 for failure (where the retcode is errno)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/* Activate LV exclusive or non-exclusive */
 | 
			
		||||
static int do_activate_lv(char *resource, int mode)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
	int status;
 | 
			
		||||
	int activate_lv;
 | 
			
		||||
	struct lvinfo lvi;
 | 
			
		||||
 | 
			
		||||
	/* Is it already open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == mode) {
 | 
			
		||||
		return 0;	/* Nothing to do */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Does the config file want us to activate this LV ? */
 | 
			
		||||
	if (!lv_activation_filter(cmd, resource, &activate_lv))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (!activate_lv)
 | 
			
		||||
		return 0;	/* Success, we did nothing! */
 | 
			
		||||
 | 
			
		||||
	/* Do we need to activate exclusively? */
 | 
			
		||||
	if (activate_lv == 2)
 | 
			
		||||
		mode = LKM_EXMODE;
 | 
			
		||||
 | 
			
		||||
	/* OK, try to get the lock */
 | 
			
		||||
	status = hold_lock(resource, mode, LKF_NOQUEUE);
 | 
			
		||||
	if (status)
 | 
			
		||||
		return errno;
 | 
			
		||||
 | 
			
		||||
	/* If it's suspended then resume it */
 | 
			
		||||
	if (!lv_info_by_lvid(cmd, resource, &lvi))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (lvi.suspended)
 | 
			
		||||
		if (!lv_resume(cmd, resource))
 | 
			
		||||
			return EIO;
 | 
			
		||||
 | 
			
		||||
	/* Now activate it */
 | 
			
		||||
	if (!lv_activate(cmd, resource))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Resume the LV if it was active */
 | 
			
		||||
static int do_resume_lv(char *resource)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
 | 
			
		||||
	/* Is it open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == -1) {
 | 
			
		||||
		DEBUGLOG("do_deactivate_lock, lock not already held\n");
 | 
			
		||||
		return 0;	/* We don't need to do anything */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_resume_if_active(cmd, resource))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Suspend the device if active */
 | 
			
		||||
static int do_suspend_lv(char *resource)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
	struct lvinfo lvi;
 | 
			
		||||
 | 
			
		||||
	/* Is it open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == -1) {
 | 
			
		||||
		DEBUGLOG("do_suspend_lv, lock held at %d\n", oldmode);
 | 
			
		||||
		return 0; /* Not active, so it's OK */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Only suspend it if it exists */
 | 
			
		||||
	if (!lv_info_by_lvid(cmd, resource, &lvi))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (lvi.exists) {
 | 
			
		||||
		if (!lv_suspend_if_active(cmd, resource)) {
 | 
			
		||||
			return EIO;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_deactivate_lv(char *resource)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	/* Is it open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == -1) {
 | 
			
		||||
		DEBUGLOG("do_deactivate_lock, lock not already held\n");
 | 
			
		||||
		return 0;	/* We don't need to do anything */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_deactivate(cmd, resource))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	status = hold_unlock(resource);
 | 
			
		||||
	if (status)
 | 
			
		||||
		return errno;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is the LOCK_LV part that happens on all nodes in the cluster -
 | 
			
		||||
   it is responsible for the interaction with device-mapper and LVM */
 | 
			
		||||
int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
{
 | 
			
		||||
	int status = 0;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
 | 
			
		||||
		 resource, command, lock_flags);
 | 
			
		||||
 | 
			
		||||
	if (!cmd->config_valid || config_files_changed(cmd)) {
 | 
			
		||||
		/* Reinitialise various settings inc. logging, filters */
 | 
			
		||||
		if (!refresh_toolcontext(cmd)) {
 | 
			
		||||
			log_error("Updated config file invalid. Aborting.");
 | 
			
		||||
			return EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (command) {
 | 
			
		||||
	case LCK_LV_EXCLUSIVE:
 | 
			
		||||
		status = do_activate_lv(resource, LKM_EXMODE);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_LV_SUSPEND:
 | 
			
		||||
		status = do_suspend_lv(resource);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_UNLOCK:
 | 
			
		||||
	case LCK_LV_RESUME:	/* if active */
 | 
			
		||||
		status = do_resume_lv(resource);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_LV_ACTIVATE:
 | 
			
		||||
		status = do_activate_lv(resource, LKM_CRMODE);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_LV_DEACTIVATE:
 | 
			
		||||
		status = do_deactivate_lv(resource);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		DEBUGLOG("Invalid LV command 0x%x\n", command);
 | 
			
		||||
		status = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* clean the pool for another command */
 | 
			
		||||
	pool_empty(cmd->mem);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Command return is %d\n", status);
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
 | 
			
		||||
int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
{
 | 
			
		||||
	/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
 | 
			
		||||
	   lock out on this node (because we are the node modifying the metadata)
 | 
			
		||||
	   before suspending cluster-wide.
 | 
			
		||||
	 */
 | 
			
		||||
	if (command == LCK_LV_SUSPEND) {
 | 
			
		||||
		DEBUGLOG("pre_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
 | 
			
		||||
			 resource, command, lock_flags);
 | 
			
		||||
 | 
			
		||||
		if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE))
 | 
			
		||||
			return errno;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
 | 
			
		||||
int post_lock_lv(unsigned char command, unsigned char lock_flags,
 | 
			
		||||
		 char *resource)
 | 
			
		||||
{
 | 
			
		||||
	/* Opposite of above, done on resume after a metadata update */
 | 
			
		||||
	if (command == LCK_LV_RESUME) {
 | 
			
		||||
		int oldmode;
 | 
			
		||||
 | 
			
		||||
		DEBUGLOG
 | 
			
		||||
		    ("post_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
 | 
			
		||||
		     resource, command, lock_flags);
 | 
			
		||||
 | 
			
		||||
		/* If the lock state is PW then restore it to what it was */
 | 
			
		||||
		oldmode = get_current_lock(resource);
 | 
			
		||||
		if (oldmode == LKM_PWMODE) {
 | 
			
		||||
			struct lvinfo lvi;
 | 
			
		||||
 | 
			
		||||
			if (!lv_info_by_lvid(cmd, resource, &lvi))
 | 
			
		||||
				return EIO;
 | 
			
		||||
 | 
			
		||||
			if (lvi.exists) {
 | 
			
		||||
				if (hold_lock(resource, LKM_CRMODE, 0))
 | 
			
		||||
					return errno;
 | 
			
		||||
			} else {
 | 
			
		||||
				if (hold_unlock(resource))
 | 
			
		||||
					return errno;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check if a VG is un use by LVM1 so we don't stomp on it */
 | 
			
		||||
int do_check_lvm1(char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	status = check_lvm1_vg_inactive(cmd, vgname);
 | 
			
		||||
 | 
			
		||||
	return status == 1 ? 0 : EBUSY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Ideally, clvmd should be started before any LVs are active
 | 
			
		||||
 * but this may not be the case...
 | 
			
		||||
 * I suppose this also comes in handy if clvmd crashes, not that it would!
 | 
			
		||||
 */
 | 
			
		||||
static void *get_initial_state()
 | 
			
		||||
{
 | 
			
		||||
	char lv[64], vg[64], flags[25];
 | 
			
		||||
	char uuid[65];
 | 
			
		||||
	char line[255];
 | 
			
		||||
	FILE *lvs =
 | 
			
		||||
	    popen
 | 
			
		||||
	    ("/sbin/lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr",
 | 
			
		||||
	     "r");
 | 
			
		||||
 | 
			
		||||
	if (!lvs)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	while (fgets(line, sizeof(line), lvs)) {
 | 
			
		||||
	        if (sscanf(line, "%s %s %s\n", vg, lv, flags) == 3) {
 | 
			
		||||
 | 
			
		||||
			/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
 | 
			
		||||
		        if (strlen(vg) == 38 &&                         /* is is a valid UUID ? */
 | 
			
		||||
			    (flags[4] == 'a' || flags[4] == 's')) {	/* is it active or suspended? */
 | 
			
		||||
				/* Convert hyphen-separated UUIDs into one */
 | 
			
		||||
				memcpy(&uuid[0], &vg[0], 6);
 | 
			
		||||
				memcpy(&uuid[6], &vg[7], 4);
 | 
			
		||||
				memcpy(&uuid[10], &vg[12], 4);
 | 
			
		||||
				memcpy(&uuid[14], &vg[17], 4);
 | 
			
		||||
				memcpy(&uuid[18], &vg[22], 4);
 | 
			
		||||
				memcpy(&uuid[22], &vg[27], 4);
 | 
			
		||||
				memcpy(&uuid[26], &vg[32], 6);
 | 
			
		||||
				memcpy(&uuid[32], &lv[0], 6);
 | 
			
		||||
				memcpy(&uuid[38], &lv[7], 4);
 | 
			
		||||
				memcpy(&uuid[42], &lv[12], 4);
 | 
			
		||||
				memcpy(&uuid[46], &lv[17], 4);
 | 
			
		||||
				memcpy(&uuid[50], &lv[22], 4);
 | 
			
		||||
				memcpy(&uuid[54], &lv[27], 4);
 | 
			
		||||
				memcpy(&uuid[58], &lv[32], 6);
 | 
			
		||||
				uuid[64] = '\0';
 | 
			
		||||
 | 
			
		||||
				DEBUGLOG("getting initial lock for %s\n", uuid);
 | 
			
		||||
				hold_lock(uuid, LKM_CRMODE, LKF_NOQUEUE);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fclose(lvs);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_lvhash()
 | 
			
		||||
{
 | 
			
		||||
	/* Create hash table for keeping LV locks & status */
 | 
			
		||||
	lv_hash = hash_create(100);
 | 
			
		||||
	pthread_mutex_init(&lv_hash_lock, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called to initialise the LVM context of the daemon */
 | 
			
		||||
int init_lvm(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!(cmd = create_toolcontext(NULL))) {
 | 
			
		||||
		log_error("Failed to allocate command context");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
 | 
			
		||||
	init_syslog(LOG_DAEMON);
 | 
			
		||||
	init_debug(_LOG_ERR);
 | 
			
		||||
 | 
			
		||||
	get_initial_state();
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								daemons/clvmd/lvm-functions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								daemons/clvmd/lvm-functions.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Functions in lvm-functions.c */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FUNCTIONS_H
 | 
			
		||||
#define _LVM_FUNCTIONS_H
 | 
			
		||||
 | 
			
		||||
extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
 | 
			
		||||
		       char *resource);
 | 
			
		||||
extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
 | 
			
		||||
		      char *resource);
 | 
			
		||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
 | 
			
		||||
			char *resource);
 | 
			
		||||
extern int do_check_lvm1(char *vgname);
 | 
			
		||||
extern int init_lvm(void);
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										369
									
								
								daemons/clvmd/system-lv.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										369
									
								
								daemons/clvmd/system-lv.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,369 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Routines dealing with the System LV */
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/uio.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <mntent.h>
 | 
			
		||||
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
#include "system-lv.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#ifdef HAVE_CCS
 | 
			
		||||
#include "ccs.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define SYSTEM_LV_FILESYSTEM "ext2"
 | 
			
		||||
#define SYSTEM_LV_MOUNTPOINT "/tmp/.clvmd-XXXXXX"
 | 
			
		||||
 | 
			
		||||
extern char *config_filename(void);
 | 
			
		||||
 | 
			
		||||
static char system_lv_name[PATH_MAX] = { '\0' };
 | 
			
		||||
static char mount_point[PATH_MAX] = { '\0' };
 | 
			
		||||
static int mounted = 0;
 | 
			
		||||
static int mounted_rw = 0;
 | 
			
		||||
static int lockid;
 | 
			
		||||
static const char *lock_name = "CLVM_SYSTEM_LV";
 | 
			
		||||
 | 
			
		||||
/* Look in /proc/mounts or (as a last resort) /etc/mtab to
 | 
			
		||||
   see if the system-lv is mounted. If it is mounted and we
 | 
			
		||||
   think it's not then abort because we don't have the right
 | 
			
		||||
   lock status and we don't know what other processes are doing with it.
 | 
			
		||||
 | 
			
		||||
   Returns 1 for mounted, 0 for not mounted so it matches the condition
 | 
			
		||||
   of the "mounted" static variable above.
 | 
			
		||||
*/
 | 
			
		||||
static int is_really_mounted(void)
 | 
			
		||||
{
 | 
			
		||||
	FILE *mountfile;
 | 
			
		||||
	struct mntent *ment;
 | 
			
		||||
 | 
			
		||||
	mountfile = setmntent("/proc/mounts", "r");
 | 
			
		||||
	if (!mountfile) {
 | 
			
		||||
		mountfile = setmntent("/etc/mtab", "r");
 | 
			
		||||
		if (!mountfile) {
 | 
			
		||||
			log_error("Unable to open /proc/mounts or /etc/mtab");
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Look for system LV name in the file */
 | 
			
		||||
	do {
 | 
			
		||||
		ment = getmntent(mountfile);
 | 
			
		||||
		if (ment) {
 | 
			
		||||
			if (strcmp(ment->mnt_fsname, system_lv_name) == 0) {
 | 
			
		||||
				endmntent(mountfile);
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	while (ment);
 | 
			
		||||
 | 
			
		||||
	endmntent(mountfile);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get the system LV name from the config file */
 | 
			
		||||
static int find_system_lv(void)
 | 
			
		||||
{
 | 
			
		||||
	if (system_lv_name[0] == '\0') {
 | 
			
		||||
#ifdef HAVE_CCS
 | 
			
		||||
		int error;
 | 
			
		||||
		ccs_node_t *ctree;
 | 
			
		||||
 | 
			
		||||
		/* Read the cluster config file */
 | 
			
		||||
		/* Open the config file */
 | 
			
		||||
		error = open_ccs_file(&ctree, "clvm.ccs");
 | 
			
		||||
		if (error) {
 | 
			
		||||
			perror("reading config file");
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		strcpy(system_lv_name, find_ccs_str(ctree,
 | 
			
		||||
						    "cluster/systemlv", '/',
 | 
			
		||||
						    "/dev/vg/system_lv"));
 | 
			
		||||
 | 
			
		||||
		/* Finished with config file */
 | 
			
		||||
		close_ccs_file(ctree);
 | 
			
		||||
#else
 | 
			
		||||
		if (getenv("CLVMD_SYSTEM_LV"))
 | 
			
		||||
			strcpy(system_lv_name, getenv("CLVMD_SYSTEM_LV"));
 | 
			
		||||
		else
 | 
			
		||||
			return -1;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* See if it has been mounted outside our control */
 | 
			
		||||
	if (is_really_mounted() != mounted) {
 | 
			
		||||
		log_error
 | 
			
		||||
		    ("The system LV state has been mounted/umounted outside the control of clvmd\n"
 | 
			
		||||
		     "it cannot not be used for cluster communications until this is fixed.\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* No prizes */
 | 
			
		||||
int system_lv_umount(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!mounted)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (umount(mount_point) < 0) {
 | 
			
		||||
		log_error("umount of system LV (%s) failed: %m\n",
 | 
			
		||||
			  system_lv_name);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sync_unlock(lock_name, lockid);
 | 
			
		||||
	mounted = 0;
 | 
			
		||||
 | 
			
		||||
	/* Remove the mount point */
 | 
			
		||||
	rmdir(mount_point);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int system_lv_mount(int readwrite)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
	int fd;
 | 
			
		||||
 | 
			
		||||
	if (find_system_lv()) {
 | 
			
		||||
		errno = EBUSY;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is it already mounted suitably? */
 | 
			
		||||
	if (mounted) {
 | 
			
		||||
		if (!readwrite || (readwrite && mounted_rw)) {
 | 
			
		||||
			return 0;
 | 
			
		||||
		} else {
 | 
			
		||||
			/* Mounted RO and we need RW */
 | 
			
		||||
			if (system_lv_umount() < 0)
 | 
			
		||||
				return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Randomize the mount point */
 | 
			
		||||
	strcpy(mount_point, SYSTEM_LV_MOUNTPOINT);
 | 
			
		||||
	fd = mkstemp(mount_point);
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		log_error("mkstemp for system LV mount point failed: %m\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Race condition here but there's no mkstemp for directories */
 | 
			
		||||
	close(fd);
 | 
			
		||||
	unlink(mount_point);
 | 
			
		||||
	mkdir(mount_point, 0600);
 | 
			
		||||
 | 
			
		||||
	/* Make sure we have a system-lv lock */
 | 
			
		||||
	status =
 | 
			
		||||
	    sync_lock(lock_name, (readwrite) ? LKM_EXMODE : LKM_CRMODE, 0,
 | 
			
		||||
		      &lockid);
 | 
			
		||||
	if (status < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* Mount it */
 | 
			
		||||
	if (mount(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
 | 
			
		||||
		  MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_SYNCHRONOUS
 | 
			
		||||
		  | (readwrite ? 0 : MS_RDONLY), NULL) < 0) {
 | 
			
		||||
		/* mount(2) returns EINVAL if the volume has no FS on it. So, if we want to
 | 
			
		||||
		   write to it we try to make a filesystem in it and retry the mount */
 | 
			
		||||
		if (errno == EINVAL && readwrite) {
 | 
			
		||||
			char cmd[256];
 | 
			
		||||
 | 
			
		||||
			log_error("Attempting mkfs on system LV device %s\n",
 | 
			
		||||
				  system_lv_name);
 | 
			
		||||
			snprintf(cmd, sizeof(cmd), "/sbin/mkfs -t %s %s",
 | 
			
		||||
				 SYSTEM_LV_FILESYSTEM, system_lv_name);
 | 
			
		||||
			system(cmd);
 | 
			
		||||
 | 
			
		||||
			if (mount
 | 
			
		||||
			    (system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
 | 
			
		||||
			     MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC |
 | 
			
		||||
			     MS_SYNCHRONOUS | (readwrite ? 0 : MS_RDONLY),
 | 
			
		||||
			     NULL) == 0)
 | 
			
		||||
				goto mounted;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		saved_errno = errno;
 | 
			
		||||
		log_error("mount of system LV (%s, %s, %s) failed: %m\n",
 | 
			
		||||
			  system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM);
 | 
			
		||||
		sync_unlock(lock_name, lockid);
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      mounted:
 | 
			
		||||
/* Set the internal flags */
 | 
			
		||||
	mounted = 1;
 | 
			
		||||
	mounted_rw = readwrite;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Erase *all* files in the root directory of the system LV.
 | 
			
		||||
   This *MUST* be called with an appropriate lock held!
 | 
			
		||||
   The LV is left mounted RW because it is assumed that the
 | 
			
		||||
   caller wants to write something here after clearing some space */
 | 
			
		||||
int system_lv_eraseall(void)
 | 
			
		||||
{
 | 
			
		||||
	DIR *dir;
 | 
			
		||||
	struct dirent *ent;
 | 
			
		||||
	char fname[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	/* Must be mounted R/W */
 | 
			
		||||
	system_lv_mount(1);
 | 
			
		||||
 | 
			
		||||
	dir = opendir(mount_point);
 | 
			
		||||
	if (!dir)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	while ((ent = readdir(dir))) {
 | 
			
		||||
		struct stat st;
 | 
			
		||||
		snprintf(fname, sizeof(fname), "%s/%s", mount_point,
 | 
			
		||||
			 ent->d_name);
 | 
			
		||||
 | 
			
		||||
		if (stat(fname, &st)) {
 | 
			
		||||
			if (S_ISREG(st.st_mode))
 | 
			
		||||
				unlink(fname);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	closedir(dir);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is a "high-level" routine - it mounts the system LV, writes
 | 
			
		||||
   the data into a file named after this node and then umounts the LV
 | 
			
		||||
   again */
 | 
			
		||||
int system_lv_write_data(char *data, ssize_t len)
 | 
			
		||||
{
 | 
			
		||||
	struct utsname nodeinfo;
 | 
			
		||||
	char fname[PATH_MAX];
 | 
			
		||||
	int outfile;
 | 
			
		||||
	ssize_t thiswrite;
 | 
			
		||||
	ssize_t written;
 | 
			
		||||
 | 
			
		||||
	if (system_lv_mount(1))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* Build the file name we are goingto use. */
 | 
			
		||||
	uname(&nodeinfo);
 | 
			
		||||
	snprintf(fname, sizeof(fname), "%s/%s", mount_point, nodeinfo.nodename);
 | 
			
		||||
 | 
			
		||||
	/* Open the file for output */
 | 
			
		||||
	outfile = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0600);
 | 
			
		||||
	if (outfile < 0) {
 | 
			
		||||
		int saved_errno = errno;
 | 
			
		||||
		system_lv_umount();
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	written = 0;
 | 
			
		||||
	do {
 | 
			
		||||
		thiswrite = write(outfile, data + written, len - written);
 | 
			
		||||
		if (thiswrite > 0)
 | 
			
		||||
			written += thiswrite;
 | 
			
		||||
 | 
			
		||||
	} while (written < len && thiswrite > 0);
 | 
			
		||||
 | 
			
		||||
	close(outfile);
 | 
			
		||||
 | 
			
		||||
	system_lv_umount();
 | 
			
		||||
	return (thiswrite < 0) ? -1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is a "high-level" routine - it mounts the system LV, reads
 | 
			
		||||
   the data from a named file and then umounts the LV
 | 
			
		||||
   again */
 | 
			
		||||
int system_lv_read_data(char *fname_base, char *data, ssize_t *len)
 | 
			
		||||
{
 | 
			
		||||
	char fname[PATH_MAX];
 | 
			
		||||
	int outfile;
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	ssize_t filesize;
 | 
			
		||||
	ssize_t thisread;
 | 
			
		||||
	ssize_t readbytes;
 | 
			
		||||
 | 
			
		||||
	if (system_lv_mount(0))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* Build the file name we are going to use. */
 | 
			
		||||
	snprintf(fname, sizeof(fname), "%s/%s", mount_point, fname_base);
 | 
			
		||||
 | 
			
		||||
	/* Get the file size and stuff. Actually we only need the file size but
 | 
			
		||||
	   this will also check that the file exists */
 | 
			
		||||
	if (stat(fname, &st) < 0) {
 | 
			
		||||
		int saved_errno = errno;
 | 
			
		||||
 | 
			
		||||
		log_error("stat of file %s on system LV failed: %m\n", fname);
 | 
			
		||||
		system_lv_umount();
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	filesize = st.st_size;
 | 
			
		||||
 | 
			
		||||
	outfile = open(fname, O_RDONLY);
 | 
			
		||||
	if (outfile < 0) {
 | 
			
		||||
		int saved_errno = errno;
 | 
			
		||||
 | 
			
		||||
		log_error("open of file %s on system LV failed: %m\n", fname);
 | 
			
		||||
		system_lv_umount();
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	readbytes = 0;
 | 
			
		||||
	do {
 | 
			
		||||
		thisread =
 | 
			
		||||
		    read(outfile, data + readbytes, filesize - readbytes);
 | 
			
		||||
		if (thisread > 0)
 | 
			
		||||
			readbytes += thisread;
 | 
			
		||||
 | 
			
		||||
	} while (readbytes < filesize && thisread > 0);
 | 
			
		||||
 | 
			
		||||
	close(outfile);
 | 
			
		||||
 | 
			
		||||
	system_lv_umount();
 | 
			
		||||
 | 
			
		||||
	*len = readbytes;
 | 
			
		||||
	return (thisread < 0) ? -1 : 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								daemons/clvmd/system-lv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								daemons/clvmd/system-lv.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _CLVM_SYSTEM_LV_H
 | 
			
		||||
#define _CLVM_SYSTEM_LV_H
 | 
			
		||||
 | 
			
		||||
/* Prototypes for System-LV functions */
 | 
			
		||||
 | 
			
		||||
/* "low-level" functions */
 | 
			
		||||
extern int system_lv_umount(void);
 | 
			
		||||
extern int system_lv_mount(int readwrite);
 | 
			
		||||
extern int system_lv_eraseall(void);
 | 
			
		||||
 | 
			
		||||
/* "high-level" functions */
 | 
			
		||||
extern int system_lv_write_data(char *data, ssize_t len);
 | 
			
		||||
extern int system_lv_read_data(char *fname_base, char *data, ssize_t *len);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										444
									
								
								daemons/clvmd/tcp-comms.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										444
									
								
								daemons/clvmd/tcp-comms.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,444 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
**
 | 
			
		||||
**  Copyright (C) Sistina Software, Inc.  2002-2003  All rights reserved.
 | 
			
		||||
**
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* This provides the inter-clvmd communications for a system without CMAN.
 | 
			
		||||
   There is a listening TCP socket which accepts new connections in the
 | 
			
		||||
   normal way.
 | 
			
		||||
   It can also make outgoing connnections to the other clvmd nodes.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "clvmd-gulm.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_TCP_PORT 21064
 | 
			
		||||
 | 
			
		||||
static int listen_fd = -1;
 | 
			
		||||
static int tcp_port;
 | 
			
		||||
struct hash_table *sock_hash;
 | 
			
		||||
 | 
			
		||||
static int get_our_ip_address(char *addr, int *family);
 | 
			
		||||
static int read_from_tcpsock(struct local_client *fd, char *buf, int len, char *csid,
 | 
			
		||||
			     struct local_client **new_client);
 | 
			
		||||
 | 
			
		||||
/* Called by init_cluster() to open up the listening socket */
 | 
			
		||||
int init_comms(unsigned short port)
 | 
			
		||||
{
 | 
			
		||||
    struct sockaddr_in6 addr;
 | 
			
		||||
 | 
			
		||||
    sock_hash = hash_create(100);
 | 
			
		||||
    tcp_port = port ? port : DEFAULT_TCP_PORT;
 | 
			
		||||
 | 
			
		||||
    listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
 | 
			
		||||
 | 
			
		||||
    if (listen_fd < 0)
 | 
			
		||||
    {
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	int one = 1;
 | 
			
		||||
	setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(&addr, 0, sizeof(addr)); // Bind to INADDR_ANY
 | 
			
		||||
    addr.sin6_family = AF_INET6;
 | 
			
		||||
    addr.sin6_port = htons(tcp_port);
 | 
			
		||||
 | 
			
		||||
    if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("Can't bind to port: %s\n", strerror(errno));
 | 
			
		||||
	syslog(LOG_ERR, "Can't bind to port %d, is clvmd already running ?", tcp_port);
 | 
			
		||||
	close(listen_fd);
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    listen(listen_fd, 5);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tcp_remove_client(char *csid)
 | 
			
		||||
 {
 | 
			
		||||
    struct local_client *client;
 | 
			
		||||
    DEBUGLOG("tcp_remove_client\n");
 | 
			
		||||
 | 
			
		||||
    /* Don't actually close the socket here - that's the
 | 
			
		||||
       job of clvmd.c whch will do the job when it notices the
 | 
			
		||||
       other end has gone. We just need to remove the client(s) from
 | 
			
		||||
       the hash table so we don't try to use it for sending any more */
 | 
			
		||||
    client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
    if (client)
 | 
			
		||||
    {
 | 
			
		||||
	hash_remove_binary(sock_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Look for a mangled one too */
 | 
			
		||||
    csid[0] ^= 0x80;
 | 
			
		||||
 | 
			
		||||
    client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
    if (client)
 | 
			
		||||
    {
 | 
			
		||||
	hash_remove_binary(sock_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Put it back as we found it */
 | 
			
		||||
    csid[0] ^= 0x80;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int alloc_client(int fd, char *csid, struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    struct local_client *client;
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid));
 | 
			
		||||
 | 
			
		||||
    /* Create a local_client and return it */
 | 
			
		||||
    client = malloc(sizeof(struct local_client));
 | 
			
		||||
    if (!client)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("malloc failed\n");
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(client, 0, sizeof(struct local_client));
 | 
			
		||||
    client->fd = fd;
 | 
			
		||||
    client->type = CLUSTER_DATA_SOCK;
 | 
			
		||||
    client->callback = read_from_tcpsock;
 | 
			
		||||
    if (new_client)
 | 
			
		||||
	*new_client = client;
 | 
			
		||||
 | 
			
		||||
    /* Add to our list of node sockets */
 | 
			
		||||
    if (hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN))
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("alloc_client mangling CSID for second connection\n");
 | 
			
		||||
	/* This is a duplicate connection but we can't close it because
 | 
			
		||||
	   the other end may already have started sending.
 | 
			
		||||
	   So, we mangle the IP address and keep it, all sending will
 | 
			
		||||
	   go out of the main FD
 | 
			
		||||
	*/
 | 
			
		||||
	csid[0] ^= 0x80;
 | 
			
		||||
	client->bits.net.flags = 1; /* indicate mangled CSID */
 | 
			
		||||
 | 
			
		||||
        /* If it still exists then kill the connection as we should only
 | 
			
		||||
           ever have one incoming connection from each node */
 | 
			
		||||
        if (hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN))
 | 
			
		||||
        {
 | 
			
		||||
	    DEBUGLOG("Multiple incoming connections from node\n");
 | 
			
		||||
            syslog(LOG_ERR, " Bogus incoming connection from %d.%d.%d.%d\n", csid[0],csid[1],csid[2],csid[3]);
 | 
			
		||||
 | 
			
		||||
	    free(client);
 | 
			
		||||
            errno = ECONNREFUSED;
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    hash_insert_binary(sock_hash, csid, MAX_CSID_LEN, client);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_main_cluster_fd()
 | 
			
		||||
{
 | 
			
		||||
    return listen_fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Read on main comms (listen) socket, accept it */
 | 
			
		||||
int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
 | 
			
		||||
			struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    int newfd;
 | 
			
		||||
    struct sockaddr_in6 addr;
 | 
			
		||||
    socklen_t addrlen = sizeof(addr);
 | 
			
		||||
    int status;
 | 
			
		||||
    char name[MAX_CLUSTER_MEMBER_NAME_LEN];
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("cluster_fd_callback\n");
 | 
			
		||||
    *new_client = NULL;
 | 
			
		||||
    newfd = accept(listen_fd, (struct sockaddr *)&addr, &addrlen);
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("cluster_fd_callback, newfd=%d (errno=%d)\n", newfd, errno);
 | 
			
		||||
    if (!newfd)
 | 
			
		||||
    {
 | 
			
		||||
	syslog(LOG_ERR, "error in accept: %m");
 | 
			
		||||
	errno = EAGAIN;
 | 
			
		||||
	return -1; /* Don't return an error or clvmd will close the listening FD */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check that the client is a member of the cluster
 | 
			
		||||
       and reject if not.
 | 
			
		||||
    */
 | 
			
		||||
    if (name_from_csid((char *)&addr.sin6_addr, name) < 0)
 | 
			
		||||
    {
 | 
			
		||||
	syslog(LOG_ERR, "Got connect from non-cluster node %s\n",
 | 
			
		||||
	       print_csid((char *)&addr.sin6_addr));
 | 
			
		||||
	DEBUGLOG("Got connect from non-cluster node %s\n",
 | 
			
		||||
		 print_csid((char *)&addr.sin6_addr));
 | 
			
		||||
	close(newfd);
 | 
			
		||||
 | 
			
		||||
	errno = EAGAIN;
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = alloc_client(newfd, (char *)&addr.sin6_addr, new_client);
 | 
			
		||||
    if (status)
 | 
			
		||||
    {
 | 
			
		||||
	DEBUGLOG("cluster_fd_callback, alloc_client failed, status = %d\n", status);
 | 
			
		||||
	close(newfd);
 | 
			
		||||
	/* See above... */
 | 
			
		||||
	errno = EAGAIN;
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
    DEBUGLOG("cluster_fd_callback, returning %d, %p\n", newfd, *new_client);
 | 
			
		||||
    return newfd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int read_from_tcpsock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
			     struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    struct sockaddr_in6 addr;
 | 
			
		||||
    socklen_t slen = sizeof(addr);
 | 
			
		||||
    int status;
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("read_from_tcpsock fd %d\n", client->fd);
 | 
			
		||||
    *new_client = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Get "csid" */
 | 
			
		||||
    getpeername(client->fd, (struct sockaddr *)&addr, &slen);
 | 
			
		||||
    memcpy(csid, &addr.sin6_addr, MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
    status = read(client->fd, buf, len);
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("read_from_tcpsock, status = %d(errno = %d)\n", status, errno);
 | 
			
		||||
 | 
			
		||||
    /* Remove it from the hash table if there's an error, clvmd will
 | 
			
		||||
       remove the socket from its lists and free the client struct */
 | 
			
		||||
    if (status == 0 ||
 | 
			
		||||
	(status < 0 && errno != EAGAIN && errno != EINTR))
 | 
			
		||||
    {
 | 
			
		||||
	char remcsid[MAX_CSID_LEN];
 | 
			
		||||
 | 
			
		||||
	memcpy(remcsid, csid, MAX_CSID_LEN);
 | 
			
		||||
	close(client->fd);
 | 
			
		||||
 | 
			
		||||
	/* If the csid was mangled, then make sure we remove the right entry */
 | 
			
		||||
	if (client->bits.net.flags)
 | 
			
		||||
	    remcsid[0] ^= 0x80;
 | 
			
		||||
	hash_remove_binary(sock_hash, remcsid, MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	/* Tell cluster manager layer */
 | 
			
		||||
	add_down_node(remcsid);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	    /* Send it back to clvmd */
 | 
			
		||||
	    process_message(client, buf, len, csid);
 | 
			
		||||
    }
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int connect_csid(char *csid, struct local_client **newclient)
 | 
			
		||||
{
 | 
			
		||||
    int fd;
 | 
			
		||||
    struct sockaddr_in6 addr;
 | 
			
		||||
    int status;
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("Connecting socket\n");
 | 
			
		||||
    fd = socket(PF_INET6, SOCK_STREAM, 0);
 | 
			
		||||
 | 
			
		||||
    if (fd < 0)
 | 
			
		||||
    {
 | 
			
		||||
	syslog(LOG_ERR, "Unable to create new socket: %m");
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addr.sin6_family = AF_INET6;
 | 
			
		||||
    memcpy(&addr.sin6_addr, csid, MAX_CSID_LEN);
 | 
			
		||||
    addr.sin6_port = htons(tcp_port);
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("Connecting socket %d\n", fd);
 | 
			
		||||
    if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0)
 | 
			
		||||
    {
 | 
			
		||||
	syslog(LOG_ERR, "Unable to connect to remote node: %m");
 | 
			
		||||
	DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno));
 | 
			
		||||
	close(fd);
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = alloc_client(fd, csid, newclient);
 | 
			
		||||
    if (status)
 | 
			
		||||
	close(fd);
 | 
			
		||||
    else
 | 
			
		||||
	add_client(*newclient);
 | 
			
		||||
 | 
			
		||||
    /* If we can connect to it, it must be running a clvmd */
 | 
			
		||||
    add_up_node(csid);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Send a message to a known CSID */
 | 
			
		||||
static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
    struct local_client *client;
 | 
			
		||||
    char ourcsid[MAX_CSID_LEN];
 | 
			
		||||
 | 
			
		||||
    assert(csid);
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("tcp_send_message, csid = %s, msglen = %d\n", print_csid(csid), msglen);
 | 
			
		||||
 | 
			
		||||
    /* Don't connect to ourself */
 | 
			
		||||
    get_our_csid(ourcsid);
 | 
			
		||||
    if (memcmp(csid, ourcsid, MAX_CSID_LEN) == 0)
 | 
			
		||||
	return msglen;
 | 
			
		||||
 | 
			
		||||
    client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
 | 
			
		||||
    if (!client)
 | 
			
		||||
    {
 | 
			
		||||
	status = connect_csid(csid, &client);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    return -1;
 | 
			
		||||
    }
 | 
			
		||||
    DEBUGLOG("tcp_send_message, fd = %d\n", client->fd);
 | 
			
		||||
 | 
			
		||||
    return write(client->fd, buf, msglen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
    int status=0;
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("cluster send message, csid = %p, msglen = %d\n", csid, msglen);
 | 
			
		||||
 | 
			
		||||
    /* If csid is NULL then send to all known (not just connected) nodes */
 | 
			
		||||
    if (!csid)
 | 
			
		||||
    {
 | 
			
		||||
	void *context = NULL;
 | 
			
		||||
	char loop_csid[MAX_CSID_LEN];
 | 
			
		||||
 | 
			
		||||
	/* Loop round all gulm-known nodes */
 | 
			
		||||
	while (get_next_node_csid(&context, loop_csid))
 | 
			
		||||
	{
 | 
			
		||||
	    status = tcp_send_message(buf, msglen, loop_csid, errtext);
 | 
			
		||||
	    if (status == 0 ||
 | 
			
		||||
		(status < 0 && (errno == EAGAIN || errno == EINTR)))
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
	status = tcp_send_message(buf, msglen, csid, errtext);
 | 
			
		||||
    }
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* To get our own IP address we get the locally bound address of the
 | 
			
		||||
   socket that's talking to GULM in the assumption(eek) that it will
 | 
			
		||||
   be on the "right" network in a multi-homed system */
 | 
			
		||||
static int get_our_ip_address(char *addr, int *family)
 | 
			
		||||
{
 | 
			
		||||
	struct utsname info;
 | 
			
		||||
 | 
			
		||||
	uname(&info);
 | 
			
		||||
	get_ip_address(info.nodename, addr);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Public version of above for those that don't care what protocol
 | 
			
		||||
   we're using */
 | 
			
		||||
void get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
    static char our_csid[MAX_CSID_LEN];
 | 
			
		||||
    static int got_csid = 0;
 | 
			
		||||
 | 
			
		||||
    if (!got_csid)
 | 
			
		||||
    {
 | 
			
		||||
	int family;
 | 
			
		||||
 | 
			
		||||
	memset(our_csid, 0, sizeof(our_csid));
 | 
			
		||||
	if (get_our_ip_address(our_csid, &family))
 | 
			
		||||
	{
 | 
			
		||||
	    got_csid = 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    memcpy(csid, our_csid, MAX_CSID_LEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
 | 
			
		||||
{
 | 
			
		||||
   ip6->s6_addr32[0] = 0;
 | 
			
		||||
   ip6->s6_addr32[1] = 0;
 | 
			
		||||
   ip6->s6_addr32[2] = htonl(0xffff);
 | 
			
		||||
   ip6->s6_addr32[3] = ip4->s_addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get someone else's IP address from DNS */
 | 
			
		||||
int get_ip_address(char *node, char *addr)
 | 
			
		||||
{
 | 
			
		||||
    struct hostent *he;
 | 
			
		||||
 | 
			
		||||
    memset(addr, 0, MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
    // TODO: what do we do about multi-homed hosts ???
 | 
			
		||||
    // CCSs ip_interfaces solved this but some bugger removed it.
 | 
			
		||||
 | 
			
		||||
    /* Try IPv6 first. The man page for gethostbyname implies that
 | 
			
		||||
       it will lookup ip6 & ip4 names, but it seems not to */
 | 
			
		||||
    he = gethostbyname2(node, AF_INET6);
 | 
			
		||||
    if (he)
 | 
			
		||||
    {
 | 
			
		||||
	memcpy(addr, he->h_addr_list[0],
 | 
			
		||||
	       he->h_length);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	he = gethostbyname2(node, AF_INET);
 | 
			
		||||
	if (!he)
 | 
			
		||||
	    return -1;
 | 
			
		||||
	map_v4_to_v6((struct in_addr *)he->h_addr_list[0], (struct in6_addr *)addr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *print_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
    static char buf[128];
 | 
			
		||||
    int *icsid = (int *)csid;
 | 
			
		||||
 | 
			
		||||
    sprintf(buf, "[%x.%x.%x.%x]",
 | 
			
		||||
	    icsid[0],icsid[1],icsid[2],icsid[3]);
 | 
			
		||||
 | 
			
		||||
    return buf;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								daemons/clvmd/tcp-comms.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								daemons/clvmd/tcp-comms.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
 | 
			
		||||
#define MAX_CLUSTER_MESSAGE 1600
 | 
			
		||||
#define MAX_CSID_LEN sizeof(struct in6_addr)
 | 
			
		||||
#define MAX_CLUSTER_MEMBER_NAME_LEN 128
 | 
			
		||||
 | 
			
		||||
extern int init_comms(unsigned short);
 | 
			
		||||
extern char *print_csid(char *);
 | 
			
		||||
							
								
								
									
										29
									
								
								doc/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								doc/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2004 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@
 | 
			
		||||
 | 
			
		||||
CONFSRC=example.conf
 | 
			
		||||
CONFDEST=lvm.conf
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
	@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
 | 
			
		||||
		echo "Installing $(CONFSRC) as $(confdir)/$(CONFDEST)"; \
 | 
			
		||||
		@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $(CONFSRC) \
 | 
			
		||||
			$(confdir)/$(CONFDEST); \
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
@@ -27,8 +27,11 @@ devices {
 | 
			
		||||
    # the device will be accepted or rejected (ignored).  Devices that
 | 
			
		||||
    # don't match any patterns are accepted.
 | 
			
		||||
 | 
			
		||||
    # If using RAID md devices as physical volumes, you should
 | 
			
		||||
    # set up a filter here to reject the constituent devices.
 | 
			
		||||
    # Be careful if there there are symbolic links or multiple filesystem 
 | 
			
		||||
    # entries for the same device as each name is checked separately against
 | 
			
		||||
    # the list of patterns.  The effect is that if any name matches any 'a'
 | 
			
		||||
    # pattern, the device is accepted; otherwise if any name matches any 'r'
 | 
			
		||||
    # pattern it is rejected; otherwise it is accepted.
 | 
			
		||||
 | 
			
		||||
    # Remember to run vgscan after you change this parameter to ensure 
 | 
			
		||||
    # that the cache file gets regenerated (see below).
 | 
			
		||||
@@ -57,14 +60,21 @@ devices {
 | 
			
		||||
    # You can turn off writing this cache file by setting this to 0.
 | 
			
		||||
    write_cache_state = 1
 | 
			
		||||
 | 
			
		||||
    # An advanced setting.
 | 
			
		||||
    # Advanced settings.
 | 
			
		||||
 | 
			
		||||
    # List of pairs of additional acceptable block device types found 
 | 
			
		||||
    # in /proc/devices with maximum (non-zero) number of partitions.
 | 
			
		||||
    # types = [ "fd", 16 ]
 | 
			
		||||
 | 
			
		||||
    # If sysfs is mounted (2.6 kernels) restrict device scanning to 
 | 
			
		||||
    # the block devices it believes are valid.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    sysfs_scan = 1	
 | 
			
		||||
 | 
			
		||||
    # By default, LVM2 will ignore devices used as components of
 | 
			
		||||
    # software RAID (md) devices by looking for md superblocks.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    md_component_detection = 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This section that allows you to configure the nature of the
 | 
			
		||||
@@ -175,6 +185,16 @@ global {
 | 
			
		||||
    # setting this to 0 should suppress the error messages.
 | 
			
		||||
    activation = 1
 | 
			
		||||
 | 
			
		||||
    # If we can't communicate with device-mapper, should we try running 
 | 
			
		||||
    # the LVM1 tools?
 | 
			
		||||
    # This option only applies to 2.4 kernels and is provided to help you
 | 
			
		||||
    # switch between device-mapper kernels and LVM1 kernels.
 | 
			
		||||
    # The LVM1 tools need to be installed with .lvm1 suffices
 | 
			
		||||
    # e.g. vgscan.lvm1 and they will stop working after you start using
 | 
			
		||||
    # the new lvm2 on-disk metadata format.
 | 
			
		||||
    # The default value is set when the tools are built.
 | 
			
		||||
    # fallback_to_lvm1 = 0
 | 
			
		||||
 | 
			
		||||
    # The default metadata format that commands should use - "lvm1" or "lvm2".
 | 
			
		||||
    # The command line override is -M1 or -M2.
 | 
			
		||||
    # Defaults to "lvm1" if compiled in, else "lvm2".
 | 
			
		||||
@@ -219,6 +239,14 @@ activation {
 | 
			
		||||
 | 
			
		||||
    # Nice value used while devices suspended
 | 
			
		||||
    process_priority = -18
 | 
			
		||||
 | 
			
		||||
    # If volume_list is defined, each LV is only activated if there is a
 | 
			
		||||
    # match against the list.
 | 
			
		||||
    #   "vgname" and "vgname/lvname" are matched exactly.
 | 
			
		||||
    #   "@tag" matches any tag set in the LV or VG.
 | 
			
		||||
    #   "@*" matches if any tag defined on the host is also set in the LV or VG
 | 
			
		||||
    #
 | 
			
		||||
    # volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								doc/example_cmdlib.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								doc/example_cmdlib.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "lvm2cmd.h"
 | 
			
		||||
 | 
			
		||||
/* All output gets passed to this function line-by-line */
 | 
			
		||||
void test_log_fn(int level, const char *file, int line, const char *format)
 | 
			
		||||
{
 | 
			
		||||
	/* Extract and process output here rather than printing it */
 | 
			
		||||
 | 
			
		||||
	if (level != 4)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	printf("%s\n", format);
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	void *handle;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	lvm2_log_fn(test_log_fn);
 | 
			
		||||
 | 
			
		||||
	handle = lvm2_init();
 | 
			
		||||
 | 
			
		||||
	lvm2_log_level(handle, 1);
 | 
			
		||||
	r = lvm2_run(handle, "vgs --noheadings vg1");
 | 
			
		||||
 | 
			
		||||
	/* More commands here */
 | 
			
		||||
 | 
			
		||||
	lvm2_exit(handle);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										165
									
								
								doc/tagging.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								doc/tagging.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
Tagging aims
 | 
			
		||||
============
 | 
			
		||||
  1) Ability to attach an unordered list of tags to LVM metadata objects.
 | 
			
		||||
  2) Ability to add or remove tags easily.
 | 
			
		||||
  3) Ability to select LVM objects for processing according to presence/absence
 | 
			
		||||
     of specific tags.
 | 
			
		||||
  4) Ability to control through the config file which VGs/LVs are activated 
 | 
			
		||||
     on different machines using names or tags.
 | 
			
		||||
  5) Ability to overlay settings from different config files e.g. override
 | 
			
		||||
     some settings in a global config file locally.
 | 
			
		||||
 | 
			
		||||
Clarifications
 | 
			
		||||
==============
 | 
			
		||||
  1) Tag character set: A-Za-z0-9_+.- 
 | 
			
		||||
     Can't start with hyphen & max length is 128 (NAME_LEN).
 | 
			
		||||
  2) LVM object types that can be tagged:
 | 
			
		||||
       VG, LV, LV segment
 | 
			
		||||
       PV - tags are stored in VG metadata so disappear when PV becomes orphaned
 | 
			
		||||
     Snapshots can't be tagged, but their origin may be.
 | 
			
		||||
  3) A tag can be used in place of any command line LVM object reference that
 | 
			
		||||
     accepts (a) a list of objects; or (b) a single object as long as the
 | 
			
		||||
     tag expands to a single object.  This is not supported everywhere yet.
 | 
			
		||||
     Duplicate arguments in a list after argument expansion may get removed 
 | 
			
		||||
     retaining the first copy of each argument.
 | 
			
		||||
  4) Wherever there may be ambiguity of argument type, a tag must be prefixed 
 | 
			
		||||
     by '@'; elsewhere an '@' prefix is optional.
 | 
			
		||||
  5) LVM1 objects cannot be tagged, as the disk format doesn't support it.
 | 
			
		||||
  6) Tags can be added or removed with --addtag or --deltag.
 | 
			
		||||
 | 
			
		||||
Config file Extensions
 | 
			
		||||
======================
 | 
			
		||||
  To define host tags in config file:
 | 
			
		||||
 | 
			
		||||
  tags {
 | 
			
		||||
  	# Set a tag with the hostname
 | 
			
		||||
	hosttags = 1
 | 
			
		||||
 | 
			
		||||
	tag1 { }
 | 
			
		||||
 | 
			
		||||
  	tag2 {
 | 
			
		||||
		# If no exact match, tag is not set.
 | 
			
		||||
		host_list = [ "hostname", "dbase" ]
 | 
			
		||||
	}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
Activation config file example
 | 
			
		||||
==============================
 | 
			
		||||
  activation {
 | 
			
		||||
      volume_list = [ "vg1/lvol0", "@database" ]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Matches against vgname, vgname/lvname or @tag set in *metadata*.
 | 
			
		||||
  @* matches exactly against *any* tag set on the host.
 | 
			
		||||
  The VG or LV only gets activated if a metadata tag matches.
 | 
			
		||||
  The default if there is no match is not to activate.
 | 
			
		||||
  If volume_list is not present and any tags are defined on the host 
 | 
			
		||||
  then it only activates if a host tag matches a metadata tag.
 | 
			
		||||
  If volume_list is not present and no tags are defined on the host 
 | 
			
		||||
  then it does activate.
 | 
			
		||||
 | 
			
		||||
Multiple config files
 | 
			
		||||
=====================
 | 
			
		||||
  (a) lvm.conf
 | 
			
		||||
  (b) lvm_<host_tag>.conf
 | 
			
		||||
 | 
			
		||||
  At startup, load lvm.conf.
 | 
			
		||||
  Process tag settings.
 | 
			
		||||
  If any host tags were defined, load lvm_tag.conf for each tag, if present.
 | 
			
		||||
 | 
			
		||||
  When searching for a specific config file entry, search order is (b)
 | 
			
		||||
  then (a), stopping at the first match.  
 | 
			
		||||
  Within (b) use reverse order tags got set, so file for last tag set is
 | 
			
		||||
  searched first.
 | 
			
		||||
  New tags set in (b) *do* trigger additional config file loads. 
 | 
			
		||||
 | 
			
		||||
Usage Examples
 | 
			
		||||
==============
 | 
			
		||||
  1) Simple activation control via metadata with static config files
 | 
			
		||||
 | 
			
		||||
  lvm.conf:  (Identical on every machine - global settings)
 | 
			
		||||
    tags {
 | 
			
		||||
      hostname_tags = 1
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  From any machine in the cluster, add db1 to the list of machines that
 | 
			
		||||
  activate vg1/lvol2:
 | 
			
		||||
 | 
			
		||||
  lvchange --tag @db1 vg1/lvol2
 | 
			
		||||
  (followed by lvchange -ay to actually activate it)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  2) Multiple hosts.  
 | 
			
		||||
 | 
			
		||||
    Activate vg1 only on the database hosts, db1 and db2.
 | 
			
		||||
    Activate vg2 only on the fileserver host fs1.
 | 
			
		||||
    Activate nothing initially on the fileserver backup host fsb1, but be
 | 
			
		||||
    prepared for it to take over from fs1.
 | 
			
		||||
 | 
			
		||||
  Option (i) - centralised admin, static configuration replicated between hosts  
 | 
			
		||||
    # Add @database tag to vg1's metadata
 | 
			
		||||
    vgchange --tag @database vg1
 | 
			
		||||
 | 
			
		||||
    # Add @fileserver tag to vg2's metadata
 | 
			
		||||
    vgchange --tag @fileserver vg2
 | 
			
		||||
 | 
			
		||||
    lvm.conf:  (Identical on every machine)
 | 
			
		||||
      tags {
 | 
			
		||||
        database {
 | 
			
		||||
          host_list = [ "db1", "db2" ]
 | 
			
		||||
        }
 | 
			
		||||
        fileserver {
 | 
			
		||||
	  host_list = [ "fs1" ]
 | 
			
		||||
        }
 | 
			
		||||
        fileserverbackup {
 | 
			
		||||
          host_list = [ "fsb1" ]
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      activation {
 | 
			
		||||
        # Only activate if host has a tag that matches a metadata tag
 | 
			
		||||
        volume_list = [ "@*" ]
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
  In the event of the fileserver host going down, vg2 can be brought up
 | 
			
		||||
  on fsb1 by running *on any node* 'vgchange --tag @fileserverbackup vg2'
 | 
			
		||||
  followed by 'vgchange -ay vg2'
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  Option (ii) - localised admin & configuation
 | 
			
		||||
  (i.e. each host holds *locally* which classes of volumes to activate)
 | 
			
		||||
    # Add @database tag to vg1's metadata
 | 
			
		||||
    vgchange --tag @database vg1
 | 
			
		||||
  
 | 
			
		||||
    # Add @fileserver tag to vg2's metadata
 | 
			
		||||
    vgchange --tag @fileserver vg2
 | 
			
		||||
  
 | 
			
		||||
    lvm.conf:  (Identical on every machine - global settings)
 | 
			
		||||
      tags {
 | 
			
		||||
        hosttags = 1
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    lvm_db1.conf: (only needs to be on db1 - could be symlink to lvm_db.conf)
 | 
			
		||||
      activation {
 | 
			
		||||
        volume_list = [ "@database" ]
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    lvm_db2.conf: (only needs to be on db2 - could be symlink to lvm_db.conf)
 | 
			
		||||
      activation {
 | 
			
		||||
        volume_list = [ "@database" ]
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    lvm_fs1.conf: (only needs to be on fs1 - could be symlink to lvm_fs.conf)
 | 
			
		||||
      activation {
 | 
			
		||||
        volume_list = [ "@fileserver" ]
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    If fileserver goes down, to bring a spare machine fsb1 in as fileserver,
 | 
			
		||||
    create lvm_fsb1.conf on fsb1 (or symlink to lvm_fs.conf):
 | 
			
		||||
 | 
			
		||||
      activation {
 | 
			
		||||
        volume_list = [ "@fileserver" ]
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    and run 'vgchange -ay vg2' or 'vgchange -ay @fileserver'
 | 
			
		||||
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
../daemons/clvmd/clvm.h
 | 
			
		||||
../lib/activate/activate.h
 | 
			
		||||
../lib/activate/targets.h
 | 
			
		||||
../lib/cache/lvmcache.h
 | 
			
		||||
../lib/commands/errors.h
 | 
			
		||||
../lib/commands/toolcontext.h
 | 
			
		||||
@@ -14,17 +16,22 @@
 | 
			
		||||
../lib/device/device.h
 | 
			
		||||
../lib/display/display.h
 | 
			
		||||
../lib/filters/filter-composite.h
 | 
			
		||||
../lib/filters/filter-md.h
 | 
			
		||||
../lib/filters/filter-persistent.h
 | 
			
		||||
../lib/filters/filter-regex.h
 | 
			
		||||
../lib/filters/filter-sysfs.h
 | 
			
		||||
../lib/filters/filter.h
 | 
			
		||||
../lib/format1/format1.h
 | 
			
		||||
../lib/format_pool/format_pool.h
 | 
			
		||||
../lib/format_text/format-text.h
 | 
			
		||||
../lib/format_text/text_export.h
 | 
			
		||||
../lib/format_text/text_import.h
 | 
			
		||||
../lib/label/label.h
 | 
			
		||||
../lib/locking/locking.h
 | 
			
		||||
../lib/log/log.h
 | 
			
		||||
../lib/metadata/lv_alloc.h
 | 
			
		||||
../lib/metadata/metadata.h
 | 
			
		||||
../lib/metadata/segtype.h
 | 
			
		||||
../lib/mm/dbg_malloc.h
 | 
			
		||||
../lib/mm/memlock.h
 | 
			
		||||
../lib/mm/pool.h
 | 
			
		||||
@@ -34,8 +41,10 @@
 | 
			
		||||
../lib/misc/lib.h
 | 
			
		||||
../lib/misc/lvm-file.h
 | 
			
		||||
../lib/misc/lvm-string.h
 | 
			
		||||
../lib/misc/selinux.h
 | 
			
		||||
../lib/misc/sharedlib.h
 | 
			
		||||
../lib/regex/matcher.h
 | 
			
		||||
../lib/report/report.h
 | 
			
		||||
../lib/uuid/uuid.h
 | 
			
		||||
../po/pogen.h
 | 
			
		||||
../tools/version.h
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,16 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001 Sistina Software
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This LVM library is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the terms of the GNU Library General Public
 | 
			
		||||
# License as published by the Free Software Foundation; either
 | 
			
		||||
# version 2 of the License, or (at your option) any later version.
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
#
 | 
			
		||||
# This LVM library is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
# Library General Public License for more details.
 | 
			
		||||
# 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 Library General Public
 | 
			
		||||
# License along with this LVM library; if not, write to the Free
 | 
			
		||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 | 
			
		||||
# MA 02111-1307, USA
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
SHELL = /bin/sh
 | 
			
		||||
 | 
			
		||||
@@ -24,6 +20,8 @@ VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
LN_S = @LN_S@
 | 
			
		||||
 | 
			
		||||
.PHONY: clean distclean all install pofile install_cluster
 | 
			
		||||
 | 
			
		||||
all: .symlinks_created
 | 
			
		||||
 | 
			
		||||
.symlinks_created: .symlinks
 | 
			
		||||
@@ -41,5 +39,5 @@ clean:
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
 | 
			
		||||
.PHONY: clean distclean all install pofile
 | 
			
		||||
install_cluster:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,16 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001 Sistina Software (UK) Limited
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is released under the GPL.
 | 
			
		||||
# 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@
 | 
			
		||||
@@ -12,7 +20,19 @@ ifeq ("@LVM1@", "shared")
 | 
			
		||||
  SUBDIRS = format1
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
SOURCES=\
 | 
			
		||||
ifeq ("@POOL@", "shared")
 | 
			
		||||
  SUBDIRS += format_pool
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@SNAPSHOTS@", "shared")
 | 
			
		||||
  SUBDIRS += snapshot
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@MIRRORS@", "shared")
 | 
			
		||||
  SUBDIRS += mirror
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
SOURCES =\
 | 
			
		||||
	activate/activate.c \
 | 
			
		||||
	cache/lvmcache.c \
 | 
			
		||||
	commands/toolcontext.c \
 | 
			
		||||
@@ -23,12 +43,15 @@ SOURCES=\
 | 
			
		||||
	datastruct/str_list.c \
 | 
			
		||||
	device/dev-cache.c \
 | 
			
		||||
	device/dev-io.c \
 | 
			
		||||
	device/dev-md.c \
 | 
			
		||||
	device/device.c \
 | 
			
		||||
	display/display.c \
 | 
			
		||||
	error/errseg.c \
 | 
			
		||||
	filters/filter-composite.c \
 | 
			
		||||
	filters/filter-persistent.c \
 | 
			
		||||
	filters/filter-regex.c \
 | 
			
		||||
	filters/filter-sysfs.c \
 | 
			
		||||
	filters/filter-md.c \
 | 
			
		||||
	filters/filter.c \
 | 
			
		||||
	format_text/archive.c \
 | 
			
		||||
	format_text/export.c \
 | 
			
		||||
@@ -36,6 +59,7 @@ SOURCES=\
 | 
			
		||||
	format_text/format-text.c \
 | 
			
		||||
	format_text/import.c \
 | 
			
		||||
	format_text/import_vsn1.c \
 | 
			
		||||
	format_text/tags.c \
 | 
			
		||||
	format_text/text_label.c \
 | 
			
		||||
	label/label.c \
 | 
			
		||||
	locking/file_locking.c \
 | 
			
		||||
@@ -47,20 +71,24 @@ SOURCES=\
 | 
			
		||||
	metadata/metadata.c \
 | 
			
		||||
	metadata/mirror.c \
 | 
			
		||||
	metadata/pv_map.c \
 | 
			
		||||
	metadata/segtype.c \
 | 
			
		||||
	metadata/snapshot_manip.c \
 | 
			
		||||
	misc/crc.c \
 | 
			
		||||
	misc/lvm-file.c \
 | 
			
		||||
	misc/lvm-string.c \
 | 
			
		||||
	mm/dbg_malloc.c \
 | 
			
		||||
	mm/memlock.c \
 | 
			
		||||
	mm/pool.c \
 | 
			
		||||
	regex/matcher.c \
 | 
			
		||||
	regex/parse_rx.c \
 | 
			
		||||
	regex/ttree.c \
 | 
			
		||||
	report/report.c \
 | 
			
		||||
	uuid/uuid.c 
 | 
			
		||||
	striped/striped.c \
 | 
			
		||||
	uuid/uuid.c \
 | 
			
		||||
	zero/zero.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@LVM1@", "internal")
 | 
			
		||||
  SOURCES+=\
 | 
			
		||||
  SOURCES +=\
 | 
			
		||||
	format1/disk-rep.c \
 | 
			
		||||
	format1/format1.c \
 | 
			
		||||
	format1/import-export.c \
 | 
			
		||||
@@ -70,29 +98,49 @@ ifeq ("@LVM1@", "internal")
 | 
			
		||||
	format1/vg_number.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@DEBUG@", "yes")
 | 
			
		||||
  SOURCES+=\
 | 
			
		||||
	mm/dbg_malloc.c
 | 
			
		||||
ifeq ("@POOL@", "internal")
 | 
			
		||||
  SOURCES +=\
 | 
			
		||||
	format_pool/disk_rep.c \
 | 
			
		||||
	format_pool/format_pool.c \
 | 
			
		||||
	format_pool/import_export.c \
 | 
			
		||||
	format_pool/pool_label.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLUSTER@", "internal")
 | 
			
		||||
  SOURCES += locking/cluster_locking.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLUSTER@", "shared")
 | 
			
		||||
  SUBDIRS += locking
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@SNAPSHOTS@", "internal")
 | 
			
		||||
  SOURCES += snapshot/snapshot.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@MIRRORS@", "internal")
 | 
			
		||||
  SOURCES += mirror/mirrored.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@DEVMAPPER@", "yes")
 | 
			
		||||
  SOURCES+=\
 | 
			
		||||
  SOURCES +=\
 | 
			
		||||
	activate/dev_manager.c \
 | 
			
		||||
	activate/fs.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@HAVE_LIBDL@", "yes")
 | 
			
		||||
  SOURCES+=\
 | 
			
		||||
  SOURCES +=\
 | 
			
		||||
	locking/external_locking.c \
 | 
			
		||||
	misc/sharedlib.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
TARGETS=liblvm.a
 | 
			
		||||
ifeq ("@HAVE_SELINUX@", "yes")
 | 
			
		||||
  SOURCES += misc/selinux.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include ../make.tmpl
 | 
			
		||||
LIB_STATIC = liblvm.a
 | 
			
		||||
 | 
			
		||||
liblvm.a: $(OBJECTS)
 | 
			
		||||
	$(RM) $@
 | 
			
		||||
	$(AR) r $@ $(OBJECTS)
 | 
			
		||||
	$(RANLIB) $@
 | 
			
		||||
$(SUBDIRS): $(LIB_STATIC)
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -10,10 +19,13 @@
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "fs.h"
 | 
			
		||||
#include "lvm-file.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "dev_manager.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -21,12 +33,34 @@
 | 
			
		||||
 | 
			
		||||
#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
 | 
			
		||||
 | 
			
		||||
int lvm1_present(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
 | 
			
		||||
	    < 0) {
 | 
			
		||||
		log_error("LVM1 proc global snprintf failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (path_exists(path))
 | 
			
		||||
		return 1;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef DEVMAPPER_SUPPORT
 | 
			
		||||
void set_activation(int act)
 | 
			
		||||
{
 | 
			
		||||
	if (act)
 | 
			
		||||
		log_error("Compiled without libdevmapper support. "
 | 
			
		||||
			  "Can't enable activation.");
 | 
			
		||||
	static int warned = 0;
 | 
			
		||||
 | 
			
		||||
	if (warned || !act)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	log_error("Compiled without libdevmapper support. "
 | 
			
		||||
		  "Can't enable activation.");
 | 
			
		||||
 | 
			
		||||
	warned = 1;
 | 
			
		||||
}
 | 
			
		||||
int activation(void)
 | 
			
		||||
{
 | 
			
		||||
@@ -40,10 +74,19 @@ int driver_version(char *version, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int target_present(const char *target_name)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -61,10 +104,18 @@ int lvs_in_vg_opened(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -73,10 +124,19 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
			 int *activate_lv)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
@@ -111,6 +171,86 @@ int activation(void)
 | 
			
		||||
	return _activation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _passes_activation_filter(struct cmd_context *cmd,
 | 
			
		||||
				     struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *cn;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
	char *str;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "activation/volume_list"))) {
 | 
			
		||||
		/* If no host tags defined, activate */
 | 
			
		||||
		if (list_empty(&cmd->tags))
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		/* If any host tag matches any LV or VG tag, activate */
 | 
			
		||||
		if (str_list_match_list(&cmd->tags, &lv->tags) ||
 | 
			
		||||
		    str_list_match_list(&cmd->tags, &lv->vg->tags))
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		/* Don't activate */
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
		if (cv->type != CFG_STRING) {
 | 
			
		||||
			log_error("Ignoring invalid string in config file "
 | 
			
		||||
				  "activation/volume_list");
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		str = cv->v.str;
 | 
			
		||||
		if (!*str) {
 | 
			
		||||
			log_error("Ignoring empty string in config file "
 | 
			
		||||
				  "activation/volume_list");
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Tag? */
 | 
			
		||||
		if (*str == '@') {
 | 
			
		||||
			str++;
 | 
			
		||||
			if (!*str) {
 | 
			
		||||
				log_error("Ignoring empty tag in config file "
 | 
			
		||||
					  "activation/volume_list");
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			/* If any host tag matches any LV or VG tag, activate */
 | 
			
		||||
			if (!strcmp(str, "*")) {
 | 
			
		||||
				if (str_list_match_list(&cmd->tags, &lv->tags)
 | 
			
		||||
				    || str_list_match_list(&cmd->tags,
 | 
			
		||||
							   &lv->vg->tags))
 | 
			
		||||
					    return 1;
 | 
			
		||||
				else
 | 
			
		||||
					continue;
 | 
			
		||||
			}
 | 
			
		||||
			/* If supplied tag matches LV or VG tag, activate */
 | 
			
		||||
			if (str_list_match_item(&lv->tags, str) ||
 | 
			
		||||
			    str_list_match_item(&lv->vg->tags, str))
 | 
			
		||||
				return 1;
 | 
			
		||||
			else
 | 
			
		||||
				continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!index(str, '/')) {
 | 
			
		||||
			/* vgname supplied */
 | 
			
		||||
			if (!strcmp(str, lv->vg->name))
 | 
			
		||||
				return 1;
 | 
			
		||||
			else
 | 
			
		||||
				continue;
 | 
			
		||||
		}
 | 
			
		||||
		/* vgname/lvname */
 | 
			
		||||
		if (lvm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
 | 
			
		||||
				 lv->name) < 0) {
 | 
			
		||||
			log_error("lvm_snprintf error from %s/%s", lv->vg->name,
 | 
			
		||||
				  lv->name);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!strcmp(path, str))
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int library_version(char *version, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	if (!activation())
 | 
			
		||||
@@ -149,6 +289,46 @@ int driver_version(char *version, size_t size)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int target_present(const char *target_name)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	struct dm_versions *target, *last_target;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Getting target version for %s", target_name);
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_run(dmt)) {
 | 
			
		||||
		log_debug("Failed to get %s target version", target_name);
 | 
			
		||||
		/* Assume this was because LIST_VERSIONS isn't supported */
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	target = dm_task_get_versions(dmt);
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		last_target = target;
 | 
			
		||||
 | 
			
		||||
		if (!strcmp(target_name, target->name)) {
 | 
			
		||||
			r = 1;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		target = (void *) target + target->next;
 | 
			
		||||
	} while (last_target != target);
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if info structure populated, else 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
@@ -162,7 +342,7 @@ static int _lv_info(const struct logical_volume *lv, int mknodes,
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -186,6 +366,17 @@ int lv_info(const struct logical_volume *lv, struct lvinfo *info)
 | 
			
		||||
	return _lv_info(lv, 0, info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return _lv_info(lv, 0, info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if percent set, else 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
@@ -197,7 +388,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -216,11 +407,20 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!info.exists)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -258,12 +458,12 @@ static int _lv_open_count(struct logical_volume *lv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Need to detect and handle an lv rename */
 | 
			
		||||
static int _lv_activate(struct logical_volume *lv)
 | 
			
		||||
static int _lv_activate_lv(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -280,7 +480,7 @@ static int _lv_deactivate(struct logical_volume *lv)
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -292,12 +492,12 @@ static int _lv_deactivate(struct logical_volume *lv)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_suspend(struct logical_volume *lv)
 | 
			
		||||
static int _lv_suspend_lv(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -310,7 +510,7 @@ static int _lv_suspend(struct logical_volume *lv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * These two functions return the number of LVs in the state,
 | 
			
		||||
 * These two functions return the number of visible LVs in the state,
 | 
			
		||||
 * or -1 on error.
 | 
			
		||||
 */
 | 
			
		||||
int lvs_in_vg_activated(struct volume_group *vg)
 | 
			
		||||
@@ -324,7 +524,8 @@ int lvs_in_vg_activated(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	list_iterate(lvh, &vg->lvs) {
 | 
			
		||||
		lv = list_item(lvh, struct lv_list)->lv;
 | 
			
		||||
		count += (_lv_active(lv) == 1);
 | 
			
		||||
		if (lv->status & VISIBLE_LV)
 | 
			
		||||
			count += (_lv_active(lv) == 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return count;
 | 
			
		||||
@@ -341,14 +542,15 @@ int lvs_in_vg_opened(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	list_iterate(lvh, &vg->lvs) {
 | 
			
		||||
		lv = list_item(lvh, struct lv_list)->lv;
 | 
			
		||||
		count += (_lv_open_count(lv) == 1);
 | 
			
		||||
		if (lv->status & VISIBLE_LV)
 | 
			
		||||
			count += (_lv_open_count(lv) > 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* These return success if the device is not active */
 | 
			
		||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		       int error_if_not_suspended)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
@@ -370,10 +572,10 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!info.exists || info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
		return error_if_not_suspended ? 0 : 1;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	if (!_lv_suspend(lv)) {
 | 
			
		||||
	if (!_lv_suspend_lv(lv)) {
 | 
			
		||||
		memlock_dec();
 | 
			
		||||
		fs_unlock();
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -382,7 +584,19 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
/* Returns success if the device is not active */
 | 
			
		||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_suspend(cmd, lvid_s, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_suspend(cmd, lvid_s, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		      int error_if_not_active)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
@@ -404,9 +618,9 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!info.exists || !info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
		return error_if_not_active ? 0 : 1;
 | 
			
		||||
 | 
			
		||||
	if (!_lv_activate(lv))
 | 
			
		||||
	if (!_lv_activate_lv(lv))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
@@ -415,6 +629,17 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Returns success if the device is not active */
 | 
			
		||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_resume(cmd, lvid_s, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_resume(cmd, lvid_s, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
@@ -440,7 +665,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	if (!info.exists)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info.open_count) {
 | 
			
		||||
	if (info.open_count && (lv->status & VISIBLE_LV)) {
 | 
			
		||||
		log_error("LV %s/%s in use: not removing", lv->vg->name,
 | 
			
		||||
			  lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -454,7 +679,31 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
/* Test if LV passes filter */
 | 
			
		||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
			 int *activate_lv)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		goto activate;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_passes_activation_filter(cmd, lv)) {
 | 
			
		||||
		log_verbose("Not activating %s/%s due to config file settings",
 | 
			
		||||
			    lv->vg->name, lv->name);
 | 
			
		||||
		*activate_lv = 0;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      activate:
 | 
			
		||||
	*activate_lv = 1;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
@@ -466,6 +715,12 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (filter && !_passes_activation_filter(cmd, lv)) {
 | 
			
		||||
		log_verbose("Not activating %s/%s due to config file settings",
 | 
			
		||||
			    lv->vg->name, lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
		_skip("Activating '%s'.", lv->name);
 | 
			
		||||
		return 1;
 | 
			
		||||
@@ -480,27 +735,45 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	r = _lv_activate(lv);
 | 
			
		||||
	r = _lv_activate_lv(lv);
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Activate LV */
 | 
			
		||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_activate(cmd, lvid_s, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Activate LV only if it passes filter */
 | 
			
		||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_activate(cmd, lvid_s, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
	if (!lv) {
 | 
			
		||||
		r = dev_manager_mknodes();
 | 
			
		||||
		fs_unlock();
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_lv_info(lv, 1, &info)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info.exists)
 | 
			
		||||
		r = dev_manager_mknodes(lv);
 | 
			
		||||
		r = dev_manager_lv_mknodes(lv);
 | 
			
		||||
	else
 | 
			
		||||
		r = dev_manager_rmnodes(lv);
 | 
			
		||||
		r = dev_manager_lv_rmnodes(lv);
 | 
			
		||||
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LVM_ACTIVATE_H
 | 
			
		||||
@@ -27,12 +36,18 @@ int activation(void);
 | 
			
		||||
 | 
			
		||||
int driver_version(char *version, size_t size);
 | 
			
		||||
int library_version(char *version, size_t size);
 | 
			
		||||
int lvm1_present(struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
int target_present(const char *target_name);
 | 
			
		||||
 | 
			
		||||
void activation_exit(void);
 | 
			
		||||
 | 
			
		||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
 | 
			
		||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
 | 
			
		||||
@@ -41,6 +56,15 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
 | 
			
		||||
 * Returns 1 if info structure has been populated, else 0.
 | 
			
		||||
 */
 | 
			
		||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info);
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
 | 
			
		||||
 */
 | 
			
		||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
			 int *activate_lv);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if percent has been set, else 0.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -12,7 +21,11 @@
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "fs.h"
 | 
			
		||||
#include "defaults.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "targets.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
@@ -53,13 +66,8 @@ enum {
 | 
			
		||||
	SUSPENDED = 4,
 | 
			
		||||
	NOPROPAGATE = 5,
 | 
			
		||||
	TOPLEVEL = 6,
 | 
			
		||||
	REMOVE = 7
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	MIRR_DISABLED,
 | 
			
		||||
	MIRR_RUNNING,
 | 
			
		||||
	MIRR_COMPLETED
 | 
			
		||||
	REMOVE = 7,
 | 
			
		||||
	RESUME_IMMEDIATE = 8
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
@@ -103,14 +111,14 @@ struct dl_list {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char *stripe_filler = NULL;
 | 
			
		||||
static uint32_t mirror_region_size = 0;
 | 
			
		||||
 | 
			
		||||
struct dev_manager {
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
 | 
			
		||||
	struct config_tree *cf;
 | 
			
		||||
	struct cmd_context *cmd;
 | 
			
		||||
 | 
			
		||||
	const char *stripe_filler;
 | 
			
		||||
	uint32_t mirror_region_size;
 | 
			
		||||
	void *target_state;
 | 
			
		||||
	uint32_t pvmove_mirror_count;
 | 
			
		||||
 | 
			
		||||
	char *vg_name;
 | 
			
		||||
@@ -157,89 +165,6 @@ static inline void _clear_flag(struct dev_layer *dl, int bit)
 | 
			
		||||
	dl->flags &= ~(1 << bit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Device layer names are all of the form <vg>-<lv>-<layer>, any
 | 
			
		||||
 * other hyphens that appear in these names are quoted with yet
 | 
			
		||||
 * another hyphen.  The top layer of any device has no layer
 | 
			
		||||
 * name.  eg, vg0-lvol0.
 | 
			
		||||
 */
 | 
			
		||||
static void _count_hyphens(const char *str, size_t *len, int *hyphens)
 | 
			
		||||
{
 | 
			
		||||
	const char *ptr;
 | 
			
		||||
 | 
			
		||||
	for (ptr = str; *ptr; ptr++, (*len)++)
 | 
			
		||||
		if (*ptr == '-')
 | 
			
		||||
			(*hyphens)++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copies a string, quoting hyphens with hyphens.
 | 
			
		||||
 */
 | 
			
		||||
static void _quote_hyphens(char **out, const char *src)
 | 
			
		||||
{
 | 
			
		||||
	while (*src) {
 | 
			
		||||
		if (*src == '-')
 | 
			
		||||
			*(*out)++ = '-';
 | 
			
		||||
 | 
			
		||||
		*(*out)++ = *src++;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
 | 
			
		||||
 */
 | 
			
		||||
static char *_build_name(struct pool *mem, const char *vg,
 | 
			
		||||
			 const char *lv, const char *layer)
 | 
			
		||||
{
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	int hyphens = 0;
 | 
			
		||||
	char *r, *out;
 | 
			
		||||
 | 
			
		||||
	_count_hyphens(vg, &len, &hyphens);
 | 
			
		||||
	_count_hyphens(lv, &len, &hyphens);
 | 
			
		||||
 | 
			
		||||
	if (layer && *layer)
 | 
			
		||||
		_count_hyphens(layer, &len, &hyphens);
 | 
			
		||||
 | 
			
		||||
	len += hyphens + 2;
 | 
			
		||||
 | 
			
		||||
	if (!(r = pool_alloc(mem, len))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	out = r;
 | 
			
		||||
	_quote_hyphens(&out, vg);
 | 
			
		||||
	*out++ = '-';
 | 
			
		||||
	_quote_hyphens(&out, lv);
 | 
			
		||||
 | 
			
		||||
	if (layer && *layer) {
 | 
			
		||||
		*out++ = '-';
 | 
			
		||||
		_quote_hyphens(&out, layer);
 | 
			
		||||
	}
 | 
			
		||||
	*out = '\0';
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find start of LV component in hyphenated name */
 | 
			
		||||
static char *_find_lv_name(char *vg)
 | 
			
		||||
{
 | 
			
		||||
	char *c = vg;
 | 
			
		||||
 | 
			
		||||
	while (*c && *(c + 1)) {
 | 
			
		||||
		if (*c == '-') {
 | 
			
		||||
			if (*(c + 1) == '-')
 | 
			
		||||
				c++;
 | 
			
		||||
			else
 | 
			
		||||
				return (c + 1);
 | 
			
		||||
		}
 | 
			
		||||
		c++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *_build_dlid(struct pool *mem, const char *lvid, const char *layer)
 | 
			
		||||
{
 | 
			
		||||
	char *dlid;
 | 
			
		||||
@@ -327,7 +252,7 @@ static int _info_run(const char *name, const char *uuid, struct dm_info *info,
 | 
			
		||||
static int _info(const char *name, const char *uuid, int mknodes,
 | 
			
		||||
		 struct dm_info *info, struct pool *mem, char **uuid_out)
 | 
			
		||||
{
 | 
			
		||||
	if (!mknodes && uuid && *uuid && 
 | 
			
		||||
	if (!mknodes && uuid && *uuid &&
 | 
			
		||||
	    _info_run(NULL, uuid, info, 0, mem, uuid_out) && info->exists)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
@@ -418,18 +343,16 @@ static int _percent_run(struct dev_manager *dm, const char *name,
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *type = NULL;
 | 
			
		||||
	char *params = NULL;
 | 
			
		||||
	float percent2;
 | 
			
		||||
	struct list *segh = &lv->segments;
 | 
			
		||||
	struct lv_segment *seg = NULL;
 | 
			
		||||
	struct segment_type *segtype;
 | 
			
		||||
 | 
			
		||||
	uint64_t numerator, denominator;
 | 
			
		||||
	uint64_t total_numerator = 0, total_denominator = 0;
 | 
			
		||||
 | 
			
		||||
	*percent = -1;
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = _setup_task(name, uuid, event_nr,
 | 
			
		||||
				wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS)))
 | 
			
		||||
	{
 | 
			
		||||
				wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -462,40 +385,19 @@ static int _percent_run(struct dev_manager *dm, const char *name,
 | 
			
		||||
		if (!type || !params || strcmp(type, target_type))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* Mirror? */
 | 
			
		||||
		if (!strcmp(type, "mirror")) {
 | 
			
		||||
			log_debug("Mirror status: %s", params);
 | 
			
		||||
			if (sscanf(params, "%*d %*x:%*x %*x:%*x %" PRIu64
 | 
			
		||||
				   "/%" PRIu64, &numerator,
 | 
			
		||||
				   &denominator) != 2) {
 | 
			
		||||
				log_error("Failure parsing mirror status: %s",
 | 
			
		||||
					  params);
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
			total_numerator += numerator;
 | 
			
		||||
			total_denominator += denominator;
 | 
			
		||||
 | 
			
		||||
			if (seg && (seg->status & PVMOVE))
 | 
			
		||||
				seg->extents_moved = dm->mirror_region_size *
 | 
			
		||||
				    numerator / lv->vg->extent_size;
 | 
			
		||||
		if (!(segtype = get_segtype_from_string(dm->cmd, type)))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (segtype->ops->target_percent &&
 | 
			
		||||
		    !segtype->ops->target_percent(&dm->target_state, dm->mem,
 | 
			
		||||
						  dm->cmd->cft, seg, params,
 | 
			
		||||
						  &total_numerator,
 | 
			
		||||
						  &total_denominator,
 | 
			
		||||
						  percent)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (strcmp(type, "snapshot"))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* Snapshot */
 | 
			
		||||
		if (index(params, '/')) {
 | 
			
		||||
			if (sscanf(params, "%" PRIu64 "/%" PRIu64,
 | 
			
		||||
				   &numerator, &denominator) == 2) {
 | 
			
		||||
				total_numerator += numerator;
 | 
			
		||||
				total_denominator += denominator;
 | 
			
		||||
			}
 | 
			
		||||
			continue;
 | 
			
		||||
		} else if (sscanf(params, "%f", &percent2) == 1) {
 | 
			
		||||
			*percent += percent2;
 | 
			
		||||
			*percent /= 2;
 | 
			
		||||
		}
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
	if (lv && (segh = list_next(&lv->segments, segh))) {
 | 
			
		||||
@@ -506,7 +408,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
 | 
			
		||||
 | 
			
		||||
	if (total_denominator)
 | 
			
		||||
		*percent = (float) total_numerator *100 / total_denominator;
 | 
			
		||||
	else
 | 
			
		||||
	else if (*percent < 0)
 | 
			
		||||
		*percent = 100;
 | 
			
		||||
 | 
			
		||||
	log_debug("LV percent: %f", *percent);
 | 
			
		||||
@@ -534,10 +436,16 @@ static int _percent(struct dev_manager *dm, const char *name, const char *uuid,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _rename(struct dev_layer *dl, char *newname)
 | 
			
		||||
static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname)
 | 
			
		||||
{
 | 
			
		||||
	int r = 1;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	char *vgname, *lvname, *layer;
 | 
			
		||||
 | 
			
		||||
	if (!split_dm_name(dm->mem, dl->name, &vgname, &lvname, &layer)) {
 | 
			
		||||
		log_error("Couldn't split up dm layer name %s", dl->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_verbose("Renaming %s to %s", dl->name, newname);
 | 
			
		||||
 | 
			
		||||
@@ -552,11 +460,13 @@ static int _rename(struct dev_layer *dl, char *newname)
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(r = dm_task_run(dmt)))
 | 
			
		||||
	if (!(r = dm_task_run(dmt))) {
 | 
			
		||||
		log_error("Couldn't rename device '%s'.", dl->name);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (r && _get_flag(dl, VISIBLE))
 | 
			
		||||
		fs_rename_lv(dl->lv, newname, _find_lv_name(dl->name));
 | 
			
		||||
		fs_rename_lv(dl->lv, newname, lvname);
 | 
			
		||||
 | 
			
		||||
	dl->name = newname;
 | 
			
		||||
 | 
			
		||||
@@ -565,6 +475,55 @@ static int _rename(struct dev_layer *dl, char *newname)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _suspend_or_resume(const char *name, action_t suspend)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	int sus = (suspend == SUSPEND) ? 1 : 0;
 | 
			
		||||
	int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
 | 
			
		||||
	if (!(dmt = _setup_task(name, NULL, 0, task))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(r = dm_task_run(dmt)))
 | 
			
		||||
		log_error("Couldn't %s device '%s'", sus ? "suspend" : "resume",
 | 
			
		||||
			  name);
 | 
			
		||||
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _suspend(struct dev_layer *dl)
 | 
			
		||||
{
 | 
			
		||||
	if (!dl->info.exists || dl->info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!_suspend_or_resume(dl->name, SUSPEND)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dl->info.suspended = 1;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _resume(struct dev_layer *dl)
 | 
			
		||||
{
 | 
			
		||||
	if (!dl->info.exists || !dl->info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!_suspend_or_resume(dl->name, RESUME)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dl->info.suspended = 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
 | 
			
		||||
{
 | 
			
		||||
	int r = 1;
 | 
			
		||||
@@ -624,9 +583,9 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
 | 
			
		||||
		log_error("Couldn't load device '%s'.", dl->name);
 | 
			
		||||
		if ((dl->lv->minor >= 0 || dl->lv->major >= 0) &&
 | 
			
		||||
		    _get_flag(dl, VISIBLE))
 | 
			
		||||
			log_error("Perhaps the persistent device number "
 | 
			
		||||
				  "%d:%d is already in use?",
 | 
			
		||||
				  dl->lv->major, dl->lv->minor);
 | 
			
		||||
			    log_error("Perhaps the persistent device number "
 | 
			
		||||
				      "%d:%d is already in use?",
 | 
			
		||||
				      dl->lv->major, dl->lv->minor);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_get_info(dmt, &dl->info)) {
 | 
			
		||||
@@ -641,6 +600,13 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_get_flag(dl, RESUME_IMMEDIATE) && dl->info.suspended &&
 | 
			
		||||
	    !_resume(dl)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		r = 0;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Activated %s %s %03u:%03u", dl->name,
 | 
			
		||||
			 dl->dlid, dl->info.major, dl->info.minor);
 | 
			
		||||
 | 
			
		||||
@@ -687,55 +653,6 @@ static int _remove(struct dev_layer *dl)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _suspend_or_resume(const char *name, action_t suspend)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	int sus = (suspend == SUSPEND) ? 1 : 0;
 | 
			
		||||
	int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
 | 
			
		||||
	if (!(dmt = _setup_task(name, NULL, 0, task))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(r = dm_task_run(dmt)))
 | 
			
		||||
		log_error("Couldn't %s device '%s'", sus ? "suspend" : "resume",
 | 
			
		||||
			  name);
 | 
			
		||||
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _suspend(struct dev_layer *dl)
 | 
			
		||||
{
 | 
			
		||||
	if (!dl->info.exists || dl->info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!_suspend_or_resume(dl->name, SUSPEND)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dl->info.suspended = 1;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _resume(struct dev_layer *dl)
 | 
			
		||||
{
 | 
			
		||||
	if (!dl->info.exists || !dl->info.suspended)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!_suspend_or_resume(dl->name, RESUME)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dl->info.suspended = 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The functions that populate the table in a dm_task as part of
 | 
			
		||||
 * a create/reload.
 | 
			
		||||
@@ -750,98 +667,26 @@ static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
 | 
			
		||||
			     size_t paramsize)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t esize = seg->lv->vg->extent_size;
 | 
			
		||||
	uint32_t s, start_area = 0u, areas = seg->area_count;
 | 
			
		||||
	int w = 0, tw = 0;
 | 
			
		||||
	int w = 0;
 | 
			
		||||
	const char *target = NULL;
 | 
			
		||||
	const char *trailing_space;
 | 
			
		||||
	int mirror_status;
 | 
			
		||||
	struct dev_layer *dl;
 | 
			
		||||
	char devbuf[10];
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	switch (seg->type) {
 | 
			
		||||
	case SEG_SNAPSHOT:
 | 
			
		||||
	if (!seg->segtype->ops->compose_target_line) {
 | 
			
		||||
		log_error("_emit_target: Internal error: Can't handle "
 | 
			
		||||
			  "SEG_SNAPSHOT");
 | 
			
		||||
			  "segment type %s", seg->segtype->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
		/* Target formats:
 | 
			
		||||
		 *   linear [device offset]+
 | 
			
		||||
		 *   striped #stripes stripe_size [device offset]+
 | 
			
		||||
		 *   mirror  log_type #log_params [log_params]* 
 | 
			
		||||
		 *           #mirrors [device offset]+
 | 
			
		||||
		 */
 | 
			
		||||
	case SEG_STRIPED:
 | 
			
		||||
		if (areas == 1)
 | 
			
		||||
			target = "linear";
 | 
			
		||||
		else if (areas > 1) {
 | 
			
		||||
			target = "striped";
 | 
			
		||||
			if ((tw = lvm_snprintf(params, paramsize, "%u %u ",
 | 
			
		||||
					       areas, seg->stripe_size)) < 0)
 | 
			
		||||
				goto error;
 | 
			
		||||
			w = tw;
 | 
			
		||||
		} else {
 | 
			
		||||
			log_error("_emit_target: Internal error: SEG_STRIPED "
 | 
			
		||||
				  "with no stripes");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case SEG_MIRRORED:
 | 
			
		||||
		mirror_status = MIRR_RUNNING;
 | 
			
		||||
		if (seg->status & PVMOVE) {
 | 
			
		||||
			if (seg->extents_moved == seg->area_len) {
 | 
			
		||||
				mirror_status = MIRR_COMPLETED;
 | 
			
		||||
				start_area = 1;
 | 
			
		||||
			} else if (dm->pvmove_mirror_count++) {
 | 
			
		||||
				mirror_status = MIRR_DISABLED;
 | 
			
		||||
				areas = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (mirror_status != MIRR_RUNNING) {
 | 
			
		||||
			target = "linear";
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		target = "mirror";
 | 
			
		||||
		if ((tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
 | 
			
		||||
				       dm->mirror_region_size, areas)) < 0)
 | 
			
		||||
			goto error;
 | 
			
		||||
		w = tw;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (s = start_area; s < areas; s++, w += tw) {
 | 
			
		||||
		trailing_space = (areas - s - 1) ? " " : "";
 | 
			
		||||
		if ((seg->area[s].type == AREA_PV &&
 | 
			
		||||
		     (!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
 | 
			
		||||
		    (seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
 | 
			
		||||
			tw = lvm_snprintf(params + w, paramsize - w,
 | 
			
		||||
					  "%s 0%s", dm->stripe_filler,
 | 
			
		||||
					  trailing_space);
 | 
			
		||||
		else if (seg->area[s].type == AREA_PV)
 | 
			
		||||
			tw = lvm_snprintf(params + w, paramsize - w,
 | 
			
		||||
					  "%s %" PRIu64 "%s",
 | 
			
		||||
					  dev_name(seg->area[s].u.pv.pv->dev),
 | 
			
		||||
					  (seg->area[s].u.pv.pv->pe_start +
 | 
			
		||||
					   (esize * seg->area[s].u.pv.pe)),
 | 
			
		||||
					  trailing_space);
 | 
			
		||||
		else {
 | 
			
		||||
			if (!(dl = hash_lookup(dm->layers,
 | 
			
		||||
					       seg->area[s].u.lv.lv->lvid.s))) {
 | 
			
		||||
				log_error("device layer %s missing from hash",
 | 
			
		||||
					  seg->area[s].u.lv.lv->lvid.s);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!dm_format_dev(devbuf, sizeof(devbuf), dl->info.major, dl->info.minor)) {
 | 
			
		||||
				log_error("Failed to format device number as dm target (%u,%u)",
 | 
			
		||||
					  dl->info.major, dl->info.minor);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			tw = lvm_snprintf(params + w, paramsize - w,
 | 
			
		||||
					  "%s %" PRIu64 "%s", devbuf,
 | 
			
		||||
					  esize * seg->area[s].u.lv.le,
 | 
			
		||||
					  trailing_space);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (tw < 0)
 | 
			
		||||
			goto error;
 | 
			
		||||
	if ((r = seg->segtype->ops->compose_target_line(dm, dm->mem,
 | 
			
		||||
							dm->cmd->cft,
 | 
			
		||||
							&dm->target_state, seg,
 | 
			
		||||
							params, paramsize,
 | 
			
		||||
							&target, &w,
 | 
			
		||||
							&dm->
 | 
			
		||||
							pvmove_mirror_count)) <=
 | 
			
		||||
	    0) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
 | 
			
		||||
@@ -854,11 +699,62 @@ static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
      error:
 | 
			
		||||
	log_debug("Insufficient space in params[%" PRIsize_t "] for target "
 | 
			
		||||
		  "parameters.", paramsize);
 | 
			
		||||
	return -1;
 | 
			
		||||
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
		       char *params, size_t paramsize, int *pos, int start_area,
 | 
			
		||||
		       int areas)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
	int tw = 0;
 | 
			
		||||
	const char *trailing_space;
 | 
			
		||||
	uint64_t esize = seg->lv->vg->extent_size;
 | 
			
		||||
	struct dev_layer *dl;
 | 
			
		||||
	char devbuf[10];
 | 
			
		||||
 | 
			
		||||
	for (s = start_area; s < areas; s++, *pos += tw) {
 | 
			
		||||
		trailing_space = (areas - s - 1) ? " " : "";
 | 
			
		||||
		if ((seg->area[s].type == AREA_PV &&
 | 
			
		||||
		     (!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
 | 
			
		||||
		    (seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
 | 
			
		||||
			tw = lvm_snprintf(params + *pos, paramsize - *pos,
 | 
			
		||||
					  "%s 0%s", dm->stripe_filler,
 | 
			
		||||
					  trailing_space);
 | 
			
		||||
		else if (seg->area[s].type == AREA_PV)
 | 
			
		||||
			tw = lvm_snprintf(params + *pos, paramsize - *pos,
 | 
			
		||||
					  "%s %" PRIu64 "%s",
 | 
			
		||||
					  dev_name(seg->area[s].u.pv.pv->dev),
 | 
			
		||||
					  (seg->area[s].u.pv.pv->pe_start +
 | 
			
		||||
					   (esize * seg->area[s].u.pv.pe)),
 | 
			
		||||
					  trailing_space);
 | 
			
		||||
		else {
 | 
			
		||||
			if (!(dl = hash_lookup(dm->layers,
 | 
			
		||||
					       seg->area[s].u.lv.lv->lvid.s))) {
 | 
			
		||||
				log_error("device layer %s missing from hash",
 | 
			
		||||
					  seg->area[s].u.lv.lv->lvid.s);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!dm_format_dev
 | 
			
		||||
			    (devbuf, sizeof(devbuf), dl->info.major,
 | 
			
		||||
			     dl->info.minor)) {
 | 
			
		||||
				log_error
 | 
			
		||||
				    ("Failed to format device number as dm target (%u,%u)",
 | 
			
		||||
				     dl->info.major, dl->info.minor);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			tw = lvm_snprintf(params + *pos, paramsize - *pos,
 | 
			
		||||
					  "%s %" PRIu64 "%s", devbuf,
 | 
			
		||||
					  esize * seg->area[s].u.lv.le,
 | 
			
		||||
					  trailing_space);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (tw < 0) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
 | 
			
		||||
@@ -883,6 +779,9 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
 | 
			
		||||
		if (ret >= 0)
 | 
			
		||||
			return ret;
 | 
			
		||||
 | 
			
		||||
		log_debug("Insufficient space in params[%" PRIsize_t
 | 
			
		||||
			  "] for target parameters.", paramsize);
 | 
			
		||||
 | 
			
		||||
		paramsize *= 2;
 | 
			
		||||
	} while (paramsize < MAX_TARGET_PARAMSIZE);
 | 
			
		||||
 | 
			
		||||
@@ -1014,13 +913,13 @@ static int _populate_snapshot(struct dev_manager *dm,
 | 
			
		||||
/*
 | 
			
		||||
 * dev_manager implementation.
 | 
			
		||||
 */
 | 
			
		||||
struct dev_manager *dev_manager_create(const char *vg_name,
 | 
			
		||||
				       struct config_tree *cf)
 | 
			
		||||
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
 | 
			
		||||
				       const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(mem = pool_create(16 * 1024))) {
 | 
			
		||||
	if (!(mem = pool_create("dev_manager", 16 * 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1030,23 +929,16 @@ struct dev_manager *dev_manager_create(const char *vg_name,
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm->cmd = cmd;
 | 
			
		||||
	dm->mem = mem;
 | 
			
		||||
	dm->cf = cf;
 | 
			
		||||
 | 
			
		||||
	if (!stripe_filler) {
 | 
			
		||||
		stripe_filler = find_config_str(cf->root,
 | 
			
		||||
		stripe_filler = find_config_str(cmd->cft->root,
 | 
			
		||||
						"activation/missing_stripe_filler",
 | 
			
		||||
						'/', DEFAULT_STRIPE_FILLER);
 | 
			
		||||
						DEFAULT_STRIPE_FILLER);
 | 
			
		||||
	}
 | 
			
		||||
	dm->stripe_filler = stripe_filler;
 | 
			
		||||
 | 
			
		||||
	if (!mirror_region_size) {
 | 
			
		||||
		mirror_region_size = 2 * find_config_int(cf->root,
 | 
			
		||||
							 "activation/mirror_region_size",
 | 
			
		||||
							 '/',
 | 
			
		||||
							 DEFAULT_MIRROR_REGION_SIZE);
 | 
			
		||||
	}
 | 
			
		||||
	dm->mirror_region_size = mirror_region_size;
 | 
			
		||||
 | 
			
		||||
	if (!(dm->vg_name = pool_strdup(dm->mem, vg_name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
@@ -1062,6 +954,8 @@ struct dev_manager *dev_manager_create(const char *vg_name,
 | 
			
		||||
	list_init(&dm->remove_list);
 | 
			
		||||
	list_init(&dm->suspend_list);
 | 
			
		||||
 | 
			
		||||
	dm->target_state = NULL;
 | 
			
		||||
 | 
			
		||||
	return dm;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
@@ -1083,7 +977,7 @@ int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
 | 
			
		||||
	/*
 | 
			
		||||
	 * Build a name for the top layer.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
 | 
			
		||||
	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1108,7 +1002,7 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
 | 
			
		||||
	/*
 | 
			
		||||
	 * Build a name for the top layer.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
 | 
			
		||||
	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1140,7 +1034,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
 | 
			
		||||
	/*
 | 
			
		||||
	 * Build a name for the top layer.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
 | 
			
		||||
	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1204,7 +1098,7 @@ static struct dev_layer *_create_layer(struct dev_manager *dm,
 | 
			
		||||
	char *name, *dlid;
 | 
			
		||||
	struct dev_layer *dl;
 | 
			
		||||
 | 
			
		||||
	if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, layer))) {
 | 
			
		||||
	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1274,15 +1168,13 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
 | 
			
		||||
	/* Add dependencies for any LVs that segments refer to */
 | 
			
		||||
	list_iterate(segh, &lv->segments) {
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
		if (seg->type != SEG_STRIPED && seg->type != SEG_MIRRORED)
 | 
			
		||||
			continue;
 | 
			
		||||
		for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
			if (seg->area[s].type != AREA_LV)
 | 
			
		||||
				continue;
 | 
			
		||||
			if (!str_list_add(dm->mem, &dl->pre_create,
 | 
			
		||||
					  _build_dlid(dm->mem,
 | 
			
		||||
						      seg->area[s].u.lv.
 | 
			
		||||
						      lv->lvid.s, NULL))) {
 | 
			
		||||
						      seg->area[s].u.lv.lv->
 | 
			
		||||
						      lvid.s, NULL))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -1303,7 +1195,7 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
 | 
			
		||||
	_clear_flag(dlr, VISIBLE);
 | 
			
		||||
	_clear_flag(dlr, TOPLEVEL);
 | 
			
		||||
	_set_flag(dlr, REMOVE);
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	/* add the dependency on the real device */
 | 
			
		||||
	if (!str_list_add(dm->mem, &dl->pre_create,
 | 
			
		||||
			  pool_strdup(dm->mem, dlr->dlid))) {
 | 
			
		||||
@@ -1328,6 +1220,9 @@ static int _expand_origin_real(struct dev_manager *dm,
 | 
			
		||||
	_clear_flag(dl, VISIBLE);
 | 
			
		||||
	_clear_flag(dl, TOPLEVEL);
 | 
			
		||||
 | 
			
		||||
	/* Size changes must take effect before tables using it are reloaded */
 | 
			
		||||
	_set_flag(dl, RESUME_IMMEDIATE);
 | 
			
		||||
 | 
			
		||||
	real_dlid = dl->dlid;
 | 
			
		||||
 | 
			
		||||
	if (!(dl = _create_layer(dm, NULL, lv))) {
 | 
			
		||||
@@ -1648,11 +1543,11 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
 | 
			
		||||
	if (dl->info.exists) {
 | 
			
		||||
		if ((suffix = rindex(dl->dlid, '-')))
 | 
			
		||||
			suffix++;
 | 
			
		||||
		newname = _build_name(dm->mem, dm->vg_name, dl->lv->name,
 | 
			
		||||
				      suffix);
 | 
			
		||||
		newname = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
 | 
			
		||||
					suffix);
 | 
			
		||||
		if (strcmp(newname, dl->name)) {
 | 
			
		||||
			if (!_suspend_parents(dm, dl) ||
 | 
			
		||||
			    !_suspend(dl) || !_rename(dl, newname)) {
 | 
			
		||||
			    !_suspend(dl) || !_rename(dm, dl, newname)) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -1680,7 +1575,6 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *lvh;
 | 
			
		||||
@@ -1748,8 +1642,7 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!str_list_add(dm->mem, &dep->pre_create,
 | 
			
		||||
					  dl->dlid)) {
 | 
			
		||||
			if (!str_list_add(dm->mem, &dep->pre_create, dl->dlid)) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -1765,8 +1658,7 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!str_list_add(dm->mem, &dep->pre_suspend,
 | 
			
		||||
					  dl->dlid)) {
 | 
			
		||||
			if (!str_list_add(dm->mem, &dep->pre_suspend, dl->dlid)) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -1940,7 +1832,6 @@ static int _add_existing_layer(struct dev_manager *dm, const char *name)
 | 
			
		||||
 | 
			
		||||
static int _scan_existing_devices(struct dev_manager *dm)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct dm_names *names;
 | 
			
		||||
	unsigned next = 0;
 | 
			
		||||
@@ -2079,6 +1970,73 @@ static int _remove_suspended_lvs(struct dev_manager *dm,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _targets_present(struct dev_manager *dm, struct list *lvs)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct list *lvh, *segh;
 | 
			
		||||
	struct segment_type *segtype;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	int snapshots = 0, mirrors = 0;
 | 
			
		||||
 | 
			
		||||
	list_iterate(lvh, lvs) {
 | 
			
		||||
		lv = list_item(lvh, struct lv_list)->lv;
 | 
			
		||||
 | 
			
		||||
		if (!snapshots)
 | 
			
		||||
			if (lv_is_cow(lv) || lv_is_origin(lv))
 | 
			
		||||
				snapshots = 1;
 | 
			
		||||
 | 
			
		||||
		if (!mirrors)
 | 
			
		||||
			if (lv->status & PVMOVE)
 | 
			
		||||
				mirrors = 1;
 | 
			
		||||
 | 
			
		||||
		if (lv->status & VIRTUAL) {
 | 
			
		||||
			list_iterate(segh, &lv->segments) {
 | 
			
		||||
				seg = list_item(segh, struct lv_segment);
 | 
			
		||||
				if (seg->segtype->ops->target_present &&
 | 
			
		||||
				    !seg->segtype->ops->target_present()) {
 | 
			
		||||
					log_error("Can't expand LV: %s target "
 | 
			
		||||
						  "support missing "
 | 
			
		||||
						  "from kernel?",
 | 
			
		||||
						  seg->segtype->name);
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mirrors) {
 | 
			
		||||
		if (!(segtype = get_segtype_from_string(dm->cmd, "mirror"))) {
 | 
			
		||||
			log_error("Can't expand LV: Mirror support "
 | 
			
		||||
				  "missing from tools?");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!segtype->ops->target_present ||
 | 
			
		||||
		    !segtype->ops->target_present()) {
 | 
			
		||||
			log_error("Can't expand LV: Mirror support missing "
 | 
			
		||||
				  "from kernel?");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (snapshots) {
 | 
			
		||||
		if (!(segtype = get_segtype_from_string(dm->cmd, "snapshot"))) {
 | 
			
		||||
			log_error("Can't expand LV: Snapshot support "
 | 
			
		||||
				  "missing from tools?");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!segtype->ops->target_present ||
 | 
			
		||||
		    !segtype->ops->target_present()) {
 | 
			
		||||
			log_error("Can't expand LV: Snapshot support missing "
 | 
			
		||||
				  "from kernel?");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	char *dlid;
 | 
			
		||||
@@ -2161,6 +2119,12 @@ static int _action(struct dev_manager *dm, struct logical_volume *lv,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_targets_present(dm, &dm->active_list) ||
 | 
			
		||||
	    !_targets_present(dm, &dm->reload_list)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_execute(dm, lv->vg)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -2184,12 +2148,12 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv)
 | 
			
		||||
	return _action(dm, lv, SUSPEND);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_manager_mknodes(const struct logical_volume *lv)
 | 
			
		||||
int dev_manager_lv_mknodes(const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	char *name;
 | 
			
		||||
 | 
			
		||||
	if (!(name = _build_name(lv->vg->cmd->mem, lv->vg->name,
 | 
			
		||||
				 lv->name, NULL))) {
 | 
			
		||||
	if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name,
 | 
			
		||||
				   lv->name, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -2197,11 +2161,25 @@ int dev_manager_mknodes(const struct logical_volume *lv)
 | 
			
		||||
	return fs_add_lv(lv, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_manager_rmnodes(const struct logical_volume *lv)
 | 
			
		||||
int dev_manager_lv_rmnodes(const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	return fs_del_lv(lv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_manager_mknodes(void)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_MKNODES)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	r = dm_task_run(dmt);
 | 
			
		||||
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dev_manager_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	dm_lib_exit();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,31 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_DEV_MANAGER_H
 | 
			
		||||
#define _LVM_DEV_MANAGER_H
 | 
			
		||||
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
struct logical_volume;
 | 
			
		||||
struct cmd_context;
 | 
			
		||||
struct dev_manager;
 | 
			
		||||
struct dm_info;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Constructor and destructor.
 | 
			
		||||
 */
 | 
			
		||||
struct dev_manager *dev_manager_create(const char *vg_name,
 | 
			
		||||
				       struct config_tree *cf);
 | 
			
		||||
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_exit(void);
 | 
			
		||||
 | 
			
		||||
@@ -38,8 +46,9 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
 | 
			
		||||
int dev_manager_mknodes(const struct logical_volume *lv);
 | 
			
		||||
int dev_manager_rmnodes(const struct logical_volume *lv);
 | 
			
		||||
int dev_manager_lv_mknodes(const struct logical_volume *lv);
 | 
			
		||||
int dev_manager_lv_rmnodes(const struct logical_volume *lv);
 | 
			
		||||
int dev_manager_mknodes(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Put the desired changes into effect.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -11,6 +20,10 @@
 | 
			
		||||
#include "lvm-file.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SELINUX
 | 
			
		||||
#  include "selinux.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
@@ -33,7 +46,7 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Creating directory %s", vg_path);
 | 
			
		||||
	if (mkdir(vg_path, 0555)) {
 | 
			
		||||
	if (mkdir(vg_path, 0777)) {
 | 
			
		||||
		log_sys_error("mkdir", vg_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -52,10 +65,10 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Removing directory %s", vg_path);
 | 
			
		||||
 | 
			
		||||
	if (is_empty_dir(vg_path))
 | 
			
		||||
	if (is_empty_dir(vg_path)) {
 | 
			
		||||
		log_very_verbose("Removing directory %s", vg_path);
 | 
			
		||||
		rmdir(vg_path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -166,6 +179,13 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SELINUX
 | 
			
		||||
        if (!set_selinux_context(lv_path)) {
 | 
			
		||||
                stack;
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -182,9 +202,9 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
 | 
			
		||||
		if (errno != ENOENT)
 | 
			
		||||
			log_error("%s not symbolic link - not removing",
 | 
			
		||||
				  lv_path);
 | 
			
		||||
		if (errno == ENOENT)
 | 
			
		||||
			return 1;
 | 
			
		||||
		log_error("%s not symbolic link - not removing", lv_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FS_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								lib/activate/targets.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/activate/targets.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_TARGETS_H
 | 
			
		||||
#define _LVM_TARGETS_H
 | 
			
		||||
 | 
			
		||||
struct dev_manager;
 | 
			
		||||
struct lv_segment;
 | 
			
		||||
 | 
			
		||||
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,                                 char *params, size_t paramsize, int *pos,
 | 
			
		||||
		                        int start_area, int areas);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										13
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -11,7 +20,6 @@
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#define ORPHAN ""
 | 
			
		||||
 | 
			
		||||
@@ -21,6 +29,10 @@
 | 
			
		||||
/* LVM specific per-volume info */
 | 
			
		||||
/* Eventual replacement for struct physical_volume perhaps? */
 | 
			
		||||
 | 
			
		||||
struct cmd_context;
 | 
			
		||||
struct format_type;
 | 
			
		||||
struct volume_group;
 | 
			
		||||
 | 
			
		||||
struct lvmcache_vginfo {
 | 
			
		||||
	struct list list;	/* Join these vginfos together */
 | 
			
		||||
	struct list infos;	/* List head for lvmcache_infos */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_ERRORS_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -14,6 +23,7 @@
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "filter-composite.h"
 | 
			
		||||
#include "filter-md.h"
 | 
			
		||||
#include "filter-persistent.h"
 | 
			
		||||
#include "filter-regex.h"
 | 
			
		||||
#include "filter-sysfs.h"
 | 
			
		||||
@@ -22,6 +32,9 @@
 | 
			
		||||
#include "format-text.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
#include "sharedlib.h"
 | 
			
		||||
@@ -31,8 +44,13 @@
 | 
			
		||||
#include "format1.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef POOL_INTERNAL
 | 
			
		||||
#include "format_pool.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <locale.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
@@ -68,7 +86,7 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* Syslog */
 | 
			
		||||
	cmd->default_settings.syslog =
 | 
			
		||||
	    find_config_int(cmd->cf->root, "log/syslog", '/', DEFAULT_SYSLOG);
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/syslog", DEFAULT_SYSLOG);
 | 
			
		||||
	if (cmd->default_settings.syslog != 1)
 | 
			
		||||
		fin_syslog();
 | 
			
		||||
 | 
			
		||||
@@ -77,47 +95,50 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* Debug level for log file output */
 | 
			
		||||
	cmd->default_settings.debug =
 | 
			
		||||
	    find_config_int(cmd->cf->root, "log/level", '/', DEFAULT_LOGLEVEL);
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/level", DEFAULT_LOGLEVEL);
 | 
			
		||||
	init_debug(cmd->default_settings.debug);
 | 
			
		||||
 | 
			
		||||
	/* Verbose level for tty output */
 | 
			
		||||
	cmd->default_settings.verbose =
 | 
			
		||||
	    find_config_int(cmd->cf->root, "log/verbose", '/', DEFAULT_VERBOSE);
 | 
			
		||||
	init_verbose(cmd->default_settings.verbose);
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/verbose", DEFAULT_VERBOSE);
 | 
			
		||||
	init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
 | 
			
		||||
 | 
			
		||||
	/* Log message formatting */
 | 
			
		||||
	init_indent(find_config_int(cmd->cf->root, "log/indent", '/',
 | 
			
		||||
	init_indent(find_config_int(cmd->cft->root, "log/indent",
 | 
			
		||||
				    DEFAULT_INDENT));
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.msg_prefix = find_config_str(cmd->cf->root,
 | 
			
		||||
							   "log/prefix", '/',
 | 
			
		||||
	cmd->default_settings.msg_prefix = find_config_str(cmd->cft->root,
 | 
			
		||||
							   "log/prefix",
 | 
			
		||||
							   DEFAULT_MSG_PREFIX);
 | 
			
		||||
	init_msg_prefix(cmd->default_settings.msg_prefix);
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.cmd_name = find_config_int(cmd->cf->root,
 | 
			
		||||
	cmd->default_settings.cmd_name = find_config_int(cmd->cft->root,
 | 
			
		||||
							 "log/command_names",
 | 
			
		||||
							 '/', DEFAULT_CMD_NAME);
 | 
			
		||||
							 DEFAULT_CMD_NAME);
 | 
			
		||||
	init_cmd_name(cmd->default_settings.cmd_name);
 | 
			
		||||
 | 
			
		||||
	/* Test mode */
 | 
			
		||||
	cmd->default_settings.test =
 | 
			
		||||
	    find_config_int(cmd->cf->root, "global/test", '/', 0);
 | 
			
		||||
	    find_config_int(cmd->cft->root, "global/test", 0);
 | 
			
		||||
 | 
			
		||||
	/* Settings for logging to file */
 | 
			
		||||
	if (find_config_int(cmd->cf->root, "log/overwrite", '/',
 | 
			
		||||
			    DEFAULT_OVERWRITE))
 | 
			
		||||
	if (find_config_int(cmd->cft->root, "log/overwrite", DEFAULT_OVERWRITE))
 | 
			
		||||
		append = 0;
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cf->root, "log/file", '/', 0);
 | 
			
		||||
	if (log_file)
 | 
			
		||||
		init_log_file(log_file, append);
 | 
			
		||||
	log_file = find_config_str(cmd->cft->root, "log/file", 0);
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cf->root, "log/activate_file", '/', 0);
 | 
			
		||||
	if (log_file) {
 | 
			
		||||
		release_log_memory();
 | 
			
		||||
		fin_log();
 | 
			
		||||
		init_log_file(log_file, append);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cft->root, "log/activate_file", 0);
 | 
			
		||||
	if (log_file)
 | 
			
		||||
		init_log_direct(log_file, append);
 | 
			
		||||
 | 
			
		||||
	init_log_while_suspended(find_config_int(cmd->cf->root,
 | 
			
		||||
						 "log/activation", '/', 0));
 | 
			
		||||
	init_log_while_suspended(find_config_int(cmd->cft->root,
 | 
			
		||||
						 "log/activation", 0));
 | 
			
		||||
 | 
			
		||||
	t = time(NULL);
 | 
			
		||||
	log_verbose("Logging initialised at %s", ctime(&t));
 | 
			
		||||
@@ -133,8 +154,8 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
	mode_t old_umask;
 | 
			
		||||
 | 
			
		||||
	/* umask */
 | 
			
		||||
	cmd->default_settings.umask = find_config_int(cmd->cf->root,
 | 
			
		||||
						      "global/umask", '/',
 | 
			
		||||
	cmd->default_settings.umask = find_config_int(cmd->cft->root,
 | 
			
		||||
						      "global/umask",
 | 
			
		||||
						      DEFAULT_UMASK);
 | 
			
		||||
 | 
			
		||||
	if ((old_umask = umask((mode_t) cmd->default_settings.umask)) !=
 | 
			
		||||
@@ -143,8 +164,8 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* dev dir */
 | 
			
		||||
	if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
 | 
			
		||||
			 find_config_str(cmd->cf->root, "devices/dir",
 | 
			
		||||
					 '/', DEFAULT_DEV_DIR)) < 0) {
 | 
			
		||||
			 find_config_str(cmd->cft->root, "devices/dir",
 | 
			
		||||
					 DEFAULT_DEV_DIR)) < 0) {
 | 
			
		||||
		log_error("Device directory given in config file too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -154,27 +175,25 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* proc dir */
 | 
			
		||||
	if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
 | 
			
		||||
			 find_config_str(cmd->cf->root, "global/proc",
 | 
			
		||||
					 '/', DEFAULT_PROC_DIR)) < 0) {
 | 
			
		||||
			 find_config_str(cmd->cft->root, "global/proc",
 | 
			
		||||
					 DEFAULT_PROC_DIR)) < 0) {
 | 
			
		||||
		log_error("Device directory given in config file too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* activation? */
 | 
			
		||||
	cmd->default_settings.activation = find_config_int(cmd->cf->root,
 | 
			
		||||
	cmd->default_settings.activation = find_config_int(cmd->cft->root,
 | 
			
		||||
							   "global/activation",
 | 
			
		||||
							   '/',
 | 
			
		||||
							   DEFAULT_ACTIVATION);
 | 
			
		||||
	set_activation(cmd->default_settings.activation);
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.suffix = find_config_int(cmd->cf->root,
 | 
			
		||||
	cmd->default_settings.suffix = find_config_int(cmd->cft->root,
 | 
			
		||||
						       "global/suffix",
 | 
			
		||||
						       '/', DEFAULT_SUFFIX);
 | 
			
		||||
						       DEFAULT_SUFFIX);
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->default_settings.unit_factor =
 | 
			
		||||
	      units_to_bytes(find_config_str(cmd->cf->root,
 | 
			
		||||
	      units_to_bytes(find_config_str(cmd->cft->root,
 | 
			
		||||
					     "global/units",
 | 
			
		||||
					     '/',
 | 
			
		||||
					     DEFAULT_UNITS),
 | 
			
		||||
			     &cmd->default_settings.unit_type))) {
 | 
			
		||||
		log_error("Invalid units specification");
 | 
			
		||||
@@ -184,57 +203,266 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find and read config file */
 | 
			
		||||
static int _init_config(struct cmd_context *cmd)
 | 
			
		||||
static int _set_tag(struct cmd_context *cmd, const char *tag)
 | 
			
		||||
{
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	char config_file[PATH_MAX] = "";
 | 
			
		||||
	log_very_verbose("Setting host tag: %s", pool_strdup(cmd->libmem, tag));
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->cf = create_config_tree())) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* No config file if LVM_SYSTEM_DIR is empty */
 | 
			
		||||
	if (!*cmd->sys_dir)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(config_file, sizeof(config_file),
 | 
			
		||||
			 "%s/lvm.conf", cmd->sys_dir) < 0) {
 | 
			
		||||
		log_error("LVM_SYSTEM_DIR was too long");
 | 
			
		||||
		destroy_config_tree(cmd->cf);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is there a config file? */
 | 
			
		||||
	if (stat(config_file, &info) == -1) {
 | 
			
		||||
		if (errno == ENOENT)
 | 
			
		||||
			return 1;
 | 
			
		||||
		log_sys_error("stat", config_file);
 | 
			
		||||
		destroy_config_tree(cmd->cf);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!read_config_file(cmd->cf, config_file)) {
 | 
			
		||||
		log_error("Failed to load config file %s", config_file);
 | 
			
		||||
		destroy_config_tree(cmd->cf);
 | 
			
		||||
	if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
 | 
			
		||||
		log_error("_set_tag: str_list_add %s failed", tag);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_dev_cache(struct cmd_context *cmd)
 | 
			
		||||
static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn,
 | 
			
		||||
			       int *passes)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
 | 
			
		||||
	*passes = 1;
 | 
			
		||||
 | 
			
		||||
	for (cn = hn; cn; cn = cn->sib) {
 | 
			
		||||
		if (!cn->v)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (!strcmp(cn->key, "host_list")) {
 | 
			
		||||
			*passes = 0;
 | 
			
		||||
			if (cn->v->type == CFG_EMPTY_ARRAY)
 | 
			
		||||
				continue;
 | 
			
		||||
			for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
				if (cv->type != CFG_STRING) {
 | 
			
		||||
					log_error("Invalid hostname string "
 | 
			
		||||
						  "for tag %s", cn->key);
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
				if (!strcmp(cv->v.str, cmd->hostname)) {
 | 
			
		||||
					*passes = 1;
 | 
			
		||||
					return 1;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (!strcmp(cn->key, "host_filter")) {
 | 
			
		||||
			log_error("host_filter not supported yet");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *tn, *cn;
 | 
			
		||||
	const char *tag;
 | 
			
		||||
	int passes;
 | 
			
		||||
 | 
			
		||||
	if (!(tn = find_config_node(cft->root, "tags")) || !tn->child)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/* NB hosttags 0 when already 1 intentionally does not delete the tag */
 | 
			
		||||
	if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags",
 | 
			
		||||
					      DEFAULT_HOSTTAGS)) {
 | 
			
		||||
		/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
 | 
			
		||||
		if (!_set_tag(cmd, cmd->hostname)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		cmd->hosttags = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (cn = tn->child; cn; cn = cn->sib) {
 | 
			
		||||
		if (cn->v)
 | 
			
		||||
			continue;
 | 
			
		||||
		tag = cn->key;
 | 
			
		||||
		if (*tag == '@')
 | 
			
		||||
			tag++;
 | 
			
		||||
		if (!validate_name(tag)) {
 | 
			
		||||
			log_error("Invalid tag in config file: %s", cn->key);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (cn->child) {
 | 
			
		||||
			passes = 0;
 | 
			
		||||
			if (!_check_host_filters(cmd, cn->child, &passes)) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!passes)
 | 
			
		||||
				continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!_set_tag(cmd, tag)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _load_config_file(struct cmd_context *cmd, const char *tag)
 | 
			
		||||
{
 | 
			
		||||
	char config_file[PATH_MAX] = "";
 | 
			
		||||
	const char *filler = "";
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	struct config_tree_list *cfl;
 | 
			
		||||
 | 
			
		||||
	if (*tag)
 | 
			
		||||
		filler = "_";
 | 
			
		||||
 | 
			
		||||
	if (lvm_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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cfl = pool_alloc(cmd->libmem, sizeof(*cfl)))) {
 | 
			
		||||
		log_error("config_tree_list allocation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cfl->cft = create_config_tree(config_file))) {
 | 
			
		||||
		log_error("config_tree allocation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is there a config file? */
 | 
			
		||||
	if (stat(config_file, &info) == -1) {
 | 
			
		||||
		if (errno == ENOENT) {
 | 
			
		||||
			list_add(&cmd->config_files, &cfl->list);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		log_sys_error("stat", config_file);
 | 
			
		||||
		destroy_config_tree(cfl->cft);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Loading config file: %s", config_file);
 | 
			
		||||
	if (!read_config_file(cfl->cft)) {
 | 
			
		||||
		log_error("Failed to load config file %s", config_file);
 | 
			
		||||
		destroy_config_tree(cfl->cft);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_add(&cmd->config_files, &cfl->list);
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (*tag)
 | 
			
		||||
		_init_tags(cmd, cfl->cft);
 | 
			
		||||
	else
 | 
			
		||||
		/* Use temporary copy of lvm.conf while loading other files */
 | 
			
		||||
		cmd->cft = cfl->cft;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find and read first config file */
 | 
			
		||||
static int _init_lvm_conf(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	/* No config file if LVM_SYSTEM_DIR is empty */
 | 
			
		||||
	if (!*cmd->sys_dir) {
 | 
			
		||||
		if (!(cmd->cft = create_config_tree(NULL))) {
 | 
			
		||||
			log_error("Failed to create config tree");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_load_config_file(cmd, "")) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Read any additional config files */
 | 
			
		||||
static int _init_tag_configs(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
	/* Tag list may grow while inside this loop */
 | 
			
		||||
	list_iterate_items(sl, &cmd->tags) {
 | 
			
		||||
		if (!_load_config_file(cmd, sl->str)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _merge_config_files(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct config_tree_list *cfl;
 | 
			
		||||
 | 
			
		||||
	/* Replace temporary duplicate copy of lvm.conf */
 | 
			
		||||
	if (cmd->cft->root) {
 | 
			
		||||
		if (!(cmd->cft = create_config_tree(NULL))) {
 | 
			
		||||
			log_error("Failed to create config tree");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(cfl, &cmd->config_files) {
 | 
			
		||||
		/* Merge all config trees into cmd->cft using merge/tag rules */
 | 
			
		||||
		if (!merge_config_tree(cmd, cmd->cft, cfl->cft)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_tags(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct list *slh, *slht;
 | 
			
		||||
 | 
			
		||||
	list_iterate_safe(slh, slht, &cmd->tags) {
 | 
			
		||||
		list_del(slh);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int config_files_changed(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct config_tree_list *cfl;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(cfl, &cmd->config_files) {
 | 
			
		||||
		if (config_file_changed(cfl->cft))
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_tag_configs(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct config_tree_list *cfl;
 | 
			
		||||
 | 
			
		||||
	if (cmd->cft && cmd->cft->root) {
 | 
			
		||||
		destroy_config_tree(cmd->cft);
 | 
			
		||||
		cmd->cft = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(cfl, &cmd->config_files) {
 | 
			
		||||
		destroy_config_tree(cfl->cft);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(&cmd->config_files);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_dev_cache(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *cn;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
 | 
			
		||||
	if (!dev_cache_init()) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cf->root, "devices/scan", '/'))) {
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "devices/scan"))) {
 | 
			
		||||
		if (!dev_cache_add_dir("/dev")) {
 | 
			
		||||
			log_error("Failed to add /dev to internal "
 | 
			
		||||
				  "device cache");
 | 
			
		||||
@@ -262,41 +490,59 @@ static int _init_dev_cache(struct cmd_context *cmd)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MAX_FILTERS 3
 | 
			
		||||
#define MAX_FILTERS 4
 | 
			
		||||
 | 
			
		||||
static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	unsigned nr_filt = 0;
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
	const struct config_node *cn;
 | 
			
		||||
	struct dev_filter *filters[MAX_FILTERS];
 | 
			
		||||
 | 
			
		||||
	memset(filters, 0, sizeof(filters));
 | 
			
		||||
 | 
			
		||||
	/* sysfs filter */
 | 
			
		||||
	if (find_config_bool(cmd->cf->root, "devices/sysfs_scan", '/',
 | 
			
		||||
	/*
 | 
			
		||||
	 * Filters listed in order: top one gets applied first.
 | 
			
		||||
	 * Failure to initialise some filters is not fatal.
 | 
			
		||||
	 * Update MAX_FILTERS definition above when adding new filters.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * sysfs filter. Only available on 2.6 kernels.  Non-critical.
 | 
			
		||||
	 * Listed first because it's very efficient at eliminating 
 | 
			
		||||
	 * unavailable devices.
 | 
			
		||||
	 */
 | 
			
		||||
	if (find_config_bool(cmd->cft->root, "devices/sysfs_scan",
 | 
			
		||||
			     DEFAULT_SYSFS_SCAN)) {
 | 
			
		||||
		if ((filters[nr_filt] = sysfs_filter_create(cmd->proc_dir)))
 | 
			
		||||
			nr_filt++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* regex filter */
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cf->root, "devices/filter", '/')))
 | 
			
		||||
		log_debug("devices/filter not found in config file: no regex "
 | 
			
		||||
			  "filter installed");
 | 
			
		||||
	/* regex filter. Optional. */
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
 | 
			
		||||
		log_very_verbose("devices/filter not found in config file: "
 | 
			
		||||
				 "no regex filter installed");
 | 
			
		||||
 | 
			
		||||
	else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) {
 | 
			
		||||
		log_error("Failed to create regex device filter");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* device type filter */
 | 
			
		||||
	cn = find_config_node(cmd->cf->root, "devices/types", '/');
 | 
			
		||||
	/* device type filter. Required. */
 | 
			
		||||
	cn = find_config_node(cmd->cft->root, "devices/types");
 | 
			
		||||
	if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
 | 
			
		||||
		log_error("Failed to create lvm type filter");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* only build a composite filter if we really need it */
 | 
			
		||||
	/* md component filter. Optional, non-critical. */
 | 
			
		||||
	if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
 | 
			
		||||
			     DEFAULT_MD_COMPONENT_DETECTION)) {
 | 
			
		||||
		init_md_filtering(1);
 | 
			
		||||
		if ((filters[nr_filt] = md_filter_create()))
 | 
			
		||||
			nr_filt++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Only build a composite filter if we really need it. */
 | 
			
		||||
	return (nr_filt == 1) ?
 | 
			
		||||
	    filters[0] : composite_filter_create(nr_filt, filters);
 | 
			
		||||
}
 | 
			
		||||
@@ -320,22 +566,22 @@ static int _init_filters(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev_cache =
 | 
			
		||||
	    find_config_str(cmd->cf->root, "devices/cache", '/', cache_file);
 | 
			
		||||
	dev_cache = find_config_str(cmd->cft->root, "devices/cache",
 | 
			
		||||
				    cache_file);
 | 
			
		||||
	if (!(f4 = persistent_filter_create(f3, dev_cache))) {
 | 
			
		||||
		log_error("Failed to create persistent device filter");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Should we ever dump persistent filter state? */
 | 
			
		||||
	if (find_config_int(cmd->cf->root, "devices/write_cache_state", '/', 1))
 | 
			
		||||
	if (find_config_int(cmd->cft->root, "devices/write_cache_state", 1))
 | 
			
		||||
		cmd->dump_filter = 1;
 | 
			
		||||
 | 
			
		||||
	if (!*cmd->sys_dir)
 | 
			
		||||
		cmd->dump_filter = 0;
 | 
			
		||||
 | 
			
		||||
	if (!stat(dev_cache, &st) &&
 | 
			
		||||
	    (st.st_mtime > config_file_timestamp(cmd->cf)) &&
 | 
			
		||||
	    (st.st_mtime > config_file_timestamp(cmd->cft)) &&
 | 
			
		||||
	    !persistent_filter_load(f4))
 | 
			
		||||
		log_verbose("Failed to load existing device cache from %s",
 | 
			
		||||
			    dev_cache);
 | 
			
		||||
@@ -353,7 +599,7 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
	struct list *fmth;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
	const struct config_node *cn;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	label_init();
 | 
			
		||||
@@ -365,10 +611,16 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
	list_add(&cmd->formats, &fmt->list);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef POOL_INTERNAL
 | 
			
		||||
	if (!(fmt = init_pool_format(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	fmt->library = NULL;
 | 
			
		||||
	list_add(&cmd->formats, &fmt->list);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	/* Load any formats in shared libs */
 | 
			
		||||
	if ((cn = find_config_node(cmd->cf->root, "global/format_libraries",
 | 
			
		||||
				   '/'))) {
 | 
			
		||||
	if ((cn = find_config_node(cmd->cft->root, "global/format_libraries"))) {
 | 
			
		||||
 | 
			
		||||
		struct config_value *cv;
 | 
			
		||||
		struct format_type *(*init_format_fn) (struct cmd_context *);
 | 
			
		||||
@@ -380,7 +632,7 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
					  "global/format_libraries");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(lib = load_shared_library(cmd->cf, cv->v.str,
 | 
			
		||||
			if (!(lib = load_shared_library(cmd->cft, cv->v.str,
 | 
			
		||||
							"format"))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
@@ -408,7 +660,7 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	cmd->fmt_backup = fmt;
 | 
			
		||||
 | 
			
		||||
	format = find_config_str(cmd->cf->root, "global/format", '/',
 | 
			
		||||
	format = find_config_str(cmd->cft->root, "global/format",
 | 
			
		||||
				 DEFAULT_FORMAT);
 | 
			
		||||
 | 
			
		||||
	list_iterate(fmth, &cmd->formats) {
 | 
			
		||||
@@ -424,6 +676,119 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_segtypes(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct segment_type *segtype;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	const struct config_node *cn;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (!(segtype = init_striped_segtype(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	segtype->library = NULL;
 | 
			
		||||
	list_add(&cmd->segtypes, &segtype->list);
 | 
			
		||||
 | 
			
		||||
	if (!(segtype = init_zero_segtype(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	segtype->library = NULL;
 | 
			
		||||
	list_add(&cmd->segtypes, &segtype->list);
 | 
			
		||||
 | 
			
		||||
	if (!(segtype = init_error_segtype(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	segtype->library = NULL;
 | 
			
		||||
	list_add(&cmd->segtypes, &segtype->list);
 | 
			
		||||
 | 
			
		||||
#ifdef SNAPSHOT_INTERNAL
 | 
			
		||||
	if (!(segtype = init_snapshot_segtype(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	segtype->library = NULL;
 | 
			
		||||
	list_add(&cmd->segtypes, &segtype->list);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MIRRORED_INTERNAL
 | 
			
		||||
	if (!(segtype = init_mirrored_segtype(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	segtype->library = NULL;
 | 
			
		||||
	list_add(&cmd->segtypes, &segtype->list);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	/* Load any formats in shared libs */
 | 
			
		||||
	if ((cn = find_config_node(cmd->cft->root, "global/segment_libraries"))) {
 | 
			
		||||
 | 
			
		||||
		struct config_value *cv;
 | 
			
		||||
		struct segment_type *(*init_segtype_fn) (struct cmd_context *);
 | 
			
		||||
		void *lib;
 | 
			
		||||
		struct list *sgtl, *tmp;
 | 
			
		||||
		struct segment_type *segtype2;
 | 
			
		||||
 | 
			
		||||
		for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
			if (cv->type != CFG_STRING) {
 | 
			
		||||
				log_error("Invalid string in config file: "
 | 
			
		||||
					  "global/segment_libraries");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(lib = load_shared_library(cmd->cft, cv->v.str,
 | 
			
		||||
							"segment type"))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
 | 
			
		||||
				log_error("Shared library %s does not contain "
 | 
			
		||||
					  "segment type functions", cv->v.str);
 | 
			
		||||
				dlclose(lib);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!(segtype = init_segtype_fn(cmd)))
 | 
			
		||||
				return 0;
 | 
			
		||||
			segtype->library = lib;
 | 
			
		||||
			list_add(&cmd->segtypes, &segtype->list);
 | 
			
		||||
 | 
			
		||||
			list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
 | 
			
		||||
				segtype2 = list_item(sgtl, struct segment_type);
 | 
			
		||||
				if (!strcmp(segtype2->name, segtype->name)) {
 | 
			
		||||
					log_error("Duplicate segment type %s: "
 | 
			
		||||
						  "unloading shared library %s",
 | 
			
		||||
						  segtype->name, cv->v.str);
 | 
			
		||||
					list_del(&segtype->list);
 | 
			
		||||
					segtype->ops->destroy(segtype);
 | 
			
		||||
					dlclose(lib);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_hostname(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct utsname uts;
 | 
			
		||||
 | 
			
		||||
	if (uname(&uts)) {
 | 
			
		||||
		log_sys_error("uname", "_init_hostname");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->hostname = pool_strdup(cmd->libmem, uts.nodename))) {
 | 
			
		||||
		log_error("_init_hostname: pool_strdup failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->kernel_vsn = pool_strdup(cmd->libmem, uts.release))) {
 | 
			
		||||
		log_error("_init_hostname: pool_strdup kernel_vsn failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Entry point */
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
{
 | 
			
		||||
@@ -434,7 +799,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (!setlocale(LC_ALL, ""))
 | 
			
		||||
		log_error("setlocale failed");
 | 
			
		||||
		log_very_verbose("setlocale failed");
 | 
			
		||||
 | 
			
		||||
#ifdef INTL_PACKAGE
 | 
			
		||||
	bindtextdomain(INTL_PACKAGE, LOCALEDIR);
 | 
			
		||||
@@ -448,7 +813,11 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
	}
 | 
			
		||||
	memset(cmd, 0, sizeof(*cmd));
 | 
			
		||||
	cmd->args = the_args;
 | 
			
		||||
	cmd->hosttags = 0;
 | 
			
		||||
	list_init(&cmd->formats);
 | 
			
		||||
	list_init(&cmd->segtypes);
 | 
			
		||||
	list_init(&cmd->tags);
 | 
			
		||||
	list_init(&cmd->config_files);
 | 
			
		||||
 | 
			
		||||
	strcpy(cmd->sys_dir, DEFAULT_SYS_DIR);
 | 
			
		||||
 | 
			
		||||
@@ -459,11 +828,28 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
	if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!_init_config(cmd))
 | 
			
		||||
	if (!(cmd->libmem = pool_create("library", 4 * 1024))) {
 | 
			
		||||
		log_error("Library memory pool creation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_init_lvm_conf(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	_init_logging(cmd);
 | 
			
		||||
 | 
			
		||||
	if (!_init_hostname(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!_init_tags(cmd, cmd->cft))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!_init_tag_configs(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!_merge_config_files(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!_process_config(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
@@ -473,7 +859,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
	if (!_init_filters(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->mem = pool_create(4 * 1024))) {
 | 
			
		||||
	if (!(cmd->mem = pool_create("command", 4 * 1024))) {
 | 
			
		||||
		log_error("Command memory pool creation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -483,8 +869,12 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
	if (!_init_formats(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!_init_segtypes(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	cmd->current_settings = cmd->default_settings;
 | 
			
		||||
 | 
			
		||||
	cmd->config_valid = 1;
 | 
			
		||||
	return cmd;
 | 
			
		||||
 | 
			
		||||
      error:
 | 
			
		||||
@@ -510,6 +900,83 @@ static void _destroy_formats(struct list *formats)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_segtypes(struct list *segtypes)
 | 
			
		||||
{
 | 
			
		||||
	struct list *sgtl, *tmp;
 | 
			
		||||
	struct segment_type *segtype;
 | 
			
		||||
	void *lib;
 | 
			
		||||
 | 
			
		||||
	list_iterate_safe(sgtl, tmp, segtypes) {
 | 
			
		||||
		segtype = list_item(sgtl, struct segment_type);
 | 
			
		||||
		list_del(&segtype->list);
 | 
			
		||||
		lib = segtype->library;
 | 
			
		||||
		segtype->ops->destroy(segtype);
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
		if (lib)
 | 
			
		||||
			dlclose(lib);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int refresh_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	log_verbose("Reloading config files");
 | 
			
		||||
 | 
			
		||||
	if (cmd->config_valid) {
 | 
			
		||||
		if (cmd->dump_filter)
 | 
			
		||||
			persistent_filter_dump(cmd->filter);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	activation_exit();
 | 
			
		||||
	lvmcache_destroy();
 | 
			
		||||
	label_exit();
 | 
			
		||||
	_destroy_segtypes(&cmd->segtypes);
 | 
			
		||||
	_destroy_formats(&cmd->formats);
 | 
			
		||||
	if (cmd->filter) {
 | 
			
		||||
		cmd->filter->destroy(cmd->filter);
 | 
			
		||||
		cmd->filter = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	dev_cache_exit();
 | 
			
		||||
	_destroy_tags(cmd);
 | 
			
		||||
	_destroy_tag_configs(cmd);
 | 
			
		||||
 | 
			
		||||
	cmd->config_valid = 0;
 | 
			
		||||
 | 
			
		||||
	cmd->hosttags = 0;
 | 
			
		||||
 | 
			
		||||
	if (!_init_lvm_conf(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	_init_logging(cmd);
 | 
			
		||||
 | 
			
		||||
	if (!_init_tags(cmd, cmd->cft))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_init_tag_configs(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_merge_config_files(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_process_config(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_init_dev_cache(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_init_filters(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_init_formats(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_init_segtypes(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	cmd->config_valid = 1;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void destroy_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	if (cmd->dump_filter)
 | 
			
		||||
@@ -518,11 +985,14 @@ void destroy_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
	activation_exit();
 | 
			
		||||
	lvmcache_destroy();
 | 
			
		||||
	label_exit();
 | 
			
		||||
	_destroy_segtypes(&cmd->segtypes);
 | 
			
		||||
	_destroy_formats(&cmd->formats);
 | 
			
		||||
	cmd->filter->destroy(cmd->filter);
 | 
			
		||||
	pool_destroy(cmd->mem);
 | 
			
		||||
	dev_cache_exit();
 | 
			
		||||
	destroy_config_tree(cmd->cf);
 | 
			
		||||
	_destroy_tags(cmd);
 | 
			
		||||
	_destroy_tag_configs(cmd);
 | 
			
		||||
	pool_destroy(cmd->libmem);
 | 
			
		||||
	dbg_free(cmd);
 | 
			
		||||
 | 
			
		||||
	release_log_memory();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_TOOLCONTEXT_H
 | 
			
		||||
#define _LVM_TOOLCONTEXT_H
 | 
			
		||||
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
@@ -39,16 +45,21 @@ struct config_info {
 | 
			
		||||
	mode_t umask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct config_tree;
 | 
			
		||||
 | 
			
		||||
/* FIXME Split into tool & library contexts */
 | 
			
		||||
/* command-instance-related variables needed by library */
 | 
			
		||||
struct cmd_context {
 | 
			
		||||
	/* format handler allocates all objects from here */
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
	struct pool *libmem;	/* For permanent config data */
 | 
			
		||||
	struct pool *mem;	/* Transient: Cleared between each command */
 | 
			
		||||
 | 
			
		||||
	const struct format_type *fmt;	/* Current format to use by default */
 | 
			
		||||
	struct format_type *fmt_backup;	/* Format to use for backups */
 | 
			
		||||
 | 
			
		||||
	struct list formats;	/* Available formats */
 | 
			
		||||
	struct list segtypes;	/* Available segment types */
 | 
			
		||||
	const char *hostname;
 | 
			
		||||
	const char *kernel_vsn;
 | 
			
		||||
 | 
			
		||||
	char *cmd_line;
 | 
			
		||||
	struct command *command;
 | 
			
		||||
@@ -58,10 +69,16 @@ struct cmd_context {
 | 
			
		||||
	struct dev_filter *filter;
 | 
			
		||||
	int dump_filter;	/* Dump filter when exiting? */
 | 
			
		||||
 | 
			
		||||
	struct config_tree *cf;
 | 
			
		||||
	struct list config_files;
 | 
			
		||||
	int config_valid;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
	struct config_info default_settings;
 | 
			
		||||
	struct config_info current_settings;
 | 
			
		||||
 | 
			
		||||
	/* List of defined tags */
 | 
			
		||||
	struct list tags;
 | 
			
		||||
	int hosttags;
 | 
			
		||||
 | 
			
		||||
	char sys_dir[PATH_MAX];
 | 
			
		||||
	char dev_dir[PATH_MAX];
 | 
			
		||||
	char proc_dir[PATH_MAX];
 | 
			
		||||
@@ -69,5 +86,7 @@ struct cmd_context {
 | 
			
		||||
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args);
 | 
			
		||||
void destroy_toolcontext(struct cmd_context *cmd);
 | 
			
		||||
int refresh_toolcontext(struct cmd_context *cmd);
 | 
			
		||||
int config_files_changed(struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -9,6 +18,8 @@
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
@@ -43,10 +54,11 @@ struct parser {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cs {
 | 
			
		||||
	struct config_tree cf;
 | 
			
		||||
	struct config_tree cft;
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
	time_t timestamp;
 | 
			
		||||
	char *filename;
 | 
			
		||||
	int exists;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void _get_token(struct parser *p, int tok_prev);
 | 
			
		||||
@@ -60,6 +72,8 @@ static struct config_value *_create_value(struct parser *p);
 | 
			
		||||
static struct config_node *_create_node(struct parser *p);
 | 
			
		||||
static char *_dup_tok(struct parser *p);
 | 
			
		||||
 | 
			
		||||
static const int sep = '/';
 | 
			
		||||
 | 
			
		||||
#define MAX_INDENT 32
 | 
			
		||||
 | 
			
		||||
#define match(t) do {\
 | 
			
		||||
@@ -82,39 +96,41 @@ static int _tok_match(const char *str, const char *b, const char *e)
 | 
			
		||||
/*
 | 
			
		||||
 * public interface
 | 
			
		||||
 */
 | 
			
		||||
struct config_tree *create_config_tree(void)
 | 
			
		||||
struct config_tree *create_config_tree(const char *filename)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c;
 | 
			
		||||
	struct pool *mem = pool_create(10 * 1024);
 | 
			
		||||
	struct pool *mem = pool_create("config", 10 * 1024);
 | 
			
		||||
 | 
			
		||||
	if (!mem) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(c = pool_alloc(mem, sizeof(*c)))) {
 | 
			
		||||
	if (!(c = pool_zalloc(mem, sizeof(*c)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		pool_destroy(mem);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c->mem = mem;
 | 
			
		||||
	c->cf.root = (struct config_node *) NULL;
 | 
			
		||||
	c->cft.root = (struct config_node *) NULL;
 | 
			
		||||
	c->timestamp = 0;
 | 
			
		||||
	c->filename = NULL;
 | 
			
		||||
	return &c->cf;
 | 
			
		||||
	c->exists = 0;
 | 
			
		||||
	if (filename)
 | 
			
		||||
		c->filename = pool_strdup(c->mem, filename);
 | 
			
		||||
	return &c->cft;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void destroy_config_tree(struct config_tree *cf)
 | 
			
		||||
void destroy_config_tree(struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	pool_destroy(((struct cs *) cf)->mem);
 | 
			
		||||
	pool_destroy(((struct cs *) cft)->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cf, struct device *dev,
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cf;
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
	struct parser *p;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	int use_mmap = 1;
 | 
			
		||||
@@ -172,7 +188,7 @@ int read_config_fd(struct config_tree *cf, struct device *dev,
 | 
			
		||||
	p->tb = p->te = p->fb;
 | 
			
		||||
	p->line = 1;
 | 
			
		||||
	_get_token(p, TOK_SECTION_E);
 | 
			
		||||
	if (!(cf->root = _file(p))) {
 | 
			
		||||
	if (!(cft->root = _file(p))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -193,99 +209,30 @@ int read_config_fd(struct config_tree *cf, struct device *dev,
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int read_config_file(struct config_tree *cf, const char *file)
 | 
			
		||||
int read_config_file(struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cf;
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
	if (stat(file, &info)) {
 | 
			
		||||
		log_sys_error("stat", file);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!S_ISREG(info.st_mode)) {
 | 
			
		||||
		log_error("%s is not a regular file", file);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info.st_size == 0) {
 | 
			
		||||
		log_verbose("%s is empty", file);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dev = dev_create_file(file, NULL, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(cf, dev, 0, (size_t) info.st_size, 0, 0,
 | 
			
		||||
			   (checksum_fn_t) NULL, 0);
 | 
			
		||||
 | 
			
		||||
	dev_close(dev);
 | 
			
		||||
 | 
			
		||||
	c->timestamp = info.st_mtime;
 | 
			
		||||
	c->filename = pool_strdup(c->mem, file);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
time_t config_file_timestamp(struct config_tree *cf)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cf;
 | 
			
		||||
 | 
			
		||||
	return c->timestamp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if config file reloaded
 | 
			
		||||
 */
 | 
			
		||||
int reload_config_file(struct config_tree **cf)
 | 
			
		||||
{
 | 
			
		||||
	struct config_tree *new_cf;
 | 
			
		||||
	struct cs *c = (struct cs *) *cf;
 | 
			
		||||
	struct cs *new_cs;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!c->filename)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (stat(c->filename, &info) == -1) {
 | 
			
		||||
		if (errno == ENOENT)
 | 
			
		||||
			return 1;
 | 
			
		||||
	if (stat(c->filename, &info)) {
 | 
			
		||||
		log_sys_error("stat", c->filename);
 | 
			
		||||
		log_error("Failed to reload configuration file");
 | 
			
		||||
		c->exists = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!S_ISREG(info.st_mode)) {
 | 
			
		||||
		log_error("Configuration file %s is not a regular file",
 | 
			
		||||
			  c->filename);
 | 
			
		||||
		log_error("%s is not a regular file", c->filename);
 | 
			
		||||
		c->exists = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Unchanged? */
 | 
			
		||||
	if (c->timestamp == info.st_mtime)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	log_verbose("Detected config file change: Reloading %s", c->filename);
 | 
			
		||||
	c->exists = 1;
 | 
			
		||||
 | 
			
		||||
	if (info.st_size == 0) {
 | 
			
		||||
		log_verbose("Config file reload: %s is empty", c->filename);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(new_cf = create_config_tree())) {
 | 
			
		||||
		log_error("Allocation of new config_tree failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
		log_verbose("%s is empty", c->filename);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
 | 
			
		||||
@@ -298,22 +245,63 @@ int reload_config_file(struct config_tree **cf)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(new_cf, dev, 0, (size_t) info.st_size,
 | 
			
		||||
			   0, 0, (checksum_fn_t) NULL, 0);
 | 
			
		||||
	r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0,
 | 
			
		||||
			   (checksum_fn_t) NULL, 0);
 | 
			
		||||
 | 
			
		||||
	dev_close(dev);
 | 
			
		||||
 | 
			
		||||
	if (r) {
 | 
			
		||||
		new_cs = (struct cs *) new_cf;
 | 
			
		||||
		new_cs->filename = pool_strdup(new_cs->mem, c->filename);
 | 
			
		||||
		new_cs->timestamp = info.st_mtime;
 | 
			
		||||
		destroy_config_tree(*cf);
 | 
			
		||||
		*cf = new_cf;
 | 
			
		||||
	}
 | 
			
		||||
	c->timestamp = info.st_mtime;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
time_t config_file_timestamp(struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
 | 
			
		||||
	return c->timestamp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return 1 if config files ought to be reloaded
 | 
			
		||||
 */
 | 
			
		||||
int config_file_changed(struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
 | 
			
		||||
	if (!c->filename)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (stat(c->filename, &info) == -1) {
 | 
			
		||||
		/* Ignore a deleted config file: still use original data */
 | 
			
		||||
		if (errno == ENOENT) {
 | 
			
		||||
			if (!c->exists)
 | 
			
		||||
				return 0;
 | 
			
		||||
			log_very_verbose("Config file %s has disappeared!",
 | 
			
		||||
					 c->filename);
 | 
			
		||||
			goto reload;
 | 
			
		||||
		}
 | 
			
		||||
		log_sys_error("stat", c->filename);
 | 
			
		||||
		log_error("Failed to reload configuration files");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!S_ISREG(info.st_mode)) {
 | 
			
		||||
		log_error("Configuration file %s is not a regular file",
 | 
			
		||||
			  c->filename);
 | 
			
		||||
		goto reload;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Unchanged? */
 | 
			
		||||
	if (c->timestamp == info.st_mtime)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
      reload:
 | 
			
		||||
	log_verbose("Detected config file change to %s", c->filename);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _write_value(FILE *fp, struct config_value *v)
 | 
			
		||||
{
 | 
			
		||||
	switch (v->type) {
 | 
			
		||||
@@ -382,7 +370,7 @@ static int _write_config(struct config_node *n, FILE *fp, int level)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int write_config_file(struct config_tree *cf, const char *file)
 | 
			
		||||
int write_config_file(struct config_tree *cft, const char *file)
 | 
			
		||||
{
 | 
			
		||||
	int r = 1;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
@@ -396,7 +384,7 @@ int write_config_file(struct config_tree *cf, const char *file)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_verbose("Dumping configuration to %s", file);
 | 
			
		||||
	if (!_write_config(cf->root, fp, 0)) {
 | 
			
		||||
	if (!_write_config(cft->root, fp, 0)) {
 | 
			
		||||
		log_error("Failure while writing configuration");
 | 
			
		||||
		r = 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -728,8 +716,8 @@ static char *_dup_tok(struct parser *p)
 | 
			
		||||
/*
 | 
			
		||||
 * utility functions
 | 
			
		||||
 */
 | 
			
		||||
struct config_node *find_config_node(struct config_node *cn,
 | 
			
		||||
				     const char *path, const int sep)
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path)
 | 
			
		||||
{
 | 
			
		||||
	const char *e;
 | 
			
		||||
 | 
			
		||||
@@ -757,13 +745,13 @@ struct config_node *find_config_node(struct config_node *cn,
 | 
			
		||||
		path = e;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cn;
 | 
			
		||||
	return (struct config_node *) cn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *find_config_str(struct config_node *cn,
 | 
			
		||||
			    const char *path, const int sep, const char *fail)
 | 
			
		||||
const char *find_config_str(const struct config_node *cn,
 | 
			
		||||
			    const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = find_config_node(cn, path, sep);
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_STRING) {
 | 
			
		||||
		if (*n->v->v.str)
 | 
			
		||||
@@ -777,10 +765,9 @@ const char *find_config_str(struct config_node *cn,
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_int(struct config_node *cn, const char *path,
 | 
			
		||||
		    const int sep, int fail)
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = find_config_node(cn, path, sep);
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_INT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %d", path, n->v->v.i);
 | 
			
		||||
@@ -792,10 +779,10 @@ int find_config_int(struct config_node *cn, const char *path,
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_float(struct config_node *cn, const char *path,
 | 
			
		||||
			const int sep, float fail)
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = find_config_node(cn, path, sep);
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_FLOAT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %f", path, n->v->v.r);
 | 
			
		||||
@@ -835,10 +822,9 @@ static int _str_to_bool(const char *str, int fail)
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_bool(struct config_node *cn, const char *path,
 | 
			
		||||
		     const int sep, int fail)
 | 
			
		||||
int find_config_bool(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = find_config_node(cn, path, sep);
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	struct config_value *v;
 | 
			
		||||
 | 
			
		||||
	if (!n)
 | 
			
		||||
@@ -857,12 +843,12 @@ int find_config_bool(struct config_node *cn, const char *path,
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_config_uint32(struct config_node *cn, const char *path,
 | 
			
		||||
		      const int sep, uint32_t *result)
 | 
			
		||||
int get_config_uint32(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint32_t *result)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n;
 | 
			
		||||
	const struct config_node *n;
 | 
			
		||||
 | 
			
		||||
	n = find_config_node(cn, path, sep);
 | 
			
		||||
	n = find_config_node(cn, path);
 | 
			
		||||
 | 
			
		||||
	if (!n || !n->v || n->v->type != CFG_INT)
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -871,12 +857,12 @@ int get_config_uint32(struct config_node *cn, const char *path,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_config_uint64(struct config_node *cn, const char *path,
 | 
			
		||||
		      const int sep, uint64_t *result)
 | 
			
		||||
int get_config_uint64(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint64_t *result)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n;
 | 
			
		||||
	const struct config_node *n;
 | 
			
		||||
 | 
			
		||||
	n = find_config_node(cn, path, sep);
 | 
			
		||||
	n = find_config_node(cn, path);
 | 
			
		||||
 | 
			
		||||
	if (!n || !n->v || n->v->type != CFG_INT)
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -886,12 +872,12 @@ int get_config_uint64(struct config_node *cn, const char *path,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_config_str(struct config_node *cn, const char *path,
 | 
			
		||||
		   const int sep, char **result)
 | 
			
		||||
int get_config_str(const struct config_node *cn, const char *path,
 | 
			
		||||
		   char **result)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n;
 | 
			
		||||
	const struct config_node *n;
 | 
			
		||||
 | 
			
		||||
	n = find_config_node(cn, path, sep);
 | 
			
		||||
	n = find_config_node(cn, path);
 | 
			
		||||
 | 
			
		||||
	if (!n || !n->v || n->v->type != CFG_STRING)
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -899,3 +885,115 @@ int get_config_str(struct config_node *cn, const char *path,
 | 
			
		||||
	*result = n->v->v.str;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Insert cn2 after cn1 */
 | 
			
		||||
static void _insert_config_node(struct config_node **cn1,
 | 
			
		||||
				struct config_node *cn2)
 | 
			
		||||
{
 | 
			
		||||
	if (!*cn1) {
 | 
			
		||||
		*cn1 = cn2;
 | 
			
		||||
		cn2->sib = NULL;
 | 
			
		||||
	} else {
 | 
			
		||||
		cn2->sib = (*cn1)->sib;
 | 
			
		||||
		(*cn1)->sib = cn2;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Merge section cn2 into section cn1 (which has the same name)
 | 
			
		||||
 * overwriting any existing cn1 nodes with matching names.
 | 
			
		||||
 */
 | 
			
		||||
static void _merge_section(struct config_node *cn1, struct config_node *cn2)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *cn, *nextn, *oldn;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
 | 
			
		||||
	for (cn = cn2->child; cn; cn = nextn) {
 | 
			
		||||
		nextn = cn->sib;
 | 
			
		||||
 | 
			
		||||
		/* Skip "tags" */
 | 
			
		||||
		if (!strcmp(cn->key, "tags"))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* Subsection? */
 | 
			
		||||
		if (!cn->v)
 | 
			
		||||
			/* Ignore - we don't have any of these yet */
 | 
			
		||||
			continue;
 | 
			
		||||
		/* Not already present? */
 | 
			
		||||
		if (!(oldn = find_config_node(cn1->child, cn->key))) {
 | 
			
		||||
			_insert_config_node(&cn1->child, cn);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		/* Merge certain value lists */
 | 
			
		||||
		if ((!strcmp(cn1->key, "activation") &&
 | 
			
		||||
		     !strcmp(cn->key, "volume_list")) ||
 | 
			
		||||
		    (!strcmp(cn1->key, "devices") &&
 | 
			
		||||
		     (!strcmp(cn->key, "filter") || !strcmp(cn->key, "types")))) {
 | 
			
		||||
			cv = cn->v;
 | 
			
		||||
			while (cv->next)
 | 
			
		||||
				cv = cv->next;
 | 
			
		||||
			cv->next = oldn->v;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Replace values */
 | 
			
		||||
		oldn->v = cn->v;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _match_host_tags(struct list *tags, struct config_node *tn)
 | 
			
		||||
{
 | 
			
		||||
	struct config_value *tv;
 | 
			
		||||
	const char *str;
 | 
			
		||||
 | 
			
		||||
	for (tv = tn->v; tv; tv = tv->next) {
 | 
			
		||||
		if (tv->type != CFG_STRING)
 | 
			
		||||
			continue;
 | 
			
		||||
		str = tv->v.str;
 | 
			
		||||
		if (*str == '@')
 | 
			
		||||
			str++;
 | 
			
		||||
		if (!*str)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (str_list_match_item(tags, str))
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Destructively merge a new config tree into an existing one */
 | 
			
		||||
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
 | 
			
		||||
		      struct config_tree *newdata)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *root = cft->root;
 | 
			
		||||
	struct config_node *cn, *nextn, *oldn, *tn, *cn2;
 | 
			
		||||
 | 
			
		||||
	for (cn = newdata->root; cn; cn = nextn) {
 | 
			
		||||
		nextn = cn->sib;
 | 
			
		||||
		/* Ignore tags section */
 | 
			
		||||
		if (!strcmp(cn->key, "tags"))
 | 
			
		||||
			continue;
 | 
			
		||||
		/* If there's a tags node, skip if host tags don't match */
 | 
			
		||||
		if ((tn = find_config_node(cn->child, "tags"))) {
 | 
			
		||||
			if (!_match_host_tags(&cmd->tags, tn))
 | 
			
		||||
				continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(oldn = find_config_node(root, cn->key))) {
 | 
			
		||||
			_insert_config_node(&cft->root, cn);
 | 
			
		||||
			/* Remove any "tags" nodes */
 | 
			
		||||
			for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
 | 
			
		||||
				if (!strcmp(cn2->key, "tags")) {
 | 
			
		||||
					cn->child = cn2->sib;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (cn2->sib && !strcmp(cn2->sib->key, "tags")) {
 | 
			
		||||
					cn2->sib = cn2->sib->sib;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		_merge_section(oldn, cn);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_CONFIG_H
 | 
			
		||||
#define _LVM_CONFIG_H
 | 
			
		||||
 | 
			
		||||
#include "device.h"
 | 
			
		||||
struct device;
 | 
			
		||||
struct cmd_context;
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	CFG_STRING,
 | 
			
		||||
@@ -36,46 +46,51 @@ struct config_tree {
 | 
			
		||||
	struct config_node *root;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct config_tree *create_config_tree(void);
 | 
			
		||||
void destroy_config_tree(struct config_tree *cf);
 | 
			
		||||
struct config_tree_list {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct config_tree *create_config_tree(const char *filename);
 | 
			
		||||
void destroy_config_tree(struct config_tree *cft);
 | 
			
		||||
 | 
			
		||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cf, struct device *dev,
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
int read_config_file(struct config_tree *cf, const char *file);
 | 
			
		||||
int write_config_file(struct config_tree *cf, const char *file);
 | 
			
		||||
int reload_config_file(struct config_tree **cf);
 | 
			
		||||
time_t config_file_timestamp(struct config_tree *cf);
 | 
			
		||||
int read_config_file(struct config_tree *cft);
 | 
			
		||||
int write_config_file(struct config_tree *cft, const char *file);
 | 
			
		||||
time_t config_file_timestamp(struct config_tree *cft);
 | 
			
		||||
int config_file_changed(struct config_tree *cft);
 | 
			
		||||
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
 | 
			
		||||
		      struct config_tree *newdata);
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_node(struct config_node *cn,
 | 
			
		||||
				     const char *path, const int separator);
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path);
 | 
			
		||||
 | 
			
		||||
const char *find_config_str(struct config_node *cn,
 | 
			
		||||
			    const char *path, const int sep, const char *fail);
 | 
			
		||||
const char *find_config_str(const struct config_node *cn, const char *path,
 | 
			
		||||
			    const char *fail);
 | 
			
		||||
 | 
			
		||||
int find_config_int(struct config_node *cn, const char *path,
 | 
			
		||||
		    const int sep, int fail);
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail);
 | 
			
		||||
 | 
			
		||||
float find_config_float(struct config_node *cn, const char *path,
 | 
			
		||||
			const int sep, float fail);
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Understands (0, ~0), (y, n), (yes, no), (on,
 | 
			
		||||
 * off), (true, false).
 | 
			
		||||
 */
 | 
			
		||||
int find_config_bool(struct config_node *cn, const char *path,
 | 
			
		||||
		     const int sep, int fail);
 | 
			
		||||
int find_config_bool(const struct config_node *cn, const char *path, int fail);
 | 
			
		||||
 | 
			
		||||
int get_config_uint32(struct config_node *cn, const char *path,
 | 
			
		||||
		      const int sep, uint32_t *result);
 | 
			
		||||
int get_config_uint32(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint32_t *result);
 | 
			
		||||
 | 
			
		||||
int get_config_uint64(struct config_node *cn, const char *path,
 | 
			
		||||
		      const int sep, uint64_t *result);
 | 
			
		||||
int get_config_uint64(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint64_t *result);
 | 
			
		||||
 | 
			
		||||
int get_config_str(struct config_node *cn, const char *path,
 | 
			
		||||
		   const int sep, char **result);
 | 
			
		||||
int get_config_str(const struct config_node *cn, const char *path,
 | 
			
		||||
		   char **result);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_DEFAULTS_H
 | 
			
		||||
@@ -20,12 +29,19 @@
 | 
			
		||||
#define DEFAULT_DEV_DIR "/dev"
 | 
			
		||||
#define DEFAULT_PROC_DIR "/proc"
 | 
			
		||||
#define DEFAULT_SYSFS_SCAN 1
 | 
			
		||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
 | 
			
		||||
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_UMASK 0077
 | 
			
		||||
 | 
			
		||||
#ifdef LVM1_FALLBACK
 | 
			
		||||
#  define DEFAULT_FALLBACK_TO_LVM1 1
 | 
			
		||||
#else
 | 
			
		||||
#  define DEFAULT_FALLBACK_TO_LVM1 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef LVM1_SUPPORT
 | 
			
		||||
#  define DEFAULT_FORMAT "lvm1"
 | 
			
		||||
#else
 | 
			
		||||
@@ -51,6 +67,7 @@
 | 
			
		||||
#define DEFAULT_INDENT 1
 | 
			
		||||
#define DEFAULT_UNITS "h"
 | 
			
		||||
#define DEFAULT_SUFFIX 1
 | 
			
		||||
#define DEFAULT_HOSTTAGS 0
 | 
			
		||||
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
#  define DEFAULT_ACTIVATION 1
 | 
			
		||||
@@ -74,14 +91,14 @@
 | 
			
		||||
#define DEFAULT_REP_HEADINGS 1
 | 
			
		||||
#define DEFAULT_REP_SEPARATOR " "
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,move_percent"
 | 
			
		||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,copy_percent"
 | 
			
		||||
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
 | 
			
		||||
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
 | 
			
		||||
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,move_pv,move_percent,lv_uuid"
 | 
			
		||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,lv_uuid"
 | 
			
		||||
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
 | 
			
		||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid"
 | 
			
		||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
 | 
			
		||||
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LVS_SORT "vg_name,lv_name"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_BITSET_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_BTREE_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -10,7 +19,8 @@
 | 
			
		||||
struct hash_node {
 | 
			
		||||
	struct hash_node *next;
 | 
			
		||||
	void *data;
 | 
			
		||||
	char key[1];
 | 
			
		||||
	int keylen;
 | 
			
		||||
	char key[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct hash_table {
 | 
			
		||||
@@ -47,22 +57,23 @@ static unsigned char _nums[] = {
 | 
			
		||||
	209
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct hash_node *_create_node(const char *str)
 | 
			
		||||
static struct hash_node *_create_node(const char *str, int len)
 | 
			
		||||
{
 | 
			
		||||
	/* remember sizeof(n) includes an extra char from key[1],
 | 
			
		||||
	   so not adding 1 to the strlen as you would expect */
 | 
			
		||||
	struct hash_node *n = dbg_malloc(sizeof(*n) + strlen(str));
 | 
			
		||||
	struct hash_node *n = dbg_malloc(sizeof(*n) + len);
 | 
			
		||||
 | 
			
		||||
	if (n)
 | 
			
		||||
		strcpy(n->key, str);
 | 
			
		||||
	if (n) {
 | 
			
		||||
		memcpy(n->key, str, len);
 | 
			
		||||
		n->keylen = len;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned _hash(const char *str)
 | 
			
		||||
static unsigned _hash(const char *str, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long h = 0, g;
 | 
			
		||||
	while (*str) {
 | 
			
		||||
	unsigned long h = 0, g, i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < len; i++) {
 | 
			
		||||
		h <<= 4;
 | 
			
		||||
		h += _nums[(int) *str++];
 | 
			
		||||
		g = h & ((unsigned long) 0xf << 16u);
 | 
			
		||||
@@ -71,6 +82,7 @@ static unsigned _hash(const char *str)
 | 
			
		||||
			h ^= g >> 5u;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -125,32 +137,35 @@ void hash_destroy(struct hash_table *t)
 | 
			
		||||
	dbg_free(t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct hash_node **_find(struct hash_table *t, const char *key)
 | 
			
		||||
static inline struct hash_node **_find(struct hash_table *t, const char *key,
 | 
			
		||||
				       uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	unsigned h = _hash(key) & (t->num_slots - 1);
 | 
			
		||||
	unsigned h = _hash(key, len) & (t->num_slots - 1);
 | 
			
		||||
	struct hash_node **c;
 | 
			
		||||
 | 
			
		||||
	for (c = &t->slots[h]; *c; c = &((*c)->next))
 | 
			
		||||
		if (!strcmp(key, (*c)->key))
 | 
			
		||||
		if (!memcmp(key, (*c)->key, len))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
	return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *hash_lookup(struct hash_table *t, const char *key)
 | 
			
		||||
void *hash_lookup_binary(struct hash_table *t, const char *key,
 | 
			
		||||
			 uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node **c = _find(t, key);
 | 
			
		||||
	struct hash_node **c = _find(t, key, len);
 | 
			
		||||
	return *c ? (*c)->data : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int hash_insert(struct hash_table *t, const char *key, void *data)
 | 
			
		||||
int hash_insert_binary(struct hash_table *t, const char *key,
 | 
			
		||||
		       uint32_t len, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node **c = _find(t, key);
 | 
			
		||||
	struct hash_node **c = _find(t, key, len);
 | 
			
		||||
 | 
			
		||||
	if (*c)
 | 
			
		||||
		(*c)->data = data;
 | 
			
		||||
	else {
 | 
			
		||||
		struct hash_node *n = _create_node(key);
 | 
			
		||||
		struct hash_node *n = _create_node(key, len);
 | 
			
		||||
 | 
			
		||||
		if (!n)
 | 
			
		||||
			return 0;
 | 
			
		||||
@@ -164,9 +179,10 @@ int hash_insert(struct hash_table *t, const char *key, void *data)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hash_remove(struct hash_table *t, const char *key)
 | 
			
		||||
void hash_remove_binary(struct hash_table *t, const char *key,
 | 
			
		||||
			uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node **c = _find(t, key);
 | 
			
		||||
	struct hash_node **c = _find(t, key, len);
 | 
			
		||||
 | 
			
		||||
	if (*c) {
 | 
			
		||||
		struct hash_node *old = *c;
 | 
			
		||||
@@ -176,6 +192,21 @@ void hash_remove(struct hash_table *t, const char *key)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *hash_lookup(struct hash_table *t, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	return hash_lookup_binary(t, key, strlen(key) + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int hash_insert(struct hash_table *t, const char *key, void *data)
 | 
			
		||||
{
 | 
			
		||||
	return hash_insert_binary(t, key, strlen(key) + 1, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hash_remove(struct hash_table *t, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	hash_remove_binary(t, key, strlen(key) + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned hash_get_num_entries(struct hash_table *t)
 | 
			
		||||
{
 | 
			
		||||
	return t->num_nodes;
 | 
			
		||||
@@ -226,6 +257,6 @@ struct hash_node *hash_get_first(struct hash_table *t)
 | 
			
		||||
 | 
			
		||||
struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n)
 | 
			
		||||
{
 | 
			
		||||
	unsigned h = _hash(n->key) & (t->num_slots - 1);
 | 
			
		||||
	unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
 | 
			
		||||
	return n->next ? n->next : _next_slot(t, h + 1);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_HASH_H
 | 
			
		||||
@@ -17,10 +26,14 @@ void hash_destroy(struct hash_table *t);
 | 
			
		||||
void hash_wipe(struct hash_table *t);
 | 
			
		||||
 | 
			
		||||
void *hash_lookup(struct hash_table *t, const char *key);
 | 
			
		||||
void *hash_lookup_fixed(struct hash_table *t, const char *key, uint32_t len);
 | 
			
		||||
int hash_insert(struct hash_table *t, const char *key, void *data);
 | 
			
		||||
void hash_remove(struct hash_table *t, const char *key);
 | 
			
		||||
 | 
			
		||||
void *hash_lookup_binary(struct hash_table *t, const char *key, uint32_t len);
 | 
			
		||||
int hash_insert_binary(struct hash_table *t, const char *key, uint32_t len,
 | 
			
		||||
		       void *data);
 | 
			
		||||
void hash_remove_binary(struct hash_table *t, const char *key, uint32_t len);
 | 
			
		||||
 | 
			
		||||
unsigned hash_get_num_entries(struct hash_table *t);
 | 
			
		||||
void hash_iter(struct hash_table *t, iterate_fn f);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_LIST_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_TYPES_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003 Sistina Software
 | 
			
		||||
 * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -57,6 +66,25 @@ int str_list_del(struct list *sll, const char *str)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
	list_init(sllnew);
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(sl, sllold) {
 | 
			
		||||
		if (!str_list_add(mem, sllnew, strdup(sl->str))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is item on list?
 | 
			
		||||
 */
 | 
			
		||||
int str_list_match_item(struct list *sll, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
@@ -68,6 +96,9 @@ int str_list_match_item(struct list *sll, const char *str)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is at least one item on both lists?
 | 
			
		||||
 */
 | 
			
		||||
int str_list_match_list(struct list *sll, struct list *sll2)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
@@ -78,3 +109,20 @@ int str_list_match_list(struct list *sll, struct list *sll2)
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Do both lists contain the same set of items?
 | 
			
		||||
 */
 | 
			
		||||
int str_list_lists_equal(struct list *sll, struct list *sll2)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
	if (list_size(sll) != list_size(sll2))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(sl, sll)
 | 
			
		||||
	    if (!str_list_match_item(sll2, sl->str))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_STR_LIST_H
 | 
			
		||||
@@ -14,5 +23,7 @@ int str_list_add(struct pool *mem, struct list *sll, const char *str);
 | 
			
		||||
int str_list_del(struct list *sll, const char *str);
 | 
			
		||||
int str_list_match_item(struct list *sll, const char *str);
 | 
			
		||||
int str_list_match_list(struct list *sll, struct list *sll2);
 | 
			
		||||
int str_list_lists_equal(struct list *sll, struct list *sll2);
 | 
			
		||||
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -73,6 +82,7 @@ struct device *dev_create_file(const char *filename, struct device *dev,
 | 
			
		||||
	dev->dev = 0;
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	dev->open_count = 0;
 | 
			
		||||
	dev->block_size = -1;
 | 
			
		||||
	memset(dev->pvid, 0, sizeof(dev->pvid));
 | 
			
		||||
	list_init(&dev->open_list);
 | 
			
		||||
 | 
			
		||||
@@ -92,6 +102,7 @@ static struct device *_dev_create(dev_t d)
 | 
			
		||||
	dev->dev = d;
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	dev->open_count = 0;
 | 
			
		||||
	dev->block_size = -1;
 | 
			
		||||
	dev->end = UINT64_C(0);
 | 
			
		||||
	memset(dev->pvid, 0, sizeof(dev->pvid));
 | 
			
		||||
	list_init(&dev->open_list);
 | 
			
		||||
@@ -378,7 +389,7 @@ int dev_cache_init(void)
 | 
			
		||||
{
 | 
			
		||||
	_cache.names = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(_cache.mem = pool_create(10 * 1024))) {
 | 
			
		||||
	if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_DEV_CACHE_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -42,12 +51,6 @@
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* FIXME Use _llseek for 64-bit
 | 
			
		||||
_syscall5(int,  _llseek,  uint,  fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
 | 
			
		||||
 if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) { 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
static LIST_INIT(_open_devices);
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------
 | 
			
		||||
@@ -78,7 +81,9 @@ static int _io(struct device_area *where, void *buffer, int should_write)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
 | 
			
		||||
		log_sys_error("lseek", dev_name(where->dev));
 | 
			
		||||
		log_error("%s: lseek %" PRIu64 " failed: %s",
 | 
			
		||||
			  dev_name(where->dev), (uint64_t) where->start,
 | 
			
		||||
			  strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -89,6 +94,14 @@ static int _io(struct device_area *where, void *buffer, int should_write)
 | 
			
		||||
			    read(fd, buffer, (size_t) where->size - total);
 | 
			
		||||
		while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 | 
			
		||||
 | 
			
		||||
		if (n < 0)
 | 
			
		||||
			log_error("%s: %s failed after %" PRIu64 " of %" PRIu64
 | 
			
		||||
				  " at %" PRIu64 ": %s", dev_name(where->dev),
 | 
			
		||||
				  should_write ? "write" : "read",
 | 
			
		||||
				  (uint64_t) total,
 | 
			
		||||
				  (uint64_t) where->size,
 | 
			
		||||
				  (uint64_t) where->start, strerror(errno));
 | 
			
		||||
 | 
			
		||||
		if (n <= 0)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
@@ -111,14 +124,18 @@ static int _io(struct device_area *where, void *buffer, int should_write)
 | 
			
		||||
 */
 | 
			
		||||
static int _get_block_size(struct device *dev, unsigned int *size)
 | 
			
		||||
{
 | 
			
		||||
	int s;
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
 | 
			
		||||
	if (ioctl(dev_fd(dev), BLKBSZGET, &s) < 0) {
 | 
			
		||||
		log_sys_error("ioctl BLKBSZGET", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	if ((dev->block_size == -1)) {
 | 
			
		||||
		if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) {
 | 
			
		||||
			log_sys_error("ioctl BLKBSZGET", name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		log_debug("%s: block size is %u bytes", name, dev->block_size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*size = (unsigned int) s;
 | 
			
		||||
	*size = (unsigned int) dev->block_size;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -209,12 +226,11 @@ static int _aligned_io(struct device_area *where, void *buffer,
 | 
			
		||||
 * Public functions
 | 
			
		||||
 *---------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
int dev_get_size(struct device *dev, uint64_t *size)
 | 
			
		||||
int dev_get_size(const struct device *dev, uint64_t *size)
 | 
			
		||||
{
 | 
			
		||||
	int fd;
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Getting size of %s", name);
 | 
			
		||||
	if ((fd = open(name, O_RDONLY)) < 0) {
 | 
			
		||||
		log_sys_error("open", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -222,22 +238,27 @@ int dev_get_size(struct device *dev, uint64_t *size)
 | 
			
		||||
 | 
			
		||||
	if (ioctl(fd, BLKGETSIZE64, size) < 0) {
 | 
			
		||||
		log_sys_error("ioctl BLKGETSIZE64", name);
 | 
			
		||||
		close(fd);
 | 
			
		||||
		if (close(fd))
 | 
			
		||||
			log_sys_error("close", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*size >>= BLKSIZE_SHIFT;	/* Convert to sectors */
 | 
			
		||||
	close(fd);
 | 
			
		||||
	if (close(fd))
 | 
			
		||||
		log_sys_error("close", name);
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Unused
 | 
			
		||||
int dev_get_sectsize(struct device *dev, uint32_t *size)
 | 
			
		||||
{
 | 
			
		||||
	int fd;
 | 
			
		||||
	int s;
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Getting size of %s", name);
 | 
			
		||||
	if ((fd = open(name, O_RDONLY)) < 0) {
 | 
			
		||||
		log_sys_error("open", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -251,8 +272,12 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
 | 
			
		||||
 | 
			
		||||
	close(fd);
 | 
			
		||||
	*size = (uint32_t) s;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
void dev_flush(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
@@ -271,8 +296,20 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
 | 
			
		||||
	const char *name;
 | 
			
		||||
 | 
			
		||||
	if (dev->fd >= 0) {
 | 
			
		||||
		dev->open_count++;
 | 
			
		||||
		return 1;
 | 
			
		||||
		if ((dev->flags & DEV_OPENED_RW) ||
 | 
			
		||||
		    ((flags & O_ACCMODE) != O_RDWR)) {
 | 
			
		||||
			dev->open_count++;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (dev->open_count) {
 | 
			
		||||
			/* FIXME Ensure we never get here */
 | 
			
		||||
			log_debug("WARNING: %s already opened read-only", 
 | 
			
		||||
				  dev_name(dev));
 | 
			
		||||
			dev->open_count++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dev_close_immediate(dev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (memlock())
 | 
			
		||||
@@ -297,19 +334,29 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
 | 
			
		||||
		flags |= O_DIRECT;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef O_NOATIME
 | 
			
		||||
	/* Don't update atime on device inodes */
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR))
 | 
			
		||||
		flags |= O_NOATIME;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if ((dev->fd = open(name, flags, 0777)) < 0) {
 | 
			
		||||
		log_sys_error("open", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev->open_count = 1;
 | 
			
		||||
	dev->open_count++;
 | 
			
		||||
	dev->flags &= ~DEV_ACCESSED_W;
 | 
			
		||||
	if ((flags & O_ACCMODE) == O_RDWR)
 | 
			
		||||
		dev->flags |= DEV_OPENED_RW;
 | 
			
		||||
	else
 | 
			
		||||
		dev->flags &= ~DEV_OPENED_RW;
 | 
			
		||||
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR) &&
 | 
			
		||||
	    ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
 | 
			
		||||
		log_error("%s: fstat failed: Has device name changed?", name);
 | 
			
		||||
		dev_close(dev);
 | 
			
		||||
		dev->fd = -1;
 | 
			
		||||
		dev_close_immediate(dev);
 | 
			
		||||
		dev->open_count = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -318,12 +365,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
 | 
			
		||||
		dev_flush(dev);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if ((flags & O_CREAT) && !(flags & O_TRUNC)) {
 | 
			
		||||
	if ((flags & O_CREAT) && !(flags & O_TRUNC))
 | 
			
		||||
		dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_add(&_open_devices, &dev->open_list);
 | 
			
		||||
	log_debug("Opened %s", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	log_debug("Opened %s %s", dev_name(dev),
 | 
			
		||||
		  dev->flags & DEV_OPENED_RW ? "RW" : "RO");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -351,6 +399,7 @@ static void _close(struct device *dev)
 | 
			
		||||
	if (close(dev->fd))
 | 
			
		||||
		log_sys_error("close", dev_name(dev));
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	dev->block_size = -1;
 | 
			
		||||
	list_del(&dev->open_list);
 | 
			
		||||
 | 
			
		||||
	log_debug("Closed %s", dev_name(dev));
 | 
			
		||||
@@ -376,8 +425,11 @@ static int _dev_close(struct device *dev, int immediate)
 | 
			
		||||
		dev_flush(dev);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (dev->open_count > 0)
 | 
			
		||||
		dev->open_count--;
 | 
			
		||||
 | 
			
		||||
	/* FIXME lookup device in cache to get vgname and see if it's locked? */
 | 
			
		||||
	if (--dev->open_count < 1 && (immediate || !vgs_locked()))
 | 
			
		||||
	if (immediate || (dev->open_count < 1 && !vgs_locked()))
 | 
			
		||||
		_close(dev);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -409,8 +461,10 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	struct device_area where;
 | 
			
		||||
 | 
			
		||||
	if (!dev->open_count)
 | 
			
		||||
	if (!dev->open_count) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	where.dev = dev;
 | 
			
		||||
	where.start = offset;
 | 
			
		||||
@@ -428,8 +482,10 @@ int dev_append(struct device *dev, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!dev->open_count)
 | 
			
		||||
	if (!dev->open_count) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = dev_write(dev, dev->end, len, buffer);
 | 
			
		||||
	dev->end += (uint64_t) len;
 | 
			
		||||
@@ -444,8 +500,10 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	struct device_area where;
 | 
			
		||||
 | 
			
		||||
	if (!dev->open_count)
 | 
			
		||||
	if (!dev->open_count) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	where.dev = dev;
 | 
			
		||||
	where.start = offset;
 | 
			
		||||
@@ -492,6 +550,5 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: Always display error */
 | 
			
		||||
	return (len == 0);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										69
									
								
								lib/device/dev-md.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								lib/device/dev-md.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Luca Berra
 | 
			
		||||
 * 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 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 "metadata.h"
 | 
			
		||||
#include "xlate.h"
 | 
			
		||||
 | 
			
		||||
/* 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)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns -1 on error
 | 
			
		||||
 */
 | 
			
		||||
int dev_is_md(struct device *dev, uint64_t *sb)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
 | 
			
		||||
	uint64_t size, sb_offset;
 | 
			
		||||
	uint32_t md_magic;
 | 
			
		||||
 | 
			
		||||
	if (!dev_get_size(dev, &size)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (size < MD_RESERVED_SECTORS * 2)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
 | 
			
		||||
 | 
			
		||||
	/* Check if it is an md component device. */
 | 
			
		||||
	if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
 | 
			
		||||
	    (md_magic == xlate32(MD_SB_MAGIC))) {
 | 
			
		||||
		if (sb)
 | 
			
		||||
			*sb = sb_offset;
 | 
			
		||||
		ret = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,22 +1,105 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This LVM library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Library General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This LVM library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Library General Public License for more details.
 | 
			
		||||
 * 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 Library General Public
 | 
			
		||||
 * License along with this LVM library; if not, write to the Free
 | 
			
		||||
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 | 
			
		||||
 * MA 02111-1307, USA
 | 
			
		||||
 * 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"
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "xlate.h"
 | 
			
		||||
 | 
			
		||||
/* See linux/genhd.h and fs/partitions/msdos */
 | 
			
		||||
 | 
			
		||||
#define PART_MAGIC 0xAA55
 | 
			
		||||
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
 | 
			
		||||
#define PART_OFFSET UINT64_C(0x1BE)
 | 
			
		||||
 | 
			
		||||
struct partition {
 | 
			
		||||
        uint8_t boot_ind;
 | 
			
		||||
        uint8_t head;
 | 
			
		||||
        uint8_t sector;
 | 
			
		||||
        uint8_t cyl;
 | 
			
		||||
        uint8_t sys_ind;	/* partition type */
 | 
			
		||||
        uint8_t end_head;
 | 
			
		||||
        uint8_t end_sector;
 | 
			
		||||
        uint8_t end_cyl;
 | 
			
		||||
        uint32_t start_sect;
 | 
			
		||||
        uint32_t nr_sects;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
static int _is_partitionable(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int parts = max_partitions(MAJOR(dev->dev));
 | 
			
		||||
 | 
			
		||||
	if ((parts <= 1) || (MINOR(dev->dev) % parts))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _has_partition_table(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	unsigned p;
 | 
			
		||||
	uint8_t buf[SECTOR_SIZE];
 | 
			
		||||
	uint16_t *part_magic;
 | 
			
		||||
	struct partition *part;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_read(dev, 0, sizeof(buf), &buf)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Check for other types of partition table too */
 | 
			
		||||
 | 
			
		||||
	/* Check for msdos partition table */
 | 
			
		||||
	part_magic = (uint16_t *)(buf + PART_MAGIC_OFFSET);
 | 
			
		||||
	if ((*part_magic == xlate16(PART_MAGIC))) {
 | 
			
		||||
		part = (struct partition *) (buf + PART_OFFSET);
 | 
			
		||||
		for (p = 0; p < 4; p++, part++) {
 | 
			
		||||
			/* Table is invalid if boot indicator not 0 or 0x80 */
 | 
			
		||||
			if ((part->boot_ind & 0x7f)) {
 | 
			
		||||
				ret = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			/* Must have at least one non-empty partition */
 | 
			
		||||
			if (part->nr_sects)
 | 
			
		||||
				ret = 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int is_partitioned_dev(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	if (!_is_partitionable(dev))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return _has_partition_table(dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
@@ -31,24 +114,13 @@
 | 
			
		||||
#include <linux/major.h>
 | 
			
		||||
#include <linux/genhd.h>
 | 
			
		||||
 | 
			
		||||
#include "dbg_malloc.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
 | 
			
		||||
int _get_partition_type(struct dev_filter *filter, struct device *d);
 | 
			
		||||
 | 
			
		||||
#define MINOR_PART(dm, d) (MINOR((d)->dev) % dev_max_partitions(dm, (d)->dev))
 | 
			
		||||
#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
 | 
			
		||||
 | 
			
		||||
int is_whole_disk(struct dev_filter *filter, struct device *d)
 | 
			
		||||
int is_extended_partition(struct device *d)
 | 
			
		||||
{
 | 
			
		||||
	return (MINOR_PART(dm, d)) ? 0 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int is_extended_partition(struct dev_mgr *dm, struct device *d)
 | 
			
		||||
{
 | 
			
		||||
	return (MINOR_PART(dm, d) > 4) ? 1 : 0;
 | 
			
		||||
	return (MINOR_PART(d) > 4) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct device *dev_primary(struct dev_mgr *dm, struct device *d)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_DEVICE_H
 | 
			
		||||
@@ -13,6 +22,7 @@
 | 
			
		||||
#define DEV_ACCESSED_W		0x00000001	/* Device written to? */
 | 
			
		||||
#define DEV_REGULAR		0x00000002	/* Regular file? */
 | 
			
		||||
#define DEV_ALLOCED		0x00000004	/* dbg_malloc used */
 | 
			
		||||
#define DEV_OPENED_RW		0x00000008	/* Opened RW */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * All devices in LVM will be represented by one of these.
 | 
			
		||||
@@ -25,6 +35,7 @@ struct device {
 | 
			
		||||
	/* private */
 | 
			
		||||
	int fd;
 | 
			
		||||
	int open_count;
 | 
			
		||||
	int block_size;
 | 
			
		||||
	uint32_t flags;
 | 
			
		||||
	uint64_t end;
 | 
			
		||||
	struct list open_list;
 | 
			
		||||
@@ -46,7 +57,7 @@ struct device_area {
 | 
			
		||||
/*
 | 
			
		||||
 * All io should use these routines.
 | 
			
		||||
 */
 | 
			
		||||
int dev_get_size(struct device *dev, uint64_t *size);
 | 
			
		||||
int dev_get_size(const struct device *dev, uint64_t *size);
 | 
			
		||||
int dev_get_sectsize(struct device *dev, uint32_t *size);
 | 
			
		||||
 | 
			
		||||
/* Use quiet version if device number could change e.g. when opening LV */
 | 
			
		||||
@@ -80,15 +91,14 @@ static inline const char *dev_name(const struct device *dev)
 | 
			
		||||
/* Return a valid device name from the alias list; NULL otherwise */
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev, int quiet);
 | 
			
		||||
 | 
			
		||||
/* Does device contain md superblock?  If so, where? */
 | 
			
		||||
int dev_is_md(struct device *dev, uint64_t *sb);
 | 
			
		||||
 | 
			
		||||
/* FIXME Check partition type if appropriate */
 | 
			
		||||
 | 
			
		||||
#define is_lvm_partition(a) 1
 | 
			
		||||
/* int is_lvm_partition(const char *name); */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
static inline int is_lvm_partition(const char *name)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
int is_partitioned_dev(struct device *dev);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001  Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This LVM library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Library General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This LVM library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Library General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Library General Public
 | 
			
		||||
 * License along with this LVM library; if not, write to the Free
 | 
			
		||||
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 | 
			
		||||
 * MA 02111-1307, USA
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -23,6 +18,7 @@
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
#define SIZE_BUF 128
 | 
			
		||||
 | 
			
		||||
@@ -31,23 +27,13 @@ static struct {
 | 
			
		||||
	const char *str;
 | 
			
		||||
} _policies[] = {
 | 
			
		||||
	{
 | 
			
		||||
	ALLOC_NEXT_FREE, "next free"}, {
 | 
			
		||||
	ALLOC_CONTIGUOUS, "contiguous"}, {
 | 
			
		||||
	ALLOC_DEFAULT, "next free (default)"}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
	segment_type_t segtype;
 | 
			
		||||
	const char *str;
 | 
			
		||||
} _segtypes[] = {
 | 
			
		||||
	{
 | 
			
		||||
	SEG_STRIPED, "striped"}, {
 | 
			
		||||
	SEG_MIRRORED, "mirror"}, {
 | 
			
		||||
	SEG_SNAPSHOT, "snapshot"}
 | 
			
		||||
	ALLOC_NORMAL, "normal"}, {
 | 
			
		||||
	ALLOC_ANYWHERE, "anywhere"}, {
 | 
			
		||||
	ALLOC_INHERIT, "inherit"}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _num_policies = sizeof(_policies) / sizeof(*_policies);
 | 
			
		||||
static int _num_segtypes = sizeof(_segtypes) / sizeof(*_segtypes);
 | 
			
		||||
 | 
			
		||||
uint64_t units_to_bytes(const char *units, char *unit_type)
 | 
			
		||||
{
 | 
			
		||||
@@ -129,17 +115,6 @@ const char *get_alloc_string(alloc_policy_t alloc)
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *get_segtype_string(segment_type_t segtype)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < _num_segtypes; i++)
 | 
			
		||||
		if (_segtypes[i].segtype == segtype)
 | 
			
		||||
			return _segtypes[i].str;
 | 
			
		||||
 | 
			
		||||
	return "unknown";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
alloc_policy_t get_alloc_from_string(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
@@ -148,26 +123,19 @@ alloc_policy_t get_alloc_from_string(const char *str)
 | 
			
		||||
		if (!strcmp(_policies[i].str, str))
 | 
			
		||||
			return _policies[i].alloc;
 | 
			
		||||
 | 
			
		||||
	log_error("Unrecognised allocation policy - using default");
 | 
			
		||||
	return ALLOC_DEFAULT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
segment_type_t get_segtype_from_string(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < _num_segtypes; i++)
 | 
			
		||||
		if (!strcmp(_segtypes[i].str, str))
 | 
			
		||||
			return _segtypes[i].segtype;
 | 
			
		||||
 | 
			
		||||
	log_error("Unrecognised segment type - using default (striped)");
 | 
			
		||||
	return SEG_STRIPED;
 | 
			
		||||
	/* Special case for old metadata */
 | 
			
		||||
	if(!strcmp("next free", str))
 | 
			
		||||
		return ALLOC_NORMAL;
 | 
			
		||||
 | 
			
		||||
	log_error("Unrecognised allocation policy %s", str);
 | 
			
		||||
	return ALLOC_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Size supplied in sectors */
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
{
 | 
			
		||||
	int s;
 | 
			
		||||
	int suffix = 1;
 | 
			
		||||
	int suffix = 1, precision;
 | 
			
		||||
	uint64_t byte = UINT64_C(0);
 | 
			
		||||
	uint64_t units = UINT64_C(1024);
 | 
			
		||||
	char *size_buf = NULL;
 | 
			
		||||
@@ -202,8 +170,9 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
 | 
			
		||||
	if (s < 8) {
 | 
			
		||||
		byte = cmd->current_settings.unit_factor;
 | 
			
		||||
		size *= UINT64_C(1024);
 | 
			
		||||
		size *= UINT64_C(512);
 | 
			
		||||
	} else {
 | 
			
		||||
		size /= 2;
 | 
			
		||||
		suffix = 1;
 | 
			
		||||
		if (cmd->current_settings.unit_type == 'H')
 | 
			
		||||
			units = UINT64_C(1000);
 | 
			
		||||
@@ -215,8 +184,18 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
			s++, byte /= units;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	snprintf(size_buf, SIZE_BUF - 1, "%.2f%s", (float) size / byte,
 | 
			
		||||
		 suffix ? size_str[s][sl] : "");
 | 
			
		||||
	/* FIXME Make precision configurable */
 | 
			
		||||
	switch(toupper((int) cmd->current_settings.unit_type)) {
 | 
			
		||||
	case 'B':
 | 
			
		||||
	case 'S':
 | 
			
		||||
		precision = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		precision = 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
 | 
			
		||||
		 (double) size / byte, suffix ? size_str[s][sl] : "");
 | 
			
		||||
 | 
			
		||||
	return size_buf;
 | 
			
		||||
}
 | 
			
		||||
@@ -269,18 +248,18 @@ 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 / 2, SIZE_SHORT);
 | 
			
		||||
	size = display_size(cmd, (uint64_t) pv->size, SIZE_SHORT);
 | 
			
		||||
	if (pv->pe_size && pv->pe_count) {
 | 
			
		||||
 | 
			
		||||
/******** FIXME display LVM on-disk data size
 | 
			
		||||
		size2 = display_size(pv->size / 2, SIZE_SHORT);
 | 
			
		||||
		size2 = display_size(pv->size, SIZE_SHORT);
 | 
			
		||||
********/
 | 
			
		||||
 | 
			
		||||
		log_print("PV Size               %s" " / not usable %s",	/*  [LVM: %s]", */
 | 
			
		||||
			  size, display_size(cmd,
 | 
			
		||||
					     (pv->size -
 | 
			
		||||
					      pv->pe_count * pv->pe_size) / 2,
 | 
			
		||||
					     SIZE_SHORT));
 | 
			
		||||
			  size,
 | 
			
		||||
			  display_size(cmd, (pv->size -
 | 
			
		||||
					     pv->pe_count * pv->pe_size),
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
	} else
 | 
			
		||||
		log_print("PV Size               %s", size);
 | 
			
		||||
@@ -391,8 +370,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
			snap_active = lv_snapshot_percent(snap->cow,
 | 
			
		||||
							  &snap_percent);
 | 
			
		||||
			if (!snap_active || snap_percent < 0 ||
 | 
			
		||||
			    snap_percent >= 100)
 | 
			
		||||
				snap_active = 0;
 | 
			
		||||
			    snap_percent >= 100) snap_active = 0;
 | 
			
		||||
			log_print("                       %s%s/%s [%s]",
 | 
			
		||||
				  lv->vg->cmd->dev_dir, lv->vg->name,
 | 
			
		||||
				  snap->cow->name,
 | 
			
		||||
@@ -424,7 +402,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
 | 
			
		||||
	log_print("LV Size                %s",
 | 
			
		||||
		  display_size(cmd,
 | 
			
		||||
			       snap ? snap->origin->size / 2 : lv->size / 2,
 | 
			
		||||
			       snap ? snap->origin->size : lv->size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
	log_print("Current LE             %u",
 | 
			
		||||
@@ -445,11 +423,11 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
			snap_percent = 100;
 | 
			
		||||
 | 
			
		||||
		log_print("Snapshot chunk size    %s",
 | 
			
		||||
			  display_size(cmd, (uint64_t) snap->chunk_size / 2,
 | 
			
		||||
			  display_size(cmd, (uint64_t) snap->chunk_size,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	size = display_size(lv->size / 2, SIZE_SHORT);
 | 
			
		||||
	size = display_size(lv->size, SIZE_SHORT);
 | 
			
		||||
	sscanf(size, "%f", &fsize);
 | 
			
		||||
	fused = fsize * snap_percent / 100;
 | 
			
		||||
*/
 | 
			
		||||
@@ -483,7 +461,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
 | 
			
		||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
 | 
			
		||||
{
 | 
			
		||||
	switch (seg->area[s].type) {
 | 
			
		||||
	case AREA_PV:
 | 
			
		||||
@@ -511,52 +489,18 @@ static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
 | 
			
		||||
 | 
			
		||||
int lvdisplay_segments(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
	struct list *segh;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	log_print("--- Segments ---");
 | 
			
		||||
 | 
			
		||||
	list_iterate(segh, &lv->segments) {
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(seg, &lv->segments) {
 | 
			
		||||
		log_print("Logical extent %u to %u:",
 | 
			
		||||
			  seg->le, seg->le + seg->len - 1);
 | 
			
		||||
 | 
			
		||||
		if (seg->type == SEG_STRIPED && seg->area_count == 1)
 | 
			
		||||
			log_print("  Type\t\tlinear");
 | 
			
		||||
		else
 | 
			
		||||
			log_print("  Type\t\t%s",
 | 
			
		||||
				  get_segtype_string(seg->type));
 | 
			
		||||
		log_print("  Type\t\t%s", seg->segtype->ops->name(seg));
 | 
			
		||||
 | 
			
		||||
		switch (seg->type) {
 | 
			
		||||
		case SEG_STRIPED:
 | 
			
		||||
			if (seg->area_count == 1)
 | 
			
		||||
				_display_stripe(seg, 0, "  ");
 | 
			
		||||
			else {
 | 
			
		||||
				log_print("  Stripes\t\t%u", seg->area_count);
 | 
			
		||||
				log_print("  Stripe size\t\t%u KB",
 | 
			
		||||
					  seg->stripe_size / 2);
 | 
			
		||||
 | 
			
		||||
				for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
					log_print("  Stripe %d:", s);
 | 
			
		||||
					_display_stripe(seg, s, "    ");
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			log_print(" ");
 | 
			
		||||
			break;
 | 
			
		||||
		case SEG_SNAPSHOT:
 | 
			
		||||
			break;
 | 
			
		||||
		case SEG_MIRRORED:
 | 
			
		||||
			log_print("  Mirrors\t\t%u", seg->area_count);
 | 
			
		||||
			log_print("  Mirror size\t\t%u", seg->area_len);
 | 
			
		||||
			log_print("  Mirror original:");
 | 
			
		||||
			_display_stripe(seg, 0, "    ");
 | 
			
		||||
			log_print("  Mirror destination:");
 | 
			
		||||
			_display_stripe(seg, 1, "    ");
 | 
			
		||||
			log_print(" ");
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (seg->segtype->ops->display)
 | 
			
		||||
			seg->segtype->ops->display(seg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print(" ");
 | 
			
		||||
@@ -610,7 +554,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) / 2, SIZE_SHORT)));
 | 
			
		||||
               ( s1 = display_size ( LVM_LV_SIZE_MAX(vg), SIZE_SHORT)));
 | 
			
		||||
      free ( s1);
 | 
			
		||||
*********/
 | 
			
		||||
	log_print("Max PV                %u", vg->max_pv);
 | 
			
		||||
@@ -619,32 +563,25 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	log_print("VG Size               %s",
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->extent_count * (vg->extent_size /
 | 
			
		||||
							      2), SIZE_SHORT));
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
	log_print("PE Size               %s",
 | 
			
		||||
		  display_size(vg->cmd, (uint64_t) vg->extent_size / 2,
 | 
			
		||||
		  display_size(vg->cmd, (uint64_t) vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
	log_print("Total PE              %u", vg->extent_count);
 | 
			
		||||
 | 
			
		||||
	log_print("Alloc PE / Size       %u / %s",
 | 
			
		||||
		  vg->extent_count - vg->free_count, display_size(vg->cmd,
 | 
			
		||||
								  ((uint64_t)
 | 
			
		||||
								   vg->
 | 
			
		||||
								   extent_count
 | 
			
		||||
								   -
 | 
			
		||||
								   vg->
 | 
			
		||||
								   free_count) *
 | 
			
		||||
								  (vg->
 | 
			
		||||
								   extent_size /
 | 
			
		||||
								   2),
 | 
			
		||||
								  SIZE_SHORT));
 | 
			
		||||
		  vg->extent_count - vg->free_count,
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       ((uint64_t) vg->extent_count - vg->free_count) *
 | 
			
		||||
			       vg->extent_size, SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
	log_print("Free  PE / Size       %u / %s", vg->free_count,
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->free_count * (vg->extent_size /
 | 
			
		||||
							    2), SIZE_SHORT));
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -659,6 +596,53 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
void vgdisplay_colons(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t active_pvs;
 | 
			
		||||
	const char *access;
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
 | 
			
		||||
	if (vg->status & PARTIAL_VG)
 | 
			
		||||
		active_pvs = list_size(&vg->pvs);
 | 
			
		||||
	else
 | 
			
		||||
		active_pvs = vg->pv_count;
 | 
			
		||||
 | 
			
		||||
	switch (vg->status & (LVM_READ | LVM_WRITE)) {
 | 
			
		||||
		case LVM_READ | LVM_WRITE:
 | 
			
		||||
			access = "r/w";
 | 
			
		||||
			break;
 | 
			
		||||
		case LVM_READ:
 | 
			
		||||
			access = "r";
 | 
			
		||||
			break;
 | 
			
		||||
		case LVM_WRITE:
 | 
			
		||||
			access = "w";
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			access = "";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print("%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
 | 
			
		||||
		  ":%u:%u:%u:%s",
 | 
			
		||||
		vg->name,
 | 
			
		||||
		access,
 | 
			
		||||
		vg->status,
 | 
			
		||||
		/* internal volume group number; obsolete */
 | 
			
		||||
		vg->max_lv,
 | 
			
		||||
		vg->lv_count,
 | 
			
		||||
		lvs_in_vg_opened(vg),
 | 
			
		||||
		/* FIXME: maximum logical volume size */
 | 
			
		||||
		vg->max_pv,
 | 
			
		||||
		vg->pv_count,
 | 
			
		||||
		active_pvs,
 | 
			
		||||
		(uint64_t) vg->extent_count * (vg->extent_size / 2),
 | 
			
		||||
		vg->extent_size / 2,
 | 
			
		||||
		vg->extent_count,
 | 
			
		||||
		vg->extent_count - vg->free_count, 
 | 
			
		||||
		vg->free_count,
 | 
			
		||||
		uuid[0] ? uuid : "none");
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -666,15 +650,34 @@ 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 / 2, SIZE_SHORT),
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT),
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       ((uint64_t) vg->extent_count -
 | 
			
		||||
				vg->free_count) * vg->extent_size / 2,
 | 
			
		||||
			       SIZE_SHORT), display_size(vg->cmd,
 | 
			
		||||
							 (uint64_t) vg->
 | 
			
		||||
							 free_count *
 | 
			
		||||
							 vg->extent_size / 2,
 | 
			
		||||
							 SIZE_SHORT));
 | 
			
		||||
				vg->free_count) * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT),
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void display_formats(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct format_type *fmt;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(fmt, &cmd->formats) {
 | 
			
		||||
		log_print("%s", fmt->name);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void display_segtypes(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct segment_type *segtype;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(segtype, &cmd->segtypes) {
 | 
			
		||||
		log_print("%s", segtype->name);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This LVM library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Library General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This LVM library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Library General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Library General Public
 | 
			
		||||
 * License along with this LVM library; if not, write to the Free
 | 
			
		||||
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 | 
			
		||||
 * MA 02111-1307, USA
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_DISPLAY_H
 | 
			
		||||
@@ -32,6 +27,7 @@ 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);
 | 
			
		||||
char *display_uuid(char *uuidstr);
 | 
			
		||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
 | 
			
		||||
 | 
			
		||||
void pvdisplay_colons(struct physical_volume *pv);
 | 
			
		||||
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
@@ -49,16 +45,13 @@ void vgdisplay_full(struct volume_group *vg);
 | 
			
		||||
void vgdisplay_colons(struct volume_group *vg);
 | 
			
		||||
void vgdisplay_short(struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void display_formats(struct cmd_context *cmd);
 | 
			
		||||
void display_segtypes(struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Allocation policy display conversion routines.
 | 
			
		||||
 */
 | 
			
		||||
const char *get_alloc_string(alloc_policy_t alloc);
 | 
			
		||||
alloc_policy_t get_alloc_from_string(const char *str);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Segment type display conversion routines.
 | 
			
		||||
 */
 | 
			
		||||
segment_type_t get_segtype_from_string(const char *str);
 | 
			
		||||
const char *get_segtype_string(segment_type_t segtype);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								lib/error/errseg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								lib/error/errseg.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "text_export.h"
 | 
			
		||||
#include "text_import.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "targets.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
 | 
			
		||||
static const char *_name(const struct lv_segment *seg)
 | 
			
		||||
{
 | 
			
		||||
	return seg->segtype->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 | 
			
		||||
{
 | 
			
		||||
	seg1->len += seg2->len;
 | 
			
		||||
	seg1->area_len += seg2->area_len;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
 | 
			
		||||
				struct config_tree *cft, void **target_state,
 | 
			
		||||
				struct lv_segment *seg, char *params,
 | 
			
		||||
				size_t paramsize, const char **target, int *pos,
 | 
			
		||||
				uint32_t *pvmove_mirror_count)
 | 
			
		||||
{
 | 
			
		||||
	/*   error */
 | 
			
		||||
 | 
			
		||||
	*target = "error";
 | 
			
		||||
	*params = '\0';
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _target_present(void)
 | 
			
		||||
{
 | 
			
		||||
	static int checked = 0;
 | 
			
		||||
	static int present = 0;
 | 
			
		||||
 | 
			
		||||
	if (!checked)
 | 
			
		||||
		present = target_present("error");
 | 
			
		||||
 | 
			
		||||
	checked = 1;
 | 
			
		||||
	return present;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void _destroy(const struct segment_type *segtype)
 | 
			
		||||
{
 | 
			
		||||
	dbg_free((void *) segtype);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct segtype_handler _error_ops = {
 | 
			
		||||
	name:_name,
 | 
			
		||||
	merge_segments:_merge_segments,
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
	compose_target_line:_compose_target_line,
 | 
			
		||||
	target_present:_target_present,
 | 
			
		||||
#endif
 | 
			
		||||
	destroy:_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct segment_type *init_error_segtype(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct segment_type *segtype = dbg_malloc(sizeof(*segtype));
 | 
			
		||||
 | 
			
		||||
	if (!segtype) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	segtype->cmd = cmd;
 | 
			
		||||
	segtype->ops = &_error_ops;
 | 
			
		||||
	segtype->name = "error";
 | 
			
		||||
	segtype->private = NULL;
 | 
			
		||||
	segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Initialised segtype: %s", segtype->name);
 | 
			
		||||
 | 
			
		||||
	return segtype;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -39,7 +48,7 @@ static void _destroy(struct dev_filter *f)
 | 
			
		||||
 | 
			
		||||
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_filter **filters_copy, *cf;
 | 
			
		||||
	struct dev_filter **filters_copy, *cft;
 | 
			
		||||
 | 
			
		||||
	if (!filters) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -54,15 +63,15 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
 | 
			
		||||
	memcpy(filters_copy, filters, sizeof(*filters) * n);
 | 
			
		||||
	filters_copy[n] = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(cf = dbg_malloc(sizeof(*cf)))) {
 | 
			
		||||
	if (!(cft = dbg_malloc(sizeof(*cft)))) {
 | 
			
		||||
		log_error("compsoite filters allocation failed");
 | 
			
		||||
		dbg_free(filters_copy);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cf->passes_filter = _and_p;
 | 
			
		||||
	cf->destroy = _destroy;
 | 
			
		||||
	cf->private = filters_copy;
 | 
			
		||||
	cft->passes_filter = _and_p;
 | 
			
		||||
	cft->destroy = _destroy;
 | 
			
		||||
	cft->private = filters_copy;
 | 
			
		||||
 | 
			
		||||
	return cf;
 | 
			
		||||
	return cft;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FILTER_COMPOSITE_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										80
									
								
								lib/filters/filter-md.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								lib/filters/filter-md.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Luca Berra
 | 
			
		||||
 *
 | 
			
		||||
 * 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 "lib.h"
 | 
			
		||||
#include "filter-md.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
	
 | 
			
		||||
	if (!md_filtering())
 | 
			
		||||
		return 1;
 | 
			
		||||
	
 | 
			
		||||
	ret = dev_is_md(dev, NULL);
 | 
			
		||||
 | 
			
		||||
	if (ret == 1) {
 | 
			
		||||
		log_debug("%s: Skipping md component device", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ret < 0) {
 | 
			
		||||
		log_debug("%s: Skipping: error in md component detection",
 | 
			
		||||
			  dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	dbg_free(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dev_filter *md_filter_create(void)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_filter *f;
 | 
			
		||||
 | 
			
		||||
	if (!(f = dbg_malloc(sizeof(*f)))) {
 | 
			
		||||
		log_error("md filter allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _ignore_md;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
	f->private = NULL;
 | 
			
		||||
 | 
			
		||||
	return f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
struct dev_filter *md_filter_create(void)
 | 
			
		||||
{
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										23
									
								
								lib/filters/filter-md.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/filters/filter-md.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Luca Berra
 | 
			
		||||
 *
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FILTER_MD_H
 | 
			
		||||
#define _LVM_FILTER_MD_H
 | 
			
		||||
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
 | 
			
		||||
struct dev_filter *md_filter_create(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -51,13 +60,13 @@ int persistent_filter_wipe(struct dev_filter *f)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_array(struct pfilter *pf, struct config_tree *cf,
 | 
			
		||||
static int _read_array(struct pfilter *pf, struct config_tree *cft,
 | 
			
		||||
		       const char *path, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
	const struct config_node *cn;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cf->root, path, '/'))) {
 | 
			
		||||
	if (!(cn = find_config_node(cft->root, path))) {
 | 
			
		||||
		log_very_verbose("Couldn't find %s array in '%s'",
 | 
			
		||||
				 path, pf->file);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -88,22 +97,22 @@ int persistent_filter_load(struct dev_filter *f)
 | 
			
		||||
	struct pfilter *pf = (struct pfilter *) f->private;
 | 
			
		||||
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct config_tree *cf;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
 | 
			
		||||
	if (!(cf = create_config_tree())) {
 | 
			
		||||
	if (!(cft = create_config_tree(pf->file))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!read_config_file(cf, pf->file)) {
 | 
			
		||||
	if (!read_config_file(cft)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_read_array(pf, cf, "persistent_filter_cache/valid_devices",
 | 
			
		||||
	_read_array(pf, cft, "persistent_filter_cache/valid_devices",
 | 
			
		||||
		    PF_GOOD_DEVICE);
 | 
			
		||||
	/* We don't gain anything by holding invalid devices */
 | 
			
		||||
	/* _read_array(pf, cf, "persistent_filter_cache/invalid_devices",
 | 
			
		||||
	/* _read_array(pf, cft, "persistent_filter_cache/invalid_devices",
 | 
			
		||||
	   PF_BAD_DEVICE); */
 | 
			
		||||
 | 
			
		||||
	/* Did we find anything? */
 | 
			
		||||
@@ -116,7 +125,7 @@ int persistent_filter_load(struct dev_filter *f)
 | 
			
		||||
	log_very_verbose("Loaded persistent filter cache from %s", pf->file);
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	destroy_config_tree(cf);
 | 
			
		||||
	destroy_config_tree(cft);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -203,13 +212,10 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
			sl = list_item(ah, struct str_list);
 | 
			
		||||
			hash_insert(pf->devices, sl->str, l);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	} else if (l == PF_BAD_DEVICE)
 | 
			
		||||
			log_debug("%s: Skipping (cached)", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	if (l == PF_BAD_DEVICE) {
 | 
			
		||||
		log_debug("%s: Skipping (cached)", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	} else
 | 
			
		||||
		return 1;
 | 
			
		||||
	return (l == PF_BAD_DEVICE) ? 0 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FILTER_PERSISTENT_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -42,7 +51,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
 | 
			
		||||
	pat++;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * get the seperator
 | 
			
		||||
	 * get the separator
 | 
			
		||||
	 */
 | 
			
		||||
	switch (*pat) {
 | 
			
		||||
	case '(':
 | 
			
		||||
@@ -75,7 +84,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
 | 
			
		||||
	 */
 | 
			
		||||
	ptr = r + strlen(r) - 1;
 | 
			
		||||
	if (*ptr != sep) {
 | 
			
		||||
		log_info("invalid seperator at end of regex");
 | 
			
		||||
		log_info("invalid separator at end of regex");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	*ptr = '\0';
 | 
			
		||||
@@ -92,7 +101,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
 | 
			
		||||
	unsigned count = 0;
 | 
			
		||||
	int i, r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(scratch = pool_create(1024))) {
 | 
			
		||||
	if (!(scratch = pool_create("filter matcher", 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -177,6 +186,9 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
		first = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rejected)
 | 
			
		||||
		log_debug("%s: Skipping (regex)", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * pass everything that doesn't match
 | 
			
		||||
	 * anything.
 | 
			
		||||
@@ -192,7 +204,7 @@ static void _destroy(struct dev_filter *f)
 | 
			
		||||
 | 
			
		||||
struct dev_filter *regex_filter_create(struct config_value *patterns)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *mem = pool_create(10 * 1024);
 | 
			
		||||
	struct pool *mem = pool_create("filter regex", 10 * 1024);
 | 
			
		||||
	struct rfilter *rf;
 | 
			
		||||
	struct dev_filter *f;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FILTER_REGEX_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,15 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Red Hat Inc
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -9,9 +17,8 @@
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/sysmacros.h>
 | 
			
		||||
#include <sys/param.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#ifdef linux
 | 
			
		||||
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
 | 
			
		||||
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
 | 
			
		||||
@@ -19,7 +26,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
 | 
			
		||||
	char proc_mounts[PATH_MAX];
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *split[2], buffer[PATH_MAX + 16];
 | 
			
		||||
	char *split[4], buffer[PATH_MAX + 16];
 | 
			
		||||
 | 
			
		||||
	if (!*proc) {
 | 
			
		||||
		log_verbose("No proc filesystem found: skipping sysfs filter");
 | 
			
		||||
@@ -38,8 +45,8 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (fgets(buffer, sizeof(buffer), fp)) {
 | 
			
		||||
		if (split_words(buffer, 2, split) == 2 &&
 | 
			
		||||
		    !strcmp(split[0], "sysfs")) {
 | 
			
		||||
		if (split_words(buffer, 4, split) == 4 &&
 | 
			
		||||
		    !strcmp(split[2], "sysfs")) {
 | 
			
		||||
			if (lvm_snprintf(path, len, "%s/%s", split[1],
 | 
			
		||||
					 "block") >= 0) {
 | 
			
		||||
				r = 1;
 | 
			
		||||
@@ -162,6 +169,8 @@ static int _read_devs(struct dev_set *ds, const char *dir)
 | 
			
		||||
{
 | 
			
		||||
        struct dirent *d;
 | 
			
		||||
        DIR *dr;
 | 
			
		||||
	unsigned char dtype;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	dev_t dev;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
@@ -182,19 +191,31 @@ static int _read_devs(struct dev_set *ds, const char *dir)
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (d->d_type == DT_DIR) {
 | 
			
		||||
		dtype = d->d_type;
 | 
			
		||||
 | 
			
		||||
		if (dtype == DT_UNKNOWN) {
 | 
			
		||||
			if (lstat(path, &info) >= 0) {
 | 
			
		||||
				if (S_ISLNK(info.st_mode))
 | 
			
		||||
					dtype = DT_LNK;
 | 
			
		||||
				else if (S_ISDIR(info.st_mode))
 | 
			
		||||
					dtype = DT_DIR;
 | 
			
		||||
				else if (S_ISREG(info.st_mode))
 | 
			
		||||
					dtype = DT_REG;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (dtype == DT_DIR) {
 | 
			
		||||
			if (!_read_devs(ds, path)) {
 | 
			
		||||
				r = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((d->d_type == DT_REG && !strcmp(d->d_name, "dev")))
 | 
			
		||||
		if ((dtype == DT_REG && !strcmp(d->d_name, "dev")))
 | 
			
		||||
			if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
 | 
			
		||||
				r = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if (closedir(dr))
 | 
			
		||||
@@ -227,7 +248,11 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	if (ds->initialised != 1)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return _set_lookup(ds, dev->dev);
 | 
			
		||||
	if (!_set_lookup(ds, dev->dev)) {
 | 
			
		||||
		log_debug("%s: Skipping (sysfs)", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	} else
 | 
			
		||||
		return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
@@ -246,7 +271,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
	if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(mem = pool_create(256))) {
 | 
			
		||||
	if (!(mem = pool_create("sysfs", 256))) {
 | 
			
		||||
		log_error("sysfs pool creation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -271,3 +296,11 @@ struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
{
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,15 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Red Hat Inc
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FILTER_SYSFS_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * lvm is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2, or (at your option)
 | 
			
		||||
 * any later version.
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * lvm is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 * 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 GNU CC; see the file COPYING.  If not, write to
 | 
			
		||||
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 | 
			
		||||
 * Boston, MA 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -23,6 +18,7 @@
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
@@ -30,7 +26,11 @@
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 | 
			
		||||
#define NUMBER_OF_MAJORS 256
 | 
			
		||||
#define NUMBER_OF_MAJORS 4096
 | 
			
		||||
 | 
			
		||||
/* FIXME Make this sparse */
 | 
			
		||||
/* 0 means LVM won't use this major number. */
 | 
			
		||||
static int _max_partitions_by_major[NUMBER_OF_MAJORS];
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	const char *name;
 | 
			
		||||
@@ -44,12 +44,19 @@ int md_major(void)
 | 
			
		||||
	return _md_major;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This list can be supplemented with devices/types in the config file */
 | 
			
		||||
/*
 | 
			
		||||
 * Devices are only checked for partition tables if their minor number
 | 
			
		||||
 * is a multiple of the number corresponding to their type below
 | 
			
		||||
 * i.e. this gives the granularity of whole-device minor numbers.
 | 
			
		||||
 * Use 1 if the device is not partitionable.
 | 
			
		||||
 *
 | 
			
		||||
 * The list can be supplemented with devices/types in the config file.
 | 
			
		||||
 */
 | 
			
		||||
static const device_info_t device_info[] = {
 | 
			
		||||
	{"ide", 16},		/* IDE disk */
 | 
			
		||||
	{"ide", 64},		/* IDE disk */
 | 
			
		||||
	{"sd", 16},		/* SCSI disk */
 | 
			
		||||
	{"md", 16},		/* Multiple Disk driver (SoftRAID) */
 | 
			
		||||
	{"loop", 16},		/* Loop device */
 | 
			
		||||
	{"md", 1},		/* Multiple Disk driver (SoftRAID) */
 | 
			
		||||
	{"loop", 1},		/* Loop device */
 | 
			
		||||
	{"dasd", 4},		/* DASD disk (IBM S/390, zSeries) */
 | 
			
		||||
	{"dac960", 8},		/* DAC960 */
 | 
			
		||||
	{"nbd", 16},		/* Network Block Device */
 | 
			
		||||
@@ -58,35 +65,59 @@ static const device_info_t device_info[] = {
 | 
			
		||||
	{"ubd", 16},		/* User-mode virtual block device */
 | 
			
		||||
	{"ataraid", 16},	/* ATA Raid */
 | 
			
		||||
	{"drbd", 16},		/* Distributed Replicated Block Device */
 | 
			
		||||
	{"emcpower", 16},	/* EMC Powerpath */
 | 
			
		||||
	{"power2", 16},		/* EMC Powerpath */
 | 
			
		||||
	{"i2o_block", 16},	/* i2o Block Disk */
 | 
			
		||||
	{"iseries/vd", 8},	/* iSeries disks */
 | 
			
		||||
	{NULL, 0}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _passes_lvm_type_device_filter(struct dev_filter *f,
 | 
			
		||||
					  struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int fd;
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	uint64_t size;
 | 
			
		||||
 | 
			
		||||
	/* Is this a recognised device type? */
 | 
			
		||||
	if (!(((int *) f->private)[MAJOR(dev->dev)])) {
 | 
			
		||||
	if (!_max_partitions_by_major[MAJOR(dev->dev)]) {
 | 
			
		||||
		log_debug("%s: Skipping: Unrecognised LVM device type %"
 | 
			
		||||
			  PRIu64, name, (uint64_t) MAJOR(dev->dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check it's accessible */
 | 
			
		||||
	if ((fd = open(name, O_RDONLY)) < 0) {
 | 
			
		||||
		log_debug("%s: Skipping: open failed: %s", name,
 | 
			
		||||
			  strerror(errno));
 | 
			
		||||
	if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
 | 
			
		||||
		log_debug("%s: Skipping: open failed", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Check it's not too small */
 | 
			
		||||
	if (!dev_get_size(dev, &size)) {
 | 
			
		||||
		log_debug("%s: Skipping: dev_get_size failed", name);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(fd);
 | 
			
		||||
	if (size < PV_MIN_SIZE) {
 | 
			
		||||
		log_debug("%s: Skipping: Too small to hold a PV", name);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	if (is_partitioned_dev(dev)) {
 | 
			
		||||
		log_debug("%s: Skipping: Partition table signature found",
 | 
			
		||||
			  name);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	dev_close(dev);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int *_scan_proc_dev(const char *proc, struct config_node *cn)
 | 
			
		||||
static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
{
 | 
			
		||||
	char line[80];
 | 
			
		||||
	char proc_devices[PATH_MAX];
 | 
			
		||||
@@ -96,35 +127,31 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
 | 
			
		||||
	int blocksection = 0;
 | 
			
		||||
	size_t dev_len = 0;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
	int *max_partitions_by_major;
 | 
			
		||||
	char *name;
 | 
			
		||||
 | 
			
		||||
	if (!(max_partitions_by_major =
 | 
			
		||||
	      dbg_malloc(sizeof(int) * NUMBER_OF_MAJORS))) {
 | 
			
		||||
		log_error("Filter failed to allocate max_partitions_by_major");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!*proc) {
 | 
			
		||||
		log_verbose("No proc filesystem found: using all block device "
 | 
			
		||||
			    "types");
 | 
			
		||||
		for (i = 0; i < NUMBER_OF_MAJORS; i++)
 | 
			
		||||
			max_partitions_by_major[i] = 1;
 | 
			
		||||
		return max_partitions_by_major;
 | 
			
		||||
			_max_partitions_by_major[i] = 1;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* All types unrecognised initially */
 | 
			
		||||
	memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(proc_devices, sizeof(proc_devices),
 | 
			
		||||
			 "%s/devices", proc) < 0) {
 | 
			
		||||
		log_error("Failed to create /proc/devices string");
 | 
			
		||||
		return NULL;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(pd = fopen(proc_devices, "r"))) {
 | 
			
		||||
		log_sys_error("fopen", proc_devices);
 | 
			
		||||
		return NULL;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
 | 
			
		||||
	while (fgets(line, 80, pd) != NULL) {
 | 
			
		||||
		i = 0;
 | 
			
		||||
		while (line[i] == ' ' && line[i] != '\0')
 | 
			
		||||
@@ -159,13 +186,13 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
 | 
			
		||||
			if (dev_len <= strlen(line + i) &&
 | 
			
		||||
			    !strncmp(device_info[j].name, line + i, dev_len) &&
 | 
			
		||||
			    (line_maj < NUMBER_OF_MAJORS)) {
 | 
			
		||||
				max_partitions_by_major[line_maj] =
 | 
			
		||||
				_max_partitions_by_major[line_maj] =
 | 
			
		||||
				    device_info[j].max_partitions;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (max_partitions_by_major[line_maj] || !cn)
 | 
			
		||||
		if (!cn)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* Check devices/types for local variations */
 | 
			
		||||
@@ -173,7 +200,7 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
 | 
			
		||||
			if (cv->type != CFG_STRING) {
 | 
			
		||||
				log_error("Expecting string in devices/types "
 | 
			
		||||
					  "in config file");
 | 
			
		||||
				return NULL;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			dev_len = strlen(cv->v.str);
 | 
			
		||||
			name = cv->v.str;
 | 
			
		||||
@@ -182,28 +209,33 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
 | 
			
		||||
				log_error("Max partition count missing for %s "
 | 
			
		||||
					  "in devices/types in config file",
 | 
			
		||||
					  name);
 | 
			
		||||
				return NULL;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!cv->v.i) {
 | 
			
		||||
				log_error("Zero partition count invalid for "
 | 
			
		||||
					  "%s in devices/types in config file",
 | 
			
		||||
					  name);
 | 
			
		||||
				return NULL;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (dev_len <= strlen(line + i) &&
 | 
			
		||||
			    !strncmp(name, line + i, dev_len) &&
 | 
			
		||||
			    (line_maj < NUMBER_OF_MAJORS)) {
 | 
			
		||||
				max_partitions_by_major[line_maj] = cv->v.i;
 | 
			
		||||
				_max_partitions_by_major[line_maj] = cv->v.i;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fclose(pd);
 | 
			
		||||
	return max_partitions_by_major;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int max_partitions(int major)
 | 
			
		||||
{
 | 
			
		||||
	return _max_partitions_by_major[major];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dev_filter *lvm_type_filter_create(const char *proc,
 | 
			
		||||
					  struct config_node *cn)
 | 
			
		||||
					  const struct config_node *cn)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_filter *f;
 | 
			
		||||
 | 
			
		||||
@@ -214,8 +246,9 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _passes_lvm_type_device_filter;
 | 
			
		||||
	f->destroy = lvm_type_filter_destroy;
 | 
			
		||||
	f->private = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(f->private = _scan_proc_dev(proc, cn))) {
 | 
			
		||||
	if (!_scan_proc_dev(proc, cn)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
@@ -225,7 +258,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
 | 
			
		||||
 | 
			
		||||
void lvm_type_filter_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	dbg_free(f->private);
 | 
			
		||||
	dbg_free(f);
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * lvm is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2, or (at your option)
 | 
			
		||||
 * any later version.
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * lvm is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 * 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 GNU CC; see the file COPYING.  If not, write to
 | 
			
		||||
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 | 
			
		||||
 * Boston, MA 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FILTER_H
 | 
			
		||||
@@ -26,7 +21,9 @@
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
#  include <linux/kdev_t.h>
 | 
			
		||||
#  define MAJOR(dev)	((dev & 0xfff00) >> 8)
 | 
			
		||||
#  define MINOR(dev)	((dev & 0xff) | ((dev >> 12) & 0xfff00))
 | 
			
		||||
#  define MKDEV(ma,mi)	((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
 | 
			
		||||
#else
 | 
			
		||||
#  define MAJOR(x) major((x))
 | 
			
		||||
#  define MINOR(x) minor((x))
 | 
			
		||||
@@ -34,10 +31,12 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct dev_filter *lvm_type_filter_create(const char *proc,
 | 
			
		||||
					  struct config_node *cn);
 | 
			
		||||
					  const struct config_node *cn);
 | 
			
		||||
 | 
			
		||||
void lvm_type_filter_destroy(struct dev_filter *f);
 | 
			
		||||
 | 
			
		||||
int md_major(void);
 | 
			
		||||
 | 
			
		||||
int max_partitions(int major);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
Base { 
 | 
			
		||||
	global:
 | 
			
		||||
		init_format;
 | 
			
		||||
	local:
 | 
			
		||||
		*;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								lib/format1/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								lib/format1/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
init_format
 | 
			
		||||
@@ -1,14 +1,22 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2002 Sistina Software (UK) Limited.
 | 
			
		||||
# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is released under the LGPL.
 | 
			
		||||
# 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@
 | 
			
		||||
 | 
			
		||||
SOURCES=\
 | 
			
		||||
SOURCES =\
 | 
			
		||||
	disk-rep.c \
 | 
			
		||||
	format1.c \
 | 
			
		||||
	import-export.c \
 | 
			
		||||
@@ -17,15 +25,12 @@ SOURCES=\
 | 
			
		||||
	lvm1-label.c \
 | 
			
		||||
	vg_number.c
 | 
			
		||||
 | 
			
		||||
TARGETS=liblvm2format1.so
 | 
			
		||||
 | 
			
		||||
include ../../make.tmpl
 | 
			
		||||
LIB_SHARED = liblvm2format1.so
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
install: liblvm2format1.so
 | 
			
		||||
	$(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/liblvm2format1.so.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f liblvm2format1.so.$(LIB_VERSION) $(libdir)/liblvm2format1.so
 | 
			
		||||
 | 
			
		||||
.PHONY: install
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -108,6 +117,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;
 | 
			
		||||
 | 
			
		||||
	switch (pvd->version) {
 | 
			
		||||
	case 1:
 | 
			
		||||
@@ -125,17 +135,54 @@ static int _munge_formats(struct pv_disk *pvd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        /* UUID too long? */
 | 
			
		||||
        if (pvd->pv_uuid[ID_LEN]) {
 | 
			
		||||
		/* Retain ID_LEN chars from end */
 | 
			
		||||
                for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
 | 
			
		||||
                        if (!pvd->pv_uuid[e]) {
 | 
			
		||||
                                e--;
 | 
			
		||||
                                break;
 | 
			
		||||
                        }
 | 
			
		||||
                }
 | 
			
		||||
		for (b = 0; b < ID_LEN; b++) {
 | 
			
		||||
			pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
 | 
			
		||||
			/* FIXME Remove all invalid chars */
 | 
			
		||||
			if (pvd->pv_uuid[b] == '/')
 | 
			
		||||
				pvd->pv_uuid[b] = '#';
 | 
			
		||||
		}
 | 
			
		||||
		memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	/* If UUID is missing, create one */
 | 
			
		||||
	if (pvd->pv_uuid[0] == '\0')
 | 
			
		||||
		uuid_from_num(pvd->pv_uuid, pvd->pv_number);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_pvd(struct device *dev, struct pv_disk *pvd)
 | 
			
		||||
/* 
 | 
			
		||||
 * If exported, remove "PV_EXP" from end of VG name 
 | 
			
		||||
 */
 | 
			
		||||
static void _munge_exported_vg(struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
 | 
			
		||||
		log_very_verbose("Failed to read PV data from %s",
 | 
			
		||||
				 dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	int l;
 | 
			
		||||
	size_t s;
 | 
			
		||||
 | 
			
		||||
	/* Return if PV not in a VG */
 | 
			
		||||
	if ((!*pvd->vg_name))
 | 
			
		||||
		return;
 | 
			
		||||
	/* FIXME also check vgd->status & VG_EXPORTED? */
 | 
			
		||||
 | 
			
		||||
	l = strlen(pvd->vg_name);
 | 
			
		||||
	s = sizeof(EXPORTED_TAG);
 | 
			
		||||
	if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
 | 
			
		||||
		pvd->vg_name[l - s + 1] = '\0';
 | 
			
		||||
                pvd->pv_status |= VG_EXPORTED;
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int munge_pvd(struct device *dev, struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	_xlate_pvd(pvd);
 | 
			
		||||
 | 
			
		||||
	if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
 | 
			
		||||
@@ -150,13 +197,23 @@ static int _read_pvd(struct device *dev, struct pv_disk *pvd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If UUID is missing, create one */
 | 
			
		||||
	if (pvd->pv_uuid[0] == '\0')
 | 
			
		||||
		uuid_from_num(pvd->pv_uuid, pvd->pv_number);
 | 
			
		||||
	/* If VG is exported, set VG name back to the real name */
 | 
			
		||||
	_munge_exported_vg(pvd);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_pvd(struct device *dev, struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
 | 
			
		||||
		log_very_verbose("Failed to read PV data from %s",
 | 
			
		||||
				 dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return munge_pvd(dev, pvd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
 | 
			
		||||
{
 | 
			
		||||
	if (!dev_read(dev, pos, sizeof(*disk), disk))
 | 
			
		||||
@@ -176,6 +233,9 @@ static int _read_vgd(struct disk_list *data)
 | 
			
		||||
 | 
			
		||||
	_xlate_vgd(vgd);
 | 
			
		||||
 | 
			
		||||
	if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
 | 
			
		||||
		fail;
 | 
			
		||||
		
 | 
			
		||||
	/* If UUID is missing, create one */
 | 
			
		||||
	if (vgd->vg_uuid[0] == '\0')
 | 
			
		||||
		uuid_from_num(vgd->vg_uuid, vgd->vg_number);
 | 
			
		||||
@@ -260,26 +320,6 @@ static int _read_extents(struct disk_list *data)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * If exported, remove "PV_EXP" from end of VG name 
 | 
			
		||||
 */
 | 
			
		||||
void munge_exported_vg(struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	int l;
 | 
			
		||||
	size_t s;
 | 
			
		||||
 | 
			
		||||
	/* Return if PV not in a VG */
 | 
			
		||||
	if ((!*pvd->vg_name))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	l = strlen(pvd->vg_name);
 | 
			
		||||
	s = sizeof(EXPORTED_TAG);
 | 
			
		||||
	if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
 | 
			
		||||
		pvd->vg_name[l - s + 1] = '\0'; 
 | 
			
		||||
		pvd->pv_status |= VG_EXPORTED;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
				     struct device *dev, struct pool *mem,
 | 
			
		||||
				     const char *vg_name)
 | 
			
		||||
@@ -303,9 +343,6 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If VG is exported, set VG name back to the real name */
 | 
			
		||||
	munge_exported_vg(&dl->pvd);
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
 | 
			
		||||
				  dl->pvd.vg_name, NULL)))
 | 
			
		||||
		stack;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef DISK_REP_FORMAT1_H
 | 
			
		||||
@@ -10,6 +19,7 @@
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
 | 
			
		||||
#define MAX_PV 256
 | 
			
		||||
#define MAX_LV 256
 | 
			
		||||
@@ -196,7 +206,8 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
 | 
			
		||||
int import_pv(struct pool *mem, struct device *dev,
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
	      struct physical_volume *pv, struct pv_disk *pvd);
 | 
			
		||||
int export_pv(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
int export_pv(struct cmd_context *cmd, struct pool *mem,
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
	      struct pv_disk *pvd, struct physical_volume *pv);
 | 
			
		||||
 | 
			
		||||
int import_vg(struct pool *mem,
 | 
			
		||||
@@ -205,7 +216,7 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
 | 
			
		||||
 | 
			
		||||
int import_extents(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
		   struct list *pvds);
 | 
			
		||||
int export_extents(struct disk_list *dl, uint32_t lv_num,
 | 
			
		||||
		   struct logical_volume *lv, struct physical_volume *pv);
 | 
			
		||||
@@ -226,7 +237,7 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg);
 | 
			
		||||
void export_numbers(struct list *pvds, struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void export_pv_act(struct list *pvds);
 | 
			
		||||
void munge_exported_vg(struct pv_disk *pvd);
 | 
			
		||||
int munge_pvd(struct device *dev, struct pv_disk *pvd);
 | 
			
		||||
 | 
			
		||||
/* blech */
 | 
			
		||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -15,6 +24,7 @@
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "lvm1-label.h"
 | 
			
		||||
#include "format1.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
#define FMT_LVM1_NAME "lvm1"
 | 
			
		||||
 | 
			
		||||
@@ -139,6 +149,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
 | 
			
		||||
	list_init(&vg->pvs);
 | 
			
		||||
	list_init(&vg->lvs);
 | 
			
		||||
	list_init(&vg->snapshots);
 | 
			
		||||
	list_init(&vg->tags);
 | 
			
		||||
 | 
			
		||||
	if (!_check_vgs(pvs, &partial))
 | 
			
		||||
		goto bad;
 | 
			
		||||
@@ -154,7 +165,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
 | 
			
		||||
	if (!import_lvs(mem, vg, pvs))
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	if (!import_extents(mem, vg, pvs))
 | 
			
		||||
	if (!import_extents(fid->fmt->cmd, vg, pvs))
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	if (!import_snapshots(mem, vg, pvs))
 | 
			
		||||
@@ -172,7 +183,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
 | 
			
		||||
				     const char *vg_name,
 | 
			
		||||
				     struct metadata_area *mda)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *mem = pool_create(1024 * 10);
 | 
			
		||||
	struct pool *mem = pool_create("lvm1 vg_read", 1024 * 10);
 | 
			
		||||
	struct list pvs;
 | 
			
		||||
	struct volume_group *vg = NULL;
 | 
			
		||||
	list_init(&pvs);
 | 
			
		||||
@@ -201,7 +212,8 @@ static struct volume_group *_vg_read(struct format_instance *fid,
 | 
			
		||||
	return vg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
static struct disk_list *_flatten_pv(struct format_instance *fid,
 | 
			
		||||
				     struct pool *mem, struct volume_group *vg,
 | 
			
		||||
				     struct physical_volume *pv,
 | 
			
		||||
				     const char *dev_dir)
 | 
			
		||||
{
 | 
			
		||||
@@ -218,7 +230,7 @@ static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
	list_init(&dl->uuids);
 | 
			
		||||
	list_init(&dl->lvds);
 | 
			
		||||
 | 
			
		||||
	if (!export_pv(mem, vg, &dl->pvd, pv) ||
 | 
			
		||||
	if (!export_pv(fid->fmt->cmd, mem, vg, &dl->pvd, pv) ||
 | 
			
		||||
	    !export_vg(&dl->vgd, vg) ||
 | 
			
		||||
	    !export_uuids(dl, vg) ||
 | 
			
		||||
	    !export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
 | 
			
		||||
@@ -242,7 +254,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
	list_iterate(pvh, &vg->pvs) {
 | 
			
		||||
		pvl = list_item(pvh, struct pv_list);
 | 
			
		||||
 | 
			
		||||
		if (!(data = _flatten_pv(mem, vg, pvl->pv, dev_dir))) {
 | 
			
		||||
		if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -264,7 +276,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
 | 
			
		||||
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
		     struct metadata_area *mda)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *mem = pool_create(1024 * 10);
 | 
			
		||||
	struct pool *mem = pool_create("lvm1 vg_write", 1024 * 10);
 | 
			
		||||
	struct list pvds;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
@@ -287,7 +299,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		    struct physical_volume *pv, struct list *mdas)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *mem = pool_create(1024);
 | 
			
		||||
	struct pool *mem = pool_create("lvm1 pv_read", 1024);
 | 
			
		||||
	struct disk_list *dl;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
@@ -334,7 +346,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 / 2,
 | 
			
		||||
			  display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -375,7 +387,7 @@ 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 / 2,
 | 
			
		||||
			  display_size(fid->fmt->cmd, max_size,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -409,7 +421,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	pv->pe_size = pv->pe_count = 0;
 | 
			
		||||
	pv->pe_start = PE_ALIGN;
 | 
			
		||||
 | 
			
		||||
	if (!(mem = pool_create(1024))) {
 | 
			
		||||
	if (!(mem = pool_create("lvm1 pv_write", 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -421,7 +433,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	dl->mem = mem;
 | 
			
		||||
	dl->dev = pv->dev;
 | 
			
		||||
 | 
			
		||||
	if (!export_pv(mem, NULL, &dl->pvd, pv)) {
 | 
			
		||||
	if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
@@ -457,21 +469,18 @@ 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
 | 
			
		||||
				       / 2,
 | 
			
		||||
				       SIZE_SHORT), display_size(fid->fmt->cmd,
 | 
			
		||||
								 (uint64_t)
 | 
			
		||||
								 MAX_PE_SIZE
 | 
			
		||||
								 / 2,
 | 
			
		||||
								 SIZE_SHORT));
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT),
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
		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 / 2, SIZE_SHORT));
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -484,6 +493,17 @@ 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)
 | 
			
		||||
{
 | 
			
		||||
	if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct metadata_area_ops _metadata_format1_ops = {
 | 
			
		||||
	vg_read:_vg_read,
 | 
			
		||||
	vg_write:_vg_write,
 | 
			
		||||
@@ -534,6 +554,7 @@ static struct format_handler _format1_ops = {
 | 
			
		||||
	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,
 | 
			
		||||
@@ -570,5 +591,7 @@ struct format_type *init_format(struct cmd_context *cmd)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Initialised format: %s", fmt->name);
 | 
			
		||||
 | 
			
		||||
	return fmt;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the GPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FORMAT1_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,20 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Translates between disk and in-core formats.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
@@ -13,9 +24,10 @@
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
 | 
			
		||||
static int _check_vg_name(const char *name)
 | 
			
		||||
{
 | 
			
		||||
@@ -56,9 +68,9 @@ int import_pv(struct pool *mem, struct device *dev,
 | 
			
		||||
 | 
			
		||||
	if (vg &&
 | 
			
		||||
	    strncmp(vg->system_id, 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);
 | 
			
		||||
		    log_very_verbose("System ID %s on %s differs from %s for "
 | 
			
		||||
				     "volume group", pvd->system_id,
 | 
			
		||||
				     dev_name(pv->dev), vg->system_id);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If exported, we still need to flag in pv->status too because
 | 
			
		||||
@@ -76,20 +88,16 @@ int import_pv(struct pool *mem, struct device *dev,
 | 
			
		||||
	pv->pe_count = pvd->pe_total;
 | 
			
		||||
	pv->pe_alloc_count = pvd->pe_allocated;
 | 
			
		||||
 | 
			
		||||
	list_init(&pv->tags);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _system_id(char *s, const char *prefix)
 | 
			
		||||
static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
 | 
			
		||||
{
 | 
			
		||||
	struct utsname uts;
 | 
			
		||||
 | 
			
		||||
	if (uname(&uts) != 0) {
 | 
			
		||||
		log_sys_error("uname", "_system_id");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(s, NAME_LEN, "%s%s%lu",
 | 
			
		||||
			 prefix, uts.nodename, time(NULL)) < 0) {
 | 
			
		||||
			 prefix, cmd->hostname, time(NULL)) < 0) {
 | 
			
		||||
		log_error("Generated system_id too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -97,7 +105,8 @@ static int _system_id(char *s, const char *prefix)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int export_pv(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
int export_pv(struct cmd_context *cmd, struct pool *mem,
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
	      struct pv_disk *pvd, struct physical_volume *pv)
 | 
			
		||||
{
 | 
			
		||||
	memset(pvd, 0, sizeof(*pvd));
 | 
			
		||||
@@ -128,7 +137,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
		if (!*vg->system_id ||
 | 
			
		||||
		    strncmp(vg->system_id, EXPORTED_TAG,
 | 
			
		||||
			    sizeof(EXPORTED_TAG) - 1)) {
 | 
			
		||||
			if (!_system_id(pvd->system_id, EXPORTED_TAG)) {
 | 
			
		||||
			if (!_system_id(cmd, pvd->system_id, EXPORTED_TAG)) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -145,7 +154,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
	/* 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(pvd->system_id, IMPORTED_TAG)) {
 | 
			
		||||
		if (!_system_id(cmd, pvd->system_id, IMPORTED_TAG)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -153,7 +162,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
 | 
			
		||||
	/* Generate system_id if PV is in VG */
 | 
			
		||||
	if (!pvd->system_id || !*pvd->system_id)
 | 
			
		||||
		if (!_system_id(pvd->system_id, "")) {
 | 
			
		||||
		if (!_system_id(cmd, pvd->system_id, "")) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -162,7 +171,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
 | 
			
		||||
	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);
 | 
			
		||||
		    strncpy(vg->system_id, pvd->system_id, NAME_LEN);
 | 
			
		||||
 | 
			
		||||
	//pvd->pv_major = MAJOR(pv->dev);
 | 
			
		||||
 | 
			
		||||
@@ -228,6 +237,7 @@ int import_vg(struct pool *mem,
 | 
			
		||||
	vg->free_count = vgd->pe_total - vgd->pe_allocated;
 | 
			
		||||
	vg->max_lv = vgd->lv_max;
 | 
			
		||||
	vg->max_pv = vgd->pv_max;
 | 
			
		||||
	vg->alloc = ALLOC_NORMAL;
 | 
			
		||||
 | 
			
		||||
	if (partial)
 | 
			
		||||
		vg->status |= PARTIAL_VG;
 | 
			
		||||
@@ -307,13 +317,14 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
 | 
			
		||||
	if (lvd->lv_allocation & LV_CONTIGUOUS)
 | 
			
		||||
		lv->alloc = ALLOC_CONTIGUOUS;
 | 
			
		||||
	else
 | 
			
		||||
		lv->alloc = ALLOC_NEXT_FREE;
 | 
			
		||||
		lv->alloc = ALLOC_NORMAL;
 | 
			
		||||
 | 
			
		||||
	lv->read_ahead = lvd->lv_read_ahead;
 | 
			
		||||
	lv->size = lvd->lv_size;
 | 
			
		||||
	lv->le_count = lvd->lv_allocated_le;
 | 
			
		||||
 | 
			
		||||
	list_init(&lv->segments);
 | 
			
		||||
	list_init(&lv->tags);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -371,9 +382,10 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
 | 
			
		||||
		seg = list_item(segh, struct lv_segment);
 | 
			
		||||
 | 
			
		||||
		for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
			if (seg->type != SEG_STRIPED) {
 | 
			
		||||
				log_error("Non-striped segment type in LV %s: "
 | 
			
		||||
					  "unsupported by format1", lv->name);
 | 
			
		||||
			if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
 | 
			
		||||
				log_error("Segment type %s in LV %s: "
 | 
			
		||||
					  "unsupported by format1",
 | 
			
		||||
					  seg->segtype->name, lv->name);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (seg->area[s].type != AREA_PV) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -10,6 +19,8 @@
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "disk-rep.h"
 | 
			
		||||
#include "lv_alloc.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * After much thought I have decided it is easier,
 | 
			
		||||
@@ -192,21 +203,24 @@ static int _check_maps_are_complete(struct hash_table *maps)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_linear(struct pool *mem, struct lv_map *lvm)
 | 
			
		||||
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t le = 0;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	while (le < lvm->lv->le_count) {
 | 
			
		||||
		seg = alloc_lv_segment(mem, 1);
 | 
			
		||||
		seg = alloc_lv_segment(cmd->mem, 1);
 | 
			
		||||
 | 
			
		||||
		seg->lv = lvm->lv;
 | 
			
		||||
		seg->type = SEG_STRIPED;
 | 
			
		||||
		if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		seg->le = le;
 | 
			
		||||
		seg->len = 0;
 | 
			
		||||
		seg->area_len = 0;
 | 
			
		||||
		seg->stripe_size = 0;
 | 
			
		||||
		seg->area_count = 1;
 | 
			
		||||
 | 
			
		||||
		seg->area[0].type = AREA_PV;
 | 
			
		||||
		seg->area[0].u.pv.pv = lvm->map[le].pv;
 | 
			
		||||
@@ -242,13 +256,12 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
 | 
			
		||||
		if ((lvm->map[le + st * len].pv != seg->area[st].u.pv.pv) ||
 | 
			
		||||
		    (seg->area[st].u.pv.pv &&
 | 
			
		||||
		     lvm->map[le + st * len].pe !=
 | 
			
		||||
		     seg->area[st].u.pv.pe + seg->len))
 | 
			
		||||
			return 0;
 | 
			
		||||
		     seg->area[st].u.pv.pe + seg->len)) return 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_stripes(struct pool *mem, struct lv_map *lvm)
 | 
			
		||||
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t st, le = 0, len;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
@@ -264,15 +277,17 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
 | 
			
		||||
	len = lvm->lv->le_count / lvm->stripes;
 | 
			
		||||
 | 
			
		||||
	while (le < len) {
 | 
			
		||||
		if (!(seg = alloc_lv_segment(mem, lvm->stripes))) {
 | 
			
		||||
		if (!(seg = alloc_lv_segment(cmd->mem, lvm->stripes))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		seg->lv = lvm->lv;
 | 
			
		||||
		seg->type = SEG_STRIPED;
 | 
			
		||||
		if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		seg->stripe_size = lvm->stripe_size;
 | 
			
		||||
		seg->area_count = lvm->stripes;
 | 
			
		||||
		seg->le = seg->area_count * le;
 | 
			
		||||
		seg->len = 1;
 | 
			
		||||
		seg->area_len = 1;
 | 
			
		||||
@@ -303,20 +318,20 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _build_segments(struct pool *mem, struct lv_map *lvm)
 | 
			
		||||
static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
 | 
			
		||||
{
 | 
			
		||||
	return (lvm->stripes > 1 ? _read_stripes(mem, lvm) :
 | 
			
		||||
		_read_linear(mem, lvm));
 | 
			
		||||
	return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
 | 
			
		||||
		_read_linear(cmd, lvm));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _build_all_segments(struct pool *mem, struct hash_table *maps)
 | 
			
		||||
static int _build_all_segments(struct cmd_context *cmd, struct hash_table *maps)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node *n;
 | 
			
		||||
	struct lv_map *lvm;
 | 
			
		||||
 | 
			
		||||
	for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
 | 
			
		||||
		lvm = (struct lv_map *) hash_get_data(maps, n);
 | 
			
		||||
		if (!_build_segments(mem, lvm)) {
 | 
			
		||||
		if (!_build_segments(cmd, lvm)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -325,10 +340,11 @@ static int _build_all_segments(struct pool *mem, struct hash_table *maps)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
 | 
			
		||||
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
		   struct list *pvds)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct pool *scratch = pool_create(10 * 1024);
 | 
			
		||||
	struct pool *scratch = pool_create("lvm1 import_extents", 10 * 1024);
 | 
			
		||||
	struct hash_table *maps;
 | 
			
		||||
 | 
			
		||||
	if (!scratch) {
 | 
			
		||||
@@ -351,7 +367,7 @@ int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_build_all_segments(mem, maps)) {
 | 
			
		||||
	if (!_build_all_segments(cmd, maps)) {
 | 
			
		||||
		log_err("Couldn't build extent segments.");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -51,7 +60,8 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
 | 
			
		||||
	struct pv_disk *pvd = (struct pv_disk *) buf;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	munge_exported_vg(pvd);
 | 
			
		||||
	munge_pvd(dev, pvd);
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_LVM1_LABEL_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 * 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"
 | 
			
		||||
@@ -21,7 +30,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
 | 
			
		||||
	struct list *pvh;
 | 
			
		||||
	struct list all_pvs;
 | 
			
		||||
	struct disk_list *dl;
 | 
			
		||||
	struct pool *mem = pool_create(10 * 1024);
 | 
			
		||||
	struct pool *mem = pool_create("lvm1 vg_number", 10 * 1024);
 | 
			
		||||
	int numbers[MAX_VG], i, r = 0;
 | 
			
		||||
 | 
			
		||||
	list_init(&all_pvs);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								lib/format_pool/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								lib/format_pool/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
init_format
 | 
			
		||||
							
								
								
									
										35
									
								
								lib/format_pool/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								lib/format_pool/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 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@
 | 
			
		||||
 | 
			
		||||
SOURCES =\
 | 
			
		||||
	disk_rep.c \
 | 
			
		||||
	format_pool.c \
 | 
			
		||||
	import_export.c \
 | 
			
		||||
	pool_label.c
 | 
			
		||||
 | 
			
		||||
LIB_SHARED = liblvm2formatpool.so
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
install: liblvm2formatpool.so
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/liblvm2formatpool.so.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f liblvm2formatpool.so.$(LIB_VERSION) \
 | 
			
		||||
		$(libdir)/liblvm2formatpool.so
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										385
									
								
								lib/format_pool/disk_rep.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										385
									
								
								lib/format_pool/disk_rep.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,385 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1997-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"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "xlate.h"
 | 
			
		||||
 | 
			
		||||
#include "disk_rep.h"
 | 
			
		||||
 | 
			
		||||
/* FIXME: memcpy might not be portable */
 | 
			
		||||
#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
 | 
			
		||||
#define CPOUT_8(x, y, z) {memcpy((y), (x), (z));}
 | 
			
		||||
#define CPIN_16(x, y) {(x) = xlate16_be((y));}
 | 
			
		||||
#define CPOUT_16(x, y) {(y) = xlate16_be((x));}
 | 
			
		||||
#define CPIN_32(x, y) {(x) = xlate32_be((y));}
 | 
			
		||||
#define CPOUT_32(x, y) {(y) = xlate32_be((x));}
 | 
			
		||||
#define CPIN_64(x, y) {(x) = xlate64_be((y));}
 | 
			
		||||
#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
 | 
			
		||||
 | 
			
		||||
static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
 | 
			
		||||
			    struct pool *mem, struct pool_list *pl,
 | 
			
		||||
			    const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char buf[512];
 | 
			
		||||
 | 
			
		||||
	/* FIXME: Need to check the cache here first */
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), 512, buf)) {
 | 
			
		||||
		log_very_verbose("Failed to read PV data from %s",
 | 
			
		||||
				 dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _add_pl_to_list(struct list *head, struct pool_list *data)
 | 
			
		||||
{
 | 
			
		||||
	struct list *pvdh;
 | 
			
		||||
	struct pool_list *pl;
 | 
			
		||||
 | 
			
		||||
	list_iterate(pvdh, head) {
 | 
			
		||||
		pl = list_item(pvdh, struct pool_list);
 | 
			
		||||
 | 
			
		||||
		if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
 | 
			
		||||
			char uuid[ID_LEN + 7];
 | 
			
		||||
 | 
			
		||||
			id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
 | 
			
		||||
 | 
			
		||||
			if (MAJOR(data->dev->dev) != md_major()) {
 | 
			
		||||
				log_very_verbose("Ignoring duplicate PV %s on "
 | 
			
		||||
						 "%s", uuid,
 | 
			
		||||
						 dev_name(data->dev));
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			log_very_verbose("Duplicate PV %s - using md %s",
 | 
			
		||||
					 uuid, dev_name(data->dev));
 | 
			
		||||
			list_del(pvdh);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	list_add(head, &data->list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int read_pool_label(struct pool_list *pl, struct labeller *l,
 | 
			
		||||
		    struct device *dev, char *buf, struct label **label)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	struct id pvid;
 | 
			
		||||
	struct id vgid;
 | 
			
		||||
	char uuid[ID_LEN + 7];
 | 
			
		||||
	struct pool_disk *pd = &pl->pd;
 | 
			
		||||
 | 
			
		||||
	pool_label_in(pd, buf);
 | 
			
		||||
 | 
			
		||||
	get_pool_pv_uuid(&pvid, pd);
 | 
			
		||||
	id_write_format(&pvid, uuid, ID_LEN + 7);
 | 
			
		||||
	log_debug("Calculated uuid %s for %s", uuid, dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	get_pool_vg_uuid(&vgid, pd);
 | 
			
		||||
	id_write_format(&vgid, uuid, ID_LEN + 7);
 | 
			
		||||
	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))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (label)
 | 
			
		||||
		*label = info->label;
 | 
			
		||||
 | 
			
		||||
	info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
 | 
			
		||||
	list_init(&info->mdas);
 | 
			
		||||
 | 
			
		||||
	info->status &= ~CACHE_INVALID;
 | 
			
		||||
 | 
			
		||||
	pl->dev = dev;
 | 
			
		||||
	pl->pv = NULL;
 | 
			
		||||
	memcpy(&pl->pv_uuid, &pvid, sizeof(pvid));
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * pool_label_out - copies a pool_label_t into a char buffer
 | 
			
		||||
 * @pl: ptr to a pool_label_t struct
 | 
			
		||||
 * @buf: ptr to raw space where label info will be copied
 | 
			
		||||
 *
 | 
			
		||||
 * This function is important because it takes care of all of
 | 
			
		||||
 * the endian issues when copying to disk.  This way, when
 | 
			
		||||
 * machines of different architectures are used, they will
 | 
			
		||||
 * be able to interpret ondisk labels correctly.  Always use
 | 
			
		||||
 * this function before writing to disk.
 | 
			
		||||
 */
 | 
			
		||||
void pool_label_out(struct pool_disk *pl, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct pool_disk *bufpl = (struct pool_disk *) buf;
 | 
			
		||||
 | 
			
		||||
	CPOUT_64(pl->pl_magic, bufpl->pl_magic);
 | 
			
		||||
	CPOUT_64(pl->pl_pool_id, bufpl->pl_pool_id);
 | 
			
		||||
	CPOUT_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
 | 
			
		||||
	CPOUT_32(pl->pl_version, bufpl->pl_version);
 | 
			
		||||
	CPOUT_32(pl->pl_subpools, bufpl->pl_subpools);
 | 
			
		||||
	CPOUT_32(pl->pl_sp_id, bufpl->pl_sp_id);
 | 
			
		||||
	CPOUT_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
 | 
			
		||||
	CPOUT_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
 | 
			
		||||
	CPOUT_32(pl->pl_sp_type, bufpl->pl_sp_type);
 | 
			
		||||
	CPOUT_64(pl->pl_blocks, bufpl->pl_blocks);
 | 
			
		||||
	CPOUT_32(pl->pl_striping, bufpl->pl_striping);
 | 
			
		||||
	CPOUT_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
 | 
			
		||||
	CPOUT_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
 | 
			
		||||
	CPOUT_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
 | 
			
		||||
	CPOUT_32(pl->pl_minor, bufpl->pl_minor);
 | 
			
		||||
	CPOUT_32(pl->pl_padding, bufpl->pl_padding);
 | 
			
		||||
	CPOUT_8(pl->pl_reserve, bufpl->pl_reserve, 184);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * pool_label_in - copies a char buffer into a pool_label_t
 | 
			
		||||
 * @pl: ptr to a pool_label_t struct
 | 
			
		||||
 * @buf: ptr to raw space where label info is copied from
 | 
			
		||||
 *
 | 
			
		||||
 * This function is important because it takes care of all of
 | 
			
		||||
 * the endian issues when information from disk is about to be
 | 
			
		||||
 * used.  This way, when machines of different architectures
 | 
			
		||||
 * are used, they will be able to interpret ondisk labels
 | 
			
		||||
 * correctly.  Always use this function before using labels that
 | 
			
		||||
 * were read from disk.
 | 
			
		||||
 */
 | 
			
		||||
void pool_label_in(struct pool_disk *pl, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct pool_disk *bufpl = (struct pool_disk *) buf;
 | 
			
		||||
 | 
			
		||||
	CPIN_64(pl->pl_magic, bufpl->pl_magic);
 | 
			
		||||
	CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id);
 | 
			
		||||
	CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
 | 
			
		||||
	CPIN_32(pl->pl_version, bufpl->pl_version);
 | 
			
		||||
	CPIN_32(pl->pl_subpools, bufpl->pl_subpools);
 | 
			
		||||
	CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id);
 | 
			
		||||
	CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
 | 
			
		||||
	CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
 | 
			
		||||
	CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type);
 | 
			
		||||
	CPIN_64(pl->pl_blocks, bufpl->pl_blocks);
 | 
			
		||||
	CPIN_32(pl->pl_striping, bufpl->pl_striping);
 | 
			
		||||
	CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
 | 
			
		||||
	CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
 | 
			
		||||
	CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
 | 
			
		||||
	CPIN_32(pl->pl_minor, bufpl->pl_minor);
 | 
			
		||||
	CPIN_32(pl->pl_padding, bufpl->pl_padding);
 | 
			
		||||
	CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char _calc_char(unsigned int id)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * [0-9A-Za-z!#] - 64 printable chars (6-bits)
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (id < 10)
 | 
			
		||||
		return id + 48;
 | 
			
		||||
	if (id < 36)
 | 
			
		||||
		return (id - 10) + 65;
 | 
			
		||||
	if (id < 62)
 | 
			
		||||
		return (id - 36) + 97;
 | 
			
		||||
	if (id == 62)
 | 
			
		||||
		return '!';
 | 
			
		||||
	if (id == 63)
 | 
			
		||||
		return '#';
 | 
			
		||||
 | 
			
		||||
	return '%';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned shifter = 0x003F;
 | 
			
		||||
 | 
			
		||||
	assert(ID_LEN == 32);
 | 
			
		||||
	memset(uuid, 0, ID_LEN);
 | 
			
		||||
	strcat(uuid, "POOL0000000000");
 | 
			
		||||
 | 
			
		||||
	/* We grab the entire 64 bits (+2 that get shifted in) */
 | 
			
		||||
	for (i = 13; i < 24; i++) {
 | 
			
		||||
		uuid[i] = _calc_char(((unsigned) poolid) & shifter);
 | 
			
		||||
		poolid = poolid >> 6;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* We grab the entire 32 bits (+4 that get shifted in) */
 | 
			
		||||
	for (i = 24; i < 30; i++) {
 | 
			
		||||
		uuid[i] = _calc_char((unsigned) (spid & shifter));
 | 
			
		||||
		spid = spid >> 6;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Since we can only have 128 devices, we only worry about the
 | 
			
		||||
	 * last 12 bits
 | 
			
		||||
	 */
 | 
			
		||||
	for (i = 30; i < 32; i++) {
 | 
			
		||||
		uuid[i] = _calc_char((unsigned) (devid & shifter));
 | 
			
		||||
		devid = devid >> 6;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
 | 
			
		||||
			struct lvmcache_vginfo *vginfo, struct list *head,
 | 
			
		||||
			uint32_t *devcount)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	struct list *vgih = NULL;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	struct pool_list *pl = NULL;
 | 
			
		||||
	struct pool *tmpmem = NULL;
 | 
			
		||||
 | 
			
		||||
	uint32_t sp_count = 0;
 | 
			
		||||
	uint32_t *sp_devs = NULL;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: maybe should return a different error in memory
 | 
			
		||||
	 * allocation failure */
 | 
			
		||||
	if (!(tmpmem = pool_create("pool read_vg", 512))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate(vgih, &vginfo->infos) {
 | 
			
		||||
		dev = list_item(vgih, struct lvmcache_info)->dev;
 | 
			
		||||
		if (dev &&
 | 
			
		||||
		    !(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
 | 
			
		||||
			    break;
 | 
			
		||||
		/*
 | 
			
		||||
		 * We need to keep track of the total expected number
 | 
			
		||||
		 * of devices per subpool
 | 
			
		||||
		 */
 | 
			
		||||
		if (!sp_count) {
 | 
			
		||||
			sp_count = pl->pd.pl_subpools;
 | 
			
		||||
			if (!(sp_devs =
 | 
			
		||||
			      pool_zalloc(tmpmem,
 | 
			
		||||
					  sizeof(uint32_t) * sp_count))) {
 | 
			
		||||
				log_error("Unable to allocate %d 32-bit uints",
 | 
			
		||||
					  sp_count);
 | 
			
		||||
				pool_destroy(tmpmem);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * watch out for a pool label with a different subpool
 | 
			
		||||
		 * count than the original - give up if it does
 | 
			
		||||
		 */
 | 
			
		||||
		if (sp_count != pl->pd.pl_subpools)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		_add_pl_to_list(head, pl);
 | 
			
		||||
 | 
			
		||||
		if (sp_count > pl->pd.pl_sp_id && sp_devs[pl->pd.pl_sp_id] == 0)
 | 
			
		||||
			sp_devs[pl->pd.pl_sp_id] = pl->pd.pl_sp_devs;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*devcount = 0;
 | 
			
		||||
	for (i = 0; i < sp_count; i++) {
 | 
			
		||||
		*devcount += sp_devs[i];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pool_destroy(tmpmem);
 | 
			
		||||
 | 
			
		||||
	if (pl && *pl->pd.pl_pool_name)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int read_pool_pds(const struct format_type *fmt, const char *vg_name,
 | 
			
		||||
		  struct pool *mem, struct list *pdhead)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	uint32_t totaldevs;
 | 
			
		||||
	int full_scan = -1;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		/*
 | 
			
		||||
		 * If the cache scanning doesn't work, this will never work
 | 
			
		||||
		 */
 | 
			
		||||
		if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
 | 
			
		||||
		    vginfo->infos.n) {
 | 
			
		||||
 | 
			
		||||
			if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
 | 
			
		||||
				/*
 | 
			
		||||
				 * If we found all the devices we were
 | 
			
		||||
				 * expecting, return success
 | 
			
		||||
				 */
 | 
			
		||||
				if (list_size(pdhead) == totaldevs)
 | 
			
		||||
					return 1;
 | 
			
		||||
 | 
			
		||||
				/*
 | 
			
		||||
				 * accept partial pool if we've done a full
 | 
			
		||||
				 * rescan of the cache
 | 
			
		||||
				 */
 | 
			
		||||
				if (full_scan > 0)
 | 
			
		||||
					return 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/* Failed */
 | 
			
		||||
		list_init(pdhead);
 | 
			
		||||
 | 
			
		||||
		full_scan++;
 | 
			
		||||
		if (full_scan > 1) {
 | 
			
		||||
			log_debug("No devices for vg %s found in cache",
 | 
			
		||||
				  vg_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		lvmcache_label_scan(fmt->cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
	} while (1);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pool_list *read_pool_disk(const struct format_type *fmt,
 | 
			
		||||
				 struct device *dev, struct pool *mem,
 | 
			
		||||
				 const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	struct pool_list *pl;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(pl = pool_zalloc(mem, sizeof(*pl)))) {
 | 
			
		||||
		log_error("Unable to allocate pool list structure");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!__read_pool_disk(fmt, dev, mem, pl, vg_name)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return pl;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										178
									
								
								lib/format_pool/disk_rep.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								lib/format_pool/disk_rep.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1997-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef DISK_REP_FORMAT_POOL_H
 | 
			
		||||
#define DISK_REP_FORMAT_POOL_H
 | 
			
		||||
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
 | 
			
		||||
/* From NSP.cf */
 | 
			
		||||
#define NSPMajorVersion	4
 | 
			
		||||
#define NSPMinorVersion	1
 | 
			
		||||
#define NSPUpdateLevel	3
 | 
			
		||||
 | 
			
		||||
/* From pool_std.h */
 | 
			
		||||
#define POOL_NAME_SIZE          (256)
 | 
			
		||||
#define POOL_MAGIC 		0x011670
 | 
			
		||||
#define POOL_MAJOR              (121)
 | 
			
		||||
#define POOL_MAX_DEVICES 	128
 | 
			
		||||
 | 
			
		||||
/* When checking for version matching, the first two numbers **
 | 
			
		||||
** are important for metadata formats, a.k.a pool labels.   **
 | 
			
		||||
** All the numbers are important when checking if the user  **
 | 
			
		||||
** space tools match up with the kernel module............. */
 | 
			
		||||
#define POOL_VERSION		(NSPMajorVersion << 16 | \
 | 
			
		||||
				 NSPMinorVersion <<  8 | \
 | 
			
		||||
				 NSPUpdateLevel)
 | 
			
		||||
 | 
			
		||||
/* Pool label is at the head of every pool disk partition */
 | 
			
		||||
#define SIZEOF_POOL_LABEL       (8192)
 | 
			
		||||
 | 
			
		||||
/* in sectors */
 | 
			
		||||
#define POOL_PE_SIZE     (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
 | 
			
		||||
#define POOL_PE_START    (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
 | 
			
		||||
 | 
			
		||||
/* Helper fxns */
 | 
			
		||||
#define get_pool_vg_uuid(id, pd) do { get_pool_uuid((char *)(id), \
 | 
			
		||||
                                                    (pd)->pl_pool_id, 0, 0); \
 | 
			
		||||
                                    } while(0)
 | 
			
		||||
#define get_pool_pv_uuid(id, pd) do { get_pool_uuid((char *)(id), \
 | 
			
		||||
                                                    (pd)->pl_pool_id, \
 | 
			
		||||
                                                    (pd)->pl_sp_id, \
 | 
			
		||||
                                                    (pd)->pl_sp_devid); \
 | 
			
		||||
                                    } while(0)
 | 
			
		||||
#define get_pool_lv_uuid(id, pd) do { get_pool_uuid((char *)&(id)[0], \
 | 
			
		||||
                                                    (pd)->pl_pool_id, 0, 0); \
 | 
			
		||||
                                      get_pool_uuid((char*)&(id)[1], \
 | 
			
		||||
                                                    (pd)->pl_pool_id, 0, 0); \
 | 
			
		||||
                                    } while(0)
 | 
			
		||||
 | 
			
		||||
struct pool_disk;
 | 
			
		||||
struct pool_list;
 | 
			
		||||
struct user_subpool;
 | 
			
		||||
struct user_device;
 | 
			
		||||
 | 
			
		||||
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
 | 
			
		||||
 | 
			
		||||
/*  Generic Labels  */
 | 
			
		||||
#define SPTYPE_DATA                (0x00000000)
 | 
			
		||||
 | 
			
		||||
/*  GFS specific labels  */
 | 
			
		||||
#define SPTYPE_GFS_DATA            (0x68011670)
 | 
			
		||||
#define SPTYPE_GFS_JOURNAL         (0x69011670)
 | 
			
		||||
 | 
			
		||||
struct sptype_name {
 | 
			
		||||
	const char *name;
 | 
			
		||||
	uint32_t label;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct sptype_name sptype_names[] = {
 | 
			
		||||
	{"data",	SPTYPE_DATA},
 | 
			
		||||
 | 
			
		||||
	{"gfs_data",	SPTYPE_GFS_DATA},
 | 
			
		||||
	{"gfs_journal",	SPTYPE_GFS_JOURNAL},
 | 
			
		||||
 | 
			
		||||
	{"", 0x0}		/*  This must be the last flag.  */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pool_disk {
 | 
			
		||||
	uint64_t pl_magic;	/* Pool magic number */
 | 
			
		||||
	uint64_t pl_pool_id;	/* Unique pool identifier */
 | 
			
		||||
	char pl_pool_name[POOL_NAME_SIZE];	/* Name of pool */
 | 
			
		||||
	uint32_t pl_version;	/* Pool version */
 | 
			
		||||
	uint32_t pl_subpools;	/* Number of subpools in this pool */
 | 
			
		||||
	uint32_t pl_sp_id;	/* Subpool number within pool */
 | 
			
		||||
	uint32_t pl_sp_devs;	/* Number of data partitions in this subpool */
 | 
			
		||||
	uint32_t pl_sp_devid;	/* Partition number within subpool */
 | 
			
		||||
	uint32_t pl_sp_type;	/* Partition type */
 | 
			
		||||
	uint64_t pl_blocks;	/* Number of blocks in this partition */
 | 
			
		||||
	uint32_t pl_striping;	/* Striping size within subpool */
 | 
			
		||||
	/*
 | 
			
		||||
	 * If the number of DMEP devices is zero, then the next field **
 | 
			
		||||
	 * ** (pl_sp_dmepid) becomes the subpool ID for redirection.  In **
 | 
			
		||||
	 * ** other words, if this subpool does not have the capability  **
 | 
			
		||||
	 * ** to do DMEP, then it must specify which subpool will do it  **
 | 
			
		||||
	 * ** in it's place
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * While the next 3 field are no longer used, they must stay to keep **
 | 
			
		||||
	 * ** backward compatibility...........................................
 | 
			
		||||
	 */
 | 
			
		||||
	uint32_t pl_sp_dmepdevs;/* Number of dmep devices in this subpool */
 | 
			
		||||
	uint32_t pl_sp_dmepid;	/* Dmep device number within subpool */
 | 
			
		||||
	uint32_t pl_sp_weight;	/* if dmep dev, pref to using it */
 | 
			
		||||
 | 
			
		||||
	uint32_t pl_minor;	/* the pool minor number */
 | 
			
		||||
	uint32_t pl_padding;	/* reminder - think about alignment */
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Even though we're zeroing out 8k at the front of the disk before
 | 
			
		||||
	 * writing the label, putting this in
 | 
			
		||||
	 */
 | 
			
		||||
	char pl_reserve[184];	/* bump the structure size out to 512 bytes */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pool_list {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	struct pool_disk pd;
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
	struct id pv_uuid;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct user_subpool {
 | 
			
		||||
	uint32_t initialized;
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
	uint32_t striping;
 | 
			
		||||
	uint32_t num_devs;
 | 
			
		||||
	uint32_t type;
 | 
			
		||||
	uint32_t dummy;
 | 
			
		||||
	struct user_device *devs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct user_device {
 | 
			
		||||
	uint32_t initialized;
 | 
			
		||||
	uint32_t sp_id;
 | 
			
		||||
	uint32_t devid;
 | 
			
		||||
	uint32_t dummy;
 | 
			
		||||
	uint64_t blocks;
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int read_pool_label(struct pool_list *pl, struct labeller *l,
 | 
			
		||||
		    struct device *dev, char *buf, struct label **label);
 | 
			
		||||
void pool_label_out(struct pool_disk *pl, char *buf);
 | 
			
		||||
void pool_label_in(struct pool_disk *pl, char *buf);
 | 
			
		||||
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
 | 
			
		||||
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls);
 | 
			
		||||
int import_pool_lvs(struct volume_group *vg, struct pool *mem,
 | 
			
		||||
		    struct list *pls);
 | 
			
		||||
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
 | 
			
		||||
		    struct list *pvs, struct pool *mem, struct list *pls);
 | 
			
		||||
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
 | 
			
		||||
		   struct volume_group *vg, struct physical_volume *pv,
 | 
			
		||||
		   struct pool_list *pl);
 | 
			
		||||
int import_pool_segments(struct list *lvs, struct pool *mem,
 | 
			
		||||
			 struct user_subpool *usp, int sp_count);
 | 
			
		||||
int read_pool_pds(const struct format_type *fmt, const char *vgname,
 | 
			
		||||
		  struct pool *mem, struct list *head);
 | 
			
		||||
struct pool_list *read_pool_disk(const struct format_type *fmt,
 | 
			
		||||
				 struct device *dev, struct pool *mem,
 | 
			
		||||
				 const char *vg_name);
 | 
			
		||||
 | 
			
		||||
#endif				/* DISK_REP_POOL_FORMAT_H */
 | 
			
		||||
							
								
								
									
										363
									
								
								lib/format_pool/format_pool.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								lib/format_pool/format_pool.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,363 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1997-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"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "limits.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "disk_rep.h"
 | 
			
		||||
#include "format_pool.h"
 | 
			
		||||
#include "pool_label.h"
 | 
			
		||||
 | 
			
		||||
#define FMT_POOL_NAME "pool"
 | 
			
		||||
 | 
			
		||||
/* Must be called after pvs are imported */
 | 
			
		||||
static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
 | 
			
		||||
				       int *sps)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	struct list *plhs;
 | 
			
		||||
	struct pool_list *pl;
 | 
			
		||||
	struct user_subpool *usp = NULL, *cur_sp = NULL;
 | 
			
		||||
	struct user_device *cur_dev = NULL;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * FIXME: Need to do some checks here - I'm tempted to add a
 | 
			
		||||
	 * user_pool structure and build the entire thing to check against.
 | 
			
		||||
	 */
 | 
			
		||||
	list_iterate(plhs, pls) {
 | 
			
		||||
		pl = list_item(plhs, struct pool_list);
 | 
			
		||||
 | 
			
		||||
		*sps = pl->pd.pl_subpools;
 | 
			
		||||
		if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
 | 
			
		||||
			log_error("Unable to allocate %d subpool structures",
 | 
			
		||||
				  *sps);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cur_sp != &usp[pl->pd.pl_sp_id]) {
 | 
			
		||||
			cur_sp = &usp[pl->pd.pl_sp_id];
 | 
			
		||||
 | 
			
		||||
			cur_sp->id = pl->pd.pl_sp_id;
 | 
			
		||||
			cur_sp->striping = pl->pd.pl_striping;
 | 
			
		||||
			cur_sp->num_devs = pl->pd.pl_sp_devs;
 | 
			
		||||
			cur_sp->type = pl->pd.pl_sp_type;
 | 
			
		||||
			cur_sp->initialized = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!cur_sp->devs &&
 | 
			
		||||
		    (!(cur_sp->devs =
 | 
			
		||||
		       pool_zalloc(mem,
 | 
			
		||||
				   sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
 | 
			
		||||
 | 
			
		||||
			log_error("Unable to allocate %d pool_device "
 | 
			
		||||
				  "structures", pl->pd.pl_sp_devs);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
 | 
			
		||||
		cur_dev->sp_id = cur_sp->id;
 | 
			
		||||
		cur_dev->devid = pl->pd.pl_sp_id;
 | 
			
		||||
		cur_dev->blocks = pl->pd.pl_blocks;
 | 
			
		||||
		cur_dev->pv = pl->pv;
 | 
			
		||||
		cur_dev->initialized = 1;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return usp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
 | 
			
		||||
{
 | 
			
		||||
	int i, j;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sp_count; i++) {
 | 
			
		||||
		if (!usp[i].initialized) {
 | 
			
		||||
			log_error("Missing subpool %d in pool %s", i, vgname);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		for (j = 0; j < usp[i].num_devs; j++) {
 | 
			
		||||
			if (!usp[i].devs[j].initialized) {
 | 
			
		||||
				log_error("Missing device %d for subpool %d"
 | 
			
		||||
					  " in pool %s", j, i, vgname);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct volume_group *_build_vg_from_pds(struct format_instance
 | 
			
		||||
					       *fid, struct pool *mem,
 | 
			
		||||
					       struct list *pds)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *smem = fid->fmt->cmd->mem;
 | 
			
		||||
	struct volume_group *vg = NULL;
 | 
			
		||||
	struct user_subpool *usp = NULL;
 | 
			
		||||
	int sp_count;
 | 
			
		||||
 | 
			
		||||
	if (!(vg = pool_zalloc(smem, sizeof(*vg)))) {
 | 
			
		||||
		log_error("Unable to allocate volume group structure");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vg->cmd = fid->fmt->cmd;
 | 
			
		||||
	vg->fid = fid;
 | 
			
		||||
	vg->name = NULL;
 | 
			
		||||
	vg->status = 0;
 | 
			
		||||
	vg->extent_count = 0;
 | 
			
		||||
	vg->pv_count = 0;
 | 
			
		||||
	vg->lv_count = 0;
 | 
			
		||||
	vg->snapshot_count = 0;
 | 
			
		||||
	vg->seqno = 1;
 | 
			
		||||
	vg->system_id = NULL;
 | 
			
		||||
	list_init(&vg->pvs);
 | 
			
		||||
	list_init(&vg->lvs);
 | 
			
		||||
	list_init(&vg->snapshots);
 | 
			
		||||
	list_init(&vg->tags);
 | 
			
		||||
 | 
			
		||||
	if (!import_pool_vg(vg, smem, pds)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!import_pool_pvs(fid->fmt, vg, &vg->pvs, smem, pds)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!import_pool_lvs(vg, smem, pds)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * I need an intermediate subpool structure that contains all the
 | 
			
		||||
	 * relevant info for this.  Then i can iterate through the subpool
 | 
			
		||||
	 * structures for checking, and create the segments
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(usp = _build_usp(pds, mem, &sp_count))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * check the subpool structures - we can't handle partial VGs in
 | 
			
		||||
	 * the pool format, so this will error out if we're missing PVs
 | 
			
		||||
	 */
 | 
			
		||||
	if (!_check_usp(vg->name, usp, sp_count)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!import_pool_segments(&vg->lvs, smem, usp, sp_count)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct volume_group *_vg_read(struct format_instance *fid,
 | 
			
		||||
				     const char *vg_name,
 | 
			
		||||
				     struct metadata_area *mda)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *mem = pool_create("pool vg_read", 1024);
 | 
			
		||||
	struct list pds;
 | 
			
		||||
	struct volume_group *vg = NULL;
 | 
			
		||||
 | 
			
		||||
	list_init(&pds);
 | 
			
		||||
 | 
			
		||||
	/* We can safely ignore the mda passed in */
 | 
			
		||||
 | 
			
		||||
	if (!mem) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Strip dev_dir if present */
 | 
			
		||||
	vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
 | 
			
		||||
 | 
			
		||||
	/* Read all the pvs in the vg */
 | 
			
		||||
	if (!read_pool_pds(fid->fmt, vg_name, mem, &pds)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Do the rest of the vg stuff */
 | 
			
		||||
	if (!(vg = _build_vg_from_pds(fid, mem, &pds))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	pool_destroy(mem);
 | 
			
		||||
	return vg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
		     uint64_t pe_start, uint32_t extent_count,
 | 
			
		||||
		     uint32_t extent_size,
 | 
			
		||||
		     int pvmetadatacopies,
 | 
			
		||||
		     uint64_t pvmetadatasize, struct list *mdas,
 | 
			
		||||
		     struct physical_volume *pv, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		    struct physical_volume *pv, struct list *mdas)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *mem = pool_create("pool pv_read", 1024);
 | 
			
		||||
	struct pool_list *pl;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Reading physical volume data %s from disk", pv_name);
 | 
			
		||||
 | 
			
		||||
	if (!mem) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * I need to read the disk and populate a pv structure here
 | 
			
		||||
	 * I'll probably need to abstract some of this later for the
 | 
			
		||||
	 * vg_read code
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(pl = read_pool_disk(fmt, dev, mem, NULL))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pv->fmt = fmt;
 | 
			
		||||
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	pool_destroy(mem);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* *INDENT-OFF* */
 | 
			
		||||
static struct metadata_area_ops _metadata_format_pool_ops = {
 | 
			
		||||
	vg_read:_vg_read,
 | 
			
		||||
};
 | 
			
		||||
/* *INDENT-ON* */
 | 
			
		||||
 | 
			
		||||
static struct format_instance *_create_instance(const struct format_type *fmt,
 | 
			
		||||
						const char *vgname,
 | 
			
		||||
						void *private)
 | 
			
		||||
{
 | 
			
		||||
	struct format_instance *fid;
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
 | 
			
		||||
	if (!(fid = pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
 | 
			
		||||
		log_error("Unable to allocate format instance structure for "
 | 
			
		||||
			  "pool format");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fid->fmt = fmt;
 | 
			
		||||
	list_init(&fid->metadata_areas);
 | 
			
		||||
 | 
			
		||||
	/* Define a NULL metadata area */
 | 
			
		||||
	if (!(mda = pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
 | 
			
		||||
		log_error("Unable to allocate metadata area structure "
 | 
			
		||||
			  "for pool format");
 | 
			
		||||
		pool_free(fmt->cmd->mem, fid);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mda->ops = &_metadata_format_pool_ops;
 | 
			
		||||
	mda->metadata_locn = NULL;
 | 
			
		||||
	list_add(&fid->metadata_areas, &mda->list);
 | 
			
		||||
 | 
			
		||||
	return fid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_instance(struct format_instance *fid)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(const struct format_type *fmt)
 | 
			
		||||
{
 | 
			
		||||
	dbg_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,
 | 
			
		||||
};
 | 
			
		||||
/* *INDENT-ON */
 | 
			
		||||
 | 
			
		||||
#ifdef POOL_INTERNAL
 | 
			
		||||
struct format_type *init_pool_format(struct cmd_context *cmd)
 | 
			
		||||
#else				/* Shared */
 | 
			
		||||
struct format_type *init_format(struct cmd_context *cmd);
 | 
			
		||||
struct format_type *init_format(struct cmd_context *cmd)
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
	struct format_type *fmt = dbg_malloc(sizeof(*fmt));
 | 
			
		||||
 | 
			
		||||
	if (!fmt) {
 | 
			
		||||
		log_error("Unable to allocate format type structure for pool "
 | 
			
		||||
			  "format");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt->cmd = cmd;
 | 
			
		||||
	fmt->ops = &_format_pool_ops;
 | 
			
		||||
	fmt->name = FMT_POOL_NAME;
 | 
			
		||||
	fmt->alias = NULL;
 | 
			
		||||
	fmt->features = 0;
 | 
			
		||||
	fmt->private = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(fmt->labeller = pool_labeller_create(fmt))) {
 | 
			
		||||
		log_error("Couldn't create pool label handler.");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(label_register_handler(FMT_POOL_NAME, fmt->labeller))) {
 | 
			
		||||
		log_error("Couldn't register pool label handler.");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Initialised format: %s", fmt->name);
 | 
			
		||||
 | 
			
		||||
	return fmt;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								lib/format_pool/format_pool.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/format_pool/format_pool.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003-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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FORMAT_POOL_H
 | 
			
		||||
#define _LVM_FORMAT_POOL_H
 | 
			
		||||
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#ifdef POOL_INTERNAL
 | 
			
		||||
struct format_type *init_pool_format(struct cmd_context *cmd);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										309
									
								
								lib/format_pool/import_export.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								lib/format_pool/import_export.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,309 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1997-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"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "disk_rep.h"
 | 
			
		||||
#include "lv_alloc.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
/* This file contains only imports at the moment... */
 | 
			
		||||
 | 
			
		||||
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
 | 
			
		||||
{
 | 
			
		||||
	struct list *plhs;
 | 
			
		||||
	struct pool_list *pl;
 | 
			
		||||
 | 
			
		||||
	list_iterate(plhs, pls) {
 | 
			
		||||
		pl = list_item(plhs, struct pool_list);
 | 
			
		||||
 | 
			
		||||
		vg->extent_count +=
 | 
			
		||||
		    ((pl->pd.pl_blocks) / POOL_PE_SIZE);
 | 
			
		||||
 | 
			
		||||
		vg->pv_count++;
 | 
			
		||||
 | 
			
		||||
		if (vg->name)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		vg->name = pool_strdup(mem, pl->pd.pl_pool_name);
 | 
			
		||||
		get_pool_vg_uuid(&vg->id, &pl->pd);
 | 
			
		||||
		vg->extent_size = POOL_PE_SIZE;
 | 
			
		||||
		vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
 | 
			
		||||
		vg->free_count = 0;
 | 
			
		||||
		vg->max_lv = 1;
 | 
			
		||||
		vg->max_pv = POOL_MAX_DEVICES;
 | 
			
		||||
		vg->alloc = ALLOC_NORMAL;
 | 
			
		||||
		vg->lv_count = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
 | 
			
		||||
{
 | 
			
		||||
	struct pool_list *pl;
 | 
			
		||||
	struct list *plhs;
 | 
			
		||||
	struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
 | 
			
		||||
	if (!lvl) {
 | 
			
		||||
		log_error("Unable to allocate lv list structure");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(lvl->lv = pool_zalloc(mem, sizeof(*lvl->lv)))) {
 | 
			
		||||
		log_error("Unable to allocate logical volume structure");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lv = lvl->lv;
 | 
			
		||||
	lv->status = 0;
 | 
			
		||||
	lv->vg = vg;
 | 
			
		||||
	lv->alloc = ALLOC_NORMAL;
 | 
			
		||||
	lv->size = 0;
 | 
			
		||||
	lv->name = NULL;
 | 
			
		||||
	lv->le_count = 0;
 | 
			
		||||
	lv->read_ahead = 0;
 | 
			
		||||
	list_init(&lv->segments);
 | 
			
		||||
	list_init(&lv->tags);
 | 
			
		||||
 | 
			
		||||
	list_iterate(plhs, pls) {
 | 
			
		||||
		pl = list_item(plhs, struct pool_list);
 | 
			
		||||
 | 
			
		||||
		lv->size += pl->pd.pl_blocks;
 | 
			
		||||
 | 
			
		||||
		if (lv->name)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (!(lv->name = pool_strdup(mem, pl->pd.pl_pool_name))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		get_pool_lv_uuid(lv->lvid.id, &pl->pd);
 | 
			
		||||
		log_debug("Calculated lv uuid for lv %s: %s", lv->name,
 | 
			
		||||
			  lv->lvid.s);
 | 
			
		||||
 | 
			
		||||
		lv->status |= VISIBLE_LV | LVM_READ | LVM_WRITE;
 | 
			
		||||
		lv->major = POOL_MAJOR;
 | 
			
		||||
 | 
			
		||||
		/* for pool a minor of 0 is dynamic */
 | 
			
		||||
		if (pl->pd.pl_minor) {
 | 
			
		||||
			lv->status |= FIXED_MINOR;
 | 
			
		||||
			lv->minor = pl->pd.pl_minor;
 | 
			
		||||
		} else {
 | 
			
		||||
			lv->minor = -1;
 | 
			
		||||
		}
 | 
			
		||||
		list_init(&lv->segments);
 | 
			
		||||
		list_init(&lv->tags);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lv->le_count = lv->size / POOL_PE_SIZE;
 | 
			
		||||
	lvl->lv = lv;
 | 
			
		||||
	list_add(&vg->lvs, &lvl->list);
 | 
			
		||||
	vg->lv_count++;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
 | 
			
		||||
		    struct list *pvs, struct pool *mem, struct list *pls)
 | 
			
		||||
{
 | 
			
		||||
	struct pv_list *pvl;
 | 
			
		||||
	struct pool_list *pl;
 | 
			
		||||
	struct list *plhs;
 | 
			
		||||
 | 
			
		||||
	list_iterate(plhs, pls) {
 | 
			
		||||
		pl = list_item(plhs, struct pool_list);
 | 
			
		||||
 | 
			
		||||
		if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
 | 
			
		||||
			log_error("Unable to allocate pv list structure");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(pvl->pv = pool_zalloc(mem, sizeof(*pvl->pv)))) {
 | 
			
		||||
			log_error("Unable to allocate pv structure");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (!import_pool_pv(fmt, mem, vg, pvl->pv, pl)) {
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		pl->pv = pvl->pv;
 | 
			
		||||
		pvl->mdas = NULL;
 | 
			
		||||
		pvl->pe_ranges = NULL;
 | 
			
		||||
		list_add(pvs, &pvl->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
 | 
			
		||||
		   struct volume_group *vg, struct physical_volume *pv,
 | 
			
		||||
		   struct pool_list *pl)
 | 
			
		||||
{
 | 
			
		||||
	struct pool_disk *pd = &pl->pd;
 | 
			
		||||
 | 
			
		||||
	memset(pv, 0, sizeof(*pv));
 | 
			
		||||
 | 
			
		||||
	get_pool_pv_uuid(&pv->id, pd);
 | 
			
		||||
	pv->fmt = fmt;
 | 
			
		||||
 | 
			
		||||
	pv->dev = pl->dev;
 | 
			
		||||
	if (!(pv->vg_name = pool_strdup(mem, pd->pl_pool_name))) {
 | 
			
		||||
		log_error("Unable to duplicate vg_name string");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	pv->status = 0;
 | 
			
		||||
	pv->size = pd->pl_blocks;
 | 
			
		||||
	pv->pe_size = POOL_PE_SIZE;
 | 
			
		||||
	pv->pe_start = POOL_PE_START;
 | 
			
		||||
	pv->pe_count = pv->size / POOL_PE_SIZE;
 | 
			
		||||
	pv->pe_alloc_count = pv->pe_count;
 | 
			
		||||
 | 
			
		||||
	list_init(&pv->tags);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *_cvt_sptype(uint32_t sptype)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	for (i = 0; sptype_names[i].name[0]; i++) {
 | 
			
		||||
		if (sptype == sptype_names[i].label) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	log_debug("Found sptype %X and converted it to %s",
 | 
			
		||||
		  sptype, sptype_names[i].name);
 | 
			
		||||
	return sptype_names[i].name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_stripe_seg(struct pool *mem,
 | 
			
		||||
			   struct user_subpool *usp, struct logical_volume *lv,
 | 
			
		||||
			   uint32_t *le_cur)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	int j;
 | 
			
		||||
 | 
			
		||||
	if (!(seg = alloc_lv_segment(mem, usp->num_devs))) {
 | 
			
		||||
		log_error("Unable to allocate striped lv_segment structure");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if(usp->striping & (usp->striping - 1)) {
 | 
			
		||||
		log_error("Stripe size must be a power of 2");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	seg->stripe_size = usp->striping;
 | 
			
		||||
	seg->status |= 0;
 | 
			
		||||
	seg->le += *le_cur;
 | 
			
		||||
 | 
			
		||||
	/* add the subpool type to the segment tag list */
 | 
			
		||||
	str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
 | 
			
		||||
 | 
			
		||||
	for (j = 0; j < usp->num_devs; j++) {
 | 
			
		||||
		if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
 | 
			
		||||
							     "striped"))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
 | 
			
		||||
		seg->len += seg->area_len;
 | 
			
		||||
		*le_cur += seg->area_len;
 | 
			
		||||
		seg->lv = lv;
 | 
			
		||||
 | 
			
		||||
		seg->area[j].type = AREA_PV;
 | 
			
		||||
		seg->area[j].u.pv.pv = usp->devs[j].pv;
 | 
			
		||||
		seg->area[j].u.pv.pe = 0;
 | 
			
		||||
	}
 | 
			
		||||
	list_add(&lv->segments, &seg->list);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_linear_seg(struct pool *mem,
 | 
			
		||||
			   struct user_subpool *usp, struct logical_volume *lv,
 | 
			
		||||
			   uint32_t *le_cur)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	int j;
 | 
			
		||||
 | 
			
		||||
	for (j = 0; j < usp->num_devs; j++) {
 | 
			
		||||
		/* linear segments only have 1 data area */
 | 
			
		||||
		if (!(seg = alloc_lv_segment(mem, 1))) {
 | 
			
		||||
			log_error("Unable to allocate linear lv_segment "
 | 
			
		||||
				  "structure");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		seg->stripe_size = usp->striping;
 | 
			
		||||
		seg->le += *le_cur;
 | 
			
		||||
		seg->chunk_size = POOL_PE_SIZE;
 | 
			
		||||
		seg->status |= 0;
 | 
			
		||||
		if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
 | 
			
		||||
							     "striped"))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		/* add the subpool type to the segment tag list */
 | 
			
		||||
		str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
 | 
			
		||||
 | 
			
		||||
		seg->lv = lv;
 | 
			
		||||
 | 
			
		||||
		seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
 | 
			
		||||
		seg->len = seg->area_len;
 | 
			
		||||
		*le_cur += seg->len;
 | 
			
		||||
		seg->area[0].type = AREA_PV;
 | 
			
		||||
		seg->area[0].u.pv.pv = usp->devs[j].pv;
 | 
			
		||||
		seg->area[0].u.pv.pe = 0;
 | 
			
		||||
		list_add(&lv->segments, &seg->list);
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int import_pool_segments(struct list *lvs, struct pool *mem,
 | 
			
		||||
			 struct user_subpool *usp, int subpools)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	struct list *lvhs;
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	uint32_t le_cur = 0;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	list_iterate(lvhs, lvs) {
 | 
			
		||||
		lvl = list_item(lvhs, struct lv_list);
 | 
			
		||||
 | 
			
		||||
		lv = lvl->lv;
 | 
			
		||||
		for (i = 0; i < subpools; i++) {
 | 
			
		||||
			if (usp[i].striping) {
 | 
			
		||||
				if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur)) {
 | 
			
		||||
					stack;
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if (!_add_linear_seg(mem, &usp[i], lv, &le_cur)) {
 | 
			
		||||
					stack;
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user