mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-03 08:23:48 +03:00 
			
		
		
		
	Compare commits
	
		
			795 Commits
		
	
	
		
			old-v1_02_
			...
			v1_02_23
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					49b2006824 | ||
| 
						 | 
					8c6f96faab | ||
| 
						 | 
					a0e648abfd | ||
| 
						 | 
					6350cd12fc | ||
| 
						 | 
					f2fab0677b | ||
| 
						 | 
					edffc52927 | ||
| 
						 | 
					d6e5e3d103 | ||
| 
						 | 
					5be7a0ebf7 | ||
| 
						 | 
					7f722fe7d3 | ||
| 
						 | 
					a01732ee9b | ||
| 
						 | 
					85ac11b69b | ||
| 
						 | 
					590cfb77a5 | ||
| 
						 | 
					f01dd16a27 | ||
| 
						 | 
					df49287e5f | ||
| 
						 | 
					c8ec8391ee | ||
| 
						 | 
					3499e48064 | ||
| 
						 | 
					2e379cb8a5 | ||
| 
						 | 
					f8ee3c2369 | ||
| 
						 | 
					c74fa11518 | ||
| 
						 | 
					ceec4455df | ||
| 
						 | 
					17c9975c0b | ||
| 
						 | 
					6c1cdff912 | ||
| 
						 | 
					79f53f569d | ||
| 
						 | 
					ccb85cc719 | ||
| 
						 | 
					c0eff8a07f | ||
| 
						 | 
					954626f157 | ||
| 
						 | 
					17e7dfa4bd | ||
| 
						 | 
					971f233fb7 | ||
| 
						 | 
					b12bc692af | ||
| 
						 | 
					730301b34d | ||
| 
						 | 
					c443bcf43c | ||
| 
						 | 
					b77e7eeddc | ||
| 
						 | 
					031b7b57a1 | ||
| 
						 | 
					5123fab525 | ||
| 
						 | 
					705b96c6f9 | ||
| 
						 | 
					9ec582002b | ||
| 
						 | 
					ee79277774 | ||
| 
						 | 
					db02dc218e | ||
| 
						 | 
					b66ce1089e | ||
| 
						 | 
					ec0e70b599 | ||
| 
						 | 
					a273482f9d | ||
| 
						 | 
					76cf8c4cf7 | ||
| 
						 | 
					9691ecc839 | ||
| 
						 | 
					59b2a86359 | ||
| 
						 | 
					fe7cd72cff | ||
| 
						 | 
					f0761fc570 | ||
| 
						 | 
					90990aa19d | ||
| 
						 | 
					a3d3ce82e4 | ||
| 
						 | 
					b8e48113a3 | ||
| 
						 | 
					d4b1003a97 | ||
| 
						 | 
					efd83567c9 | ||
| 
						 | 
					5563f373f7 | ||
| 
						 | 
					15a36619fe | ||
| 
						 | 
					38e54b626e | ||
| 
						 | 
					8aa30fb56a | ||
| 
						 | 
					b764becd1b | ||
| 
						 | 
					219370932e | ||
| 
						 | 
					90afae186c | ||
| 
						 | 
					84e49a809d | ||
| 
						 | 
					1cfb9ff46a | ||
| 
						 | 
					f35026c74f | ||
| 
						 | 
					5f2d3da8c5 | ||
| 
						 | 
					4e61f32a28 | ||
| 
						 | 
					d7814c7011 | ||
| 
						 | 
					aa40668e84 | ||
| 
						 | 
					3767e6e96f | ||
| 
						 | 
					44976cef6c | ||
| 
						 | 
					eba4417947 | ||
| 
						 | 
					c99204d370 | ||
| 
						 | 
					1bfc4335bb | ||
| 
						 | 
					6b9c7485f1 | ||
| 
						 | 
					737f3d78f2 | ||
| 
						 | 
					b1d5e1b5e3 | ||
| 
						 | 
					8d92a5cc14 | ||
| 
						 | 
					fc455df92c | ||
| 
						 | 
					c0076ebfa1 | ||
| 
						 | 
					5d607aa3cd | ||
| 
						 | 
					fa1b9a4098 | ||
| 
						 | 
					c8c4dbb409 | ||
| 
						 | 
					16628e6cea | ||
| 
						 | 
					7067c12991 | ||
| 
						 | 
					7b47e241e0 | ||
| 
						 | 
					d1e46207a5 | ||
| 
						 | 
					2a04b97cbd | ||
| 
						 | 
					e6c8ef59e0 | ||
| 
						 | 
					d3380f41de | ||
| 
						 | 
					4ef1633969 | ||
| 
						 | 
					57e593aab2 | ||
| 
						 | 
					6461caacbb | ||
| 
						 | 
					e5531e2a93 | ||
| 
						 | 
					329402a614 | ||
| 
						 | 
					4656ed462e | ||
| 
						 | 
					96ddad91a9 | ||
| 
						 | 
					5eb40588d2 | ||
| 
						 | 
					58def149aa | ||
| 
						 | 
					0ee5743d75 | ||
| 
						 | 
					7c266f3e81 | ||
| 
						 | 
					d7ce981cd1 | ||
| 
						 | 
					eadadf6299 | ||
| 
						 | 
					8ac9fabd07 | ||
| 
						 | 
					44c2b4b281 | ||
| 
						 | 
					4cd97611e5 | ||
| 
						 | 
					da27380ab5 | ||
| 
						 | 
					756e539661 | ||
| 
						 | 
					cde44e3172 | ||
| 
						 | 
					e79a4b34b0 | ||
| 
						 | 
					e9f0bdd72c | ||
| 
						 | 
					d080291150 | ||
| 
						 | 
					06c69c56ba | ||
| 
						 | 
					d79710ba9d | ||
| 
						 | 
					c9bc7dd0b6 | ||
| 
						 | 
					ebc26c7421 | ||
| 
						 | 
					3769425f6b | ||
| 
						 | 
					a50957443e | ||
| 
						 | 
					63fa007af0 | ||
| 
						 | 
					a6a52a128b | ||
| 
						 | 
					1ad58e1121 | ||
| 
						 | 
					3f507a26fb | ||
| 
						 | 
					bfc368764a | ||
| 
						 | 
					53fbce932b | ||
| 
						 | 
					a94195c6cd | ||
| 
						 | 
					626c6d1124 | ||
| 
						 | 
					471ab92bbb | ||
| 
						 | 
					fbccd12924 | ||
| 
						 | 
					e5928bbaea | ||
| 
						 | 
					3c1597bc67 | ||
| 
						 | 
					295019815e | ||
| 
						 | 
					654a391250 | ||
| 
						 | 
					9ee1465d3c | ||
| 
						 | 
					52197cf4d2 | ||
| 
						 | 
					cfbb2afac5 | ||
| 
						 | 
					8f154f65f9 | ||
| 
						 | 
					7454664997 | ||
| 
						 | 
					3393b7aedd | ||
| 
						 | 
					133ccc95b5 | ||
| 
						 | 
					c392ff1cd3 | ||
| 
						 | 
					30a0f831a5 | ||
| 
						 | 
					541ea4dc63 | ||
| 
						 | 
					afc5e0e3e5 | ||
| 
						 | 
					bcb31df10d | ||
| 
						 | 
					2192c4e269 | ||
| 
						 | 
					eec17858c4 | ||
| 
						 | 
					6d696706be | ||
| 
						 | 
					8cd88b6051 | ||
| 
						 | 
					9dbf53fdb9 | ||
| 
						 | 
					38b6963c8b | ||
| 
						 | 
					7b6248983d | ||
| 
						 | 
					4d418dee0e | ||
| 
						 | 
					06fe319347 | ||
| 
						 | 
					9dd7e3fb24 | ||
| 
						 | 
					d5a46396b0 | ||
| 
						 | 
					5e84cb560d | ||
| 
						 | 
					756c6f8560 | ||
| 
						 | 
					6fa6ce35da | ||
| 
						 | 
					b14b97599d | ||
| 
						 | 
					db6f60d6fc | ||
| 
						 | 
					25c348d7c8 | ||
| 
						 | 
					2e4bf8b034 | ||
| 
						 | 
					c1490e2f7b | ||
| 
						 | 
					b004fe9556 | ||
| 
						 | 
					67142ad046 | ||
| 
						 | 
					3c3ec06b12 | ||
| 
						 | 
					5b5caa8a16 | ||
| 
						 | 
					b2cba098bb | ||
| 
						 | 
					1ec0d47f10 | ||
| 
						 | 
					f232606ec7 | ||
| 
						 | 
					fa28cea152 | ||
| 
						 | 
					c8da1647a1 | ||
| 
						 | 
					505a0a8718 | ||
| 
						 | 
					10d3496a17 | ||
| 
						 | 
					a13c755370 | ||
| 
						 | 
					62f9996fd7 | ||
| 
						 | 
					edbcd8a1b2 | ||
| 
						 | 
					a5308d1689 | ||
| 
						 | 
					cbfe6e8fcc | ||
| 
						 | 
					5571ff35d8 | ||
| 
						 | 
					2a4819f3c8 | ||
| 
						 | 
					7121866b13 | ||
| 
						 | 
					d6e05ad9e2 | ||
| 
						 | 
					993e30a7de | ||
| 
						 | 
					49cae61254 | ||
| 
						 | 
					1ea4b2ea91 | ||
| 
						 | 
					bc1d6e1f90 | ||
| 
						 | 
					9ec6e68d0c | ||
| 
						 | 
					341bdc93e2 | ||
| 
						 | 
					6fb3e1aa15 | ||
| 
						 | 
					f1f92eb2e2 | ||
| 
						 | 
					8c2369d40f | ||
| 
						 | 
					a6d9fc58eb | ||
| 
						 | 
					f7cd471548 | ||
| 
						 | 
					5f951faf32 | ||
| 
						 | 
					b228dfaf2c | ||
| 
						 | 
					764858fa12 | ||
| 
						 | 
					5ee976d276 | ||
| 
						 | 
					8b28b6f2d3 | ||
| 
						 | 
					fe16df2e6f | ||
| 
						 | 
					779047f8c9 | ||
| 
						 | 
					094e9fb45d | ||
| 
						 | 
					1458bd0e74 | ||
| 
						 | 
					d2cb05988d | ||
| 
						 | 
					6e056767b4 | ||
| 
						 | 
					a10afb1b98 | ||
| 
						 | 
					bb6d3b6cfd | ||
| 
						 | 
					c75d4af4bc | ||
| 
						 | 
					972dc39d00 | ||
| 
						 | 
					9daac5c178 | ||
| 
						 | 
					dd2a3f40e1 | ||
| 
						 | 
					78f76c1690 | ||
| 
						 | 
					4788066a5f | ||
| 
						 | 
					10e4254e7d | ||
| 
						 | 
					0106e4df9d | ||
| 
						 | 
					8ac718a3a2 | ||
| 
						 | 
					46d45273a1 | ||
| 
						 | 
					8da9ec3599 | ||
| 
						 | 
					01fdf84d69 | ||
| 
						 | 
					cc78386e75 | ||
| 
						 | 
					3755157c61 | ||
| 
						 | 
					80f8436f0a | ||
| 
						 | 
					f88a4b7760 | ||
| 
						 | 
					de229b8ab0 | ||
| 
						 | 
					a3ba37e45e | ||
| 
						 | 
					50c779b3c6 | ||
| 
						 | 
					192372e1c3 | ||
| 
						 | 
					f88fd88c38 | ||
| 
						 | 
					6e15145af1 | ||
| 
						 | 
					4b5fad4e48 | ||
| 
						 | 
					7a13e71c80 | ||
| 
						 | 
					3c10943900 | ||
| 
						 | 
					696b8811c2 | ||
| 
						 | 
					9fd2c8602a | ||
| 
						 | 
					a3636a5af4 | ||
| 
						 | 
					f2e5f07718 | ||
| 
						 | 
					16c6fdde60 | ||
| 
						 | 
					2155c93426 | ||
| 
						 | 
					c394631e4c | ||
| 
						 | 
					8b370b7cc1 | ||
| 
						 | 
					607db9971c | ||
| 
						 | 
					6768f64e2f | ||
| 
						 | 
					f1813b1cc6 | ||
| 
						 | 
					fb665bd0dd | ||
| 
						 | 
					65dda2ef3d | ||
| 
						 | 
					b162b992af | ||
| 
						 | 
					67a3a3d130 | ||
| 
						 | 
					92cd9bf7d2 | ||
| 
						 | 
					bf97034485 | ||
| 
						 | 
					1ded1fc509 | ||
| 
						 | 
					e0592c58b3 | ||
| 
						 | 
					5ead2706b4 | ||
| 
						 | 
					52ada4853c | ||
| 
						 | 
					c2b27a8298 | ||
| 
						 | 
					3934c1d437 | ||
| 
						 | 
					e366b68ad3 | ||
| 
						 | 
					fb94fb980a | ||
| 
						 | 
					b10cc18f53 | ||
| 
						 | 
					a249de3b72 | ||
| 
						 | 
					d04e972d65 | ||
| 
						 | 
					b9f5a18a76 | ||
| 
						 | 
					d3f157f08a | ||
| 
						 | 
					2294fdb496 | ||
| 
						 | 
					d7ba0e01a5 | ||
| 
						 | 
					b6172b53fd | ||
| 
						 | 
					477ec611d5 | ||
| 
						 | 
					b6194edd67 | ||
| 
						 | 
					dcdbbb3ecb | ||
| 
						 | 
					7ef99ee4e6 | ||
| 
						 | 
					1ac1418286 | ||
| 
						 | 
					8fc854f38e | ||
| 
						 | 
					1c2360b335 | ||
| 
						 | 
					dd4477406b | ||
| 
						 | 
					9d67bbb104 | ||
| 
						 | 
					d6c8e1df61 | ||
| 
						 | 
					5ec7c8fece | ||
| 
						 | 
					86b21eaf83 | ||
| 
						 | 
					228486a971 | ||
| 
						 | 
					88c0caab26 | ||
| 
						 | 
					5cd4679419 | ||
| 
						 | 
					eeed5e0d19 | ||
| 
						 | 
					369ab1e0b2 | ||
| 
						 | 
					2e21519a10 | ||
| 
						 | 
					ecc001ed08 | ||
| 
						 | 
					cd96852696 | ||
| 
						 | 
					b9f7f30158 | ||
| 
						 | 
					ca5e423331 | ||
| 
						 | 
					fa9407089c | ||
| 
						 | 
					66f28e193a | ||
| 
						 | 
					0d93f89f5c | ||
| 
						 | 
					154e9a2c47 | ||
| 
						 | 
					84574a1257 | ||
| 
						 | 
					bf83527b64 | ||
| 
						 | 
					12c53622a0 | ||
| 
						 | 
					d8f54cf891 | ||
| 
						 | 
					625a671189 | ||
| 
						 | 
					6ebdad3102 | ||
| 
						 | 
					9a8f21aa03 | ||
| 
						 | 
					291dd8edc2 | ||
| 
						 | 
					de4c1daf29 | ||
| 
						 | 
					0b55d7d0d8 | ||
| 
						 | 
					5d86fd8fdb | ||
| 
						 | 
					1b76eb1f59 | ||
| 
						 | 
					b05678d8bf | ||
| 
						 | 
					781f4971c6 | ||
| 
						 | 
					d02ac7b99a | ||
| 
						 | 
					b1b6c97f7c | ||
| 
						 | 
					baee28ab5c | ||
| 
						 | 
					83edf68ff9 | ||
| 
						 | 
					c7588f91dd | ||
| 
						 | 
					30b432adc5 | ||
| 
						 | 
					7c9733eb5d | ||
| 
						 | 
					a223c3fea3 | ||
| 
						 | 
					d5250f4901 | ||
| 
						 | 
					25f29f4712 | ||
| 
						 | 
					382af5563d | ||
| 
						 | 
					8cf3d165d3 | ||
| 
						 | 
					0fd6ce546f | ||
| 
						 | 
					b881c372bc | ||
| 
						 | 
					94c5e7deb0 | ||
| 
						 | 
					c344766f3c | ||
| 
						 | 
					67895de0bc | ||
| 
						 | 
					ff00cb6990 | ||
| 
						 | 
					2cc75c11ed | ||
| 
						 | 
					cd79e58eda | ||
| 
						 | 
					6fa801f3d8 | ||
| 
						 | 
					684eecba1d | ||
| 
						 | 
					da9cf7e5de | ||
| 
						 | 
					f57e7445fd | ||
| 
						 | 
					fba1388719 | ||
| 
						 | 
					80ed029c17 | ||
| 
						 | 
					34a74e81e3 | ||
| 
						 | 
					cb120ddb15 | ||
| 
						 | 
					f9ee4395b0 | ||
| 
						 | 
					71f06d51ed | ||
| 
						 | 
					217f70952f | ||
| 
						 | 
					f813d41a76 | ||
| 
						 | 
					d851289d8a | ||
| 
						 | 
					b115b8a2ea | ||
| 
						 | 
					d0f7067471 | ||
| 
						 | 
					be5b4c38a7 | ||
| 
						 | 
					d6d597e3dd | ||
| 
						 | 
					84e348fade | ||
| 
						 | 
					910054657e | ||
| 
						 | 
					8357a11249 | ||
| 
						 | 
					9b021ba057 | ||
| 
						 | 
					317e588efd | ||
| 
						 | 
					b1d32a03c7 | ||
| 
						 | 
					ee6e6529ee | ||
| 
						 | 
					9d944d6cf9 | ||
| 
						 | 
					13635d281a | ||
| 
						 | 
					2493c46970 | ||
| 
						 | 
					63e4217271 | ||
| 
						 | 
					f4bd12e8e9 | ||
| 
						 | 
					df15f46900 | ||
| 
						 | 
					fb3a732361 | ||
| 
						 | 
					2d74110feb | ||
| 
						 | 
					19d102082d | ||
| 
						 | 
					d2af2c9487 | ||
| 
						 | 
					82980149fa | ||
| 
						 | 
					a19bb7b909 | ||
| 
						 | 
					9d98c3278d | ||
| 
						 | 
					26376ac1c9 | ||
| 
						 | 
					8459f99341 | ||
| 
						 | 
					e5bdb0e0b5 | ||
| 
						 | 
					1106b7775a | ||
| 
						 | 
					ae2852156d | ||
| 
						 | 
					44c6c36c43 | ||
| 
						 | 
					a81926503d | ||
| 
						 | 
					af13ccddda | ||
| 
						 | 
					392e1bc2e8 | ||
| 
						 | 
					9268d92c70 | ||
| 
						 | 
					bb3366c07d | ||
| 
						 | 
					d24d563ebc | ||
| 
						 | 
					954bd9257b | ||
| 
						 | 
					5d51a56c02 | ||
| 
						 | 
					f48648552e | ||
| 
						 | 
					edb9c3cc9f | ||
| 
						 | 
					01dc83b936 | ||
| 
						 | 
					3a8dff3a62 | ||
| 
						 | 
					13b234ccba | ||
| 
						 | 
					e451e93664 | ||
| 
						 | 
					b4f9531475 | ||
| 
						 | 
					3184ff75c4 | ||
| 
						 | 
					43243f4d30 | ||
| 
						 | 
					c975a100b1 | ||
| 
						 | 
					02bf389425 | ||
| 
						 | 
					bcb9a3dd04 | ||
| 
						 | 
					cce3baa275 | ||
| 
						 | 
					2b48fad426 | ||
| 
						 | 
					d554b2bc94 | ||
| 
						 | 
					f66943de43 | ||
| 
						 | 
					9d1e9bc2fb | ||
| 
						 | 
					2d6a014920 | ||
| 
						 | 
					c1952bf257 | ||
| 
						 | 
					a10227eb03 | ||
| 
						 | 
					475ae29b85 | ||
| 
						 | 
					0b9cfc278b | ||
| 
						 | 
					b57b6b4fba | ||
| 
						 | 
					7d948f7bc5 | ||
| 
						 | 
					459023d171 | ||
| 
						 | 
					fd6570720a | ||
| 
						 | 
					7831665417 | ||
| 
						 | 
					7c9920d982 | ||
| 
						 | 
					cbdccf0a9c | ||
| 
						 | 
					64fa83ec3f | ||
| 
						 | 
					faff865cfd | ||
| 
						 | 
					742ab55a9a | ||
| 
						 | 
					66e623fb2a | ||
| 
						 | 
					4ab17ee965 | ||
| 
						 | 
					7f48ca5132 | ||
| 
						 | 
					da983848b4 | ||
| 
						 | 
					bc03f7bad3 | ||
| 
						 | 
					a1c8bd3846 | ||
| 
						 | 
					404bc284e0 | ||
| 
						 | 
					9dee30ff0e | ||
| 
						 | 
					f91aadbea8 | ||
| 
						 | 
					aa15a10c91 | ||
| 
						 | 
					5b03e36351 | ||
| 
						 | 
					b9ba9ffad2 | ||
| 
						 | 
					642be5d16c | ||
| 
						 | 
					ee68d715bf | ||
| 
						 | 
					224084f056 | ||
| 
						 | 
					1cd8c849b8 | ||
| 
						 | 
					169f68bfcd | ||
| 
						 | 
					d2b7cfa2d1 | ||
| 
						 | 
					a40c7dff5d | ||
| 
						 | 
					e8e00630d3 | ||
| 
						 | 
					e33720c854 | ||
| 
						 | 
					bd8a4e0d17 | ||
| 
						 | 
					586a2aef76 | ||
| 
						 | 
					ce1d8f6754 | ||
| 
						 | 
					7b0f401065 | ||
| 
						 | 
					8387016eef | ||
| 
						 | 
					4e1342b641 | ||
| 
						 | 
					e45a184d90 | ||
| 
						 | 
					979e1012d2 | ||
| 
						 | 
					fe10a50e23 | ||
| 
						 | 
					8ab6d72519 | ||
| 
						 | 
					3aada6dd1d | ||
| 
						 | 
					0933036366 | ||
| 
						 | 
					05f5abdc06 | ||
| 
						 | 
					fb875e0709 | ||
| 
						 | 
					9acdc2f6bf | ||
| 
						 | 
					028ce4bff6 | ||
| 
						 | 
					3f245ad6db | ||
| 
						 | 
					23115f4116 | ||
| 
						 | 
					cf5f48e6cc | ||
| 
						 | 
					997fa756ad | ||
| 
						 | 
					e23f75b1cc | ||
| 
						 | 
					6531e88761 | ||
| 
						 | 
					e76a9c2618 | ||
| 
						 | 
					45be8a836b | ||
| 
						 | 
					954b6032e7 | ||
| 
						 | 
					bd95416f27 | ||
| 
						 | 
					df2577ace2 | ||
| 
						 | 
					720e6558c9 | ||
| 
						 | 
					c239f15d8a | ||
| 
						 | 
					dfa1f80a57 | ||
| 
						 | 
					15dfb93b17 | ||
| 
						 | 
					0ec8488c2b | ||
| 
						 | 
					94b2e29cb1 | ||
| 
						 | 
					fefa8e9b4d | ||
| 
						 | 
					32c4c44812 | ||
| 
						 | 
					05195e2b1d | ||
| 
						 | 
					4c2ff675b8 | ||
| 
						 | 
					e5692a4721 | ||
| 
						 | 
					312e6a0d31 | ||
| 
						 | 
					5bb8efa41f | ||
| 
						 | 
					949a835f4a | ||
| 
						 | 
					85e6042941 | ||
| 
						 | 
					3cd2f28975 | ||
| 
						 | 
					2179a72c3a | ||
| 
						 | 
					a5f282f156 | ||
| 
						 | 
					40e8631f63 | ||
| 
						 | 
					9ded05bb97 | ||
| 
						 | 
					ec8efa35a1 | ||
| 
						 | 
					f72bf20482 | ||
| 
						 | 
					ebde2002e8 | ||
| 
						 | 
					352a66f46f | ||
| 
						 | 
					d84c5391f7 | ||
| 
						 | 
					f4c582472b | ||
| 
						 | 
					1485586f7e | ||
| 
						 | 
					d5c9024335 | ||
| 
						 | 
					860cf80703 | ||
| 
						 | 
					897ff3161f | ||
| 
						 | 
					b356b2e501 | ||
| 
						 | 
					1d2733c893 | ||
| 
						 | 
					32d9126094 | ||
| 
						 | 
					db43314e50 | ||
| 
						 | 
					68d2baeb65 | ||
| 
						 | 
					1fd5f562d3 | ||
| 
						 | 
					48e02f2086 | ||
| 
						 | 
					eab7b2b581 | ||
| 
						 | 
					45abade7fc | ||
| 
						 | 
					5372fc4b43 | ||
| 
						 | 
					4e2f240c98 | ||
| 
						 | 
					bb3605518d | ||
| 
						 | 
					3ef6d37f27 | ||
| 
						 | 
					88e9f2f7f4 | ||
| 
						 | 
					704a447df9 | ||
| 
						 | 
					a5fcb26a33 | ||
| 
						 | 
					2491a61481 | ||
| 
						 | 
					91831d51ed | ||
| 
						 | 
					174f0c19f7 | ||
| 
						 | 
					de6fadfb4f | ||
| 
						 | 
					f946db3e00 | ||
| 
						 | 
					8d05e5bc31 | ||
| 
						 | 
					cfb46820e4 | ||
| 
						 | 
					081f1cbcc2 | ||
| 
						 | 
					7bc6da326f | ||
| 
						 | 
					cd95a0df7b | ||
| 
						 | 
					82fa497c16 | ||
| 
						 | 
					44fd345206 | ||
| 
						 | 
					088e1c9db4 | ||
| 
						 | 
					d4f16e666e | ||
| 
						 | 
					8233cfd371 | ||
| 
						 | 
					ff05e2e30d | ||
| 
						 | 
					a8ea7dd3fb | ||
| 
						 | 
					96f70a5303 | ||
| 
						 | 
					f1604c3e69 | ||
| 
						 | 
					c42c8c5192 | ||
| 
						 | 
					5facb53a41 | ||
| 
						 | 
					d039ce89af | ||
| 
						 | 
					bc7605103f | ||
| 
						 | 
					d305d655d4 | ||
| 
						 | 
					4ef1220b16 | ||
| 
						 | 
					a4fef143cd | ||
| 
						 | 
					74ecb724a9 | ||
| 
						 | 
					af235897ab | ||
| 
						 | 
					5ec4e458b5 | ||
| 
						 | 
					2dae63ce21 | ||
| 
						 | 
					be748fe33b | ||
| 
						 | 
					7408340b6a | ||
| 
						 | 
					29eb92446e | ||
| 
						 | 
					ae6918742e | ||
| 
						 | 
					863484bb65 | ||
| 
						 | 
					1cd7ebce4c | ||
| 
						 | 
					eef8c7862e | ||
| 
						 | 
					b52375d446 | ||
| 
						 | 
					6e2babc2ce | ||
| 
						 | 
					08e253bed1 | ||
| 
						 | 
					c6661477a2 | ||
| 
						 | 
					415cfd99a0 | ||
| 
						 | 
					8c2e37381a | ||
| 
						 | 
					45df79feba | ||
| 
						 | 
					5824f992b7 | ||
| 
						 | 
					b0b60fafd5 | ||
| 
						 | 
					8d98b02ba2 | ||
| 
						 | 
					a93fe79bc4 | ||
| 
						 | 
					4aebd7be37 | ||
| 
						 | 
					3170a5db32 | ||
| 
						 | 
					3605b9eef6 | ||
| 
						 | 
					a945f1fde2 | ||
| 
						 | 
					461a997b5b | ||
| 
						 | 
					a80afd7b4e | ||
| 
						 | 
					aad2b51d85 | ||
| 
						 | 
					36a9a81ff1 | ||
| 
						 | 
					42c88546ae | ||
| 
						 | 
					0f0e86ef9b | ||
| 
						 | 
					98efd9a857 | ||
| 
						 | 
					a0c27d95b7 | ||
| 
						 | 
					984651d99d | ||
| 
						 | 
					c6f7370b30 | ||
| 
						 | 
					3e4b8e8985 | ||
| 
						 | 
					73f08b98d2 | ||
| 
						 | 
					8607a74206 | ||
| 
						 | 
					8339f3ceb3 | ||
| 
						 | 
					c0c9f3cc19 | ||
| 
						 | 
					81f4813c29 | ||
| 
						 | 
					94f57745b9 | ||
| 
						 | 
					54fb2ebbe0 | ||
| 
						 | 
					02d122b65b | ||
| 
						 | 
					df0a5561a1 | ||
| 
						 | 
					f7c55da7d0 | ||
| 
						 | 
					b385f701ce | ||
| 
						 | 
					05dd42f443 | ||
| 
						 | 
					36d816d5cb | ||
| 
						 | 
					92a6746e70 | ||
| 
						 | 
					1728848a39 | ||
| 
						 | 
					f9eb4e7487 | ||
| 
						 | 
					d0b9f33aeb | ||
| 
						 | 
					718583b241 | ||
| 
						 | 
					6737127e9a | ||
| 
						 | 
					19a7b4479b | ||
| 
						 | 
					c340647502 | ||
| 
						 | 
					0f987d2982 | ||
| 
						 | 
					52bcaed169 | ||
| 
						 | 
					177bd565ac | ||
| 
						 | 
					c801c32fc5 | ||
| 
						 | 
					d090cf3058 | ||
| 
						 | 
					1e4b82cc94 | ||
| 
						 | 
					3426f31184 | ||
| 
						 | 
					b4fb7af1df | ||
| 
						 | 
					b36647598b | ||
| 
						 | 
					fd6b94f20e | ||
| 
						 | 
					296dc0ed8a | ||
| 
						 | 
					4f869e14d6 | ||
| 
						 | 
					5704270e9d | ||
| 
						 | 
					505b381e85 | ||
| 
						 | 
					da6cb15393 | ||
| 
						 | 
					16843f6cc8 | ||
| 
						 | 
					64f3ad1fd4 | ||
| 
						 | 
					ff4c4f99b3 | ||
| 
						 | 
					f5d2e09569 | ||
| 
						 | 
					f2bdbe0d4d | ||
| 
						 | 
					c51a13caa6 | ||
| 
						 | 
					7840c78a23 | ||
| 
						 | 
					c706f3246b | ||
| 
						 | 
					608eedf88d | ||
| 
						 | 
					a564ca82be | ||
| 
						 | 
					c868b1fee2 | ||
| 
						 | 
					22374f718f | ||
| 
						 | 
					abe3cfcf41 | ||
| 
						 | 
					59db4b50cd | ||
| 
						 | 
					bdae38765d | ||
| 
						 | 
					66d3ceeb61 | ||
| 
						 | 
					445dd17db3 | ||
| 
						 | 
					cff78a2577 | ||
| 
						 | 
					6a09e64195 | ||
| 
						 | 
					22eabe5eab | ||
| 
						 | 
					b69ba36c2d | ||
| 
						 | 
					5240aad22b | ||
| 
						 | 
					2897eb3cb3 | ||
| 
						 | 
					d3f2f00c25 | ||
| 
						 | 
					bacfb913a0 | ||
| 
						 | 
					c99d0236a0 | ||
| 
						 | 
					aac2b655f7 | ||
| 
						 | 
					126c41e73a | ||
| 
						 | 
					359ee54f0d | ||
| 
						 | 
					28ab560907 | ||
| 
						 | 
					ead252fee4 | ||
| 
						 | 
					abf67914c4 | ||
| 
						 | 
					127884e9dd | ||
| 
						 | 
					654f5049eb | ||
| 
						 | 
					979ca34259 | ||
| 
						 | 
					4dd1086805 | ||
| 
						 | 
					3503d4b72c | ||
| 
						 | 
					b8d32a0d33 | ||
| 
						 | 
					45dca55fc8 | ||
| 
						 | 
					445d8ecd9f | ||
| 
						 | 
					c980add503 | ||
| 
						 | 
					133842392a | ||
| 
						 | 
					8baf2ef155 | ||
| 
						 | 
					20b71340bc | ||
| 
						 | 
					61d8baf8b1 | ||
| 
						 | 
					56a9645aa5 | ||
| 
						 | 
					85877000a6 | ||
| 
						 | 
					2f7d2477b6 | ||
| 
						 | 
					21ea3f05f4 | ||
| 
						 | 
					79d3492e90 | ||
| 
						 | 
					5972777abe | ||
| 
						 | 
					8e373ff868 | ||
| 
						 | 
					a4db92da3a | ||
| 
						 | 
					9b777eb281 | ||
| 
						 | 
					bd3c652184 | ||
| 
						 | 
					800f747570 | ||
| 
						 | 
					2b8423437e | ||
| 
						 | 
					8b4b6945f8 | ||
| 
						 | 
					e5ecfec5c4 | ||
| 
						 | 
					f95dbff71f | ||
| 
						 | 
					098f6830a6 | ||
| 
						 | 
					d1ecebdb52 | ||
| 
						 | 
					590b654251 | ||
| 
						 | 
					3bf190c8ab | ||
| 
						 | 
					dcca7638e0 | ||
| 
						 | 
					70e45ad37b | ||
| 
						 | 
					db88210289 | ||
| 
						 | 
					d2e0d96cc3 | ||
| 
						 | 
					3feba82ccc | ||
| 
						 | 
					db924da231 | ||
| 
						 | 
					fc55ae7e6d | ||
| 
						 | 
					86e757a6ad | ||
| 
						 | 
					4790715cd3 | ||
| 
						 | 
					e7e9c60042 | ||
| 
						 | 
					1c3bc52cc4 | ||
| 
						 | 
					5227dff0e1 | ||
| 
						 | 
					33f0b5b7c2 | ||
| 
						 | 
					0a02968303 | ||
| 
						 | 
					f7bf658c07 | ||
| 
						 | 
					8d16a0abad | ||
| 
						 | 
					c974b97ca3 | ||
| 
						 | 
					b8025bfebd | ||
| 
						 | 
					30323b253f | ||
| 
						 | 
					535c3ede96 | ||
| 
						 | 
					89fed8ca33 | ||
| 
						 | 
					f43c77aaed | ||
| 
						 | 
					96c676b371 | ||
| 
						 | 
					113047e1a2 | ||
| 
						 | 
					abed57cb53 | ||
| 
						 | 
					c01a800a6b | ||
| 
						 | 
					d648832a2d | ||
| 
						 | 
					f06833fbd2 | ||
| 
						 | 
					c561addc94 | ||
| 
						 | 
					702f5f1f4c | ||
| 
						 | 
					1273f179e8 | ||
| 
						 | 
					5d02f60bde | ||
| 
						 | 
					4cf7a108e8 | ||
| 
						 | 
					42635c3938 | ||
| 
						 | 
					ed43dc842b | ||
| 
						 | 
					49d4db6cd2 | ||
| 
						 | 
					ea80ab2cae | ||
| 
						 | 
					382e808b8d | ||
| 
						 | 
					846befa7e0 | ||
| 
						 | 
					74dd29f843 | ||
| 
						 | 
					b0473bffcb | ||
| 
						 | 
					24dd9ab1a7 | ||
| 
						 | 
					49d3037e87 | ||
| 
						 | 
					37ad2bd4e8 | ||
| 
						 | 
					7d7b332b02 | ||
| 
						 | 
					ac033b8612 | ||
| 
						 | 
					a7b98dfe25 | ||
| 
						 | 
					7fb7c86c46 | ||
| 
						 | 
					ed036598a9 | ||
| 
						 | 
					160bb70cdf | ||
| 
						 | 
					c2e61f3c21 | ||
| 
						 | 
					18218467f3 | ||
| 
						 | 
					17e298ad2a | ||
| 
						 | 
					d031a374f9 | ||
| 
						 | 
					55f69c98cb | ||
| 
						 | 
					71f2e4306d | ||
| 
						 | 
					f8af23a025 | ||
| 
						 | 
					4ef55a6cd3 | ||
| 
						 | 
					312f866723 | ||
| 
						 | 
					0ebe1f6dec | ||
| 
						 | 
					2ad92e0e6e | ||
| 
						 | 
					ac8823cdcf | ||
| 
						 | 
					77565f7ee4 | ||
| 
						 | 
					d656d90fa8 | ||
| 
						 | 
					175b3b0834 | ||
| 
						 | 
					7477e6b714 | ||
| 
						 | 
					cd6568db69 | ||
| 
						 | 
					6aff325fb2 | ||
| 
						 | 
					0d603cfe9c | ||
| 
						 | 
					34a1f14a17 | ||
| 
						 | 
					efe1c8a070 | ||
| 
						 | 
					1575844344 | ||
| 
						 | 
					221ac1c208 | ||
| 
						 | 
					57442db759 | ||
| 
						 | 
					5fdb3e7cd6 | ||
| 
						 | 
					96f259726c | ||
| 
						 | 
					4936efba5e | ||
| 
						 | 
					d5a3559a2f | ||
| 
						 | 
					114a1c7f52 | ||
| 
						 | 
					ce5265c203 | ||
| 
						 | 
					1a575d926f | ||
| 
						 | 
					85c818a39e | ||
| 
						 | 
					4ffa2defe4 | ||
| 
						 | 
					8825157fbb | ||
| 
						 | 
					966d608dc5 | ||
| 
						 | 
					b808c89471 | ||
| 
						 | 
					75d4e6490f | ||
| 
						 | 
					a82775f544 | ||
| 
						 | 
					6a22ad0171 | ||
| 
						 | 
					c854e88186 | ||
| 
						 | 
					d02203060c | ||
| 
						 | 
					cf703b0433 | ||
| 
						 | 
					c0197a72d3 | ||
| 
						 | 
					e5a543e283 | ||
| 
						 | 
					b8b029b7d3 | ||
| 
						 | 
					370f368b1a | ||
| 
						 | 
					8288b45b4f | ||
| 
						 | 
					fe529faf8e | ||
| 
						 | 
					ab931b177d | ||
| 
						 | 
					9aa3465513 | ||
| 
						 | 
					6c70fc1a6c | ||
| 
						 | 
					1ccc39962a | ||
| 
						 | 
					99c941fc85 | ||
| 
						 | 
					19729fdcc2 | ||
| 
						 | 
					02e17998ce | ||
| 
						 | 
					459e00c67a | ||
| 
						 | 
					292f665650 | ||
| 
						 | 
					93bbb79569 | ||
| 
						 | 
					273e724f2b | ||
| 
						 | 
					5d2615c56f | ||
| 
						 | 
					bfaaf21330 | ||
| 
						 | 
					dcb8415b7a | ||
| 
						 | 
					699e1c75ce | ||
| 
						 | 
					465b6e613e | ||
| 
						 | 
					05fa105855 | ||
| 
						 | 
					d7a0cdebe5 | ||
| 
						 | 
					b049ab31eb | ||
| 
						 | 
					6db4dcff7a | ||
| 
						 | 
					3eeaef00ec | ||
| 
						 | 
					8bf4c38a00 | ||
| 
						 | 
					3a32b09ad1 | ||
| 
						 | 
					6315982752 | ||
| 
						 | 
					374a171e82 | ||
| 
						 | 
					fc5d801f91 | ||
| 
						 | 
					5146641848 | ||
| 
						 | 
					cdd0ac42cf | ||
| 
						 | 
					e5895500a2 | ||
| 
						 | 
					9cb4dde3fa | ||
| 
						 | 
					3c2a4370a5 | ||
| 
						 | 
					e7a360dd6f | ||
| 
						 | 
					c814c2fd35 | ||
| 
						 | 
					fefa7fe262 | ||
| 
						 | 
					26f01a29d1 | ||
| 
						 | 
					169d4090ab | 
							
								
								
									
										203
									
								
								COPYING.LIB
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								COPYING.LIB
									
									
									
									
									
								
							@@ -1,14 +1,14 @@
 | 
			
		||||
		  GNU LESSER GENERAL PUBLIC LICENSE
 | 
			
		||||
		       Version 2.1, February 1999
 | 
			
		||||
 | 
			
		||||
		  GNU LIBRARY GENERAL PUBLIC LICENSE
 | 
			
		||||
		       Version 2, June 1991
 | 
			
		||||
 | 
			
		||||
 Copyright (C) 1991 Free Software Foundation, Inc.
 | 
			
		||||
 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 | 
			
		||||
 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
 | 
			
		||||
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 Everyone is permitted to copy and distribute verbatim copies
 | 
			
		||||
 of this license document, but changing it is not allowed.
 | 
			
		||||
 | 
			
		||||
[This is the first released version of the library GPL.  It is
 | 
			
		||||
 numbered 2 because it goes with version 2 of the ordinary GPL.]
 | 
			
		||||
[This is the first released version of the Lesser GPL.  It also counts
 | 
			
		||||
 as the successor of the GNU Library Public License, version 2, hence
 | 
			
		||||
 the version number 2.1.]
 | 
			
		||||
 | 
			
		||||
			    Preamble
 | 
			
		||||
 | 
			
		||||
@@ -17,97 +17,109 @@ freedom to share and change it.  By contrast, the GNU General Public
 | 
			
		||||
Licenses are intended to guarantee your freedom to share and change
 | 
			
		||||
free software--to make sure the software is free for all its users.
 | 
			
		||||
 | 
			
		||||
  This license, the Library General Public License, applies to some
 | 
			
		||||
specially designated Free Software Foundation software, and to any
 | 
			
		||||
other libraries whose authors decide to use it.  You can use it for
 | 
			
		||||
your libraries, too.
 | 
			
		||||
  This license, the Lesser General Public License, applies to some
 | 
			
		||||
specially designated software packages--typically libraries--of the
 | 
			
		||||
Free Software Foundation and other authors who decide to use it.  You
 | 
			
		||||
can use it too, but we suggest you first think carefully about whether
 | 
			
		||||
this license or the ordinary General Public License is the better
 | 
			
		||||
strategy to use in any particular case, based on the explanations below.
 | 
			
		||||
 | 
			
		||||
  When we speak of free software, we are referring to freedom, not
 | 
			
		||||
price.  Our General Public Licenses are designed to make sure that you
 | 
			
		||||
have the freedom to distribute copies of free software (and charge for
 | 
			
		||||
this service if you wish), that you receive source code or can get it
 | 
			
		||||
if you want it, that you can change the software or use pieces of it
 | 
			
		||||
in new free programs; and that you know you can do these things.
 | 
			
		||||
  When we speak of free software, we are referring to freedom of use,
 | 
			
		||||
not price.  Our General Public Licenses are designed to make sure that
 | 
			
		||||
you have the freedom to distribute copies of free software (and charge
 | 
			
		||||
for this service if you wish); that you receive source code or can get
 | 
			
		||||
it if you want it; that you can change the software and use pieces of
 | 
			
		||||
it in new free programs; and that you are informed that you can do
 | 
			
		||||
these things.
 | 
			
		||||
 | 
			
		||||
  To protect your rights, we need to make restrictions that forbid
 | 
			
		||||
anyone to deny you these rights or to ask you to surrender the rights.
 | 
			
		||||
These restrictions translate to certain responsibilities for you if
 | 
			
		||||
you distribute copies of the library, or if you modify it.
 | 
			
		||||
distributors to deny you these rights or to ask you to surrender these
 | 
			
		||||
rights.  These restrictions translate to certain responsibilities for
 | 
			
		||||
you if you distribute copies of the library or if you modify it.
 | 
			
		||||
 | 
			
		||||
  For example, if you distribute copies of the library, whether gratis
 | 
			
		||||
or for a fee, you must give the recipients all the rights that we gave
 | 
			
		||||
you.  You must make sure that they, too, receive or can get the source
 | 
			
		||||
code.  If you link a program with the library, you must provide
 | 
			
		||||
complete object files to the recipients so that they can relink them
 | 
			
		||||
with the library, after making changes to the library and recompiling
 | 
			
		||||
code.  If you link other code with the library, you must provide
 | 
			
		||||
complete object files to the recipients, so that they can relink them
 | 
			
		||||
with the library after making changes to the library and recompiling
 | 
			
		||||
it.  And you must show them these terms so they know their rights.
 | 
			
		||||
 | 
			
		||||
  Our method of protecting your rights has two steps: (1) copyright
 | 
			
		||||
the library, and (2) offer you this license which gives you legal
 | 
			
		||||
  We protect your rights with a two-step method: (1) we copyright the
 | 
			
		||||
library, and (2) we offer you this license, which gives you legal
 | 
			
		||||
permission to copy, distribute and/or modify the library.
 | 
			
		||||
 | 
			
		||||
  Also, for each distributor's protection, we want to make certain
 | 
			
		||||
that everyone understands that there is no warranty for this free
 | 
			
		||||
library.  If the library is modified by someone else and passed on, we
 | 
			
		||||
want its recipients to know that what they have is not the original
 | 
			
		||||
version, so that any problems introduced by others will not reflect on
 | 
			
		||||
the original authors' reputations.
 | 
			
		||||
  To protect each distributor, we want to make it very clear that
 | 
			
		||||
there is no warranty for the free library.  Also, if the library is
 | 
			
		||||
modified by someone else and passed on, the recipients should know
 | 
			
		||||
that what they have is not the original version, so that the original
 | 
			
		||||
author's reputation will not be affected by problems that might be
 | 
			
		||||
introduced by others.
 | 
			
		||||
 | 
			
		||||
  Finally, any free program is threatened constantly by software
 | 
			
		||||
patents.  We wish to avoid the danger that companies distributing free
 | 
			
		||||
software will individually obtain patent licenses, thus in effect
 | 
			
		||||
transforming the program into proprietary software.  To prevent this,
 | 
			
		||||
we have made it clear that any patent must be licensed for everyone's
 | 
			
		||||
free use or not licensed at all.
 | 
			
		||||
  Finally, software patents pose a constant threat to the existence of
 | 
			
		||||
any free program.  We wish to make sure that a company cannot
 | 
			
		||||
effectively restrict the users of a free program by obtaining a
 | 
			
		||||
restrictive license from a patent holder.  Therefore, we insist that
 | 
			
		||||
any patent license obtained for a version of the library must be
 | 
			
		||||
consistent with the full freedom of use specified in this license.
 | 
			
		||||
 | 
			
		||||
  Most GNU software, including some libraries, is covered by the ordinary
 | 
			
		||||
GNU General Public License, which was designed for utility programs.  This
 | 
			
		||||
license, the GNU Library General Public License, applies to certain
 | 
			
		||||
designated libraries.  This license is quite different from the ordinary
 | 
			
		||||
one; be sure to read it in full, and don't assume that anything in it is
 | 
			
		||||
the same as in the ordinary license.
 | 
			
		||||
  Most GNU software, including some libraries, is covered by the
 | 
			
		||||
ordinary GNU General Public License.  This license, the GNU Lesser
 | 
			
		||||
General Public License, applies to certain designated libraries, and
 | 
			
		||||
is quite different from the ordinary General Public License.  We use
 | 
			
		||||
this license for certain libraries in order to permit linking those
 | 
			
		||||
libraries into non-free programs.
 | 
			
		||||
 | 
			
		||||
  The reason we have a separate public license for some libraries is that
 | 
			
		||||
they blur the distinction we usually make between modifying or adding to a
 | 
			
		||||
program and simply using it.  Linking a program with a library, without
 | 
			
		||||
changing the library, is in some sense simply using the library, and is
 | 
			
		||||
analogous to running a utility program or application program.  However, in
 | 
			
		||||
a textual and legal sense, the linked executable is a combined work, a
 | 
			
		||||
derivative of the original library, and the ordinary General Public License
 | 
			
		||||
treats it as such.
 | 
			
		||||
  When a program is linked with a library, whether statically or using
 | 
			
		||||
a shared library, the combination of the two is legally speaking a
 | 
			
		||||
combined work, a derivative of the original library.  The ordinary
 | 
			
		||||
General Public License therefore permits such linking only if the
 | 
			
		||||
entire combination fits its criteria of freedom.  The Lesser General
 | 
			
		||||
Public License permits more lax criteria for linking other code with
 | 
			
		||||
the library.
 | 
			
		||||
 | 
			
		||||
  Because of this blurred distinction, using the ordinary General
 | 
			
		||||
Public License for libraries did not effectively promote software
 | 
			
		||||
sharing, because most developers did not use the libraries.  We
 | 
			
		||||
concluded that weaker conditions might promote sharing better.
 | 
			
		||||
  We call this license the "Lesser" General Public License because it
 | 
			
		||||
does Less to protect the user's freedom than the ordinary General
 | 
			
		||||
Public License.  It also provides other free software developers Less
 | 
			
		||||
of an advantage over competing non-free programs.  These disadvantages
 | 
			
		||||
are the reason we use the ordinary General Public License for many
 | 
			
		||||
libraries.  However, the Lesser license provides advantages in certain
 | 
			
		||||
special circumstances.
 | 
			
		||||
 | 
			
		||||
  However, unrestricted linking of non-free programs would deprive the
 | 
			
		||||
users of those programs of all benefit from the free status of the
 | 
			
		||||
libraries themselves.  This Library General Public License is intended to
 | 
			
		||||
permit developers of non-free programs to use free libraries, while
 | 
			
		||||
preserving your freedom as a user of such programs to change the free
 | 
			
		||||
libraries that are incorporated in them.  (We have not seen how to achieve
 | 
			
		||||
this as regards changes in header files, but we have achieved it as regards
 | 
			
		||||
changes in the actual functions of the Library.)  The hope is that this
 | 
			
		||||
will lead to faster development of free libraries.
 | 
			
		||||
  For example, on rare occasions, there may be a special need to
 | 
			
		||||
encourage the widest possible use of a certain library, so that it becomes
 | 
			
		||||
a de-facto standard.  To achieve this, non-free programs must be
 | 
			
		||||
allowed to use the library.  A more frequent case is that a free
 | 
			
		||||
library does the same job as widely used non-free libraries.  In this
 | 
			
		||||
case, there is little to gain by limiting the free library to free
 | 
			
		||||
software only, so we use the Lesser General Public License.
 | 
			
		||||
 | 
			
		||||
  In other cases, permission to use a particular library in non-free
 | 
			
		||||
programs enables a greater number of people to use a large body of
 | 
			
		||||
free software.  For example, permission to use the GNU C Library in
 | 
			
		||||
non-free programs enables many more people to use the whole GNU
 | 
			
		||||
operating system, as well as its variant, the GNU/Linux operating
 | 
			
		||||
system.
 | 
			
		||||
 | 
			
		||||
  Although the Lesser General Public License is Less protective of the
 | 
			
		||||
users' freedom, it does ensure that the user of a program that is
 | 
			
		||||
linked with the Library has the freedom and the wherewithal to run
 | 
			
		||||
that program using a modified version of the Library.
 | 
			
		||||
 | 
			
		||||
  The precise terms and conditions for copying, distribution and
 | 
			
		||||
modification follow.  Pay close attention to the difference between a
 | 
			
		||||
"work based on the library" and a "work that uses the library".  The
 | 
			
		||||
former contains code derived from the library, while the latter only
 | 
			
		||||
works together with the library.
 | 
			
		||||
 | 
			
		||||
  Note that it is possible for a library to be covered by the ordinary
 | 
			
		||||
General Public License rather than by this special one.
 | 
			
		||||
former contains code derived from the library, whereas the latter must
 | 
			
		||||
be combined with the library in order to run.
 | 
			
		||||
 | 
			
		||||
		  GNU LIBRARY GENERAL PUBLIC LICENSE
 | 
			
		||||
		  GNU LESSER GENERAL PUBLIC LICENSE
 | 
			
		||||
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 | 
			
		||||
 | 
			
		||||
  0. This License Agreement applies to any software library which
 | 
			
		||||
contains a notice placed by the copyright holder or other authorized
 | 
			
		||||
party saying it may be distributed under the terms of this Library
 | 
			
		||||
General Public License (also called "this License").  Each licensee is
 | 
			
		||||
addressed as "you".
 | 
			
		||||
  0. This License Agreement applies to any software library or other
 | 
			
		||||
program which contains a notice placed by the copyright holder or
 | 
			
		||||
other authorized party saying it may be distributed under the terms of
 | 
			
		||||
this Lesser General Public License (also called "this License").
 | 
			
		||||
Each licensee is addressed as "you".
 | 
			
		||||
 | 
			
		||||
  A "library" means a collection of software functions and/or data
 | 
			
		||||
prepared so as to be conveniently linked with application programs
 | 
			
		||||
@@ -256,7 +268,7 @@ distribute the object code for the work under the terms of Section 6.
 | 
			
		||||
Any executables containing that work also fall under Section 6,
 | 
			
		||||
whether or not they are linked directly with the Library itself.
 | 
			
		||||
 | 
			
		||||
  6. As an exception to the Sections above, you may also compile or
 | 
			
		||||
  6. As an exception to the Sections above, you may also combine or
 | 
			
		||||
link a "work that uses the Library" with the Library to produce a
 | 
			
		||||
work containing portions of the Library, and distribute that work
 | 
			
		||||
under terms of your choice, provided that the terms permit
 | 
			
		||||
@@ -283,23 +295,31 @@ of these things:
 | 
			
		||||
    Library will not necessarily be able to recompile the application
 | 
			
		||||
    to use the modified definitions.)
 | 
			
		||||
 | 
			
		||||
    b) Accompany the work with a written offer, valid for at
 | 
			
		||||
    b) Use a suitable shared library mechanism for linking with the
 | 
			
		||||
    Library.  A suitable mechanism is one that (1) uses at run time a
 | 
			
		||||
    copy of the library already present on the user's computer system,
 | 
			
		||||
    rather than copying library functions into the executable, and (2)
 | 
			
		||||
    will operate properly with a modified version of the library, if
 | 
			
		||||
    the user installs one, as long as the modified version is
 | 
			
		||||
    interface-compatible with the version that the work was made with.
 | 
			
		||||
 | 
			
		||||
    c) Accompany the work with a written offer, valid for at
 | 
			
		||||
    least three years, to give the same user the materials
 | 
			
		||||
    specified in Subsection 6a, above, for a charge no more
 | 
			
		||||
    than the cost of performing this distribution.
 | 
			
		||||
 | 
			
		||||
    c) If distribution of the work is made by offering access to copy
 | 
			
		||||
    d) If distribution of the work is made by offering access to copy
 | 
			
		||||
    from a designated place, offer equivalent access to copy the above
 | 
			
		||||
    specified materials from the same place.
 | 
			
		||||
 | 
			
		||||
    d) Verify that the user has already received a copy of these
 | 
			
		||||
    e) Verify that the user has already received a copy of these
 | 
			
		||||
    materials or that you have already sent this user a copy.
 | 
			
		||||
 | 
			
		||||
  For an executable, the required form of the "work that uses the
 | 
			
		||||
Library" must include any data and utility programs needed for
 | 
			
		||||
reproducing the executable from it.  However, as a special exception,
 | 
			
		||||
the source code distributed need not include anything that is normally
 | 
			
		||||
distributed (in either source or binary form) with the major
 | 
			
		||||
the materials to be distributed need not include anything that is
 | 
			
		||||
normally distributed (in either source or binary form) with the major
 | 
			
		||||
components (compiler, kernel, and so on) of the operating system on
 | 
			
		||||
which the executable runs, unless that component itself accompanies
 | 
			
		||||
the executable.
 | 
			
		||||
@@ -348,7 +368,7 @@ Library), the recipient automatically receives a license from the
 | 
			
		||||
original licensor to copy, distribute, link with or modify the Library
 | 
			
		||||
subject to these terms and conditions.  You may not impose any further
 | 
			
		||||
restrictions on the recipients' exercise of the rights granted herein.
 | 
			
		||||
You are not responsible for enforcing compliance by third parties to
 | 
			
		||||
You are not responsible for enforcing compliance by third parties with
 | 
			
		||||
this License.
 | 
			
		||||
 | 
			
		||||
  11. If, as a consequence of a court judgment or allegation of patent
 | 
			
		||||
@@ -391,7 +411,7 @@ excluded.  In such case, this License incorporates the limitation as if
 | 
			
		||||
written in the body of this License.
 | 
			
		||||
 | 
			
		||||
  13. The Free Software Foundation may publish revised and/or new
 | 
			
		||||
versions of the Library General Public License from time to time.
 | 
			
		||||
versions of the Lesser General Public License from time to time.
 | 
			
		||||
Such new versions will be similar in spirit to the present version,
 | 
			
		||||
but may differ in detail to address new problems or concerns.
 | 
			
		||||
 | 
			
		||||
@@ -437,7 +457,7 @@ DAMAGES.
 | 
			
		||||
 | 
			
		||||
		     END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
     Appendix: How to Apply These Terms to Your New Libraries
 | 
			
		||||
           How to Apply These Terms to Your New Libraries
 | 
			
		||||
 | 
			
		||||
  If you develop a new library, and you want it to be of the greatest
 | 
			
		||||
possible use to the public, we recommend making it free software that
 | 
			
		||||
@@ -454,19 +474,18 @@ convey the exclusion of warranty; and each file should have at least the
 | 
			
		||||
    Copyright (C) <year>  <name of author>
 | 
			
		||||
 | 
			
		||||
    This library is free software; you can redistribute it and/or
 | 
			
		||||
    modify it under the terms of the GNU Library General Public
 | 
			
		||||
    modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
    License as published by the Free Software Foundation; either
 | 
			
		||||
    version 2 of the License, or (at your option) any later version.
 | 
			
		||||
    version 2.1 of the License, or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This 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.
 | 
			
		||||
    Lesser General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Library General Public
 | 
			
		||||
    License along with this 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 Lesser General Public
 | 
			
		||||
    License along with this library; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 | 
			
		||||
Also add information on how to contact you by electronic and paper mail.
 | 
			
		||||
 | 
			
		||||
@@ -481,3 +500,5 @@ necessary.  Here is a sample; alter the names:
 | 
			
		||||
  Ty Coon, President of Vice
 | 
			
		||||
 | 
			
		||||
That's all there is to it!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								Makefile.in
									
									
									
									
									
								
							@@ -1,8 +1,8 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
# 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
 | 
			
		||||
@@ -16,7 +16,7 @@ srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
SUBDIRS = doc include man 
 | 
			
		||||
SUBDIRS = doc include man scripts
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
  SUBDIRS += po
 | 
			
		||||
@@ -24,8 +24,13 @@ endif
 | 
			
		||||
 | 
			
		||||
SUBDIRS += lib tools daemons
 | 
			
		||||
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
  SUBDIRS += dmeventd
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
  SUBDIRS += daemons/clvmd \
 | 
			
		||||
	     dmeventd \
 | 
			
		||||
	     lib/format1 \
 | 
			
		||||
	     lib/format_pool \
 | 
			
		||||
	     lib/locking \
 | 
			
		||||
@@ -33,6 +38,7 @@ ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
	     lib/snapshot \
 | 
			
		||||
	     po \
 | 
			
		||||
	     test/mm test/device test/format1 test/regex test/filters
 | 
			
		||||
  DISTCLEAN_TARGETS += lib/misc/configure.h
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include make.tmpl
 | 
			
		||||
@@ -40,13 +46,28 @@ include make.tmpl
 | 
			
		||||
daemons: lib
 | 
			
		||||
lib: include
 | 
			
		||||
tools: lib
 | 
			
		||||
po: tools daemons
 | 
			
		||||
dmeventd: tools
 | 
			
		||||
po: tools daemons dmeventd
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
lib.pofile: include.pofile
 | 
			
		||||
tools.pofile: lib.pofile
 | 
			
		||||
daemons.pofile: lib.pofile
 | 
			
		||||
po.pofile: tools.pofile daemons.pofile
 | 
			
		||||
dmeventd.pofile: tools.pofile
 | 
			
		||||
po.pofile: tools.pofile daemons.pofile dmeventd.pofile
 | 
			
		||||
pofile: po.pofile
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@CFLOW_CMD@", "")
 | 
			
		||||
tools.cflow: lib.cflow
 | 
			
		||||
cflow: tools.cflow
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@CSCOPE_CMD@", "")
 | 
			
		||||
cscope.out: tools
 | 
			
		||||
	@CSCOPE_CMD@ -b -R
 | 
			
		||||
all: cscope.out
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
check: all
 | 
			
		||||
	$(MAKE) -C test all
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										533
									
								
								WHATS_NEW
									
									
									
									
									
								
							
							
						
						
									
										533
									
								
								WHATS_NEW
									
									
									
									
									
								
							@@ -1,5 +1,519 @@
 | 
			
		||||
Version 2.02.00 - 
 | 
			
		||||
Version 2.02.29 -
 | 
			
		||||
==================================
 | 
			
		||||
  Refactor pvmove allocation code.
 | 
			
		||||
  Decode cluster locking state in log message.
 | 
			
		||||
  Change file locking state messages from debug to very verbose.
 | 
			
		||||
  Fix --addtag to drop @ prefix from name.
 | 
			
		||||
  Stop clvmd going haywire if a pre_function fails.
 | 
			
		||||
  Convert some vg_reads into vg_lock_and_reads.
 | 
			
		||||
  Avoid nested vg_reads when processing PVs in VGs and fix associated locking.
 | 
			
		||||
  Accept sizes with --readahead argument.
 | 
			
		||||
  Store size arguments as sectors internally.
 | 
			
		||||
  Attempt to remove incomplete LVs with lvcreate zeroing/activation problems.
 | 
			
		||||
  Add read_ahead activation code.
 | 
			
		||||
  Add activation/readahead configuration option and FMT_RESTRICTED_READAHEAD.
 | 
			
		||||
  Extend readahead arg to accept "auto" and "none".
 | 
			
		||||
  Add lv_read_ahead and lv_kernel_read_ahead fields to reports and lvdisplay.
 | 
			
		||||
  Prevent lvconvert -s from using same LV as origin and snapshot.
 | 
			
		||||
  Fix human-readable output of odd numbers of sectors.
 | 
			
		||||
  Add pv_mda_free and vg_mda_free fields to reports for raw text format.
 | 
			
		||||
  Add LVM2 version to 'Generated by' comment in metadata.
 | 
			
		||||
  Show 'not usable' space when PV is too large for device in pvdisplay.
 | 
			
		||||
  Ignore and fix up any excessive device size found in metadata.
 | 
			
		||||
  Fix error message when fixing up PV size in lvm2 metadata (2.02.11).
 | 
			
		||||
  Fix orphan-related locking in pvdisplay and pvs.
 | 
			
		||||
  Fix missing VG unlocks in some pvchange error paths.
 | 
			
		||||
  Add some missing validation of VG names.
 | 
			
		||||
  Rename validate_vg_name() to validate_new_vg_name().
 | 
			
		||||
  Change orphan lock to VG_ORPHANS.
 | 
			
		||||
  Change format1 to use ORPHAN as orphan VG name.
 | 
			
		||||
  Convert pvchange, pvdisplay, pvscan to use is_orphan()
 | 
			
		||||
  Add is_orphan_vg() and change all hard-coded checks to use it.
 | 
			
		||||
  Detect md superblocks version 1.0, 1.1 and 1.2.
 | 
			
		||||
  Add _alloc_pv() and _free_pv() from _pv_create() code and fix error paths.
 | 
			
		||||
  Add pv_dev_name() to access PV device name.
 | 
			
		||||
  Add const attributes to pv accessor functions.
 | 
			
		||||
  Refactor vg_add_snapshot() and lv_create_empty().
 | 
			
		||||
  Handle new sysfs subsystem/block/devices directory structure.
 | 
			
		||||
  Tests are run with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
 | 
			
		||||
  Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries.
 | 
			
		||||
  Fix underquotations in lvm_dump.sh.
 | 
			
		||||
  Refactor lvcreate stripe and mirror parameter validation.
 | 
			
		||||
  All tools: print --help output to stdout, not stderr.
 | 
			
		||||
  After a diagnostic, suggest --help, rather than printing all --help output.
 | 
			
		||||
  Add %PVS extents option to lvresize, lvextend, and lvcreate.
 | 
			
		||||
  Moved the obsolete test subdirectory to old-tests.
 | 
			
		||||
  Remove no-longer-correct restrictions on PV arg count with stripes/mirrors.
 | 
			
		||||
  Fix strdup memory leak in str_list_dup().
 | 
			
		||||
  Link with -lpthread when static SELinux libraries require that.
 | 
			
		||||
  Detect command line PE values that exceed their 32-bit range.
 | 
			
		||||
  Include strerror string in dev_open_flags' stat failure message.
 | 
			
		||||
  Move guts of pvresize into library.
 | 
			
		||||
  Avoid error when --corelog is provided without --mirrorlog. (2.02.28)
 | 
			
		||||
  Correct --mirrorlog argument name in man pages (not --log).
 | 
			
		||||
  Clear MIRROR_NOTSYNCED LV flag when converting from mirror to linear.
 | 
			
		||||
  Modify lvremove to prompt for removal if LV active on other cluster nodes.
 | 
			
		||||
  Add '-f' to vgremove to force removal of VG even if LVs exist.
 | 
			
		||||
 | 
			
		||||
Version 2.02.28 - 24th August 2007
 | 
			
		||||
==================================
 | 
			
		||||
  Fix clvmd logging so you can get lvm-level debugging out of it.
 | 
			
		||||
  Introduce VG_GLOBAL lock type for vgscan/pvscan to trigger clvmd -R.
 | 
			
		||||
  Change locking_flags from int to uint32_t.
 | 
			
		||||
  Fix clvmd -R, so it fully refreshes the caches.
 | 
			
		||||
  Change lvconvert_mirrors to use mirror segtype not striped.
 | 
			
		||||
  Fix lvconvert_mirrors detection of number of existing mirrors.
 | 
			
		||||
  Clean up numerous compiler warnings that appeared in recent releases.
 | 
			
		||||
  Remove several unused parameters from _allocate().
 | 
			
		||||
  Only permit --force, --verbose and --debug arguments to be repeated.
 | 
			
		||||
  Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
 | 
			
		||||
  Move guts of vgremove and lvremove into library, including yes_no_prompt.
 | 
			
		||||
  Allow clvmd debug to be turned on in a running daemon using clvmd -d [-C].
 | 
			
		||||
  Update to use autoconf 2.61, while still supporting 2.57.
 | 
			
		||||
  Add more cluster info to lvmdump.
 | 
			
		||||
  Add further const attributes throughout.
 | 
			
		||||
  Add support for renaming mirrored LVs.
 | 
			
		||||
  Factor out core of lvrename() to library function.
 | 
			
		||||
  Add --mirrorlog argument to specify log type for mirrors.
 | 
			
		||||
  Don't attempt to monitor devices if their creation failed in _lv_activate.
 | 
			
		||||
  Don't leak a file descriptor in fcntl_lock_file() when fcntl fails.
 | 
			
		||||
  Replace create_dir with dm_create_dir.
 | 
			
		||||
  Detect stream write failure reliably with lvm_fclose using dm_fclose.
 | 
			
		||||
  Fix clvmd if compiled with gulm support. (2.02.26)
 | 
			
		||||
  Fix lvdisplay man page to say LV size is reported in sectors, not KB.
 | 
			
		||||
  Add vg_lock_and_read() external library function.
 | 
			
		||||
  Fix loading of persistent cache if cache_dir is used. (2.02.23)
 | 
			
		||||
  Reduce _compare_paths lstat error message from log_error to log_very_verbose.
 | 
			
		||||
  Create util.h with last_path_component replacing strdup + basename.
 | 
			
		||||
  Use gcc's printf attribute wherever possible.
 | 
			
		||||
  In _line_append, use "sizeof buf - 1" rather than equivalent "4095".
 | 
			
		||||
  Introduce is_same_inode macro, now including a comparison of st_dev.
 | 
			
		||||
  Don't leak a file descriptor in _lock_file() when flock fails.
 | 
			
		||||
  Add SUN's LDOM virtual block device (vdisk) and ps3disk to filters.
 | 
			
		||||
  Split metadata-external.h out from metadata.h for the tools to use.
 | 
			
		||||
 | 
			
		||||
Version 2.02.27 - 17th July 2007
 | 
			
		||||
================================
 | 
			
		||||
  Fix snapshot cow area deactivation if origin is not active. (2.02.13)
 | 
			
		||||
  Fix configure libdevmapper.h check when --with-dmdir is used.
 | 
			
		||||
  Turn _add_pv_to_vg() into external library function add_pv_to_vg().
 | 
			
		||||
  Add pv_by_path() external library function.
 | 
			
		||||
  Tidy clvmd-openais of redundant bits, and improve an error report.
 | 
			
		||||
  Cope with find_seg_by_le() failure in check_lv_segments().
 | 
			
		||||
  Call dev_iter_destroy() if _process_all_devs() is interrupted by sigint.
 | 
			
		||||
  Add vg_mda_count and pv_mda_count columns to reports.
 | 
			
		||||
  Fix dumpconfig to use log_print instead of stdout directly.
 | 
			
		||||
  Remove unused parameter 'fid' from _add_pv_to_vg.
 | 
			
		||||
  Add kernel and device-mapper targets versions to lvmdump.
 | 
			
		||||
  Replace BSD (r)index with C89 str(r)chr.
 | 
			
		||||
  Handle vgsplit of an entire VG as a vgrename.
 | 
			
		||||
  Reinitialise internal lvmdiskscan variables when called repeatedly.
 | 
			
		||||
  Fix missing lvm_shell symbol in lvm2cmd library. (2.02.23)
 | 
			
		||||
  Add vg_status function and clean up vg->status in tools directory.
 | 
			
		||||
  Add --ignoremonitoring to disable all dmeventd interaction.
 | 
			
		||||
  Remove get_ prefix from get_pv_* functions.
 | 
			
		||||
  clvmd-openais now uses cpg_local_get() to get nodeid, rather than Clm.
 | 
			
		||||
  Print warnings to stderr instead of stdout.
 | 
			
		||||
 | 
			
		||||
Version 2.02.26 - 15th June 2007
 | 
			
		||||
================================
 | 
			
		||||
  Update vgcfgrestore man page.
 | 
			
		||||
  Allow keyboard interrupt during user prompts when appropriate.
 | 
			
		||||
  Remove unused clvmd system-lv code.
 | 
			
		||||
  Replace many physical_volume struct dereferences with new get_pv_* functions.
 | 
			
		||||
  Suppress a benign compile-time warning.
 | 
			
		||||
  Convert find_pv_in_vg_by_uuid and pv_create to use PV handles.
 | 
			
		||||
  Add wrappers to some functions in preparation for external LVM library.
 | 
			
		||||
  Add -f to vgcfgrestore to list metadata backup files.
 | 
			
		||||
  Add vg_check_status to consolidate vg status checks and error messages.
 | 
			
		||||
  Add pvdisplay --maps implementation.
 | 
			
		||||
  Remove unsupported LVM1 options from vgcfgrestore man page.
 | 
			
		||||
  Update vgcfgrestore man page to show mandatory VG name.
 | 
			
		||||
  Update vgrename man page to include UUID and be consistent with lvrename.
 | 
			
		||||
  Add (experimental) OpenAIS support to clvmd.
 | 
			
		||||
  Fix deactivation code to follow dependencies and remove symlinks.
 | 
			
		||||
  Fix and clarify vgsplit error messages.
 | 
			
		||||
  Fix a segfault in device_is_usable() if a device has no table.
 | 
			
		||||
  Add some more debug messages to clvmd startup.
 | 
			
		||||
  Misc clvmd cleanups.
 | 
			
		||||
 | 
			
		||||
Version 2.02.25 - 27th April 2007
 | 
			
		||||
=================================
 | 
			
		||||
  Fix get_config_uint64() to read a 64-bit value not a 32-bit one.
 | 
			
		||||
  Add -Wformat-security and change one fprintf() to fputs().
 | 
			
		||||
  Move regex functions into libdevmapper.
 | 
			
		||||
  Change some #include lines to search only standard system directories.
 | 
			
		||||
  Add devices/preferred_names config regex list for displayed device names.
 | 
			
		||||
  Free a temporary dir string in fcntl_lock_file() after use.
 | 
			
		||||
  Fix a dm_pool_destroy() in matcher_create().
 | 
			
		||||
  Introduce goto_bad macro.
 | 
			
		||||
  Fix warnings on x86_64 involving ptrdiff_t in log_error messages.
 | 
			
		||||
  Update pvck to include text metadata area and record detection.
 | 
			
		||||
  Add support functions for token counting in config file extracts.
 | 
			
		||||
  Update pvck to read labels on disk, with --labelsector parameter.
 | 
			
		||||
  Add count_chars and count_chars_len functions.
 | 
			
		||||
  Add /sys/block listings to lvm_dump.sh.
 | 
			
		||||
  Make lvm_dump.sh list /dev recursively.
 | 
			
		||||
  Fix thread race in clvmd.
 | 
			
		||||
  Add scan_sector param to label_read and _find_labeller.
 | 
			
		||||
  Make clvmd cope with quorum devices.
 | 
			
		||||
  Add extra internal error checking to clvmd.
 | 
			
		||||
  Add dev_read_circular.
 | 
			
		||||
  Add pvck command stub.
 | 
			
		||||
  Update lists of attribute characters in man pages.
 | 
			
		||||
  Change cling alloc policy attribute character from 'C' to l'.
 | 
			
		||||
  Fix creation and conversion of mirrors with tags.
 | 
			
		||||
  Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
 | 
			
		||||
  Split metadata areas in vgsplit properly.
 | 
			
		||||
 | 
			
		||||
Version 2.02.24 - 19th March 2007
 | 
			
		||||
=================================
 | 
			
		||||
  Fix processing of exit status in init scripts
 | 
			
		||||
  Fix vgremove to require at least one vg argument.
 | 
			
		||||
  Fix reading of striped LVs in LVM1 format.
 | 
			
		||||
  Flag nolocking as clustered so clvmd startup sees clustered LVs. (2.02.10)
 | 
			
		||||
  Add a few missing pieces of vgname command line validation.
 | 
			
		||||
  Support the /dev/mapper prefix on most command lines.
 | 
			
		||||
 | 
			
		||||
Version 2.02.23 - 8th March 2007
 | 
			
		||||
================================
 | 
			
		||||
  Fix vgrename active LV check to ignore differing vgids.
 | 
			
		||||
  Remove no-longer-used uuid_out parameter from activation info functions.
 | 
			
		||||
  Fix two more segfaults if an empty config file section encountered.
 | 
			
		||||
  Move .cache file into a new /etc/lvm/cache directory by default.
 | 
			
		||||
  Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
 | 
			
		||||
  Create directory in fcntl_lock_file() if required.
 | 
			
		||||
  Exclude readline support from lvm.static.
 | 
			
		||||
  Fix a leak in a reporting error path (2.02.19).
 | 
			
		||||
 | 
			
		||||
Version 2.02.22 - 13th February 2007
 | 
			
		||||
====================================
 | 
			
		||||
  Correct -b and -P on a couple of man pages.
 | 
			
		||||
  Add global/units to example.conf.
 | 
			
		||||
  Fix loading of segment_libraries.
 | 
			
		||||
  If a PV reappears after it was removed from its VG, make it an orphan.
 | 
			
		||||
  Don't update metadata automatically if VGIDs don't match.
 | 
			
		||||
  Fix some vgreduce --removemissing command line validation.
 | 
			
		||||
 | 
			
		||||
Version 2.02.21 - 30th January 2007
 | 
			
		||||
===================================
 | 
			
		||||
  Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
 | 
			
		||||
  Fix vgsplit to handle mirrors.
 | 
			
		||||
  Reorder fields in reporting field definitions.
 | 
			
		||||
  Fix vgs to treat args as VGs even when PV fields are displayed.
 | 
			
		||||
  Fix md signature check to handle both endiannesses.
 | 
			
		||||
 | 
			
		||||
Version 2.02.20 - 25th January 2007
 | 
			
		||||
===================================
 | 
			
		||||
  dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.
 | 
			
		||||
  Add devices/ignore_suspended_devices to ignore suspended dm devices.
 | 
			
		||||
  Add some missing close() and fclose() return code checks.
 | 
			
		||||
  Fix exit statuses of reporting tools (2.02.19).
 | 
			
		||||
  Add init script for dmeventd monitoring.
 | 
			
		||||
  lvm.static no longer interacts with dmeventd unless explicitly asked to.
 | 
			
		||||
  Add field definitions to report help text.
 | 
			
		||||
  Remove unnecessary cmd arg from target_*monitor_events().
 | 
			
		||||
  Add private variable to dmeventd shared library interface.
 | 
			
		||||
  Long-lived processes write out persistent dev cache in refresh_toolcontext().
 | 
			
		||||
  Fix refresh_toolcontext() always to wipe persistent device filter cache.
 | 
			
		||||
  Add is_long_lived to toolcontext.
 | 
			
		||||
  Add --clustered to man pages.
 | 
			
		||||
  Streamline dm_report_field_* interface.
 | 
			
		||||
  Change remaining dmeventd terminology 'register' to 'monitor'.
 | 
			
		||||
  Update reporting man pages.
 | 
			
		||||
  No longer necessary to specify alignment type for report fields.
 | 
			
		||||
 | 
			
		||||
Version 2.02.19 - 17th January 2007
 | 
			
		||||
===================================
 | 
			
		||||
  Fix a segfault if an empty config file section encountered.
 | 
			
		||||
  Move basic reporting functions into libdevmapper.
 | 
			
		||||
  Fix partition table processing after sparc changes (2.02.16).
 | 
			
		||||
  Fix cmdline PE range processing segfault (2.02.13).
 | 
			
		||||
  Some libdevmapper-event interface changes.
 | 
			
		||||
  Report dmeventd mirror monitoring status.
 | 
			
		||||
  Fix dmeventd mirror status line processing.
 | 
			
		||||
 | 
			
		||||
Version 2.02.18 - 11th January 2007
 | 
			
		||||
===================================
 | 
			
		||||
  Revised libdevmapper-event interface for dmeventd.
 | 
			
		||||
  Remove dmeventd mirror status line word limit.
 | 
			
		||||
  Use CFLAGS when linking so mixed sparc builds can supply -m64.
 | 
			
		||||
  Prevent permission changes on active mirrors.
 | 
			
		||||
  Print warning instead of error message if lvconvert cannot zero volume.
 | 
			
		||||
  Add snapshot options to lvconvert man page.
 | 
			
		||||
  dumpconfig accepts a list of configuration variables to display.
 | 
			
		||||
  Change dumpconfig to use --file to redirect output to a file.
 | 
			
		||||
  Avoid vgreduce error when mirror code removes the log LV.
 | 
			
		||||
  Remove 3 redundant AC_MSG_RESULTs from configure.in.
 | 
			
		||||
  Free memory in _raw_read_mda_header() error paths.
 | 
			
		||||
  Fix ambiguous vgsplit error message for split LV.
 | 
			
		||||
  Fix lvextend man page typo.
 | 
			
		||||
  Add configure --with-dmdir to compile against a device-mapper source tree.
 | 
			
		||||
  Use no flush suspending for mirrors.
 | 
			
		||||
  Add dmeventd_mirror register_mutex, tidy initialisation & add memlock.
 | 
			
		||||
  Fix create mirror with name longer than 22 chars.
 | 
			
		||||
  Fix some activate.c prototypes when compiled without devmapper.
 | 
			
		||||
  Fix dmeventd mirror to cope if monitored device disappears.
 | 
			
		||||
 | 
			
		||||
Version 2.02.17 - 14th December 2006
 | 
			
		||||
====================================
 | 
			
		||||
  Add missing pvremove error message when device doesn't exist.
 | 
			
		||||
  When lvconvert allocates a mirror log, respect parallel area constraints.
 | 
			
		||||
  Use loop to iterate through the now-ordered policy list in _allocate().
 | 
			
		||||
  Check for failure to allocate just the mirror log.
 | 
			
		||||
  Introduce calc_area_multiple().
 | 
			
		||||
  Support mirror log allocation when there is only one PV: area_count now 0.
 | 
			
		||||
  Fix detection of smallest area in _alloc_parallel_area() for cling policy.
 | 
			
		||||
  Add manpage entry for clvmd -T
 | 
			
		||||
  Fix gulm operation of clvmd, including a hang when doing lvchange -aey
 | 
			
		||||
  Fix hang in clvmd if a pre-command failed.
 | 
			
		||||
 | 
			
		||||
Version 2.02.16 - 1st December 2006
 | 
			
		||||
===================================
 | 
			
		||||
  Fix VG clustered read locks to use PR not CR.
 | 
			
		||||
  Adjust some alignments for ia64/sparc.
 | 
			
		||||
  Fix mirror segment removal to use temporary error segment.
 | 
			
		||||
  Always compile debug logging into clvmd.
 | 
			
		||||
  Add startup timeout to RHEL4 clvmd startup script.
 | 
			
		||||
  Add -T (startup timeout) switch to clvmd.
 | 
			
		||||
  Improve lvm_dump.sh robustness.
 | 
			
		||||
  Update lvm2create_initrd to support gentoo.
 | 
			
		||||
 | 
			
		||||
Version 2.02.15 - 21st November 2006
 | 
			
		||||
====================================
 | 
			
		||||
  Fix clvmd_init_rhel4 line truncation (2.02.14).
 | 
			
		||||
  Install lvmdump by default.
 | 
			
		||||
  Fix check for snapshot module when activating snapshot.
 | 
			
		||||
  Fix pvremove error path for case when PV is in use.
 | 
			
		||||
  Warn if certain duplicate config file entries are seen.
 | 
			
		||||
  Enhance lvm_dump.sh for sysreport integration and add man page.
 | 
			
		||||
  Fix --autobackup argument which could never disable backups.
 | 
			
		||||
  Fix a label_verify error path.
 | 
			
		||||
 | 
			
		||||
Version 2.02.14 - 10th November 2006
 | 
			
		||||
====================================
 | 
			
		||||
  Fix adjusted_mirror_region_size() to handle 64-bit size.
 | 
			
		||||
  Add some missing bounds checks on 32-bit extent counters.
 | 
			
		||||
  Add Petabyte and Exabyte support.
 | 
			
		||||
  Fix lvcreate error message when 0 extents requested.
 | 
			
		||||
  lvremove man page: volumes must be cluster inactive before being removed.
 | 
			
		||||
  Protect .cache manipulations with fcntl locking.
 | 
			
		||||
  Change .cache timestamp comparisons to use ctime.
 | 
			
		||||
  Fix mirror log LV writing to set all bits in whole LV.
 | 
			
		||||
  Fix clustered VG detection and default runlevels in clvmd_init_rhel4.
 | 
			
		||||
  Fix high-level free space check for partial allocations.
 | 
			
		||||
 | 
			
		||||
Version 2.02.13 - 27th October 2006
 | 
			
		||||
===================================
 | 
			
		||||
  Add couple of missing files to tools/Makefile CLEAN_TARGETS.
 | 
			
		||||
  When adding snapshot leave cow LV mapped device active after zeroing.
 | 
			
		||||
  Fix a clvmd debug message.
 | 
			
		||||
  Add dev_flush() to set_lv().
 | 
			
		||||
  Add lvchange --resync.
 | 
			
		||||
  Perform high-level free space check before each allocation attempt.
 | 
			
		||||
  Don't allow a node to remove an LV that's exclusively active on anther node.
 | 
			
		||||
  Cope if same PV is included more than once in cmdline PE range list.
 | 
			
		||||
  Set PV size to current device size if it is found to be zero.
 | 
			
		||||
  Add segment parameter to target_present functions.
 | 
			
		||||
 | 
			
		||||
Version 2.02.12 - 16th October 2006
 | 
			
		||||
===================================
 | 
			
		||||
  Fix pvdisplay to use vg_read() for non-orphans.
 | 
			
		||||
  Fall back to internal locking if external locking lib is missing or fails.
 | 
			
		||||
  Retain activation state after changing LV minor number with --force.
 | 
			
		||||
  Propagate clustered flag in vgsplit and require resizeable flag.
 | 
			
		||||
 | 
			
		||||
Version 2.02.11 - 12th October 2006
 | 
			
		||||
===================================
 | 
			
		||||
  Add clvmd function to return the cluster name. not used by LVM yet.
 | 
			
		||||
  Add cling allocation policy.
 | 
			
		||||
  Change _check_contiguous() to use _for_each_pv().
 | 
			
		||||
  Extend _for_each_pv() to allow termination without error.
 | 
			
		||||
  Abstract _is_contiguous().
 | 
			
		||||
  Remove duplicated pv arg from _check_contiguous().
 | 
			
		||||
  Accept regionsize with lvconvert.
 | 
			
		||||
  Add report columns with underscore before field names ending 'size'.
 | 
			
		||||
  Correct regionsize default on lvcreate man page (MB).
 | 
			
		||||
  Fix clvmd bug that could cause it to die when a node with a long name crashed.
 | 
			
		||||
  Add device size to text metadata.
 | 
			
		||||
  Fix format_text mda_setup pv->size and pv_setup pe_count calculations.
 | 
			
		||||
  Fix _for_each_pv() for mirror with core log.
 | 
			
		||||
  Add lvm_dump.sh script to create a tarball of debugging info from a system.
 | 
			
		||||
  Capture error messages in clvmd and pass them back to the user.
 | 
			
		||||
  Remove unused #defines from filter-md.c.
 | 
			
		||||
  Make clvmd restart init script wait until clvmd has died before starting it.
 | 
			
		||||
  Add -R to clvmd which tells running clvmds to reload their device cache.
 | 
			
		||||
  Add LV column to reports listing kernel modules needed for activation.
 | 
			
		||||
  Show available fields if report given invalid field. (e.g. lvs -o list)
 | 
			
		||||
  Add timestamp functions with --disable-realtime configure option.
 | 
			
		||||
  Add %VG, %LV and %FREE suffices to lvcreate/lvresize --extents arg.
 | 
			
		||||
  Fix two potential NULL pointer derefs in error cases in vg_read().
 | 
			
		||||
  Separate --enable-cluster from locking lib options in lvmconf.sh.
 | 
			
		||||
  Add a missing comma in lvcreate man page.
 | 
			
		||||
 | 
			
		||||
Version 2.02.10 - 19th September 2006
 | 
			
		||||
=====================================
 | 
			
		||||
  Fix lvconvert mirror change case detection logic.
 | 
			
		||||
  Fix mirror log detachment so it correctly becomes a standalone LV.
 | 
			
		||||
  Extend _check_contiguous() to detect single-area LVs.
 | 
			
		||||
  Include mirror log (untested) in _for_each_pv() processing.
 | 
			
		||||
  Use MIRROR_LOG_SIZE constant.
 | 
			
		||||
  Remove struct seg_pvs from _for_each_pv() to generalise.
 | 
			
		||||
  Avoid adding duplicates to list of parallel PVs to avoid.
 | 
			
		||||
  Fix several incorrect comparisons in parallel area avoidance code.
 | 
			
		||||
  Fix segment lengths when flattening existing parallel areas.
 | 
			
		||||
  Log existing parallel areas prior to allocation.
 | 
			
		||||
  Fix mirror log creation when activation disabled.
 | 
			
		||||
  Don't attempt automatic recovery without proper locking.
 | 
			
		||||
  When using local file locking, skip clustered VGs.
 | 
			
		||||
  Add fallback_to_clustered_locking and fallback_to_local_locking parameters.
 | 
			
		||||
  lvm.static uses built-in cluster locking instead of external locking.
 | 
			
		||||
  Don't attempt to load shared libraries if built statically.
 | 
			
		||||
  Change default locking_lib to liblvm2clusterlock.so.
 | 
			
		||||
  Add skip_dev_dir() to process command line VGs.
 | 
			
		||||
  Stop clvmd complaining about nodes that have left the cluster.
 | 
			
		||||
  Move lvm_snprintf(), split_words() and split_dm_name() into libdevmapper.
 | 
			
		||||
  Add lvconvert man page.
 | 
			
		||||
  Add mirror options to man pages.
 | 
			
		||||
  Prevent mirror renames.
 | 
			
		||||
  Move CMDLIB code into separate file and record whether static build.
 | 
			
		||||
 | 
			
		||||
Version 2.02.09 - 17th August 2006
 | 
			
		||||
==================================
 | 
			
		||||
  Fix PE_ALIGN for pagesize over 32KB.
 | 
			
		||||
  Separate out LVM1_PE_ALIGN and pe_align().
 | 
			
		||||
  Add lvm_getpagesize wrapper.
 | 
			
		||||
  Add --maxphysicalvolumes to vgchange.
 | 
			
		||||
 | 
			
		||||
Version 2.02.08 - 15th August 2006
 | 
			
		||||
==================================
 | 
			
		||||
  Add checks for duplicate LV name, lvid and PV id before writing metadata.
 | 
			
		||||
  Report all sanity check failures, not just the first.
 | 
			
		||||
  Fix missing lockfs on first snapshot creation.
 | 
			
		||||
  Add unreliable --trustcache option to reporting commands.
 | 
			
		||||
  Fix locking for mimage removal.
 | 
			
		||||
  Fix clvmd_init_rhel4 'status' exit code.
 | 
			
		||||
 | 
			
		||||
Version 2.02.07 - 17th July 2006
 | 
			
		||||
================================
 | 
			
		||||
  Fix activation logic in lvchange --persistent.
 | 
			
		||||
  Don't ignore persistent minor numbers when activating.
 | 
			
		||||
  Use RTLD_GLOBAL when loading shared libraries.
 | 
			
		||||
  Add some forgotten memlock checks to _vg_read to protect against full scans.
 | 
			
		||||
  Add mutex to dmeventd_mirror to avoid concurrent execution.
 | 
			
		||||
  Fix vgreduce --removemissing to return success if VG is already consistent.
 | 
			
		||||
  Fix return code if VG specified on command line is not found.
 | 
			
		||||
  Fix PV tools to include orphaned PVs in default output again.
 | 
			
		||||
  Fixed unaligned access when using clvm.
 | 
			
		||||
  Fix an extra dev_close in a label_read error path.
 | 
			
		||||
  Append patches to commit emails.
 | 
			
		||||
  Fix target_register_events args.
 | 
			
		||||
  Prevent snapshots of mirrors.
 | 
			
		||||
  Add DISTCLEAN_TARGETS to make template for configure.h.
 | 
			
		||||
  More fixes to error paths.
 | 
			
		||||
  Fix lvcreate corelog validation.
 | 
			
		||||
  Add --config for overriding most config file settings from cmdline.
 | 
			
		||||
  Quote arguments when printing command line.
 | 
			
		||||
  Remove linefeed from 'initialising logging' message.
 | 
			
		||||
  Add 'Completed' debug message.
 | 
			
		||||
  Don't attempt library exit after reloading config files.
 | 
			
		||||
  Always compile with libdevmapper, even if device-mapper is disabled.
 | 
			
		||||
 | 
			
		||||
Version 2.02.06 - 12th May 2006
 | 
			
		||||
===============================
 | 
			
		||||
  Propagate --monitor around cluster.
 | 
			
		||||
  Add --monitor to vgcreate and lvcreate to control dmeventd registration.
 | 
			
		||||
  Filter LCK_NONBLOCK in clvmd lock_vg.
 | 
			
		||||
  Add --nosync to lvcreate with LV flag NOTSYNCED.
 | 
			
		||||
  Use mirror's uuid for a core log.
 | 
			
		||||
  Add mirror log fault-handling policy.
 | 
			
		||||
  Improve mirror warning messages and tidy dmeventd syslog output.
 | 
			
		||||
  Propagate nosync flag around cluster.
 | 
			
		||||
  Allow vgreduce to handle mirror log failures.
 | 
			
		||||
  Add --corelog to lvcreate and lvconvert.
 | 
			
		||||
  Create a log header for replacement in-sync mirror log.
 | 
			
		||||
  Use set_lv() and dev_set() to wipe sections of devices.
 | 
			
		||||
  Add mirror_in_sync() flag to avoid unnecessary resync on activation.
 | 
			
		||||
  Add mirror_library description to example.conf.
 | 
			
		||||
  Fix uuid_from_num() buffer overrun.
 | 
			
		||||
  Make SIZE_SHORT the default for display_size().
 | 
			
		||||
  Fix some memory leaks in error paths found by coverity.
 | 
			
		||||
  Use C99 struct initialisers.
 | 
			
		||||
  Move DEFS into configure.h.
 | 
			
		||||
  Clean-ups to remove miscellaneous compiler warnings.
 | 
			
		||||
  Improve stripe size validation.
 | 
			
		||||
  Increase maximum stripe size limit to physical extent size for lvm2 metadata.
 | 
			
		||||
  Fix activation code to check for pre-existing mirror logs.
 | 
			
		||||
  Tighten region size validation.
 | 
			
		||||
  Ignore empty strings in config files.
 | 
			
		||||
  Require non-zero regionsize and document parameter on lvcreate man page.
 | 
			
		||||
  Invalidate cache if composition of VG changed externally.
 | 
			
		||||
 | 
			
		||||
Version 2.02.05 - 21st April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  Fix vgid string termination in recent cache code.
 | 
			
		||||
 | 
			
		||||
Version 2.02.04 - 19th April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  Check for libsepol.
 | 
			
		||||
  Add some cflow & scope support.
 | 
			
		||||
  Separate out DEFS from CFLAGS.
 | 
			
		||||
  Remove inlines and use unique function names.
 | 
			
		||||
 | 
			
		||||
Version 2.02.03 - 14th April 2006
 | 
			
		||||
=================================
 | 
			
		||||
  vgrename accepts vgid and exported VG.
 | 
			
		||||
  Add --partial to pvs.
 | 
			
		||||
  When choosing between identically-named VGs, also consider creation_host.
 | 
			
		||||
  Provide total log suppression with 2.
 | 
			
		||||
  Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
 | 
			
		||||
  Add vgid to struct physical_volume and pass with vg_name to some functions.
 | 
			
		||||
  If two or more VGs are found with the same name, use one that is not exported.
 | 
			
		||||
  Whenever vgname is captured, also capture vgid and whether exported.
 | 
			
		||||
  Remove an incorrect unlock_vg() from process_each_lv().
 | 
			
		||||
  Update extent size information in vgchange and vgcreate man pages.
 | 
			
		||||
  Introduce origin_from_cow() and lv_is_visible().
 | 
			
		||||
  pvremove without -f now fails if there's no PV label.
 | 
			
		||||
  Support lvconvert -s.
 | 
			
		||||
  Suppress locking library load failure message if --ignorelockingfailure.
 | 
			
		||||
  Propagate partial mode around cluster.
 | 
			
		||||
  Fix archive file expiration.
 | 
			
		||||
  Fix dmeventd build.
 | 
			
		||||
  clvmd now uses libcman rather than cman ioctls.
 | 
			
		||||
  clvmd will allow new cman to shutdown on request.
 | 
			
		||||
 | 
			
		||||
Version 2.02.02 - 7th February 2006
 | 
			
		||||
===================================
 | 
			
		||||
  Add %.so: %.a make template rule.
 | 
			
		||||
  Switchover library building to use LIB_SUFFIX.
 | 
			
		||||
  Only do lockfs filesystem sync when suspending snapshots.
 | 
			
		||||
  Always print warning if activation is disabled.
 | 
			
		||||
  vgreduce removes mirror images.
 | 
			
		||||
  Add --mirrorsonly to vgreduce.
 | 
			
		||||
  vgreduce replaces active LVs with error segment before removing them.
 | 
			
		||||
  Set block_on_error parameter if available.
 | 
			
		||||
  Add target_version.
 | 
			
		||||
  Add details to format1 'Invalid LV in extent map' error message.
 | 
			
		||||
  Fix lvscan snapshot full display.
 | 
			
		||||
  Bring lvdisplay man page example into line.
 | 
			
		||||
  Add mirror dmeventd library.
 | 
			
		||||
  Add some activation logic to remove_mirror_images().
 | 
			
		||||
  lvconvert can remove specified PVs from a mirror.
 | 
			
		||||
  lvconvert turns an existing LV into a mirror.
 | 
			
		||||
  Allow signed mirrors arguments.
 | 
			
		||||
  Move create_mirror_log() into toollib.
 | 
			
		||||
  Determine parallel PVs to avoid with ALLOC_NORMAL allocation.
 | 
			
		||||
  Fix lv_empty.
 | 
			
		||||
 | 
			
		||||
Version 2.02.01 - 23rd November 2005
 | 
			
		||||
====================================
 | 
			
		||||
  Fix lvdisplay cmdline to accept snapshots.
 | 
			
		||||
  Fix open RO->RW promotion.
 | 
			
		||||
  Fix missing vg_revert in lvcreate error path.
 | 
			
		||||
 | 
			
		||||
Version 2.02.00 - 10th November 2005
 | 
			
		||||
====================================
 | 
			
		||||
  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.
 | 
			
		||||
@@ -503,7 +1017,7 @@ Some bug fixes & minor enhancements, including:
 | 
			
		||||
 | 
			
		||||
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 
 | 
			
		||||
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.
 | 
			
		||||
@@ -513,7 +1027,7 @@ Wednesday 30th April 2003
 | 
			
		||||
A pvmove implementation is now available for the new metadata format.
 | 
			
		||||
 | 
			
		||||
When running a command that allocates space (e.g. lvcreate), you can now
 | 
			
		||||
restrict not only which disk(s) may be used but also the Physical Extents 
 | 
			
		||||
restrict not only which disk(s) may be used but also the Physical Extents
 | 
			
		||||
on those disks.  e.g. lvcreate -L 10 vg1 /dev/hda6:1000-2000:3000-4000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -525,12 +1039,12 @@ The new format of LVM metadata is ready for you to test!
 | 
			
		||||
  It's more compact and supports transactional changes and replication.
 | 
			
		||||
  Should things go wrong on a system, it's human-readable (and editable).
 | 
			
		||||
 | 
			
		||||
Please report any problems you find to the mailing list, 
 | 
			
		||||
Please report any problems you find to the mailing list,
 | 
			
		||||
linux-lvm@sistina.com.  The software has NOT yet been thoroughly
 | 
			
		||||
tested and so quite possibly there'll still be some bugs in it.
 | 
			
		||||
Be aware of the disclaimer in the COPYING file.
 | 
			
		||||
 | 
			
		||||
While testing, we recommend turning logging on in the configuration file 
 | 
			
		||||
While testing, we recommend turning logging on in the configuration file
 | 
			
		||||
to provide us with diagnostic information:
 | 
			
		||||
  log {
 | 
			
		||||
        file="/tmp/lvm2.log"
 | 
			
		||||
@@ -541,7 +1055,7 @@ to provide us with diagnostic information:
 | 
			
		||||
You should schedule regular backups of your configuration file and
 | 
			
		||||
metadata backups and archives (normally kept under /etc/lvm).
 | 
			
		||||
 | 
			
		||||
Please read docs/example.conf and "man lvm.conf" to find out more about 
 | 
			
		||||
Please read docs/example.conf and "man lvm.conf" to find out more about
 | 
			
		||||
the configuration file.
 | 
			
		||||
 | 
			
		||||
To convert an existing volume group called vg1 to the new format using
 | 
			
		||||
@@ -570,7 +1084,7 @@ first segment could have 3 stripes while the second segment has just 2.
 | 
			
		||||
LVM2 maintains a backup of the current metadata for each volume group
 | 
			
		||||
in /etc/lvm/backup, and puts copies of previous versions in
 | 
			
		||||
/etc/lvm/archive.  "vgcfgbackup" and "vgcfgrestore" can be used to
 | 
			
		||||
create and restore from these files.  If you fully understand what 
 | 
			
		||||
create and restore from these files.  If you fully understand what
 | 
			
		||||
you're doing, metadata can be changed by editing a copy of a current
 | 
			
		||||
backup file and using vgcfgrestore to reload it.
 | 
			
		||||
 | 
			
		||||
@@ -587,8 +1101,8 @@ What's not finished?
 | 
			
		||||
The internal cache.  If you turn on debugging output you'll see lots of
 | 
			
		||||
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 
 | 
			
		||||
--test sometimes causes a command to fail (e.g. vgconvert --test) even
 | 
			
		||||
though the real command would work: again, fixing this is waiting for
 | 
			
		||||
the work on the cache.
 | 
			
		||||
 | 
			
		||||
Several of the tools do not yet contain the logic to handle full
 | 
			
		||||
@@ -601,4 +1115,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!
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										182
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							
							
						
						
									
										182
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							@@ -1,4 +1,184 @@
 | 
			
		||||
Version 1.02.00 - 
 | 
			
		||||
Version 1.02.23 - 
 | 
			
		||||
==================================
 | 
			
		||||
  Add --readahead to dmsetup.
 | 
			
		||||
  Add external read_ahead library functions and DM_READ_AHEAD_* definitions.
 | 
			
		||||
  Fix double free in a libdevmapper-event error path.
 | 
			
		||||
  Fix configure --with-dmeventd-path substitution.
 | 
			
		||||
  Allow $DM_DEV_DIR envvar to override default of "/dev".
 | 
			
		||||
  Create e.g., libdevmapper.so.1.02, in build dir alongside the .so file.
 | 
			
		||||
  Avoid static link failure with some SELinux libraries.
 | 
			
		||||
  Remove obsolete dmfs code from tree and update INSTALL.
 | 
			
		||||
 | 
			
		||||
Version 1.02.22 - 21st August 2007
 | 
			
		||||
==================================
 | 
			
		||||
  Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
 | 
			
		||||
  Update to use autoconf 2.61, while still supporting 2.57.
 | 
			
		||||
  Avoid repeated dm_task free on some dm_event_get_registered_device errors.
 | 
			
		||||
  Introduce log_sys_* macros from LVM2.
 | 
			
		||||
  Export dm_fclose and dm_create_dir; remove libdm-file.h.
 | 
			
		||||
  Don't log EROFS mkdir failures in _create_dir_recursive (for LVM2).
 | 
			
		||||
  Add fclose wrapper dm_fclose that catches write failures (using ferror).
 | 
			
		||||
 | 
			
		||||
Version 1.02.21 - 13th July 2007
 | 
			
		||||
================================
 | 
			
		||||
  Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout.
 | 
			
		||||
  Fix dmsetup -o devno string termination. (1.02.20) 
 | 
			
		||||
 | 
			
		||||
Version 1.02.20 - 15th June 2007
 | 
			
		||||
================================
 | 
			
		||||
  Fix default dmsetup report buffering and add --unbuffered.
 | 
			
		||||
  Add tree-based and dependency fields to dmsetup reports.
 | 
			
		||||
 | 
			
		||||
Version 1.02.19 - 27th April 2007
 | 
			
		||||
=================================
 | 
			
		||||
  Standardise protective include file #defines.
 | 
			
		||||
  Add regex functions to library.
 | 
			
		||||
  Avoid trailing separator in reports when there are hidden sort fields.
 | 
			
		||||
  Fix segfault in 'dmsetup status' without --showkeys against crypt target.
 | 
			
		||||
  Deal with some more compiler warnings.
 | 
			
		||||
  Introduce _add_field() and _is_same_field() to libdm-report.c.
 | 
			
		||||
  Fix some libdevmapper-event and dmeventd memory leaks.
 | 
			
		||||
  Remove unnecessary memset() return value checks.
 | 
			
		||||
  Fix a few leaks in reporting error paths. [1.02.15+]
 | 
			
		||||
 | 
			
		||||
Version 1.02.18 - 13th February 2007
 | 
			
		||||
====================================
 | 
			
		||||
  Improve dmeventd messaging protocol: drain pipe and tag messages.
 | 
			
		||||
 | 
			
		||||
Version 1.02.17 - 29th January 2007
 | 
			
		||||
===================================
 | 
			
		||||
  Add recent reporting options to dmsetup man page.
 | 
			
		||||
  Revise some report fields names.
 | 
			
		||||
  Add dmsetup 'help' command and update usage text.
 | 
			
		||||
  Use fixed-size fields in report interface and reorder.
 | 
			
		||||
 | 
			
		||||
Version 1.02.16 - 25th January 2007
 | 
			
		||||
===================================
 | 
			
		||||
  Add some missing close() and fclose() return value checks.
 | 
			
		||||
  Migrate dmsetup column-based output over to new libdevmapper report framework.
 | 
			
		||||
  Add descriptions to reporting field definitions.
 | 
			
		||||
  Add a dso-private variable to dmeventd dso interface.
 | 
			
		||||
  Add dm_event_handler_[gs]et_timeout functions.
 | 
			
		||||
  Streamline dm_report_field_* interface.
 | 
			
		||||
  Add cmdline debug & version options to dmeventd.
 | 
			
		||||
  Add DM_LIB_VERSION definition to configure.h.
 | 
			
		||||
  Suppress 'Unrecognised field' error if report field is 'help'.
 | 
			
		||||
  Add --separator and --sort to dmsetup (unused).
 | 
			
		||||
  Make alignment flag optional when specifying report fields.
 | 
			
		||||
 | 
			
		||||
Version 1.02.15 - 17th January 2007
 | 
			
		||||
===================================
 | 
			
		||||
  Add basic reporting functions to libdevmapper.
 | 
			
		||||
  Fix a malloc error path in dmsetup message.
 | 
			
		||||
  More libdevmapper-event interface changes and fixes.
 | 
			
		||||
  Rename dm_saprintf() to dm_asprintf().
 | 
			
		||||
  Report error if NULL pointer is supplied to dm_strdup_aux().
 | 
			
		||||
  Reinstate dm_event_get_registered_device.
 | 
			
		||||
 | 
			
		||||
Version 1.02.14 - 11th January 2007
 | 
			
		||||
===================================
 | 
			
		||||
  Add dm_saprintf().
 | 
			
		||||
  Use CFLAGS when linking so mixed sparc builds can supply -m64.
 | 
			
		||||
  Add dm_tree_use_no_flush_suspend().
 | 
			
		||||
  Lots of dmevent changes including revised interface.
 | 
			
		||||
  Export dm_basename().
 | 
			
		||||
  Cope with a trailing space when comparing tables prior to possible reload.
 | 
			
		||||
  Fix dmeventd to cope if monitored device disappears.
 | 
			
		||||
 | 
			
		||||
Version 1.02.13 - 28 Nov 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Update dmsetup man page (setgeometry & message).
 | 
			
		||||
  Fix dmsetup free after getline with debug.
 | 
			
		||||
  Suppress encryption key in 'dmsetup table' output unless --showkeys supplied.
 | 
			
		||||
 | 
			
		||||
Version 1.02.12 - 13 Oct 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Avoid deptree attempting to suspend a device that's already suspended.
 | 
			
		||||
 | 
			
		||||
Version 1.02.11 -  12 Oct 2006
 | 
			
		||||
==============================
 | 
			
		||||
  Add suspend noflush support.
 | 
			
		||||
  Add basic dmsetup loop support.
 | 
			
		||||
  Switch dmsetup to use dm_malloc and dm_free.
 | 
			
		||||
 | 
			
		||||
Version 1.02.10 - 19 Sep 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
 | 
			
		||||
  Reorder mm bounds_check code to reduce window for a dmeventd race.
 | 
			
		||||
 | 
			
		||||
Version 1.02.09 - 15 Aug 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Add --table argument to dmsetup for a one-line table.
 | 
			
		||||
  Abort if errors are found during cmdline option processing.
 | 
			
		||||
  Add lockfs indicator to debug output.
 | 
			
		||||
 | 
			
		||||
Version 1.02.08 - 17 July 2006
 | 
			
		||||
==============================
 | 
			
		||||
  Append full patch to check in emails.
 | 
			
		||||
  Avoid duplicate dmeventd subdir with 'make distclean'.
 | 
			
		||||
  Update dmsetup man page.
 | 
			
		||||
  Add --force to dmsetup remove* to load error target.
 | 
			
		||||
  dmsetup remove_all also performs mknodes.
 | 
			
		||||
  Don't suppress identical table reloads if permission changes.
 | 
			
		||||
  Fix corelog segment line.
 | 
			
		||||
  Suppress some compiler warnings.
 | 
			
		||||
 | 
			
		||||
Version 1.02.07 - 11 May 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
 | 
			
		||||
  Avoid a dmeventd compiler warning.
 | 
			
		||||
 | 
			
		||||
Version 1.02.06 - 10 May 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Move DEFS into configure.h.
 | 
			
		||||
  Fix leaks in error paths found by coverity.
 | 
			
		||||
  Remove dmsetup line buffer limitation.
 | 
			
		||||
 | 
			
		||||
Version 1.02.05 - 19 Apr 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Separate install_include target in makefiles.
 | 
			
		||||
  Separate out DEFS from CFLAGS.
 | 
			
		||||
  Support pkg-config.
 | 
			
		||||
  Check for libsepol.
 | 
			
		||||
 | 
			
		||||
Version 1.02.04 - 14 Apr 2006
 | 
			
		||||
=============================
 | 
			
		||||
  Bring dmsetup man page up-to-date.
 | 
			
		||||
  Use name-based device refs if kernel doesn't support device number refs.
 | 
			
		||||
  Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
 | 
			
		||||
  If _create_and_load_v4 fails part way through, revert the creation.
 | 
			
		||||
  dmeventd thread/fifo fixes.
 | 
			
		||||
  Add file & line to dm_strdup_aux().
 | 
			
		||||
  Add setgeometry.
 | 
			
		||||
 | 
			
		||||
Version 1.02.03 - 7 Feb 2006
 | 
			
		||||
============================
 | 
			
		||||
  Add exported functions to set uid, gid and mode.
 | 
			
		||||
  Rename _log to dm_log and export.
 | 
			
		||||
  Add dm_tree_skip_lockfs.
 | 
			
		||||
  Fix dm_strdup debug definition.
 | 
			
		||||
  Fix hash function to avoid using a negative array offset.
 | 
			
		||||
  Don't inline _find in hash.c and tidy signed/unsigned etc.
 | 
			
		||||
  Fix libdevmapper.h #endif.
 | 
			
		||||
  Fix dmsetup version driver version.
 | 
			
		||||
  Add sync, nosync and block_on_error mirror log parameters.
 | 
			
		||||
  Add hweight32.
 | 
			
		||||
  Fix dmeventd build.
 | 
			
		||||
 | 
			
		||||
Version 1.02.02 - 2 Dec 2005
 | 
			
		||||
============================
 | 
			
		||||
  dmeventd added.
 | 
			
		||||
  Export dm_task_update_nodes.
 | 
			
		||||
  Use names instead of numbers in messages when ioctls fail.
 | 
			
		||||
 | 
			
		||||
Version 1.02.01 - 23 Nov 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Resume snapshot-origins last.
 | 
			
		||||
  Drop leading zeros from dm_format_dev.
 | 
			
		||||
  Suppress attempt to reload identical table.
 | 
			
		||||
  Additional LVM- prefix matching for transitional period.
 | 
			
		||||
 | 
			
		||||
Version 1.02.00 - 10 Nov 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Added activation functions to library.
 | 
			
		||||
  Added return macros.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										650
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										650
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										224
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										224
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,10 @@
 | 
			
		||||
#! /bin/sh
 | 
			
		||||
# Configuration validation subroutine script.
 | 
			
		||||
#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 | 
			
		||||
#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 | 
			
		||||
#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
 | 
			
		||||
#   Inc.
 | 
			
		||||
 | 
			
		||||
timestamp='2003-06-17'
 | 
			
		||||
timestamp='2006-09-20'
 | 
			
		||||
 | 
			
		||||
# This file is (in principle) common to ALL GNU software.
 | 
			
		||||
# The presence of a machine in this file suggests that SOME GNU software
 | 
			
		||||
@@ -21,14 +22,15 @@ timestamp='2003-06-17'
 | 
			
		||||
#
 | 
			
		||||
# 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.
 | 
			
		||||
 | 
			
		||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
 | 
			
		||||
# 02110-1301, USA.
 | 
			
		||||
#
 | 
			
		||||
# As a special exception to the GNU General Public License, if you
 | 
			
		||||
# distribute this file as part of a program that contains a
 | 
			
		||||
# 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>.  Submit a context
 | 
			
		||||
# diff and a properly formatted ChangeLog entry.
 | 
			
		||||
#
 | 
			
		||||
@@ -70,7 +72,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 | 
			
		||||
version="\
 | 
			
		||||
GNU config.sub ($timestamp)
 | 
			
		||||
 | 
			
		||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
 | 
			
		||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
 | 
			
		||||
Free Software Foundation, Inc.
 | 
			
		||||
 | 
			
		||||
This is free software; see the source for copying conditions.  There is NO
 | 
			
		||||
@@ -83,11 +85,11 @@ Try \`$me --help' for more information."
 | 
			
		||||
while test $# -gt 0 ; do
 | 
			
		||||
  case $1 in
 | 
			
		||||
    --time-stamp | --time* | -t )
 | 
			
		||||
       echo "$timestamp" ; exit 0 ;;
 | 
			
		||||
       echo "$timestamp" ; exit ;;
 | 
			
		||||
    --version | -v )
 | 
			
		||||
       echo "$version" ; exit 0 ;;
 | 
			
		||||
       echo "$version" ; exit ;;
 | 
			
		||||
    --help | --h* | -h )
 | 
			
		||||
       echo "$usage"; exit 0 ;;
 | 
			
		||||
       echo "$usage"; exit ;;
 | 
			
		||||
    -- )     # Stop option processing
 | 
			
		||||
       shift; break ;;
 | 
			
		||||
    - )	# Use stdin as input.
 | 
			
		||||
@@ -99,7 +101,7 @@ while test $# -gt 0 ; do
 | 
			
		||||
    *local*)
 | 
			
		||||
       # First pass through any local machine types.
 | 
			
		||||
       echo $1
 | 
			
		||||
       exit 0;;
 | 
			
		||||
       exit ;;
 | 
			
		||||
 | 
			
		||||
    * )
 | 
			
		||||
       break ;;
 | 
			
		||||
@@ -118,7 +120,9 @@ 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* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
 | 
			
		||||
  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
 | 
			
		||||
  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
 | 
			
		||||
  storm-chaos* | os2-emx* | rtmk-nova*)
 | 
			
		||||
    os=-$maybe_os
 | 
			
		||||
    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
 | 
			
		||||
    ;;
 | 
			
		||||
@@ -144,7 +148,7 @@ case $os in
 | 
			
		||||
	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 | 
			
		||||
	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 | 
			
		||||
	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
 | 
			
		||||
	-apple | -axis)
 | 
			
		||||
	-apple | -axis | -knuth | -cray)
 | 
			
		||||
		os=
 | 
			
		||||
		basic_machine=$1
 | 
			
		||||
		;;
 | 
			
		||||
@@ -169,6 +173,10 @@ case $os in
 | 
			
		||||
	-hiux*)
 | 
			
		||||
		os=-hiuxwe2
 | 
			
		||||
		;;
 | 
			
		||||
	-sco6)
 | 
			
		||||
		os=-sco5v6
 | 
			
		||||
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 | 
			
		||||
		;;
 | 
			
		||||
	-sco5)
 | 
			
		||||
		os=-sco3.2v5
 | 
			
		||||
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 | 
			
		||||
@@ -185,6 +193,10 @@ case $os in
 | 
			
		||||
		# Don't forget version if it is 3.2v4 or newer.
 | 
			
		||||
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 | 
			
		||||
		;;
 | 
			
		||||
	-sco5v6*)
 | 
			
		||||
		# Don't forget version if it is 3.2v4 or newer.
 | 
			
		||||
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 | 
			
		||||
		;;
 | 
			
		||||
	-sco*)
 | 
			
		||||
		os=-sco3.2v2
 | 
			
		||||
		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 | 
			
		||||
@@ -228,14 +240,17 @@ case $basic_machine in
 | 
			
		||||
	| 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 \
 | 
			
		||||
	| am33_2.0 \
 | 
			
		||||
	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
 | 
			
		||||
	| bfin \
 | 
			
		||||
	| c4x | clipper \
 | 
			
		||||
	| 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 \
 | 
			
		||||
	| ip2k | iq2000 \
 | 
			
		||||
	| m32c | m32r | m32rle | m68000 | m68k | m88k \
 | 
			
		||||
	| maxq | mb | microblaze | mcore \
 | 
			
		||||
	| mips | mipsbe | mipseb | mipsel | mipsle \
 | 
			
		||||
	| mips16 \
 | 
			
		||||
	| mips64 | mips64el \
 | 
			
		||||
@@ -244,27 +259,33 @@ case $basic_machine in
 | 
			
		||||
	| mips64vr4100 | mips64vr4100el \
 | 
			
		||||
	| mips64vr4300 | mips64vr4300el \
 | 
			
		||||
	| mips64vr5000 | mips64vr5000el \
 | 
			
		||||
	| mips64vr5900 | mips64vr5900el \
 | 
			
		||||
	| mipsisa32 | mipsisa32el \
 | 
			
		||||
	| mipsisa32r2 | mipsisa32r2el \
 | 
			
		||||
	| mipsisa64 | mipsisa64el \
 | 
			
		||||
	| mipsisa64r2 | mipsisa64r2el \
 | 
			
		||||
	| mipsisa64sb1 | mipsisa64sb1el \
 | 
			
		||||
	| mipsisa64sr71k | mipsisa64sr71kel \
 | 
			
		||||
	| mipstx39 | mipstx39el \
 | 
			
		||||
	| mn10200 | mn10300 \
 | 
			
		||||
	| mt \
 | 
			
		||||
	| msp430 \
 | 
			
		||||
	| nios | nios2 \
 | 
			
		||||
	| ns16k | ns32k \
 | 
			
		||||
	| openrisc | or32 \
 | 
			
		||||
	| or32 \
 | 
			
		||||
	| pdp10 | pdp11 | pj | pjl \
 | 
			
		||||
	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
 | 
			
		||||
	| pyramid \
 | 
			
		||||
	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
 | 
			
		||||
	| score \
 | 
			
		||||
	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
 | 
			
		||||
	| sh64 | sh64le \
 | 
			
		||||
	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
 | 
			
		||||
	| strongarm \
 | 
			
		||||
	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
 | 
			
		||||
	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
 | 
			
		||||
	| spu | strongarm \
 | 
			
		||||
	| tahoe | thumb | tic4x | tic80 | tron \
 | 
			
		||||
	| v850 | v850e \
 | 
			
		||||
	| we32k \
 | 
			
		||||
	| x86 | xscale | xstormy16 | xtensa \
 | 
			
		||||
	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
 | 
			
		||||
	| z8k)
 | 
			
		||||
		basic_machine=$basic_machine-unknown
 | 
			
		||||
		;;
 | 
			
		||||
@@ -275,6 +296,9 @@ case $basic_machine in
 | 
			
		||||
		;;
 | 
			
		||||
	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
 | 
			
		||||
		;;
 | 
			
		||||
	ms1)
 | 
			
		||||
		basic_machine=mt-unknown
 | 
			
		||||
		;;
 | 
			
		||||
 | 
			
		||||
	# We use `pc' rather than `unknown'
 | 
			
		||||
	# because (1) that's what they normally are, and
 | 
			
		||||
@@ -294,20 +318,20 @@ case $basic_machine in
 | 
			
		||||
	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
 | 
			
		||||
	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
 | 
			
		||||
	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 | 
			
		||||
	| avr-* \
 | 
			
		||||
	| bs2000-* \
 | 
			
		||||
	| avr-* | avr32-* \
 | 
			
		||||
	| bfin-* | bs2000-* \
 | 
			
		||||
	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
 | 
			
		||||
	| clipper-* | cydra-* \
 | 
			
		||||
	| clipper-* | craynv-* | cydra-* \
 | 
			
		||||
	| d10v-* | d30v-* | dlx-* \
 | 
			
		||||
	| elxsi-* \
 | 
			
		||||
	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
 | 
			
		||||
	| h8300-* | h8500-* \
 | 
			
		||||
	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 | 
			
		||||
	| i*86-* | i860-* | i960-* | ia64-* \
 | 
			
		||||
	| ip2k-* \
 | 
			
		||||
	| m32r-* \
 | 
			
		||||
	| ip2k-* | iq2000-* \
 | 
			
		||||
	| m32c-* | m32r-* | m32rle-* \
 | 
			
		||||
	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
 | 
			
		||||
	| m88110-* | m88k-* | mcore-* \
 | 
			
		||||
	| m88110-* | m88k-* | maxq-* | mcore-* \
 | 
			
		||||
	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 | 
			
		||||
	| mips16-* \
 | 
			
		||||
	| mips64-* | mips64el-* \
 | 
			
		||||
@@ -316,30 +340,36 @@ case $basic_machine in
 | 
			
		||||
	| mips64vr4100-* | mips64vr4100el-* \
 | 
			
		||||
	| mips64vr4300-* | mips64vr4300el-* \
 | 
			
		||||
	| mips64vr5000-* | mips64vr5000el-* \
 | 
			
		||||
	| mips64vr5900-* | mips64vr5900el-* \
 | 
			
		||||
	| mipsisa32-* | mipsisa32el-* \
 | 
			
		||||
	| mipsisa32r2-* | mipsisa32r2el-* \
 | 
			
		||||
	| mipsisa64-* | mipsisa64el-* \
 | 
			
		||||
	| mipsisa64r2-* | mipsisa64r2el-* \
 | 
			
		||||
	| mipsisa64sb1-* | mipsisa64sb1el-* \
 | 
			
		||||
	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
 | 
			
		||||
	| mipstx39-* | mipstx39el-* \
 | 
			
		||||
	| mmix-* \
 | 
			
		||||
	| mt-* \
 | 
			
		||||
	| msp430-* \
 | 
			
		||||
	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
 | 
			
		||||
	| nios-* | nios2-* \
 | 
			
		||||
	| none-* | np1-* | ns16k-* | ns32k-* \
 | 
			
		||||
	| orion-* \
 | 
			
		||||
	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 | 
			
		||||
	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
 | 
			
		||||
	| pyramid-* \
 | 
			
		||||
	| romp-* | rs6000-* \
 | 
			
		||||
	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
 | 
			
		||||
	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 | 
			
		||||
	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 | 
			
		||||
	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
 | 
			
		||||
	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
 | 
			
		||||
	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 | 
			
		||||
	| sparclite-* \
 | 
			
		||||
	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
 | 
			
		||||
	| tahoe-* | thumb-* \
 | 
			
		||||
	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
 | 
			
		||||
	| tron-* \
 | 
			
		||||
	| v850-* | v850e-* | vax-* \
 | 
			
		||||
	| we32k-* \
 | 
			
		||||
	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
 | 
			
		||||
	| xtensa-* \
 | 
			
		||||
	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
 | 
			
		||||
	| xstormy16-* | xtensa-* \
 | 
			
		||||
	| ymp-* \
 | 
			
		||||
	| z8k-*)
 | 
			
		||||
		;;
 | 
			
		||||
@@ -359,6 +389,9 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=a29k-amd
 | 
			
		||||
		os=-udi
 | 
			
		||||
		;;
 | 
			
		||||
    	abacus)
 | 
			
		||||
		basic_machine=abacus-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	adobe68k)
 | 
			
		||||
		basic_machine=m68010-adobe
 | 
			
		||||
		os=-scout
 | 
			
		||||
@@ -376,6 +409,9 @@ case $basic_machine in
 | 
			
		||||
	amd64)
 | 
			
		||||
		basic_machine=x86_64-pc
 | 
			
		||||
		;;
 | 
			
		||||
	amd64-*)
 | 
			
		||||
		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	amdahl)
 | 
			
		||||
		basic_machine=580-amdahl
 | 
			
		||||
		os=-sysv
 | 
			
		||||
@@ -435,12 +471,27 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=j90-cray
 | 
			
		||||
		os=-unicos
 | 
			
		||||
		;;
 | 
			
		||||
	craynv)
 | 
			
		||||
		basic_machine=craynv-cray
 | 
			
		||||
		os=-unicosmp
 | 
			
		||||
		;;
 | 
			
		||||
	cr16c)
 | 
			
		||||
		basic_machine=cr16c-unknown
 | 
			
		||||
		os=-elf
 | 
			
		||||
		;;
 | 
			
		||||
	crds | unos)
 | 
			
		||||
		basic_machine=m68k-crds
 | 
			
		||||
		;;
 | 
			
		||||
	crisv32 | crisv32-* | etraxfs*)
 | 
			
		||||
		basic_machine=crisv32-axis
 | 
			
		||||
		;;
 | 
			
		||||
	cris | cris-* | etrax*)
 | 
			
		||||
		basic_machine=cris-axis
 | 
			
		||||
		;;
 | 
			
		||||
	crx)
 | 
			
		||||
		basic_machine=crx-unknown
 | 
			
		||||
		os=-elf
 | 
			
		||||
		;;
 | 
			
		||||
	da30 | da30-*)
 | 
			
		||||
		basic_machine=m68k-da30
 | 
			
		||||
		;;
 | 
			
		||||
@@ -463,6 +514,10 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=m88k-motorola
 | 
			
		||||
		os=-sysv3
 | 
			
		||||
		;;
 | 
			
		||||
	djgpp)
 | 
			
		||||
		basic_machine=i586-pc
 | 
			
		||||
		os=-msdosdjgpp
 | 
			
		||||
		;;
 | 
			
		||||
	dpx20 | dpx20-*)
 | 
			
		||||
		basic_machine=rs6000-bull
 | 
			
		||||
		os=-bosx
 | 
			
		||||
@@ -641,10 +696,6 @@ case $basic_machine in
 | 
			
		||||
	mips3*)
 | 
			
		||||
		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	mmix*)
 | 
			
		||||
		basic_machine=mmix-knuth
 | 
			
		||||
		os=-mmixware
 | 
			
		||||
		;;
 | 
			
		||||
	monitor)
 | 
			
		||||
		basic_machine=m68k-rom68k
 | 
			
		||||
		os=-coff
 | 
			
		||||
@@ -657,6 +708,9 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=i386-pc
 | 
			
		||||
		os=-msdos
 | 
			
		||||
		;;
 | 
			
		||||
	ms1-*)
 | 
			
		||||
		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
 | 
			
		||||
		;;
 | 
			
		||||
	mvs)
 | 
			
		||||
		basic_machine=i370-ibm
 | 
			
		||||
		os=-mvs
 | 
			
		||||
@@ -725,10 +779,6 @@ case $basic_machine in
 | 
			
		||||
	np1)
 | 
			
		||||
		basic_machine=np1-gould
 | 
			
		||||
		;;
 | 
			
		||||
	nv1)
 | 
			
		||||
		basic_machine=nv1-cray
 | 
			
		||||
		os=-unicosmp
 | 
			
		||||
		;;
 | 
			
		||||
	nsr-tandem)
 | 
			
		||||
		basic_machine=nsr-tandem
 | 
			
		||||
		;;
 | 
			
		||||
@@ -736,9 +786,12 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=hppa1.1-oki
 | 
			
		||||
		os=-proelf
 | 
			
		||||
		;;
 | 
			
		||||
	or32 | or32-*)
 | 
			
		||||
	openrisc | openrisc-*)
 | 
			
		||||
		basic_machine=or32-unknown
 | 
			
		||||
		os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	os400)
 | 
			
		||||
		basic_machine=powerpc-ibm
 | 
			
		||||
		os=-os400
 | 
			
		||||
		;;
 | 
			
		||||
	OSE68000 | ose68000)
 | 
			
		||||
		basic_machine=m68000-ericsson
 | 
			
		||||
@@ -765,6 +818,12 @@ case $basic_machine in
 | 
			
		||||
	pc532 | pc532-*)
 | 
			
		||||
		basic_machine=ns32k-pc532
 | 
			
		||||
		;;
 | 
			
		||||
	pc98)
 | 
			
		||||
		basic_machine=i386-pc
 | 
			
		||||
		;;
 | 
			
		||||
	pc98-*)
 | 
			
		||||
		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
 | 
			
		||||
		;;
 | 
			
		||||
	pentium | p5 | k5 | k6 | nexgen | viac3)
 | 
			
		||||
		basic_machine=i586-pc
 | 
			
		||||
		;;
 | 
			
		||||
@@ -821,6 +880,10 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=i586-unknown
 | 
			
		||||
		os=-pw32
 | 
			
		||||
		;;
 | 
			
		||||
	rdos)
 | 
			
		||||
		basic_machine=i386-pc
 | 
			
		||||
		os=-rdos
 | 
			
		||||
		;;
 | 
			
		||||
	rom68k)
 | 
			
		||||
		basic_machine=m68k-rom68k
 | 
			
		||||
		os=-coff
 | 
			
		||||
@@ -847,6 +910,10 @@ case $basic_machine in
 | 
			
		||||
	sb1el)
 | 
			
		||||
		basic_machine=mipsisa64sb1el-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	sde)
 | 
			
		||||
		basic_machine=mipsisa32-sde
 | 
			
		||||
		os=-elf
 | 
			
		||||
		;;
 | 
			
		||||
	sei)
 | 
			
		||||
		basic_machine=mips-sei
 | 
			
		||||
		os=-seiux
 | 
			
		||||
@@ -960,6 +1027,10 @@ case $basic_machine in
 | 
			
		||||
	tower | tower-32)
 | 
			
		||||
		basic_machine=m68k-ncr
 | 
			
		||||
		;;
 | 
			
		||||
	tpf)
 | 
			
		||||
		basic_machine=s390x-ibm
 | 
			
		||||
		os=-tpf
 | 
			
		||||
		;;
 | 
			
		||||
	udi29k)
 | 
			
		||||
		basic_machine=a29k-amd
 | 
			
		||||
		os=-udi
 | 
			
		||||
@@ -1003,6 +1074,10 @@ case $basic_machine in
 | 
			
		||||
		basic_machine=hppa1.1-winbond
 | 
			
		||||
		os=-proelf
 | 
			
		||||
		;;
 | 
			
		||||
	xbox)
 | 
			
		||||
		basic_machine=i686-pc
 | 
			
		||||
		os=-mingw32
 | 
			
		||||
		;;
 | 
			
		||||
	xps | xps100)
 | 
			
		||||
		basic_machine=xps100-honeywell
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1033,6 +1108,9 @@ case $basic_machine in
 | 
			
		||||
	romp)
 | 
			
		||||
		basic_machine=romp-ibm
 | 
			
		||||
		;;
 | 
			
		||||
	mmix)
 | 
			
		||||
		basic_machine=mmix-knuth
 | 
			
		||||
		;;
 | 
			
		||||
	rs6000)
 | 
			
		||||
		basic_machine=rs6000-ibm
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1049,13 +1127,10 @@ case $basic_machine in
 | 
			
		||||
	we32k)
 | 
			
		||||
		basic_machine=we32k-att
 | 
			
		||||
		;;
 | 
			
		||||
	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
 | 
			
		||||
	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
 | 
			
		||||
		basic_machine=sh-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	sh64)
 | 
			
		||||
		basic_machine=sh64-unknown
 | 
			
		||||
		;;
 | 
			
		||||
	sparc | sparcv9 | sparcv9b)
 | 
			
		||||
	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
 | 
			
		||||
		basic_machine=sparc-sun
 | 
			
		||||
		;;
 | 
			
		||||
	cydra)
 | 
			
		||||
@@ -1128,19 +1203,23 @@ case $os in
 | 
			
		||||
	      | -aos* \
 | 
			
		||||
	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 | 
			
		||||
	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 | 
			
		||||
	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
 | 
			
		||||
	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 | 
			
		||||
	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
 | 
			
		||||
	      | -openbsd* | -solidbsd* \
 | 
			
		||||
	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 | 
			
		||||
	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 | 
			
		||||
	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 | 
			
		||||
	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 | 
			
		||||
	      | -chorusos* | -chorusrdb* \
 | 
			
		||||
	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
 | 
			
		||||
	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
 | 
			
		||||
	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
 | 
			
		||||
	      | -uxpv* | -beos* | -mpeix* | -udk* \
 | 
			
		||||
	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 | 
			
		||||
	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 | 
			
		||||
	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 | 
			
		||||
	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 | 
			
		||||
	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 | 
			
		||||
	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
 | 
			
		||||
	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
 | 
			
		||||
	      | -skyos* | -haiku* | -rdos* | -toppers*)
 | 
			
		||||
	# Remember, each alternative MUST END IN *, to match a version number.
 | 
			
		||||
		;;
 | 
			
		||||
	-qnx*)
 | 
			
		||||
@@ -1158,12 +1237,15 @@ case $os in
 | 
			
		||||
		os=`echo $os | sed -e 's|nto|nto-qnx|'`
 | 
			
		||||
		;;
 | 
			
		||||
	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
 | 
			
		||||
	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
 | 
			
		||||
	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
 | 
			
		||||
	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
 | 
			
		||||
		;;
 | 
			
		||||
	-mac*)
 | 
			
		||||
		os=`echo $os | sed -e 's|mac|macos|'`
 | 
			
		||||
		;;
 | 
			
		||||
	-linux-dietlibc)
 | 
			
		||||
		os=-linux-dietlibc
 | 
			
		||||
		;;
 | 
			
		||||
	-linux*)
 | 
			
		||||
		os=`echo $os | sed -e 's|linux|linux-gnu|'`
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1176,6 +1258,9 @@ case $os in
 | 
			
		||||
	-opened*)
 | 
			
		||||
		os=-openedition
 | 
			
		||||
		;;
 | 
			
		||||
        -os400*)
 | 
			
		||||
		os=-os400
 | 
			
		||||
		;;
 | 
			
		||||
	-wince*)
 | 
			
		||||
		os=-wince
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1197,6 +1282,9 @@ case $os in
 | 
			
		||||
	-atheos*)
 | 
			
		||||
		os=-atheos
 | 
			
		||||
		;;
 | 
			
		||||
	-syllable*)
 | 
			
		||||
		os=-syllable
 | 
			
		||||
		;;
 | 
			
		||||
	-386bsd)
 | 
			
		||||
		os=-bsd
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1219,6 +1307,9 @@ case $os in
 | 
			
		||||
	-sinix*)
 | 
			
		||||
		os=-sysv4
 | 
			
		||||
		;;
 | 
			
		||||
        -tpf*)
 | 
			
		||||
		os=-tpf
 | 
			
		||||
		;;
 | 
			
		||||
	-triton*)
 | 
			
		||||
		os=-sysv3
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1255,6 +1346,9 @@ case $os in
 | 
			
		||||
	-kaos*)
 | 
			
		||||
		os=-kaos
 | 
			
		||||
		;;
 | 
			
		||||
	-zvmoe)
 | 
			
		||||
		os=-zvmoe
 | 
			
		||||
		;;
 | 
			
		||||
	-none)
 | 
			
		||||
		;;
 | 
			
		||||
	*)
 | 
			
		||||
@@ -1277,6 +1371,12 @@ else
 | 
			
		||||
# system, and we'll never get to this point.
 | 
			
		||||
 | 
			
		||||
case $basic_machine in
 | 
			
		||||
        score-*)
 | 
			
		||||
		os=-elf
 | 
			
		||||
		;;
 | 
			
		||||
        spu-*)
 | 
			
		||||
		os=-elf
 | 
			
		||||
		;;
 | 
			
		||||
	*-acorn)
 | 
			
		||||
		os=-riscix1.2
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1286,9 +1386,9 @@ case $basic_machine in
 | 
			
		||||
	arm*-semi)
 | 
			
		||||
		os=-aout
 | 
			
		||||
		;;
 | 
			
		||||
    c4x-* | tic4x-*)
 | 
			
		||||
        os=-coff
 | 
			
		||||
        ;;
 | 
			
		||||
        c4x-* | tic4x-*)
 | 
			
		||||
        	os=-coff
 | 
			
		||||
		;;
 | 
			
		||||
	# This must come before the *-dec entry.
 | 
			
		||||
	pdp10-*)
 | 
			
		||||
		os=-tops20
 | 
			
		||||
@@ -1332,9 +1432,15 @@ case $basic_machine in
 | 
			
		||||
	*-be)
 | 
			
		||||
		os=-beos
 | 
			
		||||
		;;
 | 
			
		||||
	*-haiku)
 | 
			
		||||
		os=-haiku
 | 
			
		||||
		;;
 | 
			
		||||
	*-ibm)
 | 
			
		||||
		os=-aix
 | 
			
		||||
		;;
 | 
			
		||||
    	*-knuth)
 | 
			
		||||
		os=-mmixware
 | 
			
		||||
		;;
 | 
			
		||||
	*-wec)
 | 
			
		||||
		os=-proelf
 | 
			
		||||
		;;
 | 
			
		||||
@@ -1467,9 +1573,15 @@ case $basic_machine in
 | 
			
		||||
			-mvs* | -opened*)
 | 
			
		||||
				vendor=ibm
 | 
			
		||||
				;;
 | 
			
		||||
			-os400*)
 | 
			
		||||
				vendor=ibm
 | 
			
		||||
				;;
 | 
			
		||||
			-ptx*)
 | 
			
		||||
				vendor=sequent
 | 
			
		||||
				;;
 | 
			
		||||
			-tpf*)
 | 
			
		||||
				vendor=ibm
 | 
			
		||||
				;;
 | 
			
		||||
			-vxsim* | -vxworks* | -windiss*)
 | 
			
		||||
				vendor=wrs
 | 
			
		||||
				;;
 | 
			
		||||
@@ -1494,7 +1606,7 @@ case $basic_machine in
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
echo $basic_machine$os
 | 
			
		||||
exit 0
 | 
			
		||||
exit
 | 
			
		||||
 | 
			
		||||
# Local variables:
 | 
			
		||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# install - install a program, script, or datafile
 | 
			
		||||
 | 
			
		||||
scriptversion=2003-06-13.21
 | 
			
		||||
scriptversion=2006-10-14.15
 | 
			
		||||
 | 
			
		||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
 | 
			
		||||
# later released in X11R6 (xc/config/util/install.sh) with the
 | 
			
		||||
@@ -39,15 +39,24 @@ scriptversion=2003-06-13.21
 | 
			
		||||
# when there is no Makefile.
 | 
			
		||||
#
 | 
			
		||||
# This script is compatible with the BSD install script, but was written
 | 
			
		||||
# from scratch.  It can only install one file at a time, a restriction
 | 
			
		||||
# shared with many OS's install programs.
 | 
			
		||||
# from scratch.
 | 
			
		||||
 | 
			
		||||
nl='
 | 
			
		||||
'
 | 
			
		||||
IFS=" ""	$nl"
 | 
			
		||||
 | 
			
		||||
# set DOITPROG to echo to test this script
 | 
			
		||||
 | 
			
		||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
 | 
			
		||||
doit="${DOITPROG-}"
 | 
			
		||||
if test -z "$doit"; then
 | 
			
		||||
  doit_exec=exec
 | 
			
		||||
else
 | 
			
		||||
  doit_exec=$doit
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# put in absolute paths if you don't have them in your path; or use env. vars.
 | 
			
		||||
# Put in absolute file names if you don't have them in your path;
 | 
			
		||||
# or use environment vars.
 | 
			
		||||
 | 
			
		||||
mvprog="${MVPROG-mv}"
 | 
			
		||||
cpprog="${CPPROG-cp}"
 | 
			
		||||
@@ -58,10 +67,13 @@ stripprog="${STRIPPROG-strip}"
 | 
			
		||||
rmprog="${RMPROG-rm}"
 | 
			
		||||
mkdirprog="${MKDIRPROG-mkdir}"
 | 
			
		||||
 | 
			
		||||
transformbasename=
 | 
			
		||||
transform_arg=
 | 
			
		||||
instcmd="$mvprog"
 | 
			
		||||
chmodcmd="$chmodprog 0755"
 | 
			
		||||
posix_glob=
 | 
			
		||||
posix_mkdir=
 | 
			
		||||
 | 
			
		||||
# Desired mode of installed file.
 | 
			
		||||
mode=0755
 | 
			
		||||
 | 
			
		||||
chmodcmd=$chmodprog
 | 
			
		||||
chowncmd=
 | 
			
		||||
chgrpcmd=
 | 
			
		||||
stripcmd=
 | 
			
		||||
@@ -70,22 +82,27 @@ mvcmd="$mvprog"
 | 
			
		||||
src=
 | 
			
		||||
dst=
 | 
			
		||||
dir_arg=
 | 
			
		||||
dstarg=
 | 
			
		||||
no_target_directory=
 | 
			
		||||
 | 
			
		||||
usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
 | 
			
		||||
   or: $0 -d DIR1 DIR2...
 | 
			
		||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
 | 
			
		||||
   or: $0 [OPTION]... SRCFILES... DIRECTORY
 | 
			
		||||
   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
 | 
			
		||||
   or: $0 [OPTION]... -d DIRECTORIES...
 | 
			
		||||
 | 
			
		||||
In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
 | 
			
		||||
In the second, create the directory path DIR.
 | 
			
		||||
In the 1st form, copy SRCFILE to DSTFILE.
 | 
			
		||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
 | 
			
		||||
In the 4th, create DIRECTORIES.
 | 
			
		||||
 | 
			
		||||
Options:
 | 
			
		||||
-b=TRANSFORMBASENAME
 | 
			
		||||
-c         copy source (using $cpprog) instead of moving (using $mvprog).
 | 
			
		||||
-c         (ignored)
 | 
			
		||||
-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
 | 
			
		||||
-g GROUP   $chgrpprog installed files to GROUP.
 | 
			
		||||
-m MODE    $chmodprog installed files to MODE.
 | 
			
		||||
-o USER    $chownprog installed files to USER.
 | 
			
		||||
-s         $stripprog installed files.
 | 
			
		||||
-t DIRECTORY  install into DIRECTORY.
 | 
			
		||||
-T         report an error if DSTFILE is a directory.
 | 
			
		||||
--help     display this help and exit.
 | 
			
		||||
--version  display version info and exit.
 | 
			
		||||
 | 
			
		||||
@@ -93,14 +110,9 @@ Environment variables override the default commands:
 | 
			
		||||
  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
 | 
			
		||||
"
 | 
			
		||||
 | 
			
		||||
while test -n "$1"; do
 | 
			
		||||
while test $# -ne 0; do
 | 
			
		||||
  case $1 in
 | 
			
		||||
    -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    -c) instcmd=$cpprog
 | 
			
		||||
        shift
 | 
			
		||||
    -c) shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    -d) dir_arg=true
 | 
			
		||||
@@ -112,11 +124,17 @@ while test -n "$1"; do
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    --help) echo "$usage"; exit 0;;
 | 
			
		||||
    --help) echo "$usage"; exit $?;;
 | 
			
		||||
 | 
			
		||||
    -m) chmodcmd="$chmodprog $2"
 | 
			
		||||
    -m) mode=$2
 | 
			
		||||
        shift
 | 
			
		||||
        shift
 | 
			
		||||
	case $mode in
 | 
			
		||||
	  *' '* | *'	'* | *'
 | 
			
		||||
'*	  | *'*'* | *'?'* | *'['*)
 | 
			
		||||
	    echo "$0: invalid mode: $mode" >&2
 | 
			
		||||
	    exit 1;;
 | 
			
		||||
	esac
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    -o) chowncmd="$chownprog $2"
 | 
			
		||||
@@ -128,155 +146,358 @@ while test -n "$1"; do
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
    -t=*) transformarg=`echo $1 | sed 's/-t=//'`
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
    -t) dstarg=$2
 | 
			
		||||
	shift
 | 
			
		||||
	shift
 | 
			
		||||
	continue;;
 | 
			
		||||
 | 
			
		||||
    --version) echo "$0 $scriptversion"; exit 0;;
 | 
			
		||||
    -T) no_target_directory=true
 | 
			
		||||
	shift
 | 
			
		||||
	continue;;
 | 
			
		||||
 | 
			
		||||
    *)  if test -z "$src"; then
 | 
			
		||||
          src=$1
 | 
			
		||||
        else
 | 
			
		||||
          # this colon is to work around a 386BSD /bin/sh bug
 | 
			
		||||
          :
 | 
			
		||||
          dst=$1
 | 
			
		||||
        fi
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
    --version) echo "$0 $scriptversion"; exit $?;;
 | 
			
		||||
 | 
			
		||||
    --)	shift
 | 
			
		||||
	break;;
 | 
			
		||||
 | 
			
		||||
    -*)	echo "$0: invalid option: $1" >&2
 | 
			
		||||
	exit 1;;
 | 
			
		||||
 | 
			
		||||
    *)  break;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
if test -z "$src"; then
 | 
			
		||||
  echo "$0: no input file specified." >&2
 | 
			
		||||
  exit 1
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
  if test -z "$dst"; then
 | 
			
		||||
    echo "$0: no destination specified." >&2
 | 
			
		||||
    exit 1
 | 
			
		||||
  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,^$,.,'`
 | 
			
		||||
 | 
			
		||||
# Make sure that the destination directory exists.
 | 
			
		||||
# (this part is taken from Noah Friedman's mkinstalldirs script.)
 | 
			
		||||
 | 
			
		||||
# Skip lots of stat calls in the usual case.
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
  pathcomp=
 | 
			
		||||
 | 
			
		||||
  while test $# -ne 0 ; do
 | 
			
		||||
    pathcomp=$pathcomp$1
 | 
			
		||||
    shift
 | 
			
		||||
    test -d "$pathcomp" || $mkdirprog "$pathcomp"
 | 
			
		||||
    pathcomp=$pathcomp/
 | 
			
		||||
if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
 | 
			
		||||
  # When -d is used, all remaining arguments are directories to create.
 | 
			
		||||
  # When -t is used, the destination is already specified.
 | 
			
		||||
  # Otherwise, the last argument is the destination.  Remove it from $@.
 | 
			
		||||
  for arg
 | 
			
		||||
  do
 | 
			
		||||
    if test -n "$dstarg"; then
 | 
			
		||||
      # $@ is not empty: it contains at least $arg.
 | 
			
		||||
      set fnord "$@" "$dstarg"
 | 
			
		||||
      shift # fnord
 | 
			
		||||
    fi
 | 
			
		||||
    shift # arg
 | 
			
		||||
    dstarg=$arg
 | 
			
		||||
  done
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
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"; }
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
if test $# -eq 0; then
 | 
			
		||||
  if test -z "$dir_arg"; then
 | 
			
		||||
    echo "$0: no input file specified." >&2
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
  # It's OK to call `install-sh -d' without argument.
 | 
			
		||||
  # This can happen when creating conditional directories.
 | 
			
		||||
  exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
  # don't allow the sed command to completely eliminate the filename.
 | 
			
		||||
  test -z "$dstfile" && dstfile=`basename "$dst"`
 | 
			
		||||
 | 
			
		||||
  # Make a couple of temp file names in the proper directory.
 | 
			
		||||
  dsttmp=$dstdir/_inst.$$_
 | 
			
		||||
  rmtmp=$dstdir/_rm.$$_
 | 
			
		||||
 | 
			
		||||
  # Trap to clean up those temp files at exit.
 | 
			
		||||
  trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
 | 
			
		||||
if test -z "$dir_arg"; then
 | 
			
		||||
  trap '(exit $?); exit' 1 2 13 15
 | 
			
		||||
 | 
			
		||||
  # Move or copy the file name to the temp name
 | 
			
		||||
  $doit $instcmd "$src" "$dsttmp" &&
 | 
			
		||||
  # Set umask so as not to create temps with too-generous modes.
 | 
			
		||||
  # However, 'strip' requires both read and write access to temps.
 | 
			
		||||
  case $mode in
 | 
			
		||||
    # Optimize common cases.
 | 
			
		||||
    *644) cp_umask=133;;
 | 
			
		||||
    *755) cp_umask=22;;
 | 
			
		||||
 | 
			
		||||
  # 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"; } &&
 | 
			
		||||
    *[0-7])
 | 
			
		||||
      if test -z "$stripcmd"; then
 | 
			
		||||
	u_plus_rw=
 | 
			
		||||
      else
 | 
			
		||||
	u_plus_rw='% 200'
 | 
			
		||||
      fi
 | 
			
		||||
      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
 | 
			
		||||
    *)
 | 
			
		||||
      if test -z "$stripcmd"; then
 | 
			
		||||
	u_plus_rw=
 | 
			
		||||
      else
 | 
			
		||||
	u_plus_rw=,u+rw
 | 
			
		||||
      fi
 | 
			
		||||
      cp_umask=$mode$u_plus_rw;;
 | 
			
		||||
  esac
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
  # 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
 | 
			
		||||
      :
 | 
			
		||||
for src
 | 
			
		||||
do
 | 
			
		||||
  # Protect names starting with `-'.
 | 
			
		||||
  case $src in
 | 
			
		||||
    -*) src=./$src ;;
 | 
			
		||||
  esac
 | 
			
		||||
 | 
			
		||||
  if test -n "$dir_arg"; then
 | 
			
		||||
    dst=$src
 | 
			
		||||
    dstdir=$dst
 | 
			
		||||
    test -d "$dstdir"
 | 
			
		||||
    dstdir_status=$?
 | 
			
		||||
  else
 | 
			
		||||
 | 
			
		||||
    # Waiting for this to be detected by the "$cpprog $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
 | 
			
		||||
  } &&
 | 
			
		||||
 | 
			
		||||
  # Now rename the file to the real destination.
 | 
			
		||||
  $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
 | 
			
		||||
fi &&
 | 
			
		||||
    if test -z "$dstarg"; then
 | 
			
		||||
      echo "$0: no destination specified." >&2
 | 
			
		||||
      exit 1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
# The final little trick to "correctly" pass the exit status to the exit trap.
 | 
			
		||||
{
 | 
			
		||||
  (exit 0); exit
 | 
			
		||||
}
 | 
			
		||||
    dst=$dstarg
 | 
			
		||||
    # Protect names starting with `-'.
 | 
			
		||||
    case $dst in
 | 
			
		||||
      -*) dst=./$dst ;;
 | 
			
		||||
    esac
 | 
			
		||||
 | 
			
		||||
    # If destination is a directory, append the input filename; won't work
 | 
			
		||||
    # if double slashes aren't ignored.
 | 
			
		||||
    if test -d "$dst"; then
 | 
			
		||||
      if test -n "$no_target_directory"; then
 | 
			
		||||
	echo "$0: $dstarg: Is a directory" >&2
 | 
			
		||||
	exit 1
 | 
			
		||||
      fi
 | 
			
		||||
      dstdir=$dst
 | 
			
		||||
      dst=$dstdir/`basename "$src"`
 | 
			
		||||
      dstdir_status=0
 | 
			
		||||
    else
 | 
			
		||||
      # Prefer dirname, but fall back on a substitute if dirname fails.
 | 
			
		||||
      dstdir=`
 | 
			
		||||
	(dirname "$dst") 2>/dev/null ||
 | 
			
		||||
	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
 | 
			
		||||
	     X"$dst" : 'X\(//\)[^/]' \| \
 | 
			
		||||
	     X"$dst" : 'X\(//\)$' \| \
 | 
			
		||||
	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
 | 
			
		||||
	echo X"$dst" |
 | 
			
		||||
	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
 | 
			
		||||
		   s//\1/
 | 
			
		||||
		   q
 | 
			
		||||
		 }
 | 
			
		||||
		 /^X\(\/\/\)[^/].*/{
 | 
			
		||||
		   s//\1/
 | 
			
		||||
		   q
 | 
			
		||||
		 }
 | 
			
		||||
		 /^X\(\/\/\)$/{
 | 
			
		||||
		   s//\1/
 | 
			
		||||
		   q
 | 
			
		||||
		 }
 | 
			
		||||
		 /^X\(\/\).*/{
 | 
			
		||||
		   s//\1/
 | 
			
		||||
		   q
 | 
			
		||||
		 }
 | 
			
		||||
		 s/.*/./; q'
 | 
			
		||||
      `
 | 
			
		||||
 | 
			
		||||
      test -d "$dstdir"
 | 
			
		||||
      dstdir_status=$?
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  obsolete_mkdir_used=false
 | 
			
		||||
 | 
			
		||||
  if test $dstdir_status != 0; then
 | 
			
		||||
    case $posix_mkdir in
 | 
			
		||||
      '')
 | 
			
		||||
	# Create intermediate dirs using mode 755 as modified by the umask.
 | 
			
		||||
	# This is like FreeBSD 'install' as of 1997-10-28.
 | 
			
		||||
	umask=`umask`
 | 
			
		||||
	case $stripcmd.$umask in
 | 
			
		||||
	  # Optimize common cases.
 | 
			
		||||
	  *[2367][2367]) mkdir_umask=$umask;;
 | 
			
		||||
	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
 | 
			
		||||
 | 
			
		||||
	  *[0-7])
 | 
			
		||||
	    mkdir_umask=`expr $umask + 22 \
 | 
			
		||||
	      - $umask % 100 % 40 + $umask % 20 \
 | 
			
		||||
	      - $umask % 10 % 4 + $umask % 2
 | 
			
		||||
	    `;;
 | 
			
		||||
	  *) mkdir_umask=$umask,go-w;;
 | 
			
		||||
	esac
 | 
			
		||||
 | 
			
		||||
	# With -d, create the new directory with the user-specified mode.
 | 
			
		||||
	# Otherwise, rely on $mkdir_umask.
 | 
			
		||||
	if test -n "$dir_arg"; then
 | 
			
		||||
	  mkdir_mode=-m$mode
 | 
			
		||||
	else
 | 
			
		||||
	  mkdir_mode=
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	posix_mkdir=false
 | 
			
		||||
	case $umask in
 | 
			
		||||
	  *[123567][0-7][0-7])
 | 
			
		||||
	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
 | 
			
		||||
	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
 | 
			
		||||
	    ;;
 | 
			
		||||
	  *)
 | 
			
		||||
	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
 | 
			
		||||
	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
 | 
			
		||||
 | 
			
		||||
	    if (umask $mkdir_umask &&
 | 
			
		||||
		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
 | 
			
		||||
	    then
 | 
			
		||||
	      if test -z "$dir_arg" || {
 | 
			
		||||
		   # Check for POSIX incompatibilities with -m.
 | 
			
		||||
		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
 | 
			
		||||
		   # other-writeable bit of parent directory when it shouldn't.
 | 
			
		||||
		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
 | 
			
		||||
		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
 | 
			
		||||
		   case $ls_ld_tmpdir in
 | 
			
		||||
		     d????-?r-*) different_mode=700;;
 | 
			
		||||
		     d????-?--*) different_mode=755;;
 | 
			
		||||
		     *) false;;
 | 
			
		||||
		   esac &&
 | 
			
		||||
		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
 | 
			
		||||
		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
 | 
			
		||||
		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
 | 
			
		||||
		   }
 | 
			
		||||
		 }
 | 
			
		||||
	      then posix_mkdir=:
 | 
			
		||||
	      fi
 | 
			
		||||
	      rmdir "$tmpdir/d" "$tmpdir"
 | 
			
		||||
	    else
 | 
			
		||||
	      # Remove any dirs left behind by ancient mkdir implementations.
 | 
			
		||||
	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
 | 
			
		||||
	    fi
 | 
			
		||||
	    trap '' 0;;
 | 
			
		||||
	esac;;
 | 
			
		||||
    esac
 | 
			
		||||
 | 
			
		||||
    if
 | 
			
		||||
      $posix_mkdir && (
 | 
			
		||||
	umask $mkdir_umask &&
 | 
			
		||||
	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
 | 
			
		||||
      )
 | 
			
		||||
    then :
 | 
			
		||||
    else
 | 
			
		||||
 | 
			
		||||
      # The umask is ridiculous, or mkdir does not conform to POSIX,
 | 
			
		||||
      # or it failed possibly due to a race condition.  Create the
 | 
			
		||||
      # directory the slow way, step by step, checking for races as we go.
 | 
			
		||||
 | 
			
		||||
      case $dstdir in
 | 
			
		||||
	/*) prefix=/ ;;
 | 
			
		||||
	-*) prefix=./ ;;
 | 
			
		||||
	*)  prefix= ;;
 | 
			
		||||
      esac
 | 
			
		||||
 | 
			
		||||
      case $posix_glob in
 | 
			
		||||
        '')
 | 
			
		||||
	  if (set -f) 2>/dev/null; then
 | 
			
		||||
	    posix_glob=true
 | 
			
		||||
	  else
 | 
			
		||||
	    posix_glob=false
 | 
			
		||||
	  fi ;;
 | 
			
		||||
      esac
 | 
			
		||||
 | 
			
		||||
      oIFS=$IFS
 | 
			
		||||
      IFS=/
 | 
			
		||||
      $posix_glob && set -f
 | 
			
		||||
      set fnord $dstdir
 | 
			
		||||
      shift
 | 
			
		||||
      $posix_glob && set +f
 | 
			
		||||
      IFS=$oIFS
 | 
			
		||||
 | 
			
		||||
      prefixes=
 | 
			
		||||
 | 
			
		||||
      for d
 | 
			
		||||
      do
 | 
			
		||||
	test -z "$d" && continue
 | 
			
		||||
 | 
			
		||||
	prefix=$prefix$d
 | 
			
		||||
	if test -d "$prefix"; then
 | 
			
		||||
	  prefixes=
 | 
			
		||||
	else
 | 
			
		||||
	  if $posix_mkdir; then
 | 
			
		||||
	    (umask=$mkdir_umask &&
 | 
			
		||||
	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
 | 
			
		||||
	    # Don't fail if two instances are running concurrently.
 | 
			
		||||
	    test -d "$prefix" || exit 1
 | 
			
		||||
	  else
 | 
			
		||||
	    case $prefix in
 | 
			
		||||
	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
 | 
			
		||||
	      *) qprefix=$prefix;;
 | 
			
		||||
	    esac
 | 
			
		||||
	    prefixes="$prefixes '$qprefix'"
 | 
			
		||||
	  fi
 | 
			
		||||
	fi
 | 
			
		||||
	prefix=$prefix/
 | 
			
		||||
      done
 | 
			
		||||
 | 
			
		||||
      if test -n "$prefixes"; then
 | 
			
		||||
	# Don't fail if two instances are running concurrently.
 | 
			
		||||
	(umask $mkdir_umask &&
 | 
			
		||||
	 eval "\$doit_exec \$mkdirprog $prefixes") ||
 | 
			
		||||
	  test -d "$dstdir" || exit 1
 | 
			
		||||
	obsolete_mkdir_used=true
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if test -n "$dir_arg"; then
 | 
			
		||||
    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
 | 
			
		||||
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
 | 
			
		||||
    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
 | 
			
		||||
      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
 | 
			
		||||
  else
 | 
			
		||||
 | 
			
		||||
    # Make a couple of temp file names in the proper directory.
 | 
			
		||||
    dsttmp=$dstdir/_inst.$$_
 | 
			
		||||
    rmtmp=$dstdir/_rm.$$_
 | 
			
		||||
 | 
			
		||||
    # Trap to clean up those temp files at exit.
 | 
			
		||||
    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
 | 
			
		||||
 | 
			
		||||
    # Copy the file name to the temp name.
 | 
			
		||||
    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
 | 
			
		||||
 | 
			
		||||
    # 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 $cpprog $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 $mode "$dsttmp"; } &&
 | 
			
		||||
 | 
			
		||||
    # Now rename the file to the real destination.
 | 
			
		||||
    { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
 | 
			
		||||
      || {
 | 
			
		||||
	   # The rename failed, perhaps because mv can't rename something else
 | 
			
		||||
	   # to itself, or perhaps because mv is so ancient that it does not
 | 
			
		||||
	   # support -f.
 | 
			
		||||
 | 
			
		||||
	   # 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 "$dst"; then
 | 
			
		||||
	       $doit $rmcmd -f "$dst" 2>/dev/null \
 | 
			
		||||
	       || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
 | 
			
		||||
		     && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
 | 
			
		||||
	       || {
 | 
			
		||||
		 echo "$0: cannot unlink or rename $dst" >&2
 | 
			
		||||
		 (exit 1); exit 1
 | 
			
		||||
	       }
 | 
			
		||||
	     else
 | 
			
		||||
	       :
 | 
			
		||||
	     fi
 | 
			
		||||
	   } &&
 | 
			
		||||
 | 
			
		||||
	   # Now rename the file to the real destination.
 | 
			
		||||
	   $doit $mvcmd "$dsttmp" "$dst"
 | 
			
		||||
	 }
 | 
			
		||||
    } || exit 1
 | 
			
		||||
 | 
			
		||||
    trap '' 0
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Local variables:
 | 
			
		||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										197
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										197
									
								
								configure.in
									
									
									
									
									
								
							@@ -1,8 +1,8 @@
 | 
			
		||||
##
 | 
			
		||||
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
## Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
## Copyright (C) 2004, 2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
##
 | 
			
		||||
## This file is part of the LVM2.
 | 
			
		||||
## 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
 | 
			
		||||
@@ -13,18 +13,22 @@
 | 
			
		||||
## Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
AC_PREREQ(2.53)
 | 
			
		||||
AC_PREREQ(2.57)
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Process this file with autoconf to produce a configure script.
 | 
			
		||||
AC_INIT(lib/device/dev-cache.h)
 | 
			
		||||
AC_INIT
 | 
			
		||||
AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
AC_CONFIG_HEADERS(lib/misc/configure.h)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Setup the directory where autoconf has auxilary files
 | 
			
		||||
AC_CONFIG_AUX_DIR(autoconf) 
 | 
			
		||||
AC_CONFIG_AUX_DIR(autoconf)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Get system type
 | 
			
		||||
AC_CANONICAL_SYSTEM
 | 
			
		||||
AC_CANONICAL_TARGET([])
 | 
			
		||||
 | 
			
		||||
case "$host_os" in
 | 
			
		||||
	linux*)
 | 
			
		||||
@@ -35,10 +39,11 @@ case "$host_os" in
 | 
			
		||||
		CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
 | 
			
		||||
		LDDEPS="$LDDEPS .export.sym"
 | 
			
		||||
		LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
 | 
			
		||||
		SOFLAG="-shared"
 | 
			
		||||
		LIB_SUFFIX="so"
 | 
			
		||||
		DEVMAPPER=yes
 | 
			
		||||
		ODIRECT=yes
 | 
			
		||||
		SELINUX=yes
 | 
			
		||||
		REALTIME=yes
 | 
			
		||||
		CLUSTER=internal
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
	darwin*)
 | 
			
		||||
@@ -49,10 +54,11 @@ case "$host_os" in
 | 
			
		||||
		CLDNOWHOLEARCHIVE=
 | 
			
		||||
		LDDEPS="$LDDEPS"
 | 
			
		||||
		LDFLAGS="$LDFLAGS"
 | 
			
		||||
		SOFLAG="-dynamiclib"
 | 
			
		||||
		LIB_SUFFIX="dylib"
 | 
			
		||||
		DEVMAPPER=yes
 | 
			
		||||
		ODIRECT=no
 | 
			
		||||
		SELINUX=no
 | 
			
		||||
		REALTIME=no
 | 
			
		||||
		CLUSTER=none
 | 
			
		||||
		FSADM=no ;;
 | 
			
		||||
esac
 | 
			
		||||
@@ -65,6 +71,8 @@ AC_PROG_INSTALL
 | 
			
		||||
AC_PROG_LN_S
 | 
			
		||||
AC_PROG_MAKE_SET
 | 
			
		||||
AC_PROG_RANLIB
 | 
			
		||||
AC_PATH_PROG(CFLOW_CMD, cflow)
 | 
			
		||||
AC_PATH_PROG(CSCOPE_CMD, cscope)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Checks for header files.
 | 
			
		||||
@@ -91,7 +99,7 @@ AC_TYPE_OFF_T
 | 
			
		||||
AC_TYPE_PID_T
 | 
			
		||||
AC_TYPE_SIZE_T
 | 
			
		||||
AC_TYPE_MODE_T
 | 
			
		||||
AC_STRUCT_ST_RDEV
 | 
			
		||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
 | 
			
		||||
AC_STRUCT_TM
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -150,7 +158,7 @@ AC_ARG_ENABLE(lvm1_fallback, [  --enable-lvm1_fallback  Use this to fall back an
 | 
			
		||||
AC_MSG_RESULT($LVM1_FALLBACK)
 | 
			
		||||
 | 
			
		||||
if test x$LVM1_FALLBACK = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DLVM1_FALLBACK"
 | 
			
		||||
	AC_DEFINE([LVM1_FALLBACK], 1, [Define to 1 if 'lvm' should fall back to using LVM1 binaries if device-mapper is missing from the kernel])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -170,7 +178,7 @@ if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$LVM1 = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DLVM1_INTERNAL"
 | 
			
		||||
	AC_DEFINE([LVM1_INTERNAL], 1, [Define to 1 to include built-in support for LVM1 metadata.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -190,7 +198,7 @@ if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$POOL = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DPOOL_INTERNAL"
 | 
			
		||||
	AC_DEFINE([POOL_INTERNAL], 1, [Define to 1 to include built-in support for GFS pool metadata.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -209,7 +217,7 @@ if [[ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$CLUSTER = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
 | 
			
		||||
	AC_DEFINE([CLUSTER_LOCKING_INTERNAL], 1, [Define to 1 to include built-in support for clustered LVM locking.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -229,7 +237,7 @@ if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != x
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$SNAPSHOTS = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
 | 
			
		||||
	AC_DEFINE([SNAPSHOT_INTERNAL], 1, [Define to 1 to include built-in support for snapshots.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -249,7 +257,7 @@ if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared
 | 
			
		||||
fi;
 | 
			
		||||
 | 
			
		||||
if test x$MIRRORS = xinternal; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
 | 
			
		||||
	AC_DEFINE([MIRRORED_INTERNAL], 1, [Define to 1 to include built-in support for mirrors.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -267,7 +275,7 @@ READLINE=$enableval, READLINE=no)
 | 
			
		||||
AC_MSG_RESULT($READLINE)
 | 
			
		||||
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
 | 
			
		||||
	AC_DEFINE([READLINE_SUPPORT], 1, [Define to 1 to include the LVM readline shell.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -277,6 +285,13 @@ AC_ARG_ENABLE(selinux, [  --disable-selinux       Disable selinux support],
 | 
			
		||||
SELINUX=$enableval)
 | 
			
		||||
AC_MSG_RESULT($SELINUX)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Disable realtime clock support
 | 
			
		||||
AC_MSG_CHECKING(whether to enable realtime support)
 | 
			
		||||
AC_ARG_ENABLE(realtime, [  --disable-realtime      Disable realtime clock support],
 | 
			
		||||
REALTIME=$enableval)
 | 
			
		||||
AC_MSG_RESULT($REALTIME)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Build cluster LVM daemon
 | 
			
		||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
 | 
			
		||||
@@ -305,6 +320,8 @@ AC_MSG_RESULT($DEBUG)
 | 
			
		||||
dnl -- Normally turn off optimisation for debug builds
 | 
			
		||||
if test x$DEBUG = xyes; then
 | 
			
		||||
	COPTIMISE_FLAG=
 | 
			
		||||
else
 | 
			
		||||
	CSCOPE_CMD=
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -323,7 +340,7 @@ DEVMAPPER=$enableval)
 | 
			
		||||
AC_MSG_RESULT($DEVMAPPER)
 | 
			
		||||
 | 
			
		||||
if test x$DEVMAPPER = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
 | 
			
		||||
	AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable device-mapper interaction.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -334,7 +351,7 @@ ODIRECT=$enableval)
 | 
			
		||||
AC_MSG_RESULT($ODIRECT)
 | 
			
		||||
 | 
			
		||||
if test x$ODIRECT = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
 | 
			
		||||
	AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -344,10 +361,6 @@ AC_ARG_ENABLE(cmdlib, [  --enable-cmdlib         Build shared command library],
 | 
			
		||||
CMDLIB=$enableval, CMDLIB=no)
 | 
			
		||||
AC_MSG_RESULT($CMDLIB)
 | 
			
		||||
 | 
			
		||||
if test x$CMDLIB = xyes; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DCMDLIB"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Enable fsadm
 | 
			
		||||
AC_MSG_CHECKING(whether to build fsadm)
 | 
			
		||||
@@ -355,6 +368,23 @@ AC_ARG_ENABLE(fsadm, [  --enable-fsadm          Enable fsadm],
 | 
			
		||||
FSADM=$enableval)
 | 
			
		||||
AC_MSG_RESULT($FSADM)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- enable dmeventd handling
 | 
			
		||||
AC_MSG_CHECKING(whether to use dmeventd)
 | 
			
		||||
AC_ARG_ENABLE(dmeventd, [  --enable-dmeventd       Enable the device-mapper event daemon],
 | 
			
		||||
DMEVENTD=$enableval)
 | 
			
		||||
AC_MSG_RESULT($DMEVENTD)
 | 
			
		||||
 | 
			
		||||
dnl -- dmeventd currently requires internal mirror support
 | 
			
		||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
 | 
			
		||||
AC_MSG_ERROR(
 | 
			
		||||
--enable-dmeventd currently requires --with-mirrors=internal
 | 
			
		||||
)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD = xyes; then
 | 
			
		||||
	AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
 | 
			
		||||
fi
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Mess with default exec_prefix
 | 
			
		||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
 | 
			
		||||
@@ -390,7 +420,7 @@ dnl -- Check for dlopen
 | 
			
		||||
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
 | 
			
		||||
 | 
			
		||||
if [[ "x$HAVE_LIBDL" = xyes ]]; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DHAVE_LIBDL"
 | 
			
		||||
	AC_DEFINE([HAVE_LIBDL], 1, [Define to 1 if dynamic libraries are available.])
 | 
			
		||||
	LIBS="-ldl $LIBS"
 | 
			
		||||
else
 | 
			
		||||
	HAVE_LIBDL=no
 | 
			
		||||
@@ -407,23 +437,52 @@ Features cannot be 'shared' when building statically
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for is_selinux_enabled
 | 
			
		||||
dnl -- Check for selinux
 | 
			
		||||
if test x$SELINUX = xyes; then
 | 
			
		||||
	AC_MSG_CHECKING(for is_selinux_enabled function)
 | 
			
		||||
	AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_SEPOL = xyes; then
 | 
			
		||||
		LIBS="-lsepol $LIBS"
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
 | 
			
		||||
	AC_MSG_RESULT($HAVE_SELINUX)
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
		CFLAGS="$CFLAGS -DHAVE_SELINUX"
 | 
			
		||||
		AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.])
 | 
			
		||||
		LIBS="-lselinux $LIBS"
 | 
			
		||||
	else
 | 
			
		||||
		AC_MSG_WARN(Disabling selinux)
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	# With --enable-static_link and selinux enabled, linking lvm.static
 | 
			
		||||
	# fails on at least Debian unstable due to unsatisfied references
 | 
			
		||||
	# to pthread_mutex_lock and _unlock.  See if we need -lpthread.
 | 
			
		||||
	if test "$STATIC_LINK-$HAVE_SELINUX" = yes-yes; then
 | 
			
		||||
		lvm_saved_libs=$LIBS
 | 
			
		||||
		LIBS="$LIBS -static"
 | 
			
		||||
		AC_SEARCH_LIBS([pthread_mutex_lock], [pthread],
 | 
			
		||||
		  [test "$ac_cv_search_pthread_mutex_lock" = "none required" ||
 | 
			
		||||
				LIB_PTHREAD=-lpthread])
 | 
			
		||||
		LIBS=$lvm_saved_libs
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for realtime clock support
 | 
			
		||||
if test x$REALTIME = xyes; then
 | 
			
		||||
	AC_CHECK_LIB(rt, clock_gettime, HAVE_REALTIME=yes, HAVE_REALTIME=no)
 | 
			
		||||
 | 
			
		||||
	if test x$HAVE_REALTIME = xyes; then
 | 
			
		||||
		AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
 | 
			
		||||
		LIBS="-lrt $LIBS"
 | 
			
		||||
	else
 | 
			
		||||
		AC_MSG_WARN(Disabling realtime clock)
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for getopt
 | 
			
		||||
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
 | 
			
		||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 to if getopt_long is available.]))
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
 | 
			
		||||
@@ -438,8 +497,7 @@ Note: if you are using precompiled packages you will also need the development
 | 
			
		||||
package as well (which may be called readline-devel or something similar).
 | 
			
		||||
)
 | 
			
		||||
	)
 | 
			
		||||
	AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
 | 
			
		||||
		
 | 
			
		||||
	AC_CHECK_FUNC(rl_completion_matches, AC_DEFINE([HAVE_RL_COMPLETION_MATCHES], 1, [Define to 1 if rl_completion_matches() is available.]))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -475,6 +533,17 @@ AC_ARG_WITH(staticdir,
 | 
			
		||||
  	    [ STATICDIR="$withval" ],
 | 
			
		||||
 	    [ STATICDIR='${exec_prefix}/sbin' ])
 | 
			
		||||
 | 
			
		||||
AC_ARG_WITH(dmdir,
 | 
			
		||||
	    [  --with-dmdir=DIR        Build against device-mapper source tree in DIR],
 | 
			
		||||
  	    [ DMDIR="$withval" CPPFLAGS="$CPPFLAGS -I$DMDIR/include"],
 | 
			
		||||
	    [ DMDIR= ])
 | 
			
		||||
 | 
			
		||||
# Convert a relative dir name to absolute.
 | 
			
		||||
case $DMDIR in
 | 
			
		||||
  /*) ;;
 | 
			
		||||
  *) DMDIR="`pwd`/$DMDIR" ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- Ensure additional headers required
 | 
			
		||||
if test x$READLINE = xyes; then
 | 
			
		||||
@@ -507,9 +576,7 @@ if test x$INTL = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(libintl.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DEVMAPPER = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
fi
 | 
			
		||||
AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
 | 
			
		||||
if test x$HAVE_SELINUX = xyes; then
 | 
			
		||||
	AC_CHECK_HEADERS(selinux/selinux.h,,AC_MSG_ERROR(bailing out))
 | 
			
		||||
@@ -519,7 +586,7 @@ fi
 | 
			
		||||
AC_PATH_PROG(MODPROBE_CMD, modprobe)
 | 
			
		||||
 | 
			
		||||
if test x$MODPROBE_CMD != x; then
 | 
			
		||||
	CFLAGS="$CFLAGS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
 | 
			
		||||
	AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
@@ -545,7 +612,7 @@ AC_SUBST(CLDWHOLEARCHIVE)
 | 
			
		||||
AC_SUBST(CLDNOWHOLEARCHIVE)
 | 
			
		||||
AC_SUBST(LDDEPS)
 | 
			
		||||
AC_SUBST(LDFLAGS)
 | 
			
		||||
AC_SUBST(SOFLAG)
 | 
			
		||||
AC_SUBST(LIB_SUFFIX)
 | 
			
		||||
AC_SUBST(LIBS)
 | 
			
		||||
AC_SUBST(LVM_VERSION)
 | 
			
		||||
AC_SUBST(LVM1_FALLBACK)
 | 
			
		||||
@@ -553,44 +620,50 @@ AC_SUBST(DEBUG)
 | 
			
		||||
AC_SUBST(DEVMAPPER)
 | 
			
		||||
AC_SUBST(HAVE_LIBDL)
 | 
			
		||||
AC_SUBST(HAVE_SELINUX)
 | 
			
		||||
AC_SUBST(HAVE_REALTIME)
 | 
			
		||||
AC_SUBST(CMDLIB)
 | 
			
		||||
AC_SUBST(MSGFMT)
 | 
			
		||||
AC_SUBST(LOCALEDIR)
 | 
			
		||||
AC_SUBST(CONFDIR)
 | 
			
		||||
AC_SUBST(STATICDIR)
 | 
			
		||||
AC_SUBST(DMDIR)
 | 
			
		||||
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)
 | 
			
		||||
AC_SUBST([LIB_PTHREAD])
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
dnl -- First and last lines should not contain files to generate in order to 
 | 
			
		||||
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								\
 | 
			
		||||
daemons/Makefile							\
 | 
			
		||||
daemons/clvmd/Makefile							\
 | 
			
		||||
doc/Makefile								\
 | 
			
		||||
include/Makefile						 	\
 | 
			
		||||
lib/Makefile							 	\
 | 
			
		||||
lib/format1/Makefile						 	\
 | 
			
		||||
lib/format_pool/Makefile						\
 | 
			
		||||
lib/locking/Makefile							\
 | 
			
		||||
lib/mirror/Makefile							\
 | 
			
		||||
lib/snapshot/Makefile							\
 | 
			
		||||
man/Makefile							 	\
 | 
			
		||||
po/Makefile								\
 | 
			
		||||
tools/Makefile							 	\
 | 
			
		||||
tools/version.h								\
 | 
			
		||||
tools/fsadm/Makefile							\
 | 
			
		||||
test/mm/Makefile							\
 | 
			
		||||
test/device/Makefile							\
 | 
			
		||||
test/format1/Makefile							\
 | 
			
		||||
test/regex/Makefile                                                     \
 | 
			
		||||
test/filters/Makefile                                                   \
 | 
			
		||||
)
 | 
			
		||||
AC_CONFIG_FILES([
 | 
			
		||||
Makefile
 | 
			
		||||
make.tmpl
 | 
			
		||||
daemons/Makefile
 | 
			
		||||
daemons/clvmd/Makefile
 | 
			
		||||
dmeventd/Makefile
 | 
			
		||||
dmeventd/mirror/Makefile
 | 
			
		||||
doc/Makefile
 | 
			
		||||
include/Makefile
 | 
			
		||||
lib/Makefile
 | 
			
		||||
lib/format1/Makefile
 | 
			
		||||
lib/format_pool/Makefile
 | 
			
		||||
lib/locking/Makefile
 | 
			
		||||
lib/mirror/Makefile
 | 
			
		||||
lib/snapshot/Makefile
 | 
			
		||||
test/Makefile
 | 
			
		||||
man/Makefile
 | 
			
		||||
po/Makefile
 | 
			
		||||
scripts/Makefile
 | 
			
		||||
tools/Makefile
 | 
			
		||||
tools/version.h
 | 
			
		||||
tools/fsadm/Makefile
 | 
			
		||||
])
 | 
			
		||||
AC_OUTPUT
 | 
			
		||||
 | 
			
		||||
if test x$ODIRECT != xyes; then
 | 
			
		||||
  AC_MSG_WARN(Warning: O_DIRECT disabled: low-memory pvmove may lock up)
 | 
			
		||||
@@ -599,3 +672,7 @@ fi
 | 
			
		||||
if test x$FSADM == xyes; then
 | 
			
		||||
  AC_MSG_WARN(fsadm support is untested)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test x$DMEVENTD == xyes; then
 | 
			
		||||
  AC_MSG_WARN(dmeventd support is untested)
 | 
			
		||||
fi
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
# 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
# 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
 | 
			
		||||
@@ -19,7 +19,7 @@ SOURCES = \
 | 
			
		||||
	clvmd-command.c  \
 | 
			
		||||
	clvmd.c          \
 | 
			
		||||
	lvm-functions.c  \
 | 
			
		||||
	system-lv.c
 | 
			
		||||
	refresh_clvmd.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "gulm")
 | 
			
		||||
	GULM = yes
 | 
			
		||||
@@ -29,40 +29,62 @@ ifeq ("@CLVMD@", "cman")
 | 
			
		||||
	CMAN = yes
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "openais")
 | 
			
		||||
	OPENAIS = yes
 | 
			
		||||
	GULM = no
 | 
			
		||||
	CMAN = no
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@CLVMD@", "all")
 | 
			
		||||
	GULM = yes
 | 
			
		||||
	CMAN = yes
 | 
			
		||||
	OPENAIS = no
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@DEBUG@", "yes")
 | 
			
		||||
	CFLAGS += -DDEBUG
 | 
			
		||||
	DEFS += -DDEBUG
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("$(GULM)", "yes")
 | 
			
		||||
	SOURCES += clvmd-gulm.c tcp-comms.c
 | 
			
		||||
	LMLIBS += -lccs -lgulm
 | 
			
		||||
	CFLAGS += -DUSE_GULM
 | 
			
		||||
	DEFS += -DUSE_GULM
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("$(CMAN)", "yes")
 | 
			
		||||
	SOURCES += clvmd-cman.c
 | 
			
		||||
	LMLIBS += -ldlm
 | 
			
		||||
	CFLAGS += -DUSE_CMAN
 | 
			
		||||
	LMLIBS += -ldlm -lcman
 | 
			
		||||
	DEFS += -DUSE_CMAN
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("$(OPENAIS)", "yes")
 | 
			
		||||
	SOURCES += clvmd-openais.c
 | 
			
		||||
	LMLIBS += -lSaLck -lcpg
 | 
			
		||||
	DEFS += -DUSE_OPENAIS
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
TARGETS = \
 | 
			
		||||
	clvmd
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
LVMLIBS = -llvm -lpthread
 | 
			
		||||
 | 
			
		||||
CFLAGS += -D_REENTRANT -fno-strict-aliasing
 | 
			
		||||
LIBS += -ldevmapper -llvm -lpthread
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
	LVMLIBS += -ldevmapper-event
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
LVMLIBS += -ldevmapper
 | 
			
		||||
 | 
			
		||||
DEFS += -D_REENTRANT
 | 
			
		||||
CFLAGS += -fno-strict-aliasing
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
INSTALL_TARGETS = \
 | 
			
		||||
	install_clvmd
 | 
			
		||||
 | 
			
		||||
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
 | 
			
		||||
	$(CC) -o clvmd $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(LMLIBS) $(LIBS)
 | 
			
		||||
	$(CC) -o clvmd $(OBJECTS) $(CFLAGS) $(LDFLAGS) \
 | 
			
		||||
		$(LVMLIBS) $(LMLIBS) $(LIBS)
 | 
			
		||||
 | 
			
		||||
.PHONY: install_clvmd
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
@@ -63,4 +63,8 @@ static const char CLVMD_SOCKNAME[] = "\0clvmd";
 | 
			
		||||
#define CLVMD_CMD_LOCK_LV           50
 | 
			
		||||
#define CLVMD_CMD_LOCK_VG           51
 | 
			
		||||
 | 
			
		||||
/* Misc functions */
 | 
			
		||||
#define CLVMD_CMD_REFRESH	    40
 | 
			
		||||
#define CLVMD_CMD_GET_CLUSTERNAME   41
 | 
			
		||||
#define CLVMD_CMD_SET_DEBUG	    42
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -36,29 +36,33 @@
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <libdlm.h>
 | 
			
		||||
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
 | 
			
		||||
#define LOCKSPACE_NAME "clvmd"
 | 
			
		||||
 | 
			
		||||
static int cluster_sock;
 | 
			
		||||
static int num_nodes;
 | 
			
		||||
static struct cl_cluster_node *nodes = NULL;
 | 
			
		||||
static 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 nodeid_from_csid(const char *csid);
 | 
			
		||||
static int name_from_nodeid(int nodeid, char *name);
 | 
			
		||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
 | 
			
		||||
static void data_callback(cman_handle_t handle, void *private,
 | 
			
		||||
			  char *buf, int len, uint8_t port, int nodeid);
 | 
			
		||||
 | 
			
		||||
struct lock_wait {
 | 
			
		||||
	pthread_cond_t cond;
 | 
			
		||||
@@ -68,34 +72,30 @@ struct lock_wait {
 | 
			
		||||
 | 
			
		||||
static int _init_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_cl saddr;
 | 
			
		||||
	int port = CLUSTER_PORT_CLVMD;
 | 
			
		||||
 | 
			
		||||
	/* Open the cluster communication socket */
 | 
			
		||||
	cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT);
 | 
			
		||||
	if (cluster_sock == -1) {
 | 
			
		||||
		/* Don't print an error here because we could be just probing for CMAN */
 | 
			
		||||
	c_handle = cman_init(NULL);
 | 
			
		||||
	if (!c_handle) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't open cluster manager socket: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	/* Set Close-on-exec */
 | 
			
		||||
	fcntl(cluster_sock, F_SETFD, 1);
 | 
			
		||||
	DEBUGLOG("Connected to CMAN\n");
 | 
			
		||||
 | 
			
		||||
	/* Bind to our port number on the cluster.
 | 
			
		||||
	   Writes to this will block if the cluster loses quorum */
 | 
			
		||||
	saddr.scl_family = AF_CLUSTER;
 | 
			
		||||
	saddr.scl_port = port;
 | 
			
		||||
 | 
			
		||||
	if (bind
 | 
			
		||||
	    (cluster_sock, (struct sockaddr *) &saddr,
 | 
			
		||||
	     sizeof(struct sockaddr_cl))) {
 | 
			
		||||
	if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't bind cluster socket: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cman_start_notification(c_handle, event_callback)) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't start cluster event listening");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the cluster members list */
 | 
			
		||||
	get_members();
 | 
			
		||||
	count_clvmds_running();
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("CMAN initialisation complete\n");
 | 
			
		||||
 | 
			
		||||
	/* Create a lockspace for LV & VG locks to live in */
 | 
			
		||||
	lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
 | 
			
		||||
	if (!lockspace) {
 | 
			
		||||
@@ -103,7 +103,7 @@ static int _init_cluster(void)
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	dlm_ls_pthread_init(lockspace);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("DLM initialisation complete\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -114,155 +114,127 @@ static void _cluster_init_completed(void)
 | 
			
		||||
 | 
			
		||||
static int _get_main_cluster_fd()
 | 
			
		||||
{
 | 
			
		||||
	return cluster_sock;
 | 
			
		||||
	return cman_get_fd(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_num_nodes()
 | 
			
		||||
{
 | 
			
		||||
	return num_nodes;
 | 
			
		||||
	int i;
 | 
			
		||||
	int nnodes = 0;
 | 
			
		||||
 | 
			
		||||
	/* return number of ACTIVE nodes */
 | 
			
		||||
	for (i=0; i<num_nodes; i++) {
 | 
			
		||||
		if (nodes[i].cn_member && nodes[i].cn_nodeid)
 | 
			
		||||
			nnodes++;
 | 
			
		||||
	}
 | 
			
		||||
	return nnodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send_message with the fd check removed */
 | 
			
		||||
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
 | 
			
		||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
 | 
			
		||||
				 const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	struct iovec iov[2];
 | 
			
		||||
	struct msghdr msg;
 | 
			
		||||
	struct sockaddr_cl saddr;
 | 
			
		||||
	int len = 0;
 | 
			
		||||
	int nodeid = 0;
 | 
			
		||||
 | 
			
		||||
	msg.msg_control = NULL;
 | 
			
		||||
	msg.msg_controllen = 0;
 | 
			
		||||
	msg.msg_iovlen = 1;
 | 
			
		||||
	msg.msg_iov = iov;
 | 
			
		||||
	msg.msg_flags = 0;
 | 
			
		||||
	iov[0].iov_len = msglen;
 | 
			
		||||
	iov[0].iov_base = buf;
 | 
			
		||||
	if (csid)
 | 
			
		||||
		memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	saddr.scl_family = AF_CLUSTER;
 | 
			
		||||
	saddr.scl_port = CLUSTER_PORT_CLVMD;
 | 
			
		||||
	if (csid) {
 | 
			
		||||
		msg.msg_name = &saddr;
 | 
			
		||||
		msg.msg_namelen = sizeof(saddr);
 | 
			
		||||
		memcpy(&saddr.scl_nodeid, csid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
	} else {		/* Cluster broadcast */
 | 
			
		||||
 | 
			
		||||
		msg.msg_name = NULL;
 | 
			
		||||
		msg.msg_namelen = 0;
 | 
			
		||||
	if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
 | 
			
		||||
	{
 | 
			
		||||
		log_error("%s", errtext);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		len = sendmsg(cluster_sock, &msg, 0);
 | 
			
		||||
		if (len < 0 && errno != EAGAIN)
 | 
			
		||||
			log_error(errtext);
 | 
			
		||||
 | 
			
		||||
	} while (len == -1 && errno == EAGAIN);
 | 
			
		||||
	return len;
 | 
			
		||||
	return msglen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	memset(csid, 0, CMAN_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (nodes[i].us)
 | 
			
		||||
			memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
 | 
			
		||||
	if (this_node.cn_nodeid == 0) {
 | 
			
		||||
		cman_get_node(c_handle, 0, &this_node);
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Call a callback routine for each node that known (down mean not running a clvmd) */
 | 
			
		||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
 | 
			
		||||
static int _cluster_do_node_callback(struct local_client *client,
 | 
			
		||||
			     void (*callback) (struct local_client *, char *,
 | 
			
		||||
					       int))
 | 
			
		||||
				     void (*callback) (struct local_client *,
 | 
			
		||||
						       const char *,
 | 
			
		||||
						       int))
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int somedown = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < _get_num_nodes(); i++) {
 | 
			
		||||
		callback(client, (char *)&nodes[i].node_id, node_updown[nodes[i].node_id]);
 | 
			
		||||
		if (!node_updown[nodes[i].node_id])
 | 
			
		||||
			somedown = -1;
 | 
			
		||||
		if (nodes[i].cn_member && nodes[i].cn_nodeid) {
 | 
			
		||||
			callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
 | 
			
		||||
			if (!node_updown[nodes[i].cn_nodeid])
 | 
			
		||||
				somedown = -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return somedown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Process OOB message from the cluster socket,
 | 
			
		||||
   this currently just means that a node has stopped listening on our port */
 | 
			
		||||
static void process_oob_msg(char *buf, int len, int nodeid)
 | 
			
		||||
/* Process OOB messages from the cluster socket */
 | 
			
		||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
 | 
			
		||||
{
 | 
			
		||||
	char namebuf[256];
 | 
			
		||||
	switch (buf[0]) {
 | 
			
		||||
        case CLUSTER_OOB_MSG_PORTCLOSED:
 | 
			
		||||
		name_from_nodeid(nodeid, namebuf);
 | 
			
		||||
		log_notice("clvmd on node %s has died\n", namebuf);
 | 
			
		||||
		DEBUGLOG("Got OOB message, removing node %s\n", namebuf);
 | 
			
		||||
	char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
 | 
			
		||||
 | 
			
		||||
		node_updown[nodeid] = 0;
 | 
			
		||||
	switch (reason) {
 | 
			
		||||
        case CMAN_REASON_PORTCLOSED:
 | 
			
		||||
		name_from_nodeid(arg, namebuf);
 | 
			
		||||
		log_notice("clvmd on node %s has died\n", namebuf);
 | 
			
		||||
		DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
 | 
			
		||||
 | 
			
		||||
		node_updown[arg] = 0;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLUSTER_OOB_MSG_STATECHANGE:
 | 
			
		||||
		DEBUGLOG("Got OOB message, Cluster state change\n");
 | 
			
		||||
	case CMAN_REASON_STATECHANGE:
 | 
			
		||||
		DEBUGLOG("Got state change message, re-reading members list\n");
 | 
			
		||||
		get_members();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
 | 
			
		||||
	case CMAN_REASON_PORTOPENED:
 | 
			
		||||
		/* Ignore this, wait for startup message from clvmd itself */
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CMAN_REASON_TRY_SHUTDOWN:
 | 
			
		||||
		DEBUGLOG("Got try shutdown, sending OK\n");
 | 
			
		||||
		cman_replyto_shutdown(c_handle, 1);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		/* ERROR */
 | 
			
		||||
		DEBUGLOG("Got unknown OOB message: %d\n", buf[0]);
 | 
			
		||||
		DEBUGLOG("Got unknown event callback message: %d\n", reason);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
			struct local_client **new_client)
 | 
			
		||||
static struct local_client *cman_client;
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
 | 
			
		||||
				const char *csid,
 | 
			
		||||
				struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	struct iovec iov[2];
 | 
			
		||||
	struct msghdr msg;
 | 
			
		||||
	struct sockaddr_cl saddr;
 | 
			
		||||
 | 
			
		||||
	/* Save this for data_callback */
 | 
			
		||||
	cman_client = fd;
 | 
			
		||||
 | 
			
		||||
	/* We never return a new client */
 | 
			
		||||
	*new_client = NULL;
 | 
			
		||||
 | 
			
		||||
	msg.msg_control = NULL;
 | 
			
		||||
	msg.msg_controllen = 0;
 | 
			
		||||
	msg.msg_iovlen = 1;
 | 
			
		||||
	msg.msg_iov = iov;
 | 
			
		||||
	msg.msg_name = &saddr;
 | 
			
		||||
	msg.msg_flags = 0;
 | 
			
		||||
	msg.msg_namelen = sizeof(saddr);
 | 
			
		||||
	iov[0].iov_len = len;
 | 
			
		||||
	iov[0].iov_base = buf;
 | 
			
		||||
 | 
			
		||||
	len = recvmsg(cluster_sock, &msg, MSG_OOB | O_NONBLOCK);
 | 
			
		||||
	if (len < 0 && errno == EAGAIN)
 | 
			
		||||
		return len;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Read on cluster socket, len = %d\n", len);
 | 
			
		||||
 | 
			
		||||
	/* A real error */
 | 
			
		||||
	if (len < 0) {
 | 
			
		||||
		log_error("read error on cluster socket: %m");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* EOF - we have left the cluster */
 | 
			
		||||
	if (len == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* Is it OOB? probably a node gone down */
 | 
			
		||||
	if (msg.msg_flags & MSG_OOB) {
 | 
			
		||||
		process_oob_msg(iov[0].iov_base, len, saddr.scl_nodeid);
 | 
			
		||||
 | 
			
		||||
		/* Tell the upper layer to ignore this message */
 | 
			
		||||
		len = -1;
 | 
			
		||||
		errno = EAGAIN;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		memcpy(csid, &saddr.scl_nodeid, sizeof(saddr.scl_nodeid));
 | 
			
		||||
		/* Send it back to clvmd */
 | 
			
		||||
		process_message(client, buf, len, csid);
 | 
			
		||||
	}
 | 
			
		||||
	return len;
 | 
			
		||||
	return cman_dispatch(c_handle, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _add_up_node(char *csid)
 | 
			
		||||
 | 
			
		||||
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(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	/* It's up ! */
 | 
			
		||||
	int nodeid = nodeid_from_csid(csid);
 | 
			
		||||
@@ -278,7 +250,7 @@ static void _add_up_node(char *csid)
 | 
			
		||||
				 max_updown_nodes);
 | 
			
		||||
		} else {
 | 
			
		||||
			log_error
 | 
			
		||||
			    ("Realloc failed. Node status for clvmd will be wrong. quitting\n");
 | 
			
		||||
				("Realloc failed. Node status for clvmd will be wrong. quitting\n");
 | 
			
		||||
			exit(999);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -290,19 +262,15 @@ static void _cluster_closedown()
 | 
			
		||||
{
 | 
			
		||||
	unlock_all();
 | 
			
		||||
	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
 | 
			
		||||
	close(cluster_sock);
 | 
			
		||||
	cman_finish(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_listening(int nodeid)
 | 
			
		||||
{
 | 
			
		||||
	struct cl_listen_request rq;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	rq.port = CLUSTER_PORT_CLVMD;
 | 
			
		||||
	rq.nodeid = nodeid;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		status = ioctl(cluster_sock, SIOCCLUSTER_ISLISTENING, &rq);
 | 
			
		||||
		status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
 | 
			
		||||
		if (status < 0 && errno == EBUSY) {	/* Don't busywait */
 | 
			
		||||
			sleep(1);
 | 
			
		||||
			errno = EBUSY;	/* In case sleep trashes it */
 | 
			
		||||
@@ -320,67 +288,60 @@ static void count_clvmds_running(void)
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		node_updown[nodes[i].node_id] = is_listening(nodes[i].node_id);
 | 
			
		||||
		node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get a list of active cluster members */
 | 
			
		||||
static void get_members()
 | 
			
		||||
{
 | 
			
		||||
	struct cl_cluster_nodelist nodelist;
 | 
			
		||||
	int retnodes;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
 | 
			
		||||
	num_nodes = cman_get_node_count(c_handle);
 | 
			
		||||
	if (num_nodes == -1) {
 | 
			
		||||
		log_error("Unable to get node count");
 | 
			
		||||
	} else {
 | 
			
		||||
	        /* Not enough room for new nodes list ? */
 | 
			
		||||
	        if (num_nodes > count_nodes && nodes) {
 | 
			
		||||
			free(nodes);
 | 
			
		||||
			nodes = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		if (nodes == NULL) {
 | 
			
		||||
		        count_nodes = num_nodes + 10; /* Overallocate a little */
 | 
			
		||||
		        nodes = malloc(count_nodes * sizeof(struct cl_cluster_node));
 | 
			
		||||
			if (!nodes) {
 | 
			
		||||
			        log_error("Unable to allocate nodes array\n");
 | 
			
		||||
				exit(5);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		nodelist.max_members = count_nodes;
 | 
			
		||||
		nodelist.nodes = nodes;
 | 
			
		||||
	/* Not enough room for new nodes list ? */
 | 
			
		||||
	if (num_nodes > count_nodes && nodes) {
 | 
			
		||||
		free(nodes);
 | 
			
		||||
		nodes = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
 | 
			
		||||
		if (num_nodes <= 0) {
 | 
			
		||||
		        log_error("Unable to get node details");
 | 
			
		||||
			exit(6);
 | 
			
		||||
	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);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		/* Sanity check struct */
 | 
			
		||||
		if (nodes[0].size != sizeof(struct cl_cluster_node)) {
 | 
			
		||||
			log_error
 | 
			
		||||
			    ("sizeof(cl_cluster_node) does not match size returned from the kernel: aborting\n");
 | 
			
		||||
			exit(10);
 | 
			
		||||
		}
 | 
			
		||||
	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));
 | 
			
		||||
		}
 | 
			
		||||
	if (node_updown == NULL) {
 | 
			
		||||
		size_t buf_len = sizeof(int) * max(num_nodes, max_updown_nodes);
 | 
			
		||||
		node_updown = malloc(buf_len);
 | 
			
		||||
		if (node_updown)
 | 
			
		||||
			memset(node_updown, 0, buf_len);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Convert a node name to a CSID */
 | 
			
		||||
static int _csid_from_name(char *csid, char *name)
 | 
			
		||||
static int _csid_from_name(char *csid, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (strcmp(name, nodes[i].name) == 0) {
 | 
			
		||||
			memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
 | 
			
		||||
		if (strcmp(name, nodes[i].cn_name) == 0) {
 | 
			
		||||
			memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -388,13 +349,13 @@ static int _csid_from_name(char *csid, char *name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a CSID to a node name */
 | 
			
		||||
static int _name_from_csid(char *csid, char *name)
 | 
			
		||||
static int _name_from_csid(const char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (memcmp(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN) == 0) {
 | 
			
		||||
			strcpy(name, nodes[i].name);
 | 
			
		||||
		if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
 | 
			
		||||
			strcpy(name, nodes[i].cn_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -409,8 +370,8 @@ static int name_from_nodeid(int nodeid, char *name)
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (nodeid == nodes[i].node_id) {
 | 
			
		||||
			strcpy(name, nodes[i].name);
 | 
			
		||||
		if (nodeid == nodes[i].cn_nodeid) {
 | 
			
		||||
			strcpy(name, nodes[i].cn_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -420,7 +381,7 @@ static int name_from_nodeid(int nodeid, char *name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a CSID to a node ID */
 | 
			
		||||
static int nodeid_from_csid(char *csid)
 | 
			
		||||
static int nodeid_from_csid(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
        int nodeid;
 | 
			
		||||
 | 
			
		||||
@@ -431,7 +392,7 @@ static int nodeid_from_csid(char *csid)
 | 
			
		||||
 | 
			
		||||
static int _is_quorate()
 | 
			
		||||
{
 | 
			
		||||
	return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
 | 
			
		||||
	return cman_is_quorate(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sync_ast_routine(void *arg)
 | 
			
		||||
@@ -514,6 +475,18 @@ static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_cluster_name(char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	cman_cluster_t cluster_info;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	status = cman_get_cluster(c_handle, &cluster_info);
 | 
			
		||||
	if (!status) {
 | 
			
		||||
		strncpy(buf, cluster_info.ci_name, buflen);
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops _cluster_cman_ops = {
 | 
			
		||||
	.cluster_init_completed   = _cluster_init_completed,
 | 
			
		||||
	.cluster_send_message     = _cluster_send_message,
 | 
			
		||||
@@ -527,6 +500,7 @@ static struct cluster_ops _cluster_cman_ops = {
 | 
			
		||||
	.get_our_csid             = _get_our_csid,
 | 
			
		||||
	.add_up_node              = _add_up_node,
 | 
			
		||||
	.cluster_closedown        = _cluster_closedown,
 | 
			
		||||
	.get_cluster_name         = _get_cluster_name,
 | 
			
		||||
	.sync_lock                = _sync_lock,
 | 
			
		||||
	.sync_unlock              = _sync_unlock,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -64,8 +64,9 @@
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include <libdlm.h>
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
@@ -73,7 +74,9 @@
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
 | 
			
		||||
extern debug_t debug;
 | 
			
		||||
extern struct cluster_ops *clops;
 | 
			
		||||
 | 
			
		||||
/* This is where all the real work happens:
 | 
			
		||||
   NOTE: client will be NULL when this is executed on a remote node */
 | 
			
		||||
@@ -93,18 +96,32 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
 | 
			
		||||
		/* Just a test message */
 | 
			
		||||
	case CLVMD_CMD_TEST:
 | 
			
		||||
		if (arglen > buflen) {
 | 
			
		||||
			char *new_buf;
 | 
			
		||||
			buflen = arglen + 200;
 | 
			
		||||
			*buf = realloc(*buf, buflen);
 | 
			
		||||
			new_buf = realloc(*buf, buflen);
 | 
			
		||||
			if (new_buf == NULL) {
 | 
			
		||||
				status = errno;
 | 
			
		||||
				free (*buf);
 | 
			
		||||
			}
 | 
			
		||||
			*buf = new_buf;
 | 
			
		||||
		}
 | 
			
		||||
		if (*buf) {
 | 
			
		||||
			uname(&nodeinfo);
 | 
			
		||||
			*retlen = 1 + snprintf(*buf, buflen,
 | 
			
		||||
					       "TEST from %s: %s v%s",
 | 
			
		||||
					       nodeinfo.nodename, args,
 | 
			
		||||
					       nodeinfo.release);
 | 
			
		||||
		}
 | 
			
		||||
		uname(&nodeinfo);
 | 
			
		||||
		*retlen = 1 + snprintf(*buf, buflen, "TEST from %s: %s v%s",
 | 
			
		||||
				       nodeinfo.nodename, args,
 | 
			
		||||
				       nodeinfo.release);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_VG:
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		/* Check to see if the VG is in use by LVM1 */
 | 
			
		||||
		status = do_check_lvm1(&args[2]);
 | 
			
		||||
		status = do_check_lvm1(lockname);
 | 
			
		||||
		/* P_global causes a cache refresh */
 | 
			
		||||
		if (strcmp(lockname, "P_global") == 0)
 | 
			
		||||
		      do_refresh_cache();
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_LV:
 | 
			
		||||
@@ -116,12 +133,26 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
 | 
			
		||||
		/* Replace EIO with something less scary */
 | 
			
		||||
		if (status == EIO) {
 | 
			
		||||
			*retlen =
 | 
			
		||||
			    1 + snprintf(*buf, buflen,
 | 
			
		||||
					 "Internal lvm error, check syslog");
 | 
			
		||||
			    1 + snprintf(*buf, buflen, "%s",
 | 
			
		||||
					 get_last_lvm_error());
 | 
			
		||||
			return EIO;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_REFRESH:
 | 
			
		||||
		do_refresh_cache();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_SET_DEBUG:
 | 
			
		||||
		debug = args[0];
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_GET_CLUSTERNAME:
 | 
			
		||||
		status = clops->get_cluster_name(*buf, buflen);
 | 
			
		||||
		if (!status)
 | 
			
		||||
			*retlen = strlen(*buf)+1;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		/* Won't get here because command is validated in pre_command */
 | 
			
		||||
		break;
 | 
			
		||||
@@ -129,7 +160,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
 | 
			
		||||
 | 
			
		||||
	/* Check the status of the command and return the error text */
 | 
			
		||||
	if (status) {
 | 
			
		||||
		*retlen = 1 + snprintf(*buf, buflen, strerror(status));
 | 
			
		||||
		*retlen = 1 + snprintf(*buf, buflen, "%s", strerror(status));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
@@ -179,12 +210,16 @@ static int lock_vg(struct local_client *client)
 | 
			
		||||
	    dm_hash_remove(lock_hash, lockname);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
 | 
			
		||||
	status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
 | 
			
		||||
	/* Read locks need to be PR; other modes get passed through */
 | 
			
		||||
	if ((lock_cmd & LCK_TYPE_MASK) == LCK_READ) {
 | 
			
		||||
	    lock_cmd &= ~LCK_TYPE_MASK;
 | 
			
		||||
	    lock_cmd |= LCK_PREAD;
 | 
			
		||||
	}
 | 
			
		||||
	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);
 | 
			
		||||
	    dm_hash_insert(lock_hash, lockname, (void *)(long)lkid);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return status;
 | 
			
		||||
@@ -208,7 +243,7 @@ int do_pre_command(struct local_client *client)
 | 
			
		||||
	switch (header->cmd) {
 | 
			
		||||
	case CLVMD_CMD_TEST:
 | 
			
		||||
		status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid);
 | 
			
		||||
		client->bits.localsock.private = (void *) lockid;
 | 
			
		||||
		client->bits.localsock.private = (void *)(long)lockid;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_VG:
 | 
			
		||||
@@ -222,6 +257,11 @@ int do_pre_command(struct local_client *client)
 | 
			
		||||
		status = pre_lock_lv(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_REFRESH:
 | 
			
		||||
	case CLVMD_CMD_GET_CLUSTERNAME:
 | 
			
		||||
	case CLVMD_CMD_SET_DEBUG:
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("Unknown command %d received\n", header->cmd);
 | 
			
		||||
		status = EINVAL;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,25 +25,31 @@ 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 (*cluster_send_message) (const void *buf, int msglen,
 | 
			
		||||
				     const char *csid,
 | 
			
		||||
				     const char *errtext);
 | 
			
		||||
	int (*name_from_csid) (const char *csid, char *name);
 | 
			
		||||
	int (*csid_from_name) (char *csid, const 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);
 | 
			
		||||
				    const 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));
 | 
			
		||||
					 void (*callback) (struct local_client *,
 | 
			
		||||
							   const char *csid,
 | 
			
		||||
							   int node_up));
 | 
			
		||||
	int (*is_quorate) (void);
 | 
			
		||||
 | 
			
		||||
	void (*get_our_csid) (char *csid);
 | 
			
		||||
	void (*add_up_node) (char *csid);
 | 
			
		||||
	void (*add_up_node) (const char *csid);
 | 
			
		||||
	void (*reread_config) (void);
 | 
			
		||||
	void (*cluster_closedown) (void);
 | 
			
		||||
 | 
			
		||||
	int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
 | 
			
		||||
	int (*get_cluster_name)(char *buf, int buflen);
 | 
			
		||||
 | 
			
		||||
	int (*sync_lock) (const char *resource, int mode,
 | 
			
		||||
			  int flags, int *lockid);
 | 
			
		||||
	int (*sync_unlock) (const char *resource, int lockid);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
@@ -56,15 +62,36 @@ struct cluster_ops *init_gulm_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CMAN
 | 
			
		||||
#  include "cnxman-socket.h"
 | 
			
		||||
#  include <netinet/in.h>
 | 
			
		||||
#  include "libcman.h"
 | 
			
		||||
#  define CMAN_MAX_CSID_LEN 4
 | 
			
		||||
#  ifndef MAX_CSID_LEN
 | 
			
		||||
#    define MAX_CSID_LEN CMAN_MAX_CSID_LEN
 | 
			
		||||
#  endif
 | 
			
		||||
#  undef MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#  define MAX_CLUSTER_MEMBER_NAME_LEN	CMAN_MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#  define MAX_CLUSTER_MEMBER_NAME_LEN   CMAN_MAX_NODENAME_LEN
 | 
			
		||||
#  define CMAN_MAX_CLUSTER_MESSAGE 1500
 | 
			
		||||
#  define CLUSTER_PORT_CLVMD 11
 | 
			
		||||
struct cluster_ops *init_cman_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_OPENAIS
 | 
			
		||||
#  include <openais/saAis.h>
 | 
			
		||||
#  include <openais/totem/totem.h>
 | 
			
		||||
#  define OPENAIS_CSID_LEN (sizeof(int))
 | 
			
		||||
#  define OPENAIS_MAX_CLUSTER_MESSAGE         MESSAGE_SIZE_MAX
 | 
			
		||||
#  define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
 | 
			
		||||
#  ifndef MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#    define MAX_CLUSTER_MEMBER_NAME_LEN       SA_MAX_NAME_LENGTH
 | 
			
		||||
#  endif
 | 
			
		||||
#  ifndef CMAN_MAX_CLUSTER_MESSAGE
 | 
			
		||||
#    define CMAN_MAX_CLUSTER_MESSAGE          MESSAGE_SIZE_MAX
 | 
			
		||||
#  endif
 | 
			
		||||
#  ifndef MAX_CSID_LEN
 | 
			
		||||
#    define MAX_CSID_LEN sizeof(int)
 | 
			
		||||
#  endif
 | 
			
		||||
struct cluster_ops *init_openais_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -40,9 +40,10 @@
 | 
			
		||||
#include <utmpx.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include <ccs.h>
 | 
			
		||||
#include <libgulm.h>
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "ccs.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
@@ -51,7 +52,6 @@
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "clvmd-gulm.h"
 | 
			
		||||
#include "libgulm.h"
 | 
			
		||||
 | 
			
		||||
/* Hash list of nodes in the cluster */
 | 
			
		||||
static struct dm_hash_table *node_hash;
 | 
			
		||||
@@ -86,12 +86,12 @@ struct lock_wait
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Forward */
 | 
			
		||||
static int read_from_core_sock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
static int read_from_core_sock(struct local_client *client, char *buf, int len, const char *csid,
 | 
			
		||||
			       struct local_client **new_client);
 | 
			
		||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, const char *csid,
 | 
			
		||||
			       struct local_client **new_client);
 | 
			
		||||
static int get_all_cluster_nodes(void);
 | 
			
		||||
static int _csid_from_name(char *csid, char *name);
 | 
			
		||||
static int _csid_from_name(char *csid, const char *name);
 | 
			
		||||
static void _cluster_closedown(void);
 | 
			
		||||
 | 
			
		||||
/* In tcp-comms.c */
 | 
			
		||||
@@ -278,7 +278,7 @@ static void drop_expired_locks(char *nodename)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int read_from_core_sock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
static int read_from_core_sock(struct local_client *client, char *buf, int len, const char *csid,
 | 
			
		||||
			       struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
@@ -288,7 +288,7 @@ static int read_from_core_sock(struct local_client *client, char *buf, int len,
 | 
			
		||||
    return status<0 ? status : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
 | 
			
		||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, const char *csid,
 | 
			
		||||
			       struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
@@ -346,8 +346,8 @@ static void set_node_state(struct node_info *ninfo, char *csid, uint8_t nodestat
 | 
			
		||||
     */
 | 
			
		||||
    tcp_remove_client(csid);
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("set_node_state, '%s' state = %d (oldstate=%d), num_nodes=%d\n",
 | 
			
		||||
	     ninfo->name, ninfo->state, oldstate, num_nodes);
 | 
			
		||||
    DEBUGLOG("set_node_state, '%s' state = %d num_nodes=%d\n",
 | 
			
		||||
	     ninfo->name, ninfo->state, num_nodes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_t state)
 | 
			
		||||
@@ -582,7 +582,7 @@ int get_next_node_csid(void **context, char *csid)
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int gulm_name_from_csid(char *csid, char *name)
 | 
			
		||||
int gulm_name_from_csid(const char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
@@ -598,7 +598,7 @@ int gulm_name_from_csid(char *csid, char *name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int _csid_from_name(char *csid, char *name)
 | 
			
		||||
static int _csid_from_name(char *csid, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    struct dm_hash_node *hn;
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
@@ -622,7 +622,7 @@ static int _get_num_nodes()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Node is now known to be running a clvmd */
 | 
			
		||||
void gulm_add_up_node(char *csid)
 | 
			
		||||
void gulm_add_up_node(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
@@ -661,7 +661,7 @@ void add_down_node(char *csid)
 | 
			
		||||
 | 
			
		||||
/* Call a callback for each node, so the caller knows whether it's up or down */
 | 
			
		||||
static int _cluster_do_node_callback(struct local_client *master_client,
 | 
			
		||||
				     void (*callback)(struct local_client *, char *csid, int node_up))
 | 
			
		||||
				     void (*callback)(struct local_client *, const char *csid, int node_up))
 | 
			
		||||
{
 | 
			
		||||
    struct dm_hash_node *hn;
 | 
			
		||||
    struct node_info *ninfo;
 | 
			
		||||
@@ -730,7 +730,7 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
    pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
    /* This needs to be converted from DLM/LVM2 value for GULM */
 | 
			
		||||
    if (flags == LCK_NONBLOCK) flags = lg_lock_flag_Try;
 | 
			
		||||
    if (flags & LKF_NOQUEUE) flags = lg_lock_flag_Try;
 | 
			
		||||
 | 
			
		||||
    dm_hash_insert(lock_hash, resource, &lwait);
 | 
			
		||||
    DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
 | 
			
		||||
@@ -828,6 +828,7 @@ static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
        }
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case LCK_PREAD:
 | 
			
		||||
    case LCK_READ:
 | 
			
		||||
	status = _lock_resource(lock1, lg_lock_state_Shared, flags, lockid);
 | 
			
		||||
	if (status)
 | 
			
		||||
@@ -864,6 +865,7 @@ static int _sync_unlock(const char *resource, int lockid)
 | 
			
		||||
    /* The held lock mode is in the lock id */
 | 
			
		||||
    assert(lockid == LCK_EXCL ||
 | 
			
		||||
	   lockid == LCK_READ ||
 | 
			
		||||
	   lockid == LCK_PREAD ||
 | 
			
		||||
	   lockid == LCK_WRITE);
 | 
			
		||||
 | 
			
		||||
    status = _unlock_resource(lock1, lockid);
 | 
			
		||||
@@ -963,14 +965,20 @@ static int _get_main_cluster_fd(void)
 | 
			
		||||
	return get_main_gulm_cluster_fd();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client)
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, const char *csid, struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	return cluster_fd_gulm_callback(fd, buf, len, csid, new_client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
 | 
			
		||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid, const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	return gulm_cluster_send_message(buf, msglen, csid, errtext);
 | 
			
		||||
	return gulm_cluster_send_message((char *)buf, msglen, csid, errtext);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_cluster_name(char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	strncpy(buf, cluster_name, buflen);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops _cluster_gulm_ops = {
 | 
			
		||||
@@ -987,6 +995,7 @@ static struct cluster_ops _cluster_gulm_ops = {
 | 
			
		||||
	.add_up_node              = gulm_add_up_node,
 | 
			
		||||
	.reread_config            = _reread_config,
 | 
			
		||||
	.cluster_closedown        = _cluster_closedown,
 | 
			
		||||
	.get_cluster_name         = _get_cluster_name,
 | 
			
		||||
	.sync_lock                = _sync_lock,
 | 
			
		||||
	.sync_unlock              = _sync_unlock,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,13 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* DLM constant that clvmd uses as a generic NONBLOCK lock flag */
 | 
			
		||||
#define LKF_NOQUEUE 1
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
extern int get_ip_address(const char *node, char *addr);
 | 
			
		||||
extern void tcp_remove_client(const char *csid);
 | 
			
		||||
extern int alloc_client(int fd, const char *csid, struct local_client **new_client);
 | 
			
		||||
 | 
			
		||||
void gulm_add_up_node(char *csid);
 | 
			
		||||
int gulm_name_from_csid(char *csid, char *name);
 | 
			
		||||
void gulm_add_up_node(const char *csid);
 | 
			
		||||
int gulm_name_from_csid(const char *csid, char *name);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										737
									
								
								daemons/clvmd/clvmd-openais.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										737
									
								
								daemons/clvmd/clvmd-openais.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,737 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
**
 | 
			
		||||
**  Copyright (C) 2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
**
 | 
			
		||||
*******************************************************************************
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* This provides the interface between clvmd and OpenAIS as the cluster
 | 
			
		||||
 * and lock manager.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/file.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <utmpx.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
 | 
			
		||||
#include <openais/saAis.h>
 | 
			
		||||
#include <openais/saLck.h>
 | 
			
		||||
#include <openais/cpg.h>
 | 
			
		||||
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
 | 
			
		||||
/* Timeout value for several openais calls */
 | 
			
		||||
#define TIMEOUT 10
 | 
			
		||||
 | 
			
		||||
static void lck_lock_callback(SaInvocationT invocation,
 | 
			
		||||
			      SaLckLockStatusT lockStatus,
 | 
			
		||||
			      SaAisErrorT error);
 | 
			
		||||
static void lck_unlock_callback(SaInvocationT invocation,
 | 
			
		||||
				SaAisErrorT error);
 | 
			
		||||
static void cpg_deliver_callback (cpg_handle_t handle,
 | 
			
		||||
				  struct cpg_name *groupName,
 | 
			
		||||
				  uint32_t nodeid,
 | 
			
		||||
				  uint32_t pid,
 | 
			
		||||
				  void *msg,
 | 
			
		||||
				  int msg_len);
 | 
			
		||||
static void cpg_confchg_callback(cpg_handle_t handle,
 | 
			
		||||
				 struct cpg_name *groupName,
 | 
			
		||||
				 struct cpg_address *member_list, int member_list_entries,
 | 
			
		||||
				 struct cpg_address *left_list, int left_list_entries,
 | 
			
		||||
				 struct cpg_address *joined_list, int joined_list_entries);
 | 
			
		||||
static void _cluster_closedown(void);
 | 
			
		||||
 | 
			
		||||
/* Hash list of nodes in the cluster */
 | 
			
		||||
static struct dm_hash_table *node_hash;
 | 
			
		||||
 | 
			
		||||
/* For associating lock IDs & resource handles */
 | 
			
		||||
static struct dm_hash_table *lock_hash;
 | 
			
		||||
 | 
			
		||||
/* Number of active nodes */
 | 
			
		||||
static int num_nodes;
 | 
			
		||||
static unsigned int our_nodeid;
 | 
			
		||||
 | 
			
		||||
static struct local_client *cluster_client;
 | 
			
		||||
 | 
			
		||||
/* OpenAIS handles */
 | 
			
		||||
static cpg_handle_t cpg_handle;
 | 
			
		||||
static SaLckHandleT lck_handle;
 | 
			
		||||
 | 
			
		||||
static struct cpg_name cpg_group_name;
 | 
			
		||||
 | 
			
		||||
/* Openais callback structs */
 | 
			
		||||
cpg_callbacks_t cpg_callbacks = {
 | 
			
		||||
	.cpg_deliver_fn =            cpg_deliver_callback,
 | 
			
		||||
	.cpg_confchg_fn =            cpg_confchg_callback,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
SaLckCallbacksT lck_callbacks = {
 | 
			
		||||
        .saLckLockGrantCallback      = lck_lock_callback,
 | 
			
		||||
        .saLckResourceUnlockCallback = lck_unlock_callback
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct node_info
 | 
			
		||||
{
 | 
			
		||||
	enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
 | 
			
		||||
	int nodeid;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct lock_info
 | 
			
		||||
{
 | 
			
		||||
	SaLckResourceHandleT res_handle;
 | 
			
		||||
	SaLckLockIdT         lock_id;
 | 
			
		||||
	SaNameT              lock_name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct lock_wait
 | 
			
		||||
{
 | 
			
		||||
	pthread_cond_t cond;
 | 
			
		||||
	pthread_mutex_t mutex;
 | 
			
		||||
	int status;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Set errno to something approximating the right value and return 0 or -1 */
 | 
			
		||||
static int ais_to_errno(SaAisErrorT err)
 | 
			
		||||
{
 | 
			
		||||
	switch(err)
 | 
			
		||||
	{
 | 
			
		||||
	case SA_AIS_OK:
 | 
			
		||||
		return 0;
 | 
			
		||||
        case SA_AIS_ERR_LIBRARY:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_VERSION:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_INIT:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_TIMEOUT:
 | 
			
		||||
		errno = ETIME;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_TRY_AGAIN:
 | 
			
		||||
		errno = EAGAIN;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_INVALID_PARAM:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_NO_MEMORY:
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_BAD_HANDLE:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_BUSY:
 | 
			
		||||
		errno = EBUSY;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_ACCESS:
 | 
			
		||||
		errno = EPERM;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_NOT_EXIST:
 | 
			
		||||
		errno = ENOENT;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_NAME_TOO_LONG:
 | 
			
		||||
		errno = ENAMETOOLONG;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_EXIST:
 | 
			
		||||
		errno = EEXIST;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_NO_SPACE:
 | 
			
		||||
		errno = ENOSPC;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_INTERRUPT:
 | 
			
		||||
		errno = EINTR;
 | 
			
		||||
		break;
 | 
			
		||||
	case SA_AIS_ERR_NAME_NOT_FOUND:
 | 
			
		||||
		errno = ENOENT;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_NO_RESOURCES:
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_NOT_SUPPORTED:
 | 
			
		||||
		errno = EOPNOTSUPP;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_BAD_OPERATION:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_FAILED_OPERATION:
 | 
			
		||||
		errno = EIO;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_MESSAGE_ERROR:
 | 
			
		||||
		errno = EIO;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_QUEUE_FULL:
 | 
			
		||||
		errno = EXFULL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_BAD_FLAGS:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_TOO_BIG:
 | 
			
		||||
		errno = E2BIG;
 | 
			
		||||
		break;
 | 
			
		||||
        case SA_AIS_ERR_NO_SECTIONS:
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *print_csid(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	static char buf[128];
 | 
			
		||||
	int id;
 | 
			
		||||
 | 
			
		||||
	memcpy(&id, csid, sizeof(int));
 | 
			
		||||
	sprintf(buf, "%d", id);
 | 
			
		||||
	return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int add_internal_client(int fd, fd_callback_t callback)
 | 
			
		||||
{
 | 
			
		||||
	struct local_client *client;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Add_internal_client, fd = %d\n", fd);
 | 
			
		||||
 | 
			
		||||
	client = malloc(sizeof(struct local_client));
 | 
			
		||||
	if (!client)
 | 
			
		||||
	{
 | 
			
		||||
		DEBUGLOG("malloc failed\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(client, 0, sizeof(struct local_client));
 | 
			
		||||
	client->fd = fd;
 | 
			
		||||
	client->type = CLUSTER_INTERNAL;
 | 
			
		||||
	client->callback = callback;
 | 
			
		||||
	add_client(client);
 | 
			
		||||
 | 
			
		||||
	/* Set Close-on-exec */
 | 
			
		||||
	fcntl(fd, F_SETFD, 1);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cpg_deliver_callback (cpg_handle_t handle,
 | 
			
		||||
				  struct cpg_name *groupName,
 | 
			
		||||
				  uint32_t nodeid,
 | 
			
		||||
				  uint32_t pid,
 | 
			
		||||
				  void *msg,
 | 
			
		||||
				  int msg_len)
 | 
			
		||||
{
 | 
			
		||||
	int target_nodeid;
 | 
			
		||||
 | 
			
		||||
	memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Got message from nodeid %d for %d. len %d\n",
 | 
			
		||||
		 nodeid, target_nodeid, msg_len-4);
 | 
			
		||||
 | 
			
		||||
	if (target_nodeid == our_nodeid)
 | 
			
		||||
		process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
 | 
			
		||||
				msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cpg_confchg_callback(cpg_handle_t handle,
 | 
			
		||||
				 struct cpg_name *groupName,
 | 
			
		||||
				 struct cpg_address *member_list, int member_list_entries,
 | 
			
		||||
				 struct cpg_address *left_list, int left_list_entries,
 | 
			
		||||
				 struct cpg_address *joined_list, int joined_list_entries)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("confchg callback. %d joined, %d left, %d members\n",
 | 
			
		||||
		 joined_list_entries, left_list_entries, member_list_entries);
 | 
			
		||||
 | 
			
		||||
	for (i=0; i<joined_list_entries; i++) {
 | 
			
		||||
		ninfo = dm_hash_lookup_binary(node_hash,
 | 
			
		||||
					      (char *)&joined_list[i].nodeid,
 | 
			
		||||
					      OPENAIS_CSID_LEN);
 | 
			
		||||
		if (!ninfo) {
 | 
			
		||||
			ninfo = malloc(sizeof(struct node_info));
 | 
			
		||||
			if (!ninfo) {
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				ninfo->nodeid = joined_list[i].nodeid;
 | 
			
		||||
				dm_hash_insert_binary(node_hash,
 | 
			
		||||
						      (char *)&ninfo->nodeid,
 | 
			
		||||
						      OPENAIS_CSID_LEN, ninfo);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ninfo->state = NODE_CLVMD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i=0; i<left_list_entries; i++) {
 | 
			
		||||
		ninfo = dm_hash_lookup_binary(node_hash,
 | 
			
		||||
					      (char *)&left_list[i].nodeid,
 | 
			
		||||
					      OPENAIS_CSID_LEN);
 | 
			
		||||
		if (ninfo)
 | 
			
		||||
			ninfo->state = NODE_DOWN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	num_nodes = joined_list_entries;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void lck_lock_callback(SaInvocationT invocation,
 | 
			
		||||
			      SaLckLockStatusT lockStatus,
 | 
			
		||||
			      SaAisErrorT error)
 | 
			
		||||
{
 | 
			
		||||
	struct lock_wait *lwait = (struct lock_wait *)(long)invocation;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("lck_lock_callback, error = %d\n", error);
 | 
			
		||||
 | 
			
		||||
	lwait->status = error;
 | 
			
		||||
	pthread_mutex_lock(&lwait->mutex);
 | 
			
		||||
	pthread_cond_signal(&lwait->cond);
 | 
			
		||||
	pthread_mutex_unlock(&lwait->mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void lck_unlock_callback(SaInvocationT invocation,
 | 
			
		||||
				SaAisErrorT error)
 | 
			
		||||
{
 | 
			
		||||
	struct lock_wait *lwait = (struct lock_wait *)(long)invocation;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("lck_unlock_callback\n");
 | 
			
		||||
 | 
			
		||||
	lwait->status = SA_AIS_OK;
 | 
			
		||||
	pthread_mutex_lock(&lwait->mutex);
 | 
			
		||||
	pthread_cond_signal(&lwait->cond);
 | 
			
		||||
	pthread_mutex_unlock(&lwait->mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int lck_dispatch(struct local_client *client, char *buf, int len,
 | 
			
		||||
			const char *csid, struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	*new_client = NULL;
 | 
			
		||||
	saLckDispatch(lck_handle, SA_DISPATCH_ONE);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	SaAisErrorT err;
 | 
			
		||||
	SaVersionT  ver = { 'B', 1, 1 };
 | 
			
		||||
	int select_fd;
 | 
			
		||||
 | 
			
		||||
	node_hash = dm_hash_create(100);
 | 
			
		||||
	lock_hash = dm_hash_create(10);
 | 
			
		||||
 | 
			
		||||
	err = cpg_initialize(&cpg_handle,
 | 
			
		||||
			     &cpg_callbacks);
 | 
			
		||||
	if (err != SA_AIS_OK) {
 | 
			
		||||
		syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
 | 
			
		||||
		       err);
 | 
			
		||||
		DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = saLckInitialize(&lck_handle,
 | 
			
		||||
			      &lck_callbacks,
 | 
			
		||||
			      &ver);
 | 
			
		||||
	if (err != SA_AIS_OK) {
 | 
			
		||||
		cpg_initialize(&cpg_handle, &cpg_callbacks);
 | 
			
		||||
		syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
 | 
			
		||||
		       err);
 | 
			
		||||
		DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Connect to the clvmd group */
 | 
			
		||||
	strcpy((char *)cpg_group_name.value, "clvmd");
 | 
			
		||||
	cpg_group_name.length = strlen((char *)cpg_group_name.value);
 | 
			
		||||
	err = cpg_join(cpg_handle, &cpg_group_name);
 | 
			
		||||
	if (err != SA_AIS_OK) {
 | 
			
		||||
		cpg_finalize(cpg_handle);
 | 
			
		||||
		saLckFinalize(lck_handle);
 | 
			
		||||
		syslog(LOG_ERR, "Cannot join clvmd process group");
 | 
			
		||||
		DEBUGLOG("Cannot join clvmd process group: %d\n", err);
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cpg_local_get(cpg_handle,
 | 
			
		||||
			    &our_nodeid);
 | 
			
		||||
	if (err != SA_AIS_OK) {
 | 
			
		||||
		cpg_finalize(cpg_handle);
 | 
			
		||||
		saLckFinalize(lck_handle);
 | 
			
		||||
		syslog(LOG_ERR, "Cannot get local node id\n");
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
	DEBUGLOG("Our local node id is %d\n", our_nodeid);
 | 
			
		||||
 | 
			
		||||
	saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
 | 
			
		||||
	add_internal_client(select_fd, lck_dispatch);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Connected to OpenAIS\n");
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cluster_closedown(void)
 | 
			
		||||
{
 | 
			
		||||
	DEBUGLOG("cluster_closedown\n");
 | 
			
		||||
	unlock_all();
 | 
			
		||||
 | 
			
		||||
	saLckFinalize(lck_handle);
 | 
			
		||||
	cpg_finalize(cpg_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(csid, &our_nodeid, sizeof(int));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* OpenAIS doesn't really have nmode names so we
 | 
			
		||||
   just use the node ID in hex instead */
 | 
			
		||||
static int _csid_from_name(char *csid, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	int nodeid;
 | 
			
		||||
	struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
	if (sscanf(name, "%x", &nodeid) == 1) {
 | 
			
		||||
		ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
 | 
			
		||||
		if (ninfo)
 | 
			
		||||
			return nodeid;
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _name_from_csid(const char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
	ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
 | 
			
		||||
	if (!ninfo)
 | 
			
		||||
	{
 | 
			
		||||
		sprintf(name, "UNKNOWN %s", print_csid(csid));
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sprintf(name, "%x", ninfo->nodeid);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_num_nodes()
 | 
			
		||||
{
 | 
			
		||||
	DEBUGLOG("num_nodes = %d\n", num_nodes);
 | 
			
		||||
	return num_nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Node is now known to be running a clvmd */
 | 
			
		||||
static void _add_up_node(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
	ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
 | 
			
		||||
	if (!ninfo) {
 | 
			
		||||
		DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
 | 
			
		||||
			 print_csid(csid));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
 | 
			
		||||
 | 
			
		||||
	ninfo->state = NODE_CLVMD;
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Call a callback for each node, so the caller knows whether it's up or down */
 | 
			
		||||
static int _cluster_do_node_callback(struct local_client *master_client,
 | 
			
		||||
				     void (*callback)(struct local_client *,
 | 
			
		||||
						      const char *csid, int node_up))
 | 
			
		||||
{
 | 
			
		||||
	struct dm_hash_node *hn;
 | 
			
		||||
	struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
	dm_hash_iterate(hn, node_hash)
 | 
			
		||||
	{
 | 
			
		||||
		char csid[OPENAIS_CSID_LEN];
 | 
			
		||||
 | 
			
		||||
		ninfo = dm_hash_get_data(node_hash, hn);
 | 
			
		||||
		memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
		DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
 | 
			
		||||
			 ninfo->state);
 | 
			
		||||
 | 
			
		||||
		if (ninfo->state != NODE_DOWN)
 | 
			
		||||
			callback(master_client, csid, ninfo->state == NODE_CLVMD);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Real locking */
 | 
			
		||||
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
	struct lock_wait lwait;
 | 
			
		||||
	struct lock_info *linfo;
 | 
			
		||||
	SaLckResourceHandleT res_handle;
 | 
			
		||||
	SaAisErrorT err;
 | 
			
		||||
	SaLckLockIdT lock_id;
 | 
			
		||||
 | 
			
		||||
	pthread_cond_init(&lwait.cond, NULL);
 | 
			
		||||
	pthread_mutex_init(&lwait.mutex, NULL);
 | 
			
		||||
	pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
 | 
			
		||||
	if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
 | 
			
		||||
 | 
			
		||||
	linfo = malloc(sizeof(struct lock_info));
 | 
			
		||||
	if (!linfo)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
 | 
			
		||||
 | 
			
		||||
	linfo->lock_name.length = strlen(resource)+1;
 | 
			
		||||
	strcpy((char *)linfo->lock_name.value, resource);
 | 
			
		||||
 | 
			
		||||
	err = saLckResourceOpen(lck_handle, &linfo->lock_name,
 | 
			
		||||
				SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
 | 
			
		||||
	if (err != SA_AIS_OK)
 | 
			
		||||
	{
 | 
			
		||||
		DEBUGLOG("ResourceOpen returned %d\n", err);
 | 
			
		||||
		free(linfo);
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = saLckResourceLockAsync(res_handle,
 | 
			
		||||
				     (SaInvocationT)(long)&lwait,
 | 
			
		||||
				     &lock_id,
 | 
			
		||||
				     mode,
 | 
			
		||||
				     flags,
 | 
			
		||||
				     0);
 | 
			
		||||
	if (err != SA_AIS_OK)
 | 
			
		||||
	{
 | 
			
		||||
		free(linfo);
 | 
			
		||||
		saLckResourceClose(res_handle);
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Wait for it to complete */
 | 
			
		||||
	pthread_cond_wait(&lwait.cond, &lwait.mutex);
 | 
			
		||||
	pthread_mutex_unlock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", lwait.status,
 | 
			
		||||
		 lock_id);
 | 
			
		||||
 | 
			
		||||
	linfo->lock_id = lock_id;
 | 
			
		||||
	linfo->res_handle = res_handle;
 | 
			
		||||
 | 
			
		||||
	dm_hash_insert(lock_hash, resource, linfo);
 | 
			
		||||
 | 
			
		||||
	return ais_to_errno(lwait.status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int _unlock_resource(char *resource, int lockid)
 | 
			
		||||
{
 | 
			
		||||
	struct lock_wait lwait;
 | 
			
		||||
	SaAisErrorT err;
 | 
			
		||||
	struct lock_info *linfo;
 | 
			
		||||
 | 
			
		||||
	pthread_cond_init(&lwait.cond, NULL);
 | 
			
		||||
	pthread_mutex_init(&lwait.mutex, NULL);
 | 
			
		||||
	pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("unlock_resource %s\n", resource);
 | 
			
		||||
	linfo = dm_hash_lookup(lock_hash, resource);
 | 
			
		||||
	if (!linfo)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("unlock_resource: lockid: %llx\n", linfo->lock_id);
 | 
			
		||||
	err = saLckResourceUnlockAsync((SaInvocationT)(long)&lwait, linfo->lock_id);
 | 
			
		||||
	if (err != SA_AIS_OK)
 | 
			
		||||
	{
 | 
			
		||||
		DEBUGLOG("Unlock returned %d\n", err);
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Wait for it to complete */
 | 
			
		||||
	pthread_cond_wait(&lwait.cond, &lwait.mutex);
 | 
			
		||||
	pthread_mutex_unlock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	/* Release the resource */
 | 
			
		||||
	dm_hash_remove(lock_hash, resource);
 | 
			
		||||
	saLckResourceClose(linfo->res_handle);
 | 
			
		||||
	free(linfo);
 | 
			
		||||
 | 
			
		||||
	return ais_to_errno(lwait.status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	char lock1[strlen(resource)+3];
 | 
			
		||||
	char lock2[strlen(resource)+3];
 | 
			
		||||
 | 
			
		||||
	snprintf(lock1, sizeof(lock1), "%s-1", resource);
 | 
			
		||||
	snprintf(lock2, sizeof(lock2), "%s-2", resource);
 | 
			
		||||
 | 
			
		||||
	switch (mode)
 | 
			
		||||
	{
 | 
			
		||||
	case LCK_EXCL:
 | 
			
		||||
		status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
 | 
			
		||||
		if (status)
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
		/* If we can't get this lock too then bail out */
 | 
			
		||||
		status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
 | 
			
		||||
					lockid);
 | 
			
		||||
		if (status == SA_LCK_LOCK_NOT_QUEUED)
 | 
			
		||||
		{
 | 
			
		||||
			_unlock_resource(lock1, *lockid);
 | 
			
		||||
			status = -1;
 | 
			
		||||
			errno = EAGAIN;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_PREAD:
 | 
			
		||||
	case LCK_READ:
 | 
			
		||||
		status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
 | 
			
		||||
		if (status)
 | 
			
		||||
			goto out;
 | 
			
		||||
		_unlock_resource(lock2, *lockid);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_WRITE:
 | 
			
		||||
		status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
 | 
			
		||||
		if (status)
 | 
			
		||||
			goto out;
 | 
			
		||||
		_unlock_resource(lock1, *lockid);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		status = -1;
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	*lockid = mode;
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _sync_unlock(const char *resource, int lockid)
 | 
			
		||||
{
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	char lock1[strlen(resource)+3];
 | 
			
		||||
	char lock2[strlen(resource)+3];
 | 
			
		||||
 | 
			
		||||
	snprintf(lock1, sizeof(lock1), "%s-1", resource);
 | 
			
		||||
	snprintf(lock2, sizeof(lock2), "%s-2", resource);
 | 
			
		||||
 | 
			
		||||
	_unlock_resource(lock1, lockid);
 | 
			
		||||
	_unlock_resource(lock2, lockid);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* We are always quorate ! */
 | 
			
		||||
static int _is_quorate()
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_main_cluster_fd(void)
 | 
			
		||||
{
 | 
			
		||||
	int select_fd;
 | 
			
		||||
 | 
			
		||||
	cpg_fd_get(cpg_handle, &select_fd);
 | 
			
		||||
	return select_fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
 | 
			
		||||
				const char *csid,
 | 
			
		||||
				struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	cluster_client = fd;
 | 
			
		||||
	*new_client = NULL;
 | 
			
		||||
	cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
 | 
			
		||||
				 const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	struct iovec iov[2];
 | 
			
		||||
	SaAisErrorT err;
 | 
			
		||||
	int target_node;
 | 
			
		||||
 | 
			
		||||
	if (csid)
 | 
			
		||||
		memcpy(&target_node, csid, OPENAIS_CSID_LEN);
 | 
			
		||||
	else
 | 
			
		||||
		target_node = 0;
 | 
			
		||||
 | 
			
		||||
	iov[0].iov_base = &target_node;
 | 
			
		||||
	iov[0].iov_len = sizeof(int);
 | 
			
		||||
	iov[1].iov_base = (char *)buf;
 | 
			
		||||
	iov[1].iov_len = msglen;
 | 
			
		||||
 | 
			
		||||
	err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
 | 
			
		||||
	return ais_to_errno(err);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* We don't have a cluster name to report here */
 | 
			
		||||
static int _get_cluster_name(char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	strncpy(buf, "OpenAIS", buflen);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops _cluster_openais_ops = {
 | 
			
		||||
	.cluster_init_completed   = NULL,
 | 
			
		||||
	.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,
 | 
			
		||||
	.reread_config            = NULL,
 | 
			
		||||
	.cluster_closedown        = _cluster_closedown,
 | 
			
		||||
	.get_cluster_name         = _get_cluster_name,
 | 
			
		||||
	.sync_lock                = _sync_lock,
 | 
			
		||||
	.sync_unlock              = _sync_unlock,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cluster_ops *init_openais_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!_init_cluster())
 | 
			
		||||
		return &_cluster_openais_ops;
 | 
			
		||||
	else
 | 
			
		||||
		return NULL;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
@@ -30,20 +30,21 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <libdlm.h>
 | 
			
		||||
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "version.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
#include "system-lv.h"
 | 
			
		||||
#include "refresh_clvmd.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
 | 
			
		||||
@@ -54,9 +55,7 @@
 | 
			
		||||
#define FALSE 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The maximum size of a message that will fit into a packet. Anything bigger
 | 
			
		||||
   than this is sent via the system LV */
 | 
			
		||||
#define MAX_INLINE_MESSAGE (max_cluster_message-sizeof(struct clvm_header))
 | 
			
		||||
#define MAX_RETRIES 4
 | 
			
		||||
 | 
			
		||||
#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0)
 | 
			
		||||
 | 
			
		||||
@@ -66,7 +65,7 @@ static struct local_client local_client_head;
 | 
			
		||||
 | 
			
		||||
static unsigned short global_xid = 0;	/* Last transaction ID issued */
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops *clops = NULL;
 | 
			
		||||
struct cluster_ops *clops = NULL;
 | 
			
		||||
 | 
			
		||||
static char our_csid[MAX_CSID_LEN];
 | 
			
		||||
static unsigned max_csid_len;
 | 
			
		||||
@@ -84,6 +83,8 @@ struct lvm_thread_cmd {
 | 
			
		||||
	int msglen;
 | 
			
		||||
	unsigned short xid;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
debug_t debug;
 | 
			
		||||
static pthread_t lvm_thread;
 | 
			
		||||
static pthread_mutex_t lvm_thread_mutex;
 | 
			
		||||
static pthread_cond_t lvm_thread_cond;
 | 
			
		||||
@@ -98,6 +99,7 @@ static int child_pipe[2];
 | 
			
		||||
#define DFAIL_LOCAL_SOCK 2
 | 
			
		||||
#define DFAIL_CLUSTER_IF 3
 | 
			
		||||
#define DFAIL_MALLOC     4
 | 
			
		||||
#define DFAIL_TIMEOUT    5
 | 
			
		||||
#define SUCCESS          0
 | 
			
		||||
 | 
			
		||||
/* Prototypes for code further down */
 | 
			
		||||
@@ -109,31 +111,33 @@ static void send_local_reply(struct local_client *client, int status,
 | 
			
		||||
static void free_reply(struct local_client *client);
 | 
			
		||||
static void send_version_message(void);
 | 
			
		||||
static void *pre_and_post_thread(void *arg);
 | 
			
		||||
static int send_message(void *buf, int msglen, char *csid, int fd,
 | 
			
		||||
static int send_message(void *buf, int msglen, const char *csid, int fd,
 | 
			
		||||
			const char *errtext);
 | 
			
		||||
static int read_from_local_sock(struct local_client *thisfd);
 | 
			
		||||
static int process_local_command(struct clvm_header *msg, int msglen,
 | 
			
		||||
				 struct local_client *client,
 | 
			
		||||
				 unsigned short xid);
 | 
			
		||||
static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
 | 
			
		||||
				   char *csid);
 | 
			
		||||
static int process_reply(struct clvm_header *msg, int msglen, char *csid);
 | 
			
		||||
				   const char *csid);
 | 
			
		||||
static int process_reply(const struct clvm_header *msg, int msglen,
 | 
			
		||||
			 const char *csid);
 | 
			
		||||
static int open_local_sock(void);
 | 
			
		||||
static int check_local_clvmd(void);
 | 
			
		||||
static struct local_client *find_client(int clientid);
 | 
			
		||||
static void main_loop(int local_sock, int cmd_timeout);
 | 
			
		||||
static void be_daemon(void);
 | 
			
		||||
static void be_daemon(int start_timeout);
 | 
			
		||||
static int check_all_clvmds_running(struct local_client *client);
 | 
			
		||||
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
 | 
			
		||||
				     int len, char *csid,
 | 
			
		||||
				     int len, const char *csid,
 | 
			
		||||
				     struct local_client **new_client);
 | 
			
		||||
static void *lvm_thread_fn(void *);
 | 
			
		||||
static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
 | 
			
		||||
			   int msglen, char *csid);
 | 
			
		||||
			   int msglen, const char *csid);
 | 
			
		||||
static int distribute_command(struct local_client *thisfd);
 | 
			
		||||
static void hton_clvm(struct clvm_header *hdr);
 | 
			
		||||
static void ntoh_clvm(struct clvm_header *hdr);
 | 
			
		||||
static void add_reply_to_list(struct local_client *client, int status,
 | 
			
		||||
			      char *csid, const char *buf, int len);
 | 
			
		||||
			      const char *csid, const char *buf, int len);
 | 
			
		||||
 | 
			
		||||
static void usage(char *prog, FILE *file)
 | 
			
		||||
{
 | 
			
		||||
@@ -143,7 +147,9 @@ static void usage(char *prog, FILE *file)
 | 
			
		||||
	fprintf(file, "   -V       Show version of clvmd\n");
 | 
			
		||||
	fprintf(file, "   -h       Show this help information\n");
 | 
			
		||||
	fprintf(file, "   -d       Don't fork, run in the foreground\n");
 | 
			
		||||
	fprintf(file, "   -R       Tell all running clvmds in the cluster to reload their device cache\n");
 | 
			
		||||
	fprintf(file, "   -t<secs> Command timeout (default 60 seconds)\n");
 | 
			
		||||
	fprintf(file, "   -T<secs> Startup timeout (default none)\n");
 | 
			
		||||
	fprintf(file, "\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -159,21 +165,46 @@ static void child_init_signal(int status)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void debuglog(const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	time_t P;
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	static int syslog_init = 0;
 | 
			
		||||
 | 
			
		||||
	if (debug == DEBUG_STDERR) {
 | 
			
		||||
		va_start(ap,fmt);
 | 
			
		||||
		time(&P);
 | 
			
		||||
		fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 );
 | 
			
		||||
		vfprintf(stderr, fmt, ap);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
	}
 | 
			
		||||
	if (debug == DEBUG_SYSLOG) {
 | 
			
		||||
		if (!syslog_init)
 | 
			
		||||
			openlog("clvmd", LOG_PID, LOG_DAEMON);
 | 
			
		||||
 | 
			
		||||
		va_start(ap,fmt);
 | 
			
		||||
		vsyslog(LOG_DEBUG, fmt, ap);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	int local_sock;
 | 
			
		||||
	struct local_client *newfd;
 | 
			
		||||
	struct utsname nodeinfo;
 | 
			
		||||
	signed char opt;
 | 
			
		||||
	int debug = 0;
 | 
			
		||||
	int cmd_timeout = DEFAULT_CMD_TIMEOUT;
 | 
			
		||||
	int start_timeout = 0;
 | 
			
		||||
	sigset_t ss;
 | 
			
		||||
	int using_gulm = 0;
 | 
			
		||||
	int debug_opt = 0;
 | 
			
		||||
	int clusterwide_opt = 0;
 | 
			
		||||
 | 
			
		||||
	/* Deal with command-line arguments */
 | 
			
		||||
	opterr = 0;
 | 
			
		||||
	optind = 0;
 | 
			
		||||
	while ((opt = getopt(argc, argv, "?vVhdt:")) != EOF) {
 | 
			
		||||
	while ((opt = getopt(argc, argv, "?vVhd::t:RT:C")) != EOF) {
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
		case 'h':
 | 
			
		||||
			usage(argv[0], stdout);
 | 
			
		||||
@@ -183,8 +214,19 @@ int main(int argc, char *argv[])
 | 
			
		||||
			usage(argv[0], stderr);
 | 
			
		||||
			exit(0);
 | 
			
		||||
 | 
			
		||||
		case 'R':
 | 
			
		||||
			return refresh_clvmd();
 | 
			
		||||
 | 
			
		||||
		case 'C':
 | 
			
		||||
			clusterwide_opt = 1;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case 'd':
 | 
			
		||||
			debug++;
 | 
			
		||||
			debug_opt = 1;
 | 
			
		||||
			if (optarg)
 | 
			
		||||
				debug = atoi(optarg);
 | 
			
		||||
			else
 | 
			
		||||
				debug = DEBUG_STDERR;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case 't':
 | 
			
		||||
@@ -195,6 +237,14 @@ int main(int argc, char *argv[])
 | 
			
		||||
				exit(1);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 'T':
 | 
			
		||||
			start_timeout = atoi(optarg);
 | 
			
		||||
			if (start_timeout <= 0) {
 | 
			
		||||
				fprintf(stderr, "startup timeout is invalid\n");
 | 
			
		||||
				usage(argv[0], stderr);
 | 
			
		||||
				exit(1);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case 'V':
 | 
			
		||||
		        printf("Cluster LVM daemon version: %s\n", LVM_VERSION);
 | 
			
		||||
@@ -207,9 +257,18 @@ int main(int argc, char *argv[])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Setting debug options on an existing clvmd */
 | 
			
		||||
	if (debug_opt && !check_local_clvmd()) {
 | 
			
		||||
 | 
			
		||||
		/* Sending to stderr makes no sense for a detached daemon */
 | 
			
		||||
		if (debug == DEBUG_STDERR)
 | 
			
		||||
			debug = DEBUG_SYSLOG;
 | 
			
		||||
		return debug_clvmd(debug, clusterwide_opt);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Fork into the background (unless requested not to) */
 | 
			
		||||
	if (!debug) {
 | 
			
		||||
		be_daemon();
 | 
			
		||||
	if (debug != DEBUG_STDERR) {
 | 
			
		||||
		be_daemon(start_timeout);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("CLVMD started\n");
 | 
			
		||||
@@ -247,7 +306,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
	if ((clops = init_cman_cluster())) {
 | 
			
		||||
		max_csid_len = CMAN_MAX_CSID_LEN;
 | 
			
		||||
		max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
 | 
			
		||||
		max_cluster_member_name_len = CMAN_MAX_CLUSTER_MEMBER_NAME_LEN;
 | 
			
		||||
		max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
 | 
			
		||||
		syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -261,6 +320,15 @@ int main(int argc, char *argv[])
 | 
			
		||||
			syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to GULM");
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_OPENAIS
 | 
			
		||||
	if (!clops)
 | 
			
		||||
		if ((clops = init_openais_cluster())) {
 | 
			
		||||
			max_csid_len = OPENAIS_CSID_LEN;
 | 
			
		||||
			max_cluster_message = OPENAIS_MAX_CLUSTER_MESSAGE;
 | 
			
		||||
			max_cluster_member_name_len = OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN;
 | 
			
		||||
			syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to OpenAIS");
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (!clops) {
 | 
			
		||||
		DEBUGLOG("Can't initialise cluster interface\n");
 | 
			
		||||
@@ -293,7 +361,8 @@ int main(int argc, char *argv[])
 | 
			
		||||
	/* This needs to be started after cluster initialisation
 | 
			
		||||
	   as it may need to take out locks */
 | 
			
		||||
	DEBUGLOG("starting LVM thread\n");
 | 
			
		||||
	pthread_create(&lvm_thread, NULL, lvm_thread_fn, (void *)using_gulm);
 | 
			
		||||
	pthread_create(&lvm_thread, NULL, lvm_thread_fn,
 | 
			
		||||
			(void *)(long)using_gulm);
 | 
			
		||||
 | 
			
		||||
	/* Tell the rest of the cluster our version number */
 | 
			
		||||
	/* CMAN can do this immediately, gulm needs to wait until
 | 
			
		||||
@@ -324,7 +393,8 @@ void clvmd_cluster_init_completed()
 | 
			
		||||
 | 
			
		||||
/* Data on a connected socket */
 | 
			
		||||
static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
 | 
			
		||||
			       char *csid, struct local_client **new_client)
 | 
			
		||||
			       const char *csid,
 | 
			
		||||
			       struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	*new_client = NULL;
 | 
			
		||||
	return read_from_local_sock(thisfd);
 | 
			
		||||
@@ -332,7 +402,7 @@ static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
 | 
			
		||||
 | 
			
		||||
/* Data on a connected socket */
 | 
			
		||||
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
 | 
			
		||||
				     int len, char *csid,
 | 
			
		||||
				     int len, const char *csid,
 | 
			
		||||
				     struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	/* Someone connected to our local socket, accept it. */
 | 
			
		||||
@@ -342,6 +412,9 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
 | 
			
		||||
	socklen_t sl = sizeof(socka);
 | 
			
		||||
	int client_fd = accept(thisfd->fd, (struct sockaddr *) &socka, &sl);
 | 
			
		||||
 | 
			
		||||
	if (client_fd == -1 && errno == EINTR)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (client_fd >= 0) {
 | 
			
		||||
		newfd = malloc(sizeof(struct local_client));
 | 
			
		||||
		if (!newfd) {
 | 
			
		||||
@@ -370,7 +443,7 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int local_pipe_callback(struct local_client *thisfd, char *buf,
 | 
			
		||||
			       int maxlen, char *csid,
 | 
			
		||||
			       int maxlen, const char *csid,
 | 
			
		||||
			       struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	int len;
 | 
			
		||||
@@ -379,17 +452,20 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
 | 
			
		||||
	int status = -1;	/* in error by default */
 | 
			
		||||
 | 
			
		||||
	len = read(thisfd->fd, buffer, sizeof(int));
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
 | 
			
		||||
		 thisfd->fd, len, *(int *) buffer);
 | 
			
		||||
	if (len == -1 && errno == EINTR)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (len == sizeof(int)) {
 | 
			
		||||
		status = *(int *) buffer;
 | 
			
		||||
		memcpy(&status, buffer, sizeof(int));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
 | 
			
		||||
		 thisfd->fd, len, status);
 | 
			
		||||
 | 
			
		||||
	/* EOF on pipe or an error, close it */
 | 
			
		||||
	if (len <= 0) {
 | 
			
		||||
		int jstat;
 | 
			
		||||
		void *ret = &status;
 | 
			
		||||
		close(thisfd->fd);
 | 
			
		||||
 | 
			
		||||
		/* Clear out the cross-link */
 | 
			
		||||
@@ -399,9 +475,7 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
 | 
			
		||||
 | 
			
		||||
		/* Reap child thread */
 | 
			
		||||
		if (thisfd->bits.pipe.threadid) {
 | 
			
		||||
			jstat =
 | 
			
		||||
			    pthread_join(thisfd->bits.pipe.threadid,
 | 
			
		||||
					 (void **) &status);
 | 
			
		||||
			jstat = pthread_join(thisfd->bits.pipe.threadid, &ret);
 | 
			
		||||
			thisfd->bits.pipe.threadid = 0;
 | 
			
		||||
			if (thisfd->bits.pipe.client != NULL)
 | 
			
		||||
				thisfd->bits.pipe.client->bits.localsock.
 | 
			
		||||
@@ -445,7 +519,7 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
 | 
			
		||||
   add one with "ETIMEDOUT".
 | 
			
		||||
   NOTE: This won't race with real replies because they happen in the same thread.
 | 
			
		||||
*/
 | 
			
		||||
static void timedout_callback(struct local_client *client, char *csid,
 | 
			
		||||
static void timedout_callback(struct local_client *client, const char *csid,
 | 
			
		||||
			      int node_up)
 | 
			
		||||
{
 | 
			
		||||
	if (node_up) {
 | 
			
		||||
@@ -509,6 +583,7 @@ static void main_loop(int local_sock, int cmd_timeout)
 | 
			
		||||
		int quorate = clops->is_quorate();
 | 
			
		||||
 | 
			
		||||
		/* Wait on the cluster FD and all local sockets/pipes */
 | 
			
		||||
		local_client_head.fd = clops->get_main_cluster_fd();
 | 
			
		||||
		FD_ZERO(&in);
 | 
			
		||||
		for (thisfd = &local_client_head; thisfd != NULL;
 | 
			
		||||
		     thisfd = thisfd->next) {
 | 
			
		||||
@@ -641,16 +716,66 @@ static void main_loop(int local_sock, int cmd_timeout)
 | 
			
		||||
	close(local_sock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
 | 
			
		||||
{
 | 
			
		||||
	int child_status;
 | 
			
		||||
	int sstat;
 | 
			
		||||
	fd_set fds;
 | 
			
		||||
	struct timeval tv = {timeout, 0};
 | 
			
		||||
 | 
			
		||||
	FD_ZERO(&fds);
 | 
			
		||||
	FD_SET(c_pipe, &fds);
 | 
			
		||||
 | 
			
		||||
	sstat = select(c_pipe+1, &fds, NULL, NULL, timeout? &tv: NULL);
 | 
			
		||||
	if (sstat == 0) {
 | 
			
		||||
		fprintf(stderr, "clvmd startup timed out\n");
 | 
			
		||||
		exit(DFAIL_TIMEOUT);
 | 
			
		||||
	}
 | 
			
		||||
	if (sstat == 1) {
 | 
			
		||||
		if (read(c_pipe, &child_status, sizeof(child_status)) !=
 | 
			
		||||
		    sizeof(child_status)) {
 | 
			
		||||
 | 
			
		||||
			fprintf(stderr, "clvmd failed in initialisation\n");
 | 
			
		||||
			exit(DFAIL_INIT);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			switch (child_status) {
 | 
			
		||||
			case SUCCESS:
 | 
			
		||||
				break;
 | 
			
		||||
			case DFAIL_INIT:
 | 
			
		||||
				fprintf(stderr, "clvmd failed in initialisation\n");
 | 
			
		||||
				break;
 | 
			
		||||
			case DFAIL_LOCAL_SOCK:
 | 
			
		||||
				fprintf(stderr, "clvmd could not create local socket\n");
 | 
			
		||||
				fprintf(stderr, "Another clvmd is probably already running\n");
 | 
			
		||||
				break;
 | 
			
		||||
			case DFAIL_CLUSTER_IF:
 | 
			
		||||
				fprintf(stderr, "clvmd could not connect to cluster manager\n");
 | 
			
		||||
				fprintf(stderr, "Consult syslog for more information\n");
 | 
			
		||||
				break;
 | 
			
		||||
			case DFAIL_MALLOC:
 | 
			
		||||
				fprintf(stderr, "clvmd failed, not enough memory\n");
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				fprintf(stderr, "clvmd failed, error was %d\n", child_status);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			exit(child_status);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fprintf(stderr, "clvmd startup, select failed: %s\n", strerror(errno));
 | 
			
		||||
	exit(DFAIL_INIT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Fork into the background and detach from our parent process.
 | 
			
		||||
 * In the interests of user-friendliness we wait for the daemon
 | 
			
		||||
 * to complete initialisation before returning its status
 | 
			
		||||
 * the the user.
 | 
			
		||||
 */
 | 
			
		||||
static void be_daemon()
 | 
			
		||||
static void be_daemon(int timeout)
 | 
			
		||||
{
 | 
			
		||||
        pid_t pid;
 | 
			
		||||
	int child_status;
 | 
			
		||||
	int devnull = open("/dev/null", O_RDWR);
 | 
			
		||||
	if (devnull == -1) {
 | 
			
		||||
		perror("Can't open /dev/null");
 | 
			
		||||
@@ -670,36 +795,7 @@ static void be_daemon()
 | 
			
		||||
 | 
			
		||||
	default:       /* Parent */
 | 
			
		||||
		close(child_pipe[1]);
 | 
			
		||||
		if (read(child_pipe[0], &child_status, sizeof(child_status)) !=
 | 
			
		||||
		    sizeof(child_status)) {
 | 
			
		||||
 | 
			
		||||
		        fprintf(stderr, "clvmd failed in initialisation\n");
 | 
			
		||||
		        exit(DFAIL_INIT);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
		        switch (child_status) {
 | 
			
		||||
			case SUCCESS:
 | 
			
		||||
			        break;
 | 
			
		||||
			case DFAIL_INIT:
 | 
			
		||||
			        fprintf(stderr, "clvmd failed in initialisation\n");
 | 
			
		||||
				break;
 | 
			
		||||
			case DFAIL_LOCAL_SOCK:
 | 
			
		||||
			        fprintf(stderr, "clvmd could not create local socket\n");
 | 
			
		||||
				fprintf(stderr, "Another clvmd is probably already running\n");
 | 
			
		||||
				break;
 | 
			
		||||
			case DFAIL_CLUSTER_IF:
 | 
			
		||||
			        fprintf(stderr, "clvmd could not connect to cluster manager\n");
 | 
			
		||||
				fprintf(stderr, "Consult syslog for more information\n");
 | 
			
		||||
				break;
 | 
			
		||||
			case DFAIL_MALLOC:
 | 
			
		||||
			        fprintf(stderr, "clvmd failed, not enough memory\n");
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
			        fprintf(stderr, "clvmd failed, error was %d\n", child_status);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			exit(child_status);
 | 
			
		||||
		}
 | 
			
		||||
		wait_for_child(child_pipe[0], timeout);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Detach ourself from the calling environment */
 | 
			
		||||
@@ -732,6 +828,8 @@ static int read_from_local_sock(struct local_client *thisfd)
 | 
			
		||||
	char buffer[PIPE_BUF];
 | 
			
		||||
 | 
			
		||||
	len = read(thisfd->fd, buffer, sizeof(buffer));
 | 
			
		||||
	if (len == -1 && errno == EINTR)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Read on local socket %d, len = %d\n", thisfd->fd, len);
 | 
			
		||||
 | 
			
		||||
@@ -847,8 +945,12 @@ static int read_from_local_sock(struct local_client *thisfd)
 | 
			
		||||
		    len - strlen(inheader->node) - sizeof(struct clvm_header);
 | 
			
		||||
		missing_len = inheader->arglen - argslen;
 | 
			
		||||
 | 
			
		||||
		if (missing_len < 0)
 | 
			
		||||
			missing_len = 0;
 | 
			
		||||
 | 
			
		||||
		/* Save the message */
 | 
			
		||||
		thisfd->bits.localsock.cmd = malloc(len + missing_len);
 | 
			
		||||
 | 
			
		||||
		if (!thisfd->bits.localsock.cmd) {
 | 
			
		||||
			struct clvm_header reply;
 | 
			
		||||
			reply.cmd = CLVMD_CMD_REPLY;
 | 
			
		||||
@@ -873,9 +975,8 @@ static int read_from_local_sock(struct local_client *thisfd)
 | 
			
		||||
				DEBUGLOG
 | 
			
		||||
				    ("got %d bytes, need another %d (total %d)\n",
 | 
			
		||||
				     argslen, missing_len, inheader->arglen);
 | 
			
		||||
				len =
 | 
			
		||||
				    read(thisfd->fd, argptr + argslen,
 | 
			
		||||
					 missing_len);
 | 
			
		||||
				len = read(thisfd->fd, argptr + argslen,
 | 
			
		||||
					   missing_len);
 | 
			
		||||
				if (len >= 0) {
 | 
			
		||||
					missing_len -= len;
 | 
			
		||||
					argslen += len;
 | 
			
		||||
@@ -985,31 +1086,6 @@ int add_client(struct local_client *new_client)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Send a long message using the System LV
 | 
			
		||||
 */
 | 
			
		||||
static int send_long_message(struct local_client *thisfd, struct clvm_header *inheader, int len)
 | 
			
		||||
{
 | 
			
		||||
    struct clvm_header new_header;
 | 
			
		||||
    int status;
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("Long message: being sent via system LV:\n");
 | 
			
		||||
 | 
			
		||||
    /* Use System LV */
 | 
			
		||||
    status = system_lv_write_data((char *)inheader, len);
 | 
			
		||||
    if (status < 0)
 | 
			
		||||
	    return errno;
 | 
			
		||||
 | 
			
		||||
    /* Send message indicating System-LV is being used */
 | 
			
		||||
    memcpy(&new_header, inheader, sizeof(new_header));
 | 
			
		||||
    new_header.flags |= CLVMD_FLAG_SYSTEMLV;
 | 
			
		||||
    new_header.xid = thisfd->xid;
 | 
			
		||||
 | 
			
		||||
    return send_message(&new_header, sizeof(new_header), NULL, -1,
 | 
			
		||||
		 "Error forwarding long message to cluster");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called when the pre-command has completed successfully - we
 | 
			
		||||
   now execute the real command on all the requested nodes */
 | 
			
		||||
static int distribute_command(struct local_client *thisfd)
 | 
			
		||||
@@ -1036,13 +1112,9 @@ static int distribute_command(struct local_client *thisfd)
 | 
			
		||||
			add_to_lvmqueue(thisfd, inheader, len, NULL);
 | 
			
		||||
 | 
			
		||||
			DEBUGLOG("Sending message to all cluster nodes\n");
 | 
			
		||||
			if (len > MAX_INLINE_MESSAGE) {
 | 
			
		||||
			        send_long_message(thisfd, inheader, len );
 | 
			
		||||
			} else {
 | 
			
		||||
				inheader->xid = thisfd->xid;
 | 
			
		||||
				send_message(inheader, len, NULL, -1,
 | 
			
		||||
					     "Error forwarding message to cluster");
 | 
			
		||||
			}
 | 
			
		||||
			inheader->xid = thisfd->xid;
 | 
			
		||||
			send_message(inheader, len, NULL, -1,
 | 
			
		||||
				     "Error forwarding message to cluster");
 | 
			
		||||
		} else {
 | 
			
		||||
                        /* Do it on a single node */
 | 
			
		||||
			char csid[MAX_CSID_LEN];
 | 
			
		||||
@@ -1063,14 +1135,10 @@ static int distribute_command(struct local_client *thisfd)
 | 
			
		||||
				} else {
 | 
			
		||||
					DEBUGLOG("Sending message to single node: %s\n",
 | 
			
		||||
						 inheader->node);
 | 
			
		||||
					if (len > MAX_INLINE_MESSAGE) {
 | 
			
		||||
					        send_long_message(thisfd, inheader, len );
 | 
			
		||||
					} else {
 | 
			
		||||
						inheader->xid = thisfd->xid;
 | 
			
		||||
						send_message(inheader, len,
 | 
			
		||||
							     csid, -1,
 | 
			
		||||
							     "Error forwarding message to cluster node");
 | 
			
		||||
					}
 | 
			
		||||
					inheader->xid = thisfd->xid;
 | 
			
		||||
					send_message(inheader, len,
 | 
			
		||||
						     csid, -1,
 | 
			
		||||
						     "Error forwarding message to cluster node");
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -1085,8 +1153,8 @@ static int distribute_command(struct local_client *thisfd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Process a command from a remote node and return the result */
 | 
			
		||||
void process_remote_command(struct clvm_header *msg, int msglen, int fd,
 | 
			
		||||
			    char *csid)
 | 
			
		||||
static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
 | 
			
		||||
			    	   const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	char *replyargs;
 | 
			
		||||
	char nodename[max_cluster_member_name_len];
 | 
			
		||||
@@ -1101,54 +1169,6 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
 | 
			
		||||
	DEBUGLOG("process_remote_command %d for clientid 0x%x XID %d on node %s\n",
 | 
			
		||||
		 msg->cmd, msg->clientid, msg->xid, nodename);
 | 
			
		||||
 | 
			
		||||
	/* Is the data to be found in the system LV ? */
 | 
			
		||||
	if (msg->flags & CLVMD_FLAG_SYSTEMLV) {
 | 
			
		||||
		struct clvm_header *newmsg;
 | 
			
		||||
 | 
			
		||||
		DEBUGLOG("Reading message from system LV\n");
 | 
			
		||||
		newmsg =
 | 
			
		||||
		    (struct clvm_header *) malloc(msg->arglen +
 | 
			
		||||
						  sizeof(struct clvm_header));
 | 
			
		||||
		if (newmsg) {
 | 
			
		||||
			if (system_lv_read_data
 | 
			
		||||
			    (nodename, (char *) newmsg,
 | 
			
		||||
			     (size_t *) &msglen) == 0) {
 | 
			
		||||
				msg = newmsg;
 | 
			
		||||
				msg_malloced = 1;
 | 
			
		||||
			} else {
 | 
			
		||||
				struct clvm_header head;
 | 
			
		||||
				DEBUGLOG("System LV read failed\n");
 | 
			
		||||
 | 
			
		||||
				/* Return a failure response */
 | 
			
		||||
				head.cmd = CLVMD_CMD_REPLY;
 | 
			
		||||
				head.status = EFBIG;
 | 
			
		||||
				head.flags = 0;
 | 
			
		||||
				head.clientid = msg->clientid;
 | 
			
		||||
				head.arglen = 0;
 | 
			
		||||
				head.node[0] = '\0';
 | 
			
		||||
				send_message(&head, sizeof(struct clvm_header),
 | 
			
		||||
					     csid, fd,
 | 
			
		||||
					     "Error sending ENOMEM command reply");
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			struct clvm_header head;
 | 
			
		||||
			DEBUGLOG
 | 
			
		||||
			    ("Error attempting to malloc %d bytes for system LV read\n",
 | 
			
		||||
			     msg->arglen);
 | 
			
		||||
			/* Return a failure response */
 | 
			
		||||
			head.cmd = CLVMD_CMD_REPLY;
 | 
			
		||||
			head.status = ENOMEM;
 | 
			
		||||
			head.flags = 0;
 | 
			
		||||
			head.clientid = msg->clientid;
 | 
			
		||||
			head.arglen = 0;
 | 
			
		||||
			head.node[0] = '\0';
 | 
			
		||||
			send_message(&head, sizeof(struct clvm_header), csid,
 | 
			
		||||
				     fd, "Error sending ENOMEM command reply");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check for GOAWAY and sulk */
 | 
			
		||||
	if (msg->cmd == CLVMD_CMD_GOAWAY) {
 | 
			
		||||
 | 
			
		||||
@@ -1160,8 +1180,11 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
 | 
			
		||||
	/* Version check is internal - don't bother exposing it in
 | 
			
		||||
	   clvmd-command.c */
 | 
			
		||||
	if (msg->cmd == CLVMD_CMD_VERSION) {
 | 
			
		||||
		int *version_nums = (int *) msg->args;
 | 
			
		||||
		int version_nums[3];
 | 
			
		||||
		char node[256];
 | 
			
		||||
 | 
			
		||||
		memcpy(version_nums, msg->args, sizeof(version_nums));
 | 
			
		||||
 | 
			
		||||
		clops->name_from_csid(csid, node);
 | 
			
		||||
		DEBUGLOG("Remote node %s is version %d.%d.%d\n",
 | 
			
		||||
			 node,
 | 
			
		||||
@@ -1220,40 +1243,16 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
 | 
			
		||||
				replyargs, replylen);
 | 
			
		||||
 | 
			
		||||
			agghead->xid = msg->xid;
 | 
			
		||||
 | 
			
		||||
			/* Use the system LV ? */
 | 
			
		||||
			if (replylen > MAX_INLINE_MESSAGE) {
 | 
			
		||||
				agghead->cmd = CLVMD_CMD_REPLY;
 | 
			
		||||
				agghead->status = status;
 | 
			
		||||
				agghead->flags = CLVMD_FLAG_SYSTEMLV;
 | 
			
		||||
				agghead->clientid = msg->clientid;
 | 
			
		||||
				agghead->arglen = replylen;
 | 
			
		||||
				agghead->node[0] = '\0';
 | 
			
		||||
 | 
			
		||||
				/* If System LV operation failed then report it as EFBIG but only do it
 | 
			
		||||
				   if the data buffer has something in it. */
 | 
			
		||||
				if (system_lv_write_data(aggreply,
 | 
			
		||||
							 replylen + sizeof(struct clvm_header)) < 0
 | 
			
		||||
				    && replylen > 0)
 | 
			
		||||
					agghead->status = EFBIG;
 | 
			
		||||
 | 
			
		||||
				send_message(agghead,
 | 
			
		||||
					     sizeof(struct clvm_header), csid,
 | 
			
		||||
					     fd,
 | 
			
		||||
					     "Error sending long command reply");
 | 
			
		||||
 | 
			
		||||
			} else {
 | 
			
		||||
				agghead->cmd = CLVMD_CMD_REPLY;
 | 
			
		||||
				agghead->status = status;
 | 
			
		||||
				agghead->flags = 0;
 | 
			
		||||
				agghead->clientid = msg->clientid;
 | 
			
		||||
				agghead->arglen = replylen;
 | 
			
		||||
				agghead->node[0] = '\0';
 | 
			
		||||
				send_message(aggreply,
 | 
			
		||||
					     sizeof(struct clvm_header) +
 | 
			
		||||
					     replylen, csid, fd,
 | 
			
		||||
					     "Error sending command reply");
 | 
			
		||||
			}
 | 
			
		||||
			agghead->cmd = CLVMD_CMD_REPLY;
 | 
			
		||||
			agghead->status = status;
 | 
			
		||||
			agghead->flags = 0;
 | 
			
		||||
			agghead->clientid = msg->clientid;
 | 
			
		||||
			agghead->arglen = replylen;
 | 
			
		||||
			agghead->node[0] = '\0';
 | 
			
		||||
			send_message(aggreply,
 | 
			
		||||
				     sizeof(struct clvm_header) +
 | 
			
		||||
				     replylen, csid, fd,
 | 
			
		||||
				     "Error sending command reply");
 | 
			
		||||
		} else {
 | 
			
		||||
			struct clvm_header head;
 | 
			
		||||
 | 
			
		||||
@@ -1282,7 +1281,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
 | 
			
		||||
   If we have got a full set then send them to the waiting client down the local
 | 
			
		||||
   socket */
 | 
			
		||||
static void add_reply_to_list(struct local_client *client, int status,
 | 
			
		||||
			      char *csid, const char *buf, int len)
 | 
			
		||||
			      const char *csid, const char *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
	struct node_reply *reply;
 | 
			
		||||
 | 
			
		||||
@@ -1333,10 +1332,11 @@ static void add_reply_to_list(struct local_client *client, int status,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is the thread that runs the PRE and post commands for a particular connection */
 | 
			
		||||
static void *pre_and_post_thread(void *arg)
 | 
			
		||||
static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct local_client *client = (struct local_client *) arg;
 | 
			
		||||
	int status;
 | 
			
		||||
	int write_status;
 | 
			
		||||
	sigset_t ss;
 | 
			
		||||
	int pipe_fd = client->bits.localsock.pipe;
 | 
			
		||||
 | 
			
		||||
@@ -1366,8 +1366,23 @@ static void *pre_and_post_thread(void *arg)
 | 
			
		||||
			client->bits.localsock.all_success = 0;
 | 
			
		||||
 | 
			
		||||
		DEBUGLOG("Writing status %d down pipe %d\n", status, pipe_fd);
 | 
			
		||||
 | 
			
		||||
		/* Tell the parent process we have finished this bit */
 | 
			
		||||
		write(pipe_fd, &status, sizeof(int));
 | 
			
		||||
		do {
 | 
			
		||||
			write_status = write(pipe_fd, &status, sizeof(int));
 | 
			
		||||
			if (write_status == sizeof(int))
 | 
			
		||||
				break;
 | 
			
		||||
			if (write_status < 0 &&
 | 
			
		||||
			    (errno == EINTR || errno == EAGAIN))
 | 
			
		||||
				continue;
 | 
			
		||||
			log_error("Error sending to pipe: %m\n");
 | 
			
		||||
			break;
 | 
			
		||||
		} while(1);
 | 
			
		||||
 | 
			
		||||
		if (status) {
 | 
			
		||||
			client->bits.localsock.state = POST_COMMAND;
 | 
			
		||||
			goto next_pre;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* We may need to wait for the condition variable before running the post command */
 | 
			
		||||
		pthread_mutex_lock(&client->bits.localsock.mutex);
 | 
			
		||||
@@ -1386,8 +1401,17 @@ static void *pre_and_post_thread(void *arg)
 | 
			
		||||
		status = 0;
 | 
			
		||||
		do_post_command(client);
 | 
			
		||||
 | 
			
		||||
		write(pipe_fd, &status, sizeof(int));
 | 
			
		||||
 | 
			
		||||
		do {
 | 
			
		||||
			write_status = write(pipe_fd, &status, sizeof(int));
 | 
			
		||||
			if (write_status == sizeof(int))
 | 
			
		||||
				break;
 | 
			
		||||
			if (write_status < 0 &&
 | 
			
		||||
			    (errno == EINTR || errno == EAGAIN))
 | 
			
		||||
				continue;
 | 
			
		||||
			log_error("Error sending to pipe: %m\n");
 | 
			
		||||
			break;
 | 
			
		||||
		} while(1);
 | 
			
		||||
next_pre:
 | 
			
		||||
		DEBUGLOG("Waiting for next pre command\n");
 | 
			
		||||
 | 
			
		||||
		pthread_mutex_lock(&client->bits.localsock.mutex);
 | 
			
		||||
@@ -1401,7 +1425,6 @@ static void *pre_and_post_thread(void *arg)
 | 
			
		||||
	}
 | 
			
		||||
	DEBUGLOG("Subthread finished\n");
 | 
			
		||||
	pthread_exit((void *) 0);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Process a command on the local node and store the result */
 | 
			
		||||
@@ -1437,7 +1460,7 @@ static int process_local_command(struct clvm_header *msg, int msglen,
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int process_reply(struct clvm_header *msg, int msglen, char *csid)
 | 
			
		||||
static int process_reply(const struct clvm_header *msg, int msglen, const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	struct local_client *client = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -1510,7 +1533,7 @@ static void send_local_reply(struct local_client *client, int status, int fd)
 | 
			
		||||
		if (thisreply->status)
 | 
			
		||||
			clientreply->flags |= CLVMD_FLAG_NODEERRS;
 | 
			
		||||
 | 
			
		||||
		*(int *) ptr = thisreply->status;
 | 
			
		||||
		memcpy(ptr, &thisreply->status, sizeof(int));
 | 
			
		||||
		ptr += sizeof(int);
 | 
			
		||||
 | 
			
		||||
		if (thisreply->replymsg) {
 | 
			
		||||
@@ -1566,28 +1589,36 @@ static void send_version_message()
 | 
			
		||||
{
 | 
			
		||||
	char message[sizeof(struct clvm_header) + sizeof(int) * 3];
 | 
			
		||||
	struct clvm_header *msg = (struct clvm_header *) message;
 | 
			
		||||
	int *version_nums = (int *) msg->args;
 | 
			
		||||
	int version_nums[3];
 | 
			
		||||
 | 
			
		||||
	msg->cmd = CLVMD_CMD_VERSION;
 | 
			
		||||
	msg->status = 0;
 | 
			
		||||
	msg->flags = 0;
 | 
			
		||||
	msg->clientid = 0;
 | 
			
		||||
	msg->arglen = sizeof(int) * 3;
 | 
			
		||||
	msg->arglen = sizeof(version_nums);
 | 
			
		||||
 | 
			
		||||
	version_nums[0] = htonl(CLVMD_MAJOR_VERSION);
 | 
			
		||||
	version_nums[1] = htonl(CLVMD_MINOR_VERSION);
 | 
			
		||||
	version_nums[2] = htonl(CLVMD_PATCH_VERSION);
 | 
			
		||||
 | 
			
		||||
	memcpy(&msg->args, version_nums, sizeof(version_nums));
 | 
			
		||||
 | 
			
		||||
	hton_clvm(msg);
 | 
			
		||||
 | 
			
		||||
	clops->cluster_send_message(message, sizeof(message), NULL,
 | 
			
		||||
			     "Error Sending version number");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Send a message to either a local client or another server */
 | 
			
		||||
static int send_message(void *buf, int msglen, char *csid, int fd,
 | 
			
		||||
static int send_message(void *buf, int msglen, const char *csid, int fd,
 | 
			
		||||
			const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	int len;
 | 
			
		||||
	int saved_errno = 0;
 | 
			
		||||
	struct timespec delay;
 | 
			
		||||
	struct timespec remtime;
 | 
			
		||||
 | 
			
		||||
	int retry_cnt = 0;
 | 
			
		||||
 | 
			
		||||
	/* Send remote messages down the cluster socket */
 | 
			
		||||
	if (csid == NULL || !ISLOCAL_CSID(csid)) {
 | 
			
		||||
@@ -1598,14 +1629,38 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
 | 
			
		||||
 | 
			
		||||
		/* Make sure it all goes */
 | 
			
		||||
		do {
 | 
			
		||||
			if (retry_cnt > MAX_RETRIES)
 | 
			
		||||
			{
 | 
			
		||||
				errno = saved_errno;
 | 
			
		||||
				log_error("%s", errtext);
 | 
			
		||||
				errno = saved_errno;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			len = write(fd, buf + ptr, msglen - ptr);
 | 
			
		||||
 | 
			
		||||
			if (len <= 0) {
 | 
			
		||||
				log_error(errtext);
 | 
			
		||||
				if (errno == EINTR)
 | 
			
		||||
					continue;
 | 
			
		||||
				if (errno == EAGAIN ||
 | 
			
		||||
				    errno == EIO ||
 | 
			
		||||
				    errno == ENOSPC) {
 | 
			
		||||
					saved_errno = errno;
 | 
			
		||||
					retry_cnt++;
 | 
			
		||||
 | 
			
		||||
					delay.tv_sec = 0;
 | 
			
		||||
					delay.tv_nsec = 100000;
 | 
			
		||||
					remtime.tv_sec = 0;
 | 
			
		||||
					remtime.tv_nsec = 0;
 | 
			
		||||
					(void) nanosleep (&delay, &remtime);
 | 
			
		||||
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				log_error("%s", errtext);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			ptr += len;
 | 
			
		||||
		} while (len < msglen);
 | 
			
		||||
		} while (ptr < msglen);
 | 
			
		||||
	}
 | 
			
		||||
	return len;
 | 
			
		||||
}
 | 
			
		||||
@@ -1635,11 +1690,11 @@ static int process_work_item(struct lvm_thread_cmd *cmd)
 | 
			
		||||
/*
 | 
			
		||||
 * Routine that runs in the "LVM thread".
 | 
			
		||||
 */
 | 
			
		||||
static void *lvm_thread_fn(void *arg)
 | 
			
		||||
static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct list *cmdl, *tmp;
 | 
			
		||||
	sigset_t ss;
 | 
			
		||||
	int using_gulm = (int)arg;
 | 
			
		||||
	int using_gulm = (int)(long)arg;
 | 
			
		||||
 | 
			
		||||
	/* Don't let anyone else to do work until we are started */
 | 
			
		||||
	pthread_mutex_lock(&lvm_start_mutex);
 | 
			
		||||
@@ -1687,7 +1742,7 @@ static void *lvm_thread_fn(void *arg)
 | 
			
		||||
 | 
			
		||||
/* Pass down some work to the LVM thread */
 | 
			
		||||
static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
 | 
			
		||||
			   int msglen, char *csid)
 | 
			
		||||
			   int msglen, const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvm_thread_cmd *cmd;
 | 
			
		||||
 | 
			
		||||
@@ -1729,6 +1784,32 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return 0 if we can talk to an existing clvmd */
 | 
			
		||||
static int check_local_clvmd(void)
 | 
			
		||||
{
 | 
			
		||||
	int local_socket;
 | 
			
		||||
	struct sockaddr_un sockaddr;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	/* Open local socket */
 | 
			
		||||
	if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&sockaddr, 0, sizeof(sockaddr));
 | 
			
		||||
	memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
 | 
			
		||||
	sockaddr.sun_family = AF_UNIX;
 | 
			
		||||
 | 
			
		||||
	if (connect(local_socket,(struct sockaddr *) &sockaddr,
 | 
			
		||||
		    sizeof(sockaddr))) {
 | 
			
		||||
		ret = -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(local_socket);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Open the local socket, that's the one we talk to libclvm down */
 | 
			
		||||
static int open_local_sock()
 | 
			
		||||
{
 | 
			
		||||
@@ -1765,7 +1846,8 @@ static int open_local_sock()
 | 
			
		||||
	return local_socket;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_message(struct local_client *client, char *buf, int len, char *csid)
 | 
			
		||||
void process_message(struct local_client *client, const char *buf, int len,
 | 
			
		||||
		     const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	struct clvm_header *inheader;
 | 
			
		||||
 | 
			
		||||
@@ -1778,7 +1860,7 @@ void process_message(struct local_client *client, char *buf, int len, char *csid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void check_all_callback(struct local_client *client, char *csid,
 | 
			
		||||
static void check_all_callback(struct local_client *client, const char *csid,
 | 
			
		||||
			       int node_up)
 | 
			
		||||
{
 | 
			
		||||
	if (!node_up)
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,8 @@ struct node_reply {
 | 
			
		||||
	struct node_reply *next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * These exist for the use of local sockets only when we are
 | 
			
		||||
 * collecting responses from all cluster nodes
 | 
			
		||||
@@ -76,7 +78,8 @@ struct netsock_bits {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
 | 
			
		||||
			      char *csid, struct local_client ** new_client);
 | 
			
		||||
			      const char *csid,
 | 
			
		||||
			      struct local_client ** new_client);
 | 
			
		||||
 | 
			
		||||
/* One of these for each fd we are listening on */
 | 
			
		||||
struct local_client {
 | 
			
		||||
@@ -95,11 +98,7 @@ struct local_client {
 | 
			
		||||
	} 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
 | 
			
		||||
#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args);
 | 
			
		||||
 | 
			
		||||
#ifndef max
 | 
			
		||||
#define max(a,b) ((a)>(b)?(a):(b))
 | 
			
		||||
@@ -116,7 +115,10 @@ 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);
 | 
			
		||||
extern void process_message(struct local_client *client, const char *buf,
 | 
			
		||||
			    int len, const char *csid);
 | 
			
		||||
extern void debuglog(const char *fmt, ... )
 | 
			
		||||
  __attribute__ ((format(printf, 1, 2)));
 | 
			
		||||
 | 
			
		||||
int sync_lock(const char *resource, int mode, int flags, int *lockid);
 | 
			
		||||
int sync_unlock(const char *resource, int lockid);
 | 
			
		||||
 
 | 
			
		||||
@@ -30,11 +30,11 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include <libdlm.h>
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "libdlm.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
@@ -42,19 +42,28 @@
 | 
			
		||||
 | 
			
		||||
/* LVM2 headers */
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "lvmcache.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;
 | 
			
		||||
static pthread_mutex_t lvm_lock;
 | 
			
		||||
static char last_error[1024];
 | 
			
		||||
 | 
			
		||||
struct lv_info {
 | 
			
		||||
	int lock_id;
 | 
			
		||||
	int lock_mode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
char *get_last_lvm_error()
 | 
			
		||||
{
 | 
			
		||||
	return last_error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return the mode a lock is currently held at (or -1 if not held) */
 | 
			
		||||
static int get_current_lock(char *resource)
 | 
			
		||||
{
 | 
			
		||||
@@ -200,12 +209,21 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
 | 
			
		||||
	/* Try to get the lock if it's a clustered volume group */
 | 
			
		||||
	if (lock_flags & LCK_CLUSTER_VG) {
 | 
			
		||||
		status = hold_lock(resource, mode, LKF_NOQUEUE);
 | 
			
		||||
		if (status)
 | 
			
		||||
		if (status) {
 | 
			
		||||
			/* Return an LVM-sensible error for this.
 | 
			
		||||
			 * Forcing EIO makes the upper level return this text
 | 
			
		||||
			 * rather than the strerror text for EAGAIN.
 | 
			
		||||
			 */
 | 
			
		||||
			if (errno == EAGAIN) {
 | 
			
		||||
				sprintf(last_error, "Volume is busy on another node");
 | 
			
		||||
				errno = EIO;
 | 
			
		||||
			}
 | 
			
		||||
			return errno;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If it's suspended then resume it */
 | 
			
		||||
	if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
 | 
			
		||||
	if (!lv_info_by_lvid(cmd, resource, &lvi, 0, 0))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (lvi.suspended)
 | 
			
		||||
@@ -227,7 +245,7 @@ static int do_resume_lv(char *resource)
 | 
			
		||||
	/* Is it open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == -1) {
 | 
			
		||||
		DEBUGLOG("do_deactivate_lock, lock not already held\n");
 | 
			
		||||
		DEBUGLOG("do_resume_lv, lock not already held\n");
 | 
			
		||||
		return 0;	/* We don't need to do anything */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -251,7 +269,7 @@ static int do_suspend_lv(char *resource)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Only suspend it if it exists */
 | 
			
		||||
	if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
 | 
			
		||||
	if (!lv_info_by_lvid(cmd, resource, &lvi, 0, 0))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (lvi.exists) {
 | 
			
		||||
@@ -295,14 +313,25 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
	DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
 | 
			
		||||
		 resource, command, lock_flags);
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lvm_lock);
 | 
			
		||||
	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.");
 | 
			
		||||
			pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
			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_MONITOR_MODE))
 | 
			
		||||
		init_dmeventd_monitor(0);
 | 
			
		||||
 | 
			
		||||
	switch (command) {
 | 
			
		||||
	case LCK_LV_EXCLUSIVE:
 | 
			
		||||
		status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
 | 
			
		||||
@@ -331,8 +360,18 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_PARTIAL_MODE)
 | 
			
		||||
		init_partial(0);
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
 | 
			
		||||
		init_mirror_in_sync(0);
 | 
			
		||||
 | 
			
		||||
	if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
 | 
			
		||||
		init_dmeventd_monitor(DEFAULT_DMEVENTD_MONITOR);
 | 
			
		||||
 | 
			
		||||
	/* clean the pool for another command */
 | 
			
		||||
	dm_pool_empty(cmd->mem);
 | 
			
		||||
	pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Command return is %d\n", status);
 | 
			
		||||
	return status;
 | 
			
		||||
@@ -359,6 +398,8 @@ int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
int post_lock_lv(unsigned char command, unsigned char lock_flags,
 | 
			
		||||
		 char *resource)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	/* Opposite of above, done on resume after a metadata update */
 | 
			
		||||
	if (command == LCK_LV_RESUME) {
 | 
			
		||||
		int oldmode;
 | 
			
		||||
@@ -372,7 +413,10 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
 | 
			
		||||
		if (oldmode == LKM_PWMODE) {
 | 
			
		||||
			struct lvinfo lvi;
 | 
			
		||||
 | 
			
		||||
			if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
 | 
			
		||||
			pthread_mutex_lock(&lvm_lock);
 | 
			
		||||
			status = lv_info_by_lvid(cmd, resource, &lvi, 0, 0);
 | 
			
		||||
			pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
			if (!status)
 | 
			
		||||
				return EIO;
 | 
			
		||||
 | 
			
		||||
			if (lvi.exists) {
 | 
			
		||||
@@ -388,7 +432,7 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check if a VG is un use by LVM1 so we don't stomp on it */
 | 
			
		||||
int do_check_lvm1(char *vgname)
 | 
			
		||||
int do_check_lvm1(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
@@ -397,6 +441,19 @@ int do_check_lvm1(char *vgname)
 | 
			
		||||
	return status == 1 ? 0 : EBUSY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int do_refresh_cache()
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	DEBUGLOG("Refreshing context\n");
 | 
			
		||||
	log_notice("Refreshing context");
 | 
			
		||||
 | 
			
		||||
	ret = refresh_toolcontext(cmd);
 | 
			
		||||
	init_full_scan_done(0);
 | 
			
		||||
	lvmcache_label_scan(cmd, 2);
 | 
			
		||||
 | 
			
		||||
	return ret==1?0:-1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
 | 
			
		||||
   that might be hanging around if we died for any reason
 | 
			
		||||
@@ -432,7 +489,8 @@ static void drop_vg_locks()
 | 
			
		||||
		sync_unlock(vg, LCK_EXCL);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	fclose(vgs);
 | 
			
		||||
	if (fclose(vgs))
 | 
			
		||||
		DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -482,16 +540,40 @@ static void *get_initial_state()
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fclose(lvs);
 | 
			
		||||
	if (fclose(lvs))
 | 
			
		||||
		DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void lvm2_log_fn(int level, const char *file, int line,
 | 
			
		||||
			const char *message)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	/* Send messages to the normal LVM2 logging system too,
 | 
			
		||||
	   so we get debug output when it's asked for. 
 | 
			
		||||
 	   We need to NULL the function ptr otherwise it will just call
 | 
			
		||||
	   back into here! */
 | 
			
		||||
	init_log_fn(NULL);
 | 
			
		||||
	print_log(level, file, line, "%s", message);
 | 
			
		||||
	init_log_fn(lvm2_log_fn);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Ignore non-error messages, but store the latest one for returning
 | 
			
		||||
	 * to the user.
 | 
			
		||||
	 */
 | 
			
		||||
	if (level != _LOG_ERR && level != _LOG_FATAL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	strncpy(last_error, message, sizeof(last_error));
 | 
			
		||||
	last_error[sizeof(last_error)-1] = '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This checks some basic cluster-LVM configuration stuff */
 | 
			
		||||
static void check_config()
 | 
			
		||||
{
 | 
			
		||||
	int locking_type;
 | 
			
		||||
 | 
			
		||||
	locking_type = find_config_int(cmd->cft->root, "global/locking_type", 1);
 | 
			
		||||
	locking_type = find_config_tree_int(cmd, "global/locking_type", 1);
 | 
			
		||||
 | 
			
		||||
	if (locking_type == 3) /* compiled-in cluster support */
 | 
			
		||||
		return;
 | 
			
		||||
@@ -499,7 +581,7 @@ static void check_config()
 | 
			
		||||
	if (locking_type == 2) { /* External library, check name */
 | 
			
		||||
		const char *libname;
 | 
			
		||||
 | 
			
		||||
		libname = find_config_str(cmd->cft->root, "global/locking_library",
 | 
			
		||||
		libname = find_config_tree_str(cmd, "global/locking_library",
 | 
			
		||||
					  "");
 | 
			
		||||
		if (strstr(libname, "liblvm2clusterlock.so"))
 | 
			
		||||
			return;
 | 
			
		||||
@@ -515,19 +597,23 @@ void init_lvhash()
 | 
			
		||||
	/* Create hash table for keeping LV locks & status */
 | 
			
		||||
	lv_hash = dm_hash_create(100);
 | 
			
		||||
	pthread_mutex_init(&lv_hash_lock, NULL);
 | 
			
		||||
	pthread_mutex_init(&lvm_lock, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called to initialise the LVM context of the daemon */
 | 
			
		||||
int init_lvm(int using_gulm)
 | 
			
		||||
{
 | 
			
		||||
	if (!(cmd = create_toolcontext(NULL))) {
 | 
			
		||||
	if (!(cmd = create_toolcontext(NULL, 0, 1))) {
 | 
			
		||||
		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);
 | 
			
		||||
	openlog("clvmd", LOG_PID, LOG_DAEMON);
 | 
			
		||||
	init_debug(cmd->current_settings.debug);
 | 
			
		||||
	init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
 | 
			
		||||
	set_activation(cmd->current_settings.activation);
 | 
			
		||||
 | 
			
		||||
	/* Check lvm.conf is setup for cluster-LVM */
 | 
			
		||||
	check_config();
 | 
			
		||||
@@ -538,5 +624,8 @@ int init_lvm(int using_gulm)
 | 
			
		||||
 | 
			
		||||
	get_initial_state();
 | 
			
		||||
 | 
			
		||||
	/* Trap log messages so we can pass them back to the user */
 | 
			
		||||
	init_log_fn(lvm2_log_fn);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,12 +24,14 @@ 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 do_check_lvm1(const char *vgname);
 | 
			
		||||
extern int do_refresh_cache(void);
 | 
			
		||||
extern int init_lvm(int using_gulm);
 | 
			
		||||
extern void init_lvhash(void);
 | 
			
		||||
 | 
			
		||||
extern int hold_unlock(char *resource);
 | 
			
		||||
extern int hold_lock(char *resource, int mode, int flags);
 | 
			
		||||
extern void unlock_all(void);
 | 
			
		||||
extern char *get_last_lvm_error(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										363
									
								
								daemons/clvmd/refresh_clvmd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								daemons/clvmd/refresh_clvmd.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,363 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Tell all clvmds in a cluster to refresh their toolcontext
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "refresh_clvmd.h"
 | 
			
		||||
 | 
			
		||||
typedef struct lvm_response {
 | 
			
		||||
	char node[255];
 | 
			
		||||
	char *response;
 | 
			
		||||
	int status;
 | 
			
		||||
	int len;
 | 
			
		||||
} lvm_response_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This gets stuck at the start of memory we allocate so we
 | 
			
		||||
 * can sanity-check it at deallocation time
 | 
			
		||||
 */
 | 
			
		||||
#define LVM_SIGNATURE 0x434C564D
 | 
			
		||||
 | 
			
		||||
static int _clvmd_sock = -1;
 | 
			
		||||
 | 
			
		||||
/* Open connection to the clvm daemon */
 | 
			
		||||
static int _open_local_sock(void)
 | 
			
		||||
{
 | 
			
		||||
	int local_socket;
 | 
			
		||||
	struct sockaddr_un sockaddr;
 | 
			
		||||
 | 
			
		||||
	/* Open local socket */
 | 
			
		||||
	if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
 | 
			
		||||
		fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&sockaddr, 0, sizeof(sockaddr));
 | 
			
		||||
	memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
 | 
			
		||||
 | 
			
		||||
	sockaddr.sun_family = AF_UNIX;
 | 
			
		||||
 | 
			
		||||
	if (connect(local_socket,(struct sockaddr *) &sockaddr,
 | 
			
		||||
		    sizeof(sockaddr))) {
 | 
			
		||||
		int saved_errno = errno;
 | 
			
		||||
 | 
			
		||||
		fprintf(stderr, "connect() failed on local socket: %s\n",
 | 
			
		||||
			  strerror(errno));
 | 
			
		||||
		if (close(local_socket))
 | 
			
		||||
			return -1;
 | 
			
		||||
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return local_socket;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Send a request and return the status */
 | 
			
		||||
static int _send_request(const char *inbuf, int inlen, char **retbuf)
 | 
			
		||||
{
 | 
			
		||||
	char outbuf[PIPE_BUF];
 | 
			
		||||
	struct clvm_header *outheader = (struct clvm_header *) outbuf;
 | 
			
		||||
	int len;
 | 
			
		||||
	int off;
 | 
			
		||||
	int buflen;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	/* Send it to CLVMD */
 | 
			
		||||
 rewrite:
 | 
			
		||||
	if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
 | 
			
		||||
	        if (err == -1 && errno == EINTR)
 | 
			
		||||
		        goto rewrite;
 | 
			
		||||
		fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the response */
 | 
			
		||||
 reread:
 | 
			
		||||
	if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
 | 
			
		||||
	        if (errno == EINTR)
 | 
			
		||||
		        goto reread;
 | 
			
		||||
		fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (len == 0) {
 | 
			
		||||
		fprintf(stderr, "EOF reading CLVMD");
 | 
			
		||||
		errno = ENOTCONN;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Allocate buffer */
 | 
			
		||||
	buflen = len + outheader->arglen;
 | 
			
		||||
	*retbuf = dm_malloc(buflen);
 | 
			
		||||
	if (!*retbuf) {
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Copy the header */
 | 
			
		||||
	memcpy(*retbuf, outbuf, len);
 | 
			
		||||
	outheader = (struct clvm_header *) *retbuf;
 | 
			
		||||
 | 
			
		||||
	/* Read the returned values */
 | 
			
		||||
	off = 1;		/* we've already read the first byte */
 | 
			
		||||
	while (off <= outheader->arglen && len > 0) {
 | 
			
		||||
		len = read(_clvmd_sock, outheader->args + off,
 | 
			
		||||
			   buflen - off - offsetof(struct clvm_header, args));
 | 
			
		||||
		if (len > 0)
 | 
			
		||||
			off += len;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Was it an error ? */
 | 
			
		||||
	if (outheader->status != 0) {
 | 
			
		||||
		errno = outheader->status;
 | 
			
		||||
 | 
			
		||||
		/* Only return an error here if there are no node-specific
 | 
			
		||||
		   errors present in the message that might have more detail */
 | 
			
		||||
		if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
 | 
			
		||||
			fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Build the structure header and parse-out wildcard node names */
 | 
			
		||||
static void _build_header(struct clvm_header *head, int cmd, const char *node,
 | 
			
		||||
			  int len)
 | 
			
		||||
{
 | 
			
		||||
	head->cmd = cmd;
 | 
			
		||||
	head->status = 0;
 | 
			
		||||
	head->flags = 0;
 | 
			
		||||
	head->clientid = 0;
 | 
			
		||||
	head->arglen = len;
 | 
			
		||||
 | 
			
		||||
	if (node) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Allow a couple of special node names:
 | 
			
		||||
		 * "*" for all nodes,
 | 
			
		||||
		 * "." for the local node only
 | 
			
		||||
		 */
 | 
			
		||||
		if (strcmp(node, "*") == 0) {
 | 
			
		||||
			head->node[0] = '\0';
 | 
			
		||||
		} else if (strcmp(node, ".") == 0) {
 | 
			
		||||
			head->node[0] = '\0';
 | 
			
		||||
			head->flags = CLVMD_FLAG_LOCAL;
 | 
			
		||||
		} else
 | 
			
		||||
			strcpy(head->node, node);
 | 
			
		||||
	} else
 | 
			
		||||
		head->node[0] = '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Send a message to a(or all) node(s) in the cluster and wait for replies
 | 
			
		||||
 */
 | 
			
		||||
static int _cluster_request(char cmd, const char *node, void *data, int len,
 | 
			
		||||
			   lvm_response_t ** response, int *num)
 | 
			
		||||
{
 | 
			
		||||
	char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
 | 
			
		||||
	char *inptr;
 | 
			
		||||
	char *retbuf = NULL;
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
	int num_responses = 0;
 | 
			
		||||
	struct clvm_header *head = (struct clvm_header *) outbuf;
 | 
			
		||||
	lvm_response_t *rarray;
 | 
			
		||||
 | 
			
		||||
	*num = 0;
 | 
			
		||||
 | 
			
		||||
	if (_clvmd_sock == -1)
 | 
			
		||||
		_clvmd_sock = _open_local_sock();
 | 
			
		||||
 | 
			
		||||
	if (_clvmd_sock == -1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	_build_header(head, cmd, node, len);
 | 
			
		||||
	memcpy(head->node + strlen(head->node) + 1, data, len);
 | 
			
		||||
 | 
			
		||||
	status = _send_request(outbuf, sizeof(struct clvm_header) +
 | 
			
		||||
			      strlen(head->node) + len, &retbuf);
 | 
			
		||||
	if (!status)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	/* Count the number of responses we got */
 | 
			
		||||
	head = (struct clvm_header *) retbuf;
 | 
			
		||||
	inptr = head->args;
 | 
			
		||||
	while (inptr[0]) {
 | 
			
		||||
		num_responses++;
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
		inptr += sizeof(int);
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Allocate response array.
 | 
			
		||||
	 * With an extra pair of INTs on the front to sanity
 | 
			
		||||
	 * check the pointer when we are given it back to free
 | 
			
		||||
	 */
 | 
			
		||||
	*response = dm_malloc(sizeof(lvm_response_t) * num_responses +
 | 
			
		||||
			    sizeof(int) * 2);
 | 
			
		||||
	if (!*response) {
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		status = 0;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rarray = *response;
 | 
			
		||||
 | 
			
		||||
	/* Unpack the response into an lvm_response_t array */
 | 
			
		||||
	inptr = head->args;
 | 
			
		||||
	i = 0;
 | 
			
		||||
	while (inptr[0]) {
 | 
			
		||||
		strcpy(rarray[i].node, inptr);
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
 | 
			
		||||
		memcpy(&rarray[i].status, inptr, sizeof(int));
 | 
			
		||||
		inptr += sizeof(int);
 | 
			
		||||
 | 
			
		||||
		rarray[i].response = dm_malloc(strlen(inptr) + 1);
 | 
			
		||||
		if (rarray[i].response == NULL) {
 | 
			
		||||
			/* Free up everything else and return error */
 | 
			
		||||
			int j;
 | 
			
		||||
			for (j = 0; j < i; j++)
 | 
			
		||||
				dm_free(rarray[i].response);
 | 
			
		||||
			free(*response);
 | 
			
		||||
			errno = ENOMEM;
 | 
			
		||||
			status = -1;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		strcpy(rarray[i].response, inptr);
 | 
			
		||||
		rarray[i].len = strlen(inptr);
 | 
			
		||||
		inptr += strlen(inptr) + 1;
 | 
			
		||||
		i++;
 | 
			
		||||
	}
 | 
			
		||||
	*num = num_responses;
 | 
			
		||||
	*response = rarray;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (retbuf)
 | 
			
		||||
		dm_free(retbuf);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Free reply array */
 | 
			
		||||
static int _cluster_free_request(lvm_response_t * response, int num)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num; i++) {
 | 
			
		||||
		dm_free(response[i].response);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_free(response);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int refresh_clvmd()
 | 
			
		||||
{
 | 
			
		||||
	int num_responses;
 | 
			
		||||
	char args[1]; // No args really.
 | 
			
		||||
	lvm_response_t *response;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	status = _cluster_request(CLVMD_CMD_REFRESH, "*", args, 0, &response, &num_responses);
 | 
			
		||||
 | 
			
		||||
	/* If any nodes were down then display them and return an error */
 | 
			
		||||
	for (i = 0; i < num_responses; i++) {
 | 
			
		||||
		if (response[i].status == EHOSTDOWN) {
 | 
			
		||||
			fprintf(stderr, "clvmd not running on node %s",
 | 
			
		||||
				  response[i].node);
 | 
			
		||||
			status = 0;
 | 
			
		||||
			errno = response[i].status;
 | 
			
		||||
		} else if (response[i].status) {
 | 
			
		||||
			fprintf(stderr, "Error resetting node %s: %s",
 | 
			
		||||
				  response[i].node,
 | 
			
		||||
				  response[i].response[0] ?
 | 
			
		||||
				  	response[i].response :
 | 
			
		||||
				  	strerror(response[i].status));
 | 
			
		||||
			status = 0;
 | 
			
		||||
			errno = response[i].status;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	saved_errno = errno;
 | 
			
		||||
	_cluster_free_request(response, num_responses);
 | 
			
		||||
	errno = saved_errno;
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int debug_clvmd(int level, int clusterwide)
 | 
			
		||||
{
 | 
			
		||||
	int num_responses;
 | 
			
		||||
	char args[1];
 | 
			
		||||
	const char *nodes;
 | 
			
		||||
	lvm_response_t *response;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	args[0] = level;
 | 
			
		||||
	if (clusterwide)
 | 
			
		||||
		nodes = "*";
 | 
			
		||||
	else
 | 
			
		||||
		nodes = ".";
 | 
			
		||||
 | 
			
		||||
	status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses);
 | 
			
		||||
 | 
			
		||||
	/* If any nodes were down then display them and return an error */
 | 
			
		||||
	for (i = 0; i < num_responses; i++) {
 | 
			
		||||
		if (response[i].status == EHOSTDOWN) {
 | 
			
		||||
			fprintf(stderr, "clvmd not running on node %s",
 | 
			
		||||
				  response[i].node);
 | 
			
		||||
			status = 0;
 | 
			
		||||
			errno = response[i].status;
 | 
			
		||||
		} else if (response[i].status) {
 | 
			
		||||
			fprintf(stderr, "Error setting debug on node %s: %s",
 | 
			
		||||
				  response[i].node,
 | 
			
		||||
				  response[i].response[0] ?
 | 
			
		||||
				  	response[i].response :
 | 
			
		||||
				  	strerror(response[i].status));
 | 
			
		||||
			status = 0;
 | 
			
		||||
			errno = response[i].status;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	saved_errno = errno;
 | 
			
		||||
	_cluster_free_request(response, num_responses);
 | 
			
		||||
	errno = saved_errno;
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,13 +12,7 @@
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_MATCHER_H
 | 
			
		||||
#define _LVM_MATCHER_H
 | 
			
		||||
 | 
			
		||||
struct matcher;
 | 
			
		||||
struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
 | 
			
		||||
			       unsigned num);
 | 
			
		||||
int refresh_clvmd(void);
 | 
			
		||||
int debug_clvmd(int level, int clusterwide);
 | 
			
		||||
 | 
			
		||||
int matcher_run(struct matcher *m, const char *begin);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,371 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
@@ -34,8 +34,8 @@
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
@@ -57,7 +57,7 @@ int init_comms(unsigned short port)
 | 
			
		||||
    struct sockaddr_in6 addr;
 | 
			
		||||
 | 
			
		||||
    sock_hash = dm_hash_create(100);
 | 
			
		||||
    tcp_port = port ? port : DEFAULT_TCP_PORT;
 | 
			
		||||
    tcp_port = port ? : DEFAULT_TCP_PORT;
 | 
			
		||||
 | 
			
		||||
    listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
 | 
			
		||||
 | 
			
		||||
@@ -92,41 +92,37 @@ int init_comms(unsigned short port)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tcp_remove_client(char *csid)
 | 
			
		||||
 {
 | 
			
		||||
void tcp_remove_client(const char *c_csid)
 | 
			
		||||
{
 | 
			
		||||
    struct local_client *client;
 | 
			
		||||
    char csid[GULM_MAX_CSID_LEN];
 | 
			
		||||
    unsigned int i;
 | 
			
		||||
    memcpy(csid, c_csid, sizeof csid);
 | 
			
		||||
    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)
 | 
			
		||||
    for (i = 0; i < 2; i++)
 | 
			
		||||
    {
 | 
			
		||||
	dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
 | 
			
		||||
	client->removeme = 1;
 | 
			
		||||
	close(client->fd);
 | 
			
		||||
	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, on the 2nd iteration. */
 | 
			
		||||
	csid[0] ^= 0x80;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 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)
 | 
			
		||||
int alloc_client(int fd, const char *c_csid, struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    struct local_client *client;
 | 
			
		||||
    char csid[GULM_MAX_CSID_LEN];
 | 
			
		||||
    memcpy(csid, c_csid, sizeof csid);
 | 
			
		||||
 | 
			
		||||
    DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid));
 | 
			
		||||
 | 
			
		||||
@@ -181,7 +177,7 @@ int get_main_gulm_cluster_fd()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Read on main comms (listen) socket, accept it */
 | 
			
		||||
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid,
 | 
			
		||||
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, const char *csid,
 | 
			
		||||
			struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
    int newfd;
 | 
			
		||||
@@ -315,7 +311,7 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int gulm_connect_csid(char *csid, struct local_client **newclient)
 | 
			
		||||
int gulm_connect_csid(const char *csid, struct local_client **newclient)
 | 
			
		||||
{
 | 
			
		||||
    int fd;
 | 
			
		||||
    struct sockaddr_in6 addr;
 | 
			
		||||
@@ -366,7 +362,7 @@ int gulm_connect_csid(char *csid, struct local_client **newclient)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Send a message to a known CSID */
 | 
			
		||||
static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const char *errtext)
 | 
			
		||||
static int tcp_send_message(void *buf, int msglen, const char *csid, const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
    int status;
 | 
			
		||||
    struct local_client *client;
 | 
			
		||||
@@ -394,7 +390,7 @@ static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const ch
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
 | 
			
		||||
int gulm_cluster_send_message(void *buf, int msglen, const char *csid, const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
    int status=0;
 | 
			
		||||
 | 
			
		||||
@@ -465,7 +461,7 @@ static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get someone else's IP address from DNS */
 | 
			
		||||
int get_ip_address(char *node, char *addr)
 | 
			
		||||
int get_ip_address(const char *node, char *addr)
 | 
			
		||||
{
 | 
			
		||||
    struct hostent *he;
 | 
			
		||||
 | 
			
		||||
@@ -493,7 +489,7 @@ int get_ip_address(char *node, char *addr)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *print_csid(char *csid)
 | 
			
		||||
char *print_csid(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
    static char buf[128];
 | 
			
		||||
    int *icsid = (int *)csid;
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,9 @@
 | 
			
		||||
#define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128
 | 
			
		||||
 | 
			
		||||
extern int init_comms(unsigned short);
 | 
			
		||||
extern char *print_csid(char *);
 | 
			
		||||
extern char *print_csid(const 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);
 | 
			
		||||
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, const char *csid, struct local_client **new_client);
 | 
			
		||||
int gulm_cluster_send_message(void *buf, int msglen, const char *csid, const char *errtext);
 | 
			
		||||
void get_our_gulm_csid(char *csid);
 | 
			
		||||
int gulm_connect_csid(char *csid, struct local_client **newclient);
 | 
			
		||||
int gulm_connect_csid(const char *csid, struct local_client **newclient);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,19 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
dm_event_handler_create
 | 
			
		||||
dm_event_handler_destroy
 | 
			
		||||
dm_event_handler_set_dso
 | 
			
		||||
dm_event_handler_set_dev_name
 | 
			
		||||
dm_event_handler_set_uuid
 | 
			
		||||
dm_event_handler_set_major
 | 
			
		||||
dm_event_handler_set_minor
 | 
			
		||||
dm_event_handler_set_event_mask
 | 
			
		||||
dm_event_handler_get_dso
 | 
			
		||||
dm_event_handler_get_devname
 | 
			
		||||
dm_event_handler_get_uuid
 | 
			
		||||
dm_event_handler_get_major
 | 
			
		||||
dm_event_handler_get_minor
 | 
			
		||||
dm_event_handler_get_event_mask
 | 
			
		||||
dm_event_register_handler
 | 
			
		||||
dm_event_unregister_handler
 | 
			
		||||
dm_event_get_registered_device
 | 
			
		||||
dm_event_handler_set_timeout
 | 
			
		||||
dm_event_handler_get_timeout
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,13 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the device-mapper userspace tools.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU General Public License v.2.
 | 
			
		||||
# of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
@@ -16,36 +15,69 @@ srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
VPATH = @srcdir@
 | 
			
		||||
 | 
			
		||||
TARGETS = dmevent dmeventd
 | 
			
		||||
INSTALL_TYPE = install_dynamic
 | 
			
		||||
SOURCES = libdevmapper-event.c
 | 
			
		||||
 | 
			
		||||
SOURCES = noop.c
 | 
			
		||||
CLEAN_TARGETS = dmevent.o dmeventd.o
 | 
			
		||||
LIB_STATIC = libdevmapper-event.a
 | 
			
		||||
 | 
			
		||||
ifeq ("@LIB_SUFFIX@","dylib")
 | 
			
		||||
  LIB_SHARED = libdmeventdnoop.dylib
 | 
			
		||||
  LIB_SHARED = libdevmapper-event.dylib
 | 
			
		||||
else
 | 
			
		||||
  LIB_SHARED = libdmeventdnoop.so
 | 
			
		||||
  LIB_SHARED = libdevmapper-event.so
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
LDFLAGS += -ldl -ldevmapper -lmultilog
 | 
			
		||||
 | 
			
		||||
TARGETS = dmeventd
 | 
			
		||||
CLEAN_TARGETS = dmeventd.o
 | 
			
		||||
 | 
			
		||||
include ../make.tmpl
 | 
			
		||||
 | 
			
		||||
libdmeventdnoop.so: noop.o
 | 
			
		||||
LDFLAGS += -ldl -ldevmapper -lpthread
 | 
			
		||||
CLDFLAGS += -ldl -ldevmapper -lpthread
 | 
			
		||||
 | 
			
		||||
dmevent: dmevent.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
 | 
			
		||||
	$(CC) -o $@ dmevent.o $(LDFLAGS) \
 | 
			
		||||
	      -L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog $(LIBS)
 | 
			
		||||
dmeventd: $(LIB_SHARED) dmeventd.o
 | 
			
		||||
	$(CC) -o $@ dmeventd.o $(CFLAGS) $(LDFLAGS) \
 | 
			
		||||
	-L. -ldevmapper-event $(LIBS) -rdynamic
 | 
			
		||||
 | 
			
		||||
dmeventd: dmeventd.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
 | 
			
		||||
	$(CC) -o $@ dmeventd.o $(LDFLAGS) \
 | 
			
		||||
	      -L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -lpthread -ldmevent $(LIBS)
 | 
			
		||||
.PHONY: install_dynamic install_static install_include \
 | 
			
		||||
	install_pkgconfig install_dmeventd
 | 
			
		||||
 | 
			
		||||
install: $(INSTALL_TYPE)
 | 
			
		||||
INSTALL_TYPE = install_dynamic
 | 
			
		||||
 | 
			
		||||
.PHONY: install_dynamic
 | 
			
		||||
ifeq ("@STATIC_LINK@", "yes")
 | 
			
		||||
  INSTALL_TYPE += install_static
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
install_dynamic: dmeventd
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) dmeventd $(sbindir)/dmeventd
 | 
			
		||||
ifeq ("@PKGCONFIG@", "yes")
 | 
			
		||||
  INSTALL_TYPE += install_pkgconfig
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
install: $(INSTALL_TYPE) install_include install_dmeventd
 | 
			
		||||
 | 
			
		||||
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_dmeventd: dmeventd
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$<
 | 
			
		||||
 | 
			
		||||
install_pkgconfig:
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \
 | 
			
		||||
		$(usrlibdir)/pkgconfig/devmapper-event.pc
 | 
			
		||||
 | 
			
		||||
install_static: libdevmapper-event.a
 | 
			
		||||
	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | 
			
		||||
		$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
 | 
			
		||||
	$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
 | 
			
		||||
 | 
			
		||||
.PHONY: distclean_lib distclean
 | 
			
		||||
 | 
			
		||||
distclean_lib: 
 | 
			
		||||
	$(RM) libdevmapper-event.pc
 | 
			
		||||
 | 
			
		||||
distclean: distclean_lib
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,240 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the device-mapper userspace tools.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
#include "libdm-event.h"
 | 
			
		||||
#include "libmultilog.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/file.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
static enum event_type events = ALL_ERRORS; /* All until we can distinguish. */
 | 
			
		||||
static char default_dso_name[] = "noop";  /* default DSO is noop */
 | 
			
		||||
static int default_reg = 1;		 /* default action is register */
 | 
			
		||||
static uint32_t timeout;
 | 
			
		||||
 | 
			
		||||
struct event_ops {
 | 
			
		||||
int (*dm_register_for_event)(char *dso_name, char *device,
 | 
			
		||||
			     enum event_type event_types);
 | 
			
		||||
int (*dm_unregister_for_event)(char *dso_name, char *device,
 | 
			
		||||
			       enum event_type event_types);
 | 
			
		||||
int (*dm_get_registered_device)(char **dso_name, char **device,
 | 
			
		||||
				enum event_type *event_types, int next);
 | 
			
		||||
int (*dm_set_event_timeout)(char *device, uint32_t time);
 | 
			
		||||
int (*dm_get_event_timeout)(char *device, uint32_t *time);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Display help. */
 | 
			
		||||
static void print_usage(char *name)
 | 
			
		||||
{
 | 
			
		||||
	char *cmd = strrchr(name, '/');
 | 
			
		||||
 | 
			
		||||
	cmd = cmd ? cmd + 1 : name;
 | 
			
		||||
	printf("Usage::\n"
 | 
			
		||||
	       "%s [options] <device>\n"
 | 
			
		||||
	       "\n"
 | 
			
		||||
	       "Options:\n"
 | 
			
		||||
	       "  -d <dso>           Specify the DSO to use.\n"
 | 
			
		||||
	       "  -h                 Print this usage.\n"
 | 
			
		||||
	       "  -l                 List registered devices.\n"
 | 
			
		||||
	       "  -r                 Register for event (default).\n"
 | 
			
		||||
	       "  -t <timeout>       (un)register for timeout event.\n"
 | 
			
		||||
	       "  -u                 Unregister for event.\n"
 | 
			
		||||
	       "\n", cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Parse command line arguments. */
 | 
			
		||||
static int parse_argv(int argc, char **argv, char **dso_name_arg,
 | 
			
		||||
		      char **device_arg, int *reg, int *list)
 | 
			
		||||
{
 | 
			
		||||
	int c;
 | 
			
		||||
	const char *options = "d:hlrt:u";
 | 
			
		||||
 | 
			
		||||
	while ((c = getopt(argc, argv, options)) != -1) {
 | 
			
		||||
		switch (c) {
 | 
			
		||||
		case 'd':
 | 
			
		||||
			*dso_name_arg = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'h':
 | 
			
		||||
			print_usage(argv[0]);
 | 
			
		||||
			exit(EXIT_SUCCESS);
 | 
			
		||||
		case 'l':
 | 
			
		||||
			*list = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'r':
 | 
			
		||||
			*reg = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 't':
 | 
			
		||||
			events = TIMEOUT;
 | 
			
		||||
			if (sscanf(optarg, "%"SCNu32, &timeout) != 1){
 | 
			
		||||
				fprintf(stderr, "invalid timeout '%s'\n",
 | 
			
		||||
					optarg);
 | 
			
		||||
				timeout = 0;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 'u':
 | 
			
		||||
			*reg = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			fprintf(stderr, "Unknown option '%c'.\n"
 | 
			
		||||
				"Try '-h' for help.\n", c);
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (optind >= argc) {
 | 
			
		||||
		if (!*list) {
 | 
			
		||||
			fprintf(stderr, "You need to specify a device.\n");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	} else 
 | 
			
		||||
		*device_arg = argv[optind];
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int lookup_symbol(void *dl, void **symbol, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	if ((*symbol = dlsym(dl, name)))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	fprintf(stderr, "error looking up %s symbol: %s\n", name, dlerror());
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int lookup_symbols(void *dl, struct event_ops *e)
 | 
			
		||||
{
 | 
			
		||||
	return lookup_symbol(dl, (void *) &e->dm_register_for_event,
 | 
			
		||||
			     "dm_register_for_event") &&
 | 
			
		||||
	       lookup_symbol(dl, (void *) &e->dm_unregister_for_event,
 | 
			
		||||
			     "dm_unregister_for_event") &&
 | 
			
		||||
	       lookup_symbol(dl, (void *) &e->dm_get_registered_device,
 | 
			
		||||
			     "dm_get_registered_device") &&
 | 
			
		||||
	       lookup_symbol(dl, (void *) &e->dm_set_event_timeout,
 | 
			
		||||
			     "dm_set_event_timeout") &&
 | 
			
		||||
	       lookup_symbol(dl, (void *) &e->dm_get_event_timeout,
 | 
			
		||||
			     "dm_get_event_timeout");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	void *dl;
 | 
			
		||||
	struct event_ops e;
 | 
			
		||||
	int list = 0, next = 0, ret, reg = default_reg;
 | 
			
		||||
	char *device, *device_arg = NULL, *dso_name, *dso_name_arg = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!parse_argv(argc, argv, &dso_name_arg, &device_arg, ®, &list))
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
	if (device_arg) {
 | 
			
		||||
		if (!(device = strdup(device_arg)))
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
	} else
 | 
			
		||||
		device = NULL;
 | 
			
		||||
 | 
			
		||||
	if (dso_name_arg) {
 | 
			
		||||
		if (!(dso_name = strdup(dso_name_arg)))
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!(dso_name = strdup(default_dso_name)))
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME: use -v/-q options to set this */
 | 
			
		||||
	multilog_add_type(standard, NULL);
 | 
			
		||||
	multilog_init_verbose(standard, _LOG_DEBUG);
 | 
			
		||||
 | 
			
		||||
	if (!(dl = dlopen("libdmevent.so", RTLD_NOW))){
 | 
			
		||||
		fprintf(stderr, "Cannot dlopen libdmevent.so: %s\n", dlerror());
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(lookup_symbols(dl, &e)))
 | 
			
		||||
		goto out;
 | 
			
		||||
	if (list) {
 | 
			
		||||
		while (1) {
 | 
			
		||||
			if ((ret= e.dm_get_registered_device(&dso_name,
 | 
			
		||||
							     &device,
 | 
			
		||||
							     &events, next)))
 | 
			
		||||
				break;
 | 
			
		||||
			printf("%s %s 0x%x", dso_name, device, events);
 | 
			
		||||
			if (events & TIMEOUT){
 | 
			
		||||
				if ((ret = e.dm_get_event_timeout(device,
 | 
			
		||||
							  	  &timeout))) {
 | 
			
		||||
					ret = EXIT_FAILURE;
 | 
			
		||||
					goto out;
 | 
			
		||||
				}
 | 
			
		||||
				printf(" %"PRIu32"\n", timeout);
 | 
			
		||||
			} else
 | 
			
		||||
				printf("\n");
 | 
			
		||||
			if (device_arg)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			next = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = (ret && device_arg) ? EXIT_FAILURE : EXIT_SUCCESS;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ret = reg ? e.dm_register_for_event(dso_name, device, events) :
 | 
			
		||||
			 e.dm_unregister_for_event(dso_name, device, events))) {
 | 
			
		||||
		fprintf(stderr, "Failed to %sregister %s: %s\n",
 | 
			
		||||
			reg ? "": "un", device, strerror(-ret));
 | 
			
		||||
		ret = EXIT_FAILURE;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (reg && (events & TIMEOUT) &&
 | 
			
		||||
		    ((ret = e.dm_set_event_timeout(device, timeout)))){
 | 
			
		||||
			fprintf(stderr, "Failed to set timeout for %s: %s\n",
 | 
			
		||||
				device, strerror(-ret));
 | 
			
		||||
			ret = EXIT_FAILURE;
 | 
			
		||||
		} else {
 | 
			
		||||
			printf("%s %sregistered successfully.\n",
 | 
			
		||||
			       device, reg ? "" : "un");
 | 
			
		||||
			ret = EXIT_SUCCESS;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
   out:
 | 
			
		||||
	multilog_del_type(standard);
 | 
			
		||||
 | 
			
		||||
	if (device)
 | 
			
		||||
		free(device);
 | 
			
		||||
	if (dso_name)
 | 
			
		||||
		free(dso_name);
 | 
			
		||||
 | 
			
		||||
	exit(ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Overrides for Emacs so that we follow Linus's tabbing style.
 | 
			
		||||
 * Emacs will notice this stuff at the end of the file and automatically
 | 
			
		||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
			
		||||
 * of the file.
 | 
			
		||||
 * ---------------------------------------------------------------------------
 | 
			
		||||
 * Local variables:
 | 
			
		||||
 * c-file-style: "linux"
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										66
									
								
								daemons/dmeventd/dmeventd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								daemons/dmeventd/dmeventd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005-2007 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DMEVENTD_DOT_H__
 | 
			
		||||
#define __DMEVENTD_DOT_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,
 | 
			
		||||
	DM_EVENT_CMD_HELLO,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Message passed between client and daemon. */
 | 
			
		||||
struct dm_event_daemon_message {
 | 
			
		||||
	uint32_t cmd;
 | 
			
		||||
	uint32_t size;
 | 
			
		||||
	char *data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*      EXIT_SUCCESS             0 -- stdlib.h */
 | 
			
		||||
/*      EXIT_FAILURE             1 -- stdlib.h */
 | 
			
		||||
#define EXIT_LOCKFILE_INUSE      2
 | 
			
		||||
#define EXIT_DESC_CLOSE_FAILURE  3
 | 
			
		||||
#define EXIT_DESC_OPEN_FAILURE   4
 | 
			
		||||
#define EXIT_OPEN_PID_FAILURE    5
 | 
			
		||||
#define EXIT_FIFO_FAILURE        6
 | 
			
		||||
#define EXIT_CHDIR_FAILURE       7
 | 
			
		||||
 | 
			
		||||
#endif /* __DMEVENTD_DOT_H__ */
 | 
			
		||||
							
								
								
									
										809
									
								
								daemons/dmeventd/libdevmapper-event.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										809
									
								
								daemons/dmeventd/libdevmapper-event.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,809 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005-2007 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 <sys/wait.h>
 | 
			
		||||
#include <arpa/inet.h>		/* for htonl, ntohl */
 | 
			
		||||
 | 
			
		||||
static int _sequence_nr = 0;
 | 
			
		||||
 | 
			
		||||
struct dm_event_handler {
 | 
			
		||||
	char *dso;
 | 
			
		||||
 | 
			
		||||
	char *dev_name;
 | 
			
		||||
 | 
			
		||||
	char *uuid;
 | 
			
		||||
	int major;
 | 
			
		||||
	int minor;
 | 
			
		||||
	uint32_t timeout;
 | 
			
		||||
 | 
			
		||||
	enum dm_event_mask mask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	if (dmevh->dev_name)
 | 
			
		||||
		dm_free(dmevh->dev_name);
 | 
			
		||||
	if (dmevh->uuid)
 | 
			
		||||
		dm_free(dmevh->uuid);
 | 
			
		||||
	dmevh->dev_name = dmevh->uuid = NULL;
 | 
			
		||||
	dmevh->major = dmevh->minor = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dm_event_handler *dm_event_handler_create(void)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_event_handler *dmevh = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(dmevh = dm_malloc(sizeof(*dmevh))))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;
 | 
			
		||||
	dmevh->major = dmevh->minor = 0;
 | 
			
		||||
	dmevh->mask = 0;
 | 
			
		||||
	dmevh->timeout = 0;
 | 
			
		||||
 | 
			
		||||
	return dmevh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
	if (dmevh->dso)
 | 
			
		||||
		dm_free(dmevh->dso);
 | 
			
		||||
	dm_free(dmevh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
 | 
			
		||||
{
 | 
			
		||||
	if (!path) /* noop */
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (dmevh->dso)
 | 
			
		||||
		dm_free(dmevh->dso);
 | 
			
		||||
 | 
			
		||||
	dmevh->dso = dm_strdup(path);
 | 
			
		||||
	if (!dmevh->dso)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
 | 
			
		||||
{
 | 
			
		||||
	if (!dev_name)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
 | 
			
		||||
	dmevh->dev_name = dm_strdup(dev_name);
 | 
			
		||||
	if (!dmevh->dev_name)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
 | 
			
		||||
{
 | 
			
		||||
	if (!uuid)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
 | 
			
		||||
	dmevh->uuid = dm_strdup(uuid);
 | 
			
		||||
	if (!dmevh->dev_name)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
 | 
			
		||||
{
 | 
			
		||||
	int minor = dmevh->minor;
 | 
			
		||||
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
 | 
			
		||||
	dmevh->major = major;
 | 
			
		||||
	dmevh->minor = minor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
 | 
			
		||||
{
 | 
			
		||||
	int major = dmevh->major;
 | 
			
		||||
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
 | 
			
		||||
	dmevh->major = major;
 | 
			
		||||
	dmevh->minor = minor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
 | 
			
		||||
				     enum dm_event_mask evmask)
 | 
			
		||||
{
 | 
			
		||||
	dmevh->mask = evmask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
 | 
			
		||||
{
 | 
			
		||||
	dmevh->timeout = timeout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	return dmevh->dso;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	return dmevh->dev_name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	return dmevh->uuid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	return dmevh->major;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	return dmevh->minor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	return dmevh->timeout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	return dmevh->mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _check_message_id(struct dm_event_daemon_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	int pid, seq_nr;
 | 
			
		||||
 | 
			
		||||
	if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
 | 
			
		||||
	    (pid != getpid()) || (seq_nr != _sequence_nr)) {
 | 
			
		||||
		log_error("Ignoring out-of-sequence reply from dmeventd. "
 | 
			
		||||
			  "Expected %d:%d but received %s", getpid(),
 | 
			
		||||
			  _sequence_nr, msg->data);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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, i;
 | 
			
		||||
	fd_set fds;
 | 
			
		||||
	struct timeval tval = { 0, 0 };
 | 
			
		||||
	size_t size = 2 * sizeof(uint32_t);	/* status + size */
 | 
			
		||||
	char *buf = alloca(size);
 | 
			
		||||
	int header = 1;
 | 
			
		||||
 | 
			
		||||
	while (bytes < size) {
 | 
			
		||||
		for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
 | 
			
		||||
			/* Watch daemon read FIFO for input. */
 | 
			
		||||
			FD_ZERO(&fds);
 | 
			
		||||
			FD_SET(fifos->server, &fds);
 | 
			
		||||
			tval.tv_sec = 1;
 | 
			
		||||
			ret = select(fifos->server + 1, &fds, NULL, NULL,
 | 
			
		||||
				     &tval);
 | 
			
		||||
			if (ret < 0 && errno != EINTR) {
 | 
			
		||||
				log_error("Unable to read from event server");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (ret < 1) {
 | 
			
		||||
			log_error("Unable to read from event server.");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = read(fifos->server, buf + bytes, size);
 | 
			
		||||
		if (ret < 0) {
 | 
			
		||||
			if ((errno == EINTR) || (errno == EAGAIN))
 | 
			
		||||
				continue;
 | 
			
		||||
			else {
 | 
			
		||||
				log_error("Unable to read from event server.");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bytes += ret;
 | 
			
		||||
		if (bytes == 2 * sizeof(uint32_t) && header) {
 | 
			
		||||
			msg->cmd = ntohl(*((uint32_t *)buf));
 | 
			
		||||
			msg->size = ntohl(*((uint32_t *)buf + 1));
 | 
			
		||||
			buf = msg->data = dm_malloc(msg->size);
 | 
			
		||||
			size = msg->size;
 | 
			
		||||
			bytes = 0;
 | 
			
		||||
			header = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (bytes != size) {
 | 
			
		||||
		if (msg->data)
 | 
			
		||||
			dm_free(msg->data);
 | 
			
		||||
		msg->data = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytes == size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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;
 | 
			
		||||
 | 
			
		||||
	size_t size = 2 * sizeof(uint32_t) + msg->size;
 | 
			
		||||
	char *buf = alloca(size);
 | 
			
		||||
	char drainbuf[128];
 | 
			
		||||
	struct timeval tval = { 0, 0 };
 | 
			
		||||
 | 
			
		||||
	*((uint32_t *)buf) = htonl(msg->cmd);
 | 
			
		||||
	*((uint32_t *)buf + 1) = htonl(msg->size);
 | 
			
		||||
	memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
 | 
			
		||||
 | 
			
		||||
	/* drain the answer fifo */
 | 
			
		||||
	while (1) {
 | 
			
		||||
		FD_ZERO(&fds);
 | 
			
		||||
		FD_SET(fifos->server, &fds);
 | 
			
		||||
		tval.tv_usec = 100;
 | 
			
		||||
		ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
 | 
			
		||||
		if ((ret < 0) && (errno != EINTR)) {
 | 
			
		||||
			log_error("Unable to talk to event daemon");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (ret == 0)
 | 
			
		||||
			break;
 | 
			
		||||
		read(fifos->server, drainbuf, 127);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (bytes < size) {
 | 
			
		||||
		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)) {
 | 
			
		||||
				log_error("Unable to talk to event daemon");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} while (ret < 1);
 | 
			
		||||
 | 
			
		||||
		ret = write(fifos->client, ((char *) buf) + bytes,
 | 
			
		||||
			    size - bytes);
 | 
			
		||||
		if (ret < 0) {
 | 
			
		||||
			if ((errno == EINTR) || (errno == EAGAIN))
 | 
			
		||||
				continue;
 | 
			
		||||
			else {
 | 
			
		||||
				log_error("Unable to talk to event daemon");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bytes += ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytes == size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _daemon_talk(struct dm_event_fifos *fifos,
 | 
			
		||||
			struct dm_event_daemon_message *msg, int cmd,
 | 
			
		||||
			const char *dso_name, const char *dev_name,
 | 
			
		||||
			enum dm_event_mask evmask, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	const char *dso = dso_name ? dso_name : "";
 | 
			
		||||
	const char *dev = dev_name ? dev_name : "";
 | 
			
		||||
	const char *fmt = "%d:%d %s %s %u %" PRIu32;
 | 
			
		||||
	int msg_size;
 | 
			
		||||
	memset(msg, 0, sizeof(*msg));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Set command and pack the arguments
 | 
			
		||||
	 * into ASCII message string.
 | 
			
		||||
	 */
 | 
			
		||||
	msg->cmd = cmd;
 | 
			
		||||
	if (cmd == DM_EVENT_CMD_HELLO)
 | 
			
		||||
		fmt = "%d:%d HELLO";
 | 
			
		||||
	if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
 | 
			
		||||
				    dso, dev, evmask, timeout)) < 0) {
 | 
			
		||||
		log_error("_daemon_talk: message allocation failed");
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
	msg->size = msg_size;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Write command and message to and
 | 
			
		||||
	 * read status return code from daemon.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!_daemon_write(fifos, msg)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		dm_free(msg->data);
 | 
			
		||||
		msg->data = 0;
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
 | 
			
		||||
		if (msg->data)
 | 
			
		||||
			dm_free(msg->data);
 | 
			
		||||
		msg->data = 0;
 | 
			
		||||
 | 
			
		||||
		if (!_daemon_read(fifos, msg)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return -EIO;
 | 
			
		||||
		}
 | 
			
		||||
	} while (!_check_message_id(msg));
 | 
			
		||||
 | 
			
		||||
	_sequence_nr++;
 | 
			
		||||
 | 
			
		||||
	return (int32_t) msg->cmd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * start_daemon
 | 
			
		||||
 *
 | 
			
		||||
 * This function forks off a process (dmeventd) that will handle
 | 
			
		||||
 * the events.  I am currently test opening one of the fifos to
 | 
			
		||||
 * ensure that the daemon is running and listening...  I thought
 | 
			
		||||
 * this would be less expensive than fork/exec'ing every time.
 | 
			
		||||
 * Perhaps there is an even quicker/better way (no, checking the
 | 
			
		||||
 * lock file is _not_ a better way).
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 1 on success, 0 otherwise
 | 
			
		||||
 */
 | 
			
		||||
static int _start_daemon(struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	int pid, ret = 0;
 | 
			
		||||
	int status;
 | 
			
		||||
	struct stat statbuf;
 | 
			
		||||
 | 
			
		||||
	if (stat(fifos->client_path, &statbuf))
 | 
			
		||||
		goto start_server;
 | 
			
		||||
 | 
			
		||||
	if (!S_ISFIFO(statbuf.st_mode)) {
 | 
			
		||||
		log_error("%s is not a fifo.", fifos->client_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Anyone listening?  If not, errno will be ENXIO */
 | 
			
		||||
	fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
 | 
			
		||||
	if (fifos->client >= 0) {
 | 
			
		||||
		/* server is running and listening */
 | 
			
		||||
 | 
			
		||||
		close(fifos->client);
 | 
			
		||||
		return 1;
 | 
			
		||||
	} else if (errno != ENXIO) {
 | 
			
		||||
		/* problem */
 | 
			
		||||
 | 
			
		||||
		log_error("%s: Can't open client fifo %s: %s",
 | 
			
		||||
			  __func__, fifos->client_path, strerror(errno));
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      start_server:
 | 
			
		||||
	/* server is not running */
 | 
			
		||||
	pid = fork();
 | 
			
		||||
 | 
			
		||||
	if (pid < 0)
 | 
			
		||||
		log_error("Unable to fork.");
 | 
			
		||||
 | 
			
		||||
	else if (!pid) {
 | 
			
		||||
		execvp(DMEVENTD_PATH, NULL);
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (waitpid(pid, &status, 0) < 0)
 | 
			
		||||
			log_error("Unable to start dmeventd: %s",
 | 
			
		||||
				  strerror(errno));
 | 
			
		||||
		else if (WEXITSTATUS(status))
 | 
			
		||||
			log_error("Unable to start dmeventd.");
 | 
			
		||||
		else
 | 
			
		||||
			ret = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Initialize client. */
 | 
			
		||||
static int _init_client(struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME? Is fifo the most suitable method? 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;
 | 
			
		||||
 | 
			
		||||
	if (!_start_daemon(fifos)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Open the fifo used to read from the daemon. */
 | 
			
		||||
	if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
 | 
			
		||||
		log_error("%s: open server fifo %s",
 | 
			
		||||
			  __func__, fifos->server_path);
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Lock out anyone else trying to do communication with the daemon. */
 | 
			
		||||
	if (flock(fifos->server, LOCK_EX) < 0) {
 | 
			
		||||
		log_error("%s: flock %s", __func__, fifos->server_path);
 | 
			
		||||
		close(fifos->server);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/*	if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
 | 
			
		||||
	if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
 | 
			
		||||
		log_error("%s: Can't open client fifo %s: %s",
 | 
			
		||||
			  __func__, fifos->client_path, strerror(errno));
 | 
			
		||||
		close(fifos->server);
 | 
			
		||||
		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", fifos->server_path);
 | 
			
		||||
 | 
			
		||||
	close(fifos->client);
 | 
			
		||||
	close(fifos->server);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get uuid of a device */
 | 
			
		||||
static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	struct dm_info info;
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
 | 
			
		||||
		log_error("_get_device_info: dm_task creation for info failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dmevh->uuid)
 | 
			
		||||
		dm_task_set_uuid(dmt, dmevh->uuid);
 | 
			
		||||
	else if (dmevh->dev_name)
 | 
			
		||||
		dm_task_set_name(dmt, dmevh->dev_name);
 | 
			
		||||
	else if (dmevh->major && dmevh->minor) {
 | 
			
		||||
		dm_task_set_major(dmt, dmevh->major);
 | 
			
		||||
		dm_task_set_minor(dmt, dmevh->minor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	/* FIXME Add name or uuid or devno to messages */
 | 
			
		||||
	if (!dm_task_run(dmt)) {
 | 
			
		||||
		log_error("_get_device_info: dm_task_run() failed");
 | 
			
		||||
		goto failed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_get_info(dmt, &info)) {
 | 
			
		||||
		log_error("_get_device_info: failed to get info for device");
 | 
			
		||||
		goto failed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!info.exists) {
 | 
			
		||||
		log_error("_get_device_info: device not found");
 | 
			
		||||
		goto failed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return dmt;
 | 
			
		||||
 | 
			
		||||
failed:
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle the event (de)registration call and return negative error codes. */
 | 
			
		||||
static int _do_event(int cmd, struct dm_event_daemon_message *msg,
 | 
			
		||||
		     const char *dso_name, const char *dev_name,
 | 
			
		||||
		     enum dm_event_mask evmask, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_fifos fifos;
 | 
			
		||||
 | 
			
		||||
	if (!_init_client(&fifos)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -ESRCH;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
	if (msg->data)
 | 
			
		||||
		dm_free(msg->data);
 | 
			
		||||
	msg->data = 0;
 | 
			
		||||
 | 
			
		||||
	if (!ret)
 | 
			
		||||
		ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
 | 
			
		||||
 | 
			
		||||
	/* what is the opposite of init? */
 | 
			
		||||
	_dtr_client(&fifos);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* External library interface. */
 | 
			
		||||
int dm_event_register_handler(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 1, err;
 | 
			
		||||
	const char *uuid;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	struct dm_event_daemon_message msg = { 0, 0, NULL };
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = _get_device_info(dmevh))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uuid = dm_task_get_uuid(dmt);
 | 
			
		||||
 | 
			
		||||
	if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
 | 
			
		||||
			     dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
 | 
			
		||||
		log_error("%s: event registration failed: %s",
 | 
			
		||||
			  dm_task_get_name(dmt),
 | 
			
		||||
			  msg.data ? msg.data : strerror(-err));
 | 
			
		||||
		ret = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (msg.data)
 | 
			
		||||
		dm_free(msg.data);
 | 
			
		||||
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 1, err;
 | 
			
		||||
	const char *uuid;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	struct dm_event_daemon_message msg = { 0, 0, NULL };
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = _get_device_info(dmevh))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uuid = dm_task_get_uuid(dmt);
 | 
			
		||||
 | 
			
		||||
	if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
 | 
			
		||||
			    dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
 | 
			
		||||
		log_error("%s: event deregistration failed: %s",
 | 
			
		||||
			  dm_task_get_name(dmt),
 | 
			
		||||
			  msg.data ? msg.data : strerror(-err));
 | 
			
		||||
		ret = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (msg.data)
 | 
			
		||||
		dm_free(msg.data);
 | 
			
		||||
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Fetch a string off src and duplicate it into *dest. */
 | 
			
		||||
/* FIXME: move to separate module to share with the daemon. */
 | 
			
		||||
static char *_fetch_string(char **src, const int delimiter)
 | 
			
		||||
{
 | 
			
		||||
	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 **uuid, enum dm_event_mask *evmask)
 | 
			
		||||
{
 | 
			
		||||
	char *id = NULL;
 | 
			
		||||
	char *p = msg->data;
 | 
			
		||||
 | 
			
		||||
	if ((id = _fetch_string(&p, ' ')) &&
 | 
			
		||||
	    (*dso_name = _fetch_string(&p, ' ')) &&
 | 
			
		||||
	    (*uuid = _fetch_string(&p, ' '))) {
 | 
			
		||||
		*evmask = atoi(p);
 | 
			
		||||
 | 
			
		||||
		dm_free(id);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (id)
 | 
			
		||||
		dm_free(id);
 | 
			
		||||
	return -ENOMEM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	const char *uuid = NULL;
 | 
			
		||||
	char *reply_dso = NULL, *reply_uuid = NULL;
 | 
			
		||||
	enum dm_event_mask reply_mask = 0;
 | 
			
		||||
	struct dm_task *dmt = NULL;
 | 
			
		||||
	struct dm_event_daemon_message msg = { 0, 0, NULL };
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = _get_device_info(dmevh))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uuid = dm_task_get_uuid(dmt);
 | 
			
		||||
 | 
			
		||||
	if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
 | 
			
		||||
			     DM_EVENT_CMD_GET_REGISTERED_DEVICE,
 | 
			
		||||
			      &msg, dmevh->dso, uuid, dmevh->mask, 0))) {
 | 
			
		||||
		/* FIXME this will probably horribly break if we get
 | 
			
		||||
		   ill-formatted reply */
 | 
			
		||||
		ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = -ENOENT;
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
	dmt = NULL;
 | 
			
		||||
 | 
			
		||||
	if (msg.data) {
 | 
			
		||||
		dm_free(msg.data);
 | 
			
		||||
		msg.data = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
	dmevh->uuid = dm_strdup(reply_uuid);
 | 
			
		||||
	if (!dmevh->uuid) {
 | 
			
		||||
		ret = -ENOMEM;
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = _get_device_info(dmevh))) {
 | 
			
		||||
		ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_event_handler_set_dso(dmevh, reply_dso);
 | 
			
		||||
	dm_event_handler_set_event_mask(dmevh, reply_mask);
 | 
			
		||||
 | 
			
		||||
	if (reply_dso) {
 | 
			
		||||
		dm_free(reply_dso);
 | 
			
		||||
		reply_dso = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (reply_uuid) {
 | 
			
		||||
		dm_free(reply_uuid);
 | 
			
		||||
		reply_uuid = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
 | 
			
		||||
	if (!dmevh->dev_name) {
 | 
			
		||||
		ret = -ENOMEM;
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct dm_info info;
 | 
			
		||||
	if (!dm_task_get_info(dmt, &info)) {
 | 
			
		||||
		ret = -1;
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dmevh->major = info.major;
 | 
			
		||||
	dmevh->minor = info.minor;
 | 
			
		||||
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
	if (msg.data)
 | 
			
		||||
		dm_free(msg.data);
 | 
			
		||||
	if (reply_dso)
 | 
			
		||||
		dm_free(reply_dso);
 | 
			
		||||
	if (reply_uuid)
 | 
			
		||||
		dm_free(reply_uuid);
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
	if (dmt)
 | 
			
		||||
		dm_task_destroy(dmt);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0				/* left out for now */
 | 
			
		||||
 | 
			
		||||
static char *_skip_string(char *src, const int delimiter)
 | 
			
		||||
{
 | 
			
		||||
	src = srtchr(src, delimiter);
 | 
			
		||||
	if (src && *(src + 1))
 | 
			
		||||
		return src + 1;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_event_daemon_message msg = { 0, 0, NULL };
 | 
			
		||||
 | 
			
		||||
	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(const char *device_path, uint32_t *timeout)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct dm_event_daemon_message msg = { 0, 0, NULL };
 | 
			
		||||
 | 
			
		||||
	if (!device_exists(device_path))
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
 | 
			
		||||
			     0, 0))) {
 | 
			
		||||
		char *p = _skip_string(msg.data, ' ');
 | 
			
		||||
		if (!p) {
 | 
			
		||||
			log_error("malformed reply from dmeventd '%s'\n",
 | 
			
		||||
				  msg.data);
 | 
			
		||||
			return -EIO;
 | 
			
		||||
		}
 | 
			
		||||
		*timeout = atoi(p);
 | 
			
		||||
	}
 | 
			
		||||
	if (msg.data)
 | 
			
		||||
		dm_free(msg.data);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										106
									
								
								daemons/dmeventd/libdevmapper-event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								daemons/dmeventd/libdevmapper-event.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005-2007 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>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Event library interface.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
enum dm_event_mask {
 | 
			
		||||
	DM_EVENT_SETTINGS_MASK  = 0x0000FF,
 | 
			
		||||
	DM_EVENT_SINGLE		= 0x000001, /* Report multiple errors just once. */
 | 
			
		||||
	DM_EVENT_MULTI		= 0x000002, /* Report all of them. */
 | 
			
		||||
 | 
			
		||||
	DM_EVENT_ERROR_MASK     = 0x00FF00,
 | 
			
		||||
	DM_EVENT_SECTOR_ERROR	= 0x000100, /* Failure on a particular sector. */
 | 
			
		||||
	DM_EVENT_DEVICE_ERROR	= 0x000200, /* Device failure. */
 | 
			
		||||
	DM_EVENT_PATH_ERROR	= 0x000400, /* Failure on an io path. */
 | 
			
		||||
	DM_EVENT_ADAPTOR_ERROR	= 0x000800, /* Failure of a host adaptor. */
 | 
			
		||||
 | 
			
		||||
	DM_EVENT_STATUS_MASK    = 0xFF0000,
 | 
			
		||||
	DM_EVENT_SYNC_STATUS	= 0x010000, /* Mirror synchronization completed/failed. */
 | 
			
		||||
	DM_EVENT_TIMEOUT	= 0x020000, /* Timeout has occured */
 | 
			
		||||
 | 
			
		||||
	DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
 | 
			
		||||
 | 
			
		||||
struct dm_event_handler;
 | 
			
		||||
 | 
			
		||||
struct dm_event_handler *dm_event_handler_create(void);
 | 
			
		||||
void dm_event_handler_destroy(struct dm_event_handler *dmevh);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Path of shared library to handle events.
 | 
			
		||||
 *
 | 
			
		||||
 * All of dso, device_name and uuid strings are duplicated, you do not
 | 
			
		||||
 * need to keep the pointers valid after the call succeeds. Thes may
 | 
			
		||||
 * return -ENOMEM though.
 | 
			
		||||
 */
 | 
			
		||||
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Identify the device to monitor by exactly one of device_name, uuid or
 | 
			
		||||
 * device number. String arguments are duplicated, see above.
 | 
			
		||||
 */
 | 
			
		||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
 | 
			
		||||
 | 
			
		||||
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
 | 
			
		||||
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
 | 
			
		||||
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Specify mask for events to monitor.
 | 
			
		||||
 */
 | 
			
		||||
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
 | 
			
		||||
				     enum dm_event_mask evmask);
 | 
			
		||||
 | 
			
		||||
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
 | 
			
		||||
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
 | 
			
		||||
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
 | 
			
		||||
int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
 | 
			
		||||
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
 | 
			
		||||
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
 | 
			
		||||
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
 | 
			
		||||
 | 
			
		||||
/* FIXME Review interface (what about this next thing?) */
 | 
			
		||||
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initiate monitoring using dmeventd.
 | 
			
		||||
 */
 | 
			
		||||
int dm_event_register_handler(const struct dm_event_handler *dmevh);
 | 
			
		||||
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
 | 
			
		||||
 | 
			
		||||
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
 | 
			
		||||
   detailed descriptions. */
 | 
			
		||||
void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
 | 
			
		||||
int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
 | 
			
		||||
int unregister_device(const char *device_name, const char *uuid, int major,
 | 
			
		||||
		      int minor, void **user);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										12
									
								
								daemons/dmeventd/libdevmapper-event.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								daemons/dmeventd/libdevmapper-event.pc.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
prefix=@prefix@
 | 
			
		||||
exec_prefix=@exec_prefix@
 | 
			
		||||
libdir=@libdir@
 | 
			
		||||
includedir=@includedir@
 | 
			
		||||
 | 
			
		||||
Name: devmapper-event
 | 
			
		||||
Description: device-mapper event library
 | 
			
		||||
Version: @DM_LIB_VERSION@
 | 
			
		||||
Requires: devmapper
 | 
			
		||||
Cflags: -I${includedir}
 | 
			
		||||
Libs: -L${libdir} -ldevmapper-event
 | 
			
		||||
Libs.private: -lpthread -ldl
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
#
 | 
			
		||||
# Create test devices for dmeventd
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
trap "rm -f /tmp/tmp.$$" 0 1 2 3 15
 | 
			
		||||
 | 
			
		||||
echo "0 1024 zero" > /tmp/tmp.$$
 | 
			
		||||
dmsetup create test /tmp/tmp.$$
 | 
			
		||||
dmsetup create test1 /tmp/tmp.$$
 | 
			
		||||
 | 
			
		||||
kill -15 $$
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the device-mapper userspace tools.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdm-event.h"
 | 
			
		||||
#include "libmultilog.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void process_event(char *device, enum event_type event)
 | 
			
		||||
{
 | 
			
		||||
	log_err("[%s] %s(%d) - Device: %s, Event %d\n",
 | 
			
		||||
		__FILE__, __func__, __LINE__, device, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(char *device)
 | 
			
		||||
{
 | 
			
		||||
	log_err("[%s] %s(%d) - Device: %s\n",
 | 
			
		||||
		__FILE__, __func__, __LINE__, device);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(char *device)
 | 
			
		||||
{
 | 
			
		||||
	log_err("[%s] %s(%d) - Device: %s\n",
 | 
			
		||||
		__FILE__, __func__, __LINE__, device);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								daemons/dmeventd/plugins/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								daemons/dmeventd/plugins/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of 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 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)/$<
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										281
									
								
								daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,281 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "lvm2cmd.h"
 | 
			
		||||
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include <libdevmapper-event.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 */
 | 
			
		||||
/* FIXME Missing openlog? */
 | 
			
		||||
 | 
			
		||||
#define ME_IGNORE    0
 | 
			
		||||
#define ME_INSYNC    1
 | 
			
		||||
#define ME_FAILURE   2
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * register_device() is called first and performs initialisation.
 | 
			
		||||
 * Only one device may be registered or unregistered at a time.
 | 
			
		||||
 */
 | 
			
		||||
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Number of active registrations.
 | 
			
		||||
 */
 | 
			
		||||
static int _register_count = 0;
 | 
			
		||||
 | 
			
		||||
static struct dm_pool *_mem_pool = NULL;
 | 
			
		||||
static void *_lvm_handle = NULL;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Currently only one event can be processed at a time.
 | 
			
		||||
 */
 | 
			
		||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
static int _get_mirror_event(char *params)
 | 
			
		||||
{
 | 
			
		||||
	int i, r = ME_INSYNC;
 | 
			
		||||
	char **args = NULL;
 | 
			
		||||
	char *dev_status_str;
 | 
			
		||||
	char *log_status_str;
 | 
			
		||||
	char *sync_str;
 | 
			
		||||
	char *p = NULL;
 | 
			
		||||
	int log_argc, num_devs;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * dm core parms:	     0 409600 mirror
 | 
			
		||||
	 * Mirror core parms:	     2 253:4 253:5 400/400
 | 
			
		||||
	 * New-style failure params: 1 AA
 | 
			
		||||
	 * New-style log params:     3 cluster 253:3 A
 | 
			
		||||
	 *			 or  3 disk 253:3 A
 | 
			
		||||
	 *			 or  1 core
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/* number of devices */
 | 
			
		||||
	if (!dm_split_words(params, 1, 0, &p))
 | 
			
		||||
		goto out_parse;
 | 
			
		||||
 | 
			
		||||
	if (!(num_devs = atoi(p)))
 | 
			
		||||
		goto out_parse;
 | 
			
		||||
	p += strlen(p) + 1;
 | 
			
		||||
 | 
			
		||||
	/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
 | 
			
		||||
	args = dm_malloc((num_devs + 7) * sizeof(char *));
 | 
			
		||||
	if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
 | 
			
		||||
		goto out_parse;
 | 
			
		||||
 | 
			
		||||
	dev_status_str = args[2 + num_devs];
 | 
			
		||||
	log_argc = atoi(args[3 + num_devs]);
 | 
			
		||||
	log_status_str = args[3 + num_devs + log_argc];
 | 
			
		||||
	sync_str = args[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]);
 | 
			
		||||
			r = ME_FAILURE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/* Check for bad disk log device */
 | 
			
		||||
	if (log_argc > 1 && log_status_str[0] == 'D') {
 | 
			
		||||
		syslog(LOG_ERR, "Log device, %s, has failed.\n",
 | 
			
		||||
		       args[2 + num_devs + log_argc]);
 | 
			
		||||
		r = ME_FAILURE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (r == ME_FAILURE)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	p = strstr(sync_str, "/");
 | 
			
		||||
	if (p) {
 | 
			
		||||
		p[0] = '\0';
 | 
			
		||||
		if (strcmp(sync_str, p+1))
 | 
			
		||||
			r = ME_IGNORE;
 | 
			
		||||
		p[0] = '/';
 | 
			
		||||
	} else
 | 
			
		||||
		goto out_parse;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	if (args)
 | 
			
		||||
		dm_free(args);
 | 
			
		||||
	return r;
 | 
			
		||||
	
 | 
			
		||||
out_parse:
 | 
			
		||||
	if (args)
 | 
			
		||||
		dm_free(args);
 | 
			
		||||
	syslog(LOG_ERR, "Unable to parse mirror status string.");
 | 
			
		||||
	return ME_IGNORE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
#define CMD_SIZE 256	/* FIXME Use system restriction */
 | 
			
		||||
	char cmd_str[CMD_SIZE];
 | 
			
		||||
	char *vg = NULL, *lv = NULL, *layer = NULL;
 | 
			
		||||
 | 
			
		||||
	if (strlen(device) > 200)  /* FIXME Use real restriction */
 | 
			
		||||
		return -ENAMETOOLONG;	/* FIXME These return code distinctions are not used so remove them! */
 | 
			
		||||
 | 
			
		||||
	if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to determine VG name from %s",
 | 
			
		||||
		       device);
 | 
			
		||||
		return -ENOMEM;	/* FIXME Replace with generic error return - reason for failure has already got logged */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Is any sanity-checking required on %s? */
 | 
			
		||||
	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --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; /* FIXME Replace with generic error return - reason for failure has already got logged */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = lvm2_run(_lvm_handle, cmd_str);
 | 
			
		||||
 | 
			
		||||
	dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
	return (r == 1) ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(struct dm_task *dmt, enum dm_event_mask event,
 | 
			
		||||
		   void **unused __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *target_type = NULL;
 | 
			
		||||
	char *params;
 | 
			
		||||
	const char *device = dm_task_get_name(dmt);
 | 
			
		||||
 | 
			
		||||
	if (pthread_mutex_trylock(&_event_mutex)) {
 | 
			
		||||
		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting...");
 | 
			
		||||
		pthread_mutex_lock(&_event_mutex);
 | 
			
		||||
	}
 | 
			
		||||
	do {
 | 
			
		||||
		next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
					  &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
		if (!target_type) {
 | 
			
		||||
			syslog(LOG_INFO, "%s mapping lost.\n", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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))
 | 
			
		||||
				/* FIXME Why are all the error return codes unused? Get rid of them? */
 | 
			
		||||
				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:
 | 
			
		||||
			/* FIXME Provide value then! */
 | 
			
		||||
			syslog(LOG_INFO, "Unknown event received.\n");
 | 
			
		||||
		}
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_unlock(&_event_mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device, const char *uuid, int major, int minor,
 | 
			
		||||
		   void **unused __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	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)))
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	if (!_lvm_handle) {
 | 
			
		||||
		lvm2_log_fn(_temporary_log_fn);
 | 
			
		||||
		if (!(_lvm_handle = lvm2_init())) {
 | 
			
		||||
			dm_pool_destroy(_mem_pool);
 | 
			
		||||
			_mem_pool = NULL;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
 | 
			
		||||
		/* FIXME Temporary: move to dmeventd core */
 | 
			
		||||
		lvm2_run(_lvm_handle, "_memlock_inc");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_register_count++;
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	pthread_mutex_unlock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device, const char *uuid, int major, int minor,
 | 
			
		||||
		   void **unused __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	pthread_mutex_lock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
 | 
			
		||||
	       device);
 | 
			
		||||
 | 
			
		||||
	if (!--_register_count) {
 | 
			
		||||
		dm_pool_destroy(_mem_pool);
 | 
			
		||||
		_mem_pool = NULL;
 | 
			
		||||
		lvm2_run(_lvm_handle, "_memlock_dec");
 | 
			
		||||
		lvm2_exit(_lvm_handle);
 | 
			
		||||
		_lvm_handle = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_unlock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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 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 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)/$<
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										281
									
								
								dmeventd/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								dmeventd/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,281 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "lvm2cmd.h"
 | 
			
		||||
 | 
			
		||||
#include <libdevmapper.h>
 | 
			
		||||
#include <libdevmapper-event.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 */
 | 
			
		||||
/* FIXME Missing openlog? */
 | 
			
		||||
 | 
			
		||||
#define ME_IGNORE    0
 | 
			
		||||
#define ME_INSYNC    1
 | 
			
		||||
#define ME_FAILURE   2
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * register_device() is called first and performs initialisation.
 | 
			
		||||
 * Only one device may be registered or unregistered at a time.
 | 
			
		||||
 */
 | 
			
		||||
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Number of active registrations.
 | 
			
		||||
 */
 | 
			
		||||
static int _register_count = 0;
 | 
			
		||||
 | 
			
		||||
static struct dm_pool *_mem_pool = NULL;
 | 
			
		||||
static void *_lvm_handle = NULL;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Currently only one event can be processed at a time.
 | 
			
		||||
 */
 | 
			
		||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
static int _get_mirror_event(char *params)
 | 
			
		||||
{
 | 
			
		||||
	int i, r = ME_INSYNC;
 | 
			
		||||
	char **args = NULL;
 | 
			
		||||
	char *dev_status_str;
 | 
			
		||||
	char *log_status_str;
 | 
			
		||||
	char *sync_str;
 | 
			
		||||
	char *p = NULL;
 | 
			
		||||
	int log_argc, num_devs;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * dm core parms:	     0 409600 mirror
 | 
			
		||||
	 * Mirror core parms:	     2 253:4 253:5 400/400
 | 
			
		||||
	 * New-style failure params: 1 AA
 | 
			
		||||
	 * New-style log params:     3 cluster 253:3 A
 | 
			
		||||
	 *			 or  3 disk 253:3 A
 | 
			
		||||
	 *			 or  1 core
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/* number of devices */
 | 
			
		||||
	if (!dm_split_words(params, 1, 0, &p))
 | 
			
		||||
		goto out_parse;
 | 
			
		||||
 | 
			
		||||
	if (!(num_devs = atoi(p)))
 | 
			
		||||
		goto out_parse;
 | 
			
		||||
	p += strlen(p) + 1;
 | 
			
		||||
 | 
			
		||||
	/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
 | 
			
		||||
	args = dm_malloc((num_devs + 7) * sizeof(char *));
 | 
			
		||||
	if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
 | 
			
		||||
		goto out_parse;
 | 
			
		||||
 | 
			
		||||
	dev_status_str = args[2 + num_devs];
 | 
			
		||||
	log_argc = atoi(args[3 + num_devs]);
 | 
			
		||||
	log_status_str = args[3 + num_devs + log_argc];
 | 
			
		||||
	sync_str = args[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]);
 | 
			
		||||
			r = ME_FAILURE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/* Check for bad disk log device */
 | 
			
		||||
	if (log_argc > 1 && log_status_str[0] == 'D') {
 | 
			
		||||
		syslog(LOG_ERR, "Log device, %s, has failed.\n",
 | 
			
		||||
		       args[2 + num_devs + log_argc]);
 | 
			
		||||
		r = ME_FAILURE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (r == ME_FAILURE)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	p = strstr(sync_str, "/");
 | 
			
		||||
	if (p) {
 | 
			
		||||
		p[0] = '\0';
 | 
			
		||||
		if (strcmp(sync_str, p+1))
 | 
			
		||||
			r = ME_IGNORE;
 | 
			
		||||
		p[0] = '/';
 | 
			
		||||
	} else
 | 
			
		||||
		goto out_parse;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	if (args)
 | 
			
		||||
		dm_free(args);
 | 
			
		||||
	return r;
 | 
			
		||||
	
 | 
			
		||||
out_parse:
 | 
			
		||||
	if (args)
 | 
			
		||||
		dm_free(args);
 | 
			
		||||
	syslog(LOG_ERR, "Unable to parse mirror status string.");
 | 
			
		||||
	return ME_IGNORE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
#define CMD_SIZE 256	/* FIXME Use system restriction */
 | 
			
		||||
	char cmd_str[CMD_SIZE];
 | 
			
		||||
	char *vg = NULL, *lv = NULL, *layer = NULL;
 | 
			
		||||
 | 
			
		||||
	if (strlen(device) > 200)  /* FIXME Use real restriction */
 | 
			
		||||
		return -ENAMETOOLONG;	/* FIXME These return code distinctions are not used so remove them! */
 | 
			
		||||
 | 
			
		||||
	if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to determine VG name from %s",
 | 
			
		||||
		       device);
 | 
			
		||||
		return -ENOMEM;	/* FIXME Replace with generic error return - reason for failure has already got logged */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Is any sanity-checking required on %s? */
 | 
			
		||||
	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --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; /* FIXME Replace with generic error return - reason for failure has already got logged */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = lvm2_run(_lvm_handle, cmd_str);
 | 
			
		||||
 | 
			
		||||
	dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */
 | 
			
		||||
	return (r == 1) ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(struct dm_task *dmt, enum dm_event_mask event,
 | 
			
		||||
		   void **unused __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *target_type = NULL;
 | 
			
		||||
	char *params;
 | 
			
		||||
	const char *device = dm_task_get_name(dmt);
 | 
			
		||||
 | 
			
		||||
	if (pthread_mutex_trylock(&_event_mutex)) {
 | 
			
		||||
		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting...");
 | 
			
		||||
		pthread_mutex_lock(&_event_mutex);
 | 
			
		||||
	}
 | 
			
		||||
	do {
 | 
			
		||||
		next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
					  &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
		if (!target_type) {
 | 
			
		||||
			syslog(LOG_INFO, "%s mapping lost.\n", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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))
 | 
			
		||||
				/* FIXME Why are all the error return codes unused? Get rid of them? */
 | 
			
		||||
				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:
 | 
			
		||||
			/* FIXME Provide value then! */
 | 
			
		||||
			syslog(LOG_INFO, "Unknown event received.\n");
 | 
			
		||||
		}
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_unlock(&_event_mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device, const char *uuid, int major, int minor,
 | 
			
		||||
		   void **unused __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	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)))
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	if (!_lvm_handle) {
 | 
			
		||||
		lvm2_log_fn(_temporary_log_fn);
 | 
			
		||||
		if (!(_lvm_handle = lvm2_init())) {
 | 
			
		||||
			dm_pool_destroy(_mem_pool);
 | 
			
		||||
			_mem_pool = NULL;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
 | 
			
		||||
		/* FIXME Temporary: move to dmeventd core */
 | 
			
		||||
		lvm2_run(_lvm_handle, "_memlock_inc");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_register_count++;
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	pthread_mutex_unlock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device, const char *uuid, int major, int minor,
 | 
			
		||||
		   void **unused __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	pthread_mutex_lock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
 | 
			
		||||
	       device);
 | 
			
		||||
 | 
			
		||||
	if (!--_register_count) {
 | 
			
		||||
		dm_pool_destroy(_mem_pool);
 | 
			
		||||
		_mem_pool = NULL;
 | 
			
		||||
		lvm2_run(_lvm_handle, "_memlock_dec");
 | 
			
		||||
		lvm2_exit(_lvm_handle);
 | 
			
		||||
		_lvm_handle = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_unlock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
# 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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										117
									
								
								doc/example.conf
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								doc/example.conf
									
									
									
									
									
								
							@@ -19,6 +19,14 @@ devices {
 | 
			
		||||
    # to use with LVM2.
 | 
			
		||||
    scan = [ "/dev" ]
 | 
			
		||||
 | 
			
		||||
    # If several entries in the scanned directories correspond to the
 | 
			
		||||
    # same block device and the tools need to display a name for device,
 | 
			
		||||
    # all the pathnames are matched against each item in the following
 | 
			
		||||
    # list of regular expressions in turn and the first match is used.
 | 
			
		||||
    preferred_names = [ ]
 | 
			
		||||
 | 
			
		||||
    # preferred_names = [ "^/dev/mpath/", "^/dev/[hs]d" ]
 | 
			
		||||
 | 
			
		||||
    # A filter that tells LVM2 to only use a restricted set of devices.
 | 
			
		||||
    # The filter consists of an array of regular expressions.  These
 | 
			
		||||
    # expressions can be delimited by a character of your choice, and
 | 
			
		||||
@@ -56,10 +64,14 @@ devices {
 | 
			
		||||
    # filter = [ "a|^/dev/hda8$|", "r/.*/" ]
 | 
			
		||||
 | 
			
		||||
    # The results of the filtering are cached on disk to avoid
 | 
			
		||||
    # rescanning dud devices (which can take a very long time).  By
 | 
			
		||||
    # default this cache file is hidden in the /etc/lvm directory.
 | 
			
		||||
    # It is safe to delete this file: the tools regenerate it.
 | 
			
		||||
    cache = "/etc/lvm/.cache"
 | 
			
		||||
    # rescanning dud devices (which can take a very long time).
 | 
			
		||||
    # By default this cache is stored in the /etc/lvm/cache directory
 | 
			
		||||
    # in a file called '.cache'.
 | 
			
		||||
    # It is safe to delete the contents: the tools regenerate it.
 | 
			
		||||
    # (The old setting 'cache' is still respected if neither of
 | 
			
		||||
    # these new ones is present.)
 | 
			
		||||
    cache_dir = "/etc/lvm/cache"
 | 
			
		||||
    cache_file_prefix = ""
 | 
			
		||||
 | 
			
		||||
    # You can turn off writing this cache file by setting this to 0.
 | 
			
		||||
    write_cache_state = 1
 | 
			
		||||
@@ -79,6 +91,12 @@ devices {
 | 
			
		||||
    # software RAID (md) devices by looking for md superblocks.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    md_component_detection = 1
 | 
			
		||||
 | 
			
		||||
    # If, while scanning the system for PVs, LVM2 encounters a device-mapper
 | 
			
		||||
    # device that has its I/O suspended, it waits for it to become accessible.
 | 
			
		||||
    # Set this to 1 to skip such devices.  This should only be needed
 | 
			
		||||
    # in recovery situations.
 | 
			
		||||
    ignore_suspended_devices = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This section that allows you to configure the nature of the
 | 
			
		||||
@@ -182,6 +200,9 @@ global {
 | 
			
		||||
    # command.  Defaults to off.
 | 
			
		||||
    test = 0
 | 
			
		||||
 | 
			
		||||
    # Default value for --units argument
 | 
			
		||||
    units = "h"
 | 
			
		||||
 | 
			
		||||
    # Whether or not to communicate with the kernel device-mapper.
 | 
			
		||||
    # Set to 0 if you want to use the tools to manipulate LVM metadata 
 | 
			
		||||
    # without activating any logical volumes.
 | 
			
		||||
@@ -207,11 +228,26 @@ global {
 | 
			
		||||
    # Location of proc filesystem
 | 
			
		||||
    proc = "/proc"
 | 
			
		||||
 | 
			
		||||
    # Type of locking to use. Defaults to file-based locking (1).
 | 
			
		||||
    # Type of locking to use. Defaults to local file-based locking (1).
 | 
			
		||||
    # Turn locking off by setting to 0 (dangerous: risks metadata corruption
 | 
			
		||||
    # if LVM2 commands get run concurrently).
 | 
			
		||||
    # Type 2 uses the external shared library locking_library.
 | 
			
		||||
    # Type 3 uses built-in clustered locking.
 | 
			
		||||
    locking_type = 1
 | 
			
		||||
 | 
			
		||||
    # If using external locking (type 2) and initialisation fails,
 | 
			
		||||
    # with this set to 1 an attempt will be made to use the built-in
 | 
			
		||||
    # clustered locking.
 | 
			
		||||
    # If you are using a customised locking_library you should set this to 0.
 | 
			
		||||
    fallback_to_clustered_locking = 1
 | 
			
		||||
 | 
			
		||||
    # If an attempt to initialise type 2 or type 3 locking failed, perhaps
 | 
			
		||||
    # because cluster components such as clvmd are not running, with this set
 | 
			
		||||
    # to 1 an attempt will be made to use local file-based locking (type 1).
 | 
			
		||||
    # If this succeeds, only commands against local volume groups will proceed.
 | 
			
		||||
    # Volume Groups marked as clustered will be ignored.
 | 
			
		||||
    fallback_to_local_locking = 1
 | 
			
		||||
 | 
			
		||||
    # Local non-LV directory that holds file-based locks while commands are
 | 
			
		||||
    # in progress.  A directory like /tmp that may get wiped on reboot is OK.
 | 
			
		||||
    locking_dir = "/var/lock/lvm"
 | 
			
		||||
@@ -223,6 +259,9 @@ global {
 | 
			
		||||
 | 
			
		||||
    # Search this directory first for shared libraries.
 | 
			
		||||
    #   library_dir = "/lib"
 | 
			
		||||
 | 
			
		||||
    # The external locking library to load if locking_type is set to 2.
 | 
			
		||||
    #   locking_library = "liblvm2clusterlock.so"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
activation {
 | 
			
		||||
@@ -232,9 +271,6 @@ activation {
 | 
			
		||||
    # target or make it return zeros.
 | 
			
		||||
    missing_stripe_filler = "/dev/ioerror"
 | 
			
		||||
 | 
			
		||||
    # Size (in KB) of each copy operation when mirroring
 | 
			
		||||
    mirror_region_size = 512
 | 
			
		||||
 | 
			
		||||
    # How much stack (in KB) to reserve for use while devices suspended
 | 
			
		||||
    reserved_stack = 256
 | 
			
		||||
 | 
			
		||||
@@ -251,6 +287,60 @@ activation {
 | 
			
		||||
    #   "@*" matches if any tag defined on the host is also set in the LV or VG
 | 
			
		||||
    #
 | 
			
		||||
    # volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
 | 
			
		||||
 | 
			
		||||
    # Size (in KB) of each copy operation when mirroring
 | 
			
		||||
    mirror_region_size = 512
 | 
			
		||||
 | 
			
		||||
    # Setting to use when there is no readahead value stored in the metadata.
 | 
			
		||||
    #
 | 
			
		||||
    # "none" - Disable readahead.
 | 
			
		||||
    # "auto" - Use default value chosen by kernel.
 | 
			
		||||
    readahead = "auto"
 | 
			
		||||
 | 
			
		||||
    # 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
 | 
			
		||||
    # how a device failure affecting a mirror is handled.
 | 
			
		||||
    # A mirror is composed of mirror images (copies) and a log.
 | 
			
		||||
    # A disk log ensures that a mirror does not need to be re-synced
 | 
			
		||||
    # (all copies made the same) every time a machine reboots or crashes.
 | 
			
		||||
    #
 | 
			
		||||
    # In the event of a failure, the specified policy will be used to
 | 
			
		||||
    # determine what happens:
 | 
			
		||||
    #
 | 
			
		||||
    # "remove" - Simply remove the faulty device and run without it.  If
 | 
			
		||||
    #            the log device fails, the mirror would convert to using
 | 
			
		||||
    #            an in-memory log.  This means the mirror will not
 | 
			
		||||
    #            remember its sync status across crashes/reboots and
 | 
			
		||||
    #            the entire mirror will be re-synced.  If a
 | 
			
		||||
    #            mirror image fails, the mirror will convert to a
 | 
			
		||||
    #            non-mirrored device if there is only one remaining good
 | 
			
		||||
    #            copy.
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate" - Remove the faulty device and try to allocate space on
 | 
			
		||||
    #            a new device to be a replacement for the failed device.
 | 
			
		||||
    #            Using this policy for the log is fast and maintains the
 | 
			
		||||
    #            ability to remember sync state through crashes/reboots.
 | 
			
		||||
    #            Using this policy for a mirror device is slow, as it
 | 
			
		||||
    #            requires the mirror to resynchronize the devices, but it
 | 
			
		||||
    #            will preserve the mirror characteristic of the device.
 | 
			
		||||
    #            This policy acts like "remove" if no suitable device and
 | 
			
		||||
    #            space can be allocated for the replacement.
 | 
			
		||||
    #            Currently this is not implemented properly and behaves
 | 
			
		||||
    #            similarly to:
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate_anywhere" - Operates like "allocate", but it does not
 | 
			
		||||
    #            require that the new space being allocated be on a
 | 
			
		||||
    #            device is not part of the mirror.  For a log device
 | 
			
		||||
    #            failure, this could mean that the log is allocated on
 | 
			
		||||
    #            the same device as a mirror device.  For a mirror
 | 
			
		||||
    #            device, this could mean that the mirror device is
 | 
			
		||||
    #            allocated on the same device as another mirror device.
 | 
			
		||||
    #            This policy would not be wise for mirror devices
 | 
			
		||||
    #            because it would break the redundant nature of the
 | 
			
		||||
    #            mirror.  This policy acts like "remove" if no suitable
 | 
			
		||||
    #            device and space can be allocated for the replacement.
 | 
			
		||||
 | 
			
		||||
    mirror_log_fault_policy = "allocate"
 | 
			
		||||
    mirror_device_fault_policy = "remove"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -289,4 +379,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"
 | 
			
		||||
#}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,8 @@ LVM2 that is running the LV's on my development box.
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   The important this to note is the devices section which makes sure that
 | 
			
		||||
   only the loopback devices are considered for LVM2 operations.
 | 
			
		||||
   The important thing to note is the devices section which makes sure
 | 
			
		||||
   that only the loopback devices are considered for LVM2 operations.
 | 
			
		||||
 | 
			
		||||
4) When you want to use this test setup just set the environment
 | 
			
		||||
   variable LVM_SYSTEM_DIR to point to your config directory
 | 
			
		||||
@@ -39,8 +39,3 @@ LVM2 that is running the LV's on my development box.
 | 
			
		||||
7) Test away.  Make sure that you are explicit about which lvm
 | 
			
		||||
   executable you want to execute (eg, ./lvm if you are in
 | 
			
		||||
   LVM2/tools).
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,18 +30,22 @@
 | 
			
		||||
../lib/log/log.h
 | 
			
		||||
../lib/metadata/lv_alloc.h
 | 
			
		||||
../lib/metadata/metadata.h
 | 
			
		||||
../lib/metadata/metadata-exported.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/util.h
 | 
			
		||||
../lib/misc/last-path-component.h
 | 
			
		||||
../lib/misc/lib.h
 | 
			
		||||
../lib/misc/lvm-exec.h
 | 
			
		||||
../lib/misc/lvm-file.h
 | 
			
		||||
../lib/misc/lvm-string.h
 | 
			
		||||
../lib/misc/lvm-wrappers.h
 | 
			
		||||
../lib/misc/sharedlib.h
 | 
			
		||||
../lib/regex/matcher.h
 | 
			
		||||
../lib/report/report.h
 | 
			
		||||
../lib/uuid/uuid.h
 | 
			
		||||
../po/pogen.h
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
# 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
 | 
			
		||||
@@ -41,3 +41,5 @@ install:
 | 
			
		||||
 | 
			
		||||
install_cluster:
 | 
			
		||||
 | 
			
		||||
cflow:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
# 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
 | 
			
		||||
@@ -38,6 +38,7 @@ SOURCES =\
 | 
			
		||||
	commands/toolcontext.c \
 | 
			
		||||
	config/config.c \
 | 
			
		||||
	datastruct/btree.c \
 | 
			
		||||
	datastruct/list.c \
 | 
			
		||||
	datastruct/str_list.c \
 | 
			
		||||
	device/dev-cache.c \
 | 
			
		||||
	device/dev-io.c \
 | 
			
		||||
@@ -77,10 +78,10 @@ SOURCES =\
 | 
			
		||||
	misc/lvm-exec.c \
 | 
			
		||||
	misc/lvm-file.c \
 | 
			
		||||
	misc/lvm-string.c \
 | 
			
		||||
	misc/lvm-wrappers.c \
 | 
			
		||||
	misc/timestamp.c \
 | 
			
		||||
	misc/util.c \
 | 
			
		||||
	mm/memlock.c \
 | 
			
		||||
	regex/matcher.c \
 | 
			
		||||
	regex/parse_rx.c \
 | 
			
		||||
	regex/ttree.c \
 | 
			
		||||
	report/report.c \
 | 
			
		||||
	striped/striped.c \
 | 
			
		||||
	uuid/uuid.c \
 | 
			
		||||
@@ -133,9 +134,22 @@ ifeq ("@HAVE_LIBDL@", "yes")
 | 
			
		||||
	misc/sharedlib.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
  CLDFLAGS += -ldevmapper-event
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
LIB_STATIC = liblvm.a
 | 
			
		||||
 | 
			
		||||
$(SUBDIRS): $(LIB_STATIC)
 | 
			
		||||
 | 
			
		||||
CLEAN_TARGETS += liblvm.cflow
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
liblvm.cflow: $(SOURCES)
 | 
			
		||||
	set -e; (echo -n "SOURCES += "; \
 | 
			
		||||
		 echo $(SOURCES) | \
 | 
			
		||||
		 sed "s/^/ /;s/ / $(top_srcdir)\/lib\//g;s/$$//"; \
 | 
			
		||||
		 ) > $@
 | 
			
		||||
 | 
			
		||||
cflow: liblvm.cflow
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "segtype.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -38,7 +39,7 @@ int lvm1_present(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
 | 
			
		||||
	if (dm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
 | 
			
		||||
	    < 0) {
 | 
			
		||||
		log_error("LVM1 proc global snprintf failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -50,6 +51,66 @@ int lvm1_present(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
 | 
			
		||||
			 struct list *modules)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s;
 | 
			
		||||
	struct lv_segment *seg2, *snap_seg;
 | 
			
		||||
	struct list *snh;
 | 
			
		||||
 | 
			
		||||
	if (seg->segtype->ops->modules_needed &&
 | 
			
		||||
	    !seg->segtype->ops->modules_needed(mem, seg, modules)) {
 | 
			
		||||
		log_error("module string allocation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lv_is_origin(seg->lv))
 | 
			
		||||
		list_iterate(snh, &seg->lv->snapshot_segs)
 | 
			
		||||
			if (!list_lv_modules(mem,
 | 
			
		||||
					     list_struct_base(snh,
 | 
			
		||||
							      struct lv_segment,
 | 
			
		||||
							      origin_list)->cow,
 | 
			
		||||
					     modules))
 | 
			
		||||
				return_0;
 | 
			
		||||
 | 
			
		||||
	if (lv_is_cow(seg->lv)) {
 | 
			
		||||
		snap_seg = find_cow(seg->lv);
 | 
			
		||||
		if (snap_seg->segtype->ops->modules_needed &&
 | 
			
		||||
		    !snap_seg->segtype->ops->modules_needed(mem, snap_seg,
 | 
			
		||||
							    modules)) {
 | 
			
		||||
			log_error("snap_seg module string allocation failed");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (s = 0; s < seg->area_count; s++) {
 | 
			
		||||
		switch (seg_type(seg, s)) {
 | 
			
		||||
		case AREA_LV:
 | 
			
		||||
			seg2 = find_seg_by_le(seg_lv(seg, s), seg_le(seg, s));
 | 
			
		||||
			if (seg2 && !list_segment_modules(mem, seg2, modules))
 | 
			
		||||
				return_0;
 | 
			
		||||
			break;
 | 
			
		||||
		case AREA_PV:
 | 
			
		||||
		case AREA_UNASSIGNED:
 | 
			
		||||
			;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
 | 
			
		||||
		    struct list *modules)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(seg, &lv->segments)
 | 
			
		||||
		if (!list_segment_modules(mem, seg, modules))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef DEVMAPPER_SUPPORT
 | 
			
		||||
void set_activation(int act)
 | 
			
		||||
{
 | 
			
		||||
@@ -75,26 +136,31 @@ int driver_version(char *version, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int target_present(const char *target_name)
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
		   uint32_t *min, uint32_t *patchlevel)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int target_present(const char *target_name, int use_modprobe)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
 | 
			
		||||
	    int with_open_count)
 | 
			
		||||
	    int with_open_count, int with_read_ahead)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info, int with_open_count)
 | 
			
		||||
		    struct lvinfo *info, int with_open_count, int with_read_ahead)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr)
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -102,6 +168,10 @@ int lvs_in_vg_activated(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int lvs_in_vg_opened(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -145,12 +215,17 @@ 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)
 | 
			
		||||
int pv_uses_vg(struct physical_volume *pv,
 | 
			
		||||
	       struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_release(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
@@ -170,8 +245,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_warn("WARNING: Activation disabled. No device-mapper "
 | 
			
		||||
			  "interaction will be attempted.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int activation(void)
 | 
			
		||||
@@ -187,7 +262,7 @@ static int _passes_activation_filter(struct cmd_context *cmd,
 | 
			
		||||
	char *str;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "activation/volume_list"))) {
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "activation/volume_list"))) {
 | 
			
		||||
		/* If no host tags defined, activate */
 | 
			
		||||
		if (list_empty(&cmd->tags))
 | 
			
		||||
			return 1;
 | 
			
		||||
@@ -238,7 +313,7 @@ static int _passes_activation_filter(struct cmd_context *cmd,
 | 
			
		||||
			else
 | 
			
		||||
				continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!index(str, '/')) {
 | 
			
		||||
		if (!strchr(str, '/')) {
 | 
			
		||||
			/* vgname supplied */
 | 
			
		||||
			if (!strcmp(str, lv->vg->name))
 | 
			
		||||
				return 1;
 | 
			
		||||
@@ -246,9 +321,9 @@ static int _passes_activation_filter(struct cmd_context *cmd,
 | 
			
		||||
				continue;
 | 
			
		||||
		}
 | 
			
		||||
		/* vgname/lvname */
 | 
			
		||||
		if (lvm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
 | 
			
		||||
		if (dm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
 | 
			
		||||
				 lv->name) < 0) {
 | 
			
		||||
			log_error("lvm_snprintf error from %s/%s", lv->vg->name,
 | 
			
		||||
			log_error("dm_snprintf error from %s/%s", lv->vg->name,
 | 
			
		||||
				  lv->name);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
@@ -277,7 +352,8 @@ int driver_version(char *version, size_t size)
 | 
			
		||||
	return dm_driver_version(version, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _target_present(const char *target_name)
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
		   uint32_t *min, uint32_t *patchlevel)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
@@ -300,6 +376,9 @@ static int _target_present(const char *target_name)
 | 
			
		||||
 | 
			
		||||
		if (!strcmp(target_name, target->name)) {
 | 
			
		||||
			r = 1;
 | 
			
		||||
			*maj = target->version[0];
 | 
			
		||||
			*min = target->version[1];
 | 
			
		||||
			*patchlevel = target->version[2];
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -314,6 +393,7 @@ static int _target_present(const char *target_name)
 | 
			
		||||
 | 
			
		||||
int target_present(const char *target_name, int use_modprobe)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t maj, min, patchlevel;
 | 
			
		||||
#ifdef MODPROBE_CMD
 | 
			
		||||
	char module[128];
 | 
			
		||||
#endif
 | 
			
		||||
@@ -323,10 +403,10 @@ int target_present(const char *target_name, int use_modprobe)
 | 
			
		||||
 | 
			
		||||
#ifdef MODPROBE_CMD
 | 
			
		||||
	if (use_modprobe) {
 | 
			
		||||
		if (_target_present(target_name))
 | 
			
		||||
		if (target_version(target_name, &maj, &min, &patchlevel))
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
 | 
			
		||||
		if (dm_snprintf(module, sizeof(module), "dm-%s", target_name)
 | 
			
		||||
		    < 0) {
 | 
			
		||||
			log_error("target_present module name too long: %s",
 | 
			
		||||
				  target_name);
 | 
			
		||||
@@ -338,28 +418,31 @@ int target_present(const char *target_name, int use_modprobe)
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return _target_present(target_name);
 | 
			
		||||
	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 lvinfo *info, int with_open_count, int with_read_ahead, unsigned by_uuid_only)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_info dminfo;
 | 
			
		||||
	char *name;
 | 
			
		||||
	char *name = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
 | 
			
		||||
	if (!by_uuid_only &&
 | 
			
		||||
	    !(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);
 | 
			
		||||
			      with_open_count, with_read_ahead, &dminfo,
 | 
			
		||||
			      &info->read_ahead)) {
 | 
			
		||||
		if (name)
 | 
			
		||||
			dm_pool_free(cmd->mem, name);
 | 
			
		||||
		return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -372,31 +455,33 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, in
 | 
			
		||||
	info->live_table = dminfo.live_table;
 | 
			
		||||
	info->inactive_table = dminfo.inactive_table;
 | 
			
		||||
 | 
			
		||||
	dm_pool_free(cmd->mem, name);
 | 
			
		||||
	if (name)
 | 
			
		||||
		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)
 | 
			
		||||
	    int with_open_count, int with_read_ahead)
 | 
			
		||||
{
 | 
			
		||||
	return _lv_info(cmd, lv, 0, info, with_open_count);
 | 
			
		||||
	return _lv_info(cmd, lv, 0, info, with_open_count, with_read_ahead, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info, int with_open_count)
 | 
			
		||||
		    struct lvinfo *info, int with_open_count, int with_read_ahead)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
	return _lv_info(cmd, lv, 0, info, with_open_count, with_read_ahead, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if percent set, else 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
@@ -416,8 +501,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Merge with snapshot_percent */
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr)
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
@@ -426,7 +511,7 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wa
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0))
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!info.exists)
 | 
			
		||||
@@ -443,11 +528,12 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wa
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
 | 
			
		||||
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      unsigned by_uuid_only)
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0)) {
 | 
			
		||||
	if (!_lv_info(cmd, lv, 0, &info, 0, 0, by_uuid_only)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -459,7 +545,7 @@ static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 1)) {
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 1, 0)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -512,7 +598,7 @@ static int _lv_deactivate(struct logical_volume *lv)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_suspend_lv(struct logical_volume *lv)
 | 
			
		||||
static int _lv_suspend_lv(struct logical_volume *lv, int lockfs)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
@@ -520,7 +606,7 @@ static int _lv_suspend_lv(struct logical_volume *lv)
 | 
			
		||||
	if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(r = dev_manager_suspend(dm, lv)))
 | 
			
		||||
	if (!(r = dev_manager_suspend(dm, lv, lockfs)))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	dev_manager_destroy(dm);
 | 
			
		||||
@@ -531,7 +617,7 @@ static int _lv_suspend_lv(struct logical_volume *lv)
 | 
			
		||||
 * 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)
 | 
			
		||||
static int _lvs_in_vg_activated(struct volume_group *vg, unsigned by_uuid_only)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
@@ -541,15 +627,25 @@ int lvs_in_vg_activated(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(lvl, &vg->lvs) {
 | 
			
		||||
		if (lvl->lv->status & VISIBLE_LV)
 | 
			
		||||
			count += (_lv_active(vg->cmd, lvl->lv) == 1);
 | 
			
		||||
			count += (_lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvs_in_vg_opened(struct volume_group *vg)
 | 
			
		||||
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_list *lvl;
 | 
			
		||||
	return _lvs_in_vg_activated(vg, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvs_in_vg_activated(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	return _lvs_in_vg_activated(vg, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvs_in_vg_opened(const struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	const struct lv_list *lvl;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
@@ -563,40 +659,144 @@ int lvs_in_vg_opened(struct volume_group *vg)
 | 
			
		||||
	return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 0 if an attempt to (un)monitor the device failed.
 | 
			
		||||
 * Returns 1 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int monitor_dev_for_events(struct cmd_context *cmd,
 | 
			
		||||
			    struct logical_volume *lv, int monitor)
 | 
			
		||||
{
 | 
			
		||||
#ifdef DMEVENTD
 | 
			
		||||
	int i, pending = 0, monitored;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
	struct list *tmp;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	int (*monitor_fn) (struct lv_segment *s, int e);
 | 
			
		||||
 | 
			
		||||
	/* skip dmeventd code altogether */
 | 
			
		||||
	if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Nothing to do if dmeventd configured not to be used.
 | 
			
		||||
	 */
 | 
			
		||||
	if (monitor && !dmeventd_monitor_mode())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	list_iterate(tmp, &lv->segments) {
 | 
			
		||||
		seg = list_item(tmp, struct lv_segment);
 | 
			
		||||
 | 
			
		||||
		if (!seg_monitored(seg) || (seg->status & PVMOVE))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		monitor_fn = NULL;
 | 
			
		||||
 | 
			
		||||
		/* Check monitoring status */
 | 
			
		||||
		if (seg->segtype->ops->target_monitored)
 | 
			
		||||
			monitored = seg->segtype->ops->target_monitored(seg, &pending);
 | 
			
		||||
		else
 | 
			
		||||
			continue;  /* segtype doesn't support registration */
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * FIXME: We should really try again if pending
 | 
			
		||||
		 */
 | 
			
		||||
		monitored = (pending) ? 0 : monitored;
 | 
			
		||||
 | 
			
		||||
		if (monitor) {
 | 
			
		||||
			if (monitored)
 | 
			
		||||
				log_verbose("%s/%s already monitored.", lv->vg->name, lv->name);
 | 
			
		||||
			else if (seg->segtype->ops->target_monitor_events)
 | 
			
		||||
				monitor_fn = seg->segtype->ops->target_monitor_events;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (!monitored)
 | 
			
		||||
				log_verbose("%s/%s already not monitored.", lv->vg->name, lv->name);
 | 
			
		||||
			else if (seg->segtype->ops->target_unmonitor_events)
 | 
			
		||||
				monitor_fn = seg->segtype->ops->target_unmonitor_events;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Do [un]monitor */
 | 
			
		||||
		if (!monitor_fn)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		log_verbose("%sonitoring %s/%s", monitor ? "M" : "Not m", lv->vg->name, lv->name);
 | 
			
		||||
 | 
			
		||||
		/* FIXME specify events */
 | 
			
		||||
		if (!monitor_fn(seg, 0)) {
 | 
			
		||||
			log_error("%s/%s: %s segment monitoring function failed.",
 | 
			
		||||
				  lv->vg->name, lv->name, seg->segtype->name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Check [un]monitor results */
 | 
			
		||||
		/* Try a couple times if pending, but not forever... */
 | 
			
		||||
		for (i = 0; i < 10; i++) {
 | 
			
		||||
			pending = 0;
 | 
			
		||||
			monitored = seg->segtype->ops->target_monitored(seg, &pending);
 | 
			
		||||
			if (pending ||
 | 
			
		||||
			    (!monitored && monitor) ||
 | 
			
		||||
			    (monitored && !monitor))
 | 
			
		||||
				log_very_verbose("%s/%s %smonitoring still pending: waiting...",
 | 
			
		||||
						 lv->vg->name, lv->name, monitor ? "" : "un");
 | 
			
		||||
			else
 | 
			
		||||
				break;
 | 
			
		||||
			sleep(1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		r = (monitored && monitor) || (!monitored && !monitor);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
#else
 | 
			
		||||
	return 1;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		       int error_if_not_suspended)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
	struct logical_volume *lv, *lv_pre;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int lockfs = 0;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	/* Use precommitted metadata if present */
 | 
			
		||||
	if (!(lv = lv_from_lvid(cmd, lvid_s, 1)))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (test_mode()) {
 | 
			
		||||
		_skip("Suspending '%s'.", lv->name);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0))
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0, 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->vg->status & PRECOMMITTED)) {
 | 
			
		||||
		if (!_lv_preload(lv)) {
 | 
			
		||||
	if ((lv_pre->vg->status & PRECOMMITTED)) {
 | 
			
		||||
		if (!_lv_preload(lv_pre)) {
 | 
			
		||||
			/* FIXME Revert preloading */
 | 
			
		||||
			return_0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!monitor_dev_for_events(cmd, lv, 0))
 | 
			
		||||
		/* FIXME Consider aborting here */
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	if (!_lv_suspend_lv(lv)) {
 | 
			
		||||
 | 
			
		||||
	if (lv_is_origin(lv_pre) || lv_is_cow(lv_pre))
 | 
			
		||||
		lockfs = 1;
 | 
			
		||||
 | 
			
		||||
	if (!_lv_suspend_lv(lv, lockfs)) {
 | 
			
		||||
		memlock_dec();
 | 
			
		||||
		fs_unlock();
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -633,7 +833,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0))
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!info.exists || !info.suspended)
 | 
			
		||||
@@ -645,6 +845,9 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	if (!monitor_dev_for_events(cmd, lv, 1))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -676,7 +879,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 1))
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 1, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!info.exists)
 | 
			
		||||
@@ -688,6 +891,9 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!monitor_dev_for_events(cmd, lv, 0))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	memlock_inc();
 | 
			
		||||
	r = _lv_deactivate(lv);
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
@@ -744,7 +950,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0))
 | 
			
		||||
	if (!lv_info(cmd, lv, &info, 0, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (info.exists && !info.suspended && info.live_table)
 | 
			
		||||
@@ -758,6 +964,9 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
	memlock_dec();
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
 | 
			
		||||
	if (r && !monitor_dev_for_events(cmd, lv, 1))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -784,7 +993,7 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_lv_info(cmd, lv, 1, &info, 0))
 | 
			
		||||
	if (!_lv_info(cmd, lv, 1, &info, 0, 0, 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (info.exists)
 | 
			
		||||
@@ -801,28 +1010,21 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
 | 
			
		||||
 * Does PV use VG somewhere in its construction?
 | 
			
		||||
 * Returns 1 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
               struct volume_group *vg)
 | 
			
		||||
int pv_uses_vg(struct physical_volume *pv,
 | 
			
		||||
	       struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_manager *dm;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!activation())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dev_manager_create(cmd, vg->name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	return dev_manager_device_uses_vg(pv->dev, vg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	r = dev_manager_device_uses_vg(dm, pv->dev, vg);
 | 
			
		||||
 | 
			
		||||
	dev_manager_destroy(dm);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
void activation_release(void)
 | 
			
		||||
{
 | 
			
		||||
	dev_manager_release();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void activation_exit(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
#ifndef LVM_ACTIVATE_H
 | 
			
		||||
#define LVM_ACTIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "metadata-exported.h"
 | 
			
		||||
 | 
			
		||||
struct lvinfo {
 | 
			
		||||
	int exists;
 | 
			
		||||
@@ -27,6 +27,7 @@ struct lvinfo {
 | 
			
		||||
	int read_only;
 | 
			
		||||
	int live_table;
 | 
			
		||||
	int inactive_table;
 | 
			
		||||
	uint32_t read_ahead;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void set_activation(int activation);
 | 
			
		||||
@@ -37,7 +38,14 @@ int library_version(char *version, size_t size);
 | 
			
		||||
int lvm1_present(struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
int target_present(const char *target_name, int use_modprobe);
 | 
			
		||||
int target_version(const char *target_name, uint32_t *maj,
 | 
			
		||||
                   uint32_t *min, uint32_t *patchlevel);
 | 
			
		||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
 | 
			
		||||
			 struct list *modules);
 | 
			
		||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
 | 
			
		||||
		    struct list *modules);
 | 
			
		||||
 | 
			
		||||
void activation_release(void);
 | 
			
		||||
void activation_exit(void);
 | 
			
		||||
 | 
			
		||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
 | 
			
		||||
@@ -55,9 +63,9 @@ 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(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
 | 
			
		||||
	    int with_open_count);
 | 
			
		||||
	    int with_open_count, int with_read_ahead);
 | 
			
		||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
		    struct lvinfo *info, int with_open_count);
 | 
			
		||||
		    struct lvinfo *info, int with_open_count, int with_read_ahead);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
 | 
			
		||||
@@ -68,20 +76,30 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if percent has been set, else 0.
 | 
			
		||||
 */
 | 
			
		||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
 | 
			
		||||
		      uint32_t *event_nr);
 | 
			
		||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
 | 
			
		||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		      int wait, float *percent, uint32_t *event_nr);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return number of LVs in the VG that are active.
 | 
			
		||||
 */
 | 
			
		||||
int lvs_in_vg_activated(struct volume_group *vg);
 | 
			
		||||
int lvs_in_vg_opened(struct volume_group *vg);
 | 
			
		||||
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
 | 
			
		||||
int lvs_in_vg_opened(const struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int monitor_dev_for_events(struct cmd_context *cmd,
 | 
			
		||||
			    struct logical_volume *lv, int do_reg);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if PV has a dependency tree that uses anything in VG.
 | 
			
		||||
 */
 | 
			
		||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
int pv_uses_vg(struct physical_volume *pv,
 | 
			
		||||
	       struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns 1 if mapped device is not suspended.
 | 
			
		||||
 */
 | 
			
		||||
int device_is_usable(dev_t dev);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
#include "targets.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
@@ -37,6 +38,7 @@ typedef enum {
 | 
			
		||||
	ACTIVATE,
 | 
			
		||||
	DEACTIVATE,
 | 
			
		||||
	SUSPEND,
 | 
			
		||||
	SUSPEND_WITH_LOCKFS,
 | 
			
		||||
	CLEAN
 | 
			
		||||
} action_t;
 | 
			
		||||
 | 
			
		||||
@@ -85,7 +87,7 @@ char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer)
 | 
			
		||||
	return _build_dlid(dm->mem, lvid, layer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int _read_only_lv(struct logical_volume *lv)
 | 
			
		||||
static int _read_only_lv(struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	return (!(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
 | 
			
		||||
}
 | 
			
		||||
@@ -116,12 +118,11 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _info_run(const char *name, const char *dlid, struct dm_info *info,
 | 
			
		||||
		     int mknodes, int with_open_count, struct dm_pool *mem,
 | 
			
		||||
		     char **uuid_out)
 | 
			
		||||
		     uint32_t *read_ahead, int mknodes, int with_open_count,
 | 
			
		||||
		     int with_read_ahead)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	const char *u;
 | 
			
		||||
	int dmtask;
 | 
			
		||||
 | 
			
		||||
	dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
 | 
			
		||||
@@ -141,11 +142,64 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
 | 
			
		||||
	if (!dm_task_get_info(dmt, info))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if (info->exists && uuid_out) {
 | 
			
		||||
		if (!(u = dm_task_get_uuid(dmt)))
 | 
			
		||||
			goto_out;
 | 
			
		||||
		*uuid_out = dm_pool_strdup(mem, u);
 | 
			
		||||
	if (!with_read_ahead) {
 | 
			
		||||
		if (read_ahead)
 | 
			
		||||
			*read_ahead = DM_READ_AHEAD_NONE;
 | 
			
		||||
	} else
 | 
			
		||||
		; // FIXME *read_ahead = dm_task_get_read_ahead(dmt);
 | 
			
		||||
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int device_is_usable(dev_t dev)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_task *dmt;
 | 
			
		||||
	struct dm_info info;
 | 
			
		||||
	const char *name;
 | 
			
		||||
        uint64_t start, length;
 | 
			
		||||
        char *target_type = NULL;
 | 
			
		||||
        char *params;
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
 | 
			
		||||
		log_error("Failed to allocate dm_task struct to check dev status");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev)))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_run(dmt)) {
 | 
			
		||||
		log_error("Failed to get state of mapped device");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_get_info(dmt, &info))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if (!info.exists || info.suspended)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	name = dm_task_get_name(dmt);
 | 
			
		||||
 | 
			
		||||
	/* FIXME Also check for mirror block_on_error and mpath no paths */
 | 
			
		||||
	/* For now, we exclude all mirrors */
 | 
			
		||||
 | 
			
		||||
        do {
 | 
			
		||||
                next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
                                          &target_type, ¶ms);
 | 
			
		||||
                /* Skip if target type doesn't match */
 | 
			
		||||
                if (target_type && !strcmp(target_type, "mirror"))
 | 
			
		||||
			goto out;
 | 
			
		||||
        } while (next);
 | 
			
		||||
 | 
			
		||||
	/* FIXME Also check dependencies? */
 | 
			
		||||
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
@@ -154,30 +208,32 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _info(const char *name, const char *dlid, int mknodes,
 | 
			
		||||
		 int with_open_count, struct dm_info *info,
 | 
			
		||||
		 struct dm_pool *mem, char **uuid_out)
 | 
			
		||||
		 int with_open_count, int with_read_ahead,
 | 
			
		||||
		 struct dm_info *info, uint32_t *read_ahead)
 | 
			
		||||
{
 | 
			
		||||
	if (!mknodes && dlid && *dlid) {
 | 
			
		||||
		if (_info_run(NULL, dlid, info, 0, with_open_count, mem,
 | 
			
		||||
			      uuid_out) &&
 | 
			
		||||
		if (_info_run(NULL, dlid, info, read_ahead, 0, with_open_count,
 | 
			
		||||
			      with_read_ahead) &&
 | 
			
		||||
	    	    info->exists)
 | 
			
		||||
			return 1;
 | 
			
		||||
		else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
 | 
			
		||||
				   0, with_open_count, mem, uuid_out) &&
 | 
			
		||||
				   read_ahead, 0, with_open_count,
 | 
			
		||||
				   with_read_ahead) &&
 | 
			
		||||
			 info->exists)
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (name)
 | 
			
		||||
		return _info_run(name, NULL, info, mknodes, with_open_count,
 | 
			
		||||
				 mem, uuid_out);
 | 
			
		||||
		return _info_run(name, NULL, info, read_ahead, mknodes,
 | 
			
		||||
				 with_open_count, with_read_ahead);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_manager_info(struct dm_pool *mem, const char *name,
 | 
			
		||||
		     const struct logical_volume *lv, int with_mknodes,
 | 
			
		||||
		     int with_open_count, struct dm_info *info)
 | 
			
		||||
		     int with_open_count, int with_read_ahead,
 | 
			
		||||
		     struct dm_info *info, uint32_t *read_ahead)
 | 
			
		||||
{
 | 
			
		||||
	const char *dlid;
 | 
			
		||||
 | 
			
		||||
@@ -186,8 +242,8 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return _info(name, dlid, with_mknodes, with_open_count, info,
 | 
			
		||||
		     NULL, NULL);
 | 
			
		||||
	return _info(name, dlid, with_mknodes, with_open_count, with_read_ahead,
 | 
			
		||||
		     info, read_ahead);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Interface must cope with multiple targets */
 | 
			
		||||
@@ -329,7 +385,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
 | 
			
		||||
 | 
			
		||||
		if (segtype->ops->target_percent &&
 | 
			
		||||
		    !segtype->ops->target_percent(&dm->target_state, dm->mem,
 | 
			
		||||
						  dm->cmd->cft, seg, params,
 | 
			
		||||
						  dm->cmd, seg, params,
 | 
			
		||||
						  &total_numerator,
 | 
			
		||||
						  &total_denominator,
 | 
			
		||||
						  percent))
 | 
			
		||||
@@ -392,25 +448,21 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dm = dm_pool_alloc(mem, sizeof(*dm)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(dm = dm_pool_alloc(mem, sizeof(*dm))))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	dm->cmd = cmd;
 | 
			
		||||
	dm->mem = mem;
 | 
			
		||||
 | 
			
		||||
	if (!stripe_filler) {
 | 
			
		||||
		stripe_filler = find_config_str(cmd->cft->root,
 | 
			
		||||
		stripe_filler = find_config_tree_str(cmd,
 | 
			
		||||
						"activation/missing_stripe_filler",
 | 
			
		||||
						DEFAULT_STRIPE_FILLER);
 | 
			
		||||
	}
 | 
			
		||||
	dm->stripe_filler = stripe_filler;
 | 
			
		||||
 | 
			
		||||
	if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name)))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	dm->target_state = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -426,13 +478,19 @@ void dev_manager_destroy(struct dev_manager *dm)
 | 
			
		||||
	dm_pool_destroy(dm->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dev_manager_release(void)
 | 
			
		||||
{
 | 
			
		||||
	dm_lib_release();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dev_manager_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	dm_lib_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
 | 
			
		||||
				 struct logical_volume *lv, float *percent)
 | 
			
		||||
				 const struct logical_volume *lv,
 | 
			
		||||
				 float *percent)
 | 
			
		||||
{
 | 
			
		||||
	char *name;
 | 
			
		||||
	const char *dlid;
 | 
			
		||||
@@ -516,9 +574,9 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
 | 
			
		||||
	log_debug("Getting device info for %s", dl->name);
 | 
			
		||||
 | 
			
		||||
	/* Rename? */
 | 
			
		||||
		if ((suffix = rindex(dl->dlid + sizeof(UUID_PREFIX) - 1, '-')))
 | 
			
		||||
		if ((suffix = strrchr(dl->dlid + sizeof(UUID_PREFIX) - 1, '-')))
 | 
			
		||||
			suffix++;
 | 
			
		||||
		newname = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
 | 
			
		||||
		new_name = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
 | 
			
		||||
					suffix);
 | 
			
		||||
 | 
			
		||||
static int _belong_to_vg(const char *vgname, const char *name)
 | 
			
		||||
@@ -586,7 +644,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
        log_debug("Getting device info for %s [%s]", name, dlid);
 | 
			
		||||
        if (!_info(name, dlid, 0, 1, &info, dm->mem, NULL)) {
 | 
			
		||||
        if (!_info(name, dlid, 0, 1, 0, &info, NULL)) {
 | 
			
		||||
                log_error("Failed to get info for %s [%s].", name, dlid);
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
@@ -615,6 +673,9 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struc
 | 
			
		||||
	if (!_add_dev_to_dtree(dm, dtree, lv, "cow"))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!_add_dev_to_dtree(dm, dtree, lv, "_mlog"))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -622,6 +683,8 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
 | 
			
		||||
{
 | 
			
		||||
	struct dm_tree *dtree;
 | 
			
		||||
	struct list *snh, *snht;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
 | 
			
		||||
	if (!(dtree = dm_tree_create())) {
 | 
			
		||||
		log_error("Partial dtree creation failed for %s.", lv->name);
 | 
			
		||||
@@ -640,6 +703,16 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
 | 
			
		||||
			goto fail;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/* Add any LVs used by segments in this LV */
 | 
			
		||||
	list_iterate_items(seg, &lv->segments)
 | 
			
		||||
		for (s = 0; s < seg->area_count; s++)
 | 
			
		||||
			if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
 | 
			
		||||
				if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s))) {
 | 
			
		||||
					stack;
 | 
			
		||||
					goto fail;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
	return dtree;
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
@@ -648,7 +721,8 @@ fail:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
		   struct dm_tree_node *node, int start_area, int areas)
 | 
			
		||||
		   struct dm_tree_node *node, uint32_t start_area,
 | 
			
		||||
		   uint32_t areas)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t extent_size = seg->lv->vg->extent_size;
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
@@ -662,7 +736,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
		    (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
 | 
			
		||||
			dm_tree_node_add_target_area(node,
 | 
			
		||||
							dm->stripe_filler,
 | 
			
		||||
							NULL, 0);
 | 
			
		||||
							NULL, UINT64_C(0));
 | 
			
		||||
		else if (seg_type(seg, s) == AREA_PV)
 | 
			
		||||
			dm_tree_node_add_target_area(node,
 | 
			
		||||
							dev_name(seg_dev(seg, s)),
 | 
			
		||||
@@ -687,7 +761,6 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_origin_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
					 struct dm_tree *dtree,
 | 
			
		||||
					 struct dm_tree_node *dnode,
 | 
			
		||||
					 struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
@@ -703,7 +776,6 @@ static int _add_origin_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
					   struct dm_tree *dtree,
 | 
			
		||||
					   struct dm_tree_node *dnode,
 | 
			
		||||
					   struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
@@ -732,7 +804,6 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
				  struct dm_tree *dtree,
 | 
			
		||||
				  struct dm_tree_node *dnode,
 | 
			
		||||
				  struct lv_segment *seg)
 | 
			
		||||
{
 | 
			
		||||
@@ -744,7 +815,7 @@ static int _add_target_to_dtree(struct dev_manager *dm,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd->cft,
 | 
			
		||||
	return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
 | 
			
		||||
						  &dm->target_state, seg,
 | 
			
		||||
						  dnode,
 | 
			
		||||
						  extent_size * seg->len,
 | 
			
		||||
@@ -762,12 +833,19 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
 | 
			
		||||
{
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
	struct list *snh;
 | 
			
		||||
	struct lv_segment *seg_present;
 | 
			
		||||
 | 
			
		||||
	/* Ensure required device-mapper targets are loaded */
 | 
			
		||||
	if (seg->segtype->ops->target_present &&
 | 
			
		||||
	    !seg->segtype->ops->target_present()) {
 | 
			
		||||
	seg_present = find_cow(seg->lv) ? : seg;
 | 
			
		||||
 | 
			
		||||
	log_debug("Checking kernel supports %s segment type for %s%s%s",
 | 
			
		||||
		  seg_present->segtype->name, seg->lv->name,
 | 
			
		||||
		  layer ? "-" : "", layer ? : "");
 | 
			
		||||
 | 
			
		||||
	if (seg_present->segtype->ops->target_present &&
 | 
			
		||||
	    !seg_present->segtype->ops->target_present(seg_present)) {
 | 
			
		||||
		log_error("Can't expand LV %s: %s target support missing "
 | 
			
		||||
			  "from kernel?", seg->lv->name, seg->segtype->name);
 | 
			
		||||
			  "from kernel?", seg->lv->name, seg_present->segtype->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -797,12 +875,12 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
 | 
			
		||||
 | 
			
		||||
	/* Now we've added its dependencies, we can add the target itself */
 | 
			
		||||
	if (lv_is_origin(seg->lv) && !layer) {
 | 
			
		||||
		if (!_add_origin_target_to_dtree(dm, dtree, dnode, seg->lv))
 | 
			
		||||
		if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
 | 
			
		||||
			return_0;
 | 
			
		||||
	} else if (lv_is_cow(seg->lv) && !layer) {
 | 
			
		||||
		if (!_add_snapshot_target_to_dtree(dm, dtree, dnode, seg->lv))
 | 
			
		||||
		if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv))
 | 
			
		||||
			return_0;
 | 
			
		||||
	} else if (!_add_target_to_dtree(dm, dtree, dnode, seg))
 | 
			
		||||
	} else if (!_add_target_to_dtree(dm, dnode, seg))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (lv_is_origin(seg->lv) && !layer)
 | 
			
		||||
@@ -821,6 +899,9 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 | 
			
		||||
	struct lv_layer *lvlayer;
 | 
			
		||||
	struct dm_tree_node *dnode;
 | 
			
		||||
	char *name, *dlid;
 | 
			
		||||
	uint32_t max_stripe_size = UINT32_C(0);
 | 
			
		||||
	uint32_t read_ahead = lv->read_ahead;
 | 
			
		||||
	uint32_t flags = UINT32_C(0);
 | 
			
		||||
 | 
			
		||||
	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
 | 
			
		||||
		return_0;
 | 
			
		||||
@@ -833,7 +914,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 | 
			
		||||
	    dm_tree_node_get_context(dnode))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/* FIXME How do we determine whether a pre-existing node need reloading or not? */
 | 
			
		||||
	if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
 | 
			
		||||
		log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.", lv->name, layer);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -848,10 +928,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 | 
			
		||||
	 * Major/minor settings only apply to the visible layer.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(dnode = dm_tree_add_new_dev(dtree, name, dlid,
 | 
			
		||||
					     layer ? lv->major : 0,
 | 
			
		||||
					     layer ? lv->minor : 0,
 | 
			
		||||
					     layer ? UINT32_C(0) : (uint32_t) lv->major,
 | 
			
		||||
					     layer ? UINT32_C(0) : (uint32_t) lv->minor,
 | 
			
		||||
					     _read_only_lv(lv),
 | 
			
		||||
					     lv->vg->status & PRECOMMITTED,
 | 
			
		||||
					     (lv->vg->status & PRECOMMITTED) ? 1 : 0,
 | 
			
		||||
					     lvlayer)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
@@ -868,11 +948,24 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 | 
			
		||||
			break;
 | 
			
		||||
		if (lv_is_cow(lv) && !layer)
 | 
			
		||||
			break;
 | 
			
		||||
		if (max_stripe_size < seg->stripe_size)
 | 
			
		||||
			max_stripe_size = seg->stripe_size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (read_ahead == DM_READ_AHEAD_AUTO)
 | 
			
		||||
		read_ahead = max_stripe_size;
 | 
			
		||||
	else
 | 
			
		||||
		flags = DM_READ_AHEAD_MINIMUM_FLAG;
 | 
			
		||||
 | 
			
		||||
	// FIXME dm_tree_node_set_read_ahead(dnode, read_ahead, flags);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME: symlinks should be created/destroyed at the same time
 | 
			
		||||
 * as the kernel devices but we can't do that from within libdevmapper
 | 
			
		||||
 * at present so we must walk the tree twice instead. */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Create LV symlinks for children of supplied root node.
 | 
			
		||||
 */
 | 
			
		||||
@@ -893,7 +986,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
 | 
			
		||||
		name = dm_tree_node_get_name(child);
 | 
			
		||||
 | 
			
		||||
		if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
 | 
			
		||||
	        	if (!split_dm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
 | 
			
		||||
	        	if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
 | 
			
		||||
                		log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
 | 
			
		||||
                		return 0;
 | 
			
		||||
        		}
 | 
			
		||||
@@ -905,7 +998,33 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _clean_tree(struct dev_manager *dm, struct logical_volume *lv, struct dm_tree_node *root)
 | 
			
		||||
/*
 | 
			
		||||
 * Remove LV symlinks for children of supplied root node.
 | 
			
		||||
 */
 | 
			
		||||
static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root)
 | 
			
		||||
{
 | 
			
		||||
	void *handle = NULL;
 | 
			
		||||
	struct dm_tree_node *child;
 | 
			
		||||
	char *vgname, *lvname, *layer;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
	while ((child = dm_tree_next_child(&handle, root, 0))) {
 | 
			
		||||
        	if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
 | 
			
		||||
			r = 0;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* only top level layer has symlinks */
 | 
			
		||||
		if (*layer)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
 | 
			
		||||
{
 | 
			
		||||
	void *handle = NULL;
 | 
			
		||||
	struct dm_tree_node *child;
 | 
			
		||||
@@ -919,7 +1038,7 @@ static int _clean_tree(struct dev_manager *dm, struct logical_volume *lv, struct
 | 
			
		||||
		if (!(uuid = dm_tree_node_get_uuid(child)))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
        	if (!split_dm_name(dm->mem, name, &vgname, &lvname, &layer)) {
 | 
			
		||||
        	if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
 | 
			
		||||
                	log_error("_clean_tree: Couldn't split up device name %s.", name);
 | 
			
		||||
                	return 0;
 | 
			
		||||
        	}
 | 
			
		||||
@@ -957,15 +1076,21 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
 | 
			
		||||
	switch(action) {
 | 
			
		||||
	case CLEAN:
 | 
			
		||||
		/* Deactivate any unused non-toplevel nodes */
 | 
			
		||||
		if (!_clean_tree(dm, lv, root))
 | 
			
		||||
		if (!_clean_tree(dm, root))
 | 
			
		||||
			goto_out;
 | 
			
		||||
		break;
 | 
			
		||||
	case DEACTIVATE:
 | 
			
		||||
 		/* Deactivate LV and all devices it references that nothing else has open. */
 | 
			
		||||
		if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
 | 
			
		||||
			goto_out;
 | 
			
		||||
		if (!_remove_lv_symlinks(dm, root))
 | 
			
		||||
			log_error("Failed to remove all device symlinks associated with %s.", lv->name);
 | 
			
		||||
		break;
 | 
			
		||||
	case SUSPEND:
 | 
			
		||||
		dm_tree_skip_lockfs(root);
 | 
			
		||||
		if ((lv->status & MIRRORED) && !(lv->status & PVMOVE))
 | 
			
		||||
			dm_tree_use_no_flush_suspend(root);
 | 
			
		||||
	case SUSPEND_WITH_LOCKFS:
 | 
			
		||||
		if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
 | 
			
		||||
			goto_out;
 | 
			
		||||
		break;
 | 
			
		||||
@@ -1011,6 +1136,10 @@ int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
 | 
			
		||||
 | 
			
		||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME Update the pvmove implementation! */
 | 
			
		||||
	if ((lv->status & PVMOVE) || (lv->status & LOCKED))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return _tree_action(dm, lv, PRELOAD);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1025,21 +1154,22 @@ int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv)
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
 | 
			
		||||
			int lockfs)
 | 
			
		||||
{
 | 
			
		||||
	return _tree_action(dm, lv, SUSPEND);
 | 
			
		||||
	return _tree_action(dm, lv, lockfs ? SUSPEND_WITH_LOCKFS : SUSPEND);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Does device use VG somewhere in its construction?
 | 
			
		||||
 * Returns 1 if uncertain.
 | 
			
		||||
 */
 | 
			
		||||
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
 | 
			
		||||
int dev_manager_device_uses_vg(struct device *dev,
 | 
			
		||||
			       struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_tree *dtree;
 | 
			
		||||
	struct dm_tree_node *root;
 | 
			
		||||
	char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1];
 | 
			
		||||
	char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1] __attribute((aligned(8)));
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
	if (!(dtree = dm_tree_create())) {
 | 
			
		||||
@@ -1047,7 +1177,7 @@ int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_tree_add_dev(dtree, MAJOR(dev->dev), MINOR(dev->dev))) {
 | 
			
		||||
	if (!dm_tree_add_dev(dtree, (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev))) {
 | 
			
		||||
		log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to dtree",
 | 
			
		||||
			  dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));
 | 
			
		||||
		goto out;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -29,6 +29,7 @@ struct device;
 | 
			
		||||
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
 | 
			
		||||
				       const char *vg_name);
 | 
			
		||||
void dev_manager_destroy(struct dev_manager *dm);
 | 
			
		||||
void dev_manager_release(void);
 | 
			
		||||
void dev_manager_exit(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -39,13 +40,16 @@ void dev_manager_exit(void);
 | 
			
		||||
 */
 | 
			
		||||
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 mknodes, int with_open_count, int with_read_ahead,
 | 
			
		||||
		     struct dm_info *info, uint32_t *read_ahead);
 | 
			
		||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
 | 
			
		||||
				 struct logical_volume *lv, float *percent);
 | 
			
		||||
				 const struct logical_volume *lv,
 | 
			
		||||
				 float *percent);
 | 
			
		||||
int dev_manager_mirror_percent(struct dev_manager *dm,
 | 
			
		||||
			       struct logical_volume *lv, int wait,
 | 
			
		||||
			       float *percent, uint32_t *event_nr);
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
 | 
			
		||||
			int lockfs);
 | 
			
		||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
 | 
			
		||||
@@ -58,7 +62,7 @@ int dev_manager_lv_rmnodes(const struct logical_volume *lv);
 | 
			
		||||
 */
 | 
			
		||||
int dev_manager_execute(struct dev_manager *dm);
 | 
			
		||||
 | 
			
		||||
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
 | 
			
		||||
int dev_manager_device_uses_vg(struct device *dev,
 | 
			
		||||
			       struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -30,7 +30,7 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't construct name of volume "
 | 
			
		||||
			  "group directory.");
 | 
			
		||||
@@ -53,7 +53,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't construct name of volume "
 | 
			
		||||
			  "group directory.");
 | 
			
		||||
@@ -87,7 +87,7 @@ static void _rm_blks(const char *dir)
 | 
			
		||||
		if (!strcmp(name, ".") || !strcmp(name, ".."))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (lvm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
 | 
			
		||||
		if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
 | 
			
		||||
			log_error("Couldn't create path for %s", name);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
@@ -109,28 +109,28 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
	char vg_path[PATH_MAX];
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
	if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
 | 
			
		||||
			 dev_dir, vg_name) == -1) {
 | 
			
		||||
		log_error("Couldn't create path for volume group dir %s",
 | 
			
		||||
			  vg_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
 | 
			
		||||
	if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
 | 
			
		||||
			 lv_name) == -1) {
 | 
			
		||||
		log_error("Couldn't create source pathname for "
 | 
			
		||||
			  "logical volume link %s", lv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
 | 
			
		||||
	if (dm_snprintf(link_path, sizeof(link_path), "%s/%s",
 | 
			
		||||
			 dm_dir(), dev) == -1) {
 | 
			
		||||
		log_error("Couldn't create destination pathname for "
 | 
			
		||||
			  "logical volume link for %s", lv_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
 | 
			
		||||
	if (dm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
 | 
			
		||||
			 vg_path) == -1) {
 | 
			
		||||
		log_error("Couldn't create pathname for LVM1 group file for %s",
 | 
			
		||||
			  vg_name);
 | 
			
		||||
@@ -190,7 +190,7 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	char lv_path[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
 | 
			
		||||
	if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
 | 
			
		||||
			 dev_dir, vg_name, lv_name) == -1) {
 | 
			
		||||
		log_error("Couldn't determine link pathname.");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -338,6 +338,11 @@ int fs_del_lv(const struct logical_volume *lv)
 | 
			
		||||
		      "", "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name)
 | 
			
		||||
{
 | 
			
		||||
	return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fs_rename_lv(struct logical_volume *lv,
 | 
			
		||||
		 const char *dev, const char *old_name)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
 */
 | 
			
		||||
int fs_add_lv(const struct logical_volume *lv, const char *dev);
 | 
			
		||||
int fs_del_lv(const struct logical_volume *lv);
 | 
			
		||||
int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name);
 | 
			
		||||
int fs_rename_lv(struct logical_volume *lv,
 | 
			
		||||
		 const char *dev, const char *old_name);
 | 
			
		||||
void fs_unlock(void);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -24,7 +24,7 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
		       int start_area, int areas);
 | 
			
		||||
 | 
			
		||||
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
 | 
			
		||||
                   struct dm_tree_node *node, int start_area, int areas);
 | 
			
		||||
                   struct dm_tree_node *node, uint32_t start_area, uint32_t areas);
 | 
			
		||||
 | 
			
		||||
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
 | 
			
		||||
		     size_t bufsize, const char *desc);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										394
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										394
									
								
								lib/cache/lvmcache.c
									
									
									
									
										vendored
									
									
								
							@@ -1,17 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
@@ -50,7 +49,7 @@ int lvmcache_init(void)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only)
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	if (!_lock_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
@@ -86,7 +85,8 @@ int vgs_locked(void)
 | 
			
		||||
	return _vgs_locked;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
 | 
			
		||||
/* If vgid supplied, require a match. */
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
@@ -96,10 +96,16 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
 | 
			
		||||
	if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (vgid)
 | 
			
		||||
		do 
 | 
			
		||||
			if (!strncmp(vgid, vginfo->vgid, ID_LEN))
 | 
			
		||||
				return vginfo;
 | 
			
		||||
		while ((vginfo = vginfo->next));
 | 
			
		||||
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname)
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
@@ -107,33 +113,44 @@ const struct format_type *fmt_from_vgname(const char *vgname)
 | 
			
		||||
	struct list *devh, *tmp;
 | 
			
		||||
	struct list devs;
 | 
			
		||||
	struct device_list *devl;
 | 
			
		||||
	char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname)))
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	/* This function is normally called before reading metadata so
 | 
			
		||||
 	 * we check cached labels here. Unfortunately vginfo is volatile. */
 | 
			
		||||
	list_init(&devs);
 | 
			
		||||
	list_iterate_items(info, &vginfo->infos) {
 | 
			
		||||
		devl = dm_malloc(sizeof(*devl));
 | 
			
		||||
		if (!(devl = dm_malloc(sizeof(*devl)))) {
 | 
			
		||||
			log_error("device_list element allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		devl->dev = info->dev;
 | 
			
		||||
		list_add(&devs, &devl->list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
 | 
			
		||||
 | 
			
		||||
	list_iterate_safe(devh, tmp, &devs) {
 | 
			
		||||
		devl = list_item(devh, struct device_list);
 | 
			
		||||
		label_read(devl->dev, &label);
 | 
			
		||||
		label_read(devl->dev, &label, UINT64_C(0));
 | 
			
		||||
		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];
 | 
			
		||||
	char id[ID_LEN + 1] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (!_vgid_hash || !vgid)
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -148,10 +165,27 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
 | 
			
		||||
	return vginfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	const char *vgname = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!*vgid)
 | 
			
		||||
		vgname = ORPHAN;
 | 
			
		||||
 | 
			
		||||
	if ((vginfo = vginfo_from_vgid(vgid)))
 | 
			
		||||
		vgname = vginfo->vgname;
 | 
			
		||||
 | 
			
		||||
	if (mem && vgname)
 | 
			
		||||
		return dm_pool_strdup(mem, vgname);
 | 
			
		||||
 | 
			
		||||
	return vgname;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct lvmcache_info *info_from_pvid(const char *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	char id[ID_LEN + 1];
 | 
			
		||||
	char id[ID_LEN + 1] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (!_pvid_hash || !pvid)
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -170,7 +204,7 @@ static void _rescan_entry(struct lvmcache_info *info)
 | 
			
		||||
	struct label *label;
 | 
			
		||||
 | 
			
		||||
	if (info->status & CACHE_INVALID)
 | 
			
		||||
		label_read(info->dev, &label);
 | 
			
		||||
		label_read(info->dev, &label, UINT64_C(0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _scan_invalid(void)
 | 
			
		||||
@@ -206,13 +240,13 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1: 0))) {
 | 
			
		||||
	if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
 | 
			
		||||
		log_error("dev_iter creation failed");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while ((dev = dev_iter_get(iter)))
 | 
			
		||||
		label_read(dev, &label);
 | 
			
		||||
		label_read(dev, &label, UINT64_C(0));
 | 
			
		||||
 | 
			
		||||
	dev_iter_destroy(iter);
 | 
			
		||||
 | 
			
		||||
@@ -232,10 +266,33 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *vgids;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
	if (!(vgids = str_list_create(cmd->mem))) {
 | 
			
		||||
		log_error("vgids list allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(vginfo, &_vginfos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, vgids, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, vginfo->vgid))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vgids;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
{
 | 
			
		||||
	struct list *vgnames;
 | 
			
		||||
	struct lvmcache_vginfo *vgi;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
 | 
			
		||||
	lvmcache_label_scan(cmd, full_scan);
 | 
			
		||||
 | 
			
		||||
@@ -244,9 +301,9 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(vgi, &_vginfos) {
 | 
			
		||||
	list_iterate_items(vginfo, &_vginfos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, vgnames, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, vgi->vgname))) {
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, vginfo->vgname))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
@@ -255,6 +312,32 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
 | 
			
		||||
	return vgnames;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
				const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	struct list *pvids;
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(pvids = str_list_create(cmd->mem))) {
 | 
			
		||||
		log_error("pvids list allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
 | 
			
		||||
		return pvids;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(info, &vginfo->infos) {
 | 
			
		||||
		if (!str_list_add(cmd->mem, pvids, 
 | 
			
		||||
				  dm_pool_strdup(cmd->mem, info->dev->pvid))) {
 | 
			
		||||
			log_error("strlist allocation failed");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pvids;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
@@ -262,7 +345,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
 | 
			
		||||
	/* Already cached ? */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
		if (label_read(info->dev, &label, UINT64_C(0))) {
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
@@ -273,7 +356,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
 | 
			
		||||
	/* Try again */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
		if (label_read(info->dev, &label, UINT64_C(0))) {
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
@@ -287,7 +370,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
 | 
			
		||||
	/* Try again */
 | 
			
		||||
	if ((info = info_from_pvid((char *) pvid))) {
 | 
			
		||||
		if (label_read(info->dev, &label)) {
 | 
			
		||||
		if (label_read(info->dev, &label, UINT64_C(0))) {
 | 
			
		||||
			info = (struct lvmcache_info *) label->info;
 | 
			
		||||
			if (id_equal(pvid, (struct id *) &info->dev->pvid))
 | 
			
		||||
				return info->dev;
 | 
			
		||||
@@ -297,7 +380,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
static int _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
{
 | 
			
		||||
	if (!list_empty(&info->list)) {
 | 
			
		||||
		list_del(&info->list);
 | 
			
		||||
@@ -306,8 +389,18 @@ static void _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && list_empty(&info->vginfo->infos)) {
 | 
			
		||||
		dm_hash_remove(_vgname_hash, info->vginfo->vgname);
 | 
			
		||||
		if (info->vginfo->next) {
 | 
			
		||||
                	if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
 | 
			
		||||
                        	log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
					  info->vginfo->vgname);
 | 
			
		||||
                        	return 0;
 | 
			
		||||
			}
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
		if (info->vginfo->vgname)
 | 
			
		||||
			dm_free(info->vginfo->vgname);
 | 
			
		||||
		if (info->vginfo->creation_host)
 | 
			
		||||
			dm_free(info->vginfo->creation_host);
 | 
			
		||||
		if (*info->vginfo->vgid)
 | 
			
		||||
			dm_hash_remove(_vgid_hash, info->vginfo->vgid);
 | 
			
		||||
		list_del(&info->vginfo->list);
 | 
			
		||||
@@ -315,6 +408,8 @@ static void _drop_vginfo(struct lvmcache_info *info)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->vginfo = NULL;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unused
 | 
			
		||||
@@ -350,36 +445,130 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
 | 
			
		||||
{
 | 
			
		||||
	if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid,
 | 
			
		||||
					       sizeof(info->vginfo->vgid)))
 | 
			
		||||
	if (!vgid || !info->vginfo ||
 | 
			
		||||
	    !strncmp(info->vginfo->vgid, vgid, ID_LEN))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (info->vginfo && *info->vginfo->vgid)
 | 
			
		||||
		dm_hash_remove(_vgid_hash, info->vginfo->vgid);
 | 
			
		||||
	if (!vgid)
 | 
			
		||||
	if (!vgid) {
 | 
			
		||||
		log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
 | 
			
		||||
	info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
 | 
			
		||||
	strncpy(info->vginfo->vgid, vgid, ID_LEN);
 | 
			
		||||
	info->vginfo->vgid[ID_LEN] = '\0';
 | 
			
		||||
	if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
 | 
			
		||||
		log_error("_lvmcache_update: vgid hash insertion failed: %s",
 | 
			
		||||
			  info->vginfo->vgid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
 | 
			
		||||
		  info->vginfo->vgname, info->vginfo->vgid);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
 | 
			
		||||
			  uint32_t vgstatus, const char *creation_host,
 | 
			
		||||
			  struct lvmcache_vginfo *primary_vginfo)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo;
 | 
			
		||||
	struct lvmcache_vginfo *last_vginfo = primary_vginfo;
 | 
			
		||||
	char uuid_primary[64] __attribute((aligned(8)));
 | 
			
		||||
	char uuid_new[64] __attribute((aligned(8)));
 | 
			
		||||
	int use_new = 0;
 | 
			
		||||
	
 | 
			
		||||
	/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
 | 
			
		||||
	if (primary_vginfo) {
 | 
			
		||||
		if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
 | 
			
		||||
				     sizeof(uuid_primary)))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * If   Primary not exported, new exported => keep
 | 
			
		||||
		 * Else Primary exported, new not exported => change
 | 
			
		||||
		 * Else Primary has hostname for this machine => keep
 | 
			
		||||
		 * Else Primary has no hostname, new has one => change
 | 
			
		||||
		 * Else New has hostname for this machine => change
 | 
			
		||||
		 * Else Keep primary.
 | 
			
		||||
		 */
 | 
			
		||||
		if (!(primary_vginfo->status & EXPORTED_VG) &&
 | 
			
		||||
		    (vgstatus & EXPORTED_VG))
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "Existing %s takes precedence over "
 | 
			
		||||
				  "exported %s", new_vginfo->vgname,
 | 
			
		||||
				  uuid_primary, uuid_new);
 | 
			
		||||
		else if ((primary_vginfo->status & EXPORTED_VG) &&
 | 
			
		||||
			   !(vgstatus & EXPORTED_VG)) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s takes precedence over exported %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		} else if (primary_vginfo->creation_host &&
 | 
			
		||||
			   !strcmp(primary_vginfo->creation_host,
 | 
			
		||||
				   primary_vginfo->fmt->cmd->hostname))
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "Existing %s (created here) takes precedence "
 | 
			
		||||
				  "over %s", new_vginfo->vgname, uuid_primary,
 | 
			
		||||
				  uuid_new);
 | 
			
		||||
		else if (!primary_vginfo->creation_host && creation_host) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s (with creation_host) takes precedence over %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		} else if (creation_host &&
 | 
			
		||||
			   !strcmp(creation_host,
 | 
			
		||||
				   primary_vginfo->fmt->cmd->hostname)) {
 | 
			
		||||
			log_error("WARNING: Duplicate VG name %s: "
 | 
			
		||||
				  "%s (created here) takes precedence over %s",
 | 
			
		||||
				  new_vginfo->vgname, uuid_new,
 | 
			
		||||
				  uuid_primary);
 | 
			
		||||
			use_new = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!use_new) {
 | 
			
		||||
			while (last_vginfo->next)
 | 
			
		||||
				last_vginfo = last_vginfo->next;
 | 
			
		||||
			last_vginfo->next = new_vginfo;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
 | 
			
		||||
		log_error("cache_update: vg hash insertion failed: %s",
 | 
			
		||||
		  	new_vginfo->vgname);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (primary_vginfo)
 | 
			
		||||
		new_vginfo->next = primary_vginfo;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lvmcache_update_vgname(struct lvmcache_info *info,
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus, const char *creation_host)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_vginfo *vginfo, *primary_vginfo;
 | 
			
		||||
	// struct lvmcache_vginfo  *old_vginfo, *next;
 | 
			
		||||
 | 
			
		||||
	/* If vgname is NULL and we don't already have a vgname, 
 | 
			
		||||
	 * assume ORPHAN - we want every entry to have a vginfo
 | 
			
		||||
	 * attached for scanning reasons.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!vgname && !info->vginfo)
 | 
			
		||||
	if (!vgname && !info->vginfo) {
 | 
			
		||||
		vgname = ORPHAN;
 | 
			
		||||
		vgid = ORPHAN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
 | 
			
		||||
		return 1;
 | 
			
		||||
@@ -388,7 +577,43 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
	_drop_vginfo(info);
 | 
			
		||||
 | 
			
		||||
	/* Get existing vginfo or create new one */
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname))) {
 | 
			
		||||
	if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
 | 
			
		||||
/*** FIXME - vginfo ends up duplicated instead of renamed.
 | 
			
		||||
		// Renaming?  This lookup fails.
 | 
			
		||||
		if ((vginfo = vginfo_from_vgid(vgid))) {
 | 
			
		||||
			next = vginfo->next;
 | 
			
		||||
			old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
 | 
			
		||||
			if (old_vginfo == vginfo) {
 | 
			
		||||
				dm_hash_remove(_vgname_hash, old_vginfo->vgname);
 | 
			
		||||
				if (old_vginfo->next) {
 | 
			
		||||
					if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
 | 
			
		||||
                        			log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
							  old_vginfo->vgname);
 | 
			
		||||
                        			return 0;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else do {
 | 
			
		||||
				if (old_vginfo->next == vginfo) {
 | 
			
		||||
					old_vginfo->next = vginfo->next;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			} while ((old_vginfo = old_vginfo->next));
 | 
			
		||||
			vginfo->next = NULL;
 | 
			
		||||
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
			if (!(vginfo->vgname = dm_strdup(vgname))) {
 | 
			
		||||
				log_error("cache vgname alloc failed for %s", vgname);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Rename so can assume new name does not already exist 
 | 
			
		||||
			if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
 | 
			
		||||
				log_error("vg hash re-insertion failed: %s",
 | 
			
		||||
					  vginfo->vgname);
 | 
			
		||||
                      		return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
***/
 | 
			
		||||
		if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
 | 
			
		||||
			log_error("lvmcache_update_vgname: list alloc failed");
 | 
			
		||||
			return 0;
 | 
			
		||||
@@ -400,18 +625,21 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		list_init(&vginfo->infos);
 | 
			
		||||
		if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
 | 
			
		||||
			log_error("cache_update: vg hash insertion failed: %s",
 | 
			
		||||
				  vginfo->vgname);
 | 
			
		||||
			primary_vginfo = vginfo_from_vgname(vgname, NULL);
 | 
			
		||||
		if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
 | 
			
		||||
				    primary_vginfo)) {
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
			dm_free(vginfo);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		/* Ensure orphans appear last on list_iterate */
 | 
			
		||||
		if (!*vgname)
 | 
			
		||||
		if (is_orphan_vg(vgname))
 | 
			
		||||
			list_add(&_vginfos, &vginfo->list);
 | 
			
		||||
		else
 | 
			
		||||
			list_add_h(&_vginfos, &vginfo->list);
 | 
			
		||||
/***
 | 
			
		||||
		}
 | 
			
		||||
***/
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->vginfo = vginfo;
 | 
			
		||||
@@ -420,8 +648,59 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
 | 
			
		||||
	/* FIXME Check consistency of list! */
 | 
			
		||||
	vginfo->fmt = info->fmt;
 | 
			
		||||
 | 
			
		||||
	log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
 | 
			
		||||
		  *vgname ? "in VG " : "orphaned", vgname);
 | 
			
		||||
	log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
 | 
			
		||||
		  !is_orphan_vg(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;
 | 
			
		||||
}
 | 
			
		||||
@@ -430,21 +709,18 @@ int lvmcache_update_vg(struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct pv_list *pvl;
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
	int vgid_updated = 0;
 | 
			
		||||
	char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	pvid_s[sizeof(pvid_s) - 1] = '\0';
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(pvl, &vg->pvs) {
 | 
			
		||||
		strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
 | 
			
		||||
		/* FIXME Could pvl->pv->dev->pvid ever be different? */
 | 
			
		||||
		if ((info = info_from_pvid(pvid_s))) {
 | 
			
		||||
			lvmcache_update_vgname(info, vg->name);
 | 
			
		||||
			if (!vgid_updated) {
 | 
			
		||||
				_lvmcache_update_vgid(info, (char *) &vg->id);
 | 
			
		||||
				vgid_updated = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if ((info = info_from_pvid(pvid_s)) &&
 | 
			
		||||
		    !lvmcache_update_vgname_and_id(info, vg->name,
 | 
			
		||||
						   (char *) &vg->id,
 | 
			
		||||
						   vg->status, NULL))
 | 
			
		||||
			return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -452,11 +728,12 @@ int lvmcache_update_vg(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
				   struct device *dev,
 | 
			
		||||
				   const char *vgname, const char *vgid)
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus)
 | 
			
		||||
{
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	struct lvmcache_info *existing, *info;
 | 
			
		||||
	char pvid_s[ID_LEN + 1];
 | 
			
		||||
	char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (!_vgname_hash && !lvmcache_init()) {
 | 
			
		||||
		log_error("Internal cache initialisation failed");
 | 
			
		||||
@@ -548,7 +825,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lvmcache_update_vgname(info, vgname)) {
 | 
			
		||||
	if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
 | 
			
		||||
		if (!existing) {
 | 
			
		||||
			dm_hash_remove(_pvid_hash, pvid_s);
 | 
			
		||||
			strcpy(info->dev->pvid, "");
 | 
			
		||||
@@ -558,10 +835,6 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_lvmcache_update_vgid(info, vgid))
 | 
			
		||||
		/* Non-critical */
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -576,12 +849,19 @@ static void _lvmcache_destroy_entry(struct lvmcache_info *info)
 | 
			
		||||
 | 
			
		||||
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
 | 
			
		||||
{
 | 
			
		||||
	if (vginfo->vgname)
 | 
			
		||||
		dm_free(vginfo->vgname);
 | 
			
		||||
	dm_free(vginfo);
 | 
			
		||||
	struct lvmcache_vginfo *next;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = vginfo->next;
 | 
			
		||||
		if (vginfo->vgname)
 | 
			
		||||
			dm_free(vginfo->vgname);
 | 
			
		||||
		if (vginfo->creation_host)
 | 
			
		||||
			dm_free(vginfo->creation_host);
 | 
			
		||||
		dm_free(vginfo);
 | 
			
		||||
	} while ((vginfo = next));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _lvmcache_destroy_lockname(int present)
 | 
			
		||||
static void _lvmcache_destroy_lockname(int present __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	/* Nothing to do */
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								lib/cache/lvmcache.h
									
									
									
									
										vendored
									
									
								
							@@ -1,17 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_CACHE_H
 | 
			
		||||
@@ -33,15 +32,20 @@ struct cmd_context;
 | 
			
		||||
struct format_type;
 | 
			
		||||
struct volume_group;
 | 
			
		||||
 | 
			
		||||
/* One per VG */
 | 
			
		||||
struct lvmcache_vginfo {
 | 
			
		||||
	struct list list;	/* Join these vginfos together */
 | 
			
		||||
	struct list infos;	/* List head for lvmcache_infos */
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
	char *vgname;		/* "" == orphan */
 | 
			
		||||
	uint32_t status;
 | 
			
		||||
	char vgid[ID_LEN + 1];
 | 
			
		||||
	char _padding[7];
 | 
			
		||||
	struct lvmcache_vginfo *next; /* Another VG with same name? */
 | 
			
		||||
	char *creation_host;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* One per device */
 | 
			
		||||
struct lvmcache_info {
 | 
			
		||||
	struct list list;	/* Join VG members together */
 | 
			
		||||
	struct list mdas;	/* list head for metadata areas */
 | 
			
		||||
@@ -64,21 +68,26 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
/* Add/delete a device */
 | 
			
		||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
 | 
			
		||||
				   struct device *dev,
 | 
			
		||||
				   const char *vgname, const char *vgid);
 | 
			
		||||
				   const char *vgname, const char *vgid,
 | 
			
		||||
				   uint32_t vgstatus);
 | 
			
		||||
void lvmcache_del(struct lvmcache_info *info);
 | 
			
		||||
 | 
			
		||||
/* Update things */
 | 
			
		||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname);
 | 
			
		||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
 | 
			
		||||
				  const char *vgname, const char *vgid,
 | 
			
		||||
				  uint32_t vgstatus, const char *hostname);
 | 
			
		||||
int lvmcache_update_vg(struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
 | 
			
		||||
void lvmcache_unlock_vgname(const char *vgname);
 | 
			
		||||
 | 
			
		||||
/* Queries */
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname);
 | 
			
		||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
 | 
			
		||||
					   const char *vgid);
 | 
			
		||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
 | 
			
		||||
struct lvmcache_info *info_from_pvid(const char *pvid);
 | 
			
		||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
 | 
			
		||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
 | 
			
		||||
int vgs_locked(void);
 | 
			
		||||
int vgname_is_locked(const char *vgname);
 | 
			
		||||
@@ -87,4 +96,12 @@ int vgname_is_locked(const char *vgname);
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of vgids */
 | 
			
		||||
/* Set full_scan to 1 to reread every filtered device label */
 | 
			
		||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
 | 
			
		||||
 | 
			
		||||
/* Returns list of struct str_lists containing pool-allocated copy of pvids */
 | 
			
		||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
 | 
			
		||||
				const char *vgid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,9 @@
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
@@ -59,15 +58,13 @@
 | 
			
		||||
#  include <malloc.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static FILE *_log;
 | 
			
		||||
 | 
			
		||||
static int _get_env_vars(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	const char *e;
 | 
			
		||||
 | 
			
		||||
	/* Set to "" to avoid using any system directory */
 | 
			
		||||
	if ((e = getenv("LVM_SYSTEM_DIR"))) {
 | 
			
		||||
		if (lvm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
 | 
			
		||||
		if (dm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
 | 
			
		||||
				 "%s", e) < 0) {
 | 
			
		||||
			log_error("LVM_SYSTEM_DIR environment variable "
 | 
			
		||||
				  "is too long.");
 | 
			
		||||
@@ -84,10 +81,11 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
	time_t t;
 | 
			
		||||
 | 
			
		||||
	const char *log_file;
 | 
			
		||||
	char timebuf[26];
 | 
			
		||||
 | 
			
		||||
	/* Syslog */
 | 
			
		||||
	cmd->default_settings.syslog =
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/syslog", DEFAULT_SYSLOG);
 | 
			
		||||
	    find_config_tree_int(cmd, "log/syslog", DEFAULT_SYSLOG);
 | 
			
		||||
	if (cmd->default_settings.syslog != 1)
 | 
			
		||||
		fin_syslog();
 | 
			
		||||
 | 
			
		||||
@@ -96,37 +94,37 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* Debug level for log file output */
 | 
			
		||||
	cmd->default_settings.debug =
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/level", DEFAULT_LOGLEVEL);
 | 
			
		||||
	    find_config_tree_int(cmd, "log/level", DEFAULT_LOGLEVEL);
 | 
			
		||||
	init_debug(cmd->default_settings.debug);
 | 
			
		||||
 | 
			
		||||
	/* Verbose level for tty output */
 | 
			
		||||
	cmd->default_settings.verbose =
 | 
			
		||||
	    find_config_int(cmd->cft->root, "log/verbose", DEFAULT_VERBOSE);
 | 
			
		||||
	    find_config_tree_int(cmd, "log/verbose", DEFAULT_VERBOSE);
 | 
			
		||||
	init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
 | 
			
		||||
 | 
			
		||||
	/* Log message formatting */
 | 
			
		||||
	init_indent(find_config_int(cmd->cft->root, "log/indent",
 | 
			
		||||
	init_indent(find_config_tree_int(cmd, "log/indent",
 | 
			
		||||
				    DEFAULT_INDENT));
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.msg_prefix = find_config_str(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.msg_prefix = find_config_tree_str(cmd,
 | 
			
		||||
							   "log/prefix",
 | 
			
		||||
							   DEFAULT_MSG_PREFIX);
 | 
			
		||||
	init_msg_prefix(cmd->default_settings.msg_prefix);
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.cmd_name = find_config_int(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.cmd_name = find_config_tree_int(cmd,
 | 
			
		||||
							 "log/command_names",
 | 
			
		||||
							 DEFAULT_CMD_NAME);
 | 
			
		||||
	init_cmd_name(cmd->default_settings.cmd_name);
 | 
			
		||||
 | 
			
		||||
	/* Test mode */
 | 
			
		||||
	cmd->default_settings.test =
 | 
			
		||||
	    find_config_int(cmd->cft->root, "global/test", 0);
 | 
			
		||||
	    find_config_tree_int(cmd, "global/test", 0);
 | 
			
		||||
 | 
			
		||||
	/* Settings for logging to file */
 | 
			
		||||
	if (find_config_int(cmd->cft->root, "log/overwrite", DEFAULT_OVERWRITE))
 | 
			
		||||
	if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE))
 | 
			
		||||
		append = 0;
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cft->root, "log/file", 0);
 | 
			
		||||
	log_file = find_config_tree_str(cmd, "log/file", 0);
 | 
			
		||||
 | 
			
		||||
	if (log_file) {
 | 
			
		||||
		release_log_memory();
 | 
			
		||||
@@ -134,15 +132,17 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
		init_log_file(log_file, append);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_file = find_config_str(cmd->cft->root, "log/activate_file", 0);
 | 
			
		||||
	log_file = find_config_tree_str(cmd, "log/activate_file", 0);
 | 
			
		||||
	if (log_file)
 | 
			
		||||
		init_log_direct(log_file, append);
 | 
			
		||||
 | 
			
		||||
	init_log_while_suspended(find_config_int(cmd->cft->root,
 | 
			
		||||
	init_log_while_suspended(find_config_tree_int(cmd,
 | 
			
		||||
						 "log/activation", 0));
 | 
			
		||||
 | 
			
		||||
	t = time(NULL);
 | 
			
		||||
	log_verbose("Logging initialised at %s", ctime(&t));
 | 
			
		||||
	ctime_r(&t, &timebuf[0]);
 | 
			
		||||
	timebuf[24] = '\0';
 | 
			
		||||
	log_verbose("Logging initialised at %s", timebuf);
 | 
			
		||||
 | 
			
		||||
	/* Tell device-mapper about our logging */
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
@@ -153,9 +153,10 @@ static void _init_logging(struct cmd_context *cmd)
 | 
			
		||||
static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	mode_t old_umask;
 | 
			
		||||
	const char *read_ahead;
 | 
			
		||||
 | 
			
		||||
	/* umask */
 | 
			
		||||
	cmd->default_settings.umask = find_config_int(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.umask = find_config_tree_int(cmd,
 | 
			
		||||
						      "global/umask",
 | 
			
		||||
						      DEFAULT_UMASK);
 | 
			
		||||
 | 
			
		||||
@@ -164,8 +165,8 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
		log_verbose("Set umask to %04o", cmd->default_settings.umask);
 | 
			
		||||
 | 
			
		||||
	/* dev dir */
 | 
			
		||||
	if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
 | 
			
		||||
			 find_config_str(cmd->cft->root, "devices/dir",
 | 
			
		||||
	if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
 | 
			
		||||
			 find_config_tree_str(cmd, "devices/dir",
 | 
			
		||||
					 DEFAULT_DEV_DIR)) < 0) {
 | 
			
		||||
		log_error("Device directory given in config file too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -175,31 +176,31 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* proc dir */
 | 
			
		||||
	if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
 | 
			
		||||
			 find_config_str(cmd->cft->root, "global/proc",
 | 
			
		||||
	if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
 | 
			
		||||
			 find_config_tree_str(cmd, "global/proc",
 | 
			
		||||
					 DEFAULT_PROC_DIR)) < 0) {
 | 
			
		||||
		log_error("Device directory given in config file too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
 | 
			
		||||
		log_error("Warning: proc dir %s not found - some checks will be bypassed",
 | 
			
		||||
		log_error("WARNING: proc dir %s not found - some checks will be bypassed",
 | 
			
		||||
			  cmd->proc_dir);
 | 
			
		||||
		cmd->proc_dir[0] = '\0';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* activation? */
 | 
			
		||||
	cmd->default_settings.activation = find_config_int(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.activation = find_config_tree_int(cmd,
 | 
			
		||||
							   "global/activation",
 | 
			
		||||
							   DEFAULT_ACTIVATION);
 | 
			
		||||
	set_activation(cmd->default_settings.activation);
 | 
			
		||||
 | 
			
		||||
	cmd->default_settings.suffix = find_config_int(cmd->cft->root,
 | 
			
		||||
	cmd->default_settings.suffix = find_config_tree_int(cmd,
 | 
			
		||||
						       "global/suffix",
 | 
			
		||||
						       DEFAULT_SUFFIX);
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->default_settings.unit_factor =
 | 
			
		||||
	      units_to_bytes(find_config_str(cmd->cft->root,
 | 
			
		||||
	      units_to_bytes(find_config_tree_str(cmd,
 | 
			
		||||
					     "global/units",
 | 
			
		||||
					     DEFAULT_UNITS),
 | 
			
		||||
			     &cmd->default_settings.unit_type))) {
 | 
			
		||||
@@ -207,6 +208,16 @@ static int _process_config(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	read_ahead = find_config_tree_str(cmd, "activation/readahead", DEFAULT_READ_AHEAD);
 | 
			
		||||
	if (!strcasecmp(read_ahead, "auto"))
 | 
			
		||||
		cmd->default_settings.read_ahead = DM_READ_AHEAD_AUTO;
 | 
			
		||||
	else if (!strcasecmp(read_ahead, "none"))
 | 
			
		||||
		cmd->default_settings.read_ahead = DM_READ_AHEAD_NONE;
 | 
			
		||||
	else {
 | 
			
		||||
		log_error("Invalid readahead specification");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -316,7 +327,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
 | 
			
		||||
	if (*tag)
 | 
			
		||||
		filler = "_";
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
 | 
			
		||||
	if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
 | 
			
		||||
			 cmd->sys_dir, filler, tag) < 0) {
 | 
			
		||||
		log_error("LVM_SYSTEM_DIR or tag was too long");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -327,7 +338,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cfl->cft = create_config_tree(config_file))) {
 | 
			
		||||
	if (!(cfl->cft = create_config_tree(config_file, 0))) {
 | 
			
		||||
		log_error("config_tree allocation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -367,7 +378,7 @@ static int _init_lvm_conf(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	/* No config file if LVM_SYSTEM_DIR is empty */
 | 
			
		||||
	if (!*cmd->sys_dir) {
 | 
			
		||||
		if (!(cmd->cft = create_config_tree(NULL))) {
 | 
			
		||||
		if (!(cmd->cft = create_config_tree(NULL, 0))) {
 | 
			
		||||
			log_error("Failed to create config tree");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -405,7 +416,7 @@ static int _merge_config_files(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* Replace temporary duplicate copy of lvm.conf */
 | 
			
		||||
	if (cmd->cft->root) {
 | 
			
		||||
		if (!(cmd->cft = create_config_tree(NULL))) {
 | 
			
		||||
		if (!(cmd->cft = create_config_tree(NULL, 0))) {
 | 
			
		||||
			log_error("Failed to create config tree");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -464,12 +475,10 @@ static int _init_dev_cache(struct cmd_context *cmd)
 | 
			
		||||
	const struct config_node *cn;
 | 
			
		||||
	struct config_value *cv;
 | 
			
		||||
 | 
			
		||||
	if (!dev_cache_init()) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (!dev_cache_init(cmd))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "devices/scan"))) {
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
 | 
			
		||||
		if (!dev_cache_add_dir("/dev")) {
 | 
			
		||||
			log_error("Failed to add /dev to internal "
 | 
			
		||||
				  "device cache");
 | 
			
		||||
@@ -494,7 +503,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "devices/loopfiles")))
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "devices/loopfiles")))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
@@ -536,14 +545,14 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
 | 
			
		||||
	 * Listed first because it's very efficient at eliminating 
 | 
			
		||||
	 * unavailable devices.
 | 
			
		||||
	 */
 | 
			
		||||
	if (find_config_bool(cmd->cft->root, "devices/sysfs_scan",
 | 
			
		||||
	if (find_config_tree_bool(cmd, "devices/sysfs_scan",
 | 
			
		||||
			     DEFAULT_SYSFS_SCAN)) {
 | 
			
		||||
		if ((filters[nr_filt] = sysfs_filter_create(cmd->proc_dir)))
 | 
			
		||||
			nr_filt++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* regex filter. Optional. */
 | 
			
		||||
	if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "devices/filter")))
 | 
			
		||||
		log_very_verbose("devices/filter not found in config file: "
 | 
			
		||||
				 "no regex filter installed");
 | 
			
		||||
 | 
			
		||||
@@ -553,14 +562,14 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* device type filter. Required. */
 | 
			
		||||
	cn = find_config_node(cmd->cft->root, "devices/types");
 | 
			
		||||
	cn = find_config_tree_node(cmd, "devices/types");
 | 
			
		||||
	if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
 | 
			
		||||
		log_error("Failed to create lvm type filter");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* md component filter. Optional, non-critical. */
 | 
			
		||||
	if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
 | 
			
		||||
	if (find_config_tree_bool(cmd, "devices/md_component_detection",
 | 
			
		||||
			     DEFAULT_MD_COMPONENT_DETECTION)) {
 | 
			
		||||
		init_md_filtering(1);
 | 
			
		||||
		if ((filters[nr_filt] = md_filter_create()))
 | 
			
		||||
@@ -572,9 +581,9 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
 | 
			
		||||
	    filters[0] : composite_filter_create(nr_filt, filters);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_filters(struct cmd_context *cmd)
 | 
			
		||||
static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
 | 
			
		||||
{
 | 
			
		||||
	const char *dev_cache;
 | 
			
		||||
	const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
 | 
			
		||||
	struct dev_filter *f3, *f4;
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	char cache_file[PATH_MAX];
 | 
			
		||||
@@ -584,30 +593,57 @@ static int _init_filters(struct cmd_context *cmd)
 | 
			
		||||
	if (!(f3 = _init_filter_components(cmd)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(cache_file, sizeof(cache_file),
 | 
			
		||||
			 "%s/.cache", cmd->sys_dir) < 0) {
 | 
			
		||||
		log_error("Persistent cache filename too long ('%s/.cache').",
 | 
			
		||||
			  cmd->sys_dir);
 | 
			
		||||
	init_ignore_suspended_devices(find_config_tree_int(cmd,
 | 
			
		||||
	    "devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
 | 
			
		||||
	 */
 | 
			
		||||
	cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
 | 
			
		||||
	cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
 | 
			
		||||
 | 
			
		||||
	if (cache_dir || cache_file_prefix) {
 | 
			
		||||
		if (dm_snprintf(cache_file, sizeof(cache_file),
 | 
			
		||||
		    "%s%s%s/%s.cache",
 | 
			
		||||
		    cache_dir ? "" : cmd->sys_dir,
 | 
			
		||||
		    cache_dir ? "" : "/",
 | 
			
		||||
		    cache_dir ? : DEFAULT_CACHE_SUBDIR,
 | 
			
		||||
		    cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
 | 
			
		||||
			log_error("Persistent cache filename too long.");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
 | 
			
		||||
		   (dm_snprintf(cache_file, sizeof(cache_file),
 | 
			
		||||
				"%s/%s/%s.cache",
 | 
			
		||||
				cmd->sys_dir, DEFAULT_CACHE_SUBDIR,
 | 
			
		||||
				DEFAULT_CACHE_FILE_PREFIX) < 0)) {
 | 
			
		||||
		log_error("Persistent cache filename too long.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev_cache = find_config_str(cmd->cft->root, "devices/cache",
 | 
			
		||||
				    cache_file);
 | 
			
		||||
	if (!dev_cache)
 | 
			
		||||
		dev_cache = cache_file;
 | 
			
		||||
 | 
			
		||||
	if (!(f4 = persistent_filter_create(f3, dev_cache))) {
 | 
			
		||||
		log_error("Failed to create persistent device filter");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Should we ever dump persistent filter state? */
 | 
			
		||||
	if (find_config_int(cmd->cft->root, "devices/write_cache_state", 1))
 | 
			
		||||
	if (find_config_tree_int(cmd, "devices/write_cache_state", 1))
 | 
			
		||||
		cmd->dump_filter = 1;
 | 
			
		||||
 | 
			
		||||
	if (!*cmd->sys_dir)
 | 
			
		||||
		cmd->dump_filter = 0;
 | 
			
		||||
 | 
			
		||||
	if (!stat(dev_cache, &st) &&
 | 
			
		||||
	    (st.st_mtime > config_file_timestamp(cmd->cft)) &&
 | 
			
		||||
	    !persistent_filter_load(f4))
 | 
			
		||||
	/*
 | 
			
		||||
	 * Only load persistent filter device cache on startup if it is newer
 | 
			
		||||
	 * than the config file and this is not a long-lived process.
 | 
			
		||||
	 */
 | 
			
		||||
	if (load_persistent_cache && !cmd->is_long_lived &&
 | 
			
		||||
	    !stat(dev_cache, &st) &&
 | 
			
		||||
	    (st.st_ctime > config_file_timestamp(cmd->cft)) &&
 | 
			
		||||
	    !persistent_filter_load(f4, NULL))
 | 
			
		||||
		log_verbose("Failed to load existing device cache from %s",
 | 
			
		||||
			    dev_cache);
 | 
			
		||||
 | 
			
		||||
@@ -643,8 +679,9 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	/* Load any formats in shared libs */
 | 
			
		||||
	if ((cn = find_config_node(cmd->cft->root, "global/format_libraries"))) {
 | 
			
		||||
	/* Load any formats in shared libs if not static */
 | 
			
		||||
	if (!cmd->is_static &&
 | 
			
		||||
	    (cn = find_config_tree_node(cmd, "global/format_libraries"))) {
 | 
			
		||||
 | 
			
		||||
		struct config_value *cv;
 | 
			
		||||
		struct format_type *(*init_format_fn) (struct cmd_context *);
 | 
			
		||||
@@ -656,8 +693,8 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
					  "global/format_libraries");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(lib = load_shared_library(cmd->cft, cv->v.str,
 | 
			
		||||
							"format"))) {
 | 
			
		||||
			if (!(lib = load_shared_library(cmd, cv->v.str,
 | 
			
		||||
							"format", 0))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -684,7 +721,7 @@ static int _init_formats(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	cmd->fmt_backup = fmt;
 | 
			
		||||
 | 
			
		||||
	format = find_config_str(cmd->cft->root, "global/format",
 | 
			
		||||
	format = find_config_tree_str(cmd, "global/format",
 | 
			
		||||
				 DEFAULT_FORMAT);
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(fmt, &cmd->formats) {
 | 
			
		||||
@@ -737,13 +774,13 @@ static int _init_segtypes(struct cmd_context *cmd)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDL
 | 
			
		||||
	/* Load any formats in shared libs */
 | 
			
		||||
	if ((cn = find_config_node(cmd->cft->root, "global/segment_libraries"))) {
 | 
			
		||||
	/* Load any formats in shared libs unless static */
 | 
			
		||||
	if (!cmd->is_static &&
 | 
			
		||||
	    (cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
 | 
			
		||||
 | 
			
		||||
		struct config_value *cv;
 | 
			
		||||
		struct segment_type *(*init_segtype_fn) (struct cmd_context *);
 | 
			
		||||
		void *lib;
 | 
			
		||||
		struct list *sgtl, *tmp;
 | 
			
		||||
		struct segment_type *segtype2;
 | 
			
		||||
 | 
			
		||||
		for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
@@ -752,8 +789,8 @@ static int _init_segtypes(struct cmd_context *cmd)
 | 
			
		||||
					  "global/segment_libraries");
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!(lib = load_shared_library(cmd->cft, cv->v.str,
 | 
			
		||||
							"segment type"))) {
 | 
			
		||||
			if (!(lib = load_shared_library(cmd, cv->v.str,
 | 
			
		||||
							"segment type", 0))) {
 | 
			
		||||
				stack;
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
@@ -770,18 +807,16 @@ static int _init_segtypes(struct cmd_context *cmd)
 | 
			
		||||
			segtype->library = lib;
 | 
			
		||||
			list_add(&cmd->segtypes, &segtype->list);
 | 
			
		||||
 | 
			
		||||
			list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
 | 
			
		||||
				segtype2 = list_item(sgtl, struct segment_type);
 | 
			
		||||
				if (!strcmp(segtype2->name, segtype->name)) {
 | 
			
		||||
					log_error("Duplicate segment type %s: "
 | 
			
		||||
						  "unloading shared library %s",
 | 
			
		||||
						  segtype->name, cv->v.str);
 | 
			
		||||
					list_del(&segtype->list);
 | 
			
		||||
					segtype->ops->destroy(segtype);
 | 
			
		||||
					dlclose(lib);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			list_iterate_items(segtype2, &cmd->segtypes) {
 | 
			
		||||
				if ((segtype == segtype2) ||
 | 
			
		||||
				     strcmp(segtype2->name, segtype->name))
 | 
			
		||||
					continue;
 | 
			
		||||
				log_error("Duplicate segment type %s: "
 | 
			
		||||
					  "unloading shared library %s",
 | 
			
		||||
					  segtype->name, cv->v.str);
 | 
			
		||||
				list_del(&segtype->list);
 | 
			
		||||
				segtype->ops->destroy(segtype);
 | 
			
		||||
				dlclose(lib);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -827,16 +862,16 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* set up archiving */
 | 
			
		||||
	cmd->default_settings.archive =
 | 
			
		||||
	    find_config_bool(cmd->cft->root, "backup/archive",
 | 
			
		||||
	    find_config_tree_bool(cmd, "backup/archive",
 | 
			
		||||
			     DEFAULT_ARCHIVE_ENABLED);
 | 
			
		||||
 | 
			
		||||
	days = (uint32_t) find_config_int(cmd->cft->root, "backup/retain_days",
 | 
			
		||||
	days = (uint32_t) find_config_tree_int(cmd, "backup/retain_days",
 | 
			
		||||
					  DEFAULT_ARCHIVE_DAYS);
 | 
			
		||||
 | 
			
		||||
	min = (uint32_t) find_config_int(cmd->cft->root, "backup/retain_min",
 | 
			
		||||
	min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min",
 | 
			
		||||
					 DEFAULT_ARCHIVE_NUMBER);
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf
 | 
			
		||||
	if (dm_snprintf
 | 
			
		||||
	    (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
 | 
			
		||||
	     DEFAULT_ARCHIVE_SUBDIR) == -1) {
 | 
			
		||||
		log_err("Couldn't create default archive path '%s/%s'.",
 | 
			
		||||
@@ -844,7 +879,7 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dir = find_config_str(cmd->cft->root, "backup/archive_dir",
 | 
			
		||||
	dir = find_config_tree_str(cmd, "backup/archive_dir",
 | 
			
		||||
			      default_dir);
 | 
			
		||||
 | 
			
		||||
	if (!archive_init(cmd, dir, days, min)) {
 | 
			
		||||
@@ -854,10 +889,10 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* set up the backup */
 | 
			
		||||
	cmd->default_settings.backup =
 | 
			
		||||
	    find_config_bool(cmd->cft->root, "backup/backup",
 | 
			
		||||
	    find_config_tree_bool(cmd, "backup/backup",
 | 
			
		||||
			     DEFAULT_BACKUP_ENABLED);
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf
 | 
			
		||||
	if (dm_snprintf
 | 
			
		||||
	    (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
 | 
			
		||||
	     DEFAULT_BACKUP_SUBDIR) == -1) {
 | 
			
		||||
		log_err("Couldn't create default backup path '%s/%s'.",
 | 
			
		||||
@@ -865,7 +900,7 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dir = find_config_str(cmd->cft->root, "backup/backup_dir", default_dir);
 | 
			
		||||
	dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir);
 | 
			
		||||
 | 
			
		||||
	if (!backup_init(cmd, dir)) {
 | 
			
		||||
		log_debug("backup_init failed.");
 | 
			
		||||
@@ -876,7 +911,8 @@ static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Entry point */
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
 | 
			
		||||
				       unsigned is_long_lived)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_context *cmd;
 | 
			
		||||
 | 
			
		||||
@@ -899,6 +935,8 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
	}
 | 
			
		||||
	memset(cmd, 0, sizeof(*cmd));
 | 
			
		||||
	cmd->args = the_args;
 | 
			
		||||
	cmd->is_static = is_static;
 | 
			
		||||
	cmd->is_long_lived = is_long_lived;
 | 
			
		||||
	cmd->hosttags = 0;
 | 
			
		||||
	list_init(&cmd->formats);
 | 
			
		||||
	list_init(&cmd->segtypes);
 | 
			
		||||
@@ -911,7 +949,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	/* Create system directory if it doesn't already exist */
 | 
			
		||||
	if (*cmd->sys_dir && !create_dir(cmd->sys_dir)) {
 | 
			
		||||
	if (*cmd->sys_dir && !dm_create_dir(cmd->sys_dir)) {
 | 
			
		||||
		log_error("Failed to create LVM2 system dir for metadata backups, config "
 | 
			
		||||
			  "files and internal cache.");
 | 
			
		||||
		log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
 | 
			
		||||
@@ -921,7 +959,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) {
 | 
			
		||||
		log_error("Library memory pool creation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_init_lvm_conf(cmd))
 | 
			
		||||
@@ -947,12 +985,12 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
 | 
			
		||||
	if (!_init_dev_cache(cmd))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!_init_filters(cmd))
 | 
			
		||||
	if (!_init_filters(cmd, 1))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
 | 
			
		||||
		log_error("Command memory pool creation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memlock_init(cmd);
 | 
			
		||||
@@ -1016,12 +1054,12 @@ int refresh_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	log_verbose("Reloading config files");
 | 
			
		||||
 | 
			
		||||
	if (cmd->config_valid) {
 | 
			
		||||
		if (cmd->dump_filter)
 | 
			
		||||
			persistent_filter_dump(cmd->filter);
 | 
			
		||||
	}
 | 
			
		||||
	/*
 | 
			
		||||
	 * Don't update the persistent filter cache as we will
 | 
			
		||||
	 * perform a full rescan.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	activation_exit();
 | 
			
		||||
	activation_release();
 | 
			
		||||
	lvmcache_destroy();
 | 
			
		||||
	label_exit();
 | 
			
		||||
	_destroy_segtypes(&cmd->segtypes);
 | 
			
		||||
@@ -1058,7 +1096,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
	if (!_init_dev_cache(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_init_filters(cmd))
 | 
			
		||||
	if (!_init_filters(cmd, 0))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!_init_formats(cmd))
 | 
			
		||||
@@ -1067,6 +1105,13 @@ int refresh_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
	if (!_init_segtypes(cmd))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If we are a long-lived process, write out the updated persistent
 | 
			
		||||
	 * device cache for the benefit of short-lived processes.
 | 
			
		||||
	 */
 | 
			
		||||
	if (cmd->is_long_lived && cmd->dump_filter)
 | 
			
		||||
		persistent_filter_dump(cmd->filter);
 | 
			
		||||
 | 
			
		||||
	cmd->config_valid = 1;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -1094,8 +1139,4 @@ void destroy_toolcontext(struct cmd_context *cmd)
 | 
			
		||||
	activation_exit();
 | 
			
		||||
	fin_log();
 | 
			
		||||
	fin_syslog();
 | 
			
		||||
 | 
			
		||||
	if (_log)
 | 
			
		||||
		fclose(_log);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -33,6 +33,7 @@ struct config_info {
 | 
			
		||||
	int suffix;
 | 
			
		||||
	int archive;		/* should we archive ? */
 | 
			
		||||
	int backup;		/* should we backup ? */
 | 
			
		||||
	int read_ahead;		/* DM_READ_AHEAD_NONE or _AUTO */
 | 
			
		||||
	const char *msg_prefix;
 | 
			
		||||
	struct format_type *fmt;
 | 
			
		||||
	uint64_t unit_factor;
 | 
			
		||||
@@ -64,6 +65,8 @@ struct cmd_context {
 | 
			
		||||
	struct command *command;
 | 
			
		||||
	struct arg *args;
 | 
			
		||||
	char **argv;
 | 
			
		||||
	unsigned is_static;	/* Static binary? */
 | 
			
		||||
	unsigned is_long_lived;	/* Optimises persistent_filter handling */
 | 
			
		||||
 | 
			
		||||
	struct dev_filter *filter;
 | 
			
		||||
	int dump_filter;	/* Dump filter when exiting? */
 | 
			
		||||
@@ -71,6 +74,7 @@ struct cmd_context {
 | 
			
		||||
	struct list config_files;
 | 
			
		||||
	int config_valid;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
	struct config_tree *cft_override;
 | 
			
		||||
	struct config_info default_settings;
 | 
			
		||||
	struct config_info current_settings;
 | 
			
		||||
 | 
			
		||||
@@ -86,7 +90,7 @@ struct cmd_context {
 | 
			
		||||
	char proc_dir[PATH_MAX];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args);
 | 
			
		||||
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
 | 
			
		||||
void destroy_toolcontext(struct cmd_context *cmd);
 | 
			
		||||
int refresh_toolcontext(struct cmd_context *cmd);
 | 
			
		||||
int config_files_changed(struct cmd_context *cmd);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -19,6 +19,8 @@
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "lvm-file.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
@@ -26,6 +28,9 @@
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
#define SECTION_B_CHAR '{'
 | 
			
		||||
#define SECTION_E_CHAR '}'
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	TOK_INT,
 | 
			
		||||
	TOK_FLOAT,
 | 
			
		||||
@@ -41,10 +46,10 @@ enum {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct parser {
 | 
			
		||||
	char *fb, *fe;		/* file limits */
 | 
			
		||||
	const char *fb, *fe;		/* file limits */
 | 
			
		||||
 | 
			
		||||
	int t;			/* token limits and type */
 | 
			
		||||
	char *tb, *te;
 | 
			
		||||
	const char *tb, *te;
 | 
			
		||||
 | 
			
		||||
	int fd;			/* descriptor for file being parsed */
 | 
			
		||||
	int line;		/* line number we are on */
 | 
			
		||||
@@ -58,6 +63,13 @@ struct cs {
 | 
			
		||||
	time_t timestamp;
 | 
			
		||||
	char *filename;
 | 
			
		||||
	int exists;
 | 
			
		||||
	int keep_open;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct output_line {
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void _get_token(struct parser *p, int tok_prev);
 | 
			
		||||
@@ -77,7 +89,8 @@ static const int sep = '/';
 | 
			
		||||
 | 
			
		||||
#define match(t) do {\
 | 
			
		||||
   if (!_match_aux(p, (t))) {\
 | 
			
		||||
	log_error("Parse error at line %d: unexpected token", p->line); \
 | 
			
		||||
	log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \
 | 
			
		||||
		  p->tb - p->fb + 1, p->line); \
 | 
			
		||||
      return 0;\
 | 
			
		||||
   } \
 | 
			
		||||
} while(0);
 | 
			
		||||
@@ -95,18 +108,18 @@ static int _tok_match(const char *str, const char *b, const char *e)
 | 
			
		||||
/*
 | 
			
		||||
 * public interface
 | 
			
		||||
 */
 | 
			
		||||
struct config_tree *create_config_tree(const char *filename)
 | 
			
		||||
struct config_tree *create_config_tree(const char *filename, int keep_open)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c;
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
 | 
			
		||||
 | 
			
		||||
	if (!mem) {
 | 
			
		||||
		stack;
 | 
			
		||||
		log_error("Failed to allocate config pool.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		log_error("Failed to allocate config tree.");
 | 
			
		||||
		dm_pool_destroy(mem);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -115,6 +128,8 @@ struct config_tree *create_config_tree(const char *filename)
 | 
			
		||||
	c->cft.root = (struct config_node *) NULL;
 | 
			
		||||
	c->timestamp = 0;
 | 
			
		||||
	c->exists = 0;
 | 
			
		||||
	c->keep_open = keep_open;
 | 
			
		||||
	c->dev = 0;
 | 
			
		||||
	if (filename)
 | 
			
		||||
		c->filename = dm_pool_strdup(c->mem, filename);
 | 
			
		||||
	return &c->cft;
 | 
			
		||||
@@ -122,7 +137,52 @@ struct config_tree *create_config_tree(const char *filename)
 | 
			
		||||
 | 
			
		||||
void destroy_config_tree(struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	dm_pool_destroy(((struct cs *) cft)->mem);
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
 | 
			
		||||
	if (c->dev)
 | 
			
		||||
		dev_close(c->dev);
 | 
			
		||||
 | 
			
		||||
	dm_pool_destroy(c->mem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _parse_config_file(struct parser *p, struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	p->tb = p->te = p->fb;
 | 
			
		||||
	p->line = 1;
 | 
			
		||||
	_get_token(p, TOK_SECTION_E);
 | 
			
		||||
	if (!(cft->root = _file(p)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd __attribute((unused)),
 | 
			
		||||
						   const char *config_settings)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
	struct parser *p;
 | 
			
		||||
 | 
			
		||||
	if (!(cft = create_config_tree(NULL, 0)))
 | 
			
		||||
		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,
 | 
			
		||||
@@ -134,6 +194,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	int use_mmap = 1;
 | 
			
		||||
	off_t mmap_offset = 0;
 | 
			
		||||
	char *buf = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -146,7 +207,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		use_mmap = 0;
 | 
			
		||||
 | 
			
		||||
	if (use_mmap) {
 | 
			
		||||
		mmap_offset = offset % getpagesize();
 | 
			
		||||
		mmap_offset = offset % lvm_getpagesize();
 | 
			
		||||
		/* memory map the file */
 | 
			
		||||
		p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
 | 
			
		||||
			     MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
 | 
			
		||||
@@ -156,22 +217,15 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		}
 | 
			
		||||
		p->fb = p->fb + mmap_offset;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!(p->fb = dm_malloc(size + size2))) {
 | 
			
		||||
		if (!(buf = dm_malloc(size + size2))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (!dev_read(dev, (uint64_t) offset, size, p->fb)) {
 | 
			
		||||
			log_error("Read from %s failed", dev_name(dev));
 | 
			
		||||
		if (!dev_read_circular(dev, (uint64_t) offset, size,
 | 
			
		||||
				       (uint64_t) offset2, size2, buf)) {
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (size2) {
 | 
			
		||||
			if (!dev_read(dev, (uint64_t) offset2, size2,
 | 
			
		||||
				      p->fb + size)) {
 | 
			
		||||
				log_error("Circular read from %s failed",
 | 
			
		||||
					  dev_name(dev));
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		p->fb = buf;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (checksum_fn && checksum !=
 | 
			
		||||
@@ -183,11 +237,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
 | 
			
		||||
	p->fe = p->fb + size + size2;
 | 
			
		||||
 | 
			
		||||
	/* parse */
 | 
			
		||||
	p->tb = p->te = p->fb;
 | 
			
		||||
	p->line = 1;
 | 
			
		||||
	_get_token(p, TOK_SECTION_E);
 | 
			
		||||
	if (!(cft->root = _file(p))) {
 | 
			
		||||
	if (!_parse_config_file(p, cft)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -196,7 +246,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	if (!use_mmap)
 | 
			
		||||
		dm_free(p->fb);
 | 
			
		||||
		dm_free(buf);
 | 
			
		||||
	else {
 | 
			
		||||
		/* unmap the file */
 | 
			
		||||
		if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
 | 
			
		||||
@@ -212,7 +262,6 @@ int read_config_file(struct config_tree *cft)
 | 
			
		||||
{
 | 
			
		||||
	struct cs *c = (struct cs *) cft;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
	if (stat(c->filename, &info)) {
 | 
			
		||||
@@ -234,22 +283,23 @@ int read_config_file(struct config_tree *cft)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dev = dev_create_file(c->filename, NULL, NULL, 1))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (!c->dev) {
 | 
			
		||||
		if (!(c->dev = dev_create_file(c->filename, NULL, NULL, 1)))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		if (!dev_open_flags(c->dev, O_RDONLY, 0, 0))
 | 
			
		||||
			return_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,
 | 
			
		||||
	r = read_config_fd(cft, c->dev, 0, (size_t) info.st_size, 0, 0,
 | 
			
		||||
			   (checksum_fn_t) NULL, 0);
 | 
			
		||||
 | 
			
		||||
	dev_close(dev);
 | 
			
		||||
	if (!c->keep_open) {
 | 
			
		||||
		dev_close(c->dev);
 | 
			
		||||
		c->dev = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c->timestamp = info.st_mtime;
 | 
			
		||||
	c->timestamp = info.st_ctime;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
@@ -293,7 +343,7 @@ int config_file_changed(struct config_tree *cft)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Unchanged? */
 | 
			
		||||
	if (c->timestamp == info.st_mtime)
 | 
			
		||||
	if (c->timestamp == info.st_ctime)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
      reload:
 | 
			
		||||
@@ -301,32 +351,89 @@ int config_file_changed(struct config_tree *cft)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _write_value(FILE *fp, struct config_value *v)
 | 
			
		||||
static int _line_start(struct output_line *outline)
 | 
			
		||||
{
 | 
			
		||||
	if (!dm_pool_begin_object(outline->mem, 128)) {
 | 
			
		||||
		log_error("dm_pool_begin_object failed for config line");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _line_append(struct output_line *outline, const char *fmt, ...)
 | 
			
		||||
  __attribute__ ((format(printf, 2, 3)));
 | 
			
		||||
static int _line_append(struct output_line *outline, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	char buf[4096];
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	int n;
 | 
			
		||||
 | 
			
		||||
	va_start(ap, fmt);
 | 
			
		||||
	n = vsnprintf(&buf[0], sizeof buf - 1, fmt, ap);
 | 
			
		||||
	if (n < 0 || n > (int) sizeof buf - 1) {
 | 
			
		||||
		log_error("vsnprintf failed for config line");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) {
 | 
			
		||||
		log_error("dm_pool_grew_object failed for config line");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0)
 | 
			
		||||
 | 
			
		||||
static int _line_end(struct output_line *outline)
 | 
			
		||||
{
 | 
			
		||||
	const char *line;
 | 
			
		||||
 | 
			
		||||
	if (!dm_pool_grow_object(outline->mem, "\0", 1)) {
 | 
			
		||||
		log_error("dm_pool_grow_object failed for config line");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	line = dm_pool_end_object(outline->mem);
 | 
			
		||||
	if (!outline->fp)
 | 
			
		||||
		log_print("%s", line);
 | 
			
		||||
	else
 | 
			
		||||
		fprintf(outline->fp, "%s\n", line);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _write_value(struct output_line *outline, struct config_value *v)
 | 
			
		||||
{
 | 
			
		||||
	switch (v->type) {
 | 
			
		||||
	case CFG_STRING:
 | 
			
		||||
		fprintf(fp, "\"%s\"", v->v.str);
 | 
			
		||||
		line_append("\"%s\"", v->v.str);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CFG_FLOAT:
 | 
			
		||||
		fprintf(fp, "%f", v->v.r);
 | 
			
		||||
		line_append("%f", v->v.r);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CFG_INT:
 | 
			
		||||
		fprintf(fp, "%d", v->v.i);
 | 
			
		||||
		line_append("%" PRId64, v->v.i);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CFG_EMPTY_ARRAY:
 | 
			
		||||
		fprintf(fp, "[]");
 | 
			
		||||
		line_append("[]");
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("_write_value: Unknown value type: %d", v->type);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _write_config(struct config_node *n, FILE *fp, int level)
 | 
			
		||||
static int _write_config(struct config_node *n, int only_one,
 | 
			
		||||
			 struct output_line *outline, int level)
 | 
			
		||||
{
 | 
			
		||||
	char space[MAX_INDENT + 1];
 | 
			
		||||
	int l = (level < MAX_INDENT) ? level : MAX_INDENT;
 | 
			
		||||
@@ -339,58 +446,87 @@ static int _write_config(struct config_node *n, FILE *fp, int level)
 | 
			
		||||
		space[i] = '\t';
 | 
			
		||||
	space[i] = '\0';
 | 
			
		||||
 | 
			
		||||
	while (n) {
 | 
			
		||||
		fprintf(fp, "%s%s", space, n->key);
 | 
			
		||||
	do {
 | 
			
		||||
		if (!_line_start(outline))
 | 
			
		||||
			return_0;
 | 
			
		||||
		line_append("%s%s", space, n->key);
 | 
			
		||||
		if (!n->v) {
 | 
			
		||||
			/* it's a sub section */
 | 
			
		||||
			fprintf(fp, " {\n");
 | 
			
		||||
			_write_config(n->child, fp, level + 1);
 | 
			
		||||
			fprintf(fp, "%s}", space);
 | 
			
		||||
			line_append(" {");
 | 
			
		||||
			if (!_line_end(outline))
 | 
			
		||||
				return_0;
 | 
			
		||||
			if (!_line_start(outline))
 | 
			
		||||
				return_0;
 | 
			
		||||
			_write_config(n->child, 0, outline, level + 1);
 | 
			
		||||
			line_append("%s}", space);
 | 
			
		||||
		} else {
 | 
			
		||||
			/* it's a value */
 | 
			
		||||
			struct config_value *v = n->v;
 | 
			
		||||
			fprintf(fp, "=");
 | 
			
		||||
			line_append("=");
 | 
			
		||||
			if (v->next) {
 | 
			
		||||
				fprintf(fp, "[");
 | 
			
		||||
				line_append("[");
 | 
			
		||||
				while (v) {
 | 
			
		||||
					_write_value(fp, v);
 | 
			
		||||
					if (!_write_value(outline, v))
 | 
			
		||||
						return_0;
 | 
			
		||||
					v = v->next;
 | 
			
		||||
					if (v)
 | 
			
		||||
						fprintf(fp, ", ");
 | 
			
		||||
						line_append(", ");
 | 
			
		||||
				}
 | 
			
		||||
				fprintf(fp, "]");
 | 
			
		||||
				line_append("]");
 | 
			
		||||
			} else
 | 
			
		||||
				_write_value(fp, v);
 | 
			
		||||
				if (!_write_value(outline, v))
 | 
			
		||||
					return_0;
 | 
			
		||||
		}
 | 
			
		||||
		fprintf(fp, "\n");
 | 
			
		||||
		if (!_line_end(outline))
 | 
			
		||||
			return_0;
 | 
			
		||||
		n = n->sib;
 | 
			
		||||
	}
 | 
			
		||||
	} while (n && !only_one);
 | 
			
		||||
	/* FIXME: add error checking */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int write_config_file(struct config_tree *cft, const char *file)
 | 
			
		||||
int write_config_file(struct config_tree *cft, const char *file,
 | 
			
		||||
		      int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
	int r = 1;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	struct output_line outline;
 | 
			
		||||
	outline.fp = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!file) {
 | 
			
		||||
		fp = stdout;
 | 
			
		||||
	if (!file)
 | 
			
		||||
		file = "stdout";
 | 
			
		||||
	} else if (!(fp = fopen(file, "w"))) {
 | 
			
		||||
	else if (!(outline.fp = fopen(file, "w"))) {
 | 
			
		||||
		log_sys_error("open", file);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	outline.mem = dm_pool_create("config_line", 1024);
 | 
			
		||||
 | 
			
		||||
	log_verbose("Dumping configuration to %s", file);
 | 
			
		||||
	if (!_write_config(cft->root, fp, 0)) {
 | 
			
		||||
		log_error("Failure while writing configuration");
 | 
			
		||||
	if (!argc) {
 | 
			
		||||
		if (!_write_config(cft->root, 0, &outline, 0)) {
 | 
			
		||||
			log_error("Failure while writing to %s", file);
 | 
			
		||||
			r = 0;
 | 
			
		||||
		}
 | 
			
		||||
	} else while (argc--) {
 | 
			
		||||
		if ((cn = find_config_node(cft->root, *argv))) {
 | 
			
		||||
			if (!_write_config(cn, 1, &outline, 0)) {
 | 
			
		||||
				log_error("Failure while writing to %s", file);
 | 
			
		||||
				r = 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			log_error("Configuration node %s not found", *argv);
 | 
			
		||||
			r = 0;
 | 
			
		||||
		}
 | 
			
		||||
		argv++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (outline.fp && lvm_fclose(outline.fp, file)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		r = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fp != stdout)
 | 
			
		||||
		fclose(fp);
 | 
			
		||||
 | 
			
		||||
	dm_pool_destroy(outline.mem);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -417,7 +553,7 @@ static struct config_node *_file(struct parser *p)
 | 
			
		||||
 | 
			
		||||
static struct config_node *_section(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	/* IDENTIFIER '{' VALUE* '}' */
 | 
			
		||||
	/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
 | 
			
		||||
	struct config_node *root, *n, *l = NULL;
 | 
			
		||||
	if (!(root = _create_node(p))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -506,7 +642,7 @@ static struct config_value *_type(struct parser *p)
 | 
			
		||||
	switch (p->t) {
 | 
			
		||||
	case TOK_INT:
 | 
			
		||||
		v->type = CFG_INT;
 | 
			
		||||
		v->v.i = strtol(p->tb, NULL, 0);	/* FIXME: check error */
 | 
			
		||||
		v->v.i = strtoll(p->tb, NULL, 0);	/* FIXME: check error */
 | 
			
		||||
		match(TOK_INT);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
@@ -529,7 +665,8 @@ 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 %" PRIptrdiff_t " (line %d): expected a value",
 | 
			
		||||
			  p->tb - p->fb + 1, p->line);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return v;
 | 
			
		||||
@@ -566,12 +703,12 @@ static void _get_token(struct parser *p, int tok_prev)
 | 
			
		||||
	p->t = TOK_INT;		/* fudge so the fall through for
 | 
			
		||||
				   floats works */
 | 
			
		||||
	switch (*p->te) {
 | 
			
		||||
	case '{':
 | 
			
		||||
	case SECTION_B_CHAR:
 | 
			
		||||
		p->t = TOK_SECTION_B;
 | 
			
		||||
		p->te++;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '}':
 | 
			
		||||
	case SECTION_E_CHAR:
 | 
			
		||||
		p->t = TOK_SECTION_E;
 | 
			
		||||
		p->te++;
 | 
			
		||||
		break;
 | 
			
		||||
@@ -651,8 +788,9 @@ static void _get_token(struct parser *p, int tok_prev)
 | 
			
		||||
	default:
 | 
			
		||||
		p->t = TOK_IDENTIFIER;
 | 
			
		||||
		while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
 | 
			
		||||
		       (*p->te != '#') && (*p->te != '=') && (*p->te != '{') &&
 | 
			
		||||
		       (*p->te != '}'))
 | 
			
		||||
		       (*p->te != '#') && (*p->te != '=') &&
 | 
			
		||||
		       (*p->te != SECTION_B_CHAR) &&
 | 
			
		||||
		       (*p->te != SECTION_E_CHAR))
 | 
			
		||||
			p->te++;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
@@ -688,14 +826,20 @@ static void _eat_space(struct parser *p)
 | 
			
		||||
static struct config_value *_create_value(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
 | 
			
		||||
	memset(v, 0, sizeof(*v));
 | 
			
		||||
 | 
			
		||||
	if (v)
 | 
			
		||||
		memset(v, 0, sizeof(*v));
 | 
			
		||||
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct config_node *_create_node(struct parser *p)
 | 
			
		||||
{
 | 
			
		||||
	struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
 | 
			
		||||
	memset(n, 0, sizeof(*n));
 | 
			
		||||
 | 
			
		||||
	if (n)
 | 
			
		||||
		memset(n, 0, sizeof(*n));
 | 
			
		||||
 | 
			
		||||
	return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -715,10 +859,11 @@ static char *_dup_tok(struct parser *p)
 | 
			
		||||
/*
 | 
			
		||||
 * utility functions
 | 
			
		||||
 */
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path)
 | 
			
		||||
static struct config_node *_find_config_node(const struct config_node *cn,
 | 
			
		||||
					     const char *path)
 | 
			
		||||
{
 | 
			
		||||
	const char *e;
 | 
			
		||||
	const struct config_node *cn_found = NULL;
 | 
			
		||||
 | 
			
		||||
	while (cn) {
 | 
			
		||||
		/* trim any leading slashes */
 | 
			
		||||
@@ -729,32 +874,62 @@ struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
		for (e = path; *e && (*e != sep); e++) ;
 | 
			
		||||
 | 
			
		||||
		/* hunt for the node */
 | 
			
		||||
		cn_found = NULL;
 | 
			
		||||
		while (cn) {
 | 
			
		||||
			if (_tok_match(cn->key, path, e))
 | 
			
		||||
				break;
 | 
			
		||||
			if (_tok_match(cn->key, path, e)) {
 | 
			
		||||
				/* Inefficient */
 | 
			
		||||
				if (!cn_found)
 | 
			
		||||
					cn_found = cn;
 | 
			
		||||
				else
 | 
			
		||||
					log_error("WARNING: Ignoring duplicate"
 | 
			
		||||
						  " config node: %s ("
 | 
			
		||||
						  "seeking %s)", cn->key, path);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cn = cn->sib;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cn && *e)
 | 
			
		||||
			cn = cn->child;
 | 
			
		||||
		if (cn_found && *e)
 | 
			
		||||
			cn = cn_found->child;
 | 
			
		||||
		else
 | 
			
		||||
			break;	/* don't move into the last node */
 | 
			
		||||
 | 
			
		||||
		path = e;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (struct config_node *) cn;
 | 
			
		||||
	return (struct config_node *) cn_found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *find_config_str(const struct config_node *cn,
 | 
			
		||||
			    const char *path, const char *fail)
 | 
			
		||||
static struct config_node *_find_first_config_node(const struct config_node *cn1,
 | 
			
		||||
						   const struct config_node *cn2,
 | 
			
		||||
						   const char *path)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	struct config_node *cn;
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_STRING) {
 | 
			
		||||
		if (*n->v->v.str)
 | 
			
		||||
			log_very_verbose("Setting %s to %s", path, n->v->v.str);
 | 
			
		||||
	if (cn1 && (cn = _find_config_node(cn1, path)))
 | 
			
		||||
		return cn;
 | 
			
		||||
 | 
			
		||||
	if (cn2 && (cn = _find_config_node(cn2, path)))
 | 
			
		||||
		return cn;
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_node(cn, path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *_find_config_str(const struct config_node *cn1,
 | 
			
		||||
				    const struct config_node *cn2,
 | 
			
		||||
				    const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
 | 
			
		||||
	/* Empty strings are ignored */
 | 
			
		||||
	if ((n && n->v && n->v->type == CFG_STRING) && (*n->v->v.str)) {
 | 
			
		||||
		log_very_verbose("Setting %s to %s", path, n->v->v.str);
 | 
			
		||||
		return n->v->v.str;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -764,26 +939,41 @@ const char *find_config_str(const struct config_node *cn,
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
const char *find_config_str(const struct config_node *cn,
 | 
			
		||||
			    const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	return _find_config_str(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_INT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %d", path, n->v->v.i);
 | 
			
		||||
static int64_t _find_config_int64(const struct config_node *cn1,
 | 
			
		||||
				  const struct config_node *cn2,
 | 
			
		||||
				  const char *path, int64_t fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
 | 
			
		||||
	if (n && n->v && n->v->type == CFG_INT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i);
 | 
			
		||||
		return n->v->v.i;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("%s not found in config: defaulting to %d",
 | 
			
		||||
	log_very_verbose("%s not found in config: defaulting to %" PRId64,
 | 
			
		||||
			 path, fail);
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail)
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	/* FIXME Add log_error message on overflow */
 | 
			
		||||
	return (int) _find_config_int64(cn, NULL, path, (int64_t) fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	if (n && n->v->type == CFG_FLOAT) {
 | 
			
		||||
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 && n->v->type == CFG_FLOAT) {
 | 
			
		||||
		log_very_verbose("Setting %s to %f", path, n->v->v.r);
 | 
			
		||||
		return n->v->v.r;
 | 
			
		||||
	}
 | 
			
		||||
@@ -795,6 +985,37 @@ float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_float(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_tree_node(struct cmd_context *cmd,
 | 
			
		||||
					  const char *path)
 | 
			
		||||
{
 | 
			
		||||
	return _find_first_config_node(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *find_config_tree_str(struct cmd_context *cmd,
 | 
			
		||||
				 const char *path, const char *fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_str(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_tree_int(struct cmd_context *cmd, const char *path,
 | 
			
		||||
			 int fail)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME Add log_error message on overflow */
 | 
			
		||||
	return (int) _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, (int64_t) fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float find_config_tree_float(struct cmd_context *cmd, const char *path,
 | 
			
		||||
			     float fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _str_in_array(const char *str, const char *values[])
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
@@ -821,9 +1042,11 @@ static int _str_to_bool(const char *str, int fail)
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_bool(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
static int _find_config_bool(const struct config_node *cn1,
 | 
			
		||||
			     const struct config_node *cn2,
 | 
			
		||||
			     const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *n = find_config_node(cn, path);
 | 
			
		||||
	const struct config_node *n = _find_first_config_node(cn1, cn2, path);
 | 
			
		||||
	struct config_value *v;
 | 
			
		||||
 | 
			
		||||
	if (!n)
 | 
			
		||||
@@ -842,6 +1065,16 @@ int find_config_bool(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
	return fail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_bool(const struct config_node *cn, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_bool(cn, NULL, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail)
 | 
			
		||||
{
 | 
			
		||||
	return _find_config_bool(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_config_uint32(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint32_t *result)
 | 
			
		||||
{
 | 
			
		||||
@@ -866,7 +1099,6 @@ int get_config_uint64(const struct config_node *cn, const char *path,
 | 
			
		||||
	if (!n || !n->v || n->v->type != CFG_INT)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* FIXME Support 64-bit value! */
 | 
			
		||||
	*result = (uint64_t) n->v->v.i;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -996,3 +1228,61 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Convert a token type to the char it represents.
 | 
			
		||||
 */
 | 
			
		||||
static char _token_type_to_char(int type)
 | 
			
		||||
{
 | 
			
		||||
	switch (type) {
 | 
			
		||||
		case TOK_SECTION_B:
 | 
			
		||||
			return SECTION_B_CHAR;
 | 
			
		||||
		case TOK_SECTION_E:
 | 
			
		||||
			return SECTION_E_CHAR;
 | 
			
		||||
		default:
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns:
 | 
			
		||||
 *  # of 'type' tokens in 'str'.
 | 
			
		||||
 */
 | 
			
		||||
static unsigned _count_tokens(const char *str, unsigned len, int type)
 | 
			
		||||
{
 | 
			
		||||
	char c;
 | 
			
		||||
 | 
			
		||||
	c = _token_type_to_char(type);
 | 
			
		||||
 | 
			
		||||
	return count_chars_len(str, len, c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Heuristic function to make a quick guess as to whether a text
 | 
			
		||||
 * region probably contains a valid config "section".  (Useful for
 | 
			
		||||
 * scanning areas of the disk for old metadata.)
 | 
			
		||||
 * Config sections contain various tokens, may contain other sections
 | 
			
		||||
 * and strings, and are delimited by begin (type 'TOK_SECTION_B') and
 | 
			
		||||
 * end (type 'TOK_SECTION_E') tokens.  As a quick heuristic, we just
 | 
			
		||||
 * count the number of begin and end tokens, and see if they are
 | 
			
		||||
 * non-zero and the counts match.
 | 
			
		||||
 * Full validation of the section should be done with another function
 | 
			
		||||
 * (for example, read_config_fd).
 | 
			
		||||
 *
 | 
			
		||||
 * Returns:
 | 
			
		||||
 *  0 - probably is not a valid config section
 | 
			
		||||
 *  1 - probably _is_ a valid config section
 | 
			
		||||
 */
 | 
			
		||||
unsigned maybe_config_section(const char *str, unsigned len)
 | 
			
		||||
{
 | 
			
		||||
	int begin_count;
 | 
			
		||||
	int end_count;
 | 
			
		||||
 | 
			
		||||
	begin_count = _count_tokens(str, len, TOK_SECTION_B);
 | 
			
		||||
	end_count = _count_tokens(str, len, TOK_SECTION_E);
 | 
			
		||||
 | 
			
		||||
	if (begin_count && end_count && (begin_count - end_count == 0))
 | 
			
		||||
		return 1;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -31,7 +31,7 @@ enum {
 | 
			
		||||
struct config_value {
 | 
			
		||||
	int type;
 | 
			
		||||
	union {
 | 
			
		||||
		int i;
 | 
			
		||||
		int64_t i;
 | 
			
		||||
		float r;
 | 
			
		||||
		char *str;
 | 
			
		||||
	} v;
 | 
			
		||||
@@ -53,17 +53,20 @@ struct config_tree_list {
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct config_tree *create_config_tree(const char *filename);
 | 
			
		||||
struct config_tree *create_config_tree(const char *filename, int keep_open);
 | 
			
		||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
 | 
			
		||||
						   const char *config_settings);
 | 
			
		||||
void destroy_config_tree(struct config_tree *cft);
 | 
			
		||||
 | 
			
		||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
 | 
			
		||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const void *buf, uint32_t size);
 | 
			
		||||
 | 
			
		||||
int read_config_fd(struct config_tree *cft, struct device *dev,
 | 
			
		||||
		   off_t offset, size_t size, off_t offset2, size_t size2,
 | 
			
		||||
		   checksum_fn_t checksum_fn, uint32_t checksum);
 | 
			
		||||
 | 
			
		||||
int read_config_file(struct config_tree *cft);
 | 
			
		||||
int write_config_file(struct config_tree *cft, const char *file);
 | 
			
		||||
int write_config_file(struct config_tree *cft, const char *file,
 | 
			
		||||
		      int argc, char **argv);
 | 
			
		||||
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,
 | 
			
		||||
@@ -71,20 +74,30 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
 | 
			
		||||
 | 
			
		||||
struct config_node *find_config_node(const struct config_node *cn,
 | 
			
		||||
				     const char *path);
 | 
			
		||||
 | 
			
		||||
const char *find_config_str(const struct config_node *cn, const char *path,
 | 
			
		||||
			    const char *fail);
 | 
			
		||||
 | 
			
		||||
int find_config_int(const struct config_node *cn, const char *path, int fail);
 | 
			
		||||
 | 
			
		||||
float find_config_float(const struct config_node *cn, const char *path,
 | 
			
		||||
			float fail);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * These versions check an override tree, if present, first.
 | 
			
		||||
 */
 | 
			
		||||
struct config_node *find_config_tree_node(struct cmd_context *cmd,
 | 
			
		||||
					  const char *path);
 | 
			
		||||
const char *find_config_tree_str(struct cmd_context *cmd,
 | 
			
		||||
				 const char *path, const char *fail);
 | 
			
		||||
int find_config_tree_int(struct cmd_context *cmd, const char *path,
 | 
			
		||||
			 int fail);
 | 
			
		||||
float find_config_tree_float(struct cmd_context *cmd, const char *path,
 | 
			
		||||
			     float fail);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Understands (0, ~0), (y, n), (yes, no), (on,
 | 
			
		||||
 * off), (true, false).
 | 
			
		||||
 */
 | 
			
		||||
int find_config_bool(const struct config_node *cn, const char *path, int fail);
 | 
			
		||||
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail);
 | 
			
		||||
 | 
			
		||||
int get_config_uint32(const struct config_node *cn, const char *path,
 | 
			
		||||
		      uint32_t *result);
 | 
			
		||||
@@ -95,4 +108,6 @@ int get_config_uint64(const struct config_node *cn, const char *path,
 | 
			
		||||
int get_config_str(const struct config_node *cn, const char *path,
 | 
			
		||||
		   char **result);
 | 
			
		||||
 | 
			
		||||
unsigned maybe_config_section(const char *str, unsigned len);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -21,6 +21,8 @@
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_ARCHIVE_SUBDIR "archive"
 | 
			
		||||
#define DEFAULT_BACKUP_SUBDIR "backup"
 | 
			
		||||
#define DEFAULT_CACHE_SUBDIR "cache"
 | 
			
		||||
#define DEFAULT_CACHE_FILE_PREFIX ""
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_ARCHIVE_DAYS 30
 | 
			
		||||
#define DEFAULT_ARCHIVE_NUMBER 10
 | 
			
		||||
@@ -30,9 +32,18 @@
 | 
			
		||||
#define DEFAULT_PROC_DIR "/proc"
 | 
			
		||||
#define DEFAULT_SYSFS_SCAN 1
 | 
			
		||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
 | 
			
		||||
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
 | 
			
		||||
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
 | 
			
		||||
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
 | 
			
		||||
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
 | 
			
		||||
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_MIRRORLOG "disk"
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
@@ -52,6 +63,7 @@
 | 
			
		||||
#define DEFAULT_PVMETADATASIZE 255
 | 
			
		||||
#define DEFAULT_PVMETADATACOPIES 1
 | 
			
		||||
#define DEFAULT_LABELSECTOR UINT64_C(1)
 | 
			
		||||
#define DEFAULT_READ_AHEAD "auto"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_MSG_PREFIX "  "
 | 
			
		||||
#define DEFAULT_CMD_NAME 0
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -55,7 +55,8 @@ static uint32_t _shuffle(uint32_t k)
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct node **_lookup(struct node **c, uint32_t key, struct node **p)
 | 
			
		||||
static struct node **_lookup(struct node *const *c, uint32_t key,
 | 
			
		||||
			     struct node **p)
 | 
			
		||||
{
 | 
			
		||||
	*p = NULL;
 | 
			
		||||
	while (*c) {
 | 
			
		||||
@@ -70,10 +71,10 @@ static struct node **_lookup(struct node **c, uint32_t key, struct node **p)
 | 
			
		||||
			c = &(*c)->r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c;
 | 
			
		||||
	return (struct node **)c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *btree_lookup(struct btree *t, uint32_t k)
 | 
			
		||||
void *btree_lookup(const struct btree *t, uint32_t k)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t key = _shuffle(k);
 | 
			
		||||
	struct node *p, **c = _lookup(&t->root, key, &p);
 | 
			
		||||
@@ -102,19 +103,19 @@ int btree_insert(struct btree *t, uint32_t k, void *data)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *btree_get_data(struct btree_iter *it)
 | 
			
		||||
void *btree_get_data(const 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;
 | 
			
		||||
	return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct btree_iter *btree_first(struct btree *t)
 | 
			
		||||
struct btree_iter *btree_first(const struct btree *t)
 | 
			
		||||
{
 | 
			
		||||
	if (!t->root)
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -122,7 +123,7 @@ struct btree_iter *btree_first(struct btree *t)
 | 
			
		||||
	return (struct btree_iter *) _left(t->root);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct btree_iter *btree_next(struct btree_iter *it)
 | 
			
		||||
struct btree_iter *btree_next(const struct btree_iter *it)
 | 
			
		||||
{
 | 
			
		||||
	struct node *n = (struct node *) it;
 | 
			
		||||
	uint32_t k = n->key;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-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 General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -20,13 +20,13 @@ struct btree;
 | 
			
		||||
 | 
			
		||||
struct btree *btree_create(struct dm_pool *mem);
 | 
			
		||||
 | 
			
		||||
void *btree_lookup(struct btree *t, uint32_t k);
 | 
			
		||||
void *btree_lookup(const struct btree *t, uint32_t k);
 | 
			
		||||
int btree_insert(struct btree *t, uint32_t k, void *data);
 | 
			
		||||
 | 
			
		||||
struct btree_iter;
 | 
			
		||||
void *btree_get_data(struct btree_iter *it);
 | 
			
		||||
void *btree_get_data(const struct btree_iter *it);
 | 
			
		||||
 | 
			
		||||
struct btree_iter *btree_first(struct btree *t);
 | 
			
		||||
struct btree_iter *btree_next(struct btree_iter *it);
 | 
			
		||||
struct btree_iter *btree_first(const struct btree *t);
 | 
			
		||||
struct btree_iter *btree_next(const struct btree_iter *it);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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-2007 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"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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(const struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return head->n == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the first element of the list?
 | 
			
		||||
 */
 | 
			
		||||
int list_start(const struct list *head, const struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->p == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the last element of the list?
 | 
			
		||||
 */
 | 
			
		||||
int list_end(const struct list *head, const struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->n == head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return first element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_first(const struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return last element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
struct list *list_last(const 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(const struct list *head, const 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(const struct list *head, const 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,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -33,107 +33,61 @@ struct list {
 | 
			
		||||
 * The list head's next and previous pointers point back to itself.
 | 
			
		||||
 */
 | 
			
		||||
#define LIST_INIT(name)	struct list name = { &(name), &(name) }
 | 
			
		||||
static inline void list_init(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	head->n = head->p = head;
 | 
			
		||||
}
 | 
			
		||||
void list_init(struct list *head);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element before 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the end of the list.
 | 
			
		||||
 */
 | 
			
		||||
static inline void list_add(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
 | 
			
		||||
	elem->n = head;
 | 
			
		||||
	elem->p = head->p;
 | 
			
		||||
 | 
			
		||||
	head->p->n = elem;
 | 
			
		||||
	head->p = elem;
 | 
			
		||||
}
 | 
			
		||||
void list_add(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Insert an element after 'head'.
 | 
			
		||||
 * If 'head' is the list head, this adds an element to the front of the list.
 | 
			
		||||
 */
 | 
			
		||||
static inline void list_add_h(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	assert(head->n);
 | 
			
		||||
 | 
			
		||||
	elem->n = head->n;
 | 
			
		||||
	elem->p = head;
 | 
			
		||||
 | 
			
		||||
	head->n->p = elem;
 | 
			
		||||
	head->n = elem;
 | 
			
		||||
}
 | 
			
		||||
void list_add_h(struct list *head, struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Delete an element from its list.
 | 
			
		||||
 * Note that this doesn't change the element itself - it may still be safe
 | 
			
		||||
 * to follow its pointers.
 | 
			
		||||
 */
 | 
			
		||||
static inline void list_del(struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	elem->n->p = elem->p;
 | 
			
		||||
	elem->p->n = elem->n;
 | 
			
		||||
}
 | 
			
		||||
void list_del(struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is the list empty?
 | 
			
		||||
 */
 | 
			
		||||
static inline int list_empty(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return head->n == head;
 | 
			
		||||
}
 | 
			
		||||
int list_empty(const struct list *head);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the first element of the list?
 | 
			
		||||
 */
 | 
			
		||||
static inline int list_start(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->p == head;
 | 
			
		||||
}
 | 
			
		||||
int list_start(const struct list *head, const struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this the last element of the list?
 | 
			
		||||
 */
 | 
			
		||||
static inline int list_end(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return elem->n == head;
 | 
			
		||||
}
 | 
			
		||||
int list_end(const struct list *head, const struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return first element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
static inline struct list *list_first(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->n);
 | 
			
		||||
}
 | 
			
		||||
struct list *list_first(const struct list *head);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return last element of the list or NULL if empty
 | 
			
		||||
 */
 | 
			
		||||
static inline struct list *list_last(struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	return (list_empty(head) ? NULL : head->p);
 | 
			
		||||
}
 | 
			
		||||
struct list *list_last(const struct list *head);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the previous element of the list, or NULL if we've reached the start.
 | 
			
		||||
 */
 | 
			
		||||
static inline struct list *list_prev(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_start(head, elem) ? NULL : elem->p);
 | 
			
		||||
}
 | 
			
		||||
struct list *list_prev(const struct list *head, const struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the next element of the list, or NULL if we've reached the end.
 | 
			
		||||
 */
 | 
			
		||||
static inline struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
{
 | 
			
		||||
	return (list_end(head, elem) ? NULL : elem->n);
 | 
			
		||||
}
 | 
			
		||||
struct list *list_next(const struct list *head, const struct list *elem);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Given the address v of an instance of 'struct list' called 'head' 
 | 
			
		||||
@@ -244,15 +198,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
 | 
			
		||||
/*
 | 
			
		||||
 * Return the number of elements in a list by walking it.
 | 
			
		||||
 */
 | 
			
		||||
static inline unsigned int list_size(const struct list *head)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s = 0;
 | 
			
		||||
	const struct list *v;
 | 
			
		||||
 | 
			
		||||
	list_iterate(v, head)
 | 
			
		||||
	    s++;
 | 
			
		||||
 | 
			
		||||
	return s;
 | 
			
		||||
}
 | 
			
		||||
unsigned int list_size(const struct list *head);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
 | 
			
		||||
/* Define some portable printing types */
 | 
			
		||||
#define PRIsize_t "zu"
 | 
			
		||||
#define PRIptrdiff_t "td"
 | 
			
		||||
 | 
			
		||||
struct str_list {
 | 
			
		||||
	struct list list;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-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 General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -66,14 +66,15 @@ int str_list_del(struct list *sll, const char *str)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold)
 | 
			
		||||
int str_list_dup(struct dm_pool *mem, struct list *sllnew,
 | 
			
		||||
		 const struct list *sllold)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
	list_init(sllnew);
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(sl, sllold) {
 | 
			
		||||
		if (!str_list_add(mem, sllnew, strdup(sl->str))) {
 | 
			
		||||
		if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str))) {
 | 
			
		||||
			stack;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -85,7 +86,7 @@ int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold)
 | 
			
		||||
/*
 | 
			
		||||
 * Is item on list?
 | 
			
		||||
 */
 | 
			
		||||
int str_list_match_item(struct list *sll, const char *str)
 | 
			
		||||
int str_list_match_item(const struct list *sll, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
@@ -99,7 +100,7 @@ int str_list_match_item(struct list *sll, const char *str)
 | 
			
		||||
/*
 | 
			
		||||
 * Is at least one item on both lists?
 | 
			
		||||
 */
 | 
			
		||||
int str_list_match_list(struct list *sll, struct list *sll2)
 | 
			
		||||
int str_list_match_list(const struct list *sll, const struct list *sll2)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
@@ -113,7 +114,7 @@ int str_list_match_list(struct list *sll, struct list *sll2)
 | 
			
		||||
/*
 | 
			
		||||
 * Do both lists contain the same set of items?
 | 
			
		||||
 */
 | 
			
		||||
int str_list_lists_equal(struct list *sll, struct list *sll2)
 | 
			
		||||
int str_list_lists_equal(const struct list *sll, const struct list *sll2)
 | 
			
		||||
{
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-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 General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -19,9 +19,10 @@
 | 
			
		||||
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);
 | 
			
		||||
int str_list_match_item(const struct list *sll, const char *str);
 | 
			
		||||
int str_list_match_list(const struct list *sll, const struct list *sll2);
 | 
			
		||||
int str_list_lists_equal(const struct list *sll, const struct list *sll2);
 | 
			
		||||
int str_list_dup(struct dm_pool *mem, struct list *sllnew,
 | 
			
		||||
		 const struct list *sllold);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
#include "btree.h"
 | 
			
		||||
#include "filter.h"
 | 
			
		||||
#include "filter-persistent.h"
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/param.h>
 | 
			
		||||
@@ -38,6 +39,7 @@ static struct {
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	struct dm_hash_table *names;
 | 
			
		||||
	struct btree *devices;
 | 
			
		||||
	struct dm_regex *preferred_names_matcher;
 | 
			
		||||
 | 
			
		||||
	int has_scanned;
 | 
			
		||||
	struct list dirs;
 | 
			
		||||
@@ -129,15 +131,52 @@ static struct device *_dev_create(dev_t d)
 | 
			
		||||
	return dev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dev_set_preferred_name(struct str_list *sl, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * Don't interfere with ordering specified in config file.
 | 
			
		||||
	 */
 | 
			
		||||
	if (_cache.preferred_names_matcher)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	log_debug("%s: New preferred name", sl->str);
 | 
			
		||||
	list_del(&sl->list);
 | 
			
		||||
	list_add_h(&dev->aliases, &sl->list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return 1 if we prefer path1 else return 0 */
 | 
			
		||||
static int _compare_paths(const char *path0, const char *path1)
 | 
			
		||||
{
 | 
			
		||||
	int slash0 = 0, slash1 = 0;
 | 
			
		||||
	int m0, m1;
 | 
			
		||||
	const char *p;
 | 
			
		||||
	char p0[PATH_MAX], p1[PATH_MAX];
 | 
			
		||||
	char *s0, *s1;
 | 
			
		||||
	struct stat stat0, stat1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * FIXME Better to compare patterns one-at-a-time against all names.
 | 
			
		||||
	 */
 | 
			
		||||
	if (_cache.preferred_names_matcher) {
 | 
			
		||||
		m0 = dm_regex_match(_cache.preferred_names_matcher, path0);
 | 
			
		||||
		m1 = dm_regex_match(_cache.preferred_names_matcher, path1);
 | 
			
		||||
 | 
			
		||||
		if (m0 != m1) {
 | 
			
		||||
			if (m0 < 0)
 | 
			
		||||
				return 1;
 | 
			
		||||
			if (m1 < 0)
 | 
			
		||||
				return 0;
 | 
			
		||||
			if (m0 < m1)
 | 
			
		||||
				return 1;
 | 
			
		||||
			if (m1 < m0)
 | 
			
		||||
				return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Built-in rules.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/* Return the path with fewer slashes */
 | 
			
		||||
	for (p = path0; p++; p = (const char *) strchr(p, '/'))
 | 
			
		||||
		slash0++;
 | 
			
		||||
@@ -166,11 +205,11 @@ static int _compare_paths(const char *path0, const char *path1)
 | 
			
		||||
			*s1 = '\0';
 | 
			
		||||
		}
 | 
			
		||||
		if (lstat(p0, &stat0)) {
 | 
			
		||||
			log_sys_error("lstat", p0);
 | 
			
		||||
			log_sys_very_verbose("lstat", p0);
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
		if (lstat(p1, &stat1)) {
 | 
			
		||||
			log_sys_error("lstat", p1);
 | 
			
		||||
			log_sys_very_verbose("lstat", p1);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (S_ISLNK(stat0.st_mode) && !S_ISLNK(stat1.st_mode))
 | 
			
		||||
@@ -441,7 +480,65 @@ void dev_cache_scan(int do_scan)
 | 
			
		||||
		_full_scan(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_cache_init(void)
 | 
			
		||||
static int _init_preferred_names(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	const struct config_node *cn;
 | 
			
		||||
	struct config_value *v;
 | 
			
		||||
	struct dm_pool *scratch = NULL;
 | 
			
		||||
	char **regex;
 | 
			
		||||
	unsigned count = 0;
 | 
			
		||||
	int i, r = 0;
 | 
			
		||||
 | 
			
		||||
	_cache.preferred_names_matcher = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) ||
 | 
			
		||||
	    cn->v->type == CFG_EMPTY_ARRAY) {
 | 
			
		||||
		log_very_verbose("devices/preferred_names not found in config file: "
 | 
			
		||||
				 "using built-in preferences");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (v = cn->v; v; v = v->next) {
 | 
			
		||||
		if (v->type != CFG_STRING) {
 | 
			
		||||
			log_error("preferred_names patterns must be enclosed in quotes");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}       
 | 
			
		||||
 | 
			
		||||
		count++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(scratch = dm_pool_create("preferred device name matcher", 1024)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
 | 
			
		||||
		log_error("Failed to allocate preferred device name "
 | 
			
		||||
			  "pattern list.");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (v = cn->v, i = count - 1; v; v = v->next, i--) {
 | 
			
		||||
		if (!(regex[i] = dm_pool_strdup(scratch, v->v.str))) {
 | 
			
		||||
			log_error("Failed to allocate a preferred device name "
 | 
			
		||||
				  "pattern.");
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(_cache.preferred_names_matcher =
 | 
			
		||||
		dm_regex_create(_cache.mem,(const char **) regex, count))) {
 | 
			
		||||
		log_error("Preferred device name pattern matcher creation failed.");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	dm_pool_destroy(scratch);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_cache_init(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	_cache.names = NULL;
 | 
			
		||||
	_cache.has_scanned = 0;
 | 
			
		||||
@@ -466,6 +563,9 @@ int dev_cache_init(void)
 | 
			
		||||
	list_init(&_cache.dirs);
 | 
			
		||||
	list_init(&_cache.files);
 | 
			
		||||
 | 
			
		||||
	if (!_init_preferred_names(cmd))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
@@ -479,7 +579,7 @@ static void _check_closed(struct device *dev)
 | 
			
		||||
		log_err("Device '%s' has been left open.", dev_name(dev));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void _check_for_open_devices(void)
 | 
			
		||||
static void _check_for_open_devices(void)
 | 
			
		||||
{
 | 
			
		||||
	dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
 | 
			
		||||
}
 | 
			
		||||
@@ -489,6 +589,9 @@ void dev_cache_exit(void)
 | 
			
		||||
	if (_cache.names)
 | 
			
		||||
		_check_for_open_devices();
 | 
			
		||||
 | 
			
		||||
	if (_cache.preferred_names_matcher)
 | 
			
		||||
		_cache.preferred_names_matcher = NULL;
 | 
			
		||||
 | 
			
		||||
	if (_cache.mem) {
 | 
			
		||||
		dm_pool_destroy(_cache.mem);
 | 
			
		||||
		_cache.mem = NULL;
 | 
			
		||||
@@ -645,8 +748,7 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (dev_scan) {
 | 
			
		||||
	if (dev_scan && !trust_cache()) {
 | 
			
		||||
		/* Flag gets reset between each command */
 | 
			
		||||
		if (!full_scan_done())
 | 
			
		||||
			persistent_filter_wipe(f); /* Calls _full_scan(1) */
 | 
			
		||||
@@ -664,7 +766,7 @@ void dev_iter_destroy(struct dev_iter *iter)
 | 
			
		||||
	dm_free(iter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct device *_iter_next(struct dev_iter *iter)
 | 
			
		||||
static struct device *_iter_next(struct dev_iter *iter)
 | 
			
		||||
{
 | 
			
		||||
	struct device *d = btree_get_data(iter->current);
 | 
			
		||||
	iter->current = btree_next(iter->current);
 | 
			
		||||
@@ -682,3 +784,14 @@ struct device *dev_iter_get(struct dev_iter *iter)
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_fd(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *dev_name(const struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
 | 
			
		||||
	    "unknown device";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -30,7 +30,8 @@ struct dev_filter {
 | 
			
		||||
/*
 | 
			
		||||
 * The global device cache.
 | 
			
		||||
 */
 | 
			
		||||
int dev_cache_init(void);
 | 
			
		||||
struct cmd_context;
 | 
			
		||||
int dev_cache_init(struct cmd_context *cmd);
 | 
			
		||||
void dev_cache_exit(void);
 | 
			
		||||
 | 
			
		||||
/* Trigger(1) or avoid(0) a scan */
 | 
			
		||||
@@ -41,6 +42,8 @@ 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);
 | 
			
		||||
 | 
			
		||||
void dev_set_preferred_name(struct str_list *sl, struct device *dev);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Object for iterating through the cache.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -176,7 +176,7 @@ static int _aligned_io(struct device_area *where, void *buffer,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!block_size)
 | 
			
		||||
		block_size = getpagesize();
 | 
			
		||||
		block_size = lvm_getpagesize();
 | 
			
		||||
 | 
			
		||||
	_widen_region(block_size, where, &widened);
 | 
			
		||||
 | 
			
		||||
@@ -292,11 +292,14 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
 | 
			
		||||
 | 
			
		||||
	if (ioctl(fd, BLKSSZGET, &s) < 0) {
 | 
			
		||||
		log_sys_error("ioctl BLKSSZGET", name);
 | 
			
		||||
		close(fd);
 | 
			
		||||
		if (close(fd))
 | 
			
		||||
			log_sys_error("close", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(fd);
 | 
			
		||||
	if (close(fd))
 | 
			
		||||
		log_sys_error("close", name);
 | 
			
		||||
 | 
			
		||||
	*size = (uint32_t) s;
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
 | 
			
		||||
@@ -356,10 +359,15 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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->flags & DEV_REGULAR)) {
 | 
			
		||||
		if (stat(name, &buf) < 0) {
 | 
			
		||||
			log_sys_error("%s: stat failed", name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (buf.st_rdev != dev->dev) {
 | 
			
		||||
			log_error("%s: device changed", name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef O_DIRECT_SUPPORT
 | 
			
		||||
@@ -418,7 +426,6 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
 | 
			
		||||
	    ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
 | 
			
		||||
		log_error("%s: fstat failed: Has device name changed?", name);
 | 
			
		||||
		dev_close_immediate(dev);
 | 
			
		||||
		dev->open_count = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -509,11 +516,9 @@ static int _dev_close(struct device *dev, int immediate)
 | 
			
		||||
	if (dev->open_count > 0)
 | 
			
		||||
		dev->open_count--;
 | 
			
		||||
 | 
			
		||||
	if (immediate && dev->open_count) {
 | 
			
		||||
	if (immediate && dev->open_count)
 | 
			
		||||
		log_debug("%s: Immediate close attempt while still referenced",
 | 
			
		||||
			  dev_name(dev));
 | 
			
		||||
		dev->open_count = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Close unless device is known to belong to a locked VG */
 | 
			
		||||
	if (immediate ||
 | 
			
		||||
@@ -564,6 +569,35 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
	return _aligned_io(&where, buffer, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Read from 'dev' into 'buf', possibly in 2 distinct regions, denoted
 | 
			
		||||
 * by (offset,len) and (offset2,len2).  Thus, the total size of
 | 
			
		||||
 * 'buf' should be len+len2.
 | 
			
		||||
 */
 | 
			
		||||
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
 | 
			
		||||
		      uint64_t offset2, size_t len2, void *buf)
 | 
			
		||||
{
 | 
			
		||||
	if (!dev_read(dev, offset, len, buf)) {
 | 
			
		||||
		log_error("Read from %s failed", dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The second region is optional, and allows for
 | 
			
		||||
	 * a circular buffer on the device.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!len2)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!dev_read(dev, offset2, len2, buf + len)) {
 | 
			
		||||
		log_error("Circular read from %s failed",
 | 
			
		||||
			  dev_name(dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
 | 
			
		||||
 *       But fails if concurrent processes writing
 | 
			
		||||
 */
 | 
			
		||||
@@ -605,10 +639,10 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
 | 
			
		||||
	return _aligned_io(&where, buffer, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
 | 
			
		||||
{
 | 
			
		||||
	size_t s;
 | 
			
		||||
	char buffer[4096];
 | 
			
		||||
	char buffer[4096] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -623,7 +657,7 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
 | 
			
		||||
			  " sectors", dev_name(dev), offset >> SECTOR_SHIFT,
 | 
			
		||||
			  len >> SECTOR_SHIFT);
 | 
			
		||||
 | 
			
		||||
	memset(buffer, 0, sizeof(buffer));
 | 
			
		||||
	memset(buffer, value, sizeof(buffer));
 | 
			
		||||
	while (1) {
 | 
			
		||||
		s = len > sizeof(buffer) ? sizeof(buffer) : len;
 | 
			
		||||
		if (!dev_write(dev, offset, s, buffer))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Luca Berra
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
@@ -17,25 +17,65 @@
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "xlate.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_BYTES (64 * 1024ULL)
 | 
			
		||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
 | 
			
		||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
 | 
			
		||||
				- MD_RESERVED_SECTORS)
 | 
			
		||||
 | 
			
		||||
static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t md_magic;
 | 
			
		||||
 | 
			
		||||
	/* Version 1 is little endian; version 0.90.0 is machine endian */
 | 
			
		||||
	if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
 | 
			
		||||
	    ((md_magic == xlate32(MD_SB_MAGIC)) ||
 | 
			
		||||
	     (md_magic == MD_SB_MAGIC)))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Calculate the position of the superblock.
 | 
			
		||||
 * It is always aligned to a 4K boundary and
 | 
			
		||||
 * depending on minor_version, it can be:
 | 
			
		||||
 * 0: At least 8K, but less than 12K, from end of device
 | 
			
		||||
 * 1: At start of device
 | 
			
		||||
 * 2: 4K from start of device.
 | 
			
		||||
 */
 | 
			
		||||
static uint64_t _v1_sb_offset(uint64_t size, unsigned minor_version)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t sb_offset;
 | 
			
		||||
 | 
			
		||||
	switch(minor_version) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		sb_offset = (size - 8 * 2) & ~(4 * 2 - 1ULL);
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:
 | 
			
		||||
		sb_offset = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		sb_offset = 4 * 2;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	sb_offset <<= SECTOR_SHIFT;
 | 
			
		||||
 | 
			
		||||
	return sb_offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns -1 on error
 | 
			
		||||
 */
 | 
			
		||||
int dev_is_md(struct device *dev, uint64_t *sb)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
 | 
			
		||||
	int ret = 1;
 | 
			
		||||
	unsigned minor = 0;
 | 
			
		||||
	uint64_t size, sb_offset;
 | 
			
		||||
	uint32_t md_magic;
 | 
			
		||||
 | 
			
		||||
	if (!dev_get_size(dev, &size)) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -50,20 +90,37 @@ int dev_is_md(struct device *dev, uint64_t *sb)
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
	/* Version 0.90.0 */
 | 
			
		||||
	sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
 | 
			
		||||
	if (_dev_has_md_magic(dev, sb_offset))
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	/* Version 1, try v1.0 -> v1.2 */
 | 
			
		||||
	do {
 | 
			
		||||
		sb_offset = _v1_sb_offset(size, minor);
 | 
			
		||||
		if (_dev_has_md_magic(dev, sb_offset))
 | 
			
		||||
			goto out;
 | 
			
		||||
	} while (++minor <= 2);
 | 
			
		||||
 | 
			
		||||
	ret = 0;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
	if (ret && sb)
 | 
			
		||||
		*sb = sb_offset;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
int dev_is_md(struct device *dev __attribute((unused)),
 | 
			
		||||
	      uint64_t *sb __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -53,7 +53,7 @@ static int _has_partition_table(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	unsigned p;
 | 
			
		||||
	uint8_t buf[SECTOR_SIZE];
 | 
			
		||||
	uint16_t buf[SECTOR_SIZE/sizeof(uint16_t)];
 | 
			
		||||
	uint16_t *part_magic;
 | 
			
		||||
	struct partition *part;
 | 
			
		||||
 | 
			
		||||
@@ -62,7 +62,7 @@ static int _has_partition_table(struct device *dev)
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dev_read(dev, 0, sizeof(buf), &buf)) {
 | 
			
		||||
	if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -70,9 +70,9 @@ static int _has_partition_table(struct device *dev)
 | 
			
		||||
	/* FIXME Check for other types of partition table too */
 | 
			
		||||
 | 
			
		||||
	/* Check for msdos partition table */
 | 
			
		||||
	part_magic = (uint16_t *)(buf + PART_MAGIC_OFFSET);
 | 
			
		||||
	part_magic = buf + PART_MAGIC_OFFSET/sizeof(buf[0]);
 | 
			
		||||
	if ((*part_magic == xlate16(PART_MAGIC))) {
 | 
			
		||||
		part = (struct partition *) (buf + PART_OFFSET);
 | 
			
		||||
		part = (struct partition *) (buf + PART_OFFSET/sizeof(buf[0]));
 | 
			
		||||
		for (p = 0; p < 4; p++, part++) {
 | 
			
		||||
			/* Table is invalid if boot indicator not 0 or 0x80 */
 | 
			
		||||
			if ((part->boot_ind & 0x7f)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -74,26 +74,20 @@ int dev_close_immediate(struct device *dev);
 | 
			
		||||
void dev_close_all(void);
 | 
			
		||||
int dev_test_excl(struct device *dev);
 | 
			
		||||
 | 
			
		||||
static inline int dev_fd(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->fd;
 | 
			
		||||
}
 | 
			
		||||
int dev_fd(struct device *dev);
 | 
			
		||||
const char *dev_name(const struct device *dev);
 | 
			
		||||
 | 
			
		||||
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
 | 
			
		||||
		      uint64_t offset2, size_t len2, void *buf);
 | 
			
		||||
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
 | 
			
		||||
int dev_append(struct device *dev, size_t len, void *buffer);
 | 
			
		||||
int dev_zero(struct device *dev, uint64_t offset, size_t len);
 | 
			
		||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);
 | 
			
		||||
void dev_flush(struct device *dev);
 | 
			
		||||
 | 
			
		||||
struct device *dev_create_file(const char *filename, struct device *dev,
 | 
			
		||||
			       struct str_list *alias, int use_malloc);
 | 
			
		||||
 | 
			
		||||
static inline const char *dev_name(const struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
 | 
			
		||||
	    "unknown device";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return a valid device name from the alias list; NULL otherwise */
 | 
			
		||||
const char *dev_name_confirmed(struct device *dev, int quiet);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -22,12 +22,15 @@
 | 
			
		||||
 | 
			
		||||
#define SIZE_BUF 128
 | 
			
		||||
 | 
			
		||||
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
	alloc_policy_t alloc;
 | 
			
		||||
	const char *str;
 | 
			
		||||
} _policies[] = {
 | 
			
		||||
	{
 | 
			
		||||
	ALLOC_CONTIGUOUS, "contiguous"}, {
 | 
			
		||||
	ALLOC_CLING, "cling"}, {
 | 
			
		||||
	ALLOC_NORMAL, "normal"}, {
 | 
			
		||||
	ALLOC_ANYWHERE, "anywhere"}, {
 | 
			
		||||
	ALLOC_INHERIT, "inherit"}
 | 
			
		||||
@@ -79,6 +82,12 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
 | 
			
		||||
	case 't':
 | 
			
		||||
		v *= KILO * KILO * KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
	case 'p':
 | 
			
		||||
		v *= KILO * KILO * KILO * KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
	case 'e':
 | 
			
		||||
		v *= KILO * KILO * KILO * KILO * KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
#undef KILO
 | 
			
		||||
#define KILO UINT64_C(1000)
 | 
			
		||||
	case 'K':
 | 
			
		||||
@@ -93,6 +102,12 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
 | 
			
		||||
	case 'T':
 | 
			
		||||
		v *= KILO * KILO * KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
	case 'P':
 | 
			
		||||
		v *= KILO * KILO * KILO * KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
	case 'E':
 | 
			
		||||
		v *= KILO * KILO * KILO * KILO * KILO * KILO;
 | 
			
		||||
		break;
 | 
			
		||||
#undef KILO
 | 
			
		||||
	default:
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -132,7 +147,8 @@ alloc_policy_t get_alloc_from_string(const char *str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Size supplied in sectors */
 | 
			
		||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
static const char *_display_size(const struct cmd_context *cmd,
 | 
			
		||||
				 uint64_t size, size_len_t sl)
 | 
			
		||||
{
 | 
			
		||||
	int s;
 | 
			
		||||
	int suffix = 1, precision;
 | 
			
		||||
@@ -140,6 +156,8 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
	uint64_t units = UINT64_C(1024);
 | 
			
		||||
	char *size_buf = NULL;
 | 
			
		||||
	const char *size_str[][3] = {
 | 
			
		||||
		{" Exabyte", " EB", "E"},
 | 
			
		||||
		{" Petabyte", " PB", "P"},
 | 
			
		||||
		{" Terabyte", " TB", "T"},
 | 
			
		||||
		{" Gigabyte", " GB", "G"},
 | 
			
		||||
		{" Megabyte", " MB", "M"},
 | 
			
		||||
@@ -158,7 +176,7 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
 | 
			
		||||
	suffix = cmd->current_settings.suffix;
 | 
			
		||||
 | 
			
		||||
	for (s = 0; s < 8; s++)
 | 
			
		||||
	for (s = 0; s < 10; s++)
 | 
			
		||||
		if (toupper((int) cmd->current_settings.unit_type) ==
 | 
			
		||||
		    *size_str[s][2])
 | 
			
		||||
			break;
 | 
			
		||||
@@ -168,17 +186,17 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
		return size_buf;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (s < 8) {
 | 
			
		||||
	size *= UINT64_C(512);
 | 
			
		||||
 | 
			
		||||
	if (s < 10)
 | 
			
		||||
		byte = cmd->current_settings.unit_factor;
 | 
			
		||||
		size *= UINT64_C(512);
 | 
			
		||||
	} else {
 | 
			
		||||
		size /= 2;
 | 
			
		||||
	else {
 | 
			
		||||
		suffix = 1;
 | 
			
		||||
		if (cmd->current_settings.unit_type == 'H')
 | 
			
		||||
			units = UINT64_C(1000);
 | 
			
		||||
		else
 | 
			
		||||
			units = UINT64_C(1024);
 | 
			
		||||
		byte = units * units * units;
 | 
			
		||||
		byte = units * units * units * units * units * units;
 | 
			
		||||
		s = 0;
 | 
			
		||||
		while (size_str[s] && size < byte)
 | 
			
		||||
			s++, byte /= units;
 | 
			
		||||
@@ -200,9 +218,24 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
 | 
			
		||||
	return size_buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pvdisplay_colons(struct physical_volume *pv)
 | 
			
		||||
const char *display_size_long(const struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	return _display_size(cmd, size, SIZE_LONG);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size_units(const struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _display_size(cmd, size, SIZE_UNIT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *display_size(const struct cmd_context *cmd, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	return _display_size(cmd, size, SIZE_SHORT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pvdisplay_colons(const struct physical_volume *pv)
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (!pv)
 | 
			
		||||
		return;
 | 
			
		||||
@@ -213,7 +246,7 @@ void pvdisplay_colons(struct physical_volume *pv)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print("%s:%s:%" PRIu64 ":-1:%u:%u:-1:%" PRIu32 ":%u:%u:%u:%s",
 | 
			
		||||
		  dev_name(pv->dev), pv->vg_name, pv->size,
 | 
			
		||||
		  pv_dev_name(pv), pv->vg_name, pv->size,
 | 
			
		||||
		  /* FIXME pv->pv_number, Derive or remove? */
 | 
			
		||||
		  pv->status,	/* FIXME Support old or new format here? */
 | 
			
		||||
		  pv->status & ALLOCATABLE_PV,	/* FIXME remove? */
 | 
			
		||||
@@ -226,14 +259,43 @@ void pvdisplay_colons(struct physical_volume *pv)
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Include label fields */
 | 
			
		||||
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
		    void *handle)
 | 
			
		||||
void pvdisplay_segments(const struct physical_volume *pv)
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	const struct pv_segment *pvseg;
 | 
			
		||||
 | 
			
		||||
	if (pv->pe_size)
 | 
			
		||||
		log_print("--- Physical Segments ---");
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(pvseg, &pv->segments) {
 | 
			
		||||
		log_print("Physical extent %u to %u:",
 | 
			
		||||
			  pvseg->pe, pvseg->pe + pvseg->len - 1);
 | 
			
		||||
 | 
			
		||||
		if (pvseg->lvseg) {
 | 
			
		||||
			log_print("  Logical volume\t%s%s/%s",
 | 
			
		||||
				  pvseg->lvseg->lv->vg->cmd->dev_dir,
 | 
			
		||||
				  pvseg->lvseg->lv->vg->name,
 | 
			
		||||
				  pvseg->lvseg->lv->name);
 | 
			
		||||
			log_print("  Logical extents\t%d to %d",
 | 
			
		||||
				  pvseg->lvseg->le, pvseg->lvseg->le +
 | 
			
		||||
				  pvseg->lvseg->len - 1);
 | 
			
		||||
		} else
 | 
			
		||||
			log_print("  FREE");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print(" ");
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME Include label fields */
 | 
			
		||||
void pvdisplay_full(const struct cmd_context *cmd,
 | 
			
		||||
		    const struct physical_volume *pv,
 | 
			
		||||
		    void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64] __attribute((aligned(8)));
 | 
			
		||||
	const char *size;
 | 
			
		||||
 | 
			
		||||
	uint32_t pe_free;
 | 
			
		||||
	uint64_t data_size, pvsize, unusable;
 | 
			
		||||
 | 
			
		||||
	if (!pv)
 | 
			
		||||
		return;
 | 
			
		||||
@@ -244,24 +306,24 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
 | 
			
		||||
	log_print("PV Name               %s", dev_name(pv->dev));
 | 
			
		||||
	log_print("PV Name               %s", pv_dev_name(pv));
 | 
			
		||||
	log_print("VG Name               %s%s", pv->vg_name,
 | 
			
		||||
		  pv->status & EXPORTED_VG ? " (exported)" : "");
 | 
			
		||||
 | 
			
		||||
	size = display_size(cmd, (uint64_t) pv->size, SIZE_SHORT);
 | 
			
		||||
	if (pv->pe_size && pv->pe_count) {
 | 
			
		||||
	data_size = (uint64_t) pv->pe_count * pv->pe_size;
 | 
			
		||||
	if (pv->size > data_size + pv->pe_start) {
 | 
			
		||||
		pvsize = pv->size;
 | 
			
		||||
		unusable = pvsize - data_size;
 | 
			
		||||
	} else {
 | 
			
		||||
		pvsize = data_size + pv->pe_start;
 | 
			
		||||
		unusable = pvsize - pv->size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/******** FIXME display LVM on-disk data size
 | 
			
		||||
		size2 = display_size(pv->size, SIZE_SHORT);
 | 
			
		||||
********/
 | 
			
		||||
 | 
			
		||||
		log_print("PV Size               %s" " / not usable %s",	/*  [LVM: %s]", */
 | 
			
		||||
			  size,
 | 
			
		||||
			  display_size(cmd, (pv->size -
 | 
			
		||||
				       (uint64_t) pv->pe_count * pv->pe_size),
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
 | 
			
		||||
	} else
 | 
			
		||||
	size = display_size(cmd, pvsize);
 | 
			
		||||
	if (data_size)
 | 
			
		||||
		log_print("PV Size               %s / not usable %s",	/*  [LVM: %s]", */
 | 
			
		||||
			  size, display_size(cmd, unusable));
 | 
			
		||||
	else
 | 
			
		||||
		log_print("PV Size               %s", size);
 | 
			
		||||
 | 
			
		||||
	/* PV number not part of LVM2 design
 | 
			
		||||
@@ -288,10 +350,12 @@ 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(const struct cmd_context *cmd __attribute((unused)),
 | 
			
		||||
		    const struct volume_group *vg __attribute((unused)),
 | 
			
		||||
		    const struct physical_volume *pv,
 | 
			
		||||
		    void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	char uuid[64] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (!pv)
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -301,7 +365,7 @@ int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print("PV Name               %s     ", dev_name(pv->dev));
 | 
			
		||||
	log_print("PV Name               %s     ", pv_dev_name(pv));
 | 
			
		||||
	/* FIXME  pv->pv_number); */
 | 
			
		||||
	log_print("PV UUID               %s", *uuid ? uuid : "none");
 | 
			
		||||
	log_print("PV Status             %sallocatable",
 | 
			
		||||
@@ -313,11 +377,11 @@ int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvdisplay_colons(struct logical_volume *lv)
 | 
			
		||||
void lvdisplay_colons(const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	int inkernel;
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	inkernel = lv_info(lv->vg->cmd, lv, &info, 1) && info.exists;
 | 
			
		||||
	inkernel = lv_info(lv->vg->cmd, lv, &info, 1, 0) && info.exists;
 | 
			
		||||
 | 
			
		||||
	log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
 | 
			
		||||
		  lv->vg->cmd->dev_dir,
 | 
			
		||||
@@ -333,12 +397,13 @@ void lvdisplay_colons(struct logical_volume *lv)
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		   void *handle)
 | 
			
		||||
int lvdisplay_full(struct cmd_context *cmd,
 | 
			
		||||
		   const struct logical_volume *lv,
 | 
			
		||||
		   void *handle __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct lvinfo info;
 | 
			
		||||
	int inkernel, snap_active = 0;
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	char uuid[64] __attribute((aligned(8)));
 | 
			
		||||
	struct lv_segment *snap_seg = NULL;
 | 
			
		||||
	float snap_percent;	/* fused, fsize; */
 | 
			
		||||
 | 
			
		||||
@@ -347,7 +412,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inkernel = lv_info(cmd, lv, &info, 1) && info.exists;
 | 
			
		||||
	inkernel = lv_info(cmd, lv, &info, 1, 1) && info.exists;
 | 
			
		||||
 | 
			
		||||
	log_print("--- Logical volume ---");
 | 
			
		||||
 | 
			
		||||
@@ -404,23 +469,21 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
 | 
			
		||||
	log_print("LV Size                %s",
 | 
			
		||||
		  display_size(cmd,
 | 
			
		||||
			       snap_seg ? snap_seg->origin->size : lv->size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       snap_seg ? snap_seg->origin->size : lv->size));
 | 
			
		||||
 | 
			
		||||
	log_print("Current LE             %u",
 | 
			
		||||
		  snap_seg ? snap_seg->origin->le_count : lv->le_count);
 | 
			
		||||
 | 
			
		||||
	if (snap_seg) {
 | 
			
		||||
		log_print("COW-table size         %s",
 | 
			
		||||
			  display_size(cmd, (uint64_t) lv->size, SIZE_SHORT));
 | 
			
		||||
			  display_size(cmd, (uint64_t) lv->size));
 | 
			
		||||
		log_print("COW-table LE           %u", lv->le_count);
 | 
			
		||||
 | 
			
		||||
		if (snap_active)
 | 
			
		||||
			log_print("Allocated to snapshot  %.2f%% ", snap_percent);	
 | 
			
		||||
 | 
			
		||||
		log_print("Snapshot chunk size    %s",
 | 
			
		||||
			  display_size(cmd, (uint64_t) snap_seg->chunk_size,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(cmd, (uint64_t) snap_seg->chunk_size));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_print("Segments               %u", list_size(&lv->segments));
 | 
			
		||||
@@ -430,7 +493,15 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
***********/
 | 
			
		||||
 | 
			
		||||
	log_print("Allocation             %s", get_alloc_string(lv->alloc));
 | 
			
		||||
	log_print("Read ahead sectors     %u", lv->read_ahead);
 | 
			
		||||
	if (lv->read_ahead == DM_READ_AHEAD_AUTO)
 | 
			
		||||
		log_print("Read ahead sectors     auto");
 | 
			
		||||
	else if (lv->read_ahead == DM_READ_AHEAD_NONE)
 | 
			
		||||
		log_print("Read ahead sectors     0");
 | 
			
		||||
	else
 | 
			
		||||
		log_print("Read ahead sectors     %u", lv->read_ahead);
 | 
			
		||||
 | 
			
		||||
	if (inkernel && lv->read_ahead != info.read_ahead)
 | 
			
		||||
		log_print("- currently set to     %u", info.read_ahead);
 | 
			
		||||
 | 
			
		||||
	if (lv->status & FIXED_MINOR) {
 | 
			
		||||
		if (lv->major >= 0)
 | 
			
		||||
@@ -454,7 +525,7 @@ void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
 | 
			
		||||
		/* FIXME Re-check the conditions for 'Missing' */
 | 
			
		||||
		log_print("%sPhysical volume\t%s", pre,
 | 
			
		||||
			  seg_pv(seg, s) ?
 | 
			
		||||
			  dev_name(seg_dev(seg, s)) :
 | 
			
		||||
			  pv_dev_name(seg_pv(seg, s)) :
 | 
			
		||||
			    "Missing");
 | 
			
		||||
 | 
			
		||||
		if (seg_pv(seg, s))
 | 
			
		||||
@@ -477,9 +548,9 @@ void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lvdisplay_segments(struct logical_volume *lv)
 | 
			
		||||
int lvdisplay_segments(const struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	const struct lv_segment *seg;
 | 
			
		||||
 | 
			
		||||
	log_print("--- Segments ---");
 | 
			
		||||
 | 
			
		||||
@@ -497,16 +568,16 @@ int lvdisplay_segments(struct logical_volume *lv)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vgdisplay_extents(struct volume_group *vg)
 | 
			
		||||
void vgdisplay_extents(const struct volume_group *vg __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
void vgdisplay_full(const struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t access;
 | 
			
		||||
	uint32_t active_pvs;
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	char uuid[64] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (vg->status & PARTIAL_VG)
 | 
			
		||||
		active_pvs = list_size(&vg->pvs);
 | 
			
		||||
@@ -544,7 +615,7 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
	log_print("Open LV               %u", lvs_in_vg_opened(vg));
 | 
			
		||||
/****** FIXME Max LV Size
 | 
			
		||||
      log_print ( "MAX LV Size           %s",
 | 
			
		||||
               ( s1 = display_size ( LVM_LV_SIZE_MAX(vg), SIZE_SHORT)));
 | 
			
		||||
               ( s1 = display_size ( LVM_LV_SIZE_MAX(vg))));
 | 
			
		||||
      free ( s1);
 | 
			
		||||
*********/
 | 
			
		||||
	log_print("Max PV                %u", vg->max_pv);
 | 
			
		||||
@@ -553,12 +624,10 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	log_print("VG Size               %s",
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	log_print("PE Size               %s",
 | 
			
		||||
		  display_size(vg->cmd, (uint64_t) vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
		  display_size(vg->cmd, (uint64_t) vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	log_print("Total PE              %u", vg->extent_count);
 | 
			
		||||
 | 
			
		||||
@@ -566,12 +635,11 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
		  vg->extent_count - vg->free_count,
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       ((uint64_t) vg->extent_count - vg->free_count) *
 | 
			
		||||
			       vg->extent_size, SIZE_SHORT));
 | 
			
		||||
			       vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	log_print("Free  PE / Size       %u / %s", vg->free_count,
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size));
 | 
			
		||||
 | 
			
		||||
	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -584,11 +652,11 @@ void vgdisplay_full(struct volume_group *vg)
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vgdisplay_colons(struct volume_group *vg)
 | 
			
		||||
void vgdisplay_colons(const struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t active_pvs;
 | 
			
		||||
	const char *access;
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	char uuid[64] __attribute((aligned(8)));
 | 
			
		||||
 | 
			
		||||
	if (vg->status & PARTIAL_VG)
 | 
			
		||||
		active_pvs = list_size(&vg->pvs);
 | 
			
		||||
@@ -636,38 +704,66 @@ void vgdisplay_colons(struct volume_group *vg)
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vgdisplay_short(struct volume_group *vg)
 | 
			
		||||
void vgdisplay_short(const struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
 | 
			
		||||
/********* FIXME if "open" print "/used" else print "/idle"???  ******/
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT),
 | 
			
		||||
			       (uint64_t) vg->extent_count * vg->extent_size),
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       ((uint64_t) vg->extent_count -
 | 
			
		||||
				vg->free_count) * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT),
 | 
			
		||||
				vg->free_count) * vg->extent_size),
 | 
			
		||||
		  display_size(vg->cmd,
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size,
 | 
			
		||||
			       SIZE_SHORT));
 | 
			
		||||
			       (uint64_t) vg->free_count * vg->extent_size));
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void display_formats(struct cmd_context *cmd)
 | 
			
		||||
void display_formats(const struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct format_type *fmt;
 | 
			
		||||
	const struct format_type *fmt;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(fmt, &cmd->formats) {
 | 
			
		||||
		log_print("%s", fmt->name);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void display_segtypes(struct cmd_context *cmd)
 | 
			
		||||
void display_segtypes(const struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct segment_type *segtype;
 | 
			
		||||
	const struct segment_type *segtype;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(segtype, &cmd->segtypes) {
 | 
			
		||||
		log_print("%s", segtype->name);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char yes_no_prompt(const char *prompt, ...)
 | 
			
		||||
{
 | 
			
		||||
	int c = 0, ret = 0;
 | 
			
		||||
	va_list ap;
 | 
			
		||||
 | 
			
		||||
	sigint_allow();
 | 
			
		||||
	do {
 | 
			
		||||
		if (c == '\n' || !c) {
 | 
			
		||||
			va_start(ap, prompt);
 | 
			
		||||
			vprintf(prompt, ap);
 | 
			
		||||
			va_end(ap);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((c = getchar()) == EOF) {
 | 
			
		||||
			ret = 'n';
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		c = tolower(c);
 | 
			
		||||
		if ((c == 'y') || (c == 'n'))
 | 
			
		||||
			ret = c;
 | 
			
		||||
	} while (!ret || c != '\n');
 | 
			
		||||
 | 
			
		||||
	sigint_restore();
 | 
			
		||||
 | 
			
		||||
	if (c != '\n')
 | 
			
		||||
		printf("\n");
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -16,37 +16,42 @@
 | 
			
		||||
#ifndef _LVM_DISPLAY_H
 | 
			
		||||
#define _LVM_DISPLAY_H
 | 
			
		||||
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "metadata-exported.h"
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
 | 
			
		||||
#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(const struct cmd_context *cmd, uint64_t size);
 | 
			
		||||
const char *display_size_long(const struct cmd_context *cmd, uint64_t size);
 | 
			
		||||
const char *display_size_units(const 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,
 | 
			
		||||
void pvdisplay_colons(const struct physical_volume *pv);
 | 
			
		||||
void pvdisplay_segments(const struct physical_volume *pv);
 | 
			
		||||
void pvdisplay_full(const struct cmd_context *cmd,
 | 
			
		||||
		    const struct physical_volume *pv,
 | 
			
		||||
		    void *handle);
 | 
			
		||||
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
		    struct physical_volume *pv, void *handle);
 | 
			
		||||
int pvdisplay_short(const struct cmd_context *cmd,
 | 
			
		||||
		    const struct volume_group *vg,
 | 
			
		||||
		    const struct physical_volume *pv, void *handle);
 | 
			
		||||
 | 
			
		||||
void lvdisplay_colons(struct logical_volume *lv);
 | 
			
		||||
int lvdisplay_segments(struct logical_volume *lv);
 | 
			
		||||
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
void lvdisplay_colons(const struct logical_volume *lv);
 | 
			
		||||
int lvdisplay_segments(const struct logical_volume *lv);
 | 
			
		||||
int lvdisplay_full(struct cmd_context *cmd, const struct logical_volume *lv,
 | 
			
		||||
		   void *handle);
 | 
			
		||||
 | 
			
		||||
void vgdisplay_extents(struct volume_group *vg);
 | 
			
		||||
void vgdisplay_full(struct volume_group *vg);
 | 
			
		||||
void vgdisplay_colons(struct volume_group *vg);
 | 
			
		||||
void vgdisplay_short(struct volume_group *vg);
 | 
			
		||||
void vgdisplay_extents(const struct volume_group *vg);
 | 
			
		||||
void vgdisplay_full(const struct volume_group *vg);
 | 
			
		||||
void vgdisplay_colons(const struct volume_group *vg);
 | 
			
		||||
void vgdisplay_short(const struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void display_formats(struct cmd_context *cmd);
 | 
			
		||||
void display_segtypes(struct cmd_context *cmd);
 | 
			
		||||
void display_formats(const struct cmd_context *cmd);
 | 
			
		||||
void display_segtypes(const struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Allocation policy display conversion routines.
 | 
			
		||||
@@ -54,4 +59,6 @@ void display_segtypes(struct cmd_context *cmd);
 | 
			
		||||
const char *get_alloc_string(alloc_policy_t alloc);
 | 
			
		||||
alloc_policy_t get_alloc_from_string(const char *str);
 | 
			
		||||
 | 
			
		||||
char yes_no_prompt(const char *prompt, ...);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -23,13 +23,15 @@
 | 
			
		||||
#include "targets.h"
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "str_list.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
static const char *_name(const struct lv_segment *seg)
 | 
			
		||||
static const char *_errseg_name(const struct lv_segment *seg)
 | 
			
		||||
{
 | 
			
		||||
	return seg->segtype->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 | 
			
		||||
static int _errseg_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 | 
			
		||||
{
 | 
			
		||||
	seg1->len += seg2->len;
 | 
			
		||||
	seg1->area_len += seg2->area_len;
 | 
			
		||||
@@ -38,43 +40,58 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
 | 
			
		||||
				struct config_tree *cft, void **target_state,
 | 
			
		||||
				struct lv_segment *seg,
 | 
			
		||||
static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
 | 
			
		||||
				struct dm_pool *mem __attribute((unused)),
 | 
			
		||||
				struct cmd_context *cmd __attribute((unused)),
 | 
			
		||||
				void **target_state __attribute((unused)),
 | 
			
		||||
				struct lv_segment *seg __attribute((unused)),
 | 
			
		||||
				struct dm_tree_node *node, uint64_t len,
 | 
			
		||||
				uint32_t *pvmove_mirror_count)
 | 
			
		||||
				uint32_t *pvmove_mirror_count __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return dm_tree_node_add_error_target(node, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _target_present(void)
 | 
			
		||||
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	static int checked = 0;
 | 
			
		||||
	static int present = 0;
 | 
			
		||||
	static int _errseg_checked = 0;
 | 
			
		||||
	static int _errseg_present = 0;
 | 
			
		||||
 | 
			
		||||
	/* Reported truncated in older kernels */
 | 
			
		||||
	if (!checked &&
 | 
			
		||||
	if (!_errseg_checked &&
 | 
			
		||||
	    (target_present("error", 0) || target_present("erro", 0)))
 | 
			
		||||
		present = 1;
 | 
			
		||||
		_errseg_present = 1;
 | 
			
		||||
 | 
			
		||||
	checked = 1;
 | 
			
		||||
	return present;
 | 
			
		||||
	_errseg_checked = 1;
 | 
			
		||||
	return _errseg_present;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void _destroy(const struct segment_type *segtype)
 | 
			
		||||
static int _errseg_modules_needed(struct dm_pool *mem,
 | 
			
		||||
				  const struct lv_segment *seg __attribute((unused)),
 | 
			
		||||
				  struct list *modules)
 | 
			
		||||
{
 | 
			
		||||
	dm_free((void *) segtype);
 | 
			
		||||
	if (!str_list_add(mem, modules, "error")) {
 | 
			
		||||
		log_error("error module string list allocation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
static void _errseg_destroy(const struct segment_type *segtype)
 | 
			
		||||
{
 | 
			
		||||
	dm_free((void *)segtype);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct segtype_handler _error_ops = {
 | 
			
		||||
	name:_name,
 | 
			
		||||
	merge_segments:_merge_segments,
 | 
			
		||||
	.name = _errseg_name,
 | 
			
		||||
	.merge_segments = _errseg_merge_segments,
 | 
			
		||||
#ifdef DEVMAPPER_SUPPORT
 | 
			
		||||
	add_target_line:_add_target_line,
 | 
			
		||||
	target_present:_target_present,
 | 
			
		||||
	.add_target_line = _errseg_add_target_line,
 | 
			
		||||
	.target_present = _errseg_target_present,
 | 
			
		||||
#endif
 | 
			
		||||
	destroy:_destroy,
 | 
			
		||||
	.modules_needed = _errseg_modules_needed,
 | 
			
		||||
	.destroy = _errseg_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct segment_type *init_error_segtype(struct cmd_context *cmd)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -33,7 +33,7 @@ static int _and_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _composite_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_filter **filters = (struct dev_filter **) f->private;
 | 
			
		||||
 | 
			
		||||
@@ -70,7 +70,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cft->passes_filter = _and_p;
 | 
			
		||||
	cft->destroy = _destroy;
 | 
			
		||||
	cft->destroy = _composite_destroy;
 | 
			
		||||
	cft->private = filters_copy;
 | 
			
		||||
 | 
			
		||||
	return cft;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,9 @@
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Luca Berra
 | 
			
		||||
 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
@@ -18,14 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#ifdef linux
 | 
			
		||||
 | 
			
		||||
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
 | 
			
		||||
 | 
			
		||||
#define MD_SB_MAGIC 0xa92b4efc
 | 
			
		||||
#define MD_RESERVED_BYTES (64 * 1024)
 | 
			
		||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
 | 
			
		||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
 | 
			
		||||
				- MD_RESERVED_SECTORS)
 | 
			
		||||
 | 
			
		||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "dev-cache.h"
 | 
			
		||||
#include "filter-persistent.h"
 | 
			
		||||
#include "lvm-file.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -26,11 +27,12 @@ struct pfilter {
 | 
			
		||||
	char *file;
 | 
			
		||||
	struct dm_hash_table *devices;
 | 
			
		||||
	struct dev_filter *real;
 | 
			
		||||
	time_t ctime;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * entries in the table can be in one of these
 | 
			
		||||
 * states.
 | 
			
		||||
 * The hash table holds one of these two states
 | 
			
		||||
 * against each entry.
 | 
			
		||||
 */
 | 
			
		||||
#define PF_BAD_DEVICE ((void *) 1)
 | 
			
		||||
#define PF_GOOD_DEVICE ((void *) 2)
 | 
			
		||||
@@ -93,22 +95,26 @@ static int _read_array(struct pfilter *pf, struct config_tree *cft,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int persistent_filter_load(struct dev_filter *f)
 | 
			
		||||
int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
 | 
			
		||||
{
 | 
			
		||||
	struct pfilter *pf = (struct pfilter *) f->private;
 | 
			
		||||
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	struct config_tree *cft;
 | 
			
		||||
        struct stat info;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(cft = create_config_tree(pf->file))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
        if (!stat(pf->file, &info))
 | 
			
		||||
		pf->ctime = info.st_ctime;
 | 
			
		||||
	else {
 | 
			
		||||
                log_very_verbose("%s: stat failed: %s", pf->file,
 | 
			
		||||
				 strerror(errno));
 | 
			
		||||
		return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!read_config_file(cft)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(cft = create_config_tree(pf->file, 1)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!read_config_file(cft))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	_read_array(pf, cft, "persistent_filter_cache/valid_devices",
 | 
			
		||||
		    PF_GOOD_DEVICE);
 | 
			
		||||
@@ -126,7 +132,10 @@ int persistent_filter_load(struct dev_filter *f)
 | 
			
		||||
	log_very_verbose("Loaded persistent filter cache from %s", pf->file);
 | 
			
		||||
 | 
			
		||||
      out:
 | 
			
		||||
	destroy_config_tree(cft);
 | 
			
		||||
	if (r && cft_out)
 | 
			
		||||
		*cft_out = cft;
 | 
			
		||||
	else
 | 
			
		||||
		destroy_config_tree(cft);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -163,8 +172,12 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
 | 
			
		||||
int persistent_filter_dump(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct pfilter *pf = (struct pfilter *) f->private;
 | 
			
		||||
 | 
			
		||||
	char *tmp_file;
 | 
			
		||||
	struct stat info, info2;
 | 
			
		||||
	struct config_tree *cft = NULL;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	int lockfd;
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!dm_hash_get_num_entries(pf->devices)) {
 | 
			
		||||
		log_very_verbose("Internal persistent device cache empty "
 | 
			
		||||
@@ -179,11 +192,43 @@ int persistent_filter_dump(struct dev_filter *f)
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Dumping persistent device cache to %s", pf->file);
 | 
			
		||||
 | 
			
		||||
	fp = fopen(pf->file, "w");
 | 
			
		||||
	if (!fp) {
 | 
			
		||||
		if (errno != EROFS)
 | 
			
		||||
			log_sys_error("fopen", pf->file);
 | 
			
		||||
		return 0;
 | 
			
		||||
	while (1) {
 | 
			
		||||
		if ((lockfd = fcntl_lock_file(pf->file, F_WRLCK, 0)) < 0)
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Ensure we locked the file we expected
 | 
			
		||||
		 */
 | 
			
		||||
		if (fstat(lockfd, &info)) {
 | 
			
		||||
			log_sys_error("fstat", pf->file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (stat(pf->file, &info2)) {
 | 
			
		||||
			log_sys_error("stat", pf->file);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (is_same_inode(info, info2))
 | 
			
		||||
			break;
 | 
			
		||||
	
 | 
			
		||||
		fcntl_unlock_file(lockfd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If file contents changed since we loaded it, merge new contents
 | 
			
		||||
	 */
 | 
			
		||||
	if (info.st_ctime != pf->ctime)
 | 
			
		||||
		/* Keep cft open to avoid losing lock */
 | 
			
		||||
		persistent_filter_load(f, &cft);
 | 
			
		||||
 | 
			
		||||
	tmp_file = alloca(strlen(pf->file) + 5);
 | 
			
		||||
	sprintf(tmp_file, "%s.tmp", pf->file);
 | 
			
		||||
 | 
			
		||||
	if (!(fp = fopen(tmp_file, "w"))) {
 | 
			
		||||
		/* EACCES has been reported over NFS */
 | 
			
		||||
		if (errno != EROFS && errno != EACCES)
 | 
			
		||||
			log_sys_error("fopen", tmp_file);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fprintf(fp, "# This file is automatically maintained by lvm.\n\n");
 | 
			
		||||
@@ -194,8 +239,22 @@ int persistent_filter_dump(struct dev_filter *f)
 | 
			
		||||
	/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
 | 
			
		||||
 | 
			
		||||
	fprintf(fp, "}\n");
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	return 1;
 | 
			
		||||
	if (lvm_fclose(fp, tmp_file))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if (rename(tmp_file, pf->file))
 | 
			
		||||
		log_error("%s: rename to %s failed: %s", tmp_file, pf->file,
 | 
			
		||||
			  strerror(errno));
 | 
			
		||||
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	fcntl_unlock_file(lockfd);
 | 
			
		||||
 | 
			
		||||
	if (cft)
 | 
			
		||||
		destroy_config_tree(cft);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lookup_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
@@ -217,7 +276,7 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	return (l == PF_BAD_DEVICE) ? 0 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _persistent_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct pfilter *pf = (struct pfilter *) f->private;
 | 
			
		||||
 | 
			
		||||
@@ -240,10 +299,9 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
 | 
			
		||||
	}
 | 
			
		||||
	memset(pf, 0, sizeof(*pf));
 | 
			
		||||
 | 
			
		||||
	if (!(pf->file = dm_malloc(strlen(file) + 1))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(pf->file = dm_malloc(strlen(file) + 1)))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	strcpy(pf->file, file);
 | 
			
		||||
	pf->real = real;
 | 
			
		||||
 | 
			
		||||
@@ -252,13 +310,11 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(f = dm_malloc(sizeof(*f)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(f = dm_malloc(sizeof(*f))))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _lookup_p;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
	f->destroy = _persistent_destroy;
 | 
			
		||||
	f->private = pf;
 | 
			
		||||
 | 
			
		||||
	return f;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -22,7 +22,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *f,
 | 
			
		||||
					    const char *file);
 | 
			
		||||
 | 
			
		||||
int persistent_filter_wipe(struct dev_filter *f);
 | 
			
		||||
int persistent_filter_load(struct dev_filter *f);
 | 
			
		||||
int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out);
 | 
			
		||||
int persistent_filter_dump(struct dev_filter *f);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,27 +1,26 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "filter-regex.h"
 | 
			
		||||
#include "matcher.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
 | 
			
		||||
struct rfilter {
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	dm_bitset_t accept;
 | 
			
		||||
	struct matcher *engine;
 | 
			
		||||
	struct dm_regex *engine;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _extract_pattern(struct dm_pool *mem, const char *pat,
 | 
			
		||||
@@ -98,18 +97,15 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
 | 
			
		||||
	unsigned count = 0;
 | 
			
		||||
	int i, r = 0;
 | 
			
		||||
 | 
			
		||||
	if (!(scratch = dm_pool_create("filter matcher", 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(scratch = dm_pool_create("filter dm_regex", 1024)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * count how many patterns we have.
 | 
			
		||||
	 */
 | 
			
		||||
	for (v = val; v; v = v->next) {
 | 
			
		||||
 | 
			
		||||
		if (v->type != CFG_STRING) {
 | 
			
		||||
			log_info("filter patterns must be enclosed in quotes");
 | 
			
		||||
			log_error("filter patterns must be enclosed in quotes");
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -119,10 +115,8 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
 | 
			
		||||
	/*
 | 
			
		||||
	 * allocate space for them
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count)))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * create the accept/reject bitset
 | 
			
		||||
@@ -136,15 +130,15 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
 | 
			
		||||
	 */
 | 
			
		||||
	for (v = val, i = count - 1; v; v = v->next, i--)
 | 
			
		||||
		if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) {
 | 
			
		||||
			log_info("invalid filter pattern");
 | 
			
		||||
			log_error("invalid filter pattern");
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * build the matcher.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!(rf->engine = matcher_create(rf->mem, (const char **) regex,
 | 
			
		||||
					  count)))
 | 
			
		||||
	if (!(rf->engine = dm_regex_create(rf->mem, (const char **) regex,
 | 
			
		||||
					   count)))
 | 
			
		||||
		stack;
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
@@ -160,17 +154,12 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	struct str_list *sl;
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(sl, &dev->aliases) {
 | 
			
		||||
		m = matcher_run(rf->engine, sl->str);
 | 
			
		||||
		m = dm_regex_match(rf->engine, sl->str);
 | 
			
		||||
 | 
			
		||||
		if (m >= 0) {
 | 
			
		||||
			if (dm_bit(rf->accept, m)) {
 | 
			
		||||
 | 
			
		||||
				if (!first) {
 | 
			
		||||
					log_debug("%s: New preferred name",
 | 
			
		||||
						  sl->str);
 | 
			
		||||
					list_del(&sl->list);
 | 
			
		||||
					list_add_h(&dev->aliases, &sl->list);
 | 
			
		||||
				}
 | 
			
		||||
				if (!first)
 | 
			
		||||
					dev_set_preferred_name(sl, dev);
 | 
			
		||||
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
@@ -191,7 +180,7 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
 | 
			
		||||
	return !rejected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(struct dev_filter *f)
 | 
			
		||||
static void _regex_destroy(struct dev_filter *f)
 | 
			
		||||
{
 | 
			
		||||
	struct rfilter *rf = (struct rfilter *) f->private;
 | 
			
		||||
	dm_pool_destroy(rf->mem);
 | 
			
		||||
@@ -208,25 +197,19 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	rf->mem = mem;
 | 
			
		||||
 | 
			
		||||
	if (!_build_matcher(rf, patterns)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!_build_matcher(rf, patterns))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _accept_p;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
	f->destroy = _regex_destroy;
 | 
			
		||||
	f->private = rf;
 | 
			
		||||
	return f;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,9 @@
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -20,19 +20,21 @@
 | 
			
		||||
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
 | 
			
		||||
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
 | 
			
		||||
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len,
 | 
			
		||||
				unsigned *sysfs_depth)
 | 
			
		||||
{
 | 
			
		||||
	char proc_mounts[PATH_MAX];
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *split[4], buffer[PATH_MAX + 16];
 | 
			
		||||
	const char *sys_mnt = NULL;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
 | 
			
		||||
	if (!*proc) {
 | 
			
		||||
		log_verbose("No proc filesystem found: skipping sysfs filter");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	if (lvm_snprintf(proc_mounts, sizeof(proc_mounts),
 | 
			
		||||
	if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
 | 
			
		||||
			 "%s/mounts", proc) < 0) {
 | 
			
		||||
		log_error("Failed to create /proc/mounts string");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -44,18 +46,80 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (fgets(buffer, sizeof(buffer), fp)) {
 | 
			
		||||
		if (split_words(buffer, 4, split) == 4 &&
 | 
			
		||||
		if (dm_split_words(buffer, 4, 0, split) == 4 &&
 | 
			
		||||
		    !strcmp(split[2], "sysfs")) {
 | 
			
		||||
			if (lvm_snprintf(path, len, "%s/%s", split[1],
 | 
			
		||||
					 "block") >= 0) {
 | 
			
		||||
				r = 1;
 | 
			
		||||
			}
 | 
			
		||||
			sys_mnt = split[1];
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	return r;
 | 
			
		||||
	if (fclose(fp))
 | 
			
		||||
		log_sys_error("fclose", proc_mounts);
 | 
			
		||||
 | 
			
		||||
	if (!sys_mnt) {
 | 
			
		||||
		log_error("Failed to find sysfs mount point");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * unified classification directory for all kernel subsystems
 | 
			
		||||
	 *
 | 
			
		||||
	 * /sys/subsystem/block/devices
 | 
			
		||||
	 * |-- sda -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
 | 
			
		||||
	 * |-- sda1 -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
 | 
			
		||||
	 *  `-- sr0 -> ../../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
 | 
			
		||||
	 *
 | 
			
		||||
	 */
 | 
			
		||||
	if (dm_snprintf(path, len, "%s/%s", sys_mnt,
 | 
			
		||||
			"subsystem/block/devices") >= 0) {
 | 
			
		||||
		if (!stat(path, &info)) {
 | 
			
		||||
			*sysfs_depth = 0;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * block subsystem as a class
 | 
			
		||||
	 *
 | 
			
		||||
	 * /sys/class/block
 | 
			
		||||
	 * |-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
 | 
			
		||||
	 * |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
 | 
			
		||||
	 *  `-- sr0 -> ../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
 | 
			
		||||
	 *
 | 
			
		||||
	 */
 | 
			
		||||
	if (dm_snprintf(path, len, "%s/%s", sys_mnt, "class/block") >= 0) {
 | 
			
		||||
		if (!stat(path, &info)) {
 | 
			
		||||
			*sysfs_depth = 0;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * old block subsystem layout with nested directories
 | 
			
		||||
	 *
 | 
			
		||||
	 * /sys/block/
 | 
			
		||||
	 * |-- sda
 | 
			
		||||
	 * |   |-- capability
 | 
			
		||||
	 * |   |-- dev
 | 
			
		||||
	 * ...
 | 
			
		||||
	 * |   |-- sda1
 | 
			
		||||
	 * |   |   |-- dev
 | 
			
		||||
	 * ...
 | 
			
		||||
	 * |
 | 
			
		||||
	 * `-- sr0
 | 
			
		||||
	 *     |-- capability
 | 
			
		||||
	 *     |-- dev
 | 
			
		||||
	 * ...
 | 
			
		||||
	 *
 | 
			
		||||
	 */
 | 
			
		||||
	if (dm_snprintf(path, len, "%s/%s", sys_mnt, "block") >= 0) {
 | 
			
		||||
		if (!stat(path, &info)) {
 | 
			
		||||
			*sysfs_depth = 1;
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------
 | 
			
		||||
@@ -70,11 +134,14 @@ struct entry {
 | 
			
		||||
struct dev_set {
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	const char *sys_block;
 | 
			
		||||
	unsigned sysfs_depth;
 | 
			
		||||
	int initialised;
 | 
			
		||||
	struct entry *slots[SET_BUCKETS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_block)
 | 
			
		||||
static struct dev_set *_dev_set_create(struct dm_pool *mem,
 | 
			
		||||
				       const char *sys_block,
 | 
			
		||||
				       unsigned sysfs_depth)
 | 
			
		||||
{
 | 
			
		||||
	struct dev_set *ds;
 | 
			
		||||
 | 
			
		||||
@@ -83,12 +150,13 @@ static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_bloc
 | 
			
		||||
 | 
			
		||||
	ds->mem = mem;
 | 
			
		||||
	ds->sys_block = dm_pool_strdup(mem, sys_block);
 | 
			
		||||
	ds->sysfs_depth = sysfs_depth;
 | 
			
		||||
	ds->initialised = 0;
 | 
			
		||||
 | 
			
		||||
	return ds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline unsigned _hash_dev(dev_t dev)
 | 
			
		||||
static unsigned _hash_dev(dev_t dev)
 | 
			
		||||
{
 | 
			
		||||
	return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1);
 | 
			
		||||
}
 | 
			
		||||
@@ -156,7 +224,9 @@ static int _read_dev(const char *file, dev_t *result)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = _parse_dev(file, fp, result);
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
 | 
			
		||||
	if (fclose(fp))
 | 
			
		||||
		log_sys_error("fclose", file);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
@@ -164,13 +234,13 @@ static int _read_dev(const char *file, dev_t *result)
 | 
			
		||||
/*
 | 
			
		||||
 * Recurse through sysfs directories, inserting any devs found.
 | 
			
		||||
 */
 | 
			
		||||
static int _read_devs(struct dev_set *ds, const char *dir)
 | 
			
		||||
static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
 | 
			
		||||
{
 | 
			
		||||
        struct dirent *d;
 | 
			
		||||
        DIR *dr;
 | 
			
		||||
	unsigned char dtype;
 | 
			
		||||
	struct stat info;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	dev_t dev = { 0 };
 | 
			
		||||
	int r = 1;
 | 
			
		||||
 | 
			
		||||
@@ -183,38 +253,29 @@ static int _read_devs(struct dev_set *ds, const char *dir)
 | 
			
		||||
                if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (lvm_snprintf(path, sizeof(path), "%s/%s", dir,
 | 
			
		||||
		if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
 | 
			
		||||
				 d->d_name) < 0) {
 | 
			
		||||
			log_error("sysfs path name too long: %s in %s",
 | 
			
		||||
				  d->d_name, dir);
 | 
			
		||||
			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;
 | 
			
		||||
			}
 | 
			
		||||
		/* devices have a "dev" file */
 | 
			
		||||
		if (dm_snprintf(file, sizeof(file), "%s/dev", path) < 0) {
 | 
			
		||||
			log_error("sysfs path name too long: %s in %s",
 | 
			
		||||
				  d->d_name, dir);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (dtype == DT_DIR) {
 | 
			
		||||
			if (!_read_devs(ds, path)) {
 | 
			
		||||
				r = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (!stat(file, &info)) {
 | 
			
		||||
			/* recurse if we found a device and expect subdirs */
 | 
			
		||||
			if (sysfs_depth)
 | 
			
		||||
				_read_devs(ds, path, sysfs_depth - 1);
 | 
			
		||||
 | 
			
		||||
		if ((dtype == DT_REG && !strcmp(d->d_name, "dev")))
 | 
			
		||||
			if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
 | 
			
		||||
				r = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			/* add the device we have found */
 | 
			
		||||
			if (_read_dev(file, &dev))
 | 
			
		||||
				_set_insert(ds, dev);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if (closedir(dr))
 | 
			
		||||
@@ -225,7 +286,7 @@ static int _read_devs(struct dev_set *ds, const char *dir)
 | 
			
		||||
 | 
			
		||||
static int _init_devs(struct dev_set *ds)
 | 
			
		||||
{
 | 
			
		||||
	if (!_read_devs(ds, ds->sys_block)) {
 | 
			
		||||
	if (!_read_devs(ds, ds->sys_block, ds->sysfs_depth)) {
 | 
			
		||||
		ds->initialised = -1;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -263,11 +324,12 @@ static void _destroy(struct dev_filter *f)
 | 
			
		||||
struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
{
 | 
			
		||||
	char sys_block[PATH_MAX];
 | 
			
		||||
	unsigned sysfs_depth;
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	struct dev_set *ds;
 | 
			
		||||
	struct dev_filter *f;
 | 
			
		||||
 | 
			
		||||
	if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
 | 
			
		||||
	if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block), &sysfs_depth))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(mem = dm_pool_create("sysfs", 256))) {
 | 
			
		||||
@@ -275,15 +337,13 @@ struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(ds = _dev_set_create(mem, sys_block))) {
 | 
			
		||||
	if (!(ds = _dev_set_create(mem, sys_block, sysfs_depth))) {
 | 
			
		||||
		log_error("sysfs dev_set creation failed");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	f->passes_filter = _accept_p;
 | 
			
		||||
	f->destroy = _destroy;
 | 
			
		||||
@@ -297,7 +357,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
struct dev_filter *sysfs_filter_create(const char *proc)
 | 
			
		||||
struct dev_filter *sysfs_filter_create(const char *proc __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,9 @@
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
@@ -37,6 +38,7 @@ typedef struct {
 | 
			
		||||
} device_info_t;
 | 
			
		||||
 | 
			
		||||
static int _md_major = -1;
 | 
			
		||||
static int _device_mapper_major = -1;
 | 
			
		||||
 | 
			
		||||
int md_major(void)
 | 
			
		||||
{
 | 
			
		||||
@@ -73,10 +75,12 @@ static const device_info_t device_info[] = {
 | 
			
		||||
	{"aoe", 16},		/* ATA over Ethernet */
 | 
			
		||||
	{"device-mapper", 1},	/* Other mapped devices */
 | 
			
		||||
	{"xvd", 16},		/* Xen virtual block device */
 | 
			
		||||
	{"vdisk", 8},		/* SUN's LDOM virtual block device */
 | 
			
		||||
	{"ps3disk", 16},	/* PlayStation 3 internal disk */
 | 
			
		||||
	{NULL, 0}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _passes_lvm_type_device_filter(struct dev_filter *f,
 | 
			
		||||
static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute((unused)),
 | 
			
		||||
					  struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
@@ -90,6 +94,13 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Skip suspended devices */
 | 
			
		||||
	if (MAJOR(dev->dev) == _device_mapper_major &&
 | 
			
		||||
	    ignore_suspended_devices() && !device_is_usable(dev->dev)) {
 | 
			
		||||
		log_debug("%s: Skipping: Suspended dm device", name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check it's accessible */
 | 
			
		||||
	if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
 | 
			
		||||
		log_debug("%s: Skipping: open failed", name);
 | 
			
		||||
@@ -145,7 +156,7 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
	/* All types unrecognised initially */
 | 
			
		||||
	memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
 | 
			
		||||
 | 
			
		||||
	if (lvm_snprintf(proc_devices, sizeof(proc_devices),
 | 
			
		||||
	if (dm_snprintf(proc_devices, sizeof(proc_devices),
 | 
			
		||||
			 "%s/devices", proc) < 0) {
 | 
			
		||||
		log_error("Failed to create /proc/devices string");
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -182,10 +193,14 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
		if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
 | 
			
		||||
			_md_major = line_maj;
 | 
			
		||||
 | 
			
		||||
		/* Look for device-mapper device */
 | 
			
		||||
		/* FIXME Cope with multiple majors */
 | 
			
		||||
		if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
 | 
			
		||||
			_device_mapper_major = line_maj;
 | 
			
		||||
 | 
			
		||||
		/* Go through the valid device names and if there is a
 | 
			
		||||
		   match store max number of partitions */
 | 
			
		||||
		for (j = 0; device_info[j].name != NULL; j++) {
 | 
			
		||||
 | 
			
		||||
			dev_len = strlen(device_info[j].name);
 | 
			
		||||
			if (dev_len <= strlen(line + i) &&
 | 
			
		||||
			    !strncmp(device_info[j].name, line + i, dev_len) &&
 | 
			
		||||
@@ -204,6 +219,8 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
			if (cv->type != CFG_STRING) {
 | 
			
		||||
				log_error("Expecting string in devices/types "
 | 
			
		||||
					  "in config file");
 | 
			
		||||
				if (fclose(pd))
 | 
			
		||||
					log_sys_error("fclose", proc_devices);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			dev_len = strlen(cv->v.str);
 | 
			
		||||
@@ -213,12 +230,16 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
				log_error("Max partition count missing for %s "
 | 
			
		||||
					  "in devices/types in config file",
 | 
			
		||||
					  name);
 | 
			
		||||
				if (fclose(pd))
 | 
			
		||||
					log_sys_error("fclose", proc_devices);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!cv->v.i) {
 | 
			
		||||
				log_error("Zero partition count invalid for "
 | 
			
		||||
					  "%s in devices/types in config file",
 | 
			
		||||
					  name);
 | 
			
		||||
				if (fclose(pd))
 | 
			
		||||
					log_sys_error("fclose", proc_devices);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (dev_len <= strlen(line + i) &&
 | 
			
		||||
@@ -229,7 +250,10 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fclose(pd);
 | 
			
		||||
 | 
			
		||||
	if (fclose(pd))
 | 
			
		||||
		log_sys_error("fclose", proc_devices);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -254,6 +278,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
 | 
			
		||||
 | 
			
		||||
	if (!_scan_proc_dev(proc, cn)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		dm_free(f);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-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 General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
# 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -102,7 +102,7 @@ static void _xlate_vgd(struct vg_disk *disk)
 | 
			
		||||
 | 
			
		||||
static void _xlate_extents(struct pe_disk *extents, uint32_t count)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < count; i++) {
 | 
			
		||||
		extents[i].lv_num = xlate16(extents[i].lv_num);
 | 
			
		||||
@@ -116,7 +116,7 @@ static void _xlate_extents(struct pe_disk *extents, uint32_t count)
 | 
			
		||||
static int _munge_formats(struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t pe_start;
 | 
			
		||||
	int b, e;
 | 
			
		||||
	unsigned b, e;
 | 
			
		||||
 | 
			
		||||
	switch (pvd->version) {
 | 
			
		||||
	case 1:
 | 
			
		||||
@@ -153,8 +153,10 @@ static int _munge_formats(struct pv_disk *pvd)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	/* If UUID is missing, create one */
 | 
			
		||||
	if (pvd->pv_uuid[0] == '\0')
 | 
			
		||||
		uuid_from_num(pvd->pv_uuid, pvd->pv_number);
 | 
			
		||||
	if (pvd->pv_uuid[0] == '\0') {
 | 
			
		||||
		uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
 | 
			
		||||
		pvd->pv_uuid[ID_LEN] = '\0';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -172,9 +174,9 @@ static void _munge_exported_vg(struct pv_disk *pvd)
 | 
			
		||||
		return;
 | 
			
		||||
	/* FIXME also check vgd->status & VG_EXPORTED? */
 | 
			
		||||
 | 
			
		||||
	l = strlen(pvd->vg_name);
 | 
			
		||||
	l = strlen((char *)pvd->vg_name);
 | 
			
		||||
	s = sizeof(EXPORTED_TAG);
 | 
			
		||||
	if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
 | 
			
		||||
	if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
 | 
			
		||||
		pvd->vg_name[l - s + 1] = '\0';
 | 
			
		||||
                pvd->pv_status |= VG_EXPORTED;
 | 
			
		||||
        }
 | 
			
		||||
@@ -223,11 +225,11 @@ static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_vgd(struct disk_list *data)
 | 
			
		||||
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
 | 
			
		||||
{
 | 
			
		||||
	struct vg_disk *vgd = &data->vgd;
 | 
			
		||||
	uint64_t pos = data->pvd.vg_on_disk.base;
 | 
			
		||||
	if (!dev_read(data->dev, pos, sizeof(*vgd), vgd))
 | 
			
		||||
	uint64_t pos = pvd->vg_on_disk.base;
 | 
			
		||||
 | 
			
		||||
	if (!dev_read(dev, pos, sizeof(*vgd), vgd))
 | 
			
		||||
		fail;
 | 
			
		||||
 | 
			
		||||
	_xlate_vgd(vgd);
 | 
			
		||||
@@ -237,16 +239,16 @@ static int _read_vgd(struct disk_list *data)
 | 
			
		||||
		
 | 
			
		||||
	/* If UUID is missing, create one */
 | 
			
		||||
	if (vgd->vg_uuid[0] == '\0')
 | 
			
		||||
		uuid_from_num(vgd->vg_uuid, vgd->vg_number);
 | 
			
		||||
		uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _read_uuids(struct disk_list *data)
 | 
			
		||||
{
 | 
			
		||||
	int num_read = 0;
 | 
			
		||||
	unsigned num_read = 0;
 | 
			
		||||
	struct uuid_list *ul;
 | 
			
		||||
	char buffer[NAME_LEN];
 | 
			
		||||
	char buffer[NAME_LEN] __attribute((aligned(8)));
 | 
			
		||||
	uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
 | 
			
		||||
	uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
 | 
			
		||||
 | 
			
		||||
@@ -269,7 +271,7 @@ static int _read_uuids(struct disk_list *data)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int _check_lvd(struct lv_disk *lvd)
 | 
			
		||||
static int _check_lvd(struct lv_disk *lvd)
 | 
			
		||||
{
 | 
			
		||||
	return !(lvd->lv_name[0] == '\0');
 | 
			
		||||
}
 | 
			
		||||
@@ -319,13 +321,31 @@ static int _read_extents(struct disk_list *data)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __update_lvmcache(const struct format_type *fmt,
 | 
			
		||||
			      struct disk_list *dl,
 | 
			
		||||
			      struct device *dev, const char *vgid,
 | 
			
		||||
			      unsigned exported)
 | 
			
		||||
{
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
 | 
			
		||||
				  (char *)dl->pvd.vg_name, vgid,
 | 
			
		||||
				  exported ? EXPORTED_VG : 0))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
 | 
			
		||||
	list_init(&info->mdas);
 | 
			
		||||
	info->status &= ~CACHE_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
				     struct device *dev, struct dm_pool *mem,
 | 
			
		||||
				     const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
 | 
			
		||||
	struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
 | 
			
		||||
	const char *name = dev_name(dev);
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!dl) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -337,19 +357,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
	list_init(&dl->uuids);
 | 
			
		||||
	list_init(&dl->lvds);
 | 
			
		||||
 | 
			
		||||
	if (!_read_pvd(dev, &dl->pvd)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
 | 
			
		||||
				  dl->pvd.vg_name, NULL)))
 | 
			
		||||
		stack;
 | 
			
		||||
	else {
 | 
			
		||||
		info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
 | 
			
		||||
		list_init(&info->mdas);
 | 
			
		||||
		info->status &= ~CACHE_INVALID;
 | 
			
		||||
	}
 | 
			
		||||
	if (!_read_pvd(dev, &dl->pvd))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * is it an orphan ?
 | 
			
		||||
@@ -357,26 +366,26 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
	if (!*dl->pvd.vg_name) {
 | 
			
		||||
		log_very_verbose("%s is not a member of any format1 VG", name);
 | 
			
		||||
 | 
			
		||||
		/* Update VG cache */
 | 
			
		||||
		/* vgcache_add(dl->pvd.vg_name, NULL, dev, fmt); */
 | 
			
		||||
 | 
			
		||||
		__update_lvmcache(fmt, dl, dev, NULL, 0);
 | 
			
		||||
		return (vg_name) ? NULL : dl;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_read_vgd(dl)) {
 | 
			
		||||
	if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
 | 
			
		||||
		log_error("Failed to read VG data from PV (%s)", name);
 | 
			
		||||
		__update_lvmcache(fmt, dl, dev, NULL, 0);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Update VG cache with what we found */
 | 
			
		||||
	/* vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt); */
 | 
			
		||||
 | 
			
		||||
	if (vg_name && strcmp(vg_name, dl->pvd.vg_name)) {
 | 
			
		||||
	if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
 | 
			
		||||
		log_very_verbose("%s is not a member of the VG %s",
 | 
			
		||||
				 name, vg_name);
 | 
			
		||||
		__update_lvmcache(fmt, dl, dev, NULL, 0);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	__update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
 | 
			
		||||
			  dl->vgd.vg_status & VG_EXPORTED);
 | 
			
		||||
 | 
			
		||||
	if (!_read_uuids(dl)) {
 | 
			
		||||
		log_error("Failed to read PV uuid list from %s", name);
 | 
			
		||||
		goto bad;
 | 
			
		||||
@@ -406,19 +415,19 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
 | 
			
		||||
struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
 | 
			
		||||
			    struct dm_pool *mem, const char *vg_name)
 | 
			
		||||
{
 | 
			
		||||
	struct disk_list *r;
 | 
			
		||||
	struct disk_list *dl;
 | 
			
		||||
 | 
			
		||||
	if (!dev_open(dev)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = __read_disk(fmt, dev, mem, vg_name);
 | 
			
		||||
	dl = __read_disk(fmt, dev, mem, vg_name);
 | 
			
		||||
 | 
			
		||||
	if (!dev_close(dev))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
	return dl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _add_pv_to_list(struct list *head, struct disk_list *data)
 | 
			
		||||
@@ -428,7 +437,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
 | 
			
		||||
 | 
			
		||||
	list_iterate_items(diskl, head) {
 | 
			
		||||
		pvd = &diskl->pvd;
 | 
			
		||||
		if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
 | 
			
		||||
		if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
 | 
			
		||||
			     sizeof(pvd->pv_uuid))) {
 | 
			
		||||
			if (MAJOR(data->dev->dev) != md_major()) {
 | 
			
		||||
				log_very_verbose("Ignoring duplicate PV %s on "
 | 
			
		||||
@@ -447,7 +456,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Build a list of pv_d's structures, allocated from mem.
 | 
			
		||||
 * We keep track of the first object allocated form the pool
 | 
			
		||||
 * We keep track of the first object allocated from the pool
 | 
			
		||||
 * so we can free off all the memory if something goes wrong.
 | 
			
		||||
 */
 | 
			
		||||
int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
 | 
			
		||||
@@ -461,7 +470,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	/* Fast path if we already saw this VG and cached the list of PVs */
 | 
			
		||||
	if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
 | 
			
		||||
	if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
 | 
			
		||||
	    vginfo->infos.n) {
 | 
			
		||||
		list_iterate_items(info, &vginfo->infos) {
 | 
			
		||||
			dev = info->dev;
 | 
			
		||||
@@ -471,7 +480,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Did we find the whole VG? */
 | 
			
		||||
		if (!vg_name || !*vg_name ||
 | 
			
		||||
		if (!vg_name || is_orphan_vg(vg_name) ||
 | 
			
		||||
		    (data && *data->pvd.vg_name &&
 | 
			
		||||
		     list_size(head) == data->vgd.pv_cur))
 | 
			
		||||
			return 1;
 | 
			
		||||
@@ -565,7 +574,7 @@ static int _write_lvs(struct disk_list *data)
 | 
			
		||||
 | 
			
		||||
	pos = data->pvd.lv_on_disk.base;
 | 
			
		||||
 | 
			
		||||
	if (!dev_zero(data->dev, pos, data->pvd.lv_on_disk.size)) {
 | 
			
		||||
	if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
 | 
			
		||||
		log_error("Couldn't zero lv area on device '%s'",
 | 
			
		||||
			  dev_name(data->dev));
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -644,7 +653,7 @@ static int _write_pvd(struct disk_list *data)
 | 
			
		||||
/*
 | 
			
		||||
 * assumes the device has been opened.
 | 
			
		||||
 */
 | 
			
		||||
static int __write_all_pvd(const struct format_type *fmt,
 | 
			
		||||
static int __write_all_pvd(const struct format_type *fmt __attribute((unused)),
 | 
			
		||||
			   struct disk_list *data)
 | 
			
		||||
{
 | 
			
		||||
	const char *pv_name = dev_name(data->dev);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -73,16 +73,16 @@ struct data_area {
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct pv_disk {
 | 
			
		||||
	uint8_t id[2];
 | 
			
		||||
	int8_t id[2];
 | 
			
		||||
	uint16_t version;	/* lvm version */
 | 
			
		||||
	struct data_area pv_on_disk;
 | 
			
		||||
	struct data_area vg_on_disk;
 | 
			
		||||
	struct data_area pv_uuidlist_on_disk;
 | 
			
		||||
	struct data_area lv_on_disk;
 | 
			
		||||
	struct data_area pe_on_disk;
 | 
			
		||||
	uint8_t pv_uuid[NAME_LEN];
 | 
			
		||||
	uint8_t vg_name[NAME_LEN];
 | 
			
		||||
	uint8_t system_id[NAME_LEN];	/* for vgexport/vgimport */
 | 
			
		||||
	int8_t pv_uuid[NAME_LEN];
 | 
			
		||||
	int8_t vg_name[NAME_LEN];
 | 
			
		||||
	int8_t system_id[NAME_LEN];	/* for vgexport/vgimport */
 | 
			
		||||
	uint32_t pv_major;
 | 
			
		||||
	uint32_t pv_number;
 | 
			
		||||
	uint32_t pv_status;
 | 
			
		||||
@@ -98,8 +98,8 @@ struct pv_disk {
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct lv_disk {
 | 
			
		||||
	uint8_t lv_name[NAME_LEN];
 | 
			
		||||
	uint8_t vg_name[NAME_LEN];
 | 
			
		||||
	int8_t lv_name[NAME_LEN];
 | 
			
		||||
	int8_t vg_name[NAME_LEN];
 | 
			
		||||
	uint32_t lv_access;
 | 
			
		||||
	uint32_t lv_status;
 | 
			
		||||
	uint32_t lv_open;
 | 
			
		||||
@@ -122,8 +122,8 @@ struct lv_disk {
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct vg_disk {
 | 
			
		||||
	uint8_t vg_uuid[ID_LEN];	/* volume group UUID */
 | 
			
		||||
	uint8_t vg_name_dummy[NAME_LEN - ID_LEN];	/* rest of v1 VG name */
 | 
			
		||||
	int8_t vg_uuid[ID_LEN];	/* volume group UUID */
 | 
			
		||||
	int8_t vg_name_dummy[NAME_LEN - ID_LEN];	/* rest of v1 VG name */
 | 
			
		||||
	uint32_t vg_number;	/* volume group number */
 | 
			
		||||
	uint32_t vg_access;	/* read/write */
 | 
			
		||||
	uint32_t vg_status;	/* active or not */
 | 
			
		||||
@@ -148,7 +148,7 @@ struct pe_disk {
 | 
			
		||||
 | 
			
		||||
struct uuid_list {
 | 
			
		||||
	struct list list;
 | 
			
		||||
	char uuid[NAME_LEN];
 | 
			
		||||
	char uuid[NAME_LEN] __attribute((aligned(8)));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct lvd_list {
 | 
			
		||||
@@ -161,17 +161,18 @@ struct disk_list {
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
 | 
			
		||||
	struct pv_disk pvd;
 | 
			
		||||
	struct vg_disk vgd;
 | 
			
		||||
	struct list uuids;
 | 
			
		||||
	struct list lvds;
 | 
			
		||||
	struct pe_disk *extents;
 | 
			
		||||
	struct pv_disk pvd __attribute((aligned(8)));
 | 
			
		||||
	struct vg_disk vgd __attribute((aligned(8)));
 | 
			
		||||
	struct list uuids __attribute((aligned(8)));
 | 
			
		||||
	struct list lvds __attribute((aligned(8)));
 | 
			
		||||
	struct pe_disk *extents __attribute((aligned(8)));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Layout constants.
 | 
			
		||||
 */
 | 
			
		||||
#define METADATA_ALIGN 4096UL
 | 
			
		||||
#define LVM1_PE_ALIGN (65536UL >> SECTOR_SHIFT)      /* PE alignment */
 | 
			
		||||
 | 
			
		||||
#define	METADATA_BASE 0UL
 | 
			
		||||
#define	PV_SIZE 1024UL
 | 
			
		||||
@@ -202,9 +203,10 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
 | 
			
		||||
 * Functions to translate to between disk and in
 | 
			
		||||
 * core structures.
 | 
			
		||||
 */
 | 
			
		||||
int import_pv(struct dm_pool *mem, struct device *dev,
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
	      struct physical_volume *pv, struct pv_disk *pvd);
 | 
			
		||||
int import_pv(const struct format_type *fmt, struct dm_pool *mem,
 | 
			
		||||
	      struct device *dev, struct volume_group *vg,
 | 
			
		||||
	      struct physical_volume *pv, struct pv_disk *pvd,
 | 
			
		||||
	      struct vg_disk *vgd);
 | 
			
		||||
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
	      struct pv_disk *pvd, struct physical_volume *pv);
 | 
			
		||||
@@ -222,7 +224,7 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
 | 
			
		||||
 | 
			
		||||
int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
 | 
			
		||||
	       struct volume_group *vg,
 | 
			
		||||
	       struct list *pvds, struct list *results, int *count);
 | 
			
		||||
	       struct list *pvds, struct list *results, uint32_t *count);
 | 
			
		||||
 | 
			
		||||
int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds);
 | 
			
		||||
int export_lvs(struct disk_list *dl, struct volume_group *vg,
 | 
			
		||||
@@ -237,6 +239,7 @@ void export_numbers(struct list *pvds, struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
void export_pv_act(struct list *pvds);
 | 
			
		||||
int munge_pvd(struct device *dev, struct pv_disk *pvd);
 | 
			
		||||
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd);
 | 
			
		||||
 | 
			
		||||
/* blech */
 | 
			
		||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2007 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.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
@@ -131,10 +131,10 @@ static struct volume_group *_build_vg(struct format_instance *fid,
 | 
			
		||||
	int partial;
 | 
			
		||||
 | 
			
		||||
	if (!vg)
 | 
			
		||||
		goto bad;
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	if (list_empty(pvs))
 | 
			
		||||
		goto bad;
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	memset(vg, 0, sizeof(*vg));
 | 
			
		||||
 | 
			
		||||
@@ -146,24 +146,24 @@ static struct volume_group *_build_vg(struct format_instance *fid,
 | 
			
		||||
	list_init(&vg->tags);
 | 
			
		||||
 | 
			
		||||
	if (!_check_vgs(pvs, &partial))
 | 
			
		||||
		goto bad;
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	dl = list_item(pvs->n, struct disk_list);
 | 
			
		||||
 | 
			
		||||
	if (!import_vg(mem, vg, dl, partial))
 | 
			
		||||
		goto bad;
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count))
 | 
			
		||||
		goto bad;
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	if (!import_lvs(mem, vg, pvs))
 | 
			
		||||
		goto bad;
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	if (!import_extents(fid->fmt->cmd, vg, pvs))
 | 
			
		||||
		goto bad;
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	if (!import_snapshots(mem, vg, pvs))
 | 
			
		||||
		goto bad;
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	return vg;
 | 
			
		||||
 | 
			
		||||
@@ -173,9 +173,9 @@ static struct volume_group *_build_vg(struct format_instance *fid,
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct volume_group *_vg_read(struct format_instance *fid,
 | 
			
		||||
static struct volume_group *_format1_vg_read(struct format_instance *fid,
 | 
			
		||||
				     const char *vg_name,
 | 
			
		||||
				     struct metadata_area *mda)
 | 
			
		||||
				     struct metadata_area *mda __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("lvm1 vg_read", 1024 * 10);
 | 
			
		||||
	struct list pvs;
 | 
			
		||||
@@ -191,15 +191,11 @@ static struct volume_group *_vg_read(struct format_instance *fid,
 | 
			
		||||
	vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
 | 
			
		||||
 | 
			
		||||
	if (!read_pvs_in_vg
 | 
			
		||||
	    (fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	    (fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	if (!(vg = _build_vg(fid, &pvs))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(vg = _build_vg(fid, &pvs)))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	dm_pool_destroy(mem);
 | 
			
		||||
@@ -264,8 +260,8 @@ static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
		     struct metadata_area *mda)
 | 
			
		||||
static int _format1_vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
		     struct metadata_area *mda __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("lvm1 vg_write", 1024 * 10);
 | 
			
		||||
	struct list pvds;
 | 
			
		||||
@@ -287,8 +283,8 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		    struct physical_volume *pv, struct list *mdas)
 | 
			
		||||
static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		    struct physical_volume *pv, struct list *mdas __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
 | 
			
		||||
	struct disk_list *dl;
 | 
			
		||||
@@ -312,7 +308,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd)) {
 | 
			
		||||
	if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -326,19 +322,18 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
static int _format1_pv_setup(const struct format_type *fmt,
 | 
			
		||||
		     uint64_t pe_start, uint32_t extent_count,
 | 
			
		||||
		     uint32_t extent_size,
 | 
			
		||||
		     int pvmetadatacopies,
 | 
			
		||||
		     uint64_t pvmetadatasize, struct list *mdas,
 | 
			
		||||
		     struct physical_volume *pv, struct volume_group *vg)
 | 
			
		||||
		     int pvmetadatacopies __attribute((unused)),
 | 
			
		||||
		     uint64_t pvmetadatasize __attribute((unused)), struct list *mdas __attribute((unused)),
 | 
			
		||||
		     struct physical_volume *pv, struct volume_group *vg __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	if (pv->size > MAX_PV_SIZE)
 | 
			
		||||
		pv->size--;
 | 
			
		||||
	if (pv->size > MAX_PV_SIZE) {
 | 
			
		||||
		log_error("Physical volumes cannot be bigger than %s",
 | 
			
		||||
			  display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -364,7 +359,7 @@ static int _pv_setup(const struct format_type *fmt,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
 | 
			
		||||
static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t max_size = UINT_MAX;
 | 
			
		||||
 | 
			
		||||
@@ -378,16 +373,15 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
 | 
			
		||||
	}
 | 
			
		||||
	if (lv->size > max_size) {
 | 
			
		||||
		log_error("logical volumes cannot be larger than %s",
 | 
			
		||||
			  display_size(fid->fmt->cmd, max_size,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(fid->fmt->cmd, max_size));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
		     struct list *mdas, int64_t sector)
 | 
			
		||||
static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
		     struct list *mdas __attribute((unused)), int64_t sector __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	struct disk_list *dl;
 | 
			
		||||
@@ -396,7 +390,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	struct lvmcache_info *info;
 | 
			
		||||
 | 
			
		||||
	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
 | 
			
		||||
				  pv->vg_name, NULL))) {
 | 
			
		||||
				  pv->vg_name, NULL, 0))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -410,36 +404,31 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
 | 
			
		||||
	/* Ensure any residual PE structure is gone */
 | 
			
		||||
	pv->pe_size = pv->pe_count = 0;
 | 
			
		||||
	pv->pe_start = PE_ALIGN;
 | 
			
		||||
	pv->pe_start = LVM1_PE_ALIGN;
 | 
			
		||||
 | 
			
		||||
	if (!(mem = dm_pool_create("lvm1 pv_write", 1024))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	dl->mem = mem;
 | 
			
		||||
	dl->dev = pv->dev;
 | 
			
		||||
 | 
			
		||||
	if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	/* must be set to be able to zero gap after PV structure in
 | 
			
		||||
	   dev_write in order to make other disk tools happy */
 | 
			
		||||
	dl->pvd.pv_on_disk.base = METADATA_BASE;
 | 
			
		||||
	dl->pvd.pv_on_disk.size = PV_SIZE;
 | 
			
		||||
	dl->pvd.pe_on_disk.base = PE_ALIGN << SECTOR_SHIFT;
 | 
			
		||||
	dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
 | 
			
		||||
 | 
			
		||||
	list_add(&pvs, &dl->list);
 | 
			
		||||
	if (!write_disks(fmt, &pvs)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	if (!write_disks(fmt, &pvs))
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	dm_pool_destroy(mem);
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -449,7 +438,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
static int _format1_vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	/* just check max_pv and max_lv */
 | 
			
		||||
	if (!vg->max_lv || vg->max_lv >= MAX_LV)
 | 
			
		||||
@@ -460,18 +449,15 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	if (vg->extent_size > MAX_PE_SIZE || vg->extent_size < MIN_PE_SIZE) {
 | 
			
		||||
		log_error("Extent size must be between %s and %s",
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT),
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE),
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE));
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (vg->extent_size % MIN_PE_SIZE) {
 | 
			
		||||
		log_error("Extent size must be multiple of %s",
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
 | 
			
		||||
				       SIZE_SHORT));
 | 
			
		||||
			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -484,8 +470,8 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _segtype_supported (struct format_instance *fid, 
 | 
			
		||||
			       struct segment_type *segtype)
 | 
			
		||||
static int _format1_segtype_supported(struct format_instance *fid __attribute((unused)), 
 | 
			
		||||
				      const struct segment_type *segtype)
 | 
			
		||||
{
 | 
			
		||||
	if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
 | 
			
		||||
		stack;
 | 
			
		||||
@@ -496,13 +482,14 @@ static int _segtype_supported (struct format_instance *fid,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct metadata_area_ops _metadata_format1_ops = {
 | 
			
		||||
	vg_read:_vg_read,
 | 
			
		||||
	vg_write:_vg_write,
 | 
			
		||||
	.vg_read = _format1_vg_read,
 | 
			
		||||
	.vg_write = _format1_vg_write,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct format_instance *_create_instance(const struct format_type *fmt,
 | 
			
		||||
						const char *vgname,
 | 
			
		||||
						void *private)
 | 
			
		||||
static struct format_instance *_format1_create_instance(const struct format_type *fmt,
 | 
			
		||||
						const char *vgname __attribute((unused)),
 | 
			
		||||
						const char *vgid __attribute((unused)),
 | 
			
		||||
						void *private __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	struct format_instance *fid;
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
@@ -529,26 +516,26 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
 | 
			
		||||
	return fid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy_instance(struct format_instance *fid)
 | 
			
		||||
static void _format1_destroy_instance(struct format_instance *fid __attribute((unused)))
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _destroy(const struct format_type *fmt)
 | 
			
		||||
static void _format1_destroy(const struct format_type *fmt)
 | 
			
		||||
{
 | 
			
		||||
	dm_free((void *) fmt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct format_handler _format1_ops = {
 | 
			
		||||
	pv_read:_pv_read,
 | 
			
		||||
	pv_setup:_pv_setup,
 | 
			
		||||
	pv_write:_pv_write,
 | 
			
		||||
	lv_setup:_lv_setup,
 | 
			
		||||
	vg_setup:_vg_setup,
 | 
			
		||||
	segtype_supported:_segtype_supported,
 | 
			
		||||
	create_instance:_create_instance,
 | 
			
		||||
	destroy_instance:_destroy_instance,
 | 
			
		||||
	destroy:_destroy,
 | 
			
		||||
	.pv_read = _format1_pv_read,
 | 
			
		||||
	.pv_setup = _format1_pv_setup,
 | 
			
		||||
	.pv_write = _format1_pv_write,
 | 
			
		||||
	.lv_setup = _format1_lv_setup,
 | 
			
		||||
	.vg_setup = _format1_vg_setup,
 | 
			
		||||
	.segtype_supported = _format1_segtype_supported,
 | 
			
		||||
	.create_instance = _format1_create_instance,
 | 
			
		||||
	.destroy_instance = _format1_destroy_instance,
 | 
			
		||||
	.destroy = _format1_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef LVM1_INTERNAL
 | 
			
		||||
@@ -569,7 +556,8 @@ struct format_type *init_format(struct cmd_context *cmd)
 | 
			
		||||
	fmt->ops = &_format1_ops;
 | 
			
		||||
	fmt->name = FMT_LVM1_NAME;
 | 
			
		||||
	fmt->alias = NULL;
 | 
			
		||||
	fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE;
 | 
			
		||||
	fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE |
 | 
			
		||||
			FMT_RESTRICTED_READAHEAD;
 | 
			
		||||
	fmt->private = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!(fmt->labeller = lvm1_labeller_create(fmt))) {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,9 @@
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user