mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-03 08:23:48 +03:00 
			
		
		
		
	Compare commits
	
		
			946 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					73f08b98d2 | ||
| 
						 | 
					8607a74206 | ||
| 
						 | 
					8339f3ceb3 | ||
| 
						 | 
					c0c9f3cc19 | ||
| 
						 | 
					81f4813c29 | ||
| 
						 | 
					94f57745b9 | ||
| 
						 | 
					54fb2ebbe0 | ||
| 
						 | 
					02d122b65b | ||
| 
						 | 
					df0a5561a1 | ||
| 
						 | 
					f7c55da7d0 | ||
| 
						 | 
					b385f701ce | ||
| 
						 | 
					05dd42f443 | ||
| 
						 | 
					36d816d5cb | ||
| 
						 | 
					92a6746e70 | ||
| 
						 | 
					1728848a39 | ||
| 
						 | 
					f9eb4e7487 | ||
| 
						 | 
					d0b9f33aeb | ||
| 
						 | 
					718583b241 | ||
| 
						 | 
					6737127e9a | ||
| 
						 | 
					19a7b4479b | ||
| 
						 | 
					c340647502 | ||
| 
						 | 
					0f987d2982 | ||
| 
						 | 
					52bcaed169 | ||
| 
						 | 
					177bd565ac | ||
| 
						 | 
					c801c32fc5 | ||
| 
						 | 
					d090cf3058 | ||
| 
						 | 
					1e4b82cc94 | ||
| 
						 | 
					3426f31184 | ||
| 
						 | 
					b4fb7af1df | ||
| 
						 | 
					b36647598b | ||
| 
						 | 
					fd6b94f20e | ||
| 
						 | 
					296dc0ed8a | ||
| 
						 | 
					4f869e14d6 | ||
| 
						 | 
					5704270e9d | ||
| 
						 | 
					505b381e85 | ||
| 
						 | 
					da6cb15393 | ||
| 
						 | 
					16843f6cc8 | ||
| 
						 | 
					64f3ad1fd4 | ||
| 
						 | 
					ff4c4f99b3 | ||
| 
						 | 
					f5d2e09569 | ||
| 
						 | 
					f2bdbe0d4d | ||
| 
						 | 
					c51a13caa6 | ||
| 
						 | 
					7840c78a23 | ||
| 
						 | 
					c706f3246b | ||
| 
						 | 
					608eedf88d | ||
| 
						 | 
					a564ca82be | ||
| 
						 | 
					c868b1fee2 | ||
| 
						 | 
					22374f718f | ||
| 
						 | 
					abe3cfcf41 | ||
| 
						 | 
					59db4b50cd | ||
| 
						 | 
					bdae38765d | ||
| 
						 | 
					66d3ceeb61 | ||
| 
						 | 
					445dd17db3 | ||
| 
						 | 
					cff78a2577 | ||
| 
						 | 
					6a09e64195 | ||
| 
						 | 
					22eabe5eab | ||
| 
						 | 
					b69ba36c2d | ||
| 
						 | 
					5240aad22b | ||
| 
						 | 
					2897eb3cb3 | ||
| 
						 | 
					d3f2f00c25 | ||
| 
						 | 
					bacfb913a0 | ||
| 
						 | 
					c99d0236a0 | ||
| 
						 | 
					aac2b655f7 | ||
| 
						 | 
					126c41e73a | ||
| 
						 | 
					359ee54f0d | ||
| 
						 | 
					28ab560907 | ||
| 
						 | 
					ead252fee4 | ||
| 
						 | 
					abf67914c4 | ||
| 
						 | 
					127884e9dd | ||
| 
						 | 
					654f5049eb | ||
| 
						 | 
					979ca34259 | ||
| 
						 | 
					4dd1086805 | ||
| 
						 | 
					3503d4b72c | ||
| 
						 | 
					b8d32a0d33 | ||
| 
						 | 
					45dca55fc8 | ||
| 
						 | 
					445d8ecd9f | ||
| 
						 | 
					c980add503 | ||
| 
						 | 
					133842392a | ||
| 
						 | 
					8baf2ef155 | ||
| 
						 | 
					20b71340bc | ||
| 
						 | 
					61d8baf8b1 | ||
| 
						 | 
					56a9645aa5 | ||
| 
						 | 
					85877000a6 | ||
| 
						 | 
					2f7d2477b6 | ||
| 
						 | 
					21ea3f05f4 | ||
| 
						 | 
					79d3492e90 | ||
| 
						 | 
					5972777abe | ||
| 
						 | 
					8e373ff868 | ||
| 
						 | 
					a4db92da3a | ||
| 
						 | 
					9b777eb281 | ||
| 
						 | 
					bd3c652184 | ||
| 
						 | 
					800f747570 | ||
| 
						 | 
					2b8423437e | ||
| 
						 | 
					8b4b6945f8 | ||
| 
						 | 
					e5ecfec5c4 | ||
| 
						 | 
					f95dbff71f | ||
| 
						 | 
					098f6830a6 | ||
| 
						 | 
					d1ecebdb52 | ||
| 
						 | 
					590b654251 | ||
| 
						 | 
					3bf190c8ab | ||
| 
						 | 
					dcca7638e0 | ||
| 
						 | 
					70e45ad37b | ||
| 
						 | 
					db88210289 | ||
| 
						 | 
					d2e0d96cc3 | ||
| 
						 | 
					3feba82ccc | ||
| 
						 | 
					db924da231 | ||
| 
						 | 
					fc55ae7e6d | ||
| 
						 | 
					86e757a6ad | ||
| 
						 | 
					4790715cd3 | ||
| 
						 | 
					e7e9c60042 | ||
| 
						 | 
					1c3bc52cc4 | ||
| 
						 | 
					5227dff0e1 | ||
| 
						 | 
					33f0b5b7c2 | ||
| 
						 | 
					0a02968303 | ||
| 
						 | 
					f7bf658c07 | ||
| 
						 | 
					8d16a0abad | ||
| 
						 | 
					c974b97ca3 | ||
| 
						 | 
					b8025bfebd | ||
| 
						 | 
					30323b253f | ||
| 
						 | 
					535c3ede96 | ||
| 
						 | 
					89fed8ca33 | ||
| 
						 | 
					f43c77aaed | ||
| 
						 | 
					96c676b371 | ||
| 
						 | 
					113047e1a2 | ||
| 
						 | 
					abed57cb53 | ||
| 
						 | 
					c01a800a6b | ||
| 
						 | 
					d648832a2d | ||
| 
						 | 
					f06833fbd2 | ||
| 
						 | 
					c561addc94 | ||
| 
						 | 
					702f5f1f4c | ||
| 
						 | 
					1273f179e8 | ||
| 
						 | 
					5d02f60bde | ||
| 
						 | 
					4cf7a108e8 | ||
| 
						 | 
					42635c3938 | ||
| 
						 | 
					ed43dc842b | ||
| 
						 | 
					49d4db6cd2 | ||
| 
						 | 
					ea80ab2cae | ||
| 
						 | 
					382e808b8d | ||
| 
						 | 
					846befa7e0 | ||
| 
						 | 
					74dd29f843 | ||
| 
						 | 
					b0473bffcb | ||
| 
						 | 
					24dd9ab1a7 | ||
| 
						 | 
					49d3037e87 | ||
| 
						 | 
					37ad2bd4e8 | ||
| 
						 | 
					7d7b332b02 | ||
| 
						 | 
					ac033b8612 | ||
| 
						 | 
					a7b98dfe25 | ||
| 
						 | 
					7fb7c86c46 | ||
| 
						 | 
					ed036598a9 | ||
| 
						 | 
					160bb70cdf | ||
| 
						 | 
					c2e61f3c21 | ||
| 
						 | 
					18218467f3 | ||
| 
						 | 
					17e298ad2a | ||
| 
						 | 
					d031a374f9 | ||
| 
						 | 
					55f69c98cb | ||
| 
						 | 
					71f2e4306d | ||
| 
						 | 
					f8af23a025 | ||
| 
						 | 
					4ef55a6cd3 | ||
| 
						 | 
					312f866723 | ||
| 
						 | 
					0ebe1f6dec | ||
| 
						 | 
					2ad92e0e6e | ||
| 
						 | 
					ac8823cdcf | ||
| 
						 | 
					77565f7ee4 | ||
| 
						 | 
					d656d90fa8 | ||
| 
						 | 
					175b3b0834 | ||
| 
						 | 
					7477e6b714 | ||
| 
						 | 
					cd6568db69 | ||
| 
						 | 
					6aff325fb2 | ||
| 
						 | 
					0d603cfe9c | ||
| 
						 | 
					34a1f14a17 | ||
| 
						 | 
					efe1c8a070 | ||
| 
						 | 
					1575844344 | ||
| 
						 | 
					221ac1c208 | ||
| 
						 | 
					57442db759 | ||
| 
						 | 
					5fdb3e7cd6 | ||
| 
						 | 
					96f259726c | ||
| 
						 | 
					4936efba5e | ||
| 
						 | 
					d5a3559a2f | ||
| 
						 | 
					114a1c7f52 | ||
| 
						 | 
					ce5265c203 | ||
| 
						 | 
					1a575d926f | ||
| 
						 | 
					85c818a39e | ||
| 
						 | 
					4ffa2defe4 | ||
| 
						 | 
					8825157fbb | ||
| 
						 | 
					966d608dc5 | ||
| 
						 | 
					b808c89471 | ||
| 
						 | 
					75d4e6490f | ||
| 
						 | 
					a82775f544 | ||
| 
						 | 
					6a22ad0171 | ||
| 
						 | 
					c854e88186 | ||
| 
						 | 
					d02203060c | ||
| 
						 | 
					cf703b0433 | ||
| 
						 | 
					c0197a72d3 | ||
| 
						 | 
					e5a543e283 | ||
| 
						 | 
					b8b029b7d3 | ||
| 
						 | 
					370f368b1a | ||
| 
						 | 
					8288b45b4f | ||
| 
						 | 
					fe529faf8e | ||
| 
						 | 
					ab931b177d | ||
| 
						 | 
					9aa3465513 | ||
| 
						 | 
					6c70fc1a6c | ||
| 
						 | 
					1ccc39962a | ||
| 
						 | 
					99c941fc85 | ||
| 
						 | 
					19729fdcc2 | ||
| 
						 | 
					02e17998ce | ||
| 
						 | 
					459e00c67a | ||
| 
						 | 
					292f665650 | ||
| 
						 | 
					93bbb79569 | ||
| 
						 | 
					273e724f2b | ||
| 
						 | 
					5d2615c56f | ||
| 
						 | 
					bfaaf21330 | ||
| 
						 | 
					dcb8415b7a | ||
| 
						 | 
					699e1c75ce | ||
| 
						 | 
					465b6e613e | ||
| 
						 | 
					05fa105855 | ||
| 
						 | 
					d7a0cdebe5 | ||
| 
						 | 
					b049ab31eb | ||
| 
						 | 
					6db4dcff7a | ||
| 
						 | 
					3eeaef00ec | ||
| 
						 | 
					8bf4c38a00 | ||
| 
						 | 
					3a32b09ad1 | ||
| 
						 | 
					6315982752 | ||
| 
						 | 
					374a171e82 | ||
| 
						 | 
					fc5d801f91 | ||
| 
						 | 
					5146641848 | ||
| 
						 | 
					cdd0ac42cf | ||
| 
						 | 
					e5895500a2 | ||
| 
						 | 
					9cb4dde3fa | ||
| 
						 | 
					3c2a4370a5 | ||
| 
						 | 
					e7a360dd6f | ||
| 
						 | 
					c814c2fd35 | ||
| 
						 | 
					fefa7fe262 | ||
| 
						 | 
					26f01a29d1 | ||
| 
						 | 
					169d4090ab | ||
| 
						 | 
					0b43754d60 | ||
| 
						 | 
					8b3b26b813 | ||
| 
						 | 
					5426af4f81 | ||
| 
						 | 
					4e2c3a579d | ||
| 
						 | 
					5ae2693241 | ||
| 
						 | 
					41c86b0d19 | ||
| 
						 | 
					40788e8c3d | ||
| 
						 | 
					0d29120033 | ||
| 
						 | 
					4be598f865 | ||
| 
						 | 
					558a6d509e | ||
| 
						 | 
					75cd02aad2 | ||
| 
						 | 
					e4c4451482 | ||
| 
						 | 
					0671632477 | ||
| 
						 | 
					54c230c264 | ||
| 
						 | 
					64ba878eda | ||
| 
						 | 
					01acd6dd76 | ||
| 
						 | 
					9d819b52d3 | ||
| 
						 | 
					37bac5cdc9 | ||
| 
						 | 
					78c718c591 | ||
| 
						 | 
					284b8bf6ca | ||
| 
						 | 
					5a5084b837 | ||
| 
						 | 
					3b8058e1f1 | ||
| 
						 | 
					2a3168e0d6 | ||
| 
						 | 
					a8ac6e4a15 | ||
| 
						 | 
					6172cf9fba | ||
| 
						 | 
					b728ec3909 | ||
| 
						 | 
					61a53bbcff | ||
| 
						 | 
					17d13dd084 | ||
| 
						 | 
					edcb28d591 | ||
| 
						 | 
					ad101119a7 | ||
| 
						 | 
					bc36676d31 | ||
| 
						 | 
					d76fe120ab | ||
| 
						 | 
					2e95949b80 | ||
| 
						 | 
					ae14d85e24 | ||
| 
						 | 
					fad6304c60 | ||
| 
						 | 
					a4dd3c8ce9 | ||
| 
						 | 
					6d1a5d45e2 | ||
| 
						 | 
					a6c7043e03 | ||
| 
						 | 
					bcc400dafa | ||
| 
						 | 
					8fbedf3441 | ||
| 
						 | 
					2e8a9c9874 | ||
| 
						 | 
					44fc41b3e5 | ||
| 
						 | 
					7212c20a1b | ||
| 
						 | 
					7ff142de1c | ||
| 
						 | 
					e67efb199d | ||
| 
						 | 
					20128bd04b | ||
| 
						 | 
					c0fefdde28 | ||
| 
						 | 
					f6ee160e66 | ||
| 
						 | 
					06acc2004f | ||
| 
						 | 
					43ac2ce4c8 | ||
| 
						 | 
					b32bf72b5f | ||
| 
						 | 
					c6880c957e | ||
| 
						 | 
					095b71ed96 | ||
| 
						 | 
					9160e496bc | ||
| 
						 | 
					2a7ac78f02 | ||
| 
						 | 
					64efa4627d | ||
| 
						 | 
					f7e35569ce | ||
| 
						 | 
					e8af32ec2b | ||
| 
						 | 
					e092ce51f6 | ||
| 
						 | 
					7b78edb1b7 | ||
| 
						 | 
					b332e7090e | ||
| 
						 | 
					67eb7723d6 | ||
| 
						 | 
					251d138474 | ||
| 
						 | 
					1170dfac05 | ||
| 
						 | 
					4157f141c7 | ||
| 
						 | 
					f569abd28a | ||
| 
						 | 
					088f9687c0 | ||
| 
						 | 
					e23df1f07a | ||
| 
						 | 
					c818540dfd | ||
| 
						 | 
					21365cbe1a | ||
| 
						 | 
					5471a80a96 | ||
| 
						 | 
					d7b6fa9cd0 | ||
| 
						 | 
					dfdc2e02ef | ||
| 
						 | 
					893ec9a302 | ||
| 
						 | 
					05f65c38e6 | ||
| 
						 | 
					2e9d062ec0 | ||
| 
						 | 
					6b0b394e61 | ||
| 
						 | 
					25621396c9 | ||
| 
						 | 
					82aa0271f3 | ||
| 
						 | 
					653cab13f8 | ||
| 
						 | 
					b526f86b49 | ||
| 
						 | 
					53c0f00888 | ||
| 
						 | 
					f0c4d9de40 | ||
| 
						 | 
					03ef8cec83 | ||
| 
						 | 
					85f2a2e8c2 | ||
| 
						 | 
					584b3e6642 | ||
| 
						 | 
					39b7ef841d | ||
| 
						 | 
					aa16a9098d | ||
| 
						 | 
					7b8c2707bc | ||
| 
						 | 
					60e26a31a7 | ||
| 
						 | 
					3473c25c14 | ||
| 
						 | 
					e52f022026 | ||
| 
						 | 
					b1a7df8e43 | ||
| 
						 | 
					0fd2479b7c | ||
| 
						 | 
					273857f914 | ||
| 
						 | 
					a08b85dbc8 | ||
| 
						 | 
					a0aedf299a | ||
| 
						 | 
					3c61426844 | ||
| 
						 | 
					786f228076 | ||
| 
						 | 
					004da28792 | ||
| 
						 | 
					6e2be6efb6 | ||
| 
						 | 
					a994dfcfbc | ||
| 
						 | 
					7a8ea2ac93 | ||
| 
						 | 
					0da3965d19 | ||
| 
						 | 
					885fd7bb46 | ||
| 
						 | 
					08771f9c89 | ||
| 
						 | 
					8be48195a5 | ||
| 
						 | 
					98ce2d650e | ||
| 
						 | 
					3af327116a | ||
| 
						 | 
					b75434db93 | ||
| 
						 | 
					04e912aacd | ||
| 
						 | 
					d7be352f87 | ||
| 
						 | 
					96be3ec22c | ||
| 
						 | 
					32e7e0d790 | ||
| 
						 | 
					becc320e62 | ||
| 
						 | 
					7666ed57d1 | ||
| 
						 | 
					5e61d0955e | ||
| 
						 | 
					e8a4662ae7 | ||
| 
						 | 
					a48da3bd3b | ||
| 
						 | 
					5f1a5d7b99 | ||
| 
						 | 
					3e28a9db8f | ||
| 
						 | 
					ebf6071d77 | ||
| 
						 | 
					47a35fb9fb | ||
| 
						 | 
					48e88aba44 | ||
| 
						 | 
					b85f99c140 | ||
| 
						 | 
					0a5e0e1f71 | ||
| 
						 | 
					85dc22ebb7 | ||
| 
						 | 
					5c21526009 | ||
| 
						 | 
					14dff1cefc | ||
| 
						 | 
					39fbb844f9 | ||
| 
						 | 
					ca4e0c973a | ||
| 
						 | 
					ecb42bee80 | ||
| 
						 | 
					674ed2a9f3 | ||
| 
						 | 
					252daf9717 | ||
| 
						 | 
					196b8eaad3 | ||
| 
						 | 
					8e526ba1bf | ||
| 
						 | 
					19225828d9 | ||
| 
						 | 
					7e594126be | ||
| 
						 | 
					d2529e6334 | ||
| 
						 | 
					97344f18e2 | ||
| 
						 | 
					33934db629 | ||
| 
						 | 
					6c6165c9f5 | ||
| 
						 | 
					853460b20d | ||
| 
						 | 
					cc4d9676c5 | ||
| 
						 | 
					1cf1b819f4 | ||
| 
						 | 
					f916c66d2b | ||
| 
						 | 
					550aa86b45 | ||
| 
						 | 
					014e764758 | ||
| 
						 | 
					d1fc28432b | ||
| 
						 | 
					879576f0a2 | ||
| 
						 | 
					69098210be | ||
| 
						 | 
					99df4f892d | ||
| 
						 | 
					7bc04fbad3 | ||
| 
						 | 
					8a74ce578d | ||
| 
						 | 
					0805e4e5de | ||
| 
						 | 
					f1060fc88e | ||
| 
						 | 
					7d3d3d0a3a | ||
| 
						 | 
					40377032e3 | ||
| 
						 | 
					b2971edd7d | ||
| 
						 | 
					c37d723692 | ||
| 
						 | 
					30f9026e1d | ||
| 
						 | 
					332286072e | ||
| 
						 | 
					d6da172a2a | ||
| 
						 | 
					ebfe584afc | ||
| 
						 | 
					6250023583 | ||
| 
						 | 
					6b4f3d63b8 | ||
| 
						 | 
					56db773a09 | ||
| 
						 | 
					fc6c472401 | ||
| 
						 | 
					2cd42a6866 | ||
| 
						 | 
					36a90c345c | ||
| 
						 | 
					ef1e82c72c | ||
| 
						 | 
					88f9534685 | ||
| 
						 | 
					68254a052a | ||
| 
						 | 
					2425b3a166 | ||
| 
						 | 
					5524ed753b | ||
| 
						 | 
					89711723da | ||
| 
						 | 
					bed2740ffd | ||
| 
						 | 
					751d633c3d | ||
| 
						 | 
					45952cbdf2 | ||
| 
						 | 
					b355dd7b23 | ||
| 
						 | 
					48a186f172 | ||
| 
						 | 
					39dc7ec2ab | ||
| 
						 | 
					2fedabd3b9 | ||
| 
						 | 
					6d719e9480 | ||
| 
						 | 
					05e278afda | ||
| 
						 | 
					87dbf462cb | ||
| 
						 | 
					40e896bc5b | ||
| 
						 | 
					3e940f80c7 | ||
| 
						 | 
					dbf2888d43 | ||
| 
						 | 
					d412355324 | ||
| 
						 | 
					178732217f | ||
| 
						 | 
					de17b95c3d | ||
| 
						 | 
					d14e774525 | ||
| 
						 | 
					ca5402a7fa | ||
| 
						 | 
					7a6fa7c5b4 | ||
| 
						 | 
					da36c286a6 | ||
| 
						 | 
					d3901bcf2e | ||
| 
						 | 
					94c8d4fdfb | ||
| 
						 | 
					ab8bdc18bb | ||
| 
						 | 
					c9dcd7442a | ||
| 
						 | 
					34c8f13346 | ||
| 
						 | 
					7a8ccda95c | ||
| 
						 | 
					44a1448542 | ||
| 
						 | 
					c87d89ffaf | ||
| 
						 | 
					0868749d42 | ||
| 
						 | 
					1d40ee23f0 | ||
| 
						 | 
					8893f32603 | ||
| 
						 | 
					adcf7e8dc3 | ||
| 
						 | 
					901f7c5c36 | ||
| 
						 | 
					775bb413b3 | ||
| 
						 | 
					64cd5b5a46 | ||
| 
						 | 
					ae356609b1 | ||
| 
						 | 
					6102a5d2b0 | ||
| 
						 | 
					f8782ee2d7 | ||
| 
						 | 
					6181ec4c77 | ||
| 
						 | 
					e0e7a685ef | ||
| 
						 | 
					ae1f8cdad2 | ||
| 
						 | 
					a4cf792e6d | ||
| 
						 | 
					89109ded53 | ||
| 
						 | 
					e20e52a4b2 | ||
| 
						 | 
					20c4b1cbec | ||
| 
						 | 
					5238b0241d | ||
| 
						 | 
					9cdf6c203d | ||
| 
						 | 
					839335cae6 | ||
| 
						 | 
					a99b2ce167 | ||
| 
						 | 
					b695141d87 | ||
| 
						 | 
					92d5c9f866 | ||
| 
						 | 
					7f18a1ffe0 | ||
| 
						 | 
					8c3fdaaa62 | ||
| 
						 | 
					5ac1c69710 | ||
| 
						 | 
					de2d5fba63 | ||
| 
						 | 
					33d516748f | ||
| 
						 | 
					de17f6f0fd | ||
| 
						 | 
					756731fc02 | ||
| 
						 | 
					e46be0415f | ||
| 
						 | 
					aa02fb50bf | ||
| 
						 | 
					8b6cd9c772 | ||
| 
						 | 
					cdd0d3351a | ||
| 
						 | 
					8b6d584529 | ||
| 
						 | 
					f49fdd4141 | ||
| 
						 | 
					b26e1be81a | ||
| 
						 | 
					bacab38d7f | ||
| 
						 | 
					701c05ce96 | ||
| 
						 | 
					438c452585 | ||
| 
						 | 
					0a7a1eff3f | ||
| 
						 | 
					87e743e381 | ||
| 
						 | 
					a03f1b3d55 | ||
| 
						 | 
					2d8dc3d243 | ||
| 
						 | 
					b982232cc5 | ||
| 
						 | 
					61c8d728ac | ||
| 
						 | 
					851a2bf855 | ||
| 
						 | 
					e0bdde3630 | ||
| 
						 | 
					6a0dcd7f0e | ||
| 
						 | 
					75f0b4c879 | ||
| 
						 | 
					db536a9504 | ||
| 
						 | 
					0fb114dede | ||
| 
						 | 
					e703342179 | ||
| 
						 | 
					35c8f4a611 | ||
| 
						 | 
					7c89ae44a9 | ||
| 
						 | 
					84fe06da22 | ||
| 
						 | 
					806318c8b3 | ||
| 
						 | 
					3aac2e1822 | ||
| 
						 | 
					168baef433 | ||
| 
						 | 
					6dba6cd78d | ||
| 
						 | 
					502250d08f | ||
| 
						 | 
					7395f0e680 | ||
| 
						 | 
					494d3fdaca | ||
| 
						 | 
					7b86a157de | ||
| 
						 | 
					0988c41785 | ||
| 
						 | 
					522db1bf01 | ||
| 
						 | 
					06f066f90d | ||
| 
						 | 
					f37b20677b | ||
| 
						 | 
					cd2eac1032 | ||
| 
						 | 
					8ac38d58d7 | ||
| 
						 | 
					4c80cc313a | ||
| 
						 | 
					1c65fee9b4 | ||
| 
						 | 
					90dda7edc1 | ||
| 
						 | 
					da054fae20 | ||
| 
						 | 
					bdb6611e30 | ||
| 
						 | 
					9284f973f1 | ||
| 
						 | 
					2bfd64c3c9 | ||
| 
						 | 
					939d24cce5 | ||
| 
						 | 
					27b0183c46 | ||
| 
						 | 
					d14efacac7 | ||
| 
						 | 
					150a002c40 | ||
| 
						 | 
					ce0def3bd8 | ||
| 
						 | 
					ee20fa97c2 | ||
| 
						 | 
					7403b7d700 | ||
| 
						 | 
					87ef173e0a | ||
| 
						 | 
					52a3fb6bc7 | ||
| 
						 | 
					92e2a257a6 | ||
| 
						 | 
					32e175752c | ||
| 
						 | 
					d43f7180dc | ||
| 
						 | 
					0129c2b0fc | ||
| 
						 | 
					4ed1990001 | ||
| 
						 | 
					5bd6ab27ae | ||
| 
						 | 
					f3593b89fa | ||
| 
						 | 
					23d84b2310 | ||
| 
						 | 
					fdc49402ec | ||
| 
						 | 
					5457c133e1 | ||
| 
						 | 
					292e588ee3 | ||
| 
						 | 
					243494c25e | ||
| 
						 | 
					e4365f3706 | ||
| 
						 | 
					310f3038d3 | ||
| 
						 | 
					4e6033273d | ||
| 
						 | 
					73718586d3 | ||
| 
						 | 
					011abe61e8 | ||
| 
						 | 
					fe3a37f89d | ||
| 
						 | 
					8aea44e77b | ||
| 
						 | 
					5529aec0d6 | ||
| 
						 | 
					369549d23f | ||
| 
						 | 
					181ea9a381 | ||
| 
						 | 
					76b8f2854e | ||
| 
						 | 
					320e5198f9 | ||
| 
						 | 
					e522539e2d | ||
| 
						 | 
					7c996b83d2 | ||
| 
						 | 
					3dd354d7aa | ||
| 
						 | 
					f4ad6e2157 | ||
| 
						 | 
					8b170dc2bf | ||
| 
						 | 
					dcb9d779bf | ||
| 
						 | 
					80f736d670 | ||
| 
						 | 
					8502c6da3c | ||
| 
						 | 
					b131449422 | ||
| 
						 | 
					6eebc4a620 | ||
| 
						 | 
					4661ab1179 | ||
| 
						 | 
					86046445ed | ||
| 
						 | 
					baea9bf944 | ||
| 
						 | 
					0951ee9e63 | ||
| 
						 | 
					5492528287 | ||
| 
						 | 
					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 | ||
| 
						 | 
					e3f8892003 | ||
| 
						 | 
					9d00ad5f18 | ||
| 
						 | 
					dae4344850 | ||
| 
						 | 
					aa7f3fabe2 | ||
| 
						 | 
					f93434a8ce | ||
| 
						 | 
					25dee56be9 | ||
| 
						 | 
					ce9a3f3797 | ||
| 
						 | 
					11e384920a | ||
| 
						 | 
					a0a1f1e536 | ||
| 
						 | 
					3b3d0ea9eb | ||
| 
						 | 
					2f4d78286d | ||
| 
						 | 
					677dc6f985 | ||
| 
						 | 
					d52057e732 | ||
| 
						 | 
					fa2a1cb1fb | ||
| 
						 | 
					19a0fb04ad | ||
| 
						 | 
					947352f2fe | ||
| 
						 | 
					adcbedb686 | ||
| 
						 | 
					7732f92acd | ||
| 
						 | 
					ad8a001688 | ||
| 
						 | 
					9121eada08 | ||
| 
						 | 
					49bd4d25a2 | ||
| 
						 | 
					d80b4129c6 | ||
| 
						 | 
					7edb4172d5 | ||
| 
						 | 
					c3a4677990 | ||
| 
						 | 
					5cbb893a3b | ||
| 
						 | 
					f28a2a432b | ||
| 
						 | 
					03b75a2d27 | ||
| 
						 | 
					859fe69083 | ||
| 
						 | 
					f6f2205ddb | ||
| 
						 | 
					0f9a03ef61 | ||
| 
						 | 
					9aa417c084 | ||
| 
						 | 
					7b70952f5d | ||
| 
						 | 
					edd3d07b49 | ||
| 
						 | 
					5293d0a4ec | ||
| 
						 | 
					3c8c7beae1 | ||
| 
						 | 
					9c3ba9fdcd | ||
| 
						 | 
					fb1748fb0f | ||
| 
						 | 
					0a109fbd03 | ||
| 
						 | 
					5cf64db74e | ||
| 
						 | 
					488cc94f36 | ||
| 
						 | 
					e15846bf79 | ||
| 
						 | 
					752bd00674 | ||
| 
						 | 
					7fadfcbe32 | ||
| 
						 | 
					41141e75bb | ||
| 
						 | 
					50f641e627 | ||
| 
						 | 
					c7883fd093 | ||
| 
						 | 
					4fcb24b2b1 | ||
| 
						 | 
					5003557935 | ||
| 
						 | 
					bdf1ba84da | ||
| 
						 | 
					b0b4def983 | ||
| 
						 | 
					cc184bbe9e | ||
| 
						 | 
					ad30c830aa | ||
| 
						 | 
					1d791a8af4 | ||
| 
						 | 
					e63c51cd97 | ||
| 
						 | 
					f202e32908 | ||
| 
						 | 
					26e1a08e82 | ||
| 
						 | 
					4d5119d435 | ||
| 
						 | 
					75e34ea62e | ||
| 
						 | 
					0a183d6274 | ||
| 
						 | 
					21d8060aea | ||
| 
						 | 
					9cbe906f60 | ||
| 
						 | 
					8ce4137399 | ||
| 
						 | 
					5f8a139347 | ||
| 
						 | 
					9bb009a3fe | ||
| 
						 | 
					726d65923f | ||
| 
						 | 
					8a6be4cb2d | ||
| 
						 | 
					10b06beb8e | ||
| 
						 | 
					81318c7968 | ||
| 
						 | 
					47a2c1c6e5 | ||
| 
						 | 
					39cee65c6b | ||
| 
						 | 
					8582ec724e | ||
| 
						 | 
					b0139682e8 | ||
| 
						 | 
					d39c475a6d | ||
| 
						 | 
					48f38354c6 | ||
| 
						 | 
					cd5a920ed5 | ||
| 
						 | 
					71bc1f378d | ||
| 
						 | 
					0ee6c31cff | ||
| 
						 | 
					af89a9971e | ||
| 
						 | 
					c718a8ef72 | ||
| 
						 | 
					8c8ad0faf0 | ||
| 
						 | 
					314d5bbb7f | ||
| 
						 | 
					102255757a | ||
| 
						 | 
					914067a0d0 | ||
| 
						 | 
					06e3ae2536 | ||
| 
						 | 
					7f9b252556 | ||
| 
						 | 
					3d700e243f | ||
| 
						 | 
					bcfc78ce11 | ||
| 
						 | 
					09241765d5 | ||
| 
						 | 
					671c83c265 | ||
| 
						 | 
					772d28b766 | ||
| 
						 | 
					c26fcea58d | ||
| 
						 | 
					1e5e26dbff | ||
| 
						 | 
					742fc54864 | ||
| 
						 | 
					49738f43c0 | ||
| 
						 | 
					9f85f61010 | ||
| 
						 | 
					239f422039 | ||
| 
						 | 
					67af3c37be | ||
| 
						 | 
					a9442385c4 | ||
| 
						 | 
					8c9cd10b8b | ||
| 
						 | 
					72542059dd | ||
| 
						 | 
					a843fc6d40 | ||
| 
						 | 
					4beed60c08 | ||
| 
						 | 
					4049c1e480 | ||
| 
						 | 
					8449314da2 | 
							
								
								
									
										2
									
								
								BUGS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								BUGS
									
									
									
									
									
								
							@@ -1,2 +0,0 @@
 | 
			
		||||
Snapshots under 2.4.18 can deadlock due to a bug in the VM system.
 | 
			
		||||
2.4.19-pre8 is fine.
 | 
			
		||||
							
								
								
									
										0
									
								
								CONTRIBUTORS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								CONTRIBUTORS
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										67
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								Makefile.in
									
									
									
									
									
								
							@@ -1,35 +1,70 @@
 | 
			
		||||
#
 | 
			
		||||
# 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 lib tools
 | 
			
		||||
SUBDIRS = doc include man 
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
  SUBDIRS += po
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
SUBDIRS += lib tools daemons
 | 
			
		||||
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
  SUBDIRS += dmeventd
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
  SUBDIRS += lib/format1 \
 | 
			
		||||
  SUBDIRS += daemons/clvmd \
 | 
			
		||||
	     dmeventd \
 | 
			
		||||
	     lib/format1 \
 | 
			
		||||
	     lib/format_pool \
 | 
			
		||||
	     lib/locking \
 | 
			
		||||
	     lib/mirror \
 | 
			
		||||
	     lib/snapshot \
 | 
			
		||||
	     po \
 | 
			
		||||
	     test/mm test/device test/format1 test/regex test/filters
 | 
			
		||||
  DISTCLEAN_TARGETS += lib/misc/configure.h
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include make.tmpl
 | 
			
		||||
 | 
			
		||||
daemons: lib
 | 
			
		||||
lib: include
 | 
			
		||||
tools: include lib
 | 
			
		||||
tools: lib
 | 
			
		||||
dmeventd: tools
 | 
			
		||||
po: tools daemons dmeventd
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
lib.pofile: include.pofile
 | 
			
		||||
tools.pofile: lib.pofile
 | 
			
		||||
daemons.pofile: lib.pofile
 | 
			
		||||
dmeventd.pofile: tools.pofile
 | 
			
		||||
po.pofile: tools.pofile daemons.pofile dmeventd.pofile
 | 
			
		||||
pofile: po.pofile
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@CFLOW_CMD@", "")
 | 
			
		||||
tools.cflow: lib.cflow
 | 
			
		||||
cflow: tools.cflow
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@CSCOPE_CMD@", "")
 | 
			
		||||
cscope.out: tools
 | 
			
		||||
	@CSCOPE_CMD@ -b -R
 | 
			
		||||
all: cscope.out
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								README
									
									
									
									
									
								
							@@ -1,25 +1,23 @@
 | 
			
		||||
This directory contains a beta release of LVM2, the new version of 
 | 
			
		||||
the userland LVM tools designed for the new device-mapper for 
 | 
			
		||||
the Linux kernel.
 | 
			
		||||
This directory contains LVM2, the new version of the userland LVM
 | 
			
		||||
tools designed for the new device-mapper for the Linux kernel.
 | 
			
		||||
 | 
			
		||||
The device-mapper needs to be installed before compiling these LVM2 tools.
 | 
			
		||||
 | 
			
		||||
For more information about LVM2 read the WHATS_NEW file.
 | 
			
		||||
Installation instructions are in INSTALL.
 | 
			
		||||
 | 
			
		||||
This is beta-quality software, released for testing purposes only.
 | 
			
		||||
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@tech.sistina.com:/data/cvs login
 | 
			
		||||
  CVS password: cvs1
 | 
			
		||||
  cvs -d :pserver:cvs@tech.sistina.com:/data/cvs checkout LVM2
 | 
			
		||||
  cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
 | 
			
		||||
  CVS password: cvs
 | 
			
		||||
  cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 co LVM2
 | 
			
		||||
 | 
			
		||||
Mailing list for discussion/bug reports etc.
 | 
			
		||||
  lvm-devel@sistina.com
 | 
			
		||||
  Subscribe from http://lists.sistina.com/mailman/listinfo/lvm-devel
 | 
			
		||||
  linux-lvm@redhat.com
 | 
			
		||||
  Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										643
									
								
								WHATS_NEW
									
									
									
									
									
								
							
							
						
						
									
										643
									
								
								WHATS_NEW
									
									
									
									
									
								
							@@ -1,3 +1,640 @@
 | 
			
		||||
Version 2.02.08 - 15th August 2006
 | 
			
		||||
==================================
 | 
			
		||||
  Add checks for duplicate LV name, lvid and PV id before writing metadata.
 | 
			
		||||
  Report all sanity check failures, not just the first.
 | 
			
		||||
  Fix missing lockfs on first snapshot creation.
 | 
			
		||||
  Add unreliable --trustcache option to reporting commands.
 | 
			
		||||
  Fix locking for mimage removal.
 | 
			
		||||
  Fix clvmd_init_rhel4 'status' exit code.
 | 
			
		||||
 | 
			
		||||
Version 2.02.07 - 17th July 2006
 | 
			
		||||
================================
 | 
			
		||||
  Fix activation logic in lvchange --persistent.
 | 
			
		||||
  Don't ignore persistent minor numbers when activating.
 | 
			
		||||
  Use RTLD_GLOBAL when loading shared libraries.
 | 
			
		||||
  Add some forgotten memlock checks to _vg_read to protect against full scans.
 | 
			
		||||
  Add mutex to dmeventd_mirror to avoid concurrent execution.
 | 
			
		||||
  Fix vgreduce --removemissing to return success if VG is already consistent.
 | 
			
		||||
  Fix return code if VG specified on command line is not found.
 | 
			
		||||
  Fix PV tools to include orphaned PVs in default output again.
 | 
			
		||||
  Fixed unaligned access when using clvm.
 | 
			
		||||
  Fix an extra dev_close in a label_read error path.
 | 
			
		||||
  Append patches to commit emails.
 | 
			
		||||
  Fix target_register_events args.
 | 
			
		||||
  Prevent snapshots of mirrors.
 | 
			
		||||
  Add DISTCLEAN_TARGETS to make template for configure.h.
 | 
			
		||||
  More fixes to error paths.
 | 
			
		||||
  Fix lvcreate corelog validation.
 | 
			
		||||
  Add --config for overriding most config file settings from cmdline.
 | 
			
		||||
  Quote arguments when printing command line.
 | 
			
		||||
  Remove linefeed from 'initialising logging' message.
 | 
			
		||||
  Add 'Completed' debug message.
 | 
			
		||||
  Don't attempt library exit after reloading config files.
 | 
			
		||||
  Always compile with libdevmapper, even if device-mapper is disabled.
 | 
			
		||||
 | 
			
		||||
Version 2.02.06 - 12th May 2006
 | 
			
		||||
===============================
 | 
			
		||||
  Propagate --monitor around cluster.
 | 
			
		||||
  Add --monitor to vgcreate and lvcreate to control dmeventd registration.
 | 
			
		||||
  Filter LCK_NONBLOCK in clvmd lock_vg.
 | 
			
		||||
  Add --nosync to lvcreate with LV flag NOTSYNCED.
 | 
			
		||||
  Use mirror's uuid for a core log.
 | 
			
		||||
  Add mirror log fault-handling policy.
 | 
			
		||||
  Improve mirror warning messages and tidy dmeventd syslog output.
 | 
			
		||||
  Propagate nosync flag around cluster.
 | 
			
		||||
  Allow vgreduce to handle mirror log failures.
 | 
			
		||||
  Add --corelog to lvcreate and lvconvert.
 | 
			
		||||
  Create a log header for replacement in-sync mirror log.
 | 
			
		||||
  Use set_lv() and dev_set() to wipe sections of devices.
 | 
			
		||||
  Add mirror_in_sync() flag to avoid unnecessary resync on activation.
 | 
			
		||||
  Add mirror_library description to example.conf.
 | 
			
		||||
  Fix uuid_from_num() buffer overrun.
 | 
			
		||||
  Make SIZE_SHORT the default for display_size().
 | 
			
		||||
  Fix some memory leaks in error paths found by coverity.
 | 
			
		||||
  Use C99 struct initialisers.
 | 
			
		||||
  Move DEFS into configure.h.
 | 
			
		||||
  Clean-ups to remove miscellaneous compiler warnings.
 | 
			
		||||
  Improve stripe size validation.
 | 
			
		||||
  Increase maximum stripe size limit to physical extent size for lvm2 metadata.
 | 
			
		||||
  Fix activation code to check for pre-existing mirror logs.
 | 
			
		||||
  Tighten region size validation.
 | 
			
		||||
  Ignore empty strings in config files.
 | 
			
		||||
  Require non-zero regionsize and document parameter on lvcreate man page.
 | 
			
		||||
  Invalidate cache if composition of VG changed externally.
 | 
			
		||||
 | 
			
		||||
Version 2.02.05 - 21st April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  Fix vgid string termination in recent cache code.
 | 
			
		||||
 | 
			
		||||
Version 2.02.04 - 19th April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  Check for libsepol.
 | 
			
		||||
  Add some cflow & scope support.
 | 
			
		||||
  Separate out DEFS from CFLAGS.
 | 
			
		||||
  Remove inlines and use unique function names.
 | 
			
		||||
 | 
			
		||||
Version 2.02.03 - 14th April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  vgrename accepts vgid and exported VG.
 | 
			
		||||
  Add --partial to pvs.
 | 
			
		||||
  When choosing between identically-named VGs, also consider creation_host.
 | 
			
		||||
  Provide total log suppression with 2.
 | 
			
		||||
  Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
 | 
			
		||||
  Add vgid to struct physical_volume and pass with vg_name to some functions.
 | 
			
		||||
  If two or more VGs are found with the same name, use one that is not exported.
 | 
			
		||||
  Whenever vgname is captured, also capture vgid and whether exported.
 | 
			
		||||
  Remove an incorrect unlock_vg() from process_each_lv().
 | 
			
		||||
  Update extent size information in vgchange and vgcreate man pages.
 | 
			
		||||
  Introduce origin_from_cow() and lv_is_visible().
 | 
			
		||||
  pvremove without -f now fails if there's no PV label.
 | 
			
		||||
  Support lvconvert -s.
 | 
			
		||||
  Suppress locking library load failure message if --ignorelockingfailure.
 | 
			
		||||
  Propagate partial mode around cluster.
 | 
			
		||||
  Fix archive file expiration.
 | 
			
		||||
  Fix dmeventd build.
 | 
			
		||||
  clvmd now uses libcman rather than cman ioctls.
 | 
			
		||||
  clvmd will allow new cman to shutdown on request.
 | 
			
		||||
 | 
			
		||||
Version 2.02.02 - 7th February 2006
 | 
			
		||||
===================================
 | 
			
		||||
  Add %.so: %.a make template rule.
 | 
			
		||||
  Switchover library building to use LIB_SUFFIX.
 | 
			
		||||
  Only do lockfs filesystem sync when suspending snapshots.
 | 
			
		||||
  Always print warning if activation is disabled.
 | 
			
		||||
  vgreduce removes mirror images.
 | 
			
		||||
  Add --mirrorsonly to vgreduce.
 | 
			
		||||
  vgreduce replaces active LVs with error segment before removing them.
 | 
			
		||||
  Set block_on_error parameter if available.
 | 
			
		||||
  Add target_version.
 | 
			
		||||
  Add details to format1 'Invalid LV in extent map' error message.
 | 
			
		||||
  Fix lvscan snapshot full display.
 | 
			
		||||
  Bring lvdisplay man page example into line.
 | 
			
		||||
  Add mirror dmeventd library.
 | 
			
		||||
  Add some activation logic to remove_mirror_images().
 | 
			
		||||
  lvconvert can remove specified PVs from a mirror.
 | 
			
		||||
  lvconvert turns an existing LV into a mirror.
 | 
			
		||||
  Allow signed mirrors arguments.
 | 
			
		||||
  Move create_mirror_log() into toollib.
 | 
			
		||||
  Determine parallel PVs to avoid with ALLOC_NORMAL allocation.
 | 
			
		||||
  Fix lv_empty.
 | 
			
		||||
 | 
			
		||||
Version 2.02.01 - 23rd November 2005
 | 
			
		||||
====================================
 | 
			
		||||
  Fix lvdisplay cmdline to accept snapshots.
 | 
			
		||||
  Fix open RO->RW promotion.
 | 
			
		||||
  Fix missing vg_revert in lvcreate error path.
 | 
			
		||||
 | 
			
		||||
Version 2.02.00 - 10th November 2005
 | 
			
		||||
====================================
 | 
			
		||||
  Extend allocation areas to avoid overflow with contiguous with other PVs.
 | 
			
		||||
  Stop lvcreate attempting to wipe zero or error segments.
 | 
			
		||||
  Added new lvs table attributes.
 | 
			
		||||
  Separated out activation preload.
 | 
			
		||||
  Moved activation functions into libdevmapper.
 | 
			
		||||
  Fixed build_dm_name.
 | 
			
		||||
  Add return macros.
 | 
			
		||||
  Added xen xvd devices.
 | 
			
		||||
  Clear up precommitted metadata better.
 | 
			
		||||
  A pvresize implementation.
 | 
			
		||||
  Fix contiguous allocation when there are no preceding segments.
 | 
			
		||||
  Add mirror_seg pointer to lv_segment struct.
 | 
			
		||||
  Only keep a device open if it's known to belong to a locked VG.
 | 
			
		||||
  Fix lvdisplay to show all mirror destinations.
 | 
			
		||||
  Replacement suspend code using libdevmapper dependency tree.
 | 
			
		||||
  Add DEFS to make.tmpl.
 | 
			
		||||
  Use dm_is_dm_major instead of local copy.
 | 
			
		||||
  Allow mapped devices to be used as PVs.
 | 
			
		||||
  Move set_selinux_context into libdevmapper.
 | 
			
		||||
  Fix automatic text metadata buffer expansion (using macro).
 | 
			
		||||
  Cache formatted text metadata buffer between metadata area writes.
 | 
			
		||||
  Add pe_start field to pvs.
 | 
			
		||||
  Add 'LVM-' prefix to uuids.
 | 
			
		||||
  Split lv_segment_area from lv_segment to permit extension.
 | 
			
		||||
  Replacement deactivation code using libdevmapper dependency tree.
 | 
			
		||||
  Simplify dev_manager_info().
 | 
			
		||||
  Attempt to load missing targets using modprobe.
 | 
			
		||||
  Add -a to lvscan.
 | 
			
		||||
  Move mknodes into libdevmapper.
 | 
			
		||||
  Move bitset, hash, pool and dbg_malloc into libdevmapper.
 | 
			
		||||
 | 
			
		||||
Version 2.01.15 - 16th October 2005
 | 
			
		||||
===================================
 | 
			
		||||
  Refuse to run pvcreate/pvremove on devices we can't open exclusively.
 | 
			
		||||
  Use ORPHAN lock definition throughout.
 | 
			
		||||
  Validate chunksize in lvcreate.
 | 
			
		||||
  Reduce chunksize limit to 512k.
 | 
			
		||||
  Fix chunksize field in reports.
 | 
			
		||||
  Don't hide snapshots from default 'lvs' output.
 | 
			
		||||
  Add is_dm_major() for use in duplicate device detection in lvmcache_add().
 | 
			
		||||
  Really switch device number in lvmcache when it says it is doing so.
 | 
			
		||||
  Option for bitset memory allocation using malloc as well as pool.
 | 
			
		||||
  Don't assume exactly two mirrors when parsing mirror status.
 | 
			
		||||
  Suppress fsync() error message on filesystems that don't support it.
 | 
			
		||||
  Fix yes_no_prompt() error handling.
 | 
			
		||||
  Add lvm.conf comment warning against multiple filter lines.
 | 
			
		||||
  Tidy lvmconf.sh.
 | 
			
		||||
  Add format1 dev_write debug messages.
 | 
			
		||||
  Add clustered VG attribute to report.
 | 
			
		||||
  Move lvconvert parameters into struct lvconvert_params.
 | 
			
		||||
  Add clustered VG flag to LV lock requests.
 | 
			
		||||
  Change LV locking macros to take lv instead of lvid.
 | 
			
		||||
  Prepend 'cluster' activation parameter to mirror log when appropriate.
 | 
			
		||||
  Pass exclusive flag to lv_activate and on to target activation code.
 | 
			
		||||
  Prevent snapshot creation in a clustered VG for now.
 | 
			
		||||
  Factor out adjusted_mirror_region_size() and generate_log_name_format().
 | 
			
		||||
  Move compose_log_line() into mirror directory.
 | 
			
		||||
  Factor out _get_library_path().
 | 
			
		||||
  Don't kill idling clvmd threads.
 | 
			
		||||
  clvmd no longer takes out locks for non-clustered LVs.
 | 
			
		||||
  Recognise ATA over Ethernet (aoe) devices.
 | 
			
		||||
 | 
			
		||||
Version 2.01.14 - 4th August 2005
 | 
			
		||||
=================================
 | 
			
		||||
  Fix lvconvert PV parameter in help string.
 | 
			
		||||
  Prevent snapshots getting activated in a clustered VG.
 | 
			
		||||
  Separate out _build_dev_string.
 | 
			
		||||
  Move zero_lv to toollib.
 | 
			
		||||
  Fix pool format handler to work with pv segment code.
 | 
			
		||||
 | 
			
		||||
Version 2.01.13 - 13th July 2005
 | 
			
		||||
================================
 | 
			
		||||
  Fix pvmove segment splitting.
 | 
			
		||||
  Abstract vg_validate.
 | 
			
		||||
  Only make one attempt at contiguous allocation.
 | 
			
		||||
  Fix lvm1 format metadata read.
 | 
			
		||||
  Fix lvm1 format non-mirror lvcreate.
 | 
			
		||||
 | 
			
		||||
Version 2.01.12 - 14th June 2005
 | 
			
		||||
================================
 | 
			
		||||
  Various allocation-related pvmove fixes.
 | 
			
		||||
  Log an error if clvmd can't resolve a host name got from CCS.
 | 
			
		||||
  Fix potential spin loop in clvmd.
 | 
			
		||||
 | 
			
		||||
Version 2.01.11 - 13th June 2005
 | 
			
		||||
================================
 | 
			
		||||
  Added lvmconf.sh.
 | 
			
		||||
  Use matchpathcon mode parameter.
 | 
			
		||||
  Don't defer closing dead FDs in clvmd.
 | 
			
		||||
  Remove hard-coded 64k text metadata writing restriction.
 | 
			
		||||
  Make VG name restrictions consistent.
 | 
			
		||||
  Introduce lvconvert.  So far only removes mirror images.
 | 
			
		||||
  Allow mirror images to be resized.
 | 
			
		||||
  Allow mirror images to have more than one segment.
 | 
			
		||||
  Centralise restrictions on LV names.
 | 
			
		||||
  Always insert an intermediate layer for mirrors.
 | 
			
		||||
  Suppress hidden LVs from reports unless --all is given.
 | 
			
		||||
  Use square brackets for hidden LVs in reports.
 | 
			
		||||
  Allow the creation of mirrors with contiguous extents.
 | 
			
		||||
  Always perform sanity checks against metadata before committing it to disk.
 | 
			
		||||
  Split lv_extend into two steps: choosing extents + allocation to LV(s).
 | 
			
		||||
  Add mirror log region size to metadata.
 | 
			
		||||
  Use list_iterate_items throughout and add list*back macros.
 | 
			
		||||
  Introduce seg_ macros to access areas.
 | 
			
		||||
  Add segtype_is_ macros.
 | 
			
		||||
  Support tiny metadata areas for pool conversions.
 | 
			
		||||
  Mirror activation handles disk log as well as core.
 | 
			
		||||
  Activation code recognises mirror log dependency.
 | 
			
		||||
  Add mirror_log and regionsize fields to report.
 | 
			
		||||
  Fix non-orphan pvchange -u.
 | 
			
		||||
  Fix vgmerge to handle duplicate LVIDs.
 | 
			
		||||
  Move archiver code from tools into library.
 | 
			
		||||
  vgscan/change/display/vgs automatically create metadata backups if needed.
 | 
			
		||||
  Merge cloned allocation functions.
 | 
			
		||||
  Fix contiguous allocation policy with linear.
 | 
			
		||||
  Cope with missing format1 PVs again.
 | 
			
		||||
  Remove lists of free PV segments.
 | 
			
		||||
  Simplify pv_maps code and remove slow bitset algorithm.
 | 
			
		||||
  Red-Hat-ify the clvmd rhel4 initscript.
 | 
			
		||||
  %Zu->%zu
 | 
			
		||||
  Fix loopfiles alias alloc & mem debugging.
 | 
			
		||||
  Un-inline dbg_strdup.
 | 
			
		||||
  lv_reduce tidying.
 | 
			
		||||
  Remove some unnecessary parameters.
 | 
			
		||||
  Introduce seg_is macros.
 | 
			
		||||
 | 
			
		||||
Version 2.01.10 - 3rd May 2005
 | 
			
		||||
==============================
 | 
			
		||||
  Don't create backup and archive dirs till needed.
 | 
			
		||||
  Reinstate full PV size when removing from VG.
 | 
			
		||||
  Support loopfiles for testing.
 | 
			
		||||
  Tidy lv_segment interface.
 | 
			
		||||
  pv_segment support.
 | 
			
		||||
  vgchange --physicalextentsize
 | 
			
		||||
  Internal snapshot restructuring.
 | 
			
		||||
  Remove unused internal non-persistent snapshot option.
 | 
			
		||||
  Allow offline extension of snapshot volumes.
 | 
			
		||||
  Move from 2-step to 3-step on-disk metadata commit.
 | 
			
		||||
  Scan ramdisks too and allow non-O_DIRECT fallback.
 | 
			
		||||
  Annotate, tidy and extend list.h.
 | 
			
		||||
  Alignment tidying.
 | 
			
		||||
  Make clvmd work around some "bugs" in gulm's node state notifications.
 | 
			
		||||
  Tidy clvmd's SIGHUP handler
 | 
			
		||||
 | 
			
		||||
Version 2.01.09 - 4th April 2005
 | 
			
		||||
================================
 | 
			
		||||
  Add --ignorelockingfailure to vgmknodes.
 | 
			
		||||
  clvmd: Don't allow user operations to start until the lvm thread is fully up.
 | 
			
		||||
  clvmd-gulm: set KEEPALIVE on sockets.
 | 
			
		||||
 | 
			
		||||
Version 2.01.08 - 22nd March 2005
 | 
			
		||||
=================================
 | 
			
		||||
  Add clustered attribute so vgchange can identify clustered VGs w/o locking.
 | 
			
		||||
  Improve detection of external changes affecting internal cache.
 | 
			
		||||
  Add 'already in device cache' debug message.
 | 
			
		||||
  Add -a to pvdisplay -C.
 | 
			
		||||
  Avoid rmdir opendir error messsages when dir was already removed.
 | 
			
		||||
  Tighten signal handlers.
 | 
			
		||||
  Avoid some compiler warnings.
 | 
			
		||||
  Additional rename failure error message.
 | 
			
		||||
  read/write may be macros.
 | 
			
		||||
  clvmd: don't take out lvm thread lock at startup, it only protects jobs list.
 | 
			
		||||
 | 
			
		||||
Version 2.01.07 - 8th March 2005
 | 
			
		||||
================================
 | 
			
		||||
  Cope with new devices appearing by rescanning /dev if a uuid can't be found.
 | 
			
		||||
  Remove DESTDIR from LVM_SHARED_PATH.
 | 
			
		||||
  clvmd fixes: make FDs close-on-exec
 | 
			
		||||
               gulm unlocks VG & orphan locks at startup in case they are stale
 | 
			
		||||
               gulm now unlocks VG & orphan locks if client dies.
 | 
			
		||||
 | 
			
		||||
Version 2.01.06 - 1st March 2005
 | 
			
		||||
================================
 | 
			
		||||
  Suppress 'open failed' error messages during scanning.
 | 
			
		||||
  Option to suppress warnings of file descriptors left open.
 | 
			
		||||
  Fix default value of metadatacopies in documentation (2->1).
 | 
			
		||||
  Fix clvmd-gulm locking.
 | 
			
		||||
  ./configure --enable-debug now enables debugging code in clvmd.
 | 
			
		||||
  Fix clvmd-gulm node up/down code so it actually works.
 | 
			
		||||
  clvmd-gulm now releases locks when shut down.
 | 
			
		||||
 | 
			
		||||
Version 2.01.05 - 18th February 2005
 | 
			
		||||
====================================
 | 
			
		||||
  Static binary invokes dynamic binary if appropriate.
 | 
			
		||||
  Make clvmd config check a little more tolerant.
 | 
			
		||||
  gulm clvmd can now cope with >1 message arriving in a TCP message.
 | 
			
		||||
 | 
			
		||||
Version 2.01.04 - 9th February 2005
 | 
			
		||||
===================================
 | 
			
		||||
  Add fixed offset to imported pool minor numbers.
 | 
			
		||||
  Update binary pathnames in clvmd_init_rhel4.
 | 
			
		||||
  lvm2cmd.so should skip the check for open fds.
 | 
			
		||||
  Remove unused -f from pvmove.
 | 
			
		||||
  Gulm clvmd doesn't report "connection refused" errors.
 | 
			
		||||
  clvmd does a basic config file sanity check at startup.
 | 
			
		||||
  Fix potential thread shutdown race in clvmd.
 | 
			
		||||
 | 
			
		||||
Version 2.01.03 - 1st February 2005
 | 
			
		||||
===================================
 | 
			
		||||
  More 64-bit display/report fixes.
 | 
			
		||||
  More informative startup mesg if can't create /etc/lvm.
 | 
			
		||||
  Fix snapshot device size bug (since 2.01.01).
 | 
			
		||||
  clvmd announces startup and cluster connection in syslog.
 | 
			
		||||
  Gulm clvmd doesn't hang trying to talk to a rebooted node.
 | 
			
		||||
  Gulm clvmd doesn't print cman error on startup.
 | 
			
		||||
 | 
			
		||||
Version 2.01.02 - 21st January 2005
 | 
			
		||||
===================================
 | 
			
		||||
  Update clvmd_init_rhel4: use lvm.static and don't load dlm.
 | 
			
		||||
  Fix some size_t printing.
 | 
			
		||||
  Fix 64 bit xlate consts.
 | 
			
		||||
  Split out pool sptype_names to avoid unused const.
 | 
			
		||||
  Always fail if random id generation fails.
 | 
			
		||||
  Recognise gnbd devices.
 | 
			
		||||
  Fix clvmd startup bug introduced in cman/gulm amalgamation.
 | 
			
		||||
  Improve reporting of node-specific locking errors.
 | 
			
		||||
 | 
			
		||||
Version 2.01.01 - 19th January 2005
 | 
			
		||||
===================================
 | 
			
		||||
  Fix clvmd lv_info_by_lvid open_count.
 | 
			
		||||
  Store snapshot and origin sizes separately.
 | 
			
		||||
  Update vgcreate man page.
 | 
			
		||||
 | 
			
		||||
Version 2.01.00 - 17th January 2005
 | 
			
		||||
===================================
 | 
			
		||||
  Fix vgscan metadata auto-correction.
 | 
			
		||||
  Only ask libdevmapper for open_count when we need it.
 | 
			
		||||
  Adjust RHEL4 clvmd init script priority.
 | 
			
		||||
  Enable building of CMAN & GULM versions of clvmd into a single binary
 | 
			
		||||
 | 
			
		||||
Version 2.00.33 - 7th January 2005
 | 
			
		||||
==================================
 | 
			
		||||
  pvcreate wipes first 4 sectors unless given --zero n.
 | 
			
		||||
  gulm clvmd now uses new ccsd key names.
 | 
			
		||||
  gulm clvmd now doesn't ignore the first node in cluster.conf
 | 
			
		||||
  Improve clvmd failure message if it's already running.
 | 
			
		||||
  Allow user to kill clvmd during initialisation.
 | 
			
		||||
  Fix off-by-one error in cluster_locking that could cause read hangs.
 | 
			
		||||
 | 
			
		||||
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:
 | 
			
		||||
  Backwards compatibility with LVM1 metadata improved.
 | 
			
		||||
  Missing man pages written.
 | 
			
		||||
  Tool error codes made more consistent.
 | 
			
		||||
  vgmknodes written.
 | 
			
		||||
  O_DIRECT can be turned off if it doesn't work in your kernel.
 | 
			
		||||
  dumpconfig to display the active configuration file
 | 
			
		||||
 | 
			
		||||
You need to update libdevmapper before using 'vgmknodes' or 'vgscan --mknodes'.
 | 
			
		||||
If your root filesystem is on an LV, you should run one of those two
 | 
			
		||||
commands to fix up the special files in /dev in your real root filesystem 
 | 
			
		||||
after finishing with your initrd.  Also, remember you can use
 | 
			
		||||
'vgchange --ignorelockingfailure' on your initrd if the tool fails because
 | 
			
		||||
it can't write a lock file to a read-only filesystem.
 | 
			
		||||
 | 
			
		||||
Wednesday 30th April 2003
 | 
			
		||||
=========================
 | 
			
		||||
A pvmove implementation is now available for the new metadata format.
 | 
			
		||||
@@ -25,6 +662,7 @@ to provide us with diagnostic information:
 | 
			
		||||
  log {
 | 
			
		||||
        file="/tmp/lvm2.log"
 | 
			
		||||
	level=7
 | 
			
		||||
	activation=1
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
You should schedule regular backups of your configuration file and
 | 
			
		||||
@@ -74,7 +712,7 @@ changes.
 | 
			
		||||
What's not finished?
 | 
			
		||||
====================
 | 
			
		||||
The internal cache.  If you turn on debugging output you'll see lots of
 | 
			
		||||
repeated disk reads, many of which will eventually get optimised out.
 | 
			
		||||
repeated messages, many of which will eventually get optimised out.
 | 
			
		||||
 | 
			
		||||
--test sometimes causes a command to fail (e.g. vgconvert --test) even 
 | 
			
		||||
though the real command would work: again, fixing this is waiting for 
 | 
			
		||||
@@ -91,6 +729,3 @@ Display output.  Some metadata information cannot yet be displayed.
 | 
			
		||||
Recovery tools to salvage "lost" metadata directly from the disks:
 | 
			
		||||
but we hope the new format will mean such tools are hardly ever needed!
 | 
			
		||||
 | 
			
		||||
pvmove will be enhanced to remove the volume group lock so that you can
 | 
			
		||||
run other commands alongside.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										208
									
								
								WHATS_NEW_DM
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								WHATS_NEW_DM
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,208 @@
 | 
			
		||||
Version 1.02.10 - 
 | 
			
		||||
==============================
 | 
			
		||||
 | 
			
		||||
Version 1.02.09 - 15 Aug 2006
 | 
			
		||||
==============================
 | 
			
		||||
  Add --table argument to dmsetup for a one-line table.
 | 
			
		||||
  Abort if errors are found during cmdline option processing.
 | 
			
		||||
  Add lockfs indicator to debug output.
 | 
			
		||||
 | 
			
		||||
Version 1.02.08 - 17 July 2006
 | 
			
		||||
==============================
 | 
			
		||||
  Append full patch to check in emails.
 | 
			
		||||
  Avoid duplicate dmeventd subdir with 'make distclean'.
 | 
			
		||||
  Update dmsetup man page.
 | 
			
		||||
  Add --force to dmsetup remove* to load error target.
 | 
			
		||||
  dmsetup remove_all also performs mknodes.
 | 
			
		||||
  Don't suppress identical table reloads if permission changes.
 | 
			
		||||
  Fix corelog segment line.
 | 
			
		||||
  Suppress some compiler warnings.
 | 
			
		||||
 | 
			
		||||
Version 1.02.07 - 11 May 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
 | 
			
		||||
  Avoid a dmeventd compiler warning.
 | 
			
		||||
 | 
			
		||||
Version 1.02.06 - 10 May 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Move DEFS into configure.h.
 | 
			
		||||
  Fix leaks in error paths found by coverity.
 | 
			
		||||
  Remove dmsetup line buffer limitation.
 | 
			
		||||
 | 
			
		||||
Version 1.02.05 - 19 Apr 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Separate install_include target in makefiles.
 | 
			
		||||
  Separate out DEFS from CFLAGS.
 | 
			
		||||
  Support pkg-config.
 | 
			
		||||
  Check for libsepol.
 | 
			
		||||
 | 
			
		||||
Version 1.02.04 - 14 Apr 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Bring dmsetup man page up-to-date.
 | 
			
		||||
  Use name-based device refs if kernel doesn't support device number refs.
 | 
			
		||||
  Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
 | 
			
		||||
  If _create_and_load_v4 fails part way through, revert the creation.
 | 
			
		||||
  dmeventd thread/fifo fixes.
 | 
			
		||||
  Add file & line to dm_strdup_aux().
 | 
			
		||||
  Add setgeometry.
 | 
			
		||||
 | 
			
		||||
Version 1.02.03 - 7 Feb 2006
 | 
			
		||||
============================
 | 
			
		||||
  Add exported functions to set uid, gid and mode.
 | 
			
		||||
  Rename _log to dm_log and export.
 | 
			
		||||
  Add dm_tree_skip_lockfs.
 | 
			
		||||
  Fix dm_strdup debug definition.
 | 
			
		||||
  Fix hash function to avoid using a negative array offset.
 | 
			
		||||
  Don't inline _find in hash.c and tidy signed/unsigned etc.
 | 
			
		||||
  Fix libdevmapper.h #endif.
 | 
			
		||||
  Fix dmsetup version driver version.
 | 
			
		||||
  Add sync, nosync and block_on_error mirror log parameters.
 | 
			
		||||
  Add hweight32.
 | 
			
		||||
  Fix dmeventd build.
 | 
			
		||||
 | 
			
		||||
Version 1.02.02 - 2 Dec 2005
 | 
			
		||||
============================
 | 
			
		||||
  dmeventd added.
 | 
			
		||||
  Export dm_task_update_nodes.
 | 
			
		||||
  Use names instead of numbers in messages when ioctls fail.
 | 
			
		||||
 | 
			
		||||
Version 1.02.01 - 23 Nov 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Resume snapshot-origins last.
 | 
			
		||||
  Drop leading zeros from dm_format_dev.
 | 
			
		||||
  Suppress attempt to reload identical table.
 | 
			
		||||
  Additional LVM- prefix matching for transitional period.
 | 
			
		||||
 | 
			
		||||
Version 1.02.00 - 10 Nov 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Added activation functions to library.
 | 
			
		||||
  Added return macros.
 | 
			
		||||
  Also suppress error if device doesn't exist with DM_DEVICE_STATUS.
 | 
			
		||||
  Export dm_set_selinux_context().
 | 
			
		||||
  Add dm_driver_version().
 | 
			
		||||
  Added dependency tree functions to library.
 | 
			
		||||
  Added hash, bitset, pool, dbg_malloc to library.
 | 
			
		||||
  Added ls --tree to dmsetup.
 | 
			
		||||
  Added dmsetup --nolockfs support for suspend/reload.
 | 
			
		||||
 | 
			
		||||
Version 1.01.05 - 26 Sep 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Resync list.h with LVM2.
 | 
			
		||||
  Remember increased buffer size and use for subsequent calls.
 | 
			
		||||
  On 'buffer full' condition, double buffer size and repeat ioctl.
 | 
			
		||||
  Fix termination of getopt_long() option array.
 | 
			
		||||
  Report 'buffer full' condition with v4 ioctl as well as with v1.
 | 
			
		||||
 | 
			
		||||
Version 1.01.04 - 2 Aug 2005
 | 
			
		||||
============================
 | 
			
		||||
  Fix dmsetup ls -j and status --target with empty table.
 | 
			
		||||
 | 
			
		||||
Version 1.01.03 - 13 Jun 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Use matchpathcon mode parameter.
 | 
			
		||||
  Fix configure script to re-enable selinux.
 | 
			
		||||
 | 
			
		||||
Version 1.01.02 - 17 May 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Call dm_lib_exit() and dm_lib_release() automatically now.
 | 
			
		||||
  Add --target <target_type> filter to dmsetup table/status/ls.
 | 
			
		||||
  Add --exec <command> to dmsetup ls.
 | 
			
		||||
  Fix dmsetup getopt_long usage.
 | 
			
		||||
 | 
			
		||||
Version 1.01.01 - 29 Mar 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Update dmsetup man page.
 | 
			
		||||
  Drop-in devmap_name replacement.
 | 
			
		||||
  Add option to compile without ioctl for testing.
 | 
			
		||||
  Fix DM_LIB_VERSION sed.
 | 
			
		||||
 | 
			
		||||
Version 1.01.00 - 17 Jan 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Add dm_task_no_open_count() to skip getting open_count.
 | 
			
		||||
 | 
			
		||||
Version 1.00.21 - 7 Jan 2005
 | 
			
		||||
============================
 | 
			
		||||
  Fix /proc/devices parsing.
 | 
			
		||||
 | 
			
		||||
Version 1.00.20 - 6 Jan 2005
 | 
			
		||||
============================
 | 
			
		||||
  Attempt to fix /dev/mapper/control transparently if it's wrong.
 | 
			
		||||
  Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
 | 
			
		||||
  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.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										537
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										537
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,9 @@
 | 
			
		||||
#! /bin/sh
 | 
			
		||||
# Attempt to guess a canonical system name.
 | 
			
		||||
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
 | 
			
		||||
#   Free Software Foundation, Inc.
 | 
			
		||||
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 | 
			
		||||
#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 | 
			
		||||
 | 
			
		||||
timestamp='2001-09-04'
 | 
			
		||||
timestamp='2003-06-17'
 | 
			
		||||
 | 
			
		||||
# This file is free software; you can redistribute it and/or modify it
 | 
			
		||||
# under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -24,8 +24,9 @@ timestamp='2001-09-04'
 | 
			
		||||
# configuration script generated by Autoconf, you may include it under
 | 
			
		||||
# the same distribution terms that you use for the rest of that program.
 | 
			
		||||
 | 
			
		||||
# Written by Per Bothner <bothner@cygnus.com>.
 | 
			
		||||
# Please send patches to <config-patches@gnu.org>.
 | 
			
		||||
# Originally written by Per Bothner <per@bothner.com>.
 | 
			
		||||
# Please send patches to <config-patches@gnu.org>.  Submit a context
 | 
			
		||||
# diff and a properly formatted ChangeLog entry.
 | 
			
		||||
#
 | 
			
		||||
# This script attempts to guess a canonical system name similar to
 | 
			
		||||
# config.sub.  If it succeeds, it prints the system name on stdout, and
 | 
			
		||||
@@ -87,30 +88,42 @@ if test $# != 0; then
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
trap 'exit 1' 1 2 15
 | 
			
		||||
 | 
			
		||||
dummy=dummy-$$
 | 
			
		||||
trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
 | 
			
		||||
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
 | 
			
		||||
# compiler to aid in system detection is discouraged as it requires
 | 
			
		||||
# temporary files to be created and, as you can see below, it is a
 | 
			
		||||
# headache to deal with in a portable fashion.
 | 
			
		||||
 | 
			
		||||
# CC_FOR_BUILD -- compiler used by this script.
 | 
			
		||||
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
 | 
			
		||||
# use `HOST_CC' if defined, but it is deprecated.
 | 
			
		||||
 | 
			
		||||
set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
 | 
			
		||||
 ,,)    echo "int dummy(){}" > $dummy.c ;
 | 
			
		||||
	for c in cc gcc c89 ; do
 | 
			
		||||
	  ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
 | 
			
		||||
	  if test $? = 0 ; then
 | 
			
		||||
# Portable tmp directory creation inspired by the Autoconf team.
 | 
			
		||||
 | 
			
		||||
set_cc_for_build='
 | 
			
		||||
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
 | 
			
		||||
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
 | 
			
		||||
: ${TMPDIR=/tmp} ;
 | 
			
		||||
 { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
 | 
			
		||||
 { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
 | 
			
		||||
 { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
 | 
			
		||||
 { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
 | 
			
		||||
dummy=$tmp/dummy ;
 | 
			
		||||
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
 | 
			
		||||
case $CC_FOR_BUILD,$HOST_CC,$CC in
 | 
			
		||||
 ,,)    echo "int x;" > $dummy.c ;
 | 
			
		||||
	for c in cc gcc c89 c99 ; do
 | 
			
		||||
	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
 | 
			
		||||
	     CC_FOR_BUILD="$c"; break ;
 | 
			
		||||
	  fi ;
 | 
			
		||||
	done ;
 | 
			
		||||
	rm -f $dummy.c $dummy.o $dummy.rel ;
 | 
			
		||||
	if test x"$CC_FOR_BUILD" = x ; then
 | 
			
		||||
	  CC_FOR_BUILD=no_compiler_found ;
 | 
			
		||||
	fi
 | 
			
		||||
	;;
 | 
			
		||||
 ,,*)   CC_FOR_BUILD=$CC ;;
 | 
			
		||||
 ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
 | 
			
		||||
esac'
 | 
			
		||||
esac ;'
 | 
			
		||||
 | 
			
		||||
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
 | 
			
		||||
# (ghazi@noc.rutgers.edu 1994-08-24)
 | 
			
		||||
@@ -127,29 +140,30 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 | 
			
		||||
 | 
			
		||||
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 | 
			
		||||
    *:NetBSD:*:*)
 | 
			
		||||
	# Netbsd (nbsd) targets should (where applicable) match one or
 | 
			
		||||
	# NetBSD (nbsd) targets should (where applicable) match one or
 | 
			
		||||
	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
 | 
			
		||||
	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
 | 
			
		||||
	# switched to ELF, *-*-netbsd* would select the old
 | 
			
		||||
	# object file format.  This provides both forward
 | 
			
		||||
	# compatibility and a consistent mechanism for selecting the
 | 
			
		||||
	# object file format.
 | 
			
		||||
	# Determine the machine/vendor (is the vendor relevant).
 | 
			
		||||
	case "${UNAME_MACHINE}" in
 | 
			
		||||
	    amiga) machine=m68k-unknown ;;
 | 
			
		||||
	    arm32) machine=arm-unknown ;;
 | 
			
		||||
	    atari*) machine=m68k-atari ;;
 | 
			
		||||
	    sun3*) machine=m68k-sun ;;
 | 
			
		||||
	    mac68k) machine=m68k-apple ;;
 | 
			
		||||
	    macppc) machine=powerpc-apple ;;
 | 
			
		||||
	    hp3[0-9][05]) machine=m68k-hp ;;
 | 
			
		||||
	    ibmrt|romp-ibm) machine=romp-ibm ;;
 | 
			
		||||
	    *) machine=${UNAME_MACHINE}-unknown ;;
 | 
			
		||||
	#
 | 
			
		||||
	# Note: NetBSD doesn't particularly care about the vendor
 | 
			
		||||
	# portion of the name.  We always set it to "unknown".
 | 
			
		||||
	sysctl="sysctl -n hw.machine_arch"
 | 
			
		||||
	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
 | 
			
		||||
	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
 | 
			
		||||
	case "${UNAME_MACHINE_ARCH}" in
 | 
			
		||||
	    armeb) machine=armeb-unknown ;;
 | 
			
		||||
	    arm*) machine=arm-unknown ;;
 | 
			
		||||
	    sh3el) machine=shl-unknown ;;
 | 
			
		||||
	    sh3eb) machine=sh-unknown ;;
 | 
			
		||||
	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 | 
			
		||||
	esac
 | 
			
		||||
	# The Operating System including object format, if it has switched
 | 
			
		||||
	# to ELF recently, or will in the future.
 | 
			
		||||
	case "${UNAME_MACHINE}" in
 | 
			
		||||
	    i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
 | 
			
		||||
	case "${UNAME_MACHINE_ARCH}" in
 | 
			
		||||
	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
 | 
			
		||||
		eval $set_cc_for_build
 | 
			
		||||
		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
 | 
			
		||||
			| grep __ELF__ >/dev/null
 | 
			
		||||
@@ -166,75 +180,112 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 | 
			
		||||
		;;
 | 
			
		||||
	esac
 | 
			
		||||
	# The OS release
 | 
			
		||||
	release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
 | 
			
		||||
	# Debian GNU/NetBSD machines have a different userland, and
 | 
			
		||||
	# thus, need a distinct triplet. However, they do not need
 | 
			
		||||
	# kernel version information, so it can be replaced with a
 | 
			
		||||
	# suitable tag, in the style of linux-gnu.
 | 
			
		||||
	case "${UNAME_VERSION}" in
 | 
			
		||||
	    Debian*)
 | 
			
		||||
		release='-gnu'
 | 
			
		||||
		;;
 | 
			
		||||
	    *)
 | 
			
		||||
		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
 | 
			
		||||
		;;
 | 
			
		||||
	esac
 | 
			
		||||
	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
 | 
			
		||||
	# contains redundant information, the shorter form:
 | 
			
		||||
	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
 | 
			
		||||
	echo "${machine}-${os}${release}"
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    amiga:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    arc:OpenBSD:*:*)
 | 
			
		||||
	echo mipsel-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    hp300:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mac68k:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    macppc:OpenBSD:*:*)
 | 
			
		||||
	echo powerpc-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mvme68k:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mvme88k:OpenBSD:*:*)
 | 
			
		||||
	echo m88k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mvmeppc:OpenBSD:*:*)
 | 
			
		||||
	echo powerpc-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    pmax:OpenBSD:*:*)
 | 
			
		||||
	echo mipsel-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    sgi:OpenBSD:*:*)
 | 
			
		||||
	echo mipseb-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    sun3:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    wgrisc:OpenBSD:*:*)
 | 
			
		||||
	echo mipsel-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:OpenBSD:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    alpha:OSF1:*:*)
 | 
			
		||||
	if test $UNAME_RELEASE = "V4.0"; then
 | 
			
		||||
		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
 | 
			
		||||
	fi
 | 
			
		||||
	# According to Compaq, /usr/sbin/psrinfo has been available on
 | 
			
		||||
	# OSF/1 and Tru64 systems produced since 1995.  I hope that
 | 
			
		||||
	# covers most systems running today.  This code pipes the CPU
 | 
			
		||||
	# types through head -n 1, so we only detect the type of CPU 0.
 | 
			
		||||
	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
 | 
			
		||||
	case "$ALPHA_CPU_TYPE" in
 | 
			
		||||
	    "EV4 (21064)")
 | 
			
		||||
		UNAME_MACHINE="alpha" ;;
 | 
			
		||||
	    "EV4.5 (21064)")
 | 
			
		||||
		UNAME_MACHINE="alpha" ;;
 | 
			
		||||
	    "LCA4 (21066/21068)")
 | 
			
		||||
		UNAME_MACHINE="alpha" ;;
 | 
			
		||||
	    "EV5 (21164)")
 | 
			
		||||
		UNAME_MACHINE="alphaev5" ;;
 | 
			
		||||
	    "EV5.6 (21164A)")
 | 
			
		||||
		UNAME_MACHINE="alphaev56" ;;
 | 
			
		||||
	    "EV5.6 (21164PC)")
 | 
			
		||||
		UNAME_MACHINE="alphapca56" ;;
 | 
			
		||||
	    "EV5.7 (21164PC)")
 | 
			
		||||
		UNAME_MACHINE="alphapca57" ;;
 | 
			
		||||
	    "EV6 (21264)")
 | 
			
		||||
		UNAME_MACHINE="alphaev6" ;;
 | 
			
		||||
	    "EV6.7 (21264A)")
 | 
			
		||||
		UNAME_MACHINE="alphaev67" ;;
 | 
			
		||||
	    "EV6.8CB (21264C)")
 | 
			
		||||
		UNAME_MACHINE="alphaev68" ;;
 | 
			
		||||
	    "EV6.8AL (21264B)")
 | 
			
		||||
		UNAME_MACHINE="alphaev68" ;;
 | 
			
		||||
	    "EV6.8CX (21264D)")
 | 
			
		||||
		UNAME_MACHINE="alphaev68" ;;
 | 
			
		||||
	    "EV6.9A (21264/EV69A)")
 | 
			
		||||
		UNAME_MACHINE="alphaev69" ;;
 | 
			
		||||
	    "EV7 (21364)")
 | 
			
		||||
		UNAME_MACHINE="alphaev7" ;;
 | 
			
		||||
	    "EV7.9 (21364A)")
 | 
			
		||||
		UNAME_MACHINE="alphaev79" ;;
 | 
			
		||||
	esac
 | 
			
		||||
	# A Vn.n version is a released version.
 | 
			
		||||
	# A Tn.n version is a released field test version.
 | 
			
		||||
	# A Xn.n version is an unreleased experimental baselevel.
 | 
			
		||||
	# 1.2 uses "1.2" for uname -r.
 | 
			
		||||
	cat <<EOF >$dummy.s
 | 
			
		||||
	.data
 | 
			
		||||
\$Lformat:
 | 
			
		||||
	.byte 37,100,45,37,120,10,0	# "%d-%x\n"
 | 
			
		||||
 | 
			
		||||
	.text
 | 
			
		||||
	.globl main
 | 
			
		||||
	.align 4
 | 
			
		||||
	.ent main
 | 
			
		||||
main:
 | 
			
		||||
	.frame \$30,16,\$26,0
 | 
			
		||||
	ldgp \$29,0(\$27)
 | 
			
		||||
	.prologue 1
 | 
			
		||||
	.long 0x47e03d80 # implver \$0
 | 
			
		||||
	lda \$2,-1
 | 
			
		||||
	.long 0x47e20c21 # amask \$2,\$1
 | 
			
		||||
	lda \$16,\$Lformat
 | 
			
		||||
	mov \$0,\$17
 | 
			
		||||
	not \$1,\$18
 | 
			
		||||
	jsr \$26,printf
 | 
			
		||||
	ldgp \$29,0(\$26)
 | 
			
		||||
	mov 0,\$16
 | 
			
		||||
	jsr \$26,exit
 | 
			
		||||
	.end main
 | 
			
		||||
EOF
 | 
			
		||||
	eval $set_cc_for_build
 | 
			
		||||
	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
 | 
			
		||||
	if test "$?" = 0 ; then
 | 
			
		||||
		case `./$dummy` in
 | 
			
		||||
			0-0)
 | 
			
		||||
				UNAME_MACHINE="alpha"
 | 
			
		||||
				;;
 | 
			
		||||
			1-0)
 | 
			
		||||
				UNAME_MACHINE="alphaev5"
 | 
			
		||||
				;;
 | 
			
		||||
			1-1)
 | 
			
		||||
				UNAME_MACHINE="alphaev56"
 | 
			
		||||
				;;
 | 
			
		||||
			1-101)
 | 
			
		||||
				UNAME_MACHINE="alphapca56"
 | 
			
		||||
				;;
 | 
			
		||||
			2-303)
 | 
			
		||||
				UNAME_MACHINE="alphaev6"
 | 
			
		||||
				;;
 | 
			
		||||
			2-307)
 | 
			
		||||
				UNAME_MACHINE="alphaev67"
 | 
			
		||||
				;;
 | 
			
		||||
			2-1307)
 | 
			
		||||
				UNAME_MACHINE="alphaev68"
 | 
			
		||||
				;;
 | 
			
		||||
		esac
 | 
			
		||||
	fi
 | 
			
		||||
	rm -f $dummy.s $dummy
 | 
			
		||||
	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    Alpha*:OpenVMS:*:*)
 | 
			
		||||
	echo alpha-hp-vms
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    Alpha\ *:Windows_NT*:*)
 | 
			
		||||
	# How do we know it's Interix rather than the generic POSIX subsystem?
 | 
			
		||||
	# Should we change UNAME_MACHINE based on the output of uname instead
 | 
			
		||||
@@ -247,29 +298,11 @@ EOF
 | 
			
		||||
    Amiga*:UNIX_System_V:4.0:*)
 | 
			
		||||
	echo m68k-unknown-sysv4
 | 
			
		||||
	exit 0;;
 | 
			
		||||
    amiga:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:[Aa]miga[Oo][Ss]:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-amigaos
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    arc64:OpenBSD:*:*)
 | 
			
		||||
	echo mips64el-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    arc:OpenBSD:*:*)
 | 
			
		||||
	echo mipsel-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    hkmips:OpenBSD:*:*)
 | 
			
		||||
	echo mips-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    pmax:OpenBSD:*:*)
 | 
			
		||||
	echo mipsel-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    sgi:OpenBSD:*:*)
 | 
			
		||||
	echo mips-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    wgrisc:OpenBSD:*:*)
 | 
			
		||||
	echo mipsel-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
    *:[Mm]orph[Oo][Ss]:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-morphos
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:OS/390:*:*)
 | 
			
		||||
	echo i370-ibm-openedition
 | 
			
		||||
@@ -291,6 +324,13 @@ EOF
 | 
			
		||||
    NILE*:*:*:dcosx)
 | 
			
		||||
	echo pyramid-pyramid-svr4
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    DRS?6000:unix:4.0:6*)
 | 
			
		||||
	echo sparc-icl-nx6
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    DRS?6000:UNIX_SV:4.2*:7*)
 | 
			
		||||
	case `/usr/bin/uname -p` in
 | 
			
		||||
	    sparc) echo sparc-icl-nx7 && exit 0 ;;
 | 
			
		||||
	esac ;;
 | 
			
		||||
    sun4H:SunOS:5.*:*)
 | 
			
		||||
	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -319,7 +359,7 @@ EOF
 | 
			
		||||
	echo m68k-sun-sunos${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    sun*:*:4.2BSD:*)
 | 
			
		||||
	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
 | 
			
		||||
	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
 | 
			
		||||
	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
 | 
			
		||||
	case "`/bin/arch`" in
 | 
			
		||||
	    sun3)
 | 
			
		||||
@@ -333,12 +373,6 @@ EOF
 | 
			
		||||
    aushp:SunOS:*:*)
 | 
			
		||||
	echo sparc-auspex-sunos${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    sparc*:NetBSD:*)
 | 
			
		||||
	echo `uname -p`-unknown-netbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    atari*:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    # The situation for MiNT is a little confusing.  The machine name
 | 
			
		||||
    # can be virtually everything (everything which is not
 | 
			
		||||
    # "atarist" or "atariste" at least should have a processor
 | 
			
		||||
@@ -365,18 +399,6 @@ EOF
 | 
			
		||||
    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
 | 
			
		||||
        echo m68k-unknown-mint${UNAME_RELEASE}
 | 
			
		||||
        exit 0 ;;
 | 
			
		||||
    sun3*:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mac68k:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mvme68k:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mvme88k:OpenBSD:*:*)
 | 
			
		||||
	echo m88k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    powerpc:machten:*:*)
 | 
			
		||||
	echo powerpc-apple-machten${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -415,15 +437,20 @@ EOF
 | 
			
		||||
	  exit (-1);
 | 
			
		||||
	}
 | 
			
		||||
EOF
 | 
			
		||||
	$CC_FOR_BUILD $dummy.c -o $dummy \
 | 
			
		||||
	  && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
 | 
			
		||||
	  && rm -f $dummy.c $dummy && exit 0
 | 
			
		||||
	rm -f $dummy.c $dummy
 | 
			
		||||
	$CC_FOR_BUILD -o $dummy $dummy.c \
 | 
			
		||||
	  && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
 | 
			
		||||
	  && exit 0
 | 
			
		||||
	echo mips-mips-riscos${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    Motorola:PowerMAX_OS:*:*)
 | 
			
		||||
	echo powerpc-motorola-powermax
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    Motorola:*:4.3:PL8-*)
 | 
			
		||||
	echo powerpc-harris-powermax
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
 | 
			
		||||
	echo powerpc-harris-powermax
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    Night_Hawk:Power_UNIX:*:*)
 | 
			
		||||
	echo powerpc-harris-powerunix
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -496,8 +523,7 @@ EOF
 | 
			
		||||
			exit(0);
 | 
			
		||||
			}
 | 
			
		||||
EOF
 | 
			
		||||
		$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
 | 
			
		||||
		rm -f $dummy.c $dummy
 | 
			
		||||
		$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
 | 
			
		||||
		echo rs6000-ibm-aix3.2.5
 | 
			
		||||
	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
 | 
			
		||||
		echo rs6000-ibm-aix3.2.4
 | 
			
		||||
@@ -506,7 +532,7 @@ EOF
 | 
			
		||||
	fi
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:AIX:*:[45])
 | 
			
		||||
	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
 | 
			
		||||
	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
 | 
			
		||||
	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
 | 
			
		||||
		IBM_ARCH=rs6000
 | 
			
		||||
	else
 | 
			
		||||
@@ -546,10 +572,8 @@ EOF
 | 
			
		||||
	    9000/31? )            HP_ARCH=m68000 ;;
 | 
			
		||||
	    9000/[34]?? )         HP_ARCH=m68k ;;
 | 
			
		||||
	    9000/[678][0-9][0-9])
 | 
			
		||||
              case "${HPUX_REV}" in
 | 
			
		||||
                11.[0-9][0-9])
 | 
			
		||||
                  if [ -x /usr/bin/getconf ]; then
 | 
			
		||||
                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
 | 
			
		||||
		if [ -x /usr/bin/getconf ]; then
 | 
			
		||||
		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
 | 
			
		||||
                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
 | 
			
		||||
                    case "${sc_cpu_version}" in
 | 
			
		||||
                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
 | 
			
		||||
@@ -558,13 +582,13 @@ EOF
 | 
			
		||||
                        case "${sc_kernel_bits}" in
 | 
			
		||||
                          32) HP_ARCH="hppa2.0n" ;;
 | 
			
		||||
                          64) HP_ARCH="hppa2.0w" ;;
 | 
			
		||||
			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
 | 
			
		||||
                        esac ;;
 | 
			
		||||
                    esac
 | 
			
		||||
                  fi ;;
 | 
			
		||||
              esac
 | 
			
		||||
              if [ "${HP_ARCH}" = "" ]; then
 | 
			
		||||
	      eval $set_cc_for_build
 | 
			
		||||
              sed 's/^              //' << EOF >$dummy.c
 | 
			
		||||
		fi
 | 
			
		||||
		if [ "${HP_ARCH}" = "" ]; then
 | 
			
		||||
		    eval $set_cc_for_build
 | 
			
		||||
		    sed 's/^              //' << EOF >$dummy.c
 | 
			
		||||
 | 
			
		||||
              #define _HPUX_SOURCE
 | 
			
		||||
              #include <stdlib.h>
 | 
			
		||||
@@ -597,11 +621,21 @@ EOF
 | 
			
		||||
                  exit (0);
 | 
			
		||||
              }
 | 
			
		||||
EOF
 | 
			
		||||
	    (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
 | 
			
		||||
	    if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
 | 
			
		||||
	    rm -f $dummy.c $dummy
 | 
			
		||||
	fi ;;
 | 
			
		||||
		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
 | 
			
		||||
		    test -z "$HP_ARCH" && HP_ARCH=hppa
 | 
			
		||||
		fi ;;
 | 
			
		||||
	esac
 | 
			
		||||
	if [ ${HP_ARCH} = "hppa2.0w" ]
 | 
			
		||||
	then
 | 
			
		||||
	    # avoid double evaluation of $set_cc_for_build
 | 
			
		||||
	    test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
 | 
			
		||||
	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
 | 
			
		||||
	    then
 | 
			
		||||
		HP_ARCH="hppa2.0w"
 | 
			
		||||
	    else
 | 
			
		||||
		HP_ARCH="hppa64"
 | 
			
		||||
	    fi
 | 
			
		||||
	fi
 | 
			
		||||
	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    ia64:HP-UX:*:*)
 | 
			
		||||
@@ -635,8 +669,7 @@ EOF
 | 
			
		||||
	  exit (0);
 | 
			
		||||
	}
 | 
			
		||||
EOF
 | 
			
		||||
	$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
 | 
			
		||||
	rm -f $dummy.c $dummy
 | 
			
		||||
	$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
 | 
			
		||||
	echo unknown-hitachi-hiuxwe2
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
 | 
			
		||||
@@ -664,9 +697,6 @@ EOF
 | 
			
		||||
    parisc*:Lites*:*:*)
 | 
			
		||||
	echo hppa1.1-hp-lites
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    hppa*:OpenBSD:*:*)
 | 
			
		||||
	echo hppa-unknown-openbsd
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
 | 
			
		||||
	echo c1-convex-bsd
 | 
			
		||||
        exit 0 ;;
 | 
			
		||||
@@ -685,9 +715,6 @@ EOF
 | 
			
		||||
    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
 | 
			
		||||
	echo c4-convex-bsd
 | 
			
		||||
        exit 0 ;;
 | 
			
		||||
    CRAY*X-MP:*:*:*)
 | 
			
		||||
	echo xmp-cray-unicos
 | 
			
		||||
        exit 0 ;;
 | 
			
		||||
    CRAY*Y-MP:*:*:*)
 | 
			
		||||
	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -700,27 +727,21 @@ EOF
 | 
			
		||||
    CRAY*TS:*:*:*)
 | 
			
		||||
	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    CRAY*T3D:*:*:*)
 | 
			
		||||
	echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    CRAY*T3E:*:*:*)
 | 
			
		||||
	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    CRAY*SV1:*:*:*)
 | 
			
		||||
	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    CRAY-2:*:*:*)
 | 
			
		||||
	echo cray2-cray-unicos
 | 
			
		||||
        exit 0 ;;
 | 
			
		||||
    *:UNICOS/mp:*:*)
 | 
			
		||||
	echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 | 
			
		||||
	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
 | 
			
		||||
        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
 | 
			
		||||
        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
 | 
			
		||||
        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 | 
			
		||||
        exit 0 ;;
 | 
			
		||||
    hp300:OpenBSD:*:*)
 | 
			
		||||
	echo m68k-unknown-openbsd${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -730,11 +751,19 @@ EOF
 | 
			
		||||
    *:BSD/OS:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:FreeBSD:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:OpenBSD:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
 | 
			
		||||
    *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
 | 
			
		||||
	# Determine whether the default compiler uses glibc.
 | 
			
		||||
	eval $set_cc_for_build
 | 
			
		||||
	sed 's/^	//' << EOF >$dummy.c
 | 
			
		||||
	#include <features.h>
 | 
			
		||||
	#if __GLIBC__ >= 2
 | 
			
		||||
	LIBC=gnu
 | 
			
		||||
	#else
 | 
			
		||||
	LIBC=
 | 
			
		||||
	#endif
 | 
			
		||||
EOF
 | 
			
		||||
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*:CYGWIN*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-cygwin
 | 
			
		||||
@@ -745,11 +774,17 @@ EOF
 | 
			
		||||
    i*:PW*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-pw32
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    x86:Interix*:[34]*)
 | 
			
		||||
	echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
 | 
			
		||||
	echo i${UNAME_MACHINE}-pc-mks
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
 | 
			
		||||
	# How do we know it's Interix rather than the generic POSIX subsystem?
 | 
			
		||||
	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
 | 
			
		||||
	# UNAME_MACHINE based on the output of uname instead of i386?
 | 
			
		||||
	echo i386-pc-interix
 | 
			
		||||
	echo i586-pc-interix
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*:UWIN*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-uwin
 | 
			
		||||
@@ -769,17 +804,52 @@ EOF
 | 
			
		||||
    arm*:Linux:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-linux-gnu
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    cris:Linux:*:*)
 | 
			
		||||
	echo cris-axis-linux-gnu
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    ia64:Linux:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-linux
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-linux-gnu
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    m68*:Linux:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-linux-gnu
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mips:Linux:*:*)
 | 
			
		||||
	case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
 | 
			
		||||
	  big)    echo mips-unknown-linux-gnu && exit 0 ;;
 | 
			
		||||
	  little) echo mipsel-unknown-linux-gnu && exit 0 ;;
 | 
			
		||||
	esac
 | 
			
		||||
	eval $set_cc_for_build
 | 
			
		||||
	sed 's/^	//' << EOF >$dummy.c
 | 
			
		||||
	#undef CPU
 | 
			
		||||
	#undef mips
 | 
			
		||||
	#undef mipsel
 | 
			
		||||
	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
 | 
			
		||||
	CPU=mipsel
 | 
			
		||||
	#else
 | 
			
		||||
	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
 | 
			
		||||
	CPU=mips
 | 
			
		||||
	#else
 | 
			
		||||
	CPU=
 | 
			
		||||
	#endif
 | 
			
		||||
	#endif
 | 
			
		||||
EOF
 | 
			
		||||
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
 | 
			
		||||
	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
 | 
			
		||||
	;;
 | 
			
		||||
    mips64:Linux:*:*)
 | 
			
		||||
	eval $set_cc_for_build
 | 
			
		||||
	sed 's/^	//' << EOF >$dummy.c
 | 
			
		||||
	#undef CPU
 | 
			
		||||
	#undef mips64
 | 
			
		||||
	#undef mips64el
 | 
			
		||||
	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
 | 
			
		||||
	CPU=mips64el
 | 
			
		||||
	#else
 | 
			
		||||
	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
 | 
			
		||||
	CPU=mips64
 | 
			
		||||
	#else
 | 
			
		||||
	CPU=
 | 
			
		||||
	#endif
 | 
			
		||||
	#endif
 | 
			
		||||
EOF
 | 
			
		||||
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
 | 
			
		||||
	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
 | 
			
		||||
	;;
 | 
			
		||||
    ppc:Linux:*:*)
 | 
			
		||||
	echo powerpc-unknown-linux-gnu
 | 
			
		||||
@@ -815,6 +885,9 @@ EOF
 | 
			
		||||
    s390:Linux:*:* | s390x:Linux:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-ibm-linux
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    sh64*:Linux:*:*)
 | 
			
		||||
    	echo ${UNAME_MACHINE}-unknown-linux-gnu
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    sh*:Linux:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-linux-gnu
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -828,7 +901,8 @@ EOF
 | 
			
		||||
	# The BFD linker knows what the default object file format is, so
 | 
			
		||||
	# first see if it will tell us. cd to the root directory to prevent
 | 
			
		||||
	# problems with other programs or directories called `ld' in the path.
 | 
			
		||||
	ld_supported_targets=`cd /; ld --help 2>&1 \
 | 
			
		||||
	# Set LC_ALL=C to ensure ld outputs messages in English.
 | 
			
		||||
	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
 | 
			
		||||
			 | sed -ne '/supported targets:/!d
 | 
			
		||||
				    s/[ 	][ 	]*/ /g
 | 
			
		||||
				    s/.*supported targets: *//
 | 
			
		||||
@@ -840,7 +914,7 @@ EOF
 | 
			
		||||
		;;
 | 
			
		||||
	  a.out-i386-linux)
 | 
			
		||||
		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
 | 
			
		||||
		exit 0 ;;		
 | 
			
		||||
		exit 0 ;;
 | 
			
		||||
	  coff-i386)
 | 
			
		||||
		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
 | 
			
		||||
		exit 0 ;;
 | 
			
		||||
@@ -852,32 +926,28 @@ EOF
 | 
			
		||||
	esac
 | 
			
		||||
	# Determine whether the default compiler is a.out or elf
 | 
			
		||||
	eval $set_cc_for_build
 | 
			
		||||
	cat >$dummy.c <<EOF
 | 
			
		||||
#include <features.h>
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
#include <stdio.h>  /* for printf() prototype */
 | 
			
		||||
	int main (int argc, char *argv[]) {
 | 
			
		||||
#else
 | 
			
		||||
	int main (argc, argv) int argc; char *argv[]; {
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
# ifdef __GLIBC__
 | 
			
		||||
#  if __GLIBC__ >= 2
 | 
			
		||||
    printf ("%s-pc-linux-gnu\n", argv[1]);
 | 
			
		||||
#  else
 | 
			
		||||
    printf ("%s-pc-linux-gnulibc1\n", argv[1]);
 | 
			
		||||
#  endif
 | 
			
		||||
# else
 | 
			
		||||
   printf ("%s-pc-linux-gnulibc1\n", argv[1]);
 | 
			
		||||
# endif
 | 
			
		||||
#else
 | 
			
		||||
  printf ("%s-pc-linux-gnuaout\n", argv[1]);
 | 
			
		||||
#endif
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
	sed 's/^	//' << EOF >$dummy.c
 | 
			
		||||
	#include <features.h>
 | 
			
		||||
	#ifdef __ELF__
 | 
			
		||||
	# ifdef __GLIBC__
 | 
			
		||||
	#  if __GLIBC__ >= 2
 | 
			
		||||
	LIBC=gnu
 | 
			
		||||
	#  else
 | 
			
		||||
	LIBC=gnulibc1
 | 
			
		||||
	#  endif
 | 
			
		||||
	# else
 | 
			
		||||
	LIBC=gnulibc1
 | 
			
		||||
	# endif
 | 
			
		||||
	#else
 | 
			
		||||
	#ifdef __INTEL_COMPILER
 | 
			
		||||
	LIBC=gnu
 | 
			
		||||
	#else
 | 
			
		||||
	LIBC=gnuaout
 | 
			
		||||
	#endif
 | 
			
		||||
	#endif
 | 
			
		||||
EOF
 | 
			
		||||
	$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
 | 
			
		||||
	rm -f $dummy.c $dummy
 | 
			
		||||
	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
 | 
			
		||||
	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
 | 
			
		||||
	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
 | 
			
		||||
	;;
 | 
			
		||||
    i*86:DYNIX/ptx:4*:*)
 | 
			
		||||
@@ -894,6 +964,23 @@ EOF
 | 
			
		||||
        # Use sysv4.2uw... so that sysv4* matches it.
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:OS/2:*:*)
 | 
			
		||||
	# If we were able to find `uname', then EMX Unix compatibility
 | 
			
		||||
	# is probably installed.
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-os2-emx
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:XTS-300:*:STOP)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-stop
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:atheos:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-atheos
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
 | 
			
		||||
	echo i386-unknown-lynxos${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:*DOS:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-msdosdjgpp
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
 | 
			
		||||
	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
 | 
			
		||||
	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
 | 
			
		||||
@@ -915,22 +1002,19 @@ EOF
 | 
			
		||||
		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
 | 
			
		||||
		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
 | 
			
		||||
	elif /bin/uname -X 2>/dev/null >/dev/null ; then
 | 
			
		||||
		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
 | 
			
		||||
		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
 | 
			
		||||
		(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
 | 
			
		||||
		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
 | 
			
		||||
		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
 | 
			
		||||
		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
 | 
			
		||||
			&& UNAME_MACHINE=i586
 | 
			
		||||
		(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
 | 
			
		||||
		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
 | 
			
		||||
			&& UNAME_MACHINE=i686
 | 
			
		||||
		(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
 | 
			
		||||
		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
 | 
			
		||||
			&& UNAME_MACHINE=i686
 | 
			
		||||
		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
 | 
			
		||||
	else
 | 
			
		||||
		echo ${UNAME_MACHINE}-pc-sysv32
 | 
			
		||||
	fi
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:*DOS:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-msdosdjgpp
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    pc:*:*:*)
 | 
			
		||||
	# Left here for compatibility:
 | 
			
		||||
        # uname -m prints for DJGPP always 'pc', but it prints nothing about
 | 
			
		||||
@@ -954,9 +1038,15 @@ EOF
 | 
			
		||||
	# "miniframe"
 | 
			
		||||
	echo m68010-convergent-sysv
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    mc68k:UNIX:SYSTEM5:3.51m)
 | 
			
		||||
	echo m68k-convergent-sysv
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    M680?0:D-NIX:5.3:*)
 | 
			
		||||
	echo m68k-diab-dnix
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    M68*:*:R3V[567]*:*)
 | 
			
		||||
	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
 | 
			
		||||
    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
 | 
			
		||||
    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
 | 
			
		||||
	OS_REL=''
 | 
			
		||||
	test -r /etc/.relid \
 | 
			
		||||
	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
 | 
			
		||||
@@ -973,9 +1063,6 @@ EOF
 | 
			
		||||
    mc68030:UNIX_System_V:4.*:*)
 | 
			
		||||
	echo m68k-atari-sysv4
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
 | 
			
		||||
	echo i386-unknown-lynxos${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    TSUNAMI:LynxOS:2.*:*)
 | 
			
		||||
	echo sparc-unknown-lynxos${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -1047,6 +1134,9 @@ EOF
 | 
			
		||||
    SX-5:SUPER-UX:*:*)
 | 
			
		||||
	echo sx5-nec-superux${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    SX-6:SUPER-UX:*:*)
 | 
			
		||||
	echo sx6-nec-superux${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    Power*:Rhapsody:*:*)
 | 
			
		||||
	echo powerpc-apple-rhapsody${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -1054,18 +1144,24 @@ EOF
 | 
			
		||||
	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:Darwin:*:*)
 | 
			
		||||
	echo `uname -p`-apple-darwin${UNAME_RELEASE}
 | 
			
		||||
	case `uname -p` in
 | 
			
		||||
	    *86) UNAME_PROCESSOR=i686 ;;
 | 
			
		||||
	    powerpc) UNAME_PROCESSOR=powerpc ;;
 | 
			
		||||
	esac
 | 
			
		||||
	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:procnto*:*:* | *:QNX:[0123456789]*:*)
 | 
			
		||||
	if test "${UNAME_MACHINE}" = "x86pc"; then
 | 
			
		||||
	UNAME_PROCESSOR=`uname -p`
 | 
			
		||||
	if test "$UNAME_PROCESSOR" = "x86"; then
 | 
			
		||||
		UNAME_PROCESSOR=i386
 | 
			
		||||
		UNAME_MACHINE=pc
 | 
			
		||||
	fi
 | 
			
		||||
	echo `uname -p`-${UNAME_MACHINE}-nto-qnx
 | 
			
		||||
	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:QNX:*:4*)
 | 
			
		||||
	echo i386-pc-qnx
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    NSR-[KW]:NONSTOP_KERNEL:*:*)
 | 
			
		||||
    NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
 | 
			
		||||
	echo nsr-tandem-nsk${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:NonStop-UX:*:*)
 | 
			
		||||
@@ -1088,11 +1184,6 @@ EOF
 | 
			
		||||
	fi
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-plan9
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:OS/2:*:*)
 | 
			
		||||
	# If we were able to find `uname', then EMX Unix compatibility
 | 
			
		||||
	# is probably installed.
 | 
			
		||||
	echo ${UNAME_MACHINE}-pc-os2-emx
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    *:TOPS-10:*:*)
 | 
			
		||||
	echo pdp10-unknown-tops10
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
@@ -1111,11 +1202,8 @@ EOF
 | 
			
		||||
    *:ITS:*:*)
 | 
			
		||||
	echo pdp10-unknown-its
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:XTS-300:*:STOP)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-stop
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
    i*86:atheos:*:*)
 | 
			
		||||
	echo ${UNAME_MACHINE}-unknown-atheos
 | 
			
		||||
    SEI:*:*:SEIUX)
 | 
			
		||||
        echo mips-sei-seiux${UNAME_RELEASE}
 | 
			
		||||
	exit 0 ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
@@ -1237,8 +1325,7 @@ main ()
 | 
			
		||||
}
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
 | 
			
		||||
rm -f $dummy.c $dummy
 | 
			
		||||
$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
 | 
			
		||||
 | 
			
		||||
# Apollos put the system type in the environment.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										303
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										303
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,9 @@
 | 
			
		||||
#! /bin/sh
 | 
			
		||||
# Configuration validation subroutine script.
 | 
			
		||||
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
 | 
			
		||||
#   Free Software Foundation, Inc.
 | 
			
		||||
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 | 
			
		||||
#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 | 
			
		||||
 | 
			
		||||
timestamp='2001-09-07'
 | 
			
		||||
timestamp='2003-06-17'
 | 
			
		||||
 | 
			
		||||
# This file is (in principle) common to ALL GNU software.
 | 
			
		||||
# The presence of a machine in this file suggests that SOME GNU software
 | 
			
		||||
@@ -29,7 +29,8 @@ timestamp='2001-09-07'
 | 
			
		||||
# configuration script generated by Autoconf, you may include it under
 | 
			
		||||
# the same distribution terms that you use for the rest of that program.
 | 
			
		||||
 | 
			
		||||
# Please send patches to <config-patches@gnu.org>.
 | 
			
		||||
# Please send patches to <config-patches@gnu.org>.  Submit a context
 | 
			
		||||
# diff and a properly formatted ChangeLog entry.
 | 
			
		||||
#
 | 
			
		||||
# Configuration subroutine to validate and canonicalize a configuration type.
 | 
			
		||||
# Supply the specified configuration type as an argument.
 | 
			
		||||
@@ -117,7 +118,7 @@ esac
 | 
			
		||||
# Here we must recognize all the valid KERNEL-OS combinations.
 | 
			
		||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 | 
			
		||||
case $maybe_os in
 | 
			
		||||
  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
 | 
			
		||||
  nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
 | 
			
		||||
    os=-$maybe_os
 | 
			
		||||
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
 | 
			
		||||
    ;;
 | 
			
		||||
@@ -226,32 +227,44 @@ case $basic_machine in
 | 
			
		||||
	1750a | 580 \
 | 
			
		||||
	| a29k \
 | 
			
		||||
	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 | 
			
		||||
	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 | 
			
		||||
	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
 | 
			
		||||
	| c4x | clipper \
 | 
			
		||||
	| d10v | d30v | dsp16xx \
 | 
			
		||||
	| fr30 \
 | 
			
		||||
	| d10v | d30v | dlx | dsp16xx \
 | 
			
		||||
	| fr30 | frv \
 | 
			
		||||
	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 | 
			
		||||
	| i370 | i860 | i960 | ia64 \
 | 
			
		||||
	| ip2k \
 | 
			
		||||
	| m32r | m68000 | m68k | m88k | mcore \
 | 
			
		||||
	| mips16 | mips64 | mips64el | mips64orion | mips64orionel \
 | 
			
		||||
	| mips64vr4100 | mips64vr4100el | mips64vr4300 \
 | 
			
		||||
	| mips64vr4300el | mips64vr5000 | mips64vr5000el \
 | 
			
		||||
	| mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
 | 
			
		||||
	| mipsisa32 \
 | 
			
		||||
	| mips | mipsbe | mipseb | mipsel | mipsle \
 | 
			
		||||
	| mips16 \
 | 
			
		||||
	| mips64 | mips64el \
 | 
			
		||||
	| mips64vr | mips64vrel \
 | 
			
		||||
	| mips64orion | mips64orionel \
 | 
			
		||||
	| mips64vr4100 | mips64vr4100el \
 | 
			
		||||
	| mips64vr4300 | mips64vr4300el \
 | 
			
		||||
	| mips64vr5000 | mips64vr5000el \
 | 
			
		||||
	| mipsisa32 | mipsisa32el \
 | 
			
		||||
	| mipsisa32r2 | mipsisa32r2el \
 | 
			
		||||
	| mipsisa64 | mipsisa64el \
 | 
			
		||||
	| mipsisa64sb1 | mipsisa64sb1el \
 | 
			
		||||
	| mipsisa64sr71k | mipsisa64sr71kel \
 | 
			
		||||
	| mipstx39 | mipstx39el \
 | 
			
		||||
	| mn10200 | mn10300 \
 | 
			
		||||
	| msp430 \
 | 
			
		||||
	| ns16k | ns32k \
 | 
			
		||||
	| openrisc \
 | 
			
		||||
	| openrisc | or32 \
 | 
			
		||||
	| pdp10 | pdp11 | pj | pjl \
 | 
			
		||||
	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
 | 
			
		||||
	| pyramid \
 | 
			
		||||
	| s390 | s390x \
 | 
			
		||||
	| sh | sh[34] | sh[34]eb | shbe | shle \
 | 
			
		||||
	| sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \
 | 
			
		||||
	| stormy16 | strongarm \
 | 
			
		||||
	| tahoe | thumb | tic80 | tron \
 | 
			
		||||
	| v850 \
 | 
			
		||||
	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
 | 
			
		||||
	| sh64 | sh64le \
 | 
			
		||||
	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
 | 
			
		||||
	| strongarm \
 | 
			
		||||
	| tahoe | thumb | tic4x | tic80 | tron \
 | 
			
		||||
	| v850 | v850e \
 | 
			
		||||
	| we32k \
 | 
			
		||||
	| x86 | xscale \
 | 
			
		||||
	| x86 | xscale | xstormy16 | xtensa \
 | 
			
		||||
	| z8k)
 | 
			
		||||
		basic_machine=$basic_machine-unknown
 | 
			
		||||
		;;
 | 
			
		||||
@@ -278,38 +291,55 @@ case $basic_machine in
 | 
			
		||||
	580-* \
 | 
			
		||||
	| a29k-* \
 | 
			
		||||
	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
 | 
			
		||||
	| alphapca5[67]-* | arc-* \
 | 
			
		||||
	| arm-*  | armbe-* | armle-* | armv*-* \
 | 
			
		||||
	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
 | 
			
		||||
	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
 | 
			
		||||
	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 | 
			
		||||
	| avr-* \
 | 
			
		||||
	| bs2000-* \
 | 
			
		||||
	| c[123]* | c30-* | [cjt]90-* | c54x-* \
 | 
			
		||||
	| clipper-* | cray2-* | cydra-* \
 | 
			
		||||
	| d10v-* | d30v-* \
 | 
			
		||||
	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
 | 
			
		||||
	| clipper-* | cydra-* \
 | 
			
		||||
	| d10v-* | d30v-* | dlx-* \
 | 
			
		||||
	| elxsi-* \
 | 
			
		||||
	| f30[01]-* | f700-* | fr30-* | fx80-* \
 | 
			
		||||
	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
 | 
			
		||||
	| h8300-* | h8500-* \
 | 
			
		||||
	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 | 
			
		||||
	| i*86-* | i860-* | i960-* | ia64-* \
 | 
			
		||||
	| ip2k-* \
 | 
			
		||||
	| m32r-* \
 | 
			
		||||
	| m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \
 | 
			
		||||
	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
 | 
			
		||||
	| m88110-* | m88k-* | mcore-* \
 | 
			
		||||
	| mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
 | 
			
		||||
	| mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
 | 
			
		||||
	| mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
 | 
			
		||||
	| mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
 | 
			
		||||
	| none-* | np1-* | ns16k-* | ns32k-* \
 | 
			
		||||
	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 | 
			
		||||
	| mips16-* \
 | 
			
		||||
	| mips64-* | mips64el-* \
 | 
			
		||||
	| mips64vr-* | mips64vrel-* \
 | 
			
		||||
	| mips64orion-* | mips64orionel-* \
 | 
			
		||||
	| mips64vr4100-* | mips64vr4100el-* \
 | 
			
		||||
	| mips64vr4300-* | mips64vr4300el-* \
 | 
			
		||||
	| mips64vr5000-* | mips64vr5000el-* \
 | 
			
		||||
	| mipsisa32-* | mipsisa32el-* \
 | 
			
		||||
	| mipsisa32r2-* | mipsisa32r2el-* \
 | 
			
		||||
	| mipsisa64-* | mipsisa64el-* \
 | 
			
		||||
	| mipsisa64sb1-* | mipsisa64sb1el-* \
 | 
			
		||||
	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
 | 
			
		||||
	| mipstx39-* | mipstx39el-* \
 | 
			
		||||
	| msp430-* \
 | 
			
		||||
	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
 | 
			
		||||
	| orion-* \
 | 
			
		||||
	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 | 
			
		||||
	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
 | 
			
		||||
	| pyramid-* \
 | 
			
		||||
	| romp-* | rs6000-* \
 | 
			
		||||
	| s390-* | s390x-* \
 | 
			
		||||
	| sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \
 | 
			
		||||
	| sparc-* | sparc64-* | sparc86x-* | sparclite-* \
 | 
			
		||||
	| sparcv9-* | sparcv9b-* | stormy16-* | strongarm-* | sv1-* \
 | 
			
		||||
	| t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
 | 
			
		||||
	| v850-* | vax-* \
 | 
			
		||||
	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
 | 
			
		||||
	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 | 
			
		||||
	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
 | 
			
		||||
	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
 | 
			
		||||
	| tahoe-* | thumb-* \
 | 
			
		||||
	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
 | 
			
		||||
	| tron-* \
 | 
			
		||||
	| v850-* | v850e-* | vax-* \
 | 
			
		||||
	| we32k-* \
 | 
			
		||||
	| x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \
 | 
			
		||||
	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
 | 
			
		||||
	| xtensa-* \
 | 
			
		||||
	| ymp-* \
 | 
			
		||||
	| z8k-*)
 | 
			
		||||
		;;
 | 
			
		||||
@@ -343,6 +373,9 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=a29k-none
 | 
			
		||||
		os=-bsd
 | 
			
		||||
		;;
 | 
			
		||||
	amd64)
 | 
			
		||||
		basic_machine=x86_64-pc
 | 
			
		||||
		;;
 | 
			
		||||
	amdahl)
 | 
			
		||||
		basic_machine=580-amdahl
 | 
			
		||||
		os=-sysv
 | 
			
		||||
@@ -374,6 +407,10 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=ns32k-sequent
 | 
			
		||||
		os=-dynix
 | 
			
		||||
		;;
 | 
			
		||||
	c90)
 | 
			
		||||
		basic_machine=c90-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
	convex-c1)
 | 
			
		||||
		basic_machine=c1-convex
 | 
			
		||||
		os=-bsd
 | 
			
		||||
@@ -394,16 +431,8 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=c38-convex
 | 
			
		||||
		os=-bsd
 | 
			
		||||
		;;
 | 
			
		||||
	cray | ymp)
 | 
			
		||||
		basic_machine=ymp-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
	cray2)
 | 
			
		||||
		basic_machine=cray2-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
	[cjt]90)
 | 
			
		||||
		basic_machine=${basic_machine}-cray
 | 
			
		||||
	cray | j90)
 | 
			
		||||
		basic_machine=j90-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
	crds | unos)
 | 
			
		||||
@@ -418,6 +447,14 @@ case $basic_machine in
 | 
			
		||||
	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
 | 
			
		||||
		basic_machine=mips-dec
 | 
			
		||||
		;;
 | 
			
		||||
	decsystem10* | dec10*)
 | 
			
		||||
		basic_machine=pdp10-dec
 | 
			
		||||
		os=-tops10
 | 
			
		||||
		;;
 | 
			
		||||
	decsystem20* | dec20*)
 | 
			
		||||
		basic_machine=pdp10-dec
 | 
			
		||||
		os=-tops20
 | 
			
		||||
		;;
 | 
			
		||||
	delta | 3300 | motorola-3300 | motorola-delta \
 | 
			
		||||
	      | 3300-motorola | delta-motorola)
 | 
			
		||||
		basic_machine=m68k-motorola
 | 
			
		||||
@@ -598,14 +635,6 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=m68k-atari
 | 
			
		||||
		os=-mint
 | 
			
		||||
		;;
 | 
			
		||||
	mipsel*-linux*)
 | 
			
		||||
		basic_machine=mipsel-unknown
 | 
			
		||||
		os=-linux-gnu
 | 
			
		||||
		;;
 | 
			
		||||
	mips*-linux*)
 | 
			
		||||
		basic_machine=mips-unknown
 | 
			
		||||
		os=-linux-gnu
 | 
			
		||||
		;;
 | 
			
		||||
	mips3*-*)
 | 
			
		||||
		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
 | 
			
		||||
		;;
 | 
			
		||||
@@ -620,6 +649,10 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=m68k-rom68k
 | 
			
		||||
		os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	morphos)
 | 
			
		||||
		basic_machine=powerpc-unknown
 | 
			
		||||
		os=-morphos
 | 
			
		||||
		;;
 | 
			
		||||
	msdos)
 | 
			
		||||
		basic_machine=i386-pc
 | 
			
		||||
		os=-msdos
 | 
			
		||||
@@ -692,6 +725,10 @@ case $basic_machine in
 | 
			
		||||
	np1)
 | 
			
		||||
		basic_machine=np1-gould
 | 
			
		||||
		;;
 | 
			
		||||
	nv1)
 | 
			
		||||
		basic_machine=nv1-cray
 | 
			
		||||
		os=-unicosmp
 | 
			
		||||
		;;
 | 
			
		||||
	nsr-tandem)
 | 
			
		||||
		basic_machine=nsr-tandem
 | 
			
		||||
		;;
 | 
			
		||||
@@ -699,6 +736,10 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=hppa1.1-oki
 | 
			
		||||
		os=-proelf
 | 
			
		||||
		;;
 | 
			
		||||
	or32 | or32-*)
 | 
			
		||||
		basic_machine=or32-unknown
 | 
			
		||||
		os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	OSE68000 | ose68000)
 | 
			
		||||
		basic_machine=m68000-ericsson
 | 
			
		||||
		os=-ose
 | 
			
		||||
@@ -721,49 +762,55 @@ case $basic_machine in
 | 
			
		||||
	pbb)
 | 
			
		||||
		basic_machine=m68k-tti
 | 
			
		||||
		;;
 | 
			
		||||
        pc532 | pc532-*)
 | 
			
		||||
	pc532 | pc532-*)
 | 
			
		||||
		basic_machine=ns32k-pc532
 | 
			
		||||
		;;
 | 
			
		||||
	pentium | p5 | k5 | k6 | nexgen)
 | 
			
		||||
	pentium | p5 | k5 | k6 | nexgen | viac3)
 | 
			
		||||
		basic_machine=i586-pc
 | 
			
		||||
		;;
 | 
			
		||||
	pentiumpro | p6 | 6x86 | athlon)
 | 
			
		||||
	pentiumpro | p6 | 6x86 | athlon | athlon_*)
 | 
			
		||||
		basic_machine=i686-pc
 | 
			
		||||
		;;
 | 
			
		||||
	pentiumii | pentium2)
 | 
			
		||||
	pentiumii | pentium2 | pentiumiii | pentium3)
 | 
			
		||||
		basic_machine=i686-pc
 | 
			
		||||
		;;
 | 
			
		||||
	pentium-* | p5-* | k5-* | k6-* | nexgen-*)
 | 
			
		||||
	pentium4)
 | 
			
		||||
		basic_machine=i786-pc
 | 
			
		||||
		;;
 | 
			
		||||
	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
 | 
			
		||||
		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	pentiumpro-* | p6-* | 6x86-* | athlon-*)
 | 
			
		||||
		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	pentiumii-* | pentium2-*)
 | 
			
		||||
	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
 | 
			
		||||
		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	pentium4-*)
 | 
			
		||||
		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	pn)
 | 
			
		||||
		basic_machine=pn-gould
 | 
			
		||||
		;;
 | 
			
		||||
	power)	basic_machine=power-ibm
 | 
			
		||||
		;;
 | 
			
		||||
	ppc)	basic_machine=powerpc-unknown
 | 
			
		||||
	        ;;
 | 
			
		||||
		;;
 | 
			
		||||
	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	ppcle | powerpclittle | ppc-le | powerpc-little)
 | 
			
		||||
		basic_machine=powerpcle-unknown
 | 
			
		||||
	        ;;
 | 
			
		||||
		;;
 | 
			
		||||
	ppcle-* | powerpclittle-*)
 | 
			
		||||
		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	ppc64)	basic_machine=powerpc64-unknown
 | 
			
		||||
	        ;;
 | 
			
		||||
		;;
 | 
			
		||||
	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
 | 
			
		||||
		basic_machine=powerpc64le-unknown
 | 
			
		||||
	        ;;
 | 
			
		||||
		;;
 | 
			
		||||
	ppc64le-* | powerpc64little-*)
 | 
			
		||||
		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
@@ -784,10 +831,26 @@ case $basic_machine in
 | 
			
		||||
	rtpc | rtpc-*)
 | 
			
		||||
		basic_machine=romp-ibm
 | 
			
		||||
		;;
 | 
			
		||||
	s390 | s390-*)
 | 
			
		||||
		basic_machine=s390-ibm
 | 
			
		||||
		;;
 | 
			
		||||
	s390x | s390x-*)
 | 
			
		||||
		basic_machine=s390x-ibm
 | 
			
		||||
		;;
 | 
			
		||||
	sa29200)
 | 
			
		||||
		basic_machine=a29k-amd
 | 
			
		||||
		os=-udi
 | 
			
		||||
		;;
 | 
			
		||||
	sb1)
 | 
			
		||||
		basic_machine=mipsisa64sb1-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	sb1el)
 | 
			
		||||
		basic_machine=mipsisa64sb1el-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	sei)
 | 
			
		||||
		basic_machine=mips-sei
 | 
			
		||||
		os=-seiux
 | 
			
		||||
		;;
 | 
			
		||||
	sequent)
 | 
			
		||||
		basic_machine=i386-sequent
 | 
			
		||||
		;;
 | 
			
		||||
@@ -795,7 +858,10 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=sh-hitachi
 | 
			
		||||
		os=-hms
 | 
			
		||||
		;;
 | 
			
		||||
	sparclite-wrs)
 | 
			
		||||
	sh64)
 | 
			
		||||
		basic_machine=sh64-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	sparclite-wrs | simso-wrs)
 | 
			
		||||
		basic_machine=sparclite-wrs
 | 
			
		||||
		os=-vxworks
 | 
			
		||||
		;;
 | 
			
		||||
@@ -862,19 +928,35 @@ case $basic_machine in
 | 
			
		||||
		os=-dynix
 | 
			
		||||
		;;
 | 
			
		||||
	t3e)
 | 
			
		||||
		basic_machine=t3e-cray
 | 
			
		||||
		basic_machine=alphaev5-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
	t90)
 | 
			
		||||
		basic_machine=t90-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
	tic54x | c54x*)
 | 
			
		||||
		basic_machine=tic54x-unknown
 | 
			
		||||
		os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	tic55x | c55x*)
 | 
			
		||||
		basic_machine=tic55x-unknown
 | 
			
		||||
		os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	tic6x | c6x*)
 | 
			
		||||
		basic_machine=tic6x-unknown
 | 
			
		||||
		os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	tx39)
 | 
			
		||||
		basic_machine=mipstx39-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	tx39el)
 | 
			
		||||
		basic_machine=mipstx39el-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	toad1)
 | 
			
		||||
		basic_machine=pdp10-xkl
 | 
			
		||||
		os=-tops20
 | 
			
		||||
		;;
 | 
			
		||||
	tower | tower-32)
 | 
			
		||||
		basic_machine=m68k-ncr
 | 
			
		||||
		;;
 | 
			
		||||
@@ -899,8 +981,8 @@ case $basic_machine in
 | 
			
		||||
		os=-vms
 | 
			
		||||
		;;
 | 
			
		||||
	vpp*|vx|vx-*)
 | 
			
		||||
               basic_machine=f301-fujitsu
 | 
			
		||||
               ;;
 | 
			
		||||
		basic_machine=f301-fujitsu
 | 
			
		||||
		;;
 | 
			
		||||
	vxworks960)
 | 
			
		||||
		basic_machine=i960-wrs
 | 
			
		||||
		os=-vxworks
 | 
			
		||||
@@ -921,17 +1003,13 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=hppa1.1-winbond
 | 
			
		||||
		os=-proelf
 | 
			
		||||
		;;
 | 
			
		||||
	windows32)
 | 
			
		||||
		basic_machine=i386-pc
 | 
			
		||||
		os=-windows32-msvcrt
 | 
			
		||||
		;;
 | 
			
		||||
	xmp)
 | 
			
		||||
		basic_machine=xmp-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
        xps | xps100)
 | 
			
		||||
	xps | xps100)
 | 
			
		||||
		basic_machine=xps100-honeywell
 | 
			
		||||
		;;
 | 
			
		||||
	ymp)
 | 
			
		||||
		basic_machine=ymp-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
	z8k-*-coff)
 | 
			
		||||
		basic_machine=z8k-unknown
 | 
			
		||||
		os=-sim
 | 
			
		||||
@@ -952,13 +1030,6 @@ case $basic_machine in
 | 
			
		||||
	op60c)
 | 
			
		||||
		basic_machine=hppa1.1-oki
 | 
			
		||||
		;;
 | 
			
		||||
	mips)
 | 
			
		||||
		if [ x$os = x-linux-gnu ]; then
 | 
			
		||||
			basic_machine=mips-unknown
 | 
			
		||||
		else
 | 
			
		||||
			basic_machine=mips-mips
 | 
			
		||||
		fi
 | 
			
		||||
		;;
 | 
			
		||||
	romp)
 | 
			
		||||
		basic_machine=romp-ibm
 | 
			
		||||
		;;
 | 
			
		||||
@@ -978,13 +1049,16 @@ case $basic_machine in
 | 
			
		||||
	we32k)
 | 
			
		||||
		basic_machine=we32k-att
 | 
			
		||||
		;;
 | 
			
		||||
	sh3 | sh4 | sh3eb | sh4eb)
 | 
			
		||||
	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
 | 
			
		||||
		basic_machine=sh-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	sh64)
 | 
			
		||||
		basic_machine=sh64-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	sparc | sparcv9 | sparcv9b)
 | 
			
		||||
		basic_machine=sparc-sun
 | 
			
		||||
		;;
 | 
			
		||||
        cydra)
 | 
			
		||||
	cydra)
 | 
			
		||||
		basic_machine=cydra-cydrome
 | 
			
		||||
		;;
 | 
			
		||||
	orion)
 | 
			
		||||
@@ -999,10 +1073,6 @@ case $basic_machine in
 | 
			
		||||
	pmac | pmac-mpw)
 | 
			
		||||
		basic_machine=powerpc-apple
 | 
			
		||||
		;;
 | 
			
		||||
	c4x*)
 | 
			
		||||
		basic_machine=c4x-none
 | 
			
		||||
		os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	*-unknown)
 | 
			
		||||
		# Make sure to match an already-canonicalized machine name.
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1065,10 +1135,12 @@ case $os in
 | 
			
		||||
	      | -chorusos* | -chorusrdb* \
 | 
			
		||||
	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
 | 
			
		||||
	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
 | 
			
		||||
	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
 | 
			
		||||
	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 | 
			
		||||
	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 | 
			
		||||
	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 | 
			
		||||
	      | -os2* | -vos*)
 | 
			
		||||
	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 | 
			
		||||
	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 | 
			
		||||
	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
 | 
			
		||||
	# Remember, each alternative MUST END IN *, to match a version number.
 | 
			
		||||
		;;
 | 
			
		||||
	-qnx*)
 | 
			
		||||
@@ -1080,8 +1152,10 @@ case $os in
 | 
			
		||||
			;;
 | 
			
		||||
		esac
 | 
			
		||||
		;;
 | 
			
		||||
	-nto-qnx*)
 | 
			
		||||
		;;
 | 
			
		||||
	-nto*)
 | 
			
		||||
		os=-nto-qnx
 | 
			
		||||
		os=`echo $os | sed -e 's|nto|nto-qnx|'`
 | 
			
		||||
		;;
 | 
			
		||||
	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
 | 
			
		||||
	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
 | 
			
		||||
@@ -1120,14 +1194,20 @@ case $os in
 | 
			
		||||
	-acis*)
 | 
			
		||||
		os=-aos
 | 
			
		||||
		;;
 | 
			
		||||
	-atheos*)
 | 
			
		||||
		os=-atheos
 | 
			
		||||
		;;
 | 
			
		||||
	-386bsd)
 | 
			
		||||
		os=-bsd
 | 
			
		||||
		;;
 | 
			
		||||
	-ctix* | -uts*)
 | 
			
		||||
		os=-sysv
 | 
			
		||||
		;;
 | 
			
		||||
	-nova*)
 | 
			
		||||
		os=-rtmk-nova
 | 
			
		||||
		;;
 | 
			
		||||
	-ns2 )
 | 
			
		||||
	        os=-nextstep2
 | 
			
		||||
		os=-nextstep2
 | 
			
		||||
		;;
 | 
			
		||||
	-nsk*)
 | 
			
		||||
		os=-nsk
 | 
			
		||||
@@ -1166,8 +1246,14 @@ case $os in
 | 
			
		||||
	-xenix)
 | 
			
		||||
		os=-xenix
 | 
			
		||||
		;;
 | 
			
		||||
        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
 | 
			
		||||
	        os=-mint
 | 
			
		||||
	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
 | 
			
		||||
		os=-mint
 | 
			
		||||
		;;
 | 
			
		||||
	-aros*)
 | 
			
		||||
		os=-aros
 | 
			
		||||
		;;
 | 
			
		||||
	-kaos*)
 | 
			
		||||
		os=-kaos
 | 
			
		||||
		;;
 | 
			
		||||
	-none)
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1200,10 +1286,14 @@ case $basic_machine in
 | 
			
		||||
	arm*-semi)
 | 
			
		||||
		os=-aout
 | 
			
		||||
		;;
 | 
			
		||||
    c4x-* | tic4x-*)
 | 
			
		||||
        os=-coff
 | 
			
		||||
        ;;
 | 
			
		||||
	# This must come before the *-dec entry.
 | 
			
		||||
	pdp10-*)
 | 
			
		||||
		os=-tops20
 | 
			
		||||
		;;
 | 
			
		||||
        pdp11-*)
 | 
			
		||||
	pdp11-*)
 | 
			
		||||
		os=-none
 | 
			
		||||
		;;
 | 
			
		||||
	*-dec | vax-*)
 | 
			
		||||
@@ -1230,6 +1320,9 @@ case $basic_machine in
 | 
			
		||||
	mips*-*)
 | 
			
		||||
		os=-elf
 | 
			
		||||
		;;
 | 
			
		||||
	or32-*)
 | 
			
		||||
		os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	*-tti)	# must be before sparc entry or we get the wrong os.
 | 
			
		||||
		os=-sysv3
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1293,19 +1386,19 @@ case $basic_machine in
 | 
			
		||||
	*-next)
 | 
			
		||||
		os=-nextstep3
 | 
			
		||||
		;;
 | 
			
		||||
        *-gould)
 | 
			
		||||
	*-gould)
 | 
			
		||||
		os=-sysv
 | 
			
		||||
		;;
 | 
			
		||||
        *-highlevel)
 | 
			
		||||
	*-highlevel)
 | 
			
		||||
		os=-bsd
 | 
			
		||||
		;;
 | 
			
		||||
	*-encore)
 | 
			
		||||
		os=-bsd
 | 
			
		||||
		;;
 | 
			
		||||
        *-sgi)
 | 
			
		||||
	*-sgi)
 | 
			
		||||
		os=-irix
 | 
			
		||||
		;;
 | 
			
		||||
        *-siemens)
 | 
			
		||||
	*-siemens)
 | 
			
		||||
		os=-sysv4
 | 
			
		||||
		;;
 | 
			
		||||
	*-masscomp)
 | 
			
		||||
@@ -1377,7 +1470,7 @@ case $basic_machine in
 | 
			
		||||
			-ptx*)
 | 
			
		||||
				vendor=sequent
 | 
			
		||||
				;;
 | 
			
		||||
			-vxsim* | -vxworks*)
 | 
			
		||||
			-vxsim* | -vxworks* | -windiss*)
 | 
			
		||||
				vendor=wrs
 | 
			
		||||
				;;
 | 
			
		||||
			-aux*)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,38 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
#
 | 
			
		||||
# install - install a program, script, or datafile
 | 
			
		||||
# This comes from X11R5 (mit/util/scripts/install.sh).
 | 
			
		||||
 | 
			
		||||
scriptversion=2003-06-13.21
 | 
			
		||||
 | 
			
		||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
 | 
			
		||||
# later released in X11R6 (xc/config/util/install.sh) with the
 | 
			
		||||
# following copyright and license.
 | 
			
		||||
#
 | 
			
		||||
# Copyright 1991 by the Massachusetts Institute of Technology
 | 
			
		||||
# Copyright (C) 1994 X Consortium
 | 
			
		||||
#
 | 
			
		||||
# Permission to use, copy, modify, distribute, and sell this software and its
 | 
			
		||||
# documentation for any purpose is hereby granted without fee, provided that
 | 
			
		||||
# the above copyright notice appear in all copies and that both that
 | 
			
		||||
# copyright notice and this permission notice appear in supporting
 | 
			
		||||
# documentation, and that the name of M.I.T. not be used in advertising or
 | 
			
		||||
# publicity pertaining to distribution of the software without specific,
 | 
			
		||||
# written prior permission.  M.I.T. makes no representations about the
 | 
			
		||||
# suitability of this software for any purpose.  It is provided "as is"
 | 
			
		||||
# without express or implied warranty.
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to
 | 
			
		||||
# deal in the Software without restriction, including without limitation the
 | 
			
		||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 | 
			
		||||
# sell copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in
 | 
			
		||||
# all copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
			
		||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | 
			
		||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
 | 
			
		||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
#
 | 
			
		||||
# Except as contained in this notice, the name of the X Consortium shall not
 | 
			
		||||
# be used in advertising or otherwise to promote the sale, use or other deal-
 | 
			
		||||
# ings in this Software without prior written authorization from the X Consor-
 | 
			
		||||
# tium.
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# FSF changes to this file are in the public domain.
 | 
			
		||||
#
 | 
			
		||||
# Calling this script install-sh is preferred over install.sh, to prevent
 | 
			
		||||
# `make' implicit rules from creating a file called install from it
 | 
			
		||||
@@ -23,13 +42,11 @@
 | 
			
		||||
# from scratch.  It can only install one file at a time, a restriction
 | 
			
		||||
# shared with many OS's install programs.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# set DOITPROG to echo to test this script
 | 
			
		||||
 | 
			
		||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
 | 
			
		||||
doit="${DOITPROG-}"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# put in absolute paths if you don't have them in your path; or use env. vars.
 | 
			
		||||
 | 
			
		||||
mvprog="${MVPROG-mv}"
 | 
			
		||||
@@ -41,211 +58,229 @@ stripprog="${STRIPPROG-strip}"
 | 
			
		||||
rmprog="${RMPROG-rm}"
 | 
			
		||||
mkdirprog="${MKDIRPROG-mkdir}"
 | 
			
		||||
 | 
			
		||||
transformbasename=""
 | 
			
		||||
transform_arg=""
 | 
			
		||||
transformbasename=
 | 
			
		||||
transform_arg=
 | 
			
		||||
instcmd="$mvprog"
 | 
			
		||||
chmodcmd="$chmodprog 0755"
 | 
			
		||||
chowncmd=""
 | 
			
		||||
chgrpcmd=""
 | 
			
		||||
stripcmd=""
 | 
			
		||||
chowncmd=
 | 
			
		||||
chgrpcmd=
 | 
			
		||||
stripcmd=
 | 
			
		||||
rmcmd="$rmprog -f"
 | 
			
		||||
mvcmd="$mvprog"
 | 
			
		||||
src=""
 | 
			
		||||
dst=""
 | 
			
		||||
dir_arg=""
 | 
			
		||||
src=
 | 
			
		||||
dst=
 | 
			
		||||
dir_arg=
 | 
			
		||||
 | 
			
		||||
while [ x"$1" != x ]; do
 | 
			
		||||
    case $1 in
 | 
			
		||||
	-c) instcmd="$cpprog"
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
 | 
			
		||||
   or: $0 -d DIR1 DIR2...
 | 
			
		||||
 | 
			
		||||
	-d) dir_arg=true
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
 | 
			
		||||
In the second, create the directory path DIR.
 | 
			
		||||
 | 
			
		||||
	-m) chmodcmd="$chmodprog $2"
 | 
			
		||||
	    shift
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
Options:
 | 
			
		||||
-b=TRANSFORMBASENAME
 | 
			
		||||
-c         copy source (using $cpprog) instead of moving (using $mvprog).
 | 
			
		||||
-d         create directories instead of installing files.
 | 
			
		||||
-g GROUP   $chgrp installed files to GROUP.
 | 
			
		||||
-m MODE    $chmod installed files to MODE.
 | 
			
		||||
-o USER    $chown installed files to USER.
 | 
			
		||||
-s         strip installed files (using $stripprog).
 | 
			
		||||
-t=TRANSFORM
 | 
			
		||||
--help     display this help and exit.
 | 
			
		||||
--version  display version info and exit.
 | 
			
		||||
 | 
			
		||||
	-o) chowncmd="$chownprog $2"
 | 
			
		||||
	    shift
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
Environment variables override the default commands:
 | 
			
		||||
  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
 | 
			
		||||
"
 | 
			
		||||
 | 
			
		||||
	-g) chgrpcmd="$chgrpprog $2"
 | 
			
		||||
	    shift
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
while test -n "$1"; do
 | 
			
		||||
  case $1 in
 | 
			
		||||
    -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
	-s) stripcmd="$stripprog"
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
    -c) instcmd=$cpprog
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
    -d) dir_arg=true
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
    -g) chgrpcmd="$chgrpprog $2"
 | 
			
		||||
        shift
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
	*)  if [ x"$src" = x ]
 | 
			
		||||
	    then
 | 
			
		||||
		src=$1
 | 
			
		||||
	    else
 | 
			
		||||
		# this colon is to work around a 386BSD /bin/sh bug
 | 
			
		||||
		:
 | 
			
		||||
		dst=$1
 | 
			
		||||
	    fi
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
    esac
 | 
			
		||||
    --help) echo "$usage"; exit 0;;
 | 
			
		||||
 | 
			
		||||
    -m) chmodcmd="$chmodprog $2"
 | 
			
		||||
        shift
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    -o) chowncmd="$chownprog $2"
 | 
			
		||||
        shift
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    -s) stripcmd=$stripprog
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    -t=*) transformarg=`echo $1 | sed 's/-t=//'`
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    --version) echo "$0 $scriptversion"; exit 0;;
 | 
			
		||||
 | 
			
		||||
    *)  if test -z "$src"; then
 | 
			
		||||
          src=$1
 | 
			
		||||
        else
 | 
			
		||||
          # this colon is to work around a 386BSD /bin/sh bug
 | 
			
		||||
          :
 | 
			
		||||
          dst=$1
 | 
			
		||||
        fi
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
if [ x"$src" = x ]
 | 
			
		||||
then
 | 
			
		||||
	echo "install:	no input file specified"
 | 
			
		||||
	exit 1
 | 
			
		||||
else
 | 
			
		||||
	true
 | 
			
		||||
if test -z "$src"; then
 | 
			
		||||
  echo "$0: no input file specified." >&2
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ x"$dir_arg" != x ]; then
 | 
			
		||||
	dst=$src
 | 
			
		||||
	src=""
 | 
			
		||||
	
 | 
			
		||||
	if [ -d $dst ]; then
 | 
			
		||||
		instcmd=:
 | 
			
		||||
		chmodcmd=""
 | 
			
		||||
	else
 | 
			
		||||
		instcmd=mkdir
 | 
			
		||||
	fi
 | 
			
		||||
if test -n "$dir_arg"; then
 | 
			
		||||
  dst=$src
 | 
			
		||||
  src=
 | 
			
		||||
 | 
			
		||||
  if test -d "$dst"; then
 | 
			
		||||
    instcmd=:
 | 
			
		||||
    chmodcmd=
 | 
			
		||||
  else
 | 
			
		||||
    instcmd=$mkdirprog
 | 
			
		||||
  fi
 | 
			
		||||
else
 | 
			
		||||
  # Waiting for this to be detected by the "$instcmd $src $dsttmp" command
 | 
			
		||||
  # might cause directories to be created, which would be especially bad
 | 
			
		||||
  # if $src (and thus $dsttmp) contains '*'.
 | 
			
		||||
  if test ! -f "$src" && test ! -d "$src"; then
 | 
			
		||||
    echo "$0: $src does not exist." >&2
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
 | 
			
		||||
# might cause directories to be created, which would be especially bad 
 | 
			
		||||
# if $src (and thus $dsttmp) contains '*'.
 | 
			
		||||
  if test -z "$dst"; then
 | 
			
		||||
    echo "$0: no destination specified." >&2
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
	if [ -f $src -o -d $src ]
 | 
			
		||||
	then
 | 
			
		||||
		true
 | 
			
		||||
	else
 | 
			
		||||
		echo "install:  $src does not exist"
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
	
 | 
			
		||||
	if [ x"$dst" = x ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "install:	no destination specified"
 | 
			
		||||
		exit 1
 | 
			
		||||
	else
 | 
			
		||||
		true
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
# If destination is a directory, append the input filename; if your system
 | 
			
		||||
# does not like double slashes in filenames, you may need to add some logic
 | 
			
		||||
 | 
			
		||||
	if [ -d $dst ]
 | 
			
		||||
	then
 | 
			
		||||
		dst="$dst"/`basename $src`
 | 
			
		||||
	else
 | 
			
		||||
		true
 | 
			
		||||
	fi
 | 
			
		||||
  # If destination is a directory, append the input filename; won't work
 | 
			
		||||
  # if double slashes aren't ignored.
 | 
			
		||||
  if test -d "$dst"; then
 | 
			
		||||
    dst=$dst/`basename "$src"`
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
## this sed command emulates the dirname command
 | 
			
		||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
 | 
			
		||||
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
 | 
			
		||||
 | 
			
		||||
# Make sure that the destination directory exists.
 | 
			
		||||
#  this part is taken from Noah Friedman's mkinstalldirs script
 | 
			
		||||
# (this part is taken from Noah Friedman's mkinstalldirs script.)
 | 
			
		||||
 | 
			
		||||
# Skip lots of stat calls in the usual case.
 | 
			
		||||
if [ ! -d "$dstdir" ]; then
 | 
			
		||||
defaultIFS='	
 | 
			
		||||
'
 | 
			
		||||
IFS="${IFS-${defaultIFS}}"
 | 
			
		||||
if test ! -d "$dstdir"; then
 | 
			
		||||
  defaultIFS='
 | 
			
		||||
	'
 | 
			
		||||
  IFS="${IFS-$defaultIFS}"
 | 
			
		||||
 | 
			
		||||
oIFS="${IFS}"
 | 
			
		||||
# Some sh's can't handle IFS=/ for some reason.
 | 
			
		||||
IFS='%'
 | 
			
		||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
 | 
			
		||||
IFS="${oIFS}"
 | 
			
		||||
  oIFS=$IFS
 | 
			
		||||
  # Some sh's can't handle IFS=/ for some reason.
 | 
			
		||||
  IFS='%'
 | 
			
		||||
  set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
 | 
			
		||||
  IFS=$oIFS
 | 
			
		||||
 | 
			
		||||
pathcomp=''
 | 
			
		||||
  pathcomp=
 | 
			
		||||
 | 
			
		||||
while [ $# -ne 0 ] ; do
 | 
			
		||||
	pathcomp="${pathcomp}${1}"
 | 
			
		||||
	shift
 | 
			
		||||
 | 
			
		||||
	if [ ! -d "${pathcomp}" ] ;
 | 
			
		||||
        then
 | 
			
		||||
		$mkdirprog "${pathcomp}"
 | 
			
		||||
	else
 | 
			
		||||
		true
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	pathcomp="${pathcomp}/"
 | 
			
		||||
done
 | 
			
		||||
  while test $# -ne 0 ; do
 | 
			
		||||
    pathcomp=$pathcomp$1
 | 
			
		||||
    shift
 | 
			
		||||
    test -d "$pathcomp" || $mkdirprog "$pathcomp"
 | 
			
		||||
    pathcomp=$pathcomp/
 | 
			
		||||
  done
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ x"$dir_arg" != x ]
 | 
			
		||||
then
 | 
			
		||||
	$doit $instcmd $dst &&
 | 
			
		||||
if test -n "$dir_arg"; then
 | 
			
		||||
  $doit $instcmd "$dst" \
 | 
			
		||||
    && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
 | 
			
		||||
    && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
 | 
			
		||||
    && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
 | 
			
		||||
    && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
 | 
			
		||||
 | 
			
		||||
	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
 | 
			
		||||
	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
 | 
			
		||||
	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
 | 
			
		||||
	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
 | 
			
		||||
else
 | 
			
		||||
  # If we're going to rename the final executable, determine the name now.
 | 
			
		||||
  if test -z "$transformarg"; then
 | 
			
		||||
    dstfile=`basename "$dst"`
 | 
			
		||||
  else
 | 
			
		||||
    dstfile=`basename "$dst" $transformbasename \
 | 
			
		||||
             | sed $transformarg`$transformbasename
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
# If we're going to rename the final executable, determine the name now.
 | 
			
		||||
  # don't allow the sed command to completely eliminate the filename.
 | 
			
		||||
  test -z "$dstfile" && dstfile=`basename "$dst"`
 | 
			
		||||
 | 
			
		||||
	if [ x"$transformarg" = x ] 
 | 
			
		||||
	then
 | 
			
		||||
		dstfile=`basename $dst`
 | 
			
		||||
	else
 | 
			
		||||
		dstfile=`basename $dst $transformbasename | 
 | 
			
		||||
			sed $transformarg`$transformbasename
 | 
			
		||||
	fi
 | 
			
		||||
  # Make a couple of temp file names in the proper directory.
 | 
			
		||||
  dsttmp=$dstdir/_inst.$$_
 | 
			
		||||
  rmtmp=$dstdir/_rm.$$_
 | 
			
		||||
 | 
			
		||||
# don't allow the sed command to completely eliminate the filename
 | 
			
		||||
  # Trap to clean up those temp files at exit.
 | 
			
		||||
  trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
 | 
			
		||||
  trap '(exit $?); exit' 1 2 13 15
 | 
			
		||||
 | 
			
		||||
	if [ x"$dstfile" = x ] 
 | 
			
		||||
	then
 | 
			
		||||
		dstfile=`basename $dst`
 | 
			
		||||
	else
 | 
			
		||||
		true
 | 
			
		||||
	fi
 | 
			
		||||
  # Move or copy the file name to the temp name
 | 
			
		||||
  $doit $instcmd "$src" "$dsttmp" &&
 | 
			
		||||
 | 
			
		||||
# Make a temp file name in the proper directory.
 | 
			
		||||
  # and set any options; do chmod last to preserve setuid bits.
 | 
			
		||||
  #
 | 
			
		||||
  # If any of these fail, we abort the whole thing.  If we want to
 | 
			
		||||
  # ignore errors from any of these, just make sure not to ignore
 | 
			
		||||
  # errors from the above "$doit $instcmd $src $dsttmp" command.
 | 
			
		||||
  #
 | 
			
		||||
  { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
 | 
			
		||||
    && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
 | 
			
		||||
    && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
 | 
			
		||||
    && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
 | 
			
		||||
 | 
			
		||||
	dsttmp=$dstdir/#inst.$$#
 | 
			
		||||
 | 
			
		||||
# Move or copy the file name to the temp name
 | 
			
		||||
 | 
			
		||||
	$doit $instcmd $src $dsttmp &&
 | 
			
		||||
 | 
			
		||||
	trap "rm -f ${dsttmp}" 0 &&
 | 
			
		||||
 | 
			
		||||
# and set any options; do chmod last to preserve setuid bits
 | 
			
		||||
 | 
			
		||||
# If any of these fail, we abort the whole thing.  If we want to
 | 
			
		||||
# ignore errors from any of these, just make sure not to ignore
 | 
			
		||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
 | 
			
		||||
 | 
			
		||||
	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
 | 
			
		||||
	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
 | 
			
		||||
	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
 | 
			
		||||
	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
 | 
			
		||||
 | 
			
		||||
# Now rename the file to the real destination.
 | 
			
		||||
 | 
			
		||||
	$doit $rmcmd -f $dstdir/$dstfile &&
 | 
			
		||||
	$doit $mvcmd $dsttmp $dstdir/$dstfile 
 | 
			
		||||
  # Now remove or move aside any old file at destination location.  We
 | 
			
		||||
  # try this two ways since rm can't unlink itself on some systems and
 | 
			
		||||
  # the destination file might be busy for other reasons.  In this case,
 | 
			
		||||
  # the final cleanup might fail but the new file should still install
 | 
			
		||||
  # successfully.
 | 
			
		||||
  {
 | 
			
		||||
    if test -f "$dstdir/$dstfile"; then
 | 
			
		||||
      $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
 | 
			
		||||
      || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
 | 
			
		||||
      || {
 | 
			
		||||
	  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
 | 
			
		||||
	  (exit 1); exit
 | 
			
		||||
      }
 | 
			
		||||
    else
 | 
			
		||||
      :
 | 
			
		||||
    fi
 | 
			
		||||
  } &&
 | 
			
		||||
 | 
			
		||||
  # Now rename the file to the real destination.
 | 
			
		||||
  $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
 | 
			
		||||
fi &&
 | 
			
		||||
 | 
			
		||||
# The final little trick to "correctly" pass the exit status to the exit trap.
 | 
			
		||||
{
 | 
			
		||||
  (exit 0); exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exit 0
 | 
			
		||||
# Local variables:
 | 
			
		||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
 | 
			
		||||
# time-stamp-start: "scriptversion="
 | 
			
		||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
 | 
			
		||||
# time-stamp-end: "$"
 | 
			
		||||
# End:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										568
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										568
									
								
								configure.in
									
									
									
									
									
								
							@@ -1,130 +1,399 @@
 | 
			
		||||
################################################################################
 | 
			
		||||
##
 | 
			
		||||
##    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
 | 
			
		||||
################################################################################
 | 
			
		||||
AC_CONFIG_HEADERS(lib/misc/configure.h)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
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"
 | 
			
		||||
		LIB_SUFFIX="so"
 | 
			
		||||
		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"
 | 
			
		||||
		LIB_SUFFIX="dylib"
 | 
			
		||||
		DEVMAPPER=yes
 | 
			
		||||
		ODIRECT=no
 | 
			
		||||
		SELINUX=no
 | 
			
		||||
		CLUSTER=none
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Checks for programs.
 | 
			
		||||
AC_PROG_AWK
 | 
			
		||||
AC_PROG_CC
 | 
			
		||||
AC_PROG_INSTALL
 | 
			
		||||
AC_PROG_LN_S
 | 
			
		||||
AC_PROG_MAKE_SET
 | 
			
		||||
AC_PROG_RANLIB
 | 
			
		||||
AC_PATH_PROG(CFLOW_CMD, cflow)
 | 
			
		||||
AC_PATH_PROG(CSCOPE_CMD, cscope)
 | 
			
		||||
 | 
			
		||||
dnl Checks for header files.
 | 
			
		||||
################################################################################
 | 
			
		||||
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
 | 
			
		||||
	AC_DEFINE([LVM1_FALLBACK], 1, [Define to 1 if 'lvm' should fall back to using LVM1 binaries if device-mapper is missing from the kernel])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
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"
 | 
			
		||||
	AC_DEFINE([LVM1_INTERNAL], 1, [Define to 1 to include built-in support for LVM1 metadata.])
 | 
			
		||||
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
 | 
			
		||||
	AC_DEFINE([POOL_INTERNAL], 1, [Define to 1 to include built-in support for GFS pool metadata.])
 | 
			
		||||
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
 | 
			
		||||
	AC_DEFINE([CLUSTER_LOCKING_INTERNAL], 1, [Define to 1 to include built-in support for clustered LVM locking.])
 | 
			
		||||
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
 | 
			
		||||
	AC_DEFINE([SNAPSHOT_INTERNAL], 1, [Define to 1 to include built-in support for snapshots.])
 | 
			
		||||
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
 | 
			
		||||
	AC_DEFINE([MIRRORED_INTERNAL], 1, [Define to 1 to include built-in support for mirrors.])
 | 
			
		||||
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"
 | 
			
		||||
	AC_DEFINE([READLINE_SUPPORT], 1, [Define to 1 to include the LVM readline shell.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
dnl Enable Debugging
 | 
			
		||||
AC_ARG_ENABLE(debug,    [  --enable-debug          Enable debugging],  \
 | 
			
		||||
DEBUG=yes, DEBUG=no)
 | 
			
		||||
################################################################################
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
dnl Disable devmapper
 | 
			
		||||
AC_ARG_ENABLE(devmapper, [  --disable-devmapper     Disable device-mapper interaction],  \
 | 
			
		||||
DEVMAPPER=no, DEVMAPPER=yes)
 | 
			
		||||
################################################################################
 | 
			
		||||
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/all
 | 
			
		||||
                          [TYPE=none] ],
 | 
			
		||||
  [ CLVMD="$withval" ],
 | 
			
		||||
  [ CLVMD="none" ])
 | 
			
		||||
if test x$CLVMD = xyes; then
 | 
			
		||||
	CLVMD=all
 | 
			
		||||
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=
 | 
			
		||||
else
 | 
			
		||||
	CSCOPE_CMD=
 | 
			
		||||
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"
 | 
			
		||||
	AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable device-mapper interaction.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
dnl Mess with default exec_prefix
 | 
			
		||||
################################################################################
 | 
			
		||||
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
 | 
			
		||||
	AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
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
 | 
			
		||||
	AC_DEFINE([CMDLIB], 1, [Define to 1 to build the shared command library.])
 | 
			
		||||
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 -- enable dmeventd handling
 | 
			
		||||
AC_MSG_CHECKING(whether to use dmeventd)
 | 
			
		||||
AC_ARG_ENABLE(dmeventd, [  --enable-dmeventd       Enable the device-mapper event daemon],
 | 
			
		||||
DMEVENTD=$enableval)
 | 
			
		||||
AC_MSG_RESULT($DMEVENTD)
 | 
			
		||||
 | 
			
		||||
dnl -- dmeventd currently requires internal mirror support
 | 
			
		||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
 | 
			
		||||
AC_MSG_ERROR(
 | 
			
		||||
--enable-dmeventd currently requires --with-mirrors=internal
 | 
			
		||||
)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD = xyes; then
 | 
			
		||||
	AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
 | 
			
		||||
fi
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Mess with default exec_prefix
 | 
			
		||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
 | 
			
		||||
 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(
 | 
			
		||||
@@ -137,22 +406,59 @@ 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
 | 
			
		||||
	CFLAGS="$CFLAGS -DHAVE_LIBDL"
 | 
			
		||||
if [[ "x$HAVE_LIBDL" = xyes ]]; then
 | 
			
		||||
	AC_DEFINE([HAVE_LIBDL], 1, [Define to 1 if dynamic libraries are available.])
 | 
			
		||||
	LIBS="-ldl $LIBS"
 | 
			
		||||
else
 | 
			
		||||
	HAVE_LIBDL=no
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
dnl Check for getopt
 | 
			
		||||
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
 | 
			
		||||
################################################################################
 | 
			
		||||
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 readline (Shamelessly copied from parted 1.4.17)
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for selinux
 | 
			
		||||
if test x$SELINUX = xyes; then
 | 
			
		||||
	AC_MSG_CHECKING(for sepol_check_context function)
 | 
			
		||||
	AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
 | 
			
		||||
	AC_MSG_RESULT($HAVE_SEPOL)
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_SEPOL = xyes; then
 | 
			
		||||
		LIBS="-lsepol $LIBS"
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	AC_MSG_CHECKING(for is_selinux_enabled function)
 | 
			
		||||
	AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
 | 
			
		||||
	AC_MSG_RESULT($HAVE_SELINUX)
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
		AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.])
 | 
			
		||||
		LIBS="-lselinux $LIBS"
 | 
			
		||||
	else
 | 
			
		||||
		AC_MSG_WARN(Disabling selinux)
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for getopt
 | 
			
		||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 to if getopt_long is available.]))
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	AC_CHECK_LIB(readline, readline, ,
 | 
			
		||||
		AC_MSG_ERROR(
 | 
			
		||||
@@ -163,43 +469,171 @@ 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")
 | 
			
		||||
		
 | 
			
		||||
	AC_CHECK_FUNC(rl_completion_matches, AC_DEFINE([HAVE_RL_COMPLETION_MATCHES], 1, [Define to 1 if rl_completion_matches() is available.]))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
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"
 | 
			
		||||
	AC_PATH_PROG(MSGFMT, msgfmt)
 | 
			
		||||
	if [[ "x$MSGFMT" == x ]];
 | 
			
		||||
		then  AC_MSG_ERROR(
 | 
			
		||||
		msgfmt not found in path $PATH
 | 
			
		||||
		)
 | 
			
		||||
	fi;
 | 
			
		||||
 | 
			
		||||
	AC_ARG_WITH(localedir,
 | 
			
		||||
  		    [  --with-localedir=DIR    Translation files in DIR [PREFIX/share/locale]],
 | 
			
		||||
  		    [ LOCALEDIR="$withval" ],
 | 
			
		||||
  		    [ 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 != xnone; 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
 | 
			
		||||
 | 
			
		||||
AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
 | 
			
		||||
if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(selinux/selinux.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
AC_PATH_PROG(MODPROBE_CMD, modprobe)
 | 
			
		||||
 | 
			
		||||
if test x$MODPROBE_CMD != x; then
 | 
			
		||||
	AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
 | 
			
		||||
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(LIB_SUFFIX)
 | 
			
		||||
AC_SUBST(LIBS)
 | 
			
		||||
AC_SUBST(LVM_VERSION)
 | 
			
		||||
AC_SUBST(LVM1_FALLBACK)
 | 
			
		||||
AC_SUBST(DEBUG)
 | 
			
		||||
AC_SUBST(DEVMAPPER)
 | 
			
		||||
AC_SUBST(HAVE_LIBDL)
 | 
			
		||||
dnl First and last lines should not contain files to generate in order to 
 | 
			
		||||
dnl keep utility scripts running properly
 | 
			
		||||
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)
 | 
			
		||||
AC_SUBST(CLVMD)
 | 
			
		||||
AC_SUBST(CLUSTER)
 | 
			
		||||
AC_SUBST(FSADM)
 | 
			
		||||
AC_SUBST(DMEVENTD)
 | 
			
		||||
AC_SUBST(CFLOW_CMD)
 | 
			
		||||
AC_SUBST(CSCOPE_CMD)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- First and last lines should not contain files to generate in order to 
 | 
			
		||||
dnl -- keep utility scripts running properly
 | 
			
		||||
AC_OUTPUT( 								\
 | 
			
		||||
Makefile								\
 | 
			
		||||
make.tmpl                                                               \
 | 
			
		||||
make.tmpl								\
 | 
			
		||||
daemons/Makefile							\
 | 
			
		||||
daemons/clvmd/Makefile							\
 | 
			
		||||
dmeventd/Makefile							\
 | 
			
		||||
dmeventd/mirror/Makefile						\
 | 
			
		||||
doc/Makefile								\
 | 
			
		||||
include/Makefile						 	\
 | 
			
		||||
lib/Makefile							 	\
 | 
			
		||||
lib/format1/Makefile						 	\
 | 
			
		||||
lib/format_pool/Makefile						\
 | 
			
		||||
lib/locking/Makefile							\
 | 
			
		||||
lib/mirror/Makefile							\
 | 
			
		||||
lib/snapshot/Makefile							\
 | 
			
		||||
man/Makefile							 	\
 | 
			
		||||
po/Makefile								\
 | 
			
		||||
tools/Makefile							 	\
 | 
			
		||||
tools/version.h								\
 | 
			
		||||
tools/fsadm/Makefile							\
 | 
			
		||||
test/mm/Makefile							\
 | 
			
		||||
test/device/Makefile							\
 | 
			
		||||
test/format1/Makefile							\
 | 
			
		||||
test/regex/Makefile                                                     \
 | 
			
		||||
test/filters/Makefile                                                   \
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if test x$ODIRECT != xyes; then
 | 
			
		||||
  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
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD == xyes; then
 | 
			
		||||
  AC_MSG_WARN(dmeventd 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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										84
									
								
								daemons/clvmd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								daemons/clvmd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
#
 | 
			
		||||
# 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          \
 | 
			
		||||
	lvm-functions.c  \
 | 
			
		||||
	system-lv.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "gulm")
 | 
			
		||||
	GULM = yes
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "cman")
 | 
			
		||||
	CMAN = yes
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "all")
 | 
			
		||||
	GULM = yes
 | 
			
		||||
	CMAN = yes
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@DEBUG@", "yes")
 | 
			
		||||
	DEFS += -DDEBUG
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("$(GULM)", "yes")
 | 
			
		||||
	SOURCES += clvmd-gulm.c tcp-comms.c
 | 
			
		||||
	LMLIBS += -lccs -lgulm
 | 
			
		||||
	DEFS += -DUSE_GULM
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("$(CMAN)", "yes")
 | 
			
		||||
	SOURCES += clvmd-cman.c
 | 
			
		||||
	LMLIBS += -ldlm -lcman
 | 
			
		||||
	DEFS += -DUSE_CMAN
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
TARGETS = \
 | 
			
		||||
	clvmd
 | 
			
		||||
 | 
			
		||||
LVMLIBS = -llvm -lpthread
 | 
			
		||||
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
	LVMLIBS += -ldevmapper-event
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
LVMLIBS += -ldevmapper
 | 
			
		||||
 | 
			
		||||
DEFS += -D_REENTRANT
 | 
			
		||||
CFLAGS += -fno-strict-aliasing
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
INSTALL_TARGETS = \
 | 
			
		||||
	install_clvmd
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										66
									
								
								daemons/clvmd/clvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								daemons/clvmd/clvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 */
 | 
			
		||||
#define CLVMD_FLAG_NODEERRS     4       /* Reply has errors in node-specific portion */
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
							
								
								
									
										494
									
								
								daemons/clvmd/clvmd-cman.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										494
									
								
								daemons/clvmd/clvmd-cman.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,494 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 num_nodes;
 | 
			
		||||
static struct cman_node *nodes = NULL;
 | 
			
		||||
static struct cman_node this_node;
 | 
			
		||||
static int count_nodes; /* size of allocated nodes array */
 | 
			
		||||
static int max_updown_nodes = 50;	/* Current size of the allocated array */
 | 
			
		||||
/* Node up/down status, indexed by nodeid */
 | 
			
		||||
static int *node_updown = NULL;
 | 
			
		||||
static dlm_lshandle_t *lockspace;
 | 
			
		||||
static cman_handle_t c_handle;
 | 
			
		||||
 | 
			
		||||
static void count_clvmds_running(void);
 | 
			
		||||
static void get_members(void);
 | 
			
		||||
static int nodeid_from_csid(char *csid);
 | 
			
		||||
static int name_from_nodeid(int nodeid, char *name);
 | 
			
		||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
 | 
			
		||||
static void data_callback(cman_handle_t handle, void *private,
 | 
			
		||||
			  char *buf, int len, uint8_t port, int nodeid);
 | 
			
		||||
 | 
			
		||||
struct lock_wait {
 | 
			
		||||
	pthread_cond_t cond;
 | 
			
		||||
	pthread_mutex_t mutex;
 | 
			
		||||
	struct dlm_lksb lksb;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _init_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Open the cluster communication socket */
 | 
			
		||||
	c_handle = cman_init(NULL);
 | 
			
		||||
	if (!c_handle) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't open cluster manager socket: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't bind cluster socket: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cman_start_notification(c_handle, event_callback)) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't start cluster event listening");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the cluster members list */
 | 
			
		||||
	get_members();
 | 
			
		||||
	count_clvmds_running();
 | 
			
		||||
 | 
			
		||||
	/* 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cluster_init_completed(void)
 | 
			
		||||
{
 | 
			
		||||
	clvmd_cluster_init_completed();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_main_cluster_fd()
 | 
			
		||||
{
 | 
			
		||||
	return cman_get_fd(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_num_nodes()
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int nnodes = 0;
 | 
			
		||||
 | 
			
		||||
	/* return number of ACTIVE nodes */
 | 
			
		||||
	for (i=0; i<num_nodes; i++) {
 | 
			
		||||
		if (nodes[i].cn_member)
 | 
			
		||||
			nnodes++;
 | 
			
		||||
	}
 | 
			
		||||
	return nnodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send_message with the fd check removed */
 | 
			
		||||
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	int nodeid = 0;
 | 
			
		||||
 | 
			
		||||
	if (csid)
 | 
			
		||||
		memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
 | 
			
		||||
	{
 | 
			
		||||
			log_error(errtext);
 | 
			
		||||
	}
 | 
			
		||||
	return msglen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	if (this_node.cn_nodeid == 0) {
 | 
			
		||||
		cman_get_node(c_handle, 0, &this_node);
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
 | 
			
		||||
static int _cluster_do_node_callback(struct local_client *client,
 | 
			
		||||
			     void (*callback) (struct local_client *, char *,
 | 
			
		||||
					       int))
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int somedown = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < _get_num_nodes(); i++) {
 | 
			
		||||
		callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
 | 
			
		||||
		if (!node_updown[nodes[i].cn_nodeid])
 | 
			
		||||
			somedown = -1;
 | 
			
		||||
	}
 | 
			
		||||
	return somedown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Process OOB message from the cluster socket,
 | 
			
		||||
   this currently just means that a node has stopped listening on our port */
 | 
			
		||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
 | 
			
		||||
{
 | 
			
		||||
	char namebuf[MAX_CLUSTER_NAME_LEN];
 | 
			
		||||
 | 
			
		||||
	switch (reason) {
 | 
			
		||||
        case CMAN_REASON_PORTCLOSED:
 | 
			
		||||
		name_from_nodeid(arg, namebuf);
 | 
			
		||||
		log_notice("clvmd on node %s has died\n", namebuf);
 | 
			
		||||
		DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
 | 
			
		||||
 | 
			
		||||
		node_updown[arg] = 0;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CMAN_REASON_STATECHANGE:
 | 
			
		||||
		DEBUGLOG("Got state change message, re-reading members list\n");
 | 
			
		||||
		get_members();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
 | 
			
		||||
	case CMAN_REASON_PORTOPENED:
 | 
			
		||||
		/* Ignore this, wait for startup message from clvmd itself */
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CMAN_REASON_TRY_SHUTDOWN:
 | 
			
		||||
		DEBUGLOG("Got try shutdown, sending OK\n");
 | 
			
		||||
		cman_replyto_shutdown(c_handle, 1);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		/* ERROR */
 | 
			
		||||
		DEBUGLOG("Got unknown event callback message: %d\n", reason);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct local_client *cman_client;
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
 | 
			
		||||
			struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	/* Save this for data_callback */
 | 
			
		||||
	cman_client = fd;
 | 
			
		||||
 | 
			
		||||
	/* We never return a new client */
 | 
			
		||||
	*new_client = NULL;
 | 
			
		||||
 | 
			
		||||
	return cman_dispatch(c_handle, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void data_callback(cman_handle_t handle, void *private,
 | 
			
		||||
			  char *buf, int len, uint8_t port, int nodeid)
 | 
			
		||||
{
 | 
			
		||||
	/* Ignore looped back messages */
 | 
			
		||||
	if (nodeid == this_node.cn_nodeid)
 | 
			
		||||
		return;
 | 
			
		||||
	process_message(cman_client, buf, len, (char *)&nodeid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _add_up_node(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	/* 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cluster_closedown()
 | 
			
		||||
{
 | 
			
		||||
	unlock_all();
 | 
			
		||||
	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
 | 
			
		||||
	cman_finish(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_listening(int nodeid)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
 | 
			
		||||
		if (status < 0 && errno == EBUSY) {	/* Don't busywait */
 | 
			
		||||
			sleep(1);
 | 
			
		||||
			errno = EBUSY;	/* In case sleep trashes it */
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	while (status < 0 && errno == EBUSY);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Populate the list of CLVMDs running.
 | 
			
		||||
   called only at startup time */
 | 
			
		||||
static void count_clvmds_running(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get a list of active cluster members */
 | 
			
		||||
static void get_members()
 | 
			
		||||
{
 | 
			
		||||
	int retnodes;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	num_nodes = cman_get_node_count(c_handle);
 | 
			
		||||
	if (num_nodes == -1) {
 | 
			
		||||
		log_error("Unable to get node count");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	        /* 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 cman_node));
 | 
			
		||||
			if (!nodes) {
 | 
			
		||||
			        log_error("Unable to allocate nodes array\n");
 | 
			
		||||
				exit(5);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
 | 
			
		||||
	if (status < 0) {
 | 
			
		||||
		        log_error("Unable to get node details");
 | 
			
		||||
			exit(6);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (node_updown == NULL) {
 | 
			
		||||
			node_updown =
 | 
			
		||||
			    (int *) malloc(sizeof(int) *
 | 
			
		||||
					   max(num_nodes, max_updown_nodes));
 | 
			
		||||
			memset(node_updown, 0,
 | 
			
		||||
			       sizeof(int) * max(num_nodes, max_updown_nodes));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/* Convert a node name to a CSID */
 | 
			
		||||
static int _csid_from_name(char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (strcmp(name, nodes[i].cn_name) == 0) {
 | 
			
		||||
			memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a CSID to a node name */
 | 
			
		||||
static int _name_from_csid(char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
 | 
			
		||||
			strcpy(name, nodes[i].cn_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/* Who?? */
 | 
			
		||||
	strcpy(name, "Unknown");
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a node ID to a node name */
 | 
			
		||||
static int name_from_nodeid(int nodeid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (nodeid == nodes[i].cn_nodeid) {
 | 
			
		||||
			strcpy(name, nodes[i].cn_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, CMAN_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	return nodeid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _is_quorate()
 | 
			
		||||
{
 | 
			
		||||
	return cman_is_quorate(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static 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;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops _cluster_cman_ops = {
 | 
			
		||||
	.cluster_init_completed   = _cluster_init_completed,
 | 
			
		||||
	.cluster_send_message     = _cluster_send_message,
 | 
			
		||||
	.name_from_csid           = _name_from_csid,
 | 
			
		||||
	.csid_from_name           = _csid_from_name,
 | 
			
		||||
	.get_num_nodes            = _get_num_nodes,
 | 
			
		||||
	.cluster_fd_callback      = _cluster_fd_callback,
 | 
			
		||||
	.get_main_cluster_fd      = _get_main_cluster_fd,
 | 
			
		||||
	.cluster_do_node_callback = _cluster_do_node_callback,
 | 
			
		||||
	.is_quorate               = _is_quorate,
 | 
			
		||||
	.get_our_csid             = _get_our_csid,
 | 
			
		||||
	.add_up_node              = _add_up_node,
 | 
			
		||||
	.cluster_closedown        = _cluster_closedown,
 | 
			
		||||
	.sync_lock                = _sync_lock,
 | 
			
		||||
	.sync_unlock              = _sync_unlock,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cluster_ops *init_cman_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!_init_cluster())
 | 
			
		||||
		return &_cluster_cman_ops;
 | 
			
		||||
	else
 | 
			
		||||
		return NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										286
									
								
								daemons/clvmd/clvmd-command.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								daemons/clvmd/clvmd-command.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,286 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "libdevmapper.h"
 | 
			
		||||
#include "list.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] & 0x3F;
 | 
			
		||||
		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 dm_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 dm_hash_table *)client->bits.localsock.private;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	lock_hash = dm_hash_create(3);
 | 
			
		||||
	if (!lock_hash)
 | 
			
		||||
	    return ENOMEM;
 | 
			
		||||
	client->bits.localsock.private = (void *)lock_hash;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lock_cmd = args[0] & 0x3F;
 | 
			
		||||
    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)dm_hash_lookup(lock_hash, lockname);
 | 
			
		||||
	if (lkid == 0)
 | 
			
		||||
	    return EINVAL;
 | 
			
		||||
 | 
			
		||||
	status = sync_unlock(lockname, lkid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    status = errno;
 | 
			
		||||
	else
 | 
			
		||||
	    dm_hash_remove(lock_hash, lockname);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
 | 
			
		||||
	status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    status = errno;
 | 
			
		||||
	else
 | 
			
		||||
	    dm_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 dm_hash_node *v;
 | 
			
		||||
	struct dm_hash_table *lock_hash =
 | 
			
		||||
	    (struct dm_hash_table *)client->bits.localsock.private;
 | 
			
		||||
 | 
			
		||||
	dm_hash_iterate(v, lock_hash) {
 | 
			
		||||
		int lkid = (int)(long)dm_hash_get_data(lock_hash, v);
 | 
			
		||||
		char *lockname = dm_hash_get_key(lock_hash, v);
 | 
			
		||||
 | 
			
		||||
		DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
 | 
			
		||||
		sync_unlock(lockname, lkid);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_hash_destroy(lock_hash);
 | 
			
		||||
	client->bits.localsock.private = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								daemons/clvmd/clvmd-comms.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								daemons/clvmd/clvmd-comms.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
struct cluster_ops {
 | 
			
		||||
	void (*cluster_init_completed) (void);
 | 
			
		||||
 | 
			
		||||
	int (*cluster_send_message) (void *buf, int msglen, char *csid,
 | 
			
		||||
				const char *errtext);
 | 
			
		||||
	int (*name_from_csid) (char *csid, char *name);
 | 
			
		||||
	int (*csid_from_name) (char *csid, char *name);
 | 
			
		||||
	int (*get_num_nodes) (void);
 | 
			
		||||
	int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
 | 
			
		||||
			       char *csid, struct local_client **new_client);
 | 
			
		||||
	int (*get_main_cluster_fd) (void);	/* gets accept FD or cman cluster socket */
 | 
			
		||||
	int (*cluster_do_node_callback) (struct local_client *client,
 | 
			
		||||
				    void (*callback) (struct local_client *,
 | 
			
		||||
						      char *csid, int node_up));
 | 
			
		||||
	int (*is_quorate) (void);
 | 
			
		||||
 | 
			
		||||
	void (*get_our_csid) (char *csid);
 | 
			
		||||
	void (*add_up_node) (char *csid);
 | 
			
		||||
	void (*reread_config) (void);
 | 
			
		||||
	void (*cluster_closedown) (void);
 | 
			
		||||
 | 
			
		||||
	int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
 | 
			
		||||
	int (*sync_unlock) (const char *resource, int lockid);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef USE_GULM
 | 
			
		||||
#  include "tcp-comms.h"
 | 
			
		||||
struct cluster_ops *init_gulm_cluster(void);
 | 
			
		||||
#define MAX_CSID_LEN 			GULM_MAX_CSID_LEN
 | 
			
		||||
#define MAX_CLUSTER_MEMBER_NAME_LEN	GULM_MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CMAN
 | 
			
		||||
#  include <netinet/in.h>
 | 
			
		||||
#  include "libcman.h"
 | 
			
		||||
#  define CMAN_MAX_CSID_LEN 4
 | 
			
		||||
#  ifndef MAX_CSID_LEN
 | 
			
		||||
#    define MAX_CSID_LEN CMAN_MAX_CSID_LEN
 | 
			
		||||
#  endif
 | 
			
		||||
#  undef MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#  define MAX_CLUSTER_MEMBER_NAME_LEN   CMAN_MAX_NODENAME_LEN
 | 
			
		||||
#  define CMAN_MAX_CLUSTER_MESSAGE 1500
 | 
			
		||||
#  define CLUSTER_PORT_CLVMD 11
 | 
			
		||||
struct cluster_ops *init_cman_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1000
									
								
								daemons/clvmd/clvmd-gulm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1000
									
								
								daemons/clvmd/clvmd-gulm.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										12
									
								
								daemons/clvmd/clvmd-gulm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								daemons/clvmd/clvmd-gulm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
void gulm_add_up_node(char *csid);
 | 
			
		||||
int gulm_name_from_csid(char *csid, char *name);
 | 
			
		||||
							
								
								
									
										1858
									
								
								daemons/clvmd/clvmd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1858
									
								
								daemons/clvmd/clvmd.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										124
									
								
								daemons/clvmd/clvmd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								daemons/clvmd/clvmd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
	uint8_t removeme;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct localsock_bits localsock;
 | 
			
		||||
		struct pipe_bits pipe;
 | 
			
		||||
		struct netsock_bits net;
 | 
			
		||||
	} bits;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#define DEBUGLOG(fmt, args...) {time_t P; time(&P); fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 ); 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);
 | 
			
		||||
 | 
			
		||||
int sync_lock(const char *resource, int mode, int flags, int *lockid);
 | 
			
		||||
int sync_unlock(const char *resource, int lockid);
 | 
			
		||||
 | 
			
		||||
#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 CMAN_MAX_CLUSTER_MESSAGE          1500
 | 
			
		||||
#define CMAN_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[CMAN_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
 | 
			
		||||
							
								
								
									
										561
									
								
								daemons/clvmd/lvm-functions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										561
									
								
								daemons/clvmd/lvm-functions.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,561 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "libdevmapper.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "lvm-types.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 "locking.h"
 | 
			
		||||
#include "defaults.h"
 | 
			
		||||
 | 
			
		||||
static struct cmd_context *cmd = NULL;
 | 
			
		||||
static struct dm_hash_table *lv_hash = NULL;
 | 
			
		||||
static pthread_mutex_t lv_hash_lock;
 | 
			
		||||
 | 
			
		||||
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 = dm_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 dm_hash_node *v;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
	dm_hash_iterate(v, lv_hash) {
 | 
			
		||||
		struct lv_info *lvi = dm_hash_get_data(lv_hash, v);
 | 
			
		||||
 | 
			
		||||
		sync_unlock(dm_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 = dm_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);
 | 
			
		||||
			dm_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 = dm_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);
 | 
			
		||||
		dm_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, unsigned char lock_flags, int mode)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
	int status;
 | 
			
		||||
	int activate_lv;
 | 
			
		||||
	int exclusive = 0;
 | 
			
		||||
	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)) {
 | 
			
		||||
		exclusive = 1;
 | 
			
		||||
		mode = LKM_EXMODE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Try to get the lock if it's a clustered volume group */
 | 
			
		||||
	if (lock_flags & LCK_CLUSTER_VG) {
 | 
			
		||||
		status = hold_lock(resource, mode, LKF_NOQUEUE);
 | 
			
		||||
		if (status)
 | 
			
		||||
			return errno;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If it's suspended then resume it */
 | 
			
		||||
	if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (lvi.suspended)
 | 
			
		||||
		if (!lv_resume(cmd, resource))
 | 
			
		||||
			return EIO;
 | 
			
		||||
 | 
			
		||||
	/* Now activate it */
 | 
			
		||||
	if (!lv_activate(cmd, resource, exclusive))
 | 
			
		||||
		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, 0))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (lvi.exists) {
 | 
			
		||||
		if (!lv_suspend_if_active(cmd, resource)) {
 | 
			
		||||
			return EIO;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_deactivate_lv(char *resource, unsigned char lock_flags)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	/* Is it open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_CLUSTER_VG) {
 | 
			
		||||
		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 = %x\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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_PARTIAL_MODE)
 | 
			
		||||
		init_partial(1);
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
 | 
			
		||||
		init_mirror_in_sync(1);
 | 
			
		||||
 | 
			
		||||
	if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
 | 
			
		||||
		init_dmeventd_register(0);
 | 
			
		||||
 | 
			
		||||
	switch (command) {
 | 
			
		||||
	case LCK_LV_EXCLUSIVE:
 | 
			
		||||
		status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
 | 
			
		||||
		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, lock_flags, LKM_CRMODE);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_LV_DEACTIVATE:
 | 
			
		||||
		status = do_deactivate_lv(resource, lock_flags);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		DEBUGLOG("Invalid LV command 0x%x\n", command);
 | 
			
		||||
		status = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_PARTIAL_MODE)
 | 
			
		||||
		init_partial(0);
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
 | 
			
		||||
		init_mirror_in_sync(0);
 | 
			
		||||
 | 
			
		||||
	if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
 | 
			
		||||
		init_dmeventd_register(DEFAULT_DMEVENTD_MONITOR);
 | 
			
		||||
 | 
			
		||||
	/* clean the pool for another command */
 | 
			
		||||
	dm_pool_empty(cmd->mem);
 | 
			
		||||
 | 
			
		||||
	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, 0))
 | 
			
		||||
				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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
 | 
			
		||||
   that might be hanging around if we died for any reason
 | 
			
		||||
*/
 | 
			
		||||
static void drop_vg_locks()
 | 
			
		||||
{
 | 
			
		||||
	char vg[128];
 | 
			
		||||
	char line[255];
 | 
			
		||||
	FILE *vgs =
 | 
			
		||||
	    popen
 | 
			
		||||
	    ("lvm pvs --nolocking --noheadings -o vg_name", "r");
 | 
			
		||||
 | 
			
		||||
	sync_unlock("P_orphans", LCK_EXCL);
 | 
			
		||||
 | 
			
		||||
	if (!vgs)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	while (fgets(line, sizeof(line), vgs)) {
 | 
			
		||||
		char *vgend;
 | 
			
		||||
		char *vgstart;
 | 
			
		||||
 | 
			
		||||
		if (line[strlen(line)-1] == '\n')
 | 
			
		||||
			line[strlen(line)-1] = '\0';
 | 
			
		||||
 | 
			
		||||
		vgstart = line + strspn(line, " ");
 | 
			
		||||
		vgend = vgstart + strcspn(vgstart, " ");
 | 
			
		||||
		*vgend = '\0';
 | 
			
		||||
 | 
			
		||||
		if (strncmp(vgstart, "WARNING:", 8) == 0)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		sprintf(vg, "V_%s", vgstart);
 | 
			
		||||
		sync_unlock(vg, LCK_EXCL);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	fclose(vgs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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], vg_flags[25];
 | 
			
		||||
	char uuid[65];
 | 
			
		||||
	char line[255];
 | 
			
		||||
	FILE *lvs =
 | 
			
		||||
	    popen
 | 
			
		||||
	    ("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
 | 
			
		||||
	     "r");
 | 
			
		||||
 | 
			
		||||
	if (!lvs)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	while (fgets(line, sizeof(line), lvs)) {
 | 
			
		||||
	        if (sscanf(line, "%s %s %s %s\n", vg, lv, flags, vg_flags) == 4) {
 | 
			
		||||
 | 
			
		||||
			/* 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? */
 | 
			
		||||
			    vg_flags[5] == 'c') {			/* is it clustered ? */
 | 
			
		||||
				/* 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This checks some basic cluster-LVM configuration stuff */
 | 
			
		||||
static void check_config()
 | 
			
		||||
{
 | 
			
		||||
	int locking_type;
 | 
			
		||||
 | 
			
		||||
	locking_type = find_config_tree_int(cmd, "global/locking_type", 1);
 | 
			
		||||
 | 
			
		||||
	if (locking_type == 3) /* compiled-in cluster support */
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (locking_type == 2) { /* External library, check name */
 | 
			
		||||
		const char *libname;
 | 
			
		||||
 | 
			
		||||
		libname = find_config_tree_str(cmd, "global/locking_library",
 | 
			
		||||
					  "");
 | 
			
		||||
		if (strstr(libname, "liblvm2clusterlock.so"))
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_lvhash()
 | 
			
		||||
{
 | 
			
		||||
	/* Create hash table for keeping LV locks & status */
 | 
			
		||||
	lv_hash = dm_hash_create(100);
 | 
			
		||||
	pthread_mutex_init(&lv_hash_lock, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called to initialise the LVM context of the daemon */
 | 
			
		||||
int init_lvm(int using_gulm)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	/* Check lvm.conf is setup for cluster-LVM */
 | 
			
		||||
	check_config();
 | 
			
		||||
 | 
			
		||||
	/* Remove any non-LV locks that may have been left around */
 | 
			
		||||
	if (using_gulm)
 | 
			
		||||
		drop_vg_locks();
 | 
			
		||||
 | 
			
		||||
	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(int using_gulm);
 | 
			
		||||
extern void init_lvhash(void);
 | 
			
		||||
 | 
			
		||||
extern int hold_unlock(char *resource);
 | 
			
		||||
extern int hold_lock(char *resource, int mode, int flags);
 | 
			
		||||
extern void unlock_all(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										371
									
								
								daemons/clvmd/system-lv.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								daemons/clvmd/system-lv.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,371 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.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
 | 
			
		||||
							
								
								
									
										505
									
								
								daemons/clvmd/tcp-comms.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										505
									
								
								daemons/clvmd/tcp-comms.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,505 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
**
 | 
			
		||||
**  Copyright (C) Sistina Software, Inc.  2002-2003  All rights reserved.
 | 
			
		||||
**  Copyright (C) 2004-2005 Red Hat, Inc. 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 "libdevmapper.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "clvmd-gulm.h"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_TCP_PORT 21064
 | 
			
		||||
 | 
			
		||||
static int listen_fd = -1;
 | 
			
		||||
static int tcp_port;
 | 
			
		||||
struct dm_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 = dm_hash_create(100);
 | 
			
		||||
    tcp_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));
 | 
			
		||||
	setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &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);
 | 
			
		||||
 | 
			
		||||
    /* Set Close-on-exec */
 | 
			
		||||
    fcntl(listen_fd, F_SETFD, 1);
 | 
			
		||||
 | 
			
		||||
    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 = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
 | 
			
		||||
    if (client)
 | 
			
		||||
    {
 | 
			
		||||
	dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
 | 
			
		||||
	client->removeme = 1;
 | 
			
		||||
	close(client->fd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Look for a mangled one too */
 | 
			
		||||
    csid[0] ^= 0x80;
 | 
			
		||||
 | 
			
		||||
    client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
 | 
			
		||||
    if (client)
 | 
			
		||||
    {
 | 
			
		||||
	dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
 | 
			
		||||
	client->removeme = 1;
 | 
			
		||||
	close(client->fd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 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 (dm_hash_lookup_binary(sock_hash, csid, GULM_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 (dm_hash_lookup_binary(sock_hash, csid, GULM_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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    dm_hash_insert_binary(sock_hash, csid, GULM_MAX_CSID_LEN, client);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_main_gulm_cluster_fd()
 | 
			
		||||
{
 | 
			
		||||
    return listen_fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Read on main comms (listen) socket, accept it */
 | 
			
		||||
int cluster_fd_gulm_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[GULM_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 (gulm_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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Try to get at least 'len' bytes from the socket */
 | 
			
		||||
static int really_read(int fd, char *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
	int got, offset;
 | 
			
		||||
 | 
			
		||||
	got = offset = 0;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		got = read(fd, buf+offset, len-offset);
 | 
			
		||||
		DEBUGLOG("really_read. got %d bytes\n", got);
 | 
			
		||||
		offset += got;
 | 
			
		||||
	} while (got > 0 && offset < len);
 | 
			
		||||
 | 
			
		||||
	if (got < 0)
 | 
			
		||||
		return got;
 | 
			
		||||
	else
 | 
			
		||||
		return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
    struct clvm_header *header = (struct clvm_header *)buf;
 | 
			
		||||
    int status;
 | 
			
		||||
    uint32_t arglen;
 | 
			
		||||
 | 
			
		||||
    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, GULM_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
    /* Read just the header first, then get the rest if there is any.
 | 
			
		||||
     * Stream sockets, sigh.
 | 
			
		||||
     */
 | 
			
		||||
    status = really_read(client->fd, buf, sizeof(struct clvm_header));
 | 
			
		||||
    if (status > 0)
 | 
			
		||||
    {
 | 
			
		||||
	    int status2;
 | 
			
		||||
 | 
			
		||||
	    arglen = ntohl(header->arglen);
 | 
			
		||||
 | 
			
		||||
	    /* Get the rest */
 | 
			
		||||
	    if (arglen && arglen < GULM_MAX_CLUSTER_MESSAGE)
 | 
			
		||||
	    {
 | 
			
		||||
		    status2 = really_read(client->fd, buf+status, arglen);
 | 
			
		||||
		    if (status2 > 0)
 | 
			
		||||
			    status += status2;
 | 
			
		||||
		    else
 | 
			
		||||
			    status = status2;
 | 
			
		||||
	    }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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[GULM_MAX_CSID_LEN];
 | 
			
		||||
 | 
			
		||||
	memcpy(remcsid, csid, GULM_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;
 | 
			
		||||
	dm_hash_remove_binary(sock_hash, remcsid, GULM_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	/* Tell cluster manager layer */
 | 
			
		||||
	add_down_node(remcsid);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	    gulm_add_up_node(csid);
 | 
			
		||||
	    /* Send it back to clvmd */
 | 
			
		||||
	    process_message(client, buf, status, csid);
 | 
			
		||||
    }
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int gulm_connect_csid(char *csid, struct local_client **newclient)
 | 
			
		||||
{
 | 
			
		||||
    int fd;
 | 
			
		||||
    struct sockaddr_in6 addr;
 | 
			
		||||
    int status;
 | 
			
		||||
    int one = 1;
 | 
			
		||||
 | 
			
		||||
    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, GULM_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)
 | 
			
		||||
    {
 | 
			
		||||
	/* "Connection refused" is "normal" because clvmd may not yet be running
 | 
			
		||||
	 * on that node.
 | 
			
		||||
	 */
 | 
			
		||||
	if (errno != ECONNREFUSED)
 | 
			
		||||
	{
 | 
			
		||||
	    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Set Close-on-exec */
 | 
			
		||||
    fcntl(fd, F_SETFD, 1);
 | 
			
		||||
    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int));
 | 
			
		||||
 | 
			
		||||
    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 */
 | 
			
		||||
    gulm_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[GULM_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_gulm_csid(ourcsid);
 | 
			
		||||
    if (memcmp(csid, ourcsid, GULM_MAX_CSID_LEN) == 0)
 | 
			
		||||
	return msglen;
 | 
			
		||||
 | 
			
		||||
    client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
 | 
			
		||||
    if (!client)
 | 
			
		||||
    {
 | 
			
		||||
	status = gulm_connect_csid(csid, &client);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    return -1;
 | 
			
		||||
    }
 | 
			
		||||
    DEBUGLOG("tcp_send_message, fd = %d\n", client->fd);
 | 
			
		||||
 | 
			
		||||
    return write(client->fd, buf, msglen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int gulm_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[GULM_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_gulm_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
    static char our_csid[GULM_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, GULM_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, GULM_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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								daemons/clvmd/tcp-comms.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								daemons/clvmd/tcp-comms.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
 | 
			
		||||
#define GULM_MAX_CLUSTER_MESSAGE 1600
 | 
			
		||||
#define GULM_MAX_CSID_LEN sizeof(struct in6_addr)
 | 
			
		||||
#define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128
 | 
			
		||||
 | 
			
		||||
extern int init_comms(unsigned short);
 | 
			
		||||
extern char *print_csid(char *);
 | 
			
		||||
int get_main_gulm_cluster_fd(void);
 | 
			
		||||
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client);
 | 
			
		||||
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext);
 | 
			
		||||
void get_our_gulm_csid(char *csid);
 | 
			
		||||
int gulm_connect_csid(char *csid, struct local_client **newclient);
 | 
			
		||||
							
								
								
									
										5
									
								
								daemons/dmeventd/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								daemons/dmeventd/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
dm_event_register
 | 
			
		||||
dm_event_unregister
 | 
			
		||||
dm_event_get_registered_device
 | 
			
		||||
dm_event_set_timeout
 | 
			
		||||
dm_event_get_timeout
 | 
			
		||||
							
								
								
									
										73
									
								
								daemons/dmeventd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								daemons/dmeventd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the device-mapper userspace tools.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
SOURCES = libdevmapper-event.c \
 | 
			
		||||
	  dmeventd.c
 | 
			
		||||
 | 
			
		||||
LIB_STATIC = libdevmapper-event.a
 | 
			
		||||
 | 
			
		||||
ifeq ("@LIB_SUFFIX@","dylib")
 | 
			
		||||
  LIB_SHARED = libdevmapper-event.dylib
 | 
			
		||||
else
 | 
			
		||||
  LIB_SHARED = libdevmapper-event.so
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include ../make.tmpl
 | 
			
		||||
 | 
			
		||||
CLDFLAGS += -ldl -ldevmapper -lpthread
 | 
			
		||||
 | 
			
		||||
.PHONY: install_dynamic install_static install_include \
 | 
			
		||||
	install_pkgconfig
 | 
			
		||||
 | 
			
		||||
INSTALL_TYPE = install_dynamic
 | 
			
		||||
 | 
			
		||||
ifeq ("@STATIC_LINK@", "yes")
 | 
			
		||||
  INSTALL_TYPE += install_static
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@PKGCONFIG@", "yes")
 | 
			
		||||
  INSTALL_TYPE += install_pkgconfig
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
install: $(INSTALL_TYPE) install_include
 | 
			
		||||
 | 
			
		||||
install_include:
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \
 | 
			
		||||
		$(includedir)/libdevmapper-event.h
 | 
			
		||||
 | 
			
		||||
install_dynamic: libdevmapper-event.$(LIB_SUFFIX)
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \
 | 
			
		||||
		$(libdir)/libdevmapper-event.$(LIB_SUFFIX)
 | 
			
		||||
 | 
			
		||||
install_pkgconfig:
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \
 | 
			
		||||
		$(usrlibdir)/pkgconfig/devmapper-event.pc
 | 
			
		||||
 | 
			
		||||
install_static: libdevmapper-event.a
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
 | 
			
		||||
 | 
			
		||||
.PHONY: distclean_lib distclean
 | 
			
		||||
 | 
			
		||||
distclean_lib: 
 | 
			
		||||
	$(RM) libdevmapper-event.pc
 | 
			
		||||
 | 
			
		||||
distclean: distclean_lib
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1339
									
								
								daemons/dmeventd/dmeventd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1339
									
								
								daemons/dmeventd/dmeventd.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										13
									
								
								daemons/dmeventd/dmeventd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								daemons/dmeventd/dmeventd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#ifndef __DMEVENTD_DOT_H__
 | 
			
		||||
#define __DMEVENTD_DOT_H__
 | 
			
		||||
 | 
			
		||||
#define EXIT_LOCKFILE_INUSE      2
 | 
			
		||||
#define EXIT_DESC_CLOSE_FAILURE  3
 | 
			
		||||
#define EXIT_OPEN_PID_FAILURE    4
 | 
			
		||||
#define EXIT_FIFO_FAILURE        5
 | 
			
		||||
#define EXIT_CHDIR_FAILURE       6
 | 
			
		||||
 | 
			
		||||
void dmeventd(void)
 | 
			
		||||
    __attribute((noreturn));
 | 
			
		||||
 | 
			
		||||
#endif /* __DMEVENTD_DOT_H__ */
 | 
			
		||||
							
								
								
									
										510
									
								
								daemons/dmeventd/libdevmapper-event.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								daemons/dmeventd/libdevmapper-event.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,510 @@
 | 
			
		||||
 /*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the device-mapper userspace tools.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
//#include "libmultilog.h"
 | 
			
		||||
#include "dmeventd.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/file.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
/* Set by any of the external fxns the first time one of them is called */
 | 
			
		||||
/* FIXME Unused */
 | 
			
		||||
// static int _logging = 0;
 | 
			
		||||
 | 
			
		||||
/* Fetch a string off src and duplicate it into *dest. */
 | 
			
		||||
/* FIXME: move to seperate module to share with the daemon. */
 | 
			
		||||
static const char delimiter = ' ';
 | 
			
		||||
static char *fetch_string(char **src)
 | 
			
		||||
{
 | 
			
		||||
	char *p, *ret;
 | 
			
		||||
 | 
			
		||||
	if ((p = strchr(*src, delimiter)))
 | 
			
		||||
		*p = 0;
 | 
			
		||||
 | 
			
		||||
	if ((ret = dm_strdup(*src)))
 | 
			
		||||
		*src += strlen(ret) + 1;
 | 
			
		||||
 | 
			
		||||
	if (p)
 | 
			
		||||
		*p = delimiter;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Parse a device message from the daemon. */
 | 
			
		||||
static int parse_message(struct dm_event_daemon_message *msg, char **dso_name,
 | 
			
		||||
			 char **device, enum dm_event_type *events)
 | 
			
		||||
{
 | 
			
		||||
	char *p = msg->msg;
 | 
			
		||||
 | 
			
		||||
	if ((*dso_name = fetch_string(&p)) &&
 | 
			
		||||
	    (*device   = fetch_string(&p))) {
 | 
			
		||||
		*events = atoi(p);
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -ENOMEM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * daemon_read
 | 
			
		||||
 * @fifos
 | 
			
		||||
 * @msg
 | 
			
		||||
 *
 | 
			
		||||
 * Read message from daemon.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 0 on failure, 1 on success
 | 
			
		||||
 */
 | 
			
		||||
static int daemon_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	unsigned bytes = 0;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	fd_set fds;
 | 
			
		||||
 | 
			
		||||
	memset(msg, 0, sizeof(*msg));
 | 
			
		||||
	while (bytes < sizeof(*msg)) {
 | 
			
		||||
		do {
 | 
			
		||||
			/* Watch daemon read FIFO for input. */
 | 
			
		||||
			FD_ZERO(&fds);
 | 
			
		||||
			FD_SET(fifos->server, &fds);
 | 
			
		||||
			ret = select(fifos->server+1, &fds, NULL, NULL, NULL);
 | 
			
		||||
			if (ret < 0 && errno != EINTR) {
 | 
			
		||||
				/* FIXME Log error */
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} while (ret < 1);
 | 
			
		||||
 | 
			
		||||
		ret = read(fifos->server, msg, sizeof(*msg) - bytes);
 | 
			
		||||
		if (ret < 0) {
 | 
			
		||||
			if ((errno == EINTR) || (errno == EAGAIN))
 | 
			
		||||
				continue;
 | 
			
		||||
			else {
 | 
			
		||||
				/* FIXME Log error */
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bytes += ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytes == sizeof(*msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Write message to daemon. */
 | 
			
		||||
static int daemon_write(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	unsigned bytes = 0;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	fd_set fds;
 | 
			
		||||
 | 
			
		||||
	while (bytes < sizeof(*msg)) {
 | 
			
		||||
		do {
 | 
			
		||||
			/* Watch daemon write FIFO to be ready for output. */
 | 
			
		||||
			FD_ZERO(&fds);
 | 
			
		||||
			FD_SET(fifos->client, &fds);
 | 
			
		||||
			ret = select(fifos->client +1, NULL, &fds, NULL, NULL);
 | 
			
		||||
			if ((ret < 0) && (errno != EINTR)) {
 | 
			
		||||
				/* FIXME Log error */
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} while (ret < 1);
 | 
			
		||||
 | 
			
		||||
		ret = write(fifos->client, msg, sizeof(*msg) - bytes);
 | 
			
		||||
		if (ret < 0) {
 | 
			
		||||
			if ((errno == EINTR) || (errno == EAGAIN))
 | 
			
		||||
				continue;
 | 
			
		||||
			else {
 | 
			
		||||
				/* fixme: log error */
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bytes += ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytes == sizeof(*msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int daemon_talk(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg,
 | 
			
		||||
		       int cmd, char *dso_name, char *device,
 | 
			
		||||
		       enum dm_event_type events, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	memset(msg, 0, sizeof(*msg));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Set command and pack the arguments
 | 
			
		||||
	 * into ASCII message string.
 | 
			
		||||
	 */
 | 
			
		||||
	msg->opcode.cmd = cmd;
 | 
			
		||||
 | 
			
		||||
	if (sizeof(msg->msg) <= (unsigned) snprintf(msg->msg, sizeof(msg->msg),
 | 
			
		||||
						    "%s %s %u %"PRIu32,
 | 
			
		||||
						    dso_name ? dso_name : "",
 | 
			
		||||
						    device ? device : "",
 | 
			
		||||
						    events, timeout)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Write command and message to and
 | 
			
		||||
	 * read status return code from daemon.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!daemon_write(fifos, msg)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!daemon_read(fifos, msg)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return msg->opcode.status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static volatile sig_atomic_t daemon_running = 0;
 | 
			
		||||
 | 
			
		||||
static void daemon_running_signal_handler(int sig)
 | 
			
		||||
{
 | 
			
		||||
	daemon_running = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * start_daemon
 | 
			
		||||
 *
 | 
			
		||||
 * This function forks off a process (dmeventd) that will handle
 | 
			
		||||
 * the events.  A signal must be returned from the child to
 | 
			
		||||
 * indicate when it is ready to handle requests.  The parent
 | 
			
		||||
 * (this function) returns 1 if there is a daemon running. 
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 1 on success, 0 otherwise
 | 
			
		||||
 */
 | 
			
		||||
static int start_daemon(void)
 | 
			
		||||
{
 | 
			
		||||
	int pid, ret=0;
 | 
			
		||||
	void *old_hand;
 | 
			
		||||
	sigset_t set, oset;
 | 
			
		||||
 | 
			
		||||
	/* Must be able to acquire signal */
 | 
			
		||||
	old_hand = signal(SIGUSR1, &daemon_running_signal_handler);
 | 
			
		||||
	if (old_hand == SIG_ERR) {
 | 
			
		||||
		log_error("Unable to setup signal handler.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sigemptyset(&set) || sigaddset(&set, SIGUSR1)) {
 | 
			
		||||
		log_error("Unable to fill signal set.");
 | 
			
		||||
	} else if (sigprocmask(SIG_UNBLOCK, &set, &oset)) {
 | 
			
		||||
		log_error("Can't unblock the potentially blocked signal SIGUSR1");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	pid = fork();
 | 
			
		||||
 | 
			
		||||
	if (pid < 0)
 | 
			
		||||
		log_error("Unable to fork.\n");
 | 
			
		||||
	else if (pid) { /* parent waits for child to get ready for requests */
 | 
			
		||||
		int status;
 | 
			
		||||
 | 
			
		||||
		/* FIXME Better way to do this? */
 | 
			
		||||
		while (!waitpid(pid, &status, WNOHANG) && !daemon_running)
 | 
			
		||||
			sleep(1);
 | 
			
		||||
 | 
			
		||||
		if (daemon_running) {
 | 
			
		||||
			ret = 1;
 | 
			
		||||
		} else {
 | 
			
		||||
			switch (WEXITSTATUS(status)) {
 | 
			
		||||
			case EXIT_LOCKFILE_INUSE:
 | 
			
		||||
				/*
 | 
			
		||||
				 * Note, this is ok... we still have daemon
 | 
			
		||||
				 * that we can communicate with...
 | 
			
		||||
				 */
 | 
			
		||||
				log_print("Starting dmeventd failed: "
 | 
			
		||||
					  "dmeventd already running.\n");
 | 
			
		||||
				ret = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				log_error("Unable to start dmeventd.\n");
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * Sometimes, a single process may perform multiple calls
 | 
			
		||||
		 * that result in a daemon starting and exiting.  If we
 | 
			
		||||
		 * don't reset this, the second (or greater) time the daemon
 | 
			
		||||
		 * is started will cause this logic not to work.
 | 
			
		||||
		 */
 | 
			
		||||
		daemon_running = 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		signal(SIGUSR1, SIG_IGN); /* don't care about error */
 | 
			
		||||
 | 
			
		||||
		/* dmeventd function is responsible for properly setting **
 | 
			
		||||
		** itself up.  It must never return - only exit.  This is**
 | 
			
		||||
		** why it is followed by an EXIT_FAILURE                 */
 | 
			
		||||
		dmeventd();
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME What if old_hand is SIG_ERR? */
 | 
			
		||||
	if (signal(SIGUSR1, old_hand) == SIG_ERR)
 | 
			
		||||
		log_error("Unable to reset signal handler.");
 | 
			
		||||
 | 
			
		||||
	if (sigprocmask(SIG_SETMASK, &oset, NULL))
 | 
			
		||||
		log_error("Unable to reset signal mask.");
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Initialize client. */
 | 
			
		||||
static int init_client(struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME Is fifo the most suitable method? */
 | 
			
		||||
	/* FIXME Why not share comms/daemon code with something else e.g. multipath? */
 | 
			
		||||
 | 
			
		||||
	/* init fifos */
 | 
			
		||||
	memset(fifos, 0, sizeof(*fifos));
 | 
			
		||||
	fifos->client_path = DM_EVENT_FIFO_CLIENT;
 | 
			
		||||
	fifos->server_path = DM_EVENT_FIFO_SERVER;
 | 
			
		||||
 | 
			
		||||
	/* FIXME The server should be responsible for these, not the client. */
 | 
			
		||||
	/* Create fifos */
 | 
			
		||||
	if (((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) ||
 | 
			
		||||
	    ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST)) {
 | 
			
		||||
		log_error("%s: Failed to create a fifo.\n", __func__);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Warn/abort if perms are wrong - not something to fix silently. */
 | 
			
		||||
	/* If they were already there, make sure permissions are ok. */
 | 
			
		||||
	if (chmod(fifos->client_path, 0600)) {
 | 
			
		||||
		log_error("Unable to set correct file permissions on %s",
 | 
			
		||||
			fifos->client_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (chmod(fifos->server_path, 0600)) {
 | 
			
		||||
		log_error("Unable to set correct file permissions on %s",
 | 
			
		||||
			fifos->server_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Open the fifo used to read from the daemon.
 | 
			
		||||
	 * Allows daemon to create its write fifo...
 | 
			
		||||
	 */
 | 
			
		||||
	if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
 | 
			
		||||
		log_error("%s: open server fifo %s\n",
 | 
			
		||||
			__func__, fifos->server_path);
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Lock out anyone else trying to do communication with the daemon. */
 | 
			
		||||
	/* FIXME Why failure not retry?  How do multiple processes communicate? */
 | 
			
		||||
	if (flock(fifos->server, LOCK_EX) < 0){
 | 
			
		||||
		log_error("%s: flock %s\n", __func__, fifos->server_path);
 | 
			
		||||
		close(fifos->server);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Anyone listening?  If not, errno will be ENXIO */
 | 
			
		||||
	while ((fifos->client = open(fifos->client_path,
 | 
			
		||||
				  O_WRONLY | O_NONBLOCK)) < 0) {
 | 
			
		||||
		if (errno != ENXIO) {
 | 
			
		||||
			log_error("%s: Can't open client fifo %s: %s\n",
 | 
			
		||||
				  __func__, fifos->client_path, strerror(errno));
 | 
			
		||||
			close(fifos->server);
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* FIXME Unnecessary if daemon was started before calling this */
 | 
			
		||||
		if (!start_daemon()) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dtr_client(struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	if (flock(fifos->server, LOCK_UN))
 | 
			
		||||
		log_error("flock unlock %s\n", fifos->server_path);
 | 
			
		||||
 | 
			
		||||
	close(fifos->client);
 | 
			
		||||
	close(fifos->server);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check, if a block device exists. */
 | 
			
		||||
static int device_exists(char *device)
 | 
			
		||||
{
 | 
			
		||||
	struct stat st_buf;
 | 
			
		||||
	char path2[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (!device)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (device[0] == '/') /* absolute path */
 | 
			
		||||
		return !stat(device, &st_buf) && S_ISBLK(st_buf.st_mode);
 | 
			
		||||
 | 
			
		||||
	if (PATH_MAX <= snprintf(path2, PATH_MAX, "%s/%s", dm_dir(), device))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return !stat(path2, &st_buf) && S_ISBLK(st_buf.st_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle the event (de)registration call and return negative error codes. */
 | 
			
		||||
static int do_event(int cmd, struct dm_event_daemon_message *msg,
 | 
			
		||||
		    char *dso_name, char *device, enum dm_event_type events,
 | 
			
		||||
		    uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_fifos fifos;
 | 
			
		||||
 | 
			
		||||
	/* FIXME Start the daemon here if it's not running e.g. exclusive lock file */
 | 
			
		||||
	/* FIXME Move this to separate 'dm_event_register_handler' - if no daemon here, fail */
 | 
			
		||||
	if (!init_client(&fifos)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -ESRCH;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Use separate 'dm_event_register_handler' function to pass in dso? */
 | 
			
		||||
	ret = daemon_talk(&fifos, msg, cmd, dso_name, device, events, timeout);
 | 
			
		||||
 | 
			
		||||
	/* what is the opposite of init? */
 | 
			
		||||
	dtr_client(&fifos);
 | 
			
		||||
	
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME remove dso_name - use handle instead */
 | 
			
		||||
/* FIXME Use uuid not path! */
 | 
			
		||||
/* External library interface. */
 | 
			
		||||
int dm_event_register(char *dso_name, char *device_path,
 | 
			
		||||
		      enum dm_event_type events)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path)) {
 | 
			
		||||
		log_error("%s: device not found", device_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ret = do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
 | 
			
		||||
			    dso_name, device_path, events, 0)) < 0) {
 | 
			
		||||
		log_error("%s: event registration failed: %s", device_path,
 | 
			
		||||
			  strerror(-ret));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_unregister(char *dso_name, char *device_path,
 | 
			
		||||
			enum dm_event_type events)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path)) {
 | 
			
		||||
		log_error("%s: device not found", device_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ret = do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
 | 
			
		||||
			    dso_name, device_path, events, 0)) < 0) {
 | 
			
		||||
		log_error("%s: event deregistration failed: %s", device_path,
 | 
			
		||||
			  strerror(-ret));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_get_registered_device(char **dso_name, char **device_path,
 | 
			
		||||
			     enum dm_event_type *events, int next)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	char *dso_name_arg = NULL, *device_path_arg = NULL;
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!(ret = do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
 | 
			
		||||
				    DM_EVENT_CMD_GET_REGISTERED_DEVICE,
 | 
			
		||||
			     &msg, *dso_name, *device_path, *events, 0)))
 | 
			
		||||
		ret = parse_message(&msg, &dso_name_arg, &device_path_arg,
 | 
			
		||||
				    events);
 | 
			
		||||
 | 
			
		||||
	if (next){
 | 
			
		||||
		if (*dso_name)
 | 
			
		||||
			dm_free(*dso_name);
 | 
			
		||||
		if (*device_path)
 | 
			
		||||
			dm_free(*device_path);
 | 
			
		||||
		*dso_name = dso_name_arg;
 | 
			
		||||
		*device_path = device_path_arg;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!(*dso_name))
 | 
			
		||||
			*dso_name = dso_name_arg;
 | 
			
		||||
		if (!(*device_path))
 | 
			
		||||
			*device_path = device_path_arg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_set_timeout(char *device_path, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path))
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	return do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
 | 
			
		||||
			NULL, device_path, 0, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_get_timeout(char *device_path, uint32_t *timeout)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_daemon_message msg;
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path))
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	if (!(ret = do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path, 0, 0)))
 | 
			
		||||
		*timeout = atoi(msg.msg);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Overrides for Emacs so that we follow Linus's tabbing style.
 | 
			
		||||
 * Emacs will notice this stuff at the end of the file and automatically
 | 
			
		||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
			
		||||
 * of the file.
 | 
			
		||||
 * ---------------------------------------------------------------------------
 | 
			
		||||
 * Local variables:
 | 
			
		||||
 * c-file-style: "linux"
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										108
									
								
								daemons/dmeventd/libdevmapper-event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								daemons/dmeventd/libdevmapper-event.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the device-mapper userspace tools.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Note that this file is released only as part of a technology preview
 | 
			
		||||
 * and its contents may change in future updates in ways that do not
 | 
			
		||||
 * preserve compatibility.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LIB_DMEVENT_H
 | 
			
		||||
#define LIB_DMEVENT_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* FIXME This stuff must be configurable. */
 | 
			
		||||
 | 
			
		||||
#define	DM_EVENT_DAEMON		"/sbin/dmeventd"
 | 
			
		||||
#define DM_EVENT_LOCKFILE	"/var/lock/dmeventd"
 | 
			
		||||
#define	DM_EVENT_FIFO_CLIENT	"/var/run/dmeventd-client"
 | 
			
		||||
#define	DM_EVENT_FIFO_SERVER	"/var/run/dmeventd-server"
 | 
			
		||||
#define DM_EVENT_PIDFILE	"/var/run/dmeventd.pid"
 | 
			
		||||
 | 
			
		||||
#define DM_EVENT_DEFAULT_TIMEOUT 10
 | 
			
		||||
 | 
			
		||||
/* Commands for the daemon passed in the message below. */
 | 
			
		||||
enum dm_event_command {
 | 
			
		||||
	DM_EVENT_CMD_ACTIVE = 1,
 | 
			
		||||
	DM_EVENT_CMD_REGISTER_FOR_EVENT,
 | 
			
		||||
	DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
 | 
			
		||||
	DM_EVENT_CMD_GET_REGISTERED_DEVICE,
 | 
			
		||||
	DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
 | 
			
		||||
	DM_EVENT_CMD_SET_TIMEOUT,
 | 
			
		||||
	DM_EVENT_CMD_GET_TIMEOUT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Message passed between client and daemon. */
 | 
			
		||||
struct dm_event_daemon_message {
 | 
			
		||||
	union {
 | 
			
		||||
		unsigned int cmd;	/* FIXME Use fixed size. */
 | 
			
		||||
		int	 status;	/* FIXME Use fixed size. */
 | 
			
		||||
	} opcode;
 | 
			
		||||
	char msg[252];		/* FIXME Why is this 252 ? */
 | 
			
		||||
} __attribute__((packed));	/* FIXME Do this properly! */
 | 
			
		||||
 | 
			
		||||
/* FIXME Is this meant to be exported?  I can't see where the interface uses it. */
 | 
			
		||||
/* Fifos for client/daemon communication. */
 | 
			
		||||
struct dm_event_fifos {
 | 
			
		||||
	int client;
 | 
			
		||||
	int server;
 | 
			
		||||
	const char *client_path;
 | 
			
		||||
	const char *server_path;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Event type definitions. */
 | 
			
		||||
/* FIXME Use masks to separate the types and provide for extension. */
 | 
			
		||||
enum dm_event_type {
 | 
			
		||||
	DM_EVENT_SINGLE		= 0x01, /* Report multiple errors just once. */
 | 
			
		||||
	DM_EVENT_MULTI		= 0x02, /* Report all of them. */
 | 
			
		||||
 | 
			
		||||
	DM_EVENT_SECTOR_ERROR	= 0x04, /* Failure on a particular sector. */
 | 
			
		||||
	DM_EVENT_DEVICE_ERROR	= 0x08, /* Device failure. */
 | 
			
		||||
	DM_EVENT_PATH_ERROR	= 0x10, /* Failure on an io path. */
 | 
			
		||||
	DM_EVENT_ADAPTOR_ERROR	= 0x20, /* Failure off a host adaptor. */
 | 
			
		||||
 | 
			
		||||
	DM_EVENT_SYNC_STATUS	= 0x40, /* Mirror synchronization completed/failed. */
 | 
			
		||||
	DM_EVENT_TIMEOUT	= 0x80, /* Timeout has occured */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* FIXME Use a mask. */
 | 
			
		||||
#define	DM_EVENT_ALL_ERRORS (DM_EVENT_SECTOR_ERROR | DM_EVENT_DEVICE_ERROR | \
 | 
			
		||||
			     DM_EVENT_PATH_ERROR | DM_EVENT_ADAPTOR_ERROR)
 | 
			
		||||
 | 
			
		||||
/* Prototypes for event lib interface. */
 | 
			
		||||
 | 
			
		||||
/* FIXME Replace device with standard name/uuid/devno choice */
 | 
			
		||||
/* Interface changes: 
 | 
			
		||||
   First register a handler, passing in a unique ref for the device. */
 | 
			
		||||
//  int dm_event_register_handler(const char *dso_name, const char *device);
 | 
			
		||||
//  int dm_event_register(const char *dso_name, const char *name, const char *uuid, uint32_t major, uint32_t minor, enum dm_event_type events);
 | 
			
		||||
/* Or (better?) add to task structure and use existing functions - run a task to register/unregister events - we may need to run task withe that with the new event mechanism anyway, then the dso calls just hook in.
 | 
			
		||||
*/
 | 
			
		||||
 
 | 
			
		||||
/* FIXME Missing consts? */
 | 
			
		||||
int dm_event_register(char *dso_name, char *device, enum dm_event_type events);
 | 
			
		||||
int dm_event_unregister(char *dso_name, char *device,
 | 
			
		||||
			enum dm_event_type events);
 | 
			
		||||
int dm_event_get_registered_device(char **dso_name, char **device,
 | 
			
		||||
				   enum dm_event_type *events, int next);
 | 
			
		||||
int dm_event_set_timeout(char *device, uint32_t timeout);
 | 
			
		||||
int dm_event_get_timeout(char *device, uint32_t *timeout);
 | 
			
		||||
 | 
			
		||||
/* Prototypes for DSO interface. */
 | 
			
		||||
void process_event(const char *device, enum dm_event_type event);
 | 
			
		||||
int register_device(const char *device);
 | 
			
		||||
int unregister_device(const char *device);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										12
									
								
								daemons/dmeventd/libdevmapper-event.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								daemons/dmeventd/libdevmapper-event.pc.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
prefix=@prefix@
 | 
			
		||||
exec_prefix=@exec_prefix@
 | 
			
		||||
libdir=@libdir@
 | 
			
		||||
includedir=@includedir@
 | 
			
		||||
 | 
			
		||||
Name: devmapper-event
 | 
			
		||||
Description: device-mapper event library
 | 
			
		||||
Version: @DM_LIB_VERSION@
 | 
			
		||||
Requires: devmapper
 | 
			
		||||
Cflags: -I${includedir}
 | 
			
		||||
Libs: -L${libdir} -ldevmapper-event
 | 
			
		||||
Libs.private: -lpthread -ldl
 | 
			
		||||
							
								
								
									
										22
									
								
								daemons/dmeventd/plugins/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								daemons/dmeventd/plugins/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
SUBDIRS += mirror
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								daemons/dmeventd/plugins/mirror/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								daemons/dmeventd/plugins/mirror/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
							
								
								
									
										36
									
								
								daemons/dmeventd/plugins/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								daemons/dmeventd/plugins/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I${top_srcdir}/tools
 | 
			
		||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_mirror.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@LIB_SUFFIX@","dylib")
 | 
			
		||||
  LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
 | 
			
		||||
else
 | 
			
		||||
  LIB_SHARED = libdevmapper-event-lvm2mirror.so
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/$<.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										254
									
								
								daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
 | 
			
		||||
 | 
			
		||||
#define ME_IGNORE    0
 | 
			
		||||
#define ME_INSYNC    1
 | 
			
		||||
#define ME_FAILURE   2
 | 
			
		||||
 | 
			
		||||
static pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
/* FIXME: We may need to lock around operations to these */
 | 
			
		||||
static int register_count = 0;
 | 
			
		||||
static struct dm_pool *mem_pool = NULL;
 | 
			
		||||
 | 
			
		||||
static int _get_mirror_event(char *params)
 | 
			
		||||
{
 | 
			
		||||
	int i, rtn = ME_INSYNC;
 | 
			
		||||
	int max_args = 30;  /* should support at least 8-way mirrors */
 | 
			
		||||
	char *args[max_args];
 | 
			
		||||
	char *dev_status_str;
 | 
			
		||||
	char *log_status_str;
 | 
			
		||||
	char *sync_str;
 | 
			
		||||
	char *p;
 | 
			
		||||
	int log_argc, num_devs, num_failures=0;
 | 
			
		||||
 | 
			
		||||
	if (max_args <= split_words(params, max_args, args)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
 | 
			
		||||
		return -E2BIG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Unused:  0 409600 mirror
 | 
			
		||||
	 * Used  :  2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
 | 
			
		||||
	*/
 | 
			
		||||
	num_devs = atoi(args[0]);
 | 
			
		||||
	dev_status_str = args[3 + num_devs];
 | 
			
		||||
	log_argc = atoi(args[4 + num_devs]);
 | 
			
		||||
	log_status_str = args[4 + num_devs + log_argc];
 | 
			
		||||
	sync_str = args[1 + num_devs];
 | 
			
		||||
 | 
			
		||||
	/* Check for bad mirror devices */
 | 
			
		||||
	for (i = 0; i < num_devs; i++) {
 | 
			
		||||
		if (dev_status_str[i] == 'D') {
 | 
			
		||||
			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
 | 
			
		||||
			num_failures++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check for bad log device */
 | 
			
		||||
	if (log_status_str[0] == 'D') {
 | 
			
		||||
		syslog(LOG_ERR, "Log device, %s, has failed.\n",
 | 
			
		||||
		       args[3 + num_devs + log_argc]);
 | 
			
		||||
		num_failures++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (num_failures) {
 | 
			
		||||
		rtn = ME_FAILURE;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p = strstr(sync_str, "/");
 | 
			
		||||
	if (p) {
 | 
			
		||||
		p[0] = '\0';
 | 
			
		||||
		if (strcmp(sync_str, p+1))
 | 
			
		||||
			rtn = ME_IGNORE;
 | 
			
		||||
		p[0] = '/';
 | 
			
		||||
	} else {
 | 
			
		||||
		/*
 | 
			
		||||
		 * How the hell did we get this?
 | 
			
		||||
		 * Might mean all our parameters are screwed.
 | 
			
		||||
		 */
 | 
			
		||||
		syslog(LOG_ERR, "Unable to parse sync string.");
 | 
			
		||||
		rtn = ME_IGNORE;
 | 
			
		||||
	}
 | 
			
		||||
 out:
 | 
			
		||||
	return rtn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _temporary_log_fn(int level, const char *file,
 | 
			
		||||
			      int line, const char *format)
 | 
			
		||||
{
 | 
			
		||||
	if (!strncmp(format, "WARNING: ", 9) && (level < 5))
 | 
			
		||||
		syslog(LOG_CRIT, "%s", format);
 | 
			
		||||
	else
 | 
			
		||||
		syslog(LOG_DEBUG, "%s", format);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _remove_failed_devices(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	void *handle;
 | 
			
		||||
	int cmd_size = 256;	/* FIXME Use system restriction */
 | 
			
		||||
	char cmd_str[cmd_size];
 | 
			
		||||
	char *vg = NULL, *lv = NULL, *layer = NULL;
 | 
			
		||||
 | 
			
		||||
	if (strlen(device) > 200)
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
 | 
			
		||||
	if (!split_dm_name(mem_pool, device, &vg, &lv, &layer)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to determine VG name from %s",
 | 
			
		||||
		       device);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Is any sanity-checking required on %s? */
 | 
			
		||||
	if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
 | 
			
		||||
		/* this error should be caught above, but doesn't hurt to check again */
 | 
			
		||||
		syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
 | 
			
		||||
		dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lvm2_log_fn(_temporary_log_fn);
 | 
			
		||||
	handle = lvm2_init();
 | 
			
		||||
	lvm2_log_level(handle, 1);
 | 
			
		||||
	r = lvm2_run(handle, cmd_str);
 | 
			
		||||
 | 
			
		||||
	dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
	return (r == 1)? 0: -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(const char *device, enum dm_event_type event)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *target_type = NULL;
 | 
			
		||||
	char *params;
 | 
			
		||||
 | 
			
		||||
	if (pthread_mutex_trylock(&_lock)) {
 | 
			
		||||
		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting...");
 | 
			
		||||
		pthread_mutex_lock(&_lock);
 | 
			
		||||
	}
 | 
			
		||||
	/* FIXME Move inside libdevmapper */
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to create dm_task.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_set_name(dmt, device)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to set device name.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_run(dmt)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to run task.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
					  &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
		if (strcmp(target_type, "mirror")) {
 | 
			
		||||
			syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch(_get_mirror_event(params)) {
 | 
			
		||||
		case ME_INSYNC:
 | 
			
		||||
			/* FIXME: all we really know is that this
 | 
			
		||||
			   _part_ of the device is in sync
 | 
			
		||||
			   Also, this is not an error
 | 
			
		||||
			*/
 | 
			
		||||
			syslog(LOG_NOTICE, "%s is now in-sync\n", device);
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_FAILURE:
 | 
			
		||||
			syslog(LOG_ERR, "Device failure in %s\n", device);
 | 
			
		||||
			if (_remove_failed_devices(device))
 | 
			
		||||
				syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
 | 
			
		||||
				       device);
 | 
			
		||||
			/* Should check before warning user that device is now linear
 | 
			
		||||
			else
 | 
			
		||||
				syslog(LOG_NOTICE, "%s is now a linear device.\n",
 | 
			
		||||
					device);
 | 
			
		||||
			*/
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_IGNORE:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			syslog(LOG_INFO, "Unknown event received.\n");
 | 
			
		||||
		}
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
	if (dmt)
 | 
			
		||||
		dm_task_destroy(dmt);
 | 
			
		||||
	pthread_mutex_unlock(&_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	syslog(LOG_INFO, "Monitoring mirror device, %s for events\n", device);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Need some space for allocations.  1024 should be more
 | 
			
		||||
	 * than enough for what we need (device mapper name splitting)
 | 
			
		||||
	 */
 | 
			
		||||
	if (!mem_pool)
 | 
			
		||||
		mem_pool = dm_pool_create("mirror_dso", 1024);
 | 
			
		||||
 | 
			
		||||
	if (!mem_pool)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	register_count++;
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	if (!(--register_count)) {
 | 
			
		||||
		dm_pool_destroy(mem_pool);
 | 
			
		||||
		mem_pool = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Overrides for Emacs so that we follow Linus's tabbing style.
 | 
			
		||||
 * Emacs will notice this stuff at the end of the file and automatically
 | 
			
		||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
			
		||||
 * of the file.
 | 
			
		||||
 * ---------------------------------------------------------------------------
 | 
			
		||||
 * Local variables:
 | 
			
		||||
 * c-file-style: "linux"
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										22
									
								
								dmeventd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								dmeventd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
SUBDIRS += mirror
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								dmeventd/mirror/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								dmeventd/mirror/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
							
								
								
									
										36
									
								
								dmeventd/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								dmeventd/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I${top_srcdir}/tools
 | 
			
		||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_mirror.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@LIB_SUFFIX@","dylib")
 | 
			
		||||
  LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
 | 
			
		||||
else
 | 
			
		||||
  LIB_SHARED = libdevmapper-event-lvm2mirror.so
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/$<.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										254
									
								
								dmeventd/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								dmeventd/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
 | 
			
		||||
 | 
			
		||||
#define ME_IGNORE    0
 | 
			
		||||
#define ME_INSYNC    1
 | 
			
		||||
#define ME_FAILURE   2
 | 
			
		||||
 | 
			
		||||
static pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
/* FIXME: We may need to lock around operations to these */
 | 
			
		||||
static int register_count = 0;
 | 
			
		||||
static struct dm_pool *mem_pool = NULL;
 | 
			
		||||
 | 
			
		||||
static int _get_mirror_event(char *params)
 | 
			
		||||
{
 | 
			
		||||
	int i, rtn = ME_INSYNC;
 | 
			
		||||
	int max_args = 30;  /* should support at least 8-way mirrors */
 | 
			
		||||
	char *args[max_args];
 | 
			
		||||
	char *dev_status_str;
 | 
			
		||||
	char *log_status_str;
 | 
			
		||||
	char *sync_str;
 | 
			
		||||
	char *p;
 | 
			
		||||
	int log_argc, num_devs, num_failures=0;
 | 
			
		||||
 | 
			
		||||
	if (max_args <= split_words(params, max_args, args)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
 | 
			
		||||
		return -E2BIG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Unused:  0 409600 mirror
 | 
			
		||||
	 * Used  :  2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
 | 
			
		||||
	*/
 | 
			
		||||
	num_devs = atoi(args[0]);
 | 
			
		||||
	dev_status_str = args[3 + num_devs];
 | 
			
		||||
	log_argc = atoi(args[4 + num_devs]);
 | 
			
		||||
	log_status_str = args[4 + num_devs + log_argc];
 | 
			
		||||
	sync_str = args[1 + num_devs];
 | 
			
		||||
 | 
			
		||||
	/* Check for bad mirror devices */
 | 
			
		||||
	for (i = 0; i < num_devs; i++) {
 | 
			
		||||
		if (dev_status_str[i] == 'D') {
 | 
			
		||||
			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
 | 
			
		||||
			num_failures++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check for bad log device */
 | 
			
		||||
	if (log_status_str[0] == 'D') {
 | 
			
		||||
		syslog(LOG_ERR, "Log device, %s, has failed.\n",
 | 
			
		||||
		       args[3 + num_devs + log_argc]);
 | 
			
		||||
		num_failures++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (num_failures) {
 | 
			
		||||
		rtn = ME_FAILURE;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p = strstr(sync_str, "/");
 | 
			
		||||
	if (p) {
 | 
			
		||||
		p[0] = '\0';
 | 
			
		||||
		if (strcmp(sync_str, p+1))
 | 
			
		||||
			rtn = ME_IGNORE;
 | 
			
		||||
		p[0] = '/';
 | 
			
		||||
	} else {
 | 
			
		||||
		/*
 | 
			
		||||
		 * How the hell did we get this?
 | 
			
		||||
		 * Might mean all our parameters are screwed.
 | 
			
		||||
		 */
 | 
			
		||||
		syslog(LOG_ERR, "Unable to parse sync string.");
 | 
			
		||||
		rtn = ME_IGNORE;
 | 
			
		||||
	}
 | 
			
		||||
 out:
 | 
			
		||||
	return rtn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _temporary_log_fn(int level, const char *file,
 | 
			
		||||
			      int line, const char *format)
 | 
			
		||||
{
 | 
			
		||||
	if (!strncmp(format, "WARNING: ", 9) && (level < 5))
 | 
			
		||||
		syslog(LOG_CRIT, "%s", format);
 | 
			
		||||
	else
 | 
			
		||||
		syslog(LOG_DEBUG, "%s", format);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _remove_failed_devices(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	void *handle;
 | 
			
		||||
	int cmd_size = 256;	/* FIXME Use system restriction */
 | 
			
		||||
	char cmd_str[cmd_size];
 | 
			
		||||
	char *vg = NULL, *lv = NULL, *layer = NULL;
 | 
			
		||||
 | 
			
		||||
	if (strlen(device) > 200)
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
 | 
			
		||||
	if (!split_dm_name(mem_pool, device, &vg, &lv, &layer)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to determine VG name from %s",
 | 
			
		||||
		       device);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Is any sanity-checking required on %s? */
 | 
			
		||||
	if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
 | 
			
		||||
		/* this error should be caught above, but doesn't hurt to check again */
 | 
			
		||||
		syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
 | 
			
		||||
		dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
		return -ENAMETOOLONG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lvm2_log_fn(_temporary_log_fn);
 | 
			
		||||
	handle = lvm2_init();
 | 
			
		||||
	lvm2_log_level(handle, 1);
 | 
			
		||||
	r = lvm2_run(handle, cmd_str);
 | 
			
		||||
 | 
			
		||||
	dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
	return (r == 1)? 0: -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(const char *device, enum dm_event_type event)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *target_type = NULL;
 | 
			
		||||
	char *params;
 | 
			
		||||
 | 
			
		||||
	if (pthread_mutex_trylock(&_lock)) {
 | 
			
		||||
		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting...");
 | 
			
		||||
		pthread_mutex_lock(&_lock);
 | 
			
		||||
	}
 | 
			
		||||
	/* FIXME Move inside libdevmapper */
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to create dm_task.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_set_name(dmt, device)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to set device name.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_run(dmt)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to run task.\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
					  &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
		if (strcmp(target_type, "mirror")) {
 | 
			
		||||
			syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch(_get_mirror_event(params)) {
 | 
			
		||||
		case ME_INSYNC:
 | 
			
		||||
			/* FIXME: all we really know is that this
 | 
			
		||||
			   _part_ of the device is in sync
 | 
			
		||||
			   Also, this is not an error
 | 
			
		||||
			*/
 | 
			
		||||
			syslog(LOG_NOTICE, "%s is now in-sync\n", device);
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_FAILURE:
 | 
			
		||||
			syslog(LOG_ERR, "Device failure in %s\n", device);
 | 
			
		||||
			if (_remove_failed_devices(device))
 | 
			
		||||
				syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
 | 
			
		||||
				       device);
 | 
			
		||||
			/* Should check before warning user that device is now linear
 | 
			
		||||
			else
 | 
			
		||||
				syslog(LOG_NOTICE, "%s is now a linear device.\n",
 | 
			
		||||
					device);
 | 
			
		||||
			*/
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_IGNORE:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			syslog(LOG_INFO, "Unknown event received.\n");
 | 
			
		||||
		}
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
	if (dmt)
 | 
			
		||||
		dm_task_destroy(dmt);
 | 
			
		||||
	pthread_mutex_unlock(&_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	syslog(LOG_INFO, "Monitoring mirror device, %s for events\n", device);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Need some space for allocations.  1024 should be more
 | 
			
		||||
	 * than enough for what we need (device mapper name splitting)
 | 
			
		||||
	 */
 | 
			
		||||
	if (!mem_pool)
 | 
			
		||||
		mem_pool = dm_pool_create("mirror_dso", 1024);
 | 
			
		||||
 | 
			
		||||
	if (!mem_pool)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	register_count++;
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	if (!(--register_count)) {
 | 
			
		||||
		dm_pool_destroy(mem_pool);
 | 
			
		||||
		mem_pool = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Overrides for Emacs so that we follow Linus's tabbing style.
 | 
			
		||||
 * Emacs will notice this stuff at the end of the file and automatically
 | 
			
		||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
			
		||||
 * of the file.
 | 
			
		||||
 * ---------------------------------------------------------------------------
 | 
			
		||||
 * Local variables:
 | 
			
		||||
 * c-file-style: "linux"
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										123
									
								
								doc/example.conf
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								doc/example.conf
									
									
									
									
									
								
							@@ -27,11 +27,18 @@ 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.
 | 
			
		||||
 | 
			
		||||
    # Don't have more than one filter line active at once: only one gets used.
 | 
			
		||||
 | 
			
		||||
    # Run vgscan after you change this parameter to ensure that
 | 
			
		||||
    # the cache file gets regenerated (see below).
 | 
			
		||||
    # If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
 | 
			
		||||
 | 
			
		||||
    # Remember to run vgscan after you change this parameter to ensure 
 | 
			
		||||
    # that the cache file gets regenerated (see below).
 | 
			
		||||
 | 
			
		||||
    # By default we accept every block device:
 | 
			
		||||
    filter = [ "a/.*/" ]
 | 
			
		||||
@@ -57,10 +64,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
 | 
			
		||||
@@ -104,6 +122,10 @@ log {
 | 
			
		||||
    #   indent = 0
 | 
			
		||||
    #   command_names = 1
 | 
			
		||||
    #   prefix = " -- "
 | 
			
		||||
 | 
			
		||||
    # Set this if you want log messages during activation.
 | 
			
		||||
    # Don't use this in low memory situations (can deadlock).
 | 
			
		||||
    # activation = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Configuration of metadata backups and archiving.  In LVM2 when we
 | 
			
		||||
@@ -167,6 +189,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".
 | 
			
		||||
@@ -200,8 +232,70 @@ activation {
 | 
			
		||||
    # target or make it return zeros.
 | 
			
		||||
    missing_stripe_filler = "/dev/ioerror"
 | 
			
		||||
 | 
			
		||||
    # How much stack (in KB) to reserve for use while devices suspended
 | 
			
		||||
    reserved_stack = 256
 | 
			
		||||
 | 
			
		||||
    # How much memory (in KB) to reserve for use while devices suspended
 | 
			
		||||
    reserved_memory = 8192
 | 
			
		||||
 | 
			
		||||
    # 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", "@*" ]
 | 
			
		||||
 | 
			
		||||
    # Size (in KB) of each copy operation when mirroring
 | 
			
		||||
    mirror_region_size = 512
 | 
			
		||||
 | 
			
		||||
    # 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
 | 
			
		||||
    # how a device failure affecting a mirror is handled.
 | 
			
		||||
    # A mirror is composed of mirror images (copies) and a log.
 | 
			
		||||
    # A disk log ensures that a mirror does not need to be re-synced
 | 
			
		||||
    # (all copies made the same) every time a machine reboots or crashes.
 | 
			
		||||
    #
 | 
			
		||||
    # In the event of a failure, the specified policy will be used to
 | 
			
		||||
    # determine what happens:
 | 
			
		||||
    #
 | 
			
		||||
    # "remove" - Simply remove the faulty device and run without it.  If
 | 
			
		||||
    #            the log device fails, the mirror would convert to using
 | 
			
		||||
    #            an in-memory log.  This means the mirror will not
 | 
			
		||||
    #            remember its sync status across crashes/reboots and
 | 
			
		||||
    #            the entire mirror will be re-synced.  If a
 | 
			
		||||
    #            mirror image fails, the mirror will convert to a
 | 
			
		||||
    #            non-mirrored device if there is only one remaining good
 | 
			
		||||
    #            copy.
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate" - Remove the faulty device and try to allocate space on
 | 
			
		||||
    #            a new device to be a replacement for the failed device.
 | 
			
		||||
    #            Using this policy for the log is fast and maintains the
 | 
			
		||||
    #            ability to remember sync state through crashes/reboots.
 | 
			
		||||
    #            Using this policy for a mirror device is slow, as it
 | 
			
		||||
    #            requires the mirror to resynchronize the devices, but it
 | 
			
		||||
    #            will preserve the mirror characteristic of the device.
 | 
			
		||||
    #            This policy acts like "remove" if no suitable device and
 | 
			
		||||
    #            space can be allocated for the replacement.
 | 
			
		||||
    #            Currently this is not implemented properly and behaves
 | 
			
		||||
    #            similarly to:
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate_anywhere" - Operates like "allocate", but it does not
 | 
			
		||||
    #            require that the new space being allocated be on a
 | 
			
		||||
    #            device is not part of the mirror.  For a log device
 | 
			
		||||
    #            failure, this could mean that the log is allocated on
 | 
			
		||||
    #            the same device as a mirror device.  For a mirror
 | 
			
		||||
    #            device, this could mean that the mirror device is
 | 
			
		||||
    #            allocated on the same device as another mirror device.
 | 
			
		||||
    #            This policy would not be wise for mirror devices
 | 
			
		||||
    #            because it would break the redundant nature of the
 | 
			
		||||
    #            mirror.  This policy acts like "remove" if no suitable
 | 
			
		||||
    #            device and space can be allocated for the replacement.
 | 
			
		||||
 | 
			
		||||
    mirror_log_fault_policy = "allocate"
 | 
			
		||||
    mirror_device_fault_policy = "remove"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -213,11 +307,10 @@ activation {
 | 
			
		||||
#
 | 
			
		||||
# metadata {
 | 
			
		||||
    # Default number of copies of metadata to hold on each PV.  0, 1 or 2.
 | 
			
		||||
    # It's best to leave this at 2.
 | 
			
		||||
    # You might want to override it from the command line with 0 or 1 
 | 
			
		||||
    # You might want to override it from the command line with 0 
 | 
			
		||||
    # when running pvcreate on new PVs which are to be added to large VGs.
 | 
			
		||||
 | 
			
		||||
    # pvmetadatacopies = 2
 | 
			
		||||
    # pvmetadatacopies = 1
 | 
			
		||||
 | 
			
		||||
    # Approximate default size of on-disk metadata areas in sectors.
 | 
			
		||||
    # You should increase this if you have large volume groups or
 | 
			
		||||
@@ -231,7 +324,8 @@ activation {
 | 
			
		||||
    # preferably on different (non-LV) filesystems, and with no other 
 | 
			
		||||
    # on-disk metadata (pvmetadatacopies = 0). Or this can be in
 | 
			
		||||
    # addition to on-disk metadata areas.
 | 
			
		||||
    # The feature was originally added to simplify testing.
 | 
			
		||||
    # The feature was originally added to simplify testing and is not
 | 
			
		||||
    # supported under low memory situations - the machine could lock up.
 | 
			
		||||
    #
 | 
			
		||||
    # Never edit any files in these directories by hand unless you
 | 
			
		||||
    # you are absolutely sure you know what you are doing! Use
 | 
			
		||||
@@ -240,4 +334,15 @@ activation {
 | 
			
		||||
    # dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
 | 
			
		||||
#}
 | 
			
		||||
 | 
			
		||||
# Event daemon
 | 
			
		||||
#
 | 
			
		||||
# dmeventd {
 | 
			
		||||
    # mirror_library is the library used when monitoring a mirror device.
 | 
			
		||||
    #
 | 
			
		||||
    # "libdevmapper-event-lvm2mirror.so" attempts to recover from failures.
 | 
			
		||||
    # It removes failed devices from a volume group and reconfigures a
 | 
			
		||||
    # mirror as necessary.
 | 
			
		||||
    #
 | 
			
		||||
    # mirror_library = "libdevmapper-event-lvm2mirror.so"
 | 
			
		||||
#}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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,36 +1,49 @@
 | 
			
		||||
../daemons/clvmd/clvm.h
 | 
			
		||||
../lib/activate/activate.h
 | 
			
		||||
../lib/cache/cache.h
 | 
			
		||||
../lib/activate/targets.h
 | 
			
		||||
../lib/cache/lvmcache.h
 | 
			
		||||
../lib/commands/errors.h
 | 
			
		||||
../lib/commands/toolcontext.h
 | 
			
		||||
../lib/config/config.h
 | 
			
		||||
../lib/config/defaults.h
 | 
			
		||||
../lib/datastruct/bitset.h
 | 
			
		||||
../lib/datastruct/btree.h
 | 
			
		||||
../lib/datastruct/hash.h
 | 
			
		||||
../lib/datastruct/list.h
 | 
			
		||||
../lib/datastruct/lvm-types.h
 | 
			
		||||
../lib/datastruct/str_list.h
 | 
			
		||||
../lib/device/dev-cache.h
 | 
			
		||||
../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/format1/lvm1-label.h
 | 
			
		||||
../lib/format_pool/format_pool.h
 | 
			
		||||
../lib/format_text/archiver.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/mm/dbg_malloc.h
 | 
			
		||||
../lib/mm/pool.h
 | 
			
		||||
../lib/metadata/pv_alloc.h
 | 
			
		||||
../lib/metadata/segtype.h
 | 
			
		||||
../lib/mm/memlock.h
 | 
			
		||||
../lib/mm/xlate.h
 | 
			
		||||
../lib/misc/configure.h
 | 
			
		||||
../lib/misc/crc.h
 | 
			
		||||
../lib/misc/intl.h
 | 
			
		||||
../lib/misc/lib.h
 | 
			
		||||
../lib/misc/lvm-exec.h
 | 
			
		||||
../lib/misc/lvm-file.h
 | 
			
		||||
../lib/misc/lvm-string.h
 | 
			
		||||
../lib/misc/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
 | 
			
		||||
@@ -35,9 +33,13 @@ distclean:
 | 
			
		||||
	find . -maxdepth 1 -type l -exec $(RM) \{\} \;
 | 
			
		||||
	$(RM) Makefile .include_symlinks .symlinks_created
 | 
			
		||||
 | 
			
		||||
pofile: all
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
 | 
			
		||||
.PHONY: clean distclean all install
 | 
			
		||||
install_cluster:
 | 
			
		||||
 | 
			
		||||
cflow:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										100
									
								
								lib/Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								lib/Makefile.in
									
									
									
									
									
								
							@@ -1,8 +1,16 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001 Sistina Software (UK) Limited
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 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,28 +20,46 @@ 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/cache.c \
 | 
			
		||||
	cache/lvmcache.c \
 | 
			
		||||
	commands/toolcontext.c \
 | 
			
		||||
	config/config.c \
 | 
			
		||||
	datastruct/bitset.c \
 | 
			
		||||
	datastruct/btree.c \
 | 
			
		||||
	datastruct/hash.c \
 | 
			
		||||
	datastruct/list.c \
 | 
			
		||||
	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/archiver.c \
 | 
			
		||||
	format_text/export.c \
 | 
			
		||||
	format_text/flags.c \
 | 
			
		||||
	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 \
 | 
			
		||||
@@ -44,20 +70,25 @@ SOURCES=\
 | 
			
		||||
	metadata/merge.c \
 | 
			
		||||
	metadata/metadata.c \
 | 
			
		||||
	metadata/mirror.c \
 | 
			
		||||
	metadata/pv_manip.c \
 | 
			
		||||
	metadata/pv_map.c \
 | 
			
		||||
	metadata/segtype.c \
 | 
			
		||||
	metadata/snapshot_manip.c \
 | 
			
		||||
	misc/crc.c \
 | 
			
		||||
	misc/lvm-exec.c \
 | 
			
		||||
	misc/lvm-file.c \
 | 
			
		||||
	misc/lvm-string.c \
 | 
			
		||||
	mm/pool.c \
 | 
			
		||||
	mm/memlock.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 \
 | 
			
		||||
@@ -67,29 +98,58 @@ 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 ("@DMEVENTD@", "yes")
 | 
			
		||||
  CLDFLAGS += -ldevmapper-event
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include ../make.tmpl
 | 
			
		||||
LIB_STATIC = liblvm.a
 | 
			
		||||
 | 
			
		||||
liblvm.a: $(OBJECTS)
 | 
			
		||||
	$(RM) $@
 | 
			
		||||
	$(AR) r $@ $(OBJECTS)
 | 
			
		||||
	$(RANLIB) $@
 | 
			
		||||
$(SUBDIRS): $(LIB_STATIC)
 | 
			
		||||
 | 
			
		||||
CLEAN_TARGETS += liblvm.cflow
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
liblvm.cflow: $(SOURCES)
 | 
			
		||||
	set -e; (echo -n "SOURCES += "; \
 | 
			
		||||
		 echo $(SOURCES) | \
 | 
			
		||||
		 sed "s/^/ /;s/ / $(top_srcdir)\/lib\//g;s/$$//"; \
 | 
			
		||||
		 ) > $@
 | 
			
		||||
 | 
			
		||||
cflow: liblvm.cflow
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,68 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004-2005 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"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "fs.h"
 | 
			
		||||
#include "lvm-exec.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 "filter.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
{
 | 
			
		||||
@@ -38,15 +76,31 @@ int driver_version(char *version, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
		   uint32_t *min, uint32_t *patchlevel)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
int target_present(const char *target_name)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_mirror_percent(struct logical_volume *lv, float *percent, int wait)
 | 
			
		||||
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
 | 
			
		||||
	    int with_open_count)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info, int with_open_count)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -58,10 +112,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;
 | 
			
		||||
@@ -70,10 +132,40 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
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, int exclusive)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
	       struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_release(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else				/* DEVMAPPER_SUPPORT */
 | 
			
		||||
 | 
			
		||||
@@ -89,8 +181,8 @@ void set_activation(int act)
 | 
			
		||||
		log_verbose("Activation enabled. Device-mapper kernel "
 | 
			
		||||
			    "driver will be used.");
 | 
			
		||||
	else
 | 
			
		||||
		log_verbose("Activation disabled. No device-mapper "
 | 
			
		||||
			    "interaction will be attempted.");
 | 
			
		||||
		log_print("WARNING: Activation disabled. No device-mapper "
 | 
			
		||||
			  "interaction will be attempted.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int activation(void)
 | 
			
		||||
@@ -98,37 +190,136 @@ 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_tree_node(cmd, "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())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!dm_get_library_version(version, size))
 | 
			
		||||
		return 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
	return dm_get_library_version(version, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int driver_version(char *version, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Getting driver version");
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_VERSION))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return dm_driver_version(version, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
		   uint32_t *min, uint32_t *patchlevel)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	struct dm_versions *target, *last_target;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Getting target version for %s", target_name);
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_run(dmt))
 | 
			
		||||
		log_error("Failed to get driver version");
 | 
			
		||||
	target = dm_task_get_versions(dmt);
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_get_driver_version(dmt, version, size))
 | 
			
		||||
		goto out;
 | 
			
		||||
	do {
 | 
			
		||||
		last_target = target;
 | 
			
		||||
 | 
			
		||||
	r = 1;
 | 
			
		||||
		if (!strcmp(target_name, target->name)) {
 | 
			
		||||
			r = 1;
 | 
			
		||||
			*maj = target->version[0];
 | 
			
		||||
			*min = target->version[1];
 | 
			
		||||
			*patchlevel = target->version[2];
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		target = (void *) target + target->next;
 | 
			
		||||
	} while (last_target != target);
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
@@ -136,25 +327,57 @@ int driver_version(char *version, size_t size)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if info structure populated, else 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
 | 
			
		||||
int target_present(const char *target_name, int use_modprobe)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
	struct dm_info dminfo;
 | 
			
		||||
	uint32_t maj, min, patchlevel;
 | 
			
		||||
#ifdef MODPROBE_CMD
 | 
			
		||||
	char module[128];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
#ifdef MODPROBE_CMD
 | 
			
		||||
	if (use_modprobe) {
 | 
			
		||||
		if (target_version(target_name, &maj, &min, &patchlevel))
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_info(dm, lv, &dminfo)))
 | 
			
		||||
		stack;
 | 
			
		||||
		if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
 | 
			
		||||
		    < 0) {
 | 
			
		||||
			log_error("target_present module name too long: %s",
 | 
			
		||||
				  target_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!exec_cmd(MODPROBE_CMD, module, "", ""))
 | 
			
		||||
			return_0;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return target_version(target_name, &maj, &min, &patchlevel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if info structure populated, else 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int with_mknodes,
 | 
			
		||||
		    struct lvinfo *info, int with_open_count)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_info dminfo;
 | 
			
		||||
	char *name;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	log_debug("Getting device info for %s", name);
 | 
			
		||||
	if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
 | 
			
		||||
			      with_open_count, &dminfo)) {
 | 
			
		||||
		dm_pool_free(cmd->mem, name);
 | 
			
		||||
		return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->exists = dminfo.exists;
 | 
			
		||||
	info->suspended = dminfo.suspended;
 | 
			
		||||
@@ -162,15 +385,34 @@ int lv_info(const struct logical_volume *lv, struct lvinfo *info)
 | 
			
		||||
	info->major = dminfo.major;
 | 
			
		||||
	info->minor = dminfo.minor;
 | 
			
		||||
	info->read_only = dminfo.read_only;
 | 
			
		||||
	info->live_table = dminfo.live_table;
 | 
			
		||||
	info->inactive_table = dminfo.inactive_table;
 | 
			
		||||
 | 
			
		||||
	dev_manager_destroy(dm);
 | 
			
		||||
	return r;
 | 
			
		||||
	dm_pool_free(cmd->mem, name);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
 | 
			
		||||
	    int with_open_count)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_info(cmd, lv, 0, info, with_open_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info, int with_open_count)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return _lv_info(cmd, lv, 0, info, with_open_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if percent set, else 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
@@ -178,10 +420,8 @@ 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))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -192,19 +432,24 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Merge with snapshot_percent */
 | 
			
		||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr)
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr)
 | 
			
		||||
{
 | 
			
		||||
	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))) {
 | 
			
		||||
		stack;
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!info.exists)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -214,11 +459,11 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_active(struct logical_volume *lv)
 | 
			
		||||
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -226,11 +471,11 @@ static int _lv_active(struct logical_volume *lv)
 | 
			
		||||
	return info.exists;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_open_count(struct logical_volume *lv)
 | 
			
		||||
static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 1)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -238,16 +483,13 @@ static int _lv_open_count(struct logical_volume *lv)
 | 
			
		||||
	return info.open_count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_activate(dm, lv)))
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -256,15 +498,28 @@ static int _lv_activate(struct logical_volume *lv)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_preload(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_preload(dm, lv)))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	dev_manager_destroy(dm);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_deactivate(dm, lv)))
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -273,17 +528,15 @@ 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 lockfs)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_suspend(dm, lv)))
 | 
			
		||||
	if (!(r = dev_manager_suspend(dm, lv, lockfs)))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	dev_manager_destroy(dm);
 | 
			
		||||
@@ -291,21 +544,20 @@ 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)
 | 
			
		||||
{
 | 
			
		||||
	struct list *lvh;
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	list_iterate(lvh, &vg->lvs) {
 | 
			
		||||
		lv = list_item(lvh, struct lv_list)->lv;
 | 
			
		||||
		count += (_lv_active(lv) == 1);
 | 
			
		||||
	list_iterate_items(lvl, &vg->lvs) {
 | 
			
		||||
		if (lvl->lv->status & VISIBLE_LV)
 | 
			
		||||
			count += (_lv_active(vg->cmd, lvl->lv) == 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return count;
 | 
			
		||||
@@ -313,53 +565,140 @@ int lvs_in_vg_activated(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
int lvs_in_vg_opened(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *lvh;
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	list_iterate(lvh, &vg->lvs) {
 | 
			
		||||
		lv = list_item(lvh, struct lv_list)->lv;
 | 
			
		||||
		count += (_lv_open_count(lv) == 1);
 | 
			
		||||
	list_iterate_items(lvl, &vg->lvs) {
 | 
			
		||||
		if (lvl->lv->status & VISIBLE_LV)
 | 
			
		||||
			count += (_lv_open_count(vg->cmd, lvl->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)
 | 
			
		||||
/*
 | 
			
		||||
 * register_dev_for_events
 | 
			
		||||
 *
 | 
			
		||||
 * This function uses proper error codes (but breaks convention)
 | 
			
		||||
 * to return:
 | 
			
		||||
 *      -1 on error
 | 
			
		||||
 *       0 if the lv's targets don't do event [un]registration
 | 
			
		||||
 *       0 if the lv is already [un]registered -- FIXME: not implemented
 | 
			
		||||
 *       1 if the lv had a segment which was [un]registered
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: -1 on error
 | 
			
		||||
 */
 | 
			
		||||
int register_dev_for_events(struct cmd_context *cmd,
 | 
			
		||||
			    struct logical_volume *lv, int do_reg)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
#ifdef DMEVENTD
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct list *tmp;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	int (*reg) (struct lv_segment *, int events);
 | 
			
		||||
 | 
			
		||||
	if (do_reg && !dmeventd_register_mode())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	list_iterate(tmp, &lv->segments) {
 | 
			
		||||
		seg = list_item(tmp, struct lv_segment);
 | 
			
		||||
 | 
			
		||||
		reg = NULL;
 | 
			
		||||
 | 
			
		||||
		if (do_reg) {
 | 
			
		||||
			if (seg->segtype->ops->target_register_events)
 | 
			
		||||
				reg = seg->segtype->ops->target_register_events;
 | 
			
		||||
		} else if (seg->segtype->ops->target_unregister_events)
 | 
			
		||||
			reg = seg->segtype->ops->target_unregister_events;
 | 
			
		||||
 | 
			
		||||
		if (!reg)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* FIXME specify events */
 | 
			
		||||
		if (!reg(seg, 0)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		r = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
#else
 | 
			
		||||
	return 1;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		       int error_if_not_suspended)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv, *lv_pre;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int lockfs = 0;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
	/* Use precommitted metadata if present */
 | 
			
		||||
	if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
		_skip("Suspending '%s'.", lv->name);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!info.exists || info.suspended)
 | 
			
		||||
		return error_if_not_suspended ? 0 : 1;
 | 
			
		||||
 | 
			
		||||
	/* If VG was precommitted, preload devices for the LV */
 | 
			
		||||
	if ((lv_pre->vg->status & PRECOMMITTED)) {
 | 
			
		||||
		if (!_lv_preload(lv_pre)) {
 | 
			
		||||
			/* FIXME Revert preloading */
 | 
			
		||||
			return_0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info.exists && !info.suspended)
 | 
			
		||||
		return _lv_suspend(lv);
 | 
			
		||||
	if (register_dev_for_events(cmd, lv, 0) != 1)
 | 
			
		||||
		/* FIXME Consider aborting here */
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
 | 
			
		||||
	if (lv_is_origin(lv_pre) || lv_is_cow(lv_pre))
 | 
			
		||||
		lockfs = 1;
 | 
			
		||||
 | 
			
		||||
	if (!_lv_suspend_lv(lv, lockfs)) {
 | 
			
		||||
		memlock_dec();
 | 
			
		||||
		fs_unlock();
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
@@ -367,7 +706,7 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s)))
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
@@ -375,26 +714,45 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (info.exists && info.suspended)
 | 
			
		||||
		return _lv_activate(lv);
 | 
			
		||||
	if (!info.exists || !info.suspended)
 | 
			
		||||
		return error_if_not_active ? 0 : 1;
 | 
			
		||||
 | 
			
		||||
	if (!_lv_activate_lv(lv))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	if (register_dev_for_events(cmd, lv, 1) != 1)
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s)))
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
@@ -402,42 +760,156 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
		stack;
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 1))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!info.exists)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info.open_count && (lv->status & VISIBLE_LV)) {
 | 
			
		||||
		log_error("LV %s/%s in use: not deactivating", lv->vg->name,
 | 
			
		||||
			  lv->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info.exists)
 | 
			
		||||
		return _lv_deactivate(lv);
 | 
			
		||||
	if (register_dev_for_events(cmd, lv, 0) != 1)
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	r = _lv_deactivate(lv);
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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, 0)))
 | 
			
		||||
		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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
			int exclusive, int filter)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s)))
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(lv, &info)) {
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (info.exists && !info.suspended && info.live_table)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (exclusive)
 | 
			
		||||
		lv->status |= ACTIVATE_EXCL;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	r = _lv_activate_lv(lv);
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	if (!register_dev_for_events(cmd, lv, 1) != 1)
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!info.exists || info.suspended)
 | 
			
		||||
		return _lv_activate(lv);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Activate LV */
 | 
			
		||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_activate(cmd, lvid_s, exclusive, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Activate LV only if it passes filter */
 | 
			
		||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_activate(cmd, lvid_s, exclusive, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
	if (!lv) {
 | 
			
		||||
		r = dm_mknodes(NULL);
 | 
			
		||||
		fs_unlock();
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_lv_info(cmd, lv, 1, &info, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (info.exists)
 | 
			
		||||
		r = dev_manager_lv_mknodes(lv);
 | 
			
		||||
	else
 | 
			
		||||
		r = dev_manager_lv_rmnodes(lv);
 | 
			
		||||
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Does PV use VG somewhere in its construction?
 | 
			
		||||
 * Returns 1 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int pv_uses_vg(struct physical_volume *pv,
 | 
			
		||||
	       struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return dev_manager_device_uses_vg(pv->dev, vg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_release(void)
 | 
			
		||||
{
 | 
			
		||||
	dev_manager_release();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	dev_manager_exit();
 | 
			
		||||
}
 | 
			
		||||
#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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LVM_ACTIVATE_H
 | 
			
		||||
@@ -9,10 +18,6 @@
 | 
			
		||||
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
#  include <libdevmapper.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct lvinfo {
 | 
			
		||||
	int exists;
 | 
			
		||||
	int suspended;
 | 
			
		||||
@@ -20,6 +25,8 @@ struct lvinfo {
 | 
			
		||||
	int major;
 | 
			
		||||
	int minor;
 | 
			
		||||
	int read_only;
 | 
			
		||||
	int live_table;
 | 
			
		||||
	int inactive_table;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void set_activation(int activation);
 | 
			
		||||
@@ -27,22 +34,46 @@ 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, int use_modprobe);
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
                   uint32_t *min, uint32_t *patchlevel);
 | 
			
		||||
 | 
			
		||||
void activation_release(void);
 | 
			
		||||
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(struct cmd_context *cmd, const char *lvid_s, int exclusive);
 | 
			
		||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
			    int exclusive);
 | 
			
		||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
 | 
			
		||||
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(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
 | 
			
		||||
	    int with_open_count);
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info, int with_open_count);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
 | 
			
		||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr);
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return number of LVs in the VG that are active.
 | 
			
		||||
@@ -50,6 +81,14 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
int lvs_in_vg_activated(struct volume_group *vg);
 | 
			
		||||
int lvs_in_vg_opened(struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
int lv_setup_cow_store(struct logical_volume *lv);
 | 
			
		||||
 | 
			
		||||
int register_dev_for_events(struct cmd_context *cmd,
 | 
			
		||||
			    struct logical_volume *lv, int do_reg);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if PV has a dependency tree that uses anything in VG.
 | 
			
		||||
 */
 | 
			
		||||
int pv_uses_vg(struct physical_volume *pv,
 | 
			
		||||
	       struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,24 +1,36 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 volume_group;
 | 
			
		||||
struct cmd_context;
 | 
			
		||||
struct dev_manager;
 | 
			
		||||
struct dm_info;
 | 
			
		||||
struct device;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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_release(void);
 | 
			
		||||
void dev_manager_exit(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The device handler is responsible for creating all the layered
 | 
			
		||||
@@ -26,20 +38,30 @@ void dev_manager_destroy(struct dev_manager *dm);
 | 
			
		||||
 * (eg, an origin is created before its snapshot, but is not
 | 
			
		||||
 * unsuspended until the snapshot is also created.)
 | 
			
		||||
 */
 | 
			
		||||
int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
 | 
			
		||||
		     struct dm_info *info);
 | 
			
		||||
int dev_manager_info(struct dm_pool *mem, const char *name,
 | 
			
		||||
		     const struct logical_volume *lv,
 | 
			
		||||
		     int mknodes, int with_open_count, struct dm_info *info);
 | 
			
		||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
 | 
			
		||||
				 struct logical_volume *lv, float *percent);
 | 
			
		||||
				 const struct logical_volume *lv,
 | 
			
		||||
				 float *percent);
 | 
			
		||||
int dev_manager_mirror_percent(struct dev_manager *dm,
 | 
			
		||||
			       struct logical_volume *lv, int wait,
 | 
			
		||||
			       float *percent, uint32_t *event_nr);
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
 | 
			
		||||
			int lockfs);
 | 
			
		||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
 | 
			
		||||
int dev_manager_lv_mknodes(const struct logical_volume *lv);
 | 
			
		||||
int dev_manager_lv_rmnodes(const struct logical_volume *lv);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Put the desired changes into effect.
 | 
			
		||||
 */
 | 
			
		||||
int dev_manager_execute(struct dev_manager *dm);
 | 
			
		||||
 | 
			
		||||
int dev_manager_device_uses_vg(struct device *dev,
 | 
			
		||||
			       struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
#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,20 +18,20 @@
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "lvm-file.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
 | 
			
		||||
static int _mk_dir(struct volume_group *vg)
 | 
			
		||||
static int _mk_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 vg->cmd->dev_dir, vg->name) == -1) {
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't construct name of volume "
 | 
			
		||||
			  "group directory.");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -32,7 +41,7 @@ static int _mk_dir(struct volume_group *vg)
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
@@ -40,21 +49,21 @@ static int _mk_dir(struct volume_group *vg)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _rm_dir(struct volume_group *vg)
 | 
			
		||||
static int _rm_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 vg->cmd->dev_dir, vg->name) == -1) {
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't construct name of volume "
 | 
			
		||||
			  "group directory.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Removing directory %s", vg_path);
 | 
			
		||||
 | 
			
		||||
	if (is_empty_dir(vg_path))
 | 
			
		||||
	if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
 | 
			
		||||
		log_very_verbose("Removing directory %s", vg_path);
 | 
			
		||||
		rmdir(vg_path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -93,37 +102,38 @@ static void _rm_blks(const char *dir)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _mk_link(struct logical_volume *lv, const char *dev)
 | 
			
		||||
static int _mk_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
		    const char *lv_name, const char *dev)
 | 
			
		||||
{
 | 
			
		||||
	char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX];
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 lv->vg->cmd->dev_dir, lv->vg->name) == -1) {
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't create path for volume group dir %s",
 | 
			
		||||
			  lv->vg->name);
 | 
			
		||||
			  vg_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
 | 
			
		||||
			 lv->name) == -1) {
 | 
			
		||||
			 lv_name) == -1) {
 | 
			
		||||
		log_error("Couldn't create source pathname for "
 | 
			
		||||
			  "logical volume link %s", lv->name);
 | 
			
		||||
			  "logical volume link %s", lv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
 | 
			
		||||
			 dm_dir(), dev) == -1) {
 | 
			
		||||
		log_error("Couldn't create destination pathname for "
 | 
			
		||||
			  "logical volume link for %s", lv->name);
 | 
			
		||||
			  "logical volume link for %s", lv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
 | 
			
		||||
			 vg_path) == -1) {
 | 
			
		||||
		log_error("Couldn't create pathname for LVM1 group file for %s",
 | 
			
		||||
			  lv->vg->name);
 | 
			
		||||
			  vg_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -164,21 +174,31 @@ static int _mk_link(struct logical_volume *lv, const char *dev)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SELINUX
 | 
			
		||||
        if (!dm_set_selinux_context(lv_path, S_IFLNK)) {
 | 
			
		||||
                stack;
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _rm_link(struct logical_volume *lv, const char *lv_name)
 | 
			
		||||
static int _rm_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
		    const char *lv_name)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	char lv_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
 | 
			
		||||
			 lv->vg->cmd->dev_dir, lv->vg->name, lv_name) == -1) {
 | 
			
		||||
			 dev_dir, vg_name, lv_name) == -1) {
 | 
			
		||||
		log_error("Couldn't determine link pathname.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
 | 
			
		||||
		if (errno == ENOENT)
 | 
			
		||||
			return 1;
 | 
			
		||||
		log_error("%s not symbolic link - not removing", lv_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -192,35 +212,143 @@ static int _rm_link(struct logical_volume *lv, const char *lv_name)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_add_lv(struct logical_volume *lv, const char *dev)
 | 
			
		||||
typedef enum {
 | 
			
		||||
	FS_ADD,
 | 
			
		||||
	FS_DEL,
 | 
			
		||||
	FS_RENAME
 | 
			
		||||
} fs_op_t;
 | 
			
		||||
 | 
			
		||||
static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
 | 
			
		||||
		     const char *lv_name, const char *dev,
 | 
			
		||||
		     const char *old_lv_name)
 | 
			
		||||
{
 | 
			
		||||
	if (!_mk_dir(lv->vg) || !_mk_link(lv, dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case FS_ADD:
 | 
			
		||||
		if (!_mk_dir(dev_dir, vg_name) ||
 | 
			
		||||
		    !_mk_link(dev_dir, vg_name, lv_name, dev)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case FS_DEL:
 | 
			
		||||
		if (!_rm_link(dev_dir, vg_name, lv_name) ||
 | 
			
		||||
		    !_rm_dir(dev_dir, vg_name)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
		/* FIXME Use rename() */
 | 
			
		||||
	case FS_RENAME:
 | 
			
		||||
		if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name))
 | 
			
		||||
			stack;
 | 
			
		||||
 | 
			
		||||
		if (!_mk_link(dev_dir, vg_name, lv_name, dev))
 | 
			
		||||
			stack;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_del_lv(struct logical_volume *lv)
 | 
			
		||||
static LIST_INIT(_fs_ops);
 | 
			
		||||
 | 
			
		||||
struct fs_op_parms {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	fs_op_t type;
 | 
			
		||||
	char *dev_dir;
 | 
			
		||||
	char *vg_name;
 | 
			
		||||
	char *lv_name;
 | 
			
		||||
	char *dev;
 | 
			
		||||
	char *old_lv_name;
 | 
			
		||||
	char names[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void _store_str(char **pos, char **ptr, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	if (!_rm_link(lv, lv->name) || !_rm_dir(lv->vg)) {
 | 
			
		||||
		stack;
 | 
			
		||||
	strcpy(*pos, str);
 | 
			
		||||
	*ptr = *pos;
 | 
			
		||||
	*pos += strlen(*ptr) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
 | 
			
		||||
			const char *lv_name, const char *dev,
 | 
			
		||||
			const char *old_lv_name)
 | 
			
		||||
{
 | 
			
		||||
	struct fs_op_parms *fsp;
 | 
			
		||||
	size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) +
 | 
			
		||||
	    strlen(dev) + strlen(old_lv_name) + 5;
 | 
			
		||||
	char *pos;
 | 
			
		||||
 | 
			
		||||
	if (!(fsp = dm_malloc(sizeof(*fsp) + len))) {
 | 
			
		||||
		log_error("No space to stack fs operation");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pos = fsp->names;
 | 
			
		||||
	fsp->type = type;
 | 
			
		||||
 | 
			
		||||
	_store_str(&pos, &fsp->dev_dir, dev_dir);
 | 
			
		||||
	_store_str(&pos, &fsp->vg_name, vg_name);
 | 
			
		||||
	_store_str(&pos, &fsp->lv_name, lv_name);
 | 
			
		||||
	_store_str(&pos, &fsp->dev, dev);
 | 
			
		||||
	_store_str(&pos, &fsp->old_lv_name, old_lv_name);
 | 
			
		||||
 | 
			
		||||
	list_add(&_fs_ops, &fsp->list);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Use rename() */
 | 
			
		||||
static void _pop_fs_ops(void)
 | 
			
		||||
{
 | 
			
		||||
	struct list *fsph, *fspht;
 | 
			
		||||
	struct fs_op_parms *fsp;
 | 
			
		||||
 | 
			
		||||
	list_iterate_safe(fsph, fspht, &_fs_ops) {
 | 
			
		||||
		fsp = list_item(fsph, struct fs_op_parms);
 | 
			
		||||
		_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
 | 
			
		||||
			  fsp->dev, fsp->old_lv_name);
 | 
			
		||||
		list_del(&fsp->list);
 | 
			
		||||
		dm_free(fsp);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
 | 
			
		||||
		  const char *lv_name, const char *dev, const char *old_lv_name)
 | 
			
		||||
{
 | 
			
		||||
	if (memlock()) {
 | 
			
		||||
		if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
 | 
			
		||||
				  old_lv_name)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_add_lv(const struct logical_volume *lv, const char *dev)
 | 
			
		||||
{
 | 
			
		||||
	return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
 | 
			
		||||
		      dev, "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_del_lv(const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
 | 
			
		||||
		      "", "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_rename_lv(struct logical_volume *lv,
 | 
			
		||||
		 const char *dev, const char *old_name)
 | 
			
		||||
{
 | 
			
		||||
	if (old_name && !_rm_link(lv, old_name))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	if (!_mk_link(lv, dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
	return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
 | 
			
		||||
		      dev, old_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fs_unlock(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!memlock()) {
 | 
			
		||||
		dm_lib_release();
 | 
			
		||||
		_pop_fs_ops();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -14,9 +23,10 @@
 | 
			
		||||
 * up the volume group directory in /dev and the
 | 
			
		||||
 * symbolic links to the dm device.
 | 
			
		||||
 */
 | 
			
		||||
int fs_add_lv(struct logical_volume *lv, const char *dev);
 | 
			
		||||
int fs_del_lv(struct logical_volume *lv);
 | 
			
		||||
int fs_add_lv(const struct logical_volume *lv, const char *dev);
 | 
			
		||||
int fs_del_lv(const struct logical_volume *lv);
 | 
			
		||||
int fs_rename_lv(struct logical_volume *lv,
 | 
			
		||||
		 const char *dev, const char *old_name);
 | 
			
		||||
void fs_unlock(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								lib/activate/targets.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								lib/activate/targets.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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);
 | 
			
		||||
 | 
			
		||||
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
                   struct dm_tree_node *node, uint32_t start_area, uint32_t areas);
 | 
			
		||||
 | 
			
		||||
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
 | 
			
		||||
		     size_t bufsize, const char *desc);
 | 
			
		||||
 | 
			
		||||
char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										521
									
								
								lib/cache/cache.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										521
									
								
								lib/cache/cache.c
									
									
									
									
										vendored
									
									
								
							@@ -1,521 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "cache.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
 | 
			
		||||
static struct hash_table *_pvid_hash = NULL;
 | 
			
		||||
static struct hash_table *_vgid_hash = NULL;
 | 
			
		||||
static struct hash_table *_vgname_hash = NULL;
 | 
			
		||||
static struct list _vginfos;
 | 
			
		||||
int _has_scanned = 0;
 | 
			
		||||
 | 
			
		||||
int cache_init(void)
 | 
			
		||||
{
 | 
			
		||||
	list_init(&_vginfos);
 | 
			
		||||
 | 
			
		||||
	if (!(_vgname_hash = hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(_vgid_hash = hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(_pvid_hash = hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cache_vginfo *vginfo_from_vgname(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = hash_lookup(_vgname_hash, vgname)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return vginfo->fmt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cache_vginfo *vginfo_from_vgid(const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
	char id[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_vgid_hash || !vgid)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	/* vgid not necessarily NULL-terminated */
 | 
			
		||||
	strncpy(&id[0], vgid, ID_LEN);
 | 
			
		||||
	id[ID_LEN] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = hash_lookup(_vgid_hash, id)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cache_info *info_from_pvid(const char *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	char id[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_pvid_hash || !pvid)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	strncpy(&id[0], pvid, ID_LEN);
 | 
			
		||||
	id[ID_LEN] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (!(info = hash_lookup(_pvid_hash, id)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _rescan_entry(struct cache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
 | 
			
		||||
	if (info->status & CACHE_INVALID)
 | 
			
		||||
		label_read(info->dev, &label);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _scan_invalid(void)
 | 
			
		||||
{
 | 
			
		||||
	hash_iter(_pvid_hash, (iterate_fn) _rescan_entry);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct dev_iter *iter;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	struct list *fmth;
 | 
			
		||||
	struct format_type *fmt;
 | 
			
		||||
 | 
			
		||||
	static int _scanning_in_progress = 0;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	/* Avoid recursion when a PVID can't be found! */
 | 
			
		||||
	if (_scanning_in_progress)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	_scanning_in_progress = 1;
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash && !cache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_has_scanned && !full_scan) {
 | 
			
		||||
		r = _scan_invalid();
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(iter = dev_iter_create(cmd->filter))) {
 | 
			
		||||
		log_error("dev_iter creation failed");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while ((dev = dev_iter_get(iter)))
 | 
			
		||||
		label_read(dev, &label);
 | 
			
		||||
 | 
			
		||||
	dev_iter_destroy(iter);
 | 
			
		||||
 | 
			
		||||
	_has_scanned = 1;
 | 
			
		||||
 | 
			
		||||
	/* Perform any format-specific scanning e.g. text files */
 | 
			
		||||
	list_iterate(fmth, &cmd->formats) {
 | 
			
		||||
		fmt = list_item(fmth, struct format_type);
 | 
			
		||||
		if (fmt->ops->scan && !fmt->ops->scan(fmt))
 | 
			
		||||
			goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	_scanning_in_progress = 0;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *vgih, *vgnames;
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
	cache_label_scan(cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
	if (!(vgnames = pool_alloc(cmd->mem, sizeof(struct list)))) {
 | 
			
		||||
		log_error("vgnames list allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(vgnames);
 | 
			
		||||
 | 
			
		||||
	list_iterate(vgih, &_vginfos) {
 | 
			
		||||
		if (!(sl = pool_alloc(cmd->mem, sizeof(*sl)))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(sl->str = pool_strdup(cmd->mem,
 | 
			
		||||
					    list_item(vgih,
 | 
			
		||||
						      struct cache_vginfo)->
 | 
			
		||||
					    vgname))) {
 | 
			
		||||
			log_error("vgname allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		list_add(vgnames, &sl->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vgnames;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
 | 
			
		||||
	/* Already cached ? */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct cache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cache_label_scan(cmd, 0);
 | 
			
		||||
 | 
			
		||||
	/* Try again */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct cache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cache_label_scan(cmd, 1);
 | 
			
		||||
 | 
			
		||||
	/* Try again */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct cache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _drop_vginfo(struct cache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!list_empty(&info->list)) {
 | 
			
		||||
		list_del(&info->list);
 | 
			
		||||
		list_init(&info->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && list_empty(&info->vginfo->infos)) {
 | 
			
		||||
		hash_remove(_vgname_hash, info->vginfo->vgname);
 | 
			
		||||
		if (info->vginfo->vgname)
 | 
			
		||||
			dbg_free(info->vginfo->vgname);
 | 
			
		||||
		if (*info->vginfo->vgid)
 | 
			
		||||
			hash_remove(_vgid_hash, info->vginfo->vgid);
 | 
			
		||||
		list_del(&info->vginfo->list);
 | 
			
		||||
		dbg_free(info->vginfo);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->vginfo = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unused
 | 
			
		||||
void cache_del(struct cache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (info->dev->pvid[0] && _pvid_hash)
 | 
			
		||||
		hash_remove(_pvid_hash, info->dev->pvid);
 | 
			
		||||
 | 
			
		||||
	_drop_vginfo(info);
 | 
			
		||||
 | 
			
		||||
	info->label->labeller->ops->destroy_label(info->label->labeller,
 | 
			
		||||
						info->label); 
 | 
			
		||||
	dbg_free(info);
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
} */
 | 
			
		||||
 | 
			
		||||
static int _cache_update_pvid(struct cache_info *info, const char *pvid)
 | 
			
		||||
{
 | 
			
		||||
	if (!strcmp(info->dev->pvid, pvid))
 | 
			
		||||
		return 1;
 | 
			
		||||
	if (*info->dev->pvid) {
 | 
			
		||||
		hash_remove(_pvid_hash, info->dev->pvid);
 | 
			
		||||
	}
 | 
			
		||||
	strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
 | 
			
		||||
	if (!hash_insert(_pvid_hash, pvid, info)) {
 | 
			
		||||
		log_error("_cache_update: pvid insertion failed: %s", pvid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cache_update_vgid(struct cache_info *info, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid,
 | 
			
		||||
					       sizeof(info->vginfo->vgid)))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && *info->vginfo->vgid)
 | 
			
		||||
		hash_remove(_vgid_hash, info->vginfo->vgid);
 | 
			
		||||
	if (!vgid)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
 | 
			
		||||
	info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
 | 
			
		||||
	if (!hash_insert(_vgid_hash, vgid, info->vginfo)) {
 | 
			
		||||
		log_error("_cache_update: vgid hash insertion failed: %s",
 | 
			
		||||
			  vgid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cache_update_vgname(struct cache_info *info, const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	struct cache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	/* If vgname is NULL and we don't already have a vgname, 
 | 
			
		||||
	 * assume ORPHAN - we want every entry to have a vginfo
 | 
			
		||||
	 * attached for scanning reasons.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!vgname && !info->vginfo)
 | 
			
		||||
		vgname = ORPHAN;
 | 
			
		||||
 | 
			
		||||
	if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/* Remove existing vginfo entry */
 | 
			
		||||
	_drop_vginfo(info);
 | 
			
		||||
 | 
			
		||||
	/* Get existing vginfo or create new one */
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname))) {
 | 
			
		||||
		if (!(vginfo = dbg_malloc(sizeof(*vginfo)))) {
 | 
			
		||||
			log_error("cache_update_vgname: list alloc failed");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		memset(vginfo, 0, sizeof(*vginfo));
 | 
			
		||||
		if (!(vginfo->vgname = dbg_strdup(vgname))) {
 | 
			
		||||
			dbg_free(vginfo);
 | 
			
		||||
			log_error("cache vgname alloc failed for %s", vgname);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		list_init(&vginfo->infos);
 | 
			
		||||
		if (!hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
 | 
			
		||||
			log_error("cache_update: vg hash insertion failed: %s",
 | 
			
		||||
				  vginfo->vgname);
 | 
			
		||||
			dbg_free(vginfo->vgname);
 | 
			
		||||
			dbg_free(vginfo);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		/* Ensure orphans appear last on list_iterate */
 | 
			
		||||
		if (!*vgname)
 | 
			
		||||
			list_add(&_vginfos, &vginfo->list);
 | 
			
		||||
		else
 | 
			
		||||
			list_add_h(&_vginfos, &vginfo->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->vginfo = vginfo;
 | 
			
		||||
	list_add(&vginfo->infos, &info->list);
 | 
			
		||||
 | 
			
		||||
	/* FIXME Check consistency of list! */
 | 
			
		||||
	vginfo->fmt = info->fmt;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cache_update_vg(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *pvh;
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
	struct cache_info *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
	int vgid_updated = 0;
 | 
			
		||||
 | 
			
		||||
	pvid_s[sizeof(pvid_s) - 1] = '\0';
 | 
			
		||||
 | 
			
		||||
	list_iterate(pvh, &vg->pvs) {
 | 
			
		||||
		pv = list_item(pvh, struct pv_list)->pv;
 | 
			
		||||
		strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
 | 
			
		||||
		/* FIXME Could pv->dev->pvid ever be different? */
 | 
			
		||||
		if ((info = info_from_pvid(pvid_s))) {
 | 
			
		||||
			cache_update_vgname(info, vg->name);
 | 
			
		||||
			if (!vgid_updated) {
 | 
			
		||||
				_cache_update_vgid(info, (char *) &vg->id);
 | 
			
		||||
				vgid_updated = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
			     struct device *dev,
 | 
			
		||||
			     const char *vgname, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct cache_info *existing, *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash && !cache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strncpy(pvid_s, pvid, sizeof(pvid_s));
 | 
			
		||||
	pvid_s[sizeof(pvid_s) - 1] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (!(existing = info_from_pvid(pvid_s)) &&
 | 
			
		||||
	    !(existing = info_from_pvid(dev->pvid))) {
 | 
			
		||||
		if (!(label = label_create(labeller))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(info = dbg_malloc(sizeof(*info)))) {
 | 
			
		||||
			log_error("cache_info allocation failed");
 | 
			
		||||
			label_destroy(label);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		memset(info, 0, sizeof(*info));
 | 
			
		||||
 | 
			
		||||
		label->info = info;
 | 
			
		||||
		info->label = label;
 | 
			
		||||
		list_init(&info->list);
 | 
			
		||||
		info->dev = dev;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (existing->dev != dev) {
 | 
			
		||||
			/* Is the existing entry a duplicate pvid e.g. md ? */
 | 
			
		||||
			if (MAJOR(existing->dev->dev) == md_major() &&
 | 
			
		||||
			    MAJOR(dev->dev) != md_major()) {
 | 
			
		||||
				log_very_verbose("Ignoring duplicate PV %s on "
 | 
			
		||||
						 "%s - using md %s",
 | 
			
		||||
						 pvid, dev_name(dev),
 | 
			
		||||
						 dev_name(existing->dev));
 | 
			
		||||
				return NULL;
 | 
			
		||||
			} else if (MAJOR(existing->dev->dev) != md_major() &&
 | 
			
		||||
				   MAJOR(dev->dev) == md_major())
 | 
			
		||||
				log_very_verbose("Duplicate PV %s on %s - "
 | 
			
		||||
						 "using md %s", pvid,
 | 
			
		||||
						 dev_name(existing->dev),
 | 
			
		||||
						 dev_name(dev));
 | 
			
		||||
			else
 | 
			
		||||
				log_error("Found duplicate PV %s: using %s not "
 | 
			
		||||
					  "%s", pvid, dev_name(dev),
 | 
			
		||||
					  dev_name(existing->dev));
 | 
			
		||||
		}
 | 
			
		||||
		info = existing;
 | 
			
		||||
		/* Has labeller changed? */
 | 
			
		||||
		if (info->label->labeller != labeller) {
 | 
			
		||||
			label_destroy(info->label);
 | 
			
		||||
			if (!(info->label = label_create(labeller))) {
 | 
			
		||||
				/* FIXME leaves info without label! */
 | 
			
		||||
				stack;
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			info->label->info = info;
 | 
			
		||||
		}
 | 
			
		||||
		label = info->label;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->fmt = (const struct format_type *) labeller->private;
 | 
			
		||||
	info->status |= CACHE_INVALID;
 | 
			
		||||
 | 
			
		||||
	if (!_cache_update_pvid(info, pvid_s)) {
 | 
			
		||||
		if (!existing) {
 | 
			
		||||
			dbg_free(info);
 | 
			
		||||
			label_destroy(label);
 | 
			
		||||
		}
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!cache_update_vgname(info, vgname)) {
 | 
			
		||||
		if (!existing) {
 | 
			
		||||
			hash_remove(_pvid_hash, pvid_s);
 | 
			
		||||
			strcpy(info->dev->pvid, "");
 | 
			
		||||
			dbg_free(info);
 | 
			
		||||
			label_destroy(label);
 | 
			
		||||
		}
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_cache_update_vgid(info, vgid))
 | 
			
		||||
		/* Non-critical */
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cache_destroy_entry(struct cache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!list_empty(&info->list))
 | 
			
		||||
		list_del(&info->list);
 | 
			
		||||
	strcpy(info->dev->pvid, "");
 | 
			
		||||
	label_destroy(info->label);
 | 
			
		||||
	dbg_free(info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cache_destroy_vgnamelist(struct cache_vginfo *vginfo)
 | 
			
		||||
{
 | 
			
		||||
	if (vginfo->vgname)
 | 
			
		||||
		dbg_free(vginfo->vgname);
 | 
			
		||||
	dbg_free(vginfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cache_destroy(void)
 | 
			
		||||
{
 | 
			
		||||
	_has_scanned = 0;
 | 
			
		||||
 | 
			
		||||
	if (_vgid_hash) {
 | 
			
		||||
		hash_destroy(_vgid_hash);
 | 
			
		||||
		_vgid_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_pvid_hash) {
 | 
			
		||||
		hash_iter(_pvid_hash, (iterate_fn) _cache_destroy_entry);
 | 
			
		||||
		hash_destroy(_pvid_hash);
 | 
			
		||||
		_pvid_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_vgname_hash) {
 | 
			
		||||
		hash_iter(_vgname_hash, (iterate_fn) _cache_destroy_vgnamelist);
 | 
			
		||||
		hash_destroy(_vgname_hash);
 | 
			
		||||
		_vgname_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	list_init(&_vginfos);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								lib/cache/cache.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								lib/cache/cache.h
									
									
									
									
										vendored
									
									
								
							@@ -1,70 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_CACHE_H
 | 
			
		||||
#define _LVM_CACHE_H
 | 
			
		||||
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
#define ORPHAN ""
 | 
			
		||||
 | 
			
		||||
#define CACHE_INVALID 0x00000001
 | 
			
		||||
 | 
			
		||||
/* LVM specific per-volume info */
 | 
			
		||||
/* Eventual replacement for struct physical_volume perhaps? */
 | 
			
		||||
 | 
			
		||||
struct cache_vginfo {
 | 
			
		||||
	struct list list;	/* Join these vginfos together */
 | 
			
		||||
	struct list infos;	/* List head for cache_infos */
 | 
			
		||||
	char *vgname;		/* "" == orphan */
 | 
			
		||||
	char vgid[ID_LEN + 1];
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cache_info {
 | 
			
		||||
	struct list list;	/* Join VG members together */
 | 
			
		||||
	struct list mdas;	/* list head for metadata areas */
 | 
			
		||||
	struct list das;	/* list head for data areas */
 | 
			
		||||
	struct cache_vginfo *vginfo;	/* NULL == unknown */
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	uint64_t device_size;	/* Bytes */
 | 
			
		||||
	uint32_t status;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int cache_init(void);
 | 
			
		||||
void cache_destroy(void);
 | 
			
		||||
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
int cache_label_scan(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Add/delete a device */
 | 
			
		||||
struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
			     struct device *dev,
 | 
			
		||||
			     const char *vgname, const char *vgid);
 | 
			
		||||
void cache_del(struct cache_info *info);
 | 
			
		||||
 | 
			
		||||
/* Update things */
 | 
			
		||||
int cache_update_vgname(struct cache_info *info, const char *vgname);
 | 
			
		||||
int cache_update_vg(struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
/* Queries */
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname);
 | 
			
		||||
struct cache_vginfo *vginfo_from_vgname(const char *vgname);
 | 
			
		||||
struct cache_vginfo *vginfo_from_vgid(const char *vgid);
 | 
			
		||||
struct cache_info *info_from_pvid(const char *pvid);
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										900
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										900
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,900 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
 | 
			
		||||
static struct dm_hash_table *_pvid_hash = NULL;
 | 
			
		||||
static struct dm_hash_table *_vgid_hash = NULL;
 | 
			
		||||
static struct dm_hash_table *_vgname_hash = NULL;
 | 
			
		||||
static struct dm_hash_table *_lock_hash = NULL;
 | 
			
		||||
static struct list _vginfos;
 | 
			
		||||
static int _has_scanned = 0;
 | 
			
		||||
static int _vgs_locked = 0;
 | 
			
		||||
 | 
			
		||||
int lvmcache_init(void)
 | 
			
		||||
{
 | 
			
		||||
	list_init(&_vginfos);
 | 
			
		||||
 | 
			
		||||
	if (!(_vgname_hash = dm_hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(_vgid_hash = dm_hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(_pvid_hash = dm_hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(_lock_hash = dm_hash_create(128)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	if (!_lock_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
 | 
			
		||||
		log_error("Cache locking failure for %s", vgname);
 | 
			
		||||
 | 
			
		||||
	_vgs_locked++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vgname_is_locked(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	if (!_lock_hash)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return dm_hash_lookup(_lock_hash, vgname) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvmcache_unlock_vgname(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME: Clear all CACHE_LOCKED flags in this vg */
 | 
			
		||||
	dm_hash_remove(_lock_hash, vgname);
 | 
			
		||||
 | 
			
		||||
	/* FIXME Do this per-VG */
 | 
			
		||||
	if (!--_vgs_locked)
 | 
			
		||||
		dev_close_all();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vgs_locked(void)
 | 
			
		||||
{
 | 
			
		||||
	return _vgs_locked;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* If vgid supplied, require a match. */
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (vgid)
 | 
			
		||||
		do 
 | 
			
		||||
			if (!strncmp(vgid, vginfo->vgid, ID_LEN))
 | 
			
		||||
				return vginfo;
 | 
			
		||||
		while ((vginfo = vginfo->next));
 | 
			
		||||
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct list *devh, *tmp;
 | 
			
		||||
	struct list devs;
 | 
			
		||||
	struct device_list *devl;
 | 
			
		||||
	char vgid_found[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	/* This function is normally called before reading metadata so
 | 
			
		||||
 	 * we check cached labels here. Unfortunately vginfo is volatile. */
 | 
			
		||||
	list_init(&devs);
 | 
			
		||||
	list_iterate_items(info, &vginfo->infos) {
 | 
			
		||||
		if (!(devl = dm_malloc(sizeof(*devl)))) {
 | 
			
		||||
			log_error("device_list element allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		devl->dev = info->dev;
 | 
			
		||||
		list_add(&devs, &devl->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
 | 
			
		||||
 | 
			
		||||
	list_iterate_safe(devh, tmp, &devs) {
 | 
			
		||||
		devl = list_item(devh, struct device_list);
 | 
			
		||||
		label_read(devl->dev, &label);
 | 
			
		||||
		list_del(&devl->list);
 | 
			
		||||
		dm_free(devl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If vginfo changed, caller needs to rescan */
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
 | 
			
		||||
	    strncmp(vginfo->vgid, vgid_found, ID_LEN))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return vginfo->fmt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	char id[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_vgid_hash || !vgid)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	/* vgid not necessarily NULL-terminated */
 | 
			
		||||
	strncpy(&id[0], vgid, ID_LEN);
 | 
			
		||||
	id[ID_LEN] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = dm_hash_lookup(_vgid_hash, id)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	const char *vgname = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!*vgid)
 | 
			
		||||
		vgname = ORPHAN;
 | 
			
		||||
 | 
			
		||||
	if ((vginfo = vginfo_from_vgid(vgid)))
 | 
			
		||||
		vgname = vginfo->vgname;
 | 
			
		||||
 | 
			
		||||
	if (mem && vgname)
 | 
			
		||||
		return dm_pool_strdup(mem, vgname);
 | 
			
		||||
 | 
			
		||||
	return vgname;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lvmcache_info *info_from_pvid(const char *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	char id[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_pvid_hash || !pvid)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	strncpy(&id[0], pvid, ID_LEN);
 | 
			
		||||
	id[ID_LEN] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (!(info = dm_hash_lookup(_pvid_hash, id)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _rescan_entry(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
 | 
			
		||||
	if (info->status & CACHE_INVALID)
 | 
			
		||||
		label_read(info->dev, &label);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _scan_invalid(void)
 | 
			
		||||
{
 | 
			
		||||
	dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _rescan_entry);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct dev_iter *iter;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	struct format_type *fmt;
 | 
			
		||||
 | 
			
		||||
	static int _scanning_in_progress = 0;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	/* Avoid recursion when a PVID can't be found! */
 | 
			
		||||
	if (_scanning_in_progress)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	_scanning_in_progress = 1;
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_has_scanned && !full_scan) {
 | 
			
		||||
		r = _scan_invalid();
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
 | 
			
		||||
		log_error("dev_iter creation failed");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while ((dev = dev_iter_get(iter)))
 | 
			
		||||
		label_read(dev, &label);
 | 
			
		||||
 | 
			
		||||
	dev_iter_destroy(iter);
 | 
			
		||||
 | 
			
		||||
	_has_scanned = 1;
 | 
			
		||||
 | 
			
		||||
	/* Perform any format-specific scanning e.g. text files */
 | 
			
		||||
	list_iterate_items(fmt, &cmd->formats) {
 | 
			
		||||
		if (fmt->ops->scan && !fmt->ops->scan(fmt))
 | 
			
		||||
			goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	_scanning_in_progress = 0;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *vgids;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
	if (!(vgids = str_list_create(cmd->mem))) {
 | 
			
		||||
		log_error("vgids list allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(vginfo, &_vginfos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, vgids, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, vginfo->vgid))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vgids;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *vgnames;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
	if (!(vgnames = str_list_create(cmd->mem))) {
 | 
			
		||||
		log_error("vgnames list allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(vginfo, &_vginfos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, vgnames, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, vginfo->vgname))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vgnames;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
				const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct list *pvids;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(pvids = str_list_create(cmd->mem))) {
 | 
			
		||||
		log_error("pvids list allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
 | 
			
		||||
		return pvids;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(info, &vginfo->infos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, pvids, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, info->dev->pvid))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pvids;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	/* Already cached ? */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, 0);
 | 
			
		||||
 | 
			
		||||
	/* Try again */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (memlock())
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, 2);
 | 
			
		||||
 | 
			
		||||
	/* Try again */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!list_empty(&info->list)) {
 | 
			
		||||
		list_del(&info->list);
 | 
			
		||||
		list_init(&info->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && list_empty(&info->vginfo->infos)) {
 | 
			
		||||
		dm_hash_remove(_vgname_hash, info->vginfo->vgname);
 | 
			
		||||
		if (info->vginfo->next) {
 | 
			
		||||
                	if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
 | 
			
		||||
                        	log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
					  info->vginfo->vgname);
 | 
			
		||||
                        	return 0;
 | 
			
		||||
			}
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
		if (info->vginfo->vgname)
 | 
			
		||||
			dm_free(info->vginfo->vgname);
 | 
			
		||||
		if (info->vginfo->creation_host)
 | 
			
		||||
			dm_free(info->vginfo->creation_host);
 | 
			
		||||
		if (*info->vginfo->vgid)
 | 
			
		||||
			dm_hash_remove(_vgid_hash, info->vginfo->vgid);
 | 
			
		||||
		list_del(&info->vginfo->list);
 | 
			
		||||
		dm_free(info->vginfo);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->vginfo = NULL;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unused
 | 
			
		||||
void lvmcache_del(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (info->dev->pvid[0] && _pvid_hash)
 | 
			
		||||
		dm_hash_remove(_pvid_hash, info->dev->pvid);
 | 
			
		||||
 | 
			
		||||
	_drop_vginfo(info);
 | 
			
		||||
 | 
			
		||||
	info->label->labeller->ops->destroy_label(info->label->labeller,
 | 
			
		||||
						info->label); 
 | 
			
		||||
	dm_free(info);
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
} */
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
 | 
			
		||||
{
 | 
			
		||||
	if (!strcmp(info->dev->pvid, pvid))
 | 
			
		||||
		return 1;
 | 
			
		||||
	if (*info->dev->pvid) {
 | 
			
		||||
		dm_hash_remove(_pvid_hash, info->dev->pvid);
 | 
			
		||||
	}
 | 
			
		||||
	strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
 | 
			
		||||
	if (!dm_hash_insert(_pvid_hash, pvid, info)) {
 | 
			
		||||
		log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	if (!vgid || !info->vginfo ||
 | 
			
		||||
	    !strncmp(info->vginfo->vgid, vgid, ID_LEN))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && *info->vginfo->vgid)
 | 
			
		||||
		dm_hash_remove(_vgid_hash, info->vginfo->vgid);
 | 
			
		||||
	if (!vgid) {
 | 
			
		||||
		log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strncpy(info->vginfo->vgid, vgid, ID_LEN);
 | 
			
		||||
	info->vginfo->vgid[ID_LEN] = '\0';
 | 
			
		||||
	if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
 | 
			
		||||
		log_error("_lvmcache_update: vgid hash insertion failed: %s",
 | 
			
		||||
			  info->vginfo->vgid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
 | 
			
		||||
		  info->vginfo->vgname, info->vginfo->vgid);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
 | 
			
		||||
			  uint32_t vgstatus, const char *creation_host,
 | 
			
		||||
			  struct lvmcache_vginfo *primary_vginfo)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *last_vginfo = primary_vginfo;
 | 
			
		||||
	char uuid_primary[64], uuid_new[64];
 | 
			
		||||
	int use_new = 0;
 | 
			
		||||
	
 | 
			
		||||
	/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
 | 
			
		||||
	if (primary_vginfo) {
 | 
			
		||||
		if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
 | 
			
		||||
				     sizeof(uuid_primary)))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * If   Primary not exported, new exported => keep
 | 
			
		||||
		 * Else Primary exported, new not exported => change
 | 
			
		||||
		 * Else Primary has hostname for this machine => keep
 | 
			
		||||
		 * Else Primary has no hostname, new has one => change
 | 
			
		||||
		 * Else New has hostname for this machine => change
 | 
			
		||||
		 * Else Keep primary.
 | 
			
		||||
		 */
 | 
			
		||||
		if (!(primary_vginfo->status & EXPORTED_VG) &&
 | 
			
		||||
		    (vgstatus & EXPORTED_VG))
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "Existing %s takes precedence over "
 | 
			
		||||
				  "exported %s", new_vginfo->vgname,
 | 
			
		||||
				  uuid_primary, uuid_new);
 | 
			
		||||
		else if ((primary_vginfo->status & EXPORTED_VG) &&
 | 
			
		||||
			   !(vgstatus & EXPORTED_VG)) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s takes precedence over exported %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		} else if (primary_vginfo->creation_host &&
 | 
			
		||||
			   !strcmp(primary_vginfo->creation_host,
 | 
			
		||||
				   primary_vginfo->fmt->cmd->hostname))
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "Existing %s (created here) takes precedence "
 | 
			
		||||
				  "over %s", new_vginfo->vgname, uuid_primary,
 | 
			
		||||
				  uuid_new);
 | 
			
		||||
		else if (!primary_vginfo->creation_host && creation_host) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s (with creation_host) takes precedence over %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		} else if (creation_host &&
 | 
			
		||||
			   !strcmp(creation_host,
 | 
			
		||||
				   primary_vginfo->fmt->cmd->hostname)) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s (created here) takes precedence over %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!use_new) {
 | 
			
		||||
			while (last_vginfo->next)
 | 
			
		||||
				last_vginfo = last_vginfo->next;
 | 
			
		||||
			last_vginfo->next = new_vginfo;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
 | 
			
		||||
		log_error("cache_update: vg hash insertion failed: %s",
 | 
			
		||||
		  	new_vginfo->vgname);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (primary_vginfo)
 | 
			
		||||
		new_vginfo->next = primary_vginfo;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_vgname(struct lvmcache_info *info,
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus, const char *creation_host)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo, *primary_vginfo;
 | 
			
		||||
	// struct lvmcache_vginfo  *old_vginfo, *next;
 | 
			
		||||
 | 
			
		||||
	/* If vgname is NULL and we don't already have a vgname, 
 | 
			
		||||
	 * assume ORPHAN - we want every entry to have a vginfo
 | 
			
		||||
	 * attached for scanning reasons.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!vgname && !info->vginfo) {
 | 
			
		||||
		vgname = ORPHAN;
 | 
			
		||||
		vgid = ORPHAN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/* Remove existing vginfo entry */
 | 
			
		||||
	_drop_vginfo(info);
 | 
			
		||||
 | 
			
		||||
	/* Get existing vginfo or create new one */
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
 | 
			
		||||
/*** FIXME - vginfo ends up duplicated instead of renamed.
 | 
			
		||||
		// Renaming?  This lookup fails.
 | 
			
		||||
		if ((vginfo = vginfo_from_vgid(vgid))) {
 | 
			
		||||
			next = vginfo->next;
 | 
			
		||||
			old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
 | 
			
		||||
			if (old_vginfo == vginfo) {
 | 
			
		||||
				dm_hash_remove(_vgname_hash, old_vginfo->vgname);
 | 
			
		||||
				if (old_vginfo->next) {
 | 
			
		||||
					if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
 | 
			
		||||
                        			log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
							  old_vginfo->vgname);
 | 
			
		||||
                        			return 0;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else do {
 | 
			
		||||
				if (old_vginfo->next == vginfo) {
 | 
			
		||||
					old_vginfo->next = vginfo->next;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			} while ((old_vginfo = old_vginfo->next));
 | 
			
		||||
			vginfo->next = NULL;
 | 
			
		||||
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
			if (!(vginfo->vgname = dm_strdup(vgname))) {
 | 
			
		||||
				log_error("cache vgname alloc failed for %s", vgname);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Rename so can assume new name does not already exist 
 | 
			
		||||
			if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
 | 
			
		||||
				log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
					  vginfo->vgname);
 | 
			
		||||
                      		return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
***/
 | 
			
		||||
		if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
 | 
			
		||||
			log_error("lvmcache_update_vgname: list alloc failed");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		memset(vginfo, 0, sizeof(*vginfo));
 | 
			
		||||
		if (!(vginfo->vgname = dm_strdup(vgname))) {
 | 
			
		||||
			dm_free(vginfo);
 | 
			
		||||
			log_error("cache vgname alloc failed for %s", vgname);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		list_init(&vginfo->infos);
 | 
			
		||||
			primary_vginfo = vginfo_from_vgname(vgname, NULL);
 | 
			
		||||
		if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
 | 
			
		||||
				    primary_vginfo)) {
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
			dm_free(vginfo);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		/* Ensure orphans appear last on list_iterate */
 | 
			
		||||
		if (!*vgname)
 | 
			
		||||
			list_add(&_vginfos, &vginfo->list);
 | 
			
		||||
		else
 | 
			
		||||
			list_add_h(&_vginfos, &vginfo->list);
 | 
			
		||||
/***
 | 
			
		||||
		}
 | 
			
		||||
***/
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->vginfo = vginfo;
 | 
			
		||||
	list_add(&vginfo->infos, &info->list);
 | 
			
		||||
 | 
			
		||||
	/* FIXME Check consistency of list! */
 | 
			
		||||
	vginfo->fmt = info->fmt;
 | 
			
		||||
 | 
			
		||||
	log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
 | 
			
		||||
		  *vgname ? "in VG " : "orphaned", vgname,
 | 
			
		||||
		  vginfo->vgid[0] ? " (" : "",
 | 
			
		||||
		  vginfo->vgid[0] ? vginfo->vgid : "",
 | 
			
		||||
		  vginfo->vgid[0] ? ")" : "");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
 | 
			
		||||
				     const char *creation_host)
 | 
			
		||||
{
 | 
			
		||||
	if (!info || !info->vginfo)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
 | 
			
		||||
		log_debug("lvmcache: %s: VG %s %s exported",
 | 
			
		||||
			  dev_name(info->dev), info->vginfo->vgname,
 | 
			
		||||
			  vgstatus & EXPORTED_VG ? "now" : "no longer");
 | 
			
		||||
 | 
			
		||||
	info->vginfo->status = vgstatus;
 | 
			
		||||
 | 
			
		||||
	if (!creation_host)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo->creation_host && !strcmp(creation_host,
 | 
			
		||||
						   info->vginfo->creation_host))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo->creation_host)
 | 
			
		||||
		dm_free(info->vginfo->creation_host);
 | 
			
		||||
 | 
			
		||||
	if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
 | 
			
		||||
		log_error("cache creation host alloc failed for %s",
 | 
			
		||||
			  creation_host);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
 | 
			
		||||
		  dev_name(info->dev), info->vginfo->vgname, creation_host);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
 | 
			
		||||
				  const char *vgname, const char *vgid,
 | 
			
		||||
				  uint32_t vgstatus, const char *creation_host)
 | 
			
		||||
{
 | 
			
		||||
	if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
 | 
			
		||||
				     creation_host) ||
 | 
			
		||||
	    !_lvmcache_update_vgid(info, vgid) ||
 | 
			
		||||
	    !_lvmcache_update_vgstatus(info, vgstatus, creation_host))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvmcache_update_vg(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct pv_list *pvl;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	pvid_s[sizeof(pvid_s) - 1] = '\0';
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(pvl, &vg->pvs) {
 | 
			
		||||
		strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
 | 
			
		||||
		/* FIXME Could pvl->pv->dev->pvid ever be different? */
 | 
			
		||||
		if ((info = info_from_pvid(pvid_s)) &&
 | 
			
		||||
		    !lvmcache_update_vgname_and_id(info, vg->name,
 | 
			
		||||
						   (char *) &vg->id,
 | 
			
		||||
						   vg->status, NULL))
 | 
			
		||||
			return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
				   struct device *dev,
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct lvmcache_info *existing, *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strncpy(pvid_s, pvid, sizeof(pvid_s));
 | 
			
		||||
	pvid_s[sizeof(pvid_s) - 1] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (!(existing = info_from_pvid(pvid_s)) &&
 | 
			
		||||
	    !(existing = info_from_pvid(dev->pvid))) {
 | 
			
		||||
		if (!(label = label_create(labeller))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(info = dm_malloc(sizeof(*info)))) {
 | 
			
		||||
			log_error("lvmcache_info allocation failed");
 | 
			
		||||
			label_destroy(label);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		memset(info, 0, sizeof(*info));
 | 
			
		||||
 | 
			
		||||
		label->info = info;
 | 
			
		||||
		info->label = label;
 | 
			
		||||
		list_init(&info->list);
 | 
			
		||||
		info->dev = dev;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (existing->dev != dev) {
 | 
			
		||||
			/* Is the existing entry a duplicate pvid e.g. md ? */
 | 
			
		||||
			if (MAJOR(existing->dev->dev) == md_major() &&
 | 
			
		||||
			    MAJOR(dev->dev) != md_major()) {
 | 
			
		||||
				log_very_verbose("Ignoring duplicate PV %s on "
 | 
			
		||||
						 "%s - using md %s",
 | 
			
		||||
						 pvid, dev_name(dev),
 | 
			
		||||
						 dev_name(existing->dev));
 | 
			
		||||
				return NULL;
 | 
			
		||||
			} else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
 | 
			
		||||
				   !dm_is_dm_major(MAJOR(dev->dev))) {
 | 
			
		||||
				log_very_verbose("Ignoring duplicate PV %s on "
 | 
			
		||||
						 "%s - using dm %s",
 | 
			
		||||
						 pvid, dev_name(dev),
 | 
			
		||||
						 dev_name(existing->dev));
 | 
			
		||||
				return NULL;
 | 
			
		||||
			} else if (MAJOR(existing->dev->dev) != md_major() &&
 | 
			
		||||
				   MAJOR(dev->dev) == md_major())
 | 
			
		||||
				log_very_verbose("Duplicate PV %s on %s - "
 | 
			
		||||
						 "using md %s", pvid,
 | 
			
		||||
						 dev_name(existing->dev),
 | 
			
		||||
						 dev_name(dev));
 | 
			
		||||
			else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
 | 
			
		||||
				 dm_is_dm_major(MAJOR(dev->dev)))
 | 
			
		||||
				log_very_verbose("Duplicate PV %s on %s - "
 | 
			
		||||
						 "using dm %s", pvid,
 | 
			
		||||
						 dev_name(existing->dev),
 | 
			
		||||
						 dev_name(dev));
 | 
			
		||||
			/* FIXME If both dm, check dependencies */
 | 
			
		||||
			//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
 | 
			
		||||
				 //dm_is_dm_major(MAJOR(dev->dev)))
 | 
			
		||||
				 //
 | 
			
		||||
			else
 | 
			
		||||
				log_error("Found duplicate PV %s: using %s not "
 | 
			
		||||
					  "%s", pvid, dev_name(dev),
 | 
			
		||||
					  dev_name(existing->dev));
 | 
			
		||||
		}
 | 
			
		||||
		/* Switch over to new preferred device */
 | 
			
		||||
		existing->dev = dev;
 | 
			
		||||
		info = existing;
 | 
			
		||||
		/* Has labeller changed? */
 | 
			
		||||
		if (info->label->labeller != labeller) {
 | 
			
		||||
			label_destroy(info->label);
 | 
			
		||||
			if (!(info->label = label_create(labeller))) {
 | 
			
		||||
				/* FIXME leaves info without label! */
 | 
			
		||||
				stack;
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			info->label->info = info;
 | 
			
		||||
		}
 | 
			
		||||
		label = info->label;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->fmt = (const struct format_type *) labeller->private;
 | 
			
		||||
	info->status |= CACHE_INVALID;
 | 
			
		||||
 | 
			
		||||
	if (!_lvmcache_update_pvid(info, pvid_s)) {
 | 
			
		||||
		if (!existing) {
 | 
			
		||||
			dm_free(info);
 | 
			
		||||
			label_destroy(label);
 | 
			
		||||
		}
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
 | 
			
		||||
		if (!existing) {
 | 
			
		||||
			dm_hash_remove(_pvid_hash, pvid_s);
 | 
			
		||||
			strcpy(info->dev->pvid, "");
 | 
			
		||||
			dm_free(info);
 | 
			
		||||
			label_destroy(label);
 | 
			
		||||
		}
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _lvmcache_destroy_entry(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!list_empty(&info->list))
 | 
			
		||||
		list_del(&info->list);
 | 
			
		||||
	strcpy(info->dev->pvid, "");
 | 
			
		||||
	label_destroy(info->label);
 | 
			
		||||
	dm_free(info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *next;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = vginfo->next;
 | 
			
		||||
		if (vginfo->vgname)
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
		if (vginfo->creation_host)
 | 
			
		||||
			dm_free(vginfo->creation_host);
 | 
			
		||||
		dm_free(vginfo);
 | 
			
		||||
	} while ((vginfo = next));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _lvmcache_destroy_lockname(int present __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	/* Nothing to do */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvmcache_destroy(void)
 | 
			
		||||
{
 | 
			
		||||
	log_verbose("Wiping internal VG cache");
 | 
			
		||||
 | 
			
		||||
	_has_scanned = 0;
 | 
			
		||||
 | 
			
		||||
	if (_vgid_hash) {
 | 
			
		||||
		dm_hash_destroy(_vgid_hash);
 | 
			
		||||
		_vgid_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_pvid_hash) {
 | 
			
		||||
		dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_entry);
 | 
			
		||||
		dm_hash_destroy(_pvid_hash);
 | 
			
		||||
		_pvid_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_vgname_hash) {
 | 
			
		||||
		dm_hash_iter(_vgname_hash,
 | 
			
		||||
			  (dm_hash_iterate_fn) _lvmcache_destroy_vgnamelist);
 | 
			
		||||
		dm_hash_destroy(_vgname_hash);
 | 
			
		||||
		_vgname_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_lock_hash) {
 | 
			
		||||
		dm_hash_iter(_lock_hash, (dm_hash_iterate_fn) _lvmcache_destroy_lockname);
 | 
			
		||||
		dm_hash_destroy(_lock_hash);
 | 
			
		||||
		_lock_hash = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(&_vginfos);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										108
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_CACHE_H
 | 
			
		||||
#define _LVM_CACHE_H
 | 
			
		||||
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
 | 
			
		||||
#define ORPHAN ""
 | 
			
		||||
 | 
			
		||||
#define CACHE_INVALID	0x00000001
 | 
			
		||||
#define CACHE_LOCKED	0x00000002
 | 
			
		||||
 | 
			
		||||
/* LVM specific per-volume info */
 | 
			
		||||
/* Eventual replacement for struct physical_volume perhaps? */
 | 
			
		||||
 | 
			
		||||
struct cmd_context;
 | 
			
		||||
struct format_type;
 | 
			
		||||
struct volume_group;
 | 
			
		||||
 | 
			
		||||
/* One per VG */
 | 
			
		||||
struct lvmcache_vginfo {
 | 
			
		||||
	struct list list;	/* Join these vginfos together */
 | 
			
		||||
	struct list infos;	/* List head for lvmcache_infos */
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
	char *vgname;		/* "" == orphan */
 | 
			
		||||
	uint32_t status;
 | 
			
		||||
	char vgid[ID_LEN + 1];
 | 
			
		||||
	char _padding[7];
 | 
			
		||||
	struct lvmcache_vginfo *next; /* Another VG with same name? */
 | 
			
		||||
	char *creation_host;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* One per device */
 | 
			
		||||
struct lvmcache_info {
 | 
			
		||||
	struct list list;	/* Join VG members together */
 | 
			
		||||
	struct list mdas;	/* list head for metadata areas */
 | 
			
		||||
	struct list das;	/* list head for data areas */
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;	/* NULL == unknown */
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	uint64_t device_size;	/* Bytes */
 | 
			
		||||
	uint32_t status;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int lvmcache_init(void);
 | 
			
		||||
void lvmcache_destroy(void);
 | 
			
		||||
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label or
 | 
			
		||||
 * 2 to rescan /dev for new devices */
 | 
			
		||||
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Add/delete a device */
 | 
			
		||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
				   struct device *dev,
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus);
 | 
			
		||||
void lvmcache_del(struct lvmcache_info *info);
 | 
			
		||||
 | 
			
		||||
/* Update things */
 | 
			
		||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
 | 
			
		||||
				  const char *vgname, const char *vgid,
 | 
			
		||||
				  uint32_t vgstatus, const char *hostname);
 | 
			
		||||
int lvmcache_update_vg(struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
 | 
			
		||||
void lvmcache_unlock_vgname(const char *vgname);
 | 
			
		||||
 | 
			
		||||
/* Queries */
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
 | 
			
		||||
					   const char *vgid);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
 | 
			
		||||
struct lvmcache_info *info_from_pvid(const char *pvid);
 | 
			
		||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
 | 
			
		||||
int vgs_locked(void);
 | 
			
		||||
int vgname_is_locked(const char *vgname);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of vgids */
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of pvids */
 | 
			
		||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
				const char *vgid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,15 +1,24 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
#define _LVM_ERRORS_H
 | 
			
		||||
 | 
			
		||||
#define EINVALID_CMD_LINE	1
 | 
			
		||||
#define ENO_SUCH_CMD		3
 | 
			
		||||
#define ECMD_PROCESSED		4
 | 
			
		||||
#define ECMD_PROCESSED		1
 | 
			
		||||
#define ENO_SUCH_CMD		2
 | 
			
		||||
#define EINVALID_CMD_LINE	3
 | 
			
		||||
#define ECMD_FAILED		5
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,17 +1,22 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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>
 | 
			
		||||
@@ -26,29 +31,34 @@ struct config_info {
 | 
			
		||||
	int syslog;
 | 
			
		||||
	int activation;
 | 
			
		||||
	int suffix;
 | 
			
		||||
	uint64_t unit_factor;
 | 
			
		||||
	char unit_type;
 | 
			
		||||
	const char *msg_prefix;
 | 
			
		||||
	int cmd_name;		/* Show command name? */
 | 
			
		||||
 | 
			
		||||
	int archive;		/* should we archive ? */
 | 
			
		||||
	int backup;		/* should we backup ? */
 | 
			
		||||
 | 
			
		||||
	const char *msg_prefix;
 | 
			
		||||
	struct format_type *fmt;
 | 
			
		||||
 | 
			
		||||
	uint64_t unit_factor;
 | 
			
		||||
	int cmd_name;		/* Show command name? */
 | 
			
		||||
	mode_t umask;
 | 
			
		||||
	char unit_type;
 | 
			
		||||
	char _padding[1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct config_tree;
 | 
			
		||||
struct archive_params;
 | 
			
		||||
struct backup_params;
 | 
			
		||||
 | 
			
		||||
/* 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 dm_pool *libmem;	/* For permanent config data */
 | 
			
		||||
	struct dm_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 +68,20 @@ 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_tree *cft_override;
 | 
			
		||||
	struct config_info default_settings;
 | 
			
		||||
	struct config_info current_settings;
 | 
			
		||||
 | 
			
		||||
	struct archive_params *archive_params;
 | 
			
		||||
	struct backup_params *backup_params;
 | 
			
		||||
 | 
			
		||||
	/* 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 +89,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,14 +1,24 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "crc.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
@@ -31,22 +41,23 @@ enum {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct parser {
 | 
			
		||||
	char *fb, *fe;		/* file limits */
 | 
			
		||||
	const char *fb, *fe;		/* file limits */
 | 
			
		||||
 | 
			
		||||
	int t;			/* token limits and type */
 | 
			
		||||
	char *tb, *te;
 | 
			
		||||
	const char *tb, *te;
 | 
			
		||||
 | 
			
		||||
	int fd;			/* descriptor for file being parsed */
 | 
			
		||||
	int line;		/* line number we are on */
 | 
			
		||||
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cs {
 | 
			
		||||
	struct config_tree cf;
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
	struct config_tree cft;
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	time_t timestamp;
 | 
			
		||||
	char *filename;
 | 
			
		||||
	int exists;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void _get_token(struct parser *p, int tok_prev);
 | 
			
		||||
@@ -60,11 +71,13 @@ 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 {\
 | 
			
		||||
   if (!_match_aux(p, (t))) {\
 | 
			
		||||
	log_error("Parse error at line %d: unexpected token", p->line); \
 | 
			
		||||
	log_error("Parse error at byte %d (line %d): unexpected token", p->tb - p->fb + 1, p->line); \
 | 
			
		||||
      return 0;\
 | 
			
		||||
   } \
 | 
			
		||||
} while(0);
 | 
			
		||||
@@ -82,100 +95,137 @@ 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 dm_pool *mem = dm_pool_create("config", 10 * 1024);
 | 
			
		||||
 | 
			
		||||
	if (!mem) {
 | 
			
		||||
		stack;
 | 
			
		||||
		log_error("Failed to allocate config pool.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(c = pool_alloc(mem, sizeof(*c)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		pool_destroy(mem);
 | 
			
		||||
	if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
 | 
			
		||||
		log_error("Failed to allocate config tree.");
 | 
			
		||||
		dm_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 = dm_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);
 | 
			
		||||
	dm_pool_destroy(((struct cs *) cft)->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
static int _parse_config_file(struct parser *p, struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	p->tb = p->te = p->fb;
 | 
			
		||||
	p->line = 1;
 | 
			
		||||
	_get_token(p, TOK_SECTION_E);
 | 
			
		||||
	if (!(cft->root = _file(p)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
 | 
			
		||||
						   const char *config_settings)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
	struct parser *p;
 | 
			
		||||
 | 
			
		||||
	if (!(cft = create_config_tree(NULL)))
 | 
			
		||||
		return_NULL;
 | 
			
		||||
 | 
			
		||||
	c = (struct cs *) cft;
 | 
			
		||||
	if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
 | 
			
		||||
		log_error("Failed to allocate config tree parser.");
 | 
			
		||||
		destroy_config_tree(cft);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p->mem = c->mem;
 | 
			
		||||
	p->fb = config_settings;
 | 
			
		||||
	p->fe = config_settings + strlen(config_settings);
 | 
			
		||||
 | 
			
		||||
	if (!_parse_config_file(p, cft)) {
 | 
			
		||||
		destroy_config_tree(cft);
 | 
			
		||||
		return_NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cft;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		   off_t offset, size_t size, off_t offset2, size_t size2,
 | 
			
		||||
		   checksum_fn_t checksum_fn, uint32_t checksum)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cf;
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
	struct parser *p;
 | 
			
		||||
	off_t mmap_offset = 0;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	int use_mmap = 1;
 | 
			
		||||
	off_t mmap_offset = 0;
 | 
			
		||||
	char *buf;
 | 
			
		||||
 | 
			
		||||
	if (!(p = pool_alloc(c->mem, sizeof(*p)))) {
 | 
			
		||||
	if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	p->mem = c->mem;
 | 
			
		||||
 | 
			
		||||
	if (size2) {
 | 
			
		||||
		/* FIXME Attempt adjacent mmaps MAP_FIXED into malloced space 
 | 
			
		||||
		 * one page size larger than required...
 | 
			
		||||
		 */
 | 
			
		||||
		if (!(p->fb = dbg_malloc(size + size2))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (lseek(fd, offset, SEEK_SET) < 0) {
 | 
			
		||||
			log_sys_error("lseek", file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (raw_read(fd, p->fb, size) != size) {
 | 
			
		||||
			log_error("Circular read from %s failed", file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (lseek(fd, offset2, SEEK_SET) < 0) {
 | 
			
		||||
			log_sys_error("lseek", file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (raw_read(fd, p->fb + size, size2) != size2) {
 | 
			
		||||
			log_error("Circular read from %s failed", file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
	/* Only use mmap with regular files */
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR) || size2)
 | 
			
		||||
		use_mmap = 0;
 | 
			
		||||
 | 
			
		||||
	if (use_mmap) {
 | 
			
		||||
		mmap_offset = offset % getpagesize();
 | 
			
		||||
		/* memory map the file */
 | 
			
		||||
		p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
 | 
			
		||||
			     MAP_PRIVATE, fd, offset - mmap_offset);
 | 
			
		||||
			     MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
 | 
			
		||||
		if (p->fb == (caddr_t) (-1)) {
 | 
			
		||||
			log_sys_error("mmap", file);
 | 
			
		||||
			log_sys_error("mmap", dev_name(dev));
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p->fb = p->fb + mmap_offset;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!(buf = dm_malloc(size + size2))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (!dev_read(dev, (uint64_t) offset, size, buf)) {
 | 
			
		||||
			log_error("Read from %s failed", dev_name(dev));
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (size2) {
 | 
			
		||||
			if (!dev_read(dev, (uint64_t) offset2, size2,
 | 
			
		||||
				      buf + size)) {
 | 
			
		||||
				log_error("Circular read from %s failed",
 | 
			
		||||
					  dev_name(dev));
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		p->fb = buf;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (checksum_fn && checksum !=
 | 
			
		||||
	    (checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size),
 | 
			
		||||
			 p->fb + size, size2))) {
 | 
			
		||||
		log_error("%s: Checksum error", file);
 | 
			
		||||
		log_error("%s: Checksum error", dev_name(dev));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p->fe = p->fb + size + size2;
 | 
			
		||||
 | 
			
		||||
	/* parse */
 | 
			
		||||
	p->tb = p->te = p->fb;
 | 
			
		||||
	p->line = 1;
 | 
			
		||||
	_get_token(p, TOK_SECTION_E);
 | 
			
		||||
	if (!(cf->root = _file(p))) {
 | 
			
		||||
	if (!_parse_config_file(p, cft)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -183,12 +233,12 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (size2)
 | 
			
		||||
		dbg_free(p->fb);
 | 
			
		||||
	if (!use_mmap)
 | 
			
		||||
		dm_free(buf);
 | 
			
		||||
	else {
 | 
			
		||||
		/* unmap the file */
 | 
			
		||||
		if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
 | 
			
		||||
			log_sys_error("munmap", file);
 | 
			
		||||
			log_sys_error("munmap", dev_name(dev));
 | 
			
		||||
			r = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -196,112 +246,97 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
	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;
 | 
			
		||||
	int r = 1, fd;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
	if (stat(file, &info)) {
 | 
			
		||||
		log_sys_error("stat", file);
 | 
			
		||||
	if (stat(c->filename, &info)) {
 | 
			
		||||
		log_sys_error("stat", c->filename);
 | 
			
		||||
		c->exists = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!S_ISREG(info.st_mode)) {
 | 
			
		||||
		log_error("%s is not a regular file", file);
 | 
			
		||||
		log_error("%s is not a regular file", c->filename);
 | 
			
		||||
		c->exists = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c->exists = 1;
 | 
			
		||||
 | 
			
		||||
	if (info.st_size == 0) {
 | 
			
		||||
		log_verbose("%s is empty", file);
 | 
			
		||||
		log_verbose("%s is empty", c->filename);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((fd = open(file, O_RDONLY)) < 0) {
 | 
			
		||||
		log_sys_error("open", file);
 | 
			
		||||
	if (!(dev = dev_create_file(c->filename, NULL, NULL, 1))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(cf, fd, file, 0, (size_t) info.st_size, 0, 0,
 | 
			
		||||
	if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0,
 | 
			
		||||
			   (checksum_fn_t) NULL, 0);
 | 
			
		||||
 | 
			
		||||
	close(fd);
 | 
			
		||||
	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)
 | 
			
		||||
time_t config_file_timestamp(struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cf;
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
 | 
			
		||||
	return c->timestamp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if config file reloaded
 | 
			
		||||
 * Return 1 if config files ought to be reloaded
 | 
			
		||||
 */
 | 
			
		||||
int reload_config_file(struct config_tree **cf)
 | 
			
		||||
int config_file_changed(struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	struct config_tree *new_cf;
 | 
			
		||||
	struct cs *c = (struct cs *) *cf;
 | 
			
		||||
	struct cs *new_cs;
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	int r, fd;
 | 
			
		||||
 | 
			
		||||
	if (!c->filename)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (stat(c->filename, &info) == -1) {
 | 
			
		||||
		if (errno == ENOENT)
 | 
			
		||||
			return 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 file");
 | 
			
		||||
		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);
 | 
			
		||||
		return 0;
 | 
			
		||||
		goto reload;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Unchanged? */
 | 
			
		||||
	if (c->timestamp == info.st_mtime)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	log_verbose("Detected config file change: Reloading %s", c->filename);
 | 
			
		||||
 | 
			
		||||
	if (info.st_size == 0) {
 | 
			
		||||
		log_verbose("Config file reload: %s is empty", c->filename);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((fd = open(c->filename, O_RDONLY)) < 0) {
 | 
			
		||||
		log_sys_error("open", c->filename);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(new_cf = create_config_tree())) {
 | 
			
		||||
		log_error("Allocation of new config_tree failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = read_config_fd(new_cf, fd, c->filename, 0, (size_t) info.st_size,
 | 
			
		||||
			   0, 0, (checksum_fn_t) NULL, 0);
 | 
			
		||||
	close(fd);
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
      reload:
 | 
			
		||||
	log_verbose("Detected config file change to %s", c->filename);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _write_value(FILE *fp, struct config_value *v)
 | 
			
		||||
@@ -372,20 +407,28 @@ 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 = fopen(file, "w");
 | 
			
		||||
	if (!fp) {
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
 | 
			
		||||
	if (!file) {
 | 
			
		||||
		fp = stdout;
 | 
			
		||||
		file = "stdout";
 | 
			
		||||
	} else if (!(fp = fopen(file, "w"))) {
 | 
			
		||||
		log_sys_error("open", file);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_write_config(cf->root, fp, 0)) {
 | 
			
		||||
		stack;
 | 
			
		||||
	log_verbose("Dumping configuration to %s", file);
 | 
			
		||||
	if (!_write_config(cft->root, fp, 0)) {
 | 
			
		||||
		log_error("Failure while writing configuration");
 | 
			
		||||
		r = 0;
 | 
			
		||||
	}
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
 | 
			
		||||
	if (fp != stdout)
 | 
			
		||||
		fclose(fp);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -492,7 +535,7 @@ static struct config_value *_value(struct parser *p)
 | 
			
		||||
 | 
			
		||||
static struct config_value *_type(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	/* [0-9]+ | [0-9]*\.[0-9]* | ".*" */
 | 
			
		||||
	/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
 | 
			
		||||
	struct config_value *v = _create_value(p);
 | 
			
		||||
 | 
			
		||||
	if (!v)
 | 
			
		||||
@@ -524,7 +567,7 @@ static struct config_value *_type(struct parser *p)
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("Parse error at line %d: expected a value", p->line);
 | 
			
		||||
		log_error("Parse error at byte %d (line %d): expected a value", p->tb - p->fb + 1, p->line);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return v;
 | 
			
		||||
@@ -627,6 +670,8 @@ static void _get_token(struct parser *p, int tok_prev)
 | 
			
		||||
	case '7':
 | 
			
		||||
	case '8':
 | 
			
		||||
	case '9':
 | 
			
		||||
	case '+':
 | 
			
		||||
	case '-':
 | 
			
		||||
		if (values_allowed) {
 | 
			
		||||
			p->te++;
 | 
			
		||||
			while ((p->te != p->fe) && (*p->te)) {
 | 
			
		||||
@@ -680,22 +725,28 @@ static void _eat_space(struct parser *p)
 | 
			
		||||
 */
 | 
			
		||||
static struct config_value *_create_value(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	struct config_value *v = pool_alloc(p->mem, sizeof(*v));
 | 
			
		||||
	memset(v, 0, sizeof(*v));
 | 
			
		||||
	struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
 | 
			
		||||
 | 
			
		||||
	if (v)
 | 
			
		||||
		memset(v, 0, sizeof(*v));
 | 
			
		||||
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct config_node *_create_node(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = pool_alloc(p->mem, sizeof(*n));
 | 
			
		||||
	memset(n, 0, sizeof(*n));
 | 
			
		||||
	struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
 | 
			
		||||
 | 
			
		||||
	if (n)
 | 
			
		||||
		memset(n, 0, sizeof(*n));
 | 
			
		||||
 | 
			
		||||
	return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *_dup_tok(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	size_t len = p->te - p->tb;
 | 
			
		||||
	char *str = pool_alloc(p->mem, len + 1);
 | 
			
		||||
	char *str = dm_pool_alloc(p->mem, len + 1);
 | 
			
		||||
	if (!str) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -708,8 +759,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)
 | 
			
		||||
static struct config_node *_find_config_node(const struct config_node *cn,
 | 
			
		||||
					     const char *path)
 | 
			
		||||
{
 | 
			
		||||
	const char *e;
 | 
			
		||||
 | 
			
		||||
@@ -737,17 +788,39 @@ 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)
 | 
			
		||||
static struct config_node *_find_first_config_node(const struct config_node *cn1,
 | 
			
		||||
						   const struct config_node *cn2,
 | 
			
		||||
						   const char *path)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = find_config_node(cn, path, sep);
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_STRING) {
 | 
			
		||||
		if (*n->v->v.str)
 | 
			
		||||
			log_very_verbose("Setting %s to %s", path, n->v->v.str);
 | 
			
		||||
	if (cn1 && (cn = _find_config_node(cn1, path)))
 | 
			
		||||
		return cn;
 | 
			
		||||
 | 
			
		||||
	if (cn2 && (cn = _find_config_node(cn2, path)))
 | 
			
		||||
		return cn;
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_node(cn, path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *_find_config_str(const struct config_node *cn1,
 | 
			
		||||
				    const struct config_node *cn2,
 | 
			
		||||
				    const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
 | 
			
		||||
	/* Empty strings are ignored */
 | 
			
		||||
	if ((n && n->v->type == CFG_STRING) && (*n->v->v.str)) {
 | 
			
		||||
		log_very_verbose("Setting %s to %s", path, n->v->v.str);
 | 
			
		||||
		return n->v->v.str;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -757,10 +830,17 @@ 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)
 | 
			
		||||
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);
 | 
			
		||||
	return _find_config_str(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _find_config_int(const struct config_node *cn1,
 | 
			
		||||
			    const struct config_node *cn2,
 | 
			
		||||
			    const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_INT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %d", path, n->v->v.i);
 | 
			
		||||
@@ -772,10 +852,16 @@ 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)
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = find_config_node(cn, path, sep);
 | 
			
		||||
	return _find_config_int(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static float _find_config_float(const struct config_node *cn1,
 | 
			
		||||
				const struct config_node *cn2,
 | 
			
		||||
				const char *path, float fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_FLOAT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %f", path, n->v->v.r);
 | 
			
		||||
@@ -789,6 +875,36 @@ float find_config_float(struct config_node *cn, const char *path,
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_float(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_tree_node(struct cmd_context *cmd,
 | 
			
		||||
                                          const char *path)
 | 
			
		||||
{
 | 
			
		||||
	return _find_first_config_node(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *find_config_tree_str(struct cmd_context *cmd,
 | 
			
		||||
                                 const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_str(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_tree_int(struct cmd_context *cmd, const char *path,
 | 
			
		||||
                         int fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_int(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_tree_float(struct cmd_context *cmd, const char *path,
 | 
			
		||||
                             float fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _str_in_array(const char *str, const char *values[])
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
@@ -815,10 +931,11 @@ 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)
 | 
			
		||||
static int _find_config_bool(const struct config_node *cn1,
 | 
			
		||||
			     const struct config_node *cn2,
 | 
			
		||||
			     const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = find_config_node(cn, path, sep);
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
	struct config_value *v;
 | 
			
		||||
 | 
			
		||||
	if (!n)
 | 
			
		||||
@@ -837,12 +954,22 @@ 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 find_config_bool(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n;
 | 
			
		||||
	return _find_config_bool(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	n = find_config_node(cn, path, sep);
 | 
			
		||||
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_bool(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_config_uint32(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint32_t *result)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n;
 | 
			
		||||
 | 
			
		||||
	n = find_config_node(cn, path);
 | 
			
		||||
 | 
			
		||||
	if (!n || !n->v || n->v->type != CFG_INT)
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -851,12 +978,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;
 | 
			
		||||
@@ -866,12 +993,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;
 | 
			
		||||
@@ -879,3 +1006,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,12 +1,26 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "lvm-types.h"
 | 
			
		||||
 | 
			
		||||
struct device;
 | 
			
		||||
struct cmd_context;
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	CFG_STRING,
 | 
			
		||||
	CFG_FLOAT,
 | 
			
		||||
@@ -34,46 +48,63 @@ 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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
 | 
			
		||||
struct config_tree *create_config_tree(const char *filename);
 | 
			
		||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
 | 
			
		||||
						   const char *config_settings);
 | 
			
		||||
void destroy_config_tree(struct config_tree *cft);
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cf, int fd, const char *file,
 | 
			
		||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const void *buf, uint32_t size);
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		   off_t offset, size_t size, off_t offset2, size_t size2,
 | 
			
		||||
		   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(const struct config_node *cn, const char *path,
 | 
			
		||||
			    const char *fail);
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail);
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail);
 | 
			
		||||
 | 
			
		||||
const char *find_config_str(struct config_node *cn,
 | 
			
		||||
			    const char *path, const int sep, const char *fail);
 | 
			
		||||
 | 
			
		||||
int find_config_int(struct config_node *cn, const char *path,
 | 
			
		||||
		    const int sep, int fail);
 | 
			
		||||
 | 
			
		||||
float find_config_float(struct config_node *cn, const char *path,
 | 
			
		||||
			const int sep, float fail);
 | 
			
		||||
/*
 | 
			
		||||
 * These versions check an override tree, if present, first.
 | 
			
		||||
 */
 | 
			
		||||
struct config_node *find_config_tree_node(struct cmd_context *cmd,
 | 
			
		||||
					  const char *path);
 | 
			
		||||
const char *find_config_tree_str(struct cmd_context *cmd,
 | 
			
		||||
				 const char *path, const char *fail);
 | 
			
		||||
int find_config_tree_int(struct cmd_context *cmd, const char *path,
 | 
			
		||||
			 int fail);
 | 
			
		||||
float find_config_tree_float(struct cmd_context *cmd, const char *path,
 | 
			
		||||
			     float fail);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Understands (0, ~0), (y, n), (yes, no), (on,
 | 
			
		||||
 * off), (true, false).
 | 
			
		||||
 */
 | 
			
		||||
int find_config_bool(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 find_config_tree_bool(struct cmd_context *cmd, 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
 | 
			
		||||
@@ -19,12 +28,25 @@
 | 
			
		||||
#define DEFAULT_SYS_DIR "/etc/lvm"
 | 
			
		||||
#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_MIRROR_LOG_FAULT_POLICY "allocate"
 | 
			
		||||
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
 | 
			
		||||
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
 | 
			
		||||
#define DEFAULT_DMEVENTD_MONITOR 1
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_UMASK 0077
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
@@ -50,9 +72,13 @@
 | 
			
		||||
#define DEFAULT_INDENT 1
 | 
			
		||||
#define DEFAULT_UNITS "h"
 | 
			
		||||
#define DEFAULT_SUFFIX 1
 | 
			
		||||
#define DEFAULT_HOSTTAGS 0
 | 
			
		||||
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
#  define DEFAULT_ACTIVATION 1
 | 
			
		||||
#  define DEFAULT_RESERVED_MEMORY 8192
 | 
			
		||||
#  define DEFAULT_RESERVED_STACK 256
 | 
			
		||||
#  define DEFAULT_PROCESS_PRIORITY -18
 | 
			
		||||
#else
 | 
			
		||||
#  define DEFAULT_ACTIVATION 0
 | 
			
		||||
#endif
 | 
			
		||||
@@ -70,19 +96,22 @@
 | 
			
		||||
#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,mirror_log,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_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_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,mirror_log,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_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LVS_SORT "vg_name,lv_name"
 | 
			
		||||
#define DEFAULT_VGS_SORT "vg_name"
 | 
			
		||||
#define DEFAULT_PVS_SORT "pv_name"
 | 
			
		||||
#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
 | 
			
		||||
#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
 | 
			
		||||
 | 
			
		||||
#endif				/* _LVM_DEFAULTS_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,77 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "bitset.h"
 | 
			
		||||
 | 
			
		||||
/* FIXME: calculate this. */
 | 
			
		||||
#define INT_SHIFT 5
 | 
			
		||||
 | 
			
		||||
bitset_t bitset_create(struct pool *mem, unsigned num_bits)
 | 
			
		||||
{
 | 
			
		||||
	unsigned n = (num_bits / BITS_PER_INT) + 2;
 | 
			
		||||
	size_t size = sizeof(int) * n;
 | 
			
		||||
	unsigned *bs = pool_zalloc(mem, size);
 | 
			
		||||
 | 
			
		||||
	if (!bs)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	*bs = num_bits;
 | 
			
		||||
	return bs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bitset_destroy(bitset_t bs)
 | 
			
		||||
{
 | 
			
		||||
	dbg_free(bs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bit_union(bitset_t out, bitset_t in1, bitset_t in2)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	for (i = (in1[0] / BITS_PER_INT) + 1; i; i--)
 | 
			
		||||
		out[i] = in1[i] | in2[i];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FIXME: slow
 | 
			
		||||
 */
 | 
			
		||||
static inline int _test_word(uint32_t test, int bit)
 | 
			
		||||
{
 | 
			
		||||
	while (bit < BITS_PER_INT) {
 | 
			
		||||
		if (test & (0x1 << bit))
 | 
			
		||||
			return bit;
 | 
			
		||||
		bit++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int bit_get_next(bitset_t bs, int last_bit)
 | 
			
		||||
{
 | 
			
		||||
	int bit, word;
 | 
			
		||||
	uint32_t test;
 | 
			
		||||
 | 
			
		||||
	last_bit++;		/* otherwise we'll return the same bit again */
 | 
			
		||||
 | 
			
		||||
	while (last_bit < bs[0]) {
 | 
			
		||||
		word = last_bit >> INT_SHIFT;
 | 
			
		||||
		test = bs[word + 1];
 | 
			
		||||
		bit = last_bit & (BITS_PER_INT - 1);
 | 
			
		||||
 | 
			
		||||
		if ((bit = _test_word(test, bit)) >= 0)
 | 
			
		||||
			return (word * BITS_PER_INT) + bit;
 | 
			
		||||
 | 
			
		||||
		last_bit = last_bit - (last_bit & (BITS_PER_INT - 1)) +
 | 
			
		||||
		    BITS_PER_INT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int bit_get_first(bitset_t bs)
 | 
			
		||||
{
 | 
			
		||||
	return bit_get_next(bs, -1);
 | 
			
		||||
}
 | 
			
		||||
@@ -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,13 +24,13 @@ struct node {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct btree {
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	struct node *root;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct btree *btree_create(struct pool *mem)
 | 
			
		||||
struct btree *btree_create(struct dm_pool *mem)
 | 
			
		||||
{
 | 
			
		||||
	struct btree *t = pool_alloc(mem, sizeof(*t));
 | 
			
		||||
	struct btree *t = dm_pool_alloc(mem, sizeof(*t));
 | 
			
		||||
 | 
			
		||||
	if (t) {
 | 
			
		||||
		t->mem = mem;
 | 
			
		||||
@@ -77,7 +86,7 @@ int btree_insert(struct btree *t, uint32_t k, void *data)
 | 
			
		||||
	struct node *p, **c = _lookup(&t->root, key, &p), *n;
 | 
			
		||||
 | 
			
		||||
	if (!*c) {
 | 
			
		||||
		if (!(n = pool_alloc(t->mem, sizeof(*n)))) {
 | 
			
		||||
		if (!(n = dm_pool_alloc(t->mem, sizeof(*n)))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -98,7 +107,7 @@ void *btree_get_data(struct btree_iter *it)
 | 
			
		||||
	return ((struct node *) it)->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct node *_left(struct node *n)
 | 
			
		||||
static struct node *_left(struct node *n)
 | 
			
		||||
{
 | 
			
		||||
	while (n->l)
 | 
			
		||||
		n = n->l;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,24 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
#define _LVM_BTREE_H
 | 
			
		||||
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
 | 
			
		||||
struct btree;
 | 
			
		||||
 | 
			
		||||
struct btree *btree_create(struct pool *mem);
 | 
			
		||||
struct btree *btree_create(struct dm_pool *mem);
 | 
			
		||||
 | 
			
		||||
void *btree_lookup(struct btree *t, uint32_t k);
 | 
			
		||||
int btree_insert(struct btree *t, uint32_t k, void *data);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,231 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Sistina Software
 | 
			
		||||
 *
 | 
			
		||||
 * This file is released under the LGPL.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
 | 
			
		||||
struct hash_node {
 | 
			
		||||
	struct hash_node *next;
 | 
			
		||||
	void *data;
 | 
			
		||||
	char key[1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct hash_table {
 | 
			
		||||
	int num_nodes;
 | 
			
		||||
	int num_slots;
 | 
			
		||||
	struct hash_node **slots;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Permutation of the Integers 0 through 255 */
 | 
			
		||||
static unsigned char _nums[] = {
 | 
			
		||||
	1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
 | 
			
		||||
	87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
 | 
			
		||||
	49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
 | 
			
		||||
	12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172,
 | 
			
		||||
	144,
 | 
			
		||||
	176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
 | 
			
		||||
	178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54,
 | 
			
		||||
	221,
 | 
			
		||||
	102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
 | 
			
		||||
	166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
 | 
			
		||||
	121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185,
 | 
			
		||||
	194,
 | 
			
		||||
	193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232,
 | 
			
		||||
	139,
 | 
			
		||||
	6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
 | 
			
		||||
	84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196,
 | 
			
		||||
	43,
 | 
			
		||||
	249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231,
 | 
			
		||||
	71,
 | 
			
		||||
	230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47,
 | 
			
		||||
	109,
 | 
			
		||||
	44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
 | 
			
		||||
	163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
 | 
			
		||||
	209
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct hash_node *_create_node(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	/* 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));
 | 
			
		||||
 | 
			
		||||
	if (n)
 | 
			
		||||
		strcpy(n->key, str);
 | 
			
		||||
 | 
			
		||||
	return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned _hash(const char *str)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long h = 0, g;
 | 
			
		||||
	while (*str) {
 | 
			
		||||
		h <<= 4;
 | 
			
		||||
		h += _nums[(int) *str++];
 | 
			
		||||
		g = h & ((unsigned long) 0xf << 16u);
 | 
			
		||||
		if (g) {
 | 
			
		||||
			h ^= g >> 16u;
 | 
			
		||||
			h ^= g >> 5u;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct hash_table *hash_create(unsigned size_hint)
 | 
			
		||||
{
 | 
			
		||||
	size_t len;
 | 
			
		||||
	unsigned new_size = 16u;
 | 
			
		||||
	struct hash_table *hc = dbg_malloc(sizeof(*hc));
 | 
			
		||||
 | 
			
		||||
	if (!hc) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(hc, 0, sizeof(*hc));
 | 
			
		||||
 | 
			
		||||
	/* round size hint up to a power of two */
 | 
			
		||||
	while (new_size < size_hint)
 | 
			
		||||
		new_size = new_size << 1;
 | 
			
		||||
 | 
			
		||||
	hc->num_slots = new_size;
 | 
			
		||||
	len = sizeof(*(hc->slots)) * new_size;
 | 
			
		||||
	if (!(hc->slots = dbg_malloc(len))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	memset(hc->slots, 0, len);
 | 
			
		||||
	return hc;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	dbg_free(hc->slots);
 | 
			
		||||
	dbg_free(hc);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _free_nodes(struct hash_table *t)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node *c, *n;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < t->num_slots; i++)
 | 
			
		||||
		for (c = t->slots[i]; c; c = n) {
 | 
			
		||||
			n = c->next;
 | 
			
		||||
			dbg_free(c);
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hash_destroy(struct hash_table *t)
 | 
			
		||||
{
 | 
			
		||||
	_free_nodes(t);
 | 
			
		||||
	dbg_free(t->slots);
 | 
			
		||||
	dbg_free(t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct hash_node **_find(struct hash_table *t, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	unsigned h = _hash(key) & (t->num_slots - 1);
 | 
			
		||||
	struct hash_node **c;
 | 
			
		||||
 | 
			
		||||
	for (c = &t->slots[h]; *c; c = &((*c)->next))
 | 
			
		||||
		if (!strcmp(key, (*c)->key))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
	return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *hash_lookup(struct hash_table *t, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node **c = _find(t, key);
 | 
			
		||||
	return *c ? (*c)->data : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int hash_insert(struct hash_table *t, const char *key, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node **c = _find(t, key);
 | 
			
		||||
 | 
			
		||||
	if (*c)
 | 
			
		||||
		(*c)->data = data;
 | 
			
		||||
	else {
 | 
			
		||||
		struct hash_node *n = _create_node(key);
 | 
			
		||||
 | 
			
		||||
		if (!n)
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		n->data = data;
 | 
			
		||||
		n->next = 0;
 | 
			
		||||
		*c = n;
 | 
			
		||||
		t->num_nodes++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hash_remove(struct hash_table *t, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node **c = _find(t, key);
 | 
			
		||||
 | 
			
		||||
	if (*c) {
 | 
			
		||||
		struct hash_node *old = *c;
 | 
			
		||||
		*c = (*c)->next;
 | 
			
		||||
		dbg_free(old);
 | 
			
		||||
		t->num_nodes--;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned hash_get_num_entries(struct hash_table *t)
 | 
			
		||||
{
 | 
			
		||||
	return t->num_nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hash_iter(struct hash_table *t, iterate_fn f)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node *c;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < t->num_slots; i++)
 | 
			
		||||
		for (c = t->slots[i]; c; c = c->next)
 | 
			
		||||
			f(c->data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hash_wipe(struct hash_table *t)
 | 
			
		||||
{
 | 
			
		||||
	_free_nodes(t);
 | 
			
		||||
	memset(t->slots, 0, sizeof(struct hash_node *) * t->num_slots);
 | 
			
		||||
	t->num_nodes = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *hash_get_key(struct hash_table *t, struct hash_node *n)
 | 
			
		||||
{
 | 
			
		||||
	return n->key;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *hash_get_data(struct hash_table *t, struct hash_node *n)
 | 
			
		||||
{
 | 
			
		||||
	return n->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct hash_node *_next_slot(struct hash_table *t, unsigned s)
 | 
			
		||||
{
 | 
			
		||||
	struct hash_node *c = NULL;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = s; i < t->num_slots && !c; i++)
 | 
			
		||||
		c = t->slots[i];
 | 
			
		||||
 | 
			
		||||
	return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct hash_node *hash_get_first(struct hash_table *t)
 | 
			
		||||
{
 | 
			
		||||
	return _next_slot(t, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n)
 | 
			
		||||
{
 | 
			
		||||
	unsigned h = _hash(n->key) & (t->num_slots - 1);
 | 
			
		||||
	return n->next ? n->next : _next_slot(t, h + 1);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										136
									
								
								lib/datastruct/list.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								lib/datastruct/list.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,136 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initialise a list before use.
 | 
			
		||||
 * The list head's next and previous pointers point back to itself.
 | 
			
		||||
 */
 | 
			
		||||
void list_init(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	head->n = head->p = head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element before 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the end of the list.
 | 
			
		||||
 */
 | 
			
		||||
void list_add(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
 | 
			
		||||
	elem->n = head;
 | 
			
		||||
	elem->p = head->p;
 | 
			
		||||
 | 
			
		||||
	head->p->n = elem;
 | 
			
		||||
	head->p = elem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element after 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the front of the list.
 | 
			
		||||
 */
 | 
			
		||||
void list_add_h(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
 | 
			
		||||
	elem->n = head->n;
 | 
			
		||||
	elem->p = head;
 | 
			
		||||
 | 
			
		||||
	head->n->p = elem;
 | 
			
		||||
	head->n = elem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Delete an element from its list.
 | 
			
		||||
 * Note that this doesn't change the element itself - it may still be safe
 | 
			
		||||
 * to follow its pointers.
 | 
			
		||||
 */
 | 
			
		||||
void list_del(struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	elem->n->p = elem->p;
 | 
			
		||||
	elem->p->n = elem->n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is the list empty?
 | 
			
		||||
 */
 | 
			
		||||
int list_empty(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return head->n == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the first element of the list?
 | 
			
		||||
 */
 | 
			
		||||
int list_start(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->p == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the last element of the list?
 | 
			
		||||
 */
 | 
			
		||||
int list_end(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->n == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return first element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_first(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return last element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_last(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the previous element of the list, or NULL if we've reached the start.
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_prev(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_start(head, elem) ? NULL : elem->p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the next element of the list, or NULL if we've reached the end.
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_end(head, elem) ? NULL : elem->n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the number of elements in a list by walking it.
 | 
			
		||||
 */
 | 
			
		||||
unsigned int list_size(const struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s = 0;
 | 
			
		||||
	const struct list *v;
 | 
			
		||||
 | 
			
		||||
	list_iterate(v, head)
 | 
			
		||||
	    s++;
 | 
			
		||||
 | 
			
		||||
	return s;
 | 
			
		||||
}
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -9,83 +18,186 @@
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A list consists of a list head plus elements.
 | 
			
		||||
 * Each element has 'next' and 'previous' pointers.
 | 
			
		||||
 * The list head's pointers point to the first and the last element.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct list {
 | 
			
		||||
	struct list *n, *p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline void list_init(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	head->n = head->p = head;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Initialise a list before use.
 | 
			
		||||
 * The list head's next and previous pointers point back to itself.
 | 
			
		||||
 */
 | 
			
		||||
#define LIST_INIT(name)	struct list name = { &(name), &(name) }
 | 
			
		||||
void list_init(struct list *head);
 | 
			
		||||
 | 
			
		||||
static inline void list_add(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element before 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the end of the list.
 | 
			
		||||
 */
 | 
			
		||||
void list_add(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
	elem->n = head;
 | 
			
		||||
	elem->p = head->p;
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element after 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the front of the list.
 | 
			
		||||
 */
 | 
			
		||||
void list_add_h(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
	head->p->n = elem;
 | 
			
		||||
	head->p = elem;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Delete an element from its list.
 | 
			
		||||
 * Note that this doesn't change the element itself - it may still be safe
 | 
			
		||||
 * to follow its pointers.
 | 
			
		||||
 */
 | 
			
		||||
void list_del(struct list *elem);
 | 
			
		||||
 | 
			
		||||
static inline void list_add_h(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
/*
 | 
			
		||||
 * Is the list empty?
 | 
			
		||||
 */
 | 
			
		||||
int list_empty(struct list *head);
 | 
			
		||||
 | 
			
		||||
	elem->n = head->n;
 | 
			
		||||
	elem->p = head;
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the first element of the list?
 | 
			
		||||
 */
 | 
			
		||||
int list_start(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
	head->n->p = elem;
 | 
			
		||||
	head->n = elem;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the last element of the list?
 | 
			
		||||
 */
 | 
			
		||||
int list_end(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
static inline void list_del(struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	elem->n->p = elem->p;
 | 
			
		||||
	elem->p->n = elem->n;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Return first element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_first(struct list *head);
 | 
			
		||||
 | 
			
		||||
static inline int list_empty(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return head->n == head;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Return last element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_last(struct list *head);
 | 
			
		||||
 | 
			
		||||
static inline int list_end(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->n == head;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Return the previous element of the list, or NULL if we've reached the start.
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_prev(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
static inline struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_end(head, elem) ? NULL : elem->n);
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Return the next element of the list, or NULL if we've reached the end.
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_next(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
#define list_iterate(v, head) \
 | 
			
		||||
	for (v = (head)->n; v != head; v = v->n)
 | 
			
		||||
/*
 | 
			
		||||
 * Given the address v of an instance of 'struct list' called 'head' 
 | 
			
		||||
 * contained in a structure of type t, return the containing structure.
 | 
			
		||||
 */
 | 
			
		||||
#define list_struct_base(v, t, head) \
 | 
			
		||||
    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->head))
 | 
			
		||||
 | 
			
		||||
#define list_iterate_safe(v, t, head) \
 | 
			
		||||
	for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
 | 
			
		||||
/*
 | 
			
		||||
 * Given the address v of an instance of 'struct list list' contained in
 | 
			
		||||
 * a structure of type t, return the containing structure.
 | 
			
		||||
 */
 | 
			
		||||
#define list_item(v, t) list_struct_base((v), t, list)
 | 
			
		||||
 | 
			
		||||
static inline unsigned int list_size(const struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s = 0;
 | 
			
		||||
	const struct list *v;
 | 
			
		||||
 | 
			
		||||
	list_iterate(v, head)
 | 
			
		||||
	    s++;
 | 
			
		||||
 | 
			
		||||
	return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define list_item(v, t) \
 | 
			
		||||
    ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
 | 
			
		||||
 | 
			
		||||
/* Given a known element in a known structure, locate another */
 | 
			
		||||
/*
 | 
			
		||||
 * Given the address v of one known element e in a known structure of type t,
 | 
			
		||||
 * return another element f.
 | 
			
		||||
 */
 | 
			
		||||
#define struct_field(v, t, e, f) \
 | 
			
		||||
    (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
 | 
			
		||||
 | 
			
		||||
/* Given a known element in a known structure, locate the list head */
 | 
			
		||||
/*
 | 
			
		||||
 * Given the address v of a known element e in a known structure of type t,
 | 
			
		||||
 * return the list head 'list'
 | 
			
		||||
 */
 | 
			
		||||
#define list_head(v, t, e) struct_field(v, t, e, list)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set v to each element of a list in turn.
 | 
			
		||||
 */
 | 
			
		||||
#define list_iterate(v, head) \
 | 
			
		||||
	for (v = (head)->n; v != head; v = v->n)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set v to each element in a list in turn, starting from the element 
 | 
			
		||||
 * in front of 'start'.
 | 
			
		||||
 * You can use this to 'unwind' a list_iterate and back out actions on
 | 
			
		||||
 * already-processed elements.
 | 
			
		||||
 * If 'start' is 'head' it walks the list backwards.
 | 
			
		||||
 */
 | 
			
		||||
#define list_uniterate(v, head, start) \
 | 
			
		||||
	for (v = (start)->p; v != head; v = v->p)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A safe way to walk a list and delete and free some elements along
 | 
			
		||||
 * the way.
 | 
			
		||||
 * t must be defined as a temporary variable of the same type as v.
 | 
			
		||||
 */
 | 
			
		||||
#define list_iterate_safe(v, t, head) \
 | 
			
		||||
	for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Walk a list, setting 'v' in turn to the containing structure of each item.
 | 
			
		||||
 * The containing structure should be the same type as 'v'.
 | 
			
		||||
 * The 'struct list' variable within the containing structure is 'field'.
 | 
			
		||||
 */
 | 
			
		||||
#define list_iterate_items_gen(v, head, field) \
 | 
			
		||||
	for (v = list_struct_base((head)->n, typeof(*v), field); \
 | 
			
		||||
	     &v->field != (head); \
 | 
			
		||||
	     v = list_struct_base(v->field.n, typeof(*v), field))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Walk a list, setting 'v' in turn to the containing structure of each item.
 | 
			
		||||
 * The containing structure should be the same type as 'v'.
 | 
			
		||||
 * The list should be 'struct list list' within the containing structure.
 | 
			
		||||
 */
 | 
			
		||||
#define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Walk a list, setting 'v' in turn to the containing structure of each item.
 | 
			
		||||
 * The containing structure should be the same type as 'v'.
 | 
			
		||||
 * The 'struct list' variable within the containing structure is 'field'.
 | 
			
		||||
 * t must be defined as a temporary variable of the same type as v.
 | 
			
		||||
 */
 | 
			
		||||
#define list_iterate_items_gen_safe(v, t, head, field) \
 | 
			
		||||
	for (v = list_struct_base((head)->n, typeof(*v), field), \
 | 
			
		||||
	     t = list_struct_base(v->field.n, typeof(*v), field); \
 | 
			
		||||
	     &v->field != (head); \
 | 
			
		||||
	     v = t, t = list_struct_base(v->field.n, typeof(*v), field))
 | 
			
		||||
/*
 | 
			
		||||
 * Walk a list, setting 'v' in turn to the containing structure of each item.
 | 
			
		||||
 * The containing structure should be the same type as 'v'.
 | 
			
		||||
 * The list should be 'struct list list' within the containing structure.
 | 
			
		||||
 * t must be defined as a temporary variable of the same type as v.
 | 
			
		||||
 */
 | 
			
		||||
#define list_iterate_items_safe(v, t, head) \
 | 
			
		||||
	list_iterate_items_gen_safe(v, t, (head), list)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Walk a list backwards, setting 'v' in turn to the containing structure 
 | 
			
		||||
 * of each item.
 | 
			
		||||
 * The containing structure should be the same type as 'v'.
 | 
			
		||||
 * The 'struct list' variable within the containing structure is 'field'.
 | 
			
		||||
 */
 | 
			
		||||
#define list_iterate_back_items_gen(v, head, field) \
 | 
			
		||||
	for (v = list_struct_base((head)->p, typeof(*v), field); \
 | 
			
		||||
	     &v->field != (head); \
 | 
			
		||||
	     v = list_struct_base(v->field.p, typeof(*v), field))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Walk a list backwards, setting 'v' in turn to the containing structure 
 | 
			
		||||
 * of each item.
 | 
			
		||||
 * The containing structure should be the same type as 'v'.
 | 
			
		||||
 * The list should be 'struct list list' within the containing structure.
 | 
			
		||||
 */
 | 
			
		||||
#define list_iterate_back_items(v, head) list_iterate_back_items_gen(v, (head), list)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the number of elements in a list by walking it.
 | 
			
		||||
 */
 | 
			
		||||
unsigned int list_size(const struct list *head);
 | 
			
		||||
 | 
			
		||||
#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_TYPES_H
 | 
			
		||||
@@ -13,11 +22,11 @@
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
/* Define some portable printing types */
 | 
			
		||||
#define PRIsize_t "Zu"
 | 
			
		||||
#define PRIsize_t "zu"
 | 
			
		||||
 | 
			
		||||
struct str_list {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	char *str;
 | 
			
		||||
	const char *str;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										128
									
								
								lib/datastruct/str_list.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								lib/datastruct/str_list.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
 | 
			
		||||
struct list *str_list_create(struct dm_pool *mem)
 | 
			
		||||
{
 | 
			
		||||
	struct list *sl;
 | 
			
		||||
 | 
			
		||||
	if (!(sl = dm_pool_alloc(mem, sizeof(struct list)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(sl);
 | 
			
		||||
 | 
			
		||||
	return sl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sln;
 | 
			
		||||
 | 
			
		||||
	if (!str) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Already in list? */
 | 
			
		||||
	if (str_list_match_item(sll, str))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!(sln = dm_pool_alloc(mem, sizeof(*sln)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sln->str = str;
 | 
			
		||||
	list_add(sll, &sln->list);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int str_list_del(struct list *sll, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	struct list *slh, *slht;
 | 
			
		||||
 | 
			
		||||
	list_iterate_safe(slh, slht, sll) {
 | 
			
		||||
		if (!strcmp(str, list_item(slh, struct str_list)->str))
 | 
			
		||||
			 list_del(slh);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int str_list_dup(struct dm_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;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(sl, sll)
 | 
			
		||||
	    if (!strcmp(str, sl->str))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(sl, sll)
 | 
			
		||||
	    if (str_list_match_item(sll2, sl->str))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								lib/datastruct/str_list.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								lib/datastruct/str_list.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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_STR_LIST_H
 | 
			
		||||
#define _LVM_STR_LIST_H
 | 
			
		||||
 | 
			
		||||
struct list *str_list_create(struct dm_pool *mem);
 | 
			
		||||
int str_list_add(struct dm_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 dm_pool *mem, struct list *sllnew, struct list *sllold);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,17 +1,24 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "btree.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "filter-persistent.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/param.h>
 | 
			
		||||
@@ -28,21 +35,80 @@ struct dir_list {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
	struct hash_table *names;
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	struct dm_hash_table *names;
 | 
			
		||||
	struct btree *devices;
 | 
			
		||||
 | 
			
		||||
	int has_scanned;
 | 
			
		||||
	struct list dirs;
 | 
			
		||||
	struct list files;
 | 
			
		||||
 | 
			
		||||
} _cache;
 | 
			
		||||
 | 
			
		||||
#define _alloc(x) pool_alloc(_cache.mem, (x))
 | 
			
		||||
#define _free(x) pool_free(_cache.mem, (x))
 | 
			
		||||
#define _alloc(x) dm_pool_zalloc(_cache.mem, (x))
 | 
			
		||||
#define _free(x) dm_pool_free(_cache.mem, (x))
 | 
			
		||||
#define _strdup(x) dm_pool_strdup(_cache.mem, (x))
 | 
			
		||||
 | 
			
		||||
static int _insert(const char *path, int rec);
 | 
			
		||||
 | 
			
		||||
static struct device *_create_dev(dev_t d)
 | 
			
		||||
struct device *dev_create_file(const char *filename, struct device *dev,
 | 
			
		||||
			       struct str_list *alias, int use_malloc)
 | 
			
		||||
{
 | 
			
		||||
	int allocate = !dev;
 | 
			
		||||
 | 
			
		||||
	if (allocate) {
 | 
			
		||||
		if (use_malloc) {
 | 
			
		||||
			if (!(dev = dm_malloc(sizeof(*dev)))) {
 | 
			
		||||
				log_error("struct device allocation failed");
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(alias = dm_malloc(sizeof(*alias)))) {
 | 
			
		||||
				log_error("struct str_list allocation failed");
 | 
			
		||||
				dm_free(dev);
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(alias->str = dm_strdup(filename))) {
 | 
			
		||||
				log_error("filename strdup failed");
 | 
			
		||||
				dm_free(dev);
 | 
			
		||||
				dm_free(alias);
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			dev->flags = DEV_ALLOCED;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (!(dev = _alloc(sizeof(*dev)))) {
 | 
			
		||||
				log_error("struct device allocation failed");
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(alias = _alloc(sizeof(*alias)))) {
 | 
			
		||||
				log_error("struct str_list allocation failed");
 | 
			
		||||
				_free(dev);
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(alias->str = _strdup(filename))) {
 | 
			
		||||
				log_error("filename strdup failed");
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else if (!(alias->str = dm_strdup(filename))) {
 | 
			
		||||
		log_error("filename strdup failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev->flags |= DEV_REGULAR;
 | 
			
		||||
	list_init(&dev->aliases);
 | 
			
		||||
	list_add(&dev->aliases, &alias->list);
 | 
			
		||||
	dev->end = UINT64_C(0);
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	return dev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct device *_dev_create(dev_t d)
 | 
			
		||||
{
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
 | 
			
		||||
@@ -50,12 +116,15 @@ static struct device *_create_dev(dev_t d)
 | 
			
		||||
		log_error("struct device allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev->flags = 0;
 | 
			
		||||
	list_init(&dev->aliases);
 | 
			
		||||
	dev->dev = d;
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	dev->flags = 0;
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	return dev;
 | 
			
		||||
}
 | 
			
		||||
@@ -124,7 +193,7 @@ static int _compare_paths(const char *path0, const char *path1)
 | 
			
		||||
static int _add_alias(struct device *dev, const char *path)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl = _alloc(sizeof(*sl));
 | 
			
		||||
	struct list *ah;
 | 
			
		||||
	struct str_list *strl;
 | 
			
		||||
	const char *oldpath;
 | 
			
		||||
	int prefer_old = 1;
 | 
			
		||||
 | 
			
		||||
@@ -134,14 +203,14 @@ static int _add_alias(struct device *dev, const char *path)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Is name already there? */
 | 
			
		||||
	list_iterate(ah, &dev->aliases) {
 | 
			
		||||
		if (!strcmp(list_item(ah, struct str_list)->str, path)) {
 | 
			
		||||
			stack;
 | 
			
		||||
	list_iterate_items(strl, &dev->aliases) {
 | 
			
		||||
		if (!strcmp(strl->str, path)) {
 | 
			
		||||
			log_debug("%s: Already in device cache", path);
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(sl->str = pool_strdup(_cache.mem, path))) {
 | 
			
		||||
	if (!(sl->str = dm_pool_strdup(_cache.mem, path))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -170,12 +239,27 @@ static int _add_alias(struct device *dev, const char *path)
 | 
			
		||||
static int _insert_dev(const char *path, dev_t d)
 | 
			
		||||
{
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	static dev_t loopfile_count = 0;
 | 
			
		||||
	int loopfile = 0;
 | 
			
		||||
 | 
			
		||||
	/* Generate pretend device numbers for loopfiles */
 | 
			
		||||
	if (!d) {
 | 
			
		||||
		if (dm_hash_lookup(_cache.names, path))
 | 
			
		||||
			return 1;
 | 
			
		||||
		d = ++loopfile_count;
 | 
			
		||||
		loopfile = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* is this device already registered ? */
 | 
			
		||||
	if (!(dev = (struct device *) btree_lookup(_cache.devices,
 | 
			
		||||
						   (uint32_t) d))) {
 | 
			
		||||
		/* create new device */
 | 
			
		||||
		if (!(dev = _create_dev(d))) {
 | 
			
		||||
		if (loopfile) {
 | 
			
		||||
			if (!(dev = dev_create_file(path, NULL, NULL, 0))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (!(dev = _dev_create(d))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -187,12 +271,12 @@ static int _insert_dev(const char *path, dev_t d)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_add_alias(dev, path)) {
 | 
			
		||||
	if (!loopfile && !_add_alias(dev, path)) {
 | 
			
		||||
		log_err("Couldn't add alias to dev cache.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!hash_insert(_cache.names, path, dev)) {
 | 
			
		||||
	if (!dm_hash_insert(_cache.names, path, dev)) {
 | 
			
		||||
		log_err("Couldn't add name to hash in dev cache.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -203,7 +287,7 @@ static int _insert_dev(const char *path, dev_t d)
 | 
			
		||||
static char *_join(const char *dir, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	size_t len = strlen(dir) + strlen(name) + 2;
 | 
			
		||||
	char *r = dbg_malloc(len);
 | 
			
		||||
	char *r = dm_malloc(len);
 | 
			
		||||
	if (r)
 | 
			
		||||
		snprintf(r, len, "%s/%s", dir, name);
 | 
			
		||||
 | 
			
		||||
@@ -253,7 +337,7 @@ static int _insert_dir(const char *dir)
 | 
			
		||||
 | 
			
		||||
			_collapse_slashes(path);
 | 
			
		||||
			r &= _insert(path, 1);
 | 
			
		||||
			dbg_free(path);
 | 
			
		||||
			dm_free(path);
 | 
			
		||||
 | 
			
		||||
			free(dirent[n]);
 | 
			
		||||
		}
 | 
			
		||||
@@ -263,6 +347,28 @@ static int _insert_dir(const char *dir)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _insert_file(const char *path)
 | 
			
		||||
{
 | 
			
		||||
	struct stat info;
 | 
			
		||||
 | 
			
		||||
	if (stat(path, &info) < 0) {
 | 
			
		||||
		log_sys_very_verbose("stat", path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!S_ISREG(info.st_mode)) {
 | 
			
		||||
		log_debug("%s: Not a regular file", path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_insert_dev(path, 0)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _insert(const char *path, int rec)
 | 
			
		||||
{
 | 
			
		||||
	struct stat info;
 | 
			
		||||
@@ -274,6 +380,17 @@ static int _insert(const char *path, int rec)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (S_ISDIR(info.st_mode)) {	/* add a directory */
 | 
			
		||||
		/* check it's not a symbolic link */
 | 
			
		||||
		if (lstat(path, &info) < 0) {
 | 
			
		||||
			log_sys_very_verbose("lstat", path);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (S_ISLNK(info.st_mode)) {
 | 
			
		||||
			log_debug("%s: Symbolic link to directory", path);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (rec)
 | 
			
		||||
			r = _insert_dir(path);
 | 
			
		||||
 | 
			
		||||
@@ -294,19 +411,21 @@ static int _insert(const char *path, int rec)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _full_scan(void)
 | 
			
		||||
static void _full_scan(int dev_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *dh;
 | 
			
		||||
	struct dir_list *dl;
 | 
			
		||||
 | 
			
		||||
	if (_cache.has_scanned)
 | 
			
		||||
	if (_cache.has_scanned && !dev_scan)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	list_iterate(dh, &_cache.dirs) {
 | 
			
		||||
		struct dir_list *dl = list_item(dh, struct dir_list);
 | 
			
		||||
	list_iterate_items(dl, &_cache.dirs)
 | 
			
		||||
		_insert_dir(dl->dir);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(dl, &_cache.files)
 | 
			
		||||
		_insert_file(dl->dir);
 | 
			
		||||
 | 
			
		||||
	_cache.has_scanned = 1;
 | 
			
		||||
	init_full_scan_done(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_cache_has_scanned(void)
 | 
			
		||||
@@ -318,24 +437,23 @@ void dev_cache_scan(int do_scan)
 | 
			
		||||
{
 | 
			
		||||
	if (!do_scan)
 | 
			
		||||
		_cache.has_scanned = 1;
 | 
			
		||||
	else {
 | 
			
		||||
		_cache.has_scanned = 0;
 | 
			
		||||
		_full_scan();
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		_full_scan(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_cache_init(void)
 | 
			
		||||
{
 | 
			
		||||
	_cache.names = NULL;
 | 
			
		||||
	_cache.has_scanned = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(_cache.mem = pool_create(10 * 1024))) {
 | 
			
		||||
	if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(_cache.names = hash_create(128))) {
 | 
			
		||||
	if (!(_cache.names = dm_hash_create(128))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		pool_destroy(_cache.mem);
 | 
			
		||||
		dm_pool_destroy(_cache.mem);
 | 
			
		||||
		_cache.mem = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -346,6 +464,7 @@ int dev_cache_init(void)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_init(&_cache.dirs);
 | 
			
		||||
	list_init(&_cache.files);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
 | 
			
		||||
@@ -360,18 +479,30 @@ static void _check_closed(struct device *dev)
 | 
			
		||||
		log_err("Device '%s' has been left open.", dev_name(dev));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void _check_for_open_devices(void)
 | 
			
		||||
static void _check_for_open_devices(void)
 | 
			
		||||
{
 | 
			
		||||
	hash_iter(_cache.names, (iterate_fn) _check_closed);
 | 
			
		||||
	dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dev_cache_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	_check_for_open_devices();
 | 
			
		||||
 | 
			
		||||
	pool_destroy(_cache.mem);
 | 
			
		||||
	if (_cache.names)
 | 
			
		||||
		hash_destroy(_cache.names);
 | 
			
		||||
		_check_for_open_devices();
 | 
			
		||||
 | 
			
		||||
	if (_cache.mem) {
 | 
			
		||||
		dm_pool_destroy(_cache.mem);
 | 
			
		||||
		_cache.mem = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_cache.names) {
 | 
			
		||||
		dm_hash_destroy(_cache.names);
 | 
			
		||||
		_cache.names = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_cache.devices = NULL;
 | 
			
		||||
	_cache.has_scanned = 0;
 | 
			
		||||
	list_init(&_cache.dirs);
 | 
			
		||||
	list_init(&_cache.files);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_cache_add_dir(const char *path)
 | 
			
		||||
@@ -400,25 +531,65 @@ int dev_cache_add_dir(const char *path)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_cache_add_loopfile(const char *path)
 | 
			
		||||
{
 | 
			
		||||
	struct dir_list *dl;
 | 
			
		||||
	struct stat st;
 | 
			
		||||
 | 
			
		||||
	if (stat(path, &st)) {
 | 
			
		||||
		log_error("Ignoring %s: %s", path, strerror(errno));
 | 
			
		||||
		/* But don't fail */
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!S_ISREG(st.st_mode)) {
 | 
			
		||||
		log_error("Ignoring %s: Not a regular file", path);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) {
 | 
			
		||||
		log_error("dir_list allocation failed for file");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strcpy(dl->dir, path);
 | 
			
		||||
	list_add(&_cache.files, &dl->list);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check cached device name is still valid before returning it */
 | 
			
		||||
/* This should be a rare occurrence */
 | 
			
		||||
/* set quiet if the cache is expected to be out-of-date */
 | 
			
		||||
/* FIXME Make rest of code pass/cache struct device instead of dev_name */
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev)
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev, int quiet)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	char *name;
 | 
			
		||||
	const char *name;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if ((dev->flags & DEV_REGULAR))
 | 
			
		||||
		return dev_name(dev);
 | 
			
		||||
 | 
			
		||||
	while ((r = stat(name = list_item(dev->aliases.n,
 | 
			
		||||
					  struct str_list)->str, &buf)) ||
 | 
			
		||||
	       (buf.st_rdev != dev->dev)) {
 | 
			
		||||
		if (r < 0)
 | 
			
		||||
			log_sys_error("stat", name);
 | 
			
		||||
		log_error("Path %s no longer valid for device(%d,%d)",
 | 
			
		||||
			  name, (int) MAJOR(dev->dev), (int) MINOR(dev->dev));
 | 
			
		||||
		if (r < 0) {
 | 
			
		||||
			if (quiet)
 | 
			
		||||
				log_sys_debug("stat", name);
 | 
			
		||||
			else
 | 
			
		||||
				log_sys_error("stat", name);
 | 
			
		||||
		}
 | 
			
		||||
		if (quiet)
 | 
			
		||||
			log_debug("Path %s no longer valid for device(%d,%d)",
 | 
			
		||||
				  name, (int) MAJOR(dev->dev),
 | 
			
		||||
				  (int) MINOR(dev->dev));
 | 
			
		||||
		else
 | 
			
		||||
			log_error("Path %s no longer valid for device(%d,%d)",
 | 
			
		||||
				  name, (int) MAJOR(dev->dev),
 | 
			
		||||
				  (int) MINOR(dev->dev));
 | 
			
		||||
 | 
			
		||||
		/* Remove the incorrect hash entry */
 | 
			
		||||
		hash_remove(_cache.names, name);
 | 
			
		||||
		dm_hash_remove(_cache.names, name);
 | 
			
		||||
 | 
			
		||||
		/* Leave list alone if there isn't an alternative name */
 | 
			
		||||
		/* so dev_name will always find something to return. */
 | 
			
		||||
@@ -441,32 +612,46 @@ const char *dev_name_confirmed(struct device *dev)
 | 
			
		||||
struct device *dev_cache_get(const char *name, struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	struct device *d = (struct device *) hash_lookup(_cache.names, name);
 | 
			
		||||
	struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
 | 
			
		||||
 | 
			
		||||
	if (d && (d->flags & DEV_REGULAR))
 | 
			
		||||
		return d;
 | 
			
		||||
 | 
			
		||||
	/* If the entry's wrong, remove it */
 | 
			
		||||
	if (d && (stat(name, &buf) || (buf.st_rdev != d->dev))) {
 | 
			
		||||
		hash_remove(_cache.names, name);
 | 
			
		||||
		dm_hash_remove(_cache.names, name);
 | 
			
		||||
		d = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!d) {
 | 
			
		||||
		_insert(name, 0);
 | 
			
		||||
		d = (struct device *) hash_lookup(_cache.names, name);
 | 
			
		||||
		d = (struct device *) dm_hash_lookup(_cache.names, name);
 | 
			
		||||
		if (!d) {
 | 
			
		||||
			_full_scan(0);
 | 
			
		||||
			d = (struct device *) dm_hash_lookup(_cache.names, name);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (d && (!f || f->passes_filter(f, d))) ? d : NULL;
 | 
			
		||||
	return (d && (!f || (d->flags & DEV_REGULAR) ||
 | 
			
		||||
		      f->passes_filter(f, d))) ? d : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dev_iter *dev_iter_create(struct dev_filter *f)
 | 
			
		||||
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_iter *di = dbg_malloc(sizeof(*di));
 | 
			
		||||
	struct dev_iter *di = dm_malloc(sizeof(*di));
 | 
			
		||||
 | 
			
		||||
	if (!di) {
 | 
			
		||||
		log_error("dev_iter allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_full_scan();
 | 
			
		||||
	if (dev_scan && !trust_cache()) {
 | 
			
		||||
		/* Flag gets reset between each command */
 | 
			
		||||
		if (!full_scan_done())
 | 
			
		||||
			persistent_filter_wipe(f); /* Calls _full_scan(1) */
 | 
			
		||||
	} else
 | 
			
		||||
		_full_scan(0);
 | 
			
		||||
 | 
			
		||||
	di->current = btree_first(_cache.devices);
 | 
			
		||||
	di->filter = f;
 | 
			
		||||
 | 
			
		||||
@@ -475,10 +660,10 @@ struct dev_iter *dev_iter_create(struct dev_filter *f)
 | 
			
		||||
 | 
			
		||||
void dev_iter_destroy(struct dev_iter *iter)
 | 
			
		||||
{
 | 
			
		||||
	dbg_free(iter);
 | 
			
		||||
	dm_free(iter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct device *_iter_next(struct dev_iter *iter)
 | 
			
		||||
static struct device *_iter_next(struct dev_iter *iter)
 | 
			
		||||
{
 | 
			
		||||
	struct device *d = btree_get_data(iter->current);
 | 
			
		||||
	iter->current = btree_next(iter->current);
 | 
			
		||||
@@ -489,10 +674,21 @@ struct device *dev_iter_get(struct dev_iter *iter)
 | 
			
		||||
{
 | 
			
		||||
	while (iter->current) {
 | 
			
		||||
		struct device *d = _iter_next(iter);
 | 
			
		||||
		if (!iter->filter ||
 | 
			
		||||
		if (!iter->filter || (d->flags & DEV_REGULAR) ||
 | 
			
		||||
		    iter->filter->passes_filter(iter->filter, d))
 | 
			
		||||
			return d;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_fd(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dev_name(const struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
 | 
			
		||||
	    "unknown device";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,21 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
#define _LVM_DEV_CACHE_H
 | 
			
		||||
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -30,13 +38,14 @@ void dev_cache_scan(int do_scan);
 | 
			
		||||
int dev_cache_has_scanned(void);
 | 
			
		||||
 | 
			
		||||
int dev_cache_add_dir(const char *path);
 | 
			
		||||
int dev_cache_add_loopfile(const char *path);
 | 
			
		||||
struct device *dev_cache_get(const char *name, struct dev_filter *f);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Object for iterating through the cache.
 | 
			
		||||
 */
 | 
			
		||||
struct dev_iter;
 | 
			
		||||
struct dev_iter *dev_iter_create(struct dev_filter *f);
 | 
			
		||||
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
 | 
			
		||||
void dev_iter_destroy(struct dev_iter *iter);
 | 
			
		||||
struct device *dev_iter_get(struct dev_iter *iter);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,25 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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"
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
@@ -17,20 +29,222 @@
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
#  define u64 uint64_t		/* Missing without __KERNEL__ */
 | 
			
		||||
#  undef WNOHANG		/* Avoid redefinition */
 | 
			
		||||
#  undef WUNTRACED		/* Avoid redefinition */
 | 
			
		||||
#  include <linux/fs.h>		/* For block ioctl definitions */
 | 
			
		||||
#  define BLKSIZE_SHIFT SECTOR_SHIFT
 | 
			
		||||
#  ifndef BLKGETSIZE64		/* fs.h out-of-date */
 | 
			
		||||
#    define BLKGETSIZE64 _IOR(0x12, 114, size_t)
 | 
			
		||||
#  endif /* BLKGETSIZE64 */
 | 
			
		||||
#else
 | 
			
		||||
#  include <sys/disk.h>
 | 
			
		||||
#  define BLKBSZGET DKIOCGETBLOCKSIZE
 | 
			
		||||
#  define BLKSSZGET DKIOCGETBLOCKSIZE
 | 
			
		||||
#  define BLKGETSIZE64 DKIOCGETBLOCKCOUNT
 | 
			
		||||
#  define BLKFLSBUF DKIOCSYNCHRONIZECACHE
 | 
			
		||||
#  define BLKSIZE_SHIFT 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* FIXME 64 bit offset!!!
 | 
			
		||||
_syscall5(int,  _llseek,  uint,  fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
 | 
			
		||||
*/
 | 
			
		||||
#ifdef O_DIRECT_SUPPORT
 | 
			
		||||
#  ifndef O_DIRECT
 | 
			
		||||
#    error O_DIRECT support configured but O_DIRECT definition not found in headers
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int dev_get_size(struct device *dev, uint64_t *size)
 | 
			
		||||
static LIST_INIT(_open_devices);
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------
 | 
			
		||||
 * The standard io loop that keeps submitting an io until it's
 | 
			
		||||
 * all gone.
 | 
			
		||||
 *---------------------------------------------------------------*/
 | 
			
		||||
static int _io(struct device_area *where, void *buffer, int should_write)
 | 
			
		||||
{
 | 
			
		||||
	int fd = dev_fd(where->dev);
 | 
			
		||||
	ssize_t n = 0;
 | 
			
		||||
	size_t total = 0;
 | 
			
		||||
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		log_error("Attempt to read an unopened device (%s).",
 | 
			
		||||
			  dev_name(where->dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Skip all writes in test mode.
 | 
			
		||||
	 */
 | 
			
		||||
	if (should_write && test_mode())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (where->size > SSIZE_MAX) {
 | 
			
		||||
		log_error("Read size too large: %" PRIu64, where->size);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
 | 
			
		||||
		log_error("%s: lseek %" PRIu64 " failed: %s",
 | 
			
		||||
			  dev_name(where->dev), (uint64_t) where->start,
 | 
			
		||||
			  strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (total < (size_t) where->size) {
 | 
			
		||||
		do
 | 
			
		||||
			n = should_write ?
 | 
			
		||||
			    write(fd, buffer, (size_t) where->size - total) :
 | 
			
		||||
			    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;
 | 
			
		||||
 | 
			
		||||
		total += n;
 | 
			
		||||
		buffer += n;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (total == (size_t) where->size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------
 | 
			
		||||
 * LVM2 uses O_DIRECT when performing metadata io, which requires
 | 
			
		||||
 * block size aligned accesses.  If any io is not aligned we have
 | 
			
		||||
 * to perform the io via a bounce buffer, obviously this is quite
 | 
			
		||||
 * inefficient.
 | 
			
		||||
 *---------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Get the sector size from an _open_ device.
 | 
			
		||||
 */
 | 
			
		||||
static int _get_block_size(struct device *dev, unsigned int *size)
 | 
			
		||||
{
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
 | 
			
		||||
	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) dev->block_size;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Widens a region to be an aligned region.
 | 
			
		||||
 */
 | 
			
		||||
static void _widen_region(unsigned int block_size, struct device_area *region,
 | 
			
		||||
			  struct device_area *result)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t mask = block_size - 1, delta;
 | 
			
		||||
	memcpy(result, region, sizeof(*result));
 | 
			
		||||
 | 
			
		||||
	/* adjust the start */
 | 
			
		||||
	delta = result->start & mask;
 | 
			
		||||
	if (delta) {
 | 
			
		||||
		result->start -= delta;
 | 
			
		||||
		result->size += delta;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* adjust the end */
 | 
			
		||||
	delta = (result->start + result->size) & mask;
 | 
			
		||||
	if (delta)
 | 
			
		||||
		result->size += block_size - delta;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _aligned_io(struct device_area *where, void *buffer,
 | 
			
		||||
		       int should_write)
 | 
			
		||||
{
 | 
			
		||||
	void *bounce;
 | 
			
		||||
	unsigned int block_size = 0;
 | 
			
		||||
	uintptr_t mask;
 | 
			
		||||
	struct device_area widened;
 | 
			
		||||
 | 
			
		||||
	if (!(where->dev->flags & DEV_REGULAR) &&
 | 
			
		||||
	    !_get_block_size(where->dev, &block_size)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!block_size)
 | 
			
		||||
		block_size = getpagesize();
 | 
			
		||||
 | 
			
		||||
	_widen_region(block_size, where, &widened);
 | 
			
		||||
 | 
			
		||||
	/* Do we need to use a bounce buffer? */
 | 
			
		||||
	mask = block_size - 1;
 | 
			
		||||
	if (!memcmp(where, &widened, sizeof(widened)) &&
 | 
			
		||||
	    !((uintptr_t) buffer & mask))
 | 
			
		||||
		return _io(where, buffer, should_write);
 | 
			
		||||
 | 
			
		||||
	/* Allocate a bounce buffer with an extra block */
 | 
			
		||||
	if (!(bounce = alloca((size_t) widened.size + block_size))) {
 | 
			
		||||
		log_error("Bounce buffer alloca failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Realign start of bounce buffer (using the extra sector)
 | 
			
		||||
	 */
 | 
			
		||||
	if (((uintptr_t) bounce) & mask)
 | 
			
		||||
		bounce = (void *) ((((uintptr_t) bounce) + mask) & ~mask);
 | 
			
		||||
 | 
			
		||||
	/* channel the io through the bounce buffer */
 | 
			
		||||
	if (!_io(&widened, bounce, 0)) {
 | 
			
		||||
		if (!should_write) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		/* FIXME pre-extend the file */
 | 
			
		||||
		memset(bounce, '\n', widened.size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (should_write) {
 | 
			
		||||
		memcpy(bounce + (where->start - widened.start), buffer,
 | 
			
		||||
		       (size_t) where->size);
 | 
			
		||||
 | 
			
		||||
		/* ... then we write */
 | 
			
		||||
		return _io(&widened, bounce, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(buffer, bounce + (where->start - widened.start),
 | 
			
		||||
	       (size_t) where->size);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _dev_get_size_file(const struct device *dev, uint64_t *size)
 | 
			
		||||
{
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	struct stat info;
 | 
			
		||||
 | 
			
		||||
	if (stat(name, &info)) {
 | 
			
		||||
		log_sys_error("stat", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*size = info.st_size;
 | 
			
		||||
	*size >>= SECTOR_SHIFT;	/* Convert to sectors */
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _dev_get_size_dev(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;
 | 
			
		||||
@@ -38,22 +252,39 @@ 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------------
 | 
			
		||||
 * Public functions
 | 
			
		||||
 *---------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
int dev_get_size(const struct device *dev, uint64_t *size)
 | 
			
		||||
{
 | 
			
		||||
	if ((dev->flags & DEV_REGULAR))
 | 
			
		||||
		return _dev_get_size_file(dev, size);
 | 
			
		||||
	else
 | 
			
		||||
		return _dev_get_size_dev(dev, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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;
 | 
			
		||||
@@ -67,181 +298,317 @@ 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;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
static void _flush(int fd)
 | 
			
		||||
void dev_flush(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	if (ioctl(fd, BLKFLSBUF, 0) >= 0)
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (fsync(fd) >= 0)
 | 
			
		||||
	if (fsync(dev->fd) >= 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	sync();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_open(struct device *dev, int flags)
 | 
			
		||||
int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	const char *name = dev_name_confirmed(dev);
 | 
			
		||||
	const char *name;
 | 
			
		||||
	int need_excl = 0, need_rw = 0;
 | 
			
		||||
 | 
			
		||||
	if (!name) {
 | 
			
		||||
	if ((flags & O_ACCMODE) == O_RDWR)
 | 
			
		||||
		need_rw = 1;
 | 
			
		||||
 | 
			
		||||
	if ((flags & O_EXCL))
 | 
			
		||||
		need_excl = 1;
 | 
			
		||||
 | 
			
		||||
	if (dev->fd >= 0) {
 | 
			
		||||
		if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
 | 
			
		||||
		    ((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
 | 
			
		||||
			dev->open_count++;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (dev->open_count && !need_excl) {
 | 
			
		||||
			/* 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())
 | 
			
		||||
		log_error("WARNING: dev_open(%s) called while suspended",
 | 
			
		||||
			  dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	if (dev->flags & DEV_REGULAR)
 | 
			
		||||
		name = dev_name(dev);
 | 
			
		||||
	else if (!(name = dev_name_confirmed(dev, quiet))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev->fd >= 0) {
 | 
			
		||||
		log_error("Device '%s' has already been opened", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev)) {
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR) &&
 | 
			
		||||
	    ((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev))) {
 | 
			
		||||
		log_error("%s: stat failed: Has device name changed?", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((dev->fd = open(name, flags)) < 0) {
 | 
			
		||||
		log_sys_error("open", name);
 | 
			
		||||
#ifdef O_DIRECT_SUPPORT
 | 
			
		||||
	if (direct) {
 | 
			
		||||
		if (!(dev->flags & DEV_O_DIRECT_TESTED))
 | 
			
		||||
			dev->flags |= DEV_O_DIRECT;
 | 
			
		||||
 | 
			
		||||
		if ((dev->flags & DEV_O_DIRECT))
 | 
			
		||||
			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) {
 | 
			
		||||
#ifdef O_DIRECT_SUPPORT
 | 
			
		||||
		if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) {
 | 
			
		||||
			flags &= ~O_DIRECT;
 | 
			
		||||
			if ((dev->fd = open(name, flags, 0777)) >= 0) {
 | 
			
		||||
				dev->flags &= ~DEV_O_DIRECT;
 | 
			
		||||
				log_debug("%s: Not using O_DIRECT", name);
 | 
			
		||||
				goto opened;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
		if (quiet)
 | 
			
		||||
			log_sys_debug("open", name);
 | 
			
		||||
		else
 | 
			
		||||
			log_sys_error("open", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev)) {
 | 
			
		||||
#ifdef O_DIRECT_SUPPORT
 | 
			
		||||
      opened:
 | 
			
		||||
	if (direct)
 | 
			
		||||
		dev->flags |= DEV_O_DIRECT_TESTED;
 | 
			
		||||
#endif
 | 
			
		||||
	dev->open_count++;
 | 
			
		||||
	dev->flags &= ~DEV_ACCESSED_W;
 | 
			
		||||
 | 
			
		||||
	if (need_rw)
 | 
			
		||||
		dev->flags |= DEV_OPENED_RW;
 | 
			
		||||
	else
 | 
			
		||||
		dev->flags &= ~DEV_OPENED_RW;
 | 
			
		||||
 | 
			
		||||
	if (need_excl)
 | 
			
		||||
		dev->flags |= DEV_OPENED_EXCL;
 | 
			
		||||
	else
 | 
			
		||||
		dev->flags &= ~DEV_OPENED_EXCL;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	_flush(dev->fd);
 | 
			
		||||
	dev->flags = 0;
 | 
			
		||||
 | 
			
		||||
#ifndef O_DIRECT_SUPPORT
 | 
			
		||||
	if (!(dev->flags & DEV_REGULAR))
 | 
			
		||||
		dev_flush(dev);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	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 %s%s%s", dev_name(dev),
 | 
			
		||||
		  dev->flags & DEV_OPENED_RW ? "RW" : "RO",
 | 
			
		||||
		  dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
 | 
			
		||||
		  dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_close(struct device *dev)
 | 
			
		||||
int dev_open_quiet(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int flags;
 | 
			
		||||
 | 
			
		||||
	flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
 | 
			
		||||
 | 
			
		||||
	return dev_open_flags(dev, flags, 1, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_open(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int flags;
 | 
			
		||||
 | 
			
		||||
	flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
 | 
			
		||||
 | 
			
		||||
	return dev_open_flags(dev, flags, 1, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_test_excl(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int flags;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
 | 
			
		||||
	flags |= O_EXCL;
 | 
			
		||||
 | 
			
		||||
	r = dev_open_flags(dev, flags, 1, 1);
 | 
			
		||||
	if (r)
 | 
			
		||||
		dev_close_immediate(dev);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
 | 
			
		||||
	if (dev->flags & DEV_ALLOCED) {
 | 
			
		||||
		dm_free((void *) list_item(dev->aliases.n, struct str_list)->
 | 
			
		||||
			 str);
 | 
			
		||||
		dm_free(dev->aliases.n);
 | 
			
		||||
		dm_free(dev);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _dev_close(struct device *dev, int immediate)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (dev->fd < 0) {
 | 
			
		||||
		log_error("Attempt to close device '%s' "
 | 
			
		||||
			  "which is not open.", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifndef O_DIRECT_SUPPORT
 | 
			
		||||
	if (dev->flags & DEV_ACCESSED_W)
 | 
			
		||||
		_flush(dev->fd);
 | 
			
		||||
		dev_flush(dev);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (close(dev->fd))
 | 
			
		||||
		log_sys_error("close", dev_name(dev));
 | 
			
		||||
	if (dev->open_count > 0)
 | 
			
		||||
		dev->open_count--;
 | 
			
		||||
 | 
			
		||||
	dev->fd = -1;
 | 
			
		||||
	if (immediate && dev->open_count)
 | 
			
		||||
		log_debug("%s: Immediate close attempt while still referenced",
 | 
			
		||||
			  dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	/* Close unless device is known to belong to a locked VG */
 | 
			
		||||
	if (immediate ||
 | 
			
		||||
	    (dev->open_count < 1 && 
 | 
			
		||||
	     (!(info = info_from_pvid(dev->pvid)) ||
 | 
			
		||||
	      !info->vginfo ||
 | 
			
		||||
	      !vgname_is_locked(info->vginfo->vgname))))
 | 
			
		||||
		_close(dev);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t raw_read(int fd, void *buf, size_t count)
 | 
			
		||||
int dev_close(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	ssize_t n = 0, tot = 0;
 | 
			
		||||
 | 
			
		||||
	if (count > SSIZE_MAX)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	while (tot < (signed) count) {
 | 
			
		||||
		do
 | 
			
		||||
			n = read(fd, buf, count - tot);
 | 
			
		||||
		while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 | 
			
		||||
 | 
			
		||||
		if (n <= 0)
 | 
			
		||||
			return tot ? tot : n;
 | 
			
		||||
 | 
			
		||||
		tot += n;
 | 
			
		||||
		buf += n;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tot;
 | 
			
		||||
	return _dev_close(dev, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
int dev_close_immediate(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	int fd = dev->fd;
 | 
			
		||||
	/* loff_t pos; */
 | 
			
		||||
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		log_err("Attempt to read an unopened device (%s).", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) { */
 | 
			
		||||
	if (lseek(fd, (off_t) offset, SEEK_SET) < 0) {
 | 
			
		||||
		log_sys_error("lseek", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return raw_read(fd, buffer, len);
 | 
			
		||||
	return _dev_close(dev, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _write(int fd, const void *buf, size_t count)
 | 
			
		||||
void dev_close_all(void)
 | 
			
		||||
{
 | 
			
		||||
	ssize_t n = 0;
 | 
			
		||||
	int tot = 0;
 | 
			
		||||
	struct list *doh, *doht;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
 | 
			
		||||
	/* Skip all writes */
 | 
			
		||||
	if (test_mode())
 | 
			
		||||
		return count;
 | 
			
		||||
 | 
			
		||||
	while (tot < count) {
 | 
			
		||||
		do
 | 
			
		||||
			n = write(fd, buf, count - tot);
 | 
			
		||||
		while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 | 
			
		||||
 | 
			
		||||
		if (n <= 0)
 | 
			
		||||
			return tot ? tot : n;
 | 
			
		||||
 | 
			
		||||
		tot += n;
 | 
			
		||||
		buf += n;
 | 
			
		||||
	list_iterate_safe(doh, doht, &_open_devices) {
 | 
			
		||||
		dev = list_struct_base(doh, struct device, open_list);
 | 
			
		||||
		if (dev->open_count < 1)
 | 
			
		||||
			_close(dev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tot;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t dev_write(struct device * dev, uint64_t offset, size_t len,
 | 
			
		||||
		  void *buffer)
 | 
			
		||||
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	int fd = dev->fd;
 | 
			
		||||
	struct device_area where;
 | 
			
		||||
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		log_error("Attempt to write to unopened device %s", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lseek(fd, (off_t) offset, SEEK_SET) < 0) {
 | 
			
		||||
		log_sys_error("lseek", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev->flags |= DEV_ACCESSED_W;
 | 
			
		||||
 | 
			
		||||
	return _write(fd, buffer, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	int64_t r;
 | 
			
		||||
	size_t s;
 | 
			
		||||
	char buffer[4096];
 | 
			
		||||
	int already_open;
 | 
			
		||||
 | 
			
		||||
	already_open = dev_is_open(dev);
 | 
			
		||||
 | 
			
		||||
	if (!already_open && !dev_open(dev, O_RDWR)) {
 | 
			
		||||
	if (!dev->open_count) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lseek(dev->fd, (off_t) offset, SEEK_SET) < 0) {
 | 
			
		||||
		log_sys_error("lseek", dev_name(dev));
 | 
			
		||||
		if (!already_open && !dev_close(dev))
 | 
			
		||||
			stack;
 | 
			
		||||
	where.dev = dev;
 | 
			
		||||
	where.start = offset;
 | 
			
		||||
	where.size = len;
 | 
			
		||||
 | 
			
		||||
	return _aligned_io(&where, buffer, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
 | 
			
		||||
 *       But fails if concurrent processes writing
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* FIXME pre-extend the file */
 | 
			
		||||
int dev_append(struct device *dev, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!dev->open_count) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = dev_write(dev, dev->end, len, buffer);
 | 
			
		||||
	dev->end += (uint64_t) len;
 | 
			
		||||
 | 
			
		||||
#ifndef O_DIRECT_SUPPORT
 | 
			
		||||
	dev_flush(dev);
 | 
			
		||||
#endif
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	struct device_area where;
 | 
			
		||||
 | 
			
		||||
	if (!dev->open_count) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	where.dev = dev;
 | 
			
		||||
	where.start = offset;
 | 
			
		||||
	where.size = len;
 | 
			
		||||
 | 
			
		||||
	dev->flags |= DEV_ACCESSED_W;
 | 
			
		||||
 | 
			
		||||
	return _aligned_io(&where, buffer, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
 | 
			
		||||
{
 | 
			
		||||
	size_t s;
 | 
			
		||||
	char buffer[4096];
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -253,26 +620,23 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
			  " sectors", dev_name(dev), offset >> SECTOR_SHIFT,
 | 
			
		||||
			  len >> SECTOR_SHIFT);
 | 
			
		||||
 | 
			
		||||
	memset(buffer, 0, sizeof(buffer));
 | 
			
		||||
	memset(buffer, value, sizeof(buffer));
 | 
			
		||||
	while (1) {
 | 
			
		||||
		s = len > sizeof(buffer) ? sizeof(buffer) : len;
 | 
			
		||||
		r = _write(dev->fd, buffer, s);
 | 
			
		||||
 | 
			
		||||
		if (r <= 0)
 | 
			
		||||
		if (!dev_write(dev, offset, s, buffer))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		len -= r;
 | 
			
		||||
		if (!len) {
 | 
			
		||||
			r = 1;
 | 
			
		||||
		len -= s;
 | 
			
		||||
		if (!len)
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		offset += s;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev->flags |= DEV_ACCESSED_W;
 | 
			
		||||
 | 
			
		||||
	if (!already_open && !dev_close(dev))
 | 
			
		||||
	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, UINT64_C(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)
 | 
			
		||||
@@ -130,7 +202,7 @@ int _get_partition_type(struct dev_mgr *dm, struct device *d)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(buffer = dbg_malloc(SECTOR_SIZE))) {
 | 
			
		||||
	if (!(buffer = dm_malloc(SECTOR_SIZE))) {
 | 
			
		||||
		log_error("Failed to allocate partition table buffer");
 | 
			
		||||
		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_DEVICE_H
 | 
			
		||||
@@ -9,7 +18,15 @@
 | 
			
		||||
 | 
			
		||||
#include "uuid.h"
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
#define DEV_ACCESSED_W		0x00000001	/* Device written to? */
 | 
			
		||||
#define DEV_REGULAR		0x00000002	/* Regular file? */
 | 
			
		||||
#define DEV_ALLOCED		0x00000004	/* dm_malloc used */
 | 
			
		||||
#define DEV_OPENED_RW		0x00000008	/* Opened RW */
 | 
			
		||||
#define DEV_OPENED_EXCL		0x00000010	/* Opened EXCL */
 | 
			
		||||
#define DEV_O_DIRECT		0x00000020	/* Use O_DIRECT */
 | 
			
		||||
#define DEV_O_DIRECT_TESTED	0x00000040	/* DEV_O_DIRECT is reliable */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * All devices in LVM will be represented by one of these.
 | 
			
		||||
@@ -21,9 +38,14 @@ struct device {
 | 
			
		||||
 | 
			
		||||
	/* private */
 | 
			
		||||
	int fd;
 | 
			
		||||
	int open_count;
 | 
			
		||||
	int block_size;
 | 
			
		||||
	uint32_t flags;
 | 
			
		||||
	uint64_t end;
 | 
			
		||||
	struct list open_list;
 | 
			
		||||
 | 
			
		||||
	char pvid[ID_LEN + 1];
 | 
			
		||||
	char _padding[7];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct device_list {
 | 
			
		||||
@@ -40,47 +62,41 @@ 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);
 | 
			
		||||
 | 
			
		||||
int dev_open(struct device *dev, int flags);
 | 
			
		||||
/* Use quiet version if device number could change e.g. when opening LV */
 | 
			
		||||
int dev_open(struct device *dev);
 | 
			
		||||
int dev_open_quiet(struct device *dev);
 | 
			
		||||
int dev_open_flags(struct device *dev, int flags, int direct, int quiet);
 | 
			
		||||
int dev_close(struct device *dev);
 | 
			
		||||
int dev_close_immediate(struct device *dev);
 | 
			
		||||
void dev_close_all(void);
 | 
			
		||||
int dev_test_excl(struct device *dev);
 | 
			
		||||
 | 
			
		||||
static inline int dev_fd(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd;
 | 
			
		||||
}
 | 
			
		||||
int dev_fd(struct device *dev);
 | 
			
		||||
const char *dev_name(const struct device *dev);
 | 
			
		||||
 | 
			
		||||
ssize_t raw_read(int fd, void *buf, size_t count);
 | 
			
		||||
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int dev_append(struct device *dev, size_t len, void *buffer);
 | 
			
		||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);
 | 
			
		||||
void dev_flush(struct device *dev);
 | 
			
		||||
 | 
			
		||||
ssize_t dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int64_t dev_write(struct device *dev, uint64_t offset, size_t len,
 | 
			
		||||
		  void *buffer);
 | 
			
		||||
int dev_zero(struct device *dev, uint64_t offset, size_t len);
 | 
			
		||||
 | 
			
		||||
static inline const char *dev_name(const struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
 | 
			
		||||
	    "unknown device";
 | 
			
		||||
}
 | 
			
		||||
struct device *dev_create_file(const char *filename, struct device *dev,
 | 
			
		||||
			       struct str_list *alias, int use_malloc);
 | 
			
		||||
 | 
			
		||||
/* Return a valid device name from the alias list; NULL otherwise */
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev);
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev, int quiet);
 | 
			
		||||
 | 
			
		||||
static inline int dev_is_open(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd >= 0 ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
/* 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,31 +18,24 @@
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
#define SIZE_BUF 128
 | 
			
		||||
 | 
			
		||||
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
	alloc_policy_t alloc;
 | 
			
		||||
	const char *str;
 | 
			
		||||
} _policies[] = {
 | 
			
		||||
	{
 | 
			
		||||
	ALLOC_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)
 | 
			
		||||
{
 | 
			
		||||
@@ -75,6 +63,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
 | 
			
		||||
		break;
 | 
			
		||||
	case 's':
 | 
			
		||||
		v *= SECTOR_SIZE;
 | 
			
		||||
		break;
 | 
			
		||||
	case 'b':
 | 
			
		||||
	case 'B':
 | 
			
		||||
		v *= UINT64_C(1);
 | 
			
		||||
@@ -82,6 +71,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
 | 
			
		||||
#define KILO UINT64_C(1024)
 | 
			
		||||
	case 'k':
 | 
			
		||||
		v *= KILO;
 | 
			
		||||
		break;
 | 
			
		||||
	case 'm':
 | 
			
		||||
		v *= KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
@@ -127,17 +117,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;
 | 
			
		||||
@@ -146,26 +125,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;
 | 
			
		||||
	/* Special case for old metadata */
 | 
			
		||||
	if(!strcmp("next free", str))
 | 
			
		||||
		return ALLOC_NORMAL;
 | 
			
		||||
 | 
			
		||||
	log_error("Unrecognised allocation policy %s", str);
 | 
			
		||||
	return ALLOC_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
/* Size supplied in sectors */
 | 
			
		||||
static 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;
 | 
			
		||||
@@ -181,7 +153,7 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
		{"         ", "   ", " "},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (!(size_buf = pool_alloc(cmd->mem, SIZE_BUF))) {
 | 
			
		||||
	if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
 | 
			
		||||
		log_error("no memory for size display buffer");
 | 
			
		||||
		return "";
 | 
			
		||||
	}
 | 
			
		||||
@@ -200,8 +172,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);
 | 
			
		||||
@@ -213,12 +186,37 @@ 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size_long(struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _display_size(cmd, size, SIZE_LONG);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size_units(struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _display_size(cmd, size, SIZE_UNIT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _display_size(cmd, size, SIZE_SHORT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pvdisplay_colons(struct physical_volume *pv)
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
@@ -247,7 +245,7 @@ void pvdisplay_colons(struct physical_volume *pv)
 | 
			
		||||
 | 
			
		||||
/* FIXME Include label fields */
 | 
			
		||||
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
		    void *handle)
 | 
			
		||||
		    void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	const char *size;
 | 
			
		||||
@@ -267,18 +265,17 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
	log_print("VG Name               %s%s", pv->vg_name,
 | 
			
		||||
		  pv->status & EXPORTED_VG ? " (exported)" : "");
 | 
			
		||||
 | 
			
		||||
	size = display_size(cmd, (uint64_t) pv->size / 2, SIZE_SHORT);
 | 
			
		||||
	size = display_size(cmd, (uint64_t) pv->size);
 | 
			
		||||
	if (pv->pe_size && pv->pe_count) {
 | 
			
		||||
 | 
			
		||||
/******** FIXME display LVM on-disk data size
 | 
			
		||||
		size2 = display_size(pv->size / 2, SIZE_SHORT);
 | 
			
		||||
		size2 = display_size(cmd, pv->size);
 | 
			
		||||
********/
 | 
			
		||||
 | 
			
		||||
		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 -
 | 
			
		||||
				       (uint64_t) pv->pe_count * pv->pe_size)));
 | 
			
		||||
 | 
			
		||||
	} else
 | 
			
		||||
		log_print("PV Size               %s", size);
 | 
			
		||||
@@ -307,8 +304,10 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
		    struct physical_volume *pv, void *handle)
 | 
			
		||||
int pvdisplay_short(struct cmd_context *cmd __attribute((unused)),
 | 
			
		||||
		    struct volume_group *vg __attribute((unused)),
 | 
			
		||||
		    struct physical_volume *pv,
 | 
			
		||||
		    void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
 | 
			
		||||
@@ -336,7 +335,7 @@ void lvdisplay_colons(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	int inkernel;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	inkernel = lv_info(lv, &info) && info.exists;
 | 
			
		||||
	inkernel = lv_info(lv->vg->cmd, lv, &info, 1) && info.exists;
 | 
			
		||||
 | 
			
		||||
	log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
 | 
			
		||||
		  lv->vg->cmd->dev_dir,
 | 
			
		||||
@@ -353,13 +352,12 @@ void lvdisplay_colons(struct logical_volume *lv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		   void *handle)
 | 
			
		||||
		   void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int inkernel, snap_active;
 | 
			
		||||
	int inkernel, snap_active = 0;
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	struct snapshot *snap = NULL;
 | 
			
		||||
	struct list *slh, *snaplist;
 | 
			
		||||
	struct lv_segment *snap_seg = NULL;
 | 
			
		||||
	float snap_percent;	/* fused, fsize; */
 | 
			
		||||
 | 
			
		||||
	if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
 | 
			
		||||
@@ -367,7 +365,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inkernel = lv_info(lv, &info) && info.exists;
 | 
			
		||||
	inkernel = lv_info(cmd, lv, &info, 1) && info.exists;
 | 
			
		||||
 | 
			
		||||
	log_print("--- Logical volume ---");
 | 
			
		||||
 | 
			
		||||
@@ -383,23 +381,30 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
	if (lv_is_origin(lv)) {
 | 
			
		||||
		log_print("LV snapshot status     source of");
 | 
			
		||||
 | 
			
		||||
		snaplist = find_snapshots(lv);
 | 
			
		||||
		list_iterate(slh, snaplist) {
 | 
			
		||||
			snap = list_item(slh, struct snapshot_list)->snapshot;
 | 
			
		||||
			snap_active = lv_snapshot_percent(snap->cow,
 | 
			
		||||
							  &snap_percent);
 | 
			
		||||
		list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
 | 
			
		||||
				       origin_list) {
 | 
			
		||||
			if (inkernel &&
 | 
			
		||||
			    (snap_active = lv_snapshot_percent(snap_seg->cow,
 | 
			
		||||
							       &snap_percent)))
 | 
			
		||||
				if (snap_percent < 0 || snap_percent >= 100)
 | 
			
		||||
					snap_active = 0;
 | 
			
		||||
			log_print("                       %s%s/%s [%s]",
 | 
			
		||||
				  lv->vg->cmd->dev_dir, lv->vg->name,
 | 
			
		||||
				  snap->cow->name,
 | 
			
		||||
				  snap_seg->cow->name,
 | 
			
		||||
				  (snap_active > 0) ? "active" : "INACTIVE");
 | 
			
		||||
		}
 | 
			
		||||
		snap = NULL;
 | 
			
		||||
	} else if ((snap = find_cow(lv))) {
 | 
			
		||||
		snap_active = lv_snapshot_percent(lv, &snap_percent);
 | 
			
		||||
		snap_seg = NULL;
 | 
			
		||||
	} else if ((snap_seg = find_cow(lv))) {
 | 
			
		||||
		if (inkernel &&
 | 
			
		||||
		    (snap_active = lv_snapshot_percent(snap_seg->cow,
 | 
			
		||||
						       &snap_percent)))
 | 
			
		||||
			if (snap_percent < 0 || snap_percent >= 100)
 | 
			
		||||
				snap_active = 0;
 | 
			
		||||
 | 
			
		||||
		log_print("LV snapshot status     %s destination for %s%s/%s",
 | 
			
		||||
			  (snap_active > 0) ? "active" : "INACTIVE",
 | 
			
		||||
			  lv->vg->cmd->dev_dir, lv->vg->name,
 | 
			
		||||
			  snap->origin->name);
 | 
			
		||||
			  snap_seg->origin->name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (inkernel && info.suspended)
 | 
			
		||||
@@ -417,15 +422,22 @@ 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,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       snap_seg ? snap_seg->origin->size : lv->size));
 | 
			
		||||
 | 
			
		||||
	log_print("Current LE             %u",
 | 
			
		||||
		  snap ? snap->origin->le_count : lv->le_count);
 | 
			
		||||
		  snap_seg ? snap_seg->origin->le_count : lv->le_count);
 | 
			
		||||
 | 
			
		||||
/********** FIXME allocation
 | 
			
		||||
    log_print("Allocated LE           %u", lv->allocated_le);
 | 
			
		||||
**********/
 | 
			
		||||
	if (snap_seg) {
 | 
			
		||||
		log_print("COW-table size         %s",
 | 
			
		||||
			  display_size(cmd, (uint64_t) lv->size));
 | 
			
		||||
		log_print("COW-table LE           %u", lv->le_count);
 | 
			
		||||
 | 
			
		||||
		if (snap_active)
 | 
			
		||||
			log_print("Allocated to snapshot  %.2f%% ", snap_percent);	
 | 
			
		||||
 | 
			
		||||
		log_print("Snapshot chunk size    %s",
 | 
			
		||||
			  display_size(cmd, (uint64_t) snap_seg->chunk_size));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print("Segments               %u", list_size(&lv->segments));
 | 
			
		||||
 | 
			
		||||
@@ -433,31 +445,6 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
	log_print("Stripe size (KByte)    %u", lv->stripesize / 2);
 | 
			
		||||
***********/
 | 
			
		||||
 | 
			
		||||
	if (snap) {
 | 
			
		||||
		if (snap_percent == -1)
 | 
			
		||||
			snap_percent = 100;
 | 
			
		||||
 | 
			
		||||
		log_print("Snapshot chunk size    %s",
 | 
			
		||||
			  display_size(cmd, (uint64_t) snap->chunk_size / 2,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	size = display_size(lv->size / 2, SIZE_SHORT);
 | 
			
		||||
	sscanf(size, "%f", &fsize);
 | 
			
		||||
	fused = fsize * snap_percent / 100;
 | 
			
		||||
*/
 | 
			
		||||
		log_print("Allocated to snapshot  %.2f%% ",	/* [%.2f/%s]", */
 | 
			
		||||
			  snap_percent);	/*, fused, size); */
 | 
			
		||||
		/* dbg_free(size); */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/********** FIXME Snapshot
 | 
			
		||||
	size = ???
 | 
			
		||||
	log_print("Allocated to COW-table %s", size);
 | 
			
		||||
	dbg_free(size);
 | 
			
		||||
    }
 | 
			
		||||
******************/
 | 
			
		||||
 | 
			
		||||
	log_print("Allocation             %s", get_alloc_string(lv->alloc));
 | 
			
		||||
	log_print("Read ahead sectors     %u", lv->read_ahead);
 | 
			
		||||
 | 
			
		||||
@@ -476,87 +463,57 @@ 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) {
 | 
			
		||||
	switch (seg_type(seg, s)) {
 | 
			
		||||
	case AREA_PV:
 | 
			
		||||
		/* FIXME Re-check the conditions for 'Missing' */
 | 
			
		||||
		log_print("%sPhysical volume\t%s", pre,
 | 
			
		||||
			  seg->area[s].u.pv.pv ?
 | 
			
		||||
			  dev_name(seg->area[s].u.pv.pv->dev) : "Missing");
 | 
			
		||||
			  seg_pv(seg, s) ?
 | 
			
		||||
			  dev_name(seg_dev(seg, s)) :
 | 
			
		||||
			    "Missing");
 | 
			
		||||
 | 
			
		||||
		if (seg->area[s].u.pv.pv)
 | 
			
		||||
		if (seg_pv(seg, s))
 | 
			
		||||
			log_print("%sPhysical extents\t%d to %d", pre,
 | 
			
		||||
				  seg->area[s].u.pv.pe,
 | 
			
		||||
				  seg->area[s].u.pv.pe + seg->area_len - 1);
 | 
			
		||||
				  seg_pe(seg, s),
 | 
			
		||||
				  seg_pe(seg, s) + seg->area_len - 1);
 | 
			
		||||
		break;
 | 
			
		||||
	case AREA_LV:
 | 
			
		||||
		log_print("%sLogical volume\t%s", pre,
 | 
			
		||||
			  seg->area[s].u.lv.lv ?
 | 
			
		||||
			  seg->area[s].u.lv.lv->name : "Missing");
 | 
			
		||||
			  seg_lv(seg, s) ?
 | 
			
		||||
			  seg_lv(seg, s)->name : "Missing");
 | 
			
		||||
 | 
			
		||||
		if (seg->area[s].u.lv.lv)
 | 
			
		||||
		if (seg_lv(seg, s))
 | 
			
		||||
			log_print("%sLogical extents\t%d to %d", pre,
 | 
			
		||||
				  seg->area[s].u.lv.le,
 | 
			
		||||
				  seg->area[s].u.lv.le + seg->area_len - 1);
 | 
			
		||||
 | 
			
		||||
				  seg_le(seg, s),
 | 
			
		||||
				  seg_le(seg, s) + seg->area_len - 1);
 | 
			
		||||
		break;
 | 
			
		||||
	case AREA_UNASSIGNED:
 | 
			
		||||
		log_print("%sUnassigned area", 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(" ");
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vgdisplay_extents(struct volume_group *vg)
 | 
			
		||||
void vgdisplay_extents(struct volume_group *vg __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
@@ -599,11 +556,11 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
			  vg->status & SHARED ? "yes" : "no");
 | 
			
		||||
	}
 | 
			
		||||
	log_print("MAX LV                %u", vg->max_lv);
 | 
			
		||||
	log_print("Cur LV                %u", vg->lv_count);
 | 
			
		||||
	log_print("Cur LV                %u", vg->lv_count + vg->snapshot_count);
 | 
			
		||||
	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))));
 | 
			
		||||
      free ( s1);
 | 
			
		||||
*********/
 | 
			
		||||
	log_print("Max PV                %u", vg->max_pv);
 | 
			
		||||
@@ -612,32 +569,22 @@ 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));
 | 
			
		||||
 | 
			
		||||
	log_print("PE Size               %s",
 | 
			
		||||
		  display_size(vg->cmd, (uint64_t) vg->extent_size / 2,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
		  display_size(vg->cmd, (uint64_t) vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
 | 
			
		||||
	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -652,6 +599,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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -659,15 +653,31 @@ 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),
 | 
			
		||||
		  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),
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size));
 | 
			
		||||
	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
 | 
			
		||||
@@ -25,13 +20,15 @@
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
 | 
			
		||||
 | 
			
		||||
uint64_t units_to_bytes(const char *units, char *unit_type);
 | 
			
		||||
 | 
			
		||||
/* Specify size in KB */
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl);
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size);
 | 
			
		||||
const char *display_size_long(struct cmd_context *cmd, uint64_t size);
 | 
			
		||||
const char *display_size_units(struct cmd_context *cmd, uint64_t size);
 | 
			
		||||
 | 
			
		||||
char *display_uuid(char *uuidstr);
 | 
			
		||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
 | 
			
		||||
 | 
			
		||||
void pvdisplay_colons(struct physical_volume *pv);
 | 
			
		||||
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
@@ -49,16 +46,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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										98
									
								
								lib/error/errseg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								lib/error/errseg.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "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 *_errseg_name(const struct lv_segment *seg)
 | 
			
		||||
{
 | 
			
		||||
	return seg->segtype->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _errseg_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 _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
 | 
			
		||||
				struct dm_pool *mem __attribute((unused)),
 | 
			
		||||
				struct cmd_context *cmd __attribute((unused)),
 | 
			
		||||
				void **target_state __attribute((unused)),
 | 
			
		||||
				struct lv_segment *seg __attribute((unused)),
 | 
			
		||||
				struct dm_tree_node *node, uint64_t len,
 | 
			
		||||
				uint32_t *pvmove_mirror_count __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return dm_tree_node_add_error_target(node, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _errseg_target_present(void)
 | 
			
		||||
{
 | 
			
		||||
	static int _errseg_checked = 0;
 | 
			
		||||
	static int _errseg_present = 0;
 | 
			
		||||
 | 
			
		||||
	/* Reported truncated in older kernels */
 | 
			
		||||
	if (!_errseg_checked &&
 | 
			
		||||
	    (target_present("error", 0) || target_present("erro", 0)))
 | 
			
		||||
		_errseg_present = 1;
 | 
			
		||||
 | 
			
		||||
	_errseg_checked = 1;
 | 
			
		||||
	return _errseg_present;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void _errseg_destroy(const struct segment_type *segtype)
 | 
			
		||||
{
 | 
			
		||||
	dm_free((void *)segtype);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct segtype_handler _error_ops = {
 | 
			
		||||
	.name = _errseg_name,
 | 
			
		||||
	.merge_segments = _errseg_merge_segments,
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
	.add_target_line = _errseg_add_target_line,
 | 
			
		||||
	.target_present = _errseg_target_present,
 | 
			
		||||
#endif
 | 
			
		||||
	.destroy = _errseg_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct segment_type *init_error_segtype(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
 | 
			
		||||
 | 
			
		||||
	if (!segtype)
 | 
			
		||||
		return_NULL;
 | 
			
		||||
 | 
			
		||||
	segtype->cmd = cmd;
 | 
			
		||||
	segtype->ops = &_error_ops;
 | 
			
		||||
	segtype->name = "error";
 | 
			
		||||
	segtype->private = NULL;
 | 
			
		||||
	segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
 | 
			
		||||
 | 
			
		||||
	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"
 | 
			
		||||
@@ -24,7 +33,7 @@ static int _and_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _composite_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_filter **filters = (struct dev_filter **) f->private;
 | 
			
		||||
 | 
			
		||||
@@ -33,39 +42,36 @@ static void _destroy(struct dev_filter *f)
 | 
			
		||||
		filters++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dbg_free(f->private);
 | 
			
		||||
	dbg_free(f);
 | 
			
		||||
	dm_free(f->private);
 | 
			
		||||
	dm_free(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dev_filter *composite_filter_create(int n, ...)
 | 
			
		||||
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_filter **filters = dbg_malloc(sizeof(*filters) * (n + 1));
 | 
			
		||||
	struct dev_filter *cf;
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	int i;
 | 
			
		||||
	struct dev_filter **filters_copy, *cft;
 | 
			
		||||
 | 
			
		||||
	if (!filters) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cf = dbg_malloc(sizeof(*cf)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		dbg_free(filters);
 | 
			
		||||
	if (!(filters_copy = dm_malloc(sizeof(*filters) * (n + 1)))) {
 | 
			
		||||
		log_error("composite filters allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	va_start(ap, n);
 | 
			
		||||
	for (i = 0; i < n; i++) {
 | 
			
		||||
		struct dev_filter *f = va_arg(ap, struct dev_filter *);
 | 
			
		||||
		filters[i] = f;
 | 
			
		||||
	memcpy(filters_copy, filters, sizeof(*filters) * n);
 | 
			
		||||
	filters_copy[n] = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(cft = dm_malloc(sizeof(*cft)))) {
 | 
			
		||||
		log_error("compsoite filters allocation failed");
 | 
			
		||||
		dm_free(filters_copy);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	filters[i] = NULL;
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	cf->passes_filter = _and_p;
 | 
			
		||||
	cf->destroy = _destroy;
 | 
			
		||||
	cf->private = filters;
 | 
			
		||||
	cft->passes_filter = _and_p;
 | 
			
		||||
	cft->destroy = _composite_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
 | 
			
		||||
@@ -9,6 +18,6 @@
 | 
			
		||||
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
 | 
			
		||||
struct dev_filter *composite_filter_create(int n, ...);
 | 
			
		||||
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
{
 | 
			
		||||
	dm_free(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dev_filter *md_filter_create(void)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_filter *f;
 | 
			
		||||
 | 
			
		||||
	if (!(f = dm_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,13 +1,21 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "hash.h"
 | 
			
		||||
#include "filter-persistent.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
@@ -16,7 +24,7 @@
 | 
			
		||||
 | 
			
		||||
struct pfilter {
 | 
			
		||||
	char *file;
 | 
			
		||||
	struct hash_table *devices;
 | 
			
		||||
	struct dm_hash_table *devices;
 | 
			
		||||
	struct dev_filter *real;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -30,9 +38,9 @@ struct pfilter {
 | 
			
		||||
static int _init_hash(struct pfilter *pf)
 | 
			
		||||
{
 | 
			
		||||
	if (pf->devices)
 | 
			
		||||
		hash_destroy(pf->devices);
 | 
			
		||||
		dm_hash_destroy(pf->devices);
 | 
			
		||||
 | 
			
		||||
	if (!(pf->devices = hash_create(128))) {
 | 
			
		||||
	if (!(pf->devices = dm_hash_create(128))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -44,20 +52,22 @@ int persistent_filter_wipe(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct pfilter *pf = (struct pfilter *) f->private;
 | 
			
		||||
 | 
			
		||||
	hash_wipe(pf->devices);
 | 
			
		||||
	log_verbose("Wiping cache of LVM-capable devices");
 | 
			
		||||
	dm_hash_wipe(pf->devices);
 | 
			
		||||
 | 
			
		||||
	/* Trigger complete device scan */
 | 
			
		||||
	dev_cache_scan(1);
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
@@ -74,7 +84,7 @@ static int _read_array(struct pfilter *pf, struct config_tree *cf,
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!hash_insert(pf->devices, cv->v.str, data))
 | 
			
		||||
		if (!dm_hash_insert(pf->devices, cv->v.str, data))
 | 
			
		||||
			log_verbose("Couldn't add '%s' to filter ... ignoring",
 | 
			
		||||
				    cv->v.str);
 | 
			
		||||
		/* Populate dev_cache ourselves */
 | 
			
		||||
@@ -88,26 +98,26 @@ 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? */
 | 
			
		||||
	if (hash_get_num_entries(pf->devices)) {
 | 
			
		||||
	if (dm_hash_get_num_entries(pf->devices)) {
 | 
			
		||||
		/* We populated dev_cache ourselves */
 | 
			
		||||
		dev_cache_scan(0);
 | 
			
		||||
		r = 1;
 | 
			
		||||
@@ -116,7 +126,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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -125,11 +135,11 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
 | 
			
		||||
{
 | 
			
		||||
	void *d;
 | 
			
		||||
	int first = 1;
 | 
			
		||||
	struct hash_node *n;
 | 
			
		||||
	struct dm_hash_node *n;
 | 
			
		||||
 | 
			
		||||
	for (n = hash_get_first(pf->devices); n;
 | 
			
		||||
	     n = hash_get_next(pf->devices, n)) {
 | 
			
		||||
		d = hash_get_data(pf->devices, n);
 | 
			
		||||
	for (n = dm_hash_get_first(pf->devices); n;
 | 
			
		||||
	     n = dm_hash_get_next(pf->devices, n)) {
 | 
			
		||||
		d = dm_hash_get_data(pf->devices, n);
 | 
			
		||||
 | 
			
		||||
		if (d != data)
 | 
			
		||||
			continue;
 | 
			
		||||
@@ -141,7 +151,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
 | 
			
		||||
			first = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fprintf(fp, "\t\t\"%s\"", hash_get_key(pf->devices, n));
 | 
			
		||||
		fprintf(fp, "\t\t\"%s\"", dm_hash_get_key(pf->devices, n));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!first)
 | 
			
		||||
@@ -156,7 +166,7 @@ int persistent_filter_dump(struct dev_filter *f)
 | 
			
		||||
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
 | 
			
		||||
	if (!hash_get_num_entries(pf->devices)) {
 | 
			
		||||
	if (!dm_hash_get_num_entries(pf->devices)) {
 | 
			
		||||
		log_very_verbose("Internal persistent device cache empty "
 | 
			
		||||
				 "- not writing to %s", pf->file);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -191,36 +201,31 @@ int persistent_filter_dump(struct dev_filter *f)
 | 
			
		||||
static int _lookup_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct pfilter *pf = (struct pfilter *) f->private;
 | 
			
		||||
	void *l = hash_lookup(pf->devices, dev_name(dev));
 | 
			
		||||
	void *l = dm_hash_lookup(pf->devices, dev_name(dev));
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
	struct list *ah;
 | 
			
		||||
 | 
			
		||||
	if (!l) {
 | 
			
		||||
		l = pf->real->passes_filter(pf->real, dev) ?
 | 
			
		||||
		    PF_GOOD_DEVICE : PF_BAD_DEVICE;
 | 
			
		||||
 | 
			
		||||
		list_iterate(ah, &dev->aliases) {
 | 
			
		||||
			sl = list_item(ah, struct str_list);
 | 
			
		||||
			hash_insert(pf->devices, sl->str, l);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
		list_iterate_items(sl, &dev->aliases)
 | 
			
		||||
			dm_hash_insert(pf->devices, sl->str, l);
 | 
			
		||||
 | 
			
		||||
	if (l == PF_BAD_DEVICE) {
 | 
			
		||||
		log_debug("%s: Skipping (cached)", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	} else
 | 
			
		||||
		return 1;
 | 
			
		||||
	} else if (l == PF_BAD_DEVICE)
 | 
			
		||||
			log_debug("%s: Skipping (cached)", dev_name(dev));
 | 
			
		||||
 | 
			
		||||
	return (l == PF_BAD_DEVICE) ? 0 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _persistent_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct pfilter *pf = (struct pfilter *) f->private;
 | 
			
		||||
 | 
			
		||||
	hash_destroy(pf->devices);
 | 
			
		||||
	dbg_free(pf->file);
 | 
			
		||||
	dm_hash_destroy(pf->devices);
 | 
			
		||||
	dm_free(pf->file);
 | 
			
		||||
	pf->real->destroy(pf->real);
 | 
			
		||||
	dbg_free(pf);
 | 
			
		||||
	dbg_free(f);
 | 
			
		||||
	dm_free(pf);
 | 
			
		||||
	dm_free(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dev_filter *persistent_filter_create(struct dev_filter *real,
 | 
			
		||||
@@ -229,13 +234,13 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
 | 
			
		||||
	struct pfilter *pf;
 | 
			
		||||
	struct dev_filter *f = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(pf = dbg_malloc(sizeof(*pf)))) {
 | 
			
		||||
	if (!(pf = dm_malloc(sizeof(*pf)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	memset(pf, 0, sizeof(*pf));
 | 
			
		||||
 | 
			
		||||
	if (!(pf->file = dbg_malloc(strlen(file) + 1))) {
 | 
			
		||||
	if (!(pf->file = dm_malloc(strlen(file) + 1))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
@@ -247,22 +252,22 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(f = dbg_malloc(sizeof(*f)))) {
 | 
			
		||||
	if (!(f = dm_malloc(sizeof(*f)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _lookup_p;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
	f->destroy = _persistent_destroy;
 | 
			
		||||
	f->private = pf;
 | 
			
		||||
 | 
			
		||||
	return f;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	dbg_free(pf->file);
 | 
			
		||||
	dm_free(pf->file);
 | 
			
		||||
	if (pf->devices)
 | 
			
		||||
		hash_destroy(pf->devices);
 | 
			
		||||
	dbg_free(pf);
 | 
			
		||||
	dbg_free(f);
 | 
			
		||||
		dm_hash_destroy(pf->devices);
 | 
			
		||||
	dm_free(pf);
 | 
			
		||||
	dm_free(f);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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,25 +1,31 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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"
 | 
			
		||||
#include "pool.h"
 | 
			
		||||
#include "filter-regex.h"
 | 
			
		||||
#include "matcher.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "bitset.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
 | 
			
		||||
struct rfilter {
 | 
			
		||||
	struct pool *mem;
 | 
			
		||||
	bitset_t accept;
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	dm_bitset_t accept;
 | 
			
		||||
	struct matcher *engine;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _extract_pattern(struct pool *mem, const char *pat,
 | 
			
		||||
			    char **regex, bitset_t accept, int ix)
 | 
			
		||||
static int _extract_pattern(struct dm_pool *mem, const char *pat,
 | 
			
		||||
			    char **regex, dm_bitset_t accept, int ix)
 | 
			
		||||
{
 | 
			
		||||
	char sep, *r, *ptr;
 | 
			
		||||
 | 
			
		||||
@@ -28,11 +34,11 @@ static int _extract_pattern(struct pool *mem, const char *pat,
 | 
			
		||||
	 */
 | 
			
		||||
	switch (*pat) {
 | 
			
		||||
	case 'a':
 | 
			
		||||
		bit_set(accept, ix);
 | 
			
		||||
		dm_bit_set(accept, ix);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case 'r':
 | 
			
		||||
		bit_clear(accept, ix);
 | 
			
		||||
		dm_bit_clear(accept, ix);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
@@ -42,7 +48,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
 | 
			
		||||
	pat++;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * get the seperator
 | 
			
		||||
	 * get the separator
 | 
			
		||||
	 */
 | 
			
		||||
	switch (*pat) {
 | 
			
		||||
	case '(':
 | 
			
		||||
@@ -65,7 +71,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
 | 
			
		||||
	/*
 | 
			
		||||
	 * copy the regex
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(r = pool_strdup(mem, pat))) {
 | 
			
		||||
	if (!(r = dm_pool_strdup(mem, pat))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -75,7 +81,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';
 | 
			
		||||
@@ -86,13 +92,13 @@ static int _extract_pattern(struct pool *mem, const char *pat,
 | 
			
		||||
 | 
			
		||||
static int _build_matcher(struct rfilter *rf, struct config_value *val)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *scratch;
 | 
			
		||||
	struct dm_pool *scratch;
 | 
			
		||||
	struct config_value *v;
 | 
			
		||||
	char **regex;
 | 
			
		||||
	unsigned count = 0;
 | 
			
		||||
	int i, r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(scratch = pool_create(1024))) {
 | 
			
		||||
	if (!(scratch = dm_pool_create("filter matcher", 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -113,7 +119,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
 | 
			
		||||
	/*
 | 
			
		||||
	 * allocate space for them
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(regex = pool_alloc(scratch, sizeof(*regex) * count))) {
 | 
			
		||||
	if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -121,7 +127,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
 | 
			
		||||
	/*
 | 
			
		||||
	 * create the accept/reject bitset
 | 
			
		||||
	 */
 | 
			
		||||
	rf->accept = bitset_create(rf->mem, count);
 | 
			
		||||
	rf->accept = dm_bitset_create(rf->mem, count);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * fill the array back to front because we
 | 
			
		||||
@@ -143,23 +149,21 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	pool_destroy(scratch);
 | 
			
		||||
	dm_pool_destroy(scratch);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _accept_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct list *ah;
 | 
			
		||||
	int m, first = 1, rejected = 0;
 | 
			
		||||
	struct rfilter *rf = (struct rfilter *) f->private;
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
	list_iterate(ah, &dev->aliases) {
 | 
			
		||||
		sl = list_item(ah, struct str_list);
 | 
			
		||||
	list_iterate_items(sl, &dev->aliases) {
 | 
			
		||||
		m = matcher_run(rf->engine, sl->str);
 | 
			
		||||
 | 
			
		||||
		if (m >= 0) {
 | 
			
		||||
			if (bit(rf->accept, m)) {
 | 
			
		||||
			if (dm_bit(rf->accept, m)) {
 | 
			
		||||
 | 
			
		||||
				if (!first) {
 | 
			
		||||
					log_debug("%s: New preferred name",
 | 
			
		||||
@@ -177,6 +181,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.
 | 
			
		||||
@@ -184,15 +191,15 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	return !rejected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _regex_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct rfilter *rf = (struct rfilter *) f->private;
 | 
			
		||||
	pool_destroy(rf->mem);
 | 
			
		||||
	dm_pool_destroy(rf->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dev_filter *regex_filter_create(struct config_value *patterns)
 | 
			
		||||
{
 | 
			
		||||
	struct pool *mem = pool_create(10 * 1024);
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024);
 | 
			
		||||
	struct rfilter *rf;
 | 
			
		||||
	struct dev_filter *f;
 | 
			
		||||
 | 
			
		||||
@@ -201,7 +208,7 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(rf = pool_alloc(mem, sizeof(*rf)))) {
 | 
			
		||||
	if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
@@ -213,17 +220,17 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(f = pool_zalloc(mem, sizeof(*f)))) {
 | 
			
		||||
	if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _accept_p;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
	f->destroy = _regex_destroy;
 | 
			
		||||
	f->private = rf;
 | 
			
		||||
	return f;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	pool_destroy(mem);
 | 
			
		||||
	dm_pool_destroy(mem);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										305
									
								
								lib/filters/filter-sysfs.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								lib/filters/filter-sysfs.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,305 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "filter-sysfs.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
 | 
			
		||||
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[4], buffer[PATH_MAX + 16];
 | 
			
		||||
 | 
			
		||||
	if (!*proc) {
 | 
			
		||||
		log_verbose("No proc filesystem found: skipping sysfs filter");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	if (lvm_snprintf(proc_mounts, sizeof(proc_mounts),
 | 
			
		||||
			 "%s/mounts", proc) < 0) {
 | 
			
		||||
		log_error("Failed to create /proc/mounts string");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(fp = fopen(proc_mounts, "r"))) {
 | 
			
		||||
		log_sys_error("fopen %s", proc_mounts);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (fgets(buffer, sizeof(buffer), fp)) {
 | 
			
		||||
		if (split_words(buffer, 4, split) == 4 &&
 | 
			
		||||
		    !strcmp(split[2], "sysfs")) {
 | 
			
		||||
			if (lvm_snprintf(path, len, "%s/%s", split[1],
 | 
			
		||||
					 "block") >= 0) {
 | 
			
		||||
				r = 1;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------
 | 
			
		||||
 * We need to store a set of dev_t.
 | 
			
		||||
 *--------------------------------------------------------------*/
 | 
			
		||||
struct entry {
 | 
			
		||||
	struct entry *next;
 | 
			
		||||
	dev_t dev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SET_BUCKETS 64
 | 
			
		||||
struct dev_set {
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	const char *sys_block;
 | 
			
		||||
	int initialised;
 | 
			
		||||
	struct entry *slots[SET_BUCKETS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_block)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_set *ds;
 | 
			
		||||
 | 
			
		||||
	if (!(ds = dm_pool_zalloc(mem, sizeof(*ds))))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	ds->mem = mem;
 | 
			
		||||
	ds->sys_block = dm_pool_strdup(mem, sys_block);
 | 
			
		||||
	ds->initialised = 0;
 | 
			
		||||
 | 
			
		||||
	return ds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned _hash_dev(dev_t dev)
 | 
			
		||||
{
 | 
			
		||||
	return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Doesn't check that the set already contains dev.
 | 
			
		||||
 */
 | 
			
		||||
static int _set_insert(struct dev_set *ds, dev_t dev)
 | 
			
		||||
{
 | 
			
		||||
	struct entry *e;
 | 
			
		||||
	unsigned h = _hash_dev(dev);
 | 
			
		||||
 | 
			
		||||
	if (!(e = dm_pool_alloc(ds->mem, sizeof(*e))))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	e->next = ds->slots[h];
 | 
			
		||||
	e->dev = dev;
 | 
			
		||||
	ds->slots[h] = e;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _set_lookup(struct dev_set *ds, dev_t dev)
 | 
			
		||||
{
 | 
			
		||||
	unsigned h = _hash_dev(dev);
 | 
			
		||||
	struct entry *e;
 | 
			
		||||
 | 
			
		||||
	for (e = ds->slots[h]; e; e = e->next)
 | 
			
		||||
		if (e->dev == dev)
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------
 | 
			
		||||
 * filter methods
 | 
			
		||||
 *--------------------------------------------------------------*/
 | 
			
		||||
static int _parse_dev(const char *file, FILE *fp, dev_t *result)
 | 
			
		||||
{
 | 
			
		||||
	unsigned major, minor;
 | 
			
		||||
	char buffer[64];
 | 
			
		||||
 | 
			
		||||
	if (!fgets(buffer, sizeof(buffer), fp)) {
 | 
			
		||||
		log_error("Empty sysfs device file: %s", file);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sscanf(buffer, "%u:%u", &major, &minor) != 2) {
 | 
			
		||||
		log_info("sysfs device file not correct format");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*result = makedev(major, minor);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_dev(const char *file, dev_t *result)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
 | 
			
		||||
	if (!(fp = fopen(file, "r"))) {
 | 
			
		||||
		log_sys_error("fopen", file);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = _parse_dev(file, fp, result);
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Recurse through sysfs directories, inserting any devs found.
 | 
			
		||||
 */
 | 
			
		||||
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 = { 0 };
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
        if (!(dr = opendir(dir))) {
 | 
			
		||||
                log_sys_error("opendir", dir);
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while ((d = readdir(dr))) {
 | 
			
		||||
                if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (lvm_snprintf(path, sizeof(path), "%s/%s", dir,
 | 
			
		||||
				 d->d_name) < 0) {
 | 
			
		||||
			log_error("sysfs path name too long: %s in %s",
 | 
			
		||||
				  d->d_name, dir);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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 ((dtype == DT_REG && !strcmp(d->d_name, "dev")))
 | 
			
		||||
			if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
 | 
			
		||||
				r = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if (closedir(dr))
 | 
			
		||||
                log_sys_error("closedir", dir);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_devs(struct dev_set *ds)
 | 
			
		||||
{
 | 
			
		||||
	if (!_read_devs(ds, ds->sys_block)) {
 | 
			
		||||
		ds->initialised = -1;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ds->initialised = 1;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int _accept_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_set *ds = (struct dev_set *) f->private;
 | 
			
		||||
 | 
			
		||||
	if (!ds->initialised)
 | 
			
		||||
		_init_devs(ds);
 | 
			
		||||
 | 
			
		||||
	/* Pass through if initialisation failed */
 | 
			
		||||
	if (ds->initialised != 1)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_set *ds = (struct dev_set *) f->private;
 | 
			
		||||
	dm_pool_destroy(ds->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
{
 | 
			
		||||
	char sys_block[PATH_MAX];
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	struct dev_set *ds;
 | 
			
		||||
	struct dev_filter *f;
 | 
			
		||||
 | 
			
		||||
	if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(mem = dm_pool_create("sysfs", 256))) {
 | 
			
		||||
		log_error("sysfs pool creation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(ds = _dev_set_create(mem, sys_block))) {
 | 
			
		||||
		log_error("sysfs dev_set creation failed");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _accept_p;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
	f->private = ds;
 | 
			
		||||
	return f;
 | 
			
		||||
 | 
			
		||||
 bad:
 | 
			
		||||
	dm_pool_destroy(mem);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
{
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										23
									
								
								lib/filters/filter-sysfs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/filters/filter-sysfs.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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_FILTER_SYSFS_H
 | 
			
		||||
#define _LVM_FILTER_SYSFS_H
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
 | 
			
		||||
struct dev_filter *sysfs_filter_create(const char *proc);
 | 
			
		||||
 | 
			
		||||
#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.
 | 
			
		||||
 *
 | 
			
		||||
 * 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,10 @@
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 | 
			
		||||
#define NUMBER_OF_MAJORS 256
 | 
			
		||||
#define NUMBER_OF_MAJORS 4096
 | 
			
		||||
 | 
			
		||||
/* 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 +43,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 */
 | 
			
		||||
@@ -57,35 +63,65 @@ static const device_info_t device_info[] = {
 | 
			
		||||
	{"cciss", 16},		/* Compaq CCISS array */
 | 
			
		||||
	{"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 */
 | 
			
		||||
	{"gnbd", 1},		/* Network block device */
 | 
			
		||||
	{"ramdisk", 1},		/* RAM disk */
 | 
			
		||||
	{"aoe", 16},		/* ATA over Ethernet */
 | 
			
		||||
	{"device-mapper", 1},	/* Other mapped devices */
 | 
			
		||||
	{"xvd", 16},		/* Xen virtual block device */
 | 
			
		||||
	{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, 1)) {
 | 
			
		||||
		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];
 | 
			
		||||
@@ -95,35 +131,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')
 | 
			
		||||
@@ -158,13 +190,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 */
 | 
			
		||||
@@ -172,7 +204,8 @@ 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;
 | 
			
		||||
				fclose(pd);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			dev_len = strlen(cv->v.str);
 | 
			
		||||
			name = cv->v.str;
 | 
			
		||||
@@ -181,41 +214,50 @@ 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;
 | 
			
		||||
				fclose(pd);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!cv->v.i) {
 | 
			
		||||
				log_error("Zero partition count invalid for "
 | 
			
		||||
					  "%s in devices/types in config file",
 | 
			
		||||
					  name);
 | 
			
		||||
				return NULL;
 | 
			
		||||
				fclose(pd);
 | 
			
		||||
				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;
 | 
			
		||||
 | 
			
		||||
	if (!(f = dbg_malloc(sizeof(struct dev_filter)))) {
 | 
			
		||||
	if (!(f = dm_malloc(sizeof(struct dev_filter)))) {
 | 
			
		||||
		log_error("LVM type filter allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
		dm_free(f);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -224,7 +266,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);
 | 
			
		||||
	dm_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,11 @@
 | 
			
		||||
#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
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user