mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-03 08:23:48 +03:00 
			
		
		
		
	Compare commits
	
		
			6831 Commits
		
	
	
		
			v2_03_26
			...
			old_master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					37e5ee6034 | ||
| 
						 | 
					4907609c27 | ||
| 
						 | 
					007b9d4239 | ||
| 
						 | 
					2439aa4bf1 | ||
| 
						 | 
					77ce00ddaa | ||
| 
						 | 
					a40c717162 | ||
| 
						 | 
					7b3b05c1f5 | ||
| 
						 | 
					4a7f4703ed | ||
| 
						 | 
					24972a9fcc | ||
| 
						 | 
					bd4ef6a050 | ||
| 
						 | 
					1404dc2fbf | ||
| 
						 | 
					4d45791346 | ||
| 
						 | 
					876fba9f2a | ||
| 
						 | 
					8b5db5d9b2 | ||
| 
						 | 
					8ddca409b4 | ||
| 
						 | 
					9cc266a5d2 | ||
| 
						 | 
					bee3b45081 | ||
| 
						 | 
					0c9d2a2246 | ||
| 
						 | 
					bfdfc9e68e | ||
| 
						 | 
					3a042496fd | ||
| 
						 | 
					d2a3be546f | ||
| 
						 | 
					70cacce52e | ||
| 
						 | 
					b63eb871fd | ||
| 
						 | 
					dcc18799ec | ||
| 
						 | 
					588513328c | ||
| 
						 | 
					cfc90d7af2 | ||
| 
						 | 
					1b0ca5fc45 | ||
| 
						 | 
					bab3366f5f | ||
| 
						 | 
					501a2c04a4 | ||
| 
						 | 
					9f60083aff | ||
| 
						 | 
					b54dc45c90 | ||
| 
						 | 
					a93ad77e02 | ||
| 
						 | 
					679f946dd9 | ||
| 
						 | 
					8322deefee | ||
| 
						 | 
					8c5517e01d | ||
| 
						 | 
					fdd34489dd | ||
| 
						 | 
					172a9457bf | ||
| 
						 | 
					7637b40159 | ||
| 
						 | 
					7072ed86f9 | ||
| 
						 | 
					ff8ed61f76 | ||
| 
						 | 
					50b2d511ec | ||
| 
						 | 
					9ac67656ae | ||
| 
						 | 
					c4da860fd5 | ||
| 
						 | 
					7ff84d5269 | ||
| 
						 | 
					d057cc445d | ||
| 
						 | 
					d614e1f447 | ||
| 
						 | 
					22d0b18687 | ||
| 
						 | 
					cfa6500574 | ||
| 
						 | 
					cc75389238 | ||
| 
						 | 
					e0071a8634 | ||
| 
						 | 
					4f9c54bdac | ||
| 
						 | 
					901d70b09c | ||
| 
						 | 
					2620663d7b | ||
| 
						 | 
					d74afb244b | ||
| 
						 | 
					5d048a5e26 | ||
| 
						 | 
					0afc1897b2 | ||
| 
						 | 
					95b3332658 | ||
| 
						 | 
					b8e51eae00 | ||
| 
						 | 
					b4eaf64b10 | ||
| 
						 | 
					ba568151a5 | ||
| 
						 | 
					0644a64c94 | ||
| 
						 | 
					28bc212eb0 | ||
| 
						 | 
					c63ddca435 | ||
| 
						 | 
					4c4094c33c | ||
| 
						 | 
					b51d131c59 | ||
| 
						 | 
					87a723122d | ||
| 
						 | 
					8d92388231 | ||
| 
						 | 
					a6d66a030d | ||
| 
						 | 
					f9961e6f19 | ||
| 
						 | 
					6a69a4472d | ||
| 
						 | 
					35e728ec8d | ||
| 
						 | 
					48511e9bd6 | ||
| 
						 | 
					fb4f76a29c | ||
| 
						 | 
					2d6f57be7e | ||
| 
						 | 
					c44897abfc | ||
| 
						 | 
					667d681ce0 | ||
| 
						 | 
					e1b9db7140 | ||
| 
						 | 
					a5cffcdcf9 | ||
| 
						 | 
					b798ea409d | ||
| 
						 | 
					7387343eab | ||
| 
						 | 
					53064420ff | ||
| 
						 | 
					c8d671b6ad | ||
| 
						 | 
					59a26019e0 | ||
| 
						 | 
					195aa7699e | ||
| 
						 | 
					c950126620 | ||
| 
						 | 
					600a3810ea | ||
| 
						 | 
					749f4ae7cb | ||
| 
						 | 
					e674eb6a79 | ||
| 
						 | 
					ad7d4b6c56 | ||
| 
						 | 
					ef49063b27 | ||
| 
						 | 
					0a3a88eb84 | ||
| 
						 | 
					23d0fddca5 | ||
| 
						 | 
					7e27f33433 | ||
| 
						 | 
					9359753aab | ||
| 
						 | 
					4dd8a94a20 | ||
| 
						 | 
					963ccfd981 | ||
| 
						 | 
					8df1e265f8 | ||
| 
						 | 
					8b2fdb26e5 | ||
| 
						 | 
					4687bd1015 | ||
| 
						 | 
					0237724e17 | ||
| 
						 | 
					bc013bc21f | ||
| 
						 | 
					3ac8509b99 | ||
| 
						 | 
					f02892842b | ||
| 
						 | 
					31a1a47ad5 | ||
| 
						 | 
					6e7d2724ba | ||
| 
						 | 
					adbf9a803a | ||
| 
						 | 
					7e7c9bb2f3 | ||
| 
						 | 
					70d7a8ea41 | ||
| 
						 | 
					c987c20bb3 | ||
| 
						 | 
					45d7997514 | ||
| 
						 | 
					d13c952ee4 | ||
| 
						 | 
					4fd6aae7bf | ||
| 
						 | 
					2b6dee707a | ||
| 
						 | 
					124dec2880 | ||
| 
						 | 
					f4dd47242e | ||
| 
						 | 
					268ec5553e | ||
| 
						 | 
					1238935a2d | ||
| 
						 | 
					6ef0f403c7 | ||
| 
						 | 
					523910032b | ||
| 
						 | 
					6960f5402a | ||
| 
						 | 
					b71339435d | ||
| 
						 | 
					de0e4e755a | ||
| 
						 | 
					3f5b1f651a | ||
| 
						 | 
					2d94d29def | ||
| 
						 | 
					c3b58ec989 | ||
| 
						 | 
					f19be6776b | ||
| 
						 | 
					d7bcb6e117 | ||
| 
						 | 
					6584221843 | ||
| 
						 | 
					8d46025ff8 | ||
| 
						 | 
					552f340ff5 | ||
| 
						 | 
					def8f31a2e | ||
| 
						 | 
					bac0394dc6 | ||
| 
						 | 
					303b44c8fa | ||
| 
						 | 
					23a88f868d | ||
| 
						 | 
					682be508c6 | ||
| 
						 | 
					4a01bb64fb | ||
| 
						 | 
					1b80b1086f | ||
| 
						 | 
					cbf86d952b | ||
| 
						 | 
					91c0dc527b | ||
| 
						 | 
					2412ede4c6 | ||
| 
						 | 
					b6476cba88 | ||
| 
						 | 
					4a7bc37bfa | ||
| 
						 | 
					57e379d5ee | ||
| 
						 | 
					80a1c93421 | ||
| 
						 | 
					1ce7924bbf | ||
| 
						 | 
					8a9c1b37ad | ||
| 
						 | 
					c1ce99cd81 | ||
| 
						 | 
					166393a6dd | ||
| 
						 | 
					06a9a4e867 | ||
| 
						 | 
					6b85d4df44 | ||
| 
						 | 
					c2d7d97301 | ||
| 
						 | 
					dd121cf5ff | ||
| 
						 | 
					418a0b6080 | ||
| 
						 | 
					35d8953142 | ||
| 
						 | 
					393cfa1656 | ||
| 
						 | 
					bb0234a63a | ||
| 
						 | 
					9d36f3e765 | ||
| 
						 | 
					76161a80bf | ||
| 
						 | 
					5e506c84f6 | ||
| 
						 | 
					9f354a1cae | ||
| 
						 | 
					61fe203e7d | ||
| 
						 | 
					33213a3e8e | ||
| 
						 | 
					3cf63e35bf | ||
| 
						 | 
					ac2ac815f1 | ||
| 
						 | 
					a31a947d49 | ||
| 
						 | 
					9a988ab420 | ||
| 
						 | 
					b608869a26 | ||
| 
						 | 
					28d128f1b6 | ||
| 
						 | 
					14a6a1e17e | ||
| 
						 | 
					0711a50005 | ||
| 
						 | 
					913a0dbb3a | ||
| 
						 | 
					4600444786 | ||
| 
						 | 
					24cbb72291 | ||
| 
						 | 
					bebbb5aff9 | ||
| 
						 | 
					e04c6e4972 | ||
| 
						 | 
					3fb6ddf3ce | ||
| 
						 | 
					301c011a92 | ||
| 
						 | 
					41b738c1e4 | ||
| 
						 | 
					e66e524898 | ||
| 
						 | 
					f723e0396e | ||
| 
						 | 
					eed642e0b3 | ||
| 
						 | 
					eb706b3106 | ||
| 
						 | 
					9a26228d28 | ||
| 
						 | 
					e18ea55fef | ||
| 
						 | 
					059ff7d5ff | ||
| 
						 | 
					00422596c1 | ||
| 
						 | 
					d177da6b98 | ||
| 
						 | 
					299b4751c2 | ||
| 
						 | 
					7c47bdc5ec | ||
| 
						 | 
					6859106e2a | ||
| 
						 | 
					bfb8a95111 | ||
| 
						 | 
					1a002bbe59 | ||
| 
						 | 
					598134b8e7 | ||
| 
						 | 
					cbc8dedafe | ||
| 
						 | 
					fdfa12d956 | ||
| 
						 | 
					34b6b9d0d7 | ||
| 
						 | 
					197d0d4af6 | ||
| 
						 | 
					e3e0811b67 | ||
| 
						 | 
					7659a953a7 | ||
| 
						 | 
					7e42a312ae | ||
| 
						 | 
					6aff7af424 | ||
| 
						 | 
					d61c67b52d | ||
| 
						 | 
					a18693e705 | ||
| 
						 | 
					59c71b93ad | ||
| 
						 | 
					526655301e | ||
| 
						 | 
					1eb1626f08 | ||
| 
						 | 
					17c3bf7b22 | ||
| 
						 | 
					d27834ff0a | ||
| 
						 | 
					d102667b6d | ||
| 
						 | 
					e922a85c51 | ||
| 
						 | 
					2236c69c42 | ||
| 
						 | 
					a75b0d4ee6 | ||
| 
						 | 
					f996955304 | ||
| 
						 | 
					27088d51a2 | ||
| 
						 | 
					73ef9a7eaa | ||
| 
						 | 
					48073da2b8 | ||
| 
						 | 
					657826a255 | ||
| 
						 | 
					465fe71f6c | ||
| 
						 | 
					0b60d3a05e | ||
| 
						 | 
					d84d5b113e | ||
| 
						 | 
					10dab1c621 | ||
| 
						 | 
					31128d8747 | ||
| 
						 | 
					db424996be | ||
| 
						 | 
					86d71759d0 | ||
| 
						 | 
					fa750fd0c5 | ||
| 
						 | 
					6ebad37e9b | ||
| 
						 | 
					05a2d7bcfd | ||
| 
						 | 
					6732bedecb | ||
| 
						 | 
					041c69362d | ||
| 
						 | 
					c53667ac45 | ||
| 
						 | 
					c9ab8ce0a3 | ||
| 
						 | 
					f5de369e04 | ||
| 
						 | 
					53bdfe124b | ||
| 
						 | 
					052269aa2c | ||
| 
						 | 
					50bdd70043 | ||
| 
						 | 
					6508cc6805 | ||
| 
						 | 
					942144f4a3 | ||
| 
						 | 
					ce80d6e401 | ||
| 
						 | 
					193d697ba4 | ||
| 
						 | 
					ba23f9e71f | ||
| 
						 | 
					3af3a9a68b | ||
| 
						 | 
					09977e0364 | ||
| 
						 | 
					33af17af76 | ||
| 
						 | 
					2f9161a1e2 | ||
| 
						 | 
					b10489f568 | ||
| 
						 | 
					0c598c8270 | ||
| 
						 | 
					d7d948eacc | ||
| 
						 | 
					dea586a587 | ||
| 
						 | 
					d7ca49059f | ||
| 
						 | 
					830057e338 | ||
| 
						 | 
					98711b45c7 | ||
| 
						 | 
					b009e2235e | ||
| 
						 | 
					7a3de26248 | ||
| 
						 | 
					505c0cbb2e | ||
| 
						 | 
					f2cbcb027e | ||
| 
						 | 
					7ed8790301 | ||
| 
						 | 
					3db3d4d895 | ||
| 
						 | 
					41d8247b51 | ||
| 
						 | 
					a22be5e2e9 | ||
| 
						 | 
					0098904026 | ||
| 
						 | 
					c0d7975bb2 | ||
| 
						 | 
					22266ea325 | ||
| 
						 | 
					77e9346a06 | ||
| 
						 | 
					c998f7d27a | ||
| 
						 | 
					c9d0627af6 | ||
| 
						 | 
					49d8753caf | ||
| 
						 | 
					fdc31c7a8a | ||
| 
						 | 
					535fbc2256 | ||
| 
						 | 
					9cdfa9e854 | ||
| 
						 | 
					c3cb4bb872 | ||
| 
						 | 
					da0f745cb6 | ||
| 
						 | 
					9ef8d6617e | ||
| 
						 | 
					0fd3ed18f1 | ||
| 
						 | 
					60d0b63380 | ||
| 
						 | 
					889007ee2c | ||
| 
						 | 
					95ad3abc76 | ||
| 
						 | 
					cd1f056f20 | ||
| 
						 | 
					faf8ad30f1 | ||
| 
						 | 
					4960a3c7f3 | ||
| 
						 | 
					3b45ebe86b | ||
| 
						 | 
					d7bb0d77aa | ||
| 
						 | 
					125456bb3e | ||
| 
						 | 
					e51cc452d2 | ||
| 
						 | 
					4f443a0d0c | ||
| 
						 | 
					7ed9336202 | ||
| 
						 | 
					0027de97c9 | ||
| 
						 | 
					6ddd3f5d4c | ||
| 
						 | 
					90f31fc31c | ||
| 
						 | 
					061b3169f9 | ||
| 
						 | 
					e2b77ed33c | ||
| 
						 | 
					b85b9ce4b7 | ||
| 
						 | 
					edb0de6539 | ||
| 
						 | 
					1b197085b3 | ||
| 
						 | 
					61a6481305 | ||
| 
						 | 
					dc92528f10 | ||
| 
						 | 
					fe84afbbab | ||
| 
						 | 
					9b0c352a57 | ||
| 
						 | 
					c1a04f0fe3 | ||
| 
						 | 
					42c3f42474 | ||
| 
						 | 
					460605cf71 | ||
| 
						 | 
					c401303ca2 | ||
| 
						 | 
					9656be3deb | ||
| 
						 | 
					e91a7700eb | ||
| 
						 | 
					50730ddd96 | ||
| 
						 | 
					7ce18df26b | ||
| 
						 | 
					be5d2c75f3 | ||
| 
						 | 
					dc7d369ad8 | ||
| 
						 | 
					9a3497dcfa | ||
| 
						 | 
					88a898d6cf | ||
| 
						 | 
					a80e4e0d1f | ||
| 
						 | 
					7bc76e9c20 | ||
| 
						 | 
					1336a1cbf1 | ||
| 
						 | 
					6295e3ef1e | ||
| 
						 | 
					e8681b8d42 | ||
| 
						 | 
					ed5d30f075 | ||
| 
						 | 
					75ac0b638c | ||
| 
						 | 
					e3a47a9370 | ||
| 
						 | 
					c2915dd1ed | ||
| 
						 | 
					aa558eaeb8 | ||
| 
						 | 
					8411f22f43 | ||
| 
						 | 
					33f24144bd | ||
| 
						 | 
					751e17f17b | ||
| 
						 | 
					2237e93169 | ||
| 
						 | 
					19fde08c6a | ||
| 
						 | 
					b2edbee763 | ||
| 
						 | 
					1e59596393 | ||
| 
						 | 
					7a502785b0 | ||
| 
						 | 
					2a0264eb7d | ||
| 
						 | 
					17829d245c | ||
| 
						 | 
					de61ffd1b5 | ||
| 
						 | 
					0dd5bf2730 | ||
| 
						 | 
					74d0a06513 | ||
| 
						 | 
					30cc37b645 | ||
| 
						 | 
					9d206272a5 | ||
| 
						 | 
					af8b3ace37 | ||
| 
						 | 
					4c10334843 | ||
| 
						 | 
					165a28a8a5 | ||
| 
						 | 
					0c7a75df32 | ||
| 
						 | 
					38c2ccf7b8 | ||
| 
						 | 
					becb604089 | ||
| 
						 | 
					c6101ffc0c | ||
| 
						 | 
					002f7a0ce2 | ||
| 
						 | 
					fa73b2ee3d | ||
| 
						 | 
					8acbf570b5 | ||
| 
						 | 
					40f111e9b9 | ||
| 
						 | 
					7e61f1ef44 | ||
| 
						 | 
					e10e4a5134 | ||
| 
						 | 
					aa357b8f5d | ||
| 
						 | 
					9a94507884 | ||
| 
						 | 
					73c46fa222 | ||
| 
						 | 
					3fc37a89e2 | ||
| 
						 | 
					fe81ba59e8 | ||
| 
						 | 
					16b40da2e7 | ||
| 
						 | 
					65f96d99e5 | ||
| 
						 | 
					b1e320e5c4 | ||
| 
						 | 
					6d4df258e4 | ||
| 
						 | 
					c615046eec | ||
| 
						 | 
					a742ee8b37 | ||
| 
						 | 
					bd746876ee | ||
| 
						 | 
					a2e5d2cb9c | ||
| 
						 | 
					b0fe3642c8 | ||
| 
						 | 
					a0289c969f | ||
| 
						 | 
					d6463f4890 | ||
| 
						 | 
					8da4309f07 | ||
| 
						 | 
					f71e484598 | ||
| 
						 | 
					d11718e479 | ||
| 
						 | 
					580b0e871d | ||
| 
						 | 
					d7a47a354f | ||
| 
						 | 
					351c6b96b8 | ||
| 
						 | 
					cc3552f4a8 | ||
| 
						 | 
					735a00a152 | ||
| 
						 | 
					aaf717039e | ||
| 
						 | 
					397d2bfe89 | ||
| 
						 | 
					eb9e8f8e3d | ||
| 
						 | 
					a872331404 | ||
| 
						 | 
					9fc640ffd9 | ||
| 
						 | 
					c0b2521a82 | ||
| 
						 | 
					17696422b6 | ||
| 
						 | 
					7f024cf822 | ||
| 
						 | 
					f2e7993792 | ||
| 
						 | 
					5a923ff8ad | ||
| 
						 | 
					9ec1097099 | ||
| 
						 | 
					4ec2657ac3 | ||
| 
						 | 
					9d5d312d82 | ||
| 
						 | 
					111b6717b6 | ||
| 
						 | 
					3ffe9aa27d | ||
| 
						 | 
					8a12e5a359 | ||
| 
						 | 
					cd4fce855e | ||
| 
						 | 
					017c0c9e8c | ||
| 
						 | 
					d6afd3e0fc | ||
| 
						 | 
					d05bfd3265 | ||
| 
						 | 
					4847399243 | ||
| 
						 | 
					d6f91a013b | ||
| 
						 | 
					7daa233e48 | ||
| 
						 | 
					9159aec6f1 | ||
| 
						 | 
					c5d7b90b2a | ||
| 
						 | 
					35d3d400ec | ||
| 
						 | 
					0d38ef9273 | ||
| 
						 | 
					2b62c3ed69 | ||
| 
						 | 
					cc05bde071 | ||
| 
						 | 
					27d46fc686 | ||
| 
						 | 
					07d54dd4a7 | ||
| 
						 | 
					e975f85035 | ||
| 
						 | 
					c868f0ebf0 | ||
| 
						 | 
					5a4638e22b | ||
| 
						 | 
					afed769d42 | ||
| 
						 | 
					a140caa666 | ||
| 
						 | 
					dab4bb3bdf | ||
| 
						 | 
					2833f81fb3 | ||
| 
						 | 
					bbf912b644 | ||
| 
						 | 
					05e8ec79e0 | ||
| 
						 | 
					78188982d6 | ||
| 
						 | 
					6890aea4ca | ||
| 
						 | 
					b2b5a2268a | ||
| 
						 | 
					5ca11ba420 | ||
| 
						 | 
					c227ad23cc | ||
| 
						 | 
					5dc08c01d3 | ||
| 
						 | 
					ec6a14f40a | ||
| 
						 | 
					7cf73cbc1f | ||
| 
						 | 
					193c832d12 | ||
| 
						 | 
					82e18a35a9 | ||
| 
						 | 
					69b9a614c7 | ||
| 
						 | 
					52fdced782 | ||
| 
						 | 
					2a7e2fe2d3 | ||
| 
						 | 
					3b6c6f1319 | ||
| 
						 | 
					11b3b12336 | ||
| 
						 | 
					b8a4a2b40b | ||
| 
						 | 
					3e15add713 | ||
| 
						 | 
					06eaf8974a | ||
| 
						 | 
					4ceec2023f | ||
| 
						 | 
					777a797ec3 | ||
| 
						 | 
					c559180cca | ||
| 
						 | 
					9fde529762 | ||
| 
						 | 
					50504ab73e | ||
| 
						 | 
					514976816d | ||
| 
						 | 
					00067fb64a | ||
| 
						 | 
					f6aab411f8 | ||
| 
						 | 
					c966f07bbd | ||
| 
						 | 
					e8ada4a717 | ||
| 
						 | 
					14d7b7b4e9 | ||
| 
						 | 
					395ee036d7 | ||
| 
						 | 
					1a28df6bb4 | ||
| 
						 | 
					2936951d94 | ||
| 
						 | 
					e98b640d5d | ||
| 
						 | 
					6d29fe0f33 | ||
| 
						 | 
					5365e4a53f | ||
| 
						 | 
					70e3728446 | ||
| 
						 | 
					0cb3bdcfce | ||
| 
						 | 
					d735798674 | ||
| 
						 | 
					74c7c69d34 | ||
| 
						 | 
					7ce534f911 | ||
| 
						 | 
					f03f322f13 | ||
| 
						 | 
					c929a0b3c8 | ||
| 
						 | 
					6bea32ccf2 | ||
| 
						 | 
					84facc4fa5 | ||
| 
						 | 
					7940545204 | ||
| 
						 | 
					cc525412f1 | ||
| 
						 | 
					962fd76f26 | ||
| 
						 | 
					6e40adde76 | ||
| 
						 | 
					fb6a209080 | ||
| 
						 | 
					e6b610e8ed | ||
| 
						 | 
					bb0862fbb4 | ||
| 
						 | 
					e2d2f6c7b7 | ||
| 
						 | 
					e48d39cba0 | ||
| 
						 | 
					4443aa41cc | ||
| 
						 | 
					24da0046d5 | ||
| 
						 | 
					8d9b4b0133 | ||
| 
						 | 
					328ed80160 | ||
| 
						 | 
					582c94aa21 | ||
| 
						 | 
					38188ff8aa | ||
| 
						 | 
					c84c7ee034 | ||
| 
						 | 
					a3ac5a54d0 | ||
| 
						 | 
					b93aa9eac4 | ||
| 
						 | 
					d8e7d0e2bd | ||
| 
						 | 
					759f5b3349 | ||
| 
						 | 
					433c583cd7 | ||
| 
						 | 
					02f6f4902f | ||
| 
						 | 
					90fd0f5b42 | ||
| 
						 | 
					56f6e9310d | ||
| 
						 | 
					8bec4f1a79 | ||
| 
						 | 
					f00a162500 | ||
| 
						 | 
					1228bcaa0d | ||
| 
						 | 
					b94b757e1e | ||
| 
						 | 
					49fd0fef6b | ||
| 
						 | 
					8416129244 | ||
| 
						 | 
					b329581e8e | ||
| 
						 | 
					0117473049 | ||
| 
						 | 
					09e8d81a53 | ||
| 
						 | 
					317325ed54 | ||
| 
						 | 
					6f9deb5b47 | ||
| 
						 | 
					21fc2af47e | ||
| 
						 | 
					3d0906496b | ||
| 
						 | 
					f47f37485e | ||
| 
						 | 
					3876196da4 | ||
| 
						 | 
					808f1706c2 | ||
| 
						 | 
					0f5dc427f6 | ||
| 
						 | 
					28de76ed58 | ||
| 
						 | 
					4e9ef2eea3 | ||
| 
						 | 
					a1f42a8e88 | ||
| 
						 | 
					baffb459d8 | ||
| 
						 | 
					381deeed8f | ||
| 
						 | 
					6f37aa5e65 | ||
| 
						 | 
					4343bc5e86 | ||
| 
						 | 
					255e8cb60b | ||
| 
						 | 
					6bd7f256ae | ||
| 
						 | 
					5d1d269f45 | ||
| 
						 | 
					e152c0b9e6 | ||
| 
						 | 
					cd55e7238a | ||
| 
						 | 
					dfac9aef46 | ||
| 
						 | 
					1835cb731d | ||
| 
						 | 
					ab418f0317 | ||
| 
						 | 
					4fb4548a57 | ||
| 
						 | 
					ec2012f736 | ||
| 
						 | 
					93903e1edf | ||
| 
						 | 
					500806dda9 | ||
| 
						 | 
					7e134dfb8e | ||
| 
						 | 
					dee7712483 | ||
| 
						 | 
					cfd3d9413b | ||
| 
						 | 
					5feef4f92b | ||
| 
						 | 
					9644179f39 | ||
| 
						 | 
					9142bc74bb | ||
| 
						 | 
					9518d362ab | ||
| 
						 | 
					529267fe5d | ||
| 
						 | 
					c3606d4127 | ||
| 
						 | 
					d7a3cf4744 | ||
| 
						 | 
					fd3e9e102d | ||
| 
						 | 
					7264da9af1 | ||
| 
						 | 
					c0f8f6270e | ||
| 
						 | 
					13c67c55af | ||
| 
						 | 
					538e7737d2 | ||
| 
						 | 
					f72b203392 | ||
| 
						 | 
					ea617ea71c | ||
| 
						 | 
					b05ae8b950 | ||
| 
						 | 
					cb09dc1274 | ||
| 
						 | 
					6979dccd79 | ||
| 
						 | 
					0942afa35d | ||
| 
						 | 
					fe5199c506 | ||
| 
						 | 
					ea9d0a19ca | ||
| 
						 | 
					f41e4fba91 | ||
| 
						 | 
					7c979db7a9 | ||
| 
						 | 
					efa33f0b49 | ||
| 
						 | 
					5aa7a0ec1c | ||
| 
						 | 
					7281c3ab01 | ||
| 
						 | 
					27393d999c | ||
| 
						 | 
					2ff68cece1 | ||
| 
						 | 
					c25ad6e873 | ||
| 
						 | 
					e756b80f56 | ||
| 
						 | 
					079473f10a | ||
| 
						 | 
					ba92f67e23 | ||
| 
						 | 
					e1eeb8e908 | ||
| 
						 | 
					76b1e2d9b1 | ||
| 
						 | 
					8aa66458a3 | ||
| 
						 | 
					9abe5853b2 | ||
| 
						 | 
					a563ef56b8 | ||
| 
						 | 
					3486e8332d | ||
| 
						 | 
					cf22ba1971 | ||
| 
						 | 
					3e8e48f9d0 | ||
| 
						 | 
					6bcd3263c2 | ||
| 
						 | 
					f7a26917f2 | ||
| 
						 | 
					946166795e | ||
| 
						 | 
					62fa6a8289 | ||
| 
						 | 
					8aa21348d1 | ||
| 
						 | 
					8d3933945a | ||
| 
						 | 
					06849a0d6a | ||
| 
						 | 
					491d106031 | ||
| 
						 | 
					9fae965546 | ||
| 
						 | 
					57979a273c | ||
| 
						 | 
					4174dad301 | ||
| 
						 | 
					a1224b2da8 | ||
| 
						 | 
					440a4d4c76 | ||
| 
						 | 
					3a55acee5b | ||
| 
						 | 
					dd0fc6d3a8 | ||
| 
						 | 
					5c9bebee8a | ||
| 
						 | 
					de0822a2bf | ||
| 
						 | 
					693e6e76a9 | ||
| 
						 | 
					5463a05a32 | ||
| 
						 | 
					e3b4fe6ed2 | ||
| 
						 | 
					921de583f4 | ||
| 
						 | 
					e31a3a6da6 | ||
| 
						 | 
					55bdb63f34 | ||
| 
						 | 
					75fe459800 | ||
| 
						 | 
					5bafde0b6f | ||
| 
						 | 
					57fafd762f | ||
| 
						 | 
					642da16c33 | ||
| 
						 | 
					661f154b66 | ||
| 
						 | 
					8227bf45d1 | ||
| 
						 | 
					ad96b1b460 | ||
| 
						 | 
					ee1e9fcd22 | ||
| 
						 | 
					7da3845926 | ||
| 
						 | 
					8a3960d217 | ||
| 
						 | 
					99a1830b46 | ||
| 
						 | 
					6cf41f5503 | ||
| 
						 | 
					51c8cf97af | ||
| 
						 | 
					46a75dedb4 | ||
| 
						 | 
					f4cb382829 | ||
| 
						 | 
					c06fdae782 | ||
| 
						 | 
					47bc4f5191 | ||
| 
						 | 
					52eae5fec2 | ||
| 
						 | 
					d3e0fc4374 | ||
| 
						 | 
					e906e9a160 | ||
| 
						 | 
					9e1ccf81c7 | ||
| 
						 | 
					88f8cbbb2e | ||
| 
						 | 
					235028bf0f | ||
| 
						 | 
					93bb35fd2b | ||
| 
						 | 
					d3923ece3d | ||
| 
						 | 
					58044875a8 | ||
| 
						 | 
					88bf72d388 | ||
| 
						 | 
					59bcd5a1cf | ||
| 
						 | 
					b0f1e29335 | ||
| 
						 | 
					1b9a70b6af | ||
| 
						 | 
					d0b237f46c | ||
| 
						 | 
					0857bdba0f | ||
| 
						 | 
					a1e1561a91 | ||
| 
						 | 
					219fa54fd4 | ||
| 
						 | 
					2b61011439 | ||
| 
						 | 
					6298758992 | ||
| 
						 | 
					14a165bf3f | ||
| 
						 | 
					a9ac026781 | ||
| 
						 | 
					27949793ae | ||
| 
						 | 
					e4de6d2ee0 | ||
| 
						 | 
					dc1d4e2444 | ||
| 
						 | 
					6b864994f3 | ||
| 
						 | 
					55f7917356 | ||
| 
						 | 
					2d4b741115 | ||
| 
						 | 
					bd7ec82f64 | ||
| 
						 | 
					b3d86a26a6 | ||
| 
						 | 
					cd143dc253 | ||
| 
						 | 
					b82e7a4fcd | ||
| 
						 | 
					7a17af253d | ||
| 
						 | 
					6d6b259fc0 | ||
| 
						 | 
					1b068ee26b | ||
| 
						 | 
					c3c9864ed0 | ||
| 
						 | 
					9f2e5eee45 | ||
| 
						 | 
					042d98b2d2 | ||
| 
						 | 
					721119a388 | ||
| 
						 | 
					4403e98eba | ||
| 
						 | 
					5495ef8217 | ||
| 
						 | 
					a830fcbc34 | ||
| 
						 | 
					58d9230ce2 | ||
| 
						 | 
					aa8e6be045 | ||
| 
						 | 
					999263f18d | ||
| 
						 | 
					49d06db518 | ||
| 
						 | 
					15af345602 | ||
| 
						 | 
					cbea400d06 | ||
| 
						 | 
					8344acfa2d | ||
| 
						 | 
					80924bc9ff | ||
| 
						 | 
					824ec24322 | ||
| 
						 | 
					64b817cbc6 | ||
| 
						 | 
					37e5e5e9c2 | ||
| 
						 | 
					78b7b7db1a | ||
| 
						 | 
					b24e58c0ea | ||
| 
						 | 
					8d884c5894 | ||
| 
						 | 
					7dd63d8ff2 | ||
| 
						 | 
					204aaf2253 | ||
| 
						 | 
					02941f999c | ||
| 
						 | 
					bb69784719 | ||
| 
						 | 
					52a9ed70c4 | ||
| 
						 | 
					8ec116a6b8 | ||
| 
						 | 
					a9b96bc87a | ||
| 
						 | 
					078b23379e | ||
| 
						 | 
					cde518be8b | ||
| 
						 | 
					57781b3c41 | ||
| 
						 | 
					95abf92593 | ||
| 
						 | 
					fcc74c44e0 | ||
| 
						 | 
					f0509623ce | ||
| 
						 | 
					4a927fd6db | ||
| 
						 | 
					2e72b04376 | ||
| 
						 | 
					d66df1becc | ||
| 
						 | 
					3ab1c64a47 | ||
| 
						 | 
					72a4b0eada | ||
| 
						 | 
					e0c7b65690 | ||
| 
						 | 
					13f9043a35 | ||
| 
						 | 
					9aa1e40276 | ||
| 
						 | 
					0d825ff728 | ||
| 
						 | 
					633ef1a00b | ||
| 
						 | 
					6deb7e25cc | ||
| 
						 | 
					e55220e27a | ||
| 
						 | 
					60d8256c38 | ||
| 
						 | 
					4c10cc98c7 | ||
| 
						 | 
					8b10abd792 | ||
| 
						 | 
					108cfe0b0b | ||
| 
						 | 
					f8484c44cc | ||
| 
						 | 
					f1f5572fbb | ||
| 
						 | 
					367ae9e86d | ||
| 
						 | 
					a21275e1b2 | ||
| 
						 | 
					0ae01cf29d | ||
| 
						 | 
					986a6d9d85 | ||
| 
						 | 
					4c1d56cdcf | ||
| 
						 | 
					a6d0767d3e | ||
| 
						 | 
					7411ce05c6 | ||
| 
						 | 
					a1c4a54ada | ||
| 
						 | 
					96f7c3e2da | ||
| 
						 | 
					e60993068c | ||
| 
						 | 
					dddf30e354 | ||
| 
						 | 
					26ab12e69d | ||
| 
						 | 
					dd815a4f7b | ||
| 
						 | 
					bc33c1cda4 | ||
| 
						 | 
					3d48fc1324 | ||
| 
						 | 
					b589204e85 | ||
| 
						 | 
					8e24709ef2 | ||
| 
						 | 
					eb668d8981 | ||
| 
						 | 
					988e809ed4 | ||
| 
						 | 
					b5518cb1ea | ||
| 
						 | 
					d2c074bf06 | ||
| 
						 | 
					ba89f47b8d | ||
| 
						 | 
					0c789c6a9c | ||
| 
						 | 
					2da3c698fd | ||
| 
						 | 
					5584ecf7a2 | ||
| 
						 | 
					c93cfc6a13 | ||
| 
						 | 
					bd2ea128e0 | ||
| 
						 | 
					1ee4955b70 | ||
| 
						 | 
					f0c52912f0 | ||
| 
						 | 
					3eb6a4adb6 | ||
| 
						 | 
					1b990cc8aa | ||
| 
						 | 
					520afb5a43 | ||
| 
						 | 
					69af4ab3ae | ||
| 
						 | 
					01da72eb3a | ||
| 
						 | 
					815f56fd90 | ||
| 
						 | 
					be88d03380 | ||
| 
						 | 
					d25d6d456f | ||
| 
						 | 
					2371f76c73 | ||
| 
						 | 
					1e6910032e | ||
| 
						 | 
					3b0407ad83 | ||
| 
						 | 
					00c752b931 | ||
| 
						 | 
					1a7644a0f6 | ||
| 
						 | 
					b3d6e05694 | ||
| 
						 | 
					2f6fbed90b | ||
| 
						 | 
					25227bfccb | ||
| 
						 | 
					ae6833c8fa | ||
| 
						 | 
					db6bf15fcd | ||
| 
						 | 
					caa3faa47e | ||
| 
						 | 
					56a076fb9e | ||
| 
						 | 
					32227d4720 | ||
| 
						 | 
					4d126a5a80 | ||
| 
						 | 
					d6ecde875a | ||
| 
						 | 
					134641d62d | ||
| 
						 | 
					d577391181 | ||
| 
						 | 
					70a441fcda | ||
| 
						 | 
					b316ae6fd1 | ||
| 
						 | 
					7ca380cf6d | ||
| 
						 | 
					c4c8553390 | ||
| 
						 | 
					485734ae74 | ||
| 
						 | 
					da4dca3881 | ||
| 
						 | 
					19af11c2eb | ||
| 
						 | 
					6fbce7358c | ||
| 
						 | 
					9ebfab3a9f | ||
| 
						 | 
					e8d6ac48a7 | ||
| 
						 | 
					a947464d4c | ||
| 
						 | 
					1bab67020c | ||
| 
						 | 
					264ca9ba32 | ||
| 
						 | 
					e99a9fec1b | ||
| 
						 | 
					0e7603ecbb | ||
| 
						 | 
					2d603339f1 | ||
| 
						 | 
					d39f58ac2e | ||
| 
						 | 
					8ae8b9600c | ||
| 
						 | 
					cdf67ba0d0 | ||
| 
						 | 
					03a4d297db | ||
| 
						 | 
					4486b3b6a5 | ||
| 
						 | 
					8ffa1880be | ||
| 
						 | 
					eadb017622 | ||
| 
						 | 
					9c5039d3e1 | ||
| 
						 | 
					8b7c241b1a | ||
| 
						 | 
					bb8a42ff56 | ||
| 
						 | 
					cb961cdc83 | ||
| 
						 | 
					15812aae51 | ||
| 
						 | 
					f924413d23 | ||
| 
						 | 
					23177b8aad | ||
| 
						 | 
					22e6256d00 | ||
| 
						 | 
					b9f1afd47c | ||
| 
						 | 
					98b5d31edd | ||
| 
						 | 
					209bd9887c | ||
| 
						 | 
					82a46ed62c | ||
| 
						 | 
					cde3a58d4e | ||
| 
						 | 
					1d5d5e41f7 | ||
| 
						 | 
					20e6a4528a | ||
| 
						 | 
					7aa87822f7 | ||
| 
						 | 
					69359fcc6a | ||
| 
						 | 
					bc69125ef0 | ||
| 
						 | 
					f542af20e2 | ||
| 
						 | 
					42a14fa876 | ||
| 
						 | 
					09f8dcdd7e | ||
| 
						 | 
					0fd3c2aa2b | ||
| 
						 | 
					80cdb5240e | ||
| 
						 | 
					5ee6718daa | ||
| 
						 | 
					13cca48ddc | ||
| 
						 | 
					f5aee12510 | ||
| 
						 | 
					7b2a7b7c43 | ||
| 
						 | 
					755de5972d | ||
| 
						 | 
					25fa1c2783 | ||
| 
						 | 
					48d03bb158 | ||
| 
						 | 
					3b704b8e5d | ||
| 
						 | 
					a675bc3d0a | ||
| 
						 | 
					c71178b1ab | ||
| 
						 | 
					cf3d037c96 | ||
| 
						 | 
					493ea6330b | ||
| 
						 | 
					c7b5b355f7 | ||
| 
						 | 
					1fcd3fc4b5 | ||
| 
						 | 
					b7bbad9964 | ||
| 
						 | 
					bd86888d74 | ||
| 
						 | 
					cd99a84e2b | ||
| 
						 | 
					9b55b4e08e | ||
| 
						 | 
					5a6a8f4897 | ||
| 
						 | 
					2604d06ec8 | ||
| 
						 | 
					9709a27cb6 | ||
| 
						 | 
					04275a672a | ||
| 
						 | 
					9c1f0f4aef | ||
| 
						 | 
					45e1399532 | ||
| 
						 | 
					ed6d3763da | ||
| 
						 | 
					5c796f3378 | ||
| 
						 | 
					887c9834bb | ||
| 
						 | 
					e8c577fc2e | ||
| 
						 | 
					692d718d9d | ||
| 
						 | 
					bc8bfff5ff | ||
| 
						 | 
					6e2fdfed67 | ||
| 
						 | 
					3f59f7e14f | ||
| 
						 | 
					8bf74e77c0 | ||
| 
						 | 
					79835da163 | ||
| 
						 | 
					90f6336f85 | ||
| 
						 | 
					4f12b7ad6a | ||
| 
						 | 
					e610f31ca4 | ||
| 
						 | 
					0f220e5858 | ||
| 
						 | 
					7679ee9535 | ||
| 
						 | 
					a374aed61c | ||
| 
						 | 
					866b21532a | ||
| 
						 | 
					fc260f5bcb | ||
| 
						 | 
					c239c824f5 | ||
| 
						 | 
					d1be6a0c37 | ||
| 
						 | 
					9f4ef9fda6 | ||
| 
						 | 
					2a8662ce2e | ||
| 
						 | 
					6de64854a8 | ||
| 
						 | 
					a4ddd21f8e | ||
| 
						 | 
					cd2eab0d10 | ||
| 
						 | 
					edb7aaf046 | ||
| 
						 | 
					10c2510aaf | ||
| 
						 | 
					f8690cf8d5 | ||
| 
						 | 
					49e3017e4a | ||
| 
						 | 
					5c5acddf01 | ||
| 
						 | 
					f5dace2cb6 | ||
| 
						 | 
					783b4e1068 | ||
| 
						 | 
					c752c23d33 | ||
| 
						 | 
					2fd1acc4dd | ||
| 
						 | 
					c954b73149 | ||
| 
						 | 
					681ceb16d8 | ||
| 
						 | 
					54e43fd3de | ||
| 
						 | 
					878960cdba | ||
| 
						 | 
					1ec22a4f73 | ||
| 
						 | 
					f4668058b4 | ||
| 
						 | 
					2e36a19e52 | ||
| 
						 | 
					e65626090b | ||
| 
						 | 
					b39f294d02 | ||
| 
						 | 
					0372454d07 | ||
| 
						 | 
					584a487461 | ||
| 
						 | 
					e9bdc318fd | ||
| 
						 | 
					d2cd3f4b76 | ||
| 
						 | 
					83b15720c0 | ||
| 
						 | 
					3701873dc9 | ||
| 
						 | 
					b105d7e207 | ||
| 
						 | 
					fea9b4eaa3 | ||
| 
						 | 
					eb050343b9 | ||
| 
						 | 
					4802bbc548 | ||
| 
						 | 
					3822c98285 | ||
| 
						 | 
					d70b1eea5d | ||
| 
						 | 
					0c92ec4d21 | ||
| 
						 | 
					fdeda0b438 | ||
| 
						 | 
					e7eebbc90f | ||
| 
						 | 
					fcbb8e5c5d | ||
| 
						 | 
					2c80ace622 | ||
| 
						 | 
					50a48b38f5 | ||
| 
						 | 
					76ab264200 | ||
| 
						 | 
					1986e51928 | ||
| 
						 | 
					f7235e7cb4 | ||
| 
						 | 
					857339758f | ||
| 
						 | 
					29044ecb22 | ||
| 
						 | 
					b47df54d48 | ||
| 
						 | 
					9f9b3e1e28 | ||
| 
						 | 
					43dce243ab | ||
| 
						 | 
					122476adc6 | ||
| 
						 | 
					1fef12cd31 | ||
| 
						 | 
					f53fb47dd9 | ||
| 
						 | 
					b79f082537 | ||
| 
						 | 
					b12ec9b372 | ||
| 
						 | 
					4121fbb8a4 | ||
| 
						 | 
					f683063d42 | ||
| 
						 | 
					c6d777289b | ||
| 
						 | 
					d75053e74f | ||
| 
						 | 
					27596fa624 | ||
| 
						 | 
					f8b4957694 | ||
| 
						 | 
					2daddac019 | ||
| 
						 | 
					a6d73dc760 | ||
| 
						 | 
					56fc7c0053 | ||
| 
						 | 
					4ffb50268a | ||
| 
						 | 
					3473d2f219 | ||
| 
						 | 
					4a59dda8aa | ||
| 
						 | 
					222bbab442 | ||
| 
						 | 
					3589d75998 | ||
| 
						 | 
					3016856a4c | ||
| 
						 | 
					e0948b5825 | ||
| 
						 | 
					691157a71e | ||
| 
						 | 
					e63febe5ec | ||
| 
						 | 
					88c3d4b61a | ||
| 
						 | 
					fcdcef33c3 | ||
| 
						 | 
					ead841e0a3 | ||
| 
						 | 
					26f43649f9 | ||
| 
						 | 
					d1f949465f | ||
| 
						 | 
					57f1027a03 | ||
| 
						 | 
					7f7e0704f6 | ||
| 
						 | 
					ed3d5e9409 | ||
| 
						 | 
					f0633627b4 | ||
| 
						 | 
					1dd5dfed81 | ||
| 
						 | 
					2d2d9ac875 | ||
| 
						 | 
					3416af3f5d | ||
| 
						 | 
					4da6e11c5a | ||
| 
						 | 
					bd085674b2 | ||
| 
						 | 
					71ee4b8d25 | ||
| 
						 | 
					1fd620a436 | ||
| 
						 | 
					5764014aa3 | ||
| 
						 | 
					cc12990b2f | ||
| 
						 | 
					a6791e34ba | ||
| 
						 | 
					8deff7018a | ||
| 
						 | 
					48b9cbab24 | ||
| 
						 | 
					4c71c99934 | ||
| 
						 | 
					8ed5c47ce5 | ||
| 
						 | 
					9c2095311e | ||
| 
						 | 
					5d604a99f6 | ||
| 
						 | 
					283094fb67 | ||
| 
						 | 
					4e8d5bc726 | ||
| 
						 | 
					e7bc2978e5 | ||
| 
						 | 
					1e32e75ee4 | ||
| 
						 | 
					c6e1353c4d | ||
| 
						 | 
					d00941c9a4 | ||
| 
						 | 
					373b717a5f | ||
| 
						 | 
					2729ca70bc | ||
| 
						 | 
					ef2a81b860 | ||
| 
						 | 
					3157f8e8fa | ||
| 
						 | 
					638409a573 | ||
| 
						 | 
					def057522f | ||
| 
						 | 
					1f92ab6e8a | ||
| 
						 | 
					2f64783850 | ||
| 
						 | 
					6b1629455a | ||
| 
						 | 
					1d251c85da | ||
| 
						 | 
					3fa30a939f | ||
| 
						 | 
					9cd366bf2b | ||
| 
						 | 
					d283be0597 | ||
| 
						 | 
					fb38615cf6 | ||
| 
						 | 
					c7ea2c24f8 | ||
| 
						 | 
					a456d3c77f | ||
| 
						 | 
					1a82ef4386 | ||
| 
						 | 
					8ae350ee06 | ||
| 
						 | 
					1c088b0a2b | ||
| 
						 | 
					dab5a7fad0 | ||
| 
						 | 
					cc8b9dd973 | ||
| 
						 | 
					a6fd7ce6a5 | ||
| 
						 | 
					7b3831d001 | ||
| 
						 | 
					c110bc0154 | ||
| 
						 | 
					e9bafdd2ce | ||
| 
						 | 
					7aa34a6a19 | ||
| 
						 | 
					304c544ce5 | ||
| 
						 | 
					9ee3f61aee | ||
| 
						 | 
					ff9808505b | ||
| 
						 | 
					e2749ba847 | ||
| 
						 | 
					80b6a3a309 | ||
| 
						 | 
					1207e7a5b1 | ||
| 
						 | 
					fa6b41848e | ||
| 
						 | 
					48f57c1cf0 | ||
| 
						 | 
					6a9d54829f | ||
| 
						 | 
					77bc50144c | ||
| 
						 | 
					a94299f451 | ||
| 
						 | 
					5c11544dc1 | ||
| 
						 | 
					747060fe19 | ||
| 
						 | 
					40f8cf3f7c | ||
| 
						 | 
					ba230df659 | ||
| 
						 | 
					528c26a1ce | ||
| 
						 | 
					75394455bc | ||
| 
						 | 
					b565cb3503 | ||
| 
						 | 
					6e181ba96d | ||
| 
						 | 
					cd1e29b180 | ||
| 
						 | 
					b0f8a418b5 | ||
| 
						 | 
					adc43e35d3 | ||
| 
						 | 
					02155338a6 | ||
| 
						 | 
					396ebcef66 | ||
| 
						 | 
					a9f4775dc3 | ||
| 
						 | 
					34d290b424 | ||
| 
						 | 
					8d1a933b76 | ||
| 
						 | 
					52301e7c5d | ||
| 
						 | 
					d9f3c324e6 | ||
| 
						 | 
					719a9e4605 | ||
| 
						 | 
					3bb7050e14 | ||
| 
						 | 
					572d99cacc | ||
| 
						 | 
					f89aa98af5 | ||
| 
						 | 
					0168b2fe11 | ||
| 
						 | 
					2c9cf3b73b | ||
| 
						 | 
					eb0af241f1 | ||
| 
						 | 
					39feace42e | ||
| 
						 | 
					2d8a2f35c7 | ||
| 
						 | 
					d954a7f991 | ||
| 
						 | 
					40a234183c | ||
| 
						 | 
					bfd774a20a | ||
| 
						 | 
					7d8e615c0b | ||
| 
						 | 
					0bab63a818 | ||
| 
						 | 
					3f21a5341d | ||
| 
						 | 
					d8487f1f4f | ||
| 
						 | 
					5bd65a2834 | ||
| 
						 | 
					61b33c0a0a | ||
| 
						 | 
					a083187168 | ||
| 
						 | 
					af71952d7a | ||
| 
						 | 
					ad67fb4b73 | ||
| 
						 | 
					e6273046f4 | ||
| 
						 | 
					4961eeba52 | ||
| 
						 | 
					58da345e4e | ||
| 
						 | 
					8ff2e245ac | ||
| 
						 | 
					83ca5e6d5c | ||
| 
						 | 
					d05c996d48 | ||
| 
						 | 
					867e4cfffb | ||
| 
						 | 
					10ab5428df | ||
| 
						 | 
					704cb6b4e9 | ||
| 
						 | 
					c455c4c1d9 | ||
| 
						 | 
					d19192b20e | ||
| 
						 | 
					054c6c890a | ||
| 
						 | 
					ebb39e1041 | ||
| 
						 | 
					c5120c1a7a | ||
| 
						 | 
					0de26cd346 | ||
| 
						 | 
					77729280f6 | ||
| 
						 | 
					f5a8f2d2ca | ||
| 
						 | 
					e4b64bf719 | ||
| 
						 | 
					096dbb58f9 | ||
| 
						 | 
					0b13efd7e5 | ||
| 
						 | 
					d522fa71f0 | ||
| 
						 | 
					ccc01ce94b | ||
| 
						 | 
					0031b78938 | ||
| 
						 | 
					5c216d6eb2 | ||
| 
						 | 
					c147bbddb3 | ||
| 
						 | 
					985a6a65cb | ||
| 
						 | 
					9ab111abc0 | ||
| 
						 | 
					eced331945 | ||
| 
						 | 
					6f6b2cdc52 | ||
| 
						 | 
					d91c270d1c | ||
| 
						 | 
					1f5226d652 | ||
| 
						 | 
					997dabdb9e | ||
| 
						 | 
					b90e9912f1 | ||
| 
						 | 
					fa784f6198 | ||
| 
						 | 
					066465803c | ||
| 
						 | 
					118fa896b7 | ||
| 
						 | 
					4c76c264dc | ||
| 
						 | 
					66fc323292 | ||
| 
						 | 
					dbe351860e | ||
| 
						 | 
					178675bec5 | ||
| 
						 | 
					2254b74598 | ||
| 
						 | 
					26c828a598 | ||
| 
						 | 
					c4d973530f | ||
| 
						 | 
					731c45ff37 | ||
| 
						 | 
					0b97ce28d6 | ||
| 
						 | 
					51e1300519 | ||
| 
						 | 
					5c43b9bda7 | ||
| 
						 | 
					d60c24dda8 | ||
| 
						 | 
					4020e6db24 | ||
| 
						 | 
					38c4b48f33 | ||
| 
						 | 
					dc2a994176 | ||
| 
						 | 
					93b7108bf7 | ||
| 
						 | 
					6fb30e2313 | ||
| 
						 | 
					b300359824 | ||
| 
						 | 
					fbacf137f2 | ||
| 
						 | 
					750fff3bc7 | ||
| 
						 | 
					0064f3a9a8 | ||
| 
						 | 
					8f263acd48 | ||
| 
						 | 
					4c503ee2a6 | ||
| 
						 | 
					13023bf932 | ||
| 
						 | 
					8f6b060e7f | ||
| 
						 | 
					37086f40a1 | ||
| 
						 | 
					946f96cda5 | ||
| 
						 | 
					c6a99b7ccb | ||
| 
						 | 
					ab52d127bb | ||
| 
						 | 
					6ab3b611c7 | ||
| 
						 | 
					735254fba4 | ||
| 
						 | 
					29ab9ad5b3 | ||
| 
						 | 
					b87604e649 | ||
| 
						 | 
					4fad401cd2 | ||
| 
						 | 
					cc00073da7 | ||
| 
						 | 
					bd1f90fd60 | ||
| 
						 | 
					7058ed4431 | ||
| 
						 | 
					4332bb3951 | ||
| 
						 | 
					c5bfcfd65e | ||
| 
						 | 
					3bb841dfa1 | ||
| 
						 | 
					571a3ecff0 | ||
| 
						 | 
					19a05d9764 | ||
| 
						 | 
					927e33104a | ||
| 
						 | 
					2955689c71 | ||
| 
						 | 
					a35e96114f | ||
| 
						 | 
					5fd6065e99 | ||
| 
						 | 
					0cf914b095 | ||
| 
						 | 
					787fa3705d | ||
| 
						 | 
					a684497b3d | ||
| 
						 | 
					18d2cd332b | ||
| 
						 | 
					9a9dde2d8c | ||
| 
						 | 
					470f8b1266 | ||
| 
						 | 
					219b1d015b | ||
| 
						 | 
					0e29db4a51 | ||
| 
						 | 
					fff1723b6f | ||
| 
						 | 
					93cecfbfb6 | ||
| 
						 | 
					64d62e1ded | ||
| 
						 | 
					7ad0d47c3c | ||
| 
						 | 
					cc2dcab096 | ||
| 
						 | 
					25f72cfd07 | ||
| 
						 | 
					0390acff8c | ||
| 
						 | 
					86f87f9673 | ||
| 
						 | 
					f19d62c8b2 | ||
| 
						 | 
					48aa36a654 | ||
| 
						 | 
					9c3fd6948b | ||
| 
						 | 
					c65ebf3e70 | ||
| 
						 | 
					430335e24e | ||
| 
						 | 
					e56eaf05f9 | ||
| 
						 | 
					e9bfcd0df0 | ||
| 
						 | 
					340f6f334b | ||
| 
						 | 
					46e3fe8cf4 | ||
| 
						 | 
					311d319e0a | ||
| 
						 | 
					6447934cff | ||
| 
						 | 
					739cca872a | ||
| 
						 | 
					0deb49e2b6 | ||
| 
						 | 
					bd7f41d83c | ||
| 
						 | 
					f9213d84e4 | ||
| 
						 | 
					ab42676eff | ||
| 
						 | 
					67d0232816 | ||
| 
						 | 
					b43795c364 | ||
| 
						 | 
					9f6098f724 | ||
| 
						 | 
					46d6fcc99a | ||
| 
						 | 
					63fe43c2f9 | ||
| 
						 | 
					45e96ab875 | ||
| 
						 | 
					65073ca838 | ||
| 
						 | 
					96854e8d35 | ||
| 
						 | 
					ced0c8cbd6 | ||
| 
						 | 
					01d49d0e71 | ||
| 
						 | 
					801a1b1352 | ||
| 
						 | 
					b4c05c8519 | ||
| 
						 | 
					9482fdae35 | ||
| 
						 | 
					63019dc656 | ||
| 
						 | 
					c3f5210734 | ||
| 
						 | 
					5c4c36b135 | ||
| 
						 | 
					4b20b480b1 | ||
| 
						 | 
					0574adcaa1 | ||
| 
						 | 
					c33c147c9b | ||
| 
						 | 
					95dd4eae53 | ||
| 
						 | 
					f2bf7a1cc0 | ||
| 
						 | 
					a2146d6548 | ||
| 
						 | 
					3082fa5d4c | ||
| 
						 | 
					7d6fed35c0 | ||
| 
						 | 
					81535db537 | ||
| 
						 | 
					b33c9d313f | ||
| 
						 | 
					503190e499 | ||
| 
						 | 
					fdbde27ed9 | ||
| 
						 | 
					54350d68ce | ||
| 
						 | 
					f342b6a862 | ||
| 
						 | 
					28b6842556 | ||
| 
						 | 
					ecb4ee0b5a | ||
| 
						 | 
					05e87b6b65 | ||
| 
						 | 
					9f228ea974 | ||
| 
						 | 
					e36cd89437 | ||
| 
						 | 
					d8f02da1e4 | ||
| 
						 | 
					789ed50712 | ||
| 
						 | 
					df4758d73b | ||
| 
						 | 
					8cccdb25a9 | ||
| 
						 | 
					e1154dd09e | ||
| 
						 | 
					8e5d1c93eb | ||
| 
						 | 
					f20e649ad1 | ||
| 
						 | 
					8e72b3d6d6 | ||
| 
						 | 
					8970d1b895 | ||
| 
						 | 
					056828e039 | ||
| 
						 | 
					8e1761a804 | ||
| 
						 | 
					4ac59193ee | ||
| 
						 | 
					668f986b05 | ||
| 
						 | 
					2d812dea99 | ||
| 
						 | 
					e0c9b24a6d | ||
| 
						 | 
					b546c17105 | ||
| 
						 | 
					1c8512eb62 | ||
| 
						 | 
					841a541051 | ||
| 
						 | 
					4c67e55066 | ||
| 
						 | 
					136c2e70dc | ||
| 
						 | 
					f8b6b122ca | ||
| 
						 | 
					7a16e1f399 | ||
| 
						 | 
					e66cd0dc35 | ||
| 
						 | 
					4ccc44282e | ||
| 
						 | 
					2b069d2ca5 | ||
| 
						 | 
					566939185e | ||
| 
						 | 
					1ba4781cb0 | ||
| 
						 | 
					2c860451a9 | ||
| 
						 | 
					688a4e87ce | ||
| 
						 | 
					7cd8120de1 | ||
| 
						 | 
					225d1df8a7 | ||
| 
						 | 
					459f6c60e6 | ||
| 
						 | 
					1dc49506bc | ||
| 
						 | 
					f7b3c167b0 | ||
| 
						 | 
					9f67b0f0ed | ||
| 
						 | 
					7970cad6de | ||
| 
						 | 
					84a6c240d5 | ||
| 
						 | 
					8f03913e0b | ||
| 
						 | 
					30776aea04 | ||
| 
						 | 
					ec000e1dfa | ||
| 
						 | 
					4b22b81391 | ||
| 
						 | 
					cfafb8a92a | ||
| 
						 | 
					0eee66e257 | ||
| 
						 | 
					34be5fb50f | ||
| 
						 | 
					0c6b43a8ef | ||
| 
						 | 
					3dd7f795f5 | ||
| 
						 | 
					3f98a2885d | ||
| 
						 | 
					2fcba16688 | ||
| 
						 | 
					5beb23518d | ||
| 
						 | 
					cf332f746e | ||
| 
						 | 
					2df71f33ac | ||
| 
						 | 
					61a821884d | ||
| 
						 | 
					0952bf42a8 | ||
| 
						 | 
					06577e86d8 | ||
| 
						 | 
					589154d209 | ||
| 
						 | 
					73c5f313e5 | ||
| 
						 | 
					637245e9f5 | ||
| 
						 | 
					e2aa3cf6ae | ||
| 
						 | 
					08315e3ac4 | ||
| 
						 | 
					e145fa0e83 | ||
| 
						 | 
					07324d6221 | ||
| 
						 | 
					ec8423ad76 | ||
| 
						 | 
					d5b96bdd95 | ||
| 
						 | 
					eed2109a93 | ||
| 
						 | 
					283f4a0649 | ||
| 
						 | 
					fe4a490ff3 | ||
| 
						 | 
					20f055bcb4 | ||
| 
						 | 
					daf9efb723 | ||
| 
						 | 
					2e7ab82b92 | ||
| 
						 | 
					0fac155599 | ||
| 
						 | 
					77d16e2e39 | ||
| 
						 | 
					de0e6b4119 | ||
| 
						 | 
					1c365783e8 | ||
| 
						 | 
					eb81f7ab87 | ||
| 
						 | 
					ed04c9d702 | ||
| 
						 | 
					ea687806b3 | ||
| 
						 | 
					1a3dab6075 | ||
| 
						 | 
					e828044efd | ||
| 
						 | 
					a084548cce | ||
| 
						 | 
					8d9710bed6 | ||
| 
						 | 
					0783429215 | ||
| 
						 | 
					0d7965aeca | ||
| 
						 | 
					b5997e5b05 | ||
| 
						 | 
					fbcc8450b8 | ||
| 
						 | 
					24e1d27e54 | ||
| 
						 | 
					ec98c72b04 | ||
| 
						 | 
					4ec4a0c105 | ||
| 
						 | 
					3477dd6c19 | ||
| 
						 | 
					38444f0f13 | ||
| 
						 | 
					ffd363ef38 | ||
| 
						 | 
					c99e816790 | ||
| 
						 | 
					1bc531301e | ||
| 
						 | 
					7e6c6e0741 | ||
| 
						 | 
					9313eb28be | ||
| 
						 | 
					df535c251f | ||
| 
						 | 
					e954b58f29 | ||
| 
						 | 
					5b1254a741 | ||
| 
						 | 
					4626847312 | ||
| 
						 | 
					55a359615f | ||
| 
						 | 
					e5749424a4 | ||
| 
						 | 
					9ae83a8ea9 | ||
| 
						 | 
					55525d6a92 | ||
| 
						 | 
					f9ef876aab | ||
| 
						 | 
					691e08ff76 | ||
| 
						 | 
					763e834367 | ||
| 
						 | 
					359ca22912 | ||
| 
						 | 
					6094919b5c | ||
| 
						 | 
					ccadc42707 | ||
| 
						 | 
					e5d134ff97 | ||
| 
						 | 
					60578c20cb | ||
| 
						 | 
					bb7b8d8780 | ||
| 
						 | 
					76564e3168 | ||
| 
						 | 
					19f592f230 | ||
| 
						 | 
					a543712431 | ||
| 
						 | 
					10f5ecdc64 | ||
| 
						 | 
					4964e2d615 | ||
| 
						 | 
					4abb15db5f | ||
| 
						 | 
					bb685d4e6c | ||
| 
						 | 
					15d64a0899 | ||
| 
						 | 
					81594343d3 | ||
| 
						 | 
					fab0de8998 | ||
| 
						 | 
					42a13432d0 | ||
| 
						 | 
					db40789590 | ||
| 
						 | 
					af8966c42e | ||
| 
						 | 
					e01642db66 | ||
| 
						 | 
					9e1376e5a1 | ||
| 
						 | 
					28ba223ca9 | ||
| 
						 | 
					970f51c102 | ||
| 
						 | 
					fe920a6a65 | ||
| 
						 | 
					0ee514bc81 | ||
| 
						 | 
					6f86b62946 | ||
| 
						 | 
					761b6a2189 | ||
| 
						 | 
					7f77f9d400 | ||
| 
						 | 
					ce2c219999 | ||
| 
						 | 
					5771fee535 | ||
| 
						 | 
					2c8102f7a1 | ||
| 
						 | 
					28714df966 | ||
| 
						 | 
					7979602398 | ||
| 
						 | 
					c807c139bf | ||
| 
						 | 
					72ca3644cb | ||
| 
						 | 
					329213cc57 | ||
| 
						 | 
					dbcb996ba2 | ||
| 
						 | 
					52a85391f6 | ||
| 
						 | 
					67f4a7cec4 | ||
| 
						 | 
					a52b5b8b61 | ||
| 
						 | 
					77d331c2bb | ||
| 
						 | 
					4834e71812 | ||
| 
						 | 
					20fdf0231e | ||
| 
						 | 
					6a7c185e30 | ||
| 
						 | 
					be761afa4c | ||
| 
						 | 
					7d37e830ca | ||
| 
						 | 
					3777234077 | ||
| 
						 | 
					2ca65cc602 | ||
| 
						 | 
					c2ac1bee92 | ||
| 
						 | 
					51fb2c7551 | ||
| 
						 | 
					b904359bac | ||
| 
						 | 
					7c9f1ae834 | ||
| 
						 | 
					37bfb6508d | ||
| 
						 | 
					7b64fccba1 | ||
| 
						 | 
					95986e42a1 | ||
| 
						 | 
					d792fc925c | ||
| 
						 | 
					f9e419bad6 | ||
| 
						 | 
					9a3e6e423c | ||
| 
						 | 
					efe82852a3 | ||
| 
						 | 
					02dd81f4be | ||
| 
						 | 
					912c86e526 | ||
| 
						 | 
					0285bb3312 | ||
| 
						 | 
					935e65c9ae | ||
| 
						 | 
					39235f0894 | ||
| 
						 | 
					781242009d | ||
| 
						 | 
					d9b479b3c1 | ||
| 
						 | 
					a5543b5345 | ||
| 
						 | 
					f3342c7f89 | ||
| 
						 | 
					6f776305ee | ||
| 
						 | 
					938cc8daa7 | ||
| 
						 | 
					e63f55fcc7 | ||
| 
						 | 
					24e17116d3 | ||
| 
						 | 
					d6a05b6fd7 | ||
| 
						 | 
					9139a95616 | ||
| 
						 | 
					425d920af6 | ||
| 
						 | 
					3b2eb14eea | ||
| 
						 | 
					7722eea88c | ||
| 
						 | 
					c52cf64cea | ||
| 
						 | 
					d1ca1d9cb0 | ||
| 
						 | 
					ed244de069 | ||
| 
						 | 
					2b78acd736 | ||
| 
						 | 
					0967b9504b | ||
| 
						 | 
					79bed56a52 | ||
| 
						 | 
					87edad13ea | ||
| 
						 | 
					b7c85c8aa6 | ||
| 
						 | 
					207060d03c | ||
| 
						 | 
					b641164ece | ||
| 
						 | 
					8a997e48fb | ||
| 
						 | 
					af112eb2c9 | ||
| 
						 | 
					91419c3e86 | ||
| 
						 | 
					35c174671b | ||
| 
						 | 
					5a2322eb7d | ||
| 
						 | 
					63b91e514e | ||
| 
						 | 
					e65d6e4a11 | ||
| 
						 | 
					77392833f4 | ||
| 
						 | 
					5828e7e584 | ||
| 
						 | 
					efc5d04ec7 | ||
| 
						 | 
					ba7d6c9dd0 | ||
| 
						 | 
					81095cc6ea | ||
| 
						 | 
					103b5a7538 | ||
| 
						 | 
					1f7f7cb701 | ||
| 
						 | 
					83a0836f31 | ||
| 
						 | 
					7e3042b541 | ||
| 
						 | 
					7e27d8f4db | ||
| 
						 | 
					34b60db59f | ||
| 
						 | 
					42f177b3e2 | ||
| 
						 | 
					9f8c06b31c | ||
| 
						 | 
					98ac36c049 | ||
| 
						 | 
					69dda2cfa0 | ||
| 
						 | 
					251265821f | ||
| 
						 | 
					64f51a3797 | ||
| 
						 | 
					3b0651049b | ||
| 
						 | 
					f00b069236 | ||
| 
						 | 
					a754694221 | ||
| 
						 | 
					954464e5aa | ||
| 
						 | 
					57f9272a6a | ||
| 
						 | 
					649d3a0fdf | ||
| 
						 | 
					b74ae69aad | ||
| 
						 | 
					d951cb0e68 | ||
| 
						 | 
					1fa8125125 | ||
| 
						 | 
					f251589b6b | ||
| 
						 | 
					305e8a8a5c | ||
| 
						 | 
					2ebc24197a | ||
| 
						 | 
					db6446aa2f | ||
| 
						 | 
					9458a9da09 | ||
| 
						 | 
					8207745583 | ||
| 
						 | 
					b29742d2fa | ||
| 
						 | 
					c2759c3644 | ||
| 
						 | 
					a26bc49296 | ||
| 
						 | 
					999238d4fa | ||
| 
						 | 
					9e1eeffe6f | ||
| 
						 | 
					fb5983fb8f | ||
| 
						 | 
					4497409a31 | ||
| 
						 | 
					01b265e08d | ||
| 
						 | 
					012b164bae | ||
| 
						 | 
					2b6028fd13 | ||
| 
						 | 
					8420ee864d | ||
| 
						 | 
					d010b440a3 | ||
| 
						 | 
					e720e51548 | ||
| 
						 | 
					6bc394736e | ||
| 
						 | 
					be59769771 | ||
| 
						 | 
					07834012c5 | ||
| 
						 | 
					123c9b8de5 | ||
| 
						 | 
					1d250e8cb3 | ||
| 
						 | 
					7c626d5c9a | ||
| 
						 | 
					a2222288b5 | ||
| 
						 | 
					cb385da467 | ||
| 
						 | 
					0084e7b633 | ||
| 
						 | 
					e8dd7c08fe | ||
| 
						 | 
					1847de3d68 | ||
| 
						 | 
					d8d824c6c5 | ||
| 
						 | 
					77e3ec4e28 | ||
| 
						 | 
					0e88dec738 | ||
| 
						 | 
					4d86ffec2e | ||
| 
						 | 
					4366379b3d | ||
| 
						 | 
					876d50dbe2 | ||
| 
						 | 
					eae4a9eb03 | ||
| 
						 | 
					3a609bcd5d | ||
| 
						 | 
					4428aa0fdf | ||
| 
						 | 
					fef82df095 | ||
| 
						 | 
					359d2505d3 | ||
| 
						 | 
					d3d6337ecf | ||
| 
						 | 
					aa7198a530 | ||
| 
						 | 
					9e125c5708 | ||
| 
						 | 
					2b62190d4b | ||
| 
						 | 
					466c7e43b4 | ||
| 
						 | 
					41d9b8a647 | ||
| 
						 | 
					685e54f4dd | ||
| 
						 | 
					f84700a182 | ||
| 
						 | 
					46e72765b6 | ||
| 
						 | 
					20d6bb2d9c | ||
| 
						 | 
					51d61a76da | ||
| 
						 | 
					8fb9f86271 | ||
| 
						 | 
					0c586a7359 | ||
| 
						 | 
					938ebb30bf | ||
| 
						 | 
					b5d7757c3d | ||
| 
						 | 
					d8601fd4b6 | ||
| 
						 | 
					38c3277bf6 | ||
| 
						 | 
					20c6ce9e13 | ||
| 
						 | 
					d9785ae4f1 | ||
| 
						 | 
					b118538f94 | ||
| 
						 | 
					c2501a7747 | ||
| 
						 | 
					f19572f894 | ||
| 
						 | 
					03a1410b12 | ||
| 
						 | 
					40c79aba89 | ||
| 
						 | 
					68a58ad799 | ||
| 
						 | 
					ddb128b039 | ||
| 
						 | 
					3e881b9726 | ||
| 
						 | 
					7b0f2031c4 | ||
| 
						 | 
					786d8aa089 | ||
| 
						 | 
					263c008cf5 | ||
| 
						 | 
					7fdd43860e | ||
| 
						 | 
					06f8f76ca3 | ||
| 
						 | 
					79770354fe | ||
| 
						 | 
					e717fa3bef | ||
| 
						 | 
					227457e20d | ||
| 
						 | 
					9c2c45f192 | ||
| 
						 | 
					fd30a1c96e | ||
| 
						 | 
					c537579e61 | ||
| 
						 | 
					45ba9f9c2f | ||
| 
						 | 
					67f411afc0 | ||
| 
						 | 
					38d96413d0 | ||
| 
						 | 
					7d5f270516 | ||
| 
						 | 
					5c9b44a61e | ||
| 
						 | 
					fa61ff55de | ||
| 
						 | 
					9a45e3dbbb | ||
| 
						 | 
					5993dc5b48 | ||
| 
						 | 
					c9aeaebd1a | ||
| 
						 | 
					c588dfbdfa | ||
| 
						 | 
					bc7397105c | ||
| 
						 | 
					6795c361c1 | ||
| 
						 | 
					81957c524b | ||
| 
						 | 
					070787d579 | ||
| 
						 | 
					75029c2d42 | ||
| 
						 | 
					dcb8c448d3 | ||
| 
						 | 
					d55b658e6c | ||
| 
						 | 
					bb9b9c6514 | ||
| 
						 | 
					2163383728 | ||
| 
						 | 
					23b5c9b9e5 | ||
| 
						 | 
					179139735c | ||
| 
						 | 
					9938f0c674 | ||
| 
						 | 
					0de865f20b | ||
| 
						 | 
					fc04cb0266 | ||
| 
						 | 
					7f250ab142 | ||
| 
						 | 
					eb9b172ec0 | ||
| 
						 | 
					a499caabfb | ||
| 
						 | 
					c4dbd497b2 | ||
| 
						 | 
					ed08b81e18 | ||
| 
						 | 
					8a7a401cae | ||
| 
						 | 
					cb38146acb | ||
| 
						 | 
					1d96b805e1 | ||
| 
						 | 
					65a3e6454b | ||
| 
						 | 
					96171b0c03 | ||
| 
						 | 
					4dd4e14fd8 | ||
| 
						 | 
					01a0facd7e | ||
| 
						 | 
					7ef77b52a8 | ||
| 
						 | 
					249d85882f | ||
| 
						 | 
					5261cc0402 | ||
| 
						 | 
					5cbb49ed94 | ||
| 
						 | 
					c7c59e41cd | ||
| 
						 | 
					771b5db044 | ||
| 
						 | 
					d0ffde9114 | ||
| 
						 | 
					12353bda0a | ||
| 
						 | 
					e1b1f2f961 | ||
| 
						 | 
					d58036bc42 | ||
| 
						 | 
					83f5538979 | ||
| 
						 | 
					cdc08fcc63 | ||
| 
						 | 
					ec441b4c5b | ||
| 
						 | 
					f78aec2b52 | ||
| 
						 | 
					afc29a3d69 | ||
| 
						 | 
					251029609d | ||
| 
						 | 
					3a760ad8cd | ||
| 
						 | 
					37c5724db2 | ||
| 
						 | 
					1ebe15e7ce | ||
| 
						 | 
					aed211833d | ||
| 
						 | 
					e382b2b990 | ||
| 
						 | 
					2045501076 | ||
| 
						 | 
					f43f5f7004 | ||
| 
						 | 
					16aa248a35 | ||
| 
						 | 
					e50d9e2c57 | ||
| 
						 | 
					dad7e11288 | ||
| 
						 | 
					f09295a4bd | ||
| 
						 | 
					c0a8ab7699 | ||
| 
						 | 
					b11dd1f7b3 | ||
| 
						 | 
					6bea349da8 | ||
| 
						 | 
					02c2036731 | ||
| 
						 | 
					42ebbfa703 | ||
| 
						 | 
					8f1cc91a84 | ||
| 
						 | 
					9c1b192442 | ||
| 
						 | 
					b6791ca6e4 | ||
| 
						 | 
					b352da1cc7 | ||
| 
						 | 
					e8c5b0512d | ||
| 
						 | 
					a06a7a618c | ||
| 
						 | 
					252d74032a | ||
| 
						 | 
					6d194f2014 | ||
| 
						 | 
					5ff5555418 | ||
| 
						 | 
					8329e7dc19 | ||
| 
						 | 
					3a62b826ce | ||
| 
						 | 
					d09c912b81 | ||
| 
						 | 
					60963d276e | ||
| 
						 | 
					b44de841ff | ||
| 
						 | 
					c45e064975 | ||
| 
						 | 
					559d2923a7 | ||
| 
						 | 
					a683b0c993 | ||
| 
						 | 
					1ce9f8621b | ||
| 
						 | 
					84f191ce5a | ||
| 
						 | 
					577c542adc | ||
| 
						 | 
					a0866f0990 | ||
| 
						 | 
					29c9aced14 | ||
| 
						 | 
					c154d18b11 | ||
| 
						 | 
					6ed7b4d790 | ||
| 
						 | 
					73300f8977 | ||
| 
						 | 
					fc585fc2fb | ||
| 
						 | 
					713b630c66 | ||
| 
						 | 
					3d3f093b8c | ||
| 
						 | 
					9e12eb1cf5 | ||
| 
						 | 
					5c3949eac3 | ||
| 
						 | 
					d4fd789d78 | ||
| 
						 | 
					197d68a4d0 | ||
| 
						 | 
					4ae7c94196 | ||
| 
						 | 
					248426e1ee | ||
| 
						 | 
					b9d4336960 | ||
| 
						 | 
					c60ff20842 | ||
| 
						 | 
					e4b7c72b3a | ||
| 
						 | 
					6cbcd683ba | ||
| 
						 | 
					e50edb8410 | ||
| 
						 | 
					5b8845974c | ||
| 
						 | 
					2169ecd063 | ||
| 
						 | 
					74c10192aa | ||
| 
						 | 
					cb3031b7fe | ||
| 
						 | 
					61e665d65b | ||
| 
						 | 
					2d8c68d097 | ||
| 
						 | 
					9bcd306c02 | ||
| 
						 | 
					4fa5445562 | ||
| 
						 | 
					76b030d82e | ||
| 
						 | 
					2fef22fa85 | ||
| 
						 | 
					8440981845 | ||
| 
						 | 
					5ba08f195a | ||
| 
						 | 
					342e9fee4a | ||
| 
						 | 
					0db2d39105 | ||
| 
						 | 
					27e49620ec | ||
| 
						 | 
					f2439f2096 | ||
| 
						 | 
					3289982950 | ||
| 
						 | 
					f18ec47d42 | ||
| 
						 | 
					37f5c45dd5 | ||
| 
						 | 
					fdd24fd4e5 | ||
| 
						 | 
					66a6d5c073 | ||
| 
						 | 
					73b81bcd35 | ||
| 
						 | 
					4dff097f66 | ||
| 
						 | 
					ea0c01a2dd | ||
| 
						 | 
					e1ad66800a | ||
| 
						 | 
					f0306e63b2 | ||
| 
						 | 
					4dca082776 | ||
| 
						 | 
					4efa0617b9 | ||
| 
						 | 
					3216fba3ca | ||
| 
						 | 
					e954736299 | ||
| 
						 | 
					c7e561d33d | ||
| 
						 | 
					ce94c7ea73 | ||
| 
						 | 
					6789424259 | ||
| 
						 | 
					7a18ae6da4 | ||
| 
						 | 
					5f2829b0a0 | ||
| 
						 | 
					49376579bf | ||
| 
						 | 
					8a3e1de5c8 | ||
| 
						 | 
					6470c383b2 | ||
| 
						 | 
					cbfb6504a8 | ||
| 
						 | 
					a4cdc80836 | ||
| 
						 | 
					b598e9482d | ||
| 
						 | 
					0c83d60688 | ||
| 
						 | 
					d2a3f3afa1 | ||
| 
						 | 
					f1e5f9d8d5 | ||
| 
						 | 
					92c39fea53 | ||
| 
						 | 
					d67ac7ed5c | ||
| 
						 | 
					9e397d92f5 | ||
| 
						 | 
					f40795a119 | ||
| 
						 | 
					8d4f93634f | ||
| 
						 | 
					c141fe1c44 | ||
| 
						 | 
					2e776f6b50 | ||
| 
						 | 
					437dac07eb | ||
| 
						 | 
					77e3610e1a | ||
| 
						 | 
					a23f91ad2f | ||
| 
						 | 
					4fef104bf1 | ||
| 
						 | 
					57f8bc3081 | ||
| 
						 | 
					40fbdb71bd | ||
| 
						 | 
					7cbf6fa3a6 | ||
| 
						 | 
					019423f769 | ||
| 
						 | 
					4114ac5d22 | ||
| 
						 | 
					1a2e58b067 | ||
| 
						 | 
					9ce215ed01 | ||
| 
						 | 
					ad7bccb8ea | ||
| 
						 | 
					3621b75306 | ||
| 
						 | 
					14908e3a3b | ||
| 
						 | 
					7ce032b99d | ||
| 
						 | 
					dcaf6313af | ||
| 
						 | 
					b74d30d55a | ||
| 
						 | 
					9c705ce71e | ||
| 
						 | 
					16af1b083b | ||
| 
						 | 
					f4d63e9e58 | ||
| 
						 | 
					cae4882865 | ||
| 
						 | 
					9d4bb244e3 | ||
| 
						 | 
					41b1b9487c | ||
| 
						 | 
					6c1db4a7d6 | ||
| 
						 | 
					7b0c0103a9 | ||
| 
						 | 
					ef6ec3f737 | ||
| 
						 | 
					78269c2110 | ||
| 
						 | 
					eb91c54467 | ||
| 
						 | 
					56b6c12e8a | ||
| 
						 | 
					6507ce98df | ||
| 
						 | 
					2fbadde558 | ||
| 
						 | 
					5a363d74f2 | ||
| 
						 | 
					b2817688ac | ||
| 
						 | 
					659b348a44 | ||
| 
						 | 
					6990a8c942 | ||
| 
						 | 
					98b4ee635d | ||
| 
						 | 
					7d048d52f6 | ||
| 
						 | 
					41fb54489f | ||
| 
						 | 
					3be9ec308a | ||
| 
						 | 
					f120a17b1d | ||
| 
						 | 
					fc7054c150 | ||
| 
						 | 
					cde70f94db | ||
| 
						 | 
					8f0f328dbf | ||
| 
						 | 
					10e3bdcce3 | ||
| 
						 | 
					bc036c01cb | ||
| 
						 | 
					c14f565d18 | ||
| 
						 | 
					f56007d95f | ||
| 
						 | 
					65599cfb58 | ||
| 
						 | 
					39b2b95477 | ||
| 
						 | 
					e65561feae | ||
| 
						 | 
					2a2170efc0 | ||
| 
						 | 
					adb5fb90b1 | ||
| 
						 | 
					ad9e16c198 | ||
| 
						 | 
					96a20ae9d4 | ||
| 
						 | 
					0cadf7ba66 | ||
| 
						 | 
					bb5ccf8869 | ||
| 
						 | 
					57d19b3f1b | ||
| 
						 | 
					e45d947322 | ||
| 
						 | 
					b44cdfc143 | ||
| 
						 | 
					385933819e | ||
| 
						 | 
					58e3ba19a2 | ||
| 
						 | 
					0f3ab63a24 | ||
| 
						 | 
					2697eddcba | ||
| 
						 | 
					90ba925a19 | ||
| 
						 | 
					b5d23f1591 | ||
| 
						 | 
					e6f0290d9f | ||
| 
						 | 
					23a3de988f | ||
| 
						 | 
					c4fc6c2381 | ||
| 
						 | 
					9bc24aea56 | ||
| 
						 | 
					8392d2853e | ||
| 
						 | 
					28708849a9 | ||
| 
						 | 
					9f1538687a | ||
| 
						 | 
					0ae26564ce | ||
| 
						 | 
					9c146b8a6f | ||
| 
						 | 
					2913ac8b4e | ||
| 
						 | 
					6556fcc3fc | ||
| 
						 | 
					1c6b3062bf | ||
| 
						 | 
					b00600c247 | ||
| 
						 | 
					97d680c924 | ||
| 
						 | 
					8f606cf0f6 | ||
| 
						 | 
					c05aa13dcf | ||
| 
						 | 
					12389f2089 | ||
| 
						 | 
					b3cb194c03 | ||
| 
						 | 
					1ea4c6d449 | ||
| 
						 | 
					e5526cb27e | ||
| 
						 | 
					8a8a182679 | ||
| 
						 | 
					2f19cff4df | ||
| 
						 | 
					0bceef8c78 | ||
| 
						 | 
					40eee88b06 | ||
| 
						 | 
					0c79543cfe | ||
| 
						 | 
					6ea66f6925 | ||
| 
						 | 
					8891680304 | ||
| 
						 | 
					1f80f8f371 | ||
| 
						 | 
					d2fefb2e80 | ||
| 
						 | 
					b3032f918e | ||
| 
						 | 
					bb37f26bbf | ||
| 
						 | 
					e805bfb103 | ||
| 
						 | 
					a1cbc61c34 | ||
| 
						 | 
					e3deef3baa | ||
| 
						 | 
					4b81bb549d | ||
| 
						 | 
					c0274f4018 | ||
| 
						 | 
					46ac061fb3 | ||
| 
						 | 
					5e4a1476b3 | ||
| 
						 | 
					3415f08149 | ||
| 
						 | 
					c384ad4074 | ||
| 
						 | 
					8a9dbd13e7 | ||
| 
						 | 
					1e2f3763cb | ||
| 
						 | 
					bc9b386f80 | ||
| 
						 | 
					b4940ed53c | ||
| 
						 | 
					1e9221af45 | ||
| 
						 | 
					200675b506 | ||
| 
						 | 
					6424bd9e6d | ||
| 
						 | 
					7ce425114e | ||
| 
						 | 
					b0e9ba5f4b | ||
| 
						 | 
					7837f37e21 | ||
| 
						 | 
					966bfcef27 | ||
| 
						 | 
					70ebb39097 | ||
| 
						 | 
					60d340b387 | ||
| 
						 | 
					22812bc83c | ||
| 
						 | 
					83c37777f1 | ||
| 
						 | 
					a200f50bbe | ||
| 
						 | 
					a2f563f84f | ||
| 
						 | 
					d5c94a08a7 | ||
| 
						 | 
					9fc47d67df | ||
| 
						 | 
					c697497923 | ||
| 
						 | 
					b13837c2c0 | ||
| 
						 | 
					5eb6300c77 | ||
| 
						 | 
					a1b86401a5 | ||
| 
						 | 
					5dcb17df67 | ||
| 
						 | 
					5b94a87589 | ||
| 
						 | 
					3698ce35b1 | ||
| 
						 | 
					e6ce16ae13 | ||
| 
						 | 
					7e8110ec50 | ||
| 
						 | 
					482cef7121 | ||
| 
						 | 
					3c3e95a5a8 | ||
| 
						 | 
					e0a4b67e11 | ||
| 
						 | 
					56c7200837 | ||
| 
						 | 
					0381e82b54 | ||
| 
						 | 
					28b075f78d | ||
| 
						 | 
					4f4c217659 | ||
| 
						 | 
					55d9104463 | ||
| 
						 | 
					be2679a691 | ||
| 
						 | 
					69281c1eab | ||
| 
						 | 
					ea249ebca7 | ||
| 
						 | 
					e60fe35e6b | ||
| 
						 | 
					a1945b9f12 | ||
| 
						 | 
					d41c8aed57 | ||
| 
						 | 
					fbf215ade2 | ||
| 
						 | 
					5b679c060d | ||
| 
						 | 
					acb88b5339 | ||
| 
						 | 
					c3d7df946e | ||
| 
						 | 
					1dea3b9fab | ||
| 
						 | 
					3801cb524c | ||
| 
						 | 
					001b2c264b | ||
| 
						 | 
					f1e5a95d89 | ||
| 
						 | 
					8779301c8d | ||
| 
						 | 
					2ac0e8f989 | ||
| 
						 | 
					f912e2c887 | ||
| 
						 | 
					732528e1c0 | ||
| 
						 | 
					90222d0232 | ||
| 
						 | 
					85933f336c | ||
| 
						 | 
					dc60e49a4d | ||
| 
						 | 
					d1626c2433 | ||
| 
						 | 
					2b3e80e233 | ||
| 
						 | 
					0eb26e4582 | ||
| 
						 | 
					79a9cb910a | ||
| 
						 | 
					5b958643be | ||
| 
						 | 
					6e17f8809d | ||
| 
						 | 
					75ab0236a9 | ||
| 
						 | 
					4928dded55 | ||
| 
						 | 
					61325c32b0 | ||
| 
						 | 
					4f2136c654 | ||
| 
						 | 
					9489a09e01 | ||
| 
						 | 
					b55eb45e6a | ||
| 
						 | 
					294097601d | ||
| 
						 | 
					92afd60d92 | ||
| 
						 | 
					6bb64bc0b7 | ||
| 
						 | 
					16138ebca3 | ||
| 
						 | 
					bcf4cf83e4 | ||
| 
						 | 
					5d3834485e | ||
| 
						 | 
					4bd06a929d | ||
| 
						 | 
					9f8d31c4a2 | ||
| 
						 | 
					e01d8e9702 | ||
| 
						 | 
					212f7e0409 | ||
| 
						 | 
					676492a634 | ||
| 
						 | 
					39311f404e | ||
| 
						 | 
					60b5c7dab1 | ||
| 
						 | 
					fe80296ff0 | ||
| 
						 | 
					e945819706 | ||
| 
						 | 
					caad1b4ff9 | ||
| 
						 | 
					2286995abd | ||
| 
						 | 
					3548ba3827 | ||
| 
						 | 
					de2c6ce36e | ||
| 
						 | 
					af1144cac0 | ||
| 
						 | 
					4894259eca | ||
| 
						 | 
					ab3b542a18 | ||
| 
						 | 
					262ff6e9d3 | ||
| 
						 | 
					968c382706 | ||
| 
						 | 
					d99a0313a7 | ||
| 
						 | 
					ad2a90ccc6 | ||
| 
						 | 
					64013278fb | ||
| 
						 | 
					86a974c3c3 | ||
| 
						 | 
					f56361e29f | ||
| 
						 | 
					b53badf298 | ||
| 
						 | 
					93bd371b57 | ||
| 
						 | 
					3bb9c8e43e | ||
| 
						 | 
					09c6b90d76 | ||
| 
						 | 
					032a206a83 | ||
| 
						 | 
					735d51276c | ||
| 
						 | 
					bc91078978 | ||
| 
						 | 
					8179a2dc9c | ||
| 
						 | 
					ab98a1c5dc | ||
| 
						 | 
					d9f958852c | ||
| 
						 | 
					27b0895f6d | ||
| 
						 | 
					fec4084b90 | ||
| 
						 | 
					9a9d7c1c55 | ||
| 
						 | 
					0f287ed3dd | ||
| 
						 | 
					cf048beade | ||
| 
						 | 
					558c22a454 | ||
| 
						 | 
					683f33139e | ||
| 
						 | 
					810abed9ea | ||
| 
						 | 
					9bd893bbc7 | ||
| 
						 | 
					abf79b3678 | ||
| 
						 | 
					290d1d8c3f | ||
| 
						 | 
					f1ec47e131 | ||
| 
						 | 
					0e36229da2 | ||
| 
						 | 
					5d5d6e4d4a | ||
| 
						 | 
					543f8e8cca | ||
| 
						 | 
					d5f5a46b33 | ||
| 
						 | 
					ac146fc759 | ||
| 
						 | 
					5b5c981c13 | ||
| 
						 | 
					fbe2b85f22 | ||
| 
						 | 
					377a39fcaf | ||
| 
						 | 
					6674b9a66f | ||
| 
						 | 
					73ac1ba150 | ||
| 
						 | 
					fa3bfb017b | ||
| 
						 | 
					c755772a23 | ||
| 
						 | 
					441a1d7ee2 | ||
| 
						 | 
					f6318121f4 | ||
| 
						 | 
					88943533dd | ||
| 
						 | 
					fba05d7ba1 | ||
| 
						 | 
					d302389b9f | ||
| 
						 | 
					14ccfd53b5 | ||
| 
						 | 
					e0256ba49a | ||
| 
						 | 
					22f922671e | ||
| 
						 | 
					589f03e91a | ||
| 
						 | 
					759241e905 | ||
| 
						 | 
					b68cb6026e | ||
| 
						 | 
					b1b18e183c | ||
| 
						 | 
					64cdefc540 | ||
| 
						 | 
					52aa8cabe3 | ||
| 
						 | 
					e420410f9a | ||
| 
						 | 
					45f69c7d5f | ||
| 
						 | 
					612b90ba52 | ||
| 
						 | 
					ae0ac24fdd | ||
| 
						 | 
					4e51f802a0 | ||
| 
						 | 
					e4c3b136f5 | ||
| 
						 | 
					f1329d4511 | ||
| 
						 | 
					ee5f8f12bf | ||
| 
						 | 
					cb41445647 | ||
| 
						 | 
					6d518948a9 | ||
| 
						 | 
					45628f9813 | ||
| 
						 | 
					affe488e93 | ||
| 
						 | 
					c294dbb4c8 | ||
| 
						 | 
					a60e991ee7 | ||
| 
						 | 
					3cfab15e8a | ||
| 
						 | 
					eb8af4be25 | ||
| 
						 | 
					014546ad62 | ||
| 
						 | 
					e2240edafc | ||
| 
						 | 
					e4d6cfc013 | ||
| 
						 | 
					79e3827207 | ||
| 
						 | 
					ba29d593b9 | ||
| 
						 | 
					b53f7f9993 | ||
| 
						 | 
					e6e871afbe | ||
| 
						 | 
					45edc2ae3f | ||
| 
						 | 
					d54db5013b | ||
| 
						 | 
					5426e85284 | ||
| 
						 | 
					81631b1986 | ||
| 
						 | 
					df1b244fda | ||
| 
						 | 
					004cda1b64 | ||
| 
						 | 
					97c6592073 | ||
| 
						 | 
					949b8c519b | ||
| 
						 | 
					e59624d6e9 | ||
| 
						 | 
					74b228ee94 | ||
| 
						 | 
					1565532bc7 | ||
| 
						 | 
					21a17f291c | ||
| 
						 | 
					919568a223 | ||
| 
						 | 
					ec81f7151d | ||
| 
						 | 
					46eae0cdd8 | ||
| 
						 | 
					e5ecec8140 | ||
| 
						 | 
					401f9e0eaf | ||
| 
						 | 
					06769c9ccd | ||
| 
						 | 
					009e7950bf | ||
| 
						 | 
					66ad893ca4 | ||
| 
						 | 
					15f4b08f94 | ||
| 
						 | 
					9b4b94edc0 | ||
| 
						 | 
					476099efc1 | ||
| 
						 | 
					cab4c903d0 | ||
| 
						 | 
					d9da96c8ad | ||
| 
						 | 
					d9ea736248 | ||
| 
						 | 
					b4dc68ba50 | ||
| 
						 | 
					786f8576e3 | ||
| 
						 | 
					ec739277a1 | ||
| 
						 | 
					8376fd198f | ||
| 
						 | 
					39429d3905 | ||
| 
						 | 
					4fb84eedfe | ||
| 
						 | 
					1a64b3c812 | ||
| 
						 | 
					66c590c89c | ||
| 
						 | 
					821c266f1d | ||
| 
						 | 
					4e63287d75 | ||
| 
						 | 
					7f5ac28c78 | ||
| 
						 | 
					52cd4a5893 | ||
| 
						 | 
					04c5af2130 | ||
| 
						 | 
					52893778f8 | ||
| 
						 | 
					600e67b17a | ||
| 
						 | 
					2da49b93bd | ||
| 
						 | 
					a65df0e598 | ||
| 
						 | 
					54d4416ef8 | ||
| 
						 | 
					42a7af1632 | ||
| 
						 | 
					cfbbf34d6a | ||
| 
						 | 
					5b35bbdf1b | ||
| 
						 | 
					0c46d48e40 | ||
| 
						 | 
					e78ad5f175 | ||
| 
						 | 
					09c2296a9a | ||
| 
						 | 
					55a3cf7ecd | ||
| 
						 | 
					180705e9eb | ||
| 
						 | 
					f5cf560a3c | ||
| 
						 | 
					1e11b5dd7c | ||
| 
						 | 
					f201c75a24 | ||
| 
						 | 
					41219737ad | ||
| 
						 | 
					35d1b6665c | ||
| 
						 | 
					0543201db1 | ||
| 
						 | 
					8e4da1d397 | ||
| 
						 | 
					2977bfa721 | ||
| 
						 | 
					5fa92bf619 | ||
| 
						 | 
					3e37822415 | ||
| 
						 | 
					4d65f59824 | ||
| 
						 | 
					cd5829fc42 | ||
| 
						 | 
					86b056872d | ||
| 
						 | 
					b1007b02c0 | ||
| 
						 | 
					d3126d15cf | ||
| 
						 | 
					d61ed147ac | ||
| 
						 | 
					b1f3aa2920 | ||
| 
						 | 
					8ad3bb1462 | ||
| 
						 | 
					b91a077d23 | ||
| 
						 | 
					3df29c1667 | ||
| 
						 | 
					abf6c8eb4d | ||
| 
						 | 
					cffd634681 | ||
| 
						 | 
					e72e8cc71f | ||
| 
						 | 
					8eaef39b33 | ||
| 
						 | 
					1588334093 | ||
| 
						 | 
					6f4fb574ec | ||
| 
						 | 
					64cc7834a8 | ||
| 
						 | 
					11e2edcf5f | ||
| 
						 | 
					f900ddb544 | ||
| 
						 | 
					4f60a6ea02 | ||
| 
						 | 
					dc1bc980d0 | ||
| 
						 | 
					3d3ae02e62 | ||
| 
						 | 
					a70a110f31 | ||
| 
						 | 
					05d3869acf | ||
| 
						 | 
					72489fb458 | ||
| 
						 | 
					fe8b1db933 | ||
| 
						 | 
					8fdd90eb40 | ||
| 
						 | 
					564a356f09 | ||
| 
						 | 
					3927137203 | ||
| 
						 | 
					f826ad5c89 | ||
| 
						 | 
					517ee7f6c3 | ||
| 
						 | 
					99cc41356c | ||
| 
						 | 
					e76736cf55 | ||
| 
						 | 
					2a7bbc7e46 | ||
| 
						 | 
					bda6449118 | ||
| 
						 | 
					e6166e4498 | ||
| 
						 | 
					80a878ade5 | ||
| 
						 | 
					bbf2fcf17a | ||
| 
						 | 
					c1d266bd9a | ||
| 
						 | 
					7a7f3f2f5b | ||
| 
						 | 
					0371941707 | ||
| 
						 | 
					6f449e65a4 | ||
| 
						 | 
					5491f09bab | ||
| 
						 | 
					6949ec443e | ||
| 
						 | 
					47ca8f9c12 | ||
| 
						 | 
					ba303a615b | ||
| 
						 | 
					350582bc7b | ||
| 
						 | 
					b9836e714a | ||
| 
						 | 
					aae30e6db5 | ||
| 
						 | 
					86e46f17de | ||
| 
						 | 
					fbc263659b | ||
| 
						 | 
					8c8a7cbba4 | ||
| 
						 | 
					f5e3cd0dbf | ||
| 
						 | 
					24c1a0954b | ||
| 
						 | 
					f05cf23b89 | ||
| 
						 | 
					90c883c201 | ||
| 
						 | 
					2d0b95cd49 | ||
| 
						 | 
					e2bc7a277e | ||
| 
						 | 
					adbd3e478b | ||
| 
						 | 
					7b0804c22f | ||
| 
						 | 
					47dfe904ab | ||
| 
						 | 
					7f5b44b423 | ||
| 
						 | 
					c16ca69070 | ||
| 
						 | 
					394c628931 | ||
| 
						 | 
					43695024af | ||
| 
						 | 
					1678de7f51 | ||
| 
						 | 
					063436c82b | ||
| 
						 | 
					59585550a7 | ||
| 
						 | 
					51e294c501 | ||
| 
						 | 
					22ffec640d | ||
| 
						 | 
					7ab3c4c091 | ||
| 
						 | 
					19934a59b2 | ||
| 
						 | 
					f3645e3f4b | ||
| 
						 | 
					d818035d3a | ||
| 
						 | 
					0cce8cfbaa | ||
| 
						 | 
					3e132d71f5 | ||
| 
						 | 
					2b3a4adff8 | ||
| 
						 | 
					de49d45568 | ||
| 
						 | 
					de5337b187 | ||
| 
						 | 
					f0e82e4473 | ||
| 
						 | 
					5a00c29f8a | ||
| 
						 | 
					dd5d9aa6bc | ||
| 
						 | 
					40f03c4c2c | ||
| 
						 | 
					1aaf8d589f | ||
| 
						 | 
					1b87c6ade7 | ||
| 
						 | 
					d52e9c7704 | ||
| 
						 | 
					9c7425eee4 | ||
| 
						 | 
					7cd8b4410e | ||
| 
						 | 
					c63e78714a | ||
| 
						 | 
					2b34836c61 | ||
| 
						 | 
					32d1d7b23f | ||
| 
						 | 
					e7773faa8d | ||
| 
						 | 
					b7c2a2b709 | ||
| 
						 | 
					67ef389a69 | ||
| 
						 | 
					7c1903a0c3 | ||
| 
						 | 
					c8563cac0a | ||
| 
						 | 
					42c4a7757d | ||
| 
						 | 
					8b007b358e | ||
| 
						 | 
					5cd2cfc203 | ||
| 
						 | 
					a7ca42cb22 | ||
| 
						 | 
					f562bcedef | ||
| 
						 | 
					a8dc5260b7 | ||
| 
						 | 
					d33d0b01bf | ||
| 
						 | 
					4a5195c38a | ||
| 
						 | 
					0864378250 | ||
| 
						 | 
					855e4aac41 | ||
| 
						 | 
					5f8a3896dc | ||
| 
						 | 
					903bfcaf4b | ||
| 
						 | 
					fcf46a9a42 | ||
| 
						 | 
					1d1db98a2e | ||
| 
						 | 
					51c8e01575 | ||
| 
						 | 
					b87c774102 | ||
| 
						 | 
					6aa05bdc37 | ||
| 
						 | 
					4abee1da76 | ||
| 
						 | 
					2106e8f031 | ||
| 
						 | 
					4befd355b3 | ||
| 
						 | 
					a544f403a2 | ||
| 
						 | 
					8f1afa1766 | ||
| 
						 | 
					c0789ae1b4 | ||
| 
						 | 
					9934a167a2 | ||
| 
						 | 
					798ffad9a9 | ||
| 
						 | 
					fb3b7f2274 | ||
| 
						 | 
					23dd62ec54 | ||
| 
						 | 
					a1affa1dc3 | ||
| 
						 | 
					23633cf632 | ||
| 
						 | 
					472bd55757 | ||
| 
						 | 
					2de4f65474 | ||
| 
						 | 
					38befc5ded | ||
| 
						 | 
					5f9d855d3e | ||
| 
						 | 
					3c5d941945 | ||
| 
						 | 
					2f54dbd28c | ||
| 
						 | 
					b2b6c18db3 | ||
| 
						 | 
					33e7126ba5 | ||
| 
						 | 
					2ab98aa919 | ||
| 
						 | 
					9ba875e502 | ||
| 
						 | 
					2dcdb807f8 | ||
| 
						 | 
					56fe3c6176 | ||
| 
						 | 
					321b26f3d4 | ||
| 
						 | 
					ad37ab272a | ||
| 
						 | 
					d5feddb0a0 | ||
| 
						 | 
					88ae26178c | ||
| 
						 | 
					e06357084e | ||
| 
						 | 
					2e52c46165 | ||
| 
						 | 
					a82cf6080e | ||
| 
						 | 
					78f321b32c | ||
| 
						 | 
					3113200309 | ||
| 
						 | 
					4a854b2927 | ||
| 
						 | 
					a5e61545e4 | ||
| 
						 | 
					17a259e894 | ||
| 
						 | 
					f5fb224254 | ||
| 
						 | 
					fe07d17374 | ||
| 
						 | 
					8d983d6f2d | ||
| 
						 | 
					2c028990b4 | ||
| 
						 | 
					35af86cef2 | ||
| 
						 | 
					659f47f76a | ||
| 
						 | 
					b489acb578 | ||
| 
						 | 
					e34342c1f3 | ||
| 
						 | 
					1f6952ba81 | ||
| 
						 | 
					d2f48d07bb | ||
| 
						 | 
					e9306bead5 | ||
| 
						 | 
					a3bdff883b | ||
| 
						 | 
					ddedf42d21 | ||
| 
						 | 
					b3e684d1fe | ||
| 
						 | 
					b3a13b17cb | ||
| 
						 | 
					90b4fce199 | ||
| 
						 | 
					2d3164a59f | ||
| 
						 | 
					37ee12b2eb | ||
| 
						 | 
					d8d4a1d694 | ||
| 
						 | 
					0b18937cbe | ||
| 
						 | 
					264091a239 | ||
| 
						 | 
					d324fd94df | ||
| 
						 | 
					15352cd86e | ||
| 
						 | 
					69ca87abad | ||
| 
						 | 
					e0c8e7c740 | ||
| 
						 | 
					8a9f96b21c | ||
| 
						 | 
					bfb05107e3 | ||
| 
						 | 
					1e699db631 | ||
| 
						 | 
					f3953f9a15 | ||
| 
						 | 
					7c7f889b1e | ||
| 
						 | 
					f437c92b00 | ||
| 
						 | 
					44dd5c38e2 | ||
| 
						 | 
					e0132ef4cb | ||
| 
						 | 
					94cb2db723 | ||
| 
						 | 
					52cf11338e | ||
| 
						 | 
					c4cce91dce | ||
| 
						 | 
					23aa1c6524 | ||
| 
						 | 
					9de129d5b2 | ||
| 
						 | 
					9d4cb8e97a | ||
| 
						 | 
					c1589415f0 | ||
| 
						 | 
					389cbc3686 | ||
| 
						 | 
					2508b4000b | ||
| 
						 | 
					e5164acc9c | ||
| 
						 | 
					71ee58b6bb | ||
| 
						 | 
					3512a6ad0b | ||
| 
						 | 
					b02de599a0 | ||
| 
						 | 
					38c6e8faf6 | ||
| 
						 | 
					431ca070a4 | ||
| 
						 | 
					ed2630dce5 | ||
| 
						 | 
					5a2c9c9cee | ||
| 
						 | 
					a7184430f1 | ||
| 
						 | 
					2e83fee74c | ||
| 
						 | 
					bbe29582cb | ||
| 
						 | 
					76470d9608 | ||
| 
						 | 
					715c4ca4cd | ||
| 
						 | 
					c097423d77 | ||
| 
						 | 
					54637fa44d | ||
| 
						 | 
					c192e88bcd | ||
| 
						 | 
					19a12b28bc | ||
| 
						 | 
					d55a7f18b0 | ||
| 
						 | 
					4008a5fbf9 | ||
| 
						 | 
					e260f729da | ||
| 
						 | 
					17cffe2bf9 | ||
| 
						 | 
					d1b068a68a | ||
| 
						 | 
					a5053f6ada | ||
| 
						 | 
					261a3e7e78 | ||
| 
						 | 
					36e28d4b4b | ||
| 
						 | 
					cbc562a636 | ||
| 
						 | 
					51c4e1ea4b | ||
| 
						 | 
					c8f03c38fe | ||
| 
						 | 
					4107d4d24d | ||
| 
						 | 
					f0c79d95f5 | ||
| 
						 | 
					d13b495217 | ||
| 
						 | 
					549e1dfb0d | ||
| 
						 | 
					e260ecef0b | ||
| 
						 | 
					b16b4d92a7 | ||
| 
						 | 
					c2584edbdb | ||
| 
						 | 
					aa00196b6f | ||
| 
						 | 
					75e3996d36 | ||
| 
						 | 
					d50f13b90d | ||
| 
						 | 
					652e9c00c5 | ||
| 
						 | 
					fdcf749779 | ||
| 
						 | 
					ed38f47f23 | ||
| 
						 | 
					3b0585be3b | ||
| 
						 | 
					ebe1a8080c | ||
| 
						 | 
					593bb6470b | ||
| 
						 | 
					6ce45042ef | ||
| 
						 | 
					f615e84381 | ||
| 
						 | 
					bfaf1a4ecc | ||
| 
						 | 
					bc1a30f542 | ||
| 
						 | 
					28e0d5dd64 | ||
| 
						 | 
					ffdd12841e | ||
| 
						 | 
					4b660a89d9 | ||
| 
						 | 
					48386caec5 | ||
| 
						 | 
					996360df6b | ||
| 
						 | 
					fe260a26ed | ||
| 
						 | 
					457bc4fb63 | ||
| 
						 | 
					eeb7ce60ae | ||
| 
						 | 
					e52586db1c | ||
| 
						 | 
					6cb9642200 | ||
| 
						 | 
					7ebd46ee53 | ||
| 
						 | 
					d575dfe440 | ||
| 
						 | 
					074c1880ff | ||
| 
						 | 
					b53c1011fc | ||
| 
						 | 
					11f35d31d9 | ||
| 
						 | 
					36d07a5cea | ||
| 
						 | 
					12910a5a29 | ||
| 
						 | 
					eb93c134a7 | ||
| 
						 | 
					493ad74331 | ||
| 
						 | 
					a563816d3a | ||
| 
						 | 
					43526902ae | ||
| 
						 | 
					b6ec0f9b92 | ||
| 
						 | 
					4e7f1a3a9d | ||
| 
						 | 
					50e879ef56 | ||
| 
						 | 
					06468b9049 | ||
| 
						 | 
					2bdbceca91 | ||
| 
						 | 
					d34d85efdd | ||
| 
						 | 
					7e3278ae8f | ||
| 
						 | 
					bca7c09e6c | ||
| 
						 | 
					2e163858fc | ||
| 
						 | 
					0ad2a4c72f | ||
| 
						 | 
					b69ca133af | ||
| 
						 | 
					d4f0f090c0 | ||
| 
						 | 
					e56f421490 | ||
| 
						 | 
					c9b93bf65a | ||
| 
						 | 
					9b8ce15725 | ||
| 
						 | 
					014e7daa36 | ||
| 
						 | 
					306e3b86f1 | ||
| 
						 | 
					ce7cf5f46b | ||
| 
						 | 
					3c3b5e0dbf | ||
| 
						 | 
					0fc136fcc7 | ||
| 
						 | 
					80328439be | ||
| 
						 | 
					3c649de483 | ||
| 
						 | 
					184ca578a0 | ||
| 
						 | 
					3643acadac | ||
| 
						 | 
					1c78aa19ff | ||
| 
						 | 
					a64fec0722 | ||
| 
						 | 
					962811198f | ||
| 
						 | 
					378c3b1641 | ||
| 
						 | 
					34c937510d | ||
| 
						 | 
					e924e9cfb2 | ||
| 
						 | 
					8f0fa65379 | ||
| 
						 | 
					00268c1b82 | ||
| 
						 | 
					7ab37c0ffc | ||
| 
						 | 
					4cae37c340 | ||
| 
						 | 
					63f8ad01b2 | ||
| 
						 | 
					1a6159aca5 | ||
| 
						 | 
					60e9c014a2 | ||
| 
						 | 
					8f3295456d | ||
| 
						 | 
					78df2efac2 | ||
| 
						 | 
					546357eaeb | ||
| 
						 | 
					50552f3fd5 | ||
| 
						 | 
					7d62ac4b34 | ||
| 
						 | 
					beb14c3fa7 | ||
| 
						 | 
					a15d3d8dcc | ||
| 
						 | 
					9c7755c862 | ||
| 
						 | 
					866553e76f | ||
| 
						 | 
					f8f2be527f | ||
| 
						 | 
					88880e1f89 | ||
| 
						 | 
					3cce4419c2 | ||
| 
						 | 
					bc59859a59 | ||
| 
						 | 
					ecf06d3a49 | ||
| 
						 | 
					d48af1520d | ||
| 
						 | 
					aa9797fa3c | ||
| 
						 | 
					44a82780b9 | ||
| 
						 | 
					c76681596e | ||
| 
						 | 
					3ce8520c5e | ||
| 
						 | 
					01f5823ee4 | ||
| 
						 | 
					c7ec3c65f4 | ||
| 
						 | 
					d01b8d03db | ||
| 
						 | 
					41ff900c99 | ||
| 
						 | 
					9ca07f4298 | ||
| 
						 | 
					0e93522190 | ||
| 
						 | 
					ebd1d49150 | ||
| 
						 | 
					057462c4e6 | ||
| 
						 | 
					b5e36cb96b | ||
| 
						 | 
					f58ca71942 | ||
| 
						 | 
					262a39dfd0 | ||
| 
						 | 
					d531d56dbb | ||
| 
						 | 
					8b78a832fa | ||
| 
						 | 
					8c19b52bda | ||
| 
						 | 
					a7237281ea | ||
| 
						 | 
					0b6ee2252c | ||
| 
						 | 
					a9ffbb0803 | ||
| 
						 | 
					224457fb0f | ||
| 
						 | 
					cacbf14d8e | ||
| 
						 | 
					b00dc7153a | ||
| 
						 | 
					9dbad2f74d | ||
| 
						 | 
					97617cfc76 | ||
| 
						 | 
					735cac19f2 | ||
| 
						 | 
					3755951091 | ||
| 
						 | 
					60af6fb0a2 | ||
| 
						 | 
					333cf73ceb | ||
| 
						 | 
					bc653452a7 | ||
| 
						 | 
					ca92b9a5f0 | ||
| 
						 | 
					afe102c0fe | ||
| 
						 | 
					fa7fa300e3 | ||
| 
						 | 
					3c2b019578 | ||
| 
						 | 
					87003ba5b1 | ||
| 
						 | 
					bf7d3d2208 | ||
| 
						 | 
					4e553333d9 | ||
| 
						 | 
					954df8f3d7 | ||
| 
						 | 
					078573dc2c | ||
| 
						 | 
					c4655582e6 | ||
| 
						 | 
					360f97c31d | ||
| 
						 | 
					f20300cc8b | ||
| 
						 | 
					f687bd63b8 | ||
| 
						 | 
					b68340f6d9 | ||
| 
						 | 
					c5eb266a80 | ||
| 
						 | 
					04f3cea84a | ||
| 
						 | 
					c1fe5092c3 | ||
| 
						 | 
					5257248ed9 | ||
| 
						 | 
					780010a268 | ||
| 
						 | 
					8571d54f61 | ||
| 
						 | 
					13fed1e445 | ||
| 
						 | 
					2179ff624c | ||
| 
						 | 
					8b3434061e | ||
| 
						 | 
					68a6a348b5 | ||
| 
						 | 
					d8659175cd | ||
| 
						 | 
					1431ddad9c | ||
| 
						 | 
					5f860775c8 | ||
| 
						 | 
					65f5ed533f | ||
| 
						 | 
					c4276aad11 | ||
| 
						 | 
					d4ae0dedf2 | ||
| 
						 | 
					312a15d24e | ||
| 
						 | 
					bc1024812a | ||
| 
						 | 
					451be927a8 | ||
| 
						 | 
					4839e5d913 | ||
| 
						 | 
					874d697f4c | ||
| 
						 | 
					f80cbe8c33 | ||
| 
						 | 
					154a7af5ee | ||
| 
						 | 
					cea69ab9d0 | ||
| 
						 | 
					6b3f81e647 | ||
| 
						 | 
					fbee662499 | ||
| 
						 | 
					eedf87f891 | ||
| 
						 | 
					89cb3a410a | ||
| 
						 | 
					ae1ec1b418 | ||
| 
						 | 
					c357c91b7d | ||
| 
						 | 
					b3f073c48c | ||
| 
						 | 
					cd8ffd8725 | ||
| 
						 | 
					bbe4a85be1 | ||
| 
						 | 
					7e6f58c0a9 | ||
| 
						 | 
					275654210d | ||
| 
						 | 
					f649252de9 | ||
| 
						 | 
					d3ce80e544 | ||
| 
						 | 
					ea956b4f6c | ||
| 
						 | 
					ada4c61860 | ||
| 
						 | 
					9bcaa94756 | ||
| 
						 | 
					49a81e190e | ||
| 
						 | 
					5303eca8fa | ||
| 
						 | 
					1b37183e74 | ||
| 
						 | 
					09f17bf72d | ||
| 
						 | 
					449ffc7b05 | ||
| 
						 | 
					bea9cf6725 | ||
| 
						 | 
					a0c7ead88f | ||
| 
						 | 
					3eb97ffa25 | ||
| 
						 | 
					48d651f492 | ||
| 
						 | 
					0d272a6964 | ||
| 
						 | 
					578c4098e6 | ||
| 
						 | 
					c34cb6adcf | ||
| 
						 | 
					cb5d05fd34 | ||
| 
						 | 
					5899d9b442 | ||
| 
						 | 
					40026b0762 | ||
| 
						 | 
					83b4f8366a | ||
| 
						 | 
					8e50c4e4bb | ||
| 
						 | 
					2b129732b0 | ||
| 
						 | 
					8cf86745c2 | ||
| 
						 | 
					5ee39f1a1d | ||
| 
						 | 
					8c998ebbed | ||
| 
						 | 
					e2eb9b24b7 | ||
| 
						 | 
					374e3502fe | ||
| 
						 | 
					1ad6e72ade | ||
| 
						 | 
					d7eaafe9c1 | ||
| 
						 | 
					2400150734 | ||
| 
						 | 
					8ad2a270f4 | ||
| 
						 | 
					73a006403f | ||
| 
						 | 
					a3513577f0 | ||
| 
						 | 
					29ad12df51 | ||
| 
						 | 
					e0dd25f92b | ||
| 
						 | 
					81c155b465 | ||
| 
						 | 
					ae11cc6731 | ||
| 
						 | 
					b0b0c853c7 | ||
| 
						 | 
					8701c4f50c | ||
| 
						 | 
					627d5adc63 | ||
| 
						 | 
					7a5a31888a | ||
| 
						 | 
					3d64743851 | ||
| 
						 | 
					16d704877d | ||
| 
						 | 
					3e320285a1 | ||
| 
						 | 
					3215d89e97 | ||
| 
						 | 
					b7983d4fe2 | ||
| 
						 | 
					6120f4c507 | ||
| 
						 | 
					ac24748b47 | ||
| 
						 | 
					4c449886f6 | ||
| 
						 | 
					cd3475a8cb | ||
| 
						 | 
					03c5c5fbe7 | ||
| 
						 | 
					9d3faa4753 | ||
| 
						 | 
					20399b50d6 | ||
| 
						 | 
					93c1312901 | ||
| 
						 | 
					4bde7fc926 | ||
| 
						 | 
					68086fdde4 | ||
| 
						 | 
					005ad96068 | ||
| 
						 | 
					6c1beb94dc | ||
| 
						 | 
					fa0ec772d5 | ||
| 
						 | 
					661e73d9a6 | ||
| 
						 | 
					db85b2ddc7 | ||
| 
						 | 
					4f732b1989 | ||
| 
						 | 
					78b8276111 | ||
| 
						 | 
					6ef6b6af40 | ||
| 
						 | 
					f45bbeb497 | ||
| 
						 | 
					4eb71369ed | ||
| 
						 | 
					bc11c3a1d7 | ||
| 
						 | 
					dd8ac54678 | ||
| 
						 | 
					15d7886699 | ||
| 
						 | 
					68c7b86df1 | ||
| 
						 | 
					6c8454e4e2 | ||
| 
						 | 
					a249779692 | ||
| 
						 | 
					876b6416ab | ||
| 
						 | 
					1e5d79dce1 | ||
| 
						 | 
					bd8eec0a1e | ||
| 
						 | 
					e7075c4366 | ||
| 
						 | 
					532834cbc2 | ||
| 
						 | 
					d5857e6d48 | ||
| 
						 | 
					b004ea2d7f | ||
| 
						 | 
					205ca4f8a7 | ||
| 
						 | 
					4a76f5c764 | ||
| 
						 | 
					a32e8441d0 | ||
| 
						 | 
					4d6089c042 | ||
| 
						 | 
					7929929979 | ||
| 
						 | 
					9ba50046cf | ||
| 
						 | 
					aa3bdb1911 | ||
| 
						 | 
					5ce8c9ae77 | ||
| 
						 | 
					9d8d6b1d18 | ||
| 
						 | 
					52b8978a47 | ||
| 
						 | 
					442fd05339 | ||
| 
						 | 
					4c952f0af4 | ||
| 
						 | 
					cf90b03ce4 | ||
| 
						 | 
					d4de2a7aa4 | ||
| 
						 | 
					e37b173f13 | ||
| 
						 | 
					b5d88e683f | ||
| 
						 | 
					23dd4773d4 | ||
| 
						 | 
					b7af7c9c43 | ||
| 
						 | 
					9d3955daf2 | ||
| 
						 | 
					063083a203 | ||
| 
						 | 
					46886164dd | ||
| 
						 | 
					ea04c0775c | ||
| 
						 | 
					d29aa4764e | ||
| 
						 | 
					203d1d8371 | ||
| 
						 | 
					2eb4099563 | ||
| 
						 | 
					7cd66377ef | ||
| 
						 | 
					1f9d50fa3f | ||
| 
						 | 
					be29e5ab62 | ||
| 
						 | 
					24d8818933 | ||
| 
						 | 
					803380c203 | ||
| 
						 | 
					1569059b2b | ||
| 
						 | 
					8fb6bd930b | ||
| 
						 | 
					c7cc4b7ac2 | ||
| 
						 | 
					201d0e940b | ||
| 
						 | 
					3fcd56034a | ||
| 
						 | 
					51d222469c | ||
| 
						 | 
					742d1e9424 | ||
| 
						 | 
					a04f401227 | ||
| 
						 | 
					62699dc3fd | ||
| 
						 | 
					01645a7eae | ||
| 
						 | 
					b17939f74e | ||
| 
						 | 
					aa60387ecc | ||
| 
						 | 
					4b801e21e3 | ||
| 
						 | 
					c198ca0285 | ||
| 
						 | 
					a312fc8eb9 | ||
| 
						 | 
					10b62fb0e8 | ||
| 
						 | 
					2c12325d63 | ||
| 
						 | 
					2d8b9935a1 | ||
| 
						 | 
					647d948562 | ||
| 
						 | 
					73d1626ddc | ||
| 
						 | 
					b7445913cc | ||
| 
						 | 
					6f7ca25c9b | ||
| 
						 | 
					4487c42de2 | ||
| 
						 | 
					bfbad87685 | ||
| 
						 | 
					65f0ca65f1 | ||
| 
						 | 
					d0720d5638 | ||
| 
						 | 
					5d7fd71373 | ||
| 
						 | 
					efe3e72ed0 | ||
| 
						 | 
					85f56aef97 | ||
| 
						 | 
					5ac0fdd924 | ||
| 
						 | 
					b33c7a4597 | ||
| 
						 | 
					788b9bfdc7 | ||
| 
						 | 
					41cc3b216d | ||
| 
						 | 
					dcb7878842 | ||
| 
						 | 
					b5e83471bc | ||
| 
						 | 
					bfdc05ec71 | ||
| 
						 | 
					1d7ecbe9a0 | ||
| 
						 | 
					9e30a829d5 | ||
| 
						 | 
					698dfbf953 | ||
| 
						 | 
					83fbb1ec11 | ||
| 
						 | 
					19d0f2b57c | ||
| 
						 | 
					05d40b3142 | ||
| 
						 | 
					d94fc9ce62 | ||
| 
						 | 
					ba9550f473 | ||
| 
						 | 
					28e1e7fd07 | ||
| 
						 | 
					904e38837e | ||
| 
						 | 
					697c5de267 | ||
| 
						 | 
					bfa9c7bcfb | ||
| 
						 | 
					2f81a05ce5 | ||
| 
						 | 
					7b994976e3 | ||
| 
						 | 
					662d1021e6 | ||
| 
						 | 
					2db34bd266 | ||
| 
						 | 
					f3491d93a0 | ||
| 
						 | 
					337abee8f8 | ||
| 
						 | 
					34573cf6a5 | ||
| 
						 | 
					491ef790c2 | ||
| 
						 | 
					2e9ae681c5 | ||
| 
						 | 
					a02f7ab0cb | ||
| 
						 | 
					e0b190c111 | ||
| 
						 | 
					56fa3ac1b0 | ||
| 
						 | 
					5bcbeca8e7 | ||
| 
						 | 
					adc1729212 | ||
| 
						 | 
					fd7ae0cdf4 | ||
| 
						 | 
					fdef9679b6 | ||
| 
						 | 
					dcecda51d8 | ||
| 
						 | 
					687603a144 | ||
| 
						 | 
					acb04c003e | ||
| 
						 | 
					86b10089aa | ||
| 
						 | 
					7b030379ec | ||
| 
						 | 
					5e8c230d1f | ||
| 
						 | 
					8c2890cf1d | ||
| 
						 | 
					8e9da71c32 | ||
| 
						 | 
					13deb51d3e | ||
| 
						 | 
					2c9ffffdca | ||
| 
						 | 
					13a9bce647 | ||
| 
						 | 
					dbb3cfe05e | ||
| 
						 | 
					674baa8143 | ||
| 
						 | 
					db482f3e1c | ||
| 
						 | 
					6a5a0222d7 | ||
| 
						 | 
					4512267bf1 | ||
| 
						 | 
					54555a6fab | ||
| 
						 | 
					ae2353caf8 | ||
| 
						 | 
					4eae19ed75 | ||
| 
						 | 
					e6ec837203 | ||
| 
						 | 
					b37f7c4b7b | ||
| 
						 | 
					4b8340327c | ||
| 
						 | 
					92e4442d4a | ||
| 
						 | 
					2517f9adf2 | ||
| 
						 | 
					9bad64ff72 | ||
| 
						 | 
					d1b147e2bb | ||
| 
						 | 
					1b7730c76a | ||
| 
						 | 
					28801f7470 | ||
| 
						 | 
					f4c43c11c9 | ||
| 
						 | 
					fde4a8e1b5 | ||
| 
						 | 
					abb193533c | ||
| 
						 | 
					775fac97d3 | ||
| 
						 | 
					3963c01760 | ||
| 
						 | 
					1e01a63685 | ||
| 
						 | 
					235ca704b1 | ||
| 
						 | 
					5685ba7918 | ||
| 
						 | 
					f0d1c085b9 | ||
| 
						 | 
					45490081c7 | ||
| 
						 | 
					a3503d13e5 | ||
| 
						 | 
					3ed4d07d3a | ||
| 
						 | 
					06e0023c2c | ||
| 
						 | 
					b22e0a3ecb | ||
| 
						 | 
					0802006ea7 | ||
| 
						 | 
					29a21d1627 | ||
| 
						 | 
					a0074aa07e | ||
| 
						 | 
					4e8859d851 | ||
| 
						 | 
					562ae607d2 | ||
| 
						 | 
					2426656b07 | ||
| 
						 | 
					898d3c655d | ||
| 
						 | 
					855e554051 | ||
| 
						 | 
					4aac2c543b | ||
| 
						 | 
					78024e7be6 | ||
| 
						 | 
					18f0009a41 | ||
| 
						 | 
					1cf64de2bf | ||
| 
						 | 
					b1d6be8ec6 | ||
| 
						 | 
					137a25906d | ||
| 
						 | 
					2b298cbb32 | ||
| 
						 | 
					5361b5de37 | ||
| 
						 | 
					f1fee292e4 | ||
| 
						 | 
					9c9b1f5bc8 | ||
| 
						 | 
					7e64d04db1 | ||
| 
						 | 
					2355f677fb | ||
| 
						 | 
					e42bb91382 | ||
| 
						 | 
					28aa06675f | ||
| 
						 | 
					6e86d0bb03 | ||
| 
						 | 
					4342431e39 | ||
| 
						 | 
					7452298131 | ||
| 
						 | 
					e4be66b1ac | ||
| 
						 | 
					f829547a13 | ||
| 
						 | 
					ea64fe3b51 | ||
| 
						 | 
					f293d0b951 | ||
| 
						 | 
					1967fd2429 | ||
| 
						 | 
					0fec0340c2 | ||
| 
						 | 
					bed67320b1 | ||
| 
						 | 
					8544e24770 | ||
| 
						 | 
					727b7b7e8c | ||
| 
						 | 
					bd39789144 | ||
| 
						 | 
					eb10fc962b | ||
| 
						 | 
					3318c41356 | ||
| 
						 | 
					dc2c0b1d51 | ||
| 
						 | 
					1de8da23f5 | ||
| 
						 | 
					340fa684af | ||
| 
						 | 
					34f06fa400 | ||
| 
						 | 
					5b5337e4af | ||
| 
						 | 
					d01de820d7 | ||
| 
						 | 
					5aeea69c01 | ||
| 
						 | 
					8f6c0b24d8 | ||
| 
						 | 
					b8eddf1bdc | ||
| 
						 | 
					1469dc216a | ||
| 
						 | 
					3306ae2f42 | ||
| 
						 | 
					a89db8e69c | ||
| 
						 | 
					8c6f06eb34 | ||
| 
						 | 
					fe3ed2b871 | ||
| 
						 | 
					71cb3fc201 | ||
| 
						 | 
					f9554c7d27 | ||
| 
						 | 
					384f2fc38b | ||
| 
						 | 
					cd50107ae1 | ||
| 
						 | 
					94466645ee | ||
| 
						 | 
					1acb442f60 | ||
| 
						 | 
					cff0a562fd | ||
| 
						 | 
					299db29482 | ||
| 
						 | 
					cc5045d8ca | ||
| 
						 | 
					940c32c5dd | ||
| 
						 | 
					14ad41a065 | ||
| 
						 | 
					7eaf1f294d | ||
| 
						 | 
					eb7692743f | ||
| 
						 | 
					7aa470c8d0 | ||
| 
						 | 
					4237ca85f5 | ||
| 
						 | 
					99cdfa1e71 | ||
| 
						 | 
					39f92f3cfd | ||
| 
						 | 
					9cc29191d4 | ||
| 
						 | 
					de33332491 | ||
| 
						 | 
					f9ddafdc21 | ||
| 
						 | 
					fdefd5eff9 | ||
| 
						 | 
					e9e5dbb628 | ||
| 
						 | 
					0e57141bb5 | ||
| 
						 | 
					842a3664f0 | ||
| 
						 | 
					6cf89391b6 | ||
| 
						 | 
					ca5fd21509 | ||
| 
						 | 
					d14471e44d | ||
| 
						 | 
					5197fd72c4 | ||
| 
						 | 
					c17ac96509 | ||
| 
						 | 
					4acb30c464 | ||
| 
						 | 
					d61f611adc | ||
| 
						 | 
					b19719801b | ||
| 
						 | 
					83a2bc8ec4 | ||
| 
						 | 
					aab6f07d14 | ||
| 
						 | 
					db8748cefd | ||
| 
						 | 
					23b3f55bfb | ||
| 
						 | 
					e6573a9bed | ||
| 
						 | 
					d6a19426c7 | ||
| 
						 | 
					9426d45cde | ||
| 
						 | 
					48d0cd3564 | ||
| 
						 | 
					89f61acf2c | ||
| 
						 | 
					985d87b5eb | ||
| 
						 | 
					0be2dfefdb | ||
| 
						 | 
					89f30d2df7 | ||
| 
						 | 
					0b648ce87b | ||
| 
						 | 
					0c897ecefd | ||
| 
						 | 
					f2a6d937a6 | ||
| 
						 | 
					76f4498303 | ||
| 
						 | 
					5451f79f55 | ||
| 
						 | 
					4e69ed9c98 | ||
| 
						 | 
					75f55c758c | ||
| 
						 | 
					f9d1b67e86 | ||
| 
						 | 
					04ecf25522 | ||
| 
						 | 
					52b51b70eb | ||
| 
						 | 
					3fdc1390fe | ||
| 
						 | 
					f309bd12c7 | ||
| 
						 | 
					d388f94c7f | ||
| 
						 | 
					0f878a226d | ||
| 
						 | 
					a38f899d7e | ||
| 
						 | 
					6c09d7b60c | ||
| 
						 | 
					8cb8f65010 | ||
| 
						 | 
					49437d9a07 | ||
| 
						 | 
					69962eae7c | ||
| 
						 | 
					c440f39874 | ||
| 
						 | 
					40090be220 | ||
| 
						 | 
					281a92bf74 | ||
| 
						 | 
					bbacb7fff0 | ||
| 
						 | 
					cccdc3eea0 | ||
| 
						 | 
					aa9c970f97 | ||
| 
						 | 
					4f81adb3c9 | ||
| 
						 | 
					b8f75d74ae | ||
| 
						 | 
					befffd65bf | ||
| 
						 | 
					610cd1a531 | ||
| 
						 | 
					08d06030dc | ||
| 
						 | 
					083687d0fd | ||
| 
						 | 
					f874581701 | ||
| 
						 | 
					e66d76ac5a | ||
| 
						 | 
					5d7ad8ae75 | ||
| 
						 | 
					99ab428344 | ||
| 
						 | 
					eaef92b02f | ||
| 
						 | 
					4982eabe07 | ||
| 
						 | 
					c66ce519f4 | ||
| 
						 | 
					e74208778d | ||
| 
						 | 
					67a0635e75 | ||
| 
						 | 
					def0511361 | ||
| 
						 | 
					29b8138482 | ||
| 
						 | 
					c6ee487cfc | ||
| 
						 | 
					1a6df48bd0 | ||
| 
						 | 
					6cdf300933 | ||
| 
						 | 
					5365974d6c | ||
| 
						 | 
					f1acefd241 | ||
| 
						 | 
					079fec6c5a | ||
| 
						 | 
					14258c93de | ||
| 
						 | 
					03315d77f1 | ||
| 
						 | 
					34843e7d6c | ||
| 
						 | 
					4efa67c4ec | ||
| 
						 | 
					2419c1c540 | ||
| 
						 | 
					34055f40ac | ||
| 
						 | 
					276d32973f | ||
| 
						 | 
					f3c51a049d | ||
| 
						 | 
					21573cd4f0 | ||
| 
						 | 
					f25325f4bb | ||
| 
						 | 
					5b12edfb34 | ||
| 
						 | 
					4697026132 | ||
| 
						 | 
					6c39b8f4f0 | ||
| 
						 | 
					4a9af35527 | ||
| 
						 | 
					881056af0b | ||
| 
						 | 
					e5df490d5e | ||
| 
						 | 
					7c0d6057c5 | ||
| 
						 | 
					3e5a54a791 | ||
| 
						 | 
					dbfd6e0d12 | ||
| 
						 | 
					f607a0a0a6 | ||
| 
						 | 
					b15ada28ed | ||
| 
						 | 
					6610f9bdbc | ||
| 
						 | 
					5f87626377 | ||
| 
						 | 
					54834a1761 | ||
| 
						 | 
					adf7081163 | ||
| 
						 | 
					a50b7c55d3 | ||
| 
						 | 
					f4f171e04d | ||
| 
						 | 
					d5ea20a6eb | ||
| 
						 | 
					5584f2ae46 | ||
| 
						 | 
					b79d8b1ff0 | ||
| 
						 | 
					1c33c0027f | ||
| 
						 | 
					aef0a98840 | ||
| 
						 | 
					9d23a04c0e | ||
| 
						 | 
					453bab220b | ||
| 
						 | 
					448f8c4240 | ||
| 
						 | 
					5a414c6ad1 | ||
| 
						 | 
					65a942f01f | ||
| 
						 | 
					6df32fed62 | ||
| 
						 | 
					1199b48cd7 | ||
| 
						 | 
					c493f56e1b | ||
| 
						 | 
					2e65b8ce5f | ||
| 
						 | 
					42a6d954d3 | ||
| 
						 | 
					8f73b4c3ae | ||
| 
						 | 
					adcd06fccb | ||
| 
						 | 
					c40380f72a | ||
| 
						 | 
					8e44e884a2 | ||
| 
						 | 
					e2368be912 | ||
| 
						 | 
					7986fd4db7 | ||
| 
						 | 
					6107f4a02a | ||
| 
						 | 
					2ce63814e9 | ||
| 
						 | 
					8ba508f8f7 | ||
| 
						 | 
					2100490424 | ||
| 
						 | 
					7e7639e39a | ||
| 
						 | 
					3555d0ecd5 | ||
| 
						 | 
					ecb9a01cfa | ||
| 
						 | 
					ca352ebfba | ||
| 
						 | 
					29c73eb67b | ||
| 
						 | 
					2a598ff24d | ||
| 
						 | 
					f6d5837e5e | ||
| 
						 | 
					dac8cee72c | ||
| 
						 | 
					e01a2f8324 | ||
| 
						 | 
					a092ccb82b | ||
| 
						 | 
					e894d07b92 | ||
| 
						 | 
					befef6eb00 | ||
| 
						 | 
					162224979d | ||
| 
						 | 
					a90f6e2dda | ||
| 
						 | 
					e449bfd741 | ||
| 
						 | 
					8ecc1eb99d | ||
| 
						 | 
					1fb910411e | ||
| 
						 | 
					3141b86d01 | ||
| 
						 | 
					f8ff64c87e | ||
| 
						 | 
					c71b834aad | ||
| 
						 | 
					a78e7d0287 | ||
| 
						 | 
					09cf0fe6b9 | ||
| 
						 | 
					13713bc147 | ||
| 
						 | 
					9c17cf4edf | ||
| 
						 | 
					938b25b986 | ||
| 
						 | 
					040b76f1e6 | ||
| 
						 | 
					66226207ce | ||
| 
						 | 
					999b4168c1 | ||
| 
						 | 
					9bfc452487 | ||
| 
						 | 
					df675ed9fb | ||
| 
						 | 
					4a13ae4c95 | ||
| 
						 | 
					5287c71d68 | ||
| 
						 | 
					827f1a3d30 | ||
| 
						 | 
					f6d95e19c4 | ||
| 
						 | 
					3eb93f161f | ||
| 
						 | 
					801eff0c52 | ||
| 
						 | 
					c1993e76c2 | ||
| 
						 | 
					c23f56b9cb | ||
| 
						 | 
					44e17e2aa9 | ||
| 
						 | 
					84758667c1 | ||
| 
						 | 
					8c71113cd6 | ||
| 
						 | 
					79ba99811c | ||
| 
						 | 
					55a664d6fd | ||
| 
						 | 
					b4affd607d | ||
| 
						 | 
					c7007c98d7 | ||
| 
						 | 
					fa684a97da | ||
| 
						 | 
					cad03afc54 | ||
| 
						 | 
					fe6d782751 | ||
| 
						 | 
					dfe517cfbe | ||
| 
						 | 
					46ab95f24c | ||
| 
						 | 
					9a57ea4c4a | ||
| 
						 | 
					5fc98ffa69 | ||
| 
						 | 
					814eb397e1 | ||
| 
						 | 
					77f030956c | ||
| 
						 | 
					ab7ad3451d | ||
| 
						 | 
					1107f82824 | ||
| 
						 | 
					2bc2378033 | ||
| 
						 | 
					676e214f34 | ||
| 
						 | 
					7df1ccbf91 | ||
| 
						 | 
					82d3ee5454 | ||
| 
						 | 
					fcb6fb00e0 | ||
| 
						 | 
					4e09e6ca10 | ||
| 
						 | 
					af6dd44048 | ||
| 
						 | 
					d30ec9fd1e | ||
| 
						 | 
					16ee54ad23 | ||
| 
						 | 
					627409ec38 | ||
| 
						 | 
					4ead572462 | ||
| 
						 | 
					42783a54db | ||
| 
						 | 
					84763527c5 | ||
| 
						 | 
					1744c1c2ba | ||
| 
						 | 
					7ef5fbdbe6 | ||
| 
						 | 
					b1482c52b7 | ||
| 
						 | 
					7b0d61b96d | ||
| 
						 | 
					951b974c4d | ||
| 
						 | 
					975b3c3428 | ||
| 
						 | 
					f0420012e6 | ||
| 
						 | 
					30e5413e2b | ||
| 
						 | 
					5077a1bb83 | ||
| 
						 | 
					a8ed16de33 | ||
| 
						 | 
					ee0a4914d5 | ||
| 
						 | 
					8b70a0d0b7 | ||
| 
						 | 
					8e7c6b60fb | ||
| 
						 | 
					fbb0bb63e7 | ||
| 
						 | 
					46dc1b6e99 | ||
| 
						 | 
					82b34e06f2 | ||
| 
						 | 
					bc178df8f0 | ||
| 
						 | 
					d5a3de5a97 | ||
| 
						 | 
					b8774d7aac | ||
| 
						 | 
					891246562f | ||
| 
						 | 
					e53a955115 | ||
| 
						 | 
					1ec6812246 | ||
| 
						 | 
					e896691b0f | ||
| 
						 | 
					fbe92a13c0 | ||
| 
						 | 
					94a434e9e7 | ||
| 
						 | 
					e829c626da | ||
| 
						 | 
					837adeea7f | ||
| 
						 | 
					65d6350d36 | ||
| 
						 | 
					ba99186951 | ||
| 
						 | 
					b3975f5098 | ||
| 
						 | 
					b90f909289 | ||
| 
						 | 
					d098e4def6 | ||
| 
						 | 
					835b0d9f62 | ||
| 
						 | 
					9fea2798e3 | ||
| 
						 | 
					394cae5d21 | ||
| 
						 | 
					7996aae5e9 | ||
| 
						 | 
					9788b9d7a9 | ||
| 
						 | 
					6f5e1c3d73 | ||
| 
						 | 
					d4421b12ba | ||
| 
						 | 
					099b03f038 | ||
| 
						 | 
					f84d2eeec9 | ||
| 
						 | 
					f02531802c | ||
| 
						 | 
					375cb5c31d | ||
| 
						 | 
					8f2ba4ec3c | ||
| 
						 | 
					9935d1183a | ||
| 
						 | 
					aff8e77bec | ||
| 
						 | 
					c9fd743c65 | ||
| 
						 | 
					7a4fa925fc | ||
| 
						 | 
					ff442c1e28 | ||
| 
						 | 
					5cedaa972a | ||
| 
						 | 
					2c8f647e0c | ||
| 
						 | 
					3be5edae0e | ||
| 
						 | 
					1078f24d5a | ||
| 
						 | 
					c02cc5321a | ||
| 
						 | 
					e60a7ff1d0 | ||
| 
						 | 
					91de7311d7 | ||
| 
						 | 
					e357c9fc0c | ||
| 
						 | 
					ec4daa5936 | ||
| 
						 | 
					2743fb9771 | ||
| 
						 | 
					88c4802bdc | ||
| 
						 | 
					a47e422715 | ||
| 
						 | 
					3a9ab631e5 | ||
| 
						 | 
					9ca5118a68 | ||
| 
						 | 
					d6053080f8 | ||
| 
						 | 
					b1f8076da0 | ||
| 
						 | 
					abc760c8e4 | ||
| 
						 | 
					0331a34d58 | ||
| 
						 | 
					98af0ba143 | ||
| 
						 | 
					157810ea3d | ||
| 
						 | 
					448e4251f8 | ||
| 
						 | 
					81ce20d616 | ||
| 
						 | 
					3e9ab41e76 | ||
| 
						 | 
					a3c8fbc6b6 | ||
| 
						 | 
					e9dc6880af | ||
| 
						 | 
					25fb2c4fb6 | ||
| 
						 | 
					97d28ae4d7 | ||
| 
						 | 
					b5bad15dae | ||
| 
						 | 
					3098ef4a6e | ||
| 
						 | 
					e354b1210e | ||
| 
						 | 
					895b6ff719 | ||
| 
						 | 
					0a22655ff3 | ||
| 
						 | 
					8def378b5e | ||
| 
						 | 
					7ab8b44b6c | ||
| 
						 | 
					335fe09d70 | ||
| 
						 | 
					523a7ed7d3 | ||
| 
						 | 
					f69e8e3606 | ||
| 
						 | 
					3516797b49 | ||
| 
						 | 
					1683e94f0c | ||
| 
						 | 
					1d249195a4 | ||
| 
						 | 
					2f7ee08288 | ||
| 
						 | 
					e0772fb301 | ||
| 
						 | 
					78bdbce2fd | ||
| 
						 | 
					5a5fed28fa | ||
| 
						 | 
					5818b6efb8 | ||
| 
						 | 
					53a66492e8 | ||
| 
						 | 
					b17ddc26c0 | ||
| 
						 | 
					b7e19d2fe3 | ||
| 
						 | 
					d8130a99b4 | ||
| 
						 | 
					8c654aeebe | ||
| 
						 | 
					bad318d451 | ||
| 
						 | 
					11d2997e44 | ||
| 
						 | 
					2d75d2e76e | ||
| 
						 | 
					6074f58641 | ||
| 
						 | 
					48de09c279 | ||
| 
						 | 
					032c2cb462 | ||
| 
						 | 
					2008367883 | ||
| 
						 | 
					165d88cfd8 | ||
| 
						 | 
					0c0e1fbbeb | ||
| 
						 | 
					3559e20dab | ||
| 
						 | 
					e400f6eab9 | ||
| 
						 | 
					cffffe0c2e | ||
| 
						 | 
					70fcdb495a | ||
| 
						 | 
					c1b2049df9 | ||
| 
						 | 
					f6cabc78c0 | ||
| 
						 | 
					b8526452b5 | ||
| 
						 | 
					a1cefb3e17 | ||
| 
						 | 
					def0f38f3d | ||
| 
						 | 
					58a8b00086 | ||
| 
						 | 
					50a27398b0 | ||
| 
						 | 
					eab7cba1f3 | ||
| 
						 | 
					83774ba6ae | ||
| 
						 | 
					ab700b4ea3 | ||
| 
						 | 
					bf7936d494 | ||
| 
						 | 
					14f627329d | ||
| 
						 | 
					829c996611 | ||
| 
						 | 
					dff2e8ecb4 | ||
| 
						 | 
					7c79b1c7c5 | ||
| 
						 | 
					a390fac356 | ||
| 
						 | 
					9a43e67347 | ||
| 
						 | 
					b0d08c572a | ||
| 
						 | 
					ee4eb0aa6f | ||
| 
						 | 
					07e27cac02 | ||
| 
						 | 
					cdc905cc16 | ||
| 
						 | 
					88b0c82a0d | ||
| 
						 | 
					01d3349587 | ||
| 
						 | 
					cf7f096db7 | ||
| 
						 | 
					21ed352ac5 | ||
| 
						 | 
					f8a4f79277 | ||
| 
						 | 
					16d385ac6a | ||
| 
						 | 
					3dc1945b44 | ||
| 
						 | 
					3c7db9e986 | ||
| 
						 | 
					44e1f095d1 | ||
| 
						 | 
					90c39b8371 | ||
| 
						 | 
					17b7944ac2 | ||
| 
						 | 
					bbf486f890 | ||
| 
						 | 
					20faa956a8 | ||
| 
						 | 
					74a4e04185 | ||
| 
						 | 
					b102455b57 | ||
| 
						 | 
					c2235a0baa | ||
| 
						 | 
					c36d2b02a3 | ||
| 
						 | 
					4eb8d86346 | ||
| 
						 | 
					1b33fbf98b | ||
| 
						 | 
					3f74391b87 | ||
| 
						 | 
					93c954dae1 | ||
| 
						 | 
					f736563a7a | ||
| 
						 | 
					0350c4f0f6 | ||
| 
						 | 
					0c0caf0272 | ||
| 
						 | 
					9abd966a80 | ||
| 
						 | 
					a1dbd7156c | ||
| 
						 | 
					b74e5b870c | ||
| 
						 | 
					bcb021296f | ||
| 
						 | 
					dcf907f36d | ||
| 
						 | 
					972b11e39e | ||
| 
						 | 
					10fffe842b | ||
| 
						 | 
					963cf98df1 | ||
| 
						 | 
					0f64ddf2fb | ||
| 
						 | 
					3fa82818b9 | ||
| 
						 | 
					c48ba4464c | ||
| 
						 | 
					2d1118a26f | ||
| 
						 | 
					53560b8e0b | ||
| 
						 | 
					3f647cdf32 | ||
| 
						 | 
					9a0dc6d522 | ||
| 
						 | 
					c819525e81 | ||
| 
						 | 
					4024ad5eb2 | ||
| 
						 | 
					2c0df9552f | ||
| 
						 | 
					9359586fde | ||
| 
						 | 
					68069c70e1 | ||
| 
						 | 
					6a00ceeb66 | ||
| 
						 | 
					8143f55488 | ||
| 
						 | 
					03e03fb7a1 | ||
| 
						 | 
					b13b8c1882 | ||
| 
						 | 
					02a2afb64f | ||
| 
						 | 
					ae8e907d72 | ||
| 
						 | 
					f042834068 | ||
| 
						 | 
					63130374b9 | ||
| 
						 | 
					ac01d56747 | ||
| 
						 | 
					6f751afae4 | ||
| 
						 | 
					8fd85fb6e6 | ||
| 
						 | 
					1dbfe1e856 | ||
| 
						 | 
					d3fd4c0381 | ||
| 
						 | 
					0e20e05795 | ||
| 
						 | 
					3bb0dc03af | ||
| 
						 | 
					4257485ff2 | ||
| 
						 | 
					f69b7a58f2 | ||
| 
						 | 
					fd4fe42013 | ||
| 
						 | 
					930820b738 | ||
| 
						 | 
					06cc081ca2 | ||
| 
						 | 
					ee9bf16d1a | ||
| 
						 | 
					f08e65fd04 | ||
| 
						 | 
					877de45d6e | ||
| 
						 | 
					5a4813d336 | ||
| 
						 | 
					6dc818deb1 | ||
| 
						 | 
					4b2bf06873 | ||
| 
						 | 
					839af3e90e | ||
| 
						 | 
					c059cdd0f2 | ||
| 
						 | 
					0ba837e163 | ||
| 
						 | 
					1ddcf370a7 | ||
| 
						 | 
					e0559e4fda | ||
| 
						 | 
					eeefbfd38d | ||
| 
						 | 
					60ba4943ec | ||
| 
						 | 
					ba4ac17425 | ||
| 
						 | 
					3965d3ba83 | ||
| 
						 | 
					3435f24770 | ||
| 
						 | 
					31672ff60e | ||
| 
						 | 
					6e619f8927 | ||
| 
						 | 
					2ccdb165e3 | ||
| 
						 | 
					db8eab04e3 | ||
| 
						 | 
					4e2e8954dc | ||
| 
						 | 
					a25fe81b9e | ||
| 
						 | 
					bce3ac2c73 | ||
| 
						 | 
					52b70fbbfa | ||
| 
						 | 
					08b540dd78 | ||
| 
						 | 
					22e91979bb | ||
| 
						 | 
					e3730ecfc3 | ||
| 
						 | 
					9cfc9b3ee2 | ||
| 
						 | 
					c0ff3805c8 | ||
| 
						 | 
					49ebd19ab1 | ||
| 
						 | 
					79bcc98e9b | ||
| 
						 | 
					a58980fe82 | ||
| 
						 | 
					fe67a86a5f | ||
| 
						 | 
					4d85bb13d1 | ||
| 
						 | 
					0501c06745 | ||
| 
						 | 
					abb2e6ea9b | ||
| 
						 | 
					a99a30d720 | ||
| 
						 | 
					0670c8f60f | ||
| 
						 | 
					dfdcb92f3d | ||
| 
						 | 
					bc9b5706e9 | ||
| 
						 | 
					64c37a20d1 | ||
| 
						 | 
					6d2d4f72ac | ||
| 
						 | 
					4c151970e6 | ||
| 
						 | 
					e65e815aae | ||
| 
						 | 
					db3fb23de4 | ||
| 
						 | 
					5c9adc4052 | ||
| 
						 | 
					b8c8c29ee4 | ||
| 
						 | 
					47c0c71e19 | ||
| 
						 | 
					7d26a86071 | ||
| 
						 | 
					556d880951 | ||
| 
						 | 
					4ee50ed6de | ||
| 
						 | 
					b1b5a9d8fa | ||
| 
						 | 
					62d8848bee | ||
| 
						 | 
					c63b16cf75 | ||
| 
						 | 
					d32a6f15bf | ||
| 
						 | 
					918abadb6c | ||
| 
						 | 
					7f5adb135d | ||
| 
						 | 
					b1ce301520 | ||
| 
						 | 
					cd93201e46 | ||
| 
						 | 
					c9aaf5fb24 | ||
| 
						 | 
					fdf1e32962 | ||
| 
						 | 
					36d336618e | ||
| 
						 | 
					013f27e3e6 | ||
| 
						 | 
					1b3f8a4c18 | ||
| 
						 | 
					dd8ef51fa1 | ||
| 
						 | 
					11e8d26606 | ||
| 
						 | 
					1e954bc8ef | ||
| 
						 | 
					720eb0e91c | ||
| 
						 | 
					106763ef9a | ||
| 
						 | 
					10019a9d96 | ||
| 
						 | 
					4515bcf289 | ||
| 
						 | 
					aa8728a2ab | ||
| 
						 | 
					f2d3b3661b | ||
| 
						 | 
					24b598b1be | ||
| 
						 | 
					0d98ee8916 | ||
| 
						 | 
					3eca5ad9a1 | ||
| 
						 | 
					ed2465fd30 | ||
| 
						 | 
					6d21e61889 | ||
| 
						 | 
					983312d14d | ||
| 
						 | 
					2e1271fe36 | ||
| 
						 | 
					15e53c9839 | ||
| 
						 | 
					115d48497e | ||
| 
						 | 
					a31948f3b7 | ||
| 
						 | 
					a12106eb52 | ||
| 
						 | 
					dd9f42172f | ||
| 
						 | 
					3d8e149668 | ||
| 
						 | 
					f557647525 | ||
| 
						 | 
					1efaf2cde0 | ||
| 
						 | 
					202aea4dda | ||
| 
						 | 
					eaefa1ac5d | ||
| 
						 | 
					fd49174b1a | ||
| 
						 | 
					342605bb44 | ||
| 
						 | 
					a9851f5e95 | ||
| 
						 | 
					848b39b5a0 | ||
| 
						 | 
					de372ce095 | ||
| 
						 | 
					8bbae4b10b | ||
| 
						 | 
					cff2eda198 | ||
| 
						 | 
					7a75b47da6 | ||
| 
						 | 
					79430340e5 | ||
| 
						 | 
					4494c25df7 | ||
| 
						 | 
					763d659ee2 | ||
| 
						 | 
					54086f86d2 | ||
| 
						 | 
					9195a23c95 | ||
| 
						 | 
					739ba0fbcc | ||
| 
						 | 
					93ac41e917 | ||
| 
						 | 
					1928af2a42 | ||
| 
						 | 
					45e6585e77 | ||
| 
						 | 
					8d6fbe1a89 | ||
| 
						 | 
					375b420c35 | ||
| 
						 | 
					887b48bd1d | ||
| 
						 | 
					0794a2e526 | ||
| 
						 | 
					a859e44630 | ||
| 
						 | 
					1c1a248277 | ||
| 
						 | 
					e0e2165c8e | ||
| 
						 | 
					957f8315e3 | ||
| 
						 | 
					d279ed7dd6 | ||
| 
						 | 
					827480b9d6 | ||
| 
						 | 
					1a0af097a6 | ||
| 
						 | 
					d408fc2864 | ||
| 
						 | 
					bba03eef2f | ||
| 
						 | 
					352f7d7f2b | ||
| 
						 | 
					0f07768d6b | ||
| 
						 | 
					a6a2be6e37 | ||
| 
						 | 
					e840cc8b91 | ||
| 
						 | 
					ff17105386 | ||
| 
						 | 
					d82f7b9205 | ||
| 
						 | 
					01b09aab43 | ||
| 
						 | 
					f0153d801e | ||
| 
						 | 
					319b2d8f32 | ||
| 
						 | 
					419675cd2b | ||
| 
						 | 
					9dd273626a | ||
| 
						 | 
					2997acf9dc | ||
| 
						 | 
					1ee9677b8a | ||
| 
						 | 
					9c14c897f5 | ||
| 
						 | 
					dc3e37956b | ||
| 
						 | 
					eb283dcbc6 | ||
| 
						 | 
					fec2b39df3 | ||
| 
						 | 
					1e1b8cc2d5 | ||
| 
						 | 
					8a902d7e58 | ||
| 
						 | 
					1a0d994305 | ||
| 
						 | 
					597986b711 | ||
| 
						 | 
					ba0a843482 | ||
| 
						 | 
					0ad0f9e094 | ||
| 
						 | 
					f93a548fe2 | ||
| 
						 | 
					84b0920fe0 | ||
| 
						 | 
					a3d7f70d45 | ||
| 
						 | 
					99b7ce7bf5 | ||
| 
						 | 
					819e3b9661 | ||
| 
						 | 
					cac468586a | ||
| 
						 | 
					afc8c05f7f | ||
| 
						 | 
					886e528490 | ||
| 
						 | 
					06691a0794 | ||
| 
						 | 
					c61da238e1 | ||
| 
						 | 
					e07419b4ba | ||
| 
						 | 
					cecc0e9dc8 | ||
| 
						 | 
					4d4d7c1fb3 | ||
| 
						 | 
					e50e7ee119 | ||
| 
						 | 
					0d15d01b45 | ||
| 
						 | 
					7972728e7c | ||
| 
						 | 
					d4d430ee80 | ||
| 
						 | 
					b2155fde1a | ||
| 
						 | 
					0033b9eeb5 | ||
| 
						 | 
					3d25b06fbc | ||
| 
						 | 
					32752bc3dd | ||
| 
						 | 
					f1fd43b61c | ||
| 
						 | 
					38fda754a1 | ||
| 
						 | 
					dc4e40a2f6 | ||
| 
						 | 
					9abda62c5b | ||
| 
						 | 
					cd5c37fe1c | ||
| 
						 | 
					bce8cac1f4 | ||
| 
						 | 
					4171d0c301 | ||
| 
						 | 
					2edd956853 | ||
| 
						 | 
					d77b03d6c9 | ||
| 
						 | 
					4d5a88661f | ||
| 
						 | 
					0b9b1ccd0b | ||
| 
						 | 
					d5ef8e037d | ||
| 
						 | 
					fd09a32d5e | ||
| 
						 | 
					afc5de69d4 | ||
| 
						 | 
					2adec6ef66 | ||
| 
						 | 
					5829d87313 | ||
| 
						 | 
					4422423315 | ||
| 
						 | 
					6c88b6c660 | ||
| 
						 | 
					ccca1401ae | ||
| 
						 | 
					39270f9647 | ||
| 
						 | 
					3b6a147653 | ||
| 
						 | 
					fd69075a8b | ||
| 
						 | 
					dfed228991 | ||
| 
						 | 
					5403c6122c | ||
| 
						 | 
					ec76533493 | ||
| 
						 | 
					fbdc356b7c | ||
| 
						 | 
					709e1afd31 | ||
| 
						 | 
					217bbd0dcb | ||
| 
						 | 
					e32f9edc3d | ||
| 
						 | 
					282029eb45 | ||
| 
						 | 
					0ae88174b8 | ||
| 
						 | 
					42fdc445d0 | ||
| 
						 | 
					48416fcdc1 | ||
| 
						 | 
					5dab79f1c7 | ||
| 
						 | 
					cfe2d71862 | ||
| 
						 | 
					db03ac1596 | ||
| 
						 | 
					36a1405360 | ||
| 
						 | 
					85d1fe36e1 | ||
| 
						 | 
					0148ff5ea2 | ||
| 
						 | 
					89f096d68e | ||
| 
						 | 
					db9a15e2fa | ||
| 
						 | 
					84ae15e8d1 | ||
| 
						 | 
					f69451140f | ||
| 
						 | 
					ca897d8d15 | ||
| 
						 | 
					4cacc0ee7d | ||
| 
						 | 
					93148f9334 | ||
| 
						 | 
					9ae2f02842 | ||
| 
						 | 
					bc63df367d | ||
| 
						 | 
					3f76b672f2 | ||
| 
						 | 
					c79f1d5f37 | ||
| 
						 | 
					db023c4448 | ||
| 
						 | 
					48f66c5cb4 | ||
| 
						 | 
					f54cd61ba6 | ||
| 
						 | 
					011ec46dae | ||
| 
						 | 
					6c91562aa9 | ||
| 
						 | 
					a3ce036dc0 | ||
| 
						 | 
					c82ecd6656 | ||
| 
						 | 
					7ce37c9842 | ||
| 
						 | 
					6e4baa664d | ||
| 
						 | 
					59ffb010c4 | ||
| 
						 | 
					2edb216b24 | ||
| 
						 | 
					7835e2a762 | ||
| 
						 | 
					f8c9d0c018 | ||
| 
						 | 
					2965b52563 | ||
| 
						 | 
					05762487ff | ||
| 
						 | 
					b2380fcc48 | ||
| 
						 | 
					40ec4f631c | ||
| 
						 | 
					f9238f838c | ||
| 
						 | 
					3dd756c2c1 | ||
| 
						 | 
					a92bdc094d | ||
| 
						 | 
					9b367aa0a1 | ||
| 
						 | 
					2201a47d95 | ||
| 
						 | 
					bdb578fda2 | ||
| 
						 | 
					6765f24184 | ||
| 
						 | 
					5ec0df6fe1 | ||
| 
						 | 
					594fbed146 | ||
| 
						 | 
					20e2e324e1 | ||
| 
						 | 
					f33e774f4b | ||
| 
						 | 
					dbdce70a8e | ||
| 
						 | 
					b41f609fe4 | ||
| 
						 | 
					424f396e42 | ||
| 
						 | 
					b1c01d2ac9 | ||
| 
						 | 
					fed21338fc | ||
| 
						 | 
					987fe8b638 | ||
| 
						 | 
					535c4372ca | ||
| 
						 | 
					ac1f36ae76 | ||
| 
						 | 
					b1442a1a97 | ||
| 
						 | 
					6628e7769e | ||
| 
						 | 
					5fadbc7f97 | ||
| 
						 | 
					095026b459 | ||
| 
						 | 
					496c8d01fa | ||
| 
						 | 
					63574298ce | ||
| 
						 | 
					8c1a5f033e | ||
| 
						 | 
					7e3141512a | ||
| 
						 | 
					c4510327d4 | ||
| 
						 | 
					88fc2bb3e1 | ||
| 
						 | 
					75a6913f4e | ||
| 
						 | 
					97472070c3 | ||
| 
						 | 
					5d4fd6055e | ||
| 
						 | 
					83f4e5b457 | ||
| 
						 | 
					1523a4953f | ||
| 
						 | 
					429139be78 | ||
| 
						 | 
					0307c0366a | ||
| 
						 | 
					f698db8346 | ||
| 
						 | 
					b690ccfc20 | ||
| 
						 | 
					86e97d9f87 | ||
| 
						 | 
					4a7a570953 | ||
| 
						 | 
					0b1ce57fd1 | ||
| 
						 | 
					eb39bfad81 | ||
| 
						 | 
					77533a2090 | ||
| 
						 | 
					414bc9cc44 | ||
| 
						 | 
					180d55d135 | ||
| 
						 | 
					458baea830 | ||
| 
						 | 
					aaeec65415 | ||
| 
						 | 
					3a821c040e | ||
| 
						 | 
					31fdb438bb | ||
| 
						 | 
					8db00f063d | ||
| 
						 | 
					8cca58b800 | ||
| 
						 | 
					9f2e60598d | ||
| 
						 | 
					78af10f81b | ||
| 
						 | 
					025ac59005 | ||
| 
						 | 
					2b9605e8f5 | ||
| 
						 | 
					333091a0d3 | ||
| 
						 | 
					012ff9982c | ||
| 
						 | 
					887e1d5d61 | ||
| 
						 | 
					3aca463e7e | ||
| 
						 | 
					b7255dac54 | ||
| 
						 | 
					a3158f498f | ||
| 
						 | 
					95ff997d1d | ||
| 
						 | 
					80520d4ed7 | ||
| 
						 | 
					1fbf5728e1 | ||
| 
						 | 
					216b6b3efd | ||
| 
						 | 
					557f287005 | ||
| 
						 | 
					7548112578 | ||
| 
						 | 
					323685d4c9 | ||
| 
						 | 
					4900b15a65 | ||
| 
						 | 
					adc02e52ad | ||
| 
						 | 
					4bc79321a7 | ||
| 
						 | 
					c0d270947f | ||
| 
						 | 
					8b4677dca3 | ||
| 
						 | 
					44482a809e | ||
| 
						 | 
					90d8fab02e | ||
| 
						 | 
					337d248c5d | ||
| 
						 | 
					62a636c887 | ||
| 
						 | 
					bbd12ca7aa | ||
| 
						 | 
					02f858e5c9 | ||
| 
						 | 
					536a126886 | ||
| 
						 | 
					2a42fdea85 | ||
| 
						 | 
					eb77e55fe6 | ||
| 
						 | 
					edd643b226 | ||
| 
						 | 
					4f7f3b5a50 | ||
| 
						 | 
					1b611e7cd8 | ||
| 
						 | 
					5454ec8f9b | ||
| 
						 | 
					d2d528d214 | ||
| 
						 | 
					a00d4b7845 | ||
| 
						 | 
					0eeefc4c0d | ||
| 
						 | 
					0d8600ed6d | ||
| 
						 | 
					35cf511d45 | ||
| 
						 | 
					b88fe43808 | ||
| 
						 | 
					9c72fc1d2b | ||
| 
						 | 
					e176789891 | ||
| 
						 | 
					5e3369aba3 | ||
| 
						 | 
					7b0fcd79a0 | ||
| 
						 | 
					0ed40c04c7 | ||
| 
						 | 
					7da36611dc | ||
| 
						 | 
					49aeee3017 | ||
| 
						 | 
					571cd5a94f | ||
| 
						 | 
					a044570365 | ||
| 
						 | 
					c18595ce31 | ||
| 
						 | 
					a06d6839e1 | ||
| 
						 | 
					22ba3c7b41 | ||
| 
						 | 
					e84ecd9e42 | ||
| 
						 | 
					db5e7962c9 | ||
| 
						 | 
					4782f379e2 | ||
| 
						 | 
					8762b5aad4 | ||
| 
						 | 
					147d76d2aa | ||
| 
						 | 
					a5aedfee75 | ||
| 
						 | 
					2a4c743edd | ||
| 
						 | 
					a9d820ed2f | ||
| 
						 | 
					fa059a59a8 | ||
| 
						 | 
					dc8f5ef279 | ||
| 
						 | 
					e5e30dc73d | ||
| 
						 | 
					ae94917e76 | ||
| 
						 | 
					fedb3704f3 | ||
| 
						 | 
					ea18f8e19b | ||
| 
						 | 
					cd93b0470b | ||
| 
						 | 
					4665b5aecf | ||
| 
						 | 
					1f9b9c6235 | ||
| 
						 | 
					3f4c43456f | ||
| 
						 | 
					10a3ba33a5 | ||
| 
						 | 
					db0beacf02 | ||
| 
						 | 
					a07023d613 | ||
| 
						 | 
					900c634af1 | ||
| 
						 | 
					48d9b570b9 | ||
| 
						 | 
					207ddca859 | ||
| 
						 | 
					823b00705e | ||
| 
						 | 
					4fb0ddedc7 | ||
| 
						 | 
					31b3571d31 | ||
| 
						 | 
					ee373a2721 | ||
| 
						 | 
					685bc7ae83 | ||
| 
						 | 
					bc6772282f | ||
| 
						 | 
					d0d0c1e5e5 | ||
| 
						 | 
					1ed598ada6 | ||
| 
						 | 
					b003ae7270 | ||
| 
						 | 
					18a4a3e21c | ||
| 
						 | 
					72a41480ba | ||
| 
						 | 
					6e221abda6 | ||
| 
						 | 
					e7d8b84581 | ||
| 
						 | 
					7a84430e84 | ||
| 
						 | 
					7e7274b002 | ||
| 
						 | 
					e27183d54f | ||
| 
						 | 
					f49c31ddb2 | ||
| 
						 | 
					ac959238aa | ||
| 
						 | 
					563b6561a5 | ||
| 
						 | 
					bc26690cbf | ||
| 
						 | 
					4f56896f60 | ||
| 
						 | 
					5158d34c2d | ||
| 
						 | 
					5c63f0b7e3 | ||
| 
						 | 
					1b3fa825f3 | ||
| 
						 | 
					ef182f4b64 | ||
| 
						 | 
					b706479c9b | ||
| 
						 | 
					751c4fe7ef | ||
| 
						 | 
					d09baef532 | ||
| 
						 | 
					778244e436 | ||
| 
						 | 
					f6cf83aebf | ||
| 
						 | 
					e6901382a6 | ||
| 
						 | 
					75c22b585e | ||
| 
						 | 
					5018d3b5cb | ||
| 
						 | 
					9eeacf2cfc | ||
| 
						 | 
					9c25d59b82 | ||
| 
						 | 
					4550133c81 | ||
| 
						 | 
					8a5921e4bc | ||
| 
						 | 
					470aa36c91 | ||
| 
						 | 
					1fbcff5fcc | ||
| 
						 | 
					6fb06af9ff | ||
| 
						 | 
					62941d65a9 | ||
| 
						 | 
					18fe170698 | ||
| 
						 | 
					c2cd4d5d15 | ||
| 
						 | 
					69da2ac0c7 | ||
| 
						 | 
					e08e69719d | ||
| 
						 | 
					5628024d45 | ||
| 
						 | 
					9d46d25d03 | ||
| 
						 | 
					836326f31e | ||
| 
						 | 
					34fe80f9d9 | ||
| 
						 | 
					15ae133662 | ||
| 
						 | 
					c405a5d5b3 | ||
| 
						 | 
					7acff3b938 | ||
| 
						 | 
					7099be8f44 | ||
| 
						 | 
					86e8c36a75 | ||
| 
						 | 
					bc6fe86faa | ||
| 
						 | 
					3bcab11310 | ||
| 
						 | 
					3c8b92675f | ||
| 
						 | 
					0f19d74cb1 | ||
| 
						 | 
					d796a2a768 | ||
| 
						 | 
					f962adbb52 | ||
| 
						 | 
					3479d0ee30 | ||
| 
						 | 
					70a0590ece | ||
| 
						 | 
					8414c57026 | ||
| 
						 | 
					ae2e7f0603 | ||
| 
						 | 
					7177c3b393 | ||
| 
						 | 
					11f40ba93b | ||
| 
						 | 
					273511037a | ||
| 
						 | 
					56d64f23bf | ||
| 
						 | 
					cfbeca5e65 | ||
| 
						 | 
					aaf9b56084 | ||
| 
						 | 
					e0a953e27e | ||
| 
						 | 
					f7c1e5f60d | ||
| 
						 | 
					84bf81ac31 | ||
| 
						 | 
					6a67a8c574 | ||
| 
						 | 
					0fad9eaee4 | ||
| 
						 | 
					d64d33ed07 | ||
| 
						 | 
					0e8fdf49d0 | ||
| 
						 | 
					f147256697 | ||
| 
						 | 
					dbe275ce72 | ||
| 
						 | 
					649cd608c1 | ||
| 
						 | 
					87c63e995b | ||
| 
						 | 
					cd49c5bf66 | ||
| 
						 | 
					c3ca9468d1 | ||
| 
						 | 
					89576aa2c1 | ||
| 
						 | 
					630dbab749 | ||
| 
						 | 
					8e95a2a603 | ||
| 
						 | 
					6a1c94d48d | ||
| 
						 | 
					578a9a3332 | ||
| 
						 | 
					122fe8a20d | ||
| 
						 | 
					d32f607aba | ||
| 
						 | 
					25d9591416 | ||
| 
						 | 
					33f41cc68b | ||
| 
						 | 
					d8bee53822 | ||
| 
						 | 
					0866f47904 | ||
| 
						 | 
					d230325569 | ||
| 
						 | 
					8e7930a604 | ||
| 
						 | 
					1dde89db69 | ||
| 
						 | 
					350d0a6495 | ||
| 
						 | 
					42e922d587 | ||
| 
						 | 
					57c002f324 | ||
| 
						 | 
					e5fb684ac1 | ||
| 
						 | 
					84abdc7b2d | ||
| 
						 | 
					db79a4a14b | ||
| 
						 | 
					f1b30c5aff | ||
| 
						 | 
					4db2593801 | ||
| 
						 | 
					ad685d2153 | ||
| 
						 | 
					cf9dd7cf5e | ||
| 
						 | 
					f10d82dc30 | ||
| 
						 | 
					5ec942fb2a | ||
| 
						 | 
					2897cfb556 | ||
| 
						 | 
					5484869af9 | ||
| 
						 | 
					90cc3a0f05 | ||
| 
						 | 
					99e45f71c2 | ||
| 
						 | 
					488d246ada | ||
| 
						 | 
					8189910b5a | ||
| 
						 | 
					de317b8e01 | ||
| 
						 | 
					436cf94595 | ||
| 
						 | 
					145c999762 | ||
| 
						 | 
					c82b46032a | ||
| 
						 | 
					cf9fa94eaa | ||
| 
						 | 
					d5139fef22 | ||
| 
						 | 
					f8964db41c | ||
| 
						 | 
					052169695c | ||
| 
						 | 
					f9a8a94fd1 | ||
| 
						 | 
					880d9bb33f | ||
| 
						 | 
					68aa3eb1b9 | ||
| 
						 | 
					39dbb9dad8 | ||
| 
						 | 
					ac7acf2441 | ||
| 
						 | 
					87ce5770b7 | ||
| 
						 | 
					24f3c8c29e | ||
| 
						 | 
					cf578d50ec | ||
| 
						 | 
					6c2e4110ad | ||
| 
						 | 
					01280bbd06 | ||
| 
						 | 
					0f1b7a527b | ||
| 
						 | 
					965c7e1200 | ||
| 
						 | 
					abea4f481c | ||
| 
						 | 
					71191eae5c | ||
| 
						 | 
					03d4efc5c0 | ||
| 
						 | 
					22c38019b2 | ||
| 
						 | 
					7cd8194c99 | ||
| 
						 | 
					b4747ad67f | ||
| 
						 | 
					bb6db55686 | ||
| 
						 | 
					244cd8f94f | ||
| 
						 | 
					ba856910e0 | ||
| 
						 | 
					d00e023894 | ||
| 
						 | 
					86b4b128a9 | ||
| 
						 | 
					35bd06a9a0 | ||
| 
						 | 
					bdc7574fd5 | ||
| 
						 | 
					a7cac2463c | ||
| 
						 | 
					474bc8823e | ||
| 
						 | 
					95f6b0c06e | ||
| 
						 | 
					dc205333cd | ||
| 
						 | 
					4de96ea715 | ||
| 
						 | 
					c94f02648c | ||
| 
						 | 
					2ba0dd20fb | ||
| 
						 | 
					389dc22856 | ||
| 
						 | 
					823c8af1ab | ||
| 
						 | 
					286562d202 | ||
| 
						 | 
					b83a1876ba | ||
| 
						 | 
					ed2a931ae3 | ||
| 
						 | 
					f77190f477 | ||
| 
						 | 
					2d3335fa48 | ||
| 
						 | 
					d52b3fd3fe | ||
| 
						 | 
					5a945afdc6 | ||
| 
						 | 
					8b65ad0237 | ||
| 
						 | 
					6d74246c91 | ||
| 
						 | 
					9d81c953c3 | ||
| 
						 | 
					97e41de23f | ||
| 
						 | 
					d57543b220 | ||
| 
						 | 
					13cd91bffb | ||
| 
						 | 
					2d170dfed8 | ||
| 
						 | 
					744ac0eb81 | ||
| 
						 | 
					057983ce3e | ||
| 
						 | 
					aadc34ab4d | ||
| 
						 | 
					d9c4af46ed | ||
| 
						 | 
					cdd0024bad | ||
| 
						 | 
					6e331c523f | ||
| 
						 | 
					f7712c77b8 | ||
| 
						 | 
					fd436c316a | ||
| 
						 | 
					7120f7df54 | ||
| 
						 | 
					1d30bf8af4 | ||
| 
						 | 
					40c70e12dd | ||
| 
						 | 
					31b6eb916f | ||
| 
						 | 
					09e7a582de | ||
| 
						 | 
					b8aec00dee | ||
| 
						 | 
					174f5a3a49 | ||
| 
						 | 
					758d469679 | ||
| 
						 | 
					542bdaa740 | ||
| 
						 | 
					14bd66805e | ||
| 
						 | 
					01c2d76c54 | ||
| 
						 | 
					40cd0b1dd2 | ||
| 
						 | 
					5dad791818 | ||
| 
						 | 
					3743a6858b | ||
| 
						 | 
					409a8d3678 | ||
| 
						 | 
					94084178d9 | ||
| 
						 | 
					3c80245275 | ||
| 
						 | 
					16c4b2a572 | ||
| 
						 | 
					0cf1e72ed1 | ||
| 
						 | 
					029346d322 | ||
| 
						 | 
					9e959f9bdd | ||
| 
						 | 
					3ec8c63e28 | ||
| 
						 | 
					ceeb1eca9d | ||
| 
						 | 
					5800560602 | ||
| 
						 | 
					a840a56e02 | ||
| 
						 | 
					8704f4e24e | ||
| 
						 | 
					459a5a5b1f | ||
| 
						 | 
					afc28c54ac | ||
| 
						 | 
					6772b45ea6 | ||
| 
						 | 
					7defd4dab0 | ||
| 
						 | 
					db326a14b3 | ||
| 
						 | 
					0abf2e237e | ||
| 
						 | 
					d3a2b52363 | ||
| 
						 | 
					de81594179 | ||
| 
						 | 
					06bdf8b461 | ||
| 
						 | 
					d784303591 | ||
| 
						 | 
					52d2c31427 | ||
| 
						 | 
					9bc8e56458 | ||
| 
						 | 
					489c728793 | ||
| 
						 | 
					01eaadfa53 | ||
| 
						 | 
					dddd2f9202 | ||
| 
						 | 
					31709134c9 | ||
| 
						 | 
					456efad714 | ||
| 
						 | 
					2112fc571a | ||
| 
						 | 
					0c4379ff0f | ||
| 
						 | 
					a690b36478 | ||
| 
						 | 
					6f5ed95f71 | ||
| 
						 | 
					251ee5f5a2 | ||
| 
						 | 
					9ab1d88a91 | ||
| 
						 | 
					5d3d9f57fe | ||
| 
						 | 
					0889882255 | ||
| 
						 | 
					2a1f78f95a | ||
| 
						 | 
					6faaa1a0cc | ||
| 
						 | 
					77dd12a028 | ||
| 
						 | 
					6a954445f1 | ||
| 
						 | 
					9500e898c6 | ||
| 
						 | 
					c5989d4350 | ||
| 
						 | 
					8f782be41d | ||
| 
						 | 
					afcc447a64 | ||
| 
						 | 
					8cfcba83ae | ||
| 
						 | 
					a8315726ce | ||
| 
						 | 
					da668c80b2 | ||
| 
						 | 
					55455ac21f | ||
| 
						 | 
					74adacf96a | ||
| 
						 | 
					a384b41308 | ||
| 
						 | 
					048a329afc | ||
| 
						 | 
					3c3d16e794 | ||
| 
						 | 
					d95b544dfd | ||
| 
						 | 
					5d9ea7b91b | ||
| 
						 | 
					500289229a | ||
| 
						 | 
					21d62387ae | ||
| 
						 | 
					3bbfb30dcb | ||
| 
						 | 
					819fbc6ed5 | ||
| 
						 | 
					53e7c8fa34 | ||
| 
						 | 
					35d13cad96 | ||
| 
						 | 
					c190fc702e | ||
| 
						 | 
					cd0ed7b509 | ||
| 
						 | 
					24af685db1 | ||
| 
						 | 
					d7553ded6c | ||
| 
						 | 
					884d5a7fc8 | ||
| 
						 | 
					a920074468 | ||
| 
						 | 
					5ab342e298 | ||
| 
						 | 
					c99f525821 | ||
| 
						 | 
					dff004d695 | ||
| 
						 | 
					6f53e4b536 | ||
| 
						 | 
					9d3fe84135 | ||
| 
						 | 
					e5f7ae3878 | ||
| 
						 | 
					97162d9a53 | ||
| 
						 | 
					d0b99cb260 | ||
| 
						 | 
					fa22cc2e20 | ||
| 
						 | 
					9904255490 | ||
| 
						 | 
					f75c15b477 | ||
| 
						 | 
					9404dcab69 | ||
| 
						 | 
					c4d4403955 | ||
| 
						 | 
					a0bb2dc907 | ||
| 
						 | 
					ed774a5691 | ||
| 
						 | 
					78cedddbde | ||
| 
						 | 
					3640dc2fa3 | ||
| 
						 | 
					d3c619e3d3 | ||
| 
						 | 
					c158759c11 | ||
| 
						 | 
					b49362420c | ||
| 
						 | 
					aab76646ee | ||
| 
						 | 
					259245d412 | ||
| 
						 | 
					717180a8eb | ||
| 
						 | 
					12811483be | ||
| 
						 | 
					822aa2a352 | ||
| 
						 | 
					9d788d4d9c | ||
| 
						 | 
					d405cb8dd9 | ||
| 
						 | 
					5d3e57094a | ||
| 
						 | 
					e28d3f8cbd | ||
| 
						 | 
					182494a5b7 | ||
| 
						 | 
					9487820c32 | ||
| 
						 | 
					03d00c16f8 | ||
| 
						 | 
					57a38a00d9 | ||
| 
						 | 
					779b8679fd | ||
| 
						 | 
					d0143d6f3e | ||
| 
						 | 
					7917c3fc15 | ||
| 
						 | 
					81de913b77 | ||
| 
						 | 
					0e3798cadb | ||
| 
						 | 
					7447482608 | ||
| 
						 | 
					f9b185caa5 | ||
| 
						 | 
					4761ce4b45 | ||
| 
						 | 
					9f31af4c20 | ||
| 
						 | 
					ab448cdb57 | ||
| 
						 | 
					22c4076818 | ||
| 
						 | 
					6e8bd97709 | ||
| 
						 | 
					7dd128a1a8 | ||
| 
						 | 
					dfd422a386 | ||
| 
						 | 
					6f434cd94a | ||
| 
						 | 
					a82f2fec18 | ||
| 
						 | 
					234115f384 | ||
| 
						 | 
					c522618a4b | ||
| 
						 | 
					1c65c56970 | ||
| 
						 | 
					c6cff13038 | ||
| 
						 | 
					f25b101161 | ||
| 
						 | 
					6a866e208f | ||
| 
						 | 
					11b1e5abd7 | ||
| 
						 | 
					f44c387988 | ||
| 
						 | 
					b6629080ee | ||
| 
						 | 
					4022dd564b | ||
| 
						 | 
					c848ce66c5 | ||
| 
						 | 
					26b4c34778 | ||
| 
						 | 
					7eff83d689 | ||
| 
						 | 
					125fb7fbdb | ||
| 
						 | 
					01be5511e5 | ||
| 
						 | 
					4b45c6e35a | ||
| 
						 | 
					7f831c1f4d | ||
| 
						 | 
					d6778847c9 | ||
| 
						 | 
					9a96645b53 | ||
| 
						 | 
					ffa1b19e26 | ||
| 
						 | 
					6f98b140a8 | ||
| 
						 | 
					e83d1a26e6 | ||
| 
						 | 
					b237d68c47 | ||
| 
						 | 
					1027762816 | ||
| 
						 | 
					42893fc3bd | ||
| 
						 | 
					a479761be5 | ||
| 
						 | 
					6d7265d966 | ||
| 
						 | 
					32048b7658 | ||
| 
						 | 
					08f79c6b93 | ||
| 
						 | 
					699a2268d6 | ||
| 
						 | 
					410f9c485e | ||
| 
						 | 
					8561e5e38e | ||
| 
						 | 
					17617fe839 | ||
| 
						 | 
					7f4173ab22 | ||
| 
						 | 
					84236edaf8 | ||
| 
						 | 
					370dc2d727 | ||
| 
						 | 
					211b07a2e2 | ||
| 
						 | 
					9f67ba6a38 | ||
| 
						 | 
					03798fd604 | ||
| 
						 | 
					7bb4897b9f | ||
| 
						 | 
					4b0e97e666 | ||
| 
						 | 
					5b655dd4cd | ||
| 
						 | 
					023a61c0e5 | ||
| 
						 | 
					38cc6383b7 | ||
| 
						 | 
					77ac863bb8 | ||
| 
						 | 
					fdab219755 | ||
| 
						 | 
					f31e8d08cd | ||
| 
						 | 
					224c8ec0fa | ||
| 
						 | 
					309c19ef63 | ||
| 
						 | 
					13aad7e8b4 | ||
| 
						 | 
					6f36d0d06c | ||
| 
						 | 
					76d734a4bd | ||
| 
						 | 
					b14f29b5b7 | ||
| 
						 | 
					c57b30e342 | ||
| 
						 | 
					f6023a7c76 | ||
| 
						 | 
					6357a2d9b8 | ||
| 
						 | 
					7e3a1a8b18 | ||
| 
						 | 
					5f1b8f71f3 | ||
| 
						 | 
					cca8bb9092 | ||
| 
						 | 
					647314d3cc | ||
| 
						 | 
					30e6773617 | ||
| 
						 | 
					08774dc558 | ||
| 
						 | 
					481618826d | ||
| 
						 | 
					befcada36a | ||
| 
						 | 
					b71bf9332c | ||
| 
						 | 
					1303c93139 | ||
| 
						 | 
					29c8c75492 | ||
| 
						 | 
					862d83c691 | ||
| 
						 | 
					f18eeb4da8 | ||
| 
						 | 
					d40fed016f | ||
| 
						 | 
					76dc3ddf56 | ||
| 
						 | 
					d80d9a4c4e | ||
| 
						 | 
					281ee1c2bf | ||
| 
						 | 
					65e976198e | ||
| 
						 | 
					a0d668e850 | ||
| 
						 | 
					f7d624e684 | ||
| 
						 | 
					f5c395adb2 | ||
| 
						 | 
					09192b4d6e | ||
| 
						 | 
					74ec3783e7 | ||
| 
						 | 
					1c38ce8245 | ||
| 
						 | 
					702cfe15be | ||
| 
						 | 
					54d790828f | ||
| 
						 | 
					aff35fea29 | ||
| 
						 | 
					25a82bcbe3 | ||
| 
						 | 
					cb58100587 | ||
| 
						 | 
					9fbe96fd7c | ||
| 
						 | 
					98cd400443 | ||
| 
						 | 
					873e699f6d | ||
| 
						 | 
					9a8f6c824f | ||
| 
						 | 
					a98888ad07 | ||
| 
						 | 
					db98500b72 | ||
| 
						 | 
					3feee09cfe | ||
| 
						 | 
					4a1cd0d391 | ||
| 
						 | 
					edb5071d3b | ||
| 
						 | 
					e9509aa5e6 | ||
| 
						 | 
					5e6ca1b72d | ||
| 
						 | 
					543bf2ffbd | ||
| 
						 | 
					15a7a4c38b | ||
| 
						 | 
					640d07bf35 | ||
| 
						 | 
					e5ecc2b942 | ||
| 
						 | 
					cfd8fe40f4 | ||
| 
						 | 
					abba6e0642 | ||
| 
						 | 
					ec94fb89a2 | ||
| 
						 | 
					bb167efa7b | ||
| 
						 | 
					2a550ef96d | ||
| 
						 | 
					03ed7d73fc | ||
| 
						 | 
					446852db3b | ||
| 
						 | 
					7c90b57e87 | ||
| 
						 | 
					6339e2588b | ||
| 
						 | 
					af6687405b | ||
| 
						 | 
					a2bfad1c29 | ||
| 
						 | 
					645aa55abc | ||
| 
						 | 
					05329c885a | ||
| 
						 | 
					b3fed93a74 | ||
| 
						 | 
					2c6fad0ea7 | ||
| 
						 | 
					57854c2231 | ||
| 
						 | 
					a8cf4293e0 | ||
| 
						 | 
					ba70dce803 | ||
| 
						 | 
					5b4c3ace56 | ||
| 
						 | 
					2ade7a15e2 | ||
| 
						 | 
					e83f71d678 | ||
| 
						 | 
					412c91cb6b | ||
| 
						 | 
					aa44167319 | ||
| 
						 | 
					dd5700e8b3 | ||
| 
						 | 
					ef7fc430d7 | ||
| 
						 | 
					f1bcb6c634 | ||
| 
						 | 
					4a4eb17d08 | ||
| 
						 | 
					8afc267c68 | ||
| 
						 | 
					6457ab31b6 | ||
| 
						 | 
					306dfa2043 | ||
| 
						 | 
					424bdade0b | ||
| 
						 | 
					10857e3321 | ||
| 
						 | 
					85a4e47879 | ||
| 
						 | 
					759e49f025 | ||
| 
						 | 
					43924e31b8 | ||
| 
						 | 
					3b34fcf59f | ||
| 
						 | 
					ba7253eaf7 | ||
| 
						 | 
					be23682a30 | ||
| 
						 | 
					3a5dce4c92 | ||
| 
						 | 
					22d7e60d0e | ||
| 
						 | 
					5752156c9e | ||
| 
						 | 
					a30215a530 | ||
| 
						 | 
					f9c8c1b964 | ||
| 
						 | 
					5650f67ef5 | ||
| 
						 | 
					5ec25dfb94 | ||
| 
						 | 
					ef16682725 | ||
| 
						 | 
					883486cc67 | ||
| 
						 | 
					f367f9b747 | ||
| 
						 | 
					a3d987fa73 | ||
| 
						 | 
					2d48685673 | ||
| 
						 | 
					9b21ace1e9 | ||
| 
						 | 
					be2c03fa96 | ||
| 
						 | 
					f5585e9252 | ||
| 
						 | 
					4d534dd7e4 | ||
| 
						 | 
					c8584e1cce | ||
| 
						 | 
					84a1de464c | ||
| 
						 | 
					3966f3d319 | ||
| 
						 | 
					e6166cf711 | ||
| 
						 | 
					2285712834 | ||
| 
						 | 
					53cb6128e8 | ||
| 
						 | 
					8c317baf19 | ||
| 
						 | 
					8cac933c71 | ||
| 
						 | 
					03e61a4bf8 | ||
| 
						 | 
					71446a76b2 | ||
| 
						 | 
					28db8d6c7c | ||
| 
						 | 
					786e33d7d5 | ||
| 
						 | 
					b140d6c50e | ||
| 
						 | 
					64a95abdee | ||
| 
						 | 
					57f926be17 | ||
| 
						 | 
					4933b67959 | ||
| 
						 | 
					370b4f1b9e | ||
| 
						 | 
					f3b7baa84e | ||
| 
						 | 
					eafdb2c807 | ||
| 
						 | 
					a91fa821ab | ||
| 
						 | 
					37ef162cda | ||
| 
						 | 
					770928acfc | ||
| 
						 | 
					d0f3570219 | ||
| 
						 | 
					3d07c2605f | ||
| 
						 | 
					c350798528 | ||
| 
						 | 
					6bc3cc0bec | ||
| 
						 | 
					2e3e5fcc81 | ||
| 
						 | 
					dfdb10f6de | ||
| 
						 | 
					5cbe5909eb | ||
| 
						 | 
					04d52b450b | ||
| 
						 | 
					a586a89547 | ||
| 
						 | 
					1905eacf15 | ||
| 
						 | 
					858ec0d740 | ||
| 
						 | 
					76cfd406ca | ||
| 
						 | 
					9dbaad859d | ||
| 
						 | 
					95d43e17b3 | ||
| 
						 | 
					09a2dff8de | ||
| 
						 | 
					57208f879a | ||
| 
						 | 
					149638431d | ||
| 
						 | 
					30d2940c67 | ||
| 
						 | 
					5ee86fc5d0 | ||
| 
						 | 
					a03d0e2c3f | ||
| 
						 | 
					8bd367d58d | ||
| 
						 | 
					bc633e03aa | ||
| 
						 | 
					797d0f1ef1 | ||
| 
						 | 
					1be3e86aa0 | ||
| 
						 | 
					e56dd38021 | ||
| 
						 | 
					410904bef1 | ||
| 
						 | 
					026cc120e7 | ||
| 
						 | 
					ef2fda05cf | ||
| 
						 | 
					92277e3ae2 | ||
| 
						 | 
					fbc34d70b0 | ||
| 
						 | 
					91dcddbdf7 | ||
| 
						 | 
					874f42ad6c | ||
| 
						 | 
					1989ef4ebc | ||
| 
						 | 
					4f4c72c065 | ||
| 
						 | 
					666cc72661 | ||
| 
						 | 
					4524e8f5c9 | ||
| 
						 | 
					bd07a29886 | ||
| 
						 | 
					a0d865492e | ||
| 
						 | 
					de27790de8 | ||
| 
						 | 
					9c910b7be2 | ||
| 
						 | 
					7f23ab94e2 | ||
| 
						 | 
					77dc036c8f | ||
| 
						 | 
					aa6e8d82ce | ||
| 
						 | 
					3010285bb3 | ||
| 
						 | 
					aaad3252f8 | ||
| 
						 | 
					9065f534d8 | ||
| 
						 | 
					52361c94e5 | ||
| 
						 | 
					798be60fef | ||
| 
						 | 
					6294154b15 | ||
| 
						 | 
					6594fe077d | ||
| 
						 | 
					582706cde6 | ||
| 
						 | 
					6537cbdc17 | ||
| 
						 | 
					53959459bb | ||
| 
						 | 
					22d6121099 | ||
| 
						 | 
					48d7f6f2f4 | ||
| 
						 | 
					9fd4ddc490 | ||
| 
						 | 
					a4d2fddbb2 | ||
| 
						 | 
					c54a3f2721 | ||
| 
						 | 
					04c0dba697 | ||
| 
						 | 
					5406e3b7c5 | ||
| 
						 | 
					6b624b7d00 | ||
| 
						 | 
					2d364d4d80 | ||
| 
						 | 
					1f27bf3774 | ||
| 
						 | 
					d30a2653b5 | ||
| 
						 | 
					3086822cd2 | ||
| 
						 | 
					2c08336490 | ||
| 
						 | 
					5936ac58c2 | ||
| 
						 | 
					ded77e3f5c | ||
| 
						 | 
					8a29df0a6c | ||
| 
						 | 
					9db22babaf | ||
| 
						 | 
					c318c5ed61 | ||
| 
						 | 
					61243c65cd | ||
| 
						 | 
					4a5d5cb462 | ||
| 
						 | 
					cbf1447ebd | ||
| 
						 | 
					30104441bf | ||
| 
						 | 
					b4a70804f0 | ||
| 
						 | 
					74f6707bde | ||
| 
						 | 
					223eb8c84d | ||
| 
						 | 
					107d000606 | ||
| 
						 | 
					43e05607af | ||
| 
						 | 
					55793452d5 | ||
| 
						 | 
					686ba37255 | ||
| 
						 | 
					03ed19dad5 | ||
| 
						 | 
					ad2b6e5de1 | ||
| 
						 | 
					767676d6ff | ||
| 
						 | 
					bc7a54c615 | ||
| 
						 | 
					1bda393678 | ||
| 
						 | 
					bb5495c6bd | ||
| 
						 | 
					484f905749 | ||
| 
						 | 
					e0d61a4336 | ||
| 
						 | 
					e643a16ba5 | ||
| 
						 | 
					98fadec2b6 | ||
| 
						 | 
					14f464ecb0 | ||
| 
						 | 
					2ecdaf9bd4 | ||
| 
						 | 
					707c898f66 | ||
| 
						 | 
					69e4400774 | ||
| 
						 | 
					695efde68d | ||
| 
						 | 
					0c4b769011 | ||
| 
						 | 
					e53eff0634 | ||
| 
						 | 
					6c75243a06 | ||
| 
						 | 
					efde37880b | ||
| 
						 | 
					7d8f6381be | ||
| 
						 | 
					3c361e3393 | ||
| 
						 | 
					8440ecef5e | ||
| 
						 | 
					6401f1b1c9 | ||
| 
						 | 
					7487a7c988 | ||
| 
						 | 
					f44584fa10 | ||
| 
						 | 
					7b32165614 | ||
| 
						 | 
					b0dc94d187 | ||
| 
						 | 
					0383c4e1d8 | ||
| 
						 | 
					a8c5758222 | ||
| 
						 | 
					a7fabfd8cb | ||
| 
						 | 
					5d5b575d16 | ||
| 
						 | 
					ac1373653c | ||
| 
						 | 
					b097aa787b | ||
| 
						 | 
					723be0fe69 | ||
| 
						 | 
					f0597a03de | ||
| 
						 | 
					65f0656f54 | ||
| 
						 | 
					507ece15a5 | ||
| 
						 | 
					30be4d1613 | ||
| 
						 | 
					366e89bda0 | ||
| 
						 | 
					f159c3f768 | ||
| 
						 | 
					8506d1d567 | ||
| 
						 | 
					111829da46 | ||
| 
						 | 
					605798073e | ||
| 
						 | 
					8320f2b094 | ||
| 
						 | 
					df0d8d809b | ||
| 
						 | 
					062886df64 | ||
| 
						 | 
					148ea3aaa8 | ||
| 
						 | 
					ab5f66c13a | ||
| 
						 | 
					e65ffb8e68 | ||
| 
						 | 
					949c1ab517 | ||
| 
						 | 
					946d8ee046 | ||
| 
						 | 
					c54a8a2e10 | ||
| 
						 | 
					31177e4f85 | ||
| 
						 | 
					750f81b4b5 | ||
| 
						 | 
					987ff02a45 | ||
| 
						 | 
					f5adaf813c | ||
| 
						 | 
					78ff7dc7f0 | ||
| 
						 | 
					d1fced3324 | ||
| 
						 | 
					e7df9c289b | ||
| 
						 | 
					a78d7231a9 | ||
| 
						 | 
					ba7ae0002e | ||
| 
						 | 
					a090f7b839 | ||
| 
						 | 
					34ed15a987 | ||
| 
						 | 
					cacec4c910 | ||
| 
						 | 
					3e47d4e65b | ||
| 
						 | 
					8b42fa150b | ||
| 
						 | 
					60e660b9c7 | ||
| 
						 | 
					fe74f013e3 | ||
| 
						 | 
					24c0c70f90 | ||
| 
						 | 
					757f91ca89 | ||
| 
						 | 
					5c34f7847e | ||
| 
						 | 
					de456f014e | ||
| 
						 | 
					d29565066d | ||
| 
						 | 
					4d52c9233b | ||
| 
						 | 
					6da1ca0cb9 | ||
| 
						 | 
					2f02f1518a | ||
| 
						 | 
					e8863707de | ||
| 
						 | 
					6a336dfc69 | ||
| 
						 | 
					35dec1b9e4 | ||
| 
						 | 
					f148280c99 | ||
| 
						 | 
					599fe39749 | ||
| 
						 | 
					44f3fcb238 | ||
| 
						 | 
					af40fdb285 | ||
| 
						 | 
					9daf8b825c | ||
| 
						 | 
					ef5d8ce367 | ||
| 
						 | 
					4a199ab23b | ||
| 
						 | 
					6f0f5a569d | ||
| 
						 | 
					3172fbfde6 | ||
| 
						 | 
					e97a07a505 | ||
| 
						 | 
					6579ad92da | ||
| 
						 | 
					ec2fad0cfa | ||
| 
						 | 
					6196ac7995 | ||
| 
						 | 
					095a861018 | ||
| 
						 | 
					2449ed7765 | ||
| 
						 | 
					117a0408d6 | ||
| 
						 | 
					a54b0223a3 | ||
| 
						 | 
					44ee708ba5 | ||
| 
						 | 
					58a20d0fb6 | ||
| 
						 | 
					063078a02d | ||
| 
						 | 
					01402fea50 | ||
| 
						 | 
					b7fc2d1147 | ||
| 
						 | 
					43eeb7011c | ||
| 
						 | 
					d7901a4220 | ||
| 
						 | 
					0c6271dabc | ||
| 
						 | 
					2d4cf0c9f5 | ||
| 
						 | 
					0646d0dd91 | ||
| 
						 | 
					83e54b45a5 | ||
| 
						 | 
					5cd87d3d27 | ||
| 
						 | 
					689d8a80b5 | ||
| 
						 | 
					b1d82a92e7 | ||
| 
						 | 
					4d65627a50 | ||
| 
						 | 
					ce3a68d817 | ||
| 
						 | 
					409725be24 | ||
| 
						 | 
					b74f74a0d7 | ||
| 
						 | 
					719d554430 | ||
| 
						 | 
					13f54f4521 | ||
| 
						 | 
					57dfc9cf42 | ||
| 
						 | 
					57244a6823 | ||
| 
						 | 
					8bdde01bef | ||
| 
						 | 
					09bbd5a472 | ||
| 
						 | 
					9154a74400 | ||
| 
						 | 
					1399b84b32 | ||
| 
						 | 
					2ddbb3a8fa | ||
| 
						 | 
					e46a6d1cc1 | ||
| 
						 | 
					b698ab9011 | ||
| 
						 | 
					0a2572a5eb | ||
| 
						 | 
					77d049cc3d | ||
| 
						 | 
					7b8f053be2 | ||
| 
						 | 
					2c850d5293 | ||
| 
						 | 
					4056bbf10b | ||
| 
						 | 
					896b04a846 | ||
| 
						 | 
					93cda8b6ec | ||
| 
						 | 
					bb5e930684 | ||
| 
						 | 
					43761fed2a | ||
| 
						 | 
					a636299680 | ||
| 
						 | 
					08e5bd5b72 | ||
| 
						 | 
					2f057bef5e | ||
| 
						 | 
					5ab4f21444 | ||
| 
						 | 
					9ec26ed481 | ||
| 
						 | 
					29c9df1389 | ||
| 
						 | 
					867e9c51d4 | ||
| 
						 | 
					0170f7b42a | ||
| 
						 | 
					74bb6ead95 | ||
| 
						 | 
					303388e5cb | ||
| 
						 | 
					8388779937 | ||
| 
						 | 
					fc7dfca452 | ||
| 
						 | 
					e5a1db2392 | ||
| 
						 | 
					6790656af6 | ||
| 
						 | 
					b7477bdc15 | ||
| 
						 | 
					ffc61f31de | ||
| 
						 | 
					e612871ea7 | ||
| 
						 | 
					7f40f09f10 | ||
| 
						 | 
					456e42257c | ||
| 
						 | 
					8618c271cf | ||
| 
						 | 
					72ca1ccc23 | ||
| 
						 | 
					075b4bef3f | ||
| 
						 | 
					b59fce4393 | ||
| 
						 | 
					8674a25eb8 | ||
| 
						 | 
					10bf8fd2cd | ||
| 
						 | 
					57cb22ff3c | ||
| 
						 | 
					0162abdcae | ||
| 
						 | 
					5801171518 | ||
| 
						 | 
					bf1edbd1e2 | ||
| 
						 | 
					a8484d987d | ||
| 
						 | 
					9b2147f608 | ||
| 
						 | 
					32530b378e | ||
| 
						 | 
					a42905efa6 | ||
| 
						 | 
					c59745f9dd | ||
| 
						 | 
					b4ad9a5d08 | ||
| 
						 | 
					3ead7a38b1 | ||
| 
						 | 
					bf90435200 | ||
| 
						 | 
					9c181fa3d3 | ||
| 
						 | 
					3af0b1eb90 | ||
| 
						 | 
					7110c318ee | ||
| 
						 | 
					49a552ccdc | ||
| 
						 | 
					57685f17a9 | ||
| 
						 | 
					a1c09a463f | ||
| 
						 | 
					194121760a | ||
| 
						 | 
					6a987d46bf | ||
| 
						 | 
					e3db0b39b9 | ||
| 
						 | 
					4d4f0ee188 | ||
| 
						 | 
					ac7334c167 | ||
| 
						 | 
					e7bdd69af0 | ||
| 
						 | 
					fefc655969 | ||
| 
						 | 
					4dceaef60e | ||
| 
						 | 
					6fc10dd3ae | ||
| 
						 | 
					1ecd05a584 | ||
| 
						 | 
					976acaca31 | ||
| 
						 | 
					b4e5131d59 | ||
| 
						 | 
					49f7cfefd7 | ||
| 
						 | 
					fc365092f6 | ||
| 
						 | 
					7f26240442 | ||
| 
						 | 
					db559bb20a | ||
| 
						 | 
					52850faa15 | ||
| 
						 | 
					57d9a6c836 | ||
| 
						 | 
					752c880bfc | ||
| 
						 | 
					d83a354781 | ||
| 
						 | 
					17dd81336d | ||
| 
						 | 
					eaa46a2575 | ||
| 
						 | 
					fc0ec1e71e | ||
| 
						 | 
					fb2f92df1d | ||
| 
						 | 
					74adbb77b7 | ||
| 
						 | 
					788e544e1d | ||
| 
						 | 
					368a0d4d2d | ||
| 
						 | 
					962b7222d0 | ||
| 
						 | 
					17c1f54369 | ||
| 
						 | 
					33ae38e71b | ||
| 
						 | 
					ef58af4bf1 | ||
| 
						 | 
					3fad2db2f8 | ||
| 
						 | 
					9feaeb28ca | ||
| 
						 | 
					0075364715 | ||
| 
						 | 
					99c5da5da5 | ||
| 
						 | 
					22c957bc20 | ||
| 
						 | 
					3316d59910 | ||
| 
						 | 
					a109ce1eca | ||
| 
						 | 
					e581a78d65 | ||
| 
						 | 
					3c78f9900c | ||
| 
						 | 
					bd606943e6 | ||
| 
						 | 
					6381666df4 | ||
| 
						 | 
					736f1aa301 | ||
| 
						 | 
					b1a4eac7a8 | ||
| 
						 | 
					8226a5276b | ||
| 
						 | 
					77ad0bb12e | ||
| 
						 | 
					9412b42206 | ||
| 
						 | 
					2a91d87074 | ||
| 
						 | 
					4a23617d79 | ||
| 
						 | 
					0e2ceed74d | ||
| 
						 | 
					ed56aed8eb | ||
| 
						 | 
					8d909cbdc0 | ||
| 
						 | 
					bf98943cbb | ||
| 
						 | 
					6ff4552be2 | ||
| 
						 | 
					1c7eb79370 | ||
| 
						 | 
					f095a75f1e | ||
| 
						 | 
					f70af6018c | ||
| 
						 | 
					71b3b1ff4c | ||
| 
						 | 
					d9fefa0c6c | ||
| 
						 | 
					3bfe922381 | ||
| 
						 | 
					a85cf17bf1 | ||
| 
						 | 
					dbb5a09918 | ||
| 
						 | 
					93e5097f20 | ||
| 
						 | 
					dd53f2dc83 | ||
| 
						 | 
					2b83c80593 | ||
| 
						 | 
					6930f60c06 | ||
| 
						 | 
					376b76e75c | ||
| 
						 | 
					1ddd4509dc | ||
| 
						 | 
					6af3f4f4cf | ||
| 
						 | 
					6726c5f958 | ||
| 
						 | 
					d5a9c43cb2 | ||
| 
						 | 
					19a5a6a4eb | ||
| 
						 | 
					617a599ee9 | ||
| 
						 | 
					25e2d4da44 | ||
| 
						 | 
					ad2e7218cb | ||
| 
						 | 
					917637fa9b | ||
| 
						 | 
					b595ee1c0b | ||
| 
						 | 
					c8260a4a56 | ||
| 
						 | 
					d2eaff3204 | ||
| 
						 | 
					b65f5a844f | ||
| 
						 | 
					95a69f99ba | ||
| 
						 | 
					71d609895a | ||
| 
						 | 
					9229630447 | ||
| 
						 | 
					eb18a0b7dc | ||
| 
						 | 
					05ed5c0d74 | ||
| 
						 | 
					41330ecc5e | ||
| 
						 | 
					16fbcc6e36 | ||
| 
						 | 
					d87da9c7de | ||
| 
						 | 
					94563b6017 | ||
| 
						 | 
					34d22f7047 | ||
| 
						 | 
					e24d996fbe | ||
| 
						 | 
					9b52617919 | ||
| 
						 | 
					efc1d46c89 | ||
| 
						 | 
					9397833ceb | ||
| 
						 | 
					e9433e83cd | ||
| 
						 | 
					f3c58100a0 | ||
| 
						 | 
					8900231d99 | ||
| 
						 | 
					c7a63b8a2b | ||
| 
						 | 
					90e90672a4 | ||
| 
						 | 
					fa51e5c762 | ||
| 
						 | 
					911f55d005 | ||
| 
						 | 
					d30eb4e570 | ||
| 
						 | 
					67bcfb6947 | ||
| 
						 | 
					3915a61b1e | ||
| 
						 | 
					c170d321e8 | ||
| 
						 | 
					2802c476ee | ||
| 
						 | 
					1050cebf7f | ||
| 
						 | 
					dad73465fc | ||
| 
						 | 
					8e2ac98fe2 | ||
| 
						 | 
					9aaf0c36d5 | ||
| 
						 | 
					1cb07e9cfd | ||
| 
						 | 
					f1ccdf25b1 | ||
| 
						 | 
					6dca497b27 | ||
| 
						 | 
					42a83262a1 | ||
| 
						 | 
					63ee9cbee6 | ||
| 
						 | 
					3862f8ca7c | ||
| 
						 | 
					4ada7cffd0 | ||
| 
						 | 
					a664ce4298 | ||
| 
						 | 
					8d7b6c6905 | ||
| 
						 | 
					16d22d404a | ||
| 
						 | 
					ccb24d5779 | ||
| 
						 | 
					8795b45cb4 | ||
| 
						 | 
					628d3bff45 | ||
| 
						 | 
					0336bc9de9 | ||
| 
						 | 
					033cb21797 | ||
| 
						 | 
					09b98a45df | ||
| 
						 | 
					38857ba29e | ||
| 
						 | 
					1c7520ec8f | ||
| 
						 | 
					362b9769b2 | ||
| 
						 | 
					b2d68bd3d2 | ||
| 
						 | 
					0dc7e635d4 | ||
| 
						 | 
					80e070a857 | ||
| 
						 | 
					cc203245e4 | ||
| 
						 | 
					2f9a65fc93 | ||
| 
						 | 
					62738e8001 | ||
| 
						 | 
					5ecacf0c7f | ||
| 
						 | 
					06b103c8d4 | ||
| 
						 | 
					d473b7bca8 | ||
| 
						 | 
					50a1e81ba7 | ||
| 
						 | 
					d9885b1b64 | ||
| 
						 | 
					0a9c8cada2 | ||
| 
						 | 
					60f55f8461 | ||
| 
						 | 
					7bedaea38f | ||
| 
						 | 
					9e4b87e798 | ||
| 
						 | 
					95bf59095c | ||
| 
						 | 
					e0f34a9720 | ||
| 
						 | 
					f3797c2a8e | ||
| 
						 | 
					30cbcccc80 | ||
| 
						 | 
					f49c0d696f | ||
| 
						 | 
					71f564ee5b | ||
| 
						 | 
					4b0950aba5 | ||
| 
						 | 
					8c3af822ec | ||
| 
						 | 
					878a207d19 | ||
| 
						 | 
					0537ad860a | ||
| 
						 | 
					2cdbbb1aea | ||
| 
						 | 
					7af977d36b | ||
| 
						 | 
					9afff4cf30 | ||
| 
						 | 
					48ba9734aa | ||
| 
						 | 
					897fc59f72 | ||
| 
						 | 
					947e44ae67 | ||
| 
						 | 
					e44843beba | ||
| 
						 | 
					147482ea69 | ||
| 
						 | 
					09091c5cf8 | ||
| 
						 | 
					50827a5f69 | ||
| 
						 | 
					2d6444c924 | ||
| 
						 | 
					1d2675d9aa | ||
| 
						 | 
					ad98990a8e | ||
| 
						 | 
					8e58c143f2 | ||
| 
						 | 
					556a4a2395 | ||
| 
						 | 
					5be987b40f | ||
| 
						 | 
					066bc35e69 | ||
| 
						 | 
					403779437c | ||
| 
						 | 
					fb806f61d4 | ||
| 
						 | 
					6ce306661c | ||
| 
						 | 
					3c08ff94d4 | ||
| 
						 | 
					a6afae2356 | ||
| 
						 | 
					0eea7070a7 | ||
| 
						 | 
					105c2b1eea | ||
| 
						 | 
					82bb0e8dda | ||
| 
						 | 
					8c01179075 | ||
| 
						 | 
					c9d9a96630 | ||
| 
						 | 
					8f21c9a920 | ||
| 
						 | 
					0ba7d05ea7 | ||
| 
						 | 
					5a4c5b4155 | ||
| 
						 | 
					55323fb497 | ||
| 
						 | 
					7c082d2471 | ||
| 
						 | 
					f3cafcf983 | ||
| 
						 | 
					75073e4aa6 | ||
| 
						 | 
					a3c23f650c | ||
| 
						 | 
					0545cd5879 | ||
| 
						 | 
					c96506f22c | ||
| 
						 | 
					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 | ||
| 
						 | 
					0b43754d60 | ||
| 
						 | 
					8b3b26b813 | ||
| 
						 | 
					5426af4f81 | ||
| 
						 | 
					4e2c3a579d | ||
| 
						 | 
					5ae2693241 | ||
| 
						 | 
					41c86b0d19 | ||
| 
						 | 
					40788e8c3d | ||
| 
						 | 
					0d29120033 | ||
| 
						 | 
					4be598f865 | ||
| 
						 | 
					558a6d509e | ||
| 
						 | 
					75cd02aad2 | ||
| 
						 | 
					e4c4451482 | ||
| 
						 | 
					0671632477 | ||
| 
						 | 
					54c230c264 | ||
| 
						 | 
					64ba878eda | ||
| 
						 | 
					01acd6dd76 | ||
| 
						 | 
					9d819b52d3 | ||
| 
						 | 
					37bac5cdc9 | ||
| 
						 | 
					78c718c591 | ||
| 
						 | 
					284b8bf6ca | ||
| 
						 | 
					5a5084b837 | ||
| 
						 | 
					3b8058e1f1 | ||
| 
						 | 
					2a3168e0d6 | ||
| 
						 | 
					a8ac6e4a15 | ||
| 
						 | 
					6172cf9fba | ||
| 
						 | 
					b728ec3909 | ||
| 
						 | 
					61a53bbcff | ||
| 
						 | 
					17d13dd084 | ||
| 
						 | 
					edcb28d591 | ||
| 
						 | 
					ad101119a7 | ||
| 
						 | 
					bc36676d31 | ||
| 
						 | 
					d76fe120ab | ||
| 
						 | 
					2e95949b80 | ||
| 
						 | 
					ae14d85e24 | ||
| 
						 | 
					fad6304c60 | ||
| 
						 | 
					a4dd3c8ce9 | ||
| 
						 | 
					6d1a5d45e2 | ||
| 
						 | 
					a6c7043e03 | ||
| 
						 | 
					bcc400dafa | ||
| 
						 | 
					8fbedf3441 | ||
| 
						 | 
					2e8a9c9874 | ||
| 
						 | 
					44fc41b3e5 | ||
| 
						 | 
					7212c20a1b | ||
| 
						 | 
					7ff142de1c | ||
| 
						 | 
					e67efb199d | ||
| 
						 | 
					20128bd04b | ||
| 
						 | 
					c0fefdde28 | ||
| 
						 | 
					f6ee160e66 | ||
| 
						 | 
					06acc2004f | ||
| 
						 | 
					43ac2ce4c8 | ||
| 
						 | 
					b32bf72b5f | ||
| 
						 | 
					c6880c957e | ||
| 
						 | 
					095b71ed96 | ||
| 
						 | 
					9160e496bc | ||
| 
						 | 
					2a7ac78f02 | ||
| 
						 | 
					64efa4627d | ||
| 
						 | 
					f7e35569ce | ||
| 
						 | 
					e8af32ec2b | ||
| 
						 | 
					e092ce51f6 | ||
| 
						 | 
					7b78edb1b7 | ||
| 
						 | 
					b332e7090e | ||
| 
						 | 
					67eb7723d6 | ||
| 
						 | 
					251d138474 | ||
| 
						 | 
					1170dfac05 | ||
| 
						 | 
					4157f141c7 | ||
| 
						 | 
					f569abd28a | ||
| 
						 | 
					088f9687c0 | ||
| 
						 | 
					e23df1f07a | ||
| 
						 | 
					c818540dfd | ||
| 
						 | 
					21365cbe1a | ||
| 
						 | 
					5471a80a96 | ||
| 
						 | 
					d7b6fa9cd0 | ||
| 
						 | 
					dfdc2e02ef | ||
| 
						 | 
					893ec9a302 | ||
| 
						 | 
					05f65c38e6 | ||
| 
						 | 
					2e9d062ec0 | ||
| 
						 | 
					6b0b394e61 | ||
| 
						 | 
					25621396c9 | ||
| 
						 | 
					82aa0271f3 | ||
| 
						 | 
					653cab13f8 | ||
| 
						 | 
					b526f86b49 | ||
| 
						 | 
					53c0f00888 | ||
| 
						 | 
					f0c4d9de40 | ||
| 
						 | 
					03ef8cec83 | ||
| 
						 | 
					85f2a2e8c2 | ||
| 
						 | 
					584b3e6642 | ||
| 
						 | 
					39b7ef841d | ||
| 
						 | 
					aa16a9098d | ||
| 
						 | 
					7b8c2707bc | ||
| 
						 | 
					60e26a31a7 | ||
| 
						 | 
					3473c25c14 | ||
| 
						 | 
					e52f022026 | ||
| 
						 | 
					b1a7df8e43 | ||
| 
						 | 
					0fd2479b7c | ||
| 
						 | 
					273857f914 | ||
| 
						 | 
					a08b85dbc8 | ||
| 
						 | 
					a0aedf299a | ||
| 
						 | 
					3c61426844 | ||
| 
						 | 
					786f228076 | ||
| 
						 | 
					004da28792 | ||
| 
						 | 
					6e2be6efb6 | ||
| 
						 | 
					a994dfcfbc | ||
| 
						 | 
					7a8ea2ac93 | ||
| 
						 | 
					0da3965d19 | ||
| 
						 | 
					885fd7bb46 | ||
| 
						 | 
					08771f9c89 | ||
| 
						 | 
					8be48195a5 | ||
| 
						 | 
					98ce2d650e | ||
| 
						 | 
					3af327116a | ||
| 
						 | 
					b75434db93 | ||
| 
						 | 
					04e912aacd | ||
| 
						 | 
					d7be352f87 | ||
| 
						 | 
					96be3ec22c | ||
| 
						 | 
					32e7e0d790 | ||
| 
						 | 
					becc320e62 | ||
| 
						 | 
					7666ed57d1 | ||
| 
						 | 
					5e61d0955e | ||
| 
						 | 
					e8a4662ae7 | ||
| 
						 | 
					a48da3bd3b | ||
| 
						 | 
					5f1a5d7b99 | ||
| 
						 | 
					3e28a9db8f | ||
| 
						 | 
					ebf6071d77 | ||
| 
						 | 
					47a35fb9fb | ||
| 
						 | 
					48e88aba44 | ||
| 
						 | 
					b85f99c140 | ||
| 
						 | 
					0a5e0e1f71 | ||
| 
						 | 
					85dc22ebb7 | ||
| 
						 | 
					5c21526009 | ||
| 
						 | 
					14dff1cefc | ||
| 
						 | 
					39fbb844f9 | ||
| 
						 | 
					ca4e0c973a | ||
| 
						 | 
					ecb42bee80 | ||
| 
						 | 
					674ed2a9f3 | ||
| 
						 | 
					252daf9717 | ||
| 
						 | 
					196b8eaad3 | ||
| 
						 | 
					8e526ba1bf | ||
| 
						 | 
					19225828d9 | ||
| 
						 | 
					7e594126be | ||
| 
						 | 
					d2529e6334 | ||
| 
						 | 
					97344f18e2 | ||
| 
						 | 
					33934db629 | ||
| 
						 | 
					6c6165c9f5 | ||
| 
						 | 
					853460b20d | ||
| 
						 | 
					cc4d9676c5 | ||
| 
						 | 
					1cf1b819f4 | ||
| 
						 | 
					f916c66d2b | ||
| 
						 | 
					550aa86b45 | ||
| 
						 | 
					014e764758 | ||
| 
						 | 
					d1fc28432b | ||
| 
						 | 
					879576f0a2 | ||
| 
						 | 
					69098210be | ||
| 
						 | 
					99df4f892d | ||
| 
						 | 
					7bc04fbad3 | ||
| 
						 | 
					8a74ce578d | ||
| 
						 | 
					0805e4e5de | ||
| 
						 | 
					f1060fc88e | ||
| 
						 | 
					7d3d3d0a3a | ||
| 
						 | 
					40377032e3 | ||
| 
						 | 
					b2971edd7d | ||
| 
						 | 
					c37d723692 | ||
| 
						 | 
					30f9026e1d | ||
| 
						 | 
					332286072e | ||
| 
						 | 
					d6da172a2a | ||
| 
						 | 
					ebfe584afc | ||
| 
						 | 
					6250023583 | ||
| 
						 | 
					6b4f3d63b8 | ||
| 
						 | 
					56db773a09 | ||
| 
						 | 
					fc6c472401 | ||
| 
						 | 
					2cd42a6866 | ||
| 
						 | 
					36a90c345c | ||
| 
						 | 
					ef1e82c72c | ||
| 
						 | 
					88f9534685 | ||
| 
						 | 
					68254a052a | ||
| 
						 | 
					2425b3a166 | ||
| 
						 | 
					5524ed753b | ||
| 
						 | 
					89711723da | ||
| 
						 | 
					bed2740ffd | ||
| 
						 | 
					751d633c3d | ||
| 
						 | 
					45952cbdf2 | ||
| 
						 | 
					b355dd7b23 | ||
| 
						 | 
					48a186f172 | ||
| 
						 | 
					39dc7ec2ab | ||
| 
						 | 
					2fedabd3b9 | ||
| 
						 | 
					6d719e9480 | ||
| 
						 | 
					05e278afda | ||
| 
						 | 
					87dbf462cb | ||
| 
						 | 
					40e896bc5b | ||
| 
						 | 
					3e940f80c7 | ||
| 
						 | 
					dbf2888d43 | ||
| 
						 | 
					d412355324 | ||
| 
						 | 
					178732217f | ||
| 
						 | 
					de17b95c3d | ||
| 
						 | 
					d14e774525 | ||
| 
						 | 
					ca5402a7fa | ||
| 
						 | 
					7a6fa7c5b4 | ||
| 
						 | 
					da36c286a6 | ||
| 
						 | 
					d3901bcf2e | ||
| 
						 | 
					94c8d4fdfb | ||
| 
						 | 
					ab8bdc18bb | ||
| 
						 | 
					c9dcd7442a | ||
| 
						 | 
					34c8f13346 | ||
| 
						 | 
					7a8ccda95c | ||
| 
						 | 
					44a1448542 | ||
| 
						 | 
					c87d89ffaf | ||
| 
						 | 
					0868749d42 | ||
| 
						 | 
					1d40ee23f0 | ||
| 
						 | 
					8893f32603 | ||
| 
						 | 
					adcf7e8dc3 | ||
| 
						 | 
					901f7c5c36 | ||
| 
						 | 
					775bb413b3 | ||
| 
						 | 
					64cd5b5a46 | ||
| 
						 | 
					ae356609b1 | ||
| 
						 | 
					6102a5d2b0 | ||
| 
						 | 
					f8782ee2d7 | ||
| 
						 | 
					6181ec4c77 | ||
| 
						 | 
					e0e7a685ef | ||
| 
						 | 
					ae1f8cdad2 | ||
| 
						 | 
					a4cf792e6d | ||
| 
						 | 
					89109ded53 | ||
| 
						 | 
					e20e52a4b2 | ||
| 
						 | 
					20c4b1cbec | ||
| 
						 | 
					5238b0241d | ||
| 
						 | 
					9cdf6c203d | ||
| 
						 | 
					839335cae6 | ||
| 
						 | 
					a99b2ce167 | ||
| 
						 | 
					b695141d87 | ||
| 
						 | 
					92d5c9f866 | ||
| 
						 | 
					7f18a1ffe0 | ||
| 
						 | 
					8c3fdaaa62 | ||
| 
						 | 
					5ac1c69710 | ||
| 
						 | 
					de2d5fba63 | ||
| 
						 | 
					33d516748f | ||
| 
						 | 
					de17f6f0fd | ||
| 
						 | 
					756731fc02 | ||
| 
						 | 
					e46be0415f | ||
| 
						 | 
					aa02fb50bf | ||
| 
						 | 
					8b6cd9c772 | ||
| 
						 | 
					cdd0d3351a | ||
| 
						 | 
					8b6d584529 | ||
| 
						 | 
					f49fdd4141 | ||
| 
						 | 
					b26e1be81a | ||
| 
						 | 
					bacab38d7f | ||
| 
						 | 
					701c05ce96 | ||
| 
						 | 
					438c452585 | ||
| 
						 | 
					0a7a1eff3f | ||
| 
						 | 
					87e743e381 | ||
| 
						 | 
					a03f1b3d55 | ||
| 
						 | 
					2d8dc3d243 | ||
| 
						 | 
					b982232cc5 | ||
| 
						 | 
					61c8d728ac | ||
| 
						 | 
					851a2bf855 | ||
| 
						 | 
					e0bdde3630 | ||
| 
						 | 
					6a0dcd7f0e | ||
| 
						 | 
					75f0b4c879 | ||
| 
						 | 
					db536a9504 | ||
| 
						 | 
					0fb114dede | ||
| 
						 | 
					e703342179 | ||
| 
						 | 
					35c8f4a611 | ||
| 
						 | 
					7c89ae44a9 | ||
| 
						 | 
					84fe06da22 | ||
| 
						 | 
					806318c8b3 | ||
| 
						 | 
					3aac2e1822 | ||
| 
						 | 
					168baef433 | ||
| 
						 | 
					6dba6cd78d | ||
| 
						 | 
					502250d08f | ||
| 
						 | 
					7395f0e680 | ||
| 
						 | 
					494d3fdaca | ||
| 
						 | 
					7b86a157de | ||
| 
						 | 
					0988c41785 | ||
| 
						 | 
					522db1bf01 | ||
| 
						 | 
					06f066f90d | ||
| 
						 | 
					f37b20677b | ||
| 
						 | 
					cd2eac1032 | ||
| 
						 | 
					8ac38d58d7 | ||
| 
						 | 
					4c80cc313a | ||
| 
						 | 
					1c65fee9b4 | ||
| 
						 | 
					90dda7edc1 | ||
| 
						 | 
					da054fae20 | ||
| 
						 | 
					bdb6611e30 | ||
| 
						 | 
					9284f973f1 | ||
| 
						 | 
					2bfd64c3c9 | ||
| 
						 | 
					939d24cce5 | ||
| 
						 | 
					27b0183c46 | ||
| 
						 | 
					d14efacac7 | ||
| 
						 | 
					150a002c40 | ||
| 
						 | 
					ce0def3bd8 | ||
| 
						 | 
					ee20fa97c2 | ||
| 
						 | 
					7403b7d700 | ||
| 
						 | 
					87ef173e0a | ||
| 
						 | 
					52a3fb6bc7 | ||
| 
						 | 
					92e2a257a6 | ||
| 
						 | 
					32e175752c | ||
| 
						 | 
					d43f7180dc | ||
| 
						 | 
					0129c2b0fc | ||
| 
						 | 
					4ed1990001 | ||
| 
						 | 
					5bd6ab27ae | ||
| 
						 | 
					f3593b89fa | ||
| 
						 | 
					23d84b2310 | ||
| 
						 | 
					fdc49402ec | ||
| 
						 | 
					5457c133e1 | ||
| 
						 | 
					292e588ee3 | ||
| 
						 | 
					243494c25e | ||
| 
						 | 
					e4365f3706 | ||
| 
						 | 
					310f3038d3 | ||
| 
						 | 
					4e6033273d | ||
| 
						 | 
					73718586d3 | ||
| 
						 | 
					011abe61e8 | ||
| 
						 | 
					fe3a37f89d | ||
| 
						 | 
					8aea44e77b | ||
| 
						 | 
					5529aec0d6 | ||
| 
						 | 
					369549d23f | ||
| 
						 | 
					181ea9a381 | ||
| 
						 | 
					76b8f2854e | ||
| 
						 | 
					320e5198f9 | ||
| 
						 | 
					e522539e2d | ||
| 
						 | 
					7c996b83d2 | ||
| 
						 | 
					3dd354d7aa | ||
| 
						 | 
					f4ad6e2157 | ||
| 
						 | 
					8b170dc2bf | ||
| 
						 | 
					dcb9d779bf | ||
| 
						 | 
					80f736d670 | ||
| 
						 | 
					8502c6da3c | ||
| 
						 | 
					b131449422 | ||
| 
						 | 
					6eebc4a620 | ||
| 
						 | 
					4661ab1179 | ||
| 
						 | 
					86046445ed | ||
| 
						 | 
					baea9bf944 | ||
| 
						 | 
					0951ee9e63 | ||
| 
						 | 
					5492528287 | ||
| 
						 | 
					14dbd220c2 | ||
| 
						 | 
					babc890c59 | ||
| 
						 | 
					6f7b47ff40 | ||
| 
						 | 
					3991f03202 | ||
| 
						 | 
					27271d5da7 | ||
| 
						 | 
					627312e1de | ||
| 
						 | 
					bfc9550e4e | ||
| 
						 | 
					2b9c21268b | ||
| 
						 | 
					3dce4ed6f1 | ||
| 
						 | 
					0f16c2ea87 | ||
| 
						 | 
					9a635f0686 | ||
| 
						 | 
					6a0d4b2baa | ||
| 
						 | 
					ac017098ad | ||
| 
						 | 
					98fef2640d | ||
| 
						 | 
					8bb66e133a | ||
| 
						 | 
					68a582901d | ||
| 
						 | 
					c094f4c06e | ||
| 
						 | 
					f7ca545544 | ||
| 
						 | 
					69b4716894 | ||
| 
						 | 
					7e44dcc5bf | ||
| 
						 | 
					ab9843e183 | ||
| 
						 | 
					01af706ade | ||
| 
						 | 
					9ebdb08e99 | ||
| 
						 | 
					a74ffe25d9 | ||
| 
						 | 
					7f95e27707 | ||
| 
						 | 
					1facf5bba3 | ||
| 
						 | 
					03d77009eb | ||
| 
						 | 
					8afd6812b5 | ||
| 
						 | 
					ec9ad78fcf | ||
| 
						 | 
					6f4e93dc90 | ||
| 
						 | 
					a38e43862d | ||
| 
						 | 
					39294bb037 | ||
| 
						 | 
					edc5e59b78 | ||
| 
						 | 
					c00fd9fd37 | ||
| 
						 | 
					b3e621dd9f | ||
| 
						 | 
					6e8c49b978 | ||
| 
						 | 
					398d57133d | ||
| 
						 | 
					16521a6feb | ||
| 
						 | 
					3ca0b37a3e | ||
| 
						 | 
					cf2ec1229d | ||
| 
						 | 
					fe9b1e5f9b | ||
| 
						 | 
					f5b96ddf01 | ||
| 
						 | 
					2fe076fb27 | ||
| 
						 | 
					99249cff04 | ||
| 
						 | 
					0cdf7b0613 | ||
| 
						 | 
					90bcf4f157 | ||
| 
						 | 
					03c3ec4e12 | ||
| 
						 | 
					ca9bb20d64 | ||
| 
						 | 
					c6bc078fd9 | ||
| 
						 | 
					2f4bd6e52c | ||
| 
						 | 
					2affe53727 | ||
| 
						 | 
					09654d7dd8 | ||
| 
						 | 
					90a4e37815 | ||
| 
						 | 
					60889c0c79 | ||
| 
						 | 
					20f3408d96 | ||
| 
						 | 
					e9d86789db | ||
| 
						 | 
					5152b7c66c | ||
| 
						 | 
					c494c4e12c | ||
| 
						 | 
					54d58ccb7e | ||
| 
						 | 
					714a77bfbe | ||
| 
						 | 
					d48f8bf5cc | ||
| 
						 | 
					99d97754a6 | ||
| 
						 | 
					b9d437de2a | ||
| 
						 | 
					11403f2019 | ||
| 
						 | 
					1ca102d639 | ||
| 
						 | 
					339ba55111 | ||
| 
						 | 
					14ae59885a | ||
| 
						 | 
					e3ef54f99b | ||
| 
						 | 
					001901f9a9 | ||
| 
						 | 
					6a98f60e2e | ||
| 
						 | 
					6f2e24c47d | ||
| 
						 | 
					aafa368923 | ||
| 
						 | 
					eb783cab4c | ||
| 
						 | 
					6533aa865a | ||
| 
						 | 
					f1a1e1bc07 | ||
| 
						 | 
					953f4838dd | ||
| 
						 | 
					130b892d34 | ||
| 
						 | 
					6ad525c77e | ||
| 
						 | 
					d0ca74ad27 | ||
| 
						 | 
					9806f69b4d | ||
| 
						 | 
					34d9b5e3d7 | ||
| 
						 | 
					3bf5189d86 | ||
| 
						 | 
					12e5b0681b | ||
| 
						 | 
					8c0285d608 | ||
| 
						 | 
					36558fa3b8 | ||
| 
						 | 
					235f940cde | ||
| 
						 | 
					803d61fcbc | ||
| 
						 | 
					ffbd7d8de4 | ||
| 
						 | 
					4ed924d7c7 | ||
| 
						 | 
					798dc9948b | ||
| 
						 | 
					13515f7ee4 | ||
| 
						 | 
					ef80824c26 | ||
| 
						 | 
					c8503fd65e | ||
| 
						 | 
					b3c454fb1c | ||
| 
						 | 
					1d7723e873 | ||
| 
						 | 
					77100b2365 | ||
| 
						 | 
					259a788134 | ||
| 
						 | 
					39511455cb | ||
| 
						 | 
					b04c16178e | ||
| 
						 | 
					49a959c06e | ||
| 
						 | 
					096a8932b4 | ||
| 
						 | 
					e39e66df93 | ||
| 
						 | 
					513633f49a | ||
| 
						 | 
					eb3740daaf | ||
| 
						 | 
					f7947b148a | ||
| 
						 | 
					9a2a702f3f | ||
| 
						 | 
					c65d95bf29 | ||
| 
						 | 
					753a5edc4f | ||
| 
						 | 
					0b3f853c2d | ||
| 
						 | 
					3527fcf1d5 | ||
| 
						 | 
					4544a89c7a | ||
| 
						 | 
					ffeae9005e | ||
| 
						 | 
					47217bcfb7 | ||
| 
						 | 
					80ff58b57a | ||
| 
						 | 
					d15dd368f1 | ||
| 
						 | 
					8a2ec32bd8 | ||
| 
						 | 
					410496ed52 | ||
| 
						 | 
					b7b07552e5 | ||
| 
						 | 
					44486e80d9 | ||
| 
						 | 
					7890c527d8 | ||
| 
						 | 
					2c82ab79a7 | ||
| 
						 | 
					e3ebe5fc53 | ||
| 
						 | 
					0ac430892e | ||
| 
						 | 
					a7739c942c | ||
| 
						 | 
					24581482d0 | ||
| 
						 | 
					0571c3b453 | ||
| 
						 | 
					73e7f5a0b0 | ||
| 
						 | 
					20c0adb961 | ||
| 
						 | 
					a01e03562f | ||
| 
						 | 
					d184ed0130 | ||
| 
						 | 
					089e1c2aee | ||
| 
						 | 
					ebab0e91ee | ||
| 
						 | 
					858a2b1b88 | ||
| 
						 | 
					02bd59827c | ||
| 
						 | 
					4991428510 | ||
| 
						 | 
					3b245f5dc1 | ||
| 
						 | 
					c9c81da901 | ||
| 
						 | 
					4919cdc3fb | ||
| 
						 | 
					e90e1f577d | ||
| 
						 | 
					afd4284403 | ||
| 
						 | 
					150b350d31 | ||
| 
						 | 
					2818520bd1 | ||
| 
						 | 
					2819952292 | ||
| 
						 | 
					5af71af51c | ||
| 
						 | 
					07a55b51df | ||
| 
						 | 
					66dd68b49d | ||
| 
						 | 
					9812657777 | ||
| 
						 | 
					0b09312fc6 | ||
| 
						 | 
					d0a7ac6b74 | ||
| 
						 | 
					ff9a238fbd | ||
| 
						 | 
					359fffa5f1 | ||
| 
						 | 
					5bf92ced1a | ||
| 
						 | 
					340bcc7b45 | ||
| 
						 | 
					ef03742bd4 | ||
| 
						 | 
					20431ec16d | ||
| 
						 | 
					becba8157b | ||
| 
						 | 
					51fd3bb0eb | ||
| 
						 | 
					4bbd3acb4e | ||
| 
						 | 
					3bc930ea7b | ||
| 
						 | 
					d1b26f8e86 | ||
| 
						 | 
					fdf15caaff | ||
| 
						 | 
					c7b4a53c0b | ||
| 
						 | 
					af78dc0308 | ||
| 
						 | 
					5ad39493c4 | ||
| 
						 | 
					61f597b408 | ||
| 
						 | 
					2162825240 | ||
| 
						 | 
					2b780e70d1 | ||
| 
						 | 
					a3823f818e | ||
| 
						 | 
					1f7c47bcaf | ||
| 
						 | 
					ec53c365a2 | ||
| 
						 | 
					793ad1f2d4 | ||
| 
						 | 
					9bc733b76c | ||
| 
						 | 
					21b28f0217 | ||
| 
						 | 
					d3e23caa52 | ||
| 
						 | 
					9e7518de67 | ||
| 
						 | 
					679f0047aa | ||
| 
						 | 
					d77d5ce14b | ||
| 
						 | 
					33ec22a2af | ||
| 
						 | 
					353053225f | ||
| 
						 | 
					b7f3d6f7f7 | ||
| 
						 | 
					e34577499d | ||
| 
						 | 
					4cf8960c0c | ||
| 
						 | 
					1f93ea0675 | ||
| 
						 | 
					25b705c3a8 | ||
| 
						 | 
					0725588731 | ||
| 
						 | 
					fc5c61cc8b | ||
| 
						 | 
					ac282e63c6 | ||
| 
						 | 
					c3941941ce | ||
| 
						 | 
					46cdd53323 | ||
| 
						 | 
					3ff3e302c3 | ||
| 
						 | 
					f2ceecf95c | ||
| 
						 | 
					9314c7c881 | ||
| 
						 | 
					54abb2c572 | ||
| 
						 | 
					8fa3bdd025 | ||
| 
						 | 
					5e7a308528 | ||
| 
						 | 
					7952177786 | ||
| 
						 | 
					9afbe49c84 | ||
| 
						 | 
					9f06ba2db3 | ||
| 
						 | 
					fe55bfddcf | ||
| 
						 | 
					c0842e6444 | ||
| 
						 | 
					3fed20d06a | ||
| 
						 | 
					5e8f2e2c04 | ||
| 
						 | 
					e4df99ea84 | ||
| 
						 | 
					b3276f5f11 | ||
| 
						 | 
					32667ca256 | ||
| 
						 | 
					bed122a170 | ||
| 
						 | 
					14adc9b875 | ||
| 
						 | 
					a8778bbc5a | ||
| 
						 | 
					a54e641f44 | ||
| 
						 | 
					5c99efe87a | ||
| 
						 | 
					7da1d731ff | ||
| 
						 | 
					af9828e819 | ||
| 
						 | 
					7a27136142 | ||
| 
						 | 
					012ad2d423 | ||
| 
						 | 
					ef3bdbf4da | ||
| 
						 | 
					b3bb698f7b | ||
| 
						 | 
					1ed5d1e4c1 | ||
| 
						 | 
					bdee01a03d | ||
| 
						 | 
					458f7376d7 | ||
| 
						 | 
					cb3a00e027 | ||
| 
						 | 
					482eb1f3fb | ||
| 
						 | 
					6e0f638f5e | ||
| 
						 | 
					bab349047d | ||
| 
						 | 
					28ea6b8de8 | ||
| 
						 | 
					9d51bbdae8 | ||
| 
						 | 
					d622f79533 | ||
| 
						 | 
					04c8515ad1 | ||
| 
						 | 
					53bc4251d1 | ||
| 
						 | 
					a5a751f02f | ||
| 
						 | 
					66ed5f82c4 | ||
| 
						 | 
					c802a9e6aa | ||
| 
						 | 
					880f210946 | ||
| 
						 | 
					4f9f7eb6a6 | ||
| 
						 | 
					f910c4a8e7 | ||
| 
						 | 
					529686d965 | ||
| 
						 | 
					84dfd1536f | ||
| 
						 | 
					85dedc324c | ||
| 
						 | 
					d639237411 | ||
| 
						 | 
					449aaf75f1 | ||
| 
						 | 
					b1fda66caa | ||
| 
						 | 
					66a8e90fd9 | ||
| 
						 | 
					37b487d191 | ||
| 
						 | 
					6c59fe3577 | ||
| 
						 | 
					1cbb70c992 | ||
| 
						 | 
					e06b39f882 | ||
| 
						 | 
					2602b1493e | ||
| 
						 | 
					989d14502d | ||
| 
						 | 
					f78a550282 | ||
| 
						 | 
					54a1abb284 | ||
| 
						 | 
					97b492a8e2 | ||
| 
						 | 
					0873bd14a9 | ||
| 
						 | 
					eff6ba429a | ||
| 
						 | 
					8c18064be4 | ||
| 
						 | 
					44a1ac0cf3 | ||
| 
						 | 
					28dc8d88dd | ||
| 
						 | 
					2c0c2b64ba | ||
| 
						 | 
					bd3e0f5248 | ||
| 
						 | 
					cd52d98938 | ||
| 
						 | 
					894c70e7f8 | ||
| 
						 | 
					51d70c2edd | ||
| 
						 | 
					7d4b355240 | ||
| 
						 | 
					3b56193b98 | ||
| 
						 | 
					b16045b57d | ||
| 
						 | 
					9e8b0fca5b | ||
| 
						 | 
					35cf1b3b5b | ||
| 
						 | 
					83f788af57 | ||
| 
						 | 
					2ffe378d3f | ||
| 
						 | 
					38b33a4a5e | ||
| 
						 | 
					60bf9ed0a0 | ||
| 
						 | 
					16adf4de1b | ||
| 
						 | 
					80de983023 | ||
| 
						 | 
					8703ca623f | ||
| 
						 | 
					286253a73f | ||
| 
						 | 
					bd806a41df | ||
| 
						 | 
					b89c4e9002 | ||
| 
						 | 
					6dbf31c0c3 | ||
| 
						 | 
					060c45d8a1 | ||
| 
						 | 
					33d3e82e4d | ||
| 
						 | 
					4bb074514d | ||
| 
						 | 
					e3f8892003 | ||
| 
						 | 
					9d00ad5f18 | ||
| 
						 | 
					dae4344850 | ||
| 
						 | 
					aa7f3fabe2 | ||
| 
						 | 
					f93434a8ce | ||
| 
						 | 
					25dee56be9 | ||
| 
						 | 
					ce9a3f3797 | ||
| 
						 | 
					11e384920a | ||
| 
						 | 
					a0a1f1e536 | ||
| 
						 | 
					3b3d0ea9eb | ||
| 
						 | 
					2f4d78286d | ||
| 
						 | 
					677dc6f985 | ||
| 
						 | 
					d52057e732 | ||
| 
						 | 
					fa2a1cb1fb | ||
| 
						 | 
					19a0fb04ad | ||
| 
						 | 
					947352f2fe | ||
| 
						 | 
					adcbedb686 | ||
| 
						 | 
					7732f92acd | ||
| 
						 | 
					ad8a001688 | ||
| 
						 | 
					9121eada08 | ||
| 
						 | 
					49bd4d25a2 | ||
| 
						 | 
					d80b4129c6 | ||
| 
						 | 
					7edb4172d5 | ||
| 
						 | 
					c3a4677990 | ||
| 
						 | 
					5cbb893a3b | ||
| 
						 | 
					f28a2a432b | ||
| 
						 | 
					03b75a2d27 | ||
| 
						 | 
					859fe69083 | ||
| 
						 | 
					f6f2205ddb | ||
| 
						 | 
					0f9a03ef61 | ||
| 
						 | 
					9aa417c084 | ||
| 
						 | 
					7b70952f5d | ||
| 
						 | 
					edd3d07b49 | ||
| 
						 | 
					5293d0a4ec | ||
| 
						 | 
					3c8c7beae1 | ||
| 
						 | 
					9c3ba9fdcd | ||
| 
						 | 
					fb1748fb0f | ||
| 
						 | 
					0a109fbd03 | ||
| 
						 | 
					5cf64db74e | ||
| 
						 | 
					488cc94f36 | ||
| 
						 | 
					e15846bf79 | ||
| 
						 | 
					752bd00674 | ||
| 
						 | 
					7fadfcbe32 | ||
| 
						 | 
					41141e75bb | ||
| 
						 | 
					50f641e627 | ||
| 
						 | 
					c7883fd093 | ||
| 
						 | 
					4fcb24b2b1 | ||
| 
						 | 
					5003557935 | ||
| 
						 | 
					bdf1ba84da | ||
| 
						 | 
					b0b4def983 | ||
| 
						 | 
					cc184bbe9e | ||
| 
						 | 
					ad30c830aa | ||
| 
						 | 
					1d791a8af4 | ||
| 
						 | 
					e63c51cd97 | ||
| 
						 | 
					f202e32908 | ||
| 
						 | 
					26e1a08e82 | ||
| 
						 | 
					4d5119d435 | ||
| 
						 | 
					75e34ea62e | ||
| 
						 | 
					0a183d6274 | ||
| 
						 | 
					21d8060aea | ||
| 
						 | 
					9cbe906f60 | ||
| 
						 | 
					8ce4137399 | ||
| 
						 | 
					5f8a139347 | ||
| 
						 | 
					9bb009a3fe | ||
| 
						 | 
					726d65923f | ||
| 
						 | 
					8a6be4cb2d | ||
| 
						 | 
					10b06beb8e | ||
| 
						 | 
					81318c7968 | ||
| 
						 | 
					47a2c1c6e5 | ||
| 
						 | 
					39cee65c6b | ||
| 
						 | 
					8582ec724e | ||
| 
						 | 
					b0139682e8 | ||
| 
						 | 
					d39c475a6d | ||
| 
						 | 
					48f38354c6 | ||
| 
						 | 
					cd5a920ed5 | ||
| 
						 | 
					71bc1f378d | ||
| 
						 | 
					0ee6c31cff | ||
| 
						 | 
					af89a9971e | ||
| 
						 | 
					c718a8ef72 | ||
| 
						 | 
					8c8ad0faf0 | ||
| 
						 | 
					314d5bbb7f | ||
| 
						 | 
					102255757a | ||
| 
						 | 
					914067a0d0 | ||
| 
						 | 
					06e3ae2536 | ||
| 
						 | 
					7f9b252556 | ||
| 
						 | 
					3d700e243f | ||
| 
						 | 
					bcfc78ce11 | ||
| 
						 | 
					09241765d5 | ||
| 
						 | 
					671c83c265 | ||
| 
						 | 
					772d28b766 | ||
| 
						 | 
					c26fcea58d | ||
| 
						 | 
					1e5e26dbff | ||
| 
						 | 
					742fc54864 | ||
| 
						 | 
					49738f43c0 | ||
| 
						 | 
					9f85f61010 | ||
| 
						 | 
					239f422039 | ||
| 
						 | 
					67af3c37be | ||
| 
						 | 
					a9442385c4 | ||
| 
						 | 
					8c9cd10b8b | ||
| 
						 | 
					72542059dd | ||
| 
						 | 
					a843fc6d40 | ||
| 
						 | 
					4beed60c08 | ||
| 
						 | 
					4049c1e480 | ||
| 
						 | 
					8449314da2 | ||
| 
						 | 
					63ad057028 | ||
| 
						 | 
					e720464330 | ||
| 
						 | 
					24036afef9 | ||
| 
						 | 
					c78fa1a1bc | ||
| 
						 | 
					faa8b9022c | ||
| 
						 | 
					729bafef7a | ||
| 
						 | 
					590b028632 | ||
| 
						 | 
					8150d00f36 | ||
| 
						 | 
					060065926f | ||
| 
						 | 
					70babe8a28 | ||
| 
						 | 
					c36e09664f | ||
| 
						 | 
					a9672246f3 | ||
| 
						 | 
					ff571884e9 | ||
| 
						 | 
					475138bceb | ||
| 
						 | 
					4a8af199c2 | ||
| 
						 | 
					bdabf5db72 | ||
| 
						 | 
					6a5f21b34e | ||
| 
						 | 
					d608be103c | ||
| 
						 | 
					374bb5d18a | ||
| 
						 | 
					031d6c25ff | ||
| 
						 | 
					223fb7b075 | ||
| 
						 | 
					a746741971 | ||
| 
						 | 
					120faf2a58 | ||
| 
						 | 
					990bca0dc6 | ||
| 
						 | 
					3406472db7 | ||
| 
						 | 
					1bd733c9f6 | ||
| 
						 | 
					238c7f982e | ||
| 
						 | 
					fcb81147cb | ||
| 
						 | 
					1915b73783 | ||
| 
						 | 
					ee79e621fb | ||
| 
						 | 
					d203275a3b | ||
| 
						 | 
					9e8a996222 | ||
| 
						 | 
					0126b0b3ed | ||
| 
						 | 
					458928612c | ||
| 
						 | 
					e33f88e28d | ||
| 
						 | 
					be570bbf9e | ||
| 
						 | 
					f59b4be110 | ||
| 
						 | 
					37336e41be | ||
| 
						 | 
					d24a1a3f0a | ||
| 
						 | 
					f7258955bd | ||
| 
						 | 
					2a1eae5d6f | ||
| 
						 | 
					50ee0a4adb | ||
| 
						 | 
					955a26584e | ||
| 
						 | 
					1d3e407c8f | ||
| 
						 | 
					cb809c4596 | ||
| 
						 | 
					53bbe2888e | ||
| 
						 | 
					7246f476a5 | ||
| 
						 | 
					0785d1c390 | ||
| 
						 | 
					85d2c49d14 | ||
| 
						 | 
					8b77d62b7f | ||
| 
						 | 
					373058a32a | ||
| 
						 | 
					e6293c2c8c | ||
| 
						 | 
					eff181c959 | ||
| 
						 | 
					54752c2305 | ||
| 
						 | 
					b4753c044f | ||
| 
						 | 
					26493424ae | ||
| 
						 | 
					0282fd1332 | ||
| 
						 | 
					b9a019a08b | ||
| 
						 | 
					66f6a0e687 | ||
| 
						 | 
					2dd1b9f97d | ||
| 
						 | 
					89615f3045 | ||
| 
						 | 
					7e46192f67 | ||
| 
						 | 
					e78d985cdf | ||
| 
						 | 
					e8c4bf56fe | ||
| 
						 | 
					e6aa7d323d | ||
| 
						 | 
					fca8e25929 | ||
| 
						 | 
					8e8ac286b4 | ||
| 
						 | 
					7d9770b9a2 | ||
| 
						 | 
					1996230460 | ||
| 
						 | 
					de7897a864 | ||
| 
						 | 
					e2884dcdb7 | ||
| 
						 | 
					544a53a42b | ||
| 
						 | 
					2e4787bfc8 | ||
| 
						 | 
					1829eeb171 | ||
| 
						 | 
					c7488e3c4a | ||
| 
						 | 
					3bf9606383 | ||
| 
						 | 
					4f43f18f0a | ||
| 
						 | 
					5b7f197397 | ||
| 
						 | 
					018141c97f | ||
| 
						 | 
					4d7813e57c | ||
| 
						 | 
					605c60208f | ||
| 
						 | 
					884fafcc30 | ||
| 
						 | 
					56baa90320 | ||
| 
						 | 
					6bb20ee09e | ||
| 
						 | 
					541356430c | ||
| 
						 | 
					2f4d91fd69 | ||
| 
						 | 
					f58c5e6b30 | ||
| 
						 | 
					0311d0132c | ||
| 
						 | 
					c946c97402 | ||
| 
						 | 
					84a6f51318 | ||
| 
						 | 
					24a1501b0d | ||
| 
						 | 
					383b6f5fcc | ||
| 
						 | 
					633dd7ff9b | ||
| 
						 | 
					580624fad6 | ||
| 
						 | 
					a8190f7efa | ||
| 
						 | 
					dd2157534b | ||
| 
						 | 
					38a90e7669 | ||
| 
						 | 
					6bfc526dcd | ||
| 
						 | 
					aadb8a7405 | ||
| 
						 | 
					27082bf77e | ||
| 
						 | 
					a2903c80cd | ||
| 
						 | 
					9a77c5369c | ||
| 
						 | 
					3c30741a19 | ||
| 
						 | 
					7028ad4ec0 | ||
| 
						 | 
					8de750c6aa | ||
| 
						 | 
					04f98de9ee | ||
| 
						 | 
					a1a019784b | ||
| 
						 | 
					4aeeae77bd | ||
| 
						 | 
					651cfc2b78 | ||
| 
						 | 
					2ef8af25e2 | ||
| 
						 | 
					0b13852a5b | ||
| 
						 | 
					13427578c9 | ||
| 
						 | 
					d89ca2087e | ||
| 
						 | 
					8b0ea9fba6 | ||
| 
						 | 
					9f0b653d5a | ||
| 
						 | 
					659a339233 | ||
| 
						 | 
					4c29f177a0 | ||
| 
						 | 
					d664e63d55 | ||
| 
						 | 
					2493509dbe | ||
| 
						 | 
					1c8b27f554 | ||
| 
						 | 
					68297b7186 | ||
| 
						 | 
					34dd8d0a91 | ||
| 
						 | 
					81c44790d5 | ||
| 
						 | 
					d557b335cf | ||
| 
						 | 
					e2adc28cff | ||
| 
						 | 
					0fef6a6ecc | ||
| 
						 | 
					f2fd4b8a1f | ||
| 
						 | 
					95bd5605a8 | ||
| 
						 | 
					497cca7eca | ||
| 
						 | 
					54f78feedd | ||
| 
						 | 
					76408e53ae | ||
| 
						 | 
					be19e74d30 | ||
| 
						 | 
					dac578a775 | ||
| 
						 | 
					04732ce74b | ||
| 
						 | 
					a6c95a2374 | ||
| 
						 | 
					f68622abe9 | ||
| 
						 | 
					83a9a7bdb2 | ||
| 
						 | 
					6500afc0ca | ||
| 
						 | 
					c69b7ecc96 | ||
| 
						 | 
					615ef1e2d2 | ||
| 
						 | 
					cf69a0cd7f | ||
| 
						 | 
					06e892fb33 | ||
| 
						 | 
					e6c5dd6865 | ||
| 
						 | 
					247efdebdb | ||
| 
						 | 
					76f3792287 | ||
| 
						 | 
					64d8e2c727 | ||
| 
						 | 
					ead0bd9cb0 | ||
| 
						 | 
					66fc13b2ec | ||
| 
						 | 
					f3af4128b0 | ||
| 
						 | 
					0e43107c87 | ||
| 
						 | 
					1ee3e7997e | ||
| 
						 | 
					50fd61d91f | ||
| 
						 | 
					e4cdc051a9 | ||
| 
						 | 
					778e846e96 | ||
| 
						 | 
					a27759b647 | ||
| 
						 | 
					b75eceab41 | ||
| 
						 | 
					e748a5d5f4 | ||
| 
						 | 
					99c5a3ae46 | ||
| 
						 | 
					51da710f5a | ||
| 
						 | 
					569d69b3d2 | ||
| 
						 | 
					059a6b1d90 | ||
| 
						 | 
					990af7548a | ||
| 
						 | 
					a38aefdfc8 | ||
| 
						 | 
					3bcb12e7d1 | ||
| 
						 | 
					7904ecb462 | ||
| 
						 | 
					9ba4d45109 | ||
| 
						 | 
					56b8afe19d | ||
| 
						 | 
					f7aed9a94c | ||
| 
						 | 
					e12a7e881d | ||
| 
						 | 
					5afb65325d | ||
| 
						 | 
					135f520f32 | ||
| 
						 | 
					bc251f4ff6 | ||
| 
						 | 
					b8769751f6 | ||
| 
						 | 
					eff96d839e | ||
| 
						 | 
					aa34c23807 | ||
| 
						 | 
					195acdac8c | ||
| 
						 | 
					903e03c56c | ||
| 
						 | 
					0892767b8a | ||
| 
						 | 
					83ebfa772c | ||
| 
						 | 
					1583641322 | ||
| 
						 | 
					9510e2c256 | ||
| 
						 | 
					a9dbabe07e | ||
| 
						 | 
					12884008fa | ||
| 
						 | 
					02543bad1c | ||
| 
						 | 
					a8c56a5251 | ||
| 
						 | 
					4e5a855f3f | ||
| 
						 | 
					7e497a951e | ||
| 
						 | 
					cd08eabbfa | ||
| 
						 | 
					f7e62d9f81 | ||
| 
						 | 
					9a3761e86e | ||
| 
						 | 
					3619a68693 | ||
| 
						 | 
					efaf3c3bf9 | ||
| 
						 | 
					0e4e6a6f67 | ||
| 
						 | 
					42458e6278 | ||
| 
						 | 
					41ec995377 | ||
| 
						 | 
					4f37599326 | ||
| 
						 | 
					4144520e5c | ||
| 
						 | 
					6c4800546c | ||
| 
						 | 
					733733c8a7 | ||
| 
						 | 
					2aa67cc946 | ||
| 
						 | 
					9385981a9d | ||
| 
						 | 
					fff780035d | ||
| 
						 | 
					46127e673d | ||
| 
						 | 
					70df59b224 | ||
| 
						 | 
					0fdbaa803f | ||
| 
						 | 
					6af1830eff | ||
| 
						 | 
					6f860e2bd5 | ||
| 
						 | 
					20a492f7ee | ||
| 
						 | 
					63875e7591 | ||
| 
						 | 
					0ad98cabde | ||
| 
						 | 
					668879d2e1 | ||
| 
						 | 
					2e09783302 | ||
| 
						 | 
					49734114b3 | ||
| 
						 | 
					950d9d6ee7 | ||
| 
						 | 
					f7974aee2e | ||
| 
						 | 
					c870a82621 | ||
| 
						 | 
					984929a001 | ||
| 
						 | 
					7f9e2c1db8 | ||
| 
						 | 
					324e8389dc | ||
| 
						 | 
					6f448c5a38 | ||
| 
						 | 
					ec43efbb20 | ||
| 
						 | 
					3ed065de37 | ||
| 
						 | 
					8152f0d72c | ||
| 
						 | 
					f8047f4736 | ||
| 
						 | 
					b93c66dc2d | ||
| 
						 | 
					ac877b3065 | ||
| 
						 | 
					dee8abfdde | ||
| 
						 | 
					cef3841d73 | ||
| 
						 | 
					3cd5e8a041 | ||
| 
						 | 
					515b5f866e | ||
| 
						 | 
					321f62bf92 | ||
| 
						 | 
					f94fa47b52 | ||
| 
						 | 
					c502f8a722 | ||
| 
						 | 
					59b4868ac3 | ||
| 
						 | 
					3634e12cce | ||
| 
						 | 
					6d45445391 | ||
| 
						 | 
					4f47e268cc | ||
| 
						 | 
					0035b31cdb | ||
| 
						 | 
					f2565aee03 | ||
| 
						 | 
					5bd85668dd | ||
| 
						 | 
					20f990b6ce | ||
| 
						 | 
					6821379586 | ||
| 
						 | 
					73b040eb49 | ||
| 
						 | 
					49aa4b2e1e | ||
| 
						 | 
					972241c74c | ||
| 
						 | 
					680750e3c2 | ||
| 
						 | 
					5e7d4d9d15 | ||
| 
						 | 
					1e57e60613 | ||
| 
						 | 
					3ac7ce605a | ||
| 
						 | 
					b720dea9f0 | ||
| 
						 | 
					c80722aefe | ||
| 
						 | 
					a84fa69f28 | ||
| 
						 | 
					e33781e59f | ||
| 
						 | 
					8824bc7ece | ||
| 
						 | 
					c2e3b0e448 | ||
| 
						 | 
					f61a38e85a | ||
| 
						 | 
					d23e948216 | ||
| 
						 | 
					58bdaa31f0 | ||
| 
						 | 
					b6491d88a6 | ||
| 
						 | 
					f6061ba62e | ||
| 
						 | 
					427899ddce | ||
| 
						 | 
					c4ab7d2dbd | ||
| 
						 | 
					0fd2ba033f | ||
| 
						 | 
					ed38939a93 | ||
| 
						 | 
					c7ee26ce5a | ||
| 
						 | 
					909b8cb303 | ||
| 
						 | 
					b0277370cf | ||
| 
						 | 
					2ec8656bea | ||
| 
						 | 
					b2ef256910 | ||
| 
						 | 
					63d6ce95db | ||
| 
						 | 
					a9532b189c | ||
| 
						 | 
					844545411f | ||
| 
						 | 
					4e23a2b9b8 | ||
| 
						 | 
					5deba027eb | ||
| 
						 | 
					fc8b7efc6f | ||
| 
						 | 
					a1c2d9c0f3 | ||
| 
						 | 
					4ca49a0501 | ||
| 
						 | 
					493c53d090 | ||
| 
						 | 
					b27e956d35 | ||
| 
						 | 
					35ebed75c6 | ||
| 
						 | 
					7bfdb5f77f | ||
| 
						 | 
					8d8c02317f | ||
| 
						 | 
					a34482feab | ||
| 
						 | 
					cbdc8fd4a6 | ||
| 
						 | 
					8d3afaa53c | ||
| 
						 | 
					7ced9ef3df | ||
| 
						 | 
					e8a9ae7e80 | ||
| 
						 | 
					73a88ab3d3 | ||
| 
						 | 
					aaed82738a | ||
| 
						 | 
					de7f7b96db | ||
| 
						 | 
					1a669b3e68 | ||
| 
						 | 
					333af9b13a | ||
| 
						 | 
					a5bca5e240 | ||
| 
						 | 
					c885633e02 | ||
| 
						 | 
					ca7e20b7ca | ||
| 
						 | 
					545e11a3d7 | ||
| 
						 | 
					44f5287664 | ||
| 
						 | 
					cf510897f1 | ||
| 
						 | 
					1d171345f8 | ||
| 
						 | 
					4fa7e1cd49 | ||
| 
						 | 
					acd008298e | ||
| 
						 | 
					83a8021515 | ||
| 
						 | 
					cf88dfb1db | ||
| 
						 | 
					8937c4b481 | ||
| 
						 | 
					cc6af10a4d | ||
| 
						 | 
					6d94578955 | ||
| 
						 | 
					08442ab71e | ||
| 
						 | 
					10d91d213f | ||
| 
						 | 
					b7a3b06994 | ||
| 
						 | 
					5f12c37f23 | ||
| 
						 | 
					585edebccd | ||
| 
						 | 
					9921c62234 | ||
| 
						 | 
					1ac76d2e16 | ||
| 
						 | 
					6e983bf400 | ||
| 
						 | 
					6a8fd4fa6e | ||
| 
						 | 
					3698eaa2d2 | ||
| 
						 | 
					8d97ca433c | ||
| 
						 | 
					23cc65e537 | ||
| 
						 | 
					2f5a3c2bbe | ||
| 
						 | 
					f6485616cd | ||
| 
						 | 
					6544fb43d9 | ||
| 
						 | 
					a954b32dcc | ||
| 
						 | 
					426dc7836c | ||
| 
						 | 
					ff941ffc16 | ||
| 
						 | 
					a063c201df | ||
| 
						 | 
					e2be3fa0aa | ||
| 
						 | 
					609da6fb50 | ||
| 
						 | 
					fc9f3ccec3 | ||
| 
						 | 
					f7baa67a0a | ||
| 
						 | 
					e8d78c2cdb | ||
| 
						 | 
					9d33366092 | ||
| 
						 | 
					f5d61515c2 | ||
| 
						 | 
					711a04a972 | ||
| 
						 | 
					e5b470a3f1 | ||
| 
						 | 
					31820e1e22 | ||
| 
						 | 
					4849e8cd6d | ||
| 
						 | 
					77e3b460aa | ||
| 
						 | 
					b5321001f8 | ||
| 
						 | 
					38eba9f5ea | ||
| 
						 | 
					ea6f399454 | ||
| 
						 | 
					f8bf2d7b7d | ||
| 
						 | 
					c4856caebb | ||
| 
						 | 
					fc1030bb22 | ||
| 
						 | 
					9eb6cad8dc | ||
| 
						 | 
					0fa2a78dce | ||
| 
						 | 
					a56fa1558b | ||
| 
						 | 
					261c73a997 | ||
| 
						 | 
					929c1333ca | ||
| 
						 | 
					286a79d94d | ||
| 
						 | 
					8b951f99da | ||
| 
						 | 
					abb449bca0 | ||
| 
						 | 
					bd084028d1 | ||
| 
						 | 
					138a27570b | ||
| 
						 | 
					c2ed40a74f | ||
| 
						 | 
					a7e7a00cab | ||
| 
						 | 
					64a31ab3cd | ||
| 
						 | 
					71958bc0f1 | ||
| 
						 | 
					366ec35612 | ||
| 
						 | 
					3738f6e8ae | ||
| 
						 | 
					051a8e2af1 | ||
| 
						 | 
					2f43f28d5e | ||
| 
						 | 
					b64769754b | ||
| 
						 | 
					a97daa18d1 | ||
| 
						 | 
					b6556dce8b | ||
| 
						 | 
					aa8d8bc8b5 | ||
| 
						 | 
					0800dcfdc4 | ||
| 
						 | 
					12b0101e94 | ||
| 
						 | 
					021b391a02 | ||
| 
						 | 
					d11e2b6057 | ||
| 
						 | 
					264d90e7e5 | ||
| 
						 | 
					f9f3da9e78 | ||
| 
						 | 
					6435b49153 | ||
| 
						 | 
					f9aa2941cf | ||
| 
						 | 
					5a933d4bee | ||
| 
						 | 
					5536aea0df | ||
| 
						 | 
					976666d216 | ||
| 
						 | 
					9a5bcd4392 | ||
| 
						 | 
					812060a118 | ||
| 
						 | 
					089b5052e6 | ||
| 
						 | 
					874e5d72f4 | ||
| 
						 | 
					6b11de1329 | ||
| 
						 | 
					2245a7ad8d | ||
| 
						 | 
					ee5ec1b870 | ||
| 
						 | 
					74ccfe851b | ||
| 
						 | 
					e1c24bd5a2 | ||
| 
						 | 
					1349b79728 | ||
| 
						 | 
					d294d7604c | ||
| 
						 | 
					01df2cf464 | ||
| 
						 | 
					45b7322488 | ||
| 
						 | 
					b3055e992f | ||
| 
						 | 
					3da548565c | ||
| 
						 | 
					a975e85548 | ||
| 
						 | 
					c4b5ade752 | ||
| 
						 | 
					a4b61b0794 | ||
| 
						 | 
					f6011184b8 | ||
| 
						 | 
					74de118c6e | ||
| 
						 | 
					9c25e77c17 | ||
| 
						 | 
					440113e67e | ||
| 
						 | 
					a11b60c445 | ||
| 
						 | 
					a6052681ad | ||
| 
						 | 
					482d50536a | ||
| 
						 | 
					25c79a4fcd | ||
| 
						 | 
					02946144ac | ||
| 
						 | 
					71a360e9a3 | ||
| 
						 | 
					f7912d88b1 | ||
| 
						 | 
					975101d7d2 | ||
| 
						 | 
					ef58c5ff55 | ||
| 
						 | 
					e10221804a | ||
| 
						 | 
					284ed9ee0e | ||
| 
						 | 
					5d7b961997 | ||
| 
						 | 
					c699a5c4b4 | ||
| 
						 | 
					1f4ceb89cf | ||
| 
						 | 
					0934ca0040 | ||
| 
						 | 
					4738f892c2 | ||
| 
						 | 
					33004fcf33 | ||
| 
						 | 
					34d214c166 | ||
| 
						 | 
					a56cd92a1e | ||
| 
						 | 
					7251348507 | ||
| 
						 | 
					01cd5c84d6 | ||
| 
						 | 
					e210599fa6 | ||
| 
						 | 
					dbe7cee7e9 | ||
| 
						 | 
					7370d88ceb | ||
| 
						 | 
					34458e0c57 | ||
| 
						 | 
					05c8c3abf2 | ||
| 
						 | 
					e9d464b4d3 | ||
| 
						 | 
					6968c3ab9b | ||
| 
						 | 
					131a8a9650 | ||
| 
						 | 
					379ecbf9a9 | ||
| 
						 | 
					7b9dfa9a28 | ||
| 
						 | 
					fbd0f5eed2 | ||
| 
						 | 
					5970f904ae | ||
| 
						 | 
					8cbcb2868d | ||
| 
						 | 
					8ff2a4b026 | ||
| 
						 | 
					ae14d205a5 | ||
| 
						 | 
					ec5d560ec5 | ||
| 
						 | 
					fb543b53c0 | ||
| 
						 | 
					39c16422e2 | ||
| 
						 | 
					4d5b273ebe | ||
| 
						 | 
					ed6a860fad | ||
| 
						 | 
					423e579292 | ||
| 
						 | 
					ee11aa9e75 | ||
| 
						 | 
					c46d20fa92 | ||
| 
						 | 
					dc8d17574c | ||
| 
						 | 
					5c17cd04c8 | ||
| 
						 | 
					67ada02076 | ||
| 
						 | 
					32d94c2eaf | ||
| 
						 | 
					687b39a12a | ||
| 
						 | 
					705af407bf | ||
| 
						 | 
					080052da2e | ||
| 
						 | 
					ef735fd92a | ||
| 
						 | 
					17c16dcafc | ||
| 
						 | 
					a89b3018fb | ||
| 
						 | 
					851e2ebd32 | ||
| 
						 | 
					1225ce7fe8 | ||
| 
						 | 
					7e77a31b96 | ||
| 
						 | 
					d146b9002f | ||
| 
						 | 
					1f9d567b23 | ||
| 
						 | 
					ed1b3a023c | ||
| 
						 | 
					1ca18f501a | ||
| 
						 | 
					49588ccd98 | ||
| 
						 | 
					098dedc092 | ||
| 
						 | 
					b06f6b9545 | ||
| 
						 | 
					ba3cb94999 | ||
| 
						 | 
					74c67fbf4b | ||
| 
						 | 
					32b46e4910 | ||
| 
						 | 
					ecf5539ed2 | ||
| 
						 | 
					ac9db4e4d5 | ||
| 
						 | 
					0eb96094b0 | ||
| 
						 | 
					30b3ac7dc5 | ||
| 
						 | 
					0092790c7d | ||
| 
						 | 
					28909d8a51 | ||
| 
						 | 
					b20cfbb7b6 | ||
| 
						 | 
					97639bd0a8 | ||
| 
						 | 
					161ec73c96 | ||
| 
						 | 
					957d6bea15 | ||
| 
						 | 
					f8b6e5b414 | ||
| 
						 | 
					1ab450870e | ||
| 
						 | 
					de45f4884c | ||
| 
						 | 
					5da1f3e7c8 | ||
| 
						 | 
					983014952b | ||
| 
						 | 
					55298019a3 | ||
| 
						 | 
					a1ffc3f271 | ||
| 
						 | 
					2fb60aa997 | ||
| 
						 | 
					f5ec76537a | ||
| 
						 | 
					728491fd2b | ||
| 
						 | 
					d9d3f2b9e4 | ||
| 
						 | 
					3fe4864f65 | ||
| 
						 | 
					0b156f22a4 | ||
| 
						 | 
					35b1d93813 | ||
| 
						 | 
					d770851ac0 | ||
| 
						 | 
					989e7b1033 | ||
| 
						 | 
					c4e0eb7b49 | ||
| 
						 | 
					71f5d0dac7 | ||
| 
						 | 
					561b0c4381 | ||
| 
						 | 
					995fbc7330 | ||
| 
						 | 
					10ab8949c4 | ||
| 
						 | 
					c441202fea | ||
| 
						 | 
					ca261b0bee | ||
| 
						 | 
					52f3709f67 | ||
| 
						 | 
					c2ca6187fe | ||
| 
						 | 
					671a13d295 | ||
| 
						 | 
					14c3e2eccf | ||
| 
						 | 
					08e5b852c2 | ||
| 
						 | 
					1c9606c824 | ||
| 
						 | 
					3cd47b5c9b | ||
| 
						 | 
					aedc729087 | ||
| 
						 | 
					5f7cfa3fa9 | ||
| 
						 | 
					0083f30af5 | ||
| 
						 | 
					4a06f05ef5 | ||
| 
						 | 
					8f37cadce8 | ||
| 
						 | 
					a11603ca6c | ||
| 
						 | 
					86274842e9 | ||
| 
						 | 
					cf9c955a44 | ||
| 
						 | 
					55d828c35f | ||
| 
						 | 
					cdff28aca6 | ||
| 
						 | 
					b9da39274f | ||
| 
						 | 
					c379aa5782 | ||
| 
						 | 
					9dcabac9dd | ||
| 
						 | 
					794f3a2b9f | ||
| 
						 | 
					2066121b7c | ||
| 
						 | 
					0c4067f143 | ||
| 
						 | 
					8aa69243b7 | ||
| 
						 | 
					8697263bde | ||
| 
						 | 
					ea25c4f65c | ||
| 
						 | 
					82ac3ebd7e | ||
| 
						 | 
					13cb94909c | ||
| 
						 | 
					b57ca2a763 | ||
| 
						 | 
					83c49e9745 | ||
| 
						 | 
					e15771d78d | ||
| 
						 | 
					6edc4920ba | ||
| 
						 | 
					302bb1bd93 | ||
| 
						 | 
					529b1bceee | ||
| 
						 | 
					42cd47d32e | ||
| 
						 | 
					711d884c2e | ||
| 
						 | 
					183d1c4674 | ||
| 
						 | 
					faed63a0bb | ||
| 
						 | 
					53bff262f8 | ||
| 
						 | 
					3251a708e4 | ||
| 
						 | 
					b5dbdbf7b2 | ||
| 
						 | 
					a9649e92c9 | ||
| 
						 | 
					b561f1fa8b | ||
| 
						 | 
					cecd7491b5 | ||
| 
						 | 
					55a66322b5 | ||
| 
						 | 
					155c31a2d7 | ||
| 
						 | 
					a89ce91089 | ||
| 
						 | 
					b897fe6700 | ||
| 
						 | 
					548a351b06 | ||
| 
						 | 
					4b1da57ca1 | ||
| 
						 | 
					529aec7f25 | ||
| 
						 | 
					1661e545cb | ||
| 
						 | 
					ec71d08878 | ||
| 
						 | 
					ac258b7dd7 | ||
| 
						 | 
					0f57876233 | ||
| 
						 | 
					1d25a3693d | ||
| 
						 | 
					45fa428bf1 | ||
| 
						 | 
					177fa80f1a | ||
| 
						 | 
					3261261bfe | ||
| 
						 | 
					d4de7934f8 | ||
| 
						 | 
					c3475af809 | ||
| 
						 | 
					b12f707812 | ||
| 
						 | 
					22c0c34d60 | ||
| 
						 | 
					a60b66f230 | ||
| 
						 | 
					83f6e93628 | ||
| 
						 | 
					222b5f0229 | ||
| 
						 | 
					30aa383e26 | ||
| 
						 | 
					676b401294 | ||
| 
						 | 
					ebf57159de | ||
| 
						 | 
					199d2aafec | ||
| 
						 | 
					81952f56fd | ||
| 
						 | 
					c5bac82b43 | ||
| 
						 | 
					081b86109c | ||
| 
						 | 
					8ac2028a75 | ||
| 
						 | 
					264fed1c9f | ||
| 
						 | 
					dd59f7b2c7 | ||
| 
						 | 
					9245a760db | ||
| 
						 | 
					b61b32bbc3 | ||
| 
						 | 
					09b3914f5d | ||
| 
						 | 
					fe644e4c9e | ||
| 
						 | 
					7b09bf2156 | ||
| 
						 | 
					987d0aae66 | ||
| 
						 | 
					9cbcbc1c22 | ||
| 
						 | 
					cfc4e2bc60 | ||
| 
						 | 
					a03405fa81 | ||
| 
						 | 
					d5c9ccbe6e | ||
| 
						 | 
					e52772d65f | ||
| 
						 | 
					1e3259e728 | ||
| 
						 | 
					e905a20a60 | ||
| 
						 | 
					88e2be7a33 | ||
| 
						 | 
					8939131600 | ||
| 
						 | 
					ba37ebff8b | ||
| 
						 | 
					28f4cb7e07 | ||
| 
						 | 
					db1e7102cd | ||
| 
						 | 
					07eb7a5830 | ||
| 
						 | 
					b7c6c685fa | ||
| 
						 | 
					212134df70 | ||
| 
						 | 
					6eeb5528f5 | ||
| 
						 | 
					54fad845c9 | ||
| 
						 | 
					d6c0de6fc7 | ||
| 
						 | 
					649c8649f7 | ||
| 
						 | 
					da2f53d1b1 | ||
| 
						 | 
					405139e3b8 | ||
| 
						 | 
					4f8d347171 | ||
| 
						 | 
					bf0db4876c | ||
| 
						 | 
					47a14884d6 | ||
| 
						 | 
					3a7bbc8b08 | ||
| 
						 | 
					1b1d65372c | ||
| 
						 | 
					fd2faaa16e | ||
| 
						 | 
					0609cdb9ea | ||
| 
						 | 
					d3bb140f89 | ||
| 
						 | 
					b31dc66628 | ||
| 
						 | 
					09476171a6 | ||
| 
						 | 
					33dee813b5 | ||
| 
						 | 
					bb4e73c40b | ||
| 
						 | 
					b1f23ffa94 | ||
| 
						 | 
					b0e8cec1e7 | ||
| 
						 | 
					5077ae19bc | ||
| 
						 | 
					0d8447bf59 | ||
| 
						 | 
					c6cf08a274 | ||
| 
						 | 
					dc49ae519e | ||
| 
						 | 
					904539476a | ||
| 
						 | 
					3fbf02dc82 | ||
| 
						 | 
					c9392a840d | ||
| 
						 | 
					d164e8ab72 | ||
| 
						 | 
					6dc62c9fb6 | ||
| 
						 | 
					87a9684d66 | ||
| 
						 | 
					94525e2f44 | ||
| 
						 | 
					b408b1b3b9 | ||
| 
						 | 
					27c2f09e32 | ||
| 
						 | 
					19bc4d3349 | ||
| 
						 | 
					f2b6c424d6 | ||
| 
						 | 
					a49d4453e9 | ||
| 
						 | 
					65e50087b9 | ||
| 
						 | 
					2d90f759d9 | ||
| 
						 | 
					4230ac7674 | ||
| 
						 | 
					d96e9182e9 | ||
| 
						 | 
					68c87b9616 | ||
| 
						 | 
					7f8e9a0b6d | ||
| 
						 | 
					81a229f2a5 | ||
| 
						 | 
					8be7ae2733 | ||
| 
						 | 
					846bca4cb1 | ||
| 
						 | 
					f36f353789 | ||
| 
						 | 
					939a2731ed | ||
| 
						 | 
					835dab97ff | ||
| 
						 | 
					fa904b53be | ||
| 
						 | 
					0ec52dddce | ||
| 
						 | 
					c289355a3a | ||
| 
						 | 
					02a13a5a18 | ||
| 
						 | 
					6cf2a0281b | ||
| 
						 | 
					120d35f9af | ||
| 
						 | 
					2b15d5e7b3 | ||
| 
						 | 
					fc167bd3f0 | ||
| 
						 | 
					91b04abf05 | ||
| 
						 | 
					77faac8740 | ||
| 
						 | 
					43b3d54855 | ||
| 
						 | 
					69e9b85700 | ||
| 
						 | 
					0b6d132759 | ||
| 
						 | 
					7c233c6c0c | ||
| 
						 | 
					c35b290fa4 | ||
| 
						 | 
					3d95cfb367 | ||
| 
						 | 
					b90fc3a56e | ||
| 
						 | 
					1ef3fdccf5 | ||
| 
						 | 
					02b7f77bd8 | ||
| 
						 | 
					0ac7ead922 | ||
| 
						 | 
					da9d0e03ce | ||
| 
						 | 
					120f65f672 | ||
| 
						 | 
					200a14caa4 | ||
| 
						 | 
					35bf6da8e2 | ||
| 
						 | 
					f08f70276c | ||
| 
						 | 
					1ae50fd95b | ||
| 
						 | 
					40512beb47 | ||
| 
						 | 
					0d7f9b2c94 | ||
| 
						 | 
					52f42140a7 | ||
| 
						 | 
					3f6c50297f | ||
| 
						 | 
					f72d80afc5 | ||
| 
						 | 
					7c5cb13b22 | ||
| 
						 | 
					d728750eb2 | ||
| 
						 | 
					02a70e5667 | ||
| 
						 | 
					44e51ea5fa | ||
| 
						 | 
					87e201460a | ||
| 
						 | 
					039bd945e2 | ||
| 
						 | 
					e9e52d2b4b | ||
| 
						 | 
					2bf92e7399 | ||
| 
						 | 
					5b0df241f0 | ||
| 
						 | 
					76f5b05eff | ||
| 
						 | 
					40fb6c998f | ||
| 
						 | 
					33f50a342d | ||
| 
						 | 
					81523ab68a | ||
| 
						 | 
					2bf8cc62cf | ||
| 
						 | 
					1ae8247af3 | ||
| 
						 | 
					5ef32227ec | ||
| 
						 | 
					6456e773bd | ||
| 
						 | 
					234fe53ca3 | ||
| 
						 | 
					7c93e7a7b3 | ||
| 
						 | 
					8afc6c7f4b | ||
| 
						 | 
					4609d0fa3a | ||
| 
						 | 
					d452c035c6 | ||
| 
						 | 
					45113c8f5a | ||
| 
						 | 
					0acdd3c62b | ||
| 
						 | 
					96d7d0a33e | ||
| 
						 | 
					b6b280267b | ||
| 
						 | 
					6e6d253b1a | ||
| 
						 | 
					d92c105db2 | ||
| 
						 | 
					906db728d6 | ||
| 
						 | 
					c4b7411565 | ||
| 
						 | 
					de06396046 | ||
| 
						 | 
					ee6bfeb8e3 | ||
| 
						 | 
					058347321f | ||
| 
						 | 
					feefe49324 | ||
| 
						 | 
					187381a9a2 | ||
| 
						 | 
					993dfa4368 | ||
| 
						 | 
					7e35a16440 | ||
| 
						 | 
					e4eeb15926 | ||
| 
						 | 
					634e0db26d | ||
| 
						 | 
					56855c23e1 | ||
| 
						 | 
					0b00f742e3 | ||
| 
						 | 
					b7ab3f673c | ||
| 
						 | 
					be04ea1e35 | ||
| 
						 | 
					1f8e695802 | ||
| 
						 | 
					2d82b2c64f | ||
| 
						 | 
					d076caf473 | ||
| 
						 | 
					c7abdefa31 | ||
| 
						 | 
					ba772c0bca | ||
| 
						 | 
					5bad234119 | ||
| 
						 | 
					c7e7baaf23 | ||
| 
						 | 
					36658a671b | ||
| 
						 | 
					045f2e10ba | ||
| 
						 | 
					fb5a7db66d | ||
| 
						 | 
					ba7d33982e | ||
| 
						 | 
					c62279a755 | ||
| 
						 | 
					17fa1a7ffb | ||
| 
						 | 
					e89ceac351 | ||
| 
						 | 
					0b8c30c109 | ||
| 
						 | 
					9ab0f463cc | ||
| 
						 | 
					6433dda7b8 | ||
| 
						 | 
					fa7a2f4be4 | ||
| 
						 | 
					ba90e16505 | ||
| 
						 | 
					008f710203 | ||
| 
						 | 
					df2740f126 | ||
| 
						 | 
					2db89d143e | ||
| 
						 | 
					0525d49da3 | ||
| 
						 | 
					e2b0745882 | ||
| 
						 | 
					92e804fc50 | ||
| 
						 | 
					67abf45576 | ||
| 
						 | 
					d2c9c814e7 | ||
| 
						 | 
					22f8881a64 | ||
| 
						 | 
					4ab20322fe | ||
| 
						 | 
					5370eeecea | ||
| 
						 | 
					ba71cb5dd7 | ||
| 
						 | 
					9aad6c2c52 | ||
| 
						 | 
					4d9627f20c | ||
| 
						 | 
					c142492e91 | ||
| 
						 | 
					6bf8d9e207 | ||
| 
						 | 
					4f9a6168c1 | ||
| 
						 | 
					38397f99aa | ||
| 
						 | 
					f8686d0e75 | ||
| 
						 | 
					549e3c8f9d | ||
| 
						 | 
					bb56225b95 | ||
| 
						 | 
					f00be261ba | ||
| 
						 | 
					9cd94f26d0 | ||
| 
						 | 
					4d8f5c80a7 | ||
| 
						 | 
					24a23acc3d | ||
| 
						 | 
					ca8703cfd8 | ||
| 
						 | 
					6dcbb5b2f8 | ||
| 
						 | 
					a84fdddb2a | ||
| 
						 | 
					38bb2f8ceb | ||
| 
						 | 
					23f5ef4345 | ||
| 
						 | 
					ef8a2a9054 | ||
| 
						 | 
					96103d0e36 | ||
| 
						 | 
					ff5f6748df | ||
| 
						 | 
					1c1fd6c366 | ||
| 
						 | 
					32d37d00cb | ||
| 
						 | 
					82f6cda966 | ||
| 
						 | 
					f1ff8ff0d0 | ||
| 
						 | 
					756c72902f | ||
| 
						 | 
					73f8f0bbd0 | ||
| 
						 | 
					18ed528f5d | ||
| 
						 | 
					8fd2f136bc | ||
| 
						 | 
					0524b1bf67 | ||
| 
						 | 
					15716f65ce | ||
| 
						 | 
					d46bdba332 | ||
| 
						 | 
					760728110a | ||
| 
						 | 
					12d0a194ca | ||
| 
						 | 
					4104543508 | ||
| 
						 | 
					5c211db015 | ||
| 
						 | 
					2dc6180f8d | ||
| 
						 | 
					e222a34b69 | ||
| 
						 | 
					ef17d95063 | ||
| 
						 | 
					853502e5d7 | ||
| 
						 | 
					c18e297e77 | ||
| 
						 | 
					c5a49599ba | ||
| 
						 | 
					df9da9edf5 | ||
| 
						 | 
					e2200fd050 | ||
| 
						 | 
					c6207f5d9c | ||
| 
						 | 
					4302b7ff6b | ||
| 
						 | 
					50a7923438 | ||
| 
						 | 
					ab416445c8 | ||
| 
						 | 
					a54698d43c | ||
| 
						 | 
					c5a77cc1c0 | ||
| 
						 | 
					a9ffa811fc | ||
| 
						 | 
					080a2608e0 | ||
| 
						 | 
					57f2e83d6a | ||
| 
						 | 
					5b030139d3 | ||
| 
						 | 
					0da1ff42d1 | ||
| 
						 | 
					2c599b7baa | ||
| 
						 | 
					5c8af8d21a | ||
| 
						 | 
					026f3cfde2 | ||
| 
						 | 
					f6349180e8 | ||
| 
						 | 
					aa6421921c | ||
| 
						 | 
					7d41d2dab2 | ||
| 
						 | 
					f0b4d18f93 | ||
| 
						 | 
					6750f06e10 | ||
| 
						 | 
					b2bd38fa9e | ||
| 
						 | 
					3482a01e22 | ||
| 
						 | 
					6335467552 | ||
| 
						 | 
					4a39e65b62 | ||
| 
						 | 
					c50a23e918 | ||
| 
						 | 
					1e76b72b98 | ||
| 
						 | 
					b94cf39eef | ||
| 
						 | 
					fef254ffff | ||
| 
						 | 
					e5495863a2 | ||
| 
						 | 
					3b4df2abf0 | ||
| 
						 | 
					aef2aee6a4 | ||
| 
						 | 
					d0d9519149 | ||
| 
						 | 
					685df1d2c5 | ||
| 
						 | 
					08e6b6f2e7 | ||
| 
						 | 
					66c887d0f3 | ||
| 
						 | 
					22e9960697 | ||
| 
						 | 
					64aa6e1f2d | ||
| 
						 | 
					7a93ed9d04 | ||
| 
						 | 
					a905e922e9 | ||
| 
						 | 
					f9f08fc720 | ||
| 
						 | 
					8d402d76d0 | ||
| 
						 | 
					46fda6281c | ||
| 
						 | 
					a14dbe1ea6 | ||
| 
						 | 
					18810a4c16 | ||
| 
						 | 
					147bc80dba | ||
| 
						 | 
					c7a484195a | ||
| 
						 | 
					4968eb6503 | ||
| 
						 | 
					a6f2d698a9 | ||
| 
						 | 
					ea5ed93ea5 | ||
| 
						 | 
					e1140134c6 | ||
| 
						 | 
					5ed11e012e | ||
| 
						 | 
					5380bd39ca | ||
| 
						 | 
					2ee2685688 | ||
| 
						 | 
					782002245b | ||
| 
						 | 
					7fc0905843 | ||
| 
						 | 
					72ecb99e54 | ||
| 
						 | 
					c863507d08 | ||
| 
						 | 
					cff86c9093 | ||
| 
						 | 
					0479dfcc54 | ||
| 
						 | 
					68dd67f21c | ||
| 
						 | 
					540f6858b5 | ||
| 
						 | 
					b61e791a4f | ||
| 
						 | 
					d0986f9482 | ||
| 
						 | 
					112cb0dc28 | ||
| 
						 | 
					0d3d7fdcf2 | ||
| 
						 | 
					5d6b89ef3b | ||
| 
						 | 
					ed0b26c09e | ||
| 
						 | 
					ae292bd920 | ||
| 
						 | 
					6c85a90723 | ||
| 
						 | 
					852592066c | ||
| 
						 | 
					96e1bc9b44 | ||
| 
						 | 
					b41d81ed31 | ||
| 
						 | 
					e241ec2244 | ||
| 
						 | 
					16e1f1a94c | ||
| 
						 | 
					7a68c42b26 | ||
| 
						 | 
					37ccc2e118 | ||
| 
						 | 
					4192fe1ab2 | ||
| 
						 | 
					d5c743d7bb | ||
| 
						 | 
					11814d63e8 | ||
| 
						 | 
					b753656d50 | ||
| 
						 | 
					f7e87611fc | ||
| 
						 | 
					1fb0e1900e | ||
| 
						 | 
					954a9731e0 | ||
| 
						 | 
					65c3364ad8 | ||
| 
						 | 
					3d72b7dccc | ||
| 
						 | 
					13ee569f06 | ||
| 
						 | 
					d79ef23a75 | ||
| 
						 | 
					5d0797d4ba | ||
| 
						 | 
					47a8d7475f | ||
| 
						 | 
					4939053121 | ||
| 
						 | 
					b525bf554e | ||
| 
						 | 
					f00285d2b2 | ||
| 
						 | 
					040f8d6eda | ||
| 
						 | 
					66d905325c | ||
| 
						 | 
					8b0cd95e73 | ||
| 
						 | 
					d867cca6d9 | ||
| 
						 | 
					a28f736369 | ||
| 
						 | 
					5c3a71cc59 | ||
| 
						 | 
					cef6dadb08 | ||
| 
						 | 
					36be817a3e | ||
| 
						 | 
					02f571f081 | ||
| 
						 | 
					157159e487 | ||
| 
						 | 
					02ada9f800 | ||
| 
						 | 
					6fcf9a97bb | ||
| 
						 | 
					17a5d8799f | ||
| 
						 | 
					31f3fe7a22 | ||
| 
						 | 
					89e46d3d83 | ||
| 
						 | 
					885795e67d | ||
| 
						 | 
					92bfb53dd4 | ||
| 
						 | 
					4cecbeb115 | ||
| 
						 | 
					5971480f55 | ||
| 
						 | 
					05bebea511 | ||
| 
						 | 
					76fa6c5cfb | ||
| 
						 | 
					633b68b518 | ||
| 
						 | 
					6913d8e995 | ||
| 
						 | 
					f3654e6f8d | ||
| 
						 | 
					d685dbcf22 | ||
| 
						 | 
					6a57fa079e | ||
| 
						 | 
					0a91d145ba | ||
| 
						 | 
					c2866e799d | ||
| 
						 | 
					d8cffcaae7 | ||
| 
						 | 
					30abca7be2 | ||
| 
						 | 
					edce87f3fb | ||
| 
						 | 
					66bac98fc2 | ||
| 
						 | 
					59156de92b | ||
| 
						 | 
					e0d7d10600 | ||
| 
						 | 
					daaf862257 | ||
| 
						 | 
					9de53d4b59 | ||
| 
						 | 
					f1571e2d46 | ||
| 
						 | 
					bd28d06298 | ||
| 
						 | 
					a24e4655eb | ||
| 
						 | 
					20a6c8d8e5 | ||
| 
						 | 
					98d264faf4 | ||
| 
						 | 
					321902a9b5 | ||
| 
						 | 
					8df5d06f9a | ||
| 
						 | 
					e69ea529cc | ||
| 
						 | 
					15405b1119 | ||
| 
						 | 
					d2f97ce2da | ||
| 
						 | 
					543ca631e9 | ||
| 
						 | 
					f184886db1 | ||
| 
						 | 
					8432ab4324 | ||
| 
						 | 
					6c05b37ca3 | ||
| 
						 | 
					35f4beeb47 | ||
| 
						 | 
					cbad7caa68 | ||
| 
						 | 
					b0388a4012 | ||
| 
						 | 
					df3fab4d55 | ||
| 
						 | 
					da49f88a03 | ||
| 
						 | 
					e28feceb06 | ||
| 
						 | 
					50496a164d | ||
| 
						 | 
					6f1dce1572 | ||
| 
						 | 
					6847776ae7 | ||
| 
						 | 
					67bd53bdd8 | ||
| 
						 | 
					e735abfdfd | ||
| 
						 | 
					1de93a2d6d | ||
| 
						 | 
					36f9e7c742 | ||
| 
						 | 
					9462763bbb | ||
| 
						 | 
					4ae0880ea6 | ||
| 
						 | 
					6ae2b6c835 | ||
| 
						 | 
					a0f180fd48 | ||
| 
						 | 
					bf1cf89914 | ||
| 
						 | 
					297a047fb4 | ||
| 
						 | 
					52ffc15ffc | ||
| 
						 | 
					e478c9c693 | ||
| 
						 | 
					d004f28074 | ||
| 
						 | 
					bc68ed8b1d | ||
| 
						 | 
					04555ae650 | ||
| 
						 | 
					e8f62085be | ||
| 
						 | 
					f430bffe2a | ||
| 
						 | 
					1f0520634f | ||
| 
						 | 
					902d4c31fb | ||
| 
						 | 
					17364ac09f | ||
| 
						 | 
					0b889f8f81 | ||
| 
						 | 
					40e349ff35 | ||
| 
						 | 
					c943b1b1df | ||
| 
						 | 
					912bc1d4e1 | ||
| 
						 | 
					cacb1533a3 | ||
| 
						 | 
					f0feaca9d7 | ||
| 
						 | 
					b6656f171b | ||
| 
						 | 
					6206ab3931 | ||
| 
						 | 
					c35fc58b1f | ||
| 
						 | 
					deed8abed7 | ||
| 
						 | 
					7151ad23f0 | ||
| 
						 | 
					0166d938af | ||
| 
						 | 
					6194aeddb0 | ||
| 
						 | 
					903dbf2c30 | ||
| 
						 | 
					9380f9ff57 | ||
| 
						 | 
					259ed95486 | ||
| 
						 | 
					2ebc92681e | ||
| 
						 | 
					195a1ffe13 | ||
| 
						 | 
					a8c2978185 | ||
| 
						 | 
					140f97a457 | ||
| 
						 | 
					7f94445a1e | ||
| 
						 | 
					82a89aec65 | ||
| 
						 | 
					7e95110232 | ||
| 
						 | 
					ec4aaaad89 | ||
| 
						 | 
					1b790fde24 | ||
| 
						 | 
					aaccea731e | ||
| 
						 | 
					29e31d7610 | ||
| 
						 | 
					aa51f4a98f | ||
| 
						 | 
					e6ccd12f00 | ||
| 
						 | 
					b134315df1 | ||
| 
						 | 
					7f34dffa13 | ||
| 
						 | 
					fa239e78c9 | ||
| 
						 | 
					707a6c4d6a | ||
| 
						 | 
					e5da303b43 | ||
| 
						 | 
					84ccd66331 | ||
| 
						 | 
					ad8cc2baea | ||
| 
						 | 
					7c4cf70309 | ||
| 
						 | 
					c3211e9b4f | ||
| 
						 | 
					268d94c983 | ||
| 
						 | 
					0bcacbba58 | ||
| 
						 | 
					8cdc26add9 | ||
| 
						 | 
					e0b2238886 | ||
| 
						 | 
					369a2e4029 | ||
| 
						 | 
					c4089e3b51 | ||
| 
						 | 
					9e2e9bc5b8 | ||
| 
						 | 
					a9e44426ed | 
							
								
								
									
										340
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										340
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,340 @@
 | 
			
		||||
		    GNU GENERAL PUBLIC LICENSE
 | 
			
		||||
		       Version 2, June 1991
 | 
			
		||||
 | 
			
		||||
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
 | 
			
		||||
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 Everyone is permitted to copy and distribute verbatim copies
 | 
			
		||||
 of this license document, but changing it is not allowed.
 | 
			
		||||
 | 
			
		||||
			    Preamble
 | 
			
		||||
 | 
			
		||||
  The licenses for most software are designed to take away your
 | 
			
		||||
freedom to share and change it.  By contrast, the GNU General Public
 | 
			
		||||
License is intended to guarantee your freedom to share and change free
 | 
			
		||||
software--to make sure the software is free for all its users.  This
 | 
			
		||||
General Public License applies to most of the Free Software
 | 
			
		||||
Foundation's software and to any other program whose authors commit to
 | 
			
		||||
using it.  (Some other Free Software Foundation software is covered by
 | 
			
		||||
the GNU Library General Public License instead.)  You can apply it to
 | 
			
		||||
your programs, too.
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
 | 
			
		||||
  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 software, or if you modify it.
 | 
			
		||||
 | 
			
		||||
  For example, if you distribute copies of such a program, whether
 | 
			
		||||
gratis or for a fee, you must give the recipients all the rights that
 | 
			
		||||
you have.  You must make sure that they, too, receive or can get the
 | 
			
		||||
source code.  And you must show them these terms so they know their
 | 
			
		||||
rights.
 | 
			
		||||
 | 
			
		||||
  We protect your rights with two steps: (1) copyright the software, and
 | 
			
		||||
(2) offer you this license which gives you legal permission to copy,
 | 
			
		||||
distribute and/or modify the software.
 | 
			
		||||
 | 
			
		||||
  Also, for each author's protection and ours, we want to make certain
 | 
			
		||||
that everyone understands that there is no warranty for this free
 | 
			
		||||
software.  If the software is modified by someone else and passed on, we
 | 
			
		||||
want its recipients to know that what they have is not the original, so
 | 
			
		||||
that any problems introduced by others will not reflect on the original
 | 
			
		||||
authors' reputations.
 | 
			
		||||
 | 
			
		||||
  Finally, any free program is threatened constantly by software
 | 
			
		||||
patents.  We wish to avoid the danger that redistributors of a free
 | 
			
		||||
program will individually obtain patent licenses, in effect making the
 | 
			
		||||
program proprietary.  To prevent this, we have made it clear that any
 | 
			
		||||
patent must be licensed for everyone's free use or not licensed at all.
 | 
			
		||||
 | 
			
		||||
  The precise terms and conditions for copying, distribution and
 | 
			
		||||
modification follow.
 | 
			
		||||
 | 
			
		||||
		    GNU GENERAL PUBLIC LICENSE
 | 
			
		||||
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 | 
			
		||||
 | 
			
		||||
  0. This License applies to any program or other work which contains
 | 
			
		||||
a notice placed by the copyright holder saying it may be distributed
 | 
			
		||||
under the terms of this General Public License.  The "Program", below,
 | 
			
		||||
refers to any such program or work, and a "work based on the Program"
 | 
			
		||||
means either the Program or any derivative work under copyright law:
 | 
			
		||||
that is to say, a work containing the Program or a portion of it,
 | 
			
		||||
either verbatim or with modifications and/or translated into another
 | 
			
		||||
language.  (Hereinafter, translation is included without limitation in
 | 
			
		||||
the term "modification".)  Each licensee is addressed as "you".
 | 
			
		||||
 | 
			
		||||
Activities other than copying, distribution and modification are not
 | 
			
		||||
covered by this License; they are outside its scope.  The act of
 | 
			
		||||
running the Program is not restricted, and the output from the Program
 | 
			
		||||
is covered only if its contents constitute a work based on the
 | 
			
		||||
Program (independent of having been made by running the Program).
 | 
			
		||||
Whether that is true depends on what the Program does.
 | 
			
		||||
 | 
			
		||||
  1. You may copy and distribute verbatim copies of the Program's
 | 
			
		||||
source code as you receive it, in any medium, provided that you
 | 
			
		||||
conspicuously and appropriately publish on each copy an appropriate
 | 
			
		||||
copyright notice and disclaimer of warranty; keep intact all the
 | 
			
		||||
notices that refer to this License and to the absence of any warranty;
 | 
			
		||||
and give any other recipients of the Program a copy of this License
 | 
			
		||||
along with the Program.
 | 
			
		||||
 | 
			
		||||
You may charge a fee for the physical act of transferring a copy, and
 | 
			
		||||
you may at your option offer warranty protection in exchange for a fee.
 | 
			
		||||
 | 
			
		||||
  2. You may modify your copy or copies of the Program or any portion
 | 
			
		||||
of it, thus forming a work based on the Program, and copy and
 | 
			
		||||
distribute such modifications or work under the terms of Section 1
 | 
			
		||||
above, provided that you also meet all of these conditions:
 | 
			
		||||
 | 
			
		||||
    a) You must cause the modified files to carry prominent notices
 | 
			
		||||
    stating that you changed the files and the date of any change.
 | 
			
		||||
 | 
			
		||||
    b) You must cause any work that you distribute or publish, that in
 | 
			
		||||
    whole or in part contains or is derived from the Program or any
 | 
			
		||||
    part thereof, to be licensed as a whole at no charge to all third
 | 
			
		||||
    parties under the terms of this License.
 | 
			
		||||
 | 
			
		||||
    c) If the modified program normally reads commands interactively
 | 
			
		||||
    when run, you must cause it, when started running for such
 | 
			
		||||
    interactive use in the most ordinary way, to print or display an
 | 
			
		||||
    announcement including an appropriate copyright notice and a
 | 
			
		||||
    notice that there is no warranty (or else, saying that you provide
 | 
			
		||||
    a warranty) and that users may redistribute the program under
 | 
			
		||||
    these conditions, and telling the user how to view a copy of this
 | 
			
		||||
    License.  (Exception: if the Program itself is interactive but
 | 
			
		||||
    does not normally print such an announcement, your work based on
 | 
			
		||||
    the Program is not required to print an announcement.)
 | 
			
		||||
 | 
			
		||||
These requirements apply to the modified work as a whole.  If
 | 
			
		||||
identifiable sections of that work are not derived from the Program,
 | 
			
		||||
and can be reasonably considered independent and separate works in
 | 
			
		||||
themselves, then this License, and its terms, do not apply to those
 | 
			
		||||
sections when you distribute them as separate works.  But when you
 | 
			
		||||
distribute the same sections as part of a whole which is a work based
 | 
			
		||||
on the Program, the distribution of the whole must be on the terms of
 | 
			
		||||
this License, whose permissions for other licensees extend to the
 | 
			
		||||
entire whole, and thus to each and every part regardless of who wrote it.
 | 
			
		||||
 | 
			
		||||
Thus, it is not the intent of this section to claim rights or contest
 | 
			
		||||
your rights to work written entirely by you; rather, the intent is to
 | 
			
		||||
exercise the right to control the distribution of derivative or
 | 
			
		||||
collective works based on the Program.
 | 
			
		||||
 | 
			
		||||
In addition, mere aggregation of another work not based on the Program
 | 
			
		||||
with the Program (or with a work based on the Program) on a volume of
 | 
			
		||||
a storage or distribution medium does not bring the other work under
 | 
			
		||||
the scope of this License.
 | 
			
		||||
 | 
			
		||||
  3. You may copy and distribute the Program (or a work based on it,
 | 
			
		||||
under Section 2) in object code or executable form under the terms of
 | 
			
		||||
Sections 1 and 2 above provided that you also do one of the following:
 | 
			
		||||
 | 
			
		||||
    a) Accompany it with the complete corresponding machine-readable
 | 
			
		||||
    source code, which must be distributed under the terms of Sections
 | 
			
		||||
    1 and 2 above on a medium customarily used for software interchange; or,
 | 
			
		||||
 | 
			
		||||
    b) Accompany it with a written offer, valid for at least three
 | 
			
		||||
    years, to give any third party, for a charge no more than your
 | 
			
		||||
    cost of physically performing source distribution, a complete
 | 
			
		||||
    machine-readable copy of the corresponding source code, to be
 | 
			
		||||
    distributed under the terms of Sections 1 and 2 above on a medium
 | 
			
		||||
    customarily used for software interchange; or,
 | 
			
		||||
 | 
			
		||||
    c) Accompany it with the information you received as to the offer
 | 
			
		||||
    to distribute corresponding source code.  (This alternative is
 | 
			
		||||
    allowed only for noncommercial distribution and only if you
 | 
			
		||||
    received the program in object code or executable form with such
 | 
			
		||||
    an offer, in accord with Subsection b above.)
 | 
			
		||||
 | 
			
		||||
The source code for a work means the preferred form of the work for
 | 
			
		||||
making modifications to it.  For an executable work, complete source
 | 
			
		||||
code means all the source code for all modules it contains, plus any
 | 
			
		||||
associated interface definition files, plus the scripts used to
 | 
			
		||||
control compilation and installation of the executable.  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 components (compiler, kernel, and so on) of the
 | 
			
		||||
operating system on which the executable runs, unless that component
 | 
			
		||||
itself accompanies the executable.
 | 
			
		||||
 | 
			
		||||
If distribution of executable or object code is made by offering
 | 
			
		||||
access to copy from a designated place, then offering equivalent
 | 
			
		||||
access to copy the source code from the same place counts as
 | 
			
		||||
distribution of the source code, even though third parties are not
 | 
			
		||||
compelled to copy the source along with the object code.
 | 
			
		||||
 | 
			
		||||
  4. You may not copy, modify, sublicense, or distribute the Program
 | 
			
		||||
except as expressly provided under this License.  Any attempt
 | 
			
		||||
otherwise to copy, modify, sublicense or distribute the Program is
 | 
			
		||||
void, and will automatically terminate your rights under this License.
 | 
			
		||||
However, parties who have received copies, or rights, from you under
 | 
			
		||||
this License will not have their licenses terminated so long as such
 | 
			
		||||
parties remain in full compliance.
 | 
			
		||||
 | 
			
		||||
  5. You are not required to accept this License, since you have not
 | 
			
		||||
signed it.  However, nothing else grants you permission to modify or
 | 
			
		||||
distribute the Program or its derivative works.  These actions are
 | 
			
		||||
prohibited by law if you do not accept this License.  Therefore, by
 | 
			
		||||
modifying or distributing the Program (or any work based on the
 | 
			
		||||
Program), you indicate your acceptance of this License to do so, and
 | 
			
		||||
all its terms and conditions for copying, distributing or modifying
 | 
			
		||||
the Program or works based on it.
 | 
			
		||||
 | 
			
		||||
  6. Each time you redistribute the Program (or any work based on the
 | 
			
		||||
Program), the recipient automatically receives a license from the
 | 
			
		||||
original licensor to copy, distribute or modify the Program 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
 | 
			
		||||
this License.
 | 
			
		||||
 | 
			
		||||
  7. If, as a consequence of a court judgment or allegation of patent
 | 
			
		||||
infringement or for any other reason (not limited to patent issues),
 | 
			
		||||
conditions are imposed on you (whether by court order, agreement or
 | 
			
		||||
otherwise) that contradict the conditions of this License, they do not
 | 
			
		||||
excuse you from the conditions of this License.  If you cannot
 | 
			
		||||
distribute so as to satisfy simultaneously your obligations under this
 | 
			
		||||
License and any other pertinent obligations, then as a consequence you
 | 
			
		||||
may not distribute the Program at all.  For example, if a patent
 | 
			
		||||
license would not permit royalty-free redistribution of the Program by
 | 
			
		||||
all those who receive copies directly or indirectly through you, then
 | 
			
		||||
the only way you could satisfy both it and this License would be to
 | 
			
		||||
refrain entirely from distribution of the Program.
 | 
			
		||||
 | 
			
		||||
If any portion of this section is held invalid or unenforceable under
 | 
			
		||||
any particular circumstance, the balance of the section is intended to
 | 
			
		||||
apply and the section as a whole is intended to apply in other
 | 
			
		||||
circumstances.
 | 
			
		||||
 | 
			
		||||
It is not the purpose of this section to induce you to infringe any
 | 
			
		||||
patents or other property right claims or to contest validity of any
 | 
			
		||||
such claims; this section has the sole purpose of protecting the
 | 
			
		||||
integrity of the free software distribution system, which is
 | 
			
		||||
implemented by public license practices.  Many people have made
 | 
			
		||||
generous contributions to the wide range of software distributed
 | 
			
		||||
through that system in reliance on consistent application of that
 | 
			
		||||
system; it is up to the author/donor to decide if he or she is willing
 | 
			
		||||
to distribute software through any other system and a licensee cannot
 | 
			
		||||
impose that choice.
 | 
			
		||||
 | 
			
		||||
This section is intended to make thoroughly clear what is believed to
 | 
			
		||||
be a consequence of the rest of this License.
 | 
			
		||||
 | 
			
		||||
  8. If the distribution and/or use of the Program is restricted in
 | 
			
		||||
certain countries either by patents or by copyrighted interfaces, the
 | 
			
		||||
original copyright holder who places the Program under this License
 | 
			
		||||
may add an explicit geographical distribution limitation excluding
 | 
			
		||||
those countries, so that distribution is permitted only in or among
 | 
			
		||||
countries not thus excluded.  In such case, this License incorporates
 | 
			
		||||
the limitation as if written in the body of this License.
 | 
			
		||||
 | 
			
		||||
  9. The Free Software Foundation may publish revised and/or new versions
 | 
			
		||||
of the 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.
 | 
			
		||||
 | 
			
		||||
Each version is given a distinguishing version number.  If the Program
 | 
			
		||||
specifies a version number of this License which applies to it and "any
 | 
			
		||||
later version", you have the option of following the terms and conditions
 | 
			
		||||
either of that version or of any later version published by the Free
 | 
			
		||||
Software Foundation.  If the Program does not specify a version number of
 | 
			
		||||
this License, you may choose any version ever published by the Free Software
 | 
			
		||||
Foundation.
 | 
			
		||||
 | 
			
		||||
  10. If you wish to incorporate parts of the Program into other free
 | 
			
		||||
programs whose distribution conditions are different, write to the author
 | 
			
		||||
to ask for permission.  For software which is copyrighted by the Free
 | 
			
		||||
Software Foundation, write to the Free Software Foundation; we sometimes
 | 
			
		||||
make exceptions for this.  Our decision will be guided by the two goals
 | 
			
		||||
of preserving the free status of all derivatives of our free software and
 | 
			
		||||
of promoting the sharing and reuse of software generally.
 | 
			
		||||
 | 
			
		||||
			    NO WARRANTY
 | 
			
		||||
 | 
			
		||||
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 | 
			
		||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
 | 
			
		||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 | 
			
		||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 | 
			
		||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 | 
			
		||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 | 
			
		||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 | 
			
		||||
REPAIR OR CORRECTION.
 | 
			
		||||
 | 
			
		||||
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
			
		||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 | 
			
		||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 | 
			
		||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 | 
			
		||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 | 
			
		||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 | 
			
		||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 | 
			
		||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 | 
			
		||||
POSSIBILITY OF SUCH DAMAGES.
 | 
			
		||||
 | 
			
		||||
		     END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
	    How to Apply These Terms to Your New Programs
 | 
			
		||||
 | 
			
		||||
  If you develop a new program, and you want it to be of the greatest
 | 
			
		||||
possible use to the public, the best way to achieve this is to make it
 | 
			
		||||
free software which everyone can redistribute and change under these terms.
 | 
			
		||||
 | 
			
		||||
  To do so, attach the following notices to the program.  It is safest
 | 
			
		||||
to attach them to the start of each source file to most effectively
 | 
			
		||||
convey the exclusion of warranty; and each file should have at least
 | 
			
		||||
the "copyright" line and a pointer to where the full notice is found.
 | 
			
		||||
 | 
			
		||||
    <one line to give the program's name and a brief idea of what it does.>
 | 
			
		||||
    Copyright (C) <year>  <name of author>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Also add information on how to contact you by electronic and paper mail.
 | 
			
		||||
 | 
			
		||||
If the program is interactive, make it output a short notice like this
 | 
			
		||||
when it starts in an interactive mode:
 | 
			
		||||
 | 
			
		||||
    Gnomovision version 69, Copyright (C) year  name of author
 | 
			
		||||
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 | 
			
		||||
    This is free software, and you are welcome to redistribute it
 | 
			
		||||
    under certain conditions; type `show c' for details.
 | 
			
		||||
 | 
			
		||||
The hypothetical commands `show w' and `show c' should show the appropriate
 | 
			
		||||
parts of the General Public License.  Of course, the commands you use may
 | 
			
		||||
be called something other than `show w' and `show c'; they could even be
 | 
			
		||||
mouse-clicks or menu items--whatever suits your program.
 | 
			
		||||
 | 
			
		||||
You should also get your employer (if you work as a programmer) or your
 | 
			
		||||
school, if any, to sign a "copyright disclaimer" for the program, if
 | 
			
		||||
necessary.  Here is a sample; alter the names:
 | 
			
		||||
 | 
			
		||||
  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 | 
			
		||||
  `Gnomovision' (which makes passes at compilers) written by James Hacker.
 | 
			
		||||
 | 
			
		||||
  <signature of Ty Coon>, 1 April 1989
 | 
			
		||||
  Ty Coon, President of Vice
 | 
			
		||||
 | 
			
		||||
This General Public License does not permit incorporating your program into
 | 
			
		||||
proprietary programs.  If your program is a subroutine library, you may
 | 
			
		||||
consider it more useful to permit linking proprietary applications with the
 | 
			
		||||
library.  If this is what you want to do, use the GNU Library General
 | 
			
		||||
Public License instead of this License.
 | 
			
		||||
							
								
								
									
										504
									
								
								COPYING.LIB
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										504
									
								
								COPYING.LIB
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,504 @@
 | 
			
		||||
		  GNU LESSER GENERAL PUBLIC LICENSE
 | 
			
		||||
		       Version 2.1, February 1999
 | 
			
		||||
 | 
			
		||||
 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 Lesser GPL.  It also counts
 | 
			
		||||
 as the successor of the GNU Library Public License, version 2, hence
 | 
			
		||||
 the version number 2.1.]
 | 
			
		||||
 | 
			
		||||
			    Preamble
 | 
			
		||||
 | 
			
		||||
  The licenses for most software are designed to take away your
 | 
			
		||||
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 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 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
 | 
			
		||||
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 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.
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
 | 
			
		||||
  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, 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.  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.
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
 | 
			
		||||
  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, whereas the latter must
 | 
			
		||||
be combined with the library in order to run.
 | 
			
		||||
 | 
			
		||||
		  GNU LESSER GENERAL PUBLIC LICENSE
 | 
			
		||||
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
(which use some of those functions and data) to form executables.
 | 
			
		||||
 | 
			
		||||
  The "Library", below, refers to any such software library or work
 | 
			
		||||
which has been distributed under these terms.  A "work based on the
 | 
			
		||||
Library" means either the Library or any derivative work under
 | 
			
		||||
copyright law: that is to say, a work containing the Library or a
 | 
			
		||||
portion of it, either verbatim or with modifications and/or translated
 | 
			
		||||
straightforwardly into another language.  (Hereinafter, translation is
 | 
			
		||||
included without limitation in the term "modification".)
 | 
			
		||||
 | 
			
		||||
  "Source code" for a work means the preferred form of the work for
 | 
			
		||||
making modifications to it.  For a library, complete source code means
 | 
			
		||||
all the source code for all modules it contains, plus any associated
 | 
			
		||||
interface definition files, plus the scripts used to control compilation
 | 
			
		||||
and installation of the library.
 | 
			
		||||
 | 
			
		||||
  Activities other than copying, distribution and modification are not
 | 
			
		||||
covered by this License; they are outside its scope.  The act of
 | 
			
		||||
running a program using the Library is not restricted, and output from
 | 
			
		||||
such a program is covered only if its contents constitute a work based
 | 
			
		||||
on the Library (independent of the use of the Library in a tool for
 | 
			
		||||
writing it).  Whether that is true depends on what the Library does
 | 
			
		||||
and what the program that uses the Library does.
 | 
			
		||||
  
 | 
			
		||||
  1. You may copy and distribute verbatim copies of the Library's
 | 
			
		||||
complete source code as you receive it, in any medium, provided that
 | 
			
		||||
you conspicuously and appropriately publish on each copy an
 | 
			
		||||
appropriate copyright notice and disclaimer of warranty; keep intact
 | 
			
		||||
all the notices that refer to this License and to the absence of any
 | 
			
		||||
warranty; and distribute a copy of this License along with the
 | 
			
		||||
Library.
 | 
			
		||||
 | 
			
		||||
  You may charge a fee for the physical act of transferring a copy,
 | 
			
		||||
and you may at your option offer warranty protection in exchange for a
 | 
			
		||||
fee.
 | 
			
		||||
 | 
			
		||||
  2. You may modify your copy or copies of the Library or any portion
 | 
			
		||||
of it, thus forming a work based on the Library, and copy and
 | 
			
		||||
distribute such modifications or work under the terms of Section 1
 | 
			
		||||
above, provided that you also meet all of these conditions:
 | 
			
		||||
 | 
			
		||||
    a) The modified work must itself be a software library.
 | 
			
		||||
 | 
			
		||||
    b) You must cause the files modified to carry prominent notices
 | 
			
		||||
    stating that you changed the files and the date of any change.
 | 
			
		||||
 | 
			
		||||
    c) You must cause the whole of the work to be licensed at no
 | 
			
		||||
    charge to all third parties under the terms of this License.
 | 
			
		||||
 | 
			
		||||
    d) If a facility in the modified Library refers to a function or a
 | 
			
		||||
    table of data to be supplied by an application program that uses
 | 
			
		||||
    the facility, other than as an argument passed when the facility
 | 
			
		||||
    is invoked, then you must make a good faith effort to ensure that,
 | 
			
		||||
    in the event an application does not supply such function or
 | 
			
		||||
    table, the facility still operates, and performs whatever part of
 | 
			
		||||
    its purpose remains meaningful.
 | 
			
		||||
 | 
			
		||||
    (For example, a function in a library to compute square roots has
 | 
			
		||||
    a purpose that is entirely well-defined independent of the
 | 
			
		||||
    application.  Therefore, Subsection 2d requires that any
 | 
			
		||||
    application-supplied function or table used by this function must
 | 
			
		||||
    be optional: if the application does not supply it, the square
 | 
			
		||||
    root function must still compute square roots.)
 | 
			
		||||
 | 
			
		||||
These requirements apply to the modified work as a whole.  If
 | 
			
		||||
identifiable sections of that work are not derived from the Library,
 | 
			
		||||
and can be reasonably considered independent and separate works in
 | 
			
		||||
themselves, then this License, and its terms, do not apply to those
 | 
			
		||||
sections when you distribute them as separate works.  But when you
 | 
			
		||||
distribute the same sections as part of a whole which is a work based
 | 
			
		||||
on the Library, the distribution of the whole must be on the terms of
 | 
			
		||||
this License, whose permissions for other licensees extend to the
 | 
			
		||||
entire whole, and thus to each and every part regardless of who wrote
 | 
			
		||||
it.
 | 
			
		||||
 | 
			
		||||
Thus, it is not the intent of this section to claim rights or contest
 | 
			
		||||
your rights to work written entirely by you; rather, the intent is to
 | 
			
		||||
exercise the right to control the distribution of derivative or
 | 
			
		||||
collective works based on the Library.
 | 
			
		||||
 | 
			
		||||
In addition, mere aggregation of another work not based on the Library
 | 
			
		||||
with the Library (or with a work based on the Library) on a volume of
 | 
			
		||||
a storage or distribution medium does not bring the other work under
 | 
			
		||||
the scope of this License.
 | 
			
		||||
 | 
			
		||||
  3. You may opt to apply the terms of the ordinary GNU General Public
 | 
			
		||||
License instead of this License to a given copy of the Library.  To do
 | 
			
		||||
this, you must alter all the notices that refer to this License, so
 | 
			
		||||
that they refer to the ordinary GNU General Public License, version 2,
 | 
			
		||||
instead of to this License.  (If a newer version than version 2 of the
 | 
			
		||||
ordinary GNU General Public License has appeared, then you can specify
 | 
			
		||||
that version instead if you wish.)  Do not make any other change in
 | 
			
		||||
these notices.
 | 
			
		||||
 | 
			
		||||
  Once this change is made in a given copy, it is irreversible for
 | 
			
		||||
that copy, so the ordinary GNU General Public License applies to all
 | 
			
		||||
subsequent copies and derivative works made from that copy.
 | 
			
		||||
 | 
			
		||||
  This option is useful when you wish to copy part of the code of
 | 
			
		||||
the Library into a program that is not a library.
 | 
			
		||||
 | 
			
		||||
  4. You may copy and distribute the Library (or a portion or
 | 
			
		||||
derivative of it, under Section 2) in object code or executable form
 | 
			
		||||
under the terms of Sections 1 and 2 above provided that you accompany
 | 
			
		||||
it with the complete corresponding machine-readable source code, which
 | 
			
		||||
must be distributed under the terms of Sections 1 and 2 above on a
 | 
			
		||||
medium customarily used for software interchange.
 | 
			
		||||
 | 
			
		||||
  If distribution of object code is made by offering access to copy
 | 
			
		||||
from a designated place, then offering equivalent access to copy the
 | 
			
		||||
source code from the same place satisfies the requirement to
 | 
			
		||||
distribute the source code, even though third parties are not
 | 
			
		||||
compelled to copy the source along with the object code.
 | 
			
		||||
 | 
			
		||||
  5. A program that contains no derivative of any portion of the
 | 
			
		||||
Library, but is designed to work with the Library by being compiled or
 | 
			
		||||
linked with it, is called a "work that uses the Library".  Such a
 | 
			
		||||
work, in isolation, is not a derivative work of the Library, and
 | 
			
		||||
therefore falls outside the scope of this License.
 | 
			
		||||
 | 
			
		||||
  However, linking a "work that uses the Library" with the Library
 | 
			
		||||
creates an executable that is a derivative of the Library (because it
 | 
			
		||||
contains portions of the Library), rather than a "work that uses the
 | 
			
		||||
library".  The executable is therefore covered by this License.
 | 
			
		||||
Section 6 states terms for distribution of such executables.
 | 
			
		||||
 | 
			
		||||
  When a "work that uses the Library" uses material from a header file
 | 
			
		||||
that is part of the Library, the object code for the work may be a
 | 
			
		||||
derivative work of the Library even though the source code is not.
 | 
			
		||||
Whether this is true is especially significant if the work can be
 | 
			
		||||
linked without the Library, or if the work is itself a library.  The
 | 
			
		||||
threshold for this to be true is not precisely defined by law.
 | 
			
		||||
 | 
			
		||||
  If such an object file uses only numerical parameters, data
 | 
			
		||||
structure layouts and accessors, and small macros and small inline
 | 
			
		||||
functions (ten lines or less in length), then the use of the object
 | 
			
		||||
file is unrestricted, regardless of whether it is legally a derivative
 | 
			
		||||
work.  (Executables containing this object code plus portions of the
 | 
			
		||||
Library will still fall under Section 6.)
 | 
			
		||||
 | 
			
		||||
  Otherwise, if the work is a derivative of the Library, you may
 | 
			
		||||
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 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
 | 
			
		||||
modification of the work for the customer's own use and reverse
 | 
			
		||||
engineering for debugging such modifications.
 | 
			
		||||
 | 
			
		||||
  You must give prominent notice with each copy of the work that the
 | 
			
		||||
Library is used in it and that the Library and its use are covered by
 | 
			
		||||
this License.  You must supply a copy of this License.  If the work
 | 
			
		||||
during execution displays copyright notices, you must include the
 | 
			
		||||
copyright notice for the Library among them, as well as a reference
 | 
			
		||||
directing the user to the copy of this License.  Also, you must do one
 | 
			
		||||
of these things:
 | 
			
		||||
 | 
			
		||||
    a) Accompany the work with the complete corresponding
 | 
			
		||||
    machine-readable source code for the Library including whatever
 | 
			
		||||
    changes were used in the work (which must be distributed under
 | 
			
		||||
    Sections 1 and 2 above); and, if the work is an executable linked
 | 
			
		||||
    with the Library, with the complete machine-readable "work that
 | 
			
		||||
    uses the Library", as object code and/or source code, so that the
 | 
			
		||||
    user can modify the Library and then relink to produce a modified
 | 
			
		||||
    executable containing the modified Library.  (It is understood
 | 
			
		||||
    that the user who changes the contents of definitions files in the
 | 
			
		||||
    Library will not necessarily be able to recompile the application
 | 
			
		||||
    to use the modified definitions.)
 | 
			
		||||
 | 
			
		||||
    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.
 | 
			
		||||
 | 
			
		||||
    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.
 | 
			
		||||
 | 
			
		||||
    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 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.
 | 
			
		||||
 | 
			
		||||
  It may happen that this requirement contradicts the license
 | 
			
		||||
restrictions of other proprietary libraries that do not normally
 | 
			
		||||
accompany the operating system.  Such a contradiction means you cannot
 | 
			
		||||
use both them and the Library together in an executable that you
 | 
			
		||||
distribute.
 | 
			
		||||
 | 
			
		||||
  7. You may place library facilities that are a work based on the
 | 
			
		||||
Library side-by-side in a single library together with other library
 | 
			
		||||
facilities not covered by this License, and distribute such a combined
 | 
			
		||||
library, provided that the separate distribution of the work based on
 | 
			
		||||
the Library and of the other library facilities is otherwise
 | 
			
		||||
permitted, and provided that you do these two things:
 | 
			
		||||
 | 
			
		||||
    a) Accompany the combined library with a copy of the same work
 | 
			
		||||
    based on the Library, uncombined with any other library
 | 
			
		||||
    facilities.  This must be distributed under the terms of the
 | 
			
		||||
    Sections above.
 | 
			
		||||
 | 
			
		||||
    b) Give prominent notice with the combined library of the fact
 | 
			
		||||
    that part of it is a work based on the Library, and explaining
 | 
			
		||||
    where to find the accompanying uncombined form of the same work.
 | 
			
		||||
 | 
			
		||||
  8. You may not copy, modify, sublicense, link with, or distribute
 | 
			
		||||
the Library except as expressly provided under this License.  Any
 | 
			
		||||
attempt otherwise to copy, modify, sublicense, link with, or
 | 
			
		||||
distribute the Library is void, and will automatically terminate your
 | 
			
		||||
rights under this License.  However, parties who have received copies,
 | 
			
		||||
or rights, from you under this License will not have their licenses
 | 
			
		||||
terminated so long as such parties remain in full compliance.
 | 
			
		||||
 | 
			
		||||
  9. You are not required to accept this License, since you have not
 | 
			
		||||
signed it.  However, nothing else grants you permission to modify or
 | 
			
		||||
distribute the Library or its derivative works.  These actions are
 | 
			
		||||
prohibited by law if you do not accept this License.  Therefore, by
 | 
			
		||||
modifying or distributing the Library (or any work based on the
 | 
			
		||||
Library), you indicate your acceptance of this License to do so, and
 | 
			
		||||
all its terms and conditions for copying, distributing or modifying
 | 
			
		||||
the Library or works based on it.
 | 
			
		||||
 | 
			
		||||
  10. Each time you redistribute the Library (or any work based on the
 | 
			
		||||
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 with
 | 
			
		||||
this License.
 | 
			
		||||
 | 
			
		||||
  11. If, as a consequence of a court judgment or allegation of patent
 | 
			
		||||
infringement or for any other reason (not limited to patent issues),
 | 
			
		||||
conditions are imposed on you (whether by court order, agreement or
 | 
			
		||||
otherwise) that contradict the conditions of this License, they do not
 | 
			
		||||
excuse you from the conditions of this License.  If you cannot
 | 
			
		||||
distribute so as to satisfy simultaneously your obligations under this
 | 
			
		||||
License and any other pertinent obligations, then as a consequence you
 | 
			
		||||
may not distribute the Library at all.  For example, if a patent
 | 
			
		||||
license would not permit royalty-free redistribution of the Library by
 | 
			
		||||
all those who receive copies directly or indirectly through you, then
 | 
			
		||||
the only way you could satisfy both it and this License would be to
 | 
			
		||||
refrain entirely from distribution of the Library.
 | 
			
		||||
 | 
			
		||||
If any portion of this section is held invalid or unenforceable under any
 | 
			
		||||
particular circumstance, the balance of the section is intended to apply,
 | 
			
		||||
and the section as a whole is intended to apply in other circumstances.
 | 
			
		||||
 | 
			
		||||
It is not the purpose of this section to induce you to infringe any
 | 
			
		||||
patents or other property right claims or to contest validity of any
 | 
			
		||||
such claims; this section has the sole purpose of protecting the
 | 
			
		||||
integrity of the free software distribution system which is
 | 
			
		||||
implemented by public license practices.  Many people have made
 | 
			
		||||
generous contributions to the wide range of software distributed
 | 
			
		||||
through that system in reliance on consistent application of that
 | 
			
		||||
system; it is up to the author/donor to decide if he or she is willing
 | 
			
		||||
to distribute software through any other system and a licensee cannot
 | 
			
		||||
impose that choice.
 | 
			
		||||
 | 
			
		||||
This section is intended to make thoroughly clear what is believed to
 | 
			
		||||
be a consequence of the rest of this License.
 | 
			
		||||
 | 
			
		||||
  12. If the distribution and/or use of the Library is restricted in
 | 
			
		||||
certain countries either by patents or by copyrighted interfaces, the
 | 
			
		||||
original copyright holder who places the Library under this License may add
 | 
			
		||||
an explicit geographical distribution limitation excluding those countries,
 | 
			
		||||
so that distribution is permitted only in or among countries not thus
 | 
			
		||||
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 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.
 | 
			
		||||
 | 
			
		||||
Each version is given a distinguishing version number.  If the Library
 | 
			
		||||
specifies a version number of this License which applies to it and
 | 
			
		||||
"any later version", you have the option of following the terms and
 | 
			
		||||
conditions either of that version or of any later version published by
 | 
			
		||||
the Free Software Foundation.  If the Library does not specify a
 | 
			
		||||
license version number, you may choose any version ever published by
 | 
			
		||||
the Free Software Foundation.
 | 
			
		||||
 | 
			
		||||
  14. If you wish to incorporate parts of the Library into other free
 | 
			
		||||
programs whose distribution conditions are incompatible with these,
 | 
			
		||||
write to the author to ask for permission.  For software which is
 | 
			
		||||
copyrighted by the Free Software Foundation, write to the Free
 | 
			
		||||
Software Foundation; we sometimes make exceptions for this.  Our
 | 
			
		||||
decision will be guided by the two goals of preserving the free status
 | 
			
		||||
of all derivatives of our free software and of promoting the sharing
 | 
			
		||||
and reuse of software generally.
 | 
			
		||||
 | 
			
		||||
			    NO WARRANTY
 | 
			
		||||
 | 
			
		||||
  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
 | 
			
		||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
 | 
			
		||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
 | 
			
		||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
 | 
			
		||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
			
		||||
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
 | 
			
		||||
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
 | 
			
		||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 | 
			
		||||
 | 
			
		||||
  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
 | 
			
		||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
 | 
			
		||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
 | 
			
		||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
 | 
			
		||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
 | 
			
		||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
 | 
			
		||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
 | 
			
		||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
 | 
			
		||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 | 
			
		||||
DAMAGES.
 | 
			
		||||
 | 
			
		||||
		     END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
           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
 | 
			
		||||
everyone can redistribute and change.  You can do so by permitting
 | 
			
		||||
redistribution under these terms (or, alternatively, under the terms of the
 | 
			
		||||
ordinary General Public License).
 | 
			
		||||
 | 
			
		||||
  To apply these terms, attach the following notices to the library.  It is
 | 
			
		||||
safest to attach them to the start of each source file to most effectively
 | 
			
		||||
convey the exclusion of warranty; and each file should have at least the
 | 
			
		||||
"copyright" line and a pointer to where the full notice is found.
 | 
			
		||||
 | 
			
		||||
    <one line to give the library's name and a brief idea of what it does.>
 | 
			
		||||
    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 Lesser General Public
 | 
			
		||||
    License as published by the Free Software Foundation; either
 | 
			
		||||
    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
 | 
			
		||||
    Lesser General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    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.
 | 
			
		||||
 | 
			
		||||
You should also get your employer (if you work as a programmer) or your
 | 
			
		||||
school, if any, to sign a "copyright disclaimer" for the library, if
 | 
			
		||||
necessary.  Here is a sample; alter the names:
 | 
			
		||||
 | 
			
		||||
  Yoyodyne, Inc., hereby disclaims all copyright interest in the
 | 
			
		||||
  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
 | 
			
		||||
 | 
			
		||||
  <signature of Ty Coon>, 1 April 1990
 | 
			
		||||
  Ty Coon, President of Vice
 | 
			
		||||
 | 
			
		||||
That's all there is to it!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								INSTALL
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								INSTALL
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
Installation
 | 
			
		||||
============
 | 
			
		||||
 | 
			
		||||
1) Generate custom makefiles.
 | 
			
		||||
 | 
			
		||||
   Run the 'configure' script from the top directory.
 | 
			
		||||
 | 
			
		||||
   If you don't want to include the LVM1 backwards-compatibility code use:
 | 
			
		||||
     ./configure --with-lvm1=none 
 | 
			
		||||
 | 
			
		||||
   To separate the LVM1 support into a shared library loaded by lvm.conf use:
 | 
			
		||||
     ./configure --with-lvm1=shared
 | 
			
		||||
 | 
			
		||||
   Use ./configure --help to see other options.
 | 
			
		||||
 | 
			
		||||
2) Build and install.
 | 
			
		||||
 | 
			
		||||
   Run 'make' from the top directory to build everything you configured.
 | 
			
		||||
   Run 'make install' to build and install everything you configured.
 | 
			
		||||
 | 
			
		||||
   If you only want the device-mapper libraries and tools use
 | 
			
		||||
   'make device-mapper' or 'make install_device-mapper'.
 | 
			
		||||
 | 
			
		||||
3) If using LVM2, create a configuration file.
 | 
			
		||||
 | 
			
		||||
   The tools will work fine without a configuration file being
 | 
			
		||||
   present, but you ought to review the example file in doc/example.conf.
 | 
			
		||||
 | 
			
		||||
Please also refer to the WHATS_NEW file and the manual pages for the 
 | 
			
		||||
individual commands.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										177
									
								
								Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,177 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2010 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
SUBDIRS = doc include man scripts
 | 
			
		||||
 | 
			
		||||
ifeq ("@UDEV_RULES@", "yes")
 | 
			
		||||
  SUBDIRS += udev
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
  SUBDIRS += po
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
SUBDIRS += lib tools daemons libdm
 | 
			
		||||
 | 
			
		||||
ifeq ("@APPLIB@", "yes")
 | 
			
		||||
  SUBDIRS += liblvm
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@BUILD_LVMETAD@", "yes")
 | 
			
		||||
  SUBDIRS += libdaemon
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@VERITYSETUP@", "yes")
 | 
			
		||||
  SUBDIRS += verity
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# FIXME Should use intermediate Makefiles here!
 | 
			
		||||
ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
  SUBDIRS = doc include man scripts \
 | 
			
		||||
    libdaemon lib tools daemons libdm \
 | 
			
		||||
    udev po liblvm test \
 | 
			
		||||
    unit-tests/datastruct unit-tests/mm unit-tests/regex verity
 | 
			
		||||
endif
 | 
			
		||||
DISTCLEAN_DIRS += lcov_reports*
 | 
			
		||||
DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
 | 
			
		||||
 | 
			
		||||
include make.tmpl
 | 
			
		||||
 | 
			
		||||
libdm: include
 | 
			
		||||
lib: libdm libdaemon
 | 
			
		||||
liblvm: lib
 | 
			
		||||
daemons: lib libdaemon tools
 | 
			
		||||
tools: lib libdaemon device-mapper
 | 
			
		||||
verity: libdm
 | 
			
		||||
po: tools daemons
 | 
			
		||||
 | 
			
		||||
lib.device-mapper: include.device-mapper
 | 
			
		||||
libdm.device-mapper: include.device-mapper
 | 
			
		||||
liblvm.device-mapper: include.device-mapper
 | 
			
		||||
daemons.device-mapper: libdm.device-mapper
 | 
			
		||||
tools.device-mapper: libdm.device-mapper
 | 
			
		||||
device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
 | 
			
		||||
 | 
			
		||||
ifeq ("@INTL@", "yes")
 | 
			
		||||
lib.pofile: include.pofile
 | 
			
		||||
tools.pofile: lib.pofile
 | 
			
		||||
daemons.pofile: lib.pofile
 | 
			
		||||
po.pofile: tools.pofile daemons.pofile
 | 
			
		||||
pofile: po.pofile
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("$(CFLOW_CMD)", "")
 | 
			
		||||
tools.cflow: libdm.cflow lib.cflow
 | 
			
		||||
daemons.cflow: tools.cflow
 | 
			
		||||
cflow: include.cflow
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@CSCOPE_CMD@", "")
 | 
			
		||||
cscope.out:
 | 
			
		||||
	@CSCOPE_CMD@ -b -R -s$(top_srcdir)
 | 
			
		||||
all: cscope.out
 | 
			
		||||
endif
 | 
			
		||||
DISTCLEAN_TARGETS += cscope.out
 | 
			
		||||
 | 
			
		||||
check check_cluster check_local check_lvmetad unit: all
 | 
			
		||||
	$(MAKE) -C test $(@)
 | 
			
		||||
 | 
			
		||||
install_system_dirs:
 | 
			
		||||
	$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
 | 
			
		||||
	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
 | 
			
		||||
	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR)
 | 
			
		||||
	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR)
 | 
			
		||||
	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR)
 | 
			
		||||
	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
 | 
			
		||||
	$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
 | 
			
		||||
 | 
			
		||||
install_initscripts: 
 | 
			
		||||
	$(MAKE) -C scripts install_initscripts
 | 
			
		||||
 | 
			
		||||
install_systemd_units:
 | 
			
		||||
	$(MAKE) -C scripts install_systemd_units
 | 
			
		||||
 | 
			
		||||
install_tmpfiles_configuration:
 | 
			
		||||
	$(MAKE) -C scripts install_tmpfiles_configuration
 | 
			
		||||
 | 
			
		||||
install_verity:
 | 
			
		||||
	$(MAKE) -C verity install_verity
 | 
			
		||||
	$(MAKE) -C man install_verity
 | 
			
		||||
 | 
			
		||||
LCOV_TRACES = libdm.info lib.info tools.info \
 | 
			
		||||
	daemons/dmeventd.info daemons/clvmd.info
 | 
			
		||||
CLEAN_TARGETS += $(LCOV_TRACES)
 | 
			
		||||
 | 
			
		||||
ifneq ("$(LCOV)", "")
 | 
			
		||||
.PHONY: lcov-reset lcov lcov-dated $(LCOV_TRACES)
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKECMDGOALS),lcov-dated)
 | 
			
		||||
LCOV_REPORTS_DIR := lcov_reports-$(shell date +%Y%m%d%k%M%S)
 | 
			
		||||
lcov-dated: lcov
 | 
			
		||||
else
 | 
			
		||||
LCOV_REPORTS_DIR := lcov_reports
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
lcov-reset:
 | 
			
		||||
	$(LCOV) --zerocounters $(addprefix -d , $(basename $(LCOV_TRACES)))
 | 
			
		||||
 | 
			
		||||
# maybe use subdirs processing to create tracefiles...
 | 
			
		||||
$(LCOV_TRACES):
 | 
			
		||||
	$(LCOV) -b $(basename $@) -d $(basename $@) \
 | 
			
		||||
		--ignore-errors source -c -o - | $(SED) \
 | 
			
		||||
		-e "s/\(dmeventd_lvm.[ch]\)/plugins\/lvm2\/\1/" \
 | 
			
		||||
		-e "s/dmeventd_\(mirror\|snapshot\|thin\|raid\)\.c/plugins\/\1\/dmeventd_\1\.c/" \
 | 
			
		||||
		>$@
 | 
			
		||||
 | 
			
		||||
ifneq ("$(GENHTML)", "")
 | 
			
		||||
lcov: $(LCOV_TRACES)
 | 
			
		||||
	$(RM) -r $(LCOV_REPORTS_DIR)
 | 
			
		||||
	$(MKDIR_P) $(LCOV_REPORTS_DIR)
 | 
			
		||||
	for i in $(LCOV_TRACES); do \
 | 
			
		||||
		test -s $$i && lc="$$lc $$i"; \
 | 
			
		||||
	done; \
 | 
			
		||||
	test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
 | 
			
		||||
		-o $(LCOV_REPORTS_DIR) $$lc
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("$(TESTING)", "yes")
 | 
			
		||||
# testing and report generation
 | 
			
		||||
RUBY=ruby1.9 -Ireport-generators/lib -Ireport-generators/test
 | 
			
		||||
 | 
			
		||||
.PHONEY: unit-test ruby-test test-programs
 | 
			
		||||
 | 
			
		||||
# FIXME: put dependencies on libdm and liblvm
 | 
			
		||||
# FIXME: Should be handled by Makefiles in subdirs, not here at top level.
 | 
			
		||||
test-programs:
 | 
			
		||||
	cd unit-tests/regex && $(MAKE)
 | 
			
		||||
	cd unit-tests/datastruct && $(MAKE)
 | 
			
		||||
	cd unit-tests/mm && $(MAKE)
 | 
			
		||||
 | 
			
		||||
unit-test: test-programs
 | 
			
		||||
	$(RUBY) report-generators/unit_test.rb $(shell find . -name TESTS)
 | 
			
		||||
	$(RUBY) report-generators/title_page.rb
 | 
			
		||||
 | 
			
		||||
memcheck: test-programs
 | 
			
		||||
	$(RUBY) report-generators/memcheck.rb $(shell find . -name TESTS)
 | 
			
		||||
	$(RUBY) report-generators/title_page.rb
 | 
			
		||||
 | 
			
		||||
ruby-test:
 | 
			
		||||
	$(RUBY) report-generators/test/ts.rb
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										40
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								README
									
									
									
									
									
								
							@@ -1,2 +1,38 @@
 | 
			
		||||
This is pretty much empty so far...if you can't see subdirectories,
 | 
			
		||||
try 'cvs -f update'
 | 
			
		||||
NEWS
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
On 7th June 2012, we froze this copy of the source code and moved it to
 | 
			
		||||
fedorahosted.org:
 | 
			
		||||
 | 
			
		||||
  http://git.fedorahosted.org/git/lvm2.git
 | 
			
		||||
  git clone git://git.fedorahosted.org/git/lvm2.git
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
This tree contains the LVM2 and device-mapper tools and libraries.
 | 
			
		||||
 | 
			
		||||
For more information about LVM2 read the changelog in the WHATS_NEW file.
 | 
			
		||||
Installation instructions are in INSTALL.
 | 
			
		||||
 | 
			
		||||
There is no warranty - see COPYING and COPYING.LIB.
 | 
			
		||||
 | 
			
		||||
Tarballs are available from:
 | 
			
		||||
  ftp://sources.redhat.com/pub/lvm2/
 | 
			
		||||
 | 
			
		||||
To access the CVS tree use:
 | 
			
		||||
  cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
 | 
			
		||||
  CVS password: cvs
 | 
			
		||||
  cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 co LVM2
 | 
			
		||||
 | 
			
		||||
Mailing list for general discussion related to LVM2:
 | 
			
		||||
  linux-lvm@redhat.com
 | 
			
		||||
  Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
 | 
			
		||||
 | 
			
		||||
Mailing list for LVM2 development, patches and commits:
 | 
			
		||||
  lvm-devel@redhat.com
 | 
			
		||||
  Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
 | 
			
		||||
 | 
			
		||||
Mailing list for device-mapper development, including kernel patches
 | 
			
		||||
and multipath-tools:
 | 
			
		||||
  dm-devel@redhat.com
 | 
			
		||||
  Subscribe from https://www.redhat.com/mailman/listinfo/dm-devel
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								VERSION_DM
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								VERSION_DM
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
1.02.75-cvs (2012-03-06)
 | 
			
		||||
							
								
								
									
										804
									
								
								WHATS_NEW_DM
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										804
									
								
								WHATS_NEW_DM
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,804 @@
 | 
			
		||||
On 7th June 2012, we froze this copy of the source code and moved it to
 | 
			
		||||
fedorahosted.org:
 | 
			
		||||
 | 
			
		||||
  http://git.fedorahosted.org/git/lvm2.git
 | 
			
		||||
  git clone git://git.fedorahosted.org/git/lvm2.git
 | 
			
		||||
 | 
			
		||||
--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Version 1.02.75 - 
 | 
			
		||||
================================
 | 
			
		||||
  Remove unsupported udev_get_dev_path libudev call used for checking udev dir.
 | 
			
		||||
  Set delay_resume_if_new on deptree snapshot origin.
 | 
			
		||||
  Log value chosen in _find_config_bool like other variable types do.
 | 
			
		||||
  Synchronize with dead of dmeventd.
 | 
			
		||||
  Rename (Blk)DevNames/DevNos dmsetup header to (Blk)DevNamesUsed/DevNosUsed.
 | 
			
		||||
  Add configure --with-veritysetup for independent veritysetup tool.
 | 
			
		||||
  Properly support passed in dmevent path in dm_event_register_handler().
 | 
			
		||||
  Remove dmeventd fifos on exit if they are not managed by systemd.
 | 
			
		||||
  Use SD_ACTIVATION env. var. in systemd units to better detect systemd in use.
 | 
			
		||||
  Do not run a new dmeventd instance on restart if there's no existing one.
 | 
			
		||||
  Make the time window for reading fifo longer 5sec (1.02.73).
 | 
			
		||||
 | 
			
		||||
Version 1.02.74 - 6th March 2012
 | 
			
		||||
================================
 | 
			
		||||
  Check for multiply-mangled names in auto mangling mode.
 | 
			
		||||
  Fix dm_task_get_name_unmangled to not unmangle already unmangled name.
 | 
			
		||||
  Check whether device names are properly mangled on ioctl return.
 | 
			
		||||
  Deactivation of failed thin check on thin pool returns success.
 | 
			
		||||
 | 
			
		||||
Version 1.02.73 - 3rd March 2012
 | 
			
		||||
================================
 | 
			
		||||
  Test _thread_registry list with holding mutex in dmeventd.
 | 
			
		||||
  Add dm_tree_node_set_callback() for preload and deactivation hooks.
 | 
			
		||||
  Drop unsupported TRIM message for thin pool.
 | 
			
		||||
  Improve logging for fifo startup in dmeventd.
 | 
			
		||||
  Better detection of missing dmeventd fifo connection (1.02.71).
 | 
			
		||||
  Add a few pointer validations in dmsetup.
 | 
			
		||||
  Support dm_task_get_driver_version() query without version string.
 | 
			
		||||
  Log failure of pthread_join when cleaning unused threads in dmeventd.
 | 
			
		||||
  Fix empty string warning logic in _find_config_str. (1.02.68)
 | 
			
		||||
  Fix dm_task_set_name to properly resolve path to dm name (1.02.71).
 | 
			
		||||
  Add dm_strncpy() function as a faster strncpy() replacement.
 | 
			
		||||
 | 
			
		||||
Version 1.02.72 - 23rd February 2012
 | 
			
		||||
====================================
 | 
			
		||||
  Avoid memory reallocation for dm_asprintf.
 | 
			
		||||
 | 
			
		||||
Version 1.02.71 - 20th February 2012
 | 
			
		||||
====================================
 | 
			
		||||
  Switch to using built-in blkid in 13-dm-disk.rules.
 | 
			
		||||
  Add "watch" rule to 13-dm-disk.rules.
 | 
			
		||||
  Detect failing fifo and skip 20s retry communication period.
 | 
			
		||||
  Add DM_DEFAULT_NAME_MANGLING_MODE environment variable as an override.
 | 
			
		||||
  Add dm_lib_init to automatically initialise device-mapper library on load.
 | 
			
		||||
  Replace any '\' char with '\\' in dm table specification on input.
 | 
			
		||||
  Add mangle command to dmsetup to provide renaming to correct mangled form.
 | 
			
		||||
  Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o.
 | 
			
		||||
  Add --manglename option to dmsetup to select the name mangling mode.
 | 
			
		||||
  Add dm_task_get_name_mangled/unmangled to libdevmapper.
 | 
			
		||||
  Mangle device name on dm_task_set_name/newname call if necessary.
 | 
			
		||||
  Add dm_set/get_name_mangling_mode to set/get name mangling in libdevmapper.
 | 
			
		||||
  Add configure --with-default-name-mangling for udev-friendly dev name charset.
 | 
			
		||||
  Test for parsed words in _umount() dmeventd snapshot plugin.
 | 
			
		||||
  Fix memory leak in fail path of parse_loop_device_name() in dmsetup.
 | 
			
		||||
  Check for missing reply_uuid in dm_event_get_registered_device().
 | 
			
		||||
  Check for allocation failure in dmeventd restart().
 | 
			
		||||
  Add few missing allocation failures tests in dmsetup.
 | 
			
		||||
  Fix potential risk of writing in front of buffer in _sysfs_get_dm_name().
 | 
			
		||||
 | 
			
		||||
Version 1.02.70 - 12th February 2012
 | 
			
		||||
====================================
 | 
			
		||||
  Fix dm_event_get_version() check.
 | 
			
		||||
  Add pointer test for dependency check in _add_dev().
 | 
			
		||||
  Validate name and uuid params of dm_tree_add_new_dev_with_udev_flags().
 | 
			
		||||
  Do not crash for dm_report_init() sort_key == NULL and behave like "".
 | 
			
		||||
  Return error for failing allocation in dm_asprintf().
 | 
			
		||||
  Add missing test for failing allocation in dm_realloc() code.
 | 
			
		||||
  Add test for memory allocation failures in regex matcher code.
 | 
			
		||||
  Simplify dm_task_set_geometry() and use dm_asprintf().
 | 
			
		||||
  Set all parameters to 0 for dm_get_next_target() for NULL return.
 | 
			
		||||
  Fix fd resource leak in error path for _udev_notify_sem_create().
 | 
			
		||||
  Leave space for '\0' for readline() call in _sysfs_get_kernel_name().
 | 
			
		||||
 | 
			
		||||
Version 1.02.69 - 1st February 2012
 | 
			
		||||
===================================
 | 
			
		||||
  Clean up dmeventd systemd unit ordering and requirements.
 | 
			
		||||
 | 
			
		||||
Version 1.02.68 - 26th January 2012
 | 
			
		||||
===================================
 | 
			
		||||
  Reset all members of info struct in dm_tree_add_new_dev_with_udev_flags.
 | 
			
		||||
  Add dmsetup wipe_table to replace table with one that uses error target.
 | 
			
		||||
  Add 'blkdevname' and 'blkdevs_used' fields to dmsetup info -c -o.
 | 
			
		||||
  Add 'blkdevname' option to dmsetup ls --tree to see block device names.
 | 
			
		||||
  Add -o devno/blkdevname/devname to dmsetup deps and ls.
 | 
			
		||||
  Add dm_device_get_name to get map name or block device name for given devno.
 | 
			
		||||
  Remove empty devices when clearing left-over inactive tables in deptree.
 | 
			
		||||
  Add dm_uuid_prefix/dm_set_uuid_prefix to override hard-coded LVM- prefix.
 | 
			
		||||
  Improve dmsetup man page description of readahead parameter.
 | 
			
		||||
  Use sysfs to set/get readahead if possible.
 | 
			
		||||
  Fix lvm2-monitor init script to use normalized output when using vgs.
 | 
			
		||||
  Add test for max length (DM_MAX_TYPE_NAME) of target type name.
 | 
			
		||||
  Include a copy of kernel DM documentation in doc/kernel.
 | 
			
		||||
  Improve man page style for dmsetup and mention more targets.
 | 
			
		||||
  Fix _get_proc_number to be tolerant of malformed /proc/misc entries.
 | 
			
		||||
  Fix missing thread list manipulation protection in dmeventd.
 | 
			
		||||
  Add ExecReload to dm-event.service for systemd to reload dmeventd properly.
 | 
			
		||||
  Add dm_config_tree_find_str_allow_empty and dm_config_find_str_allow_empty.
 | 
			
		||||
  Fix compile-time pool memory locking with DEBUG_MEM.
 | 
			
		||||
  Fix valgrind error reports in free of pool chunks with DEBUG_MEM.
 | 
			
		||||
  Align size of structure chunk for fast pool allocator to 8 bytes.
 | 
			
		||||
  Simplify some pointer operations in dm_free_aux() debug code.
 | 
			
		||||
  Remove unused dbg_malloc.h file from source tree.
 | 
			
		||||
  Cleanup backtraces for _create_and_load_v4().
 | 
			
		||||
  Fix alignment warning in bitcount calculation for raid segment.
 | 
			
		||||
  Allocate dm_tree structure from dm_tree pool.
 | 
			
		||||
  Update debug logging for _resume_node.
 | 
			
		||||
  Add functions to support thin provisioning target.
 | 
			
		||||
  Improve libdm-config error path reporting.
 | 
			
		||||
  Update dmsetup resume man with --addnodeonresume/create options.
 | 
			
		||||
  Add dependency for dm man pages to man subdirectory make all target.
 | 
			
		||||
  Add dm_tree_retry_remove to use retry logic for device removal in a dm_tree.
 | 
			
		||||
  Add dm_device_has_mounted_fs fn to check mounted filesystem on a device.
 | 
			
		||||
  Add dm_device_has_holders fn to to check use of the device by another device.
 | 
			
		||||
  Add dm_sysfs_dir to libdevmapper to retrieve sysfs location set.
 | 
			
		||||
  Add dm_set_sysfs_dir to libdevmapper to set sysfs location.
 | 
			
		||||
  Add --retry option for dmsetup remove to retry removal if not successful.
 | 
			
		||||
  Add dm_task_retry_remove fn to use retry logic for device removal.
 | 
			
		||||
  Remove unused passed parameters for _mirror_emit_segment_line().
 | 
			
		||||
  Add dm_config and string character escaping functions to libdevmapper.
 | 
			
		||||
  Mark unreleased memory pools as internal error.
 | 
			
		||||
 | 
			
		||||
Version 1.02.67 - 19th August 2011
 | 
			
		||||
==================================
 | 
			
		||||
  Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked.
 | 
			
		||||
 | 
			
		||||
Version 1.02.66 - 12th August 2011
 | 
			
		||||
==================================
 | 
			
		||||
  Release geometry buffer in dm_task_destroy.
 | 
			
		||||
  Update udev rules to skip DM flags decoding for removed devices.
 | 
			
		||||
  Add compile-time pool memory locking options (to debug shared VG structs).
 | 
			
		||||
  Remove device name prefix from dmsetup line output if -j & -m or -u supplied.
 | 
			
		||||
  Remove support for the original version 1 dm ioctls.
 | 
			
		||||
  Add missing check for allocation failure _create_dir_recursive().
 | 
			
		||||
  Add support for systemd file descriptor handover in dmeventd.
 | 
			
		||||
  Fix memory leak in dmsetup _message() memory allocation error path.
 | 
			
		||||
  Use new oom killer adjustment interface (oom_score_adj) when available.
 | 
			
		||||
  Add systemd unit files for dmeventd.
 | 
			
		||||
  Fix read-only identical table reload supression.
 | 
			
		||||
 | 
			
		||||
Version 1.02.65 - 8th July 2011
 | 
			
		||||
===============================
 | 
			
		||||
  Remove dev name prefix from dmsetup line output if exactly one dev requested.
 | 
			
		||||
  Report internal error if suspending a device using an already-suspended dev.
 | 
			
		||||
  Report error if a table load requiring target parameters has none supplied.
 | 
			
		||||
  Add dmsetup --checks and dm_task_enable_checks framework to validate ioctls.
 | 
			
		||||
  Add age_in_minutes parameter to dmsetup udevcomplete_all.
 | 
			
		||||
  Return immediately from dm_lib_exit() if called more than once.
 | 
			
		||||
  Disable udev fallback by default and add --verifyudev option to dmsetup.
 | 
			
		||||
  Report internal error if any table is loaded while any dev is known suspended.
 | 
			
		||||
  Add dm_get_suspended_counter() for number of devs in suspended state by lib.
 | 
			
		||||
  Fix "all" report field prefix matching to include label fields with pv_all.
 | 
			
		||||
  Delay resuming new preloaded mirror devices with core logs in deptree code.
 | 
			
		||||
  Accept new kernel version 3 uname formats in initialisation.
 | 
			
		||||
 | 
			
		||||
Version 1.02.64 - 29th April 2011
 | 
			
		||||
==================================
 | 
			
		||||
  Require libudev >= 143 when compiling with udev support.
 | 
			
		||||
  Use word alignment for dm_pool_strdup() and dm_pool_strndup().
 | 
			
		||||
  Use dm_snprintf() to fix signedness warning in dm_set_dev_dir().
 | 
			
		||||
  Use unsigned loop counter to fix signedness warning in _other_node_ops().
 | 
			
		||||
  Fix const cast in dmsetup calls of dm_report_field_string().
 | 
			
		||||
  Streamline /dev/mapper/control node code for common cases.
 | 
			
		||||
  Use hard-coded dm control node device number for 2.6.36 kernels and above.
 | 
			
		||||
  Improve stack debug reporting in dm_task_create().
 | 
			
		||||
  Fallback to control node creation only if node doesn't exist yet.
 | 
			
		||||
  Change dm_hash binary functions to take void *key instead of char *.
 | 
			
		||||
  Fix uninitialised memory use with empty params in _reload_with_suppression_v4.
 | 
			
		||||
  Lower severity of selabel_lookup and matchpathcon failure to log_debug.
 | 
			
		||||
  Add test for failed allocation from dm_task_set_uuid() in dmeventd.
 | 
			
		||||
  Add dm_event_get_version to dmeventd for use with -R.
 | 
			
		||||
  Avoid dmeventd core dumps when handling request with unknown command ID.
 | 
			
		||||
  Have dmeventd -R start up even when no existing copy is running.
 | 
			
		||||
  Accept multiple mapped device names on many dmsetup command lines.
 | 
			
		||||
  Fix dm_udev_wait calls in dmsetup to occur before readahead display not after.
 | 
			
		||||
  Include an implicit dm_task_update_nodes() within dm_udev_wait().
 | 
			
		||||
  Fix _create_and_load_v4 not to lose the --addnodeoncreate setting (1.02.62).
 | 
			
		||||
  Add inactive table query support for kernel driver >= 4.11.6 (RHEL 5.7).
 | 
			
		||||
  Log debug open_count in _node_has_closed_parents().
 | 
			
		||||
  Add a const to dm_report_field_string() data parameter.
 | 
			
		||||
 | 
			
		||||
Version 1.02.63 - 9th February 2011
 | 
			
		||||
===================================
 | 
			
		||||
  Reinstate DEBUG_MEM as it's part of the API. (1.02.62)
 | 
			
		||||
 | 
			
		||||
Version 1.02.62 - 4th February 2011
 | 
			
		||||
===================================
 | 
			
		||||
  Add configure --with-device-nodes-on=create for previous behaviour.
 | 
			
		||||
  Move creation of device nodes from 'create' to 'resume'.
 | 
			
		||||
  Add --addnodeonresume and --addnodeoncreate options to dmsetup.
 | 
			
		||||
  Add dm_task_set_add_node to libdevmapper to control dev node creation time.
 | 
			
		||||
  Add dm_task_secure_data to libdevmapper to wipe ioctl buffers in kernel.
 | 
			
		||||
  Log debug message when expected uevent is not generated.
 | 
			
		||||
  Only compile memory debugging code when DEBUG_MEM is set.
 | 
			
		||||
  Set DM_UDEV_DISABLE_OTHER_RULES_FLAG for suspended DM devices in udev rules.
 | 
			
		||||
  Begin a new pool object for each row in _output_as_rows() correctly.
 | 
			
		||||
 | 
			
		||||
Version 1.02.61 - 10th January 2011
 | 
			
		||||
===================================
 | 
			
		||||
  Add DM_COOKIE_AUTO_CREATE to libdevmapper.h.
 | 
			
		||||
  Export DM_CONTROL_NODE_UMASK and use it while creating /dev/mapper/control.
 | 
			
		||||
 | 
			
		||||
Version 1.02.60 - 20th December 2010
 | 
			
		||||
====================================
 | 
			
		||||
  Check for unlink failure in remove_lockfile() in dmeventd.
 | 
			
		||||
  Use dm_free for dm_malloc-ed areas in _clog_ctr/_clog_dtr in cmirrord.
 | 
			
		||||
  Use char* arithmetic in _process_all() & _targets() in dmsetup.
 | 
			
		||||
  Change dm_regex_create() API to accept const char * const *patterns.
 | 
			
		||||
  Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
 | 
			
		||||
  Detect existence of new SELinux selabel interface during configure.
 | 
			
		||||
 | 
			
		||||
Version 1.02.59 - 6th December 2010
 | 
			
		||||
===================================
 | 
			
		||||
  Add backtraces to _process_mapper_dir and  _create_and_load_v4 error paths.
 | 
			
		||||
  Remove superfluous checks for NULL before calling dm_free.
 | 
			
		||||
 | 
			
		||||
Version 1.02.58 - 22nd November 2010
 | 
			
		||||
====================================
 | 
			
		||||
  Fix _output_field crash from field_id free with DEBUG_MEM. (1.02.57)
 | 
			
		||||
 | 
			
		||||
Version 1.02.57 - 8th November 2010
 | 
			
		||||
===================================
 | 
			
		||||
  Fix regex optimiser not to ignore RHS of OR nodes in _find_leftmost_common.
 | 
			
		||||
  Add dmeventd -R to restart dmeventd without losing monitoring state. (1.02.56)
 | 
			
		||||
  Fix memory leak of field_id in _output_field function.
 | 
			
		||||
  Allocate buffer for reporting functions dynamically to support long outputs.
 | 
			
		||||
 | 
			
		||||
Version 1.02.56 - 25th October 2010
 | 
			
		||||
===================================
 | 
			
		||||
  Return const pointer from dm_basename() in libdevmapper.
 | 
			
		||||
  Implement dmeventd -R to restart without state loss.
 | 
			
		||||
  Add dm_zalloc and use it and dm_pool_zalloc throughout.
 | 
			
		||||
  Add --setuuid to dmsetup rename.
 | 
			
		||||
  Add dm_task_set_newuuid to set uuid of mapped device post-creation.
 | 
			
		||||
 | 
			
		||||
Version 1.02.55 - 24th September 2010
 | 
			
		||||
=====================================
 | 
			
		||||
  Fix the way regions are marked complete to avoid slow --nosync cmirror I/O.
 | 
			
		||||
  Add DM_REPORT_FIELD_TYPE_ID_LEN to libdevmapper.h.
 | 
			
		||||
 | 
			
		||||
Version 1.02.54 - 18th August 2010
 | 
			
		||||
==================================
 | 
			
		||||
  Fix dm-mod autoloading logic to not assume control node is set correctly.
 | 
			
		||||
  Add dmeventd/executable to lvm.conf to test alternative dmeventd.
 | 
			
		||||
  Export dm_event_handler_set_dmeventd_path to override built-in dmeventd path.
 | 
			
		||||
  Generate libdevmapper-event exported symbols.
 | 
			
		||||
  Remove superfluous NULL pointer tests before dm_free from dmeventd.
 | 
			
		||||
  Assume dm-mod autoloading support is in kernel 2.6.36 and higher, not 2.6.35.
 | 
			
		||||
  Fix udev rules to support udev database content generated by older rules.
 | 
			
		||||
  Reinstate detection of inappropriate uevent with DISK_RO set and suppress it.
 | 
			
		||||
  Fix regex ttree off-by-one error.
 | 
			
		||||
  Add --enable-valgrind-pool to configure.
 | 
			
		||||
  Fix segfault in regex matcher with characters of ordinal value > 127.
 | 
			
		||||
  Fix 'void*' arithmetic warnings in dbg_malloc.c and libdm-iface.c.
 | 
			
		||||
  Wait for node creation before displaying debug info in dmsetup.
 | 
			
		||||
  Fix return status 0 for "dmsetup info -c -o help".
 | 
			
		||||
  Add check for kernel semaphore support and disable udev_sync if not available.
 | 
			
		||||
 | 
			
		||||
Version 1.02.53 - 28th July 2010
 | 
			
		||||
================================
 | 
			
		||||
  Revert failed table load preparation after "create, load and resume".
 | 
			
		||||
  Switch dmeventd to use dm_create_lockfile and drop duplicate code.
 | 
			
		||||
  Add dm_create_lockfile to libdm to handle pidfiles for all daemons.
 | 
			
		||||
  Replace lookup with next in struct dfa_state & calculate states on demand.
 | 
			
		||||
  Improve the regex matcher, reducing the number of charset nodes used.
 | 
			
		||||
  Add dm_regex_fingerprint to facilitate regex testing.
 | 
			
		||||
  Skip ffs(0) in _test_word in bitset functions.
 | 
			
		||||
  Use "nowatch" udev rule for inappropriate devices.
 | 
			
		||||
 | 
			
		||||
Version 1.02.52 - 6th July 2010
 | 
			
		||||
===============================
 | 
			
		||||
  Fix dmlosetup snprintf %llu compiler warning.
 | 
			
		||||
  Add parentheses to some libdevmapper.h macro arguments.
 | 
			
		||||
  Add printf format attributes to dm_{sn,as}printf and fix a caller.
 | 
			
		||||
  Move dmeventd man page from install_lvm2 to install_device-mapper. (1.02.50)
 | 
			
		||||
 | 
			
		||||
Version 1.02.51 - 30th June 2010
 | 
			
		||||
================================
 | 
			
		||||
  Generate libdevmapper exported symbols from header file.
 | 
			
		||||
 | 
			
		||||
Version 1.02.50 - 23rd June 2010
 | 
			
		||||
================================
 | 
			
		||||
  Fix INTERNAL_ERROR typo in ioctl iface unknown task message.
 | 
			
		||||
  Fix udev rules to handle spurious events properly.
 | 
			
		||||
  Use C99 [] not [0] in dm_ulog_request struct to avoid abort when fortified.
 | 
			
		||||
  Allow use of devmapper header file in C++ mode (extern "C" and __typeof__).
 | 
			
		||||
  Add dmeventd man page.
 | 
			
		||||
 | 
			
		||||
Version 1.02.49 - 4th June 2010
 | 
			
		||||
===============================
 | 
			
		||||
  Support autoloading of dm-mod module for kernels from 2.6.35.
 | 
			
		||||
  Document 'clear' in dmsetup man page.
 | 
			
		||||
  Fix semctl parameter (union) to avoid misaligned parameter on some arches.
 | 
			
		||||
  Add dm_tree_node_set_presuspend_node() to presuspend child when deactivating.
 | 
			
		||||
  Initial support for replicator target.
 | 
			
		||||
 | 
			
		||||
Version 1.02.48 - 17th May 2010
 | 
			
		||||
================================
 | 
			
		||||
  Use -d to control level of messages sent to syslog by dmeventd.
 | 
			
		||||
  Change -d to -f to run dmeventd in foreground.
 | 
			
		||||
  Do not print encryption key in message debug output (cryptsetup luksResume).
 | 
			
		||||
  Fix dmeventd static build library dependencies.
 | 
			
		||||
  Fix udev flags on remove in create_and_load error path.
 | 
			
		||||
 | 
			
		||||
Version 1.02.47 - 30th April 2010
 | 
			
		||||
=================================
 | 
			
		||||
  Add support for new IMPORT{db} udev rule.
 | 
			
		||||
  Add DM_UDEV_PRIMARY_SOURCE_FLAG udev flag to recognize proper DM events.
 | 
			
		||||
  Also include udev libs in libdevmapper.pc when udev_sync is enabled.
 | 
			
		||||
  Cache bitset locations to speed up _calc_states.
 | 
			
		||||
  Add a regex optimisation pass for shared prefixes and suffixes.
 | 
			
		||||
  Add dm_bit_and and dm_bitset_equal to libdevmapper.
 | 
			
		||||
  Simplify dm_bitset_create.
 | 
			
		||||
  Speed up dm_bit_get_next with ffs().
 | 
			
		||||
 | 
			
		||||
Version 1.02.46 - 14th April 2010
 | 
			
		||||
=================================
 | 
			
		||||
  Change dm_tree_deactivate_children to fail if device is open.
 | 
			
		||||
  Wipe memory buffers for dm-ioctl parameters before releasing.
 | 
			
		||||
  Strictly require libudev if udev_sync is used.
 | 
			
		||||
  Add support for ioctl's DM_UEVENT_GENERATED_FLAG.
 | 
			
		||||
 | 
			
		||||
Version 1.02.45 - 9th March 2010
 | 
			
		||||
================================
 | 
			
		||||
  Add --showkeys parameter description to dmsetup man page.
 | 
			
		||||
  Add --help option as synonym for help command.
 | 
			
		||||
 | 
			
		||||
Version 1.02.44 - 15th February 2010
 | 
			
		||||
====================================
 | 
			
		||||
  Add DM_UDEV_DISABLE_LIBRARY_FALLBACK udev flag to rely on udev only.
 | 
			
		||||
  Export dm_udev_create_cookie function to create new cookies on demand.
 | 
			
		||||
  Add --udevcookie, udevcreatecookie and udevreleasecookie to dmsetup.
 | 
			
		||||
  Set udev state automatically instead of using DM_UDEV_DISABLE_CHECKING.
 | 
			
		||||
 | 
			
		||||
Version 1.02.43 - 21st January 2010
 | 
			
		||||
===================================
 | 
			
		||||
  Remove bitset, hash and pool headers superceded by libdevmapper.h.
 | 
			
		||||
  Fix off-by-one error causing bad cluster mirror table construction.
 | 
			
		||||
 | 
			
		||||
Version 1.02.42 - 14th January 2010
 | 
			
		||||
===================================
 | 
			
		||||
  Add support for the "snapshot-merge" kernel target (2.6.33-rc1).
 | 
			
		||||
  Introduce a third activation_priority level in dm_tree_activate_children.
 | 
			
		||||
 | 
			
		||||
Version 1.02.41 - 12th January 2010
 | 
			
		||||
===================================
 | 
			
		||||
  If DM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings.
 | 
			
		||||
  Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags.
 | 
			
		||||
  Add --noudevrules option for dmsetup to disable /dev node management by udev.
 | 
			
		||||
  Fix 'dmsetup info -c -o all' to show all fields.
 | 
			
		||||
  Return errors if dm_tree_*_children functions fail.
 | 
			
		||||
  Fix coredump and memory leak for 'dmsetup help -c'.
 | 
			
		||||
  Disable udev rules for change events with DISK_RO set.
 | 
			
		||||
 | 
			
		||||
Version 1.02.40 - 19th November 2009
 | 
			
		||||
====================================
 | 
			
		||||
  Fix install_device-mapper Makefile target to not build dmeventd plugins.
 | 
			
		||||
  Support udev flags even when udev_sync is disabled or not compiled in.
 | 
			
		||||
  Remove 'last_rule' from udev rules: honour DM_UDEV_DISABLE_OTHER_RULES_FLAG.
 | 
			
		||||
  Add dmsetup --inactive support.
 | 
			
		||||
  Add dm_task_query_inactive_table to libdevmapper for kernel driver >= 4.16.
 | 
			
		||||
  Fix hash lookup segfault when keys compared are different lengths.
 | 
			
		||||
 | 
			
		||||
Version 1.02.39 - 26th October 2009
 | 
			
		||||
===================================
 | 
			
		||||
  Remove strict default permissions for DM devices from 95-dm-notify.rules.
 | 
			
		||||
  Add dmsetup udevflags command to decode udev flags in given cookie value.
 | 
			
		||||
  Support udev flags in libdevmapper incl. dm_tree_add_new_dev_with_udev_flags.
 | 
			
		||||
  Make libdm ABI consistent when built with/without selinux support.
 | 
			
		||||
 | 
			
		||||
Version 1.02.38 - 25th September 2009
 | 
			
		||||
=====================================
 | 
			
		||||
  Export DM_DEV_DIR_UMASK, the default umask for /dev directories created.
 | 
			
		||||
  Handle any path supplied to dm_task_set_name by looking up in /dev/mapper.
 | 
			
		||||
  Add several examples to 12-dm-permissions.rules.
 | 
			
		||||
  Add splitname and --yes to dmsetup man page.
 | 
			
		||||
  Fix _mirror_emit_segment_line return code.
 | 
			
		||||
  Fix dmeventd _temporary_log_fn parameters. (2.02.50)
 | 
			
		||||
 | 
			
		||||
Version 1.02.37 - 15th September 2009
 | 
			
		||||
=====================================
 | 
			
		||||
  Add dmsetup manpage entries for udevcomplete_all and udevcookies.
 | 
			
		||||
  Check udev is running when processing cookies and retain state internally.
 | 
			
		||||
  Add y|--yes option to dmsetup for default 'yes' answer to prompts.
 | 
			
		||||
  Fix tools Makefile to process dmsetup sources separately.
 | 
			
		||||
  Restore umask when device node creation fails.
 | 
			
		||||
  Check kernel vsn to use 'block_on_error' or 'handle_errors' in mirror table.
 | 
			
		||||
  Add dm-log-userspace.h to tree for cmirrord builds.
 | 
			
		||||
 | 
			
		||||
Version 1.02.36 - 6th August 2009
 | 
			
		||||
=================================
 | 
			
		||||
  Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
 | 
			
		||||
  Add libdevmapper functions to support synchronisation with udev.
 | 
			
		||||
 | 
			
		||||
Version 1.02.35 - 28th July 2009
 | 
			
		||||
================================
 | 
			
		||||
  Add LOG_LINE_WITH_ERRNO macro.
 | 
			
		||||
  Use log_error macro consistently throughout in place of log_err.
 | 
			
		||||
 | 
			
		||||
Version 1.02.34 - 15th July 2009
 | 
			
		||||
================================
 | 
			
		||||
  Use _exit() not exit() after forking to avoid flushing libc buffers twice.
 | 
			
		||||
  Rename plog macro to LOG_LINE & add LOG_MESG variant for dm_dump_memory_debug.
 | 
			
		||||
  Change plog to use dm_log_with_errno unless deprecated dm_log_init was used.
 | 
			
		||||
  Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns.
 | 
			
		||||
  Fix whitespace in linear target line to fix identical table line detection.
 | 
			
		||||
  Add device number to more log messages during activation.
 | 
			
		||||
 | 
			
		||||
Version 1.02.33 - 30th June 2009
 | 
			
		||||
================================
 | 
			
		||||
  Don't fallback to default major number: use dm_task_set_major_minor. (1.02.31)
 | 
			
		||||
  Do not fork daemon when dmeventd cannot be found.
 | 
			
		||||
  Add crypt target handling to libdevmapper tree nodes.
 | 
			
		||||
  Add splitname command to dmsetup.
 | 
			
		||||
  Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports.
 | 
			
		||||
  Make mempool optional in dm_split_lvm_name().
 | 
			
		||||
 | 
			
		||||
Version 1.02.32 - 21st May 2009
 | 
			
		||||
===============================
 | 
			
		||||
  Only generate libdevmapper.a when configured to link statically.
 | 
			
		||||
  Export dm_tree_node_size_changed() from libdevmapper.
 | 
			
		||||
  Propagate the table size_changed property up the dm device tree.
 | 
			
		||||
  Detect failure to free memory pools when releasing the library.
 | 
			
		||||
  Fix segfault when getopt processes dmsetup -U, -G and -M options.
 | 
			
		||||
 | 
			
		||||
Version 1.02.31 - 3rd March 2009
 | 
			
		||||
================================
 | 
			
		||||
  If kernel supports only one dm major number, use in place of any supplied.
 | 
			
		||||
 | 
			
		||||
Version 1.02.30 - 26th January 2009
 | 
			
		||||
====================================
 | 
			
		||||
  Add "all" field to reports expanding to all fields of report type.
 | 
			
		||||
  Enforce device name length and character limitations in libdm.
 | 
			
		||||
  Replace _dm_snprintf with EMIT_PARAMS macro for creating target lines.
 | 
			
		||||
 | 
			
		||||
Version 1.02.29 - 10th November 2008
 | 
			
		||||
====================================
 | 
			
		||||
  Merge device-mapper into the LVM2 tree.
 | 
			
		||||
  Split out dm-logging.h from log.h.
 | 
			
		||||
  Use lvm-types.h.
 | 
			
		||||
  Add usrsbindir to configure.
 | 
			
		||||
 | 
			
		||||
Version 1.02.28 - 18th September 2008
 | 
			
		||||
=====================================
 | 
			
		||||
  Only resume devices in dm_tree_preload_children if size changes.
 | 
			
		||||
  Extend deptree buffers so the largest possible device numbers fit.
 | 
			
		||||
  Generate versioned libdevmapper-event.so.
 | 
			
		||||
  Underline longer report help text headings.
 | 
			
		||||
 | 
			
		||||
Version 1.02.27 - 25th June 2008
 | 
			
		||||
================================
 | 
			
		||||
  Align struct memblock in dbg_malloc for sparc.
 | 
			
		||||
  Add --unquoted and --rows to dmsetup.
 | 
			
		||||
  Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro.
 | 
			
		||||
  Fix inverted no_flush debug message.
 | 
			
		||||
  Remove --enable-jobs from configure. (Set at runtime instead.)
 | 
			
		||||
  Bring configure.in and list.h into line with the lvm2 versions.
 | 
			
		||||
 | 
			
		||||
Version 1.02.26 - 6th June 2008
 | 
			
		||||
===============================
 | 
			
		||||
  Initialise params buffer to empty string in _emit_segment.
 | 
			
		||||
  Skip add_dev_node when ioctls disabled.
 | 
			
		||||
  Make dm_hash_iter safe against deletion.
 | 
			
		||||
  Accept a NULL pointer to dm_free silently.
 | 
			
		||||
  Add tables_loaded, readonly and suspended columns to reports.
 | 
			
		||||
  Add --nameprefixes to dmsetup.
 | 
			
		||||
  Add field name prefix option to reporting functions.
 | 
			
		||||
  Calculate string size within dm_pool_grow_object.
 | 
			
		||||
 | 
			
		||||
Version 1.02.25 - 10th April 2008
 | 
			
		||||
=================================
 | 
			
		||||
  Remove redundant if-before-free tests.
 | 
			
		||||
  Use log_warn for reporting field help text instead of log_print.
 | 
			
		||||
  Change cluster mirror log type name (s/clustered_/clustered-/)
 | 
			
		||||
 | 
			
		||||
Version 1.02.24 - 20th December 2007
 | 
			
		||||
====================================
 | 
			
		||||
  Fix deptree to pass new name to _resume_node after a rename.
 | 
			
		||||
  Suppress other node operations if node is deleted.
 | 
			
		||||
  Add node operation stack debug messages.
 | 
			
		||||
  Report error when empty device name passed to readahead functions.
 | 
			
		||||
  Fix minimum readahead debug message.
 | 
			
		||||
 | 
			
		||||
Version 1.02.23 - 5th December 2007
 | 
			
		||||
===================================
 | 
			
		||||
  Update dm-ioctl.h after removal of compat code.
 | 
			
		||||
  Add readahead support to libdevmapper and dmsetup.
 | 
			
		||||
  Fix double free in a libdevmapper-event error path.
 | 
			
		||||
  Fix configure --with-dmeventd-path substitution.
 | 
			
		||||
  Allow a DM_DEV_DIR environment variable to override /dev in dmsetup.
 | 
			
		||||
  Create a libdevmapper.so.$LIB_VERSION symlink within the build tree.
 | 
			
		||||
  Avoid static link failure with some SELinux libraries that require libpthread.
 | 
			
		||||
  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.
 | 
			
		||||
  Also suppress error if device doesn't exist with DM_DEVICE_STATUS.
 | 
			
		||||
  Export dm_set_selinux_context().
 | 
			
		||||
  Add dm_driver_version().
 | 
			
		||||
  Added dependency tree functions to library.
 | 
			
		||||
  Added hash, bitset, pool, dbg_malloc to library.
 | 
			
		||||
  Added ls --tree to dmsetup.
 | 
			
		||||
  Added dmsetup --nolockfs support for suspend/reload.
 | 
			
		||||
 | 
			
		||||
Version 1.01.05 - 26 Sep 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Resync list.h with LVM2.
 | 
			
		||||
  Remember increased buffer size and use for subsequent calls.
 | 
			
		||||
  On 'buffer full' condition, double buffer size and repeat ioctl.
 | 
			
		||||
  Fix termination of getopt_long() option array.
 | 
			
		||||
  Report 'buffer full' condition with v4 ioctl as well as with v1.
 | 
			
		||||
 | 
			
		||||
Version 1.01.04 - 2 Aug 2005
 | 
			
		||||
============================
 | 
			
		||||
  Fix dmsetup ls -j and status --target with empty table.
 | 
			
		||||
 | 
			
		||||
Version 1.01.03 - 13 Jun 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Use matchpathcon mode parameter.
 | 
			
		||||
  Fix configure script to re-enable selinux.
 | 
			
		||||
 | 
			
		||||
Version 1.01.02 - 17 May 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Call dm_lib_exit() and dm_lib_release() automatically now.
 | 
			
		||||
  Add --target <target_type> filter to dmsetup table/status/ls.
 | 
			
		||||
  Add --exec <command> to dmsetup ls.
 | 
			
		||||
  Fix dmsetup getopt_long usage.
 | 
			
		||||
 | 
			
		||||
Version 1.01.01 - 29 Mar 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Update dmsetup man page.
 | 
			
		||||
  Drop-in devmap_name replacement.
 | 
			
		||||
  Add option to compile without ioctl for testing.
 | 
			
		||||
  Fix DM_LIB_VERSION sed.
 | 
			
		||||
 | 
			
		||||
Version 1.01.00 - 17 Jan 2005
 | 
			
		||||
=============================
 | 
			
		||||
  Add dm_task_no_open_count() to skip getting open_count.
 | 
			
		||||
 | 
			
		||||
Version 1.00.21 - 7 Jan 2005
 | 
			
		||||
============================
 | 
			
		||||
  Fix /proc/devices parsing.
 | 
			
		||||
 | 
			
		||||
Version 1.00.20 - 6 Jan 2005
 | 
			
		||||
============================
 | 
			
		||||
  Attempt to fix /dev/mapper/control transparently if it's wrong.
 | 
			
		||||
  Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
 | 
			
		||||
  Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
 | 
			
		||||
  Add --noheadings columns option for colon-separated dmsetup output.
 | 
			
		||||
  Support device referencing by uuid or major/minor.
 | 
			
		||||
  Warn if kernel data didn't fit in buffer.
 | 
			
		||||
  Fix a printf.
 | 
			
		||||
 | 
			
		||||
Version 1.00.19 - 3 July 2004
 | 
			
		||||
=============================
 | 
			
		||||
  More autoconf fixes.
 | 
			
		||||
  Fix a dmsetup newline.
 | 
			
		||||
  Fix device number handling for 2.6 kernels.
 | 
			
		||||
 | 
			
		||||
Version 1.00.18 - 20 Jun 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Fix a uuid free in libdm-iface.
 | 
			
		||||
  Fix a targets string size calc in driver.
 | 
			
		||||
  Add -c to dmsetup for column-based output.
 | 
			
		||||
  Add target message-passing ioctl.
 | 
			
		||||
 | 
			
		||||
Version 1.00.17 - 17 Apr 2004
 | 
			
		||||
=============================
 | 
			
		||||
  configure --with-owner= --with-group= to avoid -o and -g args to 'install'
 | 
			
		||||
  Fix library selinux linking.
 | 
			
		||||
 | 
			
		||||
Version 1.00.16 - 16 Apr 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Ignore error setting selinux file context if fs doesn't support it.
 | 
			
		||||
 | 
			
		||||
Version 1.00.15 - 7 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Fix status overflow check in kernel patches.
 | 
			
		||||
 | 
			
		||||
Version 1.00.14 - 6 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Fix static selinux build.
 | 
			
		||||
 | 
			
		||||
Version 1.00.13 - 6 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Add some basic selinux support.
 | 
			
		||||
 | 
			
		||||
Version 1.00.12 - 6 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Fix dmsetup.static install.
 | 
			
		||||
 | 
			
		||||
Version 1.00.11 - 5 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  configure --enable-static_link does static build in addition to dynamic.
 | 
			
		||||
  Moved Makefile library targets definition into template.
 | 
			
		||||
 | 
			
		||||
Version 1.00.10 - 2 Apr 2004
 | 
			
		||||
============================
 | 
			
		||||
  Fix DESTDIR handling.
 | 
			
		||||
  Static build installs to dmsetup.static.
 | 
			
		||||
  Basic support for internationalisation.
 | 
			
		||||
  Minor Makefile tidy-ups/fixes.
 | 
			
		||||
 | 
			
		||||
Version 1.00.09 - 31 Mar 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Update copyright notices to Red Hat.
 | 
			
		||||
  Move full mknodes functionality from dmsetup into libdevmapper.
 | 
			
		||||
  Avoid sscanf %as for uClibc compatibility.
 | 
			
		||||
  Cope if DM_LIST_VERSIONS is not defined.
 | 
			
		||||
  Add DM_LIST_VERSIONS functionality to kernel patches.
 | 
			
		||||
  Generate new kernel patches for 2.4.26-rc1.
 | 
			
		||||
 | 
			
		||||
Version 1.00.08 - 27 Feb 2004
 | 
			
		||||
=============================
 | 
			
		||||
  Added 'dmsetup targets'.
 | 
			
		||||
  Added event_nr support to 'dmsetup wait'.
 | 
			
		||||
  Updated dmsetup man page.
 | 
			
		||||
  Allow logging function to be reset to use internal one.
 | 
			
		||||
  Bring log macros in line with LVM2 ones.
 | 
			
		||||
  Added 'make install_static_lib' which installs libdevmapper.a.
 | 
			
		||||
  Made configure/makefiles closer to LVM2 versions.
 | 
			
		||||
  Fixed DESTDIR for make install/install_static_lib.
 | 
			
		||||
  Updated README/INSTALL to reflect move to sources.redhat.com.
 | 
			
		||||
  Updated autoconf files to 2003-06-17.
 | 
			
		||||
							
								
								
									
										171
									
								
								aclocal.m4
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								aclocal.m4
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
 | 
			
		||||
 | 
			
		||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 | 
			
		||||
# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
 | 
			
		||||
# This file is free software; the Free Software Foundation
 | 
			
		||||
# gives unlimited permission to copy and/or distribute it,
 | 
			
		||||
# with or without modifications, as long as this notice is preserved.
 | 
			
		||||
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
 | 
			
		||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 | 
			
		||||
# PARTICULAR PURPOSE.
 | 
			
		||||
 | 
			
		||||
# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
 | 
			
		||||
# serial 1 (pkg-config-0.24)
 | 
			
		||||
# 
 | 
			
		||||
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
 | 
			
		||||
#
 | 
			
		||||
# This program is free software; you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful, but
 | 
			
		||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
# General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# 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.
 | 
			
		||||
#
 | 
			
		||||
# 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.
 | 
			
		||||
 | 
			
		||||
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
 | 
			
		||||
# ----------------------------------
 | 
			
		||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
 | 
			
		||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
 | 
			
		||||
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
 | 
			
		||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
 | 
			
		||||
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
 | 
			
		||||
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
 | 
			
		||||
 | 
			
		||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
 | 
			
		||||
	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
 | 
			
		||||
fi
 | 
			
		||||
if test -n "$PKG_CONFIG"; then
 | 
			
		||||
	_pkg_min_version=m4_default([$1], [0.9.0])
 | 
			
		||||
	AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
 | 
			
		||||
	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
 | 
			
		||||
		AC_MSG_RESULT([yes])
 | 
			
		||||
	else
 | 
			
		||||
		AC_MSG_RESULT([no])
 | 
			
		||||
		PKG_CONFIG=""
 | 
			
		||||
	fi
 | 
			
		||||
fi[]dnl
 | 
			
		||||
])# PKG_PROG_PKG_CONFIG
 | 
			
		||||
 | 
			
		||||
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
 | 
			
		||||
#
 | 
			
		||||
# Check to see whether a particular set of modules exists.  Similar
 | 
			
		||||
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
 | 
			
		||||
#
 | 
			
		||||
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
 | 
			
		||||
# only at the first occurence in configure.ac, so if the first place
 | 
			
		||||
# it's called might be skipped (such as if it is within an "if", you
 | 
			
		||||
# have to call PKG_CHECK_EXISTS manually
 | 
			
		||||
# --------------------------------------------------------------
 | 
			
		||||
AC_DEFUN([PKG_CHECK_EXISTS],
 | 
			
		||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
 | 
			
		||||
if test -n "$PKG_CONFIG" && \
 | 
			
		||||
    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
 | 
			
		||||
  m4_default([$2], [:])
 | 
			
		||||
m4_ifvaln([$3], [else
 | 
			
		||||
  $3])dnl
 | 
			
		||||
fi])
 | 
			
		||||
 | 
			
		||||
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
 | 
			
		||||
# ---------------------------------------------
 | 
			
		||||
m4_define([_PKG_CONFIG],
 | 
			
		||||
[if test -n "$$1"; then
 | 
			
		||||
    pkg_cv_[]$1="$$1"
 | 
			
		||||
 elif test -n "$PKG_CONFIG"; then
 | 
			
		||||
    PKG_CHECK_EXISTS([$3],
 | 
			
		||||
                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
 | 
			
		||||
		     [pkg_failed=yes])
 | 
			
		||||
 else
 | 
			
		||||
    pkg_failed=untried
 | 
			
		||||
fi[]dnl
 | 
			
		||||
])# _PKG_CONFIG
 | 
			
		||||
 | 
			
		||||
# _PKG_SHORT_ERRORS_SUPPORTED
 | 
			
		||||
# -----------------------------
 | 
			
		||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
 | 
			
		||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
 | 
			
		||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
 | 
			
		||||
        _pkg_short_errors_supported=yes
 | 
			
		||||
else
 | 
			
		||||
        _pkg_short_errors_supported=no
 | 
			
		||||
fi[]dnl
 | 
			
		||||
])# _PKG_SHORT_ERRORS_SUPPORTED
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
 | 
			
		||||
# [ACTION-IF-NOT-FOUND])
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# Note that if there is a possibility the first call to
 | 
			
		||||
# PKG_CHECK_MODULES might not happen, you should be sure to include an
 | 
			
		||||
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------
 | 
			
		||||
AC_DEFUN([PKG_CHECK_MODULES],
 | 
			
		||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
 | 
			
		||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
 | 
			
		||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
 | 
			
		||||
 | 
			
		||||
pkg_failed=no
 | 
			
		||||
AC_MSG_CHECKING([for $1])
 | 
			
		||||
 | 
			
		||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
 | 
			
		||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
 | 
			
		||||
 | 
			
		||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
 | 
			
		||||
and $1[]_LIBS to avoid the need to call pkg-config.
 | 
			
		||||
See the pkg-config man page for more details.])
 | 
			
		||||
 | 
			
		||||
if test $pkg_failed = yes; then
 | 
			
		||||
   	AC_MSG_RESULT([no])
 | 
			
		||||
        _PKG_SHORT_ERRORS_SUPPORTED
 | 
			
		||||
        if test $_pkg_short_errors_supported = yes; then
 | 
			
		||||
	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
 | 
			
		||||
        else 
 | 
			
		||||
	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
 | 
			
		||||
        fi
 | 
			
		||||
	# Put the nasty error message in config.log where it belongs
 | 
			
		||||
	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
 | 
			
		||||
 | 
			
		||||
	m4_default([$4], [AC_MSG_ERROR(
 | 
			
		||||
[Package requirements ($2) were not met:
 | 
			
		||||
 | 
			
		||||
$$1_PKG_ERRORS
 | 
			
		||||
 | 
			
		||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
 | 
			
		||||
installed software in a non-standard prefix.
 | 
			
		||||
 | 
			
		||||
_PKG_TEXT])
 | 
			
		||||
        ])
 | 
			
		||||
elif test $pkg_failed = untried; then
 | 
			
		||||
     	AC_MSG_RESULT([no])
 | 
			
		||||
	m4_default([$4], [AC_MSG_FAILURE(
 | 
			
		||||
[The pkg-config script could not be found or is too old.  Make sure it
 | 
			
		||||
is in your PATH or set the PKG_CONFIG environment variable to the full
 | 
			
		||||
path to pkg-config.
 | 
			
		||||
 | 
			
		||||
_PKG_TEXT
 | 
			
		||||
 | 
			
		||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])
 | 
			
		||||
        ])
 | 
			
		||||
else
 | 
			
		||||
	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
 | 
			
		||||
	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
 | 
			
		||||
        AC_MSG_RESULT([yes])
 | 
			
		||||
	$3
 | 
			
		||||
fi[]dnl
 | 
			
		||||
])# PKG_CHECK_MODULES
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1463
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1463
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										777
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										777
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,36 +1,62 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
#
 | 
			
		||||
# install - install a program, script, or datafile
 | 
			
		||||
# This comes from X11R5 (mit/util/scripts/install.sh).
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
# following copyright and license.
 | 
			
		||||
#
 | 
			
		||||
# Copyright 1991 by the Massachusetts Institute of Technology
 | 
			
		||||
# Copyright (C) 1994 X Consortium
 | 
			
		||||
#
 | 
			
		||||
# Permission to use, copy, modify, distribute, and sell this software and its
 | 
			
		||||
# documentation for any purpose is hereby granted without fee, provided that
 | 
			
		||||
# the above copyright notice appear in all copies and that both that
 | 
			
		||||
# copyright notice and this permission notice appear in supporting
 | 
			
		||||
# documentation, and that the name of M.I.T. not be used in advertising or
 | 
			
		||||
# publicity pertaining to distribution of the software without specific,
 | 
			
		||||
# written prior permission.  M.I.T. makes no representations about the
 | 
			
		||||
# suitability of this software for any purpose.  It is provided "as is"
 | 
			
		||||
# without express or implied warranty.
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to
 | 
			
		||||
# deal in the Software without restriction, including without limitation the
 | 
			
		||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 | 
			
		||||
# sell copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in
 | 
			
		||||
# all copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
			
		||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | 
			
		||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
 | 
			
		||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
#
 | 
			
		||||
# Except as contained in this notice, the name of the X Consortium shall not
 | 
			
		||||
# be used in advertising or otherwise to promote the sale, use or other deal-
 | 
			
		||||
# ings in this Software without prior written authorization from the X Consor-
 | 
			
		||||
# tium.
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# FSF changes to this file are in the public domain.
 | 
			
		||||
#
 | 
			
		||||
# Calling this script install-sh is preferred over install.sh, to prevent
 | 
			
		||||
# `make' implicit rules from creating a file called install from it
 | 
			
		||||
# 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}"
 | 
			
		||||
@@ -41,211 +67,441 @@ stripprog="${STRIPPROG-strip}"
 | 
			
		||||
rmprog="${RMPROG-rm}"
 | 
			
		||||
mkdirprog="${MKDIRPROG-mkdir}"
 | 
			
		||||
 | 
			
		||||
transformbasename=""
 | 
			
		||||
transform_arg=""
 | 
			
		||||
instcmd="$mvprog"
 | 
			
		||||
chmodcmd="$chmodprog 0755"
 | 
			
		||||
chowncmd=""
 | 
			
		||||
chgrpcmd=""
 | 
			
		||||
stripcmd=""
 | 
			
		||||
posix_glob=
 | 
			
		||||
posix_mkdir=
 | 
			
		||||
 | 
			
		||||
# Desired mode of installed file.
 | 
			
		||||
mode=0755
 | 
			
		||||
 | 
			
		||||
chmodcmd=$chmodprog
 | 
			
		||||
chowncmd=
 | 
			
		||||
chgrpcmd=
 | 
			
		||||
stripcmd=
 | 
			
		||||
rmcmd="$rmprog -f"
 | 
			
		||||
mvcmd="$mvprog"
 | 
			
		||||
src=""
 | 
			
		||||
dst=""
 | 
			
		||||
dir_arg=""
 | 
			
		||||
src=
 | 
			
		||||
dst=
 | 
			
		||||
dir_arg=
 | 
			
		||||
dstarg=
 | 
			
		||||
no_target_directory=
 | 
			
		||||
 | 
			
		||||
while [ x"$1" != x ]; do
 | 
			
		||||
    case $1 in
 | 
			
		||||
	-c) instcmd="$cpprog"
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
 | 
			
		||||
   or: $0 [OPTION]... SRCFILES... DIRECTORY
 | 
			
		||||
   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
 | 
			
		||||
   or: $0 [OPTION]... -d DIRECTORIES...
 | 
			
		||||
 | 
			
		||||
	-d) dir_arg=true
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
In the 1st form, copy SRCFILE to DSTFILE.
 | 
			
		||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
 | 
			
		||||
In the 4th, create DIRECTORIES.
 | 
			
		||||
 | 
			
		||||
	-m) chmodcmd="$chmodprog $2"
 | 
			
		||||
	    shift
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
Options:
 | 
			
		||||
-c         (ignored)
 | 
			
		||||
-d         create directories instead of installing files.
 | 
			
		||||
-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.
 | 
			
		||||
 | 
			
		||||
	-o) chowncmd="$chownprog $2"
 | 
			
		||||
	    shift
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
Environment variables override the default commands:
 | 
			
		||||
  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
 | 
			
		||||
"
 | 
			
		||||
 | 
			
		||||
	-g) chgrpcmd="$chgrpprog $2"
 | 
			
		||||
	    shift
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
while test $# -ne 0; do
 | 
			
		||||
  case $1 in
 | 
			
		||||
    -c) shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
	-s) stripcmd="$stripprog"
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
    -d) dir_arg=true
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
    -g) chgrpcmd="$chgrpprog $2"
 | 
			
		||||
        shift
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
    --help) echo "$usage"; exit $?;;
 | 
			
		||||
 | 
			
		||||
	*)  if [ x"$src" = x ]
 | 
			
		||||
	    then
 | 
			
		||||
		src=$1
 | 
			
		||||
	    else
 | 
			
		||||
		# this colon is to work around a 386BSD /bin/sh bug
 | 
			
		||||
		:
 | 
			
		||||
		dst=$1
 | 
			
		||||
	    fi
 | 
			
		||||
	    shift
 | 
			
		||||
	    continue;;
 | 
			
		||||
    esac
 | 
			
		||||
done
 | 
			
		||||
    -m) mode=$2
 | 
			
		||||
        shift
 | 
			
		||||
        shift
 | 
			
		||||
	case $mode in
 | 
			
		||||
	  *' '* | *'	'* | *'
 | 
			
		||||
'*	  | *'*'* | *'?'* | *'['*)
 | 
			
		||||
	    echo "$0: invalid mode: $mode" >&2
 | 
			
		||||
	    exit 1;;
 | 
			
		||||
	esac
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
if [ x"$src" = x ]
 | 
			
		||||
then
 | 
			
		||||
	echo "install:	no input file specified"
 | 
			
		||||
	exit 1
 | 
			
		||||
else
 | 
			
		||||
	true
 | 
			
		||||
fi
 | 
			
		||||
    -o) chowncmd="$chownprog $2"
 | 
			
		||||
        shift
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
if [ x"$dir_arg" != x ]; then
 | 
			
		||||
	dst=$src
 | 
			
		||||
	src=""
 | 
			
		||||
	
 | 
			
		||||
	if [ -d $dst ]; then
 | 
			
		||||
		instcmd=:
 | 
			
		||||
		chmodcmd=""
 | 
			
		||||
	else
 | 
			
		||||
		instcmd=mkdir
 | 
			
		||||
	fi
 | 
			
		||||
else
 | 
			
		||||
    -s) stripcmd=$stripprog
 | 
			
		||||
        shift
 | 
			
		||||
        continue;;
 | 
			
		||||
 | 
			
		||||
# 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 [ -f $src -o -d $src ]
 | 
			
		||||
	then
 | 
			
		||||
		true
 | 
			
		||||
	else
 | 
			
		||||
		echo "install:  $src does not exist"
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
	
 | 
			
		||||
	if [ x"$dst" = x ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "install:	no destination specified"
 | 
			
		||||
		exit 1
 | 
			
		||||
	else
 | 
			
		||||
		true
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
# If destination is a directory, append the input filename; if your system
 | 
			
		||||
# does not like double slashes in filenames, you may need to add some logic
 | 
			
		||||
 | 
			
		||||
	if [ -d $dst ]
 | 
			
		||||
	then
 | 
			
		||||
		dst="$dst"/`basename $src`
 | 
			
		||||
	else
 | 
			
		||||
		true
 | 
			
		||||
	fi
 | 
			
		||||
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 [ ! -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 [ $# -ne 0 ] ; do
 | 
			
		||||
	pathcomp="${pathcomp}${1}"
 | 
			
		||||
    -t) dstarg=$2
 | 
			
		||||
	shift
 | 
			
		||||
	shift
 | 
			
		||||
	continue;;
 | 
			
		||||
 | 
			
		||||
	if [ ! -d "${pathcomp}" ] ;
 | 
			
		||||
        then
 | 
			
		||||
		$mkdirprog "${pathcomp}"
 | 
			
		||||
	else
 | 
			
		||||
		true
 | 
			
		||||
	fi
 | 
			
		||||
    -T) no_target_directory=true
 | 
			
		||||
	shift
 | 
			
		||||
	continue;;
 | 
			
		||||
 | 
			
		||||
	pathcomp="${pathcomp}/"
 | 
			
		||||
    --version) echo "$0 $scriptversion"; exit $?;;
 | 
			
		||||
 | 
			
		||||
    --)	shift
 | 
			
		||||
	break;;
 | 
			
		||||
 | 
			
		||||
    -*)	echo "$0: invalid option: $1" >&2
 | 
			
		||||
	exit 1;;
 | 
			
		||||
 | 
			
		||||
    *)  break;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
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 [ x"$dir_arg" != x ]
 | 
			
		||||
then
 | 
			
		||||
	$doit $instcmd $dst &&
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
 | 
			
		||||
	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
 | 
			
		||||
	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
 | 
			
		||||
	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
 | 
			
		||||
else
 | 
			
		||||
if test -z "$dir_arg"; then
 | 
			
		||||
  trap '(exit $?); exit' 1 2 13 15
 | 
			
		||||
 | 
			
		||||
# If we're going to rename the final executable, determine the name now.
 | 
			
		||||
  # 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;;
 | 
			
		||||
 | 
			
		||||
	if [ x"$transformarg" = x ] 
 | 
			
		||||
	then
 | 
			
		||||
		dstfile=`basename $dst`
 | 
			
		||||
    *[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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
    if test -z "$dstarg"; then
 | 
			
		||||
      echo "$0: no destination specified." >&2
 | 
			
		||||
      exit 1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
		dstfile=`basename $dst $transformbasename | 
 | 
			
		||||
			sed $transformarg`$transformbasename
 | 
			
		||||
	  mkdir_mode=
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
# don't allow the sed command to completely eliminate the filename
 | 
			
		||||
	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 [ x"$dstfile" = x ] 
 | 
			
		||||
	then
 | 
			
		||||
		dstfile=`basename $dst`
 | 
			
		||||
	    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
 | 
			
		||||
		true
 | 
			
		||||
	  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
 | 
			
		||||
 | 
			
		||||
# Make a temp file name in the proper directory.
 | 
			
		||||
      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
 | 
			
		||||
 | 
			
		||||
	dsttmp=$dstdir/#inst.$$#
 | 
			
		||||
  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
 | 
			
		||||
 | 
			
		||||
# Move or copy the file name to the temp name
 | 
			
		||||
    # Make a couple of temp file names in the proper directory.
 | 
			
		||||
    dsttmp=$dstdir/_inst.$$_
 | 
			
		||||
    rmtmp=$dstdir/_rm.$$_
 | 
			
		||||
 | 
			
		||||
	$doit $instcmd $src $dsttmp &&
 | 
			
		||||
    # Trap to clean up those temp files at exit.
 | 
			
		||||
    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
 | 
			
		||||
 | 
			
		||||
	trap "rm -f ${dsttmp}" 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
 | 
			
		||||
    # 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"; } &&
 | 
			
		||||
 | 
			
		||||
# 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.
 | 
			
		||||
    # 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.
 | 
			
		||||
 | 
			
		||||
	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
 | 
			
		||||
	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
 | 
			
		||||
	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
 | 
			
		||||
	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
 | 
			
		||||
	   # Now 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.
 | 
			
		||||
	   # Now rename the file to the real destination.
 | 
			
		||||
	   $doit $mvcmd "$dsttmp" "$dst"
 | 
			
		||||
	 }
 | 
			
		||||
    } || exit 1
 | 
			
		||||
 | 
			
		||||
	$doit $rmcmd -f $dstdir/$dstfile &&
 | 
			
		||||
	$doit $mvcmd $dsttmp $dstdir/$dstfile 
 | 
			
		||||
    trap '' 0
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
fi &&
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exit 0
 | 
			
		||||
# Local variables:
 | 
			
		||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
 | 
			
		||||
# time-stamp-start: "scriptversion="
 | 
			
		||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
 | 
			
		||||
# time-stamp-end: "$"
 | 
			
		||||
# End:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1652
									
								
								configure.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1652
									
								
								configure.in
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										47
									
								
								daemons/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								daemons/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2004-2011 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
ifeq ("@BUILD_LVMETAD@", "yes")
 | 
			
		||||
  SUBDIRS += lvmetad
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
.PHONY: dmeventd clvmd cmirrord lvmetad
 | 
			
		||||
 | 
			
		||||
ifneq ("@CLVMD@", "none")
 | 
			
		||||
  SUBDIRS += clvmd
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@BUILD_CMIRRORD@", "yes")
 | 
			
		||||
  SUBDIRS += cmirrord
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ("@BUILD_DMEVENTD@", "yes")
 | 
			
		||||
  SUBDIRS += dmeventd
 | 
			
		||||
ifneq ("$(CFLOW_CMD)", "")
 | 
			
		||||
daemons.cflow: dmeventd.cflow
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
  SUBDIRS = clvmd cmirrord dmeventd lvmetad
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
ifeq ("@BUILD_DMEVENTD@", "yes")
 | 
			
		||||
device-mapper: dmeventd.device-mapper
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										107
									
								
								daemons/clvmd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								daemons/clvmd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
#
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
CMAN_LIBS = @CMAN_LIBS@
 | 
			
		||||
CMAN_CFLAGS = @CMAN_CFLAGS@
 | 
			
		||||
CMAP_LIBS = @CMAP_LIBS@
 | 
			
		||||
CMAP_CFLAGS = @CMAP_CFLAGS@
 | 
			
		||||
CONFDB_LIBS = @CONFDB_LIBS@
 | 
			
		||||
CONFDB_CFLAGS = @CONFDB_CFLAGS@
 | 
			
		||||
CPG_LIBS = @CPG_LIBS@
 | 
			
		||||
CPG_CFLAGS = @CPG_CFLAGS@
 | 
			
		||||
DLM_LIBS = @DLM_LIBS@
 | 
			
		||||
DLM_CFLAGS = @DLM_CFLAGS@
 | 
			
		||||
QUORUM_LIBS = @QUORUM_LIBS@
 | 
			
		||||
QUORUM_CFLAGS = @QUORUM_CFLAGS@
 | 
			
		||||
SALCK_LIBS = @SALCK_LIBS@
 | 
			
		||||
SALCK_CFLAGS = @SALCK_CFLAGS@
 | 
			
		||||
 | 
			
		||||
SOURCES = \
 | 
			
		||||
	clvmd-command.c  \
 | 
			
		||||
	clvmd.c          \
 | 
			
		||||
	lvm-functions.c  \
 | 
			
		||||
	refresh_clvmd.c
 | 
			
		||||
 | 
			
		||||
ifeq ("@DEBUG@", "yes")
 | 
			
		||||
	DEFS += -DDEBUG
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq (,$(findstring cman,, "@CLVMD@,"))
 | 
			
		||||
	SOURCES += clvmd-cman.c
 | 
			
		||||
	LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
 | 
			
		||||
	CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS)
 | 
			
		||||
	DEFS += -DUSE_CMAN
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq (,$(findstring openais,, "@CLVMD@,"))
 | 
			
		||||
	SOURCES += clvmd-openais.c
 | 
			
		||||
	LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS)
 | 
			
		||||
	CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS)
 | 
			
		||||
	DEFS += -DUSE_OPENAIS
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq (,$(findstring corosync,, "@CLVMD@,"))
 | 
			
		||||
	SOURCES += clvmd-corosync.c
 | 
			
		||||
	LMLIBS += $(CMAP_LIBS) $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS)
 | 
			
		||||
	CFLAGS += $(CMAP_CFLAGS) $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(DLM_CFLAGS) $(QUORUM_CFLAGS)
 | 
			
		||||
	DEFS += -DUSE_COROSYNC
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq (,$(findstring singlenode,, "@CLVMD@,"))
 | 
			
		||||
	SOURCES += clvmd-singlenode.c
 | 
			
		||||
	DEFS += -DUSE_SINGLENODE
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
	SOURCES += clvmd-cman.c
 | 
			
		||||
	SOURCES += clvmd-openais.c
 | 
			
		||||
	SOURCES += clvmd-corosync.c
 | 
			
		||||
	SOURCES += clvmd-singlenode.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
TARGETS = \
 | 
			
		||||
	clvmd
 | 
			
		||||
 | 
			
		||||
LVMLIBS = $(LVMINTERNAL_LIBS)
 | 
			
		||||
 | 
			
		||||
ifeq ("@DMEVENTD@", "yes")
 | 
			
		||||
	LVMLIBS += -ldevmapper-event
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
LVMLIBS += -ldevmapper
 | 
			
		||||
LIBS += $(PTHREAD_LIBS)
 | 
			
		||||
 | 
			
		||||
DEFS += -D_REENTRANT
 | 
			
		||||
CFLAGS += -fno-strict-aliasing
 | 
			
		||||
 | 
			
		||||
INSTALL_TARGETS = \
 | 
			
		||||
	install_clvmd
 | 
			
		||||
 | 
			
		||||
clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
 | 
			
		||||
	$(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \
 | 
			
		||||
		$(LVMLIBS) $(LMLIBS) $(LIBS)
 | 
			
		||||
 | 
			
		||||
.PHONY: install_clvmd
 | 
			
		||||
 | 
			
		||||
install_clvmd: $(TARGETS)
 | 
			
		||||
	$(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd
 | 
			
		||||
 | 
			
		||||
install: $(INSTALL_TARGETS)
 | 
			
		||||
 | 
			
		||||
install_cluster: $(INSTALL_TARGETS)
 | 
			
		||||
							
								
								
									
										82
									
								
								daemons/clvmd/clvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								daemons/clvmd/clvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Definitions for CLVMD server and clients */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The protocol spoken over the cluster and across the local socket.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _CLVM_H
 | 
			
		||||
#define _CLVM_H
 | 
			
		||||
 | 
			
		||||
#include "configure.h"
 | 
			
		||||
 | 
			
		||||
struct clvm_header {
 | 
			
		||||
	uint8_t  cmd;	        /* See below */
 | 
			
		||||
	uint8_t  flags;	        /* See below */
 | 
			
		||||
	uint16_t xid;	        /* Transaction ID */
 | 
			
		||||
	uint32_t clientid;	/* Only used in Daemon->Daemon comms */
 | 
			
		||||
	int32_t  status;	/* For replies, whether request succeeded */
 | 
			
		||||
	uint32_t arglen;	/* Length of argument below.
 | 
			
		||||
				   If >1500 then it will be passed
 | 
			
		||||
				   around the cluster in the system LV */
 | 
			
		||||
	char node[1];		/* Actually a NUL-terminated string, node name.
 | 
			
		||||
				   If this is empty then the command is
 | 
			
		||||
				   forwarded to all cluster nodes unless
 | 
			
		||||
				   FLAG_LOCAL or FLAG_REMOTE is also set. */
 | 
			
		||||
	char args[1];		/* Arguments for the command follow the
 | 
			
		||||
				   node name, This member is only
 | 
			
		||||
				   valid if the node name is empty */
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
/* Flags */
 | 
			
		||||
#define CLVMD_FLAG_LOCAL	1	/* Only do this on the local node */
 | 
			
		||||
#define CLVMD_FLAG_SYSTEMLV	2	/* Data in system LV under my node name */
 | 
			
		||||
#define CLVMD_FLAG_NODEERRS	4	/* Reply has errors in node-specific portion */
 | 
			
		||||
#define CLVMD_FLAG_REMOTE	8	/* Do this on all nodes except for the local node */
 | 
			
		||||
 | 
			
		||||
/* Name of the local socket to communicate between lvm and clvmd */
 | 
			
		||||
static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock";
 | 
			
		||||
 | 
			
		||||
/* Internal commands & replies */
 | 
			
		||||
#define CLVMD_CMD_REPLY    1
 | 
			
		||||
#define CLVMD_CMD_VERSION  2	/* Send version around cluster when we start */
 | 
			
		||||
#define CLVMD_CMD_GOAWAY   3	/* Die if received this - we are running
 | 
			
		||||
				   an incompatible version */
 | 
			
		||||
#define CLVMD_CMD_TEST     4	/* Just for mucking about */
 | 
			
		||||
 | 
			
		||||
#define CLVMD_CMD_LOCK              30
 | 
			
		||||
#define CLVMD_CMD_UNLOCK            31
 | 
			
		||||
 | 
			
		||||
/* Lock/Unlock commands */
 | 
			
		||||
#define CLVMD_CMD_LOCK_LV           50
 | 
			
		||||
#define CLVMD_CMD_LOCK_VG           51
 | 
			
		||||
#define CLVMD_CMD_LOCK_QUERY	    52
 | 
			
		||||
 | 
			
		||||
/* Misc functions */
 | 
			
		||||
#define CLVMD_CMD_REFRESH	    40
 | 
			
		||||
#define CLVMD_CMD_GET_CLUSTERNAME   41
 | 
			
		||||
#define CLVMD_CMD_SET_DEBUG	    42
 | 
			
		||||
#define CLVMD_CMD_VG_BACKUP	    43
 | 
			
		||||
#define CLVMD_CMD_RESTART	    44
 | 
			
		||||
#define CLVMD_CMD_SYNC_NAMES	    45
 | 
			
		||||
 | 
			
		||||
/* Used internally by some callers, but not part of the protocol.*/
 | 
			
		||||
#define NODE_ALL	"*"
 | 
			
		||||
#define NODE_LOCAL	"."
 | 
			
		||||
#define NODE_REMOTE	"^"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										506
									
								
								daemons/clvmd/clvmd-cman.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										506
									
								
								daemons/clvmd/clvmd-cman.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,506 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * CMAN communication layer for clvmd.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "clvmd-common.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
 | 
			
		||||
#include <libdlm.h>
 | 
			
		||||
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
 | 
			
		||||
#define LOCKSPACE_NAME "clvmd"
 | 
			
		||||
 | 
			
		||||
struct clvmd_node
 | 
			
		||||
{
 | 
			
		||||
	struct cman_node *node;
 | 
			
		||||
	int clvmd_up;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int num_nodes;
 | 
			
		||||
static struct cman_node *nodes = NULL;
 | 
			
		||||
static struct cman_node this_node;
 | 
			
		||||
static int count_nodes; /* size of allocated nodes array */
 | 
			
		||||
static struct dm_hash_table *node_updown_hash;
 | 
			
		||||
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(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;
 | 
			
		||||
	pthread_mutex_t mutex;
 | 
			
		||||
	struct dlm_lksb lksb;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _init_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	node_updown_hash = dm_hash_create(100);
 | 
			
		||||
 | 
			
		||||
	/* Open the cluster communication socket */
 | 
			
		||||
	c_handle = cman_init(NULL);
 | 
			
		||||
	if (!c_handle) {
 | 
			
		||||
		syslog(LOG_ERR, "Can't open cluster manager socket: %m");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	DEBUGLOG("Connected to CMAN\n");
 | 
			
		||||
 | 
			
		||||
	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_open_lockspace(LOCKSPACE_NAME);
 | 
			
		||||
	if (!lockspace) {
 | 
			
		||||
		lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
 | 
			
		||||
		if (!lockspace) {
 | 
			
		||||
			syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		DEBUGLOG("Created DLM lockspace for CLVMD.\n");
 | 
			
		||||
	} else
 | 
			
		||||
		DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
 | 
			
		||||
 | 
			
		||||
	dlm_ls_pthread_init(lockspace);
 | 
			
		||||
	DEBUGLOG("DLM initialisation complete\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cluster_init_completed(void)
 | 
			
		||||
{
 | 
			
		||||
	clvmd_cluster_init_completed();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_main_cluster_fd()
 | 
			
		||||
{
 | 
			
		||||
	return cman_get_fd(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_num_nodes()
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int nnodes = 0;
 | 
			
		||||
 | 
			
		||||
	/* return number of ACTIVE nodes */
 | 
			
		||||
	for (i=0; i<num_nodes; i++) {
 | 
			
		||||
		if (nodes[i].cn_member && nodes[i].cn_nodeid)
 | 
			
		||||
			nnodes++;
 | 
			
		||||
	}
 | 
			
		||||
	return nnodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send_message with the fd check removed */
 | 
			
		||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
 | 
			
		||||
				 const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	int nodeid = 0;
 | 
			
		||||
 | 
			
		||||
	if (csid)
 | 
			
		||||
		memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
 | 
			
		||||
	{
 | 
			
		||||
		log_error("%s", errtext);
 | 
			
		||||
	}
 | 
			
		||||
	return msglen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	if (this_node.cn_nodeid == 0) {
 | 
			
		||||
		cman_get_node(c_handle, 0, &this_node);
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
 | 
			
		||||
static int _cluster_do_node_callback(struct local_client *client,
 | 
			
		||||
				     void (*callback) (struct local_client *,
 | 
			
		||||
						       const char *,
 | 
			
		||||
						       int))
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int somedown = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < _get_num_nodes(); i++) {
 | 
			
		||||
		if (nodes[i].cn_member && nodes[i].cn_nodeid) {
 | 
			
		||||
			int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
 | 
			
		||||
 | 
			
		||||
			callback(client, (char *)&nodes[i].cn_nodeid, up);
 | 
			
		||||
			if (!up)
 | 
			
		||||
				somedown = -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return somedown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Process OOB messages from the cluster socket */
 | 
			
		||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
 | 
			
		||||
{
 | 
			
		||||
	char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
 | 
			
		||||
 | 
			
		||||
	switch (reason) {
 | 
			
		||||
        case CMAN_REASON_PORTCLOSED:
 | 
			
		||||
		name_from_nodeid(arg, namebuf);
 | 
			
		||||
		log_notice("clvmd on node %s has died\n", namebuf);
 | 
			
		||||
		DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
 | 
			
		||||
 | 
			
		||||
		dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CMAN_REASON_STATECHANGE:
 | 
			
		||||
		DEBUGLOG("Got state change message, re-reading members list\n");
 | 
			
		||||
		get_members();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
 | 
			
		||||
	case CMAN_REASON_PORTOPENED:
 | 
			
		||||
		/* Ignore this, wait for startup message from clvmd itself */
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CMAN_REASON_TRY_SHUTDOWN:
 | 
			
		||||
		DEBUGLOG("Got try shutdown, sending OK\n");
 | 
			
		||||
		cman_replyto_shutdown(c_handle, 1);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		/* ERROR */
 | 
			
		||||
		DEBUGLOG("Got unknown event callback message: %d\n", reason);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct local_client *cman_client;
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
 | 
			
		||||
				const char *csid,
 | 
			
		||||
				struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	/* Save this for data_callback */
 | 
			
		||||
	cman_client = fd;
 | 
			
		||||
 | 
			
		||||
	/* We never return a new client */
 | 
			
		||||
	*new_client = NULL;
 | 
			
		||||
 | 
			
		||||
	return cman_dispatch(c_handle, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void data_callback(cman_handle_t handle, void *private,
 | 
			
		||||
			  char *buf, int len, uint8_t port, int nodeid)
 | 
			
		||||
{
 | 
			
		||||
	/* Ignore looped back messages */
 | 
			
		||||
	if (nodeid == this_node.cn_nodeid)
 | 
			
		||||
		return;
 | 
			
		||||
	process_message(cman_client, buf, len, (char *)&nodeid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _add_up_node(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	/* It's up ! */
 | 
			
		||||
	int nodeid = nodeid_from_csid(csid);
 | 
			
		||||
 | 
			
		||||
	dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
 | 
			
		||||
	DEBUGLOG("Added new node %d to updown list\n", nodeid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cluster_closedown()
 | 
			
		||||
{
 | 
			
		||||
	destroy_lvhash();
 | 
			
		||||
	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
 | 
			
		||||
	cman_finish(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_listening(int nodeid)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
 | 
			
		||||
		if (status < 0 && errno == EBUSY) {	/* Don't busywait */
 | 
			
		||||
			sleep(1);
 | 
			
		||||
			errno = EBUSY;	/* In case sleep trashes it */
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	while (status < 0 && errno == EBUSY);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Populate the list of CLVMDs running.
 | 
			
		||||
   called only at startup time */
 | 
			
		||||
static void count_clvmds_running(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		int nodeid = nodes[i].cn_nodeid;
 | 
			
		||||
 | 
			
		||||
		if (is_listening(nodeid) == 1)
 | 
			
		||||
			dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
 | 
			
		||||
		else
 | 
			
		||||
			dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get a list of active cluster members */
 | 
			
		||||
static void get_members()
 | 
			
		||||
{
 | 
			
		||||
	int retnodes;
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
	int high_nodeid = 0;
 | 
			
		||||
 | 
			
		||||
	num_nodes = cman_get_node_count(c_handle);
 | 
			
		||||
	if (num_nodes == -1) {
 | 
			
		||||
		log_error("Unable to get node count");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Not enough room for new nodes list ? */
 | 
			
		||||
	if (num_nodes > count_nodes && nodes) {
 | 
			
		||||
		free(nodes);
 | 
			
		||||
		nodes = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (nodes == NULL) {
 | 
			
		||||
		count_nodes = num_nodes + 10; /* Overallocate a little */
 | 
			
		||||
		nodes = malloc(count_nodes * sizeof(struct cman_node));
 | 
			
		||||
		if (!nodes) {
 | 
			
		||||
			log_error("Unable to allocate nodes array\n");
 | 
			
		||||
			exit(5);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
 | 
			
		||||
	if (status < 0) {
 | 
			
		||||
		log_error("Unable to get node details");
 | 
			
		||||
		exit(6);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the highest nodeid */
 | 
			
		||||
	for (i=0; i<retnodes; i++) {
 | 
			
		||||
		if (nodes[i].cn_nodeid > high_nodeid)
 | 
			
		||||
			high_nodeid = nodes[i].cn_nodeid;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Convert a node name to a CSID */
 | 
			
		||||
static int _csid_from_name(char *csid, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (strcmp(name, nodes[i].cn_name) == 0) {
 | 
			
		||||
			memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a CSID to a node name */
 | 
			
		||||
static int _name_from_csid(const char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
 | 
			
		||||
			strcpy(name, nodes[i].cn_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/* Who?? */
 | 
			
		||||
	strcpy(name, "Unknown");
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a node ID to a node name */
 | 
			
		||||
static int name_from_nodeid(int nodeid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_nodes; i++) {
 | 
			
		||||
		if (nodeid == nodes[i].cn_nodeid) {
 | 
			
		||||
			strcpy(name, nodes[i].cn_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/* Who?? */
 | 
			
		||||
	strcpy(name, "Unknown");
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert a CSID to a node ID */
 | 
			
		||||
static int nodeid_from_csid(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
        int nodeid;
 | 
			
		||||
 | 
			
		||||
	memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	return nodeid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _is_quorate()
 | 
			
		||||
{
 | 
			
		||||
	return cman_is_quorate(c_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sync_ast_routine(void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct lock_wait *lwait = arg;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lwait->mutex);
 | 
			
		||||
	pthread_cond_signal(&lwait->cond);
 | 
			
		||||
	pthread_mutex_unlock(&lwait->mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	struct lock_wait lwait;
 | 
			
		||||
 | 
			
		||||
	if (!lockid) {
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
 | 
			
		||||
	/* Conversions need the lockid in the LKSB */
 | 
			
		||||
	if (flags & LKF_CONVERT)
 | 
			
		||||
		lwait.lksb.sb_lkid = *lockid;
 | 
			
		||||
 | 
			
		||||
	pthread_cond_init(&lwait.cond, NULL);
 | 
			
		||||
	pthread_mutex_init(&lwait.mutex, NULL);
 | 
			
		||||
	pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	status = dlm_ls_lock(lockspace,
 | 
			
		||||
			     mode,
 | 
			
		||||
			     &lwait.lksb,
 | 
			
		||||
			     flags,
 | 
			
		||||
			     resource,
 | 
			
		||||
			     strlen(resource),
 | 
			
		||||
			     0, sync_ast_routine, &lwait, NULL, NULL);
 | 
			
		||||
	if (status)
 | 
			
		||||
		return status;
 | 
			
		||||
 | 
			
		||||
	/* Wait for it to complete */
 | 
			
		||||
	pthread_cond_wait(&lwait.cond, &lwait.mutex);
 | 
			
		||||
	pthread_mutex_unlock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	*lockid = lwait.lksb.sb_lkid;
 | 
			
		||||
 | 
			
		||||
	errno = lwait.lksb.sb_status;
 | 
			
		||||
	DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
 | 
			
		||||
	if (lwait.lksb.sb_status)
 | 
			
		||||
		return -1;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	struct lock_wait lwait;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
 | 
			
		||||
 | 
			
		||||
	pthread_cond_init(&lwait.cond, NULL);
 | 
			
		||||
	pthread_mutex_init(&lwait.mutex, NULL);
 | 
			
		||||
	pthread_mutex_lock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
 | 
			
		||||
 | 
			
		||||
	if (status)
 | 
			
		||||
		return status;
 | 
			
		||||
 | 
			
		||||
	/* Wait for it to complete */
 | 
			
		||||
	pthread_cond_wait(&lwait.cond, &lwait.mutex);
 | 
			
		||||
	pthread_mutex_unlock(&lwait.mutex);
 | 
			
		||||
 | 
			
		||||
	errno = lwait.lksb.sb_status;
 | 
			
		||||
	if (lwait.lksb.sb_status != EUNLOCK)
 | 
			
		||||
		return -1;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static 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 = {
 | 
			
		||||
	.name                     = "cman",
 | 
			
		||||
	.cluster_init_completed   = _cluster_init_completed,
 | 
			
		||||
	.cluster_send_message     = _cluster_send_message,
 | 
			
		||||
	.name_from_csid           = _name_from_csid,
 | 
			
		||||
	.csid_from_name           = _csid_from_name,
 | 
			
		||||
	.get_num_nodes            = _get_num_nodes,
 | 
			
		||||
	.cluster_fd_callback      = _cluster_fd_callback,
 | 
			
		||||
	.get_main_cluster_fd      = _get_main_cluster_fd,
 | 
			
		||||
	.cluster_do_node_callback = _cluster_do_node_callback,
 | 
			
		||||
	.is_quorate               = _is_quorate,
 | 
			
		||||
	.get_our_csid             = _get_our_csid,
 | 
			
		||||
	.add_up_node              = _add_up_node,
 | 
			
		||||
	.cluster_closedown        = _cluster_closedown,
 | 
			
		||||
	.get_cluster_name         = _get_cluster_name,
 | 
			
		||||
	.sync_lock                = _sync_lock,
 | 
			
		||||
	.sync_unlock              = _sync_unlock,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cluster_ops *init_cman_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!_init_cluster())
 | 
			
		||||
		return &_cluster_cman_ops;
 | 
			
		||||
	else
 | 
			
		||||
		return NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										434
									
								
								daemons/clvmd/clvmd-command.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								daemons/clvmd/clvmd-command.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,434 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  CLVMD Cluster LVM daemon command processor.
 | 
			
		||||
 | 
			
		||||
  To add commands to the daemon simply add a processor in do_command and return
 | 
			
		||||
  and messages back in buf and the length in *retlen. The initial value of
 | 
			
		||||
  buflen is the maximum size of the buffer. if buf is not large enough then it
 | 
			
		||||
  may be reallocated by the functions in here to a suitable size bearing in
 | 
			
		||||
  mind that anything larger than the passed-in size will have to be returned
 | 
			
		||||
  using the system LV and so performance will suffer.
 | 
			
		||||
 | 
			
		||||
  The status return will be negated and passed back to the originating node.
 | 
			
		||||
 | 
			
		||||
  pre- and post- command routines are called only on the local node. The
 | 
			
		||||
  purpose is primarily to get and release locks, though the pre- routine should
 | 
			
		||||
  also do any other local setups required by the command (if any) and can
 | 
			
		||||
  return a failure code that prevents the command from being distributed around
 | 
			
		||||
  the cluster
 | 
			
		||||
 | 
			
		||||
  The pre- and post- routines are run in their own thread so can block as long
 | 
			
		||||
  they like, do_command is run in the main clvmd thread so should not block for
 | 
			
		||||
  too long. If the pre-command returns an error code (!=0) then the command
 | 
			
		||||
  will not be propogated around the cluster but the post-command WILL be called
 | 
			
		||||
 | 
			
		||||
  Also note that the pre and post routine are *always* called on the local
 | 
			
		||||
  node, even if the command to be executed was only requested to run on a
 | 
			
		||||
  remote node. It may peek inside the client structure to check the status of
 | 
			
		||||
  the command.
 | 
			
		||||
 | 
			
		||||
  The clients of the daemon must, naturally, understand the return messages and
 | 
			
		||||
  codes.
 | 
			
		||||
 | 
			
		||||
  Routines in here may only READ the values in the client structure passed in
 | 
			
		||||
  apart from client->private which they are free to do what they like with.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "clvmd-common.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "lvm-globals.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
 | 
			
		||||
extern struct cluster_ops *clops;
 | 
			
		||||
static int restart_clvmd(void);
 | 
			
		||||
 | 
			
		||||
/* This is where all the real work happens:
 | 
			
		||||
   NOTE: client will be NULL when this is executed on a remote node */
 | 
			
		||||
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
 | 
			
		||||
	       char **buf, int buflen, int *retlen)
 | 
			
		||||
{
 | 
			
		||||
	char *args = msg->node + strlen(msg->node) + 1;
 | 
			
		||||
	int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	char *lockname;
 | 
			
		||||
	const char *locktype;
 | 
			
		||||
	struct utsname nodeinfo;
 | 
			
		||||
	unsigned char lock_cmd;
 | 
			
		||||
	unsigned char lock_flags;
 | 
			
		||||
 | 
			
		||||
	/* Reset test mode before we start */
 | 
			
		||||
	init_test(0);
 | 
			
		||||
 | 
			
		||||
	/* Do the command */
 | 
			
		||||
	switch (msg->cmd) {
 | 
			
		||||
		/* Just a test message */
 | 
			
		||||
	case CLVMD_CMD_TEST:
 | 
			
		||||
		if (arglen > buflen) {
 | 
			
		||||
			char *new_buf;
 | 
			
		||||
			buflen = arglen + 200;
 | 
			
		||||
			new_buf = realloc(*buf, buflen);
 | 
			
		||||
			if (new_buf == NULL) {
 | 
			
		||||
				status = errno;
 | 
			
		||||
				free (*buf);
 | 
			
		||||
			}
 | 
			
		||||
			*buf = new_buf;
 | 
			
		||||
		}
 | 
			
		||||
		if (*buf) {
 | 
			
		||||
			if (uname(&nodeinfo))
 | 
			
		||||
				memset(&nodeinfo, 0, sizeof(nodeinfo));
 | 
			
		||||
 | 
			
		||||
			*retlen = 1 + dm_snprintf(*buf, buflen,
 | 
			
		||||
						  "TEST from %s: %s v%s",
 | 
			
		||||
						  nodeinfo.nodename, args,
 | 
			
		||||
						  nodeinfo.release);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_VG:
 | 
			
		||||
		lock_cmd = args[0];
 | 
			
		||||
		lock_flags = args[1];
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		/* Check to see if the VG is in use by LVM1 */
 | 
			
		||||
		status = do_check_lvm1(lockname);
 | 
			
		||||
		if (lock_flags & LCK_TEST_MODE)
 | 
			
		||||
			init_test(1);
 | 
			
		||||
		do_lock_vg(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_LV:
 | 
			
		||||
		/* This is the biggie */
 | 
			
		||||
		lock_cmd = args[0];
 | 
			
		||||
		lock_flags = args[1];
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		if (lock_flags & LCK_TEST_MODE)
 | 
			
		||||
			init_test(1);
 | 
			
		||||
		status = do_lock_lv(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		/* Replace EIO with something less scary */
 | 
			
		||||
		if (status == EIO) {
 | 
			
		||||
			*retlen = 1 + dm_snprintf(*buf, buflen, "%s",
 | 
			
		||||
						  get_last_lvm_error());
 | 
			
		||||
			return EIO;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_QUERY:
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		if (buflen < 3)
 | 
			
		||||
			return EIO;
 | 
			
		||||
		if ((locktype = do_lock_query(lockname)))
 | 
			
		||||
			*retlen = 1 + dm_snprintf(*buf, buflen, "%s", locktype);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_REFRESH:
 | 
			
		||||
		do_refresh_cache();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_SYNC_NAMES:
 | 
			
		||||
		lvm_do_fs_unlock();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_SET_DEBUG:
 | 
			
		||||
		clvmd_set_debug((debug_t) args[0]);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_RESTART:
 | 
			
		||||
		status = restart_clvmd();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_GET_CLUSTERNAME:
 | 
			
		||||
		status = clops->get_cluster_name(*buf, buflen);
 | 
			
		||||
		if (!status)
 | 
			
		||||
			*retlen = strlen(*buf)+1;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_VG_BACKUP:
 | 
			
		||||
		/*
 | 
			
		||||
		 * Do not run backup on local node, caller should do that.
 | 
			
		||||
		 */
 | 
			
		||||
		if (!client)
 | 
			
		||||
			lvm_do_backup(&args[2]);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		/* Won't get here because command is validated in pre_command */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check the status of the command and return the error text */
 | 
			
		||||
	if (status) {
 | 
			
		||||
		*retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s",
 | 
			
		||||
						    strerror(status)) : -1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int lock_vg(struct local_client *client)
 | 
			
		||||
{
 | 
			
		||||
    struct dm_hash_table *lock_hash;
 | 
			
		||||
    struct clvm_header *header =
 | 
			
		||||
	(struct clvm_header *) client->bits.localsock.cmd;
 | 
			
		||||
    unsigned char lock_cmd;
 | 
			
		||||
    int lock_mode;
 | 
			
		||||
    char *args = header->node + strlen(header->node) + 1;
 | 
			
		||||
    int lkid;
 | 
			
		||||
    int status = 0;
 | 
			
		||||
    char *lockname;
 | 
			
		||||
 | 
			
		||||
    /* Keep a track of VG locks in our own hash table. In current
 | 
			
		||||
       practice there should only ever be more than two VGs locked
 | 
			
		||||
       if a user tries to merge lots of them at once */
 | 
			
		||||
    if (client->bits.localsock.private) {
 | 
			
		||||
	lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	lock_hash = dm_hash_create(3);
 | 
			
		||||
	if (!lock_hash)
 | 
			
		||||
	    return ENOMEM;
 | 
			
		||||
	client->bits.localsock.private = (void *)lock_hash;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
 | 
			
		||||
    lock_mode = ((int)lock_cmd & LCK_TYPE_MASK);
 | 
			
		||||
    /* lock_flags = args[1]; */
 | 
			
		||||
    lockname = &args[2];
 | 
			
		||||
    DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
 | 
			
		||||
 | 
			
		||||
    if (lock_mode == LCK_UNLOCK) {
 | 
			
		||||
 | 
			
		||||
	lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
 | 
			
		||||
	if (lkid == 0)
 | 
			
		||||
	    return EINVAL;
 | 
			
		||||
 | 
			
		||||
	status = sync_unlock(lockname, lkid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    status = errno;
 | 
			
		||||
	else
 | 
			
		||||
	    dm_hash_remove(lock_hash, lockname);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	/* Read locks need to be PR; other modes get passed through */
 | 
			
		||||
	if (lock_mode == LCK_READ)
 | 
			
		||||
	    lock_mode = LCK_PREAD;
 | 
			
		||||
	status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid);
 | 
			
		||||
	if (status)
 | 
			
		||||
	    status = errno;
 | 
			
		||||
	else
 | 
			
		||||
	    if (!dm_hash_insert(lock_hash, lockname, (void *)(long)lkid))
 | 
			
		||||
                    return ENOMEM;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Pre-command is a good place to get locks that are needed only for the duration
 | 
			
		||||
   of the commands around the cluster (don't forget to free them in post-command),
 | 
			
		||||
   and to sanity check the command arguments */
 | 
			
		||||
int do_pre_command(struct local_client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct clvm_header *header =
 | 
			
		||||
	    (struct clvm_header *) client->bits.localsock.cmd;
 | 
			
		||||
	unsigned char lock_cmd;
 | 
			
		||||
	unsigned char lock_flags;
 | 
			
		||||
	char *args = header->node + strlen(header->node) + 1;
 | 
			
		||||
	int lockid = 0;
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	char *lockname;
 | 
			
		||||
 | 
			
		||||
	init_test(0);
 | 
			
		||||
	switch (header->cmd) {
 | 
			
		||||
	case CLVMD_CMD_TEST:
 | 
			
		||||
		status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
 | 
			
		||||
		client->bits.localsock.private = (void *)(long)lockid;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_VG:
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		/* We take out a real lock unless LCK_CACHE was set */
 | 
			
		||||
		if (!strncmp(lockname, "V_", 2) ||
 | 
			
		||||
		    !strncmp(lockname, "P_#", 3))
 | 
			
		||||
			status = lock_vg(client);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_LV:
 | 
			
		||||
		lock_cmd = args[0];
 | 
			
		||||
		lock_flags = args[1];
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		if (lock_flags & LCK_TEST_MODE)
 | 
			
		||||
			init_test(1);
 | 
			
		||||
		status = pre_lock_lv(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_REFRESH:
 | 
			
		||||
	case CLVMD_CMD_GET_CLUSTERNAME:
 | 
			
		||||
	case CLVMD_CMD_SET_DEBUG:
 | 
			
		||||
	case CLVMD_CMD_VG_BACKUP:
 | 
			
		||||
	case CLVMD_CMD_SYNC_NAMES:
 | 
			
		||||
	case CLVMD_CMD_LOCK_QUERY:
 | 
			
		||||
	case CLVMD_CMD_RESTART:
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		log_error("Unknown command %d received\n", header->cmd);
 | 
			
		||||
		status = EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Note that the post-command routine is called even if the pre-command or the real command
 | 
			
		||||
   failed */
 | 
			
		||||
int do_post_command(struct local_client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct clvm_header *header =
 | 
			
		||||
	    (struct clvm_header *) client->bits.localsock.cmd;
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	unsigned char lock_cmd;
 | 
			
		||||
	unsigned char lock_flags;
 | 
			
		||||
	char *args = header->node + strlen(header->node) + 1;
 | 
			
		||||
	char *lockname;
 | 
			
		||||
 | 
			
		||||
	init_test(0);
 | 
			
		||||
	switch (header->cmd) {
 | 
			
		||||
	case CLVMD_CMD_TEST:
 | 
			
		||||
		status =
 | 
			
		||||
		    sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
 | 
			
		||||
		client->bits.localsock.private = 0;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CLVMD_CMD_LOCK_LV:
 | 
			
		||||
		lock_cmd = args[0];
 | 
			
		||||
		lock_flags = args[1];
 | 
			
		||||
		lockname = &args[2];
 | 
			
		||||
		if (lock_flags & LCK_TEST_MODE)
 | 
			
		||||
			init_test(1);
 | 
			
		||||
		status = post_lock_lv(lock_cmd, lock_flags, lockname);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		/* Nothing to do here */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Called when the client is about to be deleted */
 | 
			
		||||
void cmd_client_cleanup(struct local_client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_hash_node *v;
 | 
			
		||||
	struct dm_hash_table *lock_hash;
 | 
			
		||||
	int lkid;
 | 
			
		||||
	char *lockname;
 | 
			
		||||
 | 
			
		||||
	if (!client->bits.localsock.private)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
 | 
			
		||||
 | 
			
		||||
	dm_hash_iterate(v, lock_hash) {
 | 
			
		||||
		lkid = (int)(long)dm_hash_get_data(lock_hash, v);
 | 
			
		||||
		lockname = dm_hash_get_key(lock_hash, v);
 | 
			
		||||
		DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
 | 
			
		||||
		(void) sync_unlock(lockname, lkid);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_hash_destroy(lock_hash);
 | 
			
		||||
	client->bits.localsock.private = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int restart_clvmd(void)
 | 
			
		||||
{
 | 
			
		||||
	const char **argv;
 | 
			
		||||
	char *lv_name;
 | 
			
		||||
	int argc = 0, max_locks = 0;
 | 
			
		||||
	struct dm_hash_node *hn = NULL;
 | 
			
		||||
	char debug_arg[16];
 | 
			
		||||
	const char *clvmd = getenv("LVM_CLVMD_BINARY") ? : CLVMD_PATH;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("clvmd restart requested\n");
 | 
			
		||||
 | 
			
		||||
	/* Count exclusively-open LVs */
 | 
			
		||||
	do {
 | 
			
		||||
		hn = get_next_excl_lock(hn, &lv_name);
 | 
			
		||||
		if (lv_name) {
 | 
			
		||||
			max_locks++;
 | 
			
		||||
			if (!*lv_name)
 | 
			
		||||
				break; /* FIXME: Is this error ? */
 | 
			
		||||
		}
 | 
			
		||||
	} while (hn);
 | 
			
		||||
 | 
			
		||||
	/* clvmd + locks (-E uuid) + debug (-d X) + NULL */
 | 
			
		||||
	if (!(argv = malloc((max_locks * 2 + 5) * sizeof(*argv))))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Build the command-line
 | 
			
		||||
	 */
 | 
			
		||||
	argv[argc++] = "clvmd";
 | 
			
		||||
 | 
			
		||||
	/* Propogate debug options */
 | 
			
		||||
	if (clvmd_get_debug()) {
 | 
			
		||||
		if (dm_snprintf(debug_arg, sizeof(debug_arg), "-d%u", clvmd_get_debug()) < 0)
 | 
			
		||||
			goto_out;
 | 
			
		||||
		argv[argc++] = debug_arg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	argv[argc++] = "-I";
 | 
			
		||||
	argv[argc++] = clops->name;
 | 
			
		||||
 | 
			
		||||
	/* Now add the exclusively-open LVs */
 | 
			
		||||
	hn = NULL;
 | 
			
		||||
	do {
 | 
			
		||||
		hn = get_next_excl_lock(hn, &lv_name);
 | 
			
		||||
		if (lv_name) {
 | 
			
		||||
			if (!*lv_name)
 | 
			
		||||
				break; /* FIXME: Is this error ? */
 | 
			
		||||
			argv[argc++] = "-E";
 | 
			
		||||
			argv[argc++] = lv_name;
 | 
			
		||||
			DEBUGLOG("excl lock: %s\n", lv_name);
 | 
			
		||||
		}
 | 
			
		||||
	} while (hn);
 | 
			
		||||
	argv[argc] = NULL;
 | 
			
		||||
 | 
			
		||||
	/* Exec new clvmd */
 | 
			
		||||
	DEBUGLOG("--- Restarting %s ---\n", clvmd);
 | 
			
		||||
	for (argc = 1; argv[argc]; argc++) DEBUGLOG("--- %d: %s\n", argc, argv[argc]);
 | 
			
		||||
 | 
			
		||||
	/* NOTE: This will fail when downgrading! */
 | 
			
		||||
	execvp(clvmd, (char **)argv);
 | 
			
		||||
out:
 | 
			
		||||
	/* We failed */
 | 
			
		||||
	DEBUGLOG("Restart of clvmd failed.\n");
 | 
			
		||||
 | 
			
		||||
	free(argv);
 | 
			
		||||
 | 
			
		||||
	return EIO;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								daemons/clvmd/clvmd-common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								daemons/clvmd/clvmd-common.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This file must be included first by every clvmd source file.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _LVM_CLVMD_COMMON_H
 | 
			
		||||
#define _LVM_CLVMD_COMMON_H
 | 
			
		||||
 | 
			
		||||
#include "configure.h"
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
#define _FILE_OFFSET_BITS 64
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
 | 
			
		||||
#include "lvm-logging.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										119
									
								
								daemons/clvmd/clvmd-comms.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								daemons/clvmd/clvmd-comms.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Abstraction layer for clvmd cluster communications
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _CLVMD_COMMS_H
 | 
			
		||||
#define _CLVMD_COMMS_H
 | 
			
		||||
 | 
			
		||||
struct local_client;
 | 
			
		||||
 | 
			
		||||
struct cluster_ops {
 | 
			
		||||
	const char *name;
 | 
			
		||||
	void (*cluster_init_completed) (void);
 | 
			
		||||
 | 
			
		||||
	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,
 | 
			
		||||
				    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 *,
 | 
			
		||||
							   const char *csid,
 | 
			
		||||
							   int node_up));
 | 
			
		||||
	int (*is_quorate) (void);
 | 
			
		||||
 | 
			
		||||
	void (*get_our_csid) (char *csid);
 | 
			
		||||
	void (*add_up_node) (const char *csid);
 | 
			
		||||
	void (*reread_config) (void);
 | 
			
		||||
	void (*cluster_closedown) (void);
 | 
			
		||||
 | 
			
		||||
	int (*get_cluster_name)(char *buf, int buflen);
 | 
			
		||||
 | 
			
		||||
	int (*sync_lock) (const char *resource, int mode,
 | 
			
		||||
			  int flags, int *lockid);
 | 
			
		||||
	int (*sync_unlock) (const char *resource, int lockid);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef USE_CMAN
 | 
			
		||||
#  include <netinet/in.h>
 | 
			
		||||
#  include "libcman.h"
 | 
			
		||||
#  define CMAN_MAX_CSID_LEN 4
 | 
			
		||||
#  ifndef MAX_CSID_LEN
 | 
			
		||||
#    define MAX_CSID_LEN CMAN_MAX_CSID_LEN
 | 
			
		||||
#  endif
 | 
			
		||||
#  undef MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#  define MAX_CLUSTER_MEMBER_NAME_LEN   CMAN_MAX_NODENAME_LEN
 | 
			
		||||
#  define CMAN_MAX_CLUSTER_MESSAGE 1500
 | 
			
		||||
#  define CLUSTER_PORT_CLVMD 11
 | 
			
		||||
struct cluster_ops *init_cman_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_OPENAIS
 | 
			
		||||
#  include <openais/saAis.h>
 | 
			
		||||
#  include <corosync/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
 | 
			
		||||
 | 
			
		||||
#ifdef USE_COROSYNC
 | 
			
		||||
#  include <corosync/corotypes.h>
 | 
			
		||||
#  define COROSYNC_CSID_LEN (sizeof(int))
 | 
			
		||||
#  define COROSYNC_MAX_CLUSTER_MESSAGE         65535
 | 
			
		||||
#  define COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
 | 
			
		||||
#  ifndef MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#    define MAX_CLUSTER_MEMBER_NAME_LEN       CS_MAX_NAME_LENGTH
 | 
			
		||||
#  endif
 | 
			
		||||
#  ifndef CMAN_MAX_CLUSTER_MESSAGE
 | 
			
		||||
#    define CMAN_MAX_CLUSTER_MESSAGE          65535
 | 
			
		||||
#  endif
 | 
			
		||||
#  ifndef MAX_CSID_LEN
 | 
			
		||||
#    define MAX_CSID_LEN sizeof(int)
 | 
			
		||||
#  endif
 | 
			
		||||
struct cluster_ops *init_corosync_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SINGLENODE
 | 
			
		||||
#  define SINGLENODE_CSID_LEN (sizeof(int))
 | 
			
		||||
#  ifndef MAX_CLUSTER_MEMBER_NAME_LEN
 | 
			
		||||
#    define MAX_CLUSTER_MEMBER_NAME_LEN       64
 | 
			
		||||
#  endif
 | 
			
		||||
#  define SINGLENODE_MAX_CLUSTER_MESSAGE          65535
 | 
			
		||||
#  ifndef MAX_CSID_LEN
 | 
			
		||||
#    define MAX_CSID_LEN sizeof(int)
 | 
			
		||||
#  endif
 | 
			
		||||
struct cluster_ops *init_singlenode_cluster(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										684
									
								
								daemons/clvmd/clvmd-corosync.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										684
									
								
								daemons/clvmd/clvmd-corosync.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,684 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2009-2012 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This provides the interface between clvmd and corosync/DLM as the cluster
 | 
			
		||||
 * and lock manager.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "clvmd-common.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
 | 
			
		||||
#include <corosync/cpg.h>
 | 
			
		||||
#include <corosync/quorum.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_COROSYNC_CONFDB_H
 | 
			
		||||
#  include <corosync/confdb.h>
 | 
			
		||||
#elif defined HAVE_COROSYNC_CMAP_H
 | 
			
		||||
#  include <corosync/cmap.h>
 | 
			
		||||
#else
 | 
			
		||||
#  error "Either HAVE_COROSYNC_CONFDB_H or HAVE_COROSYNC_CMAP_H must be defined."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <libdlm.h>
 | 
			
		||||
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
 | 
			
		||||
/* Timeout value for several corosync calls */
 | 
			
		||||
#define LOCKSPACE_NAME "clvmd"
 | 
			
		||||
 | 
			
		||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
 | 
			
		||||
				  const struct cpg_name *groupName,
 | 
			
		||||
				  uint32_t nodeid,
 | 
			
		||||
				  uint32_t pid,
 | 
			
		||||
				  void *msg,
 | 
			
		||||
				  size_t msg_len);
 | 
			
		||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
 | 
			
		||||
				 const struct cpg_name *groupName,
 | 
			
		||||
				 const struct cpg_address *member_list, size_t member_list_entries,
 | 
			
		||||
				 const struct cpg_address *left_list, size_t left_list_entries,
 | 
			
		||||
				 const struct cpg_address *joined_list, size_t joined_list_entries);
 | 
			
		||||
static void _cluster_closedown(void);
 | 
			
		||||
 | 
			
		||||
/* Hash list of nodes in the cluster */
 | 
			
		||||
static struct dm_hash_table *node_hash;
 | 
			
		||||
 | 
			
		||||
/* Number of active nodes */
 | 
			
		||||
static int num_nodes;
 | 
			
		||||
static unsigned int our_nodeid;
 | 
			
		||||
 | 
			
		||||
static struct local_client *cluster_client;
 | 
			
		||||
 | 
			
		||||
/* Corosync handles */
 | 
			
		||||
static cpg_handle_t cpg_handle;
 | 
			
		||||
static quorum_handle_t quorum_handle;
 | 
			
		||||
 | 
			
		||||
/* DLM Handle */
 | 
			
		||||
static dlm_lshandle_t *lockspace;
 | 
			
		||||
 | 
			
		||||
static struct cpg_name cpg_group_name;
 | 
			
		||||
 | 
			
		||||
/* Corosync callback structs */
 | 
			
		||||
cpg_callbacks_t corosync_cpg_callbacks = {
 | 
			
		||||
	.cpg_deliver_fn =            corosync_cpg_deliver_callback,
 | 
			
		||||
	.cpg_confchg_fn =            corosync_cpg_confchg_callback,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
quorum_callbacks_t quorum_callbacks = {
 | 
			
		||||
	.quorum_notify_fn = NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct node_info
 | 
			
		||||
{
 | 
			
		||||
	enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
 | 
			
		||||
	int nodeid;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Set errno to something approximating the right value and return 0 or -1 */
 | 
			
		||||
static int cs_to_errno(cs_error_t err)
 | 
			
		||||
{
 | 
			
		||||
	switch(err)
 | 
			
		||||
	{
 | 
			
		||||
	case CS_OK:
 | 
			
		||||
		return 0;
 | 
			
		||||
        case CS_ERR_LIBRARY:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_VERSION:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_INIT:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_TIMEOUT:
 | 
			
		||||
		errno = ETIME;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_TRY_AGAIN:
 | 
			
		||||
		errno = EAGAIN;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_INVALID_PARAM:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_NO_MEMORY:
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_BAD_HANDLE:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_BUSY:
 | 
			
		||||
		errno = EBUSY;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_ACCESS:
 | 
			
		||||
		errno = EPERM;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_NOT_EXIST:
 | 
			
		||||
		errno = ENOENT;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_NAME_TOO_LONG:
 | 
			
		||||
		errno = ENAMETOOLONG;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_EXIST:
 | 
			
		||||
		errno = EEXIST;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_NO_SPACE:
 | 
			
		||||
		errno = ENOSPC;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_INTERRUPT:
 | 
			
		||||
		errno = EINTR;
 | 
			
		||||
		break;
 | 
			
		||||
	case CS_ERR_NAME_NOT_FOUND:
 | 
			
		||||
		errno = ENOENT;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_NO_RESOURCES:
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_NOT_SUPPORTED:
 | 
			
		||||
		errno = EOPNOTSUPP;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_BAD_OPERATION:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_FAILED_OPERATION:
 | 
			
		||||
		errno = EIO;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_MESSAGE_ERROR:
 | 
			
		||||
		errno = EIO;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_QUEUE_FULL:
 | 
			
		||||
		errno = EXFULL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_QUEUE_NOT_AVAILABLE:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_BAD_FLAGS:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_TOO_BIG:
 | 
			
		||||
		errno = E2BIG;
 | 
			
		||||
		break;
 | 
			
		||||
        case CS_ERR_NO_SECTIONS:
 | 
			
		||||
		errno = ENOMEM;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *print_corosync_csid(const char *csid)
 | 
			
		||||
{
 | 
			
		||||
	static char buf[128];
 | 
			
		||||
	int id;
 | 
			
		||||
 | 
			
		||||
	memcpy(&id, csid, sizeof(int));
 | 
			
		||||
	sprintf(buf, "%d", id);
 | 
			
		||||
	return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
 | 
			
		||||
				  const struct cpg_name *groupName,
 | 
			
		||||
				  uint32_t nodeid,
 | 
			
		||||
				  uint32_t pid,
 | 
			
		||||
				  void *msg,
 | 
			
		||||
				  size_t msg_len)
 | 
			
		||||
{
 | 
			
		||||
	int target_nodeid;
 | 
			
		||||
 | 
			
		||||
	memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
 | 
			
		||||
		 our_nodeid, nodeid, target_nodeid, msg_len-4);
 | 
			
		||||
 | 
			
		||||
	if (nodeid != our_nodeid)
 | 
			
		||||
		if (target_nodeid == our_nodeid || target_nodeid == 0)
 | 
			
		||||
			process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
 | 
			
		||||
					msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
 | 
			
		||||
				 const struct cpg_name *groupName,
 | 
			
		||||
				 const struct cpg_address *member_list, size_t member_list_entries,
 | 
			
		||||
				 const struct cpg_address *left_list, size_t left_list_entries,
 | 
			
		||||
				 const struct cpg_address *joined_list, size_t joined_list_entries)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("confchg callback. %zd joined, %zd left, %zd 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,
 | 
			
		||||
					      COROSYNC_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,
 | 
			
		||||
						      COROSYNC_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,
 | 
			
		||||
					      COROSYNC_CSID_LEN);
 | 
			
		||||
		if (ninfo)
 | 
			
		||||
			ninfo->state = NODE_DOWN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i=0; i<member_list_entries; i++) {
 | 
			
		||||
		if (member_list[i].nodeid == 0) continue;
 | 
			
		||||
		ninfo = dm_hash_lookup_binary(node_hash,
 | 
			
		||||
				(char *)&member_list[i].nodeid,
 | 
			
		||||
				COROSYNC_CSID_LEN);
 | 
			
		||||
		if (!ninfo) {
 | 
			
		||||
			ninfo = malloc(sizeof(struct node_info));
 | 
			
		||||
			if (!ninfo) {
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				ninfo->nodeid = member_list[i].nodeid;
 | 
			
		||||
				dm_hash_insert_binary(node_hash,
 | 
			
		||||
						(char *)&ninfo->nodeid,
 | 
			
		||||
						COROSYNC_CSID_LEN, ninfo);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ninfo->state = NODE_CLVMD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	num_nodes = member_list_entries;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	cs_error_t err;
 | 
			
		||||
 | 
			
		||||
#ifdef QUORUM_SET	/* corosync/quorum.h */
 | 
			
		||||
	uint32_t quorum_type;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	node_hash = dm_hash_create(100);
 | 
			
		||||
 | 
			
		||||
	err = cpg_initialize(&cpg_handle,
 | 
			
		||||
			     &corosync_cpg_callbacks);
 | 
			
		||||
	if (err != CS_OK) {
 | 
			
		||||
		syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
 | 
			
		||||
		       err);
 | 
			
		||||
		DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
 | 
			
		||||
		return cs_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef QUORUM_SET
 | 
			
		||||
	err = quorum_initialize(&quorum_handle,
 | 
			
		||||
				&quorum_callbacks,
 | 
			
		||||
				&quorum_type);
 | 
			
		||||
 | 
			
		||||
	if (quorum_type != QUORUM_SET) {
 | 
			
		||||
		syslog(LOG_ERR, "Corosync quorum service is not configured");
 | 
			
		||||
		DEBUGLOG("Corosync quorum service is not configured");
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	err = quorum_initialize(&quorum_handle,
 | 
			
		||||
				&quorum_callbacks);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (err != CS_OK) {
 | 
			
		||||
		syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
 | 
			
		||||
		       err);
 | 
			
		||||
		DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
 | 
			
		||||
		return cs_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create a lockspace for LV & VG locks to live in */
 | 
			
		||||
	lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
 | 
			
		||||
	if (!lockspace) {
 | 
			
		||||
		lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
 | 
			
		||||
		if (!lockspace) {
 | 
			
		||||
			syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		DEBUGLOG("Created DLM lockspace for CLVMD.\n");
 | 
			
		||||
	} else
 | 
			
		||||
		DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
 | 
			
		||||
 | 
			
		||||
	dlm_ls_pthread_init(lockspace);
 | 
			
		||||
	DEBUGLOG("DLM initialisation complete\n");
 | 
			
		||||
 | 
			
		||||
	/* 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 != CS_OK) {
 | 
			
		||||
		cpg_finalize(cpg_handle);
 | 
			
		||||
		quorum_finalize(quorum_handle);
 | 
			
		||||
		dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
 | 
			
		||||
		syslog(LOG_ERR, "Cannot join clvmd process group");
 | 
			
		||||
		DEBUGLOG("Cannot join clvmd process group: %d\n", err);
 | 
			
		||||
		return cs_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cpg_local_get(cpg_handle,
 | 
			
		||||
			    &our_nodeid);
 | 
			
		||||
	if (err != CS_OK) {
 | 
			
		||||
		cpg_finalize(cpg_handle);
 | 
			
		||||
		quorum_finalize(quorum_handle);
 | 
			
		||||
		dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
 | 
			
		||||
		syslog(LOG_ERR, "Cannot get local node id\n");
 | 
			
		||||
		return cs_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
	DEBUGLOG("Our local node id is %d\n", our_nodeid);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Connected to Corosync\n");
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cluster_closedown(void)
 | 
			
		||||
{
 | 
			
		||||
	DEBUGLOG("cluster_closedown\n");
 | 
			
		||||
	destroy_lvhash();
 | 
			
		||||
 | 
			
		||||
	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
 | 
			
		||||
	cpg_finalize(cpg_handle);
 | 
			
		||||
	quorum_finalize(quorum_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(csid, &our_nodeid, sizeof(int));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Corosync 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, COROSYNC_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, COROSYNC_CSID_LEN);
 | 
			
		||||
	if (!ninfo)
 | 
			
		||||
	{
 | 
			
		||||
		sprintf(name, "UNKNOWN %s", print_corosync_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, COROSYNC_CSID_LEN);
 | 
			
		||||
	if (!ninfo) {
 | 
			
		||||
		DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
 | 
			
		||||
			 print_corosync_csid(csid));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("corosync_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;
 | 
			
		||||
	int somedown = 0;
 | 
			
		||||
 | 
			
		||||
	dm_hash_iterate(hn, node_hash)
 | 
			
		||||
	{
 | 
			
		||||
		char csid[COROSYNC_CSID_LEN];
 | 
			
		||||
 | 
			
		||||
		ninfo = dm_hash_get_data(node_hash, hn);
 | 
			
		||||
		memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_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);
 | 
			
		||||
		if (ninfo->state != NODE_CLVMD)
 | 
			
		||||
			somedown = -1;
 | 
			
		||||
	}
 | 
			
		||||
	return somedown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Real locking */
 | 
			
		||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
	struct dlm_lksb lksb;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
 | 
			
		||||
 | 
			
		||||
	if (flags & LKF_CONVERT)
 | 
			
		||||
		lksb.sb_lkid = *lockid;
 | 
			
		||||
 | 
			
		||||
	err = dlm_ls_lock_wait(lockspace,
 | 
			
		||||
			       mode,
 | 
			
		||||
			       &lksb,
 | 
			
		||||
			       flags,
 | 
			
		||||
			       resource,
 | 
			
		||||
			       strlen(resource),
 | 
			
		||||
			       0,
 | 
			
		||||
			       NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	if (err != 0)
 | 
			
		||||
	{
 | 
			
		||||
		DEBUGLOG("dlm_ls_lock returned %d\n", errno);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (lksb.sb_status != 0)
 | 
			
		||||
	{
 | 
			
		||||
		DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
 | 
			
		||||
		errno = lksb.sb_status;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
 | 
			
		||||
 | 
			
		||||
	*lockid = lksb.sb_lkid;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int _unlock_resource(const char *resource, int lockid)
 | 
			
		||||
{
 | 
			
		||||
	struct dlm_lksb lksb;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
 | 
			
		||||
	lksb.sb_lkid = lockid;
 | 
			
		||||
 | 
			
		||||
	err = dlm_ls_unlock_wait(lockspace,
 | 
			
		||||
				 lockid,
 | 
			
		||||
				 0,
 | 
			
		||||
				 &lksb);
 | 
			
		||||
	if (err != 0)
 | 
			
		||||
	{
 | 
			
		||||
		DEBUGLOG("Unlock returned %d\n", err);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (lksb.sb_status != EUNLOCK)
 | 
			
		||||
	{
 | 
			
		||||
		DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
 | 
			
		||||
		errno = lksb.sb_status;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}   
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _is_quorate()
 | 
			
		||||
{
 | 
			
		||||
	int quorate;
 | 
			
		||||
	if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
 | 
			
		||||
		return quorate;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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, CS_DISPATCH_ONE);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
 | 
			
		||||
				 const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	struct iovec iov[2];
 | 
			
		||||
	cs_error_t err;
 | 
			
		||||
	int target_node;
 | 
			
		||||
 | 
			
		||||
	if (csid)
 | 
			
		||||
		memcpy(&target_node, csid, COROSYNC_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 cs_to_errno(err);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_COROSYNC_CONFDB_H
 | 
			
		||||
/*
 | 
			
		||||
 * We are not necessarily connected to a Red Hat Cluster system,
 | 
			
		||||
 * but if we are, this returns the cluster name from cluster.conf.
 | 
			
		||||
 * I've used confdb rather than ccs to reduce the inter-package
 | 
			
		||||
 * dependancies as well as to allow people to set a cluster name
 | 
			
		||||
 * for themselves even if they are not running on RH cluster.
 | 
			
		||||
 */
 | 
			
		||||
static int _get_cluster_name(char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	confdb_handle_t handle;
 | 
			
		||||
	int result;
 | 
			
		||||
	size_t namelen = buflen;
 | 
			
		||||
	hdb_handle_t cluster_handle;
 | 
			
		||||
	confdb_callbacks_t callbacks = {
 | 
			
		||||
		.confdb_key_change_notify_fn = NULL,
 | 
			
		||||
		.confdb_object_create_change_notify_fn = NULL,
 | 
			
		||||
		.confdb_object_delete_change_notify_fn = NULL
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/* This is a default in case everything else fails */
 | 
			
		||||
	strncpy(buf, "Corosync", buflen);
 | 
			
		||||
 | 
			
		||||
	/* Look for a cluster name in confdb */
 | 
			
		||||
	result = confdb_initialize (&handle, &callbacks);
 | 
			
		||||
        if (result != CS_OK)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
        result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
 | 
			
		||||
	if (result != CS_OK)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
        result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
 | 
			
		||||
        if (result != CS_OK)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
        result = confdb_key_get(handle, cluster_handle, (void *)"name", strlen("name"), buf, &namelen);
 | 
			
		||||
        if (result != CS_OK)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	buf[namelen] = '\0';
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	confdb_finalize(handle);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined HAVE_COROSYNC_CMAP_H
 | 
			
		||||
 | 
			
		||||
static int _get_cluster_name(char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	cmap_handle_t cmap_handle = 0;
 | 
			
		||||
	int result;
 | 
			
		||||
	char *name = NULL;
 | 
			
		||||
 | 
			
		||||
	/* This is a default in case everything else fails */
 | 
			
		||||
	strncpy(buf, "Corosync", buflen);
 | 
			
		||||
 | 
			
		||||
	/* Look for a cluster name in cmap */
 | 
			
		||||
	result = cmap_initialize(&cmap_handle);
 | 
			
		||||
	if (result != CS_OK)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	result = cmap_get_string(cmap_handle, "totem.cluster_name", &name);
 | 
			
		||||
	if (result != CS_OK)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	memset(buf, 0, buflen);
 | 
			
		||||
	strncpy(buf, name, buflen - 1);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	if (name)
 | 
			
		||||
		free(name);
 | 
			
		||||
	cmap_finalize(cmap_handle);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops _cluster_corosync_ops = {
 | 
			
		||||
	.name                     = "corosync",
 | 
			
		||||
	.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                = _lock_resource,
 | 
			
		||||
	.sync_unlock              = _unlock_resource,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cluster_ops *init_corosync_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!_init_cluster())
 | 
			
		||||
		return &_cluster_corosync_ops;
 | 
			
		||||
	else
 | 
			
		||||
		return NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										695
									
								
								daemons/clvmd/clvmd-openais.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										695
									
								
								daemons/clvmd/clvmd-openais.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,695 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2007-2009 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This provides the interface between clvmd and OpenAIS as the cluster
 | 
			
		||||
 * and lock manager.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "clvmd-common.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
 | 
			
		||||
#include <openais/saAis.h>
 | 
			
		||||
#include <openais/saLck.h>
 | 
			
		||||
 | 
			
		||||
#include <corosync/corotypes.h>
 | 
			
		||||
#include <corosync/cpg.h>
 | 
			
		||||
 | 
			
		||||
#include "locking.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 openais_cpg_deliver_callback (cpg_handle_t handle,
 | 
			
		||||
				  const struct cpg_name *groupName,
 | 
			
		||||
				  uint32_t nodeid,
 | 
			
		||||
				  uint32_t pid,
 | 
			
		||||
				  void *msg,
 | 
			
		||||
				  size_t msg_len);
 | 
			
		||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
 | 
			
		||||
				 const struct cpg_name *groupName,
 | 
			
		||||
				 const struct cpg_address *member_list, size_t member_list_entries,
 | 
			
		||||
				 const struct cpg_address *left_list, size_t left_list_entries,
 | 
			
		||||
				 const struct cpg_address *joined_list, size_t 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 openais_cpg_callbacks = {
 | 
			
		||||
	.cpg_deliver_fn =            openais_cpg_deliver_callback,
 | 
			
		||||
	.cpg_confchg_fn =            openais_cpg_confchg_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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 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_openais_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 openais_cpg_deliver_callback (cpg_handle_t handle,
 | 
			
		||||
				  const struct cpg_name *groupName,
 | 
			
		||||
				  uint32_t nodeid,
 | 
			
		||||
				  uint32_t pid,
 | 
			
		||||
				  void *msg,
 | 
			
		||||
				  size_t msg_len)
 | 
			
		||||
{
 | 
			
		||||
	int target_nodeid;
 | 
			
		||||
 | 
			
		||||
	memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("%u got message from nodeid %d for %d. len %" PRIsize_t "\n",
 | 
			
		||||
		 our_nodeid, nodeid, target_nodeid, msg_len-4);
 | 
			
		||||
 | 
			
		||||
	if (nodeid != our_nodeid)
 | 
			
		||||
		if (target_nodeid == our_nodeid || target_nodeid == 0)
 | 
			
		||||
			process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
 | 
			
		||||
					msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
 | 
			
		||||
				 const struct cpg_name *groupName,
 | 
			
		||||
				 const struct cpg_address *member_list, size_t member_list_entries,
 | 
			
		||||
				 const struct cpg_address *left_list, size_t left_list_entries,
 | 
			
		||||
				 const struct cpg_address *joined_list, size_t joined_list_entries)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	struct node_info *ninfo;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("confchg callback. %" PRIsize_t " joined, "
 | 
			
		||||
		 "%" PRIsize_t " left, %" PRIsize_t " 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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i=0; i<member_list_entries; i++) {
 | 
			
		||||
		if (member_list[i].nodeid == 0) continue;
 | 
			
		||||
		ninfo = dm_hash_lookup_binary(node_hash,
 | 
			
		||||
				(char *)&member_list[i].nodeid,
 | 
			
		||||
				OPENAIS_CSID_LEN);
 | 
			
		||||
		if (!ninfo) {
 | 
			
		||||
			ninfo = malloc(sizeof(struct node_info));
 | 
			
		||||
			if (!ninfo) {
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				ninfo->nodeid = member_list[i].nodeid;
 | 
			
		||||
				dm_hash_insert_binary(node_hash,
 | 
			
		||||
						(char *)&ninfo->nodeid,
 | 
			
		||||
						OPENAIS_CSID_LEN, ninfo);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ninfo->state = NODE_CLVMD;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	num_nodes = member_list_entries;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
			     &openais_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,
 | 
			
		||||
					NULL,
 | 
			
		||||
			      &ver);
 | 
			
		||||
	if (err != SA_AIS_OK) {
 | 
			
		||||
		cpg_initialize(&cpg_handle, &openais_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");
 | 
			
		||||
	destroy_lvhash();
 | 
			
		||||
 | 
			
		||||
	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_openais_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_openais_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;
 | 
			
		||||
	int somedown = 0;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
		if (ninfo->state != NODE_CLVMD)
 | 
			
		||||
			somedown = -1;
 | 
			
		||||
	}
 | 
			
		||||
	return somedown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Real locking */
 | 
			
		||||
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
	struct lock_info *linfo;
 | 
			
		||||
	SaLckResourceHandleT res_handle;
 | 
			
		||||
	SaAisErrorT err;
 | 
			
		||||
	SaLckLockIdT lock_id;
 | 
			
		||||
	SaLckLockStatusT lockStatus;
 | 
			
		||||
 | 
			
		||||
	/* 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 = saLckResourceLock(
 | 
			
		||||
			res_handle,
 | 
			
		||||
			&lock_id,
 | 
			
		||||
			mode,
 | 
			
		||||
			flags,
 | 
			
		||||
			0,
 | 
			
		||||
			SA_TIME_END,
 | 
			
		||||
			&lockStatus);
 | 
			
		||||
	if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
 | 
			
		||||
	{
 | 
			
		||||
		free(linfo);
 | 
			
		||||
		saLckResourceClose(res_handle);
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Wait for it to complete */
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("lock_resource returning %d, lock_id=%" PRIx64 "\n",
 | 
			
		||||
		 err, lock_id);
 | 
			
		||||
 | 
			
		||||
	linfo->lock_id = lock_id;
 | 
			
		||||
	linfo->res_handle = res_handle;
 | 
			
		||||
 | 
			
		||||
	dm_hash_insert(lock_hash, resource, linfo);
 | 
			
		||||
 | 
			
		||||
	return ais_to_errno(err);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int _unlock_resource(char *resource, int lockid)
 | 
			
		||||
{
 | 
			
		||||
	SaAisErrorT err;
 | 
			
		||||
	struct lock_info *linfo;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("unlock_resource %s\n", resource);
 | 
			
		||||
	linfo = dm_hash_lookup(lock_hash, resource);
 | 
			
		||||
	if (!linfo)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("unlock_resource: lockid: %" PRIx64 "\n", linfo->lock_id);
 | 
			
		||||
	err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
 | 
			
		||||
	if (err != SA_AIS_OK)
 | 
			
		||||
	{
 | 
			
		||||
		DEBUGLOG("Unlock returned %d\n", err);
 | 
			
		||||
		return ais_to_errno(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Release the resource */
 | 
			
		||||
	dm_hash_remove(lock_hash, resource);
 | 
			
		||||
	saLckResourceClose(linfo->res_handle);
 | 
			
		||||
	free(linfo);
 | 
			
		||||
 | 
			
		||||
	return ais_to_errno(err);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 = {
 | 
			
		||||
	.name                     = "openais",
 | 
			
		||||
	.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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										316
									
								
								daemons/clvmd/clvmd-singlenode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								daemons/clvmd/clvmd-singlenode.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,316 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2009 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 "clvmd-common.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include "locking.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock";
 | 
			
		||||
static int listen_fd = -1;
 | 
			
		||||
 | 
			
		||||
static struct dm_hash_table *_locks;
 | 
			
		||||
static int _lockid;
 | 
			
		||||
 | 
			
		||||
struct lock {
 | 
			
		||||
	int lockid;
 | 
			
		||||
	int mode;
 | 
			
		||||
	int excl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void close_comms(void)
 | 
			
		||||
{
 | 
			
		||||
	if (listen_fd != -1 && close(listen_fd))
 | 
			
		||||
		stack;
 | 
			
		||||
	(void)unlink(SINGLENODE_CLVMD_SOCKNAME);
 | 
			
		||||
	listen_fd = -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int init_comms(void)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_un addr;
 | 
			
		||||
	mode_t old_mask;
 | 
			
		||||
 | 
			
		||||
	close_comms();
 | 
			
		||||
 | 
			
		||||
	(void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK);
 | 
			
		||||
	old_mask = umask(0077);
 | 
			
		||||
 | 
			
		||||
	listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
 | 
			
		||||
	if (listen_fd < 0) {
 | 
			
		||||
		DEBUGLOG("Can't create local socket: %s\n", strerror(errno));
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
	/* Set Close-on-exec */
 | 
			
		||||
	if (fcntl(listen_fd, F_SETFD, 1)) {
 | 
			
		||||
		DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno));
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&addr, 0, sizeof(addr));
 | 
			
		||||
	memcpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
 | 
			
		||||
	       sizeof(SINGLENODE_CLVMD_SOCKNAME));
 | 
			
		||||
	addr.sun_family = AF_UNIX;
 | 
			
		||||
 | 
			
		||||
	if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 | 
			
		||||
		DEBUGLOG("Can't bind local socket: %s\n", strerror(errno));
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
	if (listen(listen_fd, 10) < 0) {
 | 
			
		||||
		DEBUGLOG("Can't listen local socket: %s\n", strerror(errno));
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	umask(old_mask);
 | 
			
		||||
	(void) dm_prepare_selinux_context(NULL, 0);
 | 
			
		||||
	return 0;
 | 
			
		||||
error:
 | 
			
		||||
	umask(old_mask);
 | 
			
		||||
	(void) dm_prepare_selinux_context(NULL, 0);
 | 
			
		||||
	close_comms();
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!(_locks = dm_hash_create(128))) {
 | 
			
		||||
		DEBUGLOG("Failed to allocate single-node hash table.\n");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = init_comms();
 | 
			
		||||
	if (r) {
 | 
			
		||||
		dm_hash_destroy(_locks);
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Single-node cluster initialised.\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _cluster_closedown(void)
 | 
			
		||||
{
 | 
			
		||||
	close_comms();
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("cluster_closedown\n");
 | 
			
		||||
	destroy_lvhash();
 | 
			
		||||
	dm_hash_destroy(_locks);
 | 
			
		||||
	_locks = NULL;
 | 
			
		||||
	_lockid = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _get_our_csid(char *csid)
 | 
			
		||||
{
 | 
			
		||||
	int nodeid = 1;
 | 
			
		||||
	memcpy(csid, &nodeid, sizeof(int));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _csid_from_name(char *csid, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _name_from_csid(const char *csid, char *name)
 | 
			
		||||
{
 | 
			
		||||
	sprintf(name, "SINGLENODE");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_num_nodes(void)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Node is now known to be running a clvmd */
 | 
			
		||||
static void _add_up_node(const 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 *,
 | 
			
		||||
				     const char *csid, int node_up))
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int _lock_file(const char *file, uint32_t flags);
 | 
			
		||||
 | 
			
		||||
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
/* Using one common condition for all locks for simplicity */
 | 
			
		||||
static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
/* Real locking */
 | 
			
		||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
 | 
			
		||||
{
 | 
			
		||||
	struct lock *lck;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Locking resource %s, flags=%d, mode=%d\n",
 | 
			
		||||
		 resource, flags, mode);
 | 
			
		||||
 | 
			
		||||
	mode &= LCK_TYPE_MASK;
 | 
			
		||||
	pthread_mutex_lock(&_lock_mutex);
 | 
			
		||||
retry:
 | 
			
		||||
	if (!(lck = dm_hash_lookup(_locks, resource))) {
 | 
			
		||||
		/* Add new locked resource */
 | 
			
		||||
		if (!(lck = dm_zalloc(sizeof(struct lock))) ||
 | 
			
		||||
		    !dm_hash_insert(_locks, resource, lck))
 | 
			
		||||
			goto bad;
 | 
			
		||||
 | 
			
		||||
		lck->lockid = ++_lockid;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        /* Update/convert lock */
 | 
			
		||||
	if (flags == LCKF_CONVERT) {
 | 
			
		||||
		if (lck->excl)
 | 
			
		||||
			mode = LCK_EXCL;
 | 
			
		||||
	} else if ((lck->mode == LCK_WRITE) || (lck->mode == LCK_EXCL)) {
 | 
			
		||||
		DEBUGLOG("Resource %s already %s locked (%d)...\n", resource,
 | 
			
		||||
			 (lck->mode == LCK_WRITE) ? "write" : "exclusively", lck->lockid);
 | 
			
		||||
		goto maybe_retry;
 | 
			
		||||
	} else if (lck->mode > mode) {
 | 
			
		||||
		DEBUGLOG("Resource %s already locked and %s lock requested...\n",
 | 
			
		||||
			 resource,
 | 
			
		||||
			 (mode == LCK_READ) ? "READ" :
 | 
			
		||||
			 (mode == LCK_WRITE) ? "WRITE" : "EXCLUSIVE");
 | 
			
		||||
		goto maybe_retry;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	*lockid = lck->lockid;
 | 
			
		||||
	lck->mode = mode;
 | 
			
		||||
	lck->excl |= (mode == LCK_EXCL);
 | 
			
		||||
	DEBUGLOG("Locked resource %s, lockid=%d, mode=%d\n", resource, lck->lockid, mode);
 | 
			
		||||
	pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
 | 
			
		||||
	pthread_mutex_unlock(&_lock_mutex);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
maybe_retry:
 | 
			
		||||
	if (!(flags & LCK_NONBLOCK)) {
 | 
			
		||||
		pthread_cond_wait(&_lock_cond, &_lock_mutex);
 | 
			
		||||
		DEBUGLOG("Resource %s RETRYING lock...\n", resource);
 | 
			
		||||
		goto retry;
 | 
			
		||||
	}
 | 
			
		||||
bad:
 | 
			
		||||
	DEBUGLOG("Failed to lock resource %s\n", resource);
 | 
			
		||||
	pthread_mutex_unlock(&_lock_mutex);
 | 
			
		||||
 | 
			
		||||
	return 1; /* fail */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _unlock_resource(const char *resource, int lockid)
 | 
			
		||||
{
 | 
			
		||||
	struct lock *lck;
 | 
			
		||||
 | 
			
		||||
	if (lockid < 0) {
 | 
			
		||||
		DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
 | 
			
		||||
			 resource, lockid);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
 | 
			
		||||
	pthread_mutex_lock(&_lock_mutex);
 | 
			
		||||
 | 
			
		||||
	if (!(lck = dm_hash_lookup(_locks, resource))) {
 | 
			
		||||
		pthread_mutex_unlock(&_lock_mutex);
 | 
			
		||||
		DEBUGLOG("Resource %s, lockid=%d is not locked.\n", resource, lockid);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lck->lockid != lockid) {
 | 
			
		||||
		pthread_mutex_unlock(&_lock_mutex);
 | 
			
		||||
		DEBUGLOG("Resource %s has wrong lockid %d, expected %d.\n",
 | 
			
		||||
			 resource, lck->lockid, lockid);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_hash_remove(_locks, resource);
 | 
			
		||||
	dm_free(lck);
 | 
			
		||||
	pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
 | 
			
		||||
	pthread_mutex_unlock(&_lock_mutex);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _is_quorate(void)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_main_cluster_fd(void)
 | 
			
		||||
{
 | 
			
		||||
	return listen_fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
 | 
			
		||||
				const char *csid,
 | 
			
		||||
				struct local_client **new_client)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _cluster_send_message(const void *buf, int msglen,
 | 
			
		||||
				 const char *csid,
 | 
			
		||||
				 const char *errtext)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_cluster_name(char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	strncpy(buf, "localcluster", buflen);
 | 
			
		||||
	buf[buflen - 1] = 0;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct cluster_ops _cluster_singlenode_ops = {
 | 
			
		||||
	.name                     = "singlenode",
 | 
			
		||||
	.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                = _lock_resource,
 | 
			
		||||
	.sync_unlock              = _unlock_resource,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cluster_ops *init_singlenode_cluster(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!_init_cluster())
 | 
			
		||||
		return &_cluster_singlenode_ops;
 | 
			
		||||
	else
 | 
			
		||||
		return NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2340
									
								
								daemons/clvmd/clvmd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2340
									
								
								daemons/clvmd/clvmd.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										126
									
								
								daemons/clvmd/clvmd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								daemons/clvmd/clvmd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,126 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _CLVMD_H
 | 
			
		||||
#define _CLVMD_H
 | 
			
		||||
 | 
			
		||||
#define CLVMD_MAJOR_VERSION 0
 | 
			
		||||
#define CLVMD_MINOR_VERSION 2
 | 
			
		||||
#define CLVMD_PATCH_VERSION 1
 | 
			
		||||
 | 
			
		||||
/* Default time (in seconds) we will wait for all remote commands to execute
 | 
			
		||||
   before declaring them dead */
 | 
			
		||||
#define DEFAULT_CMD_TIMEOUT 60
 | 
			
		||||
 | 
			
		||||
/* One of these for each reply we get from command execution on a node */
 | 
			
		||||
struct node_reply {
 | 
			
		||||
	char node[MAX_CLUSTER_MEMBER_NAME_LEN];
 | 
			
		||||
	char *replymsg;
 | 
			
		||||
	int status;
 | 
			
		||||
	struct node_reply *next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 */
 | 
			
		||||
struct localsock_bits {
 | 
			
		||||
	struct node_reply *replies;
 | 
			
		||||
	int num_replies;
 | 
			
		||||
	int expected_replies;
 | 
			
		||||
	time_t sent_time;	/* So we can check for timeouts */
 | 
			
		||||
	int in_progress;	/* Only execute one cmd at a time per client */
 | 
			
		||||
	int sent_out;		/* Flag to indicate that a command was sent
 | 
			
		||||
				   to remote nodes */
 | 
			
		||||
	void *private;		/* Private area for command processor use */
 | 
			
		||||
	void *cmd;		/* Whole command as passed down local socket */
 | 
			
		||||
	int cmd_len;		/* Length of above */
 | 
			
		||||
	int pipe;		/* Pipe to send PRE completion status down */
 | 
			
		||||
	int finished;		/* Flag to tell subthread to exit */
 | 
			
		||||
	int all_success;	/* Set to 0 if any node (or the pre_command)
 | 
			
		||||
				   failed */
 | 
			
		||||
	struct local_client *pipe_client;
 | 
			
		||||
	pthread_t threadid;
 | 
			
		||||
	enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
 | 
			
		||||
	pthread_mutex_t mutex;	/* Main thread and worker synchronisation */
 | 
			
		||||
	pthread_cond_t cond;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_t reply_mutex;	/* Protect reply structure */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Entries for PIPE clients */
 | 
			
		||||
struct pipe_bits {
 | 
			
		||||
	struct local_client *client;	/* Actual (localsock) client */
 | 
			
		||||
	pthread_t threadid;		/* Our own copy of the thread id */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Entries for Network socket clients */
 | 
			
		||||
struct netsock_bits {
 | 
			
		||||
	void *private;
 | 
			
		||||
	int flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
 | 
			
		||||
			      const char *csid,
 | 
			
		||||
			      struct local_client ** new_client);
 | 
			
		||||
 | 
			
		||||
/* One of these for each fd we are listening on */
 | 
			
		||||
struct local_client {
 | 
			
		||||
	int fd;
 | 
			
		||||
	enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
 | 
			
		||||
		    LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
 | 
			
		||||
	struct local_client *next;
 | 
			
		||||
	unsigned short xid;
 | 
			
		||||
	fd_callback_t callback;
 | 
			
		||||
	uint8_t removeme;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct localsock_bits localsock;
 | 
			
		||||
		struct pipe_bits pipe;
 | 
			
		||||
		struct netsock_bits net;
 | 
			
		||||
	} bits;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args);
 | 
			
		||||
 | 
			
		||||
#ifndef max
 | 
			
		||||
#define max(a,b) ((a)>(b)?(a):(b))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The real command processor is in clvmd-command.c */
 | 
			
		||||
extern int do_command(struct local_client *client, struct clvm_header *msg,
 | 
			
		||||
		      int msglen, char **buf, int buflen, int *retlen);
 | 
			
		||||
 | 
			
		||||
/* Pre and post command routines are called only on the local node */
 | 
			
		||||
extern int do_pre_command(struct local_client *client);
 | 
			
		||||
extern int do_post_command(struct local_client *client);
 | 
			
		||||
extern void cmd_client_cleanup(struct local_client *client);
 | 
			
		||||
extern int add_client(struct local_client *new_client);
 | 
			
		||||
 | 
			
		||||
extern void clvmd_cluster_init_completed(void);
 | 
			
		||||
extern void process_message(struct local_client *client, char *buf,
 | 
			
		||||
			    int len, const char *csid);
 | 
			
		||||
extern void debuglog(const char *fmt, ... )
 | 
			
		||||
  __attribute__ ((format(printf, 1, 2)));
 | 
			
		||||
 | 
			
		||||
void clvmd_set_debug(debug_t new_de);
 | 
			
		||||
debug_t clvmd_get_debug(void);
 | 
			
		||||
 | 
			
		||||
int sync_lock(const char *resource, int mode, int flags, int *lockid);
 | 
			
		||||
int sync_unlock(const char *resource, int lockid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										927
									
								
								daemons/clvmd/lvm-functions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										927
									
								
								daemons/clvmd/lvm-functions.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,927 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "clvmd-common.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include "lvm-types.h"
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "clvmd-comms.h"
 | 
			
		||||
#include "clvmd.h"
 | 
			
		||||
#include "lvm-functions.h"
 | 
			
		||||
 | 
			
		||||
/* LVM2 headers */
 | 
			
		||||
#include "toolcontext.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "lvm-globals.h"
 | 
			
		||||
#include "activate.h"
 | 
			
		||||
#include "archiver.h"
 | 
			
		||||
#include "memlock.h"
 | 
			
		||||
 | 
			
		||||
#include <syslog.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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char *decode_full_locking_cmd(uint32_t cmdl)
 | 
			
		||||
{
 | 
			
		||||
	static char buf[128];
 | 
			
		||||
	const char *type;
 | 
			
		||||
	const char *scope;
 | 
			
		||||
	const char *command;
 | 
			
		||||
 | 
			
		||||
	switch (cmdl & LCK_TYPE_MASK) {
 | 
			
		||||
	case LCK_NULL:
 | 
			
		||||
		type = "NULL";
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_READ:
 | 
			
		||||
		type = "READ";
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_PREAD:
 | 
			
		||||
		type = "PREAD";
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_WRITE:
 | 
			
		||||
		type = "WRITE";
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_EXCL:
 | 
			
		||||
		type = "EXCL";
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_UNLOCK:
 | 
			
		||||
		type = "UNLOCK";
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		type = "unknown";
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (cmdl & LCK_SCOPE_MASK) {
 | 
			
		||||
	case LCK_VG:
 | 
			
		||||
		scope = "VG";
 | 
			
		||||
		command = "LCK_VG";
 | 
			
		||||
		break;
 | 
			
		||||
	case LCK_LV:
 | 
			
		||||
		scope = "LV";
 | 
			
		||||
		switch (cmdl & LCK_MASK) {
 | 
			
		||||
		case LCK_LV_EXCLUSIVE & LCK_MASK:
 | 
			
		||||
			command = "LCK_LV_EXCLUSIVE";
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_LV_SUSPEND & LCK_MASK:
 | 
			
		||||
			command = "LCK_LV_SUSPEND";
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_LV_RESUME & LCK_MASK:
 | 
			
		||||
			command = "LCK_LV_RESUME";
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_LV_ACTIVATE & LCK_MASK:
 | 
			
		||||
			command = "LCK_LV_ACTIVATE";
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_LV_DEACTIVATE & LCK_MASK:
 | 
			
		||||
			command = "LCK_LV_DEACTIVATE";
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			command = "unknown";
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		scope = "unknown";
 | 
			
		||||
		command = "unknown";
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sprintf(buf, "0x%x %s (%s|%s%s%s%s%s)", cmdl, command, type, scope,
 | 
			
		||||
		cmdl & LCK_NONBLOCK   ? "|NONBLOCK" : "",
 | 
			
		||||
		cmdl & LCK_HOLD       ? "|HOLD" : "",
 | 
			
		||||
		cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
 | 
			
		||||
		cmdl & LCK_CACHE      ? "|CACHE" : "");
 | 
			
		||||
 | 
			
		||||
	return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Only processes 8 bits: excludes LCK_CACHE.
 | 
			
		||||
 */
 | 
			
		||||
static const char *decode_locking_cmd(unsigned char cmdl)
 | 
			
		||||
{
 | 
			
		||||
	return decode_full_locking_cmd((uint32_t) cmdl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *decode_flags(unsigned char flags)
 | 
			
		||||
{
 | 
			
		||||
	static char buf[128];
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	len = sprintf(buf, "0x%x ( %s%s%s%s%s%s%s)", flags,
 | 
			
		||||
		flags & LCK_PARTIAL_MODE	  ? "PARTIAL_MODE|" : "",
 | 
			
		||||
		flags & LCK_MIRROR_NOSYNC_MODE	  ? "MIRROR_NOSYNC|" : "",
 | 
			
		||||
		flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
 | 
			
		||||
		flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
 | 
			
		||||
		flags & LCK_TEST_MODE ? "TEST|" : "",
 | 
			
		||||
		flags & LCK_CONVERT ? "CONVERT|" : "",
 | 
			
		||||
		flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "");
 | 
			
		||||
 | 
			
		||||
	if (len > 1)
 | 
			
		||||
		buf[len - 2] = ' ';
 | 
			
		||||
	else
 | 
			
		||||
		buf[0] = '\0';
 | 
			
		||||
 | 
			
		||||
	return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *get_last_lvm_error(void)
 | 
			
		||||
{
 | 
			
		||||
	return last_error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Hash lock info helpers
 | 
			
		||||
 */
 | 
			
		||||
static struct lv_info *lookup_info(const char *resource)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
	lvi = dm_hash_lookup(lv_hash, resource);
 | 
			
		||||
	pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
 | 
			
		||||
	return lvi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int insert_info(const char *resource, struct lv_info *lvi)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
	ret = dm_hash_insert(lv_hash, resource, lvi);
 | 
			
		||||
	pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void remove_info(const char *resource)
 | 
			
		||||
{
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
	dm_hash_remove(lv_hash, resource);
 | 
			
		||||
	pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the mode a lock is currently held at (or -1 if not held)
 | 
			
		||||
 */
 | 
			
		||||
static int get_current_lock(char *resource)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
 | 
			
		||||
	if ((lvi = lookup_info(resource)))
 | 
			
		||||
		return lvi->lock_mode;
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void init_lvhash(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Create hash table for keeping LV locks & status */
 | 
			
		||||
	lv_hash = dm_hash_create(1024);
 | 
			
		||||
	pthread_mutex_init(&lv_hash_lock, NULL);
 | 
			
		||||
	pthread_mutex_init(&lvm_lock, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called at shutdown to tidy the lockspace */
 | 
			
		||||
void destroy_lvhash(void)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_hash_node *v;
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
	char *resource;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lv_hash_lock);
 | 
			
		||||
 | 
			
		||||
	dm_hash_iterate(v, lv_hash) {
 | 
			
		||||
		lvi = dm_hash_get_data(lv_hash, v);
 | 
			
		||||
		resource = dm_hash_get_key(lv_hash, v);
 | 
			
		||||
 | 
			
		||||
		if ((status = sync_unlock(resource, lvi->lock_id)))
 | 
			
		||||
			DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
 | 
			
		||||
				 status,  strerror(errno));
 | 
			
		||||
		free(lvi);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_hash_destroy(lv_hash);
 | 
			
		||||
	lv_hash = NULL;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_unlock(&lv_hash_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Gets a real lock and keeps the info in the hash table */
 | 
			
		||||
static int hold_lock(char *resource, int mode, int flags)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
 | 
			
		||||
	if (test_mode())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* Mask off invalid options */
 | 
			
		||||
	flags &= LCKF_NOQUEUE | LCKF_CONVERT;
 | 
			
		||||
 | 
			
		||||
	lvi = lookup_info(resource);
 | 
			
		||||
 | 
			
		||||
	if (lvi) {
 | 
			
		||||
		if (lvi->lock_mode == mode) {
 | 
			
		||||
			DEBUGLOG("hold_lock, lock mode %d already held\n",
 | 
			
		||||
				 mode);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
 | 
			
		||||
			DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
 | 
			
		||||
				 "ignoring LCK_WRITE request");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Only allow explicit conversions */
 | 
			
		||||
	if (lvi && !(flags & LCKF_CONVERT)) {
 | 
			
		||||
		errno = EBUSY;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	if (lvi) {
 | 
			
		||||
		/* Already exists - convert it */
 | 
			
		||||
		status =
 | 
			
		||||
		    sync_lock(resource, mode, flags, &lvi->lock_id);
 | 
			
		||||
		saved_errno = errno;
 | 
			
		||||
		if (!status)
 | 
			
		||||
			lvi->lock_mode = mode;
 | 
			
		||||
 | 
			
		||||
		if (status) {
 | 
			
		||||
			DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
 | 
			
		||||
				 strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
	} else {
 | 
			
		||||
		lvi = malloc(sizeof(struct lv_info));
 | 
			
		||||
		if (!lvi) {
 | 
			
		||||
			errno = ENOMEM;
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		lvi->lock_mode = mode;
 | 
			
		||||
		status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
 | 
			
		||||
		saved_errno = errno;
 | 
			
		||||
		if (status) {
 | 
			
		||||
			free(lvi);
 | 
			
		||||
			DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
 | 
			
		||||
				 strerror(errno));
 | 
			
		||||
		} else
 | 
			
		||||
			if (!insert_info(resource, lvi)) {
 | 
			
		||||
				errno = ENOMEM;
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
	}
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unlock and remove it from the hash table */
 | 
			
		||||
static int hold_unlock(char *resource)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
	int status;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
 | 
			
		||||
	if (test_mode())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(lvi = lookup_info(resource))) {
 | 
			
		||||
		DEBUGLOG("hold_unlock, lock not already held\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	status = sync_unlock(resource, lvi->lock_id);
 | 
			
		||||
	saved_errno = errno;
 | 
			
		||||
	if (!status) {
 | 
			
		||||
		remove_info(resource);
 | 
			
		||||
		free(lvi);
 | 
			
		||||
	} else {
 | 
			
		||||
		DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
 | 
			
		||||
			 strerror(errno));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	errno = saved_errno;
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Watch the return codes here.
 | 
			
		||||
   liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
 | 
			
		||||
   libdlm API functions return 0 for success, -1 for failure and do set errno.
 | 
			
		||||
   These functions here return 0 for success or >0 for failure (where the retcode is errno)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/* Activate LV exclusive or non-exclusive */
 | 
			
		||||
static int do_activate_lv(char *resource, unsigned char command, unsigned char lock_flags, int mode)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
	int status;
 | 
			
		||||
	int activate_lv;
 | 
			
		||||
	int exclusive = 0;
 | 
			
		||||
	struct lvinfo lvi;
 | 
			
		||||
 | 
			
		||||
	/* Is it already open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == mode && (command & LCK_CLUSTER_VG)) {
 | 
			
		||||
		DEBUGLOG("do_activate_lv, lock already held at %d\n", oldmode);
 | 
			
		||||
		return 0;	/* Nothing to do */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Does the config file want us to activate this LV ? */
 | 
			
		||||
	if (!lv_activation_filter(cmd, resource, &activate_lv))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (!activate_lv)
 | 
			
		||||
		return 0;	/* Success, we did nothing! */
 | 
			
		||||
 | 
			
		||||
	/* Do we need to activate exclusively? */
 | 
			
		||||
	if ((activate_lv == 2) || (mode == LCK_EXCL)) {
 | 
			
		||||
		exclusive = 1;
 | 
			
		||||
		mode = LCK_EXCL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Try to get the lock if it's a clustered volume group.
 | 
			
		||||
	 * Use lock conversion only if requested, to prevent implicit conversion
 | 
			
		||||
	 * of exclusive lock to shared one during activation.
 | 
			
		||||
	 */
 | 
			
		||||
	if (command & LCK_CLUSTER_VG) {
 | 
			
		||||
		status = hold_lock(resource, mode, LCKF_NOQUEUE | (lock_flags & LCK_CONVERT ? LCKF_CONVERT:0));
 | 
			
		||||
		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, 0, &lvi, 0, 0))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	if (lvi.suspended) {
 | 
			
		||||
		critical_section_inc(cmd, "resuming");
 | 
			
		||||
		if (!lv_resume(cmd, resource, 0)) {
 | 
			
		||||
			critical_section_dec(cmd, "resumed");
 | 
			
		||||
			goto error;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Now activate it */
 | 
			
		||||
	if (!lv_activate(cmd, resource, exclusive))
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	if (oldmode == -1 || oldmode != mode)
 | 
			
		||||
		(void)hold_unlock(resource);
 | 
			
		||||
	return EIO;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Resume the LV if it was active */
 | 
			
		||||
static int do_resume_lv(char *resource, unsigned char command, unsigned char lock_flags)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode, origin_only, exclusive, revert;
 | 
			
		||||
 | 
			
		||||
	/* Is it open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
 | 
			
		||||
		DEBUGLOG("do_resume_lv, lock not already held\n");
 | 
			
		||||
		return 0;	/* We don't need to do anything */
 | 
			
		||||
	}
 | 
			
		||||
	origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
 | 
			
		||||
	exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
 | 
			
		||||
	revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
	if (!lv_resume_if_active(cmd, resource, origin_only, exclusive, revert))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Suspend the device if active */
 | 
			
		||||
static int do_suspend_lv(char *resource, unsigned char command, unsigned char lock_flags)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
	struct lvinfo lvi;
 | 
			
		||||
	unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
 | 
			
		||||
	unsigned exclusive;
 | 
			
		||||
 | 
			
		||||
	/* Is it open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
 | 
			
		||||
		DEBUGLOG("do_suspend_lv, lock not already held\n");
 | 
			
		||||
		return 0; /* Not active, so it's OK */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
	/* Only suspend it if it exists */
 | 
			
		||||
	if (!lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (lvi.exists &&
 | 
			
		||||
	    !lv_suspend_if_active(cmd, resource, origin_only, exclusive))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_deactivate_lv(char *resource, unsigned char command, unsigned char lock_flags)
 | 
			
		||||
{
 | 
			
		||||
	int oldmode;
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	/* Is it open ? */
 | 
			
		||||
	oldmode = get_current_lock(resource);
 | 
			
		||||
	if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
 | 
			
		||||
		DEBUGLOG("do_deactivate_lock, lock not already held\n");
 | 
			
		||||
		return 0;	/* We don't need to do anything */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_deactivate(cmd, resource))
 | 
			
		||||
		return EIO;
 | 
			
		||||
 | 
			
		||||
	if (command & LCK_CLUSTER_VG) {
 | 
			
		||||
		status = hold_unlock(resource);
 | 
			
		||||
		if (status)
 | 
			
		||||
			return errno;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *do_lock_query(char *resource)
 | 
			
		||||
{
 | 
			
		||||
	int mode;
 | 
			
		||||
	const char *type = NULL;
 | 
			
		||||
 | 
			
		||||
	mode = get_current_lock(resource);
 | 
			
		||||
	switch (mode) {
 | 
			
		||||
		case LCK_NULL: type = "NL"; break;
 | 
			
		||||
		case LCK_READ: type = "CR"; break;
 | 
			
		||||
		case LCK_PREAD:type = "PR"; break;
 | 
			
		||||
		case LCK_WRITE:type = "PW"; break;
 | 
			
		||||
		case LCK_EXCL: type = "EX"; break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "?");
 | 
			
		||||
 | 
			
		||||
	return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is the LOCK_LV part that happens on all nodes in the cluster -
 | 
			
		||||
   it is responsible for the interaction with device-mapper and LVM */
 | 
			
		||||
int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
{
 | 
			
		||||
	int status = 0;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
 | 
			
		||||
		 resource, decode_locking_cmd(command), decode_flags(lock_flags), critical_section());
 | 
			
		||||
 | 
			
		||||
	if (!cmd->config_valid || config_files_changed(cmd)) {
 | 
			
		||||
		/* Reinitialise various settings inc. logging, filters */
 | 
			
		||||
		if (do_refresh_cache()) {
 | 
			
		||||
			log_error("Updated config file invalid. Aborting.");
 | 
			
		||||
			return EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lvm_lock);
 | 
			
		||||
	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
 | 
			
		||||
		init_mirror_in_sync(1);
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_DMEVENTD_MONITOR_IGNORE)
 | 
			
		||||
		init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
 | 
			
		||||
	else {
 | 
			
		||||
		if (lock_flags & LCK_DMEVENTD_MONITOR_MODE)
 | 
			
		||||
			init_dmeventd_monitor(1);
 | 
			
		||||
		else
 | 
			
		||||
			init_dmeventd_monitor(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd->partial_activation = (lock_flags & LCK_PARTIAL_MODE) ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
	/* clvmd should never try to read suspended device */
 | 
			
		||||
	init_ignore_suspended_devices(1);
 | 
			
		||||
 | 
			
		||||
	switch (command & LCK_MASK) {
 | 
			
		||||
	case LCK_LV_EXCLUSIVE:
 | 
			
		||||
		status = do_activate_lv(resource, command, lock_flags, LCK_EXCL);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_LV_SUSPEND:
 | 
			
		||||
		status = do_suspend_lv(resource, command, lock_flags);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_UNLOCK:
 | 
			
		||||
	case LCK_LV_RESUME:	/* if active */
 | 
			
		||||
		status = do_resume_lv(resource, command, lock_flags);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_LV_ACTIVATE:
 | 
			
		||||
		status = do_activate_lv(resource, command, lock_flags, LCK_READ);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LCK_LV_DEACTIVATE:
 | 
			
		||||
		status = do_deactivate_lv(resource, command, lock_flags);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		DEBUGLOG("Invalid LV command 0x%x\n", command);
 | 
			
		||||
		status = EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
 | 
			
		||||
		init_mirror_in_sync(0);
 | 
			
		||||
 | 
			
		||||
	cmd->partial_activation = 0;
 | 
			
		||||
 | 
			
		||||
	/* clean the pool for another command */
 | 
			
		||||
	dm_pool_empty(cmd->mem);
 | 
			
		||||
	pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Command return is %d, critical_section is %d\n", status, critical_section());
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
 | 
			
		||||
int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
{
 | 
			
		||||
	/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
 | 
			
		||||
	   lock out on this node (because we are the node modifying the metadata)
 | 
			
		||||
	   before suspending cluster-wide.
 | 
			
		||||
	   LCKF_CONVERT is used always, local node is going to modify metadata
 | 
			
		||||
	 */
 | 
			
		||||
	if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND &&
 | 
			
		||||
	    (command & LCK_CLUSTER_VG)) {
 | 
			
		||||
		DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
 | 
			
		||||
			 resource, decode_locking_cmd(command), decode_flags(lock_flags));
 | 
			
		||||
 | 
			
		||||
		if (hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT))
 | 
			
		||||
			return errno;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
 | 
			
		||||
int post_lock_lv(unsigned char command, unsigned char lock_flags,
 | 
			
		||||
		 char *resource)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
	/* Opposite of above, done on resume after a metadata update */
 | 
			
		||||
	if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME &&
 | 
			
		||||
	    (command & LCK_CLUSTER_VG)) {
 | 
			
		||||
		int oldmode;
 | 
			
		||||
 | 
			
		||||
		DEBUGLOG
 | 
			
		||||
		    ("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
 | 
			
		||||
		     resource, decode_locking_cmd(command), decode_flags(lock_flags));
 | 
			
		||||
 | 
			
		||||
		/* If the lock state is PW then restore it to what it was */
 | 
			
		||||
		oldmode = get_current_lock(resource);
 | 
			
		||||
		if (oldmode == LCK_WRITE) {
 | 
			
		||||
			struct lvinfo lvi;
 | 
			
		||||
 | 
			
		||||
			pthread_mutex_lock(&lvm_lock);
 | 
			
		||||
			status = lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0);
 | 
			
		||||
			pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
			if (!status)
 | 
			
		||||
				return EIO;
 | 
			
		||||
 | 
			
		||||
			if (lvi.exists) {
 | 
			
		||||
				if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
 | 
			
		||||
					return errno;
 | 
			
		||||
			} else if (hold_unlock(resource))
 | 
			
		||||
				return errno;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check if a VG is in use by LVM1 so we don't stomp on it */
 | 
			
		||||
int do_check_lvm1(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
 | 
			
		||||
	status = check_lvm1_vg_inactive(cmd, vgname);
 | 
			
		||||
 | 
			
		||||
	return status == 1 ? 0 : EBUSY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int do_refresh_cache(void)
 | 
			
		||||
{
 | 
			
		||||
	DEBUGLOG("Refreshing context\n");
 | 
			
		||||
	log_notice("Refreshing context");
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lvm_lock);
 | 
			
		||||
 | 
			
		||||
	if (!refresh_toolcontext(cmd)) {
 | 
			
		||||
		pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	init_full_scan_done(0);
 | 
			
		||||
	init_ignore_suspended_devices(1);
 | 
			
		||||
	lvmcache_label_scan(cmd, 2);
 | 
			
		||||
	dm_pool_empty(cmd->mem);
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Handle VG lock - drop metadata or update lvmcache state
 | 
			
		||||
 */
 | 
			
		||||
void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t lock_cmd = command;
 | 
			
		||||
	char *vgname = resource + 2;
 | 
			
		||||
 | 
			
		||||
	lock_cmd &= (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_HOLD);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Check if LCK_CACHE should be set. All P_ locks except # are cache related.
 | 
			
		||||
	 */
 | 
			
		||||
	if (strncmp(resource, "P_#", 3) && !strncmp(resource, "P_", 2))
 | 
			
		||||
		lock_cmd |= LCK_CACHE;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("do_lock_vg: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
 | 
			
		||||
		 resource, decode_full_locking_cmd(lock_cmd), decode_flags(lock_flags), critical_section());
 | 
			
		||||
 | 
			
		||||
	/* P_#global causes a full cache refresh */
 | 
			
		||||
	if (!strcmp(resource, "P_" VG_GLOBAL)) {
 | 
			
		||||
		do_refresh_cache();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lvm_lock);
 | 
			
		||||
	switch (lock_cmd) {
 | 
			
		||||
		case LCK_VG_COMMIT:
 | 
			
		||||
			DEBUGLOG("vg_commit notification for VG %s\n", vgname);
 | 
			
		||||
			lvmcache_commit_metadata(vgname);
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_VG_REVERT:
 | 
			
		||||
			DEBUGLOG("vg_revert notification for VG %s\n", vgname);
 | 
			
		||||
			lvmcache_drop_metadata(vgname, 1);
 | 
			
		||||
			break;
 | 
			
		||||
		case LCK_VG_DROP_CACHE:
 | 
			
		||||
		default:
 | 
			
		||||
			DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
 | 
			
		||||
			lvmcache_drop_metadata(vgname, 0);
 | 
			
		||||
	}
 | 
			
		||||
	pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Ideally, clvmd should be started before any LVs are active
 | 
			
		||||
 * but this may not be the case...
 | 
			
		||||
 * I suppose this also comes in handy if clvmd crashes, not that it would!
 | 
			
		||||
 */
 | 
			
		||||
static int get_initial_state(struct dm_hash_table *excl_uuid)
 | 
			
		||||
{
 | 
			
		||||
	int lock_mode;
 | 
			
		||||
	char lv[64], vg[64], flags[25], vg_flags[25];
 | 
			
		||||
	char uuid[65];
 | 
			
		||||
	char line[255];
 | 
			
		||||
	char *lvs_cmd;
 | 
			
		||||
	const char *lvm_binary = getenv("LVM_BINARY") ? : LVM_PATH;
 | 
			
		||||
	FILE *lvs;
 | 
			
		||||
 | 
			
		||||
	if (dm_asprintf(&lvs_cmd, "%s lvs  --config 'log{command_names=0 prefix=\"\"}' "
 | 
			
		||||
			"--nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
 | 
			
		||||
			lvm_binary) < 0)
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: Maybe link and use liblvm2cmd directly instead of fork */
 | 
			
		||||
	if (!(lvs = popen(lvs_cmd, "r"))) {
 | 
			
		||||
		dm_free(lvs_cmd);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (fgets(line, sizeof(line), lvs)) {
 | 
			
		||||
	        if (sscanf(line, "%64s %64s %25s %25s\n", vg, lv, flags, vg_flags) == 4) {
 | 
			
		||||
 | 
			
		||||
			/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
 | 
			
		||||
		        if (strlen(vg) == 38 &&                         /* is is a valid UUID ? */
 | 
			
		||||
			    (flags[4] == 'a' || flags[4] == 's') &&	/* is it active or suspended? */
 | 
			
		||||
			    vg_flags[5] == 'c') {			/* is it clustered ? */
 | 
			
		||||
				/* Convert hyphen-separated UUIDs into one */
 | 
			
		||||
				memcpy(&uuid[0], &vg[0], 6);
 | 
			
		||||
				memcpy(&uuid[6], &vg[7], 4);
 | 
			
		||||
				memcpy(&uuid[10], &vg[12], 4);
 | 
			
		||||
				memcpy(&uuid[14], &vg[17], 4);
 | 
			
		||||
				memcpy(&uuid[18], &vg[22], 4);
 | 
			
		||||
				memcpy(&uuid[22], &vg[27], 4);
 | 
			
		||||
				memcpy(&uuid[26], &vg[32], 6);
 | 
			
		||||
				memcpy(&uuid[32], &lv[0], 6);
 | 
			
		||||
				memcpy(&uuid[38], &lv[7], 4);
 | 
			
		||||
				memcpy(&uuid[42], &lv[12], 4);
 | 
			
		||||
				memcpy(&uuid[46], &lv[17], 4);
 | 
			
		||||
				memcpy(&uuid[50], &lv[22], 4);
 | 
			
		||||
				memcpy(&uuid[54], &lv[27], 4);
 | 
			
		||||
				memcpy(&uuid[58], &lv[32], 6);
 | 
			
		||||
				uuid[64] = '\0';
 | 
			
		||||
 | 
			
		||||
				/* Look for this lock in the list of EX locks
 | 
			
		||||
				   we were passed on the command-line */
 | 
			
		||||
				lock_mode = (dm_hash_lookup(excl_uuid, uuid)) ?
 | 
			
		||||
					LCK_EXCL : LCK_READ;
 | 
			
		||||
 | 
			
		||||
				DEBUGLOG("getting initial lock for %s\n", uuid);
 | 
			
		||||
				if (hold_lock(uuid, lock_mode, LCKF_NOQUEUE))
 | 
			
		||||
					DEBUGLOG("Failed to hold lock %s\n", uuid);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (fclose(lvs))
 | 
			
		||||
		DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
 | 
			
		||||
 | 
			
		||||
	dm_free(lvs_cmd);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void lvm2_log_fn(int level, const char *file, int line, int dm_errno,
 | 
			
		||||
			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, dm_errno, "%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(void)
 | 
			
		||||
{
 | 
			
		||||
	int locking_type;
 | 
			
		||||
 | 
			
		||||
	locking_type = find_config_tree_int(cmd, "global/locking_type", 1);
 | 
			
		||||
 | 
			
		||||
	if (locking_type == 3) /* compiled-in cluster support */
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (locking_type == 2) { /* External library, check name */
 | 
			
		||||
		const char *libname;
 | 
			
		||||
 | 
			
		||||
		libname = find_config_tree_str(cmd, "global/locking_library",
 | 
			
		||||
					  "");
 | 
			
		||||
		if (strstr(libname, "liblvm2clusterlock.so"))
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Backups up the LVM metadata if it's changed */
 | 
			
		||||
void lvm_do_backup(const char *vgname)
 | 
			
		||||
{
 | 
			
		||||
	struct volume_group * vg;
 | 
			
		||||
	int consistent = 0;
 | 
			
		||||
 | 
			
		||||
	DEBUGLOG("Triggering backup of VG metadata for %s.\n", vgname);
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&lvm_lock);
 | 
			
		||||
 | 
			
		||||
	vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, 1, &consistent);
 | 
			
		||||
 | 
			
		||||
	if (vg && consistent)
 | 
			
		||||
		check_current_backup(vg);
 | 
			
		||||
	else
 | 
			
		||||
		log_error("Error backing up metadata, can't find VG for group %s", vgname);
 | 
			
		||||
 | 
			
		||||
	release_vg(vg);
 | 
			
		||||
	dm_pool_empty(cmd->mem);
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name)
 | 
			
		||||
{
 | 
			
		||||
	struct lv_info *lvi;
 | 
			
		||||
 | 
			
		||||
	*name = NULL;
 | 
			
		||||
	if (!v)
 | 
			
		||||
		v = dm_hash_get_first(lv_hash);
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		if (v) {
 | 
			
		||||
			lvi = dm_hash_get_data(lv_hash, v);
 | 
			
		||||
			DEBUGLOG("Looking for EX locks. found %x mode %d\n", lvi->lock_id, lvi->lock_mode);
 | 
			
		||||
 | 
			
		||||
			if (lvi->lock_mode == LCK_EXCL) {
 | 
			
		||||
				*name = dm_hash_get_key(lv_hash, v);
 | 
			
		||||
			}
 | 
			
		||||
			v = dm_hash_get_next(lv_hash, v);
 | 
			
		||||
		}
 | 
			
		||||
	} while (v && !*name);
 | 
			
		||||
 | 
			
		||||
	if (*name)
 | 
			
		||||
		DEBUGLOG("returning EXclusive UUID %s\n", *name);
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lvm_do_fs_unlock(void)
 | 
			
		||||
{
 | 
			
		||||
	pthread_mutex_lock(&lvm_lock);
 | 
			
		||||
	DEBUGLOG("Syncing device names\n");
 | 
			
		||||
	fs_unlock();
 | 
			
		||||
	pthread_mutex_unlock(&lvm_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called to initialise the LVM context of the daemon */
 | 
			
		||||
int init_clvm(struct dm_hash_table *excl_uuid)
 | 
			
		||||
{
 | 
			
		||||
	/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
 | 
			
		||||
	init_syslog(LOG_DAEMON);
 | 
			
		||||
	openlog("clvmd", LOG_PID, LOG_DAEMON);
 | 
			
		||||
 | 
			
		||||
	/* Initialise already held locks */
 | 
			
		||||
	if (!get_initial_state(excl_uuid))
 | 
			
		||||
		log_error("Cannot load initial lock states.");
 | 
			
		||||
 | 
			
		||||
	if (!(cmd = create_toolcontext(1, NULL, 0, 1))) {
 | 
			
		||||
		log_error("Failed to allocate command context");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (stored_errno()) {
 | 
			
		||||
		destroy_toolcontext(cmd);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd->cmd_line = "clvmd";
 | 
			
		||||
 | 
			
		||||
	/* Check lvm.conf is setup for cluster-LVM */
 | 
			
		||||
	check_config();
 | 
			
		||||
	init_ignore_suspended_devices(1);
 | 
			
		||||
 | 
			
		||||
	/* Trap log messages so we can pass them back to the user */
 | 
			
		||||
	init_log_fn(lvm2_log_fn);
 | 
			
		||||
	memlock_inc_daemon(cmd);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void destroy_lvm(void)
 | 
			
		||||
{
 | 
			
		||||
	if (cmd) {
 | 
			
		||||
		memlock_dec_daemon(cmd);
 | 
			
		||||
		destroy_toolcontext(cmd);
 | 
			
		||||
	}
 | 
			
		||||
	cmd = NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								daemons/clvmd/lvm-functions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								daemons/clvmd/lvm-functions.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Functions in lvm-functions.c */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_FUNCTIONS_H
 | 
			
		||||
#define _LVM_FUNCTIONS_H
 | 
			
		||||
 | 
			
		||||
extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
 | 
			
		||||
		       char *resource);
 | 
			
		||||
extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
 | 
			
		||||
		      char *resource);
 | 
			
		||||
extern const char *do_lock_query(char *resource);
 | 
			
		||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
 | 
			
		||||
			char *resource);
 | 
			
		||||
extern int do_check_lvm1(const char *vgname);
 | 
			
		||||
extern int do_refresh_cache(void);
 | 
			
		||||
extern int init_clvm(struct dm_hash_table *excl_uuid);
 | 
			
		||||
extern void destroy_lvm(void);
 | 
			
		||||
extern void init_lvhash(void);
 | 
			
		||||
extern void destroy_lvhash(void);
 | 
			
		||||
extern void lvm_do_backup(const char *vgname);
 | 
			
		||||
extern char *get_last_lvm_error(void);
 | 
			
		||||
extern void do_lock_vg(unsigned char command, unsigned char lock_flags,
 | 
			
		||||
		      char *resource);
 | 
			
		||||
extern struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name);
 | 
			
		||||
void lvm_do_fs_unlock(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										385
									
								
								daemons/clvmd/refresh_clvmd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										385
									
								
								daemons/clvmd/refresh_clvmd.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,385 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2010 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* FIXME Remove duplicated functions from this file. */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Send a command to a running clvmd from the command-line
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "clvmd-common.h"
 | 
			
		||||
 | 
			
		||||
#include "clvm.h"
 | 
			
		||||
#include "refresh_clvmd.h"
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/un.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, int no_response)
 | 
			
		||||
{
 | 
			
		||||
	char outbuf[PIPE_BUF];
 | 
			
		||||
	struct clvm_header *outheader = (struct clvm_header *) outbuf;
 | 
			
		||||
	int len;
 | 
			
		||||
	unsigned 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;
 | 
			
		||||
	}
 | 
			
		||||
	if (no_response)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/* 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,
 | 
			
		||||
			  unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	head->cmd = cmd;
 | 
			
		||||
	head->status = 0;
 | 
			
		||||
	head->flags = 0;
 | 
			
		||||
	head->xid = 0;
 | 
			
		||||
	head->clientid = 0;
 | 
			
		||||
	if (len)
 | 
			
		||||
		/* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */
 | 
			
		||||
		head->arglen = len - 1;
 | 
			
		||||
	else {
 | 
			
		||||
		head->arglen = 0;
 | 
			
		||||
		*head->args = '\0';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Translate special node names.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!node || !strcmp(node, NODE_ALL))
 | 
			
		||||
		head->node[0] = '\0';
 | 
			
		||||
	else if (!strcmp(node, NODE_LOCAL)) {
 | 
			
		||||
		head->node[0] = '\0';
 | 
			
		||||
		head->flags = CLVMD_FLAG_LOCAL;
 | 
			
		||||
	} else
 | 
			
		||||
		strcpy(head->node, node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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, int no_response)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
	if (len)
 | 
			
		||||
		memcpy(head->node + strlen(head->node) + 1, data, len);
 | 
			
		||||
 | 
			
		||||
	status = _send_request(outbuf, sizeof(struct clvm_header) +
 | 
			
		||||
			       strlen(head->node) + len, &retbuf, no_response);
 | 
			
		||||
	if (!status || no_response)
 | 
			
		||||
		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 all_nodes)
 | 
			
		||||
{
 | 
			
		||||
	int num_responses;
 | 
			
		||||
	char args[1]; // No args really.
 | 
			
		||||
	lvm_response_t *response = NULL;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes ? NODE_ALL : NODE_LOCAL, args, 0, &response, &num_responses, 0);
 | 
			
		||||
 | 
			
		||||
	/* 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 restart_clvmd(int all_nodes)
 | 
			
		||||
{
 | 
			
		||||
	int dummy, status;
 | 
			
		||||
 | 
			
		||||
	status = _cluster_request(CLVMD_CMD_RESTART, all_nodes ? NODE_ALL : NODE_LOCAL, NULL, 0, NULL, &dummy, 1);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * FIXME: we cannot receive response, clvmd re-exec before it.
 | 
			
		||||
	 *        but also should not close socket too early (the whole rq is dropped then).
 | 
			
		||||
	 * FIXME: This should be handled this way:
 | 
			
		||||
	 *  - client waits for RESTART ack (and socket close)
 | 
			
		||||
	 *  - server restarts
 | 
			
		||||
	 *  - client checks that server is ready again (VERSION command?)
 | 
			
		||||
	 */
 | 
			
		||||
	usleep(500000);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int debug_clvmd(int level, int clusterwide)
 | 
			
		||||
{
 | 
			
		||||
	int num_responses;
 | 
			
		||||
	char args[1];
 | 
			
		||||
	const char *nodes;
 | 
			
		||||
	lvm_response_t *response = NULL;
 | 
			
		||||
	int saved_errno;
 | 
			
		||||
	int status;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	args[0] = level;
 | 
			
		||||
	if (clusterwide)
 | 
			
		||||
		nodes = NODE_ALL;
 | 
			
		||||
	else
 | 
			
		||||
		nodes = NODE_LOCAL;
 | 
			
		||||
 | 
			
		||||
	status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0);
 | 
			
		||||
 | 
			
		||||
	/* 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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								daemons/clvmd/refresh_clvmd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								daemons/clvmd/refresh_clvmd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int refresh_clvmd(int all_nodes);
 | 
			
		||||
int restart_clvmd(int all_nodes);
 | 
			
		||||
int debug_clvmd(int level, int clusterwide);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								daemons/cmirrord/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								daemons/cmirrord/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2009-2010 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
CPG_LIBS = @CPG_LIBS@
 | 
			
		||||
CPG_CFLAGS = @CPG_CFLAGS@
 | 
			
		||||
SACKPT_LIBS = @SACKPT_LIBS@
 | 
			
		||||
SACKPT_CFLAGS = @SACKPT_CFLAGS@
 | 
			
		||||
 | 
			
		||||
SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
 | 
			
		||||
 | 
			
		||||
TARGETS = cmirrord
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
LIBS += -ldevmapper
 | 
			
		||||
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
 | 
			
		||||
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS)
 | 
			
		||||
 | 
			
		||||
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
 | 
			
		||||
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
 | 
			
		||||
		$(LVMLIBS) $(LMLIBS) $(LIBS)
 | 
			
		||||
 | 
			
		||||
install: $(TARGETS)
 | 
			
		||||
	$(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
 | 
			
		||||
							
								
								
									
										246
									
								
								daemons/cmirrord/clogd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								daemons/cmirrord/clogd.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,246 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
#include "logging.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "functions.h"
 | 
			
		||||
#include "link_mon.h"
 | 
			
		||||
#include "local.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
static volatile sig_atomic_t exit_now = 0;
 | 
			
		||||
/* FIXME Review signal handling.  Should be volatile sig_atomic_t */
 | 
			
		||||
static sigset_t signal_mask;
 | 
			
		||||
static volatile sig_atomic_t signal_received;
 | 
			
		||||
 | 
			
		||||
static void process_signals(void);
 | 
			
		||||
static void daemonize(void);
 | 
			
		||||
static void init_all(void);
 | 
			
		||||
static void cleanup_all(void);
 | 
			
		||||
 | 
			
		||||
int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
	daemonize();
 | 
			
		||||
 | 
			
		||||
	init_all();
 | 
			
		||||
 | 
			
		||||
	/* Parent can now exit, we're ready to handle requests */
 | 
			
		||||
	kill(getppid(), SIGTERM);
 | 
			
		||||
 | 
			
		||||
	LOG_PRINT("Starting cmirrord:");
 | 
			
		||||
	LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
 | 
			
		||||
	LOG_DBG(" Compiled with debugging.");
 | 
			
		||||
 | 
			
		||||
	while (!exit_now) {
 | 
			
		||||
		links_monitor();
 | 
			
		||||
 | 
			
		||||
		links_issue_callbacks();
 | 
			
		||||
 | 
			
		||||
		process_signals();
 | 
			
		||||
	}
 | 
			
		||||
	exit(EXIT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * parent_exit_handler: exit the parent
 | 
			
		||||
 * @sig: the signal
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
static void parent_exit_handler(int sig __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
	exit_now = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sig_handler(int sig)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME Races - don't touch signal_mask here. */
 | 
			
		||||
	sigaddset(&signal_mask, sig);
 | 
			
		||||
	signal_received = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void process_signal(int sig){
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	switch(sig) {
 | 
			
		||||
	case SIGINT:
 | 
			
		||||
	case SIGQUIT:
 | 
			
		||||
	case SIGTERM:
 | 
			
		||||
	case SIGHUP:
 | 
			
		||||
		r += log_status();
 | 
			
		||||
		break;
 | 
			
		||||
	case SIGUSR1:
 | 
			
		||||
	case SIGUSR2:
 | 
			
		||||
		log_debug();
 | 
			
		||||
		/*local_debug();*/
 | 
			
		||||
		cluster_debug();
 | 
			
		||||
		return;
 | 
			
		||||
	default:
 | 
			
		||||
		LOG_PRINT("Unknown signal received... ignoring");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!r) {
 | 
			
		||||
		LOG_DBG("No current cluster logs... safe to exit.");
 | 
			
		||||
		cleanup_all();
 | 
			
		||||
		exit(EXIT_SUCCESS);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LOG_ERROR("Cluster logs exist.  Refusing to exit.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void process_signals(void)
 | 
			
		||||
{
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	if (!signal_received)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	signal_received = 0;
 | 
			
		||||
 | 
			
		||||
	for (x = 1; x < _NSIG; x++) {
 | 
			
		||||
		if (sigismember(&signal_mask, x)) {
 | 
			
		||||
			sigdelset(&signal_mask, x);
 | 
			
		||||
			process_signal(x);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void remove_lockfile(void)
 | 
			
		||||
{
 | 
			
		||||
	if (unlink(CMIRRORD_PIDFILE))
 | 
			
		||||
		LOG_ERROR("Unable to remove \"" CMIRRORD_PIDFILE "\" %s", strerror(errno));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * daemonize
 | 
			
		||||
 *
 | 
			
		||||
 * Performs the steps necessary to become a daemon.
 | 
			
		||||
 */
 | 
			
		||||
static void daemonize(void)
 | 
			
		||||
{
 | 
			
		||||
	int pid;
 | 
			
		||||
	int status;
 | 
			
		||||
	int devnull;
 | 
			
		||||
 | 
			
		||||
	if ((devnull = open("/dev/null", O_RDWR)) == -1) {
 | 
			
		||||
		LOG_ERROR("Can't open /dev/null: %s", strerror(errno));
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	signal(SIGTERM, &parent_exit_handler);
 | 
			
		||||
 | 
			
		||||
	pid = fork();
 | 
			
		||||
 | 
			
		||||
	if (pid < 0) {
 | 
			
		||||
		LOG_ERROR("Unable to fork()");
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pid) {
 | 
			
		||||
		/* Parent waits here for child to get going */
 | 
			
		||||
		while (!waitpid(pid, &status, WNOHANG) && !exit_now);
 | 
			
		||||
		if (exit_now)
 | 
			
		||||
			exit(EXIT_SUCCESS);
 | 
			
		||||
 | 
			
		||||
		switch (WEXITSTATUS(status)) {
 | 
			
		||||
		case EXIT_LOCKFILE:
 | 
			
		||||
			LOG_ERROR("Failed to create lockfile");
 | 
			
		||||
			LOG_ERROR("Process already running?");
 | 
			
		||||
			break;
 | 
			
		||||
		case EXIT_KERNEL_SOCKET:
 | 
			
		||||
			LOG_ERROR("Unable to create netlink socket");
 | 
			
		||||
			break;
 | 
			
		||||
		case EXIT_KERNEL_BIND:
 | 
			
		||||
			LOG_ERROR("Unable to bind to netlink socket");
 | 
			
		||||
			break;
 | 
			
		||||
		case EXIT_KERNEL_SETSOCKOPT:
 | 
			
		||||
			LOG_ERROR("Unable to setsockopt on netlink socket");
 | 
			
		||||
			break;
 | 
			
		||||
		case EXIT_CLUSTER_CKPT_INIT:
 | 
			
		||||
			LOG_ERROR("Unable to initialize checkpoint service");
 | 
			
		||||
			LOG_ERROR("Has the cluster infrastructure been started?");
 | 
			
		||||
			break;
 | 
			
		||||
		case EXIT_FAILURE:
 | 
			
		||||
			LOG_ERROR("Failed to start: Generic error");
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			LOG_ERROR("Failed to start: Unknown error");
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setsid();
 | 
			
		||||
	chdir("/");
 | 
			
		||||
	umask(0);
 | 
			
		||||
 | 
			
		||||
	if (close(0) || close(1) || close(2)) {
 | 
			
		||||
		LOG_ERROR("Failed to close terminal FDs");
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((dup2(devnull, 0) < 0) || /* reopen stdin */
 | 
			
		||||
	    (dup2(devnull, 1) < 0) || /* reopen stdout */
 | 
			
		||||
	    (dup2(devnull, 2) < 0))   /* reopen stderr */
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
	LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
 | 
			
		||||
 | 
			
		||||
	(void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG);
 | 
			
		||||
	if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
 | 
			
		||||
		exit(EXIT_LOCKFILE);
 | 
			
		||||
	(void) dm_prepare_selinux_context(NULL, 0);
 | 
			
		||||
 | 
			
		||||
	atexit(remove_lockfile);
 | 
			
		||||
 | 
			
		||||
	/* FIXME Replace with sigaction. (deprecated) */
 | 
			
		||||
	signal(SIGINT, &sig_handler);
 | 
			
		||||
	signal(SIGQUIT, &sig_handler);
 | 
			
		||||
	signal(SIGTERM, &sig_handler);
 | 
			
		||||
	signal(SIGHUP, &sig_handler);
 | 
			
		||||
	signal(SIGPIPE, SIG_IGN);
 | 
			
		||||
	signal(SIGUSR1, &sig_handler);
 | 
			
		||||
	signal(SIGUSR2, &sig_handler);
 | 
			
		||||
	sigemptyset(&signal_mask);
 | 
			
		||||
	signal_received = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * init_all
 | 
			
		||||
 *
 | 
			
		||||
 * Initialize modules.  Exit on failure.
 | 
			
		||||
 */
 | 
			
		||||
static void init_all(void)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if ((r = init_local()) ||
 | 
			
		||||
	    (r = init_cluster())) {
 | 
			
		||||
		exit(r);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * cleanup_all
 | 
			
		||||
 *
 | 
			
		||||
 * Clean up before exiting
 | 
			
		||||
 */
 | 
			
		||||
static void cleanup_all(void)
 | 
			
		||||
{
 | 
			
		||||
	cleanup_local();
 | 
			
		||||
	cleanup_cluster();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1756
									
								
								daemons/cmirrord/cluster.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1756
									
								
								daemons/cmirrord/cluster.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										76
									
								
								daemons/cmirrord/cluster.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								daemons/cmirrord/cluster.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _LVM_CLOG_CLUSTER_H
 | 
			
		||||
#define _LVM_CLOG_CLUSTER_H
 | 
			
		||||
 | 
			
		||||
#include "dm-log-userspace.h"
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
 | 
			
		||||
#define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */
 | 
			
		||||
#define DM_ULOG_CHECKPOINT_READY 21
 | 
			
		||||
#define DM_ULOG_MEMBER_JOIN      22
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * There is other information in addition to what can
 | 
			
		||||
 * be found in the dm_ulog_request structure that we
 | 
			
		||||
 * need for processing.  'clog_request' is the wrapping
 | 
			
		||||
 * structure we use to make the additional fields
 | 
			
		||||
 * available.
 | 
			
		||||
 */
 | 
			
		||||
struct clog_request {
 | 
			
		||||
	/*
 | 
			
		||||
	 * If we don't use a union, the structure size will
 | 
			
		||||
	 * vary between 32-bit and 64-bit machines.  So, we
 | 
			
		||||
	 * pack two 64-bit version numbers in there to force
 | 
			
		||||
	 * the size of the structure to be the same.
 | 
			
		||||
	 *
 | 
			
		||||
	 * The two version numbers also help us with endian
 | 
			
		||||
	 * issues.  The first is always little endian, while
 | 
			
		||||
	 * the second is in native format of the sending
 | 
			
		||||
	 * machine.  If the two are equal, there is no need
 | 
			
		||||
	 * to do endian conversions.
 | 
			
		||||
	 */
 | 
			
		||||
	union {
 | 
			
		||||
		uint64_t version[2]; /* LE version and native version */
 | 
			
		||||
		struct dm_list list;
 | 
			
		||||
	} u;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * 'originator' is the machine from which the requests
 | 
			
		||||
	 * was made.
 | 
			
		||||
	 */
 | 
			
		||||
	uint32_t originator;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * 'pit_server' is the "point-in-time" server for the
 | 
			
		||||
	 * request.  (I.e.  The machine that was the server at
 | 
			
		||||
	 * the time the request was issued - only important during
 | 
			
		||||
	 * startup.
 | 
			
		||||
	 */
 | 
			
		||||
	uint32_t pit_server;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The request from the kernel that is being processed
 | 
			
		||||
	 */
 | 
			
		||||
	struct dm_ulog_request u_rq;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int init_cluster(void);
 | 
			
		||||
void cleanup_cluster(void);
 | 
			
		||||
void cluster_debug(void);
 | 
			
		||||
 | 
			
		||||
int create_cluster_cpg(char *uuid, uint64_t luid);
 | 
			
		||||
int destroy_cluster_cpg(char *uuid);
 | 
			
		||||
 | 
			
		||||
int cluster_send(struct clog_request *rq);
 | 
			
		||||
 | 
			
		||||
#endif /* _LVM_CLOG_CLUSTER_H */
 | 
			
		||||
							
								
								
									
										33
									
								
								daemons/cmirrord/common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								daemons/cmirrord/common.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _LVM_CLOG_COMMON_H
 | 
			
		||||
#define _LVM_CLOG_COMMON_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * If there are problems when forking off to become a daemon,
 | 
			
		||||
 * the child will exist with one of these codes.  This allows
 | 
			
		||||
 * the parent to know the reason for the failure and print it
 | 
			
		||||
 * to the launching terminal.
 | 
			
		||||
 *
 | 
			
		||||
 * #define EXIT_SUCCESS 0 (from stdlib.h)
 | 
			
		||||
 * #define EXIT_FAILURE 1 (from stdlib.h)
 | 
			
		||||
 */
 | 
			
		||||
#define EXIT_LOCKFILE              2
 | 
			
		||||
#define EXIT_KERNEL_SOCKET         3 /* Failed netlink socket create */
 | 
			
		||||
#define EXIT_KERNEL_BIND           4
 | 
			
		||||
#define EXIT_KERNEL_SETSOCKOPT     5
 | 
			
		||||
#define EXIT_CLUSTER_CKPT_INIT     6 /* Failed to init checkpoint */
 | 
			
		||||
#define EXIT_QUEUE_NOMEM           7
 | 
			
		||||
 | 
			
		||||
#define DM_ULOG_REQUEST_SIZE 1024
 | 
			
		||||
 | 
			
		||||
#endif /* _LVM_CLOG_COMMON_H */
 | 
			
		||||
							
								
								
									
										210
									
								
								daemons/cmirrord/compat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								daemons/cmirrord/compat.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 */
 | 
			
		||||
#include "logging.h"
 | 
			
		||||
#include "cluster.h"
 | 
			
		||||
#include "compat.h"
 | 
			
		||||
#include "xlate.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Older versions of the log daemon communicate with different
 | 
			
		||||
 * versions of the inter-machine communication structure, which
 | 
			
		||||
 * varies in size and fields.  The older versions append the
 | 
			
		||||
 * standard upstream version of the structure to every request.
 | 
			
		||||
 * COMPAT_OFFSET is where the upstream structure starts.
 | 
			
		||||
 */
 | 
			
		||||
#define COMPAT_OFFSET 256
 | 
			
		||||
 | 
			
		||||
static void v5_data_endian_switch(struct clog_request *rq, int to_network __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
	int i, end;
 | 
			
		||||
	int64_t *pi64;
 | 
			
		||||
	uint64_t *pu64;
 | 
			
		||||
	uint32_t rq_type = rq->u_rq.request_type & ~DM_ULOG_RESPONSE;
 | 
			
		||||
 | 
			
		||||
	if (rq->u_rq.request_type & DM_ULOG_RESPONSE) {
 | 
			
		||||
		switch (rq_type) {
 | 
			
		||||
		case DM_ULOG_CTR:
 | 
			
		||||
		case DM_ULOG_DTR:
 | 
			
		||||
			LOG_ERROR("Invalid response type in endian switch");
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
		case DM_ULOG_PRESUSPEND:
 | 
			
		||||
		case DM_ULOG_POSTSUSPEND:
 | 
			
		||||
		case DM_ULOG_RESUME:
 | 
			
		||||
		case DM_ULOG_FLUSH:
 | 
			
		||||
		case DM_ULOG_MARK_REGION:
 | 
			
		||||
		case DM_ULOG_CLEAR_REGION:
 | 
			
		||||
		case DM_ULOG_SET_REGION_SYNC:
 | 
			
		||||
		case DM_ULOG_CHECKPOINT_READY:
 | 
			
		||||
		case DM_ULOG_MEMBER_JOIN:
 | 
			
		||||
		case DM_ULOG_STATUS_INFO:
 | 
			
		||||
		case DM_ULOG_STATUS_TABLE:
 | 
			
		||||
			/* No outbound data */
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case DM_ULOG_GET_REGION_SIZE:
 | 
			
		||||
		case DM_ULOG_GET_SYNC_COUNT:
 | 
			
		||||
			pu64 = (uint64_t *)rq->u_rq.data;
 | 
			
		||||
			*pu64 = xlate64(*pu64);
 | 
			
		||||
			break;
 | 
			
		||||
		case DM_ULOG_IS_CLEAN:
 | 
			
		||||
		case DM_ULOG_IN_SYNC:
 | 
			
		||||
			pi64 = (int64_t *)rq->u_rq.data;
 | 
			
		||||
			*pi64 = xlate64(*pi64);
 | 
			
		||||
			break;
 | 
			
		||||
		case DM_ULOG_GET_RESYNC_WORK:
 | 
			
		||||
		case DM_ULOG_IS_REMOTE_RECOVERING:
 | 
			
		||||
			pi64 = (int64_t *)rq->u_rq.data;
 | 
			
		||||
			pu64 = ((uint64_t *)rq->u_rq.data) + 1;
 | 
			
		||||
			*pi64 = xlate64(*pi64);
 | 
			
		||||
			*pu64 = xlate64(*pu64);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			LOG_ERROR("Unknown request type, %u", rq_type);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		switch (rq_type) {
 | 
			
		||||
		case DM_ULOG_CTR:
 | 
			
		||||
		case DM_ULOG_DTR:
 | 
			
		||||
			LOG_ERROR("Invalid request type in endian switch");
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
		case DM_ULOG_PRESUSPEND:
 | 
			
		||||
		case DM_ULOG_POSTSUSPEND:
 | 
			
		||||
		case DM_ULOG_RESUME:
 | 
			
		||||
		case DM_ULOG_GET_REGION_SIZE:
 | 
			
		||||
		case DM_ULOG_FLUSH:
 | 
			
		||||
		case DM_ULOG_GET_RESYNC_WORK:
 | 
			
		||||
		case DM_ULOG_GET_SYNC_COUNT:
 | 
			
		||||
		case DM_ULOG_STATUS_INFO:
 | 
			
		||||
		case DM_ULOG_STATUS_TABLE:
 | 
			
		||||
		case DM_ULOG_CHECKPOINT_READY:
 | 
			
		||||
		case DM_ULOG_MEMBER_JOIN:
 | 
			
		||||
			/* No incoming data */
 | 
			
		||||
			break;
 | 
			
		||||
		case DM_ULOG_IS_CLEAN:
 | 
			
		||||
		case DM_ULOG_IN_SYNC:
 | 
			
		||||
		case DM_ULOG_IS_REMOTE_RECOVERING:
 | 
			
		||||
			pu64 = (uint64_t *)rq->u_rq.data;
 | 
			
		||||
			*pu64 = xlate64(*pu64);
 | 
			
		||||
			break;
 | 
			
		||||
		case DM_ULOG_MARK_REGION:
 | 
			
		||||
		case DM_ULOG_CLEAR_REGION:
 | 
			
		||||
			end = rq->u_rq.data_size/sizeof(uint64_t);
 | 
			
		||||
 | 
			
		||||
			pu64 = (uint64_t *)rq->u_rq.data;
 | 
			
		||||
			for (i = 0; i < end; i++)
 | 
			
		||||
				pu64[i] = xlate64(pu64[i]);
 | 
			
		||||
			break;
 | 
			
		||||
		case DM_ULOG_SET_REGION_SYNC:
 | 
			
		||||
			pu64 = (uint64_t *)rq->u_rq.data;
 | 
			
		||||
			pi64 = ((int64_t *)rq->u_rq.data) + 1;
 | 
			
		||||
			*pu64 = xlate64(*pu64);
 | 
			
		||||
			*pi64 = xlate64(*pi64);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			LOG_ERROR("Unknown request type, %u", rq_type);
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int v5_endian_to_network(struct clog_request *rq)
 | 
			
		||||
{
 | 
			
		||||
	int size;
 | 
			
		||||
	struct dm_ulog_request *u_rq = &rq->u_rq;
 | 
			
		||||
 | 
			
		||||
	size = sizeof(*rq) + u_rq->data_size;
 | 
			
		||||
 | 
			
		||||
	u_rq->error = xlate32(u_rq->error);
 | 
			
		||||
	u_rq->seq = xlate32(u_rq->seq);
 | 
			
		||||
	u_rq->request_type = xlate32(u_rq->request_type);
 | 
			
		||||
	u_rq->data_size = xlate64(u_rq->data_size);
 | 
			
		||||
 | 
			
		||||
	rq->originator = xlate32(rq->originator);
 | 
			
		||||
 | 
			
		||||
	v5_data_endian_switch(rq, 1);
 | 
			
		||||
 | 
			
		||||
	return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int clog_request_to_network(struct clog_request *rq)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: Remove this safety check */
 | 
			
		||||
	if (rq->u.version[0] != xlate64(rq->u.version[1])) {
 | 
			
		||||
		LOG_ERROR("Programmer error:  version[0] must be LE");
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Are we already running in the endian mode we send
 | 
			
		||||
	 * over the wire?
 | 
			
		||||
	 */
 | 
			
		||||
	if (rq->u.version[0] == rq->u.version[1])
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	r = v5_endian_to_network(rq);
 | 
			
		||||
	if (r < 0)
 | 
			
		||||
		return r;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int v5_endian_from_network(struct clog_request *rq)
 | 
			
		||||
{
 | 
			
		||||
	int size;
 | 
			
		||||
	struct dm_ulog_request *u_rq = &rq->u_rq;
 | 
			
		||||
 | 
			
		||||
	u_rq->error = xlate32(u_rq->error);
 | 
			
		||||
	u_rq->seq = xlate32(u_rq->seq);
 | 
			
		||||
	u_rq->request_type = xlate32(u_rq->request_type);
 | 
			
		||||
	u_rq->data_size = xlate64(u_rq->data_size);
 | 
			
		||||
 | 
			
		||||
	rq->originator = xlate32(rq->originator);
 | 
			
		||||
 | 
			
		||||
	size = sizeof(*rq) + u_rq->data_size;
 | 
			
		||||
 | 
			
		||||
	v5_data_endian_switch(rq, 0);
 | 
			
		||||
 | 
			
		||||
	return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int clog_request_from_network(void *data, size_t data_len)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t *vp = data;
 | 
			
		||||
	uint64_t version = xlate64(vp[0]);
 | 
			
		||||
	uint64_t unconverted_version = vp[1];
 | 
			
		||||
	struct clog_request *rq = data;
 | 
			
		||||
 | 
			
		||||
	switch (version) {
 | 
			
		||||
	case 5: /* Upstream */
 | 
			
		||||
		if (version == unconverted_version)
 | 
			
		||||
			return 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case 4: /* RHEL 5.[45] */
 | 
			
		||||
	case 3: /* RHEL 5.3 */
 | 
			
		||||
	case 2: /* RHEL 5.2 */
 | 
			
		||||
		/* FIXME: still need to account for payload */
 | 
			
		||||
		if (data_len < (COMPAT_OFFSET + sizeof(*rq)))
 | 
			
		||||
			return -ENOSPC;
 | 
			
		||||
 | 
			
		||||
		rq = (struct clog_request *)((char *)data + COMPAT_OFFSET);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOG_ERROR("Unable to process cluster message: "
 | 
			
		||||
			  "Incompatible version");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v5_endian_from_network(rq);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								daemons/cmirrord/compat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								daemons/cmirrord/compat.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _LVM_CLOG_COMPAT_H
 | 
			
		||||
#define _LVM_CLOG_COMPAT_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The intermachine communication structure version are:
 | 
			
		||||
 *	0: Unused
 | 
			
		||||
 *	1: Never in the wild
 | 
			
		||||
 *	2: RHEL 5.2
 | 
			
		||||
 *	3: RHEL 5.3
 | 
			
		||||
 *	4: RHEL 5.4, RHEL 5.5
 | 
			
		||||
 *	5: RHEL 6, Current Upstream Format
 | 
			
		||||
 */
 | 
			
		||||
#define CLOG_TFR_VERSION 5
 | 
			
		||||
 | 
			
		||||
int clog_request_to_network(struct clog_request *rq);
 | 
			
		||||
int clog_request_from_network(void *data, size_t data_len);
 | 
			
		||||
 | 
			
		||||
#endif /* _LVM_CLOG_COMPAT_H */
 | 
			
		||||
							
								
								
									
										1954
									
								
								daemons/cmirrord/functions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1954
									
								
								daemons/cmirrord/functions.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										34
									
								
								daemons/cmirrord/functions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								daemons/cmirrord/functions.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _LVM_CLOG_FUNCTIONS_H
 | 
			
		||||
#define _LVM_CLOG_FUNCTIONS_H
 | 
			
		||||
 | 
			
		||||
#include "dm-log-userspace.h"
 | 
			
		||||
#include "cluster.h"
 | 
			
		||||
 | 
			
		||||
#define LOG_RESUMED   1
 | 
			
		||||
#define LOG_SUSPENDED 2
 | 
			
		||||
 | 
			
		||||
int local_resume(struct dm_ulog_request *rq);
 | 
			
		||||
int cluster_postsuspend(char *, uint64_t);
 | 
			
		||||
 | 
			
		||||
int do_request(struct clog_request *rq, int server);
 | 
			
		||||
int push_state(const char *uuid, uint64_t luid,
 | 
			
		||||
	       const char *which, char **buf, uint32_t debug_who);
 | 
			
		||||
int pull_state(const char *uuid, uint64_t luid,
 | 
			
		||||
	       const char *which, char *buf, int size);
 | 
			
		||||
 | 
			
		||||
int log_get_state(struct dm_ulog_request *rq);
 | 
			
		||||
int log_status(void);
 | 
			
		||||
void log_debug(void);
 | 
			
		||||
 | 
			
		||||
#endif /* _LVM_CLOG_FUNCTIONS_H */
 | 
			
		||||
							
								
								
									
										151
									
								
								daemons/cmirrord/link_mon.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								daemons/cmirrord/link_mon.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,151 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU 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 "logging.h"
 | 
			
		||||
#include "link_mon.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
struct link_callback {
 | 
			
		||||
	int fd;
 | 
			
		||||
	const char *name;
 | 
			
		||||
	void *data;
 | 
			
		||||
	int (*callback)(void *data);
 | 
			
		||||
 | 
			
		||||
	struct link_callback *next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static unsigned used_pfds = 0;
 | 
			
		||||
static unsigned free_pfds = 0;
 | 
			
		||||
static struct pollfd *pfds = NULL;
 | 
			
		||||
static struct link_callback *callbacks = NULL;
 | 
			
		||||
 | 
			
		||||
int links_register(int fd, const char *name, int (*callback)(void *data), void *data)
 | 
			
		||||
{
 | 
			
		||||
	unsigned i;
 | 
			
		||||
	struct link_callback *lc;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < used_pfds; i++) {
 | 
			
		||||
		if (fd == pfds[i].fd) {
 | 
			
		||||
			LOG_ERROR("links_register: Duplicate file descriptor");
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lc = malloc(sizeof(*lc));
 | 
			
		||||
	if (!lc)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	lc->fd = fd;
 | 
			
		||||
	lc->name = name;
 | 
			
		||||
	lc->data = data;
 | 
			
		||||
	lc->callback = callback;
 | 
			
		||||
 | 
			
		||||
	if (!free_pfds) {
 | 
			
		||||
		struct pollfd *tmp;
 | 
			
		||||
		tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1));
 | 
			
		||||
		if (!tmp) {
 | 
			
		||||
			free(lc);
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pfds = tmp;
 | 
			
		||||
		free_pfds = used_pfds + 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	free_pfds--;
 | 
			
		||||
	pfds[used_pfds].fd = fd;
 | 
			
		||||
	pfds[used_pfds].events = POLLIN;
 | 
			
		||||
	pfds[used_pfds].revents = 0;
 | 
			
		||||
	used_pfds++;
 | 
			
		||||
 | 
			
		||||
	lc->next = callbacks;
 | 
			
		||||
	callbacks = lc;
 | 
			
		||||
	LOG_DBG("Adding %s/%d", lc->name, lc->fd);
 | 
			
		||||
	LOG_DBG(" used_pfds = %u, free_pfds = %u",
 | 
			
		||||
		used_pfds, free_pfds);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int links_unregister(int fd)
 | 
			
		||||
{
 | 
			
		||||
	unsigned i;
 | 
			
		||||
	struct link_callback *p, *c;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < used_pfds; i++)
 | 
			
		||||
		if (fd == pfds[i].fd) {
 | 
			
		||||
			/* entire struct is copied (overwritten) */
 | 
			
		||||
			pfds[i] = pfds[used_pfds - 1];
 | 
			
		||||
			used_pfds--;
 | 
			
		||||
			free_pfds++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	for (p = NULL, c = callbacks; c; p = c, c = c->next)
 | 
			
		||||
		if (fd == c->fd) {
 | 
			
		||||
			LOG_DBG("Freeing up %s/%d", c->name, c->fd);
 | 
			
		||||
			LOG_DBG(" used_pfds = %u, free_pfds = %u",
 | 
			
		||||
				used_pfds, free_pfds);
 | 
			
		||||
			if (p)
 | 
			
		||||
				p->next = c->next;
 | 
			
		||||
			else
 | 
			
		||||
				callbacks = c->next;
 | 
			
		||||
			free(c);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int links_monitor(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned i;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < used_pfds; i++) {
 | 
			
		||||
		pfds[i].revents = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = poll(pfds, used_pfds, -1);
 | 
			
		||||
	if (r <= 0)
 | 
			
		||||
		return r;
 | 
			
		||||
 | 
			
		||||
	r = 0;
 | 
			
		||||
	/* FIXME: handle POLLHUP */
 | 
			
		||||
	for (i = 0; i < used_pfds; i++)
 | 
			
		||||
		if (pfds[i].revents & POLLIN) {
 | 
			
		||||
			LOG_DBG("Data ready on %d", pfds[i].fd);
 | 
			
		||||
 | 
			
		||||
			/* FIXME: Add this back return 1;*/
 | 
			
		||||
			r++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int links_issue_callbacks(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned i;
 | 
			
		||||
	struct link_callback *lc;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < used_pfds; i++)
 | 
			
		||||
		if (pfds[i].revents & POLLIN)
 | 
			
		||||
			for (lc = callbacks; lc; lc = lc->next)
 | 
			
		||||
				if (pfds[i].fd == lc->fd) {
 | 
			
		||||
					LOG_DBG("Issuing callback on %s/%d",
 | 
			
		||||
						lc->name, lc->fd);
 | 
			
		||||
					lc->callback(lc->data);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								daemons/cmirrord/link_mon.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								daemons/cmirrord/link_mon.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _LVM_CLOG_LINK_MON_H
 | 
			
		||||
#define _LVM_CLOG_LINK_MON_H
 | 
			
		||||
 | 
			
		||||
int links_register(int fd, const char *name, int (*callback)(void *data), void *data);
 | 
			
		||||
int links_unregister(int fd);
 | 
			
		||||
int links_monitor(void);
 | 
			
		||||
int links_issue_callbacks(void);
 | 
			
		||||
 | 
			
		||||
#endif /* _LVM_CLOG_LINK_MON_H */
 | 
			
		||||
							
								
								
									
										416
									
								
								daemons/cmirrord/local.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										416
									
								
								daemons/cmirrord/local.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,416 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU 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 "logging.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "functions.h"
 | 
			
		||||
#include "link_mon.h"
 | 
			
		||||
#include "local.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <linux/connector.h>
 | 
			
		||||
#include <linux/netlink.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#ifndef CN_IDX_DM
 | 
			
		||||
/* Kernel 2.6.31 is required to run this code */
 | 
			
		||||
#define CN_IDX_DM                       0x7     /* Device Mapper */
 | 
			
		||||
#define CN_VAL_DM_USERSPACE_LOG         0x1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int cn_fd;  /* Connector (netlink) socket fd */
 | 
			
		||||
static char recv_buf[2048];
 | 
			
		||||
static char send_buf[2048];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* FIXME: merge this function with kernel_send_helper */
 | 
			
		||||
static int kernel_ack(uint32_t seq, int error)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct nlmsghdr *nlh = (struct nlmsghdr *)send_buf;
 | 
			
		||||
	struct cn_msg *msg = NLMSG_DATA(nlh);
 | 
			
		||||
 | 
			
		||||
	if (error < 0) {
 | 
			
		||||
		LOG_ERROR("Programmer error: error codes must be positive");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(send_buf, 0, sizeof(send_buf));
 | 
			
		||||
 | 
			
		||||
	nlh->nlmsg_seq = 0;
 | 
			
		||||
	nlh->nlmsg_pid = getpid();
 | 
			
		||||
	nlh->nlmsg_type = NLMSG_DONE;
 | 
			
		||||
	nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg));
 | 
			
		||||
	nlh->nlmsg_flags = 0;
 | 
			
		||||
 | 
			
		||||
	msg->len = 0;
 | 
			
		||||
	msg->id.idx = CN_IDX_DM;
 | 
			
		||||
	msg->id.val = CN_VAL_DM_USERSPACE_LOG;
 | 
			
		||||
	msg->seq = seq;
 | 
			
		||||
	msg->ack = error;
 | 
			
		||||
 | 
			
		||||
	r = send(cn_fd, nlh, NLMSG_LENGTH(sizeof(struct cn_msg)), 0);
 | 
			
		||||
	/* FIXME: do better error processing */
 | 
			
		||||
	if (r <= 0)
 | 
			
		||||
		return -EBADE;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * kernel_recv
 | 
			
		||||
 * @rq: the newly allocated request from kernel
 | 
			
		||||
 *
 | 
			
		||||
 * Read requests from the kernel and allocate space for the new request.
 | 
			
		||||
 * If there is no request from the kernel, *rq is NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * This function is not thread safe due to returned stack pointer.  In fact,
 | 
			
		||||
 * the returned pointer must not be in-use when this function is called again.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 0 on success, -EXXX on error
 | 
			
		||||
 */
 | 
			
		||||
static int kernel_recv(struct clog_request **rq)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	ssize_t len;
 | 
			
		||||
	char *foo;
 | 
			
		||||
	struct cn_msg *msg;
 | 
			
		||||
	struct dm_ulog_request *u_rq;
 | 
			
		||||
	struct nlmsghdr *nlmsg_h;
 | 
			
		||||
 | 
			
		||||
	*rq = NULL;
 | 
			
		||||
	memset(recv_buf, 0, sizeof(recv_buf));
 | 
			
		||||
 | 
			
		||||
	len = recv(cn_fd, recv_buf, sizeof(recv_buf), 0);
 | 
			
		||||
	if (len < 0) {
 | 
			
		||||
		LOG_ERROR("Failed to recv message from kernel");
 | 
			
		||||
		r = -errno;
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nlmsg_h = (struct nlmsghdr *)recv_buf;
 | 
			
		||||
	switch (nlmsg_h->nlmsg_type) {
 | 
			
		||||
	case NLMSG_ERROR:
 | 
			
		||||
		LOG_ERROR("Unable to recv message from kernel: NLMSG_ERROR");
 | 
			
		||||
		r = -EBADE;
 | 
			
		||||
		goto fail;
 | 
			
		||||
	case NLMSG_DONE:
 | 
			
		||||
		msg = (struct cn_msg *)NLMSG_DATA((struct nlmsghdr *)recv_buf);
 | 
			
		||||
		len -= (ssize_t)sizeof(struct nlmsghdr);
 | 
			
		||||
 | 
			
		||||
		if (len < (ssize_t)sizeof(struct cn_msg)) {
 | 
			
		||||
			LOG_ERROR("Incomplete request from kernel received");
 | 
			
		||||
			r = -EBADE;
 | 
			
		||||
			goto fail;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (msg->len > DM_ULOG_REQUEST_SIZE) {
 | 
			
		||||
			LOG_ERROR("Not enough space to receive kernel request (%d/%d)",
 | 
			
		||||
				  msg->len, DM_ULOG_REQUEST_SIZE);
 | 
			
		||||
			r = -EBADE;
 | 
			
		||||
			goto fail;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!msg->len)
 | 
			
		||||
			LOG_ERROR("Zero length message received");
 | 
			
		||||
 | 
			
		||||
		len -= (ssize_t)sizeof(struct cn_msg);
 | 
			
		||||
 | 
			
		||||
		if (len < msg->len)
 | 
			
		||||
			LOG_ERROR("len = %zd, msg->len = %" PRIu16, len, msg->len);
 | 
			
		||||
 | 
			
		||||
		msg->data[msg->len] = '\0'; /* Cleaner way to ensure this? */
 | 
			
		||||
		u_rq = (struct dm_ulog_request *)msg->data;
 | 
			
		||||
 | 
			
		||||
		if (!u_rq->request_type) {
 | 
			
		||||
			LOG_DBG("Bad transmission, requesting resend [%u]",
 | 
			
		||||
				msg->seq);
 | 
			
		||||
			r = -EAGAIN;
 | 
			
		||||
 | 
			
		||||
			if (kernel_ack(msg->seq, EAGAIN)) {
 | 
			
		||||
				LOG_ERROR("Failed to NACK kernel transmission [%u]",
 | 
			
		||||
					  msg->seq);
 | 
			
		||||
				r = -EBADE;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Now we've got sizeof(struct cn_msg) + sizeof(struct nlmsghdr)
 | 
			
		||||
		 * worth of space that precede the request structure from the
 | 
			
		||||
		 * kernel.  Since that space isn't going to be used again, we
 | 
			
		||||
		 * can take it for our purposes; rather than allocating a whole
 | 
			
		||||
		 * new structure and doing a memcpy.
 | 
			
		||||
		 *
 | 
			
		||||
		 * We should really make sure 'clog_request' doesn't grow
 | 
			
		||||
		 * beyond what is available to us, but we need only check it
 | 
			
		||||
		 * once... perhaps at compile time?
 | 
			
		||||
		 */
 | 
			
		||||
		foo = (char *)u_rq;
 | 
			
		||||
		foo -= (sizeof(struct clog_request) - sizeof(struct dm_ulog_request));
 | 
			
		||||
		*rq = (struct clog_request *) foo;
 | 
			
		||||
 | 
			
		||||
		/* Clear the wrapper container fields */
 | 
			
		||||
		memset(*rq, 0, (size_t)((char *)u_rq - (char *)(*rq)));
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOG_ERROR("Unknown nlmsg_type");
 | 
			
		||||
		r = -EBADE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
	if (r)
 | 
			
		||||
		*rq = NULL;
 | 
			
		||||
 | 
			
		||||
	return (r == -EAGAIN) ? 0 : r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int kernel_send_helper(void *data, uint16_t out_size)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct nlmsghdr *nlh;
 | 
			
		||||
	struct cn_msg *msg;
 | 
			
		||||
 | 
			
		||||
	memset(send_buf, 0, sizeof(send_buf));
 | 
			
		||||
 | 
			
		||||
	nlh = (struct nlmsghdr *)send_buf;
 | 
			
		||||
	nlh->nlmsg_seq = 0;  /* FIXME: Is this used? */
 | 
			
		||||
	nlh->nlmsg_pid = getpid();
 | 
			
		||||
	nlh->nlmsg_type = NLMSG_DONE;
 | 
			
		||||
	nlh->nlmsg_len = NLMSG_LENGTH(out_size + sizeof(struct cn_msg));
 | 
			
		||||
	nlh->nlmsg_flags = 0;
 | 
			
		||||
 | 
			
		||||
	msg = NLMSG_DATA(nlh);
 | 
			
		||||
	memcpy(msg->data, data, out_size);
 | 
			
		||||
	msg->len = out_size;
 | 
			
		||||
	msg->id.idx = CN_IDX_DM;
 | 
			
		||||
	msg->id.val = CN_VAL_DM_USERSPACE_LOG;
 | 
			
		||||
	msg->seq = 0;
 | 
			
		||||
 | 
			
		||||
	r = send(cn_fd, nlh, NLMSG_LENGTH(out_size + sizeof(struct cn_msg)), 0);
 | 
			
		||||
	/* FIXME: do better error processing */
 | 
			
		||||
	if (r <= 0)
 | 
			
		||||
		return -EBADE;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * do_local_work
 | 
			
		||||
 *
 | 
			
		||||
 * Any processing errors are placed in the 'rq'
 | 
			
		||||
 * structure to be reported back to the kernel.
 | 
			
		||||
 * It may be pointless for this function to
 | 
			
		||||
 * return an int.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 0 on success, -EXXX on failure
 | 
			
		||||
 */
 | 
			
		||||
static int do_local_work(void *data __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct clog_request *rq;
 | 
			
		||||
	struct dm_ulog_request *u_rq = NULL;
 | 
			
		||||
 | 
			
		||||
	r = kernel_recv(&rq);
 | 
			
		||||
	if (r)
 | 
			
		||||
		return r;
 | 
			
		||||
 | 
			
		||||
	if (!rq)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	u_rq = &rq->u_rq;
 | 
			
		||||
	LOG_DBG("[%s]  Request from kernel received: [%s/%u]",
 | 
			
		||||
		SHORT_UUID(u_rq->uuid), RQ_TYPE(u_rq->request_type),
 | 
			
		||||
		u_rq->seq);
 | 
			
		||||
	switch (u_rq->request_type) {
 | 
			
		||||
	case DM_ULOG_CTR:
 | 
			
		||||
	case DM_ULOG_DTR:
 | 
			
		||||
	case DM_ULOG_GET_REGION_SIZE:
 | 
			
		||||
	case DM_ULOG_IN_SYNC:
 | 
			
		||||
	case DM_ULOG_GET_SYNC_COUNT:
 | 
			
		||||
	case DM_ULOG_STATUS_TABLE:
 | 
			
		||||
	case DM_ULOG_PRESUSPEND:
 | 
			
		||||
		/* We do not specify ourselves as server here */
 | 
			
		||||
		r = do_request(rq, 0);
 | 
			
		||||
		if (r)
 | 
			
		||||
			LOG_DBG("Returning failed request to kernel [%s]",
 | 
			
		||||
				RQ_TYPE(u_rq->request_type));
 | 
			
		||||
		r = kernel_send(u_rq);
 | 
			
		||||
		if (r)
 | 
			
		||||
			LOG_ERROR("Failed to respond to kernel [%s]",
 | 
			
		||||
				  RQ_TYPE(u_rq->request_type));
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	case DM_ULOG_RESUME:
 | 
			
		||||
		/*
 | 
			
		||||
		 * Resume is a special case that requires a local
 | 
			
		||||
		 * component to join the CPG, and a cluster component
 | 
			
		||||
		 * to handle the request.
 | 
			
		||||
		 */
 | 
			
		||||
		r = local_resume(u_rq);
 | 
			
		||||
		if (r) {
 | 
			
		||||
			LOG_DBG("Returning failed request to kernel [%s]",
 | 
			
		||||
				RQ_TYPE(u_rq->request_type));
 | 
			
		||||
			r = kernel_send(u_rq);
 | 
			
		||||
			if (r)
 | 
			
		||||
				LOG_ERROR("Failed to respond to kernel [%s]",
 | 
			
		||||
					  RQ_TYPE(u_rq->request_type));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		/* ELSE, fall through */
 | 
			
		||||
	case DM_ULOG_IS_CLEAN:
 | 
			
		||||
	case DM_ULOG_FLUSH:
 | 
			
		||||
	case DM_ULOG_MARK_REGION:
 | 
			
		||||
	case DM_ULOG_GET_RESYNC_WORK:
 | 
			
		||||
	case DM_ULOG_SET_REGION_SYNC:
 | 
			
		||||
	case DM_ULOG_STATUS_INFO:
 | 
			
		||||
	case DM_ULOG_IS_REMOTE_RECOVERING:
 | 
			
		||||
	case DM_ULOG_POSTSUSPEND:
 | 
			
		||||
		r = cluster_send(rq);
 | 
			
		||||
		if (r) {
 | 
			
		||||
			u_rq->data_size = 0;
 | 
			
		||||
			u_rq->error = r;
 | 
			
		||||
			kernel_send(u_rq);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	case DM_ULOG_CLEAR_REGION:
 | 
			
		||||
		r = kernel_ack(u_rq->seq, 0);
 | 
			
		||||
 | 
			
		||||
		r = cluster_send(rq);
 | 
			
		||||
		if (r) {
 | 
			
		||||
			/*
 | 
			
		||||
			 * FIXME: store error for delivery on flush
 | 
			
		||||
			 *        This would allow us to optimize MARK_REGION
 | 
			
		||||
			 *        too.
 | 
			
		||||
			 */
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOG_ERROR("Invalid log request received (%u), ignoring.",
 | 
			
		||||
			  u_rq->request_type);
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (r && !u_rq->error)
 | 
			
		||||
		u_rq->error = r;
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * kernel_send
 | 
			
		||||
 * @u_rq: result to pass back to kernel
 | 
			
		||||
 *
 | 
			
		||||
 * This function returns the u_rq structure
 | 
			
		||||
 * (containing the results) to the kernel.
 | 
			
		||||
 * It then frees the structure.
 | 
			
		||||
 *
 | 
			
		||||
 * WARNING: should the structure be freed if
 | 
			
		||||
 * there is an error?  I vote 'yes'.  If the
 | 
			
		||||
 * kernel doesn't get the response, it should
 | 
			
		||||
 * resend the request.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 0 on success, -EXXX on failure
 | 
			
		||||
 */
 | 
			
		||||
int kernel_send(struct dm_ulog_request *u_rq)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	uint16_t size;
 | 
			
		||||
 | 
			
		||||
	if (!u_rq)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	size = (uint16_t)(sizeof(struct dm_ulog_request) + u_rq->data_size);
 | 
			
		||||
 | 
			
		||||
	if (!u_rq->data_size && !u_rq->error) {
 | 
			
		||||
		/* An ACK is all that is needed */
 | 
			
		||||
 | 
			
		||||
		/* FIXME: add ACK code */
 | 
			
		||||
	} else if (size > DM_ULOG_REQUEST_SIZE) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * If we gotten here, we've already overrun
 | 
			
		||||
		 * our allotted space somewhere.
 | 
			
		||||
		 *
 | 
			
		||||
		 * We must do something, because the kernel
 | 
			
		||||
		 * is waiting for a response.
 | 
			
		||||
		 */
 | 
			
		||||
		LOG_ERROR("Not enough space to respond to server");
 | 
			
		||||
		u_rq->error = -ENOSPC;
 | 
			
		||||
		size = sizeof(struct dm_ulog_request);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = kernel_send_helper(u_rq, size);
 | 
			
		||||
	if (r)
 | 
			
		||||
		LOG_ERROR("Failed to send msg to kernel.");
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * init_local
 | 
			
		||||
 *
 | 
			
		||||
 * Initialize kernel communication socket (netlink)
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: 0 on success, values from common.h on failure
 | 
			
		||||
 */
 | 
			
		||||
int init_local(void)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	unsigned opt;
 | 
			
		||||
	struct sockaddr_nl addr;
 | 
			
		||||
 | 
			
		||||
	cn_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
 | 
			
		||||
	if (cn_fd < 0)
 | 
			
		||||
		return EXIT_KERNEL_SOCKET;
 | 
			
		||||
 | 
			
		||||
	/* memset to fix valgrind complaint */
 | 
			
		||||
	memset(&addr, 0, sizeof(struct sockaddr_nl));
 | 
			
		||||
 | 
			
		||||
	addr.nl_family = AF_NETLINK;
 | 
			
		||||
	addr.nl_groups = CN_IDX_DM;
 | 
			
		||||
	addr.nl_pid = 0;
 | 
			
		||||
 | 
			
		||||
	r = bind(cn_fd, (struct sockaddr *) &addr, sizeof(addr));
 | 
			
		||||
	if (r < 0) {
 | 
			
		||||
		close(cn_fd);
 | 
			
		||||
		return EXIT_KERNEL_BIND;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	opt = addr.nl_groups;
 | 
			
		||||
	r = setsockopt(cn_fd, 270, NETLINK_ADD_MEMBERSHIP, &opt, sizeof(opt));
 | 
			
		||||
	if (r) {
 | 
			
		||||
		close(cn_fd);
 | 
			
		||||
		return EXIT_KERNEL_SETSOCKOPT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	r = fcntl(cn_fd, F_SETFL, FNDELAY);
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	links_register(cn_fd, "local", do_local_work, NULL);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * cleanup_local
 | 
			
		||||
 *
 | 
			
		||||
 * Clean up before exiting
 | 
			
		||||
 */
 | 
			
		||||
void cleanup_local(void)
 | 
			
		||||
{
 | 
			
		||||
	links_unregister(cn_fd);
 | 
			
		||||
	close(cn_fd);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								daemons/cmirrord/local.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								daemons/cmirrord/local.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _LVM_CLOG_LOCAL_H
 | 
			
		||||
#define _LVM_CLOG_LOCAL_H
 | 
			
		||||
 | 
			
		||||
int init_local(void);
 | 
			
		||||
void cleanup_local(void);
 | 
			
		||||
 | 
			
		||||
int kernel_send(struct dm_ulog_request *rq);
 | 
			
		||||
 | 
			
		||||
#endif /* _LVM_CLOG_LOCAL_H */
 | 
			
		||||
							
								
								
									
										57
									
								
								daemons/cmirrord/logging.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								daemons/cmirrord/logging.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU 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 "logging.h"
 | 
			
		||||
 | 
			
		||||
const char *__rq_types_off_by_one[] = {
 | 
			
		||||
	"DM_ULOG_CTR",
 | 
			
		||||
	"DM_ULOG_DTR",
 | 
			
		||||
	"DM_ULOG_PRESUSPEND",
 | 
			
		||||
	"DM_ULOG_POSTSUSPEND",
 | 
			
		||||
	"DM_ULOG_RESUME",
 | 
			
		||||
	"DM_ULOG_GET_REGION_SIZE",
 | 
			
		||||
	"DM_ULOG_IS_CLEAN",
 | 
			
		||||
	"DM_ULOG_IN_SYNC",
 | 
			
		||||
	"DM_ULOG_FLUSH",
 | 
			
		||||
	"DM_ULOG_MARK_REGION",
 | 
			
		||||
	"DM_ULOG_CLEAR_REGION",
 | 
			
		||||
	"DM_ULOG_GET_RESYNC_WORK",
 | 
			
		||||
	"DM_ULOG_SET_REGION_SYNC",
 | 
			
		||||
	"DM_ULOG_GET_SYNC_COUNT",
 | 
			
		||||
	"DM_ULOG_STATUS_INFO",
 | 
			
		||||
	"DM_ULOG_STATUS_TABLE",
 | 
			
		||||
	"DM_ULOG_IS_REMOTE_RECOVERING",
 | 
			
		||||
	NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int log_tabbing = 0;
 | 
			
		||||
int log_is_open = 0;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Variables for various conditional logging
 | 
			
		||||
 */
 | 
			
		||||
#ifdef MEMB
 | 
			
		||||
int log_membership_change = 1;
 | 
			
		||||
#else
 | 
			
		||||
int log_membership_change = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CKPT
 | 
			
		||||
int log_checkpoint = 1;
 | 
			
		||||
#else
 | 
			
		||||
int log_checkpoint = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef RESEND
 | 
			
		||||
int log_resend_requests = 1;
 | 
			
		||||
#else
 | 
			
		||||
int log_resend_requests = 0;
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										77
									
								
								daemons/cmirrord/logging.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								daemons/cmirrord/logging.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_CLOG_LOGGING_H
 | 
			
		||||
#define _LVM_CLOG_LOGGING_H
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
#define _FILE_OFFSET_BITS 64
 | 
			
		||||
 | 
			
		||||
#include "configure.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
 | 
			
		||||
/* SHORT_UUID - print last 8 chars of a string */
 | 
			
		||||
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
 | 
			
		||||
 | 
			
		||||
extern const char *__rq_types_off_by_one[];
 | 
			
		||||
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
 | 
			
		||||
 | 
			
		||||
extern int log_tabbing;
 | 
			
		||||
extern int log_is_open;
 | 
			
		||||
extern int log_membership_change;
 | 
			
		||||
extern int log_checkpoint;
 | 
			
		||||
extern int log_resend_requests;
 | 
			
		||||
 | 
			
		||||
#define LOG_OPEN(ident, option, facility) do { \
 | 
			
		||||
		openlog(ident, option, facility); \
 | 
			
		||||
		log_is_open = 1;		  \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
#define LOG_CLOSE(void) do { \
 | 
			
		||||
		log_is_open = 0; \
 | 
			
		||||
		closelog();	 \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
#define LOG_OUTPUT(level, f, arg...) do {				\
 | 
			
		||||
		int __i;						\
 | 
			
		||||
		char __buffer[16];					\
 | 
			
		||||
		FILE *fp = (level > LOG_NOTICE) ? stderr : stdout;	\
 | 
			
		||||
		if (log_is_open) {					\
 | 
			
		||||
			for (__i = 0; (__i < log_tabbing) && (__i < 15); __i++) \
 | 
			
		||||
				__buffer[__i] = '\t';			\
 | 
			
		||||
			__buffer[__i] = '\0';				\
 | 
			
		||||
			syslog(level, "%s" f "\n", __buffer, ## arg);	\
 | 
			
		||||
		} else {						\
 | 
			
		||||
			for (__i = 0; __i < log_tabbing; __i++)		\
 | 
			
		||||
				fprintf(fp, "\t");			\
 | 
			
		||||
			fprintf(fp, f "\n", ## arg);			\
 | 
			
		||||
		}							\
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
 | 
			
		||||
#else /* DEBUG */
 | 
			
		||||
#define LOG_DBG(f, arg...)
 | 
			
		||||
#endif /* DEBUG */
 | 
			
		||||
 | 
			
		||||
#define LOG_COND(__X, f, arg...) do {\
 | 
			
		||||
		if (__X) { 	     \
 | 
			
		||||
			LOG_OUTPUT(LOG_NOTICE, f, ## arg); \
 | 
			
		||||
		} \
 | 
			
		||||
	} while (0)
 | 
			
		||||
#define LOG_PRINT(f, arg...) LOG_OUTPUT(LOG_NOTICE, f, ## arg)
 | 
			
		||||
#define LOG_ERROR(f, arg...) LOG_OUTPUT(LOG_ERR, f, ## arg)
 | 
			
		||||
 | 
			
		||||
#endif /* _LVM_CLOG_LOGGING_H */
 | 
			
		||||
							
								
								
									
										4
									
								
								daemons/dmeventd/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								daemons/dmeventd/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
init_fifos
 | 
			
		||||
fini_fifos
 | 
			
		||||
daemon_talk
 | 
			
		||||
dm_event_get_version
 | 
			
		||||
							
								
								
									
										108
									
								
								daemons/dmeventd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								daemons/dmeventd/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the device-mapper userspace tools.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
SOURCES = libdevmapper-event.c
 | 
			
		||||
SOURCES2 = dmeventd.c
 | 
			
		||||
 | 
			
		||||
TARGETS = dmeventd
 | 
			
		||||
 | 
			
		||||
.PHONY: install_lib_dynamic install_lib_static install_include \
 | 
			
		||||
	install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
 | 
			
		||||
	install_lib install_dmeventd
 | 
			
		||||
 | 
			
		||||
INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic
 | 
			
		||||
INSTALL_LIB_TARGETS = install_lib_dynamic
 | 
			
		||||
 | 
			
		||||
LIB_NAME = libdevmapper-event
 | 
			
		||||
ifeq ("@STATIC_LINK@", "yes")
 | 
			
		||||
  LIB_STATIC = $(LIB_NAME).a
 | 
			
		||||
  TARGETS += $(LIB_STATIC) dmeventd.static
 | 
			
		||||
  INSTALL_DMEVENTD_TARGETS += install_dmeventd_static
 | 
			
		||||
  INSTALL_LIB_TARGETS += install_lib_static
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
LIB_VERSION = $(LIB_VERSION_DM)
 | 
			
		||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
 | 
			
		||||
 | 
			
		||||
CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a
 | 
			
		||||
 | 
			
		||||
ifneq ($(MAKECMDGOALS),device-mapper)
 | 
			
		||||
  SUBDIRS+=plugins
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
CFLOW_LIST = $(SOURCES)
 | 
			
		||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
 | 
			
		||||
CFLOW_TARGET = dmeventd
 | 
			
		||||
 | 
			
		||||
EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
 | 
			
		||||
EXPORTED_FN_PREFIX = dm_event
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
all: device-mapper
 | 
			
		||||
device-mapper: $(TARGETS)
 | 
			
		||||
 | 
			
		||||
LIBS += -ldevmapper
 | 
			
		||||
LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS)
 | 
			
		||||
 | 
			
		||||
dmeventd: $(LIB_SHARED) dmeventd.o
 | 
			
		||||
	$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \
 | 
			
		||||
	$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
 | 
			
		||||
 | 
			
		||||
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
 | 
			
		||||
	$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
 | 
			
		||||
	dmeventd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
 | 
			
		||||
 | 
			
		||||
ifeq ("@PKGCONFIG@", "yes")
 | 
			
		||||
  INSTALL_LIB_TARGETS += install_pkgconfig
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("$(CFLOW_CMD)", "")
 | 
			
		||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
 | 
			
		||||
-include $(top_builddir)/libdm/libdevmapper.cflow
 | 
			
		||||
-include $(top_builddir)/lib/liblvm-internal.cflow
 | 
			
		||||
-include $(top_builddir)/lib/liblvm2cmd.cflow
 | 
			
		||||
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
 | 
			
		||||
-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
install_include: $(srcdir)/libdevmapper-event.h
 | 
			
		||||
	$(INSTALL_DATA) -D $< $(includedir)/$(<F)
 | 
			
		||||
 | 
			
		||||
install_pkgconfig: libdevmapper-event.pc
 | 
			
		||||
	$(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
 | 
			
		||||
 | 
			
		||||
install_lib_dynamic: install_lib_shared
 | 
			
		||||
 | 
			
		||||
install_lib_static: $(LIB_STATIC)
 | 
			
		||||
	$(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
 | 
			
		||||
 | 
			
		||||
install_lib: $(INSTALL_LIB_TARGETS)
 | 
			
		||||
 | 
			
		||||
install_dmeventd_dynamic: dmeventd
 | 
			
		||||
	$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
 | 
			
		||||
 | 
			
		||||
install_dmeventd_static: dmeventd.static
 | 
			
		||||
	$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
 | 
			
		||||
 | 
			
		||||
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
 | 
			
		||||
 | 
			
		||||
install: install_include install_lib install_dmeventd
 | 
			
		||||
 | 
			
		||||
install_device-mapper: install_include install_lib install_dmeventd
 | 
			
		||||
 | 
			
		||||
DISTCLEAN_TARGETS += libdevmapper-event.pc
 | 
			
		||||
							
								
								
									
										2031
									
								
								daemons/dmeventd/dmeventd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2031
									
								
								daemons/dmeventd/dmeventd.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										75
									
								
								daemons/dmeventd/dmeventd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								daemons/dmeventd/dmeventd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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_FIFO_CLIENT	"/var/run/dmeventd-client"
 | 
			
		||||
#define	DM_EVENT_FIFO_SERVER	"/var/run/dmeventd-server"
 | 
			
		||||
 | 
			
		||||
#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,
 | 
			
		||||
	DM_EVENT_CMD_DIE,
 | 
			
		||||
	DM_EVENT_CMD_GET_STATUS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 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 */
 | 
			
		||||
/*      EXIT_LOCKFILE_INUSE      2 -- obsoleted */
 | 
			
		||||
#define EXIT_DESC_CLOSE_FAILURE  3
 | 
			
		||||
#define EXIT_DESC_OPEN_FAILURE   4
 | 
			
		||||
/*      EXIT_OPEN_PID_FAILURE    5 -- obsoleted */
 | 
			
		||||
#define EXIT_FIFO_FAILURE        6
 | 
			
		||||
#define EXIT_CHDIR_FAILURE       7
 | 
			
		||||
 | 
			
		||||
/* Implemented in libdevmapper-event.c, but not part of public API. */
 | 
			
		||||
// FIXME  misuse of bitmask as enum
 | 
			
		||||
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);
 | 
			
		||||
int init_fifos(struct dm_event_fifos *fifos);
 | 
			
		||||
void fini_fifos(struct dm_event_fifos *fifos);
 | 
			
		||||
int dm_event_get_version(struct dm_event_fifos *fifos, int *version);
 | 
			
		||||
 | 
			
		||||
#endif /* __DMEVENTD_DOT_H__ */
 | 
			
		||||
							
								
								
									
										874
									
								
								daemons/dmeventd/libdevmapper-event.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										874
									
								
								daemons/dmeventd/libdevmapper-event.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,874 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "dmlib.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 *dmeventd_path;
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	dm_free(dmevh->dev_name);
 | 
			
		||||
	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->dmeventd_path = 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);
 | 
			
		||||
	dm_free(dmevh->dso);
 | 
			
		||||
	dm_free(dmevh->dmeventd_path);
 | 
			
		||||
	dm_free(dmevh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
 | 
			
		||||
{
 | 
			
		||||
	if (!dmeventd_path) /* noop */
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	dm_free(dmevh->dmeventd_path);
 | 
			
		||||
 | 
			
		||||
	dmevh->dmeventd_path = dm_strdup(dmeventd_path);
 | 
			
		||||
	if (!dmevh->dmeventd_path)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
 | 
			
		||||
{
 | 
			
		||||
	if (!path) /* noop */
 | 
			
		||||
		return 0;
 | 
			
		||||
	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->uuid)
 | 
			
		||||
		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 */
 | 
			
		||||
	uint32_t *header = alloca(size);
 | 
			
		||||
	char *buf = (char *)header;
 | 
			
		||||
 | 
			
		||||
	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 == 0) && (i > 4) && !bytes) {
 | 
			
		||||
				log_error("No input 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 (header && (bytes == 2 * sizeof(uint32_t))) {
 | 
			
		||||
			msg->cmd = ntohl(header[0]);
 | 
			
		||||
			msg->size = ntohl(header[1]);
 | 
			
		||||
			buf = msg->data = dm_malloc(msg->size);
 | 
			
		||||
			size = msg->size;
 | 
			
		||||
			bytes = 0;
 | 
			
		||||
			header = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (bytes != size) {
 | 
			
		||||
		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;
 | 
			
		||||
	uint32_t *header = alloca(size);
 | 
			
		||||
	char *buf = (char *)header;
 | 
			
		||||
	char drainbuf[128];
 | 
			
		||||
	struct timeval tval = { 0, 0 };
 | 
			
		||||
 | 
			
		||||
	header[0] = htonl(msg->cmd);
 | 
			
		||||
	header[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;
 | 
			
		||||
		ret = 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, 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
 | 
			
		||||
		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(char *dmeventd_path, struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	int pid, ret = 0;
 | 
			
		||||
	int status;
 | 
			
		||||
	struct stat statbuf;
 | 
			
		||||
	char default_dmeventd_path[] = DMEVENTD_PATH;
 | 
			
		||||
	char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
 | 
			
		||||
 | 
			
		||||
	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 */
 | 
			
		||||
		if (close(fifos->client))
 | 
			
		||||
			log_sys_error("close", fifos->client_path);
 | 
			
		||||
		return 1;
 | 
			
		||||
	} else if (errno != ENXIO) {
 | 
			
		||||
		/* problem */
 | 
			
		||||
		log_sys_error("open", fifos->client_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      start_server:
 | 
			
		||||
	/* server is not running */
 | 
			
		||||
 | 
			
		||||
	if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
 | 
			
		||||
		log_sys_error("stat", args[0]);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pid = fork();
 | 
			
		||||
 | 
			
		||||
	if (pid < 0)
 | 
			
		||||
		log_sys_error("fork", "");
 | 
			
		||||
 | 
			
		||||
	else if (!pid) {
 | 
			
		||||
		execvp(args[0], args);
 | 
			
		||||
		log_error("Unable to exec dmeventd: %s", strerror(errno));
 | 
			
		||||
		_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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int init_fifos(struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	/* FIXME? Is fifo the most suitable method? Why not share
 | 
			
		||||
	   comms/daemon code with something else e.g. multipath? */
 | 
			
		||||
 | 
			
		||||
	/* FIXME Make these either configurable or depend directly on dmeventd_path */
 | 
			
		||||
	fifos->client_path = DM_EVENT_FIFO_CLIENT;
 | 
			
		||||
	fifos->server_path = DM_EVENT_FIFO_SERVER;
 | 
			
		||||
 | 
			
		||||
	/* Open the fifo used to read from the daemon. */
 | 
			
		||||
	if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
 | 
			
		||||
		log_sys_error("open", fifos->server_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Lock out anyone else trying to do communication with the daemon. */
 | 
			
		||||
	if (flock(fifos->server, LOCK_EX) < 0) {
 | 
			
		||||
		log_sys_error("flock", fifos->server_path);
 | 
			
		||||
		if (close(fifos->server))
 | 
			
		||||
			log_sys_error("close", fifos->server_path);
 | 
			
		||||
		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_sys_error("open", fifos->client_path);
 | 
			
		||||
		if (close(fifos->server))
 | 
			
		||||
			log_sys_error("close", fifos->server_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Initialize client. */
 | 
			
		||||
static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	/* init fifos */
 | 
			
		||||
	memset(fifos, 0, sizeof(*fifos));
 | 
			
		||||
 | 
			
		||||
	/* FIXME Make these either configurable or depend directly on dmeventd_path */
 | 
			
		||||
	fifos->client_path = DM_EVENT_FIFO_CLIENT;
 | 
			
		||||
	fifos->server_path = DM_EVENT_FIFO_SERVER;
 | 
			
		||||
 | 
			
		||||
	if (!_start_daemon(dmeventd_path, fifos))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	return init_fifos(fifos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fini_fifos(struct dm_event_fifos *fifos)
 | 
			
		||||
{
 | 
			
		||||
	if (flock(fifos->server, LOCK_UN))
 | 
			
		||||
		log_error("flock unlock %s", fifos->server_path);
 | 
			
		||||
 | 
			
		||||
	if (close(fifos->client))
 | 
			
		||||
		log_sys_error("close", fifos->client_path);
 | 
			
		||||
	if (close(fifos->server))
 | 
			
		||||
		log_sys_error("close", fifos->server_path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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) {
 | 
			
		||||
		if (!dm_task_set_uuid(dmt, dmevh->uuid))
 | 
			
		||||
			goto_bad;
 | 
			
		||||
	} else if (dmevh->dev_name) {
 | 
			
		||||
		if (!dm_task_set_name(dmt, dmevh->dev_name))
 | 
			
		||||
			goto_bad;
 | 
			
		||||
	} else if (dmevh->major && dmevh->minor) {
 | 
			
		||||
		if (!dm_task_set_major(dmt, dmevh->major) ||
 | 
			
		||||
		    !dm_task_set_minor(dmt, dmevh->minor))
 | 
			
		||||
			goto_bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Add name or uuid or devno to messages */
 | 
			
		||||
	if (!dm_task_run(dmt)) {
 | 
			
		||||
		log_error("_get_device_info: dm_task_run() failed");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_task_get_info(dmt, &info)) {
 | 
			
		||||
		log_error("_get_device_info: failed to get info for device");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!info.exists) {
 | 
			
		||||
		log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found",
 | 
			
		||||
			  dmevh->uuid ? : "", 
 | 
			
		||||
			  (!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "", 
 | 
			
		||||
			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? "(" : "",
 | 
			
		||||
			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? dmevh->major : 0,
 | 
			
		||||
			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ":" : "",
 | 
			
		||||
			  (!dmevh->uuid && !dmevh->dev_name && dmevh->minor > 0) ? dmevh->minor : 0,
 | 
			
		||||
			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) && dmevh->minor == 0 ? "0" : "",
 | 
			
		||||
			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ") " : "");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		  
 | 
			
		||||
	return dmt;
 | 
			
		||||
 | 
			
		||||
      bad:
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handle the event (de)registration call and return negative error codes. */
 | 
			
		||||
static int _do_event(int cmd, char *dmeventd_path, 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(dmeventd_path, &fifos)) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return -ESRCH;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
 | 
			
		||||
 | 
			
		||||
	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? */
 | 
			
		||||
	fini_fifos(&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, dmevh->dmeventd_path, &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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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, dmevh->dmeventd_path, &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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 };
 | 
			
		||||
	struct dm_info info;
 | 
			
		||||
 | 
			
		||||
	if (!(dmt = _get_device_info(dmevh))) {
 | 
			
		||||
		stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uuid = dm_task_get_uuid(dmt);
 | 
			
		||||
 | 
			
		||||
	if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
 | 
			
		||||
		      DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
 | 
			
		||||
		      &msg, dmevh->dso, uuid, dmevh->mask, 0)) {
 | 
			
		||||
		log_debug("%s: device not registered.", dm_task_get_name(dmt));
 | 
			
		||||
		ret = -ENOENT;
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME this will probably horribly break if we get
 | 
			
		||||
	   ill-formatted reply */
 | 
			
		||||
	ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
 | 
			
		||||
 | 
			
		||||
	dm_task_destroy(dmt);
 | 
			
		||||
	dmt = NULL;
 | 
			
		||||
 | 
			
		||||
	dm_free(msg.data);
 | 
			
		||||
	msg.data = NULL;
 | 
			
		||||
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
	if (!reply_uuid) {
 | 
			
		||||
		ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	dm_free(reply_dso);
 | 
			
		||||
	reply_dso = NULL;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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:
 | 
			
		||||
	dm_free(msg.data);
 | 
			
		||||
	dm_free(reply_dso);
 | 
			
		||||
	dm_free(reply_uuid);
 | 
			
		||||
	_dm_event_handler_clear_dev_info(dmevh);
 | 
			
		||||
	if (dmt)
 | 
			
		||||
		dm_task_destroy(dmt);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * You can (and have to) call this at the stage of the protocol where
 | 
			
		||||
 *     daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0)
 | 
			
		||||
 *
 | 
			
		||||
 * would be normally sent. This call will parse the version reply from
 | 
			
		||||
 * dmeventd, in addition to above call. It is not safe to call this at any
 | 
			
		||||
 * other place in the protocol.
 | 
			
		||||
 *
 | 
			
		||||
 * This is an internal function, not exposed in the public API.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
 | 
			
		||||
	char *p;
 | 
			
		||||
	struct dm_event_daemon_message msg = { 0, 0, NULL };
 | 
			
		||||
 | 
			
		||||
	if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
 | 
			
		||||
		return 0;
 | 
			
		||||
	p = msg.data;
 | 
			
		||||
	*version = 0;
 | 
			
		||||
 | 
			
		||||
	p = strchr(p, ' '); /* Message ID */
 | 
			
		||||
        if (!p) return 0;
 | 
			
		||||
	p = strchr(p + 1, ' '); /* HELLO */
 | 
			
		||||
        if (!p) return 0;
 | 
			
		||||
	p = strchr(p + 1, ' '); /* HELLO, once more */
 | 
			
		||||
	if (p)
 | 
			
		||||
		*version = atoi(p);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
							
								
								
									
										115
									
								
								daemons/dmeventd/libdevmapper-event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								daemons/dmeventd/libdevmapper-event.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
#define DM_EVENT_PROTOCOL_VERSION 1
 | 
			
		||||
 | 
			
		||||
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 dmeventd, dso, device_name and uuid strings are duplicated so
 | 
			
		||||
 * you do not need to keep the pointers valid after the call succeeds.
 | 
			
		||||
 * They may return -ENOMEM though.
 | 
			
		||||
 */
 | 
			
		||||
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Path of dmeventd binary.
 | 
			
		||||
 */
 | 
			
		||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_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.
 | 
			
		||||
 */
 | 
			
		||||
// FIXME  misuse of bitmask as enum
 | 
			
		||||
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);
 | 
			
		||||
// FIXME  misuse of bitmask as enum
 | 
			
		||||
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. */
 | 
			
		||||
// FIXME  misuse of bitmask as enum
 | 
			
		||||
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
 | 
			
		||||
							
								
								
									
										11
									
								
								daemons/dmeventd/libdevmapper-event.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								daemons/dmeventd/libdevmapper-event.pc.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
prefix=@prefix@
 | 
			
		||||
exec_prefix=@exec_prefix@
 | 
			
		||||
libdir=@libdir@
 | 
			
		||||
includedir=@includedir@
 | 
			
		||||
 | 
			
		||||
Name: devmapper-event
 | 
			
		||||
Description: device-mapper event library
 | 
			
		||||
Version: @DM_LIB_PATCHLEVEL@
 | 
			
		||||
Cflags: -I${includedir}
 | 
			
		||||
Libs: -L${libdir} -ldevmapper-event
 | 
			
		||||
Requires.private: devmapper
 | 
			
		||||
							
								
								
									
										46
									
								
								daemons/dmeventd/plugins/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								daemons/dmeventd/plugins/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005, 2011 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
SUBDIRS += lvm2
 | 
			
		||||
 | 
			
		||||
ifneq ("@MIRRORS@", "none")
 | 
			
		||||
  SUBDIRS += mirror
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@SNAPSHOTS@", "none")
 | 
			
		||||
  SUBDIRS += snapshot
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@RAID@", "none")
 | 
			
		||||
  SUBDIRS += raid
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ("@THIN@", "none")
 | 
			
		||||
  SUBDIRS += thin
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(MAKECMDGOALS),distclean)
 | 
			
		||||
  SUBDIRS = lvm2 mirror snapshot raid thin
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
snapshot: lvm2
 | 
			
		||||
mirror: lvm2
 | 
			
		||||
raid: lvm2
 | 
			
		||||
thin: lvm2
 | 
			
		||||
							
								
								
									
										7
									
								
								daemons/dmeventd/plugins/lvm2/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								daemons/dmeventd/plugins/lvm2/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
dmeventd_lvm2_init
 | 
			
		||||
dmeventd_lvm2_exit
 | 
			
		||||
dmeventd_lvm2_lock
 | 
			
		||||
dmeventd_lvm2_unlock
 | 
			
		||||
dmeventd_lvm2_pool
 | 
			
		||||
dmeventd_lvm2_run
 | 
			
		||||
dmeventd_lvm2_command
 | 
			
		||||
							
								
								
									
										31
									
								
								daemons/dmeventd/plugins/lvm2/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								daemons/dmeventd/plugins/lvm2/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2010-2011 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
CLDFLAGS += -L$(top_builddir)/tools
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_lvm.c
 | 
			
		||||
 | 
			
		||||
LIB_SHARED = libdevmapper-event-lvm2.$(LIB_SUFFIX)
 | 
			
		||||
LIB_VERSION = $(LIB_VERSION_LVM)
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS) $(DAEMON_LIBS)
 | 
			
		||||
 | 
			
		||||
install_lvm2: install_lib_shared
 | 
			
		||||
 | 
			
		||||
install: install_lvm2
 | 
			
		||||
							
								
								
									
										178
									
								
								daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "errors.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "dmeventd_lvm.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
 | 
			
		||||
extern int dmeventd_debug;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FIXME Do not pass things directly to syslog, rather use the existing logging
 | 
			
		||||
 * facilities to sort logging ... however that mechanism needs to be somehow
 | 
			
		||||
 * configurable and we don't have that option yet
 | 
			
		||||
 */
 | 
			
		||||
static void _temporary_log_fn(int level,
 | 
			
		||||
			      const char *file __attribute__((unused)),
 | 
			
		||||
			      int line __attribute__((unused)),
 | 
			
		||||
			      int dm_errno __attribute__((unused)),
 | 
			
		||||
			      const char *message)
 | 
			
		||||
{
 | 
			
		||||
	level &= ~(_LOG_STDERR | _LOG_ONCE);
 | 
			
		||||
 | 
			
		||||
	switch (level) {
 | 
			
		||||
	case _LOG_DEBUG:
 | 
			
		||||
		if (dmeventd_debug >= 3)
 | 
			
		||||
			syslog(LOG_DEBUG, "%s", message);
 | 
			
		||||
		break;
 | 
			
		||||
	case _LOG_INFO:
 | 
			
		||||
		if (dmeventd_debug >= 2)
 | 
			
		||||
			syslog(LOG_INFO, "%s", message);
 | 
			
		||||
		break;
 | 
			
		||||
	case _LOG_NOTICE:
 | 
			
		||||
		if (dmeventd_debug >= 1)
 | 
			
		||||
			syslog(LOG_NOTICE, "%s", message);
 | 
			
		||||
		break;
 | 
			
		||||
	case _LOG_WARN:
 | 
			
		||||
		syslog(LOG_WARNING, "%s", message);
 | 
			
		||||
		break;
 | 
			
		||||
	case _LOG_ERR:
 | 
			
		||||
		syslog(LOG_ERR, "%s", message);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		syslog(LOG_CRIT, "%s", message);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dmeventd_lvm2_lock(void)
 | 
			
		||||
{
 | 
			
		||||
	pthread_mutex_lock(&_event_mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dmeventd_lvm2_unlock(void)
 | 
			
		||||
{
 | 
			
		||||
	pthread_mutex_unlock(&_event_mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dmeventd_lvm2_init(void)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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_disable_dmeventd_monitoring(_lvm_handle);
 | 
			
		||||
		/* FIXME Temporary: move to dmeventd core */
 | 
			
		||||
		lvm2_run(_lvm_handle, "_memlock_inc");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_register_count++;
 | 
			
		||||
	r = 1;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	pthread_mutex_unlock(&_register_mutex);
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dmeventd_lvm2_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	pthread_mutex_lock(&_register_mutex);
 | 
			
		||||
 | 
			
		||||
	if (!--_register_count) {
 | 
			
		||||
		lvm2_run(_lvm_handle, "_memlock_dec");
 | 
			
		||||
		dm_pool_destroy(_mem_pool);
 | 
			
		||||
		_mem_pool = NULL;
 | 
			
		||||
		lvm2_exit(_lvm_handle);
 | 
			
		||||
		_lvm_handle = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_unlock(&_register_mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dm_pool *dmeventd_lvm2_pool(void)
 | 
			
		||||
{
 | 
			
		||||
	return _mem_pool;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dmeventd_lvm2_run(const char *cmdline)
 | 
			
		||||
{
 | 
			
		||||
	return lvm2_run(_lvm_handle, cmdline);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
 | 
			
		||||
			  const char *cmd, const char *device)
 | 
			
		||||
{
 | 
			
		||||
	char *vg = NULL, *lv = NULL, *layer;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to determine VG name from %s.\n",
 | 
			
		||||
		       device);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* strip off the mirror component designations */
 | 
			
		||||
	layer = strstr(lv, "_mlog");
 | 
			
		||||
	if (layer)
 | 
			
		||||
		*layer = '\0';
 | 
			
		||||
 | 
			
		||||
	r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv);
 | 
			
		||||
 | 
			
		||||
	dm_pool_free(mem, vg);
 | 
			
		||||
 | 
			
		||||
	if (r < 0) {
 | 
			
		||||
		syslog(LOG_ERR, "Unable to form LVM command. (too long).\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Wrappers around liblvm2cmd functions for dmeventd plug-ins.
 | 
			
		||||
 *
 | 
			
		||||
 * liblvm2cmd is not thread-safe so the locking in this library helps dmeventd
 | 
			
		||||
 * threads to co-operate in sharing a single instance.
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME Either support this properly as a generic liblvm2cmd wrapper or make
 | 
			
		||||
 * liblvm2cmd thread-safe so this can go away.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "libdevmapper.h"
 | 
			
		||||
 | 
			
		||||
#ifndef _DMEVENTD_LVMWRAP_H
 | 
			
		||||
#define _DMEVENTD_LVMWRAP_H
 | 
			
		||||
 | 
			
		||||
int dmeventd_lvm2_init(void);
 | 
			
		||||
void dmeventd_lvm2_exit(void);
 | 
			
		||||
int dmeventd_lvm2_run(const char *cmdline);
 | 
			
		||||
 | 
			
		||||
void dmeventd_lvm2_lock(void);
 | 
			
		||||
void dmeventd_lvm2_unlock(void);
 | 
			
		||||
 | 
			
		||||
struct dm_pool *dmeventd_lvm2_pool(void);
 | 
			
		||||
 | 
			
		||||
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
 | 
			
		||||
			  const char *cmd, const char *device);
 | 
			
		||||
 | 
			
		||||
#endif /* _DMEVENTD_LVMWRAP_H */
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										37
									
								
								daemons/dmeventd/plugins/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								daemons/dmeventd/plugins/mirror/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2005, 2008-2011 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
 | 
			
		||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_mirror.c
 | 
			
		||||
 | 
			
		||||
LIB_NAME = libdevmapper-event-lvm2mirror
 | 
			
		||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
 | 
			
		||||
LIB_VERSION = $(LIB_VERSION_LVM)
 | 
			
		||||
 | 
			
		||||
CFLOW_LIST = $(SOURCES)
 | 
			
		||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper $(DAEMON_LIBS)
 | 
			
		||||
 | 
			
		||||
install_lvm2: install_dm_plugin
 | 
			
		||||
 | 
			
		||||
install: install_lvm2
 | 
			
		||||
							
								
								
									
										235
									
								
								daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,235 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005-2012 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "errors.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "dmeventd_lvm.h"
 | 
			
		||||
#include "defaults.h"
 | 
			
		||||
 | 
			
		||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
 | 
			
		||||
/* FIXME Missing openlog? */
 | 
			
		||||
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
 | 
			
		||||
/* FIXME Reformat to 80 char lines. */
 | 
			
		||||
 | 
			
		||||
#define ME_IGNORE    0
 | 
			
		||||
#define ME_INSYNC    1
 | 
			
		||||
#define ME_FAILURE   2
 | 
			
		||||
 | 
			
		||||
static int _process_status_code(const char status_code, const char *dev_name,
 | 
			
		||||
				const char *dev_type, int r)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 *    A => Alive - No failures
 | 
			
		||||
	 *    D => Dead - A write failure occurred leaving mirror out-of-sync
 | 
			
		||||
	 *    F => Flush failed.
 | 
			
		||||
	 *    S => Sync - A sychronization failure occurred, mirror out-of-sync
 | 
			
		||||
	 *    R => Read - A read failure occurred, mirror data unaffected
 | 
			
		||||
	 *    U => Unclassified failure (bug)
 | 
			
		||||
	 */ 
 | 
			
		||||
	if (status_code == 'F') {
 | 
			
		||||
		syslog(LOG_ERR, "%s device %s flush failed.",
 | 
			
		||||
		       dev_type, dev_name);
 | 
			
		||||
		r = ME_FAILURE;
 | 
			
		||||
	} else if (status_code == 'S')
 | 
			
		||||
		syslog(LOG_ERR, "%s device %s sync failed.",
 | 
			
		||||
		       dev_type, dev_name);
 | 
			
		||||
	else if (status_code == 'R')
 | 
			
		||||
		syslog(LOG_ERR, "%s device %s read failed.",
 | 
			
		||||
		       dev_type, dev_name);
 | 
			
		||||
	else if (status_code != 'A') {
 | 
			
		||||
		syslog(LOG_ERR, "%s device %s has failed (%c).",
 | 
			
		||||
		       dev_type, dev_name, status_code);
 | 
			
		||||
		r = ME_FAILURE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)) ||
 | 
			
		||||
	    (num_devs > DEFAULT_MIRROR_MAX_IMAGES) || (num_devs < 0))
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: Code differs from lib/mirror/mirrored.c */
 | 
			
		||||
	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++)
 | 
			
		||||
		r = _process_status_code(dev_status_str[i], args[i],
 | 
			
		||||
			i ? "Secondary mirror" : "Primary mirror", r);
 | 
			
		||||
 | 
			
		||||
	/* Check for bad disk log device */
 | 
			
		||||
	if (log_argc > 1)
 | 
			
		||||
		r = _process_status_code(log_status_str[0],
 | 
			
		||||
					 args[2 + num_devs + log_argc],
 | 
			
		||||
					 "Log", r);
 | 
			
		||||
 | 
			
		||||
	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:
 | 
			
		||||
	dm_free(args);
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
out_parse:
 | 
			
		||||
	dm_free(args);
 | 
			
		||||
	syslog(LOG_ERR, "Unable to parse mirror status string.");
 | 
			
		||||
	return ME_IGNORE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _remove_failed_devices(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
#define CMD_SIZE 256	/* FIXME Use system restriction */
 | 
			
		||||
	char cmd_str[CMD_SIZE];
 | 
			
		||||
 | 
			
		||||
	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
 | 
			
		||||
				  "lvconvert --config devices{ignore_suspended_devices=1} "
 | 
			
		||||
				  "--repair --use-policies", device))
 | 
			
		||||
		return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
 | 
			
		||||
 | 
			
		||||
	r = dmeventd_lvm2_run(cmd_str);
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "Repair of mirrored device %s %s.", device,
 | 
			
		||||
	       (r == ECMD_PROCESSED) ? "finished successfully" : "failed");
 | 
			
		||||
 | 
			
		||||
	return (r == ECMD_PROCESSED) ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(struct dm_task *dmt,
 | 
			
		||||
		   enum dm_event_mask event __attribute__((unused)),
 | 
			
		||||
		   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);
 | 
			
		||||
 | 
			
		||||
	dmeventd_lvm2_lock();
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
					  &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
		if (!target_type) {
 | 
			
		||||
			syslog(LOG_INFO, "%s mapping lost.", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (strcmp(target_type, "mirror")) {
 | 
			
		||||
			syslog(LOG_INFO, "%s has unmirrored portion.", 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.", device);
 | 
			
		||||
			break;
 | 
			
		||||
		case ME_FAILURE:
 | 
			
		||||
			syslog(LOG_ERR, "Device failure in %s.", 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.",
 | 
			
		||||
				       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.");
 | 
			
		||||
		}
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
	dmeventd_lvm2_unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device,
 | 
			
		||||
		    const char *uuid __attribute__((unused)),
 | 
			
		||||
		    int major __attribute__((unused)),
 | 
			
		||||
		    int minor __attribute__((unused)),
 | 
			
		||||
		    void **unused __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
	if (!dmeventd_lvm2_init())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "Monitoring mirror device %s for events.", device);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device,
 | 
			
		||||
		      const char *uuid __attribute__((unused)),
 | 
			
		||||
		      int major __attribute__((unused)),
 | 
			
		||||
		      int minor __attribute__((unused)),
 | 
			
		||||
		      void **unused __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
	syslog(LOG_INFO, "No longer monitoring mirror device %s for events.",
 | 
			
		||||
	       device);
 | 
			
		||||
	dmeventd_lvm2_exit();
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								daemons/dmeventd/plugins/raid/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								daemons/dmeventd/plugins/raid/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
							
								
								
									
										36
									
								
								daemons/dmeventd/plugins/raid/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								daemons/dmeventd/plugins/raid/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2011 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
 | 
			
		||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_raid.c
 | 
			
		||||
 | 
			
		||||
LIB_NAME = libdevmapper-event-lvm2raid
 | 
			
		||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
 | 
			
		||||
LIB_VERSION = $(LIB_VERSION_LVM)
 | 
			
		||||
 | 
			
		||||
CFLOW_LIST = $(SOURCES)
 | 
			
		||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
 | 
			
		||||
 | 
			
		||||
install_lvm2: install_dm_plugin
 | 
			
		||||
 | 
			
		||||
install: install_lvm2
 | 
			
		||||
							
								
								
									
										172
									
								
								daemons/dmeventd/plugins/raid/dmeventd_raid.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								daemons/dmeventd/plugins/raid/dmeventd_raid.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "errors.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "dmeventd_lvm.h"
 | 
			
		||||
 | 
			
		||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
 | 
			
		||||
/* FIXME Missing openlog? */
 | 
			
		||||
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
 | 
			
		||||
/* FIXME Reformat to 80 char lines. */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * run_repair is a close copy to
 | 
			
		||||
 * plugins/mirror/dmeventd_mirror.c:_remove_failed_devices()
 | 
			
		||||
 */
 | 
			
		||||
static int run_repair(const char *device)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
#define CMD_SIZE 256	/* FIXME Use system restriction */
 | 
			
		||||
	char cmd_str[CMD_SIZE];
 | 
			
		||||
 | 
			
		||||
	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
 | 
			
		||||
				  "lvconvert --config devices{ignore_suspended_devices=1} "
 | 
			
		||||
				  "--repair --use-policies", device))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	r = dmeventd_lvm2_run(cmd_str);
 | 
			
		||||
 | 
			
		||||
	if (r != ECMD_PROCESSED)
 | 
			
		||||
		syslog(LOG_INFO, "Repair of RAID device %s failed.", device);
 | 
			
		||||
 | 
			
		||||
	return (r == ECMD_PROCESSED) ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _process_raid_event(char *params, const char *device)
 | 
			
		||||
{
 | 
			
		||||
	int i, n, failure = 0;
 | 
			
		||||
	char *p, *a[4];
 | 
			
		||||
	char *raid_type;
 | 
			
		||||
	char *num_devices;
 | 
			
		||||
	char *health_chars;
 | 
			
		||||
	char *resync_ratio;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * RAID parms:     <raid_type> <#raid_disks> \
 | 
			
		||||
	 *                 <health chars> <resync ratio>
 | 
			
		||||
	 */
 | 
			
		||||
	if (!dm_split_words(params, 4, 0, a)) {
 | 
			
		||||
		syslog(LOG_ERR, "Failed to process status line for %s\n",
 | 
			
		||||
		       device);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	raid_type = a[0];
 | 
			
		||||
	num_devices = a[1];
 | 
			
		||||
	health_chars = a[2];
 | 
			
		||||
	resync_ratio = a[3];
 | 
			
		||||
 | 
			
		||||
	if (!(n = atoi(num_devices))) {
 | 
			
		||||
		syslog(LOG_ERR, "Failed to parse number of devices for %s: %s",
 | 
			
		||||
		       device, num_devices);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < n; i++) {
 | 
			
		||||
		switch (health_chars[i]) {
 | 
			
		||||
		case 'A':
 | 
			
		||||
			/* Device is 'A'live and well */
 | 
			
		||||
		case 'a':
 | 
			
		||||
			/* Device is 'a'live, but not yet in-sync */
 | 
			
		||||
			break;
 | 
			
		||||
		case 'D':
 | 
			
		||||
			syslog(LOG_ERR,
 | 
			
		||||
			       "Device #%d of %s array, %s, has failed.",
 | 
			
		||||
			       i, raid_type, device);
 | 
			
		||||
			failure++;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			/* Unhandled character returned from kernel */
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (failure)
 | 
			
		||||
			return run_repair(device);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p = strstr(resync_ratio, "/");
 | 
			
		||||
	if (!p) {
 | 
			
		||||
		syslog(LOG_ERR, "Failed to parse resync_ratio for %s: %s",
 | 
			
		||||
		       device, resync_ratio);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	p[0] = '\0';
 | 
			
		||||
	syslog(LOG_INFO, "%s array, %s, is %s in-sync.",
 | 
			
		||||
	       raid_type, device, strcmp(resync_ratio, p+1) ? "not" : "now");
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(struct dm_task *dmt,
 | 
			
		||||
		   enum dm_event_mask event __attribute__((unused)),
 | 
			
		||||
		   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);
 | 
			
		||||
 | 
			
		||||
	dmeventd_lvm2_lock();
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		next = dm_get_next_target(dmt, next, &start, &length,
 | 
			
		||||
					  &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
		if (!target_type) {
 | 
			
		||||
			syslog(LOG_INFO, "%s mapping lost.", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (strcmp(target_type, "raid")) {
 | 
			
		||||
			syslog(LOG_INFO, "%s has non-raid portion.", device);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (_process_raid_event(params, device))
 | 
			
		||||
			syslog(LOG_ERR, "Failed to process event for %s",
 | 
			
		||||
			       device);
 | 
			
		||||
	} while (next);
 | 
			
		||||
 | 
			
		||||
	dmeventd_lvm2_unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device,
 | 
			
		||||
		    const char *uuid __attribute__((unused)),
 | 
			
		||||
		    int major __attribute__((unused)),
 | 
			
		||||
		    int minor __attribute__((unused)),
 | 
			
		||||
		    void **unused __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
	if (!dmeventd_lvm2_init())
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "Monitoring RAID device %s for events.", device);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device,
 | 
			
		||||
		      const char *uuid __attribute__((unused)),
 | 
			
		||||
		      int major __attribute__((unused)),
 | 
			
		||||
		      int minor __attribute__((unused)),
 | 
			
		||||
		      void **unused __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
	syslog(LOG_INFO, "No longer monitoring RAID device %s for events.",
 | 
			
		||||
	       device);
 | 
			
		||||
	dmeventd_lvm2_exit();
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								daemons/dmeventd/plugins/snapshot/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								daemons/dmeventd/plugins/snapshot/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
							
								
								
									
										33
									
								
								daemons/dmeventd/plugins/snapshot/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								daemons/dmeventd/plugins/snapshot/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | 
			
		||||
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# This file is part of the LVM2.
 | 
			
		||||
#
 | 
			
		||||
# This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
# modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
# of the GNU General Public License v.2.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
 | 
			
		||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_snapshot.c
 | 
			
		||||
 | 
			
		||||
LIB_SHARED = libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
 | 
			
		||||
LIB_VERSION = $(LIB_VERSION_LVM)
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper $(DAEMON_LIBS)
 | 
			
		||||
 | 
			
		||||
install_lvm2: install_dm_plugin
 | 
			
		||||
 | 
			
		||||
install: install_lvm2
 | 
			
		||||
							
								
								
									
										283
									
								
								daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,283 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2007-2011 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "errors.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "dmeventd_lvm.h"
 | 
			
		||||
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
 | 
			
		||||
/* FIXME Missing openlog? */
 | 
			
		||||
 | 
			
		||||
/* First warning when snapshot is 80% full. */
 | 
			
		||||
#define WARNING_THRESH 80
 | 
			
		||||
/* Run a check every 5%. */
 | 
			
		||||
#define CHECK_STEP 5
 | 
			
		||||
/* Do not bother checking snapshots less than 50% full. */
 | 
			
		||||
#define CHECK_MINIMUM 50
 | 
			
		||||
 | 
			
		||||
#define UMOUNT_COMMAND "/bin/umount"
 | 
			
		||||
 | 
			
		||||
struct snap_status {
 | 
			
		||||
	int invalid;
 | 
			
		||||
	int used;
 | 
			
		||||
	int max;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct dso_state {
 | 
			
		||||
	int percent_check;
 | 
			
		||||
	int known_size;
 | 
			
		||||
	char cmd_str[1024];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* FIXME possibly reconcile this with target_percent when we gain
 | 
			
		||||
   access to regular LVM library here. */
 | 
			
		||||
static void _parse_snapshot_params(char *params, struct snap_status *status)
 | 
			
		||||
{
 | 
			
		||||
	char *p;
 | 
			
		||||
	/*
 | 
			
		||||
	 * xx/xx	-- fractions used/max
 | 
			
		||||
	 * Invalid	-- snapshot invalidated
 | 
			
		||||
	 * Unknown	-- status unknown
 | 
			
		||||
	 */
 | 
			
		||||
	status->used = status->max = 0;
 | 
			
		||||
 | 
			
		||||
	if (!strncmp(params, "Invalid", 7)) {
 | 
			
		||||
		status->invalid = 1;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * When we return without setting non-zero max, the parent is
 | 
			
		||||
	 * responsible for reporting errors.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!strncmp(params, "Unknown", 7))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (!(p = strstr(params, "/")))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	*p = '\0';
 | 
			
		||||
	p++;
 | 
			
		||||
 | 
			
		||||
	status->used = atoi(params);
 | 
			
		||||
	status->max = atoi(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _run(const char *cmd, ...)
 | 
			
		||||
{
 | 
			
		||||
        va_list ap;
 | 
			
		||||
        int argc = 1; /* for argv[0], i.e. cmd */
 | 
			
		||||
        int i = 0;
 | 
			
		||||
        const char **argv;
 | 
			
		||||
        pid_t pid = fork();
 | 
			
		||||
        int status;
 | 
			
		||||
 | 
			
		||||
        if (pid == 0) { /* child */
 | 
			
		||||
                va_start(ap, cmd);
 | 
			
		||||
                while (va_arg(ap, const char *))
 | 
			
		||||
                        ++ argc;
 | 
			
		||||
                va_end(ap);
 | 
			
		||||
 | 
			
		||||
                /* + 1 for the terminating NULL */
 | 
			
		||||
                argv = alloca(sizeof(const char *) * (argc + 1));
 | 
			
		||||
 | 
			
		||||
                argv[0] = cmd;
 | 
			
		||||
                va_start(ap, cmd);
 | 
			
		||||
                while ((argv[++i] = va_arg(ap, const char *)));
 | 
			
		||||
                va_end(ap);
 | 
			
		||||
 | 
			
		||||
                execvp(cmd, (char **)argv);
 | 
			
		||||
                syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
 | 
			
		||||
                exit(127);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (pid > 0) { /* parent */
 | 
			
		||||
                if (waitpid(pid, &status, 0) != pid)
 | 
			
		||||
                        return 0; /* waitpid failed */
 | 
			
		||||
                if (!WIFEXITED(status) || WEXITSTATUS(status))
 | 
			
		||||
                        return 0; /* the child failed */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (pid < 0)
 | 
			
		||||
                return 0; /* fork failed */
 | 
			
		||||
 | 
			
		||||
        return 1; /* all good */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _extend(const char *cmd)
 | 
			
		||||
{
 | 
			
		||||
	return dmeventd_lvm2_run(cmd) == ECMD_PROCESSED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _umount(const char *device, int major, int minor)
 | 
			
		||||
{
 | 
			
		||||
	FILE *mounts;
 | 
			
		||||
	char buffer[4096];
 | 
			
		||||
	char *words[3];
 | 
			
		||||
	struct stat st;
 | 
			
		||||
 | 
			
		||||
	if (!(mounts = fopen("/proc/mounts", "r"))) {
 | 
			
		||||
		syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (!feof(mounts)) {
 | 
			
		||||
		/* read a line of /proc/mounts */
 | 
			
		||||
		if (!fgets(buffer, sizeof(buffer), mounts))
 | 
			
		||||
			break; /* eof, likely */
 | 
			
		||||
 | 
			
		||||
		/* words[0] is the mount point and words[1] is the device path */
 | 
			
		||||
		if (dm_split_words(buffer, 3, 0, words) < 2)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* find the major/minor of the device */
 | 
			
		||||
		if (stat(words[0], &st))
 | 
			
		||||
			continue; /* can't stat, skip this one */
 | 
			
		||||
 | 
			
		||||
		if (S_ISBLK(st.st_mode) &&
 | 
			
		||||
		    major(st.st_rdev) == major &&
 | 
			
		||||
		    minor(st.st_rdev) == minor) {
 | 
			
		||||
			syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.\n", device, words[1]);
 | 
			
		||||
                        if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
 | 
			
		||||
                                syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.\n",
 | 
			
		||||
                                       device, words[1], strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fclose(mounts))
 | 
			
		||||
		syslog(LOG_ERR, "Failed to close /proc/mounts.\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void process_event(struct dm_task *dmt,
 | 
			
		||||
		   enum dm_event_mask event __attribute__((unused)),
 | 
			
		||||
		   void **private)
 | 
			
		||||
{
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *target_type = NULL;
 | 
			
		||||
	char *params;
 | 
			
		||||
	struct snap_status status = { 0 };
 | 
			
		||||
	const char *device = dm_task_get_name(dmt);
 | 
			
		||||
	int percent;
 | 
			
		||||
	struct dso_state *state = *private;
 | 
			
		||||
 | 
			
		||||
	/* No longer monitoring, waiting for remove */
 | 
			
		||||
	if (!state->percent_check)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	dmeventd_lvm2_lock();
 | 
			
		||||
 | 
			
		||||
	dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
 | 
			
		||||
	if (!target_type)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	_parse_snapshot_params(params, &status);
 | 
			
		||||
 | 
			
		||||
	if (status.invalid) {
 | 
			
		||||
		struct dm_info info;
 | 
			
		||||
		if (dm_task_get_info(dmt, &info)) {
 | 
			
		||||
			dmeventd_lvm2_unlock();
 | 
			
		||||
			_umount(device, info.major, info.minor);
 | 
			
		||||
                        return;
 | 
			
		||||
		} /* else; too bad, but this is best-effort thing... */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Snapshot size had changed. Clear the threshold. */
 | 
			
		||||
	if (state->known_size != status.max) {
 | 
			
		||||
		state->percent_check = CHECK_MINIMUM;
 | 
			
		||||
		state->known_size = status.max;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If the snapshot has been invalidated or we failed to parse
 | 
			
		||||
	 * the status string. Report the full status string to syslog.
 | 
			
		||||
	 */
 | 
			
		||||
	if (status.invalid || !status.max) {
 | 
			
		||||
		syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
 | 
			
		||||
		state->percent_check = 0;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	percent = 100 * status.used / status.max;
 | 
			
		||||
	if (percent >= state->percent_check) {
 | 
			
		||||
		/* Usage has raised more than CHECK_STEP since the last
 | 
			
		||||
		   time. Run actions. */
 | 
			
		||||
		state->percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
 | 
			
		||||
 | 
			
		||||
		if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
 | 
			
		||||
			syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
 | 
			
		||||
		/* Try to extend the snapshot, in accord with user-set policies */
 | 
			
		||||
		if (!_extend(state->cmd_str))
 | 
			
		||||
			syslog(LOG_ERR, "Failed to extend snapshot %s.\n", device);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	dmeventd_lvm2_unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device,
 | 
			
		||||
		    const char *uuid __attribute__((unused)),
 | 
			
		||||
		    int major __attribute__((unused)),
 | 
			
		||||
		    int minor __attribute__((unused)),
 | 
			
		||||
		    void **private)
 | 
			
		||||
{
 | 
			
		||||
	struct dso_state *state;
 | 
			
		||||
 | 
			
		||||
	if (!dmeventd_lvm2_init())
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	if (!(state = dm_zalloc(sizeof(*state))))
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(),
 | 
			
		||||
                                   state->cmd_str, sizeof(state->cmd_str),
 | 
			
		||||
				   "lvextend --use-policies", device))
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	state->percent_check = CHECK_MINIMUM;
 | 
			
		||||
	state->known_size = 0;
 | 
			
		||||
	*private = state;
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
bad:
 | 
			
		||||
	dm_free(state);
 | 
			
		||||
	dmeventd_lvm2_exit();
 | 
			
		||||
out:
 | 
			
		||||
	syslog(LOG_ERR, "Failed to monitor snapshot %s.\n", device);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device,
 | 
			
		||||
		      const char *uuid __attribute__((unused)),
 | 
			
		||||
		      int major __attribute__((unused)),
 | 
			
		||||
		      int minor __attribute__((unused)),
 | 
			
		||||
		      void **private)
 | 
			
		||||
{
 | 
			
		||||
	struct dso_state *state = *private;
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "No longer monitoring snapshot %s\n", device);
 | 
			
		||||
	dm_free(state);
 | 
			
		||||
	dmeventd_lvm2_exit();
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								daemons/dmeventd/plugins/thin/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								daemons/dmeventd/plugins/thin/.exported_symbols
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
process_event
 | 
			
		||||
register_device
 | 
			
		||||
unregister_device
 | 
			
		||||
							
								
								
									
										36
									
								
								daemons/dmeventd/plugins/thin/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								daemons/dmeventd/plugins/thin/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2011 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
 | 
			
		||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
 | 
			
		||||
 | 
			
		||||
SOURCES = dmeventd_thin.c
 | 
			
		||||
 | 
			
		||||
LIB_NAME = libdevmapper-event-lvm2thin
 | 
			
		||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
 | 
			
		||||
LIB_VERSION = $(LIB_VERSION_LVM)
 | 
			
		||||
 | 
			
		||||
CFLOW_LIST = $(SOURCES)
 | 
			
		||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
 | 
			
		||||
 | 
			
		||||
install_lvm2: install_dm_plugin
 | 
			
		||||
 | 
			
		||||
install: install_lvm2
 | 
			
		||||
							
								
								
									
										288
									
								
								daemons/dmeventd/plugins/thin/dmeventd_thin.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								daemons/dmeventd/plugins/thin/dmeventd_thin.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,288 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lib.h"
 | 
			
		||||
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include "errors.h"
 | 
			
		||||
#include "libdevmapper-event.h"
 | 
			
		||||
#include "dmeventd_lvm.h"
 | 
			
		||||
 | 
			
		||||
#include "lvm-string.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
 | 
			
		||||
/* FIXME Missing openlog? */
 | 
			
		||||
 | 
			
		||||
/* First warning when thin is 80% full. */
 | 
			
		||||
#define WARNING_THRESH 80
 | 
			
		||||
/* Run a check every 5%. */
 | 
			
		||||
#define CHECK_STEP 5
 | 
			
		||||
/* Do not bother checking thins less than 50% full. */
 | 
			
		||||
#define CHECK_MINIMUM 50
 | 
			
		||||
 | 
			
		||||
#define UMOUNT_COMMAND "/bin/umount"
 | 
			
		||||
 | 
			
		||||
#define THIN_DEBUG 0
 | 
			
		||||
 | 
			
		||||
struct dso_state {
 | 
			
		||||
	struct dm_pool *mem;
 | 
			
		||||
	int metadata_percent_check;
 | 
			
		||||
	int data_percent_check;
 | 
			
		||||
	uint64_t known_metadata_size;
 | 
			
		||||
	uint64_t known_data_size;
 | 
			
		||||
	char cmd_str[1024];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int _extend(struct dso_state *state)
 | 
			
		||||
{
 | 
			
		||||
#if THIN_DEBUG
 | 
			
		||||
	syslog(LOG_INFO, "dmeventd executes: %s.\n", state->cmd_str);
 | 
			
		||||
#endif
 | 
			
		||||
	return (dmeventd_lvm2_run(state->cmd_str) == ECMD_PROCESSED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int _run(const char *cmd, ...)
 | 
			
		||||
{
 | 
			
		||||
        va_list ap;
 | 
			
		||||
        int argc = 1; /* for argv[0], i.e. cmd */
 | 
			
		||||
        int i = 0;
 | 
			
		||||
        const char **argv;
 | 
			
		||||
        pid_t pid = fork();
 | 
			
		||||
        int status;
 | 
			
		||||
 | 
			
		||||
        if (pid == 0) { /* child */
 | 
			
		||||
                va_start(ap, cmd);
 | 
			
		||||
                while (va_arg(ap, const char *))
 | 
			
		||||
                        ++argc;
 | 
			
		||||
                va_end(ap);
 | 
			
		||||
 | 
			
		||||
                /* + 1 for the terminating NULL */
 | 
			
		||||
                argv = alloca(sizeof(const char *) * (argc + 1));
 | 
			
		||||
 | 
			
		||||
                argv[0] = cmd;
 | 
			
		||||
                va_start(ap, cmd);
 | 
			
		||||
                while ((argv[++i] = va_arg(ap, const char *)));
 | 
			
		||||
                va_end(ap);
 | 
			
		||||
 | 
			
		||||
                execvp(cmd, (char **)argv);
 | 
			
		||||
                syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
 | 
			
		||||
                exit(127);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (pid > 0) { /* parent */
 | 
			
		||||
                if (waitpid(pid, &status, 0) != pid)
 | 
			
		||||
                        return 0; /* waitpid failed */
 | 
			
		||||
                if (!WIFEXITED(status) || WEXITSTATUS(status))
 | 
			
		||||
                        return 0; /* the child failed */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (pid < 0)
 | 
			
		||||
                return 0; /* fork failed */
 | 
			
		||||
 | 
			
		||||
        return 1; /* all good */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME: all thin pool users needs to be here */
 | 
			
		||||
static void _umount(const char *device, int major, int minor)
 | 
			
		||||
{
 | 
			
		||||
	FILE *mounts;
 | 
			
		||||
	char buffer[4096];
 | 
			
		||||
	char *words[3];
 | 
			
		||||
	struct stat st;
 | 
			
		||||
 | 
			
		||||
	if (!(mounts = fopen("/proc/mounts", "r"))) {
 | 
			
		||||
		syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (!feof(mounts)) {
 | 
			
		||||
		/* read a line of /proc/mounts */
 | 
			
		||||
		if (!fgets(buffer, sizeof(buffer), mounts))
 | 
			
		||||
			break; /* eof, likely */
 | 
			
		||||
 | 
			
		||||
		/* words[0] is the mount point and words[1] is the device path */
 | 
			
		||||
		dm_split_words(buffer, 3, 0, words);
 | 
			
		||||
 | 
			
		||||
		/* find the major/minor of the device */
 | 
			
		||||
		if (stat(words[0], &st))
 | 
			
		||||
			continue; /* can't stat, skip this one */
 | 
			
		||||
 | 
			
		||||
		if (S_ISBLK(st.st_mode) &&
 | 
			
		||||
		    (int) major(st.st_rdev) == major &&
 | 
			
		||||
		    (int) minor(st.st_rdev) == minor) {
 | 
			
		||||
			syslog(LOG_ERR, "Unmounting invalid thin %s from %s.\n", device, words[1]);
 | 
			
		||||
			if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
 | 
			
		||||
				syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
 | 
			
		||||
				       device, words[1], strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fclose(mounts))
 | 
			
		||||
		syslog(LOG_ERR, "Failed to close /proc/mounts.\n");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void process_event(struct dm_task *dmt,
 | 
			
		||||
		   enum dm_event_mask event __attribute__((unused)),
 | 
			
		||||
		   void **private)
 | 
			
		||||
{
 | 
			
		||||
	const char *device = dm_task_get_name(dmt);
 | 
			
		||||
	int percent;
 | 
			
		||||
	struct dso_state *state = *private;
 | 
			
		||||
	struct dm_status_thin_pool *tps = NULL;
 | 
			
		||||
	void *next = NULL;
 | 
			
		||||
	uint64_t start, length;
 | 
			
		||||
	char *target_type = NULL;
 | 
			
		||||
	char *params;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	/* No longer monitoring, waiting for remove */
 | 
			
		||||
	if (!state->meta_percent_check && !state->data_percent_check)
 | 
			
		||||
		return;
 | 
			
		||||
#endif
 | 
			
		||||
	dmeventd_lvm2_lock();
 | 
			
		||||
 | 
			
		||||
	dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
 | 
			
		||||
 | 
			
		||||
	if (!target_type || (strcmp(target_type, "thin-pool") != 0)) {
 | 
			
		||||
		syslog(LOG_ERR, "Invalid target type.\n");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
 | 
			
		||||
		syslog(LOG_ERR, "Failed to parse status.\n");
 | 
			
		||||
#if 0
 | 
			
		||||
		/* FIXME hmm what we should do? */
 | 
			
		||||
		struct dm_info info;
 | 
			
		||||
		if (dm_task_get_info(dmt, &info)) {
 | 
			
		||||
			dmeventd_lvm2_unlock();
 | 
			
		||||
			_umount(device, info.major, info.minor);
 | 
			
		||||
		} /* else; too bad, but this is best-effort thing... */
 | 
			
		||||
#endif
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if THIN_DEBUG
 | 
			
		||||
	syslog(LOG_INFO, "%p: Got status %" PRIu64 " / %" PRIu64
 | 
			
		||||
	       " %" PRIu64  " / %" PRIu64 ".\n", state,
 | 
			
		||||
	       tps->used_metadata_blocks, tps->total_metadata_blocks,
 | 
			
		||||
	       tps->used_data_blocks, tps->total_data_blocks);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Thin pool size had changed. Clear the threshold. */
 | 
			
		||||
	if (state->known_metadata_size != tps->total_metadata_blocks) {
 | 
			
		||||
		state->metadata_percent_check = CHECK_MINIMUM;
 | 
			
		||||
		state->known_metadata_size = tps->total_metadata_blocks;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (state->known_data_size != tps->total_data_blocks) {
 | 
			
		||||
		state->data_percent_check = CHECK_MINIMUM;
 | 
			
		||||
		state->known_data_size = tps->total_data_blocks;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	percent = 100 * tps->used_metadata_blocks / tps->total_metadata_blocks;
 | 
			
		||||
	if (percent >= state->metadata_percent_check) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Usage has raised more than CHECK_STEP since the last
 | 
			
		||||
		 * time. Run actions.
 | 
			
		||||
		 */
 | 
			
		||||
		state->metadata_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
 | 
			
		||||
 | 
			
		||||
		/* FIXME: extension of metadata needs to be written! */
 | 
			
		||||
		if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
 | 
			
		||||
			syslog(LOG_WARNING, "Thin metadata %s is now %i%% full.\n",
 | 
			
		||||
			       device, percent);
 | 
			
		||||
		 /* Try to extend the metadata, in accord with user-set policies */
 | 
			
		||||
		if (!_extend(state))
 | 
			
		||||
			syslog(LOG_ERR, "Failed to extend thin metadata %s.\n",
 | 
			
		||||
			       device);
 | 
			
		||||
		/* FIXME: hmm READ-ONLY switch should happen in error path */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	percent = 100 * tps->used_data_blocks / tps->total_data_blocks;
 | 
			
		||||
	if (percent >= state->data_percent_check) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Usage has raised more than CHECK_STEP since
 | 
			
		||||
		 * the last time. Run actions.
 | 
			
		||||
		 */
 | 
			
		||||
		state->data_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
 | 
			
		||||
 | 
			
		||||
		if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
 | 
			
		||||
			syslog(LOG_WARNING, "Thin %s is now %i%% full.\n", device, percent);
 | 
			
		||||
		/* Try to extend the thin data, in accord with user-set policies */
 | 
			
		||||
		if (!_extend(state))
 | 
			
		||||
			syslog(LOG_ERR, "Failed to extend thin %s.\n", device);
 | 
			
		||||
		/* FIXME: hmm READ-ONLY switch should happen in error path */
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	if (tps)
 | 
			
		||||
		dm_pool_free(state->mem, tps);
 | 
			
		||||
 | 
			
		||||
	dmeventd_lvm2_unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int register_device(const char *device,
 | 
			
		||||
		    const char *uuid __attribute__((unused)),
 | 
			
		||||
		    int major __attribute__((unused)),
 | 
			
		||||
		    int minor __attribute__((unused)),
 | 
			
		||||
		    void **private)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_pool *statemem = NULL;
 | 
			
		||||
	struct dso_state *state;
 | 
			
		||||
 | 
			
		||||
	if (!dmeventd_lvm2_init())
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	if (!(statemem = dm_pool_create("thin_pool_state", 2048)) ||
 | 
			
		||||
	    !(state = dm_pool_zalloc(statemem, sizeof(*state))) ||
 | 
			
		||||
	    !dmeventd_lvm2_command(statemem, state->cmd_str,
 | 
			
		||||
				   sizeof(state->cmd_str),
 | 
			
		||||
				   "lvextend --use-policies",
 | 
			
		||||
				   device)) {
 | 
			
		||||
		if (statemem)
 | 
			
		||||
			dm_pool_destroy(statemem);
 | 
			
		||||
		dmeventd_lvm2_exit();
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	state->mem = statemem;
 | 
			
		||||
	state->metadata_percent_check = CHECK_MINIMUM;
 | 
			
		||||
	state->data_percent_check = CHECK_MINIMUM;
 | 
			
		||||
	*private = state;
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "Monitoring thin %s.\n", device);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
bad:
 | 
			
		||||
	syslog(LOG_ERR, "Failed to monitor thin %s.\n", device);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int unregister_device(const char *device,
 | 
			
		||||
		      const char *uuid __attribute__((unused)),
 | 
			
		||||
		      int major __attribute__((unused)),
 | 
			
		||||
		      int minor __attribute__((unused)),
 | 
			
		||||
		      void **private)
 | 
			
		||||
{
 | 
			
		||||
	struct dso_state *state = *private;
 | 
			
		||||
 | 
			
		||||
	syslog(LOG_INFO, "No longer monitoring thin %s.\n", device);
 | 
			
		||||
	dm_pool_destroy(state->mem);
 | 
			
		||||
	dmeventd_lvm2_exit();
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								daemons/lvmetad/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								daemons/lvmetad/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2011-2012 Red Hat, Inc.
 | 
			
		||||
#
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
srcdir = @srcdir@
 | 
			
		||||
top_srcdir = @top_srcdir@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
SOURCES = lvmetad-core.c
 | 
			
		||||
SOURCES2 = testclient.c
 | 
			
		||||
 | 
			
		||||
TARGETS = lvmetad lvmetad-testclient
 | 
			
		||||
 | 
			
		||||
.PHONY: install_lvmetad
 | 
			
		||||
 | 
			
		||||
CFLOW_LIST = $(SOURCES)
 | 
			
		||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
 | 
			
		||||
CFLOW_TARGET = lvmetad
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
 | 
			
		||||
LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
 | 
			
		||||
 | 
			
		||||
LIBS += $(PTHREAD_LIBS)
 | 
			
		||||
 | 
			
		||||
LDFLAGS += -L$(top_builddir)/libdaemon/server
 | 
			
		||||
CLDFLAGS += -L$(top_builddir)/libdaemon/server
 | 
			
		||||
 | 
			
		||||
lvmetad: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
 | 
			
		||||
		    $(top_builddir)/libdaemon/server/libdaemonserver.a
 | 
			
		||||
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
 | 
			
		||||
	$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
 | 
			
		||||
 | 
			
		||||
# TODO: No idea. No idea how to test either.
 | 
			
		||||
#ifneq ("$(CFLOW_CMD)", "")
 | 
			
		||||
#CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
 | 
			
		||||
#-include $(top_builddir)/libdm/libdevmapper.cflow
 | 
			
		||||
#-include $(top_builddir)/lib/liblvm-internal.cflow
 | 
			
		||||
#-include $(top_builddir)/lib/liblvm2cmd.cflow
 | 
			
		||||
#-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
 | 
			
		||||
#-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
install_lvmetad: lvmetad
 | 
			
		||||
	$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
 | 
			
		||||
 | 
			
		||||
install_lvm2: install_lvmetad
 | 
			
		||||
 | 
			
		||||
install: install_lvm2
 | 
			
		||||
							
								
								
									
										81
									
								
								daemons/lvmetad/lvmetad-client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								daemons/lvmetad/lvmetad-client.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2011-2012 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU Lesser General Public License v.2.1.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _LVM_LVMETAD_CLIENT_H
 | 
			
		||||
#define _LVM_LVMETAD_CLIENT_H
 | 
			
		||||
 | 
			
		||||
#include "daemon-client.h"
 | 
			
		||||
 | 
			
		||||
struct volume_group;
 | 
			
		||||
 | 
			
		||||
/* Different types of replies we may get from lvmetad. */
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	daemon_reply r;
 | 
			
		||||
	const char **uuids; /* NULL terminated array */
 | 
			
		||||
} lvmetad_uuidlist;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	daemon_reply r;
 | 
			
		||||
	struct dm_config_tree *cft;
 | 
			
		||||
} lvmetad_vg;
 | 
			
		||||
 | 
			
		||||
/* Get a list of VG UUIDs that match a given VG name. */
 | 
			
		||||
lvmetad_uuidlist lvmetad_lookup_vgname(daemon_handle h, const char *name);
 | 
			
		||||
 | 
			
		||||
/* Get the metadata of a single VG, identified by UUID. */
 | 
			
		||||
lvmetad_vg lvmetad_get_vg(daemon_handle h, const char *uuid);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Add and remove PVs on demand. Udev-driven systems will use this interface
 | 
			
		||||
 * instead of scanning.
 | 
			
		||||
 */
 | 
			
		||||
daemon_reply lvmetad_add_pv(daemon_handle h, const char *pv_uuid, const char *mda_content);
 | 
			
		||||
daemon_reply lvmetad_remove_pv(daemon_handle h, const char *pv_uuid);
 | 
			
		||||
 | 
			
		||||
/* Trigger a full disk scan, throwing away all caches. XXX do we eventually want
 | 
			
		||||
 * this? Probably not yet, anyway.
 | 
			
		||||
 *     daemon_reply lvmetad_rescan(daemon_handle h);
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Update the version of metadata of a volume group. The VG has to be locked for
 | 
			
		||||
 * writing for this, and the VG metadata here has to match whatever has been
 | 
			
		||||
 * written to the disk (under this lock). This initially avoids the requirement
 | 
			
		||||
 * for lvmetad to write to disk (in later revisions, lvmetad_supersede_vg may
 | 
			
		||||
 * also do the writing, or we probably add another function to do that).
 | 
			
		||||
 */
 | 
			
		||||
daemon_reply lvmetad_supersede_vg(daemon_handle h, struct volume_group *vg);
 | 
			
		||||
 | 
			
		||||
/* Wrappers to open/close connection */
 | 
			
		||||
 | 
			
		||||
static inline daemon_handle lvmetad_open(const char *socket)
 | 
			
		||||
{
 | 
			
		||||
	daemon_info lvmetad_info = {
 | 
			
		||||
		.path = "lvmetad",
 | 
			
		||||
		.socket = socket ?: DEFAULT_RUN_DIR "/lvmetad.socket",
 | 
			
		||||
		.protocol = "lvmetad",
 | 
			
		||||
		.protocol_version = 1,
 | 
			
		||||
		.autostart = 0
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	return daemon_open(lvmetad_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void lvmetad_close(daemon_handle h)
 | 
			
		||||
{
 | 
			
		||||
	return daemon_close(h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1131
									
								
								daemons/lvmetad/lvmetad-core.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1131
									
								
								daemons/lvmetad/lvmetad-core.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										16
									
								
								daemons/lvmetad/test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								daemons/lvmetad/test.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
export LD_LIBRARY_PATH="$1"
 | 
			
		||||
 | 
			
		||||
test -n "$2" && {
 | 
			
		||||
    rm -f /var/run/lvmetad.{socket,pid}
 | 
			
		||||
    chmod +rx lvmetad
 | 
			
		||||
    valgrind ./lvmetad -f &
 | 
			
		||||
    PID=$!
 | 
			
		||||
    sleep 1
 | 
			
		||||
    ./testclient
 | 
			
		||||
    kill $PID
 | 
			
		||||
    exit 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sudo ./test.sh "$1" .
 | 
			
		||||
							
								
								
									
										127
									
								
								daemons/lvmetad/testclient.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								daemons/lvmetad/testclient.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
			
		||||
#include "lvmetad-client.h"
 | 
			
		||||
#include "label.h"
 | 
			
		||||
#include "lvmcache.h"
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
const char *uuid1 = "abcd-efgh";
 | 
			
		||||
const char *uuid2 = "bbcd-efgh";
 | 
			
		||||
const char *vgid = "yada-yada";
 | 
			
		||||
const char *uuid3 = "cbcd-efgh";
 | 
			
		||||
 | 
			
		||||
const char *metadata2 = "{\n"
 | 
			
		||||
	"id = \"yada-yada\"\n"
 | 
			
		||||
	"seqno = 15\n"
 | 
			
		||||
	"status = [\"READ\", \"WRITE\"]\n"
 | 
			
		||||
	"flags = []\n"
 | 
			
		||||
	"extent_size = 8192\n"
 | 
			
		||||
	"physical_volumes {\n"
 | 
			
		||||
	"    pv0 {\n"
 | 
			
		||||
	"        id = \"abcd-efgh\"\n"
 | 
			
		||||
	"    }\n"
 | 
			
		||||
	"    pv1 {\n"
 | 
			
		||||
	"        id = \"bbcd-efgh\"\n"
 | 
			
		||||
	"    }\n"
 | 
			
		||||
	"    pv2 {\n"
 | 
			
		||||
	"        id = \"cbcd-efgh\"\n"
 | 
			
		||||
	"    }\n"
 | 
			
		||||
	"}\n"
 | 
			
		||||
	"}\n";
 | 
			
		||||
 | 
			
		||||
void _handle_reply(daemon_reply reply) {
 | 
			
		||||
	const char *repl = daemon_reply_str(reply, "response", NULL);
 | 
			
		||||
	const char *status = daemon_reply_str(reply, "status", NULL);
 | 
			
		||||
	const char *vgid = daemon_reply_str(reply, "vgid", NULL);
 | 
			
		||||
 | 
			
		||||
	fprintf(stderr, "[C] REPLY: %s\n", repl);
 | 
			
		||||
	if (!strcmp(repl, "failed"))
 | 
			
		||||
		fprintf(stderr, "[C] REASON: %s\n", daemon_reply_str(reply, "reason", "unknown"));
 | 
			
		||||
	if (vgid)
 | 
			
		||||
		fprintf(stderr, "[C] VGID: %s\n", vgid);
 | 
			
		||||
	if (status)
 | 
			
		||||
		fprintf(stderr, "[C] STATUS: %s\n", status);
 | 
			
		||||
	daemon_reply_destroy(reply);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _pv_add(daemon_handle h, const char *uuid, const char *metadata)
 | 
			
		||||
{
 | 
			
		||||
	daemon_reply reply = daemon_send_simple(h, "pv_add", "uuid = %s", uuid,
 | 
			
		||||
						             "metadata = %b", metadata,
 | 
			
		||||
						             NULL);
 | 
			
		||||
	_handle_reply(reply);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int scan(daemon_handle h, char *fn) {
 | 
			
		||||
	struct device *dev = dev_cache_get(fn, NULL);
 | 
			
		||||
 | 
			
		||||
	struct label *label;
 | 
			
		||||
	if (!label_read(dev, &label, 0)) {
 | 
			
		||||
		fprintf(stderr, "[C] no label found on %s\n", fn);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	char uuid[64];
 | 
			
		||||
	id_write_format(dev->pvid, uuid, 64);
 | 
			
		||||
	fprintf(stderr, "[C] found PV: %s\n", uuid);
 | 
			
		||||
	struct lvmcache_info *info = (struct lvmcache_info *) label->info;
 | 
			
		||||
	struct physical_volume pv = { 0, };
 | 
			
		||||
 | 
			
		||||
	if (!(info->fmt->ops->pv_read(info->fmt, dev_name(dev), &pv, 0))) {
 | 
			
		||||
		fprintf(stderr, "[C] Failed to read PV %s", dev_name(dev));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct format_instance_ctx fic;
 | 
			
		||||
	struct format_instance *fid = info->fmt->ops->create_instance(info->fmt, &fic);
 | 
			
		||||
	struct metadata_area *mda;
 | 
			
		||||
	struct volume_group *vg = NULL;
 | 
			
		||||
	dm_list_iterate_items(mda, &info->mdas) {
 | 
			
		||||
		struct volume_group *this = mda->ops->vg_read(fid, "", mda);
 | 
			
		||||
		if (this && !vg || this->seqno > vg->seqno)
 | 
			
		||||
			vg = this;
 | 
			
		||||
	}
 | 
			
		||||
	if (vg) {
 | 
			
		||||
		char *buf = NULL;
 | 
			
		||||
		/* TODO. This is not entirely correct, since export_vg_to_buffer
 | 
			
		||||
		 * adds trailing garbage to the buffer. We may need to use
 | 
			
		||||
		 * export_vg_to_config_tree and format the buffer ourselves. It
 | 
			
		||||
		 * does, however, work for now, since the garbage is well
 | 
			
		||||
		 * formatted and has no conflicting keys with the rest of the
 | 
			
		||||
		 * request.  */
 | 
			
		||||
		export_vg_to_buffer(vg, &buf);
 | 
			
		||||
		daemon_reply reply =
 | 
			
		||||
			daemon_send_simple(h, "pv_add", "uuid = %s", uuid,
 | 
			
		||||
					      "metadata = %b", strchr(buf, '{'),
 | 
			
		||||
					      NULL);
 | 
			
		||||
		_handle_reply(reply);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _dump_vg(daemon_handle h, const char *uuid)
 | 
			
		||||
{
 | 
			
		||||
	daemon_reply reply = daemon_send_simple(h, "vg_by_uuid", "uuid = %s", uuid, NULL);
 | 
			
		||||
	fprintf(stderr, "[C] reply buffer: %s\n", reply.buffer);
 | 
			
		||||
	daemon_reply_destroy(reply);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
	daemon_handle h = lvmetad_open();
 | 
			
		||||
 | 
			
		||||
	if (argc > 1) {
 | 
			
		||||
		int i;
 | 
			
		||||
		struct cmd_context *cmd = create_toolcontext(0, NULL, 0, 0);
 | 
			
		||||
		for (i = 1; i < argc; ++i) {
 | 
			
		||||
			const char *uuid = NULL;
 | 
			
		||||
			scan(h, argv[i]);
 | 
			
		||||
		}
 | 
			
		||||
		destroy_toolcontext(cmd);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_pv_add(h, uuid1, NULL);
 | 
			
		||||
	_pv_add(h, uuid2, metadata2);
 | 
			
		||||
	_dump_vg(h, vgid);
 | 
			
		||||
	_pv_add(h, uuid3, NULL);
 | 
			
		||||
 | 
			
		||||
	daemon_close(h);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								doc/Makefile.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								doc/Makefile.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2004-2010 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@
 | 
			
		||||
top_builddir = @top_builddir@
 | 
			
		||||
 | 
			
		||||
CONFSRC=example.conf
 | 
			
		||||
CONFDEST=lvm.conf
 | 
			
		||||
 | 
			
		||||
include $(top_builddir)/make.tmpl
 | 
			
		||||
 | 
			
		||||
install_lvm2: $(CONFSRC)
 | 
			
		||||
	@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
 | 
			
		||||
		echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST)"; \
 | 
			
		||||
		$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST); \
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
install: install_lvm2
 | 
			
		||||
 | 
			
		||||
DISTCLEAN_TARGETS += $(CONFSRC)
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
Wow!  This is really incredible documentation!
 | 
			
		||||
							
								
								
									
										782
									
								
								doc/example.conf.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										782
									
								
								doc/example.conf.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,782 @@
 | 
			
		||||
# This is an example configuration file for the LVM2 system.
 | 
			
		||||
# It contains the default settings that would be used if there was no
 | 
			
		||||
# @DEFAULT_SYS_DIR@/lvm.conf file.
 | 
			
		||||
#
 | 
			
		||||
# Refer to 'man lvm.conf' for further information including the file layout.
 | 
			
		||||
#
 | 
			
		||||
# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set
 | 
			
		||||
# the environment variable LVM_SYSTEM_DIR before running the tools.
 | 
			
		||||
#
 | 
			
		||||
# N.B. Take care that each setting only appears once if uncommenting
 | 
			
		||||
# example settings in this file.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# This section allows you to configure which block devices should
 | 
			
		||||
# be used by the LVM system.
 | 
			
		||||
devices {
 | 
			
		||||
 | 
			
		||||
    # Where do you want your volume groups to appear ?
 | 
			
		||||
    dir = "/dev"
 | 
			
		||||
 | 
			
		||||
    # An array of directories that contain the device nodes you wish
 | 
			
		||||
    # to use with LVM2.
 | 
			
		||||
    scan = [ "/dev" ]
 | 
			
		||||
 | 
			
		||||
    # If set, the cache of block device nodes with all associated symlinks
 | 
			
		||||
    # will be constructed out of the existing udev database content.
 | 
			
		||||
    # This avoids using and opening any inapplicable non-block devices or
 | 
			
		||||
    # subdirectories found in the device directory. This setting is applied
 | 
			
		||||
    # to udev-managed device directory only, other directories will be scanned
 | 
			
		||||
    # fully. LVM2 needs to be compiled with udev support for this setting to
 | 
			
		||||
    # take effect. N.B. Any device node or symlink not managed by udev in
 | 
			
		||||
    # udev directory will be ignored with this setting on.
 | 
			
		||||
    obtain_device_list_from_udev = 1
 | 
			
		||||
 | 
			
		||||
    # 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 = [ ]
 | 
			
		||||
 | 
			
		||||
    # Try to avoid using undescriptive /dev/dm-N names, if present.
 | 
			
		||||
    # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/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
 | 
			
		||||
    # prefixed with either an 'a' (for accept) or 'r' (for reject).
 | 
			
		||||
    # The first expression found to match a device name determines if
 | 
			
		||||
    # the device will be accepted or rejected (ignored).  Devices that
 | 
			
		||||
    # don't match any patterns are accepted.
 | 
			
		||||
 | 
			
		||||
    # Be careful if there there are symbolic links or multiple filesystem 
 | 
			
		||||
    # entries for the same device as each name is checked separately against
 | 
			
		||||
    # the list of patterns.  The effect is that if the first pattern in the 
 | 
			
		||||
    # list to match a name is an 'a' pattern for any of the names, the device
 | 
			
		||||
    # is accepted; otherwise if the first pattern in the list to match a name
 | 
			
		||||
    # is an 'r' pattern for any of the names it is rejected; otherwise it is
 | 
			
		||||
    # accepted.
 | 
			
		||||
 | 
			
		||||
    # Don't have more than one filter line active at once: only one gets used.
 | 
			
		||||
 | 
			
		||||
    # Run vgscan after you change this parameter to ensure that
 | 
			
		||||
    # the cache file gets regenerated (see below).
 | 
			
		||||
    # If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # By default we accept every block device:
 | 
			
		||||
    filter = [ "a/.*/" ]
 | 
			
		||||
 | 
			
		||||
    # Exclude the cdrom drive
 | 
			
		||||
    # filter = [ "r|/dev/cdrom|" ]
 | 
			
		||||
 | 
			
		||||
    # When testing I like to work with just loopback devices:
 | 
			
		||||
    # filter = [ "a/loop/", "r/.*/" ]
 | 
			
		||||
 | 
			
		||||
    # Or maybe all loops and ide drives except hdc:
 | 
			
		||||
    # filter =[ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
 | 
			
		||||
 | 
			
		||||
    # Use anchors if you want to be really specific
 | 
			
		||||
    # 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 is stored in the @DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@ 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 = "@DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@"
 | 
			
		||||
    cache_file_prefix = ""
 | 
			
		||||
 | 
			
		||||
    # You can turn off writing this cache file by setting this to 0.
 | 
			
		||||
    write_cache_state = 1
 | 
			
		||||
 | 
			
		||||
    # Advanced settings.
 | 
			
		||||
 | 
			
		||||
    # List of pairs of additional acceptable block device types found 
 | 
			
		||||
    # in /proc/devices with maximum (non-zero) number of partitions.
 | 
			
		||||
    # types = [ "fd", 16 ]
 | 
			
		||||
 | 
			
		||||
    # If sysfs is mounted (2.6 kernels) restrict device scanning to 
 | 
			
		||||
    # the block devices it believes are valid.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    sysfs_scan = 1
 | 
			
		||||
 | 
			
		||||
    # By default, LVM2 will ignore devices used as component paths
 | 
			
		||||
    # of device-mapper multipath devices.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    multipath_component_detection = 1
 | 
			
		||||
 | 
			
		||||
    # By default, LVM2 will ignore devices used as components of
 | 
			
		||||
    # software RAID (md) devices by looking for md superblocks.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    md_component_detection = 1
 | 
			
		||||
 | 
			
		||||
    # By default, if a PV is placed directly upon an md device, LVM2
 | 
			
		||||
    # will align its data blocks with the md device's stripe-width.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    md_chunk_alignment = 1
 | 
			
		||||
 | 
			
		||||
    # Default alignment of the start of a data area in MB.  If set to 0,
 | 
			
		||||
    # a value of 64KB will be used.  Set to 1 for 1MiB, 2 for 2MiB, etc.
 | 
			
		||||
    # default_data_alignment = @DEFAULT_DATA_ALIGNMENT@
 | 
			
		||||
 | 
			
		||||
    # By default, the start of a PV's data area will be a multiple of
 | 
			
		||||
    # the 'minimum_io_size' or 'optimal_io_size' exposed in sysfs.
 | 
			
		||||
    # - minimum_io_size - the smallest request the device can perform
 | 
			
		||||
    #   w/o incurring a read-modify-write penalty (e.g. MD's chunk size)
 | 
			
		||||
    # - optimal_io_size - the device's preferred unit of receiving I/O
 | 
			
		||||
    #   (e.g. MD's stripe width)
 | 
			
		||||
    # minimum_io_size is used if optimal_io_size is undefined (0).
 | 
			
		||||
    # If md_chunk_alignment is enabled, that detects the optimal_io_size.
 | 
			
		||||
    # This setting takes precedence over md_chunk_alignment.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    data_alignment_detection = 1
 | 
			
		||||
 | 
			
		||||
    # Alignment (in KB) of start of data area when creating a new PV.
 | 
			
		||||
    # md_chunk_alignment and data_alignment_detection are disabled if set.
 | 
			
		||||
    # Set to 0 for the default alignment (see: data_alignment_default)
 | 
			
		||||
    # or page size, if larger.
 | 
			
		||||
    data_alignment = 0
 | 
			
		||||
 | 
			
		||||
    # By default, the start of the PV's aligned data area will be shifted by
 | 
			
		||||
    # the 'alignment_offset' exposed in sysfs.  This offset is often 0 but
 | 
			
		||||
    # may be non-zero; e.g.: certain 4KB sector drives that compensate for
 | 
			
		||||
    # windows partitioning will have an alignment_offset of 3584 bytes
 | 
			
		||||
    # (sector 7 is the lowest aligned logical block, the 4KB sectors start
 | 
			
		||||
    # at LBA -1, and consequently sector 63 is aligned on a 4KB boundary).
 | 
			
		||||
    # But note that pvcreate --dataalignmentoffset will skip this detection.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    data_alignment_offset_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
 | 
			
		||||
 | 
			
		||||
    # During each LVM operation errors received from each device are counted.
 | 
			
		||||
    # If the counter of a particular device exceeds the limit set here, no
 | 
			
		||||
    # further I/O is sent to that device for the remainder of the respective
 | 
			
		||||
    # operation. Setting the parameter to 0 disables the counters altogether.
 | 
			
		||||
    disable_after_error_count = 0
 | 
			
		||||
 | 
			
		||||
    # Allow use of pvcreate --uuid without requiring --restorefile.
 | 
			
		||||
    require_restorefile_with_uuid = 1
 | 
			
		||||
 | 
			
		||||
    # Minimum size (in KB) of block devices which can be used as PVs.
 | 
			
		||||
    # In a clustered environment all nodes must use the same value.
 | 
			
		||||
    # Any value smaller than 512KB is ignored.
 | 
			
		||||
 | 
			
		||||
    # Ignore devices smaller than 2MB such as floppy drives.
 | 
			
		||||
    pv_min_size = 2048
 | 
			
		||||
 | 
			
		||||
    # The original built-in setting was 512 up to and including version 2.02.84.
 | 
			
		||||
    # pv_min_size = 512
 | 
			
		||||
 | 
			
		||||
    # Issue discards to a logical volumes's underlying physical volume(s) when
 | 
			
		||||
    # the logical volume is no longer using the physical volumes' space (e.g.
 | 
			
		||||
    # lvremove, lvreduce, etc).  Discards inform the storage that a region is
 | 
			
		||||
    # no longer in use.  Storage that supports discards advertise the protocol
 | 
			
		||||
    # specific way discards should be issued by the kernel (TRIM, UNMAP, or
 | 
			
		||||
    # WRITE SAME with UNMAP bit set).  Not all storage will support or benefit
 | 
			
		||||
    # from discards but SSDs and thinly provisioned LUNs generally do.  If set
 | 
			
		||||
    # to 1, discards will only be issued if both the storage and kernel provide
 | 
			
		||||
    # support.
 | 
			
		||||
    # 1 enables; 0 disables.
 | 
			
		||||
    issue_discards = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This section allows you to configure the way in which LVM selects
 | 
			
		||||
# free space for its Logical Volumes.
 | 
			
		||||
allocation {
 | 
			
		||||
 | 
			
		||||
    # When searching for free space to extend an LV, the "cling"
 | 
			
		||||
    # allocation policy will choose space on the same PVs as the last
 | 
			
		||||
    # segment of the existing LV.  If there is insufficient space and a
 | 
			
		||||
    # list of tags is defined here, it will check whether any of them are
 | 
			
		||||
    # attached to the PVs concerned and then seek to match those PV tags
 | 
			
		||||
    # between existing extents and new extents.
 | 
			
		||||
    # Use the special tag "@*" as a wildcard to match any PV tag.
 | 
			
		||||
 
 | 
			
		||||
    # Example: LVs are mirrored between two sites within a single VG.
 | 
			
		||||
    # PVs are tagged with either @site1 or @site2 to indicate where
 | 
			
		||||
    # they are situated.
 | 
			
		||||
 | 
			
		||||
    # cling_tag_list = [ "@site1", "@site2" ]
 | 
			
		||||
    # cling_tag_list = [ "@*" ]
 | 
			
		||||
 | 
			
		||||
    # Changes made in version 2.02.85 extended the reach of the 'cling'
 | 
			
		||||
    # policies to detect more situations where data can be grouped
 | 
			
		||||
    # onto the same disks.  Set this to 0 to revert to the previous
 | 
			
		||||
    # algorithm.
 | 
			
		||||
    maximise_cling = 1
 | 
			
		||||
 | 
			
		||||
    # Set to 1 to guarantee that mirror logs will always be placed on 
 | 
			
		||||
    # different PVs from the mirror images.  This was the default
 | 
			
		||||
    # until version 2.02.85.
 | 
			
		||||
    mirror_logs_require_separate_pvs = 0
 | 
			
		||||
 | 
			
		||||
    # Set to 1 to guarantee that thin pool metadata will always
 | 
			
		||||
    # be placed on different PVs from the pool data.
 | 
			
		||||
    thin_pool_metadata_require_separate_pvs = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This section that allows you to configure the nature of the
 | 
			
		||||
# information that LVM2 reports.
 | 
			
		||||
log {
 | 
			
		||||
 | 
			
		||||
    # Controls the messages sent to stdout or stderr.
 | 
			
		||||
    # There are three levels of verbosity, 3 being the most verbose.
 | 
			
		||||
    verbose = 0
 | 
			
		||||
 | 
			
		||||
    # Should we send log messages through syslog?
 | 
			
		||||
    # 1 is yes; 0 is no.
 | 
			
		||||
    syslog = 1
 | 
			
		||||
 | 
			
		||||
    # Should we log error and debug messages to a file?
 | 
			
		||||
    # By default there is no log file.
 | 
			
		||||
    #file = "/var/log/lvm2.log"
 | 
			
		||||
 | 
			
		||||
    # Should we overwrite the log file each time the program is run?
 | 
			
		||||
    # By default we append.
 | 
			
		||||
    overwrite = 0
 | 
			
		||||
 | 
			
		||||
    # What level of log messages should we send to the log file and/or syslog?
 | 
			
		||||
    # There are 6 syslog-like log levels currently in use - 2 to 7 inclusive.
 | 
			
		||||
    # 7 is the most verbose (LOG_DEBUG).
 | 
			
		||||
    level = 0
 | 
			
		||||
 | 
			
		||||
    # Format of output messages
 | 
			
		||||
    # Whether or not (1 or 0) to indent messages according to their severity
 | 
			
		||||
    indent = 1
 | 
			
		||||
 | 
			
		||||
    # Whether or not (1 or 0) to display the command name on each line output
 | 
			
		||||
    command_names = 0
 | 
			
		||||
 | 
			
		||||
    # A prefix to use before the message text (but after the command name,
 | 
			
		||||
    # if selected).  Default is two spaces, so you can see/grep the severity
 | 
			
		||||
    # of each message.
 | 
			
		||||
    prefix = "  "
 | 
			
		||||
 | 
			
		||||
    # To make the messages look similar to the original LVM tools use:
 | 
			
		||||
    #   indent = 0
 | 
			
		||||
    #   command_names = 1
 | 
			
		||||
    #   prefix = " -- "
 | 
			
		||||
 | 
			
		||||
    # Set this if you want log messages during activation.
 | 
			
		||||
    # Don't use this in low memory situations (can deadlock).
 | 
			
		||||
    # activation = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Configuration of metadata backups and archiving.  In LVM2 when we
 | 
			
		||||
# talk about a 'backup' we mean making a copy of the metadata for the
 | 
			
		||||
# *current* system.  The 'archive' contains old metadata configurations.
 | 
			
		||||
# Backups are stored in a human readeable text format.
 | 
			
		||||
backup {
 | 
			
		||||
 | 
			
		||||
    # Should we maintain a backup of the current metadata configuration ?
 | 
			
		||||
    # Use 1 for Yes; 0 for No.
 | 
			
		||||
    # Think very hard before turning this off!
 | 
			
		||||
    backup = 1
 | 
			
		||||
 | 
			
		||||
    # Where shall we keep it ?
 | 
			
		||||
    # Remember to back up this directory regularly!
 | 
			
		||||
    backup_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_BACKUP_SUBDIR@"
 | 
			
		||||
 | 
			
		||||
    # Should we maintain an archive of old metadata configurations.
 | 
			
		||||
    # Use 1 for Yes; 0 for No.
 | 
			
		||||
    # On by default.  Think very hard before turning this off.
 | 
			
		||||
    archive = 1
 | 
			
		||||
 | 
			
		||||
    # Where should archived files go ?
 | 
			
		||||
    # Remember to back up this directory regularly!
 | 
			
		||||
    archive_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_ARCHIVE_SUBDIR@"
 | 
			
		||||
 | 
			
		||||
    # What is the minimum number of archive files you wish to keep ?
 | 
			
		||||
    retain_min = 10
 | 
			
		||||
 | 
			
		||||
    # What is the minimum time you wish to keep an archive file for ?
 | 
			
		||||
    retain_days = 30
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Settings for the running LVM2 in shell (readline) mode.
 | 
			
		||||
shell {
 | 
			
		||||
 | 
			
		||||
    # Number of lines of history to store in ~/.lvm_history
 | 
			
		||||
    history_size = 100
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Miscellaneous global LVM2 settings
 | 
			
		||||
global {
 | 
			
		||||
 | 
			
		||||
    # The file creation mask for any files and directories created.
 | 
			
		||||
    # Interpreted as octal if the first digit is zero.
 | 
			
		||||
    umask = 077
 | 
			
		||||
 | 
			
		||||
    # Allow other users to read the files
 | 
			
		||||
    #umask = 022
 | 
			
		||||
 | 
			
		||||
    # Enabling test mode means that no changes to the on disk metadata
 | 
			
		||||
    # will be made.  Equivalent to having the -t option on every
 | 
			
		||||
    # command.  Defaults to off.
 | 
			
		||||
    test = 0
 | 
			
		||||
 | 
			
		||||
    # Default value for --units argument
 | 
			
		||||
    units = "h"
 | 
			
		||||
 | 
			
		||||
    # Since version 2.02.54, the tools distinguish between powers of
 | 
			
		||||
    # 1024 bytes (e.g. KiB, MiB, GiB) and powers of 1000 bytes (e.g.
 | 
			
		||||
    # KB, MB, GB).
 | 
			
		||||
    # If you have scripts that depend on the old behaviour, set this to 0
 | 
			
		||||
    # temporarily until you update them.
 | 
			
		||||
    si_unit_consistency = 1
 | 
			
		||||
 | 
			
		||||
    # 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.
 | 
			
		||||
    # If the device-mapper kernel driver is not present in your kernel
 | 
			
		||||
    # setting this to 0 should suppress the error messages.
 | 
			
		||||
    activation = 1
 | 
			
		||||
 | 
			
		||||
    # If we can't communicate with device-mapper, should we try running 
 | 
			
		||||
    # the LVM1 tools?
 | 
			
		||||
    # This option only applies to 2.4 kernels and is provided to help you
 | 
			
		||||
    # switch between device-mapper kernels and LVM1 kernels.
 | 
			
		||||
    # The LVM1 tools need to be installed with .lvm1 suffices
 | 
			
		||||
    # e.g. vgscan.lvm1 and they will stop working after you start using
 | 
			
		||||
    # the new lvm2 on-disk metadata format.
 | 
			
		||||
    # The default value is set when the tools are built.
 | 
			
		||||
    # fallback_to_lvm1 = 0
 | 
			
		||||
 | 
			
		||||
    # The default metadata format that commands should use - "lvm1" or "lvm2".
 | 
			
		||||
    # The command line override is -M1 or -M2.
 | 
			
		||||
    # Defaults to "lvm2".
 | 
			
		||||
    # format = "lvm2"
 | 
			
		||||
 | 
			
		||||
    # Location of proc filesystem
 | 
			
		||||
    proc = "/proc"
 | 
			
		||||
 | 
			
		||||
    # 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.
 | 
			
		||||
    # Type 4 uses read-only locking which forbids any operations that might 
 | 
			
		||||
    # change metadata.
 | 
			
		||||
    locking_type = 1
 | 
			
		||||
 | 
			
		||||
    # Set to 0 to fail when a lock request cannot be satisfied immediately.
 | 
			
		||||
    wait_for_locks = 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 = "@DEFAULT_LOCK_DIR@"
 | 
			
		||||
 | 
			
		||||
    # Whenever there are competing read-only and read-write access requests for
 | 
			
		||||
    # a volume group's metadata, instead of always granting the read-only
 | 
			
		||||
    # requests immediately, delay them to allow the read-write requests to be
 | 
			
		||||
    # serviced.  Without this setting, write access may be stalled by a high
 | 
			
		||||
    # volume of read-only requests.
 | 
			
		||||
    # NB. This option only affects locking_type = 1 viz. local file-based
 | 
			
		||||
    # locking.
 | 
			
		||||
    prioritise_write_locks = 1
 | 
			
		||||
 | 
			
		||||
    # Other entries can go here to allow you to load shared libraries
 | 
			
		||||
    # e.g. if support for LVM1 metadata was compiled as a shared library use
 | 
			
		||||
    #   format_libraries = "liblvm2format1.so" 
 | 
			
		||||
    # Full pathnames can be given.
 | 
			
		||||
 | 
			
		||||
    # 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"
 | 
			
		||||
 | 
			
		||||
    # Treat any internal errors as fatal errors, aborting the process that
 | 
			
		||||
    # encountered the internal error. Please only enable for debugging.
 | 
			
		||||
    abort_on_internal_errors = 0
 | 
			
		||||
 | 
			
		||||
    # Check whether CRC is matching when parsed VG is used multiple times.
 | 
			
		||||
    # This is useful to catch unexpected internal cached volume group
 | 
			
		||||
    # structure modification. Please only enable for debugging.
 | 
			
		||||
    detect_internal_vg_cache_corruption = 0
 | 
			
		||||
 | 
			
		||||
    # If set to 1, no operations that change on-disk metadata will be permitted.
 | 
			
		||||
    # Additionally, read-only commands that encounter metadata in need of repair
 | 
			
		||||
    # will still be allowed to proceed exactly as if the repair had been 
 | 
			
		||||
    # performed (except for the unchanged vg_seqno).
 | 
			
		||||
    # Inappropriate use could mess up your system, so seek advice first!
 | 
			
		||||
    metadata_read_only = 0
 | 
			
		||||
 | 
			
		||||
    # 'mirror_segtype_default' defines which segtype will be used when the
 | 
			
		||||
    # shorthand '-m' option is used for mirroring.  The possible options are:
 | 
			
		||||
    #
 | 
			
		||||
    # "mirror" - The original RAID1 implementation provided by LVM2/DM.  It is
 | 
			
		||||
    # 	         characterized by a flexible log solution (core, disk, mirrored)
 | 
			
		||||
    #		 and by the necessity to block I/O while reconfiguring in the
 | 
			
		||||
    #		 event of a failure.
 | 
			
		||||
    #
 | 
			
		||||
    #		 There is an inherent race in the dmeventd failure handling
 | 
			
		||||
    #		 logic with snapshots of devices using this type of RAID1 that
 | 
			
		||||
    #		 in the worst case could cause a deadlock.
 | 
			
		||||
    #		   Ref: https://bugzilla.redhat.com/show_bug.cgi?id=817130#c10
 | 
			
		||||
    #
 | 
			
		||||
    # "raid1"  - This implementation leverages MD's RAID1 personality through
 | 
			
		||||
    # 	       	 device-mapper.  It is characterized by a lack of log options.
 | 
			
		||||
    #		 (A log is always allocated for every device and they are placed
 | 
			
		||||
    #		 on the same device as the image - no separate devices are
 | 
			
		||||
    #		 required.)  This mirror implementation does not require I/O
 | 
			
		||||
    #		 to be blocked in the kernel in the event of a failure.
 | 
			
		||||
    #		 This mirror implementation is not cluster-aware and cannot be
 | 
			
		||||
    #		 used in a shared (active/active) fashion in a cluster.
 | 
			
		||||
    #
 | 
			
		||||
    # Specify the '--type <mirror|raid1>' option to override this default
 | 
			
		||||
    # setting.
 | 
			
		||||
    mirror_segtype_default = "mirror"
 | 
			
		||||
 | 
			
		||||
    # The default format for displaying LV names in lvdisplay was changed 
 | 
			
		||||
    # in version 2.02.89 to show the LV name and path separately.
 | 
			
		||||
    # Previously this was always shown as /dev/vgname/lvname even when that
 | 
			
		||||
    # was never a valid path in the /dev filesystem.
 | 
			
		||||
    # Set to 1 to reinstate the previous format.
 | 
			
		||||
    #
 | 
			
		||||
    # lvdisplay_shows_full_device_path = 0
 | 
			
		||||
 | 
			
		||||
    # Whether to use (trust) a running instance of lvmetad. If this is set to
 | 
			
		||||
    # 0, all commands fall back to the usual scanning mechanisms. When set to 1
 | 
			
		||||
    # *and* when lvmetad is running (it is not auto-started), the volume group
 | 
			
		||||
    # metadata and PV state flags are obtained from the lvmetad instance and no
 | 
			
		||||
    # scanning is done by the individual commands. In a setup with lvmetad,
 | 
			
		||||
    # lvmetad udev rules *must* be set up for LVM to work correctly. Without
 | 
			
		||||
    # proper udev rules, all changes in block device configuration will be
 | 
			
		||||
    # *ignored* until a manual 'vgscan' is performed.
 | 
			
		||||
    use_lvmetad = 0
 | 
			
		||||
 | 
			
		||||
    # Full path of the utility called to check that a thin metadata device
 | 
			
		||||
    # is in a state that allows it to be used.
 | 
			
		||||
    # Each time a thin pool needs to be activated or after it is deactivated
 | 
			
		||||
    # this utility is executed. The activation will only proceed if the utility
 | 
			
		||||
    # has an exit status of 0.
 | 
			
		||||
    # Set to "" to skip this check.  (Not recommended.)
 | 
			
		||||
    # The thin tools are available as part of the device-mapper-persistent-data
 | 
			
		||||
    # package from https://github.com/jthornber/thin-provisioning-tools.
 | 
			
		||||
    #
 | 
			
		||||
    thin_check_executable = "@THIN_CHECK_CMD@"
 | 
			
		||||
 | 
			
		||||
    # String with options passed with thin_check command. By default,
 | 
			
		||||
    # option '-q' is for quiet output.
 | 
			
		||||
    thin_check_options = [ "-q" ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
activation {
 | 
			
		||||
    # Set to 1 to perform internal checks on the operations issued to
 | 
			
		||||
    # libdevmapper.  Useful for debugging problems with activation.
 | 
			
		||||
    # Some of the checks may be expensive, so it's best to use this
 | 
			
		||||
    # only when there seems to be a problem.
 | 
			
		||||
    checks = 0
 | 
			
		||||
 | 
			
		||||
    # Set to 0 to disable udev synchronisation (if compiled into the binaries).
 | 
			
		||||
    # Processes will not wait for notification from udev.
 | 
			
		||||
    # They will continue irrespective of any possible udev processing
 | 
			
		||||
    # in the background.  You should only use this if udev is not running
 | 
			
		||||
    # or has rules that ignore the devices LVM2 creates.
 | 
			
		||||
    # The command line argument --nodevsync takes precedence over this setting.
 | 
			
		||||
    # If set to 1 when udev is not running, and there are LVM2 processes
 | 
			
		||||
    # waiting for udev, run 'dmsetup udevcomplete_all' manually to wake them up.
 | 
			
		||||
    udev_sync = 1
 | 
			
		||||
 | 
			
		||||
    # Set to 0 to disable the udev rules installed by LVM2 (if built with
 | 
			
		||||
    # --enable-udev_rules). LVM2 will then manage the /dev nodes and symlinks
 | 
			
		||||
    # for active logical volumes directly itself.
 | 
			
		||||
    # N.B. Manual intervention may be required if this setting is changed
 | 
			
		||||
    # while any logical volumes are active.
 | 
			
		||||
    udev_rules = 1
 | 
			
		||||
 | 
			
		||||
    # Set to 1 for LVM2 to verify operations performed by udev. This turns on
 | 
			
		||||
    # additional checks (and if necessary, repairs) on entries in the device
 | 
			
		||||
    # directory after udev has completed processing its events. 
 | 
			
		||||
    # Useful for diagnosing problems with LVM2/udev interactions.
 | 
			
		||||
    verify_udev_operations = 0
 | 
			
		||||
 | 
			
		||||
    # If set to 1 and if deactivation of an LV fails, perhaps because
 | 
			
		||||
    # a process run from a quick udev rule temporarily opened the device,
 | 
			
		||||
    # retry the operation for a few seconds before failing.
 | 
			
		||||
    retry_deactivation = 1
 | 
			
		||||
 | 
			
		||||
    # How to fill in missing stripes if activating an incomplete volume.
 | 
			
		||||
    # Using "error" will make inaccessible parts of the device return
 | 
			
		||||
    # I/O errors on access.  You can instead use a device path, in which 
 | 
			
		||||
    # case, that device will be used to in place of missing stripes.
 | 
			
		||||
    # But note that using anything other than "error" with mirrored 
 | 
			
		||||
    # or snapshotted volumes is likely to result in data corruption.
 | 
			
		||||
    missing_stripe_filler = "error"
 | 
			
		||||
 | 
			
		||||
    # The linear target is an optimised version of the striped target
 | 
			
		||||
    # that only handles a single stripe.  Set this to 0 to disable this
 | 
			
		||||
    # optimisation and always use the striped target.
 | 
			
		||||
    use_linear_target = 1
 | 
			
		||||
 | 
			
		||||
    # How much stack (in KB) to reserve for use while devices suspended
 | 
			
		||||
    # Prior to version 2.02.89 this used to be set to 256KB
 | 
			
		||||
    reserved_stack = 64
 | 
			
		||||
 | 
			
		||||
    # How much memory (in KB) to reserve for use while devices suspended
 | 
			
		||||
    reserved_memory = 8192
 | 
			
		||||
 | 
			
		||||
    # Nice value used while devices suspended
 | 
			
		||||
    process_priority = -18
 | 
			
		||||
 | 
			
		||||
    # If volume_list is defined, each LV is only activated if there is a
 | 
			
		||||
    # match against the list.
 | 
			
		||||
    #   "vgname" and "vgname/lvname" are matched exactly.
 | 
			
		||||
    #   "@tag" matches any tag set in the LV or VG.
 | 
			
		||||
    #   "@*" matches if any tag defined on the host is also set in the LV or VG
 | 
			
		||||
    #
 | 
			
		||||
    # volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
 | 
			
		||||
 | 
			
		||||
    # If read_only_volume_list is defined, each LV that is to be activated 
 | 
			
		||||
    # is checked against the list, and if it matches, it as activated
 | 
			
		||||
    # in read-only mode.  (This overrides '--permission rw' stored in the
 | 
			
		||||
    # metadata.)
 | 
			
		||||
    #   "vgname" and "vgname/lvname" are matched exactly.
 | 
			
		||||
    #   "@tag" matches any tag set in the LV or VG.
 | 
			
		||||
    #   "@*" matches if any tag defined on the host is also set in the LV or VG
 | 
			
		||||
    #
 | 
			
		||||
    # read_only_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"
 | 
			
		||||
 | 
			
		||||
    # 'raid_fault_policy' defines how a device failure in a RAID logical
 | 
			
		||||
    # volume is handled.  This includes logical volumes that have the following
 | 
			
		||||
    # segment types: raid1, raid4, raid5*, and raid6*.
 | 
			
		||||
    #
 | 
			
		||||
    # In the event of a failure, the following policies will determine what
 | 
			
		||||
    # actions are performed during the automated response to failures (when
 | 
			
		||||
    # dmeventd is monitoring the RAID logical volume) and when 'lvconvert' is
 | 
			
		||||
    # called manually with the options '--repair' and '--use-policies'.
 | 
			
		||||
    #
 | 
			
		||||
    # "warn"	- Use the system log to warn the user that a device in the RAID
 | 
			
		||||
    # 		  logical volume has failed.  It is left to the user to run
 | 
			
		||||
    #		  'lvconvert --repair' manually to remove or replace the failed
 | 
			
		||||
    #		  device.  As long as the number of failed devices does not
 | 
			
		||||
    #		  exceed the redundancy of the logical volume (1 device for
 | 
			
		||||
    #		  raid4/5, 2 for raid6, etc) the logical volume will remain
 | 
			
		||||
    #		  usable.
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate" - Attempt to use any extra physical volumes in the volume
 | 
			
		||||
    # 		  group as spares and replace faulty devices.
 | 
			
		||||
    #
 | 
			
		||||
    raid_fault_policy = "warn"
 | 
			
		||||
 | 
			
		||||
    # 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
 | 
			
		||||
    # how a device failure affecting a mirror (of "mirror" segment type) 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. This applies to automatic repairs (when the mirror is being
 | 
			
		||||
    # monitored by dmeventd) and to manual lvconvert --repair when
 | 
			
		||||
    # --use-policies is given.
 | 
			
		||||
    #
 | 
			
		||||
    # "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.
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate_anywhere" - Not yet implemented. Useful to place the log device
 | 
			
		||||
    #            temporarily on same physical volume as one of the mirror
 | 
			
		||||
    #            images. This policy is not recommended for mirror devices
 | 
			
		||||
    #            since 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_image_fault_policy = "remove"
 | 
			
		||||
 | 
			
		||||
    # 'snapshot_autoextend_threshold' and 'snapshot_autoextend_percent' define
 | 
			
		||||
    # how to handle automatic snapshot extension. The former defines when the
 | 
			
		||||
    # snapshot should be extended: when its space usage exceeds this many
 | 
			
		||||
    # percent. The latter defines how much extra space should be allocated for
 | 
			
		||||
    # the snapshot, in percent of its current size.
 | 
			
		||||
    #
 | 
			
		||||
    # For example, if you set snapshot_autoextend_threshold to 70 and
 | 
			
		||||
    # snapshot_autoextend_percent to 20, whenever a snapshot exceeds 70% usage,
 | 
			
		||||
    # it will be extended by another 20%. For a 1G snapshot, using up 700M will
 | 
			
		||||
    # trigger a resize to 1.2G. When the usage exceeds 840M, the snapshot will
 | 
			
		||||
    # be extended to 1.44G, and so on.
 | 
			
		||||
    #
 | 
			
		||||
    # Setting snapshot_autoextend_threshold to 100 disables automatic
 | 
			
		||||
    # extensions. The minimum value is 50 (A setting below 50 will be treated
 | 
			
		||||
    # as 50).
 | 
			
		||||
 | 
			
		||||
    snapshot_autoextend_threshold = 100
 | 
			
		||||
    snapshot_autoextend_percent = 20
 | 
			
		||||
 | 
			
		||||
    # 'thin_pool_autoextend_threshold' and 'thin_pool_autoextend_percent' define
 | 
			
		||||
    # how to handle automatic pool extension. The former defines when the
 | 
			
		||||
    # pool should be extended: when its space usage exceeds this many
 | 
			
		||||
    # percent. The latter defines how much extra space should be allocated for
 | 
			
		||||
    # the pool, in percent of its current size.
 | 
			
		||||
    #
 | 
			
		||||
    # For example, if you set thin_pool_autoextend_threshold to 70 and
 | 
			
		||||
    # thin_pool_autoextend_percent to 20, whenever a pool exceeds 70% usage,
 | 
			
		||||
    # it will be extended by another 20%. For a 1G pool, using up 700M will
 | 
			
		||||
    # trigger a resize to 1.2G. When the usage exceeds 840M, the pool will
 | 
			
		||||
    # be extended to 1.44G, and so on.
 | 
			
		||||
    #
 | 
			
		||||
    # Setting thin_pool_autoextend_threshold to 100 disables automatic
 | 
			
		||||
    # extensions. The minimum value is 50 (A setting below 50 will be treated
 | 
			
		||||
    # as 50).
 | 
			
		||||
 | 
			
		||||
    thin_pool_autoextend_threshold = 100
 | 
			
		||||
    thin_pool_autoextend_percent = 20
 | 
			
		||||
 | 
			
		||||
    # While activating devices, I/O to devices being (re)configured is
 | 
			
		||||
    # suspended, and as a precaution against deadlocks, LVM2 needs to pin
 | 
			
		||||
    # any memory it is using so it is not paged out.  Groups of pages that
 | 
			
		||||
    # are known not to be accessed during activation need not be pinned
 | 
			
		||||
    # into memory.  Each string listed in this setting is compared against
 | 
			
		||||
    # each line in /proc/self/maps, and the pages corresponding to any
 | 
			
		||||
    # lines that match are not pinned.  On some systems locale-archive was
 | 
			
		||||
    # found to make up over 80% of the memory used by the process.
 | 
			
		||||
    # mlock_filter = [ "locale/locale-archive", "gconv/gconv-modules.cache" ]
 | 
			
		||||
 | 
			
		||||
    # Set to 1 to revert to the default behaviour prior to version 2.02.62
 | 
			
		||||
    # which used mlockall() to pin the whole process's memory while activating
 | 
			
		||||
    # devices.
 | 
			
		||||
    use_mlockall = 0
 | 
			
		||||
 | 
			
		||||
    # Monitoring is enabled by default when activating logical volumes.
 | 
			
		||||
    # Set to 0 to disable monitoring or use the --ignoremonitoring option.
 | 
			
		||||
    monitoring = 1
 | 
			
		||||
 | 
			
		||||
    # When pvmove or lvconvert must wait for the kernel to finish
 | 
			
		||||
    # synchronising or merging data, they check and report progress
 | 
			
		||||
    # at intervals of this number of seconds.  The default is 15 seconds.
 | 
			
		||||
    # If this is set to 0 and there is only one thing to wait for, there
 | 
			
		||||
    # are no progress reports, but the process is awoken immediately the
 | 
			
		||||
    # operation is complete.
 | 
			
		||||
    polling_interval = 15
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
####################
 | 
			
		||||
# Advanced section #
 | 
			
		||||
####################
 | 
			
		||||
 | 
			
		||||
# Metadata settings
 | 
			
		||||
#
 | 
			
		||||
# metadata {
 | 
			
		||||
    # Default number of copies of metadata to hold on each PV.  0, 1 or 2.
 | 
			
		||||
    # You might want to override it from the command line with 0 
 | 
			
		||||
    # when running pvcreate on new PVs which are to be added to large VGs.
 | 
			
		||||
 | 
			
		||||
    # pvmetadatacopies = 1
 | 
			
		||||
 | 
			
		||||
    # Default number of copies of metadata to maintain for each VG.
 | 
			
		||||
    # If set to a non-zero value, LVM automatically chooses which of
 | 
			
		||||
    # the available metadata areas to use to achieve the requested
 | 
			
		||||
    # number of copies of the VG metadata.  If you set a value larger
 | 
			
		||||
    # than the the total number of metadata areas available then
 | 
			
		||||
    # metadata is stored in them all.
 | 
			
		||||
    # The default value of 0 ("unmanaged") disables this automatic
 | 
			
		||||
    # management and allows you to control which metadata areas
 | 
			
		||||
    # are used at the individual PV level using 'pvchange
 | 
			
		||||
    # --metadataignore y/n'.
 | 
			
		||||
 | 
			
		||||
    # vgmetadatacopies = 0
 | 
			
		||||
 | 
			
		||||
    # Approximate default size of on-disk metadata areas in sectors.
 | 
			
		||||
    # You should increase this if you have large volume groups or
 | 
			
		||||
    # you want to retain a large on-disk history of your metadata changes.
 | 
			
		||||
 | 
			
		||||
    # pvmetadatasize = 255
 | 
			
		||||
 | 
			
		||||
    # List of directories holding live copies of text format metadata.
 | 
			
		||||
    # These directories must not be on logical volumes!
 | 
			
		||||
    # It's possible to use LVM2 with a couple of directories here,
 | 
			
		||||
    # preferably on different (non-LV) filesystems, and with no other 
 | 
			
		||||
    # on-disk metadata (pvmetadatacopies = 0). Or this can be in
 | 
			
		||||
    # addition to on-disk metadata areas.
 | 
			
		||||
    # The feature was originally added to simplify testing and is not
 | 
			
		||||
    # supported under low memory situations - the machine could lock up.
 | 
			
		||||
    #
 | 
			
		||||
    # Never edit any files in these directories by hand unless you
 | 
			
		||||
    # you are absolutely sure you know what you are doing! Use
 | 
			
		||||
    # the supplied toolset to make changes (e.g. vgcfgrestore).
 | 
			
		||||
 | 
			
		||||
    # 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. If no mirror library is
 | 
			
		||||
    # provided, mirrors are not monitored through dmeventd.
 | 
			
		||||
 | 
			
		||||
    mirror_library = "libdevmapper-event-lvm2mirror.so"
 | 
			
		||||
 | 
			
		||||
    # snapshot_library is the library used when monitoring a snapshot device.
 | 
			
		||||
    #
 | 
			
		||||
    # "libdevmapper-event-lvm2snapshot.so" monitors the filling of
 | 
			
		||||
    # snapshots and emits a warning through syslog when the use of
 | 
			
		||||
    # the snapshot exceeds 80%. The warning is repeated when 85%, 90% and
 | 
			
		||||
    # 95% of the snapshot is filled.
 | 
			
		||||
 | 
			
		||||
    snapshot_library = "libdevmapper-event-lvm2snapshot.so"
 | 
			
		||||
 | 
			
		||||
    # thin_library is the library used when monitoring a thin device.
 | 
			
		||||
    #
 | 
			
		||||
    # "libdevmapper-event-lvm2thin.so" monitors the filling of
 | 
			
		||||
    # pool and emits a warning through syslog when the use of
 | 
			
		||||
    # the pool exceeds 80%. The warning is repeated when 85%, 90% and
 | 
			
		||||
    # 95% of the pool is filled.
 | 
			
		||||
 | 
			
		||||
    thin_library = "libdevmapper-event-lvm2thin.so"
 | 
			
		||||
 | 
			
		||||
    # Full path of the dmeventd binary.
 | 
			
		||||
    #
 | 
			
		||||
    # executable = "@DMEVENTD_PATH@"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								doc/example_cmdlib.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								doc/example_cmdlib.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of LVM2.
 | 
			
		||||
 *
 | 
			
		||||
 * This copyrighted material is made available to anyone wishing to use,
 | 
			
		||||
 * modify, copy, or redistribute it subject to the terms and conditions
 | 
			
		||||
 * of the GNU General Public License v.2.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "lvm2cmd.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
/* All output gets passed to this function line-by-line */
 | 
			
		||||
void test_log_fn(int level, const char *file, int line,
 | 
			
		||||
		 int dm_errno, const char *format)
 | 
			
		||||
{
 | 
			
		||||
	/* Extract and process output here rather than printing it */
 | 
			
		||||
 | 
			
		||||
	if (level != 4)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	printf("%s\n", format);
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	void *handle;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	lvm2_log_fn(test_log_fn);
 | 
			
		||||
 | 
			
		||||
	handle = lvm2_init();
 | 
			
		||||
 | 
			
		||||
	lvm2_log_level(handle, 1);
 | 
			
		||||
	r = lvm2_run(handle, "vgs --noheadings vg1");
 | 
			
		||||
 | 
			
		||||
	/* More commands here */
 | 
			
		||||
 | 
			
		||||
	lvm2_exit(handle);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										76
									
								
								doc/kernel/crypt.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								doc/kernel/crypt.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
dm-crypt
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
Device-Mapper's "crypt" target provides transparent encryption of block devices
 | 
			
		||||
using the kernel crypto API.
 | 
			
		||||
 | 
			
		||||
Parameters: <cipher> <key> <iv_offset> <device path> \
 | 
			
		||||
	      <offset> [<#opt_params> <opt_params>]
 | 
			
		||||
 | 
			
		||||
<cipher>
 | 
			
		||||
    Encryption cipher and an optional IV generation mode.
 | 
			
		||||
    (In format cipher[:keycount]-chainmode-ivopts:ivmode).
 | 
			
		||||
    Examples:
 | 
			
		||||
       des
 | 
			
		||||
       aes-cbc-essiv:sha256
 | 
			
		||||
       twofish-ecb
 | 
			
		||||
 | 
			
		||||
    /proc/crypto contains supported crypto modes
 | 
			
		||||
 | 
			
		||||
<key>
 | 
			
		||||
    Key used for encryption. It is encoded as a hexadecimal number.
 | 
			
		||||
    You can only use key sizes that are valid for the selected cipher.
 | 
			
		||||
 | 
			
		||||
<keycount>
 | 
			
		||||
    Multi-key compatibility mode. You can define <keycount> keys and
 | 
			
		||||
    then sectors are encrypted according to their offsets (sector 0 uses key0;
 | 
			
		||||
    sector 1 uses key1 etc.).  <keycount> must be a power of two.
 | 
			
		||||
 | 
			
		||||
<iv_offset>
 | 
			
		||||
    The IV offset is a sector count that is added to the sector number
 | 
			
		||||
    before creating the IV.
 | 
			
		||||
 | 
			
		||||
<device path>
 | 
			
		||||
    This is the device that is going to be used as backend and contains the
 | 
			
		||||
    encrypted data.  You can specify it as a path like /dev/xxx or a device
 | 
			
		||||
    number <major>:<minor>.
 | 
			
		||||
 | 
			
		||||
<offset>
 | 
			
		||||
    Starting sector within the device where the encrypted data begins.
 | 
			
		||||
 | 
			
		||||
<#opt_params>
 | 
			
		||||
    Number of optional parameters. If there are no optional parameters,
 | 
			
		||||
    the optional paramaters section can be skipped or #opt_params can be zero.
 | 
			
		||||
    Otherwise #opt_params is the number of following arguments.
 | 
			
		||||
 | 
			
		||||
    Example of optional parameters section:
 | 
			
		||||
        1 allow_discards
 | 
			
		||||
 | 
			
		||||
allow_discards
 | 
			
		||||
    Block discard requests (a.k.a. TRIM) are passed through the crypt device.
 | 
			
		||||
    The default is to ignore discard requests.
 | 
			
		||||
 | 
			
		||||
    WARNING: Assess the specific security risks carefully before enabling this
 | 
			
		||||
    option.  For example, allowing discards on encrypted devices may lead to
 | 
			
		||||
    the leak of information about the ciphertext device (filesystem type,
 | 
			
		||||
    used space etc.) if the discarded blocks can be located easily on the
 | 
			
		||||
    device later.
 | 
			
		||||
 | 
			
		||||
Example scripts
 | 
			
		||||
===============
 | 
			
		||||
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
 | 
			
		||||
encryption with dm-crypt using the 'cryptsetup' utility, see
 | 
			
		||||
http://code.google.com/p/cryptsetup/
 | 
			
		||||
 | 
			
		||||
[[
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# Create a crypt device using dmsetup
 | 
			
		||||
dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
[[
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# Create a crypt device using cryptsetup and LUKS header with default cipher
 | 
			
		||||
cryptsetup luksFormat $1
 | 
			
		||||
cryptsetup luksOpen $1 crypt1
 | 
			
		||||
]]
 | 
			
		||||
							
								
								
									
										26
									
								
								doc/kernel/delay.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								doc/kernel/delay.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
dm-delay
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
Device-Mapper's "delay" target delays reads and/or writes
 | 
			
		||||
and maps them to different devices.
 | 
			
		||||
 | 
			
		||||
Parameters:
 | 
			
		||||
    <device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
 | 
			
		||||
 | 
			
		||||
With separate write parameters, the first set is only used for reads.
 | 
			
		||||
Delays are specified in milliseconds.
 | 
			
		||||
 | 
			
		||||
Example scripts
 | 
			
		||||
===============
 | 
			
		||||
[[
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# Create device delaying rw operation for 500ms
 | 
			
		||||
echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
[[
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# Create device delaying only write operation for 500ms and
 | 
			
		||||
# splitting reads and writes to different devices $1 $2
 | 
			
		||||
echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
 | 
			
		||||
]]
 | 
			
		||||
							
								
								
									
										53
									
								
								doc/kernel/flakey.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								doc/kernel/flakey.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
dm-flakey
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
This target is the same as the linear target except that it exhibits
 | 
			
		||||
unreliable behaviour periodically.  It's been found useful in simulating
 | 
			
		||||
failing devices for testing purposes.
 | 
			
		||||
 | 
			
		||||
Starting from the time the table is loaded, the device is available for
 | 
			
		||||
<up interval> seconds, then exhibits unreliable behaviour for <down
 | 
			
		||||
interval> seconds, and then this cycle repeats.
 | 
			
		||||
 | 
			
		||||
Also, consider using this in combination with the dm-delay target too,
 | 
			
		||||
which can delay reads and writes and/or send them to different
 | 
			
		||||
underlying devices.
 | 
			
		||||
 | 
			
		||||
Table parameters
 | 
			
		||||
----------------
 | 
			
		||||
  <dev path> <offset> <up interval> <down interval> \
 | 
			
		||||
    [<num_features> [<feature arguments>]]
 | 
			
		||||
 | 
			
		||||
Mandatory parameters:
 | 
			
		||||
    <dev path>: Full pathname to the underlying block-device, or a
 | 
			
		||||
                "major:minor" device-number.
 | 
			
		||||
    <offset>: Starting sector within the device.
 | 
			
		||||
    <up interval>: Number of seconds device is available.
 | 
			
		||||
    <down interval>: Number of seconds device returns errors.
 | 
			
		||||
 | 
			
		||||
Optional feature parameters:
 | 
			
		||||
  If no feature parameters are present, during the periods of
 | 
			
		||||
  unreliability, all I/O returns errors.
 | 
			
		||||
 | 
			
		||||
  drop_writes:
 | 
			
		||||
	All write I/O is silently ignored.
 | 
			
		||||
	Read I/O is handled correctly.
 | 
			
		||||
 | 
			
		||||
  corrupt_bio_byte <Nth_byte> <direction> <value> <flags>:
 | 
			
		||||
	During <down interval>, replace <Nth_byte> of the data of
 | 
			
		||||
	each matching bio with <value>.
 | 
			
		||||
 | 
			
		||||
    <Nth_byte>: The offset of the byte to replace.
 | 
			
		||||
		Counting starts at 1, to replace the first byte.
 | 
			
		||||
    <direction>: Either 'r' to corrupt reads or 'w' to corrupt writes.
 | 
			
		||||
		 'w' is incompatible with drop_writes.
 | 
			
		||||
    <value>: The value (from 0-255) to write.
 | 
			
		||||
    <flags>: Perform the replacement only if bio->bi_rw has all the
 | 
			
		||||
	     selected flags set.
 | 
			
		||||
 | 
			
		||||
Examples:
 | 
			
		||||
  corrupt_bio_byte 32 r 1 0
 | 
			
		||||
	- replaces the 32nd byte of READ bios with the value 1
 | 
			
		||||
 | 
			
		||||
  corrupt_bio_byte 224 w 0 32
 | 
			
		||||
	- replaces the 224th byte of REQ_META (=32) bios with the value 0
 | 
			
		||||
							
								
								
									
										75
									
								
								doc/kernel/io.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								doc/kernel/io.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
dm-io
 | 
			
		||||
=====
 | 
			
		||||
 | 
			
		||||
Dm-io provides synchronous and asynchronous I/O services. There are three
 | 
			
		||||
types of I/O services available, and each type has a sync and an async
 | 
			
		||||
version.
 | 
			
		||||
 | 
			
		||||
The user must set up an io_region structure to describe the desired location
 | 
			
		||||
of the I/O. Each io_region indicates a block-device along with the starting
 | 
			
		||||
sector and size of the region.
 | 
			
		||||
 | 
			
		||||
   struct io_region {
 | 
			
		||||
      struct block_device *bdev;
 | 
			
		||||
      sector_t sector;
 | 
			
		||||
      sector_t count;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
Dm-io can read from one io_region or write to one or more io_regions. Writes
 | 
			
		||||
to multiple regions are specified by an array of io_region structures.
 | 
			
		||||
 | 
			
		||||
The first I/O service type takes a list of memory pages as the data buffer for
 | 
			
		||||
the I/O, along with an offset into the first page.
 | 
			
		||||
 | 
			
		||||
   struct page_list {
 | 
			
		||||
      struct page_list *next;
 | 
			
		||||
      struct page *page;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
 | 
			
		||||
                  struct page_list *pl, unsigned int offset,
 | 
			
		||||
                  unsigned long *error_bits);
 | 
			
		||||
   int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
 | 
			
		||||
                   struct page_list *pl, unsigned int offset,
 | 
			
		||||
                   io_notify_fn fn, void *context);
 | 
			
		||||
 | 
			
		||||
The second I/O service type takes an array of bio vectors as the data buffer
 | 
			
		||||
for the I/O. This service can be handy if the caller has a pre-assembled bio,
 | 
			
		||||
but wants to direct different portions of the bio to different devices.
 | 
			
		||||
 | 
			
		||||
   int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where,
 | 
			
		||||
                       int rw, struct bio_vec *bvec,
 | 
			
		||||
                       unsigned long *error_bits);
 | 
			
		||||
   int dm_io_async_bvec(unsigned int num_regions, struct io_region *where,
 | 
			
		||||
                        int rw, struct bio_vec *bvec,
 | 
			
		||||
                        io_notify_fn fn, void *context);
 | 
			
		||||
 | 
			
		||||
The third I/O service type takes a pointer to a vmalloc'd memory buffer as the
 | 
			
		||||
data buffer for the I/O. This service can be handy if the caller needs to do
 | 
			
		||||
I/O to a large region but doesn't want to allocate a large number of individual
 | 
			
		||||
memory pages.
 | 
			
		||||
 | 
			
		||||
   int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
 | 
			
		||||
                     void *data, unsigned long *error_bits);
 | 
			
		||||
   int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
 | 
			
		||||
                      void *data, io_notify_fn fn, void *context);
 | 
			
		||||
 | 
			
		||||
Callers of the asynchronous I/O services must include the name of a completion
 | 
			
		||||
callback routine and a pointer to some context data for the I/O.
 | 
			
		||||
 | 
			
		||||
   typedef void (*io_notify_fn)(unsigned long error, void *context);
 | 
			
		||||
 | 
			
		||||
The "error" parameter in this callback, as well as the "*error" parameter in
 | 
			
		||||
all of the synchronous versions, is a bitset (instead of a simple error value).
 | 
			
		||||
In the case of an write-I/O to multiple regions, this bitset allows dm-io to
 | 
			
		||||
indicate success or failure on each individual region.
 | 
			
		||||
 | 
			
		||||
Before using any of the dm-io services, the user should call dm_io_get()
 | 
			
		||||
and specify the number of pages they expect to perform I/O on concurrently.
 | 
			
		||||
Dm-io will attempt to resize its mempool to make sure enough pages are
 | 
			
		||||
always available in order to avoid unnecessary waiting while performing I/O.
 | 
			
		||||
 | 
			
		||||
When the user is finished using the dm-io services, they should call
 | 
			
		||||
dm_io_put() and specify the same number of pages that were given on the
 | 
			
		||||
dm_io_get() call.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								doc/kernel/kcopyd.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								doc/kernel/kcopyd.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
kcopyd
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
Kcopyd provides the ability to copy a range of sectors from one block-device
 | 
			
		||||
to one or more other block-devices, with an asynchronous completion
 | 
			
		||||
notification. It is used by dm-snapshot and dm-mirror.
 | 
			
		||||
 | 
			
		||||
Users of kcopyd must first create a client and indicate how many memory pages
 | 
			
		||||
to set aside for their copy jobs. This is done with a call to
 | 
			
		||||
kcopyd_client_create().
 | 
			
		||||
 | 
			
		||||
   int kcopyd_client_create(unsigned int num_pages,
 | 
			
		||||
                            struct kcopyd_client **result);
 | 
			
		||||
 | 
			
		||||
To start a copy job, the user must set up io_region structures to describe
 | 
			
		||||
the source and destinations of the copy. Each io_region indicates a
 | 
			
		||||
block-device along with the starting sector and size of the region. The source
 | 
			
		||||
of the copy is given as one io_region structure, and the destinations of the
 | 
			
		||||
copy are given as an array of io_region structures.
 | 
			
		||||
 | 
			
		||||
   struct io_region {
 | 
			
		||||
      struct block_device *bdev;
 | 
			
		||||
      sector_t sector;
 | 
			
		||||
      sector_t count;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
To start the copy, the user calls kcopyd_copy(), passing in the client
 | 
			
		||||
pointer, pointers to the source and destination io_regions, the name of a
 | 
			
		||||
completion callback routine, and a pointer to some context data for the copy.
 | 
			
		||||
 | 
			
		||||
   int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
 | 
			
		||||
                   unsigned int num_dests, struct io_region *dests,
 | 
			
		||||
                   unsigned int flags, kcopyd_notify_fn fn, void *context);
 | 
			
		||||
 | 
			
		||||
   typedef void (*kcopyd_notify_fn)(int read_err, unsigned int write_err,
 | 
			
		||||
				    void *context);
 | 
			
		||||
 | 
			
		||||
When the copy completes, kcopyd will call the user's completion routine,
 | 
			
		||||
passing back the user's context pointer. It will also indicate if a read or
 | 
			
		||||
write error occurred during the copy.
 | 
			
		||||
 | 
			
		||||
When a user is done with all their copy jobs, they should call
 | 
			
		||||
kcopyd_client_destroy() to delete the kcopyd client, which will release the
 | 
			
		||||
associated memory pages.
 | 
			
		||||
 | 
			
		||||
   void kcopyd_client_destroy(struct kcopyd_client *kc);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								doc/kernel/linear.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								doc/kernel/linear.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
dm-linear
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
Device-Mapper's "linear" target maps a linear range of the Device-Mapper
 | 
			
		||||
device onto a linear range of another device.  This is the basic building
 | 
			
		||||
block of logical volume managers.
 | 
			
		||||
 | 
			
		||||
Parameters: <dev path> <offset>
 | 
			
		||||
    <dev path>: Full pathname to the underlying block-device, or a
 | 
			
		||||
                "major:minor" device-number.
 | 
			
		||||
    <offset>: Starting sector within the device.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Example scripts
 | 
			
		||||
===============
 | 
			
		||||
[[
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# Create an identity mapping for a device
 | 
			
		||||
echo "0 `blockdev --getsize $1` linear $1 0" | dmsetup create identity
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
# Join 2 devices together
 | 
			
		||||
size1=`blockdev --getsize $1`
 | 
			
		||||
size2=`blockdev --getsize $2`
 | 
			
		||||
echo "0 $size1 linear $1 0
 | 
			
		||||
$size1 $size2 linear $2 0" | dmsetup create joined
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
# Split a device into 4M chunks and then join them together in reverse order.
 | 
			
		||||
 | 
			
		||||
my $name = "reverse";
 | 
			
		||||
my $extent_size = 4 * 1024 * 2;
 | 
			
		||||
my $dev = $ARGV[0];
 | 
			
		||||
my $table = "";
 | 
			
		||||
my $count = 0;
 | 
			
		||||
 | 
			
		||||
if (!defined($dev)) {
 | 
			
		||||
        die("Please specify a device.\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
my $dev_size = `blockdev --getsize $dev`;
 | 
			
		||||
my $extents = int($dev_size / $extent_size) -
 | 
			
		||||
              (($dev_size % $extent_size) ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
while ($extents > 0) {
 | 
			
		||||
        my $this_start = $count * $extent_size;
 | 
			
		||||
        $extents--;
 | 
			
		||||
        $count++;
 | 
			
		||||
        my $this_offset = $extents * $extent_size;
 | 
			
		||||
 | 
			
		||||
        $table .= "$this_start $extent_size linear $dev $this_offset\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
`echo \"$table\" | dmsetup create $name`;
 | 
			
		||||
]]
 | 
			
		||||
							
								
								
									
										54
									
								
								doc/kernel/log.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								doc/kernel/log.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
Device-Mapper Logging
 | 
			
		||||
=====================
 | 
			
		||||
The device-mapper logging code is used by some of the device-mapper
 | 
			
		||||
RAID targets to track regions of the disk that are not consistent.
 | 
			
		||||
A region (or portion of the address space) of the disk may be
 | 
			
		||||
inconsistent because a RAID stripe is currently being operated on or
 | 
			
		||||
a machine died while the region was being altered.  In the case of
 | 
			
		||||
mirrors, a region would be considered dirty/inconsistent while you
 | 
			
		||||
are writing to it because the writes need to be replicated for all
 | 
			
		||||
the legs of the mirror and may not reach the legs at the same time.
 | 
			
		||||
Once all writes are complete, the region is considered clean again.
 | 
			
		||||
 | 
			
		||||
There is a generic logging interface that the device-mapper RAID
 | 
			
		||||
implementations use to perform logging operations (see
 | 
			
		||||
dm_dirty_log_type in include/linux/dm-dirty-log.h).  Various different
 | 
			
		||||
logging implementations are available and provide different
 | 
			
		||||
capabilities.  The list includes:
 | 
			
		||||
 | 
			
		||||
Type		Files
 | 
			
		||||
====		=====
 | 
			
		||||
disk		drivers/md/dm-log.c
 | 
			
		||||
core		drivers/md/dm-log.c
 | 
			
		||||
userspace	drivers/md/dm-log-userspace* include/linux/dm-log-userspace.h
 | 
			
		||||
 | 
			
		||||
The "disk" log type
 | 
			
		||||
-------------------
 | 
			
		||||
This log implementation commits the log state to disk.  This way, the
 | 
			
		||||
logging state survives reboots/crashes.
 | 
			
		||||
 | 
			
		||||
The "core" log type
 | 
			
		||||
-------------------
 | 
			
		||||
This log implementation keeps the log state in memory.  The log state
 | 
			
		||||
will not survive a reboot or crash, but there may be a small boost in
 | 
			
		||||
performance.  This method can also be used if no storage device is
 | 
			
		||||
available for storing log state.
 | 
			
		||||
 | 
			
		||||
The "userspace" log type
 | 
			
		||||
------------------------
 | 
			
		||||
This log type simply provides a way to export the log API to userspace,
 | 
			
		||||
so log implementations can be done there.  This is done by forwarding most
 | 
			
		||||
logging requests to userspace, where a daemon receives and processes the
 | 
			
		||||
request.
 | 
			
		||||
 | 
			
		||||
The structure used for communication between kernel and userspace are
 | 
			
		||||
located in include/linux/dm-log-userspace.h.  Due to the frequency,
 | 
			
		||||
diversity, and 2-way communication nature of the exchanges between
 | 
			
		||||
kernel and userspace, 'connector' is used as the interface for
 | 
			
		||||
communication.
 | 
			
		||||
 | 
			
		||||
There are currently two userspace log implementations that leverage this
 | 
			
		||||
framework - "clustered-disk" and "clustered-core".  These implementations
 | 
			
		||||
provide a cluster-coherent log for shared-storage.  Device-mapper mirroring
 | 
			
		||||
can be used in a shared-storage environment when the cluster log implementations
 | 
			
		||||
are employed.
 | 
			
		||||
							
								
								
									
										84
									
								
								doc/kernel/persistent-data.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								doc/kernel/persistent-data.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
Introduction
 | 
			
		||||
============
 | 
			
		||||
 | 
			
		||||
The more-sophisticated device-mapper targets require complex metadata
 | 
			
		||||
that is managed in kernel.  In late 2010 we were seeing that various
 | 
			
		||||
different targets were rolling their own data strutures, for example:
 | 
			
		||||
 | 
			
		||||
- Mikulas Patocka's multisnap implementation
 | 
			
		||||
- Heinz Mauelshagen's thin provisioning target
 | 
			
		||||
- Another btree-based caching target posted to dm-devel
 | 
			
		||||
- Another multi-snapshot target based on a design of Daniel Phillips
 | 
			
		||||
 | 
			
		||||
Maintaining these data structures takes a lot of work, so if possible
 | 
			
		||||
we'd like to reduce the number.
 | 
			
		||||
 | 
			
		||||
The persistent-data library is an attempt to provide a re-usable
 | 
			
		||||
framework for people who want to store metadata in device-mapper
 | 
			
		||||
targets.  It's currently used by the thin-provisioning target and an
 | 
			
		||||
upcoming hierarchical storage target.
 | 
			
		||||
 | 
			
		||||
Overview
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
The main documentation is in the header files which can all be found
 | 
			
		||||
under drivers/md/persistent-data.
 | 
			
		||||
 | 
			
		||||
The block manager
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
dm-block-manager.[hc]
 | 
			
		||||
 | 
			
		||||
This provides access to the data on disk in fixed sized-blocks.  There
 | 
			
		||||
is a read/write locking interface to prevent concurrent accesses, and
 | 
			
		||||
keep data that is being used in the cache.
 | 
			
		||||
 | 
			
		||||
Clients of persistent-data are unlikely to use this directly.
 | 
			
		||||
 | 
			
		||||
The transaction manager
 | 
			
		||||
-----------------------
 | 
			
		||||
 | 
			
		||||
dm-transaction-manager.[hc]
 | 
			
		||||
 | 
			
		||||
This restricts access to blocks and enforces copy-on-write semantics.
 | 
			
		||||
The only way you can get hold of a writable block through the
 | 
			
		||||
transaction manager is by shadowing an existing block (ie. doing
 | 
			
		||||
copy-on-write) or allocating a fresh one.  Shadowing is elided within
 | 
			
		||||
the same transaction so performance is reasonable.  The commit method
 | 
			
		||||
ensures that all data is flushed before it writes the superblock.
 | 
			
		||||
On power failure your metadata will be as it was when last committed.
 | 
			
		||||
 | 
			
		||||
The Space Maps
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
dm-space-map.h
 | 
			
		||||
dm-space-map-metadata.[hc]
 | 
			
		||||
dm-space-map-disk.[hc]
 | 
			
		||||
 | 
			
		||||
On-disk data structures that keep track of reference counts of blocks.
 | 
			
		||||
Also acts as the allocator of new blocks.  Currently two
 | 
			
		||||
implementations: a simpler one for managing blocks on a different
 | 
			
		||||
device (eg. thinly-provisioned data blocks); and one for managing
 | 
			
		||||
the metadata space.  The latter is complicated by the need to store
 | 
			
		||||
its own data within the space it's managing.
 | 
			
		||||
 | 
			
		||||
The data structures
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
dm-btree.[hc]
 | 
			
		||||
dm-btree-remove.c
 | 
			
		||||
dm-btree-spine.c
 | 
			
		||||
dm-btree-internal.h
 | 
			
		||||
 | 
			
		||||
Currently there is only one data structure, a hierarchical btree.
 | 
			
		||||
There are plans to add more.  For example, something with an
 | 
			
		||||
array-like interface would see a lot of use.
 | 
			
		||||
 | 
			
		||||
The btree is 'hierarchical' in that you can define it to be composed
 | 
			
		||||
of nested btrees, and take multiple keys.  For example, the
 | 
			
		||||
thin-provisioning target uses a btree with two levels of nesting.
 | 
			
		||||
The first maps a device id to a mapping tree, and that in turn maps a
 | 
			
		||||
virtual block to a physical block.
 | 
			
		||||
 | 
			
		||||
Values stored in the btrees can have arbitrary size.  Keys are always
 | 
			
		||||
64bits, although nesting allows you to use multiple keys.
 | 
			
		||||
							
								
								
									
										39
									
								
								doc/kernel/queue-length.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								doc/kernel/queue-length.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
dm-queue-length
 | 
			
		||||
===============
 | 
			
		||||
 | 
			
		||||
dm-queue-length is a path selector module for device-mapper targets,
 | 
			
		||||
which selects a path with the least number of in-flight I/Os.
 | 
			
		||||
The path selector name is 'queue-length'.
 | 
			
		||||
 | 
			
		||||
Table parameters for each path: [<repeat_count>]
 | 
			
		||||
	<repeat_count>: The number of I/Os to dispatch using the selected
 | 
			
		||||
			path before switching to the next path.
 | 
			
		||||
			If not given, internal default is used. To check
 | 
			
		||||
			the default value, see the activated table.
 | 
			
		||||
 | 
			
		||||
Status for each path: <status> <fail-count> <in-flight>
 | 
			
		||||
	<status>: 'A' if the path is active, 'F' if the path is failed.
 | 
			
		||||
	<fail-count>: The number of path failures.
 | 
			
		||||
	<in-flight>: The number of in-flight I/Os on the path.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Algorithm
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
dm-queue-length increments/decrements 'in-flight' when an I/O is
 | 
			
		||||
dispatched/completed respectively.
 | 
			
		||||
dm-queue-length selects a path with the minimum 'in-flight'.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Examples
 | 
			
		||||
========
 | 
			
		||||
In case that 2 paths (sda and sdb) are used with repeat_count == 128.
 | 
			
		||||
 | 
			
		||||
# echo "0 10 multipath 0 0 1 1 queue-length 0 2 1 8:0 128 8:16 128" \
 | 
			
		||||
  dmsetup create test
 | 
			
		||||
#
 | 
			
		||||
# dmsetup table
 | 
			
		||||
test: 0 10 multipath 0 0 1 1 queue-length 0 2 1 8:0 128 8:16 128
 | 
			
		||||
#
 | 
			
		||||
# dmsetup status
 | 
			
		||||
test: 0 10 multipath 2 0 0 0 1 1 E 0 2 1 8:0 A 0 0 8:16 A 0 0
 | 
			
		||||
							
								
								
									
										108
									
								
								doc/kernel/raid.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								doc/kernel/raid.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
dm-raid
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
The device-mapper RAID (dm-raid) target provides a bridge from DM to MD.
 | 
			
		||||
It allows the MD RAID drivers to be accessed using a device-mapper
 | 
			
		||||
interface.
 | 
			
		||||
 | 
			
		||||
The target is named "raid" and it accepts the following parameters:
 | 
			
		||||
 | 
			
		||||
  <raid_type> <#raid_params> <raid_params> \
 | 
			
		||||
    <#raid_devs> <metadata_dev0> <dev0> [.. <metadata_devN> <devN>]
 | 
			
		||||
 | 
			
		||||
<raid_type>:
 | 
			
		||||
  raid1		RAID1 mirroring
 | 
			
		||||
  raid4		RAID4 dedicated parity disk
 | 
			
		||||
  raid5_la	RAID5 left asymmetric
 | 
			
		||||
		- rotating parity 0 with data continuation
 | 
			
		||||
  raid5_ra	RAID5 right asymmetric
 | 
			
		||||
		- rotating parity N with data continuation
 | 
			
		||||
  raid5_ls	RAID5 left symmetric
 | 
			
		||||
		- rotating parity 0 with data restart
 | 
			
		||||
  raid5_rs 	RAID5 right symmetric
 | 
			
		||||
		- rotating parity N with data restart
 | 
			
		||||
  raid6_zr	RAID6 zero restart
 | 
			
		||||
		- rotating parity zero (left-to-right) with data restart
 | 
			
		||||
  raid6_nr	RAID6 N restart
 | 
			
		||||
		- rotating parity N (right-to-left) with data restart
 | 
			
		||||
  raid6_nc	RAID6 N continue
 | 
			
		||||
		- rotating parity N (right-to-left) with data continuation
 | 
			
		||||
 | 
			
		||||
  Refererence: Chapter 4 of
 | 
			
		||||
  http://www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf
 | 
			
		||||
 | 
			
		||||
<#raid_params>: The number of parameters that follow.
 | 
			
		||||
 | 
			
		||||
<raid_params> consists of
 | 
			
		||||
    Mandatory parameters:
 | 
			
		||||
        <chunk_size>: Chunk size in sectors.  This parameter is often known as
 | 
			
		||||
		      "stripe size".  It is the only mandatory parameter and
 | 
			
		||||
		      is placed first.
 | 
			
		||||
 | 
			
		||||
    followed by optional parameters (in any order):
 | 
			
		||||
	[sync|nosync]   Force or prevent RAID initialization.
 | 
			
		||||
 | 
			
		||||
	[rebuild <idx>]	Rebuild drive number idx (first drive is 0).
 | 
			
		||||
 | 
			
		||||
	[daemon_sleep <ms>]
 | 
			
		||||
		Interval between runs of the bitmap daemon that
 | 
			
		||||
		clear bits.  A longer interval means less bitmap I/O but
 | 
			
		||||
		resyncing after a failure is likely to take longer.
 | 
			
		||||
 | 
			
		||||
	[min_recovery_rate <kB/sec/disk>]  Throttle RAID initialization
 | 
			
		||||
	[max_recovery_rate <kB/sec/disk>]  Throttle RAID initialization
 | 
			
		||||
	[write_mostly <idx>]		   Drive index is write-mostly
 | 
			
		||||
	[max_write_behind <sectors>]       See '-write-behind=' (man mdadm)
 | 
			
		||||
	[stripe_cache <sectors>]           Stripe cache size (higher RAIDs only)
 | 
			
		||||
	[region_size <sectors>]
 | 
			
		||||
		The region_size multiplied by the number of regions is the
 | 
			
		||||
		logical size of the array.  The bitmap records the device
 | 
			
		||||
		synchronisation state for each region.
 | 
			
		||||
 | 
			
		||||
<#raid_devs>: The number of devices composing the array.
 | 
			
		||||
	Each device consists of two entries.  The first is the device
 | 
			
		||||
	containing the metadata (if any); the second is the one containing the
 | 
			
		||||
	data.
 | 
			
		||||
 | 
			
		||||
	If a drive has failed or is missing at creation time, a '-' can be
 | 
			
		||||
	given for both the metadata and data drives for a given position.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Example tables
 | 
			
		||||
--------------
 | 
			
		||||
# RAID4 - 4 data drives, 1 parity (no metadata devices)
 | 
			
		||||
# No metadata devices specified to hold superblock/bitmap info
 | 
			
		||||
# Chunk size of 1MiB
 | 
			
		||||
# (Lines separated for easy reading)
 | 
			
		||||
 | 
			
		||||
0 1960893648 raid \
 | 
			
		||||
        raid4 1 2048 \
 | 
			
		||||
        5 - 8:17 - 8:33 - 8:49 - 8:65 - 8:81
 | 
			
		||||
 | 
			
		||||
# RAID4 - 4 data drives, 1 parity (with metadata devices)
 | 
			
		||||
# Chunk size of 1MiB, force RAID initialization,
 | 
			
		||||
#       min recovery rate at 20 kiB/sec/disk
 | 
			
		||||
 | 
			
		||||
0 1960893648 raid \
 | 
			
		||||
        raid4 4 2048 sync min_recovery_rate 20 \
 | 
			
		||||
        5 8:17 8:18 8:33 8:34 8:49 8:50 8:65 8:66 8:81 8:82
 | 
			
		||||
 | 
			
		||||
'dmsetup table' displays the table used to construct the mapping.
 | 
			
		||||
The optional parameters are always printed in the order listed
 | 
			
		||||
above with "sync" or "nosync" always output ahead of the other
 | 
			
		||||
arguments, regardless of the order used when originally loading the table.
 | 
			
		||||
Arguments that can be repeated are ordered by value.
 | 
			
		||||
 | 
			
		||||
'dmsetup status' yields information on the state and health of the
 | 
			
		||||
array.
 | 
			
		||||
The output is as follows:
 | 
			
		||||
1: <s> <l> raid \
 | 
			
		||||
2:      <raid_type> <#devices> <1 health char for each dev> <resync_ratio>
 | 
			
		||||
 | 
			
		||||
Line 1 is the standard output produced by device-mapper.
 | 
			
		||||
Line 2 is produced by the raid target, and best explained by example:
 | 
			
		||||
        0 1960893648 raid raid4 5 AAAAA 2/490221568
 | 
			
		||||
Here we can see the RAID type is raid4, there are 5 devices - all of
 | 
			
		||||
which are 'A'live, and the array is 2/490221568 complete with recovery.
 | 
			
		||||
Faulty or missing devices are marked 'D'.  Devices that are out-of-sync
 | 
			
		||||
are marked 'a'.
 | 
			
		||||
							
								
								
									
										91
									
								
								doc/kernel/service-time.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								doc/kernel/service-time.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
dm-service-time
 | 
			
		||||
===============
 | 
			
		||||
 | 
			
		||||
dm-service-time is a path selector module for device-mapper targets,
 | 
			
		||||
which selects a path with the shortest estimated service time for
 | 
			
		||||
the incoming I/O.
 | 
			
		||||
 | 
			
		||||
The service time for each path is estimated by dividing the total size
 | 
			
		||||
of in-flight I/Os on a path with the performance value of the path.
 | 
			
		||||
The performance value is a relative throughput value among all paths
 | 
			
		||||
in a path-group, and it can be specified as a table argument.
 | 
			
		||||
 | 
			
		||||
The path selector name is 'service-time'.
 | 
			
		||||
 | 
			
		||||
Table parameters for each path: [<repeat_count> [<relative_throughput>]]
 | 
			
		||||
	<repeat_count>: The number of I/Os to dispatch using the selected
 | 
			
		||||
			path before switching to the next path.
 | 
			
		||||
			If not given, internal default is used.  To check
 | 
			
		||||
			the default value, see the activated table.
 | 
			
		||||
	<relative_throughput>: The relative throughput value of the path
 | 
			
		||||
			among all paths in the path-group.
 | 
			
		||||
			The valid range is 0-100.
 | 
			
		||||
			If not given, minimum value '1' is used.
 | 
			
		||||
			If '0' is given, the path isn't selected while
 | 
			
		||||
			other paths having a positive value are available.
 | 
			
		||||
 | 
			
		||||
Status for each path: <status> <fail-count> <in-flight-size> \
 | 
			
		||||
		      <relative_throughput>
 | 
			
		||||
	<status>: 'A' if the path is active, 'F' if the path is failed.
 | 
			
		||||
	<fail-count>: The number of path failures.
 | 
			
		||||
	<in-flight-size>: The size of in-flight I/Os on the path.
 | 
			
		||||
	<relative_throughput>: The relative throughput value of the path
 | 
			
		||||
			among all paths in the path-group.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Algorithm
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
dm-service-time adds the I/O size to 'in-flight-size' when the I/O is
 | 
			
		||||
dispatched and subtracts when completed.
 | 
			
		||||
Basically, dm-service-time selects a path having minimum service time
 | 
			
		||||
which is calculated by:
 | 
			
		||||
 | 
			
		||||
	('in-flight-size' + 'size-of-incoming-io') / 'relative_throughput'
 | 
			
		||||
 | 
			
		||||
However, some optimizations below are used to reduce the calculation
 | 
			
		||||
as much as possible.
 | 
			
		||||
 | 
			
		||||
	1. If the paths have the same 'relative_throughput', skip
 | 
			
		||||
	   the division and just compare the 'in-flight-size'.
 | 
			
		||||
 | 
			
		||||
	2. If the paths have the same 'in-flight-size', skip the division
 | 
			
		||||
	   and just compare the 'relative_throughput'.
 | 
			
		||||
 | 
			
		||||
	3. If some paths have non-zero 'relative_throughput' and others
 | 
			
		||||
	   have zero 'relative_throughput', ignore those paths with zero
 | 
			
		||||
	   'relative_throughput'.
 | 
			
		||||
 | 
			
		||||
If such optimizations can't be applied, calculate service time, and
 | 
			
		||||
compare service time.
 | 
			
		||||
If calculated service time is equal, the path having maximum
 | 
			
		||||
'relative_throughput' may be better.  So compare 'relative_throughput'
 | 
			
		||||
then.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Examples
 | 
			
		||||
========
 | 
			
		||||
In case that 2 paths (sda and sdb) are used with repeat_count == 128
 | 
			
		||||
and sda has an average throughput 1GB/s and sdb has 4GB/s,
 | 
			
		||||
'relative_throughput' value may be '1' for sda and '4' for sdb.
 | 
			
		||||
 | 
			
		||||
# echo "0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 1 8:16 128 4" \
 | 
			
		||||
  dmsetup create test
 | 
			
		||||
#
 | 
			
		||||
# dmsetup table
 | 
			
		||||
test: 0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 1 8:16 128 4
 | 
			
		||||
#
 | 
			
		||||
# dmsetup status
 | 
			
		||||
test: 0 10 multipath 2 0 0 0 1 1 E 0 2 2 8:0 A 0 0 1 8:16 A 0 0 4
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Or '2' for sda and '8' for sdb would be also true.
 | 
			
		||||
 | 
			
		||||
# echo "0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 2 8:16 128 8" \
 | 
			
		||||
  dmsetup create test
 | 
			
		||||
#
 | 
			
		||||
# dmsetup table
 | 
			
		||||
test: 0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 2 8:16 128 8
 | 
			
		||||
#
 | 
			
		||||
# dmsetup status
 | 
			
		||||
test: 0 10 multipath 2 0 0 0 1 1 E 0 2 2 8:0 A 0 0 2 8:16 A 0 0 8
 | 
			
		||||
							
								
								
									
										168
									
								
								doc/kernel/snapshot.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								doc/kernel/snapshot.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
Device-mapper snapshot support
 | 
			
		||||
==============================
 | 
			
		||||
 | 
			
		||||
Device-mapper allows you, without massive data copying:
 | 
			
		||||
 | 
			
		||||
*) To create snapshots of any block device i.e. mountable, saved states of
 | 
			
		||||
the block device which are also writable without interfering with the
 | 
			
		||||
original content;
 | 
			
		||||
*) To create device "forks", i.e. multiple different versions of the
 | 
			
		||||
same data stream.
 | 
			
		||||
*) To merge a snapshot of a block device back into the snapshot's origin
 | 
			
		||||
device.
 | 
			
		||||
 | 
			
		||||
In the first two cases, dm copies only the chunks of data that get
 | 
			
		||||
changed and uses a separate copy-on-write (COW) block device for
 | 
			
		||||
storage.
 | 
			
		||||
 | 
			
		||||
For snapshot merge the contents of the COW storage are merged back into
 | 
			
		||||
the origin device.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
There are three dm targets available:
 | 
			
		||||
snapshot, snapshot-origin, and snapshot-merge.
 | 
			
		||||
 | 
			
		||||
*) snapshot-origin <origin>
 | 
			
		||||
 | 
			
		||||
which will normally have one or more snapshots based on it.
 | 
			
		||||
Reads will be mapped directly to the backing device. For each write, the
 | 
			
		||||
original data will be saved in the <COW device> of each snapshot to keep
 | 
			
		||||
its visible content unchanged, at least until the <COW device> fills up.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
*) snapshot <origin> <COW device> <persistent?> <chunksize>
 | 
			
		||||
 | 
			
		||||
A snapshot of the <origin> block device is created. Changed chunks of
 | 
			
		||||
<chunksize> sectors will be stored on the <COW device>.  Writes will
 | 
			
		||||
only go to the <COW device>.  Reads will come from the <COW device> or
 | 
			
		||||
from <origin> for unchanged data.  <COW device> will often be
 | 
			
		||||
smaller than the origin and if it fills up the snapshot will become
 | 
			
		||||
useless and be disabled, returning errors.  So it is important to monitor
 | 
			
		||||
the amount of free space and expand the <COW device> before it fills up.
 | 
			
		||||
 | 
			
		||||
<persistent?> is P (Persistent) or N (Not persistent - will not survive
 | 
			
		||||
after reboot).
 | 
			
		||||
The difference is that for transient snapshots less metadata must be
 | 
			
		||||
saved on disk - they can be kept in memory by the kernel.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
* snapshot-merge <origin> <COW device> <persistent> <chunksize>
 | 
			
		||||
 | 
			
		||||
takes the same table arguments as the snapshot target except it only
 | 
			
		||||
works with persistent snapshots.  This target assumes the role of the
 | 
			
		||||
"snapshot-origin" target and must not be loaded if the "snapshot-origin"
 | 
			
		||||
is still present for <origin>.
 | 
			
		||||
 | 
			
		||||
Creates a merging snapshot that takes control of the changed chunks
 | 
			
		||||
stored in the <COW device> of an existing snapshot, through a handover
 | 
			
		||||
procedure, and merges these chunks back into the <origin>.  Once merging
 | 
			
		||||
has started (in the background) the <origin> may be opened and the merge
 | 
			
		||||
will continue while I/O is flowing to it.  Changes to the <origin> are
 | 
			
		||||
deferred until the merging snapshot's corresponding chunk(s) have been
 | 
			
		||||
merged.  Once merging has started the snapshot device, associated with
 | 
			
		||||
the "snapshot" target, will return -EIO when accessed.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
How snapshot is used by LVM2
 | 
			
		||||
============================
 | 
			
		||||
When you create the first LVM2 snapshot of a volume, four dm devices are used:
 | 
			
		||||
 | 
			
		||||
1) a device containing the original mapping table of the source volume;
 | 
			
		||||
2) a device used as the <COW device>;
 | 
			
		||||
3) a "snapshot" device, combining #1 and #2, which is the visible snapshot
 | 
			
		||||
   volume;
 | 
			
		||||
4) the "original" volume (which uses the device number used by the original
 | 
			
		||||
   source volume), whose table is replaced by a "snapshot-origin" mapping
 | 
			
		||||
   from device #1.
 | 
			
		||||
 | 
			
		||||
A fixed naming scheme is used, so with the following commands:
 | 
			
		||||
 | 
			
		||||
lvcreate -L 1G -n base volumeGroup
 | 
			
		||||
lvcreate -L 100M --snapshot -n snap volumeGroup/base
 | 
			
		||||
 | 
			
		||||
we'll have this situation (with volumes in above order):
 | 
			
		||||
 | 
			
		||||
# dmsetup table|grep volumeGroup
 | 
			
		||||
 | 
			
		||||
volumeGroup-base-real: 0 2097152 linear 8:19 384
 | 
			
		||||
volumeGroup-snap-cow: 0 204800 linear 8:19 2097536
 | 
			
		||||
volumeGroup-snap: 0 2097152 snapshot 254:11 254:12 P 16
 | 
			
		||||
volumeGroup-base: 0 2097152 snapshot-origin 254:11
 | 
			
		||||
 | 
			
		||||
# ls -lL /dev/mapper/volumeGroup-*
 | 
			
		||||
brw-------  1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
 | 
			
		||||
brw-------  1 root root 254, 12 29 ago 18:15 /dev/mapper/volumeGroup-snap-cow
 | 
			
		||||
brw-------  1 root root 254, 13 29 ago 18:15 /dev/mapper/volumeGroup-snap
 | 
			
		||||
brw-------  1 root root 254, 10 29 ago 18:14 /dev/mapper/volumeGroup-base
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
How snapshot-merge is used by LVM2
 | 
			
		||||
==================================
 | 
			
		||||
A merging snapshot assumes the role of the "snapshot-origin" while
 | 
			
		||||
merging.  As such the "snapshot-origin" is replaced with
 | 
			
		||||
"snapshot-merge".  The "-real" device is not changed and the "-cow"
 | 
			
		||||
device is renamed to <origin name>-cow to aid LVM2's cleanup of the
 | 
			
		||||
merging snapshot after it completes.  The "snapshot" that hands over its
 | 
			
		||||
COW device to the "snapshot-merge" is deactivated (unless using lvchange
 | 
			
		||||
--refresh); but if it is left active it will simply return I/O errors.
 | 
			
		||||
 | 
			
		||||
A snapshot will merge into its origin with the following command:
 | 
			
		||||
 | 
			
		||||
lvconvert --merge volumeGroup/snap
 | 
			
		||||
 | 
			
		||||
we'll now have this situation:
 | 
			
		||||
 | 
			
		||||
# dmsetup table|grep volumeGroup
 | 
			
		||||
 | 
			
		||||
volumeGroup-base-real: 0 2097152 linear 8:19 384
 | 
			
		||||
volumeGroup-base-cow: 0 204800 linear 8:19 2097536
 | 
			
		||||
volumeGroup-base: 0 2097152 snapshot-merge 254:11 254:12 P 16
 | 
			
		||||
 | 
			
		||||
# ls -lL /dev/mapper/volumeGroup-*
 | 
			
		||||
brw-------  1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
 | 
			
		||||
brw-------  1 root root 254, 12 29 ago 18:16 /dev/mapper/volumeGroup-base-cow
 | 
			
		||||
brw-------  1 root root 254, 10 29 ago 18:16 /dev/mapper/volumeGroup-base
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
How to determine when a merging is complete
 | 
			
		||||
===========================================
 | 
			
		||||
The snapshot-merge and snapshot status lines end with:
 | 
			
		||||
  <sectors_allocated>/<total_sectors> <metadata_sectors>
 | 
			
		||||
 | 
			
		||||
Both <sectors_allocated> and <total_sectors> include both data and metadata.
 | 
			
		||||
During merging, the number of sectors allocated gets smaller and
 | 
			
		||||
smaller.  Merging has finished when the number of sectors holding data
 | 
			
		||||
is zero, in other words <sectors_allocated> == <metadata_sectors>.
 | 
			
		||||
 | 
			
		||||
Here is a practical example (using a hybrid of lvm and dmsetup commands):
 | 
			
		||||
 | 
			
		||||
# lvs
 | 
			
		||||
  LV      VG          Attr   LSize Origin  Snap%  Move Log Copy%  Convert
 | 
			
		||||
  base    volumeGroup owi-a- 4.00g
 | 
			
		||||
  snap    volumeGroup swi-a- 1.00g base  18.97
 | 
			
		||||
 | 
			
		||||
# dmsetup status volumeGroup-snap
 | 
			
		||||
0 8388608 snapshot 397896/2097152 1560
 | 
			
		||||
                                  ^^^^ metadata sectors
 | 
			
		||||
 | 
			
		||||
# lvconvert --merge -b volumeGroup/snap
 | 
			
		||||
  Merging of volume snap started.
 | 
			
		||||
 | 
			
		||||
# lvs volumeGroup/snap
 | 
			
		||||
  LV      VG          Attr   LSize Origin  Snap%  Move Log Copy%  Convert
 | 
			
		||||
  base    volumeGroup Owi-a- 4.00g          17.23
 | 
			
		||||
 | 
			
		||||
# dmsetup status volumeGroup-base
 | 
			
		||||
0 8388608 snapshot-merge 281688/2097152 1104
 | 
			
		||||
 | 
			
		||||
# dmsetup status volumeGroup-base
 | 
			
		||||
0 8388608 snapshot-merge 180480/2097152 712
 | 
			
		||||
 | 
			
		||||
# dmsetup status volumeGroup-base
 | 
			
		||||
0 8388608 snapshot-merge 16/2097152 16
 | 
			
		||||
 | 
			
		||||
Merging has finished.
 | 
			
		||||
 | 
			
		||||
# lvs
 | 
			
		||||
  LV      VG          Attr   LSize Origin  Snap%  Move Log Copy%  Convert
 | 
			
		||||
  base    volumeGroup owi-a- 4.00g
 | 
			
		||||
							
								
								
									
										58
									
								
								doc/kernel/striped.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								doc/kernel/striped.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
dm-stripe
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
Device-Mapper's "striped" target is used to create a striped (i.e. RAID-0)
 | 
			
		||||
device across one or more underlying devices. Data is written in "chunks",
 | 
			
		||||
with consecutive chunks rotating among the underlying devices. This can
 | 
			
		||||
potentially provide improved I/O throughput by utilizing several physical
 | 
			
		||||
devices in parallel.
 | 
			
		||||
 | 
			
		||||
Parameters: <num devs> <chunk size> [<dev path> <offset>]+
 | 
			
		||||
    <num devs>: Number of underlying devices.
 | 
			
		||||
    <chunk size>: Size of each chunk of data. Must be a power-of-2 and at
 | 
			
		||||
                  least as large as the system's PAGE_SIZE.
 | 
			
		||||
    <dev path>: Full pathname to the underlying block-device, or a
 | 
			
		||||
                "major:minor" device-number.
 | 
			
		||||
    <offset>: Starting sector within the device.
 | 
			
		||||
 | 
			
		||||
One or more underlying devices can be specified. The striped device size must
 | 
			
		||||
be a multiple of the chunk size and a multiple of the number of underlying
 | 
			
		||||
devices.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Example scripts
 | 
			
		||||
===============
 | 
			
		||||
 | 
			
		||||
[[
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
# Create a striped device across any number of underlying devices. The device
 | 
			
		||||
# will be called "stripe_dev" and have a chunk-size of 128k.
 | 
			
		||||
 | 
			
		||||
my $chunk_size = 128 * 2;
 | 
			
		||||
my $dev_name = "stripe_dev";
 | 
			
		||||
my $num_devs = @ARGV;
 | 
			
		||||
my @devs = @ARGV;
 | 
			
		||||
my ($min_dev_size, $stripe_dev_size, $i);
 | 
			
		||||
 | 
			
		||||
if (!$num_devs) {
 | 
			
		||||
        die("Specify at least one device\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$min_dev_size = `blockdev --getsize $devs[0]`;
 | 
			
		||||
for ($i = 1; $i < $num_devs; $i++) {
 | 
			
		||||
        my $this_size = `blockdev --getsize $devs[$i]`;
 | 
			
		||||
        $min_dev_size = ($min_dev_size < $this_size) ?
 | 
			
		||||
                        $min_dev_size : $this_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$stripe_dev_size = $min_dev_size * $num_devs;
 | 
			
		||||
$stripe_dev_size -= $stripe_dev_size % ($chunk_size * $num_devs);
 | 
			
		||||
 | 
			
		||||
$table = "0 $stripe_dev_size striped $num_devs $chunk_size";
 | 
			
		||||
for ($i = 0; $i < $num_devs; $i++) {
 | 
			
		||||
        $table .= " $devs[$i] 0";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
`echo $table | dmsetup create $dev_name`;
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										285
									
								
								doc/kernel/thin-provisioning.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								doc/kernel/thin-provisioning.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,285 @@
 | 
			
		||||
Introduction
 | 
			
		||||
============
 | 
			
		||||
 | 
			
		||||
This document descibes a collection of device-mapper targets that
 | 
			
		||||
between them implement thin-provisioning and snapshots.
 | 
			
		||||
 | 
			
		||||
The main highlight of this implementation, compared to the previous
 | 
			
		||||
implementation of snapshots, is that it allows many virtual devices to
 | 
			
		||||
be stored on the same data volume.  This simplifies administration and
 | 
			
		||||
allows the sharing of data between volumes, thus reducing disk usage.
 | 
			
		||||
 | 
			
		||||
Another significant feature is support for an arbitrary depth of
 | 
			
		||||
recursive snapshots (snapshots of snapshots of snapshots ...).  The
 | 
			
		||||
previous implementation of snapshots did this by chaining together
 | 
			
		||||
lookup tables, and so performance was O(depth).  This new
 | 
			
		||||
implementation uses a single data structure to avoid this degradation
 | 
			
		||||
with depth.  Fragmentation may still be an issue, however, in some
 | 
			
		||||
scenarios.
 | 
			
		||||
 | 
			
		||||
Metadata is stored on a separate device from data, giving the
 | 
			
		||||
administrator some freedom, for example to:
 | 
			
		||||
 | 
			
		||||
- Improve metadata resilience by storing metadata on a mirrored volume
 | 
			
		||||
  but data on a non-mirrored one.
 | 
			
		||||
 | 
			
		||||
- Improve performance by storing the metadata on SSD.
 | 
			
		||||
 | 
			
		||||
Status
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
These targets are very much still in the EXPERIMENTAL state.  Please
 | 
			
		||||
do not yet rely on them in production.  But do experiment and offer us
 | 
			
		||||
feedback.  Different use cases will have different performance
 | 
			
		||||
characteristics, for example due to fragmentation of the data volume.
 | 
			
		||||
 | 
			
		||||
If you find this software is not performing as expected please mail
 | 
			
		||||
dm-devel@redhat.com with details and we'll try our best to improve
 | 
			
		||||
things for you.
 | 
			
		||||
 | 
			
		||||
Userspace tools for checking and repairing the metadata are under
 | 
			
		||||
development.
 | 
			
		||||
 | 
			
		||||
Cookbook
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
This section describes some quick recipes for using thin provisioning.
 | 
			
		||||
They use the dmsetup program to control the device-mapper driver
 | 
			
		||||
directly.  End users will be advised to use a higher-level volume
 | 
			
		||||
manager such as LVM2 once support has been added.
 | 
			
		||||
 | 
			
		||||
Pool device
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
The pool device ties together the metadata volume and the data volume.
 | 
			
		||||
It maps I/O linearly to the data volume and updates the metadata via
 | 
			
		||||
two mechanisms:
 | 
			
		||||
 | 
			
		||||
- Function calls from the thin targets
 | 
			
		||||
 | 
			
		||||
- Device-mapper 'messages' from userspace which control the creation of new
 | 
			
		||||
  virtual devices amongst other things.
 | 
			
		||||
 | 
			
		||||
Setting up a fresh pool device
 | 
			
		||||
------------------------------
 | 
			
		||||
 | 
			
		||||
Setting up a pool device requires a valid metadata device, and a
 | 
			
		||||
data device.  If you do not have an existing metadata device you can
 | 
			
		||||
make one by zeroing the first 4k to indicate empty metadata.
 | 
			
		||||
 | 
			
		||||
    dd if=/dev/zero of=$metadata_dev bs=4096 count=1
 | 
			
		||||
 | 
			
		||||
The amount of metadata you need will vary according to how many blocks
 | 
			
		||||
are shared between thin devices (i.e. through snapshots).  If you have
 | 
			
		||||
less sharing than average you'll need a larger-than-average metadata device.
 | 
			
		||||
 | 
			
		||||
As a guide, we suggest you calculate the number of bytes to use in the
 | 
			
		||||
metadata device as 48 * $data_dev_size / $data_block_size but round it up
 | 
			
		||||
to 2MB if the answer is smaller.  The largest size supported is 16GB.
 | 
			
		||||
 | 
			
		||||
If you're creating large numbers of snapshots which are recording large
 | 
			
		||||
amounts of change, you may need find you need to increase this.
 | 
			
		||||
 | 
			
		||||
Reloading a pool table
 | 
			
		||||
----------------------
 | 
			
		||||
 | 
			
		||||
You may reload a pool's table, indeed this is how the pool is resized
 | 
			
		||||
if it runs out of space.  (N.B. While specifying a different metadata
 | 
			
		||||
device when reloading is not forbidden at the moment, things will go
 | 
			
		||||
wrong if it does not route I/O to exactly the same on-disk location as
 | 
			
		||||
previously.)
 | 
			
		||||
 | 
			
		||||
Using an existing pool device
 | 
			
		||||
-----------------------------
 | 
			
		||||
 | 
			
		||||
    dmsetup create pool \
 | 
			
		||||
	--table "0 20971520 thin-pool $metadata_dev $data_dev \
 | 
			
		||||
		 $data_block_size $low_water_mark"
 | 
			
		||||
 | 
			
		||||
$data_block_size gives the smallest unit of disk space that can be
 | 
			
		||||
allocated at a time expressed in units of 512-byte sectors.  People
 | 
			
		||||
primarily interested in thin provisioning may want to use a value such
 | 
			
		||||
as 1024 (512KB).  People doing lots of snapshotting may want a smaller value
 | 
			
		||||
such as 128 (64KB).  If you are not zeroing newly-allocated data,
 | 
			
		||||
a larger $data_block_size in the region of 256000 (128MB) is suggested.
 | 
			
		||||
$data_block_size must be the same for the lifetime of the
 | 
			
		||||
metadata device.
 | 
			
		||||
 | 
			
		||||
$low_water_mark is expressed in blocks of size $data_block_size.  If
 | 
			
		||||
free space on the data device drops below this level then a dm event
 | 
			
		||||
will be triggered which a userspace daemon should catch allowing it to
 | 
			
		||||
extend the pool device.  Only one such event will be sent.
 | 
			
		||||
Resuming a device with a new table itself triggers an event so the
 | 
			
		||||
userspace daemon can use this to detect a situation where a new table
 | 
			
		||||
already exceeds the threshold.
 | 
			
		||||
 | 
			
		||||
Thin provisioning
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
i) Creating a new thinly-provisioned volume.
 | 
			
		||||
 | 
			
		||||
  To create a new thinly- provisioned volume you must send a message to an
 | 
			
		||||
  active pool device, /dev/mapper/pool in this example.
 | 
			
		||||
 | 
			
		||||
    dmsetup message /dev/mapper/pool 0 "create_thin 0"
 | 
			
		||||
 | 
			
		||||
  Here '0' is an identifier for the volume, a 24-bit number.  It's up
 | 
			
		||||
  to the caller to allocate and manage these identifiers.  If the
 | 
			
		||||
  identifier is already in use, the message will fail with -EEXIST.
 | 
			
		||||
 | 
			
		||||
ii) Using a thinly-provisioned volume.
 | 
			
		||||
 | 
			
		||||
  Thinly-provisioned volumes are activated using the 'thin' target:
 | 
			
		||||
 | 
			
		||||
    dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"
 | 
			
		||||
 | 
			
		||||
  The last parameter is the identifier for the thinp device.
 | 
			
		||||
 | 
			
		||||
Internal snapshots
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
i) Creating an internal snapshot.
 | 
			
		||||
 | 
			
		||||
  Snapshots are created with another message to the pool.
 | 
			
		||||
 | 
			
		||||
  N.B.  If the origin device that you wish to snapshot is active, you
 | 
			
		||||
  must suspend it before creating the snapshot to avoid corruption.
 | 
			
		||||
  This is NOT enforced at the moment, so please be careful!
 | 
			
		||||
 | 
			
		||||
    dmsetup suspend /dev/mapper/thin
 | 
			
		||||
    dmsetup message /dev/mapper/pool 0 "create_snap 1 0"
 | 
			
		||||
    dmsetup resume /dev/mapper/thin
 | 
			
		||||
 | 
			
		||||
  Here '1' is the identifier for the volume, a 24-bit number.  '0' is the
 | 
			
		||||
  identifier for the origin device.
 | 
			
		||||
 | 
			
		||||
ii) Using an internal snapshot.
 | 
			
		||||
 | 
			
		||||
  Once created, the user doesn't have to worry about any connection
 | 
			
		||||
  between the origin and the snapshot.  Indeed the snapshot is no
 | 
			
		||||
  different from any other thinly-provisioned device and can be
 | 
			
		||||
  snapshotted itself via the same method.  It's perfectly legal to
 | 
			
		||||
  have only one of them active, and there's no ordering requirement on
 | 
			
		||||
  activating or removing them both.  (This differs from conventional
 | 
			
		||||
  device-mapper snapshots.)
 | 
			
		||||
 | 
			
		||||
  Activate it exactly the same way as any other thinly-provisioned volume:
 | 
			
		||||
 | 
			
		||||
    dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
 | 
			
		||||
 | 
			
		||||
Deactivation
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
All devices using a pool must be deactivated before the pool itself
 | 
			
		||||
can be.
 | 
			
		||||
 | 
			
		||||
    dmsetup remove thin
 | 
			
		||||
    dmsetup remove snap
 | 
			
		||||
    dmsetup remove pool
 | 
			
		||||
 | 
			
		||||
Reference
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
'thin-pool' target
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
i) Constructor
 | 
			
		||||
 | 
			
		||||
    thin-pool <metadata dev> <data dev> <data block size (sectors)> \
 | 
			
		||||
	      <low water mark (blocks)> [<number of feature args> [<arg>]*]
 | 
			
		||||
 | 
			
		||||
    Optional feature arguments:
 | 
			
		||||
    - 'skip_block_zeroing': skips the zeroing of newly-provisioned blocks.
 | 
			
		||||
 | 
			
		||||
    Data block size must be between 64KB (128 sectors) and 1GB
 | 
			
		||||
    (2097152 sectors) inclusive.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ii) Status
 | 
			
		||||
 | 
			
		||||
    <transaction id> <used metadata blocks>/<total metadata blocks>
 | 
			
		||||
    <used data blocks>/<total data blocks> <held metadata root>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    transaction id:
 | 
			
		||||
	A 64-bit number used by userspace to help synchronise with metadata
 | 
			
		||||
	from volume managers.
 | 
			
		||||
 | 
			
		||||
    used data blocks / total data blocks
 | 
			
		||||
	If the number of free blocks drops below the pool's low water mark a
 | 
			
		||||
	dm event will be sent to userspace.  This event is edge-triggered and
 | 
			
		||||
	it will occur only once after each resume so volume manager writers
 | 
			
		||||
	should register for the event and then check the target's status.
 | 
			
		||||
 | 
			
		||||
    held metadata root:
 | 
			
		||||
	The location, in sectors, of the metadata root that has been
 | 
			
		||||
	'held' for userspace read access.  '-' indicates there is no
 | 
			
		||||
	held root.  This feature is not yet implemented so '-' is
 | 
			
		||||
	always returned.
 | 
			
		||||
 | 
			
		||||
iii) Messages
 | 
			
		||||
 | 
			
		||||
    create_thin <dev id>
 | 
			
		||||
 | 
			
		||||
	Create a new thinly-provisioned device.
 | 
			
		||||
	<dev id> is an arbitrary unique 24-bit identifier chosen by
 | 
			
		||||
	the caller.
 | 
			
		||||
 | 
			
		||||
    create_snap <dev id> <origin id>
 | 
			
		||||
 | 
			
		||||
	Create a new snapshot of another thinly-provisioned device.
 | 
			
		||||
	<dev id> is an arbitrary unique 24-bit identifier chosen by
 | 
			
		||||
	the caller.
 | 
			
		||||
	<origin id> is the identifier of the thinly-provisioned device
 | 
			
		||||
	of which the new device will be a snapshot.
 | 
			
		||||
 | 
			
		||||
    delete <dev id>
 | 
			
		||||
 | 
			
		||||
	Deletes a thin device.  Irreversible.
 | 
			
		||||
 | 
			
		||||
    trim <dev id> <new size in sectors>
 | 
			
		||||
 | 
			
		||||
	Delete mappings from the end of a thin device.  Irreversible.
 | 
			
		||||
	You might want to use this if you're reducing the size of
 | 
			
		||||
	your thinly-provisioned device.  In many cases, due to the
 | 
			
		||||
	sharing of blocks between devices, it is not possible to
 | 
			
		||||
	determine in advance how much space 'trim' will release.  (In
 | 
			
		||||
	future a userspace tool might be able to perform this
 | 
			
		||||
	calculation.)
 | 
			
		||||
 | 
			
		||||
    set_transaction_id <current id> <new id>
 | 
			
		||||
 | 
			
		||||
	Userland volume managers, such as LVM, need a way to
 | 
			
		||||
	synchronise their external metadata with the internal metadata of the
 | 
			
		||||
	pool target.  The thin-pool target offers to store an
 | 
			
		||||
	arbitrary 64-bit transaction id and return it on the target's
 | 
			
		||||
	status line.  To avoid races you must provide what you think
 | 
			
		||||
	the current transaction id is when you change it with this
 | 
			
		||||
	compare-and-swap message.
 | 
			
		||||
 | 
			
		||||
'thin' target
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
i) Constructor
 | 
			
		||||
 | 
			
		||||
    thin <pool dev> <dev id>
 | 
			
		||||
 | 
			
		||||
    pool dev:
 | 
			
		||||
	the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
 | 
			
		||||
 | 
			
		||||
    dev id:
 | 
			
		||||
	the internal device identifier of the device to be
 | 
			
		||||
	activated.
 | 
			
		||||
 | 
			
		||||
The pool doesn't store any size against the thin devices.  If you
 | 
			
		||||
load a thin target that is smaller than you've been using previously,
 | 
			
		||||
then you'll have no access to blocks mapped beyond the end.  If you
 | 
			
		||||
load a target that is bigger than before, then extra blocks will be
 | 
			
		||||
provisioned as and when needed.
 | 
			
		||||
 | 
			
		||||
If you wish to reduce the size of your thin device and potentially
 | 
			
		||||
regain some space then send the 'trim' message to the pool.
 | 
			
		||||
 | 
			
		||||
ii) Status
 | 
			
		||||
 | 
			
		||||
     <nr mapped sectors> <highest mapped sector>
 | 
			
		||||
							
								
								
									
										97
									
								
								doc/kernel/uevent.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								doc/kernel/uevent.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
The device-mapper uevent code adds the capability to device-mapper to create
 | 
			
		||||
and send kobject uevents (uevents).  Previously device-mapper events were only
 | 
			
		||||
available through the ioctl interface.  The advantage of the uevents interface
 | 
			
		||||
is the event contains environment attributes providing increased context for
 | 
			
		||||
the event avoiding the need to query the state of the device-mapper device after
 | 
			
		||||
the event is received.
 | 
			
		||||
 | 
			
		||||
There are two functions currently for device-mapper events.  The first function
 | 
			
		||||
listed creates the event and the second function sends the event(s).
 | 
			
		||||
 | 
			
		||||
void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
 | 
			
		||||
                    const char *path, unsigned nr_valid_paths)
 | 
			
		||||
 | 
			
		||||
void dm_send_uevents(struct list_head *events, struct kobject *kobj)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The variables added to the uevent environment are:
 | 
			
		||||
 | 
			
		||||
Variable Name: DM_TARGET
 | 
			
		||||
Uevent Action(s): KOBJ_CHANGE
 | 
			
		||||
Type: string
 | 
			
		||||
Description:
 | 
			
		||||
Value: Name of device-mapper target that generated the event.
 | 
			
		||||
 | 
			
		||||
Variable Name: DM_ACTION
 | 
			
		||||
Uevent Action(s): KOBJ_CHANGE
 | 
			
		||||
Type: string
 | 
			
		||||
Description:
 | 
			
		||||
Value: Device-mapper specific action that caused the uevent action.
 | 
			
		||||
	PATH_FAILED - A path has failed.
 | 
			
		||||
	PATH_REINSTATED - A path has been reinstated.
 | 
			
		||||
 | 
			
		||||
Variable Name: DM_SEQNUM
 | 
			
		||||
Uevent Action(s): KOBJ_CHANGE
 | 
			
		||||
Type: unsigned integer
 | 
			
		||||
Description: A sequence number for this specific device-mapper device.
 | 
			
		||||
Value: Valid unsigned integer range.
 | 
			
		||||
 | 
			
		||||
Variable Name: DM_PATH
 | 
			
		||||
Uevent Action(s): KOBJ_CHANGE
 | 
			
		||||
Type: string
 | 
			
		||||
Description: Major and minor number of the path device pertaining to this
 | 
			
		||||
event.
 | 
			
		||||
Value: Path name in the form of "Major:Minor"
 | 
			
		||||
 | 
			
		||||
Variable Name: DM_NR_VALID_PATHS
 | 
			
		||||
Uevent Action(s): KOBJ_CHANGE
 | 
			
		||||
Type: unsigned integer
 | 
			
		||||
Description:
 | 
			
		||||
Value: Valid unsigned integer range.
 | 
			
		||||
 | 
			
		||||
Variable Name: DM_NAME
 | 
			
		||||
Uevent Action(s): KOBJ_CHANGE
 | 
			
		||||
Type: string
 | 
			
		||||
Description: Name of the device-mapper device.
 | 
			
		||||
Value: Name
 | 
			
		||||
 | 
			
		||||
Variable Name: DM_UUID
 | 
			
		||||
Uevent Action(s): KOBJ_CHANGE
 | 
			
		||||
Type: string
 | 
			
		||||
Description: UUID of the device-mapper device.
 | 
			
		||||
Value: UUID. (Empty string if there isn't one.)
 | 
			
		||||
 | 
			
		||||
An example of the uevents generated as captured by udevmonitor is shown
 | 
			
		||||
below.
 | 
			
		||||
 | 
			
		||||
1.) Path failure.
 | 
			
		||||
UEVENT[1192521009.711215] change@/block/dm-3
 | 
			
		||||
ACTION=change
 | 
			
		||||
DEVPATH=/block/dm-3
 | 
			
		||||
SUBSYSTEM=block
 | 
			
		||||
DM_TARGET=multipath
 | 
			
		||||
DM_ACTION=PATH_FAILED
 | 
			
		||||
DM_SEQNUM=1
 | 
			
		||||
DM_PATH=8:32
 | 
			
		||||
DM_NR_VALID_PATHS=0
 | 
			
		||||
DM_NAME=mpath2
 | 
			
		||||
DM_UUID=mpath-35333333000002328
 | 
			
		||||
MINOR=3
 | 
			
		||||
MAJOR=253
 | 
			
		||||
SEQNUM=1130
 | 
			
		||||
 | 
			
		||||
2.) Path reinstate.
 | 
			
		||||
UEVENT[1192521132.989927] change@/block/dm-3
 | 
			
		||||
ACTION=change
 | 
			
		||||
DEVPATH=/block/dm-3
 | 
			
		||||
SUBSYSTEM=block
 | 
			
		||||
DM_TARGET=multipath
 | 
			
		||||
DM_ACTION=PATH_REINSTATED
 | 
			
		||||
DM_SEQNUM=2
 | 
			
		||||
DM_PATH=8:32
 | 
			
		||||
DM_NR_VALID_PATHS=1
 | 
			
		||||
DM_NAME=mpath2
 | 
			
		||||
DM_UUID=mpath-35333333000002328
 | 
			
		||||
MINOR=3
 | 
			
		||||
MAJOR=253
 | 
			
		||||
SEQNUM=1131
 | 
			
		||||
							
								
								
									
										37
									
								
								doc/kernel/zero.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								doc/kernel/zero.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
dm-zero
 | 
			
		||||
=======
 | 
			
		||||
 | 
			
		||||
Device-Mapper's "zero" target provides a block-device that always returns
 | 
			
		||||
zero'd data on reads and silently drops writes. This is similar behavior to
 | 
			
		||||
/dev/zero, but as a block-device instead of a character-device.
 | 
			
		||||
 | 
			
		||||
Dm-zero has no target-specific parameters.
 | 
			
		||||
 | 
			
		||||
One very interesting use of dm-zero is for creating "sparse" devices in
 | 
			
		||||
conjunction with dm-snapshot. A sparse device reports a device-size larger
 | 
			
		||||
than the amount of actual storage space available for that device. A user can
 | 
			
		||||
write data anywhere within the sparse device and read it back like a normal
 | 
			
		||||
device. Reads to previously unwritten areas will return a zero'd buffer. When
 | 
			
		||||
enough data has been written to fill up the actual storage space, the sparse
 | 
			
		||||
device is deactivated. This can be very useful for testing device and
 | 
			
		||||
filesystem limitations.
 | 
			
		||||
 | 
			
		||||
To create a sparse device, start by creating a dm-zero device that's the
 | 
			
		||||
desired size of the sparse device. For this example, we'll assume a 10TB
 | 
			
		||||
sparse device.
 | 
			
		||||
 | 
			
		||||
TEN_TERABYTES=`expr 10 \* 1024 \* 1024 \* 1024 \* 2`   # 10 TB in sectors
 | 
			
		||||
echo "0 $TEN_TERABYTES zero" | dmsetup create zero1
 | 
			
		||||
 | 
			
		||||
Then create a snapshot of the zero device, using any available block-device as
 | 
			
		||||
the COW device. The size of the COW device will determine the amount of real
 | 
			
		||||
space available to the sparse device. For this example, we'll assume /dev/sdb1
 | 
			
		||||
is an available 10GB partition.
 | 
			
		||||
 | 
			
		||||
echo "0 $TEN_TERABYTES snapshot /dev/mapper/zero1 /dev/sdb1 p 128" | \
 | 
			
		||||
   dmsetup create sparse1
 | 
			
		||||
 | 
			
		||||
This will create a 10TB sparse device called /dev/mapper/sparse1 that has
 | 
			
		||||
10GB of actual storage space available. If more than 10GB of data is written
 | 
			
		||||
to this device, it will start returning I/O errors.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										475
									
								
								doc/lvm2-raid.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										475
									
								
								doc/lvm2-raid.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,475 @@
 | 
			
		||||
=======================
 | 
			
		||||
= LVM RAID Design Doc =
 | 
			
		||||
=======================
 | 
			
		||||
 | 
			
		||||
#############################
 | 
			
		||||
# Chapter 1: User-Interface #
 | 
			
		||||
#############################
 | 
			
		||||
 | 
			
		||||
***************** CREATING A RAID DEVICE ******************
 | 
			
		||||
 | 
			
		||||
01: lvcreate --type <RAID type> \
 | 
			
		||||
02:	     [--regionsize <size>] \
 | 
			
		||||
03:	     [-i/--stripes <#>] [-I,--stripesize <size>] \
 | 
			
		||||
04:	     [-m/--mirrors <#>] \
 | 
			
		||||
05:	     [--[min|max]recoveryrate <kB/sec/disk>] \
 | 
			
		||||
06:	     [--stripecache <size>] \
 | 
			
		||||
07:	     [--writemostly <devices>] \
 | 
			
		||||
08:	     [--maxwritebehind <size>] \
 | 
			
		||||
09:	     [[no]sync] \
 | 
			
		||||
10:	     <Other normal args, like: -L 5G -n lv vg> \
 | 
			
		||||
11:	     [devices]
 | 
			
		||||
 | 
			
		||||
Line 01:
 | 
			
		||||
I don't intend for there to be shorthand options for specifying the
 | 
			
		||||
segment type.  The available RAID types are:
 | 
			
		||||
	"raid0"  - Stripe [NOT IMPLEMENTED]
 | 
			
		||||
	"raid1"  - should replace DM Mirroring
 | 
			
		||||
	"raid10" - striped mirrors, [NOT IMPLEMENTED]
 | 
			
		||||
	"raid4"  - RAID4
 | 
			
		||||
	"raid5"  - Same as "raid5_ls" (Same default as MD)
 | 
			
		||||
	"raid5_la" - RAID5 Rotating parity 0 with data continuation
 | 
			
		||||
	"raid5_ra" - RAID5 Rotating parity N with data continuation
 | 
			
		||||
	"raid5_ls" - RAID5 Rotating parity 0 with data restart
 | 
			
		||||
	"raid5_rs" - RAID5 Rotating parity N with data restart
 | 
			
		||||
	"raid6"    - Same as "raid6_zr"
 | 
			
		||||
	"raid6_zr" - RAID6 Rotating parity 0 with data restart
 | 
			
		||||
	"raid6_nr" - RAID6 Rotating parity N with data restart
 | 
			
		||||
	"raid6_nc" - RAID6 Rotating parity N with data continuation
 | 
			
		||||
The exception to 'no shorthand options' will be where the RAID implementations
 | 
			
		||||
can displace traditional tagets.  This is the case with 'mirror' and 'raid1'.
 | 
			
		||||
In this case, "mirror_segtype_default" - found under the "global" section in
 | 
			
		||||
lvm.conf - can be set to "mirror" or "raid1".  The segment type inferred when
 | 
			
		||||
the '-m' option is used will be taken from this setting.  The default segment
 | 
			
		||||
types can be overridden on the command line by using the '--type' argument.
 | 
			
		||||
 | 
			
		||||
Line 02:
 | 
			
		||||
Region size is relevant for all RAID types.  It defines the granularity for
 | 
			
		||||
which the bitmap will track the active areas of disk.  The default is currently
 | 
			
		||||
4MiB.  I see no reason to change this unless it is a problem for MD performance.
 | 
			
		||||
MD does impose a restriction of 2^21 regions for a given device, however.  This
 | 
			
		||||
means two things: 1) we should never need a metadata area larger than
 | 
			
		||||
8kiB+sizeof(superblock)+bitmap_offset (IOW, pretty small) and 2) the region
 | 
			
		||||
size will have to be upwardly revised if the device is larger than 8TiB
 | 
			
		||||
(assuming defaults).
 | 
			
		||||
 | 
			
		||||
Line 03/04:
 | 
			
		||||
The '-m/--mirrors' option is only relevant to RAID1 and will be used just like
 | 
			
		||||
it is today for DM mirroring.  For all other RAID types, -i/--stripes and
 | 
			
		||||
-I/--stripesize are relevant.  The former will specify the number of data
 | 
			
		||||
devices that will be used for striping.  For example, if the user specifies
 | 
			
		||||
'--type raid0 -i 3', then 3 devices are needed.  If the user specifies
 | 
			
		||||
'--type raid6 -i 3', then 5 devices are needed.  The -I/--stripesize may be
 | 
			
		||||
confusing to MD users, as they use the term "chunksize".  I think they will
 | 
			
		||||
adapt without issue and I don't wish to create a conflict with the term
 | 
			
		||||
"chunksize" that we use for snapshots.
 | 
			
		||||
 | 
			
		||||
Line 05/06/07:
 | 
			
		||||
I'm still not clear on how to specify these options.  Some are easier than
 | 
			
		||||
others.  '--writemostly' is particularly hard because it involves specifying
 | 
			
		||||
which devices shall be 'write-mostly' and thus, also have 'max-write-behind'
 | 
			
		||||
applied to them.  It has been suggested that a '--readmostly'/'--readfavored'
 | 
			
		||||
or similar option could be introduced as a way to specify a primary disk vs.
 | 
			
		||||
specifying all the non-primary disks via '--writemostly'.  I like this idea,
 | 
			
		||||
but haven't come up with a good name yet.  Thus, these will remain
 | 
			
		||||
unimplemented until future specification.
 | 
			
		||||
 | 
			
		||||
Line 09/10/11:
 | 
			
		||||
These are familiar.
 | 
			
		||||
 | 
			
		||||
Further creation related ideas:
 | 
			
		||||
Today, you can specify '--type mirror' without an '-m/--mirrors' argument
 | 
			
		||||
necessary.  The number of devices defaults to two (and the log defaults to
 | 
			
		||||
'disk').  A similar thing should happen with the RAID types.  All of them
 | 
			
		||||
should default to having two data devices unless otherwise specified.  This
 | 
			
		||||
would mean a total number of 2 devices for RAID 0/1, 3 devices for RAID 4/5,
 | 
			
		||||
and 4 devices for RAID 6/10.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
***************** CONVERTING A RAID DEVICE ******************
 | 
			
		||||
 | 
			
		||||
01: lvconvert [--type <RAID type>] \
 | 
			
		||||
02:	      [-R/--regionsize <size>] \
 | 
			
		||||
03:	      [-i/--stripes <#>] [-I,--stripesize <size>] \
 | 
			
		||||
04:	      [-m/--mirrors <#>] \
 | 
			
		||||
05:	      [--merge]
 | 
			
		||||
06:	      [--splitmirrors <#> [--trackchanges]] \
 | 
			
		||||
07:	      [--replace <sub_lv|device>] \
 | 
			
		||||
08:	      [--[min|max]recoveryrate <kB/sec/disk>] \
 | 
			
		||||
09:	      [--stripecache <size>] \
 | 
			
		||||
10:	      [--writemostly <devices>] \
 | 
			
		||||
11:	      [--maxwritebehind <size>] \
 | 
			
		||||
12:	      vg/lv
 | 
			
		||||
13:	      [devices]
 | 
			
		||||
 | 
			
		||||
lvconvert should work exactly as it does now when dealing with mirrors -
 | 
			
		||||
even if(when) we switch to MD RAID1.  Of course, there are no plans to
 | 
			
		||||
allow the presense of the metadata area to be configurable (e.g. --corelog).
 | 
			
		||||
It will be simple enough to detect if the LV being up/down-converted is
 | 
			
		||||
new or old-style mirroring.
 | 
			
		||||
 | 
			
		||||
If we choose to use MD RAID0 as well, it will be possible to change the
 | 
			
		||||
number of stripes and the stripesize.  It is therefore conceivable to see
 | 
			
		||||
something like, 'lvconvert -i +1 vg/lv'.
 | 
			
		||||
 | 
			
		||||
Line 01:
 | 
			
		||||
It is possible to change the RAID type of an LV - even if that LV is already
 | 
			
		||||
a RAID device of a different type.  For example, you could change from
 | 
			
		||||
RAID4 to RAID5 or RAID5 to RAID6.
 | 
			
		||||
 | 
			
		||||
Line 02/03/04:
 | 
			
		||||
These are familiar options - all of which would now be available as options
 | 
			
		||||
for change.  (However, it'd be nice if we didn't have regionsize in there.
 | 
			
		||||
It's simple on the kernel side, but is just an extra - often unecessary -
 | 
			
		||||
parameter to many functions in the LVM codebase.)
 | 
			
		||||
 | 
			
		||||
Line 05:
 | 
			
		||||
This option is used to merge an LV back into a RAID1 array - provided it was
 | 
			
		||||
split for temporary read-only use by '--splitmirrors 1 --trackchanges'.
 | 
			
		||||
 | 
			
		||||
Line 06:
 | 
			
		||||
The '--splitmirrors <#>' argument should be familiar from the "mirror" segment
 | 
			
		||||
type.  It allows RAID1 images to be split from the array to form a new LV.
 | 
			
		||||
Either the original LV or the split LV - or both - could become a linear LV as
 | 
			
		||||
a result.  If the '--trackchanges' argument is specified in addition to
 | 
			
		||||
'--splitmirrors', an LV will be split from the array.  It will be read-only.
 | 
			
		||||
This operation does not change the original array - except that it uses an empty
 | 
			
		||||
slot to hold the position of the split LV which it expects to return in the
 | 
			
		||||
future (see the '--merge' argument).  It tracks any changes that occur to the
 | 
			
		||||
array while the slot is kept in reserve.  If the LV is merged back into the
 | 
			
		||||
array, only the changes are resync'ed to the returning image.  Repeating the
 | 
			
		||||
'lvconvert' operation without the '--trackchanges' option will complete the
 | 
			
		||||
split of the LV permanently.
 | 
			
		||||
 | 
			
		||||
Line 07:
 | 
			
		||||
This option allows the user to specify a sub_lv (e.g. a mirror image) or
 | 
			
		||||
a particular device for replacement.  The device (or all the devices in
 | 
			
		||||
the sub_lv) will be removed and replaced with different devices from the
 | 
			
		||||
VG.
 | 
			
		||||
 | 
			
		||||
Line 08/09/10/11:
 | 
			
		||||
It should be possible to alter these parameters of a RAID device.  As with
 | 
			
		||||
lvcreate, however, I'm not entirely certain how to best define some of these.
 | 
			
		||||
We don't need all the capabilities at once though, so it isn't a pressing
 | 
			
		||||
issue.
 | 
			
		||||
 | 
			
		||||
Line 12:
 | 
			
		||||
The LV to operate on.
 | 
			
		||||
 | 
			
		||||
Line 13:
 | 
			
		||||
Devices that are to be used to satisfy the conversion request.  If the
 | 
			
		||||
operation removes devices or splits a mirror, then the devices specified
 | 
			
		||||
form the list of candidates for removal.  If the operation adds or replaces
 | 
			
		||||
devices, then the devices specified form the list of candidates for allocation.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###############################################
 | 
			
		||||
# Chapter 2: LVM RAID internal representation #
 | 
			
		||||
###############################################
 | 
			
		||||
 | 
			
		||||
The internal representation is somewhat like mirroring, but with alterations
 | 
			
		||||
for the different metadata components.  LVM mirroring has a single log LV,
 | 
			
		||||
but RAID will have one for each data device.  Because of this, I've added a
 | 
			
		||||
new 'areas' list to the 'struct lv_segment' - 'meta_areas'.  There is exactly
 | 
			
		||||
a one-to-one relationship between 'areas' and 'meta_areas'.  The 'areas' array
 | 
			
		||||
still holds the data sub-lv's (similar to mirroring), while the 'meta_areas'
 | 
			
		||||
array holds the metadata sub-lv's (akin to the mirroring log device).
 | 
			
		||||
 | 
			
		||||
The sub_lvs will be named '%s_rimage_%d' instead of '%s_mimage_%d' as it is
 | 
			
		||||
for mirroring, and '%s_rmeta_%d' instead of '%s_mlog'.  Thus, you can imagine
 | 
			
		||||
an LV named 'foo' with the following layout:
 | 
			
		||||
foo
 | 
			
		||||
[foo's lv_segment]
 | 
			
		||||
|
 | 
			
		||||
|-> foo_rimage_0 (areas[0])
 | 
			
		||||
|   [foo_rimage_0's lv_segment]
 | 
			
		||||
|-> foo_rimage_1 (areas[1])
 | 
			
		||||
|   [foo_rimage_1's lv_segment]
 | 
			
		||||
|
 | 
			
		||||
|-> foo_rmeta_0 (meta_areas[0])
 | 
			
		||||
|   [foo_rmeta_0's lv_segment]
 | 
			
		||||
|-> foo_rmeta_1 (meta_areas[1])
 | 
			
		||||
|   [foo_rmeta_1's lv_segment]
 | 
			
		||||
 | 
			
		||||
LVM Meta-data format
 | 
			
		||||
====================
 | 
			
		||||
The RAID format will need to be able to store parameters that are unique to
 | 
			
		||||
RAID and unique to specific RAID sub-devices.  It will be modeled after that
 | 
			
		||||
of mirroring.
 | 
			
		||||
 | 
			
		||||
Here is an example of the mirroring layout:
 | 
			
		||||
lv {
 | 
			
		||||
	id = "agL1vP-1B8Z-5vnB-41cS-lhBJ-Gcvz-dh3L3H"
 | 
			
		||||
	status = ["READ", "WRITE", "VISIBLE"]
 | 
			
		||||
	flags = []
 | 
			
		||||
	segment_count = 1
 | 
			
		||||
 | 
			
		||||
	segment1 {
 | 
			
		||||
		start_extent = 0
 | 
			
		||||
		extent_count = 125      # 500 Megabytes
 | 
			
		||||
 | 
			
		||||
		type = "mirror"
 | 
			
		||||
		mirror_count = 2
 | 
			
		||||
		mirror_log = "lv_mlog"
 | 
			
		||||
		region_size = 1024
 | 
			
		||||
 | 
			
		||||
		mirrors = [
 | 
			
		||||
			"lv_mimage_0", 0,
 | 
			
		||||
			"lv_mimage_1", 0
 | 
			
		||||
		]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
The real trick is dealing with the metadata devices.  Mirroring has an entry,
 | 
			
		||||
'mirror_log', in the top-level segment.  This won't work for RAID because there
 | 
			
		||||
is a one-to-one mapping between the data devices and the metadata devices.  The
 | 
			
		||||
mirror devices are layed-out in sub-device/le pairs.  The 'le' parameter is
 | 
			
		||||
redundant since it will always be zero.  So for RAID, I have simple put the
 | 
			
		||||
metadata and data devices in pairs without the 'le' parameter.
 | 
			
		||||
 | 
			
		||||
RAID metadata:
 | 
			
		||||
lv {
 | 
			
		||||
	id = "EnpqAM-5PEg-i9wB-5amn-P116-1T8k-nS3GfD"
 | 
			
		||||
	status = ["READ", "WRITE", "VISIBLE"]
 | 
			
		||||
	flags = []
 | 
			
		||||
	segment_count = 1
 | 
			
		||||
 | 
			
		||||
	segment1 {
 | 
			
		||||
		start_extent = 0
 | 
			
		||||
		extent_count = 125      # 500 Megabytes
 | 
			
		||||
 | 
			
		||||
		type = "raid1"
 | 
			
		||||
		device_count = 2
 | 
			
		||||
		region_size = 1024
 | 
			
		||||
 | 
			
		||||
		raids = [
 | 
			
		||||
			"lv_rmeta_0", "lv_rimage_0",
 | 
			
		||||
			"lv_rmeta_1", "lv_rimage_1",
 | 
			
		||||
		]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
The metadata also must be capable of representing the various tunables.  We
 | 
			
		||||
already have a good example for one from mirroring, region_size.
 | 
			
		||||
'max_write_behind', 'stripe_cache', and '[min|max]_recovery_rate' could also
 | 
			
		||||
be handled in this way.  However, 'write_mostly' cannot be handled in this
 | 
			
		||||
way, because it is a characteristic associated with the sub_lvs, not the
 | 
			
		||||
array as a whole.  In these cases, the status field of the sub-lv's themselves
 | 
			
		||||
will hold these flags - the meaning being only useful in the larger context.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##############################################
 | 
			
		||||
# Chapter 3: LVM RAID implementation details #
 | 
			
		||||
##############################################
 | 
			
		||||
 | 
			
		||||
New Segment Type(s)
 | 
			
		||||
===================
 | 
			
		||||
I've created a new file 'lib/raid/raid.c' that will handle the various different
 | 
			
		||||
RAID types.  While there will be a unique segment type for each RAID variant,
 | 
			
		||||
they will all share a common backend - segtype_handler functions and
 | 
			
		||||
segtype->flags = SEG_RAID.
 | 
			
		||||
 | 
			
		||||
I'm also adding a new field to 'struct segment_type', parity_devs.  For every
 | 
			
		||||
segment_type except RAID4/5/6, this will be 0.  This field facilitates in
 | 
			
		||||
allocation and size calculations.  For example, the lvcreate for RAID5 would
 | 
			
		||||
look something like:
 | 
			
		||||
~> lvcreate --type raid5 -L 30G -i 3 -n my_raid5 my_vg
 | 
			
		||||
or
 | 
			
		||||
~> lvcreate --type raid5 -n my_raid5 my_vg /dev/sd[bcdef]1
 | 
			
		||||
 | 
			
		||||
In the former case, the stripe count (3) and device size are computed, and
 | 
			
		||||
then 'segtype->parity_devs' extra devices are allocated of the same size.  In
 | 
			
		||||
the latter case, the number of PVs is determined and 'segtype->parity_devs' is
 | 
			
		||||
subtracted off to determine the number of stripes.
 | 
			
		||||
 | 
			
		||||
This should also work in the case of RAID10 and doing things in this manor
 | 
			
		||||
should not affect the way size is calculated via the area_multiple.
 | 
			
		||||
 | 
			
		||||
Allocation
 | 
			
		||||
==========
 | 
			
		||||
When a RAID device is created, metadata LVs must be created along with the
 | 
			
		||||
data LVs that will ultimately compose the top-level RAID array.  For the
 | 
			
		||||
foreseeable future, the metadata LVs must reside on the same device as (or
 | 
			
		||||
at least one of the devices that compose) the data LV.  We use this property
 | 
			
		||||
to simplify the allocation process.  Rather than allocating for the data LVs
 | 
			
		||||
and then asking for a small chunk of space on the same device (or the other
 | 
			
		||||
way around), we simply ask for the aggregate size of the data LV plus the
 | 
			
		||||
metadata LV.  Once we have the space allocated, we divide it between the
 | 
			
		||||
metadata and data LVs.  This also greatly simplifies the process of finding
 | 
			
		||||
parallel space for all the data LVs that will compose the RAID array.  When
 | 
			
		||||
a RAID device is resized, we will not need to take the metadata LV into
 | 
			
		||||
account, because it will already be present.
 | 
			
		||||
 | 
			
		||||
Apart from the metadata areas, the other unique characteristic of RAID
 | 
			
		||||
devices is the parity device count.  The number of parity devices does nothing
 | 
			
		||||
to the calculation of size-per-device.  The 'area_multiple' means nothing
 | 
			
		||||
here.  The parity devices will simply be the same size as all the other devices
 | 
			
		||||
and will also require a metadata LV (i.e. it is treated no differently than
 | 
			
		||||
the other devices).
 | 
			
		||||
 | 
			
		||||
Therefore, to allocate space for RAID devices, we need to know two things:
 | 
			
		||||
1) how many parity devices are required and 2) does an allocated area need to
 | 
			
		||||
be split out for the metadata LVs after finding the space to fill the request.
 | 
			
		||||
We simply add these two fields to the 'alloc_handle' data structure as,
 | 
			
		||||
'parity_count' and 'alloc_and_split_meta'.  These two fields get set in
 | 
			
		||||
'_alloc_init'.   The 'segtype->parity_devs' holds the number of parity
 | 
			
		||||
drives and can be directly copied to 'ah->parity_count' and
 | 
			
		||||
'alloc_and_split_meta' is set when a RAID segtype is detected and
 | 
			
		||||
'metadata_area_count' has been specified.  With these two variables set, we
 | 
			
		||||
can calculate how many allocated areas we need.  Also, in the routines that
 | 
			
		||||
find the actual space, they stop not when they have found ah->area_count but
 | 
			
		||||
when they have found (ah->area_count + ah->parity_count).
 | 
			
		||||
 | 
			
		||||
Conversion
 | 
			
		||||
==========
 | 
			
		||||
RAID -> RAID, adding images
 | 
			
		||||
---------------------------
 | 
			
		||||
When adding images to a RAID array, metadata and data components must be added
 | 
			
		||||
as a pair.  It is best to perform as many operations as possible before writing
 | 
			
		||||
new LVM metadata.  This allows us to error-out without having to unwind any
 | 
			
		||||
changes.  It also makes things easier if the machine should crash during a
 | 
			
		||||
conversion operation.  Thus, the actions performed when adding a new image are:
 | 
			
		||||
        1) Allocate the required number of metadata/data pairs using the method
 | 
			
		||||
	   describe above in 'Allocation' (i.e. find the metadata/data space
 | 
			
		||||
	   as one unit and split the space between them after found - this keeps
 | 
			
		||||
	   them together on the same device).
 | 
			
		||||
	2) Form the metadata/data LVs from the allocated space (leave them
 | 
			
		||||
	   visible) - setting required RAID_[IMAGE | META] flags as appropriate.
 | 
			
		||||
	3) Write the LVM metadata
 | 
			
		||||
	4) Activate and clear the metadata LVs.  The clearing of the metadata
 | 
			
		||||
	   requires the LVM metadata be written (step 3) and is a requirement
 | 
			
		||||
	   before adding the new metadata LVs to the array.  If the metadata
 | 
			
		||||
	   is not cleared, it carry residual superblock state from a previous
 | 
			
		||||
	   array the device may have been part of.
 | 
			
		||||
	5) Deactivate new sub-LVs and set them "hidden".
 | 
			
		||||
	6) expand the 'first_seg(raid_lv)->areas' and '->meta_areas' array
 | 
			
		||||
	   for inclusion of the new sub-LVs
 | 
			
		||||
	7) Add new sub-LVs and update 'first_seg(raid_lv)->area_count'
 | 
			
		||||
	8) Commit new LVM metadata
 | 
			
		||||
Failure during any of these steps will not affect the original RAID array.  In
 | 
			
		||||
the worst scenario, the user may have to remove the new sub-LVs that did not
 | 
			
		||||
yet make it into the array.
 | 
			
		||||
 | 
			
		||||
RAID -> RAID, removing images
 | 
			
		||||
-----------------------------
 | 
			
		||||
To remove images from a RAID, the metadata/data LV pairs must be removed
 | 
			
		||||
together.  This is pretty straight-forward, but one place where RAID really
 | 
			
		||||
differs from the "mirror" segment type is how the resulting "holes" are filled.
 | 
			
		||||
When a device is removed from a "mirror" segment type, it is identified, moved
 | 
			
		||||
to the end of the 'mirrored_seg->areas' array, and then removed.  This action
 | 
			
		||||
causes the other images to shift down and fill the position of the device which
 | 
			
		||||
was removed.  While "raid1" could be handled in this way, the other RAID types
 | 
			
		||||
could not be - it would corrupt the ordering of the data on the array.  Thus,
 | 
			
		||||
when a device is removed from a RAID array, the corresponding metadata/data
 | 
			
		||||
sub-LVs are removed from the 'raid_seg->meta_areas' and 'raid_seg->areas' arrays.
 | 
			
		||||
The slot in these 'lv_segment_area' arrays are set to 'AREA_UNASSIGNED'.  RAID
 | 
			
		||||
is perfectly happy to construct a DM table mapping with '- -' if it comes across
 | 
			
		||||
area assigned in such a way.  The pair of dashes is a valid way to tell the RAID
 | 
			
		||||
kernel target that the slot should be considered empty.  So, we can remove
 | 
			
		||||
devices from a RAID array without affecting the correct operation of the RAID.
 | 
			
		||||
(It also becomes easy to replace the empty slots properly if a spare device is
 | 
			
		||||
available.)  In the case of RAID1 device removal, the empty slot can be safely
 | 
			
		||||
eliminated.  This is done by shifting the higher indexed devices down to fill
 | 
			
		||||
the slot.  Even the names of the images will be renamed to properly reflect
 | 
			
		||||
their index in the array.  Unlike the "mirror" segment type, you will never have
 | 
			
		||||
an image named "*_rimage_1" occupying the index position 0.
 | 
			
		||||
 | 
			
		||||
As with adding images, removing images holds off on commiting LVM metadata
 | 
			
		||||
until all possible changes have been made.  This reduces the likelyhood of bad
 | 
			
		||||
intermediate stages being left due to a failure of operation or machine crash.
 | 
			
		||||
 | 
			
		||||
RAID1 '--splitmirrors', '--trackchanges', and '--merge' operations
 | 
			
		||||
------------------------------------------------------------------
 | 
			
		||||
This suite of operations is only available to the "raid1" segment type.
 | 
			
		||||
 | 
			
		||||
Splitting an image from a RAID1 array is almost identical to the removal of
 | 
			
		||||
an image described above.  However, the metadata LV associated with the split
 | 
			
		||||
image is removed and the data LV is kept and promoted to a top-level device.
 | 
			
		||||
(i.e.  It is made visible and stripped of its RAID_IMAGE status flags.)
 | 
			
		||||
 | 
			
		||||
When the '--trackchanges' option is given along with the '--splitmirrors'
 | 
			
		||||
argument, the metadata LV is left as part of the original array.  The data LV
 | 
			
		||||
is set as 'VISIBLE' and read-only (~LVM_WRITE).  When the array DM table is
 | 
			
		||||
being created, it notices the read-only, VISIBLE nature of the sub-LV and puts
 | 
			
		||||
in the '- -' sentinel.  Only a single image can be split from the mirror and
 | 
			
		||||
the name of the sub-LV cannot be changed.  Unlike '--splitmirrors' on its own,
 | 
			
		||||
the '--name' argument must not be specified.  Therefore, the name of the newly
 | 
			
		||||
split LV will remain the same '<lv>_rimage_<N>', where 'N' is the index of the
 | 
			
		||||
slot in the array for which it is associated.
 | 
			
		||||
 | 
			
		||||
When an LV which was split from a RAID1 array with the '--trackchanges' option
 | 
			
		||||
is merged back into the array, its read/write status is restored and it is
 | 
			
		||||
set as "hidden" again.  Recycling the array (suspend/resume) restores the sub-LV
 | 
			
		||||
to its position in the array and begins the process of sync'ing the changes that
 | 
			
		||||
were made since the time it was split from the array.
 | 
			
		||||
 | 
			
		||||
RAID device replacement with '--replace'
 | 
			
		||||
----------------------------------------
 | 
			
		||||
This option is available to all RAID segment types.
 | 
			
		||||
 | 
			
		||||
The '--replace' option can be used to remove a particular device from a RAID
 | 
			
		||||
logical volume and replace it with a different one in one action (CLI command).
 | 
			
		||||
The device device to be removed is specified as the argument to the '--replace'
 | 
			
		||||
option.  This option can be specified more than once in a single command,
 | 
			
		||||
allowing multiple devices to be replaced at the same time - provided the RAID
 | 
			
		||||
logical volume has the necessary redundancy to allow the action.  The devices
 | 
			
		||||
to be used as replacements can also be specified in the command; similar to the
 | 
			
		||||
way allocatable devices are specified during an up-convert.
 | 
			
		||||
 | 
			
		||||
Example> lvconvert --replace /dev/sdd1 --replace /dev/sde1 vg/lv /dev/sd[bc]1
 | 
			
		||||
 | 
			
		||||
RAID '--repair'
 | 
			
		||||
---------------
 | 
			
		||||
This 'lvconvert' option is available to all RAID segment types and is described
 | 
			
		||||
under "RAID Fault Handling".
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RAID Fault Handling
 | 
			
		||||
===================
 | 
			
		||||
RAID is not like traditional LVM mirroring (i.e. the "mirror" segment type).
 | 
			
		||||
LVM mirroring required failed devices to be removed or the logical volume would
 | 
			
		||||
simply hang.  RAID arrays can keep on running with failed devices.  In fact, for
 | 
			
		||||
RAID types other than RAID1 removing a device would mean substituting an error
 | 
			
		||||
target or converting to a lower level RAID (e.g. RAID6 -> RAID5, or RAID4/5 to
 | 
			
		||||
RAID0).  Therefore, rather than removing a failed device unconditionally, the
 | 
			
		||||
user has a couple of options to choose from.
 | 
			
		||||
 | 
			
		||||
The automated response to a device failure is handled according to the user's
 | 
			
		||||
preference defined in lvm.conf:activation.raid_fault_policy.  The options are:
 | 
			
		||||
    # "warn"    - Use the system log to warn the user that a device in the RAID
 | 
			
		||||
    #             logical volume has failed.  It is left to the user to run
 | 
			
		||||
    #             'lvconvert --repair' manually to remove or replace the failed
 | 
			
		||||
    #             device.  As long as the number of failed devices does not
 | 
			
		||||
    #             exceed the redundancy of the logical volume (1 device for
 | 
			
		||||
    #             raid4/5, 2 for raid6, etc) the logical volume will remain
 | 
			
		||||
    #             usable.
 | 
			
		||||
    #
 | 
			
		||||
    # "remove"  - NOT CURRENTLY IMPLEMENTED OR DOCUMENTED IN example.conf.in.
 | 
			
		||||
    #             Remove the failed device and reduce the RAID logical volume
 | 
			
		||||
    #             accordingly.  If a single device dies in a 3-way mirror,
 | 
			
		||||
    #             remove it and reduce the mirror to 2-way.  If a single device
 | 
			
		||||
    #             dies in a RAID 4/5 logical volume, reshape it to a striped
 | 
			
		||||
    #             volume, etc - RAID 6 -> RAID 4/5 -> RAID 0.  If devices
 | 
			
		||||
    #             cannot be removed for lack of redundancy, fail.
 | 
			
		||||
    #             THIS OPTION CANNOT YET BE IMPLEMENTED BECAUSE RESHAPE IS NOT
 | 
			
		||||
    #             YET SUPPORTED IN linux/drivers/md/dm-raid.c.  The superblock
 | 
			
		||||
    #             does not yet hold enough information to support reshaping.
 | 
			
		||||
    #
 | 
			
		||||
    # "allocate" - Attempt to use any extra physical volumes in the volume
 | 
			
		||||
    #             group as spares and replace faulty devices.
 | 
			
		||||
 | 
			
		||||
If manual intervention is taken, either in response to the automated solution's
 | 
			
		||||
"warn" mode or simply because dmeventd hadn't run, then the user can call
 | 
			
		||||
'lvconvert --repair vg/lv' and follow the prompts.  They will be prompted
 | 
			
		||||
whether or not to replace the device and cause a full recovery of the failed
 | 
			
		||||
device.
 | 
			
		||||
 | 
			
		||||
If replacement is chosen via the manual method or "allocate" is the policy taken
 | 
			
		||||
by the automated response, then 'lvconvert --replace' is the mechanism used to
 | 
			
		||||
attempt the replacement of the failed device.
 | 
			
		||||
 | 
			
		||||
'vgreduce --removemissing' is ineffectual at repairing RAID logical volumes.  It
 | 
			
		||||
will remove the failed device, but the RAID logical volume will simply continue
 | 
			
		||||
to operate with an <unknown> sub-LV.  The user should clear the failed device
 | 
			
		||||
with 'lvconvert --repair'.
 | 
			
		||||
							
								
								
									
										202
									
								
								doc/lvm_fault_handling.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								doc/lvm_fault_handling.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
			
		||||
LVM device fault handling
 | 
			
		||||
=========================
 | 
			
		||||
 | 
			
		||||
Introduction
 | 
			
		||||
------------
 | 
			
		||||
This document is to serve as the definitive source for information
 | 
			
		||||
regarding the policies and procedures surrounding device failures
 | 
			
		||||
in LVM.  It codifies LVM's responses to device failures as well as
 | 
			
		||||
the responsibilities of administrators.
 | 
			
		||||
 | 
			
		||||
Device failures can be permanent or transient.  A permanent failure
 | 
			
		||||
is one where a device becomes inaccessible and will never be
 | 
			
		||||
revived.  A transient failure is a failure that can be recovered
 | 
			
		||||
from (e.g. a power failure, intermittent network outage, block
 | 
			
		||||
relocation, etc).  The policies for handling both types of failures
 | 
			
		||||
is described herein.
 | 
			
		||||
 | 
			
		||||
Users need to be aware that there are two implementations of RAID1 in LVM.
 | 
			
		||||
The first is defined by the "mirror" segment type.  The second is defined by
 | 
			
		||||
the "raid1" segment type.  The characteristics of each of these are defined
 | 
			
		||||
in lvm.conf under 'mirror_segtype_default' - the configuration setting used to
 | 
			
		||||
identify the default RAID1 implementation used for LVM operations.
 | 
			
		||||
 | 
			
		||||
Available Operations During a Device Failure
 | 
			
		||||
--------------------------------------------
 | 
			
		||||
When there is a device failure, LVM behaves somewhat differently because
 | 
			
		||||
only a subset of the available devices will be found for the particular
 | 
			
		||||
volume group.  The number of operations available to the administrator
 | 
			
		||||
is diminished.  It is not possible to create new logical volumes while
 | 
			
		||||
PVs cannot be accessed, for example.  Operations that create, convert, or
 | 
			
		||||
resize logical volumes are disallowed, such as:
 | 
			
		||||
- lvcreate
 | 
			
		||||
- lvresize
 | 
			
		||||
- lvreduce
 | 
			
		||||
- lvextend
 | 
			
		||||
- lvconvert (unless '--repair' is used)
 | 
			
		||||
Operations that activate, deactivate, remove, report, or repair logical
 | 
			
		||||
volumes are allowed, such as:
 | 
			
		||||
- lvremove
 | 
			
		||||
- vgremove (will remove all LVs, but not the VG until consistent)
 | 
			
		||||
- pvs
 | 
			
		||||
- vgs
 | 
			
		||||
- lvs
 | 
			
		||||
- lvchange -a [yn]
 | 
			
		||||
- vgchange -a [yn]
 | 
			
		||||
Operations specific to the handling of failed devices are allowed and
 | 
			
		||||
are as follows:
 | 
			
		||||
 | 
			
		||||
- 'vgreduce --removemissing <VG>':  This action is designed to remove
 | 
			
		||||
  the reference of a failed device from the LVM metadata stored on the
 | 
			
		||||
  remaining devices.  If there are (portions of) logical volumes on the
 | 
			
		||||
  failed devices, the ability of the operation to proceed will depend
 | 
			
		||||
  on the type of logical volumes found.  If an image (i.e leg or side)
 | 
			
		||||
  of a mirror is located on the device, that image/leg of the mirror
 | 
			
		||||
  is eliminated along with the failed device.  The result of such a
 | 
			
		||||
  mirror reduction could be a no-longer-redundant linear device.  If
 | 
			
		||||
  a linear, stripe, or snapshot device is located on the failed device
 | 
			
		||||
  the command will not proceed without a '--force' option.  The result
 | 
			
		||||
  of using the '--force' option is the entire removal and complete
 | 
			
		||||
  loss of the non-redundant logical volume.  If an image or metadata area
 | 
			
		||||
  of a RAID logical volume is on the failed device, the sub-LV affected is
 | 
			
		||||
  replace with an error target device - appearing as <unknown> in 'lvs'
 | 
			
		||||
  output.  RAID logical volumes cannot be completely repaired by vgreduce -
 | 
			
		||||
  'lvconvert --repair' (listed below) must be used.  Once this operation is
 | 
			
		||||
  complete on volume groups not containing RAID logical volumes, the volume
 | 
			
		||||
  group will again have a complete and consistent view of the devices it
 | 
			
		||||
  contains.  Thus, all operations will be permitted - including creation,
 | 
			
		||||
  conversion, and resizing operations.  It is currently the preferred method
 | 
			
		||||
  to call 'lvconvert --repair' on the individual logical volumes to repair
 | 
			
		||||
  them followed by 'vgreduce --removemissing' to extract the physical volume's
 | 
			
		||||
  representation in the volume group.
 | 
			
		||||
 | 
			
		||||
- 'lvconvert --repair <VG/LV>':  This action is designed specifically
 | 
			
		||||
  to operate on individual logical volumes.  If, for example, a failed
 | 
			
		||||
  device happened to contain the images of four distinct mirrors, it would
 | 
			
		||||
  be necessary to run 'lvconvert --repair' on each of them.  The ultimate
 | 
			
		||||
  result is to leave the faulty device in the volume group, but have no logical
 | 
			
		||||
  volumes referencing it.  (This allows for 'vgreduce --removemissing' to
 | 
			
		||||
  removed the physical volumes cleanly.)  In addition to removing mirror or
 | 
			
		||||
  RAID images that reside on failed devices, 'lvconvert --repair' can also
 | 
			
		||||
  replace the failed device if there are spare devices available in the
 | 
			
		||||
  volume group.  The user is prompted whether to simply remove the failed
 | 
			
		||||
  portions of the mirror or to also allocate a replacement, if run from the
 | 
			
		||||
  command-line.  Optionally, the '--use-policies' flag can be specified which
 | 
			
		||||
  will cause the operation not to prompt the user, but instead respect
 | 
			
		||||
  the policies outlined in the LVM configuration file - usually,
 | 
			
		||||
  /etc/lvm/lvm.conf.  Once this operation is complete, the logical volumes
 | 
			
		||||
  will be consistent.  However, the volume group will still be inconsistent -
 | 
			
		||||
  due to the refernced-but-missing device/PV - and operations will still be
 | 
			
		||||
  restricted to the aformentioned actions until either the device is
 | 
			
		||||
  restored or 'vgreduce --removemissing' is run.
 | 
			
		||||
 | 
			
		||||
Device Revival (transient failures):
 | 
			
		||||
------------------------------------
 | 
			
		||||
During a device failure, the above section describes what limitations
 | 
			
		||||
a user can expect.  However, if the device returns after a period of
 | 
			
		||||
time, what to expect will depend on what has happened during the time
 | 
			
		||||
period when the device was failed.  If no automated actions (described
 | 
			
		||||
below) or user actions were necessary or performed, then no change in
 | 
			
		||||
operations or logical volume layout will occur.  However, if an
 | 
			
		||||
automated action or one of the aforementioned repair commands was
 | 
			
		||||
manually run, the returning device will be perceived as having stale
 | 
			
		||||
LVM metadata.  In this case, the user can expect to see a warning
 | 
			
		||||
concerning inconsistent metadata.  The metadata on the returning
 | 
			
		||||
device will be automatically replaced with the latest copy of the
 | 
			
		||||
LVM metadata - restoring consistency.  Note, while most LVM commands
 | 
			
		||||
will automatically update the metadata on a restored devices, the
 | 
			
		||||
following possible exceptions exist:
 | 
			
		||||
- pvs (when it does not read/update VG metadata)
 | 
			
		||||
 | 
			
		||||
Automated Target Response to Failures:
 | 
			
		||||
--------------------------------------
 | 
			
		||||
The only LVM target types (i.e. "personalities") that have an automated
 | 
			
		||||
response to failures are the mirror and RAID logical volumes.  The other target
 | 
			
		||||
types (linear, stripe, snapshot, etc) will simply propagate the failure.
 | 
			
		||||
[A snapshot becomes invalid if its underlying device fails, but the
 | 
			
		||||
origin will remain valid - presuming the origin device has not failed.]
 | 
			
		||||
 | 
			
		||||
Starting with the "mirror" segment type, there are three types of errors that
 | 
			
		||||
a mirror can suffer - read, write, and resynchronization errors.  Each is
 | 
			
		||||
described in depth below.
 | 
			
		||||
 | 
			
		||||
Mirror read failures:
 | 
			
		||||
If a mirror is 'in-sync' (i.e. all images have been initialized and
 | 
			
		||||
are identical), a read failure will only produce a warning.  Data is
 | 
			
		||||
simply pulled from one of the other images and the fault is recorded.
 | 
			
		||||
Sometimes - like in the case of bad block relocation - read errors can
 | 
			
		||||
be recovered from by the storage hardware.  Therefore, it is up to the
 | 
			
		||||
user to decide whether to reconfigure the mirror and remove the device
 | 
			
		||||
that caused the error.  Managing the composition of a mirror is done with
 | 
			
		||||
'lvconvert' and removing a device from a volume group can be done with
 | 
			
		||||
'vgreduce'.
 | 
			
		||||
 | 
			
		||||
If a mirror is not 'in-sync', a read failure will produce an I/O error.
 | 
			
		||||
This error will propagate all the way up to the applications above the
 | 
			
		||||
logical volume (e.g. the file system).  No automatic intervention will
 | 
			
		||||
take place in this case either.  It is up to the user to decide what
 | 
			
		||||
can be done/salvaged in this senario.  If the user is confident that the
 | 
			
		||||
images of the mirror are the same (or they are willing to simply attempt
 | 
			
		||||
to retreive whatever data they can), 'lvconvert' can be used to eliminate
 | 
			
		||||
the failed image and proceed.
 | 
			
		||||
 | 
			
		||||
Mirror resynchronization errors:
 | 
			
		||||
A resynchronization error is one that occurs when trying to initialize
 | 
			
		||||
all mirror images to be the same.  It can happen due to a failure to
 | 
			
		||||
read the primary image (the image considered to have the 'good' data), or
 | 
			
		||||
due to a failure to write the secondary images.  This type of failure
 | 
			
		||||
only produces a warning, and it is up to the user to take action in this
 | 
			
		||||
case.  If the error is transient, the user can simply reactivate the
 | 
			
		||||
mirrored logical volume to make another attempt at resynchronization.
 | 
			
		||||
If attempts to finish resynchronization fail, 'lvconvert' can be used to
 | 
			
		||||
remove the faulty device from the mirror.
 | 
			
		||||
 | 
			
		||||
TODO...
 | 
			
		||||
Some sort of response to this type of error could be automated.
 | 
			
		||||
Since this document is the definitive source for how to handle device
 | 
			
		||||
failures, the process should be defined here.  If the process is defined
 | 
			
		||||
but not implemented, it should be noted as such.  One idea might be to
 | 
			
		||||
make a single attempt to suspend/resume the mirror in an attempt to
 | 
			
		||||
redo the sync operation that failed.  On the other hand, if there is
 | 
			
		||||
a permanent failure, it may simply be best to wait for the user or the
 | 
			
		||||
automated response that is sure to follow from a write failure.
 | 
			
		||||
...TODO
 | 
			
		||||
 | 
			
		||||
Mirror write failures:
 | 
			
		||||
When a write error occurs on a mirror constituent device, an attempt
 | 
			
		||||
to handle the failure is automatically made.  This is done by calling
 | 
			
		||||
'lvconvert --repair --use-policies'.  The policies implied by this
 | 
			
		||||
command are set in the LVM configuration file.  They are:
 | 
			
		||||
- mirror_log_fault_policy:  This defines what action should be taken
 | 
			
		||||
  if the device containing the log fails.  The available options are
 | 
			
		||||
  "remove" and "allocate".  Either of these options will cause the
 | 
			
		||||
  faulty log device to be removed from the mirror.  The "allocate"
 | 
			
		||||
  policy will attempt the further action of trying to replace the
 | 
			
		||||
  failed disk log by using space that might be available in the
 | 
			
		||||
  volume group.  If the allocation fails (or the "remove" policy
 | 
			
		||||
  is specified), the mirror log will be maintained in memory.  Should
 | 
			
		||||
  the machine be rebooted or the logical volume deactivated, a
 | 
			
		||||
  complete resynchronization of the mirror will be necessary upon
 | 
			
		||||
  the follow activation - such is the nature of a mirror with a 'core'
 | 
			
		||||
  log.  The default policy for handling log failures is "allocate".
 | 
			
		||||
  The service disruption incurred by replacing the failed log is
 | 
			
		||||
  negligible, while the benefits of having persistent log is
 | 
			
		||||
  pronounced.
 | 
			
		||||
- mirror_image_fault_policy:  This defines what action should be taken
 | 
			
		||||
  if a device containing an image fails.  Again, the available options
 | 
			
		||||
  are "remove" and "allocate".  Both of these options will cause the
 | 
			
		||||
  faulty image device to be removed - adjusting the logical volume
 | 
			
		||||
  accordingly.  For example, if one image of a 2-way mirror fails, the
 | 
			
		||||
  mirror will be converted to a linear device.  If one image of a
 | 
			
		||||
  3-way mirror fails, the mirror will be converted to a 2-way mirror.
 | 
			
		||||
  The "allocate" policy takes the further action of trying to replace
 | 
			
		||||
  the failed image using space that is available in the volume group.
 | 
			
		||||
  Replacing a failed mirror image will incure the cost of
 | 
			
		||||
  resynchronizing - degrading the performance of the mirror.  The
 | 
			
		||||
  default policy for handling an image failure is "remove".  This
 | 
			
		||||
  allows the mirror to still function, but gives the administrator the
 | 
			
		||||
  choice of when to incure the extra performance costs of replacing
 | 
			
		||||
  the failed image.
 | 
			
		||||
 | 
			
		||||
RAID logical volume device failures are handled differently from the "mirror"
 | 
			
		||||
segment type.  Discussion of this can be found in lvm2-raid.txt.
 | 
			
		||||
							
								
								
									
										197
									
								
								doc/lvmetad_design.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								doc/lvmetad_design.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,197 @@
 | 
			
		||||
The design of LVMetaD
 | 
			
		||||
=====================
 | 
			
		||||
 | 
			
		||||
Invocation and setup
 | 
			
		||||
--------------------
 | 
			
		||||
 | 
			
		||||
The daemon should be started automatically by the first LVM command issued on
 | 
			
		||||
the system, when needed. The usage of the daemon should be configurable in
 | 
			
		||||
lvm.conf, probably with its own section. Say
 | 
			
		||||
 | 
			
		||||
    lvmetad {
 | 
			
		||||
        enabled = 1 # default
 | 
			
		||||
        autostart = 1 # default
 | 
			
		||||
        socket = "/path/to/socket" # defaults to /var/run/lvmetad or such
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
Library integration
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
When a command needs to access metadata, it currently needs to perform a scan
 | 
			
		||||
of the physical devices available in the system. This is a possibly quite
 | 
			
		||||
expensive operation, especially if many devices are attached to the system. In
 | 
			
		||||
most cases, LVM needs a complete image of the system's PVs to operate
 | 
			
		||||
correctly, so all devices need to be read, to at least determine presence (and
 | 
			
		||||
content) of a PV label. Additional IO is done to obtain or write metadata
 | 
			
		||||
areas, but this is only marginally related and addressed by Dave's
 | 
			
		||||
metadata-balancing work.
 | 
			
		||||
 | 
			
		||||
In the existing scanning code, a cache layer exists, under
 | 
			
		||||
lib/cache/lvmcache.[hc]. This layer is keeping a textual copy of the metadata
 | 
			
		||||
for a given volume group, in a format_text form, as a character string. We can
 | 
			
		||||
plug the lvmetad interface at this level: in lvmcache_get_vg, which is
 | 
			
		||||
responsible for looking up metadata in a local cache, we can, if the metadata
 | 
			
		||||
is not available in the local cache, query lvmetad. Under normal circumstances,
 | 
			
		||||
when a VG is not cached yet, this operation fails and prompts the caller to
 | 
			
		||||
perform a scan. Under the lvmetad enabled scenario, this would never happen and
 | 
			
		||||
the fall-through would only be activated when lvmetad is disabled, which would
 | 
			
		||||
lead to local cache being populated as usual through a locally executed scan.
 | 
			
		||||
 | 
			
		||||
Therefore, existing stand-alone (i.e. no lvmetad) functionality of the tools
 | 
			
		||||
would be not compromised by adding lvmetad. With lvmetad enabled, however,
 | 
			
		||||
significant portions of the code would be short-circuited.
 | 
			
		||||
 | 
			
		||||
Scanning
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
Initially (at least), the lvmetad will be not allowed to read disks: it will
 | 
			
		||||
rely on an external program to provide the metadata. In the ideal case, this
 | 
			
		||||
will be triggered by udev. The role of lvmetad is then to collect and maintain
 | 
			
		||||
an accurate (up to the data it has received) image of the VGs available in the
 | 
			
		||||
system. I imagine we could extend the pvscan command (or add a new one, say
 | 
			
		||||
lvmetad_client, if pvscan is found to be inappropriate):
 | 
			
		||||
 | 
			
		||||
    $ pvscan --cache /dev/foo
 | 
			
		||||
    $ pvscan --cache --remove /dev/foo
 | 
			
		||||
 | 
			
		||||
These commands would simply read the label and the MDA (if applicable) from the
 | 
			
		||||
given PV and feed that data to the running lvmetad, using
 | 
			
		||||
lvmetad_{add,remove}_pv (see lvmetad_client.h).
 | 
			
		||||
 | 
			
		||||
We however need to ensure a couple of things here:
 | 
			
		||||
 | 
			
		||||
1) only LVM commands ever touch PV labels and VG metadata
 | 
			
		||||
2) when a device is added or removed, udev fires a rule to notify lvmetad
 | 
			
		||||
 | 
			
		||||
While the latter is straightforward, there are issues with the first. We
 | 
			
		||||
*might* want to invoke the dreaded "watch" udev rule in this case, however it
 | 
			
		||||
ends up being implemented. Of course, we can also rely on the sysadmin to be
 | 
			
		||||
reasonable and not write over existing LVM metadata without first telling LVM
 | 
			
		||||
to let go of the respective device(s).
 | 
			
		||||
 | 
			
		||||
Even if we simply ignore the problem, metadata write should fail in these
 | 
			
		||||
cases, so the admin should be unable to do substantial damage to the system. If
 | 
			
		||||
there were active LVs on top of the vanished PV, they are in trouble no matter
 | 
			
		||||
what happens there.
 | 
			
		||||
 | 
			
		||||
Incremental scan
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
There are some new issues arising with the "udev" scan mode. Namely, the
 | 
			
		||||
devices of a volume group will be appearing one by one. The behaviour in this
 | 
			
		||||
case will be very similar to the current behaviour when devices are missing:
 | 
			
		||||
the volume group, until *all* its physical volumes have been discovered and
 | 
			
		||||
announced by udev, will be in a state with some of its devices flagged as
 | 
			
		||||
MISSING_PV. This means that the volume group will be, for most purposes,
 | 
			
		||||
read-only until it is complete and LVs residing on yet-unknown PVs won't
 | 
			
		||||
activate without --partial. Under usual circumstances, this is not a problem
 | 
			
		||||
and the current code for dealing with MISSING_PVs should be adequate.
 | 
			
		||||
 | 
			
		||||
However, the code for reading volume groups from disks will need to be adapted,
 | 
			
		||||
since it currently does not work incrementally. Such support will need to track
 | 
			
		||||
metadata-less PVs that have been encountered so far and to provide a way to
 | 
			
		||||
update an existing volume group. When the first PV with metadata of a given VG
 | 
			
		||||
is encountered, the VG is created in lvmetad (probably in the form of "struct
 | 
			
		||||
volume_group") and it is assigned any previously cached metadata-less PVs it is
 | 
			
		||||
referencing. Any PVs that were not yet encountered will be marked as MISSING_PV
 | 
			
		||||
in the "struct volume_group". Upon scanning a new PV, if it belongs to any
 | 
			
		||||
already-known volume group, this PV is checked for consistency with the already
 | 
			
		||||
cached metadata (in a case of mismatch, the VG needs to be recovered or
 | 
			
		||||
declared conflicted), and is subsequently unmarked MISSING_PV. Care need be
 | 
			
		||||
taken not to unmark MISSING_PV on PVs that have this flag in their persistent
 | 
			
		||||
metadata, though.
 | 
			
		||||
 | 
			
		||||
The most problematic aspect of the whole design may be orphan PVs. At any given
 | 
			
		||||
point, a metadata-less PV may appear orphaned, if a PV of its VG with metadata
 | 
			
		||||
has not been scanned yet. Eventually, we will have to decide that this PV is
 | 
			
		||||
really an orphan and enable its usage for creating or extending VGs. In
 | 
			
		||||
practice, the decision might be governed by a timeout or assumed immediately --
 | 
			
		||||
the former case is a little safer, the latter is probably more transparent. I
 | 
			
		||||
am not very keen on using timeouts and we can probably assume that the admin
 | 
			
		||||
won't blindly try to re-use devices in a way that would trip up LVM in this
 | 
			
		||||
respect. I would be in favour of just assuming that metadata-less VGs with no
 | 
			
		||||
known referencing VGs are orphans -- after all, this is the same approach as we
 | 
			
		||||
use today. The metadata balancing support may stress this a bit more than the
 | 
			
		||||
usual contemporary setups do, though.
 | 
			
		||||
 | 
			
		||||
Automatic activation
 | 
			
		||||
--------------------
 | 
			
		||||
 | 
			
		||||
It may also be prudent to provide a command that will block until a volume
 | 
			
		||||
group is complete, so that scripts can reliably activate/mount LVs and such. Of
 | 
			
		||||
course, some PVs may never appear, so a timeout is necessary. Again, this is
 | 
			
		||||
something not handled by current tools, but may become more important in
 | 
			
		||||
future. It probably does not need to be implemented right away though.
 | 
			
		||||
 | 
			
		||||
The other aspect of the progressive VG assembly is automatic activation. The
 | 
			
		||||
currently only problem with that is that we would like to avoid having
 | 
			
		||||
activation code in lvmetad, so we would prefer to fire up an event of some sort
 | 
			
		||||
and let someone else handle the activation and whatnot.
 | 
			
		||||
 | 
			
		||||
Cluster support
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
When working in a cluster, clvmd integration will be necessary: clvmd will need
 | 
			
		||||
to instruct lvmetad to re-read metadata as appropriate due to writes on remote
 | 
			
		||||
hosts. Overall, this is not hard, but the devil is in the details. I would
 | 
			
		||||
possibly disable lvmetad for clustered volume groups in the first phase and
 | 
			
		||||
only proceed when the local mode is robust and well tested.
 | 
			
		||||
 | 
			
		||||
Protocol & co.
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
I expect a simple text-based protocol executed on top of an Unix Domain Socket
 | 
			
		||||
to be the communication interface for lvmetad. Ideally, the requests and
 | 
			
		||||
replies will be well-formed "config file" style strings, so we can re-use
 | 
			
		||||
existing parsing infrastructure.
 | 
			
		||||
 | 
			
		||||
Since we already have two daemons, I would probably look into factoring some
 | 
			
		||||
common code for daemon-y things, like sockets, communication (including thread
 | 
			
		||||
management) and maybe logging and re-using it in all the daemons (clvmd,
 | 
			
		||||
dmeventd and lvmetad). This shared infrastructure should live under
 | 
			
		||||
daemons/common, and the existing daemons shall be gradually migrated to the
 | 
			
		||||
shared code.
 | 
			
		||||
 | 
			
		||||
Future extensions
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
The above should basically cover the use of lvmetad as a cache-only
 | 
			
		||||
daemon. Writes could still be executed locally, and the new metadata version
 | 
			
		||||
can be provided to lvmetad through the socket the usual way. This is fairly
 | 
			
		||||
natural and in my opinion reasonable. The lvmetad acts like a cache that will
 | 
			
		||||
hold metadata, no more no less.
 | 
			
		||||
 | 
			
		||||
Above this, there is a couple of things that could be worked on later, when the
 | 
			
		||||
above basic design is finished and implemented.
 | 
			
		||||
 | 
			
		||||
_Metadata writing_: We may want to support writing new metadata through
 | 
			
		||||
lvmetad. This may or may not be a better design, but the write itself should be
 | 
			
		||||
more or less orthogonal to the rest of the story outlined above.
 | 
			
		||||
 | 
			
		||||
_Locking_: Other than directing metadata writes through lvmetad, one could
 | 
			
		||||
conceivably also track VG/LV locking through the same.
 | 
			
		||||
 | 
			
		||||
_Clustering_: A deeper integration of lvmetad with clvmd might be possible and
 | 
			
		||||
maybe desirable. Since clvmd communicates over the network with other clvmd
 | 
			
		||||
instances, this could be extended to metadata exchange between lvmetad's,
 | 
			
		||||
further cutting down scanning costs. This would combine well with the
 | 
			
		||||
write-through-lvmetad approach.
 | 
			
		||||
 | 
			
		||||
Testing
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
Since (at least bare-bones) lvmetad has no disk interaction and is fed metadata
 | 
			
		||||
externally, it should be very amenable to automated testing. We need to provide
 | 
			
		||||
a client that can feed arbitrary, synthetic metadata to the daemon and request
 | 
			
		||||
the data back, providing reasonable (nearly unit-level) testing infrastructure.
 | 
			
		||||
 | 
			
		||||
Battle plan & code layout
 | 
			
		||||
=========================
 | 
			
		||||
 | 
			
		||||
- config_tree from lib/config needs to move to libdm/
 | 
			
		||||
- daemon/common *client* code can go to libdm/ as well (say
 | 
			
		||||
  libdm/libdm-daemon.{h,c} or such)
 | 
			
		||||
- daemon/common *server* code stays, is built in daemon/ toplevel as a static
 | 
			
		||||
  library, say libdaemon-common.a
 | 
			
		||||
- daemon/lvmetad *client* code goes to lib/lvmetad
 | 
			
		||||
- daemon/lvmetad *server* code stays (links in daemon/libdaemon_common.a)
 | 
			
		||||
							
								
								
									
										52
									
								
								doc/pvmove_outline.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								doc/pvmove_outline.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
Let's say we have an LV, made up of three segments of different PV's,
 | 
			
		||||
I've also added in the device major:minor as this will be useful
 | 
			
		||||
later:
 | 
			
		||||
 | 
			
		||||
+-----------------------------+
 | 
			
		||||
|  PV1     |   PV2   |   PV3  | 254:3
 | 
			
		||||
+----------+---------+--------+
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Now our hero decides to PV move PV2 to PV4:
 | 
			
		||||
 | 
			
		||||
1. Suspend our LV (254:3), this starts queueing all io, and flushes
 | 
			
		||||
   all pending io.  Once the suspend has completed we are free to change
 | 
			
		||||
   the mapping table.
 | 
			
		||||
 | 
			
		||||
2. Set up *another* (254:4) device with the mapping table of our LV.
 | 
			
		||||
 | 
			
		||||
3. Load a new mapping table into (254:3) that has identity targets for
 | 
			
		||||
   parts that aren't moving, and a mirror target for parts that are.
 | 
			
		||||
 | 
			
		||||
4. Unsuspend (254:3)
 | 
			
		||||
 | 
			
		||||
So now we have:
 | 
			
		||||
                           destination of copy
 | 
			
		||||
               +--------------------->--------------+
 | 
			
		||||
               |                                    |
 | 
			
		||||
+-----------------------------+               + -----------+
 | 
			
		||||
| Identity | mirror  | Ident. | 254:3         |    PV4     |
 | 
			
		||||
+----------+---------+--------+               +------------+
 | 
			
		||||
     |         |         |
 | 
			
		||||
     \/        \/        \/
 | 
			
		||||
+-----------------------------+
 | 
			
		||||
|  PV1     |   PV2   |   PV3  | 254:4
 | 
			
		||||
+----------+---------+--------+
 | 
			
		||||
 | 
			
		||||
Any writes to segment2 of the LV get intercepted by the mirror target
 | 
			
		||||
who checks that that chunk has been copied to the new destination, if
 | 
			
		||||
it hasn't it queues the initial copy and defers the current io until
 | 
			
		||||
it has finished.  Then the current io is written to *both* PV2 and the
 | 
			
		||||
PV4.
 | 
			
		||||
 | 
			
		||||
5. When the copying has completed 254:3 is suspended/pending flushed.
 | 
			
		||||
 | 
			
		||||
6. 254:4 is taken down
 | 
			
		||||
 | 
			
		||||
7. metadata is updated on disk
 | 
			
		||||
 | 
			
		||||
8. 254:3 has new mapping table loaded:
 | 
			
		||||
 | 
			
		||||
+-----------------------------+
 | 
			
		||||
|  PV1     |   PV4   |   PV3  | 254:3
 | 
			
		||||
+----------+---------+--------+
 | 
			
		||||
							
								
								
									
										165
									
								
								doc/tagging.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								doc/tagging.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
Tagging aims
 | 
			
		||||
============
 | 
			
		||||
  1) Ability to attach an unordered list of tags to LVM metadata objects.
 | 
			
		||||
  2) Ability to add or remove tags easily.
 | 
			
		||||
  3) Ability to select LVM objects for processing according to presence/absence
 | 
			
		||||
     of specific tags.
 | 
			
		||||
  4) Ability to control through the config file which VGs/LVs are activated 
 | 
			
		||||
     on different machines using names or tags.
 | 
			
		||||
  5) Ability to overlay settings from different config files e.g. override
 | 
			
		||||
     some settings in a global config file locally.
 | 
			
		||||
 | 
			
		||||
Clarifications
 | 
			
		||||
==============
 | 
			
		||||
  1) Tag character set: A-Za-z0-9_+.- 
 | 
			
		||||
     Can't start with hyphen & max length is 128 (NAME_LEN).
 | 
			
		||||
  2) LVM object types that can be tagged:
 | 
			
		||||
       VG, LV, LV segment
 | 
			
		||||
       PV - tags are stored in VG metadata so disappear when PV becomes orphaned
 | 
			
		||||
     Snapshots can't be tagged, but their origin may be.
 | 
			
		||||
  3) A tag can be used in place of any command line LVM object reference that
 | 
			
		||||
     accepts (a) a list of objects; or (b) a single object as long as the
 | 
			
		||||
     tag expands to a single object.  This is not supported everywhere yet.
 | 
			
		||||
     Duplicate arguments in a list after argument expansion may get removed 
 | 
			
		||||
     retaining the first copy of each argument.
 | 
			
		||||
  4) Wherever there may be ambiguity of argument type, a tag must be prefixed 
 | 
			
		||||
     by '@'; elsewhere an '@' prefix is optional.
 | 
			
		||||
  5) LVM1 objects cannot be tagged, as the disk format doesn't support it.
 | 
			
		||||
  6) Tags can be added or removed with --addtag or --deltag.
 | 
			
		||||
 | 
			
		||||
Config file Extensions
 | 
			
		||||
======================
 | 
			
		||||
  To define host tags in config file:
 | 
			
		||||
 | 
			
		||||
  tags {
 | 
			
		||||
  	# Set a tag with the hostname
 | 
			
		||||
	hosttags = 1
 | 
			
		||||
 | 
			
		||||
	tag1 { }
 | 
			
		||||
 | 
			
		||||
  	tag2 {
 | 
			
		||||
		# If no exact match, tag is not set.
 | 
			
		||||
		host_list = [ "hostname", "dbase" ]
 | 
			
		||||
	}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
Activation config file example
 | 
			
		||||
==============================
 | 
			
		||||
  activation {
 | 
			
		||||
      volume_list = [ "vg1/lvol0", "@database" ]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Matches against vgname, vgname/lvname or @tag set in *metadata*.
 | 
			
		||||
  @* matches exactly against *any* tag set on the host.
 | 
			
		||||
  The VG or LV only gets activated if a metadata tag matches.
 | 
			
		||||
  The default if there is no match is not to activate.
 | 
			
		||||
  If volume_list is not present and any tags are defined on the host 
 | 
			
		||||
  then it only activates if a host tag matches a metadata tag.
 | 
			
		||||
  If volume_list is not present and no tags are defined on the host 
 | 
			
		||||
  then it does activate.
 | 
			
		||||
 | 
			
		||||
Multiple config files
 | 
			
		||||
=====================
 | 
			
		||||
  (a) lvm.conf
 | 
			
		||||
  (b) lvm_<host_tag>.conf
 | 
			
		||||
 | 
			
		||||
  At startup, load lvm.conf.
 | 
			
		||||
  Process tag settings.
 | 
			
		||||
  If any host tags were defined, load lvm_tag.conf for each tag, if present.
 | 
			
		||||
 | 
			
		||||
  When searching for a specific config file entry, search order is (b)
 | 
			
		||||
  then (a), stopping at the first match.  
 | 
			
		||||
  Within (b) use reverse order tags got set, so file for last tag set is
 | 
			
		||||
  searched first.
 | 
			
		||||
  New tags set in (b) *do* trigger additional config file loads. 
 | 
			
		||||
 | 
			
		||||
Usage Examples
 | 
			
		||||
==============
 | 
			
		||||
  1) Simple activation control via metadata with static config files
 | 
			
		||||
 | 
			
		||||
  lvm.conf:  (Identical on every machine - global settings)
 | 
			
		||||
    tags {
 | 
			
		||||
      hosttags = 1
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  From any machine in the cluster, add db1 to the list of machines that
 | 
			
		||||
  activate vg1/lvol2:
 | 
			
		||||
 | 
			
		||||
  lvchange --addtag @db1 vg1/lvol2
 | 
			
		||||
  (followed by lvchange -ay to actually activate it)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  2) Multiple hosts.  
 | 
			
		||||
 | 
			
		||||
    Activate vg1 only on the database hosts, db1 and db2.
 | 
			
		||||
    Activate vg2 only on the fileserver host fs1.
 | 
			
		||||
    Activate nothing initially on the fileserver backup host fsb1, but be
 | 
			
		||||
    prepared for it to take over from fs1.
 | 
			
		||||
 | 
			
		||||
  Option (i) - centralised admin, static configuration replicated between hosts  
 | 
			
		||||
    # Add @database tag to vg1's metadata
 | 
			
		||||
    vgchange --addtag @database vg1
 | 
			
		||||
 | 
			
		||||
    # Add @fileserver tag to vg2's metadata
 | 
			
		||||
    vgchange --addtag @fileserver vg2
 | 
			
		||||
 | 
			
		||||
    lvm.conf:  (Identical on every machine)
 | 
			
		||||
      tags {
 | 
			
		||||
        database {
 | 
			
		||||
          host_list = [ "db1", "db2" ]
 | 
			
		||||
        }
 | 
			
		||||
        fileserver {
 | 
			
		||||
	  host_list = [ "fs1" ]
 | 
			
		||||
        }
 | 
			
		||||
        fileserverbackup {
 | 
			
		||||
          host_list = [ "fsb1" ]
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      activation {
 | 
			
		||||
        # Only activate if host has a tag that matches a metadata tag
 | 
			
		||||
        volume_list = [ "@*" ]
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
  In the event of the fileserver host going down, vg2 can be brought up
 | 
			
		||||
  on fsb1 by running *on any node* 'vgchange --addtag @fileserverbackup vg2'
 | 
			
		||||
  followed by 'vgchange -ay vg2'
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  Option (ii) - localised admin & configuation
 | 
			
		||||
  (i.e. each host holds *locally* which classes of volumes to activate)
 | 
			
		||||
    # Add @database tag to vg1's metadata
 | 
			
		||||
    vgchange --addtag @database vg1
 | 
			
		||||
  
 | 
			
		||||
    # Add @fileserver tag to vg2's metadata
 | 
			
		||||
    vgchange --addtag @fileserver vg2
 | 
			
		||||
  
 | 
			
		||||
    lvm.conf:  (Identical on every machine - global settings)
 | 
			
		||||
      tags {
 | 
			
		||||
        hosttags = 1
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    lvm_db1.conf: (only needs to be on db1 - could be symlink to lvm_db.conf)
 | 
			
		||||
      activation {
 | 
			
		||||
        volume_list = [ "@database" ]
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    lvm_db2.conf: (only needs to be on db2 - could be symlink to lvm_db.conf)
 | 
			
		||||
      activation {
 | 
			
		||||
        volume_list = [ "@database" ]
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    lvm_fs1.conf: (only needs to be on fs1 - could be symlink to lvm_fs.conf)
 | 
			
		||||
      activation {
 | 
			
		||||
        volume_list = [ "@fileserver" ]
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    If fileserver goes down, to bring a spare machine fsb1 in as fileserver,
 | 
			
		||||
    create lvm_fsb1.conf on fsb1 (or symlink to lvm_fs.conf):
 | 
			
		||||
 | 
			
		||||
      activation {
 | 
			
		||||
        volume_list = [ "@fileserver" ]
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    and run 'vgchange -ay vg2' or 'vgchange -ay @fileserver'
 | 
			
		||||
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user