mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-10-22 19:33:16 +03:00 
			
		
		
		
	Compare commits
	
		
			1942 Commits
		
	
	
		
			dev-bmr-dm
			...
			v2_02_07
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 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 | 
							
								
								
									
										32
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,32 +0,0 @@ | |||||||
| *.5 |  | ||||||
| *.7 |  | ||||||
| *.8 |  | ||||||
| *.a |  | ||||||
| *.d |  | ||||||
| *.o |  | ||||||
| *.orig |  | ||||||
| *.pc |  | ||||||
| *.pot |  | ||||||
| *.pyc |  | ||||||
| *.pyo |  | ||||||
| *.rej |  | ||||||
| *.so |  | ||||||
| *.so.* |  | ||||||
| *.sw* |  | ||||||
| *~ |  | ||||||
|  |  | ||||||
| .export.sym |  | ||||||
| .exported_symbols_generated |  | ||||||
| .gdb_history |  | ||||||
|  |  | ||||||
| Makefile |  | ||||||
| make.tmpl |  | ||||||
|  |  | ||||||
| /autom4te.cache/ |  | ||||||
| /autoscan.log |  | ||||||
| /config.log |  | ||||||
| /config.status |  | ||||||
| /configure.scan |  | ||||||
| /cscope.out |  | ||||||
| /tags |  | ||||||
| /tmp/ |  | ||||||
							
								
								
									
										4
									
								
								COPYING
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								COPYING
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | |||||||
| 		       Version 2, June 1991 | 		       Version 2, June 1991 | ||||||
|  |  | ||||||
|  Copyright (C) 1989, 1991 Free Software Foundation, Inc. |  Copyright (C) 1989, 1991 Free Software Foundation, Inc. | ||||||
|  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  Everyone is permitted to copy and distribute verbatim copies |  Everyone is permitted to copy and distribute verbatim copies | ||||||
|  of this license document, but changing it is not allowed. |  of this license document, but changing it is not allowed. | ||||||
|  |  | ||||||
| @@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found. | |||||||
|  |  | ||||||
|     You should have received a copy of the GNU General Public License |     You should have received a copy of the GNU General Public License | ||||||
|     along with this program; if not, write to the Free Software |     along with this program; if not, write to the Free Software | ||||||
|     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |     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. | Also add information on how to contact you by electronic and paper mail. | ||||||
|   | |||||||
							
								
								
									
										203
									
								
								COPYING.LIB
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								COPYING.LIB
									
									
									
									
									
								
							| @@ -1,14 +1,14 @@ | |||||||
| 		  GNU LESSER GENERAL PUBLIC LICENSE |  | ||||||
| 		       Version 2.1, February 1999 |  | ||||||
|  |  | ||||||
|  Copyright (C) 1991, 1999 Free Software Foundation, Inc. | 		  GNU LIBRARY GENERAL PUBLIC LICENSE | ||||||
|  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | 		       Version 2, June 1991 | ||||||
|  |  | ||||||
|  |  Copyright (C) 1991 Free Software Foundation, Inc. | ||||||
|  |  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||||||
|  Everyone is permitted to copy and distribute verbatim copies |  Everyone is permitted to copy and distribute verbatim copies | ||||||
|  of this license document, but changing it is not allowed. |  of this license document, but changing it is not allowed. | ||||||
|  |  | ||||||
| [This is the first released version of the Lesser GPL.  It also counts | [This is the first released version of the library GPL.  It is | ||||||
|  as the successor of the GNU Library Public License, version 2, hence |  numbered 2 because it goes with version 2 of the ordinary GPL.] | ||||||
|  the version number 2.1.] |  | ||||||
|  |  | ||||||
| 			    Preamble | 			    Preamble | ||||||
|  |  | ||||||
| @@ -17,109 +17,97 @@ freedom to share and change it.  By contrast, the GNU General Public | |||||||
| Licenses are intended to guarantee your freedom to share and change | Licenses are intended to guarantee your freedom to share and change | ||||||
| free software--to make sure the software is free for all its users. | free software--to make sure the software is free for all its users. | ||||||
|  |  | ||||||
|   This license, the Lesser General Public License, applies to some |   This license, the Library General Public License, applies to some | ||||||
| specially designated software packages--typically libraries--of the | specially designated Free Software Foundation software, and to any | ||||||
| Free Software Foundation and other authors who decide to use it.  You | other libraries whose authors decide to use it.  You can use it for | ||||||
| can use it too, but we suggest you first think carefully about whether | your libraries, too. | ||||||
| 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, |   When we speak of free software, we are referring to freedom, not | ||||||
| not price.  Our General Public Licenses are designed to make sure that | price.  Our General Public Licenses are designed to make sure that you | ||||||
| you have the freedom to distribute copies of free software (and charge | have the freedom to distribute copies of free software (and charge for | ||||||
| for this service if you wish); that you receive source code or can get | this service if you wish), that you receive source code or can get it | ||||||
| it if you want it; that you can change the software and use pieces of | if you want it, that you can change the software or use pieces of it | ||||||
| it in new free programs; and that you are informed that you can do | in new free programs; and that you know you can do these things. | ||||||
| these things. |  | ||||||
|  |  | ||||||
|   To protect your rights, we need to make restrictions that forbid |   To protect your rights, we need to make restrictions that forbid | ||||||
| distributors to deny you these rights or to ask you to surrender these | anyone to deny you these rights or to ask you to surrender the rights. | ||||||
| rights.  These restrictions translate to certain responsibilities for | These restrictions translate to certain responsibilities for you if | ||||||
| you if you distribute copies of the library or if you modify it. | you distribute copies of the library, or if you modify it. | ||||||
|  |  | ||||||
|   For example, if you distribute copies of the library, whether gratis |   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 | 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 | 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 | code.  If you link a program with the library, you must provide | ||||||
| complete object files to the recipients, so that they can relink them | complete object files to the recipients so that they can relink them | ||||||
| with the library after making changes to the library and recompiling | with the library, after making changes to the library and recompiling | ||||||
| it.  And you must show them these terms so they know their rights. | 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 |   Our method of protecting your rights has two steps: (1) copyright | ||||||
| library, and (2) we offer you this license, which gives you legal | the library, and (2) offer you this license which gives you legal | ||||||
| permission to copy, distribute and/or modify the library. | permission to copy, distribute and/or modify the library. | ||||||
|  |  | ||||||
|   To protect each distributor, we want to make it very clear that |   Also, for each distributor's protection, we want to make certain | ||||||
| there is no warranty for the free library.  Also, if the library is | that everyone understands that there is no warranty for this free | ||||||
| modified by someone else and passed on, the recipients should know | library.  If the library is modified by someone else and passed on, we | ||||||
| that what they have is not the original version, so that the original | want its recipients to know that what they have is not the original | ||||||
| author's reputation will not be affected by problems that might be | version, so that any problems introduced by others will not reflect on | ||||||
| introduced by others. | the original authors' reputations. | ||||||
|  |  | ||||||
|   Finally, software patents pose a constant threat to the existence of |   Finally, any free program is threatened constantly by software | ||||||
| any free program.  We wish to make sure that a company cannot | patents.  We wish to avoid the danger that companies distributing free | ||||||
| effectively restrict the users of a free program by obtaining a | software will individually obtain patent licenses, thus in effect | ||||||
| restrictive license from a patent holder.  Therefore, we insist that | transforming the program into proprietary software.  To prevent this, | ||||||
| any patent license obtained for a version of the library must be | we have made it clear that any patent must be licensed for everyone's | ||||||
| consistent with the full freedom of use specified in this license. | free use or not licensed at all. | ||||||
|  |  | ||||||
|   Most GNU software, including some libraries, is covered by the |   Most GNU software, including some libraries, is covered by the ordinary | ||||||
| ordinary GNU General Public License.  This license, the GNU Lesser | GNU General Public License, which was designed for utility programs.  This | ||||||
| General Public License, applies to certain designated libraries, and | license, the GNU Library General Public License, applies to certain | ||||||
| is quite different from the ordinary General Public License.  We use | designated libraries.  This license is quite different from the ordinary | ||||||
| this license for certain libraries in order to permit linking those | one; be sure to read it in full, and don't assume that anything in it is | ||||||
| libraries into non-free programs. | the same as in the ordinary license. | ||||||
|  |  | ||||||
|   When a program is linked with a library, whether statically or using |   The reason we have a separate public license for some libraries is that | ||||||
| a shared library, the combination of the two is legally speaking a | they blur the distinction we usually make between modifying or adding to a | ||||||
| combined work, a derivative of the original library.  The ordinary | program and simply using it.  Linking a program with a library, without | ||||||
| General Public License therefore permits such linking only if the | changing the library, is in some sense simply using the library, and is | ||||||
| entire combination fits its criteria of freedom.  The Lesser General | analogous to running a utility program or application program.  However, in | ||||||
| Public License permits more lax criteria for linking other code with | a textual and legal sense, the linked executable is a combined work, a | ||||||
| the library. | derivative of the original library, and the ordinary General Public License | ||||||
|  | treats it as such. | ||||||
|  |  | ||||||
|   We call this license the "Lesser" General Public License because it |   Because of this blurred distinction, using the ordinary General | ||||||
| does Less to protect the user's freedom than the ordinary General | Public License for libraries did not effectively promote software | ||||||
| Public License.  It also provides other free software developers Less | sharing, because most developers did not use the libraries.  We | ||||||
| of an advantage over competing non-free programs.  These disadvantages | concluded that weaker conditions might promote sharing better. | ||||||
| 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 |   However, unrestricted linking of non-free programs would deprive the | ||||||
| encourage the widest possible use of a certain library, so that it becomes | users of those programs of all benefit from the free status of the | ||||||
| a de-facto standard.  To achieve this, non-free programs must be | libraries themselves.  This Library General Public License is intended to | ||||||
| allowed to use the library.  A more frequent case is that a free | permit developers of non-free programs to use free libraries, while | ||||||
| library does the same job as widely used non-free libraries.  In this | preserving your freedom as a user of such programs to change the free | ||||||
| case, there is little to gain by limiting the free library to free | libraries that are incorporated in them.  (We have not seen how to achieve | ||||||
| software only, so we use the Lesser General Public License. | this as regards changes in header files, but we have achieved it as regards | ||||||
|  | changes in the actual functions of the Library.)  The hope is that this | ||||||
|   In other cases, permission to use a particular library in non-free | will lead to faster development of free libraries. | ||||||
| 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 |   The precise terms and conditions for copying, distribution and | ||||||
| modification follow.  Pay close attention to the difference between a | modification follow.  Pay close attention to the difference between a | ||||||
| "work based on the library" and a "work that uses the library".  The | "work based on the library" and a "work that uses the library".  The | ||||||
| former contains code derived from the library, whereas the latter must | former contains code derived from the library, while the latter only | ||||||
| be combined with the library in order to run. | works together with the library. | ||||||
|  |  | ||||||
|  |   Note that it is possible for a library to be covered by the ordinary | ||||||
|  | General Public License rather than by this special one. | ||||||
|  |  | ||||||
| 		  GNU LESSER GENERAL PUBLIC LICENSE | 		  GNU LIBRARY GENERAL PUBLIC LICENSE | ||||||
|    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||||||
|  |  | ||||||
|   0. This License Agreement applies to any software library or other |   0. This License Agreement applies to any software library which | ||||||
| program which contains a notice placed by the copyright holder or | contains a notice placed by the copyright holder or other authorized | ||||||
| other authorized party saying it may be distributed under the terms of | party saying it may be distributed under the terms of this Library | ||||||
| this Lesser General Public License (also called "this License"). | General Public License (also called "this License").  Each licensee is | ||||||
| Each licensee is addressed as "you". | addressed as "you". | ||||||
|  |  | ||||||
|   A "library" means a collection of software functions and/or data |   A "library" means a collection of software functions and/or data | ||||||
| prepared so as to be conveniently linked with application programs | prepared so as to be conveniently linked with application programs | ||||||
| @@ -268,7 +256,7 @@ distribute the object code for the work under the terms of Section 6. | |||||||
| Any executables containing that work also fall under Section 6, | Any executables containing that work also fall under Section 6, | ||||||
| whether or not they are linked directly with the Library itself. | whether or not they are linked directly with the Library itself. | ||||||
|  |  | ||||||
|   6. As an exception to the Sections above, you may also combine or |   6. As an exception to the Sections above, you may also compile or | ||||||
| link a "work that uses the Library" with the Library to produce a | link a "work that uses the Library" with the Library to produce a | ||||||
| work containing portions of the Library, and distribute that work | work containing portions of the Library, and distribute that work | ||||||
| under terms of your choice, provided that the terms permit | under terms of your choice, provided that the terms permit | ||||||
| @@ -295,31 +283,23 @@ of these things: | |||||||
|     Library will not necessarily be able to recompile the application |     Library will not necessarily be able to recompile the application | ||||||
|     to use the modified definitions.) |     to use the modified definitions.) | ||||||
|  |  | ||||||
|     b) Use a suitable shared library mechanism for linking with the |     b) Accompany the work with a written offer, valid for at | ||||||
|     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 |     least three years, to give the same user the materials | ||||||
|     specified in Subsection 6a, above, for a charge no more |     specified in Subsection 6a, above, for a charge no more | ||||||
|     than the cost of performing this distribution. |     than the cost of performing this distribution. | ||||||
|  |  | ||||||
|     d) If distribution of the work is made by offering access to copy |     c) If distribution of the work is made by offering access to copy | ||||||
|     from a designated place, offer equivalent access to copy the above |     from a designated place, offer equivalent access to copy the above | ||||||
|     specified materials from the same place. |     specified materials from the same place. | ||||||
|  |  | ||||||
|     e) Verify that the user has already received a copy of these |     d) Verify that the user has already received a copy of these | ||||||
|     materials or that you have already sent this user a copy. |     materials or that you have already sent this user a copy. | ||||||
|  |  | ||||||
|   For an executable, the required form of the "work that uses the |   For an executable, the required form of the "work that uses the | ||||||
| Library" must include any data and utility programs needed for | Library" must include any data and utility programs needed for | ||||||
| reproducing the executable from it.  However, as a special exception, | reproducing the executable from it.  However, as a special exception, | ||||||
| the materials to be distributed need not include anything that is | the source code distributed need not include anything that is normally | ||||||
| normally distributed (in either source or binary form) with the major | distributed (in either source or binary form) with the major | ||||||
| components (compiler, kernel, and so on) of the operating system on | components (compiler, kernel, and so on) of the operating system on | ||||||
| which the executable runs, unless that component itself accompanies | which the executable runs, unless that component itself accompanies | ||||||
| the executable. | the executable. | ||||||
| @@ -368,7 +348,7 @@ Library), the recipient automatically receives a license from the | |||||||
| original licensor to copy, distribute, link with or modify the Library | original licensor to copy, distribute, link with or modify the Library | ||||||
| subject to these terms and conditions.  You may not impose any further | subject to these terms and conditions.  You may not impose any further | ||||||
| restrictions on the recipients' exercise of the rights granted herein. | restrictions on the recipients' exercise of the rights granted herein. | ||||||
| You are not responsible for enforcing compliance by third parties with | You are not responsible for enforcing compliance by third parties to | ||||||
| this License. | this License. | ||||||
|  |  | ||||||
|   11. If, as a consequence of a court judgment or allegation of patent |   11. If, as a consequence of a court judgment or allegation of patent | ||||||
| @@ -411,7 +391,7 @@ excluded.  In such case, this License incorporates the limitation as if | |||||||
| written in the body of this License. | written in the body of this License. | ||||||
|  |  | ||||||
|   13. The Free Software Foundation may publish revised and/or new |   13. The Free Software Foundation may publish revised and/or new | ||||||
| versions of the Lesser General Public License from time to time. | versions of the Library General Public License from time to time. | ||||||
| Such new versions will be similar in spirit to the present version, | Such new versions will be similar in spirit to the present version, | ||||||
| but may differ in detail to address new problems or concerns. | but may differ in detail to address new problems or concerns. | ||||||
|  |  | ||||||
| @@ -457,7 +437,7 @@ DAMAGES. | |||||||
|  |  | ||||||
| 		     END OF TERMS AND CONDITIONS | 		     END OF TERMS AND CONDITIONS | ||||||
|  |  | ||||||
|            How to Apply These Terms to Your New Libraries |      Appendix: How to Apply These Terms to Your New Libraries | ||||||
|  |  | ||||||
|   If you develop a new library, and you want it to be of the greatest |   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 | possible use to the public, we recommend making it free software that | ||||||
| @@ -474,18 +454,19 @@ convey the exclusion of warranty; and each file should have at least the | |||||||
|     Copyright (C) <year>  <name of author> |     Copyright (C) <year>  <name of author> | ||||||
|  |  | ||||||
|     This library is free software; you can redistribute it and/or |     This library is free software; you can redistribute it and/or | ||||||
|     modify it under the terms of the GNU Lesser General Public |     modify it under the terms of the GNU Library General Public | ||||||
|     License as published by the Free Software Foundation; either |     License as published by the Free Software Foundation; either | ||||||
|     version 2.1 of the License, or (at your option) any later version. |     version 2 of the License, or (at your option) any later version. | ||||||
|  |  | ||||||
|     This library is distributed in the hope that it will be useful, |     This library is distributed in the hope that it will be useful, | ||||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of |     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||||
|     Lesser General Public License for more details. |     Library General Public License for more details. | ||||||
|  |  | ||||||
|     You should have received a copy of the GNU Lesser General Public |     You should have received a copy of the GNU Library General Public | ||||||
|     License along with this library; if not, write to the Free Software |     License along with this library; if not, write to the Free | ||||||
|     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA |     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. | Also add information on how to contact you by electronic and paper mail. | ||||||
|  |  | ||||||
| @@ -500,5 +481,3 @@ necessary.  Here is a sample; alter the names: | |||||||
|   Ty Coon, President of Vice |   Ty Coon, President of Vice | ||||||
|  |  | ||||||
| That's all there is to it! | That's all there is to it! | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								INSTALL
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								INSTALL
									
									
									
									
									
								
							| @@ -1,30 +1,44 @@ | |||||||
| Installation | LVM2 installation | ||||||
| ============ | ================= | ||||||
|  |  | ||||||
| 1) Generate custom makefiles. | 1) Install device-mapper | ||||||
|  |  | ||||||
|  |    Ensure the device-mapper has been installed on the machine. | ||||||
|  |  | ||||||
|  |    The device-mapper should be in the kernel (look for 'device-mapper' | ||||||
|  |    messages in the kernel logs) and /usr/include/libdevmapper.h  | ||||||
|  |    and libdevmapper.so should be present. | ||||||
|  |  | ||||||
|  |    The device-mapper is available from: | ||||||
|  |      ftp://ftp.sistina.com/pub/LVM2/device-mapper/ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 2) Generate custom makefiles. | ||||||
|  |  | ||||||
|    Run the 'configure' script from the top directory. |    Run the 'configure' script from the top directory. | ||||||
|  |  | ||||||
|  |    If you wish to use the built-in LVM2 shell and have GNU readline  | ||||||
|  |    installed (http://www.gnu.org/directory/readline.html) use: | ||||||
|  |      ./configure --enable-readline | ||||||
|  |  | ||||||
|    If you don't want to include the LVM1 backwards-compatibility code use: |    If you don't want to include the LVM1 backwards-compatibility code use: | ||||||
|      ./configure --with-lvm1=none  |      ./configure --with-lvm1=none  | ||||||
|  |  | ||||||
|    To separate the LVM1 support into a shared library loaded by lvm.conf use: |    To separate the LVM1 support into a shared library loaded by lvm.conf use: | ||||||
|      ./configure --with-lvm1=shared |      ./configure --with-lvm1=shared | ||||||
|  |  | ||||||
|    Use ./configure --help to see other options. |  | ||||||
|  |  | ||||||
| 2) Build and install. | 3) Build and install LVM2. | ||||||
|  |  | ||||||
|    Run 'make' from the top directory to build everything you configured. |    Run 'make install' from the top directory. | ||||||
|    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. | 4) Create a configuration file | ||||||
|  |  | ||||||
|    The tools will work fine without a configuration file being |    The tools will work fine without a configuration file being | ||||||
|    present, but you ought to review the example file in doc/example.conf. |    present, but you ought to review the example file in doc/example.conf. | ||||||
|  |    For example, specifying the devices that LVM2 is to use can | ||||||
|  |    make the tools run more efficiently - and avoid scanning /dev/cdrom! | ||||||
|  |  | ||||||
| Please also refer to the WHATS_NEW file and the manual pages for the  | Please also refer to the WHATS_NEW file and the manual pages for the  | ||||||
| individual commands. | individual commands. | ||||||
|   | |||||||
							
								
								
									
										235
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										235
									
								
								Makefile.in
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | |||||||
| # | # | ||||||
| # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. | # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. | ||||||
| # Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. | # Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
| # | # | ||||||
| # This file is part of LVM2. | # This file is part of the LVM2. | ||||||
| # | # | ||||||
| # This copyrighted material is made available to anyone wishing to use, | # This copyrighted material is made available to anyone wishing to use, | ||||||
| # modify, copy, or redistribute it subject to the terms and conditions | # modify, copy, or redistribute it subject to the terms and conditions | ||||||
| @@ -10,234 +10,61 @@ | |||||||
| # | # | ||||||
| # You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | ||||||
| # along with this program; if not, write to the Free Software Foundation, | # along with this program; if not, write to the Free Software Foundation, | ||||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  | ||||||
| srcdir = @srcdir@ | srcdir = @srcdir@ | ||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| top_builddir = @top_builddir@ | VPATH = @srcdir@ | ||||||
| abs_top_builddir = @abs_top_builddir@ |  | ||||||
| abs_top_srcdir = @abs_top_srcdir@ |  | ||||||
|  |  | ||||||
| SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools | SUBDIRS = doc include man  | ||||||
|  |  | ||||||
| ifeq ("@UDEV_RULES@", "yes") |  | ||||||
|   SUBDIRS += udev |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ("@INTL@", "yes") | ifeq ("@INTL@", "yes") | ||||||
|   SUBDIRS += po |   SUBDIRS += po | ||||||
| endif | endif | ||||||
|  |  | ||||||
| ifeq ("@APPLIB@", "yes") | SUBDIRS += lib tools daemons | ||||||
|   SUBDIRS += liblvm |  | ||||||
|  | ifeq ("@DMEVENTD@", "yes") | ||||||
|  |   SUBDIRS += dmeventd | ||||||
| endif | endif | ||||||
|  |  | ||||||
| ifeq ("@PYTHON_BINDINGS@", "yes") |  | ||||||
|   SUBDIRS += python |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ($(MAKECMDGOALS),clean) |  | ||||||
|   SUBDIRS += test |  | ||||||
| endif |  | ||||||
| # FIXME Should use intermediate Makefiles here! |  | ||||||
| ifeq ($(MAKECMDGOALS),distclean) | ifeq ($(MAKECMDGOALS),distclean) | ||||||
|   SUBDIRS = conf include man test scripts \ |   SUBDIRS += daemons/clvmd \ | ||||||
|     libdaemon lib tools daemons libdm \ | 	     dmeventd \ | ||||||
|     udev po liblvm python \ | 	     lib/format1 \ | ||||||
|     unit-tests/datastruct unit-tests/mm unit-tests/regex | 	     lib/format_pool \ | ||||||
| tools.distclean: test.distclean | 	     lib/locking \ | ||||||
|  | 	     lib/mirror \ | ||||||
|  | 	     lib/snapshot \ | ||||||
|  | 	     po \ | ||||||
|  | 	     test/mm test/device test/format1 test/regex test/filters | ||||||
|  |   DISTCLEAN_TARGETS += lib/misc/configure.h | ||||||
| endif | endif | ||||||
| DISTCLEAN_DIRS += lcov_reports* |  | ||||||
| DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl |  | ||||||
|  |  | ||||||
| include make.tmpl | include make.tmpl | ||||||
|  |  | ||||||
| libdm: include | daemons: lib | ||||||
| libdaemon: include | lib: include | ||||||
| lib: libdm libdaemon | tools: lib | ||||||
| liblvm: lib | dmeventd: tools | ||||||
| daemons: lib libdaemon tools | po: tools daemons dmeventd | ||||||
| tools: lib libdaemon device-mapper |  | ||||||
| po: tools daemons |  | ||||||
| scripts: liblvm libdm |  | ||||||
|  |  | ||||||
| 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 |  | ||||||
| scripts.device-mapper: include.device-mapper |  | ||||||
| device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper |  | ||||||
|  |  | ||||||
| ifeq ("@INTL@", "yes") | ifeq ("@INTL@", "yes") | ||||||
| lib.pofile: include.pofile | lib.pofile: include.pofile | ||||||
| tools.pofile: lib.pofile | tools.pofile: lib.pofile | ||||||
| daemons.pofile: lib.pofile | daemons.pofile: lib.pofile | ||||||
| po.pofile: tools.pofile daemons.pofile | dmeventd.pofile: tools.pofile | ||||||
|  | po.pofile: tools.pofile daemons.pofile dmeventd.pofile | ||||||
| pofile: po.pofile | pofile: po.pofile | ||||||
| endif | endif | ||||||
|  |  | ||||||
| ifeq ("@PYTHON_BINDINGS@", "yes") | ifneq ("@CFLOW_CMD@", "") | ||||||
| python: liblvm | tools.cflow: lib.cflow | ||||||
| endif | cflow: tools.cflow | ||||||
|  |  | ||||||
| ifneq ("$(CFLOW_CMD)", "") |  | ||||||
| tools.cflow: libdm.cflow lib.cflow |  | ||||||
| daemons.cflow: tools.cflow |  | ||||||
| cflow: include.cflow |  | ||||||
| endif | endif | ||||||
|  |  | ||||||
| ifneq ("@CSCOPE_CMD@", "") | ifneq ("@CSCOPE_CMD@", "") | ||||||
| cscope.out: | cscope.out: tools | ||||||
| 	@CSCOPE_CMD@ -b -R -s$(top_srcdir) | 	@CSCOPE_CMD@ -b -R | ||||||
| all: cscope.out | all: cscope.out | ||||||
| endif | endif | ||||||
| DISTCLEAN_TARGETS += cscope.out |  | ||||||
| CLEAN_DIRS += autom4te.cache |  | ||||||
|  |  | ||||||
| check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all |  | ||||||
| 	$(MAKE) -C test $(@) |  | ||||||
|  |  | ||||||
| conf.generate: tools |  | ||||||
|  |  | ||||||
| # how to use parenthesis in makefiles |  | ||||||
| leftparen:=( |  | ||||||
| LVM_VER := $(firstword $(subst $(leftparen), ,$(LVM_VERSION))) |  | ||||||
| VER := LVM2.$(LVM_VER) |  | ||||||
| # release file name |  | ||||||
| FILE_VER := $(VER).tgz |  | ||||||
| CLEAN_TARGETS += $(FILE_VER) |  | ||||||
| CLEAN_DIRS += $(rpmbuilddir) |  | ||||||
|  |  | ||||||
| dist: |  | ||||||
| 	@echo "Generating $(FILE_VER)";\ |  | ||||||
| 	(cd $(top_srcdir); git ls-tree -r HEAD --name-only | xargs tar --transform "s,^,$(VER)/," -c) | gzip >$(FILE_VER) |  | ||||||
|  |  | ||||||
| rpm: dist |  | ||||||
| 	$(RM) -r $(rpmbuilddir)/SOURCES |  | ||||||
| 	$(MKDIR_P) $(rpmbuilddir)/SOURCES |  | ||||||
| 	$(LN_S) -f $(abs_top_builddir)/$(FILE_VER) $(rpmbuilddir)/SOURCES |  | ||||||
| 	$(LN_S) -f $(abs_top_srcdir)/spec/build.inc $(rpmbuilddir)/SOURCES |  | ||||||
| 	$(LN_S) -f $(abs_top_srcdir)/spec/macros.inc $(rpmbuilddir)/SOURCES |  | ||||||
| 	$(LN_S) -f $(abs_top_srcdir)/spec/packages.inc $(rpmbuilddir)/SOURCES |  | ||||||
| 	DM_VER=$$(cut -d- -f1 $(top_srcdir)/VERSION_DM);\ |  | ||||||
| 	GIT_VER=$$(cd $(top_srcdir); git describe | cut -d- --output-delimiter=. -f2,3 || echo 0);\ |  | ||||||
| 	sed -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \ |  | ||||||
| 	    -e "s,^\(Version:[^0-9%]*\)[0-9.]*$$,\1 $(LVM_VER)," \ |  | ||||||
| 	    -e "s,^\(Release:[^0-9%]*\)[0-9.]\+,\1 $$GIT_VER," \ |  | ||||||
| 	    $(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc |  | ||||||
| 	rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec |  | ||||||
|  |  | ||||||
| generate: conf.generate |  | ||||||
| 	$(MAKE) -C conf generate |  | ||||||
|  |  | ||||||
| all_man: |  | ||||||
| 	$(MAKE) -C man all_man |  | ||||||
|  |  | ||||||
| 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_generators: |  | ||||||
| 	$(MAKE) -C scripts install_systemd_generators |  | ||||||
| 	$(MAKE) -C man install_systemd_generators |  | ||||||
|  |  | ||||||
| install_systemd_units: |  | ||||||
| 	$(MAKE) -C scripts install_systemd_units |  | ||||||
|  |  | ||||||
| install_all_man: |  | ||||||
| 	$(MAKE) -C man install_all_man |  | ||||||
|  |  | ||||||
| ifeq ("@PYTHON_BINDINGS@", "yes") |  | ||||||
| install_python_bindings: |  | ||||||
| 	$(MAKE) -C liblvm/python install_python_bindings |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| install_tmpfiles_configuration: |  | ||||||
| 	$(MAKE) -C scripts install_tmpfiles_configuration |  | ||||||
|  |  | ||||||
| LCOV_TRACES = libdm.info lib.info liblvm.info tools.info \ |  | ||||||
| 	libdaemon/client.info libdaemon/server.info \ |  | ||||||
| 	daemons/clvmd.info \ |  | ||||||
| 	daemons/dmeventd.info \ |  | ||||||
| 	daemons/lvmetad.info \ |  | ||||||
| 	daemons/lvmlockd.info \ |  | ||||||
| 	daemons/lvmpolld.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 -a $$(wc -w <$$i) -ge 100 && 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 |  | ||||||
|  |  | ||||||
| .PHONY: 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 |  | ||||||
|  |  | ||||||
| ifneq ($(shell which ctags),) |  | ||||||
| .PHONY: tags |  | ||||||
| tags: |  | ||||||
| 	test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags |  | ||||||
| 	test -f tags || find $(top_srcdir) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' + |  | ||||||
|  |  | ||||||
| CLEAN_TARGETS += tags |  | ||||||
| endif |  | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								README
									
									
									
									
									
								
							| @@ -1,33 +1,23 @@ | |||||||
| This tree contains the LVM2 and device-mapper tools and libraries. | This directory contains LVM2, the new version of the userland LVM | ||||||
|  | tools designed for the new device-mapper for the Linux kernel. | ||||||
|  |  | ||||||
| For more information about LVM2 read the changelog in the WHATS_NEW file. | The device-mapper needs to be installed before compiling these LVM2 tools. | ||||||
|  |  | ||||||
|  | For more information about LVM2 read the WHATS_NEW file. | ||||||
| Installation instructions are in INSTALL. | Installation instructions are in INSTALL. | ||||||
|  |  | ||||||
| There is no warranty - see COPYING and COPYING.LIB. | There is no warranty - see COPYING and COPYING.LIB. | ||||||
|  |  | ||||||
| Tarballs are available from: | Tarballs are available from: | ||||||
|   ftp://sources.redhat.com/pub/lvm2/ |   ftp://sources.redhat.com/pub/lvm2/ | ||||||
|  |   ftp://sources.redhat.com/pub/dm/ | ||||||
|  |  | ||||||
| The source code is stored in git: | To access the CVS tree use: | ||||||
|   http://git.fedorahosted.org/git/lvm2.git |   cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login | ||||||
|   git clone git://git.fedorahosted.org/git/lvm2.git |   CVS password: cvs | ||||||
|  |   cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 co LVM2 | ||||||
|  |  | ||||||
| Mailing list for general discussion related to LVM2: | Mailing list for discussion/bug reports etc. | ||||||
|   linux-lvm@redhat.com |   linux-lvm@redhat.com | ||||||
|   Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm |   Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm | ||||||
|  |  | ||||||
| Mailing lists for LVM2 development, patches and commits: |  | ||||||
|   lvm-devel@redhat.com |  | ||||||
|   Subscribe from https://www.redhat.com/mailman/listinfo/lvm-devel |  | ||||||
|  |  | ||||||
|   lvm2-commits@lists.fedorahosted.org (Read-only archive of commits) |  | ||||||
|   Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits |  | ||||||
|  |  | ||||||
| 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 |  | ||||||
|  |  | ||||||
| The source code repository used until 7th June 2012 is accessible here: |  | ||||||
|   http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2. |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1 +0,0 @@ | |||||||
| 1.02.138-git (2016-11-30) |  | ||||||
							
								
								
									
										1141
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							
							
						
						
									
										1141
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										234
									
								
								acinclude.m4
									
									
									
									
									
								
							
							
						
						
									
										234
									
								
								acinclude.m4
									
									
									
									
									
								
							| @@ -1,234 +0,0 @@ | |||||||
| dnl AC_GCC_VERSION |  | ||||||
| dnl check for compiler version |  | ||||||
| dnl sets COMPILER_VERSION and GCC_VERSION |  | ||||||
|  |  | ||||||
| AC_DEFUN([AC_CC_VERSION], |  | ||||||
| [ |  | ||||||
|     AC_MSG_CHECKING([C compiler version]) |  | ||||||
|     COMPILER_VERSION=`$CC -v 2>&1 | grep version` |  | ||||||
|     case "$COMPILER_VERSION" in |  | ||||||
|         *gcc*) |  | ||||||
| 	   dnl Ok, how to turn $3 into the real $3 |  | ||||||
| 	   GCC_VERSION=`echo $COMPILER_VERSION | \ |  | ||||||
| 	   sed -e 's/[[^ ]]*\ [[^ ]]*\ \([[^ ]]*\)\ .*/\1/'` ;; |  | ||||||
| 	*) GCC_VERSION=unknown ;; |  | ||||||
|     esac |  | ||||||
|     AC_MSG_RESULT($GCC_VERSION) |  | ||||||
| ]) |  | ||||||
|  |  | ||||||
| dnl AC_TRY_CCFLAG([CCFLAG], [VAR], [ACTION-IF-WORKS], [ACTION-IF-FAILS]) |  | ||||||
| dnl check if $CC supports a given flag |  | ||||||
|  |  | ||||||
| AC_DEFUN([AC_TRY_CCFLAG], |  | ||||||
| [ |  | ||||||
|     AC_REQUIRE([AC_PROG_CC]) |  | ||||||
|     ac_save_CFLAGS=$CFLAGS |  | ||||||
|     CFLAGS=$1 |  | ||||||
|     AC_CACHE_CHECK([whether $CC accepts $1 flag], [ac_cv_flag_$2], |  | ||||||
| 	[AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], |  | ||||||
| 			   [AS_VAR_SET([ac_cv_flag_$2], [yes])], |  | ||||||
| 			   [AS_VAR_SET([ac_cv_flag_$2], [no])])]) |  | ||||||
|     CFLAGS=$ac_save_CFLAGS |  | ||||||
|     $2=AS_VAR_GET([ac_cv_flag_$2]) |  | ||||||
|     if test "$2" = yes; then |  | ||||||
|         ifelse([$3], [], [:], [$3]) |  | ||||||
|     else |  | ||||||
|         ifelse([$4], [], [:], [$4]) |  | ||||||
|     fi |  | ||||||
| ]) |  | ||||||
|  |  | ||||||
| dnl AC_IF_YES([TEST-FOR-YES], [ACTION-IF-TRUE], [ACTION-IF-FALSE]) |  | ||||||
| dnl AS_IF() abstraction, checks shell variable for 'yes' |  | ||||||
| AC_DEFUN([AC_IF_YES], [AS_IF([test $$1 = yes], [$2], [$3])]) |  | ||||||
|  |  | ||||||
| dnl AC_TRY_LDFLAGS([LDFLAGS], [VAR], [ACTION-IF-WORKS], [ACTION-IF-FAILS]) |  | ||||||
| dnl check if $CC supports given ld flags |  | ||||||
|  |  | ||||||
| AC_DEFUN([AC_TRY_LDFLAGS], |  | ||||||
| [ |  | ||||||
|     AC_REQUIRE([AC_PROG_CC]) |  | ||||||
|     ac_save_LDFLAGS=$LDFLAGS |  | ||||||
|     LDFLAGS=$1 |  | ||||||
| 	AC_CACHE_CHECK([whether $CC accepts $1 ld flags], [ac_cv_flag_$2], |  | ||||||
| 	[AC_LINK_IFELSE([AC_LANG_PROGRAM()], |  | ||||||
| 			[AS_VAR_SET([ac_cv_flag_$2], [yes])], |  | ||||||
| 			[AS_VAR_SET([ac_cv_flag_$2], [no])])]) |  | ||||||
|     LDFLAGS=$ac_save_LDFLAGS |  | ||||||
|     $2=AS_VAR_GET([ac_cv_flag_$2]) |  | ||||||
|     if test "$2" = yes; then |  | ||||||
|         ifelse([$3], [], [:], [$3]) |  | ||||||
|     else |  | ||||||
|         ifelse([$4], [], [:], [$4]) |  | ||||||
|     fi |  | ||||||
| ]) |  | ||||||
|  |  | ||||||
| # =========================================================================== |  | ||||||
| #      http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html |  | ||||||
| # =========================================================================== |  | ||||||
| # |  | ||||||
| # SYNOPSIS |  | ||||||
| # |  | ||||||
| #   AX_GCC_BUILTIN(BUILTIN) |  | ||||||
| # |  | ||||||
| # DESCRIPTION |  | ||||||
| # |  | ||||||
| #   This macro checks if the compiler supports one of GCC's built-in |  | ||||||
| #   functions; many other compilers also provide those same built-ins. |  | ||||||
| # |  | ||||||
| #   The BUILTIN parameter is the name of the built-in function. |  | ||||||
| # |  | ||||||
| #   If BUILTIN is supported define HAVE_<BUILTIN>. Keep in mind that since |  | ||||||
| #   builtins usually start with two underscores they will be copied over |  | ||||||
| #   into the HAVE_<BUILTIN> definition (e.g. HAVE___BUILTIN_EXPECT for |  | ||||||
| #   __builtin_expect()). |  | ||||||
| # |  | ||||||
| #   The macro caches its result in the ax_cv_have_<BUILTIN> variable (e.g. |  | ||||||
| #   ax_cv_have___builtin_expect). |  | ||||||
| # |  | ||||||
| #   The macro currently supports the following built-in functions: |  | ||||||
| # |  | ||||||
| #    __builtin_assume_aligned |  | ||||||
| #    __builtin_bswap16 |  | ||||||
| #    __builtin_bswap32 |  | ||||||
| #    __builtin_bswap64 |  | ||||||
| #    __builtin_choose_expr |  | ||||||
| #    __builtin___clear_cache |  | ||||||
| #    __builtin_clrsb |  | ||||||
| #    __builtin_clrsbl |  | ||||||
| #    __builtin_clrsbll |  | ||||||
| #    __builtin_clz |  | ||||||
| #    __builtin_clzl |  | ||||||
| #    __builtin_clzll |  | ||||||
| #    __builtin_complex |  | ||||||
| #    __builtin_constant_p |  | ||||||
| #    __builtin_ctz |  | ||||||
| #    __builtin_ctzl |  | ||||||
| #    __builtin_ctzll |  | ||||||
| #    __builtin_expect |  | ||||||
| #    __builtin_ffs |  | ||||||
| #    __builtin_ffsl |  | ||||||
| #    __builtin_ffsll |  | ||||||
| #    __builtin_fpclassify |  | ||||||
| #    __builtin_huge_val |  | ||||||
| #    __builtin_huge_valf |  | ||||||
| #    __builtin_huge_vall |  | ||||||
| #    __builtin_inf |  | ||||||
| #    __builtin_infd128 |  | ||||||
| #    __builtin_infd32 |  | ||||||
| #    __builtin_infd64 |  | ||||||
| #    __builtin_inff |  | ||||||
| #    __builtin_infl |  | ||||||
| #    __builtin_isinf_sign |  | ||||||
| #    __builtin_nan |  | ||||||
| #    __builtin_nand128 |  | ||||||
| #    __builtin_nand32 |  | ||||||
| #    __builtin_nand64 |  | ||||||
| #    __builtin_nanf |  | ||||||
| #    __builtin_nanl |  | ||||||
| #    __builtin_nans |  | ||||||
| #    __builtin_nansf |  | ||||||
| #    __builtin_nansl |  | ||||||
| #    __builtin_object_size |  | ||||||
| #    __builtin_parity |  | ||||||
| #    __builtin_parityl |  | ||||||
| #    __builtin_parityll |  | ||||||
| #    __builtin_popcount |  | ||||||
| #    __builtin_popcountl |  | ||||||
| #    __builtin_popcountll |  | ||||||
| #    __builtin_powi |  | ||||||
| #    __builtin_powif |  | ||||||
| #    __builtin_powil |  | ||||||
| #    __builtin_prefetch |  | ||||||
| #    __builtin_trap |  | ||||||
| #    __builtin_types_compatible_p |  | ||||||
| #    __builtin_unreachable |  | ||||||
| # |  | ||||||
| #   Unsuppored built-ins will be tested with an empty parameter set and the |  | ||||||
| #   result of the check might be wrong or meaningless so use with care. |  | ||||||
| # |  | ||||||
| # LICENSE |  | ||||||
| # |  | ||||||
| #   Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com> |  | ||||||
| # |  | ||||||
| #   Copying and distribution of this file, with or without modification, are |  | ||||||
| #   permitted in any medium without royalty provided the copyright notice |  | ||||||
| #   and this notice are preserved.  This file is offered as-is, without any |  | ||||||
| #   warranty. |  | ||||||
|  |  | ||||||
| #serial 3 |  | ||||||
|  |  | ||||||
| AC_DEFUN([AX_GCC_BUILTIN], [ |  | ||||||
|     AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1]) |  | ||||||
|  |  | ||||||
|     AC_CACHE_CHECK([for $1], [ac_var], [ |  | ||||||
|         AC_LINK_IFELSE([AC_LANG_PROGRAM([], [ |  | ||||||
|             m4_case([$1], |  | ||||||
|                 [__builtin_assume_aligned], [$1("", 0)], |  | ||||||
|                 [__builtin_bswap16], [$1(0)], |  | ||||||
|                 [__builtin_bswap32], [$1(0)], |  | ||||||
|                 [__builtin_bswap64], [$1(0)], |  | ||||||
|                 [__builtin_choose_expr], [$1(0, 0, 0)], |  | ||||||
|                 [__builtin___clear_cache], [$1("", "")], |  | ||||||
|                 [__builtin_clrsb], [$1(0)], |  | ||||||
|                 [__builtin_clrsbl], [$1(0)], |  | ||||||
|                 [__builtin_clrsbll], [$1(0)], |  | ||||||
|                 [__builtin_clz], [$1(0)], |  | ||||||
|                 [__builtin_clzl], [$1(0)], |  | ||||||
|                 [__builtin_clzll], [$1(0)], |  | ||||||
|                 [__builtin_complex], [$1(0.0, 0.0)], |  | ||||||
|                 [__builtin_constant_p], [$1(0)], |  | ||||||
|                 [__builtin_ctz], [$1(0)], |  | ||||||
|                 [__builtin_ctzl], [$1(0)], |  | ||||||
|                 [__builtin_ctzll], [$1(0)], |  | ||||||
|                 [__builtin_expect], [$1(0, 0)], |  | ||||||
|                 [__builtin_ffs], [$1(0)], |  | ||||||
|                 [__builtin_ffsl], [$1(0)], |  | ||||||
|                 [__builtin_ffsll], [$1(0)], |  | ||||||
|                 [__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)], |  | ||||||
|                 [__builtin_huge_val], [$1()], |  | ||||||
|                 [__builtin_huge_valf], [$1()], |  | ||||||
|                 [__builtin_huge_vall], [$1()], |  | ||||||
|                 [__builtin_inf], [$1()], |  | ||||||
|                 [__builtin_infd128], [$1()], |  | ||||||
|                 [__builtin_infd32], [$1()], |  | ||||||
|                 [__builtin_infd64], [$1()], |  | ||||||
|                 [__builtin_inff], [$1()], |  | ||||||
|                 [__builtin_infl], [$1()], |  | ||||||
|                 [__builtin_isinf_sign], [$1(0.0)], |  | ||||||
|                 [__builtin_nan], [$1("")], |  | ||||||
|                 [__builtin_nand128], [$1("")], |  | ||||||
|                 [__builtin_nand32], [$1("")], |  | ||||||
|                 [__builtin_nand64], [$1("")], |  | ||||||
|                 [__builtin_nanf], [$1("")], |  | ||||||
|                 [__builtin_nanl], [$1("")], |  | ||||||
|                 [__builtin_nans], [$1("")], |  | ||||||
|                 [__builtin_nansf], [$1("")], |  | ||||||
|                 [__builtin_nansl], [$1("")], |  | ||||||
|                 [__builtin_object_size], [$1("", 0)], |  | ||||||
|                 [__builtin_parity], [$1(0)], |  | ||||||
|                 [__builtin_parityl], [$1(0)], |  | ||||||
|                 [__builtin_parityll], [$1(0)], |  | ||||||
|                 [__builtin_popcount], [$1(0)], |  | ||||||
|                 [__builtin_popcountl], [$1(0)], |  | ||||||
|                 [__builtin_popcountll], [$1(0)], |  | ||||||
|                 [__builtin_powi], [$1(0, 0)], |  | ||||||
|                 [__builtin_powif], [$1(0, 0)], |  | ||||||
|                 [__builtin_powil], [$1(0, 0)], |  | ||||||
|                 [__builtin_prefetch], [$1("")], |  | ||||||
|                 [__builtin_trap], [$1()], |  | ||||||
|                 [__builtin_types_compatible_p], [$1(int, int)], |  | ||||||
|                 [__builtin_unreachable], [$1()], |  | ||||||
|                 [m4_warn([syntax], [Unsupported built-in $1, the test may fail]) |  | ||||||
|                  $1()] |  | ||||||
|             ) |  | ||||||
|             ])], |  | ||||||
|             [AS_VAR_SET([ac_var], [yes])], |  | ||||||
|             [AS_VAR_SET([ac_var], [no])]) |  | ||||||
|     ]) |  | ||||||
|  |  | ||||||
|     AS_IF([test yes = AS_VAR_GET([ac_var])], |  | ||||||
|         [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1, |  | ||||||
|             [Define to 1 if the system has the `$1' built-in function])], []) |  | ||||||
|  |  | ||||||
|     AS_VAR_POPDEF([ac_var]) |  | ||||||
| ]) |  | ||||||
							
								
								
									
										540
									
								
								aclocal.m4
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										540
									
								
								aclocal.m4
									
									
									
									
										vendored
									
									
								
							| @@ -1,540 +0,0 @@ | |||||||
| # generated automatically by aclocal 1.15 -*- Autoconf -*- |  | ||||||
|  |  | ||||||
| # Copyright (C) 1996-2014 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. |  | ||||||
|  |  | ||||||
| m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) |  | ||||||
| # =========================================================================== |  | ||||||
| #     http://www.gnu.org/software/autoconf-archive/ax_python_module.html |  | ||||||
| # =========================================================================== |  | ||||||
| # |  | ||||||
| # SYNOPSIS |  | ||||||
| # |  | ||||||
| #   AX_PYTHON_MODULE(modname[, fatal, python]) |  | ||||||
| # |  | ||||||
| # DESCRIPTION |  | ||||||
| # |  | ||||||
| #   Checks for Python module. |  | ||||||
| # |  | ||||||
| #   If fatal is non-empty then absence of a module will trigger an error. |  | ||||||
| #   The third parameter can either be "python" for Python 2 or "python3" for |  | ||||||
| #   Python 3; defaults to Python 3. |  | ||||||
| # |  | ||||||
| # LICENSE |  | ||||||
| # |  | ||||||
| #   Copyright (c) 2008 Andrew Collier |  | ||||||
| # |  | ||||||
| #   Copying and distribution of this file, with or without modification, are |  | ||||||
| #   permitted in any medium without royalty provided the copyright notice |  | ||||||
| #   and this notice are preserved. This file is offered as-is, without any |  | ||||||
| #   warranty. |  | ||||||
|  |  | ||||||
| #serial 8 |  | ||||||
|  |  | ||||||
| AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE]) |  | ||||||
| AC_DEFUN([AX_PYTHON_MODULE],[ |  | ||||||
|     if test -z $PYTHON; |  | ||||||
|     then |  | ||||||
|         if test -z "$3"; |  | ||||||
|         then |  | ||||||
|             PYTHON="python3" |  | ||||||
|         else |  | ||||||
|             PYTHON="$3" |  | ||||||
|         fi |  | ||||||
|     fi |  | ||||||
|     PYTHON_NAME=`basename $PYTHON` |  | ||||||
|     AC_MSG_CHECKING($PYTHON_NAME module: $1) |  | ||||||
|     $PYTHON -c "import $1" 2>/dev/null |  | ||||||
|     if test $? -eq 0; |  | ||||||
|     then |  | ||||||
|         AC_MSG_RESULT(yes) |  | ||||||
|         eval AS_TR_CPP(HAVE_PYMOD_$1)=yes |  | ||||||
|     else |  | ||||||
|         AC_MSG_RESULT(no) |  | ||||||
|         eval AS_TR_CPP(HAVE_PYMOD_$1)=no |  | ||||||
|         # |  | ||||||
|         if test -n "$2" |  | ||||||
|         then |  | ||||||
|             AC_MSG_ERROR(failed to find required module $1) |  | ||||||
|             exit 1 |  | ||||||
|         fi |  | ||||||
|     fi |  | ||||||
| ]) |  | ||||||
|  |  | ||||||
| # 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|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) |  | ||||||
| m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) |  | ||||||
| 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` |  | ||||||
| 		      test "x$?" != "x0" && pkg_failed=yes ], |  | ||||||
| 		     [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 --cflags --libs "$2" 2>&1` |  | ||||||
|         else  |  | ||||||
| 	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$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])[]dnl |  | ||||||
|         ]) |  | ||||||
| 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/>.])[]dnl |  | ||||||
|         ]) |  | ||||||
| else |  | ||||||
| 	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS |  | ||||||
| 	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS |  | ||||||
|         AC_MSG_RESULT([yes]) |  | ||||||
| 	$3 |  | ||||||
| fi[]dnl |  | ||||||
| ])# PKG_CHECK_MODULES |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # PKG_INSTALLDIR(DIRECTORY) |  | ||||||
| # ------------------------- |  | ||||||
| # Substitutes the variable pkgconfigdir as the location where a module |  | ||||||
| # should install pkg-config .pc files. By default the directory is |  | ||||||
| # $libdir/pkgconfig, but the default can be changed by passing |  | ||||||
| # DIRECTORY. The user can override through the --with-pkgconfigdir |  | ||||||
| # parameter. |  | ||||||
| AC_DEFUN([PKG_INSTALLDIR], |  | ||||||
| [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) |  | ||||||
| m4_pushdef([pkg_description], |  | ||||||
|     [pkg-config installation directory @<:@]pkg_default[@:>@]) |  | ||||||
| AC_ARG_WITH([pkgconfigdir], |  | ||||||
|     [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, |  | ||||||
|     [with_pkgconfigdir=]pkg_default) |  | ||||||
| AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) |  | ||||||
| m4_popdef([pkg_default]) |  | ||||||
| m4_popdef([pkg_description]) |  | ||||||
| ]) dnl PKG_INSTALLDIR |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # PKG_NOARCH_INSTALLDIR(DIRECTORY) |  | ||||||
| # ------------------------- |  | ||||||
| # Substitutes the variable noarch_pkgconfigdir as the location where a |  | ||||||
| # module should install arch-independent pkg-config .pc files. By |  | ||||||
| # default the directory is $datadir/pkgconfig, but the default can be |  | ||||||
| # changed by passing DIRECTORY. The user can override through the |  | ||||||
| # --with-noarch-pkgconfigdir parameter. |  | ||||||
| AC_DEFUN([PKG_NOARCH_INSTALLDIR], |  | ||||||
| [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) |  | ||||||
| m4_pushdef([pkg_description], |  | ||||||
|     [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) |  | ||||||
| AC_ARG_WITH([noarch-pkgconfigdir], |  | ||||||
|     [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, |  | ||||||
|     [with_noarch_pkgconfigdir=]pkg_default) |  | ||||||
| AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) |  | ||||||
| m4_popdef([pkg_default]) |  | ||||||
| m4_popdef([pkg_description]) |  | ||||||
| ]) dnl PKG_NOARCH_INSTALLDIR |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, |  | ||||||
| # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) |  | ||||||
| # ------------------------------------------- |  | ||||||
| # Retrieves the value of the pkg-config variable for the given module. |  | ||||||
| AC_DEFUN([PKG_CHECK_VAR], |  | ||||||
| [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl |  | ||||||
| AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl |  | ||||||
|  |  | ||||||
| _PKG_CONFIG([$1], [variable="][$3]["], [$2]) |  | ||||||
| AS_VAR_COPY([$1], [pkg_cv_][$1]) |  | ||||||
|  |  | ||||||
| AS_VAR_IF([$1], [""], [$5], [$4])dnl |  | ||||||
| ])# PKG_CHECK_VAR |  | ||||||
|  |  | ||||||
| # Copyright (C) 1999-2014 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. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) |  | ||||||
| # --------------------------------------------------------------------------- |  | ||||||
| # Adds support for distributing Python modules and packages.  To |  | ||||||
| # install modules, copy them to $(pythondir), using the python_PYTHON |  | ||||||
| # automake variable.  To install a package with the same name as the |  | ||||||
| # automake package, install to $(pkgpythondir), or use the |  | ||||||
| # pkgpython_PYTHON automake variable. |  | ||||||
| # |  | ||||||
| # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as |  | ||||||
| # locations to install python extension modules (shared libraries). |  | ||||||
| # Another macro is required to find the appropriate flags to compile |  | ||||||
| # extension modules. |  | ||||||
| # |  | ||||||
| # If your package is configured with a different prefix to python, |  | ||||||
| # users will have to add the install directory to the PYTHONPATH |  | ||||||
| # environment variable, or create a .pth file (see the python |  | ||||||
| # documentation for details). |  | ||||||
| # |  | ||||||
| # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will |  | ||||||
| # cause an error if the version of python installed on the system |  | ||||||
| # doesn't meet the requirement.  MINIMUM-VERSION should consist of |  | ||||||
| # numbers and dots only. |  | ||||||
| AC_DEFUN([AM_PATH_PYTHON], |  | ||||||
|  [ |  | ||||||
|   dnl Find a Python interpreter.  Python versions prior to 2.0 are not |  | ||||||
|   dnl supported. (2.0 was released on October 16, 2000). |  | ||||||
|   m4_define_default([_AM_PYTHON_INTERPRETER_LIST], |  | ||||||
| [python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl |  | ||||||
|  python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) |  | ||||||
|  |  | ||||||
|   AC_ARG_VAR([PYTHON], [the Python interpreter]) |  | ||||||
|  |  | ||||||
|   m4_if([$1],[],[ |  | ||||||
|     dnl No version check is needed. |  | ||||||
|     # Find any Python interpreter. |  | ||||||
|     if test -z "$PYTHON"; then |  | ||||||
|       AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) |  | ||||||
|     fi |  | ||||||
|     am_display_PYTHON=python |  | ||||||
|   ], [ |  | ||||||
|     dnl A version check is needed. |  | ||||||
|     if test -n "$PYTHON"; then |  | ||||||
|       # If the user set $PYTHON, use it and don't search something else. |  | ||||||
|       AC_MSG_CHECKING([whether $PYTHON version is >= $1]) |  | ||||||
|       AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], |  | ||||||
| 			      [AC_MSG_RESULT([yes])], |  | ||||||
| 			      [AC_MSG_RESULT([no]) |  | ||||||
| 			       AC_MSG_ERROR([Python interpreter is too old])]) |  | ||||||
|       am_display_PYTHON=$PYTHON |  | ||||||
|     else |  | ||||||
|       # Otherwise, try each interpreter until we find one that satisfies |  | ||||||
|       # VERSION. |  | ||||||
|       AC_CACHE_CHECK([for a Python interpreter with version >= $1], |  | ||||||
| 	[am_cv_pathless_PYTHON],[ |  | ||||||
| 	for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do |  | ||||||
| 	  test "$am_cv_pathless_PYTHON" = none && break |  | ||||||
| 	  AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) |  | ||||||
| 	done]) |  | ||||||
|       # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. |  | ||||||
|       if test "$am_cv_pathless_PYTHON" = none; then |  | ||||||
| 	PYTHON=: |  | ||||||
|       else |  | ||||||
|         AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) |  | ||||||
|       fi |  | ||||||
|       am_display_PYTHON=$am_cv_pathless_PYTHON |  | ||||||
|     fi |  | ||||||
|   ]) |  | ||||||
|  |  | ||||||
|   if test "$PYTHON" = :; then |  | ||||||
|   dnl Run any user-specified action, or abort. |  | ||||||
|     m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) |  | ||||||
|   else |  | ||||||
|  |  | ||||||
|   dnl Query Python for its version number.  Getting [:3] seems to be |  | ||||||
|   dnl the best way to do this; it's what "site.py" does in the standard |  | ||||||
|   dnl library. |  | ||||||
|  |  | ||||||
|   AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], |  | ||||||
|     [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) |  | ||||||
|   AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) |  | ||||||
|  |  | ||||||
|   dnl Use the values of $prefix and $exec_prefix for the corresponding |  | ||||||
|   dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX.  These are made |  | ||||||
|   dnl distinct variables so they can be overridden if need be.  However, |  | ||||||
|   dnl general consensus is that you shouldn't need this ability. |  | ||||||
|  |  | ||||||
|   AC_SUBST([PYTHON_PREFIX], ['${prefix}']) |  | ||||||
|   AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) |  | ||||||
|  |  | ||||||
|   dnl At times (like when building shared libraries) you may want |  | ||||||
|   dnl to know which OS platform Python thinks this is. |  | ||||||
|  |  | ||||||
|   AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], |  | ||||||
|     [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) |  | ||||||
|   AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) |  | ||||||
|  |  | ||||||
|   # Just factor out some code duplication. |  | ||||||
|   am_python_setup_sysconfig="\ |  | ||||||
| import sys |  | ||||||
| # Prefer sysconfig over distutils.sysconfig, for better compatibility |  | ||||||
| # with python 3.x.  See automake bug#10227. |  | ||||||
| try: |  | ||||||
|     import sysconfig |  | ||||||
| except ImportError: |  | ||||||
|     can_use_sysconfig = 0 |  | ||||||
| else: |  | ||||||
|     can_use_sysconfig = 1 |  | ||||||
| # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: |  | ||||||
| # <https://github.com/pypa/virtualenv/issues/118> |  | ||||||
| try: |  | ||||||
|     from platform import python_implementation |  | ||||||
|     if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': |  | ||||||
|         can_use_sysconfig = 0 |  | ||||||
| except ImportError: |  | ||||||
|     pass" |  | ||||||
|  |  | ||||||
|   dnl Set up 4 directories: |  | ||||||
|  |  | ||||||
|   dnl pythondir -- where to install python scripts.  This is the |  | ||||||
|   dnl   site-packages directory, not the python standard library |  | ||||||
|   dnl   directory like in previous automake betas.  This behavior |  | ||||||
|   dnl   is more consistent with lispdir.m4 for example. |  | ||||||
|   dnl Query distutils for this directory. |  | ||||||
|   AC_CACHE_CHECK([for $am_display_PYTHON script directory], |  | ||||||
|     [am_cv_python_pythondir], |  | ||||||
|     [if test "x$prefix" = xNONE |  | ||||||
|      then |  | ||||||
|        am_py_prefix=$ac_default_prefix |  | ||||||
|      else |  | ||||||
|        am_py_prefix=$prefix |  | ||||||
|      fi |  | ||||||
|      am_cv_python_pythondir=`$PYTHON -c " |  | ||||||
| $am_python_setup_sysconfig |  | ||||||
| if can_use_sysconfig: |  | ||||||
|     sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) |  | ||||||
| else: |  | ||||||
|     from distutils import sysconfig |  | ||||||
|     sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') |  | ||||||
| sys.stdout.write(sitedir)"` |  | ||||||
|      case $am_cv_python_pythondir in |  | ||||||
|      $am_py_prefix*) |  | ||||||
|        am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` |  | ||||||
|        am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` |  | ||||||
|        ;; |  | ||||||
|      *) |  | ||||||
|        case $am_py_prefix in |  | ||||||
|          /usr|/System*) ;; |  | ||||||
|          *) |  | ||||||
| 	  am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages |  | ||||||
| 	  ;; |  | ||||||
|        esac |  | ||||||
|        ;; |  | ||||||
|      esac |  | ||||||
|     ]) |  | ||||||
|   AC_SUBST([pythondir], [$am_cv_python_pythondir]) |  | ||||||
|  |  | ||||||
|   dnl pkgpythondir -- $PACKAGE directory under pythondir.  Was |  | ||||||
|   dnl   PYTHON_SITE_PACKAGE in previous betas, but this naming is |  | ||||||
|   dnl   more consistent with the rest of automake. |  | ||||||
|  |  | ||||||
|   AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) |  | ||||||
|  |  | ||||||
|   dnl pyexecdir -- directory for installing python extension modules |  | ||||||
|   dnl   (shared libraries) |  | ||||||
|   dnl Query distutils for this directory. |  | ||||||
|   AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], |  | ||||||
|     [am_cv_python_pyexecdir], |  | ||||||
|     [if test "x$exec_prefix" = xNONE |  | ||||||
|      then |  | ||||||
|        am_py_exec_prefix=$am_py_prefix |  | ||||||
|      else |  | ||||||
|        am_py_exec_prefix=$exec_prefix |  | ||||||
|      fi |  | ||||||
|      am_cv_python_pyexecdir=`$PYTHON -c " |  | ||||||
| $am_python_setup_sysconfig |  | ||||||
| if can_use_sysconfig: |  | ||||||
|     sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) |  | ||||||
| else: |  | ||||||
|     from distutils import sysconfig |  | ||||||
|     sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') |  | ||||||
| sys.stdout.write(sitedir)"` |  | ||||||
|      case $am_cv_python_pyexecdir in |  | ||||||
|      $am_py_exec_prefix*) |  | ||||||
|        am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` |  | ||||||
|        am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` |  | ||||||
|        ;; |  | ||||||
|      *) |  | ||||||
|        case $am_py_exec_prefix in |  | ||||||
|          /usr|/System*) ;; |  | ||||||
|          *) |  | ||||||
| 	   am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages |  | ||||||
| 	   ;; |  | ||||||
|        esac |  | ||||||
|        ;; |  | ||||||
|      esac |  | ||||||
|     ]) |  | ||||||
|   AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) |  | ||||||
|  |  | ||||||
|   dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) |  | ||||||
|  |  | ||||||
|   AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) |  | ||||||
|  |  | ||||||
|   dnl Run any user-specified action. |  | ||||||
|   $2 |  | ||||||
|   fi |  | ||||||
|  |  | ||||||
| ]) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) |  | ||||||
| # --------------------------------------------------------------------------- |  | ||||||
| # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. |  | ||||||
| # Run ACTION-IF-FALSE otherwise. |  | ||||||
| # This test uses sys.hexversion instead of the string equivalent (first |  | ||||||
| # word of sys.version), in order to cope with versions such as 2.2c1. |  | ||||||
| # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). |  | ||||||
| AC_DEFUN([AM_PYTHON_CHECK_VERSION], |  | ||||||
|  [prog="import sys |  | ||||||
| # split strings by '.' and convert to numeric.  Append some zeros |  | ||||||
| # because we need at least 4 digits for the hex conversion. |  | ||||||
| # map returns an iterator in Python 3.0 and a list in 2.x |  | ||||||
| minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] |  | ||||||
| minverhex = 0 |  | ||||||
| # xrange is not present in Python 3.0 and range returns an iterator |  | ||||||
| for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] |  | ||||||
| sys.exit(sys.hexversion < minverhex)" |  | ||||||
|   AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) |  | ||||||
|  |  | ||||||
| # Copyright (C) 2001-2014 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. |  | ||||||
|  |  | ||||||
| # AM_RUN_LOG(COMMAND) |  | ||||||
| # ------------------- |  | ||||||
| # Run COMMAND, save the exit status in ac_status, and log it. |  | ||||||
| # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) |  | ||||||
| AC_DEFUN([AM_RUN_LOG], |  | ||||||
| [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD |  | ||||||
|    ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD |  | ||||||
|    ac_status=$? |  | ||||||
|    echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD |  | ||||||
|    (exit $ac_status); }]) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| m4_include([acinclude.m4]) |  | ||||||
							
								
								
									
										1120
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1120
									
								
								autoconf/config.guess
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										531
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										531
									
								
								autoconf/config.sub
									
									
									
									
										vendored
									
									
								
							| @@ -1,40 +1,42 @@ | |||||||
| #! /bin/sh | #! /bin/sh | ||||||
| # Configuration validation subroutine script. | # Configuration validation subroutine script. | ||||||
| #   Copyright 1992-2014 Free Software Foundation, Inc. | #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, | ||||||
|  | #   2000, 2001, 2002, 2003 Free Software Foundation, Inc. | ||||||
|  |  | ||||||
| timestamp='2014-01-01' | timestamp='2003-06-17' | ||||||
|  |  | ||||||
| # This file is free software; you can redistribute it and/or modify it | # This file is (in principle) common to ALL GNU software. | ||||||
| # under the terms of the GNU General Public License as published by | # The presence of a machine in this file suggests that SOME GNU software | ||||||
| # the Free Software Foundation; either version 3 of the License, or | # can handle that machine.  It does not imply ALL GNU software can. | ||||||
|  | # | ||||||
|  | # This file is free software; you can redistribute it and/or modify | ||||||
|  | # it under the terms of the GNU General Public License as published by | ||||||
|  | # the Free Software Foundation; either version 2 of the License, or | ||||||
| # (at your option) any later version. | # (at your option) any later version. | ||||||
| # | # | ||||||
| # This program is distributed in the hope that it will be useful, but | # This program is distributed in the hope that it will be useful, | ||||||
| # WITHOUT ANY WARRANTY; without even the implied warranty of | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| # General Public License for more details. | # GNU General Public License for more details. | ||||||
| # | # | ||||||
| # You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | ||||||
| # along with this program; if not, see <http://www.gnu.org/licenses/>. | # 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 | # As a special exception to the GNU General Public License, if you | ||||||
| # distribute this file as part of a program that contains a | # distribute this file as part of a program that contains a | ||||||
| # configuration script generated by Autoconf, you may include it under | # configuration script generated by Autoconf, you may include it under | ||||||
| # the same distribution terms that you use for the rest of that | # the same distribution terms that you use for the rest of that program. | ||||||
| # program.  This Exception is an additional permission under section 7 |  | ||||||
| # of the GNU General Public License, version 3 ("GPLv3"). |  | ||||||
|  |  | ||||||
|  | # Please send patches to <config-patches@gnu.org>.  Submit a context | ||||||
| # Please send patches with a ChangeLog entry to config-patches@gnu.org. | # diff and a properly formatted ChangeLog entry. | ||||||
| # | # | ||||||
| # Configuration subroutine to validate and canonicalize a configuration type. | # Configuration subroutine to validate and canonicalize a configuration type. | ||||||
| # Supply the specified configuration type as an argument. | # Supply the specified configuration type as an argument. | ||||||
| # If it is invalid, we print an error message on stderr and exit with code 1. | # If it is invalid, we print an error message on stderr and exit with code 1. | ||||||
| # Otherwise, we print the canonical config type on stdout and succeed. | # Otherwise, we print the canonical config type on stdout and succeed. | ||||||
|  |  | ||||||
| # You can get the latest version of this script from: |  | ||||||
| # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD |  | ||||||
|  |  | ||||||
| # This file is supposed to be the same for all GNU packages | # This file is supposed to be the same for all GNU packages | ||||||
| # and recognize all the CPU types, system types and aliases | # and recognize all the CPU types, system types and aliases | ||||||
| # that are meaningful with *any* GNU software. | # that are meaningful with *any* GNU software. | ||||||
| @@ -68,7 +70,8 @@ Report bugs and patches to <config-patches@gnu.org>." | |||||||
| version="\ | version="\ | ||||||
| GNU config.sub ($timestamp) | GNU config.sub ($timestamp) | ||||||
|  |  | ||||||
| Copyright 1992-2014 Free Software Foundation, Inc. | Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 | ||||||
|  | Free Software Foundation, Inc. | ||||||
|  |  | ||||||
| This is free software; see the source for copying conditions.  There is NO | This is free software; see the source for copying conditions.  There is NO | ||||||
| warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." | ||||||
| @@ -80,11 +83,11 @@ Try \`$me --help' for more information." | |||||||
| while test $# -gt 0 ; do | while test $# -gt 0 ; do | ||||||
|   case $1 in |   case $1 in | ||||||
|     --time-stamp | --time* | -t ) |     --time-stamp | --time* | -t ) | ||||||
|        echo "$timestamp" ; exit ;; |        echo "$timestamp" ; exit 0 ;; | ||||||
|     --version | -v ) |     --version | -v ) | ||||||
|        echo "$version" ; exit ;; |        echo "$version" ; exit 0 ;; | ||||||
|     --help | --h* | -h ) |     --help | --h* | -h ) | ||||||
|        echo "$usage"; exit ;; |        echo "$usage"; exit 0 ;; | ||||||
|     -- )     # Stop option processing |     -- )     # Stop option processing | ||||||
|        shift; break ;; |        shift; break ;; | ||||||
|     - )	# Use stdin as input. |     - )	# Use stdin as input. | ||||||
| @@ -96,7 +99,7 @@ while test $# -gt 0 ; do | |||||||
|     *local*) |     *local*) | ||||||
|        # First pass through any local machine types. |        # First pass through any local machine types. | ||||||
|        echo $1 |        echo $1 | ||||||
|        exit ;; |        exit 0;; | ||||||
|  |  | ||||||
|     * ) |     * ) | ||||||
|        break ;; |        break ;; | ||||||
| @@ -115,18 +118,10 @@ esac | |||||||
| # Here we must recognize all the valid KERNEL-OS combinations. | # Here we must recognize all the valid KERNEL-OS combinations. | ||||||
| maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` | maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` | ||||||
| case $maybe_os in | case $maybe_os in | ||||||
|   nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ |   nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) | ||||||
|   linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ |  | ||||||
|   knetbsd*-gnu* | netbsd*-gnu* | \ |  | ||||||
|   kopensolaris*-gnu* | \ |  | ||||||
|   storm-chaos* | os2-emx* | rtmk-nova*) |  | ||||||
|     os=-$maybe_os |     os=-$maybe_os | ||||||
|     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` |     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` | ||||||
|     ;; |     ;; | ||||||
|   android-linux) |  | ||||||
|     os=-linux-android |  | ||||||
|     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown |  | ||||||
|     ;; |  | ||||||
|   *) |   *) | ||||||
|     basic_machine=`echo $1 | sed 's/-[^-]*$//'` |     basic_machine=`echo $1 | sed 's/-[^-]*$//'` | ||||||
|     if [ $basic_machine != $1 ] |     if [ $basic_machine != $1 ] | ||||||
| @@ -149,13 +144,10 @@ case $os in | |||||||
| 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ | 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ | ||||||
| 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ | 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ | ||||||
| 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ | 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ | ||||||
| 	-apple | -axis | -knuth | -cray | -microblaze*) | 	-apple | -axis) | ||||||
| 		os= | 		os= | ||||||
| 		basic_machine=$1 | 		basic_machine=$1 | ||||||
| 		;; | 		;; | ||||||
| 	-bluegene*) |  | ||||||
| 		os=-cnk |  | ||||||
| 		;; |  | ||||||
| 	-sim | -cisco | -oki | -wec | -winbond) | 	-sim | -cisco | -oki | -wec | -winbond) | ||||||
| 		os= | 		os= | ||||||
| 		basic_machine=$1 | 		basic_machine=$1 | ||||||
| @@ -170,17 +162,13 @@ case $os in | |||||||
| 		os=-chorusos | 		os=-chorusos | ||||||
| 		basic_machine=$1 | 		basic_machine=$1 | ||||||
| 		;; | 		;; | ||||||
| 	-chorusrdb) |  	-chorusrdb) | ||||||
| 		os=-chorusrdb |  		os=-chorusrdb | ||||||
| 		basic_machine=$1 | 		basic_machine=$1 | ||||||
| 		;; |  		;; | ||||||
| 	-hiux*) | 	-hiux*) | ||||||
| 		os=-hiuxwe2 | 		os=-hiuxwe2 | ||||||
| 		;; | 		;; | ||||||
| 	-sco6) |  | ||||||
| 		os=-sco5v6 |  | ||||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` |  | ||||||
| 		;; |  | ||||||
| 	-sco5) | 	-sco5) | ||||||
| 		os=-sco3.2v5 | 		os=-sco3.2v5 | ||||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||||
| @@ -197,10 +185,6 @@ case $os in | |||||||
| 		# Don't forget version if it is 3.2v4 or newer. | 		# Don't forget version if it is 3.2v4 or newer. | ||||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||||
| 		;; | 		;; | ||||||
| 	-sco5v6*) |  | ||||||
| 		# Don't forget version if it is 3.2v4 or newer. |  | ||||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` |  | ||||||
| 		;; |  | ||||||
| 	-sco*) | 	-sco*) | ||||||
| 		os=-sco3.2v2 | 		os=-sco3.2v2 | ||||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||||
| @@ -218,12 +202,6 @@ case $os in | |||||||
| 	-isc*) | 	-isc*) | ||||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||||
| 		;; | 		;; | ||||||
| 	-lynx*178) |  | ||||||
| 		os=-lynxos178 |  | ||||||
| 		;; |  | ||||||
| 	-lynx*5) |  | ||||||
| 		os=-lynxos5 |  | ||||||
| 		;; |  | ||||||
| 	-lynx*) | 	-lynx*) | ||||||
| 		os=-lynxos | 		os=-lynxos | ||||||
| 		;; | 		;; | ||||||
| @@ -248,107 +226,55 @@ case $basic_machine in | |||||||
| 	# Some are omitted here because they have special meanings below. | 	# Some are omitted here because they have special meanings below. | ||||||
| 	1750a | 580 \ | 	1750a | 580 \ | ||||||
| 	| a29k \ | 	| a29k \ | ||||||
| 	| aarch64 | aarch64_be \ |  | ||||||
| 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | ||||||
| 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | ||||||
| 	| am33_2.0 \ | 	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | ||||||
| 	| arc | arceb \ | 	| c4x | clipper \ | ||||||
| 	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ |  | ||||||
| 	| avr | avr32 \ |  | ||||||
| 	| be32 | be64 \ |  | ||||||
| 	| bfin \ |  | ||||||
| 	| c4x | c8051 | clipper \ |  | ||||||
| 	| d10v | d30v | dlx | dsp16xx \ | 	| d10v | d30v | dlx | dsp16xx \ | ||||||
| 	| epiphany \ | 	| fr30 | frv \ | ||||||
| 	| fido | fr30 | frv \ |  | ||||||
| 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | ||||||
| 	| hexagon \ |  | ||||||
| 	| i370 | i860 | i960 | ia64 \ | 	| i370 | i860 | i960 | ia64 \ | ||||||
| 	| ip2k | iq2000 \ | 	| ip2k \ | ||||||
| 	| k1om \ | 	| m32r | m68000 | m68k | m88k | mcore \ | ||||||
| 	| le32 | le64 \ |  | ||||||
| 	| lm32 \ |  | ||||||
| 	| m32c | m32r | m32rle | m68000 | m68k | m88k \ |  | ||||||
| 	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \ |  | ||||||
| 	| mips | mipsbe | mipseb | mipsel | mipsle \ | 	| mips | mipsbe | mipseb | mipsel | mipsle \ | ||||||
| 	| mips16 \ | 	| mips16 \ | ||||||
| 	| mips64 | mips64el \ | 	| mips64 | mips64el \ | ||||||
| 	| mips64octeon | mips64octeonel \ |  | ||||||
| 	| mips64orion | mips64orionel \ |  | ||||||
| 	| mips64r5900 | mips64r5900el \ |  | ||||||
| 	| mips64vr | mips64vrel \ | 	| mips64vr | mips64vrel \ | ||||||
|  | 	| mips64orion | mips64orionel \ | ||||||
| 	| mips64vr4100 | mips64vr4100el \ | 	| mips64vr4100 | mips64vr4100el \ | ||||||
| 	| mips64vr4300 | mips64vr4300el \ | 	| mips64vr4300 | mips64vr4300el \ | ||||||
| 	| mips64vr5000 | mips64vr5000el \ | 	| mips64vr5000 | mips64vr5000el \ | ||||||
| 	| mips64vr5900 | mips64vr5900el \ |  | ||||||
| 	| mipsisa32 | mipsisa32el \ | 	| mipsisa32 | mipsisa32el \ | ||||||
| 	| mipsisa32r2 | mipsisa32r2el \ | 	| mipsisa32r2 | mipsisa32r2el \ | ||||||
| 	| mipsisa64 | mipsisa64el \ | 	| mipsisa64 | mipsisa64el \ | ||||||
| 	| mipsisa64r2 | mipsisa64r2el \ |  | ||||||
| 	| mipsisa64sb1 | mipsisa64sb1el \ | 	| mipsisa64sb1 | mipsisa64sb1el \ | ||||||
| 	| mipsisa64sr71k | mipsisa64sr71kel \ | 	| mipsisa64sr71k | mipsisa64sr71kel \ | ||||||
| 	| mipsr5900 | mipsr5900el \ |  | ||||||
| 	| mipstx39 | mipstx39el \ | 	| mipstx39 | mipstx39el \ | ||||||
| 	| mn10200 | mn10300 \ | 	| mn10200 | mn10300 \ | ||||||
| 	| moxie \ |  | ||||||
| 	| mt \ |  | ||||||
| 	| msp430 \ | 	| msp430 \ | ||||||
| 	| nds32 | nds32le | nds32be \ |  | ||||||
| 	| nios | nios2 | nios2eb | nios2el \ |  | ||||||
| 	| ns16k | ns32k \ | 	| ns16k | ns32k \ | ||||||
| 	| open8 \ | 	| openrisc | or32 \ | ||||||
| 	| or1k | or32 \ |  | ||||||
| 	| pdp10 | pdp11 | pj | pjl \ | 	| pdp10 | pdp11 | pj | pjl \ | ||||||
| 	| powerpc | powerpc64 | powerpc64le | powerpcle \ | 	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | ||||||
| 	| pyramid \ | 	| pyramid \ | ||||||
| 	| rl78 | rx \ | 	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | ||||||
| 	| score \ |  | ||||||
| 	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ |  | ||||||
| 	| sh64 | sh64le \ | 	| sh64 | sh64le \ | ||||||
| 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | 	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | ||||||
| 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | 	| strongarm \ | ||||||
| 	| spu \ | 	| tahoe | thumb | tic4x | tic80 | tron \ | ||||||
| 	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | 	| v850 | v850e \ | ||||||
| 	| ubicom32 \ |  | ||||||
| 	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ |  | ||||||
| 	| we32k \ | 	| we32k \ | ||||||
| 	| x86 | xc16x | xstormy16 | xtensa \ | 	| x86 | xscale | xstormy16 | xtensa \ | ||||||
| 	| z8k | z80) | 	| z8k) | ||||||
| 		basic_machine=$basic_machine-unknown | 		basic_machine=$basic_machine-unknown | ||||||
| 		;; | 		;; | ||||||
| 	c54x) | 	m6811 | m68hc11 | m6812 | m68hc12) | ||||||
| 		basic_machine=tic54x-unknown | 		# Motorola 68HC11/12. | ||||||
| 		;; |  | ||||||
| 	c55x) |  | ||||||
| 		basic_machine=tic55x-unknown |  | ||||||
| 		;; |  | ||||||
| 	c6x) |  | ||||||
| 		basic_machine=tic6x-unknown |  | ||||||
| 		;; |  | ||||||
| 	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) |  | ||||||
| 		basic_machine=$basic_machine-unknown | 		basic_machine=$basic_machine-unknown | ||||||
| 		os=-none | 		os=-none | ||||||
| 		;; | 		;; | ||||||
| 	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) | 	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) | ||||||
| 		;; | 		;; | ||||||
| 	ms1) |  | ||||||
| 		basic_machine=mt-unknown |  | ||||||
| 		;; |  | ||||||
|  |  | ||||||
| 	strongarm | thumb | xscale) |  | ||||||
| 		basic_machine=arm-unknown |  | ||||||
| 		;; |  | ||||||
| 	xgate) |  | ||||||
| 		basic_machine=$basic_machine-unknown |  | ||||||
| 		os=-none |  | ||||||
| 		;; |  | ||||||
| 	xscaleeb) |  | ||||||
| 		basic_machine=armeb-unknown |  | ||||||
| 		;; |  | ||||||
|  |  | ||||||
| 	xscaleel) |  | ||||||
| 		basic_machine=armel-unknown |  | ||||||
| 		;; |  | ||||||
|  |  | ||||||
| 	# We use `pc' rather than `unknown' | 	# We use `pc' rather than `unknown' | ||||||
| 	# because (1) that's what they normally are, and | 	# because (1) that's what they normally are, and | ||||||
| @@ -364,83 +290,58 @@ case $basic_machine in | |||||||
| 	# Recognize the basic CPU types with company name. | 	# Recognize the basic CPU types with company name. | ||||||
| 	580-* \ | 	580-* \ | ||||||
| 	| a29k-* \ | 	| a29k-* \ | ||||||
| 	| aarch64-* | aarch64_be-* \ |  | ||||||
| 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | ||||||
| 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | ||||||
| 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | ||||||
| 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \ | 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \ | ||||||
| 	| avr-* | avr32-* \ | 	| avr-* \ | ||||||
| 	| be32-* | be64-* \ | 	| bs2000-* \ | ||||||
| 	| bfin-* | bs2000-* \ | 	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | ||||||
| 	| c[123]* | c30-* | [cjt]90-* | c4x-* \ | 	| clipper-* | cydra-* \ | ||||||
| 	| c8051-* | clipper-* | craynv-* | cydra-* \ |  | ||||||
| 	| d10v-* | d30v-* | dlx-* \ | 	| d10v-* | d30v-* | dlx-* \ | ||||||
| 	| elxsi-* \ | 	| elxsi-* \ | ||||||
| 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | 	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | ||||||
| 	| h8300-* | h8500-* \ | 	| h8300-* | h8500-* \ | ||||||
| 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | ||||||
| 	| hexagon-* \ |  | ||||||
| 	| i*86-* | i860-* | i960-* | ia64-* \ | 	| i*86-* | i860-* | i960-* | ia64-* \ | ||||||
| 	| ip2k-* | iq2000-* \ | 	| ip2k-* \ | ||||||
| 	| k1om-* \ | 	| m32r-* \ | ||||||
| 	| le32-* | le64-* \ |  | ||||||
| 	| lm32-* \ |  | ||||||
| 	| m32c-* | m32r-* | m32rle-* \ |  | ||||||
| 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | ||||||
| 	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | 	| m88110-* | m88k-* | mcore-* \ | ||||||
| 	| microblaze-* | microblazeel-* \ |  | ||||||
| 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | ||||||
| 	| mips16-* \ | 	| mips16-* \ | ||||||
| 	| mips64-* | mips64el-* \ | 	| mips64-* | mips64el-* \ | ||||||
| 	| mips64octeon-* | mips64octeonel-* \ |  | ||||||
| 	| mips64orion-* | mips64orionel-* \ |  | ||||||
| 	| mips64r5900-* | mips64r5900el-* \ |  | ||||||
| 	| mips64vr-* | mips64vrel-* \ | 	| mips64vr-* | mips64vrel-* \ | ||||||
|  | 	| mips64orion-* | mips64orionel-* \ | ||||||
| 	| mips64vr4100-* | mips64vr4100el-* \ | 	| mips64vr4100-* | mips64vr4100el-* \ | ||||||
| 	| mips64vr4300-* | mips64vr4300el-* \ | 	| mips64vr4300-* | mips64vr4300el-* \ | ||||||
| 	| mips64vr5000-* | mips64vr5000el-* \ | 	| mips64vr5000-* | mips64vr5000el-* \ | ||||||
| 	| mips64vr5900-* | mips64vr5900el-* \ |  | ||||||
| 	| mipsisa32-* | mipsisa32el-* \ | 	| mipsisa32-* | mipsisa32el-* \ | ||||||
| 	| mipsisa32r2-* | mipsisa32r2el-* \ | 	| mipsisa32r2-* | mipsisa32r2el-* \ | ||||||
| 	| mipsisa64-* | mipsisa64el-* \ | 	| mipsisa64-* | mipsisa64el-* \ | ||||||
| 	| mipsisa64r2-* | mipsisa64r2el-* \ |  | ||||||
| 	| mipsisa64sb1-* | mipsisa64sb1el-* \ | 	| mipsisa64sb1-* | mipsisa64sb1el-* \ | ||||||
| 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \ | 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \ | ||||||
| 	| mipsr5900-* | mipsr5900el-* \ |  | ||||||
| 	| mipstx39-* | mipstx39el-* \ | 	| mipstx39-* | mipstx39el-* \ | ||||||
| 	| mmix-* \ |  | ||||||
| 	| mt-* \ |  | ||||||
| 	| msp430-* \ | 	| msp430-* \ | ||||||
| 	| nds32-* | nds32le-* | nds32be-* \ | 	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | ||||||
| 	| nios-* | nios2-* | nios2eb-* | nios2el-* \ |  | ||||||
| 	| none-* | np1-* | ns16k-* | ns32k-* \ |  | ||||||
| 	| open8-* \ |  | ||||||
| 	| orion-* \ | 	| orion-* \ | ||||||
| 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | ||||||
| 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | ||||||
| 	| pyramid-* \ | 	| pyramid-* \ | ||||||
| 	| rl78-* | romp-* | rs6000-* | rx-* \ | 	| romp-* | rs6000-* \ | ||||||
| 	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | 	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | ||||||
| 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | ||||||
| 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | 	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | ||||||
| 	| sparclite-* \ | 	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | ||||||
| 	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | 	| tahoe-* | thumb-* \ | ||||||
| 	| tahoe-* \ |  | ||||||
| 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | ||||||
| 	| tile*-* \ |  | ||||||
| 	| tron-* \ | 	| tron-* \ | ||||||
| 	| ubicom32-* \ | 	| v850-* | v850e-* | vax-* \ | ||||||
| 	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ |  | ||||||
| 	| vax-* \ |  | ||||||
| 	| we32k-* \ | 	| we32k-* \ | ||||||
| 	| x86-* | x86_64-* | xc16x-* | xps100-* \ | 	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | ||||||
| 	| xstormy16-* | xtensa*-* \ | 	| xtensa-* \ | ||||||
| 	| ymp-* \ | 	| ymp-* \ | ||||||
| 	| z8k-* | z80-*) | 	| z8k-*) | ||||||
| 		;; |  | ||||||
| 	# Recognize the basic CPU types without company name, with glob match. |  | ||||||
| 	xtensa*) |  | ||||||
| 		basic_machine=$basic_machine-unknown |  | ||||||
| 		;; | 		;; | ||||||
| 	# Recognize the various machine names and aliases which stand | 	# Recognize the various machine names and aliases which stand | ||||||
| 	# for a CPU type and a company and sometimes even an OS. | 	# for a CPU type and a company and sometimes even an OS. | ||||||
| @@ -458,9 +359,6 @@ case $basic_machine in | |||||||
| 		basic_machine=a29k-amd | 		basic_machine=a29k-amd | ||||||
| 		os=-udi | 		os=-udi | ||||||
| 		;; | 		;; | ||||||
| 	abacus) |  | ||||||
| 		basic_machine=abacus-unknown |  | ||||||
| 		;; |  | ||||||
| 	adobe68k) | 	adobe68k) | ||||||
| 		basic_machine=m68010-adobe | 		basic_machine=m68010-adobe | ||||||
| 		os=-scout | 		os=-scout | ||||||
| @@ -478,9 +376,6 @@ case $basic_machine in | |||||||
| 	amd64) | 	amd64) | ||||||
| 		basic_machine=x86_64-pc | 		basic_machine=x86_64-pc | ||||||
| 		;; | 		;; | ||||||
| 	amd64-*) |  | ||||||
| 		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		;; |  | ||||||
| 	amdahl) | 	amdahl) | ||||||
| 		basic_machine=580-amdahl | 		basic_machine=580-amdahl | ||||||
| 		os=-sysv | 		os=-sysv | ||||||
| @@ -504,10 +399,6 @@ case $basic_machine in | |||||||
| 		basic_machine=m68k-apollo | 		basic_machine=m68k-apollo | ||||||
| 		os=-bsd | 		os=-bsd | ||||||
| 		;; | 		;; | ||||||
| 	aros) |  | ||||||
| 		basic_machine=i386-pc |  | ||||||
| 		os=-aros |  | ||||||
| 		;; |  | ||||||
| 	aux) | 	aux) | ||||||
| 		basic_machine=m68k-apple | 		basic_machine=m68k-apple | ||||||
| 		os=-aux | 		os=-aux | ||||||
| @@ -516,35 +407,10 @@ case $basic_machine in | |||||||
| 		basic_machine=ns32k-sequent | 		basic_machine=ns32k-sequent | ||||||
| 		os=-dynix | 		os=-dynix | ||||||
| 		;; | 		;; | ||||||
| 	blackfin) |  | ||||||
| 		basic_machine=bfin-unknown |  | ||||||
| 		os=-linux |  | ||||||
| 		;; |  | ||||||
| 	blackfin-*) |  | ||||||
| 		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		os=-linux |  | ||||||
| 		;; |  | ||||||
| 	bluegene*) |  | ||||||
| 		basic_machine=powerpc-ibm |  | ||||||
| 		os=-cnk |  | ||||||
| 		;; |  | ||||||
| 	c54x-*) |  | ||||||
| 		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		;; |  | ||||||
| 	c55x-*) |  | ||||||
| 		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		;; |  | ||||||
| 	c6x-*) |  | ||||||
| 		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		;; |  | ||||||
| 	c90) | 	c90) | ||||||
| 		basic_machine=c90-cray | 		basic_machine=c90-cray | ||||||
| 		os=-unicos | 		os=-unicos | ||||||
| 		;; | 		;; | ||||||
| 	cegcc) |  | ||||||
| 		basic_machine=arm-unknown |  | ||||||
| 		os=-cegcc |  | ||||||
| 		;; |  | ||||||
| 	convex-c1) | 	convex-c1) | ||||||
| 		basic_machine=c1-convex | 		basic_machine=c1-convex | ||||||
| 		os=-bsd | 		os=-bsd | ||||||
| @@ -569,27 +435,12 @@ case $basic_machine in | |||||||
| 		basic_machine=j90-cray | 		basic_machine=j90-cray | ||||||
| 		os=-unicos | 		os=-unicos | ||||||
| 		;; | 		;; | ||||||
| 	craynv) |  | ||||||
| 		basic_machine=craynv-cray |  | ||||||
| 		os=-unicosmp |  | ||||||
| 		;; |  | ||||||
| 	cr16 | cr16-*) |  | ||||||
| 		basic_machine=cr16-unknown |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	crds | unos) | 	crds | unos) | ||||||
| 		basic_machine=m68k-crds | 		basic_machine=m68k-crds | ||||||
| 		;; | 		;; | ||||||
| 	crisv32 | crisv32-* | etraxfs*) |  | ||||||
| 		basic_machine=crisv32-axis |  | ||||||
| 		;; |  | ||||||
| 	cris | cris-* | etrax*) | 	cris | cris-* | etrax*) | ||||||
| 		basic_machine=cris-axis | 		basic_machine=cris-axis | ||||||
| 		;; | 		;; | ||||||
| 	crx) |  | ||||||
| 		basic_machine=crx-unknown |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	da30 | da30-*) | 	da30 | da30-*) | ||||||
| 		basic_machine=m68k-da30 | 		basic_machine=m68k-da30 | ||||||
| 		;; | 		;; | ||||||
| @@ -612,14 +463,6 @@ case $basic_machine in | |||||||
| 		basic_machine=m88k-motorola | 		basic_machine=m88k-motorola | ||||||
| 		os=-sysv3 | 		os=-sysv3 | ||||||
| 		;; | 		;; | ||||||
| 	dicos) |  | ||||||
| 		basic_machine=i686-pc |  | ||||||
| 		os=-dicos |  | ||||||
| 		;; |  | ||||||
| 	djgpp) |  | ||||||
| 		basic_machine=i586-pc |  | ||||||
| 		os=-msdosdjgpp |  | ||||||
| 		;; |  | ||||||
| 	dpx20 | dpx20-*) | 	dpx20 | dpx20-*) | ||||||
| 		basic_machine=rs6000-bull | 		basic_machine=rs6000-bull | ||||||
| 		os=-bosx | 		os=-bosx | ||||||
| @@ -731,6 +574,7 @@ case $basic_machine in | |||||||
| 	i370-ibm* | ibm*) | 	i370-ibm* | ibm*) | ||||||
| 		basic_machine=i370-ibm | 		basic_machine=i370-ibm | ||||||
| 		;; | 		;; | ||||||
|  | # I'm not sure what "Sysv32" means.  Should this be sysv3.2? | ||||||
| 	i*86v32) | 	i*86v32) | ||||||
| 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` | 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` | ||||||
| 		os=-sysv32 | 		os=-sysv32 | ||||||
| @@ -769,14 +613,6 @@ case $basic_machine in | |||||||
| 		basic_machine=m68k-isi | 		basic_machine=m68k-isi | ||||||
| 		os=-sysv | 		os=-sysv | ||||||
| 		;; | 		;; | ||||||
| 	m68knommu) |  | ||||||
| 		basic_machine=m68k-unknown |  | ||||||
| 		os=-linux |  | ||||||
| 		;; |  | ||||||
| 	m68knommu-*) |  | ||||||
| 		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		os=-linux |  | ||||||
| 		;; |  | ||||||
| 	m88k-omron*) | 	m88k-omron*) | ||||||
| 		basic_machine=m88k-omron | 		basic_machine=m88k-omron | ||||||
| 		;; | 		;; | ||||||
| @@ -788,21 +624,10 @@ case $basic_machine in | |||||||
| 		basic_machine=ns32k-utek | 		basic_machine=ns32k-utek | ||||||
| 		os=-sysv | 		os=-sysv | ||||||
| 		;; | 		;; | ||||||
| 	microblaze*) |  | ||||||
| 		basic_machine=microblaze-xilinx |  | ||||||
| 		;; |  | ||||||
| 	mingw64) |  | ||||||
| 		basic_machine=x86_64-pc |  | ||||||
| 		os=-mingw64 |  | ||||||
| 		;; |  | ||||||
| 	mingw32) | 	mingw32) | ||||||
| 		basic_machine=i686-pc | 		basic_machine=i386-pc | ||||||
| 		os=-mingw32 | 		os=-mingw32 | ||||||
| 		;; | 		;; | ||||||
| 	mingw32ce) |  | ||||||
| 		basic_machine=arm-unknown |  | ||||||
| 		os=-mingw32ce |  | ||||||
| 		;; |  | ||||||
| 	miniframe) | 	miniframe) | ||||||
| 		basic_machine=m68000-convergent | 		basic_machine=m68000-convergent | ||||||
| 		;; | 		;; | ||||||
| @@ -816,6 +641,10 @@ case $basic_machine in | |||||||
| 	mips3*) | 	mips3*) | ||||||
| 		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown | 		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown | ||||||
| 		;; | 		;; | ||||||
|  | 	mmix*) | ||||||
|  | 		basic_machine=mmix-knuth | ||||||
|  | 		os=-mmixware | ||||||
|  | 		;; | ||||||
| 	monitor) | 	monitor) | ||||||
| 		basic_machine=m68k-rom68k | 		basic_machine=m68k-rom68k | ||||||
| 		os=-coff | 		os=-coff | ||||||
| @@ -828,21 +657,10 @@ case $basic_machine in | |||||||
| 		basic_machine=i386-pc | 		basic_machine=i386-pc | ||||||
| 		os=-msdos | 		os=-msdos | ||||||
| 		;; | 		;; | ||||||
| 	ms1-*) |  | ||||||
| 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` |  | ||||||
| 		;; |  | ||||||
| 	msys) |  | ||||||
| 		basic_machine=i686-pc |  | ||||||
| 		os=-msys |  | ||||||
| 		;; |  | ||||||
| 	mvs) | 	mvs) | ||||||
| 		basic_machine=i370-ibm | 		basic_machine=i370-ibm | ||||||
| 		os=-mvs | 		os=-mvs | ||||||
| 		;; | 		;; | ||||||
| 	nacl) |  | ||||||
| 		basic_machine=le32-unknown |  | ||||||
| 		os=-nacl |  | ||||||
| 		;; |  | ||||||
| 	ncr3000) | 	ncr3000) | ||||||
| 		basic_machine=i486-ncr | 		basic_machine=i486-ncr | ||||||
| 		os=-sysv4 | 		os=-sysv4 | ||||||
| @@ -907,11 +725,9 @@ case $basic_machine in | |||||||
| 	np1) | 	np1) | ||||||
| 		basic_machine=np1-gould | 		basic_machine=np1-gould | ||||||
| 		;; | 		;; | ||||||
| 	neo-tandem) | 	nv1) | ||||||
| 		basic_machine=neo-tandem | 		basic_machine=nv1-cray | ||||||
| 		;; | 		os=-unicosmp | ||||||
| 	nse-tandem) |  | ||||||
| 		basic_machine=nse-tandem |  | ||||||
| 		;; | 		;; | ||||||
| 	nsr-tandem) | 	nsr-tandem) | ||||||
| 		basic_machine=nsr-tandem | 		basic_machine=nsr-tandem | ||||||
| @@ -920,12 +736,9 @@ case $basic_machine in | |||||||
| 		basic_machine=hppa1.1-oki | 		basic_machine=hppa1.1-oki | ||||||
| 		os=-proelf | 		os=-proelf | ||||||
| 		;; | 		;; | ||||||
| 	openrisc | openrisc-*) | 	or32 | or32-*) | ||||||
| 		basic_machine=or32-unknown | 		basic_machine=or32-unknown | ||||||
| 		;; | 		os=-coff | ||||||
| 	os400) |  | ||||||
| 		basic_machine=powerpc-ibm |  | ||||||
| 		os=-os400 |  | ||||||
| 		;; | 		;; | ||||||
| 	OSE68000 | ose68000) | 	OSE68000 | ose68000) | ||||||
| 		basic_machine=m68000-ericsson | 		basic_machine=m68000-ericsson | ||||||
| @@ -943,14 +756,6 @@ case $basic_machine in | |||||||
| 		basic_machine=i860-intel | 		basic_machine=i860-intel | ||||||
| 		os=-osf | 		os=-osf | ||||||
| 		;; | 		;; | ||||||
| 	parisc) |  | ||||||
| 		basic_machine=hppa-unknown |  | ||||||
| 		os=-linux |  | ||||||
| 		;; |  | ||||||
| 	parisc-*) |  | ||||||
| 		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		os=-linux |  | ||||||
| 		;; |  | ||||||
| 	pbd) | 	pbd) | ||||||
| 		basic_machine=sparc-tti | 		basic_machine=sparc-tti | ||||||
| 		;; | 		;; | ||||||
| @@ -960,12 +765,6 @@ case $basic_machine in | |||||||
| 	pc532 | pc532-*) | 	pc532 | pc532-*) | ||||||
| 		basic_machine=ns32k-pc532 | 		basic_machine=ns32k-pc532 | ||||||
| 		;; | 		;; | ||||||
| 	pc98) |  | ||||||
| 		basic_machine=i386-pc |  | ||||||
| 		;; |  | ||||||
| 	pc98-*) |  | ||||||
| 		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		;; |  | ||||||
| 	pentium | p5 | k5 | k6 | nexgen | viac3) | 	pentium | p5 | k5 | k6 | nexgen | viac3) | ||||||
| 		basic_machine=i586-pc | 		basic_machine=i586-pc | ||||||
| 		;; | 		;; | ||||||
| @@ -995,10 +794,9 @@ case $basic_machine in | |||||||
| 		;; | 		;; | ||||||
| 	power)	basic_machine=power-ibm | 	power)	basic_machine=power-ibm | ||||||
| 		;; | 		;; | ||||||
| 	ppc | ppcbe)	basic_machine=powerpc-unknown | 	ppc)	basic_machine=powerpc-unknown | ||||||
| 		;; | 		;; | ||||||
| 	ppc-* | ppcbe-*) | 	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` | ||||||
| 		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		;; | 		;; | ||||||
| 	ppcle | powerpclittle | ppc-le | powerpc-little) | 	ppcle | powerpclittle | ppc-le | powerpc-little) | ||||||
| 		basic_machine=powerpcle-unknown | 		basic_machine=powerpcle-unknown | ||||||
| @@ -1023,14 +821,6 @@ case $basic_machine in | |||||||
| 		basic_machine=i586-unknown | 		basic_machine=i586-unknown | ||||||
| 		os=-pw32 | 		os=-pw32 | ||||||
| 		;; | 		;; | ||||||
| 	rdos | rdos64) |  | ||||||
| 		basic_machine=x86_64-pc |  | ||||||
| 		os=-rdos |  | ||||||
| 		;; |  | ||||||
| 	rdos32) |  | ||||||
| 		basic_machine=i386-pc |  | ||||||
| 		os=-rdos |  | ||||||
| 		;; |  | ||||||
| 	rom68k) | 	rom68k) | ||||||
| 		basic_machine=m68k-rom68k | 		basic_machine=m68k-rom68k | ||||||
| 		os=-coff | 		os=-coff | ||||||
| @@ -1057,10 +847,6 @@ case $basic_machine in | |||||||
| 	sb1el) | 	sb1el) | ||||||
| 		basic_machine=mipsisa64sb1el-unknown | 		basic_machine=mipsisa64sb1el-unknown | ||||||
| 		;; | 		;; | ||||||
| 	sde) |  | ||||||
| 		basic_machine=mipsisa32-sde |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	sei) | 	sei) | ||||||
| 		basic_machine=mips-sei | 		basic_machine=mips-sei | ||||||
| 		os=-seiux | 		os=-seiux | ||||||
| @@ -1072,9 +858,6 @@ case $basic_machine in | |||||||
| 		basic_machine=sh-hitachi | 		basic_machine=sh-hitachi | ||||||
| 		os=-hms | 		os=-hms | ||||||
| 		;; | 		;; | ||||||
| 	sh5el) |  | ||||||
| 		basic_machine=sh5le-unknown |  | ||||||
| 		;; |  | ||||||
| 	sh64) | 	sh64) | ||||||
| 		basic_machine=sh64-unknown | 		basic_machine=sh64-unknown | ||||||
| 		;; | 		;; | ||||||
| @@ -1096,9 +879,6 @@ case $basic_machine in | |||||||
| 		basic_machine=i860-stratus | 		basic_machine=i860-stratus | ||||||
| 		os=-sysv4 | 		os=-sysv4 | ||||||
| 		;; | 		;; | ||||||
| 	strongarm-* | thumb-*) |  | ||||||
| 		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` |  | ||||||
| 		;; |  | ||||||
| 	sun2) | 	sun2) | ||||||
| 		basic_machine=m68000-sun | 		basic_machine=m68000-sun | ||||||
| 		;; | 		;; | ||||||
| @@ -1155,9 +935,17 @@ case $basic_machine in | |||||||
| 		basic_machine=t90-cray | 		basic_machine=t90-cray | ||||||
| 		os=-unicos | 		os=-unicos | ||||||
| 		;; | 		;; | ||||||
| 	tile*) | 	tic54x | c54x*) | ||||||
| 		basic_machine=$basic_machine-unknown | 		basic_machine=tic54x-unknown | ||||||
| 		os=-linux-gnu | 		os=-coff | ||||||
|  | 		;; | ||||||
|  | 	tic55x | c55x*) | ||||||
|  | 		basic_machine=tic55x-unknown | ||||||
|  | 		os=-coff | ||||||
|  | 		;; | ||||||
|  | 	tic6x | c6x*) | ||||||
|  | 		basic_machine=tic6x-unknown | ||||||
|  | 		os=-coff | ||||||
| 		;; | 		;; | ||||||
| 	tx39) | 	tx39) | ||||||
| 		basic_machine=mipstx39-unknown | 		basic_machine=mipstx39-unknown | ||||||
| @@ -1172,10 +960,6 @@ case $basic_machine in | |||||||
| 	tower | tower-32) | 	tower | tower-32) | ||||||
| 		basic_machine=m68k-ncr | 		basic_machine=m68k-ncr | ||||||
| 		;; | 		;; | ||||||
| 	tpf) |  | ||||||
| 		basic_machine=s390x-ibm |  | ||||||
| 		os=-tpf |  | ||||||
| 		;; |  | ||||||
| 	udi29k) | 	udi29k) | ||||||
| 		basic_machine=a29k-amd | 		basic_machine=a29k-amd | ||||||
| 		os=-udi | 		os=-udi | ||||||
| @@ -1219,16 +1003,9 @@ case $basic_machine in | |||||||
| 		basic_machine=hppa1.1-winbond | 		basic_machine=hppa1.1-winbond | ||||||
| 		os=-proelf | 		os=-proelf | ||||||
| 		;; | 		;; | ||||||
| 	xbox) |  | ||||||
| 		basic_machine=i686-pc |  | ||||||
| 		os=-mingw32 |  | ||||||
| 		;; |  | ||||||
| 	xps | xps100) | 	xps | xps100) | ||||||
| 		basic_machine=xps100-honeywell | 		basic_machine=xps100-honeywell | ||||||
| 		;; | 		;; | ||||||
| 	xscale-* | xscalee[bl]-*) |  | ||||||
| 		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` |  | ||||||
| 		;; |  | ||||||
| 	ymp) | 	ymp) | ||||||
| 		basic_machine=ymp-cray | 		basic_machine=ymp-cray | ||||||
| 		os=-unicos | 		os=-unicos | ||||||
| @@ -1237,10 +1014,6 @@ case $basic_machine in | |||||||
| 		basic_machine=z8k-unknown | 		basic_machine=z8k-unknown | ||||||
| 		os=-sim | 		os=-sim | ||||||
| 		;; | 		;; | ||||||
| 	z80-*-coff) |  | ||||||
| 		basic_machine=z80-unknown |  | ||||||
| 		os=-sim |  | ||||||
| 		;; |  | ||||||
| 	none) | 	none) | ||||||
| 		basic_machine=none-none | 		basic_machine=none-none | ||||||
| 		os=-none | 		os=-none | ||||||
| @@ -1260,9 +1033,6 @@ case $basic_machine in | |||||||
| 	romp) | 	romp) | ||||||
| 		basic_machine=romp-ibm | 		basic_machine=romp-ibm | ||||||
| 		;; | 		;; | ||||||
| 	mmix) |  | ||||||
| 		basic_machine=mmix-knuth |  | ||||||
| 		;; |  | ||||||
| 	rs6000) | 	rs6000) | ||||||
| 		basic_machine=rs6000-ibm | 		basic_machine=rs6000-ibm | ||||||
| 		;; | 		;; | ||||||
| @@ -1279,10 +1049,13 @@ case $basic_machine in | |||||||
| 	we32k) | 	we32k) | ||||||
| 		basic_machine=we32k-att | 		basic_machine=we32k-att | ||||||
| 		;; | 		;; | ||||||
| 	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) | 	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) | ||||||
| 		basic_machine=sh-unknown | 		basic_machine=sh-unknown | ||||||
| 		;; | 		;; | ||||||
| 	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) | 	sh64) | ||||||
|  | 		basic_machine=sh64-unknown | ||||||
|  | 		;; | ||||||
|  | 	sparc | sparcv9 | sparcv9b) | ||||||
| 		basic_machine=sparc-sun | 		basic_machine=sparc-sun | ||||||
| 		;; | 		;; | ||||||
| 	cydra) | 	cydra) | ||||||
| @@ -1326,12 +1099,9 @@ esac | |||||||
| if [ x"$os" != x"" ] | if [ x"$os" != x"" ] | ||||||
| then | then | ||||||
| case $os in | case $os in | ||||||
| 	# First match some system type aliases |         # First match some system type aliases | ||||||
| 	# that might get confused with valid system types. |         # that might get confused with valid system types. | ||||||
| 	# -solaris* is a basic system type, with this one exception. | 	# -solaris* is a basic system type, with this one exception. | ||||||
| 	-auroraux) |  | ||||||
| 		os=-auroraux |  | ||||||
| 		;; |  | ||||||
| 	-solaris1 | -solaris1.*) | 	-solaris1 | -solaris1.*) | ||||||
| 		os=`echo $os | sed -e 's|solaris1|sunos4|'` | 		os=`echo $os | sed -e 's|solaris1|sunos4|'` | ||||||
| 		;; | 		;; | ||||||
| @@ -1352,31 +1122,25 @@ case $os in | |||||||
| 	# Each alternative MUST END IN A *, to match a version number. | 	# Each alternative MUST END IN A *, to match a version number. | ||||||
| 	# -sysv* is not here because it comes later, after sysvr4. | 	# -sysv* is not here because it comes later, after sysvr4. | ||||||
| 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | ||||||
| 	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | 	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | ||||||
| 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | ||||||
| 	      | -sym* | -kopensolaris* | -plan9* \ |  | ||||||
| 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | ||||||
| 	      | -aos* | -aros* \ | 	      | -aos* \ | ||||||
| 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | ||||||
| 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | ||||||
| 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | 	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | ||||||
| 	      | -bitrig* | -openbsd* | -solidbsd* \ | 	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | ||||||
| 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ |  | ||||||
| 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ |  | ||||||
| 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | ||||||
| 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | ||||||
| 	      | -chorusos* | -chorusrdb* | -cegcc* \ | 	      | -chorusos* | -chorusrdb* \ | ||||||
| 	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | ||||||
| 	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | 	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | ||||||
| 	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \ |  | ||||||
| 	      | -uxpv* | -beos* | -mpeix* | -udk* \ |  | ||||||
| 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | ||||||
| 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | ||||||
| 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | ||||||
| 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | ||||||
| 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | ||||||
| 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei*) | ||||||
| 	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) |  | ||||||
| 	# Remember, each alternative MUST END IN *, to match a version number. | 	# Remember, each alternative MUST END IN *, to match a version number. | ||||||
| 		;; | 		;; | ||||||
| 	-qnx*) | 	-qnx*) | ||||||
| @@ -1394,15 +1158,12 @@ case $os in | |||||||
| 		os=`echo $os | sed -e 's|nto|nto-qnx|'` | 		os=`echo $os | sed -e 's|nto|nto-qnx|'` | ||||||
| 		;; | 		;; | ||||||
| 	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | 	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | ||||||
| 	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | 	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | ||||||
| 	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) | 	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) | ||||||
| 		;; | 		;; | ||||||
| 	-mac*) | 	-mac*) | ||||||
| 		os=`echo $os | sed -e 's|mac|macos|'` | 		os=`echo $os | sed -e 's|mac|macos|'` | ||||||
| 		;; | 		;; | ||||||
| 	-linux-dietlibc) |  | ||||||
| 		os=-linux-dietlibc |  | ||||||
| 		;; |  | ||||||
| 	-linux*) | 	-linux*) | ||||||
| 		os=`echo $os | sed -e 's|linux|linux-gnu|'` | 		os=`echo $os | sed -e 's|linux|linux-gnu|'` | ||||||
| 		;; | 		;; | ||||||
| @@ -1415,9 +1176,6 @@ case $os in | |||||||
| 	-opened*) | 	-opened*) | ||||||
| 		os=-openedition | 		os=-openedition | ||||||
| 		;; | 		;; | ||||||
| 	-os400*) |  | ||||||
| 		os=-os400 |  | ||||||
| 		;; |  | ||||||
| 	-wince*) | 	-wince*) | ||||||
| 		os=-wince | 		os=-wince | ||||||
| 		;; | 		;; | ||||||
| @@ -1439,9 +1197,6 @@ case $os in | |||||||
| 	-atheos*) | 	-atheos*) | ||||||
| 		os=-atheos | 		os=-atheos | ||||||
| 		;; | 		;; | ||||||
| 	-syllable*) |  | ||||||
| 		os=-syllable |  | ||||||
| 		;; |  | ||||||
| 	-386bsd) | 	-386bsd) | ||||||
| 		os=-bsd | 		os=-bsd | ||||||
| 		;; | 		;; | ||||||
| @@ -1464,9 +1219,6 @@ case $os in | |||||||
| 	-sinix*) | 	-sinix*) | ||||||
| 		os=-sysv4 | 		os=-sysv4 | ||||||
| 		;; | 		;; | ||||||
| 	-tpf*) |  | ||||||
| 		os=-tpf |  | ||||||
| 		;; |  | ||||||
| 	-triton*) | 	-triton*) | ||||||
| 		os=-sysv3 | 		os=-sysv3 | ||||||
| 		;; | 		;; | ||||||
| @@ -1500,13 +1252,8 @@ case $os in | |||||||
| 	-aros*) | 	-aros*) | ||||||
| 		os=-aros | 		os=-aros | ||||||
| 		;; | 		;; | ||||||
| 	-zvmoe) | 	-kaos*) | ||||||
| 		os=-zvmoe | 		os=-kaos | ||||||
| 		;; |  | ||||||
| 	-dicos*) |  | ||||||
| 		os=-dicos |  | ||||||
| 		;; |  | ||||||
| 	-nacl*) |  | ||||||
| 		;; | 		;; | ||||||
| 	-none) | 	-none) | ||||||
| 		;; | 		;; | ||||||
| @@ -1530,12 +1277,6 @@ else | |||||||
| # system, and we'll never get to this point. | # system, and we'll never get to this point. | ||||||
|  |  | ||||||
| case $basic_machine in | case $basic_machine in | ||||||
| 	score-*) |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	spu-*) |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	*-acorn) | 	*-acorn) | ||||||
| 		os=-riscix1.2 | 		os=-riscix1.2 | ||||||
| 		;; | 		;; | ||||||
| @@ -1545,24 +1286,9 @@ case $basic_machine in | |||||||
| 	arm*-semi) | 	arm*-semi) | ||||||
| 		os=-aout | 		os=-aout | ||||||
| 		;; | 		;; | ||||||
| 	c4x-* | tic4x-*) |     c4x-* | tic4x-*) | ||||||
| 		os=-coff |         os=-coff | ||||||
| 		;; |         ;; | ||||||
| 	c8051-*) |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	hexagon-*) |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	tic54x-*) |  | ||||||
| 		os=-coff |  | ||||||
| 		;; |  | ||||||
| 	tic55x-*) |  | ||||||
| 		os=-coff |  | ||||||
| 		;; |  | ||||||
| 	tic6x-*) |  | ||||||
| 		os=-coff |  | ||||||
| 		;; |  | ||||||
| 	# This must come before the *-dec entry. | 	# This must come before the *-dec entry. | ||||||
| 	pdp10-*) | 	pdp10-*) | ||||||
| 		os=-tops20 | 		os=-tops20 | ||||||
| @@ -1581,22 +1307,19 @@ case $basic_machine in | |||||||
| 		;; | 		;; | ||||||
| 	m68000-sun) | 	m68000-sun) | ||||||
| 		os=-sunos3 | 		os=-sunos3 | ||||||
|  | 		# This also exists in the configure program, but was not the | ||||||
|  | 		# default. | ||||||
|  | 		# os=-sunos4 | ||||||
| 		;; | 		;; | ||||||
| 	m68*-cisco) | 	m68*-cisco) | ||||||
| 		os=-aout | 		os=-aout | ||||||
| 		;; | 		;; | ||||||
| 	mep-*) |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	mips*-cisco) | 	mips*-cisco) | ||||||
| 		os=-elf | 		os=-elf | ||||||
| 		;; | 		;; | ||||||
| 	mips*-*) | 	mips*-*) | ||||||
| 		os=-elf | 		os=-elf | ||||||
| 		;; | 		;; | ||||||
| 	or1k-*) |  | ||||||
| 		os=-elf |  | ||||||
| 		;; |  | ||||||
| 	or32-*) | 	or32-*) | ||||||
| 		os=-coff | 		os=-coff | ||||||
| 		;; | 		;; | ||||||
| @@ -1609,15 +1332,9 @@ case $basic_machine in | |||||||
| 	*-be) | 	*-be) | ||||||
| 		os=-beos | 		os=-beos | ||||||
| 		;; | 		;; | ||||||
| 	*-haiku) |  | ||||||
| 		os=-haiku |  | ||||||
| 		;; |  | ||||||
| 	*-ibm) | 	*-ibm) | ||||||
| 		os=-aix | 		os=-aix | ||||||
| 		;; | 		;; | ||||||
| 	*-knuth) |  | ||||||
| 		os=-mmixware |  | ||||||
| 		;; |  | ||||||
| 	*-wec) | 	*-wec) | ||||||
| 		os=-proelf | 		os=-proelf | ||||||
| 		;; | 		;; | ||||||
| @@ -1720,7 +1437,7 @@ case $basic_machine in | |||||||
| 			-sunos*) | 			-sunos*) | ||||||
| 				vendor=sun | 				vendor=sun | ||||||
| 				;; | 				;; | ||||||
| 			-cnk*|-aix*) | 			-aix*) | ||||||
| 				vendor=ibm | 				vendor=ibm | ||||||
| 				;; | 				;; | ||||||
| 			-beos*) | 			-beos*) | ||||||
| @@ -1750,15 +1467,9 @@ case $basic_machine in | |||||||
| 			-mvs* | -opened*) | 			-mvs* | -opened*) | ||||||
| 				vendor=ibm | 				vendor=ibm | ||||||
| 				;; | 				;; | ||||||
| 			-os400*) |  | ||||||
| 				vendor=ibm |  | ||||||
| 				;; |  | ||||||
| 			-ptx*) | 			-ptx*) | ||||||
| 				vendor=sequent | 				vendor=sequent | ||||||
| 				;; | 				;; | ||||||
| 			-tpf*) |  | ||||||
| 				vendor=ibm |  | ||||||
| 				;; |  | ||||||
| 			-vxsim* | -vxworks* | -windiss*) | 			-vxsim* | -vxworks* | -windiss*) | ||||||
| 				vendor=wrs | 				vendor=wrs | ||||||
| 				;; | 				;; | ||||||
| @@ -1783,7 +1494,7 @@ case $basic_machine in | |||||||
| esac | esac | ||||||
|  |  | ||||||
| echo $basic_machine$os | echo $basic_machine$os | ||||||
| exit | exit 0 | ||||||
|  |  | ||||||
| # Local variables: | # Local variables: | ||||||
| # eval: (add-hook 'write-file-hooks 'time-stamp) | # eval: (add-hook 'write-file-hooks 'time-stamp) | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| #!/bin/sh | #!/bin/sh | ||||||
| # install - install a program, script, or datafile | # install - install a program, script, or datafile | ||||||
|  |  | ||||||
| scriptversion=2006-10-14.15 | scriptversion=2003-06-13.21 | ||||||
|  |  | ||||||
| # This originates from X11R5 (mit/util/scripts/install.sh), which was | # This originates from X11R5 (mit/util/scripts/install.sh), which was | ||||||
| # later released in X11R6 (xc/config/util/install.sh) with the | # later released in X11R6 (xc/config/util/install.sh) with the | ||||||
| @@ -39,24 +39,15 @@ scriptversion=2006-10-14.15 | |||||||
| # when there is no Makefile. | # when there is no Makefile. | ||||||
| # | # | ||||||
| # This script is compatible with the BSD install script, but was written | # This script is compatible with the BSD install script, but was written | ||||||
| # from scratch. | # from scratch.  It can only install one file at a time, a restriction | ||||||
|  | # shared with many OS's install programs. | ||||||
| nl=' |  | ||||||
| ' |  | ||||||
| IFS=" ""	$nl" |  | ||||||
|  |  | ||||||
| # set DOITPROG to echo to test this script | # set DOITPROG to echo to test this script | ||||||
|  |  | ||||||
| # Don't use :- since 4.3BSD and earlier shells don't like it. | # Don't use :- since 4.3BSD and earlier shells don't like it. | ||||||
| doit="${DOITPROG-}" | doit="${DOITPROG-}" | ||||||
| if test -z "$doit"; then |  | ||||||
|   doit_exec=exec |  | ||||||
| else |  | ||||||
|   doit_exec=$doit |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| # Put in absolute file names if you don't have them in your path; | # put in absolute paths if you don't have them in your path; or use env. vars. | ||||||
| # or use environment vars. |  | ||||||
|  |  | ||||||
| mvprog="${MVPROG-mv}" | mvprog="${MVPROG-mv}" | ||||||
| cpprog="${CPPROG-cp}" | cpprog="${CPPROG-cp}" | ||||||
| @@ -67,13 +58,10 @@ stripprog="${STRIPPROG-strip}" | |||||||
| rmprog="${RMPROG-rm}" | rmprog="${RMPROG-rm}" | ||||||
| mkdirprog="${MKDIRPROG-mkdir}" | mkdirprog="${MKDIRPROG-mkdir}" | ||||||
|  |  | ||||||
| posix_glob= | transformbasename= | ||||||
| posix_mkdir= | transform_arg= | ||||||
|  | instcmd="$mvprog" | ||||||
| # Desired mode of installed file. | chmodcmd="$chmodprog 0755" | ||||||
| mode=0755 |  | ||||||
|  |  | ||||||
| chmodcmd=$chmodprog |  | ||||||
| chowncmd= | chowncmd= | ||||||
| chgrpcmd= | chgrpcmd= | ||||||
| stripcmd= | stripcmd= | ||||||
| @@ -82,27 +70,22 @@ mvcmd="$mvprog" | |||||||
| src= | src= | ||||||
| dst= | dst= | ||||||
| dir_arg= | dir_arg= | ||||||
| dstarg= |  | ||||||
| no_target_directory= |  | ||||||
|  |  | ||||||
| usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE | usage="Usage: $0 [OPTION]... SRCFILE DSTFILE | ||||||
|    or: $0 [OPTION]... SRCFILES... DIRECTORY |    or: $0 -d DIR1 DIR2... | ||||||
|    or: $0 [OPTION]... -t DIRECTORY SRCFILES... |  | ||||||
|    or: $0 [OPTION]... -d DIRECTORIES... |  | ||||||
|  |  | ||||||
| In the 1st form, copy SRCFILE to DSTFILE. | In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default. | ||||||
| In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. | In the second, create the directory path DIR. | ||||||
| In the 4th, create DIRECTORIES. |  | ||||||
|  |  | ||||||
| Options: | Options: | ||||||
| -c         (ignored) | -b=TRANSFORMBASENAME | ||||||
|  | -c         copy source (using $cpprog) instead of moving (using $mvprog). | ||||||
| -d         create directories instead of installing files. | -d         create directories instead of installing files. | ||||||
| -g GROUP   $chgrpprog installed files to GROUP. | -g GROUP   $chgrp installed files to GROUP. | ||||||
| -m MODE    $chmodprog installed files to MODE. | -m MODE    $chmod installed files to MODE. | ||||||
| -o USER    $chownprog installed files to USER. | -o USER    $chown installed files to USER. | ||||||
| -s         $stripprog installed files. | -s         strip installed files (using $stripprog). | ||||||
| -t DIRECTORY  install into DIRECTORY. | -t=TRANSFORM | ||||||
| -T         report an error if DSTFILE is a directory. |  | ||||||
| --help     display this help and exit. | --help     display this help and exit. | ||||||
| --version  display version info and exit. | --version  display version info and exit. | ||||||
|  |  | ||||||
| @@ -110,9 +93,14 @@ Environment variables override the default commands: | |||||||
|   CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG |   CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG | ||||||
| " | " | ||||||
|  |  | ||||||
| while test $# -ne 0; do | while test -n "$1"; do | ||||||
|   case $1 in |   case $1 in | ||||||
|     -c) shift |     -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | ||||||
|  |         shift | ||||||
|  |         continue;; | ||||||
|  |  | ||||||
|  |     -c) instcmd=$cpprog | ||||||
|  |         shift | ||||||
|         continue;; |         continue;; | ||||||
|  |  | ||||||
|     -d) dir_arg=true |     -d) dir_arg=true | ||||||
| @@ -124,17 +112,11 @@ while test $# -ne 0; do | |||||||
|         shift |         shift | ||||||
|         continue;; |         continue;; | ||||||
|  |  | ||||||
|     --help) echo "$usage"; exit $?;; |     --help) echo "$usage"; exit 0;; | ||||||
|  |  | ||||||
|     -m) mode=$2 |     -m) chmodcmd="$chmodprog $2" | ||||||
|         shift |         shift | ||||||
|         shift |         shift | ||||||
| 	case $mode in |  | ||||||
| 	  *' '* | *'	'* | *' |  | ||||||
| '*	  | *'*'* | *'?'* | *'['*) |  | ||||||
| 	    echo "$0: invalid mode: $mode" >&2 |  | ||||||
| 	    exit 1;; |  | ||||||
| 	esac |  | ||||||
|         continue;; |         continue;; | ||||||
|  |  | ||||||
|     -o) chowncmd="$chownprog $2" |     -o) chowncmd="$chownprog $2" | ||||||
| @@ -146,358 +128,155 @@ while test $# -ne 0; do | |||||||
|         shift |         shift | ||||||
|         continue;; |         continue;; | ||||||
|  |  | ||||||
|     -t) dstarg=$2 |     -t=*) transformarg=`echo $1 | sed 's/-t=//'` | ||||||
| 	shift |         shift | ||||||
| 	shift |         continue;; | ||||||
| 	continue;; |  | ||||||
|  |  | ||||||
|     -T) no_target_directory=true |     --version) echo "$0 $scriptversion"; exit 0;; | ||||||
| 	shift |  | ||||||
| 	continue;; |  | ||||||
|  |  | ||||||
|     --version) echo "$0 $scriptversion"; exit $?;; |     *)  if test -z "$src"; then | ||||||
|  |           src=$1 | ||||||
|     --)	shift |         else | ||||||
| 	break;; |           # this colon is to work around a 386BSD /bin/sh bug | ||||||
|  |           : | ||||||
|     -*)	echo "$0: invalid option: $1" >&2 |           dst=$1 | ||||||
| 	exit 1;; |         fi | ||||||
|  |         shift | ||||||
|     *)  break;; |         continue;; | ||||||
|   esac |   esac | ||||||
| done | done | ||||||
|  |  | ||||||
| if test $# -ne 0 && test -z "$dir_arg$dstarg"; then | if test -z "$src"; then | ||||||
|   # When -d is used, all remaining arguments are directories to create. |   echo "$0: no input file specified." >&2 | ||||||
|   # When -t is used, the destination is already specified. |   exit 1 | ||||||
|   # Otherwise, the last argument is the destination.  Remove it from $@. | fi | ||||||
|   for arg |  | ||||||
|   do | if test -n "$dir_arg"; then | ||||||
|     if test -n "$dstarg"; then |   dst=$src | ||||||
|       # $@ is not empty: it contains at least $arg. |   src= | ||||||
|       set fnord "$@" "$dstarg" |  | ||||||
|       shift # fnord |   if test -d "$dst"; then | ||||||
|     fi |     instcmd=: | ||||||
|     shift # arg |     chmodcmd= | ||||||
|     dstarg=$arg |   else | ||||||
|  |     instcmd=$mkdirprog | ||||||
|  |   fi | ||||||
|  | else | ||||||
|  |   # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | ||||||
|  |   # might cause directories to be created, which would be especially bad | ||||||
|  |   # if $src (and thus $dsttmp) contains '*'. | ||||||
|  |   if test ! -f "$src" && test ! -d "$src"; then | ||||||
|  |     echo "$0: $src does not exist." >&2 | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  |  | ||||||
|  |   if test -z "$dst"; then | ||||||
|  |     echo "$0: no destination specified." >&2 | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  |  | ||||||
|  |   # If destination is a directory, append the input filename; won't work | ||||||
|  |   # if double slashes aren't ignored. | ||||||
|  |   if test -d "$dst"; then | ||||||
|  |     dst=$dst/`basename "$src"` | ||||||
|  |   fi | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | ## this sed command emulates the dirname command | ||||||
|  | dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | ||||||
|  |  | ||||||
|  | # Make sure that the destination directory exists. | ||||||
|  | # (this part is taken from Noah Friedman's mkinstalldirs script.) | ||||||
|  |  | ||||||
|  | # Skip lots of stat calls in the usual case. | ||||||
|  | if test ! -d "$dstdir"; then | ||||||
|  |   defaultIFS=' | ||||||
|  | 	' | ||||||
|  |   IFS="${IFS-$defaultIFS}" | ||||||
|  |  | ||||||
|  |   oIFS=$IFS | ||||||
|  |   # Some sh's can't handle IFS=/ for some reason. | ||||||
|  |   IFS='%' | ||||||
|  |   set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` | ||||||
|  |   IFS=$oIFS | ||||||
|  |  | ||||||
|  |   pathcomp= | ||||||
|  |  | ||||||
|  |   while test $# -ne 0 ; do | ||||||
|  |     pathcomp=$pathcomp$1 | ||||||
|  |     shift | ||||||
|  |     test -d "$pathcomp" || $mkdirprog "$pathcomp" | ||||||
|  |     pathcomp=$pathcomp/ | ||||||
|   done |   done | ||||||
| fi | fi | ||||||
|  |  | ||||||
| if test $# -eq 0; then | if test -n "$dir_arg"; then | ||||||
|   if test -z "$dir_arg"; then |   $doit $instcmd "$dst" \ | ||||||
|     echo "$0: no input file specified." >&2 |     && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ | ||||||
|     exit 1 |     && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ | ||||||
|   fi |     && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ | ||||||
|   # It's OK to call `install-sh -d' without argument. |     && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } | ||||||
|   # This can happen when creating conditional directories. |  | ||||||
|   exit 0 |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| if test -z "$dir_arg"; then | else | ||||||
|  |   # If we're going to rename the final executable, determine the name now. | ||||||
|  |   if test -z "$transformarg"; then | ||||||
|  |     dstfile=`basename "$dst"` | ||||||
|  |   else | ||||||
|  |     dstfile=`basename "$dst" $transformbasename \ | ||||||
|  |              | sed $transformarg`$transformbasename | ||||||
|  |   fi | ||||||
|  |  | ||||||
|  |   # don't allow the sed command to completely eliminate the filename. | ||||||
|  |   test -z "$dstfile" && dstfile=`basename "$dst"` | ||||||
|  |  | ||||||
|  |   # Make a couple of temp file names in the proper directory. | ||||||
|  |   dsttmp=$dstdir/_inst.$$_ | ||||||
|  |   rmtmp=$dstdir/_rm.$$_ | ||||||
|  |  | ||||||
|  |   # Trap to clean up those temp files at exit. | ||||||
|  |   trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 | ||||||
|   trap '(exit $?); exit' 1 2 13 15 |   trap '(exit $?); exit' 1 2 13 15 | ||||||
|  |  | ||||||
|   # Set umask so as not to create temps with too-generous modes. |   # Move or copy the file name to the temp name | ||||||
|   # However, 'strip' requires both read and write access to temps. |   $doit $instcmd "$src" "$dsttmp" && | ||||||
|   case $mode in |  | ||||||
|     # Optimize common cases. |  | ||||||
|     *644) cp_umask=133;; |  | ||||||
|     *755) cp_umask=22;; |  | ||||||
|  |  | ||||||
|     *[0-7]) |   # and set any options; do chmod last to preserve setuid bits. | ||||||
|       if test -z "$stripcmd"; then |   # | ||||||
| 	u_plus_rw= |   # If any of these fail, we abort the whole thing.  If we want to | ||||||
|       else |   # ignore errors from any of these, just make sure not to ignore | ||||||
| 	u_plus_rw='% 200' |   # errors from the above "$doit $instcmd $src $dsttmp" command. | ||||||
|       fi |   # | ||||||
|       cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; |   { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ | ||||||
|     *) |     && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ | ||||||
|       if test -z "$stripcmd"; then |     && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ | ||||||
| 	u_plus_rw= |     && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && | ||||||
|       else |  | ||||||
| 	u_plus_rw=,u+rw |  | ||||||
|       fi |  | ||||||
|       cp_umask=$mode$u_plus_rw;; |  | ||||||
|   esac |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| for src |   # Now remove or move aside any old file at destination location.  We | ||||||
| do |   # try this two ways since rm can't unlink itself on some systems and | ||||||
|   # Protect names starting with `-'. |   # the destination file might be busy for other reasons.  In this case, | ||||||
|   case $src in |   # the final cleanup might fail but the new file should still install | ||||||
|     -*) src=./$src ;; |   # successfully. | ||||||
|   esac |   { | ||||||
|  |     if test -f "$dstdir/$dstfile"; then | ||||||
|   if test -n "$dir_arg"; then |       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ | ||||||
|     dst=$src |       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ | ||||||
|     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 |  | ||||||
| 	  mkdir_mode= |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| 	posix_mkdir=false |  | ||||||
| 	case $umask in |  | ||||||
| 	  *[123567][0-7][0-7]) |  | ||||||
| 	    # POSIX mkdir -p sets u+wx bits regardless of umask, which |  | ||||||
| 	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0. |  | ||||||
| 	    ;; |  | ||||||
| 	  *) |  | ||||||
| 	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ |  | ||||||
| 	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 |  | ||||||
|  |  | ||||||
| 	    if (umask $mkdir_umask && |  | ||||||
| 		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 |  | ||||||
| 	    then |  | ||||||
| 	      if test -z "$dir_arg" || { |  | ||||||
| 		   # Check for POSIX incompatibilities with -m. |  | ||||||
| 		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or |  | ||||||
| 		   # other-writeable bit of parent directory when it shouldn't. |  | ||||||
| 		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. |  | ||||||
| 		   ls_ld_tmpdir=`ls -ld "$tmpdir"` |  | ||||||
| 		   case $ls_ld_tmpdir in |  | ||||||
| 		     d????-?r-*) different_mode=700;; |  | ||||||
| 		     d????-?--*) different_mode=755;; |  | ||||||
| 		     *) false;; |  | ||||||
| 		   esac && |  | ||||||
| 		   $mkdirprog -m$different_mode -p -- "$tmpdir" && { |  | ||||||
| 		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"` |  | ||||||
| 		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" |  | ||||||
| 		   } |  | ||||||
| 		 } |  | ||||||
| 	      then posix_mkdir=: |  | ||||||
| 	      fi |  | ||||||
| 	      rmdir "$tmpdir/d" "$tmpdir" |  | ||||||
| 	    else |  | ||||||
| 	      # Remove any dirs left behind by ancient mkdir implementations. |  | ||||||
| 	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null |  | ||||||
| 	    fi |  | ||||||
| 	    trap '' 0;; |  | ||||||
| 	esac;; |  | ||||||
|     esac |  | ||||||
|  |  | ||||||
|     if |  | ||||||
|       $posix_mkdir && ( |  | ||||||
| 	umask $mkdir_umask && |  | ||||||
| 	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" |  | ||||||
|       ) |  | ||||||
|     then : |  | ||||||
|     else |  | ||||||
|  |  | ||||||
|       # The umask is ridiculous, or mkdir does not conform to POSIX, |  | ||||||
|       # or it failed possibly due to a race condition.  Create the |  | ||||||
|       # directory the slow way, step by step, checking for races as we go. |  | ||||||
|  |  | ||||||
|       case $dstdir in |  | ||||||
| 	/*) prefix=/ ;; |  | ||||||
| 	-*) prefix=./ ;; |  | ||||||
| 	*)  prefix= ;; |  | ||||||
|       esac |  | ||||||
|  |  | ||||||
|       case $posix_glob in |  | ||||||
|         '') |  | ||||||
| 	  if (set -f) 2>/dev/null; then |  | ||||||
| 	    posix_glob=true |  | ||||||
| 	  else |  | ||||||
| 	    posix_glob=false |  | ||||||
| 	  fi ;; |  | ||||||
|       esac |  | ||||||
|  |  | ||||||
|       oIFS=$IFS |  | ||||||
|       IFS=/ |  | ||||||
|       $posix_glob && set -f |  | ||||||
|       set fnord $dstdir |  | ||||||
|       shift |  | ||||||
|       $posix_glob && set +f |  | ||||||
|       IFS=$oIFS |  | ||||||
|  |  | ||||||
|       prefixes= |  | ||||||
|  |  | ||||||
|       for d |  | ||||||
|       do |  | ||||||
| 	test -z "$d" && continue |  | ||||||
|  |  | ||||||
| 	prefix=$prefix$d |  | ||||||
| 	if test -d "$prefix"; then |  | ||||||
| 	  prefixes= |  | ||||||
| 	else |  | ||||||
| 	  if $posix_mkdir; then |  | ||||||
| 	    (umask=$mkdir_umask && |  | ||||||
| 	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break |  | ||||||
| 	    # Don't fail if two instances are running concurrently. |  | ||||||
| 	    test -d "$prefix" || exit 1 |  | ||||||
| 	  else |  | ||||||
| 	    case $prefix in |  | ||||||
| 	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; |  | ||||||
| 	      *) qprefix=$prefix;; |  | ||||||
| 	    esac |  | ||||||
| 	    prefixes="$prefixes '$qprefix'" |  | ||||||
| 	  fi |  | ||||||
| 	fi |  | ||||||
| 	prefix=$prefix/ |  | ||||||
|       done |  | ||||||
|  |  | ||||||
|       if test -n "$prefixes"; then |  | ||||||
| 	# Don't fail if two instances are running concurrently. |  | ||||||
| 	(umask $mkdir_umask && |  | ||||||
| 	 eval "\$doit_exec \$mkdirprog $prefixes") || |  | ||||||
| 	  test -d "$dstdir" || exit 1 |  | ||||||
| 	obsolete_mkdir_used=true |  | ||||||
|       fi |  | ||||||
|     fi |  | ||||||
|   fi |  | ||||||
|  |  | ||||||
|   if test -n "$dir_arg"; then |  | ||||||
|     { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && |  | ||||||
|     { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && |  | ||||||
|     { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || |  | ||||||
|       test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 |  | ||||||
|   else |  | ||||||
|  |  | ||||||
|     # Make a couple of temp file names in the proper directory. |  | ||||||
|     dsttmp=$dstdir/_inst.$$_ |  | ||||||
|     rmtmp=$dstdir/_rm.$$_ |  | ||||||
|  |  | ||||||
|     # Trap to clean up those temp files at exit. |  | ||||||
|     trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 |  | ||||||
|  |  | ||||||
|     # Copy the file name to the temp name. |  | ||||||
|     (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && |  | ||||||
|  |  | ||||||
|     # and set any options; do chmod last to preserve setuid bits. |  | ||||||
|     # |  | ||||||
|     # If any of these fail, we abort the whole thing.  If we want to |  | ||||||
|     # ignore errors from any of these, just make sure not to ignore |  | ||||||
|     # errors from the above "$doit $cpprog $src $dsttmp" command. |  | ||||||
|     # |  | ||||||
|     { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ |  | ||||||
|       && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ |  | ||||||
|       && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ |  | ||||||
|       && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && |  | ||||||
|  |  | ||||||
|     # Now rename the file to the real destination. |  | ||||||
|     { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \ |  | ||||||
|       || { |       || { | ||||||
| 	   # The rename failed, perhaps because mv can't rename something else | 	  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 | ||||||
| 	   # to itself, or perhaps because mv is so ancient that it does not | 	  (exit 1); exit | ||||||
| 	   # support -f. |       } | ||||||
|  |     else | ||||||
|  |       : | ||||||
|  |     fi | ||||||
|  |   } && | ||||||
|  |  | ||||||
| 	   # Now remove or move aside any old file at destination location. |   # Now rename the file to the real destination. | ||||||
| 	   # We try this two ways since rm can't unlink itself on some |   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" | ||||||
| 	   # systems and the destination file might be busy for other | fi && | ||||||
| 	   # 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. | # The final little trick to "correctly" pass the exit status to the exit trap. | ||||||
| 	   $doit $mvcmd "$dsttmp" "$dst" | { | ||||||
| 	 } |   (exit 0); exit | ||||||
|     } || exit 1 | } | ||||||
|  |  | ||||||
|     trap '' 0 |  | ||||||
|   fi |  | ||||||
| done |  | ||||||
|  |  | ||||||
| # Local variables: | # Local variables: | ||||||
| # eval: (add-hook 'write-file-hooks 'time-stamp) | # eval: (add-hook 'write-file-hooks 'time-stamp) | ||||||
|   | |||||||
| @@ -1,170 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| # py-compile - Compile a Python program |  | ||||||
|  |  | ||||||
| scriptversion=2011-06-08.12; # UTC |  | ||||||
|  |  | ||||||
| # Copyright (C) 2000-2014 Free Software Foundation, Inc. |  | ||||||
|  |  | ||||||
| # 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, 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, see <http://www.gnu.org/licenses/>. |  | ||||||
|  |  | ||||||
| # 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. |  | ||||||
|  |  | ||||||
| # This file is maintained in Automake, please report |  | ||||||
| # bugs to <bug-automake@gnu.org> or send patches to |  | ||||||
| # <automake-patches@gnu.org>. |  | ||||||
|  |  | ||||||
| if [ -z "$PYTHON" ]; then |  | ||||||
|   PYTHON=python |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| me=py-compile |  | ||||||
|  |  | ||||||
| usage_error () |  | ||||||
| { |  | ||||||
|   echo "$me: $*" >&2 |  | ||||||
|   echo "Try '$me --help' for more information." >&2 |  | ||||||
|   exit 1 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| basedir= |  | ||||||
| destdir= |  | ||||||
| while test $# -ne 0; do |  | ||||||
|   case "$1" in |  | ||||||
|     --basedir) |  | ||||||
|       if test $# -lt 2; then |  | ||||||
|         usage_error "option '--basedir' requires an argument" |  | ||||||
|       else |  | ||||||
|         basedir=$2 |  | ||||||
|       fi |  | ||||||
|       shift |  | ||||||
|       ;; |  | ||||||
|     --destdir) |  | ||||||
|       if test $# -lt 2; then |  | ||||||
|         usage_error "option '--destdir' requires an argument" |  | ||||||
|       else |  | ||||||
|         destdir=$2 |  | ||||||
|       fi |  | ||||||
|       shift |  | ||||||
|       ;; |  | ||||||
|     -h|--help) |  | ||||||
|       cat <<\EOF |  | ||||||
| Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..." |  | ||||||
|  |  | ||||||
| Byte compile some python scripts FILES.  Use --destdir to specify any |  | ||||||
| leading directory path to the FILES that you don't want to include in the |  | ||||||
| byte compiled file.  Specify --basedir for any additional path information you |  | ||||||
| do want to be shown in the byte compiled file. |  | ||||||
|  |  | ||||||
| Example: |  | ||||||
|   py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py |  | ||||||
|  |  | ||||||
| Report bugs to <bug-automake@gnu.org>. |  | ||||||
| EOF |  | ||||||
|       exit $? |  | ||||||
|       ;; |  | ||||||
|     -v|--version) |  | ||||||
|       echo "$me $scriptversion" |  | ||||||
|       exit $? |  | ||||||
|       ;; |  | ||||||
|     --) |  | ||||||
|       shift |  | ||||||
|       break |  | ||||||
|       ;; |  | ||||||
|     -*) |  | ||||||
|       usage_error "unrecognized option '$1'" |  | ||||||
|       ;; |  | ||||||
|     *) |  | ||||||
|       break |  | ||||||
|       ;; |  | ||||||
|   esac |  | ||||||
|   shift |  | ||||||
| done |  | ||||||
|  |  | ||||||
| files=$* |  | ||||||
| if test -z "$files"; then |  | ||||||
|     usage_error "no files given" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| # if basedir was given, then it should be prepended to filenames before |  | ||||||
| # byte compilation. |  | ||||||
| if [ -z "$basedir" ]; then |  | ||||||
|     pathtrans="path = file" |  | ||||||
| else |  | ||||||
|     pathtrans="path = os.path.join('$basedir', file)" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| # if destdir was given, then it needs to be prepended to the filename to |  | ||||||
| # byte compile but not go into the compiled file. |  | ||||||
| if [ -z "$destdir" ]; then |  | ||||||
|     filetrans="filepath = path" |  | ||||||
| else |  | ||||||
|     filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| $PYTHON -c " |  | ||||||
| import sys, os, py_compile, imp |  | ||||||
|  |  | ||||||
| files = '''$files''' |  | ||||||
|  |  | ||||||
| sys.stdout.write('Byte-compiling python modules...\n') |  | ||||||
| for file in files.split(): |  | ||||||
|     $pathtrans |  | ||||||
|     $filetrans |  | ||||||
|     if not os.path.exists(filepath) or not (len(filepath) >= 3 |  | ||||||
|                                             and filepath[-3:] == '.py'): |  | ||||||
| 	    continue |  | ||||||
|     sys.stdout.write(file) |  | ||||||
|     sys.stdout.flush() |  | ||||||
|     if hasattr(imp, 'get_tag'): |  | ||||||
|         py_compile.compile(filepath, imp.cache_from_source(filepath), path) |  | ||||||
|     else: |  | ||||||
|         py_compile.compile(filepath, filepath + 'c', path) |  | ||||||
| sys.stdout.write('\n')" || exit $? |  | ||||||
|  |  | ||||||
| # this will fail for python < 1.5, but that doesn't matter ... |  | ||||||
| $PYTHON -O -c " |  | ||||||
| import sys, os, py_compile, imp |  | ||||||
|  |  | ||||||
| # pypy does not use .pyo optimization |  | ||||||
| if hasattr(sys, 'pypy_translation_info'): |  | ||||||
|     sys.exit(0) |  | ||||||
|  |  | ||||||
| files = '''$files''' |  | ||||||
| sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n') |  | ||||||
| for file in files.split(): |  | ||||||
|     $pathtrans |  | ||||||
|     $filetrans |  | ||||||
|     if not os.path.exists(filepath) or not (len(filepath) >= 3 |  | ||||||
|                                             and filepath[-3:] == '.py'): |  | ||||||
| 	    continue |  | ||||||
|     sys.stdout.write(file) |  | ||||||
|     sys.stdout.flush() |  | ||||||
|     if hasattr(imp, 'get_tag'): |  | ||||||
|         py_compile.compile(filepath, imp.cache_from_source(filepath, False), path) |  | ||||||
|     else: |  | ||||||
|         py_compile.compile(filepath, filepath + 'o', path) |  | ||||||
| sys.stdout.write('\n')" 2>/dev/null || : |  | ||||||
|  |  | ||||||
| # Local Variables: |  | ||||||
| # mode: shell-script |  | ||||||
| # sh-indentation: 2 |  | ||||||
| # eval: (add-hook 'write-file-hooks 'time-stamp) |  | ||||||
| # time-stamp-start: "scriptversion=" |  | ||||||
| # time-stamp-format: "%:y-%02m-%02d.%02H" |  | ||||||
| # time-stamp-time-zone: "UTC" |  | ||||||
| # time-stamp-end: "; # UTC" |  | ||||||
| # End: |  | ||||||
							
								
								
									
										6
									
								
								conf/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								conf/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +0,0 @@ | |||||||
| command_profile_template.profile |  | ||||||
| example.conf |  | ||||||
| lvmlocal.conf |  | ||||||
| metadata_profile_template.profile |  | ||||||
| configure.h |  | ||||||
| lvm-version.h |  | ||||||
| @@ -1,58 +0,0 @@ | |||||||
| # |  | ||||||
| # Copyright (C) 2004-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  |  | ||||||
| srcdir = @srcdir@ |  | ||||||
| top_srcdir = @top_srcdir@ |  | ||||||
| top_builddir = @top_builddir@ |  | ||||||
|  |  | ||||||
| CONFSRC=example.conf |  | ||||||
| CONFDEST=lvm.conf |  | ||||||
| CONFLOCAL=lvmlocal.conf |  | ||||||
|  |  | ||||||
| PROFILE_TEMPLATES=command_profile_template.profile metadata_profile_template.profile |  | ||||||
| PROFILES=$(PROFILE_TEMPLATES) \ |  | ||||||
| 	$(srcdir)/cache-mq.profile \ |  | ||||||
| 	$(srcdir)/cache-smq.profile \ |  | ||||||
| 	$(srcdir)/thin-generic.profile \ |  | ||||||
| 	$(srcdir)/thin-performance.profile \ |  | ||||||
| 	$(srcdir)/lvmdbusd.profile |  | ||||||
|  |  | ||||||
| include $(top_builddir)/make.tmpl |  | ||||||
|  |  | ||||||
| .PHONY: install_conf install_localconf install_profiles |  | ||||||
|  |  | ||||||
| generate: |  | ||||||
| 	(cat $(top_srcdir)/conf/example.conf.base && LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withcomments --ignorelocal --withspaces) > example.conf.in |  | ||||||
| 	(cat $(top_srcdir)/conf/lvmlocal.conf.base && LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withcomments --withspaces local) > lvmlocal.conf.in |  | ||||||
|  |  | ||||||
| install_conf: $(CONFSRC) |  | ||||||
| 	@if [ ! -e $(confdir)/$(CONFDEST) ]; then \ |  | ||||||
| 		echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST)"; \ |  | ||||||
| 		$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST); \ |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| install_localconf: $(CONFLOCAL) |  | ||||||
| 	@if [ ! -e $(confdir)/$(CONFLOCAL) ]; then \ |  | ||||||
| 		echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFLOCAL)"; \ |  | ||||||
| 		$(INSTALL_WDATA) -D $< $(confdir)/$(CONFLOCAL); \ |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| install_profiles: $(PROFILES) |  | ||||||
| 	$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_PROFILE_DIR) |  | ||||||
| 	$(INSTALL_DATA) $(PROFILES) $(DESTDIR)$(DEFAULT_PROFILE_DIR)/ |  | ||||||
|  |  | ||||||
| install_lvm2: install_conf install_localconf install_profiles |  | ||||||
|  |  | ||||||
| install: install_lvm2 |  | ||||||
|  |  | ||||||
| DISTCLEAN_TARGETS += $(CONFSRC) $(CONFLOCAL) $(PROFILE_TEMPLATES) |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| # Demo configuration 'mq' cache policy |  | ||||||
| # |  | ||||||
| # Note: This policy has been deprecated in favor of the smq policy |  | ||||||
| # keyword "default" means, setting is left with kernel defaults. |  | ||||||
| # |  | ||||||
|  |  | ||||||
| allocation { |  | ||||||
| 	cache_pool_chunk_size = 64 |  | ||||||
| 	cache_mode = "writethrough" |  | ||||||
| 	cache_policy = "mq" |  | ||||||
| 	cache_settings { |  | ||||||
| 		mq { |  | ||||||
| 			sequential_threshold = "default"	#  #nr_sequential_ios |  | ||||||
| 			random_threshold = "default"		#  #nr_random_ios |  | ||||||
| 			read_promote_adjustment = "default" |  | ||||||
| 			write_promote_adjustment = "default" |  | ||||||
| 			discard_promote_adjustment = "default" |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
| # Demo configuration 'smq' cache policy |  | ||||||
| # |  | ||||||
| # The stochastic multi-queue (smq) policy addresses some of the problems |  | ||||||
| # with the multiqueue (mq) policy and uses less memory. |  | ||||||
| # |  | ||||||
|  |  | ||||||
| allocation { |  | ||||||
| 	cache_pool_chunk_size = 64 |  | ||||||
| 	cache_mode = "writethrough" |  | ||||||
| 	cache_policy = "smq" |  | ||||||
| 	cache_settings { |  | ||||||
| 	        # currently no settins for "smq" policy |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,74 +0,0 @@ | |||||||
| # This is a command profile template for the LVM2 system. |  | ||||||
| # |  | ||||||
| # It contains all configuration settings that are customizable by command |  | ||||||
| # profiles. To create a new command profile, select the settings you want |  | ||||||
| # to customize and add them in a new file named <profile_name>.profile. |  | ||||||
| # Then install the new profile in a directory as defined by config/profile_dir |  | ||||||
| # setting found in @DEFAULT_SYS_DIR@/lvm.conf file. |  | ||||||
| # |  | ||||||
| # Command profiles can be referenced by using the --commandprofile option then. |  | ||||||
| # |  | ||||||
| # Refer to 'man lvm.conf' for further information about profiles and |  | ||||||
| # general configuration file layout. |  | ||||||
| # |  | ||||||
| allocation { |  | ||||||
| 	cache_mode="writethrough" |  | ||||||
| 	cache_settings { |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| log { |  | ||||||
| 	report_command_log=0 |  | ||||||
| 	command_log_sort="log_seq_num" |  | ||||||
| 	command_log_cols="log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code" |  | ||||||
| 	command_log_selection="!(log_type=status && message=success)" |  | ||||||
| } |  | ||||||
| global { |  | ||||||
| 	units="h" |  | ||||||
| 	si_unit_consistency=1 |  | ||||||
| 	suffix=1 |  | ||||||
| 	lvdisplay_shows_full_device_path=0 |  | ||||||
| } |  | ||||||
| report { |  | ||||||
| 	output_format="basic" |  | ||||||
| 	compact_output=0 |  | ||||||
| 	compact_output_cols="" |  | ||||||
| 	aligned=1 |  | ||||||
| 	buffered=1 |  | ||||||
| 	headings=1 |  | ||||||
| 	separator=" " |  | ||||||
| 	list_item_separator="," |  | ||||||
| 	prefixes=0 |  | ||||||
| 	quoted=1 |  | ||||||
| 	columns_as_rows=0 |  | ||||||
| 	binary_values_as_numeric=0 |  | ||||||
| 	time_format="%Y-%m-%d %T %z" |  | ||||||
| 	devtypes_sort="devtype_name" |  | ||||||
| 	devtypes_cols="devtype_name,devtype_max_partitions,devtype_description" |  | ||||||
| 	devtypes_cols_verbose="devtype_name,devtype_max_partitions,devtype_description" |  | ||||||
| 	lvs_sort="vg_name,lv_name" |  | ||||||
| 	lvs_cols="lv_name,vg_name,lv_attr,lv_size,pool_lv,origin,data_percent,metadata_percent,move_pv,mirror_log,copy_percent,convert_lv" |  | ||||||
| 	lvs_cols_verbose="lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,pool_lv,origin,data_percent,metadata_percent,move_pv,copy_percent,mirror_log,convert_lv,lv_uuid,lv_profile" |  | ||||||
| 	vgs_sort="vg_name" |  | ||||||
| 	vgs_cols="vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free" |  | ||||||
| 	vgs_cols_verbose="vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid,vg_profile" |  | ||||||
| 	pvs_sort="pv_name" |  | ||||||
| 	pvs_cols="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free" |  | ||||||
| 	pvs_cols_verbose="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid" |  | ||||||
| 	segs_sort="vg_name,lv_name,seg_start" |  | ||||||
| 	segs_cols="lv_name,vg_name,lv_attr,stripes,segtype,seg_size" |  | ||||||
| 	segs_cols_verbose="lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize" |  | ||||||
| 	pvsegs_sort="pv_name,pvseg_start" |  | ||||||
| 	pvsegs_cols="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size" |  | ||||||
| 	pvsegs_cols_verbose="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges" |  | ||||||
| 	vgs_cols_full="vg_all" |  | ||||||
| 	pvs_cols_full="pv_all" |  | ||||||
| 	lvs_cols_full="lv_all" |  | ||||||
| 	pvsegs_cols_full="pvseg_all,pv_uuid,lv_uuid" |  | ||||||
| 	segs_cols_full="seg_all,lv_uuid" |  | ||||||
| 	vgs_sort_full="vg_name" |  | ||||||
| 	pvs_sort_full="pv_name" |  | ||||||
| 	lvs_sort_full="vg_name,lv_name" |  | ||||||
| 	pvsegs_sort_full="pv_uuid,pvseg_start" |  | ||||||
| 	segs_sort_full="lv_uuid,seg_start" |  | ||||||
| 	mark_hidden_devices=1 |  | ||||||
| } |  | ||||||
| @@ -1,23 +0,0 @@ | |||||||
| # 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. |  | ||||||
| # |  | ||||||
| # Refer to 'man lvm.conf' for information about how settings configured in |  | ||||||
| # this file are combined with built-in values and command line options to |  | ||||||
| # arrive at the final values used by LVM. |  | ||||||
| # |  | ||||||
| # Refer to 'man lvmconfig' for information about displaying the built-in |  | ||||||
| # and configured values used by LVM. |  | ||||||
| # |  | ||||||
| # If a default value is set in this file (not commented out), then a |  | ||||||
| # new version of LVM using this file will continue using that value, |  | ||||||
| # even if the new version of LVM changes the built-in default value. |  | ||||||
| # |  | ||||||
| # 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. |  | ||||||
|  |  | ||||||
							
								
								
									
										2104
									
								
								conf/example.conf.in
									
									
									
									
									
								
							
							
						
						
									
										2104
									
								
								conf/example.conf.in
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,50 +0,0 @@ | |||||||
| # |  | ||||||
| # DO NOT EDIT THIS FILE! |  | ||||||
| # |  | ||||||
| # LVM configuration profile used by lvmdbusd daemon. |  | ||||||
| # |  | ||||||
| # This sets up LVM to produce output in the most suitable format for processing |  | ||||||
| # by lvmdbusd daemon which utilizes LVM shell to execute LVM commands. |  | ||||||
| # |  | ||||||
| # Do not edit this file in any way. This profile is distributed together with |  | ||||||
| # lvmdbusd and it contains configuration that is important for lvmdbusd to |  | ||||||
| # cooperate and interface with LVM correctly. |  | ||||||
| # |  | ||||||
|  |  | ||||||
| global { |  | ||||||
| 	# use bytes for expected and deterministic output |  | ||||||
| 	units=b |  | ||||||
| 	# no need for suffix if we have units set |  | ||||||
| 	suffix=0 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| report { |  | ||||||
| 	compact_output=0 |  | ||||||
| 	compact_output_cols="" |  | ||||||
| 	binary_values_as_numeric=0 |  | ||||||
| 	# time in number of seconds since the Epoch |  | ||||||
| 	time_format="%s" |  | ||||||
| 	mark_hidden_devices=1 |  | ||||||
| 	# lvmdbusd expects JSON output |  | ||||||
| 	output_format=json |  | ||||||
| 	# *_cols_full for lvm fullreport's fields which lvmdbusd relies on to update its state |  | ||||||
| 	vgs_cols_full="vg_name,vg_uuid,vg_fmt,vg_size,vg_free,vg_sysid,vg_extent_size,vg_extent_count,vg_free_count,vg_profile,max_lv,max_pv,pv_count,lv_count,snap_count,vg_seqno,vg_mda_count,vg_mda_free,vg_mda_size,vg_mda_used_count,vg_attr,vg_tags" |  | ||||||
| 	pvs_cols_full="pv_name,pv_uuid,pv_fmt,pv_size,pv_free,pv_used,dev_size,pv_mda_size,pv_mda_free,pv_ba_start,pv_ba_size,pe_start,pv_pe_count,pv_pe_alloc_count,pv_attr,pv_tags,vg_name,vg_uuid" |  | ||||||
| 	lvs_cols_full="lv_uuid,lv_name,lv_path,lv_size,vg_name,pool_lv_uuid,pool_lv,origin_uuid,origin,data_percent,lv_attr,lv_tags,vg_uuid,lv_active,data_lv,metadata_lv,lv_parent,lv_role,lv_layout" |  | ||||||
| 	pvsegs_cols_full="pvseg_start,pvseg_size,segtype,pv_uuid,lv_uuid,pv_name" |  | ||||||
| 	segs_cols_full="seg_pe_ranges,segtype,lv_uuid" |  | ||||||
| 	vgs_sort_full="vg_name" |  | ||||||
| 	pvs_sort_full="pv_name" |  | ||||||
| 	lvs_sort_full="vg_name,lv_name" |  | ||||||
| 	pvsegs_sort_full="pv_uuid,pvseg_start" |  | ||||||
| 	segs_sort_full="lv_uuid,seg_start" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| log { |  | ||||||
| 	# lvmdbusd relies on command log report to inspect LVM command's execution status |  | ||||||
| 	report_command_log=1 |  | ||||||
| 	# display only outermost LVM shell-related log that lvmdbusd inspects first after LVM command execution (it calls 'lastlog' for more detailed log afterwards if needed) |  | ||||||
| 	command_log_selection="log_context=shell" |  | ||||||
| 	command_log_cols="log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code" |  | ||||||
| 	command_log_sort="log_seq_num" |  | ||||||
| } |  | ||||||
| @@ -1,19 +0,0 @@ | |||||||
| # This is a local configuration file template for the LVM2 system |  | ||||||
| # which should be installed as @DEFAULT_SYS_DIR@/lvmlocal.conf . |  | ||||||
| # |  | ||||||
| # Refer to 'man lvm.conf' for information about 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. |  | ||||||
| # |  | ||||||
| # The lvmlocal.conf file is normally expected to contain only the |  | ||||||
| # "local" section which contains settings that should not be shared or |  | ||||||
| # repeated among different hosts.  (But if other sections are present, |  | ||||||
| # they *will* get processed.  Settings in this file override equivalent |  | ||||||
| # ones in lvm.conf and are in turn overridden by ones in any enabled |  | ||||||
| # lvm_<tag>.conf files.) |  | ||||||
| # |  | ||||||
| # Please take care that each setting only appears once if uncommenting |  | ||||||
| # example settings in this file and never copy this file between hosts. |  | ||||||
|  |  | ||||||
| @@ -1,57 +0,0 @@ | |||||||
| # This is a local configuration file template for the LVM2 system |  | ||||||
| # which should be installed as @DEFAULT_SYS_DIR@/lvmlocal.conf . |  | ||||||
| # |  | ||||||
| # Refer to 'man lvm.conf' for information about 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. |  | ||||||
| # |  | ||||||
| # The lvmlocal.conf file is normally expected to contain only the |  | ||||||
| # "local" section which contains settings that should not be shared or |  | ||||||
| # repeated among different hosts.  (But if other sections are present, |  | ||||||
| # they *will* get processed.  Settings in this file override equivalent |  | ||||||
| # ones in lvm.conf and are in turn overridden by ones in any enabled |  | ||||||
| # lvm_<tag>.conf files.) |  | ||||||
| # |  | ||||||
| # Please take care that each setting only appears once if uncommenting |  | ||||||
| # example settings in this file and never copy this file between hosts. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Configuration section local. |  | ||||||
| # LVM settings that are specific to the local host. |  | ||||||
| local { |  | ||||||
|  |  | ||||||
| 	# Configuration option local/system_id. |  | ||||||
| 	# Defines the local system ID for lvmlocal mode. |  | ||||||
| 	# This is used when global/system_id_source is set to 'lvmlocal' in the |  | ||||||
| 	# main configuration file, e.g. lvm.conf. When used, it must be set to |  | ||||||
| 	# a unique value among all hosts sharing access to the storage, |  | ||||||
| 	# e.g. a host name. |  | ||||||
| 	#  |  | ||||||
| 	# Example |  | ||||||
| 	# Set no system ID: |  | ||||||
| 	# system_id = "" |  | ||||||
| 	# Set the system_id to a specific name: |  | ||||||
| 	# system_id = "host1" |  | ||||||
| 	#  |  | ||||||
| 	# This configuration option has an automatic default value. |  | ||||||
| 	# system_id = "" |  | ||||||
|  |  | ||||||
| 	# Configuration option local/extra_system_ids. |  | ||||||
| 	# A list of extra VG system IDs the local host can access. |  | ||||||
| 	# VGs with the system IDs listed here (in addition to the host's own |  | ||||||
| 	# system ID) can be fully accessed by the local host. (These are |  | ||||||
| 	# system IDs that the host sees in VGs, not system IDs that identify |  | ||||||
| 	# the local host, which is determined by system_id_source.) |  | ||||||
| 	# Use this only after consulting 'man lvmsystemid' to be certain of |  | ||||||
| 	# correct usage and possible dangers. |  | ||||||
| 	# This configuration option does not have a default value defined. |  | ||||||
|  |  | ||||||
| 	# Configuration option local/host_id. |  | ||||||
| 	# The lvmlockd sanlock host_id. |  | ||||||
| 	# This must be unique among all hosts, and must be between 1 and 2000. |  | ||||||
| 	# Applicable only if LVM is compiled with lockd support |  | ||||||
| 	# This configuration option has an automatic default value. |  | ||||||
| 	# host_id = 0 |  | ||||||
| } |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| # This is a metadata profile template for the LVM2 system. |  | ||||||
| # |  | ||||||
| # It contains all configuration settings that are customizable by metadata |  | ||||||
| # profiles. To create a new metadata profile, select the settings you want |  | ||||||
| # to customize and add them in a new file named <profile_name>.profile. |  | ||||||
| # Then install the new profile in a directory as defined by config/profile_dir |  | ||||||
| # setting found in @DEFAULT_SYS_DIR@/lvm.conf file. |  | ||||||
| # |  | ||||||
| # Metadata profiles can be referenced by using the --metadataprofile LVM2 |  | ||||||
| # command line option. |  | ||||||
| # |  | ||||||
| # Refer to 'man lvm.conf' for further information about profiles and |  | ||||||
| # general configuration file layout. |  | ||||||
| # |  | ||||||
| allocation { |  | ||||||
| 	thin_pool_zero=1 |  | ||||||
| 	thin_pool_discards="passdown" |  | ||||||
| 	thin_pool_chunk_size_policy="generic" |  | ||||||
| #	thin_pool_chunk_size=128 |  | ||||||
| } |  | ||||||
| activation { |  | ||||||
| 	thin_pool_autoextend_threshold=100 |  | ||||||
| 	thin_pool_autoextend_percent=20 |  | ||||||
| } |  | ||||||
| @@ -1,4 +0,0 @@ | |||||||
| allocation { |  | ||||||
| 	thin_pool_chunk_size_policy = "generic" |  | ||||||
| 	thin_pool_zero = 1 |  | ||||||
| } |  | ||||||
| @@ -1,4 +0,0 @@ | |||||||
| allocation { |  | ||||||
| 	thin_pool_chunk_size_policy = "performance" |  | ||||||
| 	thin_pool_zero = 0 |  | ||||||
| } |  | ||||||
							
								
								
									
										2320
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										2320
									
								
								configure.in
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,122 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Coverity usage: |  | ||||||
|  * |  | ||||||
|  * translate model into xml |  | ||||||
|  * cov-make-library -of coverity_model.xml coverity_model.c |  | ||||||
|  * |  | ||||||
|  * compile (using outdir 'cov'): |  | ||||||
|  * cov-build --dir=cov make CC=gcc |  | ||||||
|  * |  | ||||||
|  * analyze (agressively, using 'cov') |  | ||||||
|  * cov-analyze --dir cov --wait-for-license --hfa --concurrency --enable-fnptr --enable-constraint-fpp --security --all --aggressiveness-level=high --field-offset-escape --user-model-file=coverity/coverity_model.xml |  | ||||||
|  * |  | ||||||
|  * generate html output (to 'html' from 'cov'): |  | ||||||
|  * cov-format-errors --dir cov  --html-output html |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| struct lv_segment; |  | ||||||
| struct logical_volume; |  | ||||||
|  |  | ||||||
| struct lv_segment *first_seg(const struct logical_volume *lv) |  | ||||||
| { |  | ||||||
| 	return ((struct lv_segment **)lv)[0]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct lv_segment *last_seg(const struct logical_volume *lv) |  | ||||||
| { |  | ||||||
| 	return ((struct lv_segment **)lv)[0]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* simple_memccpy() from glibc */ |  | ||||||
| void *memccpy(void *dest, const void *src, int c, size_t n) |  | ||||||
| { |  | ||||||
| 	const char *s = src; |  | ||||||
| 	char *d = dest; |  | ||||||
|  |  | ||||||
| 	while (n-- > 0) |  | ||||||
| 		if ((*d++ = *s++) == (char) c) |  | ||||||
| 			return d; |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * 2 lines bellow needs to be placed in coverity/config/user_nodefs.h |  | ||||||
|  * Not sure about any other way. |  | ||||||
|  * Without them, coverity shows warning since x86 system header files |  | ||||||
|  * are using inline assembly to reset fdset |  | ||||||
|  */ |  | ||||||
| //#nodef FD_ZERO model_FD_ZERO |  | ||||||
| //void model_FD_ZERO(void *fdset); |  | ||||||
|  |  | ||||||
| void model_FD_ZERO(void *fdset) |  | ||||||
| { |  | ||||||
| 	unsigned i; |  | ||||||
|  |  | ||||||
| 	for (i = 0; i < 1024 / 8 / sizeof(long); ++i) |  | ||||||
| 		((long*)fdset)[i] = 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Added extra pointer check to not need these models, |  | ||||||
|  * for now just keep then in file |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| struct cmd_context; |  | ||||||
| struct profile; |  | ||||||
|  |  | ||||||
| const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile) |  | ||||||
| { |  | ||||||
|         return "text"; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const char *find_config_tree_str_allow_empty(struct cmd_context *cmd, int id, struct profile *profile) |  | ||||||
| { |  | ||||||
|         return "text"; |  | ||||||
| } |  | ||||||
| */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Until fixed coverity case# 00531860: |  | ||||||
|  *   A FORWARD_NULL false positive on a recursive function call |  | ||||||
|  * |  | ||||||
|  * model also these functions: |  | ||||||
|  */ |  | ||||||
| /* |  | ||||||
| const struct dm_config_node; |  | ||||||
| const struct dm_config_node *find_config_tree_array(struct cmd_context *cmd, int id, struct profile *profile) |  | ||||||
| { |  | ||||||
| 	const struct dm_config_node *cn; |  | ||||||
|  |  | ||||||
| 	return cn; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, int id, struct profile *profile) |  | ||||||
| { |  | ||||||
| 	const struct dm_config_node *cn; |  | ||||||
|  |  | ||||||
| 	return cn; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int find_config_tree_bool(struct cmd_context *cmd, int id, struct profile *profile) |  | ||||||
| { |  | ||||||
| 	int b; |  | ||||||
|  |  | ||||||
| 	return b; |  | ||||||
| } |  | ||||||
| */ |  | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| # | # | ||||||
| # Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. | # Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
| # | # | ||||||
| # This file is part of LVM2. | # This file is part of the LVM2. | ||||||
| # | # | ||||||
| # This copyrighted material is made available to anyone wishing to use, | # This copyrighted material is made available to anyone wishing to use, | ||||||
| # modify, copy, or redistribute it subject to the terms and conditions | # modify, copy, or redistribute it subject to the terms and conditions | ||||||
| @@ -9,51 +9,15 @@ | |||||||
| # | # | ||||||
| # You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | ||||||
| # along with this program; if not, write to the Free Software Foundation, | # along with this program; if not, write to the Free Software Foundation, | ||||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  | ||||||
| srcdir = @srcdir@ | srcdir = @srcdir@ | ||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| top_builddir = @top_builddir@ | VPATH = @srcdir@ | ||||||
|  |  | ||||||
| .PHONY: dmeventd clvmd cmirrord lvmetad lvmpolld lvmlockd |  | ||||||
|  |  | ||||||
| ifneq ("@CLVMD@", "none") | ifneq ("@CLVMD@", "none") | ||||||
|   SUBDIRS += clvmd |   SUBDIRS = clvmd | ||||||
| endif | endif | ||||||
|  |  | ||||||
| ifeq ("@BUILD_CMIRRORD@", "yes") | include $(top_srcdir)/make.tmpl | ||||||
|   SUBDIRS += cmirrord |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ("@BUILD_DMEVENTD@", "yes") |  | ||||||
|   SUBDIRS += dmeventd |  | ||||||
| ifneq ("$(CFLOW_CMD)", "") |  | ||||||
| daemons.cflow: dmeventd.cflow |  | ||||||
| endif |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ("@BUILD_LVMETAD@", "yes") |  | ||||||
|   SUBDIRS += lvmetad |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ("@BUILD_LVMPOLLD@", "yes") |  | ||||||
|   SUBDIRS += lvmpolld |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ("@BUILD_LVMLOCKD@", "yes") |  | ||||||
|   SUBDIRS += lvmlockd |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ("@BUILD_LVMDBUSD@", "yes") |  | ||||||
|   SUBDIRS += lvmdbusd |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ($(MAKECMDGOALS),distclean) |  | ||||||
|   SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| include $(top_builddir)/make.tmpl |  | ||||||
|  |  | ||||||
| ifeq ("@BUILD_DMEVENTD@", "yes") |  | ||||||
| device-mapper: dmeventd.device-mapper |  | ||||||
| endif |  | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								daemons/clvmd/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								daemons/clvmd/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | |||||||
| clvmd |  | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| # | # | ||||||
| # Copyright (C) 2004 Red Hat, Inc. All rights reserved. | # Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
| # | # | ||||||
| # This file is part of LVM2. | # This file is part of the LVM2. | ||||||
| # | # | ||||||
| # This copyrighted material is made available to anyone wishing to use, | # This copyrighted material is made available to anyone wishing to use, | ||||||
| # modify, copy, or redistribute it subject to the terms and conditions | # modify, copy, or redistribute it subject to the terms and conditions | ||||||
| @@ -9,95 +9,76 @@ | |||||||
| # | # | ||||||
| # You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | ||||||
| # along with this program; if not, write to the Free Software Foundation, | # along with this program; if not, write to the Free Software Foundation, | ||||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  | ||||||
| srcdir = @srcdir@ | srcdir = @srcdir@ | ||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| top_builddir = @top_builddir@ | VPATH = @srcdir@ | ||||||
|  |  | ||||||
| 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 = \ | SOURCES = \ | ||||||
| 	clvmd-command.c  \ | 	clvmd-command.c  \ | ||||||
| 	clvmd.c          \ | 	clvmd.c          \ | ||||||
| 	lvm-functions.c  \ | 	lvm-functions.c  \ | ||||||
| 	refresh_clvmd.c | 	system-lv.c | ||||||
|  |  | ||||||
| ifneq (,$(findstring cman,, "@CLVMD@,")) | ifeq ("@CLVMD@", "gulm") | ||||||
|  | 	GULM = yes | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | ifeq ("@CLVMD@", "cman") | ||||||
|  | 	CMAN = yes | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | ifeq ("@CLVMD@", "all") | ||||||
|  | 	GULM = yes | ||||||
|  | 	CMAN = yes | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | ifeq ("@DEBUG@", "yes") | ||||||
|  | 	DEFS += -DDEBUG | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | ifeq ("$(GULM)", "yes") | ||||||
|  | 	SOURCES += clvmd-gulm.c tcp-comms.c | ||||||
|  | 	LMLIBS += -lccs -lgulm | ||||||
|  | 	DEFS += -DUSE_GULM | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | ifeq ("$(CMAN)", "yes") | ||||||
| 	SOURCES += clvmd-cman.c | 	SOURCES += clvmd-cman.c | ||||||
| 	LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS) | 	LMLIBS += -ldlm -lcman | ||||||
| 	CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS) |  | ||||||
| 	DEFS += -DUSE_CMAN | 	DEFS += -DUSE_CMAN | ||||||
| endif | 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 = \ | TARGETS = \ | ||||||
| 	clvmd | 	clvmd | ||||||
|  |  | ||||||
| LVMLIBS = $(LVMINTERNAL_LIBS) | LVMLIBS = -llvm -lpthread | ||||||
|  |  | ||||||
| ifeq ("@DMEVENTD@", "yes") | ifeq ("@DMEVENTD@", "yes") | ||||||
| 	LVMLIBS += -ldevmapper-event | 	LVMLIBS += -ldevmapper-event | ||||||
| endif | endif | ||||||
|   |   | ||||||
| include $(top_builddir)/make.tmpl |  | ||||||
|  |  | ||||||
| LVMLIBS += -ldevmapper | LVMLIBS += -ldevmapper | ||||||
| LIBS += $(PTHREAD_LIBS) |  | ||||||
|  |  | ||||||
| CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS) | DEFS += -D_REENTRANT | ||||||
| LDFLAGS += $(EXTRA_EXEC_LDFLAGS) | CFLAGS += -fno-strict-aliasing | ||||||
|  |  | ||||||
|  | include $(top_srcdir)/make.tmpl | ||||||
|  |  | ||||||
| INSTALL_TARGETS = \ | INSTALL_TARGETS = \ | ||||||
| 	install_clvmd | 	install_clvmd | ||||||
|  |  | ||||||
| clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a | clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a | ||||||
| 	$(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \ | 	$(CC) -o clvmd $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(LMLIBS) $(LIBS) | ||||||
| 		$(LVMLIBS) $(LMLIBS) $(LIBS) |  | ||||||
|  |  | ||||||
| .PHONY: install_clvmd | .PHONY: install_clvmd | ||||||
|  |  | ||||||
| install_clvmd: $(TARGETS) | install_clvmd: $(TARGETS) | ||||||
| 	$(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd | 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) clvmd \ | ||||||
|  | 		$(sbindir)/clvmd | ||||||
|  |  | ||||||
| install: $(INSTALL_TARGETS) | install: $(INSTALL_TARGETS) | ||||||
|  |  | ||||||
| install_cluster: $(INSTALL_TARGETS) | install_cluster: $(INSTALL_TARGETS) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| /* | /* | ||||||
|  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. |  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. | ||||||
|  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |  * Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
|  * |  * | ||||||
|  * This file is part of LVM2. |  * This file is part of LVM2. | ||||||
|  * |  * | ||||||
| @@ -10,7 +10,7 @@ | |||||||
|  * |  * | ||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program; if not, write to the Free Software Foundation, |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* Definitions for CLVMD server and clients */ | /* Definitions for CLVMD server and clients */ | ||||||
| @@ -22,40 +22,37 @@ | |||||||
| #ifndef _CLVM_H | #ifndef _CLVM_H | ||||||
| #define _CLVM_H | #define _CLVM_H | ||||||
|  |  | ||||||
| #include "configure.h" |  | ||||||
| #include <inttypes.h> |  | ||||||
|  |  | ||||||
| struct clvm_header { | struct clvm_header { | ||||||
| 	uint8_t  cmd;	        /* See below */ | 	uint8_t  cmd;	        /* See below */ | ||||||
| 	uint8_t  flags;	        /* See below */ | 	uint8_t  flags;	        /* See below */ | ||||||
| 	uint16_t xid;	        /* Transaction ID */ | 	uint16_t xid;	        /* Transaction ID */ | ||||||
| 	uint32_t clientid;	/* Only used in Daemon->Daemon comms */ | 	uint32_t clientid;	/* Only used in Daemon->Daemon comms */ | ||||||
| 	int32_t  status;	/* For replies, whether request succeeded */ | 	int32_t  status;	/* For replies, whether request succeeded */ | ||||||
| 	uint32_t arglen;	/* Length of argument below. | 	uint32_t arglen;	/* Length of argument below.  | ||||||
| 				   If >1500 then it will be passed | 				   If >1500 then it will be passed  | ||||||
| 				   around the cluster in the system LV */ | 				   around the cluster in the system LV */ | ||||||
| 	char node[1];		/* Actually a NUL-terminated string, node name. | 	char node[1];		/* Actually a NUL-terminated string, node name. | ||||||
| 				   If this is empty then the command is | 				   If this is empty then the command is  | ||||||
| 				   forwarded to all cluster nodes unless | 				   forwarded to all cluster nodes unless  | ||||||
| 				   FLAG_LOCAL or FLAG_REMOTE is also set. */ | 				   FLAG_LOCAL is also set. */ | ||||||
| 	char args[1];		/* Arguments for the command follow the | 	char args[1];		/* Arguments for the command follow the  | ||||||
| 				   node name, This member is only | 				   node name, This member is only | ||||||
| 				   valid if the node name is empty */ | 				   valid if the node name is empty */ | ||||||
| } __attribute__ ((packed)); | } __attribute__ ((packed)); | ||||||
|  |  | ||||||
| /* Flags */ | /* Flags */ | ||||||
| #define CLVMD_FLAG_LOCAL	1	/* Only do this on the local node */ | #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_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_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 */ | /* Name of the local socket to communicate between libclvm and clvmd */ | ||||||
| #define CLVMD_SOCKNAME		DEFAULT_RUN_DIR "/clvmd.sock" | //static const char CLVMD_SOCKNAME[]="/var/run/clvmd"; | ||||||
|  | static const char CLVMD_SOCKNAME[] = "\0clvmd"; | ||||||
|  |  | ||||||
| /* Internal commands & replies */ | /* Internal commands & replies */ | ||||||
| #define CLVMD_CMD_REPLY    1 | #define CLVMD_CMD_REPLY    1 | ||||||
| #define CLVMD_CMD_VERSION  2	/* Send version around cluster when we start */ | #define CLVMD_CMD_VERSION  2	/* Send version around cluster when we start */ | ||||||
| #define CLVMD_CMD_GOAWAY   3	/* Die if received this - we are running | #define CLVMD_CMD_GOAWAY   3	/* Die if received this - we are running  | ||||||
| 				   an incompatible version */ | 				   an incompatible version */ | ||||||
| #define CLVMD_CMD_TEST     4	/* Just for mucking about */ | #define CLVMD_CMD_TEST     4	/* Just for mucking about */ | ||||||
|  |  | ||||||
| @@ -65,21 +62,5 @@ struct clvm_header { | |||||||
| /* Lock/Unlock commands */ | /* Lock/Unlock commands */ | ||||||
| #define CLVMD_CMD_LOCK_LV           50 | #define CLVMD_CMD_LOCK_LV           50 | ||||||
| #define CLVMD_CMD_LOCK_VG           51 | #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.*/ |  | ||||||
| #ifndef NODE_ALL |  | ||||||
| #  define NODE_ALL	"*" |  | ||||||
| #  define NODE_LOCAL	"." |  | ||||||
| #  define NODE_REMOTE	"^" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -10,45 +10,55 @@ | |||||||
|  * |  * | ||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program; if not, write to the Free Software Foundation, |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * CMAN communication layer for clvmd. |  * CMAN communication layer for clvmd. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "clvmd-common.h" |  | ||||||
|  |  | ||||||
| #include <pthread.h> | #include <pthread.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #include <sys/uio.h> | ||||||
|  | #include <sys/un.h> | ||||||
|  | #include <sys/time.h> | ||||||
|  | #include <sys/ioctl.h> | ||||||
|  | #include <sys/utsname.h> | ||||||
|  | #include <syslog.h> | ||||||
|  | #include <netinet/in.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <getopt.h> | ||||||
|  | #include <errno.h> | ||||||
|  |  | ||||||
| #include "clvmd-comms.h" | #include "clvmd-comms.h" | ||||||
| #include "clvm.h" | #include "clvm.h" | ||||||
|  | #include "libdlm.h" | ||||||
|  | #include "log.h" | ||||||
| #include "clvmd.h" | #include "clvmd.h" | ||||||
| #include "lvm-functions.h" | #include "lvm-functions.h" | ||||||
|  |  | ||||||
| #include <libdlm.h> |  | ||||||
|  |  | ||||||
| #include <syslog.h> |  | ||||||
|  |  | ||||||
| #define LOCKSPACE_NAME "clvmd" | #define LOCKSPACE_NAME "clvmd" | ||||||
|  |  | ||||||
| struct clvmd_node |  | ||||||
| { |  | ||||||
| 	struct cman_node *node; |  | ||||||
| 	int clvmd_up; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static int num_nodes; | static int num_nodes; | ||||||
| static struct cman_node *nodes = NULL; | static struct cman_node *nodes = NULL; | ||||||
| static struct cman_node this_node; | static struct cman_node this_node; | ||||||
| static int count_nodes; /* size of allocated nodes array */ | static int count_nodes; /* size of allocated nodes array */ | ||||||
| static struct dm_hash_table *node_updown_hash; | static int max_updown_nodes = 50;	/* Current size of the allocated array */ | ||||||
|  | /* Node up/down status, indexed by nodeid */ | ||||||
|  | static int *node_updown = NULL; | ||||||
| static dlm_lshandle_t *lockspace; | static dlm_lshandle_t *lockspace; | ||||||
| static cman_handle_t c_handle; | static cman_handle_t c_handle; | ||||||
|  |  | ||||||
| static void count_clvmds_running(void); | static void count_clvmds_running(void); | ||||||
| static void get_members(void); | static void get_members(void); | ||||||
| static int nodeid_from_csid(const char *csid); | static int nodeid_from_csid(char *csid); | ||||||
| static int name_from_nodeid(int nodeid, char *name); | 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 event_callback(cman_handle_t handle, void *private, int reason, int arg); | ||||||
| static void data_callback(cman_handle_t handle, void *private, | static void data_callback(cman_handle_t handle, void *private, | ||||||
| @@ -62,15 +72,12 @@ struct lock_wait { | |||||||
|  |  | ||||||
| static int _init_cluster(void) | static int _init_cluster(void) | ||||||
| { | { | ||||||
| 	node_updown_hash = dm_hash_create(100); |  | ||||||
|  |  | ||||||
| 	/* Open the cluster communication socket */ | 	/* Open the cluster communication socket */ | ||||||
| 	c_handle = cman_init(NULL); | 	c_handle = cman_init(NULL); | ||||||
| 	if (!c_handle) { | 	if (!c_handle) { | ||||||
| 		syslog(LOG_ERR, "Can't open cluster manager socket: %m"); | 		syslog(LOG_ERR, "Can't open cluster manager socket: %m"); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 	DEBUGLOG("Connected to CMAN\n"); |  | ||||||
|  |  | ||||||
| 	if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) { | 	if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) { | ||||||
| 		syslog(LOG_ERR, "Can't bind cluster socket: %m"); | 		syslog(LOG_ERR, "Can't bind cluster socket: %m"); | ||||||
| @@ -86,22 +93,14 @@ static int _init_cluster(void) | |||||||
| 	get_members(); | 	get_members(); | ||||||
| 	count_clvmds_running(); | 	count_clvmds_running(); | ||||||
|  |  | ||||||
| 	DEBUGLOG("CMAN initialisation complete\n"); |  | ||||||
|  |  | ||||||
| 	/* Create a lockspace for LV & VG locks to live in */ | 	/* Create a lockspace for LV & VG locks to live in */ | ||||||
| 	lockspace = dlm_open_lockspace(LOCKSPACE_NAME); | 	lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600); | ||||||
| 	if (!lockspace) { | 	if (!lockspace) { | ||||||
| 		lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600); | 		syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m"); | ||||||
| 		if (!lockspace) { | 		return -1; | ||||||
| 			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); | 	dlm_ls_pthread_init(lockspace); | ||||||
| 	DEBUGLOG("DLM initialisation complete\n"); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -110,27 +109,26 @@ static void _cluster_init_completed(void) | |||||||
| 	clvmd_cluster_init_completed(); | 	clvmd_cluster_init_completed(); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int _get_main_cluster_fd(void) | static int _get_main_cluster_fd() | ||||||
| { | { | ||||||
| 	return cman_get_fd(c_handle); | 	return cman_get_fd(c_handle); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int _get_num_nodes(void) | static int _get_num_nodes() | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 	int nnodes = 0; | 	int nnodes = 0; | ||||||
|  |  | ||||||
| 	/* return number of ACTIVE nodes */ | 	/* return number of ACTIVE nodes */ | ||||||
| 	for (i=0; i<num_nodes; i++) { | 	for (i=0; i<num_nodes; i++) { | ||||||
| 		if (nodes[i].cn_member && nodes[i].cn_nodeid) | 		if (nodes[i].cn_member) | ||||||
| 			nnodes++; | 			nnodes++; | ||||||
| 	} | 	} | ||||||
| 	return nnodes; | 	return nnodes; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* send_message with the fd check removed */ | /* send_message with the fd check removed */ | ||||||
| static int _cluster_send_message(const void *buf, int msglen, const char *csid, | static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext) | ||||||
| 				 const char *errtext) |  | ||||||
| { | { | ||||||
| 	int nodeid = 0; | 	int nodeid = 0; | ||||||
|  |  | ||||||
| @@ -139,7 +137,7 @@ static int _cluster_send_message(const void *buf, int msglen, const char *csid, | |||||||
|  |  | ||||||
| 	if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0) | 	if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0) | ||||||
| 	{ | 	{ | ||||||
| 		log_error("%s", errtext); | 			log_error(errtext); | ||||||
| 	} | 	} | ||||||
| 	return msglen; | 	return msglen; | ||||||
| } | } | ||||||
| @@ -154,29 +152,25 @@ static void _get_our_csid(char *csid) | |||||||
|  |  | ||||||
| /* Call a callback routine for each node is that known (down means not running a clvmd) */ | /* Call a callback routine for each node is that known (down means not running a clvmd) */ | ||||||
| static int _cluster_do_node_callback(struct local_client *client, | static int _cluster_do_node_callback(struct local_client *client, | ||||||
| 				     void (*callback) (struct local_client *, | 			     void (*callback) (struct local_client *, char *, | ||||||
| 						       const char *, | 					       int)) | ||||||
| 						       int)) |  | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 	int somedown = 0; | 	int somedown = 0; | ||||||
|  |  | ||||||
| 	for (i = 0; i < _get_num_nodes(); i++) { | 	for (i = 0; i < _get_num_nodes(); i++) { | ||||||
| 		if (nodes[i].cn_member && nodes[i].cn_nodeid) { | 		callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]); | ||||||
| 			int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int)); | 		if (!node_updown[nodes[i].cn_nodeid]) | ||||||
|  | 			somedown = -1; | ||||||
| 			callback(client, (char *)&nodes[i].cn_nodeid, up); |  | ||||||
| 			if (!up) |  | ||||||
| 				somedown = -1; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	return somedown; | 	return somedown; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Process OOB messages from the cluster socket */ | /* Process OOB message from the cluster socket, | ||||||
|  |    this currently just means that a node has stopped listening on our port */ | ||||||
| static void event_callback(cman_handle_t handle, void *private, int reason, int arg) | static void event_callback(cman_handle_t handle, void *private, int reason, int arg) | ||||||
| { | { | ||||||
| 	char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN]; | 	char namebuf[MAX_CLUSTER_NAME_LEN]; | ||||||
|  |  | ||||||
| 	switch (reason) { | 	switch (reason) { | ||||||
|         case CMAN_REASON_PORTCLOSED: |         case CMAN_REASON_PORTCLOSED: | ||||||
| @@ -184,7 +178,7 @@ static void event_callback(cman_handle_t handle, void *private, int reason, int | |||||||
| 		log_notice("clvmd on node %s has died\n", namebuf); | 		log_notice("clvmd on node %s has died\n", namebuf); | ||||||
| 		DEBUGLOG("Got port closed message, removing node %s\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); | 		node_updown[arg] = 0; | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	case CMAN_REASON_STATECHANGE: | 	case CMAN_REASON_STATECHANGE: | ||||||
| @@ -210,9 +204,8 @@ static void event_callback(cman_handle_t handle, void *private, int reason, int | |||||||
| } | } | ||||||
|  |  | ||||||
| static struct local_client *cman_client; | static struct local_client *cman_client; | ||||||
| static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, | static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid, | ||||||
| 				const char *csid, | 			struct local_client **new_client) | ||||||
| 				struct local_client **new_client) |  | ||||||
| { | { | ||||||
|  |  | ||||||
| 	/* Save this for data_callback */ | 	/* Save this for data_callback */ | ||||||
| @@ -234,17 +227,33 @@ static void data_callback(cman_handle_t handle, void *private, | |||||||
| 	process_message(cman_client, buf, len, (char *)&nodeid); | 	process_message(cman_client, buf, len, (char *)&nodeid); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void _add_up_node(const char *csid) | static void _add_up_node(char *csid) | ||||||
| { | { | ||||||
| 	/* It's up ! */ | 	/* It's up ! */ | ||||||
| 	int nodeid = nodeid_from_csid(csid); | 	int nodeid = nodeid_from_csid(csid); | ||||||
|  |  | ||||||
| 	dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1); | 	if (nodeid >= max_updown_nodes) { | ||||||
|  | 	        int new_size = nodeid + 10; | ||||||
|  | 		int *new_updown = realloc(node_updown, new_size); | ||||||
|  |  | ||||||
|  | 		if (new_updown) { | ||||||
|  | 			node_updown = new_updown; | ||||||
|  | 			max_updown_nodes = new_size; | ||||||
|  | 			DEBUGLOG("realloced more space for nodes. now %d\n", | ||||||
|  | 				 max_updown_nodes); | ||||||
|  | 		} else { | ||||||
|  | 			log_error | ||||||
|  | 			    ("Realloc failed. Node status for clvmd will be wrong. quitting\n"); | ||||||
|  | 			exit(999); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	node_updown[nodeid] = 1; | ||||||
| 	DEBUGLOG("Added new node %d to updown list\n", nodeid); | 	DEBUGLOG("Added new node %d to updown list\n", nodeid); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void _cluster_closedown(void) | static void _cluster_closedown() | ||||||
| { | { | ||||||
|  | 	unlock_all(); | ||||||
| 	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1); | 	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1); | ||||||
| 	cman_finish(c_handle); | 	cman_finish(c_handle); | ||||||
| } | } | ||||||
| @@ -272,22 +281,15 @@ static void count_clvmds_running(void) | |||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| 	for (i = 0; i < num_nodes; i++) { | 	for (i = 0; i < num_nodes; i++) { | ||||||
| 		int nodeid = nodes[i].cn_nodeid; | 		node_updown[nodes[i].cn_nodeid] = is_listening(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 */ | /* Get a list of active cluster members */ | ||||||
| static void get_members(void) | static void get_members() | ||||||
| { | { | ||||||
| 	int retnodes; | 	int retnodes; | ||||||
| 	int status; | 	int status; | ||||||
| 	int i; |  | ||||||
| 	int high_nodeid = 0; |  | ||||||
|  |  | ||||||
| 	num_nodes = cman_get_node_count(c_handle); | 	num_nodes = cman_get_node_count(c_handle); | ||||||
| 	if (num_nodes == -1) { | 	if (num_nodes == -1) { | ||||||
| @@ -295,37 +297,38 @@ static void get_members(void) | |||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Not enough room for new nodes list ? */ | 	        /* Not enough room for new nodes list ? */ | ||||||
| 	if (num_nodes > count_nodes && nodes) { | 	        if (num_nodes > count_nodes && nodes) { | ||||||
| 		free(nodes); | 			free(nodes); | ||||||
| 		nodes = NULL; | 			nodes = NULL; | ||||||
| 	} | 		} | ||||||
|  |  | ||||||
| 	if (nodes == NULL) { | 		if (nodes == NULL) { | ||||||
| 		count_nodes = num_nodes + 10; /* Overallocate a little */ | 		        count_nodes = num_nodes + 10; /* Overallocate a little */ | ||||||
| 		nodes = malloc(count_nodes * sizeof(struct cman_node)); | 		nodes = malloc(count_nodes * sizeof(struct cman_node)); | ||||||
| 		if (!nodes) { | 			if (!nodes) { | ||||||
| 			log_error("Unable to allocate nodes array\n"); | 			        log_error("Unable to allocate nodes array\n"); | ||||||
| 			exit(5); | 				exit(5); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes); | 	status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes); | ||||||
| 	if (status < 0) { | 	if (status < 0) { | ||||||
| 		log_error("Unable to get node details"); | 		        log_error("Unable to get node details"); | ||||||
| 		exit(6); | 			exit(6); | ||||||
| 	} | 		} | ||||||
|  |  | ||||||
| 	/* Get the highest nodeid */ | 		if (node_updown == NULL) { | ||||||
| 	for (i=0; i<retnodes; i++) { | 			node_updown = | ||||||
| 		if (nodes[i].cn_nodeid > high_nodeid) | 			    (int *) malloc(sizeof(int) * | ||||||
| 			high_nodeid = nodes[i].cn_nodeid; | 					   max(num_nodes, max_updown_nodes)); | ||||||
|  | 			memset(node_updown, 0, | ||||||
|  | 			       sizeof(int) * max(num_nodes, max_updown_nodes)); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Convert a node name to a CSID */ | /* Convert a node name to a CSID */ | ||||||
| static int _csid_from_name(char *csid, const char *name) | static int _csid_from_name(char *csid, char *name) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| @@ -339,7 +342,7 @@ static int _csid_from_name(char *csid, const char *name) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Convert a CSID to a node name */ | /* Convert a CSID to a node name */ | ||||||
| static int _name_from_csid(const char *csid, char *name) | static int _name_from_csid(char *csid, char *name) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| @@ -371,7 +374,7 @@ static int name_from_nodeid(int nodeid, char *name) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Convert a CSID to a node ID */ | /* Convert a CSID to a node ID */ | ||||||
| static int nodeid_from_csid(const char *csid) | static int nodeid_from_csid(char *csid) | ||||||
| { | { | ||||||
|         int nodeid; |         int nodeid; | ||||||
|  |  | ||||||
| @@ -380,7 +383,7 @@ static int nodeid_from_csid(const char *csid) | |||||||
| 	return nodeid; | 	return nodeid; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int _is_quorate(void) | static int _is_quorate() | ||||||
| { | { | ||||||
| 	return cman_is_quorate(c_handle); | 	return cman_is_quorate(c_handle); | ||||||
| } | } | ||||||
| @@ -465,20 +468,7 @@ static int _sync_unlock(const char *resource /* UNUSED */, int lockid) | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int _get_cluster_name(char *buf, int buflen) |  | ||||||
| { |  | ||||||
| 	cman_cluster_t cluster_info; |  | ||||||
| 	int status; |  | ||||||
|  |  | ||||||
| 	status = cman_get_cluster(c_handle, &cluster_info); |  | ||||||
| 	if (!status) { |  | ||||||
| 		strncpy(buf, cluster_info.ci_name, buflen); |  | ||||||
| 	} |  | ||||||
| 	return status; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static struct cluster_ops _cluster_cman_ops = { | static struct cluster_ops _cluster_cman_ops = { | ||||||
| 	.name                     = "cman", |  | ||||||
| 	.cluster_init_completed   = _cluster_init_completed, | 	.cluster_init_completed   = _cluster_init_completed, | ||||||
| 	.cluster_send_message     = _cluster_send_message, | 	.cluster_send_message     = _cluster_send_message, | ||||||
| 	.name_from_csid           = _name_from_csid, | 	.name_from_csid           = _name_from_csid, | ||||||
| @@ -491,7 +481,6 @@ static struct cluster_ops _cluster_cman_ops = { | |||||||
| 	.get_our_csid             = _get_our_csid, | 	.get_our_csid             = _get_our_csid, | ||||||
| 	.add_up_node              = _add_up_node, | 	.add_up_node              = _add_up_node, | ||||||
| 	.cluster_closedown        = _cluster_closedown, | 	.cluster_closedown        = _cluster_closedown, | ||||||
| 	.get_cluster_name         = _get_cluster_name, |  | ||||||
| 	.sync_lock                = _sync_lock, | 	.sync_lock                = _sync_lock, | ||||||
| 	.sync_unlock              = _sync_unlock, | 	.sync_unlock              = _sync_unlock, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| /* | /* | ||||||
|  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. |  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. | ||||||
|  * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. |  * Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
|  * |  * | ||||||
|  * This file is part of LVM2. |  * This file is part of LVM2. | ||||||
|  * |  * | ||||||
| @@ -10,7 +10,7 @@ | |||||||
|  * |  * | ||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program; if not, write to the Free Software Foundation, |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -50,19 +50,30 @@ | |||||||
|  |  | ||||||
| */ | */ | ||||||
|  |  | ||||||
| #include "clvmd-common.h" | #include <pthread.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/utsname.h> | ||||||
|  | #include <sys/ioctl.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <errno.h> | ||||||
|  |  | ||||||
|  | #include "libdevmapper.h" | ||||||
|  | #include "list.h" | ||||||
|  | #include "locking.h" | ||||||
|  | #include "log.h" | ||||||
|  | #include "lvm-functions.h" | ||||||
| #include "clvmd-comms.h" | #include "clvmd-comms.h" | ||||||
| #include "clvm.h" | #include "clvm.h" | ||||||
| #include "clvmd.h" | #include "clvmd.h" | ||||||
| #include "lvm-globals.h" | #include "libdlm.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: | /* This is where all the real work happens: | ||||||
|    NOTE: client will be NULL when this is executed on a remote node */ |    NOTE: client will be NULL when this is executed on a remote node */ | ||||||
| @@ -73,7 +84,6 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen, | |||||||
| 	int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node); | 	int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node); | ||||||
| 	int status = 0; | 	int status = 0; | ||||||
| 	char *lockname; | 	char *lockname; | ||||||
| 	const char *locktype; |  | ||||||
| 	struct utsname nodeinfo; | 	struct utsname nodeinfo; | ||||||
| 	unsigned char lock_cmd; | 	unsigned char lock_cmd; | ||||||
| 	unsigned char lock_flags; | 	unsigned char lock_flags; | ||||||
| @@ -83,87 +93,35 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen, | |||||||
| 		/* Just a test message */ | 		/* Just a test message */ | ||||||
| 	case CLVMD_CMD_TEST: | 	case CLVMD_CMD_TEST: | ||||||
| 		if (arglen > buflen) { | 		if (arglen > buflen) { | ||||||
| 			char *new_buf; |  | ||||||
| 			buflen = arglen + 200; | 			buflen = arglen + 200; | ||||||
| 			new_buf = realloc(*buf, buflen); | 			*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); |  | ||||||
| 		} | 		} | ||||||
|  | 		uname(&nodeinfo); | ||||||
|  | 		*retlen = 1 + snprintf(*buf, buflen, "TEST from %s: %s v%s", | ||||||
|  | 				       nodeinfo.nodename, args, | ||||||
|  | 				       nodeinfo.release); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	case CLVMD_CMD_LOCK_VG: | 	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 */ | 		/* Check to see if the VG is in use by LVM1 */ | ||||||
| 		status = do_check_lvm1(lockname); | 		status = do_check_lvm1(&args[2]); | ||||||
| 		do_lock_vg(lock_cmd, lock_flags, lockname); |  | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	case CLVMD_CMD_LOCK_LV: | 	case CLVMD_CMD_LOCK_LV: | ||||||
| 		/* This is the biggie */ | 		/* This is the biggie */ | ||||||
| 		lock_cmd = args[0]; | 		lock_cmd = args[0] & 0x3F; | ||||||
| 		lock_flags = args[1]; | 		lock_flags = args[1]; | ||||||
| 		lockname = &args[2]; | 		lockname = &args[2]; | ||||||
| 		status = do_lock_lv(lock_cmd, lock_flags, lockname); | 		status = do_lock_lv(lock_cmd, lock_flags, lockname); | ||||||
| 		/* Replace EIO with something less scary */ | 		/* Replace EIO with something less scary */ | ||||||
| 		if (status == EIO) { | 		if (status == EIO) { | ||||||
| 			*retlen = 1 + dm_snprintf(*buf, buflen, "%s", | 			*retlen = | ||||||
| 						  get_last_lvm_error()); | 			    1 + snprintf(*buf, buflen, | ||||||
|  | 					 "Internal lvm error, check syslog"); | ||||||
| 			return EIO; | 			return EIO; | ||||||
| 		} | 		} | ||||||
| 		break; | 		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: | 	default: | ||||||
| 		/* Won't get here because command is validated in pre_command */ | 		/* Won't get here because command is validated in pre_command */ | ||||||
| 		break; | 		break; | ||||||
| @@ -171,63 +129,65 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen, | |||||||
|  |  | ||||||
| 	/* Check the status of the command and return the error text */ | 	/* Check the status of the command and return the error text */ | ||||||
| 	if (status) { | 	if (status) { | ||||||
| 		*retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s", | 		*retlen = 1 + snprintf(*buf, buflen, strerror(status)); | ||||||
| 						    strerror(status)) : -1); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return status; | 	return status; | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lock_vg(struct local_client *client) | static int lock_vg(struct local_client *client) | ||||||
| { | { | ||||||
| 	struct dm_hash_table *lock_hash; |     struct dm_hash_table *lock_hash; | ||||||
| 	struct clvm_header *header = |     struct clvm_header *header = | ||||||
| 		(struct clvm_header *) client->bits.localsock.cmd; | 	(struct clvm_header *) client->bits.localsock.cmd; | ||||||
| 	unsigned char lock_cmd; |     unsigned char lock_cmd; | ||||||
| 	int lock_mode; |     unsigned char lock_flags; | ||||||
| 	char *args = header->node + strlen(header->node) + 1; |     char *args = header->node + strlen(header->node) + 1; | ||||||
| 	int lkid; |     int lkid; | ||||||
| 	int status; |     int status = 0; | ||||||
| 	char *lockname; |     char *lockname; | ||||||
|  |  | ||||||
| 	/* |     /* Keep a track of VG locks in our own hash table. In current | ||||||
| 	 * Keep a track of VG locks in our own hash table. In current |        practice there should only ever be more than two VGs locked | ||||||
| 	 * practice there should only ever be more than two VGs locked |        if a user tries to merge lots of them at once */ | ||||||
| 	 * 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; | ||||||
| 	if (!client->bits.localsock.private) { |     } | ||||||
| 		if (!(lock_hash = dm_hash_create(3))) |     else { | ||||||
| 			return ENOMEM; | 	lock_hash = dm_hash_create(3); | ||||||
| 		client->bits.localsock.private = (void *) lock_hash; | 	if (!lock_hash) | ||||||
| 	} else | 	    return ENOMEM; | ||||||
| 		lock_hash = (struct dm_hash_table *) client->bits.localsock.private; | 	client->bits.localsock.private = (void *)lock_hash; | ||||||
|  |     } | ||||||
|  |  | ||||||
| 	lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK); |     lock_cmd = args[0] & 0x3F; | ||||||
| 	lock_mode = ((int) lock_cmd & LCK_TYPE_MASK); |     lock_flags = args[1]; | ||||||
| 	/* lock_flags = args[1]; */ |     lockname = &args[2]; | ||||||
| 	lockname = &args[2]; |     DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client); | ||||||
| 	DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client); |  | ||||||
|  |  | ||||||
| 	if (lock_mode == LCK_UNLOCK) { |     if (lock_cmd == LCK_UNLOCK) { | ||||||
| 		if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname))) |  | ||||||
| 			return EINVAL; |  | ||||||
|  |  | ||||||
| 		if ((status = sync_unlock(lockname, lkid))) | 	lkid = (int)(long)dm_hash_lookup(lock_hash, lockname); | ||||||
| 			status = errno; | 	if (lkid == 0) | ||||||
| 		else | 	    return EINVAL; | ||||||
| 			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; |  | ||||||
|  |  | ||||||
| 		if ((status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid))) | 	status = sync_unlock(lockname, lkid); | ||||||
| 			status = errno; | 	if (status) | ||||||
| 		else if (!dm_hash_insert(lock_hash, lockname, (void *) (long) lkid)) | 	    status = errno; | ||||||
| 			return ENOMEM; | 	else | ||||||
| 	} | 	    dm_hash_remove(lock_hash, lockname); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |  | ||||||
| 	return status; | 	status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid); | ||||||
|  | 	if (status) | ||||||
|  | 	    status = errno; | ||||||
|  | 	else | ||||||
|  | 	    dm_hash_insert(lock_hash, lockname, (void *)lkid); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return status; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -241,22 +201,18 @@ int do_pre_command(struct local_client *client) | |||||||
| 	unsigned char lock_cmd; | 	unsigned char lock_cmd; | ||||||
| 	unsigned char lock_flags; | 	unsigned char lock_flags; | ||||||
| 	char *args = header->node + strlen(header->node) + 1; | 	char *args = header->node + strlen(header->node) + 1; | ||||||
| 	int lockid = 0; | 	int lockid; | ||||||
| 	int status = 0; | 	int status = 0; | ||||||
| 	char *lockname; | 	char *lockname; | ||||||
|  |  | ||||||
| 	switch (header->cmd) { | 	switch (header->cmd) { | ||||||
| 	case CLVMD_CMD_TEST: | 	case CLVMD_CMD_TEST: | ||||||
| 		status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid); | 		status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid); | ||||||
| 		client->bits.localsock.private = (void *)(long)lockid; | 		client->bits.localsock.private = (void *) lockid; | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	case CLVMD_CMD_LOCK_VG: | 	case CLVMD_CMD_LOCK_VG: | ||||||
| 		lockname = &args[2]; |        	        status = lock_vg(client); | ||||||
| 		/* 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; | 		break; | ||||||
|  |  | ||||||
| 	case CLVMD_CMD_LOCK_LV: | 	case CLVMD_CMD_LOCK_LV: | ||||||
| @@ -266,15 +222,6 @@ int do_pre_command(struct local_client *client) | |||||||
| 		status = pre_lock_lv(lock_cmd, lock_flags, lockname); | 		status = pre_lock_lv(lock_cmd, lock_flags, lockname); | ||||||
| 		break; | 		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: | 	default: | ||||||
| 		log_error("Unknown command %d received\n", header->cmd); | 		log_error("Unknown command %d received\n", header->cmd); | ||||||
| 		status = EINVAL; | 		status = EINVAL; | ||||||
| @@ -296,8 +243,13 @@ int do_post_command(struct local_client *client) | |||||||
|  |  | ||||||
| 	switch (header->cmd) { | 	switch (header->cmd) { | ||||||
| 	case CLVMD_CMD_TEST: | 	case CLVMD_CMD_TEST: | ||||||
| 		status = sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private); | 		status = | ||||||
| 		client->bits.localsock.private = NULL; | 		    sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private); | ||||||
|  | 		client->bits.localsock.private = 0; | ||||||
|  | 		break; | ||||||
|  |  | ||||||
|  | 	case CLVMD_CMD_LOCK_VG: | ||||||
|  | 		/* Nothing to do here */ | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	case CLVMD_CMD_LOCK_LV: | 	case CLVMD_CMD_LOCK_LV: | ||||||
| @@ -306,10 +258,6 @@ int do_post_command(struct local_client *client) | |||||||
| 		lockname = &args[2]; | 		lockname = &args[2]; | ||||||
| 		status = post_lock_lv(lock_cmd, lock_flags, lockname); | 		status = post_lock_lv(lock_cmd, lock_flags, lockname); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	default: |  | ||||||
| 		/* Nothing to do here */ |  | ||||||
| 		break; |  | ||||||
| 	} | 	} | ||||||
| 	return status; | 	return status; | ||||||
| } | } | ||||||
| @@ -318,97 +266,21 @@ int do_post_command(struct local_client *client) | |||||||
| /* Called when the client is about to be deleted */ | /* Called when the client is about to be deleted */ | ||||||
| void cmd_client_cleanup(struct local_client *client) | void cmd_client_cleanup(struct local_client *client) | ||||||
| { | { | ||||||
|  |     if (client->bits.localsock.private) { | ||||||
|  |  | ||||||
| 	struct dm_hash_node *v; | 	struct dm_hash_node *v; | ||||||
| 	struct dm_hash_table *lock_hash; | 	struct dm_hash_table *lock_hash = | ||||||
| 	int lkid; | 	    (struct dm_hash_table *)client->bits.localsock.private; | ||||||
| 	char *lockname; |  | ||||||
|  |  | ||||||
| 	DEBUGLOG("Client thread cleanup (%p)\n", client); |  | ||||||
| 	if (!client->bits.localsock.private) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	lock_hash = (struct dm_hash_table *)client->bits.localsock.private; |  | ||||||
|  |  | ||||||
| 	dm_hash_iterate(v, lock_hash) { | 	dm_hash_iterate(v, lock_hash) { | ||||||
| 		lkid = (int)(long)dm_hash_get_data(lock_hash, v); | 		int lkid = (int)(long)dm_hash_get_data(lock_hash, v); | ||||||
| 		lockname = dm_hash_get_key(lock_hash, v); | 		char *lockname = dm_hash_get_key(lock_hash, v); | ||||||
| 		DEBUGLOG("Cleanup (%p): Unlocking lock %s %x\n", client, lockname, lkid); |  | ||||||
| 		(void) sync_unlock(lockname, lkid); | 		DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid); | ||||||
|  | 		sync_unlock(lockname, lkid); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	dm_hash_destroy(lock_hash); | 	dm_hash_destroy(lock_hash); | ||||||
| 	client->bits.localsock.private = NULL; | 	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 + 6) * sizeof(*argv)))) |  | ||||||
| 		goto_out; |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Build the command-line |  | ||||||
| 	 */ |  | ||||||
| 	argv[argc++] = "clvmd"; |  | ||||||
|  |  | ||||||
| 	/* Propagate 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; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Propagate foreground options */ |  | ||||||
| 	if (clvmd_get_foreground()) |  | ||||||
| 		argv[argc++] = "-f"; |  | ||||||
|  |  | ||||||
| 	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; |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,27 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * This file must be included first by every clvmd source file. |  | ||||||
|  */ |  | ||||||
| #ifndef _LVM_CLVMD_COMMON_H |  | ||||||
| #define _LVM_CLVMD_COMMON_H |  | ||||||
|  |  | ||||||
| #define _REENTRANT |  | ||||||
|  |  | ||||||
| #include "tool.h" |  | ||||||
|  |  | ||||||
| #include "lvm-logging.h" |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| /* | /* | ||||||
|  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. |  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. | ||||||
|  * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. |  * Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
|  * |  * | ||||||
|  * This file is part of LVM2. |  * This file is part of LVM2. | ||||||
|  * |  * | ||||||
| @@ -10,7 +10,7 @@ | |||||||
|  * |  * | ||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program; if not, write to the Free Software Foundation, |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -23,38 +23,38 @@ | |||||||
| struct local_client; | struct local_client; | ||||||
|  |  | ||||||
| struct cluster_ops { | struct cluster_ops { | ||||||
| 	const char *name; |  | ||||||
| 	void (*cluster_init_completed) (void); | 	void (*cluster_init_completed) (void); | ||||||
|  |  | ||||||
| 	int (*cluster_send_message) (const void *buf, int msglen, | 	int (*cluster_send_message) (void *buf, int msglen, char *csid, | ||||||
| 				     const char *csid, | 				const char *errtext); | ||||||
| 				     const char *errtext); | 	int (*name_from_csid) (char *csid, char *name); | ||||||
| 	int (*name_from_csid) (const char *csid, char *name); | 	int (*csid_from_name) (char *csid, char *name); | ||||||
| 	int (*csid_from_name) (char *csid, const char *name); |  | ||||||
| 	int (*get_num_nodes) (void); | 	int (*get_num_nodes) (void); | ||||||
| 	int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len, | 	int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len, | ||||||
| 				    const char *csid, | 			       char *csid, struct local_client **new_client); | ||||||
| 				    struct local_client **new_client); |  | ||||||
| 	int (*get_main_cluster_fd) (void);	/* gets accept FD or cman cluster socket */ | 	int (*get_main_cluster_fd) (void);	/* gets accept FD or cman cluster socket */ | ||||||
| 	int (*cluster_do_node_callback) (struct local_client *client, | 	int (*cluster_do_node_callback) (struct local_client *client, | ||||||
| 					 void (*callback) (struct local_client *, | 				    void (*callback) (struct local_client *, | ||||||
| 							   const char *csid, | 						      char *csid, int node_up)); | ||||||
| 							   int node_up)); |  | ||||||
| 	int (*is_quorate) (void); | 	int (*is_quorate) (void); | ||||||
|  |  | ||||||
| 	void (*get_our_csid) (char *csid); | 	void (*get_our_csid) (char *csid); | ||||||
| 	void (*add_up_node) (const char *csid); | 	void (*add_up_node) (char *csid); | ||||||
| 	void (*reread_config) (void); | 	void (*reread_config) (void); | ||||||
| 	void (*cluster_closedown) (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_lock) (const char *resource, int mode, |  | ||||||
| 			  int flags, int *lockid); |  | ||||||
| 	int (*sync_unlock) (const char *resource, int lockid); | 	int (*sync_unlock) (const char *resource, int lockid); | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | #ifdef USE_GULM | ||||||
|  | #  include "tcp-comms.h" | ||||||
|  | struct cluster_ops *init_gulm_cluster(void); | ||||||
|  | #define MAX_CSID_LEN 			GULM_MAX_CSID_LEN | ||||||
|  | #define MAX_CLUSTER_MEMBER_NAME_LEN	GULM_MAX_CLUSTER_MEMBER_NAME_LEN | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef USE_CMAN | #ifdef USE_CMAN | ||||||
| #  include <netinet/in.h> | #  include <netinet/in.h> | ||||||
| #  include "libcman.h" | #  include "libcman.h" | ||||||
| @@ -69,51 +69,6 @@ struct cluster_ops { | |||||||
| struct cluster_ops *init_cman_cluster(void); | struct cluster_ops *init_cman_cluster(void); | ||||||
| #endif | #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 | #endif | ||||||
|   | |||||||
| @@ -1,658 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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_DOWN, 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; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	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) |  | ||||||
| { |  | ||||||
| 	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(void) |  | ||||||
| { |  | ||||||
| 	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; |  | ||||||
|  |  | ||||||
| 	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_CLVMD) |  | ||||||
| 			callback(master_client, csid, 1); |  | ||||||
| 	} |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* 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(void) |  | ||||||
| { |  | ||||||
| 	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; |  | ||||||
| } |  | ||||||
							
								
								
									
										1000
									
								
								daemons/clvmd/clvmd-gulm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1000
									
								
								daemons/clvmd/clvmd-gulm.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										12
									
								
								daemons/clvmd/clvmd-gulm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								daemons/clvmd/clvmd-gulm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | extern int get_next_node_csid(void **context, char *csid); | ||||||
|  | extern void add_down_node(char *csid); | ||||||
|  | extern int gulm_fd(void); | ||||||
|  | extern int get_ip_address(char *node, char *addr); | ||||||
|  | extern void tcp_remove_client(char *csid); | ||||||
|  | extern int alloc_client(int fd, char *csid, struct local_client **new_client); | ||||||
|  |  | ||||||
|  | void gulm_add_up_node(char *csid); | ||||||
|  | int gulm_name_from_csid(char *csid, char *name); | ||||||
| @@ -1,689 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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); |  | ||||||
|  |  | ||||||
| 	if (!(client = dm_zalloc(sizeof(*client)))) { |  | ||||||
| 		DEBUGLOG("malloc failed\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	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, " |  | ||||||
| 		 FMTsize_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) |  | ||||||
| { |  | ||||||
| 	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; |  | ||||||
|  |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
| @@ -1,382 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2009-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "clvmd-common.h" |  | ||||||
|  |  | ||||||
| #include <pthread.h> |  | ||||||
|  |  | ||||||
| #include "locking.h" |  | ||||||
| #include "clvm.h" |  | ||||||
| #include "clvmd-comms.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; |  | ||||||
|  |  | ||||||
| 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; |  | ||||||
|  |  | ||||||
| struct lock { |  | ||||||
| 	struct dm_list list; |  | ||||||
| 	int lockid; |  | ||||||
| 	int mode; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| 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) |  | ||||||
| { |  | ||||||
| 	mode_t old_mask; |  | ||||||
| 	struct sockaddr_un addr = { .sun_family = AF_UNIX }; |  | ||||||
|  |  | ||||||
| 	if (!dm_strncpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME, |  | ||||||
| 			sizeof(addr.sun_path))) { |  | ||||||
| 		DEBUGLOG("%s: singlenode socket name too long.", |  | ||||||
| 			 SINGLENODE_CLVMD_SOCKNAME); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	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; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	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); |  | ||||||
| 		_locks = NULL; |  | ||||||
| 		return r; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	DEBUGLOG("Single-node cluster initialised.\n"); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void _cluster_closedown(void) |  | ||||||
| { |  | ||||||
| 	close_comms(); |  | ||||||
|  |  | ||||||
| 	/* If there is any awaited resource, kill it softly */ |  | ||||||
| 	pthread_mutex_lock(&_lock_mutex); |  | ||||||
| 	dm_hash_destroy(_locks); |  | ||||||
| 	_locks = NULL; |  | ||||||
| 	_lockid = 0; |  | ||||||
| 	pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */ |  | ||||||
| 	pthread_mutex_unlock(&_lock_mutex); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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) |  | ||||||
| { |  | ||||||
| 	strcpy(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 const char *_get_mode(int mode) |  | ||||||
| { |  | ||||||
| 	switch (mode) { |  | ||||||
| 	case LCK_NULL: return "NULL"; |  | ||||||
| 	case LCK_READ: return "READ"; |  | ||||||
| 	case LCK_PREAD: return "PREAD"; |  | ||||||
| 	case LCK_WRITE: return "WRITE"; |  | ||||||
| 	case LCK_EXCL: return "EXCLUSIVE"; |  | ||||||
| 	case LCK_UNLOCK: return "UNLOCK"; |  | ||||||
| 	default: return "????"; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Real locking */ |  | ||||||
| static int _lock_resource(const char *resource, int mode, int flags, int *lockid) |  | ||||||
| { |  | ||||||
| 	/* DLM table of allowed transition states */ |  | ||||||
| 	static const int _dlm_table[6][6] = { |  | ||||||
| 	/* Mode	   NL	CR	CW	PR	PW	EX */ |  | ||||||
| 	/* NL */ { 1,	 1,	 1,	 1,	 1,	 1}, |  | ||||||
| 	/* CR */ { 1,	 1,	 1,	 1,	 1,	 0}, |  | ||||||
| 	/* CW */ { 1,	 1,	 1,	 0,	 0,	 0}, |  | ||||||
| 	/* PR */ { 1,	 1,	 0,	 1,	 0,	 0}, |  | ||||||
| 	/* PW */ { 1,	 1,	 0,	 0,	 0,	 0}, |  | ||||||
| 	/* EX */ { 1,	 0,	 0,	 0,	 0,	 0} |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	struct lock *lck = NULL, *lckt; |  | ||||||
| 	struct dm_list *head; |  | ||||||
|  |  | ||||||
| 	DEBUGLOG("Locking resource %s, flags=0x%02x (%s%s%s), mode=%s (%d)\n", |  | ||||||
| 		 resource, flags, |  | ||||||
| 		 (flags & LCKF_NOQUEUE) ? "NOQUEUE" : "", |  | ||||||
| 		 ((flags & (LCKF_NOQUEUE | LCKF_CONVERT)) == |  | ||||||
| 		  (LCKF_NOQUEUE | LCKF_CONVERT)) ? "|" : "", |  | ||||||
| 		 (flags & LCKF_CONVERT) ? "CONVERT" : "", |  | ||||||
| 		 _get_mode(mode), mode); |  | ||||||
|  |  | ||||||
| 	mode &= LCK_TYPE_MASK; |  | ||||||
| 	pthread_mutex_lock(&_lock_mutex); |  | ||||||
|  |  | ||||||
| retry: |  | ||||||
| 	if (!(head = dm_hash_lookup(_locks, resource))) { |  | ||||||
| 		if (flags & LCKF_CONVERT) { |  | ||||||
| 			/* In real DLM, lock is identified only by lockid, resource is not used */ |  | ||||||
| 			DEBUGLOG("Unlocked resource %s cannot be converted\n", resource); |  | ||||||
| 			goto_bad; |  | ||||||
| 		} |  | ||||||
| 		/* Add new locked resource */ |  | ||||||
| 		if (!(head = dm_malloc(sizeof(struct dm_list))) || |  | ||||||
| 		    !dm_hash_insert(_locks, resource, head)) { |  | ||||||
| 			dm_free(head); |  | ||||||
| 			goto_bad; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		dm_list_init(head); |  | ||||||
| 	} else	/* Update/convert locked resource */ |  | ||||||
| 		dm_list_iterate_items(lck, head) { |  | ||||||
| 			/* Check is all locks are compatible with requested lock */ |  | ||||||
| 			if (flags & LCKF_CONVERT) { |  | ||||||
| 				if (lck->lockid != *lockid) |  | ||||||
| 					continue; |  | ||||||
|  |  | ||||||
| 				DEBUGLOG("Converting resource %s lockid=%d mode:%s -> %s...\n", |  | ||||||
| 					 resource, lck->lockid, _get_mode(lck->mode), _get_mode(mode)); |  | ||||||
| 				dm_list_iterate_items(lckt, head) { |  | ||||||
| 					if ((lckt->lockid != *lockid) && |  | ||||||
| 					    !_dlm_table[mode][lckt->mode]) { |  | ||||||
| 						if (!(flags & LCKF_NOQUEUE) && |  | ||||||
| 						    /* TODO: Real dlm uses here conversion queues */ |  | ||||||
| 						    !pthread_cond_wait(&_lock_cond, &_lock_mutex) && |  | ||||||
| 						    _locks) /* End of the game? */ |  | ||||||
| 							goto retry; |  | ||||||
| 						goto bad; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				lck->mode = mode; /* Lock is now converted */ |  | ||||||
| 				goto out; |  | ||||||
| 			} else if (!_dlm_table[mode][lck->mode]) { |  | ||||||
| 				DEBUGLOG("Resource %s already locked lockid=%d, mode:%s\n", |  | ||||||
| 					 resource, lck->lockid, _get_mode(lck->mode)); |  | ||||||
| 				if (!(flags & LCKF_NOQUEUE) && |  | ||||||
| 				    !pthread_cond_wait(&_lock_cond, &_lock_mutex) && |  | ||||||
| 				    _locks) { /* End of the game? */ |  | ||||||
| 					DEBUGLOG("Resource %s retrying lock in mode:%s...\n", |  | ||||||
| 						 resource, _get_mode(mode)); |  | ||||||
| 					goto retry; |  | ||||||
| 				} |  | ||||||
| 				goto bad; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 	if (!(flags & LCKF_CONVERT)) { |  | ||||||
| 		if (!(lck = dm_malloc(sizeof(struct lock)))) |  | ||||||
| 			goto_bad; |  | ||||||
|  |  | ||||||
| 		*lockid = lck->lockid = ++_lockid; |  | ||||||
| 		lck->mode = mode; |  | ||||||
| 		dm_list_add(head, &lck->list); |  | ||||||
| 	} |  | ||||||
| out: |  | ||||||
| 	pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */ |  | ||||||
| 	pthread_mutex_unlock(&_lock_mutex); |  | ||||||
| 	DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n", |  | ||||||
| 		 resource, lck->lockid, _get_mode(lck->mode)); |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| bad: |  | ||||||
| 	pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */ |  | ||||||
| 	pthread_mutex_unlock(&_lock_mutex); |  | ||||||
| 	DEBUGLOG("Failed to lock resource %s\n", resource); |  | ||||||
|  |  | ||||||
| 	return 1; /* fail */ |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int _unlock_resource(const char *resource, int lockid) |  | ||||||
| { |  | ||||||
| 	struct lock *lck; |  | ||||||
| 	struct dm_list *head; |  | ||||||
| 	int r = 1; |  | ||||||
|  |  | ||||||
| 	if (lockid < 0) { |  | ||||||
| 		DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n", |  | ||||||
| 			 resource, lockid); |  | ||||||
| 		return 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid); |  | ||||||
| 	pthread_mutex_lock(&_lock_mutex); |  | ||||||
| 	pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */ |  | ||||||
|  |  | ||||||
| 	if (!(head = dm_hash_lookup(_locks, resource))) { |  | ||||||
| 		pthread_mutex_unlock(&_lock_mutex); |  | ||||||
| 		DEBUGLOG("Resource %s is not locked.\n", resource); |  | ||||||
| 		return 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	dm_list_iterate_items(lck, head) |  | ||||||
| 		if (lck->lockid == lockid) { |  | ||||||
| 			dm_list_del(&lck->list); |  | ||||||
| 			dm_free(lck); |  | ||||||
| 			r = 0; |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 	DEBUGLOG("Resource %s has wrong lockid %d.\n", resource, lockid); |  | ||||||
| out: |  | ||||||
| 	if (dm_list_empty(head)) { |  | ||||||
| 		//DEBUGLOG("Resource %s is no longer hashed (lockid=%d).\n", resource, lockid); |  | ||||||
| 		dm_hash_remove(_locks, resource); |  | ||||||
| 		dm_free(head); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	pthread_mutex_unlock(&_lock_mutex); |  | ||||||
|  |  | ||||||
| 	return r; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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) |  | ||||||
| { |  | ||||||
| 	return dm_strncpy(buf, "localcluster", buflen) ? 0 : 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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; |  | ||||||
|  |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,7 +10,7 @@ | |||||||
|  * |  * | ||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program; if not, write to the Free Software Foundation, |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef _CLVMD_H | #ifndef _CLVMD_H | ||||||
| @@ -20,6 +20,9 @@ | |||||||
| #define CLVMD_MINOR_VERSION 2 | #define CLVMD_MINOR_VERSION 2 | ||||||
| #define CLVMD_PATCH_VERSION 1 | #define CLVMD_PATCH_VERSION 1 | ||||||
|  |  | ||||||
|  | /* Name of the cluster LVM admin lock */ | ||||||
|  | #define ADMIN_LOCK_NAME "CLVMD_ADMIN" | ||||||
|  |  | ||||||
| /* Default time (in seconds) we will wait for all remote commands to execute | /* Default time (in seconds) we will wait for all remote commands to execute | ||||||
|    before declaring them dead */ |    before declaring them dead */ | ||||||
| #define DEFAULT_CMD_TIMEOUT 60 | #define DEFAULT_CMD_TIMEOUT 60 | ||||||
| @@ -32,8 +35,6 @@ struct node_reply { | |||||||
| 	struct node_reply *next; | 	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 |  * These exist for the use of local sockets only when we are | ||||||
|  * collecting responses from all cluster nodes |  * collecting responses from all cluster nodes | ||||||
| @@ -53,12 +54,13 @@ struct localsock_bits { | |||||||
| 	int finished;		/* Flag to tell subthread to exit */ | 	int finished;		/* Flag to tell subthread to exit */ | ||||||
| 	int all_success;	/* Set to 0 if any node (or the pre_command) | 	int all_success;	/* Set to 0 if any node (or the pre_command) | ||||||
| 				   failed */ | 				   failed */ | ||||||
| 	int cleanup_needed;     /* helper for cleanup_zombie */ |  | ||||||
| 	struct local_client *pipe_client; | 	struct local_client *pipe_client; | ||||||
| 	pthread_t threadid; | 	pthread_t threadid; | ||||||
| 	enum { PRE_COMMAND, POST_COMMAND } state; | 	enum { PRE_COMMAND, POST_COMMAND, QUIT } state; | ||||||
| 	pthread_mutex_t mutex;	/* Main thread and worker synchronisation */ | 	pthread_mutex_t mutex;	/* Main thread and worker synchronisation */ | ||||||
| 	pthread_cond_t cond; | 	pthread_cond_t cond; | ||||||
|  |  | ||||||
|  | 	pthread_mutex_t reply_mutex;	/* Protect reply structure */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* Entries for PIPE clients */ | /* Entries for PIPE clients */ | ||||||
| @@ -74,8 +76,7 @@ struct netsock_bits { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len, | typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len, | ||||||
| 			      const char *csid, | 			      char *csid, struct local_client ** new_client); | ||||||
| 			      struct local_client ** new_client); |  | ||||||
|  |  | ||||||
| /* One of these for each fd we are listening on */ | /* One of these for each fd we are listening on */ | ||||||
| struct local_client { | struct local_client { | ||||||
| @@ -94,7 +95,11 @@ struct local_client { | |||||||
| 	} bits; | 	} bits; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define DEBUGLOG(fmt, args...) debuglog(fmt, ## args) | #ifdef DEBUG | ||||||
|  | #define DEBUGLOG(fmt, args...) {time_t P; time(&P); fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 ); fprintf(stderr, fmt, ## args);} | ||||||
|  | #else | ||||||
|  | #define DEBUGLOG(fmt, args...) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifndef max | #ifndef max | ||||||
| #define max(a,b) ((a)>(b)?(a):(b)) | #define max(a,b) ((a)>(b)?(a):(b)) | ||||||
| @@ -111,14 +116,7 @@ extern void cmd_client_cleanup(struct local_client *client); | |||||||
| extern int add_client(struct local_client *new_client); | extern int add_client(struct local_client *new_client); | ||||||
|  |  | ||||||
| extern void clvmd_cluster_init_completed(void); | extern void clvmd_cluster_init_completed(void); | ||||||
| extern void process_message(struct local_client *client, char *buf, | extern void process_message(struct local_client *client, char *buf, int len, char *csid); | ||||||
| 			    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 clvmd_get_foreground(void); |  | ||||||
|  |  | ||||||
| int sync_lock(const char *resource, int mode, int flags, int *lockid); | int sync_lock(const char *resource, int mode, int flags, int *lockid); | ||||||
| int sync_unlock(const char *resource, int lockid); | int sync_unlock(const char *resource, int lockid); | ||||||
|   | |||||||
							
								
								
									
										226
									
								
								daemons/clvmd/cnxman-socket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								daemons/clvmd/cnxman-socket.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,226 @@ | |||||||
|  | /****************************************************************************** | ||||||
|  | ******************************************************************************* | ||||||
|  | ** | ||||||
|  | **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved. | ||||||
|  | **  Copyright (C) 2004 Red Hat, Inc.  All rights reserved. | ||||||
|  | ** | ||||||
|  | **  This copyrighted material is made available to anyone wishing to use, | ||||||
|  | **  modify, copy, or redistribute it subject to the terms and conditions | ||||||
|  | **  of the GNU General Public License v.2. | ||||||
|  | ** | ||||||
|  | ******************************************************************************* | ||||||
|  | ******************************************************************************/ | ||||||
|  |  | ||||||
|  | /* CMAN socket interface header, | ||||||
|  |    may be include by user or kernel code */ | ||||||
|  |  | ||||||
|  | #ifndef __CNXMAN_SOCKET_H | ||||||
|  | #define __CNXMAN_SOCKET_H | ||||||
|  |  | ||||||
|  | /* A currently unused number. TIPC also uses this number and you're unlikely | ||||||
|  |    to be using both. | ||||||
|  |  */ | ||||||
|  | #define AF_CLUSTER 30 | ||||||
|  | #define PF_CLUSTER AF_CLUSTER | ||||||
|  |  | ||||||
|  | /* Protocol(socket) types */ | ||||||
|  | #define CLPROTO_MASTER 2 | ||||||
|  | #define CLPROTO_CLIENT 3 | ||||||
|  |  | ||||||
|  | /* ioctls -- should register these properly */ | ||||||
|  | #define SIOCCLUSTER_NOTIFY            _IOW('x', 0x01, int) | ||||||
|  | #define SIOCCLUSTER_REMOVENOTIFY      _IO( 'x', 0x02) | ||||||
|  | #define SIOCCLUSTER_GETMEMBERS        _IOR('x', 0x03, struct cl_cluster_nodelist) | ||||||
|  | #define SIOCCLUSTER_SETEXPECTED_VOTES _IOW('x', 0x04, int) | ||||||
|  | #define SIOCCLUSTER_ISQUORATE         _IO( 'x', 0x05) | ||||||
|  | #define SIOCCLUSTER_ISLISTENING       _IOW('x', 0x06, struct cl_listen_request) | ||||||
|  | #define SIOCCLUSTER_GETALLMEMBERS     _IOR('x', 0x07, struct cl_cluster_nodelist) | ||||||
|  | #define SIOCCLUSTER_SET_VOTES         _IOW('x', 0x08, int) | ||||||
|  | #define SIOCCLUSTER_GET_VERSION       _IOR('x', 0x09, struct cl_version) | ||||||
|  | #define SIOCCLUSTER_SET_VERSION       _IOW('x', 0x0a, struct cl_version) | ||||||
|  | #define SIOCCLUSTER_ISACTIVE          _IO( 'x', 0x0b) | ||||||
|  | #define SIOCCLUSTER_KILLNODE          _IOW('x', 0x0c, int) | ||||||
|  | #define SIOCCLUSTER_GET_JOINCOUNT     _IO( 'x', 0x0d) | ||||||
|  | #define SIOCCLUSTER_SERVICE_REGISTER  _IOW('x', 0x0e, char) | ||||||
|  | #define SIOCCLUSTER_SERVICE_UNREGISTER _IO('x', 0x0f) | ||||||
|  | #define SIOCCLUSTER_SERVICE_JOIN      _IO( 'x', 0x10) | ||||||
|  | #define SIOCCLUSTER_SERVICE_LEAVE     _IO( 'x', 0x20) | ||||||
|  | #define SIOCCLUSTER_SERVICE_SETSIGNAL _IOW('x', 0x30, int) | ||||||
|  | #define SIOCCLUSTER_SERVICE_STARTDONE _IOW('x', 0x40, unsigned int) | ||||||
|  | #define SIOCCLUSTER_SERVICE_GETEVENT  _IOR('x', 0x50, struct cl_service_event) | ||||||
|  | #define SIOCCLUSTER_SERVICE_GETMEMBERS _IOR('x', 0x60, struct cl_cluster_nodelist) | ||||||
|  | #define SIOCCLUSTER_SERVICE_GLOBALID  _IOR('x', 0x70, uint32_t) | ||||||
|  | #define SIOCCLUSTER_SERVICE_SETLEVEL  _IOR('x', 0x80, int) | ||||||
|  | #define SIOCCLUSTER_GETNODE	      _IOWR('x', 0x90, struct cl_cluster_node) | ||||||
|  | #define SIOCCLUSTER_BARRIER           _IOW('x', 0x0a0, struct cl_barrier_info) | ||||||
|  |  | ||||||
|  | /* These were setsockopts */ | ||||||
|  | #define SIOCCLUSTER_PASS_SOCKET       _IOW('x', 0x0b0, struct cl_passed_sock) | ||||||
|  | #define SIOCCLUSTER_SET_NODENAME      _IOW('x', 0x0b1, char *) | ||||||
|  | #define SIOCCLUSTER_SET_NODEID        _IOW('x', 0x0b2, int) | ||||||
|  | #define SIOCCLUSTER_JOIN_CLUSTER      _IOW('x', 0x0b3, struct cl_join_cluster_info) | ||||||
|  | #define SIOCCLUSTER_LEAVE_CLUSTER     _IOW('x', 0x0b4, int) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Maximum size of a cluster message */ | ||||||
|  | #define CMAN_MAX_CLUSTER_MESSAGE          1500 | ||||||
|  | #define CMAN_MAX_CLUSTER_MEMBER_NAME_LEN   255 | ||||||
|  | #define MAX_BARRIER_NAME_LEN           33 | ||||||
|  | #define MAX_SA_ADDR_LEN                12 | ||||||
|  | #define MAX_CLUSTER_NAME_LEN           16 | ||||||
|  |  | ||||||
|  | /* Well-known cluster port numbers */ | ||||||
|  | #define CLUSTER_PORT_MEMBERSHIP  1	/* Mustn't block during cluster | ||||||
|  | 					 * transitions! */ | ||||||
|  | #define CLUSTER_PORT_SERVICES    2 | ||||||
|  | #define CLUSTER_PORT_SYSMAN      10	/* Remote execution daemon */ | ||||||
|  | #define CLUSTER_PORT_CLVMD       11	/* Cluster LVM daemon */ | ||||||
|  | #define CLUSTER_PORT_SLM         12	/* LVM SLM (simple lock manager) */ | ||||||
|  |  | ||||||
|  | /* Port numbers above this will be blocked when the cluster is inquorate or in | ||||||
|  |  * transition */ | ||||||
|  | #define HIGH_PROTECTED_PORT      9 | ||||||
|  |  | ||||||
|  | /* Reasons for leaving the cluster */ | ||||||
|  | #define CLUSTER_LEAVEFLAG_DOWN     0	/* Normal shutdown */ | ||||||
|  | #define CLUSTER_LEAVEFLAG_KILLED   1 | ||||||
|  | #define CLUSTER_LEAVEFLAG_PANIC    2 | ||||||
|  | #define CLUSTER_LEAVEFLAG_REMOVED  3	/* This one can reduce quorum */ | ||||||
|  | #define CLUSTER_LEAVEFLAG_REJECTED 4	/* Not allowed into the cluster in the | ||||||
|  | 					 * first place */ | ||||||
|  | #define CLUSTER_LEAVEFLAG_INCONSISTENT 5	/* Our view of the cluster is | ||||||
|  | 						 * in a minority */ | ||||||
|  | #define CLUSTER_LEAVEFLAG_DEAD         6	/* Discovered to be dead */ | ||||||
|  | #define CLUSTER_LEAVEFLAG_FORCE     0x10	/* Forced by command-line */ | ||||||
|  |  | ||||||
|  | /* OOB messages sent to a local socket */ | ||||||
|  | #define CLUSTER_OOB_MSG_PORTCLOSED  1 | ||||||
|  | #define CLUSTER_OOB_MSG_STATECHANGE 2 | ||||||
|  | #define CLUSTER_OOB_MSG_SERVICEEVENT 3 | ||||||
|  |  | ||||||
|  | /* Sendmsg flags, these are above the normal sendmsg flags so they don't | ||||||
|  |  * interfere */ | ||||||
|  | #define MSG_NOACK     0x010000	/* Don't need an ACK for this message */ | ||||||
|  | #define MSG_QUEUE     0x020000	/* Queue the message for sending later */ | ||||||
|  | #define MSG_MULTICAST 0x080000	/* Message was sent to all nodes in the cluster | ||||||
|  | 				 */ | ||||||
|  | #define MSG_ALLINT    0x100000	/* Send out of all interfaces */ | ||||||
|  | #define MSG_REPLYEXP  0x200000	/* Reply is expected */ | ||||||
|  |  | ||||||
|  | typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER, | ||||||
|  | 	       NODESTATE_DEAD } nodestate_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct sockaddr_cl { | ||||||
|  | 	unsigned short scl_family; | ||||||
|  | 	unsigned char scl_flags; | ||||||
|  | 	unsigned char scl_port; | ||||||
|  | 	int           scl_nodeid; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This is how we pass the multicast & receive sockets into kernel space. | ||||||
|  |  */ | ||||||
|  | struct cl_passed_sock { | ||||||
|  | 	int fd;			/* FD of master socket to do multicast on */ | ||||||
|  | 	int number;		/* Socket number, to match up recvonly & bcast | ||||||
|  | 				 * sockets */ | ||||||
|  |         int multicast;          /* Is it multicast or receive ? */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Cluster configuration info passed when we join the cluster */ | ||||||
|  | struct cl_join_cluster_info { | ||||||
|  | 	unsigned char votes; | ||||||
|  | 	unsigned int expected_votes; | ||||||
|  | 	unsigned int two_node; | ||||||
|  | 	unsigned int config_version; | ||||||
|  |  | ||||||
|  |         char cluster_name[17]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* This is the structure, per node, returned from the membership ioctl */ | ||||||
|  | struct cl_cluster_node { | ||||||
|  | 	unsigned int size; | ||||||
|  | 	unsigned int node_id; | ||||||
|  | 	unsigned int us; | ||||||
|  | 	unsigned int leave_reason; | ||||||
|  | 	unsigned int incarnation; | ||||||
|  | 	nodestate_t state; | ||||||
|  | 	char name[CMAN_MAX_CLUSTER_MEMBER_NAME_LEN]; | ||||||
|  | 	unsigned char votes; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* The struct passed to the membership ioctls */ | ||||||
|  | struct cl_cluster_nodelist { | ||||||
|  |         uint32_t max_members; | ||||||
|  |         struct cl_cluster_node *nodes; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Structure passed to SIOCCLUSTER_ISLISTENING */ | ||||||
|  | struct cl_listen_request { | ||||||
|  | 	unsigned char port; | ||||||
|  |         int           nodeid; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* A Cluster PORTCLOSED message - received by a local user as an OOB message */ | ||||||
|  | struct cl_portclosed_oob { | ||||||
|  | 	unsigned char cmd;	/* CLUSTER_OOB_MSG_PORTCLOSED */ | ||||||
|  | 	unsigned char port; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Get all version numbers or set the config version */ | ||||||
|  | struct cl_version { | ||||||
|  | 	unsigned int major; | ||||||
|  | 	unsigned int minor; | ||||||
|  | 	unsigned int patch; | ||||||
|  | 	unsigned int config; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* structure passed to barrier ioctls */ | ||||||
|  | struct cl_barrier_info { | ||||||
|  | 	char cmd; | ||||||
|  | 	char name[MAX_BARRIER_NAME_LEN]; | ||||||
|  | 	unsigned int flags; | ||||||
|  | 	unsigned long arg; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef enum { SERVICE_EVENT_STOP, SERVICE_EVENT_START, SERVICE_EVENT_FINISH, | ||||||
|  | 		SERVICE_EVENT_LEAVEDONE } service_event_t; | ||||||
|  |  | ||||||
|  | typedef enum { SERVICE_START_FAILED, SERVICE_START_JOIN, SERVICE_START_LEAVE } | ||||||
|  | 		service_start_t; | ||||||
|  |  | ||||||
|  | struct cl_service_event { | ||||||
|  | 	service_event_t type; | ||||||
|  | 	service_start_t start_type; | ||||||
|  | 	unsigned int event_id; | ||||||
|  | 	unsigned int last_stop; | ||||||
|  | 	unsigned int last_start; | ||||||
|  | 	unsigned int last_finish; | ||||||
|  | 	unsigned int node_count; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Commands to the barrier ioctl */ | ||||||
|  | #define BARRIER_IOCTL_REGISTER 1 | ||||||
|  | #define BARRIER_IOCTL_CHANGE   2 | ||||||
|  | #define BARRIER_IOCTL_DELETE   3 | ||||||
|  | #define BARRIER_IOCTL_WAIT     4 | ||||||
|  |  | ||||||
|  | /* Attributes of a barrier - bitmask */ | ||||||
|  | #define BARRIER_ATTR_AUTODELETE 1 | ||||||
|  | #define BARRIER_ATTR_MULTISTEP  2 | ||||||
|  | #define BARRIER_ATTR_MANUAL     4 | ||||||
|  | #define BARRIER_ATTR_ENABLED    8 | ||||||
|  | #define BARRIER_ATTR_CALLBACK  16 | ||||||
|  |  | ||||||
|  | /* Attribute setting commands */ | ||||||
|  | #define BARRIER_SETATTR_AUTODELETE 1 | ||||||
|  | #define BARRIER_SETATTR_MULTISTEP  2 | ||||||
|  | #define BARRIER_SETATTR_ENABLED    3 | ||||||
|  | #define BARRIER_SETATTR_NODES      4 | ||||||
|  | #define BARRIER_SETATTR_CALLBACK   5 | ||||||
|  | #define BARRIER_SETATTR_TIMEOUT    6 | ||||||
|  |  | ||||||
|  | #endif | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| /* | /* | ||||||
|  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. |  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. | ||||||
|  * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved. |  * Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
|  * |  * | ||||||
|  * This file is part of LVM2. |  * This file is part of LVM2. | ||||||
|  * |  * | ||||||
| @@ -10,7 +10,7 @@ | |||||||
|  * |  * | ||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program; if not, write to the Free Software Foundation, |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* Functions in lvm-functions.c */ | /* Functions in lvm-functions.c */ | ||||||
| @@ -22,20 +22,14 @@ extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, | |||||||
| 		       char *resource); | 		       char *resource); | ||||||
| extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, | extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, | ||||||
| 		      char *resource); | 		      char *resource); | ||||||
| extern const char *do_lock_query(char *resource); |  | ||||||
| extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, | extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, | ||||||
| 			char *resource); | 			char *resource); | ||||||
| extern int do_check_lvm1(const char *vgname); | extern int do_check_lvm1(char *vgname); | ||||||
| extern int do_refresh_cache(void); | extern int init_lvm(int using_gulm); | ||||||
| extern int init_clvm(struct dm_hash_table *excl_uuid); |  | ||||||
| extern void destroy_lvm(void); |  | ||||||
| extern void init_lvhash(void); | extern void init_lvhash(void); | ||||||
| extern void destroy_lvhash(void); |  | ||||||
| extern void lvm_do_backup(const char *vgname); | extern int hold_unlock(char *resource); | ||||||
| extern char *get_last_lvm_error(void); | extern int hold_lock(char *resource, int mode, int flags); | ||||||
| extern void do_lock_vg(unsigned char command, unsigned char lock_flags, | extern void unlock_all(void); | ||||||
| 		      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 | #endif | ||||||
|   | |||||||
| @@ -1,382 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 = { .sun_family = AF_UNIX }; |  | ||||||
|  |  | ||||||
| 	if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) { |  | ||||||
| 		fprintf(stderr, "%s: clvmd socket name too long.", CLVMD_SOCKNAME); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Open local socket */ |  | ||||||
| 	if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { |  | ||||||
| 		fprintf(stderr, "Local socket creation failed: %s", strerror(errno)); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	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 = NULL; |  | ||||||
| 	if (!(rarray = dm_malloc(sizeof(lvm_response_t) * num_responses + |  | ||||||
| 				 sizeof(int) * 2))) { |  | ||||||
| 		errno = ENOMEM; |  | ||||||
| 		status = 0; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* 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); |  | ||||||
| 			dm_free(rarray); |  | ||||||
| 			errno = ENOMEM; |  | ||||||
| 			status = 0; |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		strcpy(rarray[i].response, inptr); |  | ||||||
| 		rarray[i].len = strlen(inptr); |  | ||||||
| 		inptr += strlen(inptr) + 1; |  | ||||||
| 		i++; |  | ||||||
| 	} |  | ||||||
| 	*num = num_responses; |  | ||||||
| 	*response = rarray; |  | ||||||
|  |  | ||||||
|       out: |  | ||||||
| 	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; |  | ||||||
| } |  | ||||||
							
								
								
									
										371
									
								
								daemons/clvmd/system-lv.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								daemons/clvmd/system-lv.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,371 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. | ||||||
|  |  * Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
|  |  * | ||||||
|  |  * This file is part of LVM2. | ||||||
|  |  * | ||||||
|  |  * This copyrighted material is made available to anyone wishing to use, | ||||||
|  |  * modify, copy, or redistribute it subject to the terms and conditions | ||||||
|  |  * of the GNU General Public License v.2. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* Routines dealing with the System LV */ | ||||||
|  |  | ||||||
|  | #include <pthread.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #include <sys/uio.h> | ||||||
|  | #include <sys/un.h> | ||||||
|  | #include <sys/time.h> | ||||||
|  | #include <sys/ioctl.h> | ||||||
|  | #include <sys/mount.h> | ||||||
|  | #include <sys/utsname.h> | ||||||
|  | #include <syslog.h> | ||||||
|  | #include <netinet/in.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <dirent.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <mntent.h> | ||||||
|  |  | ||||||
|  | #include "libdlm.h" | ||||||
|  | #include "log.h" | ||||||
|  | #include "list.h" | ||||||
|  | #include "locking.h" | ||||||
|  | #include "system-lv.h" | ||||||
|  | #include "clvm.h" | ||||||
|  | #include "clvmd-comms.h" | ||||||
|  | #include "clvmd.h" | ||||||
|  | #ifdef HAVE_CCS | ||||||
|  | #include "ccs.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define SYSTEM_LV_FILESYSTEM "ext2" | ||||||
|  | #define SYSTEM_LV_MOUNTPOINT "/tmp/.clvmd-XXXXXX" | ||||||
|  |  | ||||||
|  | extern char *config_filename(void); | ||||||
|  |  | ||||||
|  | static char system_lv_name[PATH_MAX] = { '\0' }; | ||||||
|  | static char mount_point[PATH_MAX] = { '\0' }; | ||||||
|  | static int mounted = 0; | ||||||
|  | static int mounted_rw = 0; | ||||||
|  | static int lockid; | ||||||
|  | static const char *lock_name = "CLVM_SYSTEM_LV"; | ||||||
|  |  | ||||||
|  | /* Look in /proc/mounts or (as a last resort) /etc/mtab to | ||||||
|  |    see if the system-lv is mounted. If it is mounted and we | ||||||
|  |    think it's not then abort because we don't have the right | ||||||
|  |    lock status and we don't know what other processes are doing with it. | ||||||
|  |  | ||||||
|  |    Returns 1 for mounted, 0 for not mounted so it matches the condition | ||||||
|  |    of the "mounted" static variable above. | ||||||
|  | */ | ||||||
|  | static int is_really_mounted(void) | ||||||
|  | { | ||||||
|  | 	FILE *mountfile; | ||||||
|  | 	struct mntent *ment; | ||||||
|  |  | ||||||
|  | 	mountfile = setmntent("/proc/mounts", "r"); | ||||||
|  | 	if (!mountfile) { | ||||||
|  | 		mountfile = setmntent("/etc/mtab", "r"); | ||||||
|  | 		if (!mountfile) { | ||||||
|  | 			log_error("Unable to open /proc/mounts or /etc/mtab"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Look for system LV name in the file */ | ||||||
|  | 	do { | ||||||
|  | 		ment = getmntent(mountfile); | ||||||
|  | 		if (ment) { | ||||||
|  | 			if (strcmp(ment->mnt_fsname, system_lv_name) == 0) { | ||||||
|  | 				endmntent(mountfile); | ||||||
|  | 				return 1; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	while (ment); | ||||||
|  |  | ||||||
|  | 	endmntent(mountfile); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Get the system LV name from the config file */ | ||||||
|  | static int find_system_lv(void) | ||||||
|  | { | ||||||
|  | 	if (system_lv_name[0] == '\0') { | ||||||
|  | #ifdef HAVE_CCS | ||||||
|  | 		int error; | ||||||
|  | 		ccs_node_t *ctree; | ||||||
|  |  | ||||||
|  | 		/* Read the cluster config file */ | ||||||
|  | 		/* Open the config file */ | ||||||
|  | 		error = open_ccs_file(&ctree, "clvm.ccs"); | ||||||
|  | 		if (error) { | ||||||
|  | 			perror("reading config file"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		strcpy(system_lv_name, find_ccs_str(ctree, | ||||||
|  | 						    "cluster/systemlv", '/', | ||||||
|  | 						    "/dev/vg/system_lv")); | ||||||
|  |  | ||||||
|  | 		/* Finished with config file */ | ||||||
|  | 		close_ccs_file(ctree); | ||||||
|  | #else | ||||||
|  | 		if (getenv("CLVMD_SYSTEM_LV")) | ||||||
|  | 			strcpy(system_lv_name, getenv("CLVMD_SYSTEM_LV")); | ||||||
|  | 		else | ||||||
|  | 			return -1; | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* See if it has been mounted outside our control */ | ||||||
|  | 	if (is_really_mounted() != mounted) { | ||||||
|  | 		log_error | ||||||
|  | 		    ("The system LV state has been mounted/umounted outside the control of clvmd\n" | ||||||
|  | 		     "it cannot not be used for cluster communications until this is fixed.\n"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* No prizes */ | ||||||
|  | int system_lv_umount(void) | ||||||
|  | { | ||||||
|  | 	if (!mounted) | ||||||
|  | 		return 0; | ||||||
|  |  | ||||||
|  | 	if (umount(mount_point) < 0) { | ||||||
|  | 		log_error("umount of system LV (%s) failed: %m\n", | ||||||
|  | 			  system_lv_name); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	sync_unlock(lock_name, lockid); | ||||||
|  | 	mounted = 0; | ||||||
|  |  | ||||||
|  | 	/* Remove the mount point */ | ||||||
|  | 	rmdir(mount_point); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int system_lv_mount(int readwrite) | ||||||
|  | { | ||||||
|  | 	int status; | ||||||
|  | 	int saved_errno; | ||||||
|  | 	int fd; | ||||||
|  |  | ||||||
|  | 	if (find_system_lv()) { | ||||||
|  | 		errno = EBUSY; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Is it already mounted suitably? */ | ||||||
|  | 	if (mounted) { | ||||||
|  | 		if (!readwrite || (readwrite && mounted_rw)) { | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			/* Mounted RO and we need RW */ | ||||||
|  | 			if (system_lv_umount() < 0) | ||||||
|  | 				return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Randomize the mount point */ | ||||||
|  | 	strcpy(mount_point, SYSTEM_LV_MOUNTPOINT); | ||||||
|  | 	fd = mkstemp(mount_point); | ||||||
|  | 	if (fd < 0) { | ||||||
|  | 		log_error("mkstemp for system LV mount point failed: %m\n"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Race condition here but there's no mkstemp for directories */ | ||||||
|  | 	close(fd); | ||||||
|  | 	unlink(mount_point); | ||||||
|  | 	mkdir(mount_point, 0600); | ||||||
|  |  | ||||||
|  | 	/* Make sure we have a system-lv lock */ | ||||||
|  | 	status = | ||||||
|  | 	    sync_lock(lock_name, (readwrite) ? LKM_EXMODE : LKM_CRMODE, 0, | ||||||
|  | 		      &lockid); | ||||||
|  | 	if (status < 0) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	/* Mount it */ | ||||||
|  | 	if (mount(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM, | ||||||
|  | 		  MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_SYNCHRONOUS | ||||||
|  | 		  | (readwrite ? 0 : MS_RDONLY), NULL) < 0) { | ||||||
|  | 		/* mount(2) returns EINVAL if the volume has no FS on it. So, if we want to | ||||||
|  | 		   write to it we try to make a filesystem in it and retry the mount */ | ||||||
|  | 		if (errno == EINVAL && readwrite) { | ||||||
|  | 			char cmd[256]; | ||||||
|  |  | ||||||
|  | 			log_error("Attempting mkfs on system LV device %s\n", | ||||||
|  | 				  system_lv_name); | ||||||
|  | 			snprintf(cmd, sizeof(cmd), "/sbin/mkfs -t %s %s", | ||||||
|  | 				 SYSTEM_LV_FILESYSTEM, system_lv_name); | ||||||
|  | 			system(cmd); | ||||||
|  |  | ||||||
|  | 			if (mount | ||||||
|  | 			    (system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM, | ||||||
|  | 			     MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC | | ||||||
|  | 			     MS_SYNCHRONOUS | (readwrite ? 0 : MS_RDONLY), | ||||||
|  | 			     NULL) == 0) | ||||||
|  | 				goto mounted; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		saved_errno = errno; | ||||||
|  | 		log_error("mount of system LV (%s, %s, %s) failed: %m\n", | ||||||
|  | 			  system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM); | ||||||
|  | 		sync_unlock(lock_name, lockid); | ||||||
|  | 		errno = saved_errno; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |       mounted: | ||||||
|  | /* Set the internal flags */ | ||||||
|  | 	mounted = 1; | ||||||
|  | 	mounted_rw = readwrite; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Erase *all* files in the root directory of the system LV. | ||||||
|  |    This *MUST* be called with an appropriate lock held! | ||||||
|  |    The LV is left mounted RW because it is assumed that the | ||||||
|  |    caller wants to write something here after clearing some space */ | ||||||
|  | int system_lv_eraseall(void) | ||||||
|  | { | ||||||
|  | 	DIR *dir; | ||||||
|  | 	struct dirent *ent; | ||||||
|  | 	char fname[PATH_MAX]; | ||||||
|  |  | ||||||
|  | 	/* Must be mounted R/W */ | ||||||
|  | 	system_lv_mount(1); | ||||||
|  |  | ||||||
|  | 	dir = opendir(mount_point); | ||||||
|  | 	if (!dir) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	while ((ent = readdir(dir))) { | ||||||
|  | 		struct stat st; | ||||||
|  | 		snprintf(fname, sizeof(fname), "%s/%s", mount_point, | ||||||
|  | 			 ent->d_name); | ||||||
|  |  | ||||||
|  | 		if (stat(fname, &st)) { | ||||||
|  | 			if (S_ISREG(st.st_mode)) | ||||||
|  | 				unlink(fname); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	closedir(dir); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* This is a "high-level" routine - it mounts the system LV, writes | ||||||
|  |    the data into a file named after this node and then umounts the LV | ||||||
|  |    again */ | ||||||
|  | int system_lv_write_data(char *data, ssize_t len) | ||||||
|  | { | ||||||
|  | 	struct utsname nodeinfo; | ||||||
|  | 	char fname[PATH_MAX]; | ||||||
|  | 	int outfile; | ||||||
|  | 	ssize_t thiswrite; | ||||||
|  | 	ssize_t written; | ||||||
|  |  | ||||||
|  | 	if (system_lv_mount(1)) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	/* Build the file name we are goingto use. */ | ||||||
|  | 	uname(&nodeinfo); | ||||||
|  | 	snprintf(fname, sizeof(fname), "%s/%s", mount_point, nodeinfo.nodename); | ||||||
|  |  | ||||||
|  | 	/* Open the file for output */ | ||||||
|  | 	outfile = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0600); | ||||||
|  | 	if (outfile < 0) { | ||||||
|  | 		int saved_errno = errno; | ||||||
|  | 		system_lv_umount(); | ||||||
|  | 		errno = saved_errno; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	written = 0; | ||||||
|  | 	do { | ||||||
|  | 		thiswrite = write(outfile, data + written, len - written); | ||||||
|  | 		if (thiswrite > 0) | ||||||
|  | 			written += thiswrite; | ||||||
|  |  | ||||||
|  | 	} while (written < len && thiswrite > 0); | ||||||
|  |  | ||||||
|  | 	close(outfile); | ||||||
|  |  | ||||||
|  | 	system_lv_umount(); | ||||||
|  | 	return (thiswrite < 0) ? -1 : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* This is a "high-level" routine - it mounts the system LV, reads | ||||||
|  |    the data from a named file and then umounts the LV | ||||||
|  |    again */ | ||||||
|  | int system_lv_read_data(char *fname_base, char *data, ssize_t *len) | ||||||
|  | { | ||||||
|  | 	char fname[PATH_MAX]; | ||||||
|  | 	int outfile; | ||||||
|  | 	struct stat st; | ||||||
|  | 	ssize_t filesize; | ||||||
|  | 	ssize_t thisread; | ||||||
|  | 	ssize_t readbytes; | ||||||
|  |  | ||||||
|  | 	if (system_lv_mount(0)) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	/* Build the file name we are going to use. */ | ||||||
|  | 	snprintf(fname, sizeof(fname), "%s/%s", mount_point, fname_base); | ||||||
|  |  | ||||||
|  | 	/* Get the file size and stuff. Actually we only need the file size but | ||||||
|  | 	   this will also check that the file exists */ | ||||||
|  | 	if (stat(fname, &st) < 0) { | ||||||
|  | 		int saved_errno = errno; | ||||||
|  |  | ||||||
|  | 		log_error("stat of file %s on system LV failed: %m\n", fname); | ||||||
|  | 		system_lv_umount(); | ||||||
|  | 		errno = saved_errno; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	filesize = st.st_size; | ||||||
|  |  | ||||||
|  | 	outfile = open(fname, O_RDONLY); | ||||||
|  | 	if (outfile < 0) { | ||||||
|  | 		int saved_errno = errno; | ||||||
|  |  | ||||||
|  | 		log_error("open of file %s on system LV failed: %m\n", fname); | ||||||
|  | 		system_lv_umount(); | ||||||
|  | 		errno = saved_errno; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	readbytes = 0; | ||||||
|  | 	do { | ||||||
|  | 		thisread = | ||||||
|  | 		    read(outfile, data + readbytes, filesize - readbytes); | ||||||
|  | 		if (thisread > 0) | ||||||
|  | 			readbytes += thisread; | ||||||
|  |  | ||||||
|  | 	} while (readbytes < filesize && thisread > 0); | ||||||
|  |  | ||||||
|  | 	close(outfile); | ||||||
|  |  | ||||||
|  | 	system_lv_umount(); | ||||||
|  |  | ||||||
|  | 	*len = readbytes; | ||||||
|  | 	return (thisread < 0) ? -1 : 0; | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								daemons/clvmd/system-lv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								daemons/clvmd/system-lv.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. | ||||||
|  |  * Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||||
|  |  * | ||||||
|  |  * This file is part of LVM2. | ||||||
|  |  * | ||||||
|  |  * This copyrighted material is made available to anyone wishing to use, | ||||||
|  |  * modify, copy, or redistribute it subject to the terms and conditions | ||||||
|  |  * of the GNU General Public License v.2. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _CLVM_SYSTEM_LV_H | ||||||
|  | #define _CLVM_SYSTEM_LV_H | ||||||
|  |  | ||||||
|  | /* Prototypes for System-LV functions */ | ||||||
|  |  | ||||||
|  | /* "low-level" functions */ | ||||||
|  | extern int system_lv_umount(void); | ||||||
|  | extern int system_lv_mount(int readwrite); | ||||||
|  | extern int system_lv_eraseall(void); | ||||||
|  |  | ||||||
|  | /* "high-level" functions */ | ||||||
|  | extern int system_lv_write_data(char *data, ssize_t len); | ||||||
|  | extern int system_lv_read_data(char *fname_base, char *data, ssize_t *len); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										505
									
								
								daemons/clvmd/tcp-comms.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										505
									
								
								daemons/clvmd/tcp-comms.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,505 @@ | |||||||
|  | /****************************************************************************** | ||||||
|  | ******************************************************************************* | ||||||
|  | ** | ||||||
|  | **  Copyright (C) Sistina Software, Inc.  2002-2003  All rights reserved. | ||||||
|  | **  Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | ||||||
|  | ** | ||||||
|  | ******************************************************************************* | ||||||
|  | ******************************************************************************/ | ||||||
|  |  | ||||||
|  | /* This provides the inter-clvmd communications for a system without CMAN. | ||||||
|  |    There is a listening TCP socket which accepts new connections in the | ||||||
|  |    normal way. | ||||||
|  |    It can also make outgoing connnections to the other clvmd nodes. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #include <pthread.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/utsname.h> | ||||||
|  | #include <sys/ioctl.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #include <netinet/in.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <syslog.h> | ||||||
|  | #include <netdb.h> | ||||||
|  | #include <assert.h> | ||||||
|  |  | ||||||
|  | #include "libdevmapper.h" | ||||||
|  | #include "clvm.h" | ||||||
|  | #include "clvmd-comms.h" | ||||||
|  | #include "clvmd.h" | ||||||
|  | #include "clvmd-gulm.h" | ||||||
|  |  | ||||||
|  | #define DEFAULT_TCP_PORT 21064 | ||||||
|  |  | ||||||
|  | static int listen_fd = -1; | ||||||
|  | static int tcp_port; | ||||||
|  | struct dm_hash_table *sock_hash; | ||||||
|  |  | ||||||
|  | static int get_our_ip_address(char *addr, int *family); | ||||||
|  | static int read_from_tcpsock(struct local_client *fd, char *buf, int len, char *csid, | ||||||
|  | 			     struct local_client **new_client); | ||||||
|  |  | ||||||
|  | /* Called by init_cluster() to open up the listening socket */ | ||||||
|  | int init_comms(unsigned short port) | ||||||
|  | { | ||||||
|  |     struct sockaddr_in6 addr; | ||||||
|  |  | ||||||
|  |     sock_hash = dm_hash_create(100); | ||||||
|  |     tcp_port = port ? : DEFAULT_TCP_PORT; | ||||||
|  |  | ||||||
|  |     listen_fd = socket(AF_INET6, SOCK_STREAM, 0); | ||||||
|  |  | ||||||
|  |     if (listen_fd < 0) | ||||||
|  |     { | ||||||
|  | 	return -1; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  | 	int one = 1; | ||||||
|  | 	setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)); | ||||||
|  | 	setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     memset(&addr, 0, sizeof(addr)); // Bind to INADDR_ANY | ||||||
|  |     addr.sin6_family = AF_INET6; | ||||||
|  |     addr.sin6_port = htons(tcp_port); | ||||||
|  |  | ||||||
|  |     if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) | ||||||
|  |     { | ||||||
|  | 	DEBUGLOG("Can't bind to port: %s\n", strerror(errno)); | ||||||
|  | 	syslog(LOG_ERR, "Can't bind to port %d, is clvmd already running ?", tcp_port); | ||||||
|  | 	close(listen_fd); | ||||||
|  | 	return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     listen(listen_fd, 5); | ||||||
|  |  | ||||||
|  |     /* Set Close-on-exec */ | ||||||
|  |     fcntl(listen_fd, F_SETFD, 1); | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void tcp_remove_client(char *csid) | ||||||
|  |  { | ||||||
|  |     struct local_client *client; | ||||||
|  |     DEBUGLOG("tcp_remove_client\n"); | ||||||
|  |  | ||||||
|  |     /* Don't actually close the socket here - that's the | ||||||
|  |        job of clvmd.c whch will do the job when it notices the | ||||||
|  |        other end has gone. We just need to remove the client(s) from | ||||||
|  |        the hash table so we don't try to use it for sending any more */ | ||||||
|  |     client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN); | ||||||
|  |     if (client) | ||||||
|  |     { | ||||||
|  | 	dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN); | ||||||
|  | 	client->removeme = 1; | ||||||
|  | 	close(client->fd); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Look for a mangled one too */ | ||||||
|  |     csid[0] ^= 0x80; | ||||||
|  |  | ||||||
|  |     client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN); | ||||||
|  |     if (client) | ||||||
|  |     { | ||||||
|  | 	dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN); | ||||||
|  | 	client->removeme = 1; | ||||||
|  | 	close(client->fd); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Put it back as we found it */ | ||||||
|  |     csid[0] ^= 0x80; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int alloc_client(int fd, char *csid, struct local_client **new_client) | ||||||
|  | { | ||||||
|  |     struct local_client *client; | ||||||
|  |  | ||||||
|  |     DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid)); | ||||||
|  |  | ||||||
|  |     /* Create a local_client and return it */ | ||||||
|  |     client = malloc(sizeof(struct local_client)); | ||||||
|  |     if (!client) | ||||||
|  |     { | ||||||
|  | 	DEBUGLOG("malloc failed\n"); | ||||||
|  | 	return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     memset(client, 0, sizeof(struct local_client)); | ||||||
|  |     client->fd = fd; | ||||||
|  |     client->type = CLUSTER_DATA_SOCK; | ||||||
|  |     client->callback = read_from_tcpsock; | ||||||
|  |     if (new_client) | ||||||
|  | 	*new_client = client; | ||||||
|  |  | ||||||
|  |     /* Add to our list of node sockets */ | ||||||
|  |     if (dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN)) | ||||||
|  |     { | ||||||
|  | 	DEBUGLOG("alloc_client mangling CSID for second connection\n"); | ||||||
|  | 	/* This is a duplicate connection but we can't close it because | ||||||
|  | 	   the other end may already have started sending. | ||||||
|  | 	   So, we mangle the IP address and keep it, all sending will | ||||||
|  | 	   go out of the main FD | ||||||
|  | 	*/ | ||||||
|  | 	csid[0] ^= 0x80; | ||||||
|  | 	client->bits.net.flags = 1; /* indicate mangled CSID */ | ||||||
|  |  | ||||||
|  |         /* If it still exists then kill the connection as we should only | ||||||
|  |            ever have one incoming connection from each node */ | ||||||
|  |         if (dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN)) | ||||||
|  |         { | ||||||
|  | 	    DEBUGLOG("Multiple incoming connections from node\n"); | ||||||
|  |             syslog(LOG_ERR, " Bogus incoming connection from %d.%d.%d.%d\n", csid[0],csid[1],csid[2],csid[3]); | ||||||
|  |  | ||||||
|  | 	    free(client); | ||||||
|  |             errno = ECONNREFUSED; | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     dm_hash_insert_binary(sock_hash, csid, GULM_MAX_CSID_LEN, client); | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int get_main_gulm_cluster_fd() | ||||||
|  | { | ||||||
|  |     return listen_fd; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Read on main comms (listen) socket, accept it */ | ||||||
|  | int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid, | ||||||
|  | 			struct local_client **new_client) | ||||||
|  | { | ||||||
|  |     int newfd; | ||||||
|  |     struct sockaddr_in6 addr; | ||||||
|  |     socklen_t addrlen = sizeof(addr); | ||||||
|  |     int status; | ||||||
|  |     char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN]; | ||||||
|  |  | ||||||
|  |     DEBUGLOG("cluster_fd_callback\n"); | ||||||
|  |     *new_client = NULL; | ||||||
|  |     newfd = accept(listen_fd, (struct sockaddr *)&addr, &addrlen); | ||||||
|  |  | ||||||
|  |     DEBUGLOG("cluster_fd_callback, newfd=%d (errno=%d)\n", newfd, errno); | ||||||
|  |     if (!newfd) | ||||||
|  |     { | ||||||
|  | 	syslog(LOG_ERR, "error in accept: %m"); | ||||||
|  | 	errno = EAGAIN; | ||||||
|  | 	return -1; /* Don't return an error or clvmd will close the listening FD */ | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Check that the client is a member of the cluster | ||||||
|  |        and reject if not. | ||||||
|  |     */ | ||||||
|  |     if (gulm_name_from_csid((char *)&addr.sin6_addr, name) < 0) | ||||||
|  |     { | ||||||
|  | 	syslog(LOG_ERR, "Got connect from non-cluster node %s\n", | ||||||
|  | 	       print_csid((char *)&addr.sin6_addr)); | ||||||
|  | 	DEBUGLOG("Got connect from non-cluster node %s\n", | ||||||
|  | 		 print_csid((char *)&addr.sin6_addr)); | ||||||
|  | 	close(newfd); | ||||||
|  |  | ||||||
|  | 	errno = EAGAIN; | ||||||
|  | 	return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     status = alloc_client(newfd, (char *)&addr.sin6_addr, new_client); | ||||||
|  |     if (status) | ||||||
|  |     { | ||||||
|  | 	DEBUGLOG("cluster_fd_callback, alloc_client failed, status = %d\n", status); | ||||||
|  | 	close(newfd); | ||||||
|  | 	/* See above... */ | ||||||
|  | 	errno = EAGAIN; | ||||||
|  | 	return -1; | ||||||
|  |     } | ||||||
|  |     DEBUGLOG("cluster_fd_callback, returning %d, %p\n", newfd, *new_client); | ||||||
|  |     return newfd; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Try to get at least 'len' bytes from the socket */ | ||||||
|  | static int really_read(int fd, char *buf, int len) | ||||||
|  | { | ||||||
|  | 	int got, offset; | ||||||
|  |  | ||||||
|  | 	got = offset = 0; | ||||||
|  |  | ||||||
|  | 	do { | ||||||
|  | 		got = read(fd, buf+offset, len-offset); | ||||||
|  | 		DEBUGLOG("really_read. got %d bytes\n", got); | ||||||
|  | 		offset += got; | ||||||
|  | 	} while (got > 0 && offset < len); | ||||||
|  |  | ||||||
|  | 	if (got < 0) | ||||||
|  | 		return got; | ||||||
|  | 	else | ||||||
|  | 		return offset; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static int read_from_tcpsock(struct local_client *client, char *buf, int len, char *csid, | ||||||
|  | 			     struct local_client **new_client) | ||||||
|  | { | ||||||
|  |     struct sockaddr_in6 addr; | ||||||
|  |     socklen_t slen = sizeof(addr); | ||||||
|  |     struct clvm_header *header = (struct clvm_header *)buf; | ||||||
|  |     int status; | ||||||
|  |     uint32_t arglen; | ||||||
|  |  | ||||||
|  |     DEBUGLOG("read_from_tcpsock fd %d\n", client->fd); | ||||||
|  |     *new_client = NULL; | ||||||
|  |  | ||||||
|  |     /* Get "csid" */ | ||||||
|  |     getpeername(client->fd, (struct sockaddr *)&addr, &slen); | ||||||
|  |     memcpy(csid, &addr.sin6_addr, GULM_MAX_CSID_LEN); | ||||||
|  |  | ||||||
|  |     /* Read just the header first, then get the rest if there is any. | ||||||
|  |      * Stream sockets, sigh. | ||||||
|  |      */ | ||||||
|  |     status = really_read(client->fd, buf, sizeof(struct clvm_header)); | ||||||
|  |     if (status > 0) | ||||||
|  |     { | ||||||
|  | 	    int status2; | ||||||
|  |  | ||||||
|  | 	    arglen = ntohl(header->arglen); | ||||||
|  |  | ||||||
|  | 	    /* Get the rest */ | ||||||
|  | 	    if (arglen && arglen < GULM_MAX_CLUSTER_MESSAGE) | ||||||
|  | 	    { | ||||||
|  | 		    status2 = really_read(client->fd, buf+status, arglen); | ||||||
|  | 		    if (status2 > 0) | ||||||
|  | 			    status += status2; | ||||||
|  | 		    else | ||||||
|  | 			    status = status2; | ||||||
|  | 	    } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     DEBUGLOG("read_from_tcpsock, status = %d(errno = %d)\n", status, errno); | ||||||
|  |  | ||||||
|  |     /* Remove it from the hash table if there's an error, clvmd will | ||||||
|  |        remove the socket from its lists and free the client struct */ | ||||||
|  |     if (status == 0 || | ||||||
|  | 	(status < 0 && errno != EAGAIN && errno != EINTR)) | ||||||
|  |     { | ||||||
|  | 	char remcsid[GULM_MAX_CSID_LEN]; | ||||||
|  |  | ||||||
|  | 	memcpy(remcsid, csid, GULM_MAX_CSID_LEN); | ||||||
|  | 	close(client->fd); | ||||||
|  |  | ||||||
|  | 	/* If the csid was mangled, then make sure we remove the right entry */ | ||||||
|  | 	if (client->bits.net.flags) | ||||||
|  | 	    remcsid[0] ^= 0x80; | ||||||
|  | 	dm_hash_remove_binary(sock_hash, remcsid, GULM_MAX_CSID_LEN); | ||||||
|  |  | ||||||
|  | 	/* Tell cluster manager layer */ | ||||||
|  | 	add_down_node(remcsid); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  | 	    gulm_add_up_node(csid); | ||||||
|  | 	    /* Send it back to clvmd */ | ||||||
|  | 	    process_message(client, buf, status, csid); | ||||||
|  |     } | ||||||
|  |     return status; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int gulm_connect_csid(char *csid, struct local_client **newclient) | ||||||
|  | { | ||||||
|  |     int fd; | ||||||
|  |     struct sockaddr_in6 addr; | ||||||
|  |     int status; | ||||||
|  |     int one = 1; | ||||||
|  |  | ||||||
|  |     DEBUGLOG("Connecting socket\n"); | ||||||
|  |     fd = socket(PF_INET6, SOCK_STREAM, 0); | ||||||
|  |  | ||||||
|  |     if (fd < 0) | ||||||
|  |     { | ||||||
|  | 	syslog(LOG_ERR, "Unable to create new socket: %m"); | ||||||
|  | 	return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     addr.sin6_family = AF_INET6; | ||||||
|  |     memcpy(&addr.sin6_addr, csid, GULM_MAX_CSID_LEN); | ||||||
|  |     addr.sin6_port = htons(tcp_port); | ||||||
|  |  | ||||||
|  |     DEBUGLOG("Connecting socket %d\n", fd); | ||||||
|  |     if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0) | ||||||
|  |     { | ||||||
|  | 	/* "Connection refused" is "normal" because clvmd may not yet be running | ||||||
|  | 	 * on that node. | ||||||
|  | 	 */ | ||||||
|  | 	if (errno != ECONNREFUSED) | ||||||
|  | 	{ | ||||||
|  | 	    syslog(LOG_ERR, "Unable to connect to remote node: %m"); | ||||||
|  | 	} | ||||||
|  | 	DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno)); | ||||||
|  | 	close(fd); | ||||||
|  | 	return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Set Close-on-exec */ | ||||||
|  |     fcntl(fd, F_SETFD, 1); | ||||||
|  |     setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int)); | ||||||
|  |  | ||||||
|  |     status = alloc_client(fd, csid, newclient); | ||||||
|  |     if (status) | ||||||
|  | 	close(fd); | ||||||
|  |     else | ||||||
|  | 	add_client(*newclient); | ||||||
|  |  | ||||||
|  |     /* If we can connect to it, it must be running a clvmd */ | ||||||
|  |     gulm_add_up_node(csid); | ||||||
|  |     return status; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Send a message to a known CSID */ | ||||||
|  | static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const char *errtext) | ||||||
|  | { | ||||||
|  |     int status; | ||||||
|  |     struct local_client *client; | ||||||
|  |     char ourcsid[GULM_MAX_CSID_LEN]; | ||||||
|  |  | ||||||
|  |     assert(csid); | ||||||
|  |  | ||||||
|  |     DEBUGLOG("tcp_send_message, csid = %s, msglen = %d\n", print_csid(csid), msglen); | ||||||
|  |  | ||||||
|  |     /* Don't connect to ourself */ | ||||||
|  |     get_our_gulm_csid(ourcsid); | ||||||
|  |     if (memcmp(csid, ourcsid, GULM_MAX_CSID_LEN) == 0) | ||||||
|  | 	return msglen; | ||||||
|  |  | ||||||
|  |     client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN); | ||||||
|  |     if (!client) | ||||||
|  |     { | ||||||
|  | 	status = gulm_connect_csid(csid, &client); | ||||||
|  | 	if (status) | ||||||
|  | 	    return -1; | ||||||
|  |     } | ||||||
|  |     DEBUGLOG("tcp_send_message, fd = %d\n", client->fd); | ||||||
|  |  | ||||||
|  |     return write(client->fd, buf, msglen); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext) | ||||||
|  | { | ||||||
|  |     int status=0; | ||||||
|  |  | ||||||
|  |     DEBUGLOG("cluster send message, csid = %p, msglen = %d\n", csid, msglen); | ||||||
|  |  | ||||||
|  |     /* If csid is NULL then send to all known (not just connected) nodes */ | ||||||
|  |     if (!csid) | ||||||
|  |     { | ||||||
|  | 	void *context = NULL; | ||||||
|  | 	char loop_csid[GULM_MAX_CSID_LEN]; | ||||||
|  |  | ||||||
|  | 	/* Loop round all gulm-known nodes */ | ||||||
|  | 	while (get_next_node_csid(&context, loop_csid)) | ||||||
|  | 	{ | ||||||
|  | 	    status = tcp_send_message(buf, msglen, loop_csid, errtext); | ||||||
|  | 	    if (status == 0 || | ||||||
|  | 		(status < 0 && (errno == EAGAIN || errno == EINTR))) | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |  | ||||||
|  | 	status = tcp_send_message(buf, msglen, csid, errtext); | ||||||
|  |     } | ||||||
|  |     return status; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* To get our own IP address we get the locally bound address of the | ||||||
|  |    socket that's talking to GULM in the assumption(eek) that it will | ||||||
|  |    be on the "right" network in a multi-homed system */ | ||||||
|  | static int get_our_ip_address(char *addr, int *family) | ||||||
|  | { | ||||||
|  | 	struct utsname info; | ||||||
|  |  | ||||||
|  | 	uname(&info); | ||||||
|  | 	get_ip_address(info.nodename, addr); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Public version of above for those that don't care what protocol | ||||||
|  |    we're using */ | ||||||
|  | void get_our_gulm_csid(char *csid) | ||||||
|  | { | ||||||
|  |     static char our_csid[GULM_MAX_CSID_LEN]; | ||||||
|  |     static int got_csid = 0; | ||||||
|  |  | ||||||
|  |     if (!got_csid) | ||||||
|  |     { | ||||||
|  | 	int family; | ||||||
|  |  | ||||||
|  | 	memset(our_csid, 0, sizeof(our_csid)); | ||||||
|  | 	if (get_our_ip_address(our_csid, &family)) | ||||||
|  | 	{ | ||||||
|  | 	    got_csid = 1; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |     memcpy(csid, our_csid, GULM_MAX_CSID_LEN); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6) | ||||||
|  | { | ||||||
|  |    ip6->s6_addr32[0] = 0; | ||||||
|  |    ip6->s6_addr32[1] = 0; | ||||||
|  |    ip6->s6_addr32[2] = htonl(0xffff); | ||||||
|  |    ip6->s6_addr32[3] = ip4->s_addr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Get someone else's IP address from DNS */ | ||||||
|  | int get_ip_address(char *node, char *addr) | ||||||
|  | { | ||||||
|  |     struct hostent *he; | ||||||
|  |  | ||||||
|  |     memset(addr, 0, GULM_MAX_CSID_LEN); | ||||||
|  |  | ||||||
|  |     // TODO: what do we do about multi-homed hosts ??? | ||||||
|  |     // CCSs ip_interfaces solved this but some bugger removed it. | ||||||
|  |  | ||||||
|  |     /* Try IPv6 first. The man page for gethostbyname implies that | ||||||
|  |        it will lookup ip6 & ip4 names, but it seems not to */ | ||||||
|  |     he = gethostbyname2(node, AF_INET6); | ||||||
|  |     if (he) | ||||||
|  |     { | ||||||
|  | 	memcpy(addr, he->h_addr_list[0], | ||||||
|  | 	       he->h_length); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  | 	he = gethostbyname2(node, AF_INET); | ||||||
|  | 	if (!he) | ||||||
|  | 	    return -1; | ||||||
|  | 	map_v4_to_v6((struct in_addr *)he->h_addr_list[0], (struct in6_addr *)addr); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *print_csid(char *csid) | ||||||
|  | { | ||||||
|  |     static char buf[128]; | ||||||
|  |     int *icsid = (int *)csid; | ||||||
|  |  | ||||||
|  |     sprintf(buf, "[%x.%x.%x.%x]", | ||||||
|  | 	    icsid[0],icsid[1],icsid[2],icsid[3]); | ||||||
|  |  | ||||||
|  |     return buf; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								daemons/clvmd/tcp-comms.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								daemons/clvmd/tcp-comms.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | #include <netinet/in.h> | ||||||
|  |  | ||||||
|  | #define GULM_MAX_CLUSTER_MESSAGE 1600 | ||||||
|  | #define GULM_MAX_CSID_LEN sizeof(struct in6_addr) | ||||||
|  | #define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128 | ||||||
|  |  | ||||||
|  | extern int init_comms(unsigned short); | ||||||
|  | extern char *print_csid(char *); | ||||||
|  | int get_main_gulm_cluster_fd(void); | ||||||
|  | int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client); | ||||||
|  | int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext); | ||||||
|  | void get_our_gulm_csid(char *csid); | ||||||
|  | int gulm_connect_csid(char *csid, struct local_client **newclient); | ||||||
							
								
								
									
										1
									
								
								daemons/cmirrord/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								daemons/cmirrord/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | |||||||
| cmirrord |  | ||||||
| @@ -1,39 +0,0 @@ | |||||||
| # |  | ||||||
| # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) $(EXTRA_EXEC_CFLAGS) |  | ||||||
| LDFLAGS += $(EXTRA_EXEC_LDFLAGS) |  | ||||||
|  |  | ||||||
| cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a |  | ||||||
| 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \ |  | ||||||
| 		$(LVMLIBS) $(LMLIBS) $(LIBS) |  | ||||||
|  |  | ||||||
| install: $(TARGETS) |  | ||||||
| 	$(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord |  | ||||||
| @@ -1,292 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
| #include "logging.h" |  | ||||||
| #include "common.h" |  | ||||||
| #include "functions.h" |  | ||||||
| #include "link_mon.h" |  | ||||||
| #include "local.h" |  | ||||||
|  |  | ||||||
| #include <getopt.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); |  | ||||||
|  |  | ||||||
| static void usage (FILE *dest) |  | ||||||
| { |  | ||||||
| 	fprintf (dest, "Usage: cmirrord [options]\n" |  | ||||||
| 		 "   -f, --foreground    stay in the foreground, log to the terminal\n" |  | ||||||
| 		 "   -h, --help          print this help\n"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int main(int argc, char *argv[]) |  | ||||||
| { |  | ||||||
| 	int foreground_mode = 0; |  | ||||||
| 	struct option longopts[] = { |  | ||||||
| 		{ "foreground", no_argument, NULL, 'f' }, |  | ||||||
| 		{ "help"      , no_argument, NULL, 'h' }, |  | ||||||
| 		{ 0, 0, 0, 0 } |  | ||||||
| 	}; |  | ||||||
| 	int opt; |  | ||||||
|  |  | ||||||
| 	while ((opt = getopt_long (argc, argv, "fh", longopts, NULL)) != -1) { |  | ||||||
| 		switch (opt) { |  | ||||||
| 		case 'f': |  | ||||||
| 			foreground_mode = 1; |  | ||||||
| 			break; |  | ||||||
| 		case 'h': |  | ||||||
| 			usage (stdout); |  | ||||||
| 			exit (0); |  | ||||||
| 		default: |  | ||||||
| 			usage (stderr); |  | ||||||
| 			exit (2); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if (optind < argc) { |  | ||||||
| 		usage (stderr); |  | ||||||
| 		exit (2); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (!foreground_mode) |  | ||||||
| 		daemonize(); |  | ||||||
|  |  | ||||||
| 	init_all(); |  | ||||||
|  |  | ||||||
| 	/* Parent can now exit, we're ready to handle requests */ |  | ||||||
| 	if (!foreground_mode) |  | ||||||
| 		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(); |  | ||||||
| 	if (chdir("/")) { |  | ||||||
| 		LOG_ERROR("Failed to chdir /: %s", strerror(errno)); |  | ||||||
| 		exit(EXIT_FAILURE); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	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); |  | ||||||
|  |  | ||||||
| 	if ((devnull > STDERR_FILENO) && close(devnull)) { |  | ||||||
| 		LOG_ERROR("Failed to close descriptor %d: %s", |  | ||||||
| 			  devnull, strerror(errno)); |  | ||||||
| 		exit(EXIT_FAILURE); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * init_all |  | ||||||
|  * |  | ||||||
|  * Initialize modules.  Exit on failure. |  | ||||||
|  */ |  | ||||||
| static void init_all(void) |  | ||||||
| { |  | ||||||
| 	int r; |  | ||||||
|  |  | ||||||
| 	(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; |  | ||||||
|  |  | ||||||
| 	if ((r = init_local()) || |  | ||||||
| 	    (r = init_cluster())) { |  | ||||||
| 		exit(r); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * cleanup_all |  | ||||||
|  * |  | ||||||
|  * Clean up before exiting |  | ||||||
|  */ |  | ||||||
| static void cleanup_all(void) |  | ||||||
| { |  | ||||||
| 	cleanup_local(); |  | ||||||
| 	cleanup_cluster(); |  | ||||||
| } |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,76 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 */ |  | ||||||
| @@ -1,33 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 */ |  | ||||||
| @@ -1,210 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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); |  | ||||||
|  |  | ||||||
| 	rq->originator = xlate32(rq->originator); |  | ||||||
|  |  | ||||||
| 	v5_data_endian_switch(rq, 1); |  | ||||||
|  |  | ||||||
| 	u_rq->request_type = xlate32(u_rq->request_type); |  | ||||||
| 	u_rq->data_size = xlate32(u_rq->data_size); |  | ||||||
|  |  | ||||||
| 	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 = xlate32(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]); |  | ||||||
| 	struct clog_request *rq = data; |  | ||||||
|  |  | ||||||
| 	switch (version) { |  | ||||||
| 	case 5: /* Upstream */ |  | ||||||
| 		if (version == vp[0]) |  | ||||||
| 			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; |  | ||||||
| } |  | ||||||
| @@ -1,25 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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 */ |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,34 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 */ |  | ||||||
| @@ -1,151 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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; |  | ||||||
| } |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 */ |  | ||||||
| @@ -1,424 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 = -1;  /* 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; |  | ||||||
| 			if (kernel_send(u_rq)) |  | ||||||
| 				LOG_ERROR("Failed to respond to kernel [%s]", |  | ||||||
| 					  RQ_TYPE(u_rq->request_type)); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		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) { |  | ||||||
| 		if (close(cn_fd)) |  | ||||||
| 			LOG_ERROR("Failed to close socket: %s", |  | ||||||
| 				  strerror(errno)); |  | ||||||
| 		return EXIT_KERNEL_BIND; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	opt = addr.nl_groups; |  | ||||||
| 	r = setsockopt(cn_fd, 270, NETLINK_ADD_MEMBERSHIP, &opt, sizeof(opt)); |  | ||||||
| 	if (r) { |  | ||||||
| 		if (close(cn_fd)) |  | ||||||
| 			LOG_ERROR("Failed to close socket: %s", |  | ||||||
| 				  strerror(errno)); |  | ||||||
| 		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); |  | ||||||
| 	if (cn_fd >= 0 && close(cn_fd)) |  | ||||||
| 		LOG_ERROR("Failed to close socket: %s", |  | ||||||
| 			  strerror(errno)); |  | ||||||
| } |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 */ |  | ||||||
| @@ -1,57 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 |  | ||||||
| @@ -1,77 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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...) do {} while (0) |  | ||||||
| #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 */ |  | ||||||
| @@ -1,4 +1,5 @@ | |||||||
| init_fifos | dm_event_register | ||||||
| fini_fifos | dm_event_unregister | ||||||
| daemon_talk | dm_event_get_registered_device | ||||||
| dm_event_get_version | dm_event_set_timeout | ||||||
|  | dm_event_get_timeout | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								daemons/dmeventd/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								daemons/dmeventd/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | |||||||
| dmeventd |  | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| # | # | ||||||
| # Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved. | # Copyright (C) 2005 Red Hat, Inc. All rights reserved. | ||||||
| # | # | ||||||
| # This file is part of the device-mapper userspace tools. | # This file is part of the device-mapper userspace tools. | ||||||
| # | # | ||||||
| @@ -9,102 +9,65 @@ | |||||||
| # | # | ||||||
| # You should have received a copy of the GNU Lesser General Public License | # You should have received a copy of the GNU Lesser General Public License | ||||||
| # along with this program; if not, write to the Free Software Foundation, | # along with this program; if not, write to the Free Software Foundation, | ||||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  | ||||||
| srcdir = @srcdir@ | srcdir = @srcdir@ | ||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| top_builddir = @top_builddir@ | VPATH = @srcdir@ | ||||||
|  |  | ||||||
| SOURCES = libdevmapper-event.c | SOURCES = libdevmapper-event.c \ | ||||||
| SOURCES2 = dmeventd.c | 	  dmeventd.c | ||||||
|  |  | ||||||
| TARGETS = dmeventd | LIB_STATIC = libdevmapper-event.a | ||||||
|  |  | ||||||
| .PHONY: install_lib_dynamic install_lib_static install_include \ | ifeq ("@LIB_SUFFIX@","dylib") | ||||||
| 	install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \ |   LIB_SHARED = libdevmapper-event.dylib | ||||||
| 	install_lib install_dmeventd | else | ||||||
|  |   LIB_SHARED = libdevmapper-event.so | ||||||
|  | endif | ||||||
|  |  | ||||||
| INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic | include ../make.tmpl | ||||||
| INSTALL_LIB_TARGETS = install_lib_dynamic |  | ||||||
|  | CLDFLAGS += -ldl -ldevmapper -lpthread | ||||||
|  |  | ||||||
|  | .PHONY: install_dynamic install_static install_include \ | ||||||
|  | 	install_pkgconfig | ||||||
|  |  | ||||||
|  | INSTALL_TYPE = install_dynamic | ||||||
|  |  | ||||||
| LIB_NAME = libdevmapper-event |  | ||||||
| ifeq ("@STATIC_LINK@", "yes") | ifeq ("@STATIC_LINK@", "yes") | ||||||
|   LIB_STATIC = $(LIB_NAME).a |   INSTALL_TYPE += install_static | ||||||
|   TARGETS += $(LIB_STATIC) dmeventd.static |  | ||||||
|   INSTALL_DMEVENTD_TARGETS += install_dmeventd_static |  | ||||||
|   INSTALL_LIB_TARGETS += install_lib_static |  | ||||||
| endif | 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) |  | ||||||
|  |  | ||||||
| CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS) |  | ||||||
|  |  | ||||||
| dmeventd: $(LIB_SHARED) dmeventd.o |  | ||||||
| 	$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_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") | ifeq ("@PKGCONFIG@", "yes") | ||||||
|   INSTALL_LIB_TARGETS += install_pkgconfig |   INSTALL_TYPE += install_pkgconfig | ||||||
| endif | endif | ||||||
|  |  | ||||||
| ifneq ("$(CFLOW_CMD)", "") | install: $(INSTALL_TYPE) install_include | ||||||
| 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_include: | ||||||
| 	$(INSTALL_DATA) -D $< $(includedir)/$(<F) | 	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \ | ||||||
|  | 		$(includedir)/libdevmapper-event.h | ||||||
|  |  | ||||||
| install_pkgconfig: libdevmapper-event.pc | install_dynamic: libdevmapper-event.$(LIB_SUFFIX) | ||||||
| 	$(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc | 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ | ||||||
|  | 		$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) | ||||||
|  | 	$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \ | ||||||
|  | 		$(libdir)/libdevmapper-event.$(LIB_SUFFIX) | ||||||
|  |  | ||||||
| install_lib_dynamic: install_lib_shared | install_pkgconfig: | ||||||
|  | 	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \ | ||||||
|  | 		$(usrlibdir)/pkgconfig/devmapper-event.pc | ||||||
|  |  | ||||||
| install_lib_static: $(LIB_STATIC) | install_static: libdevmapper-event.a | ||||||
| 	$(INSTALL_DATA) -D $< $(usrlibdir)/$(<F) | 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ | ||||||
|  | 		$(libdir)/libdevmapper-event.a.$(LIB_VERSION) | ||||||
|  | 	$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a | ||||||
|  |  | ||||||
| install_lib: $(INSTALL_LIB_TARGETS) | .PHONY: distclean_lib distclean | ||||||
|  |  | ||||||
| install_dmeventd_dynamic: dmeventd | distclean_lib:  | ||||||
| 	$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F) | 	$(RM) libdevmapper-event.pc | ||||||
|  |  | ||||||
| install_dmeventd_static: dmeventd.static | distclean: distclean_lib | ||||||
| 	$(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 |  | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,76 +1,13 @@ | |||||||
| /* |  | ||||||
|  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #ifndef __DMEVENTD_DOT_H__ | #ifndef __DMEVENTD_DOT_H__ | ||||||
| #define __DMEVENTD_DOT_H__ | #define __DMEVENTD_DOT_H__ | ||||||
|  |  | ||||||
| /* FIXME This stuff must be configurable. */ | #define EXIT_LOCKFILE_INUSE      2 | ||||||
|  |  | ||||||
| #define	DM_EVENT_FIFO_CLIENT	DEFAULT_DM_RUN_DIR "/dmeventd-client" |  | ||||||
| #define	DM_EVENT_FIFO_SERVER	DEFAULT_DM_RUN_DIR "/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, |  | ||||||
| 	DM_EVENT_CMD_GET_PARAMETERS, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* 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_CLOSE_FAILURE  3 | ||||||
| #define EXIT_DESC_OPEN_FAILURE   4 | #define EXIT_OPEN_PID_FAILURE    4 | ||||||
| /*      EXIT_OPEN_PID_FAILURE    5 -- obsoleted */ | #define EXIT_FIFO_FAILURE        5 | ||||||
| #define EXIT_FIFO_FAILURE        6 | #define EXIT_CHDIR_FAILURE       6 | ||||||
| #define EXIT_CHDIR_FAILURE       7 |  | ||||||
|  |  | ||||||
| /* Implemented in libdevmapper-event.c, but not part of public API. */ | void dmeventd(void) | ||||||
| // FIXME  misuse of bitmask as enum |     __attribute((noreturn)); | ||||||
| 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__ */ | #endif /* __DMEVENTD_DOT_H__ */ | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved. |  * Copyright (C) 2005 Red Hat, Inc. All rights reserved. | ||||||
|  * |  * | ||||||
|  * This file is part of the device-mapper userspace tools. |  * This file is part of the device-mapper userspace tools. | ||||||
|  * |  * | ||||||
| @@ -9,7 +9,7 @@ | |||||||
|  * |  * | ||||||
|  * You should have received a copy of the GNU Lesser General Public License |  * You should have received a copy of the GNU Lesser General Public License | ||||||
|  * along with this program; if not, write to the Free Software Foundation, |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -23,113 +23,86 @@ | |||||||
|  |  | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  |  | ||||||
| /* | /* FIXME This stuff must be configurable. */ | ||||||
|  * Event library interface. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| enum dm_event_mask { | #define	DM_EVENT_DAEMON		"/sbin/dmeventd" | ||||||
| 	DM_EVENT_SETTINGS_MASK  = 0x0000FF, | #define DM_EVENT_LOCKFILE	"/var/lock/dmeventd" | ||||||
| 	DM_EVENT_SINGLE		= 0x000001, /* Report multiple errors just once. */ | #define	DM_EVENT_FIFO_CLIENT	"/var/run/dmeventd-client" | ||||||
| 	DM_EVENT_MULTI		= 0x000002, /* Report all of them. */ | #define	DM_EVENT_FIFO_SERVER	"/var/run/dmeventd-server" | ||||||
|  | #define DM_EVENT_PIDFILE	"/var/run/dmeventd.pid" | ||||||
|  |  | ||||||
| 	DM_EVENT_ERROR_MASK     = 0x00FF00, | #define DM_EVENT_DEFAULT_TIMEOUT 10 | ||||||
| 	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, | /* Commands for the daemon passed in the message below. */ | ||||||
| 	DM_EVENT_SYNC_STATUS	= 0x010000, /* Mirror synchronization completed/failed. */ | enum dm_event_command { | ||||||
| 	DM_EVENT_TIMEOUT	= 0x020000, /* Timeout has occured */ | 	DM_EVENT_CMD_ACTIVE = 1, | ||||||
|  | 	DM_EVENT_CMD_REGISTER_FOR_EVENT, | ||||||
| 	DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */ | 	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, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK | /* Message passed between client and daemon. */ | ||||||
| #define DM_EVENT_PROTOCOL_VERSION 2 | struct dm_event_daemon_message { | ||||||
|  | 	union { | ||||||
|  | 		unsigned int cmd;	/* FIXME Use fixed size. */ | ||||||
|  | 		int	 status;	/* FIXME Use fixed size. */ | ||||||
|  | 	} opcode; | ||||||
|  | 	char msg[252];		/* FIXME Why is this 252 ? */ | ||||||
|  | } __attribute__((packed));	/* FIXME Do this properly! */ | ||||||
|  |  | ||||||
| struct dm_task; | /* FIXME Is this meant to be exported?  I can't see where the interface uses it. */ | ||||||
| struct dm_event_handler; | /* Fifos for client/daemon communication. */ | ||||||
|  | struct dm_event_fifos { | ||||||
|  | 	int client; | ||||||
|  | 	int server; | ||||||
|  | 	const char *client_path; | ||||||
|  | 	const char *server_path; | ||||||
|  | }; | ||||||
|  |  | ||||||
| struct dm_event_handler *dm_event_handler_create(void); | /* Event type definitions. */ | ||||||
| void dm_event_handler_destroy(struct dm_event_handler *dmevh); | /* FIXME Use masks to separate the types and provide for extension. */ | ||||||
|  | enum dm_event_type { | ||||||
|  | 	DM_EVENT_SINGLE		= 0x01, /* Report multiple errors just once. */ | ||||||
|  | 	DM_EVENT_MULTI		= 0x02, /* Report all of them. */ | ||||||
|  |  | ||||||
| /* | 	DM_EVENT_SECTOR_ERROR	= 0x04, /* Failure on a particular sector. */ | ||||||
|  * Path of shared library to handle events. | 	DM_EVENT_DEVICE_ERROR	= 0x08, /* Device failure. */ | ||||||
|  * | 	DM_EVENT_PATH_ERROR	= 0x10, /* Failure on an io path. */ | ||||||
|  * All of dmeventd, dso, device_name and uuid strings are duplicated so | 	DM_EVENT_ADAPTOR_ERROR	= 0x20, /* Failure off a host adaptor. */ | ||||||
|  * 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); |  | ||||||
|  |  | ||||||
| /* | 	DM_EVENT_SYNC_STATUS	= 0x40, /* Mirror synchronization completed/failed. */ | ||||||
|  * Path of dmeventd binary. | 	DM_EVENT_TIMEOUT	= 0x80, /* Timeout has occured */ | ||||||
|  */ | }; | ||||||
| int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path); |  | ||||||
|  |  | ||||||
| /* | /* FIXME Use a mask. */ | ||||||
|  * Identify the device to monitor by exactly one of device_name, uuid or | #define	DM_EVENT_ALL_ERRORS (DM_EVENT_SECTOR_ERROR | DM_EVENT_DEVICE_ERROR | \ | ||||||
|  * device number. String arguments are duplicated, see above. | 			     DM_EVENT_PATH_ERROR | DM_EVENT_ADAPTOR_ERROR) | ||||||
|  */ |  | ||||||
| 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); | /* Prototypes for event lib interface. */ | ||||||
|  |  | ||||||
| void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major); | /* FIXME Replace device with standard name/uuid/devno choice */ | ||||||
| void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor); | /* Interface changes:  | ||||||
| void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout); |    First register a handler, passing in a unique ref for the device. */ | ||||||
|  | //  int dm_event_register_handler(const char *dso_name, const char *device); | ||||||
|  | //  int dm_event_register(const char *dso_name, const char *name, const char *uuid, uint32_t major, uint32_t minor, enum dm_event_type events); | ||||||
|  | /* Or (better?) add to task structure and use existing functions - run a task to register/unregister events - we may need to run task withe that with the new event mechanism anyway, then the dso calls just hook in. | ||||||
|  | */ | ||||||
|  |   | ||||||
|  | /* FIXME Missing consts? */ | ||||||
|  | int dm_event_register(char *dso_name, char *device, enum dm_event_type events); | ||||||
|  | int dm_event_unregister(char *dso_name, char *device, | ||||||
|  | 			enum dm_event_type events); | ||||||
|  | int dm_event_get_registered_device(char **dso_name, char **device, | ||||||
|  | 				   enum dm_event_type *events, int next); | ||||||
|  | int dm_event_set_timeout(char *device, uint32_t timeout); | ||||||
|  | int dm_event_get_timeout(char *device, uint32_t *timeout); | ||||||
|  |  | ||||||
| /* | /* Prototypes for DSO interface. */ | ||||||
|  * Specify mask for events to monitor. | void process_event(const char *device, enum dm_event_type event); | ||||||
|  */ | int register_device(const char *device); | ||||||
| // FIXME  misuse of bitmask as enum | int unregister_device(const char *device); | ||||||
| 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); |  | ||||||
|  |  | ||||||
| /* Set debug level for logging, and whether to log on stdout/stderr or syslog */ |  | ||||||
| void dm_event_log_set(int debug_log_level, int use_syslog); |  | ||||||
|  |  | ||||||
| /* Log messages acroding to current debug level  */ |  | ||||||
| __attribute__((format(printf, 6, 0))) |  | ||||||
| void dm_event_log(const char *subsys, int level, const char *file, |  | ||||||
| 		  int line, int dm_errno_or_class, |  | ||||||
| 		  const char *format, va_list ap); |  | ||||||
| /* Macro to route print_log do dm_event_log() */ |  | ||||||
| #define DM_EVENT_LOG_FN(subsys) \ |  | ||||||
| void print_log(int level, const char *file, int line, int dm_errno_or_class,\ |  | ||||||
| 	       const char *format, ...)\ |  | ||||||
| {\ |  | ||||||
| 	va_list ap;\ |  | ||||||
| 	va_start(ap, format);\ |  | ||||||
| 	dm_event_log(subsys, level, file, line, dm_errno_or_class, format, ap);\ |  | ||||||
| 	va_end(ap);\ |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* 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 | #endif | ||||||
|   | |||||||
| @@ -5,7 +5,8 @@ includedir=@includedir@ | |||||||
|  |  | ||||||
| Name: devmapper-event | Name: devmapper-event | ||||||
| Description: device-mapper event library | Description: device-mapper event library | ||||||
| Version: @DM_LIB_PATCHLEVEL@ | Version: @DM_LIB_VERSION@ | ||||||
|  | Requires: devmapper | ||||||
| Cflags: -I${includedir} | Cflags: -I${includedir} | ||||||
| Libs: -L${libdir} -ldevmapper-event | Libs: -L${libdir} -ldevmapper-event | ||||||
| Requires.private: devmapper | Libs.private: -lpthread -ldl | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| # | # | ||||||
| # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. | # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. | ||||||
| # Copyright (C) 2004-2005, 2011 Red Hat, Inc. All rights reserved. | # Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | ||||||
| # | # | ||||||
| # This file is part of LVM2. | # This file is part of the LVM2. | ||||||
| # | # | ||||||
| # This copyrighted material is made available to anyone wishing to use, | # This copyrighted material is made available to anyone wishing to use, | ||||||
| # modify, copy, or redistribute it subject to the terms and conditions | # modify, copy, or redistribute it subject to the terms and conditions | ||||||
| @@ -10,37 +10,13 @@ | |||||||
| # | # | ||||||
| # You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | ||||||
| # along with this program; if not, write to the Free Software Foundation, | # along with this program; if not, write to the Free Software Foundation, | ||||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  | ||||||
| srcdir = @srcdir@ | srcdir = @srcdir@ | ||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| top_builddir = @top_builddir@ | VPATH = @srcdir@ | ||||||
|  |  | ||||||
| SUBDIRS += lvm2 | SUBDIRS += mirror | ||||||
|  |  | ||||||
| ifneq ("@MIRRORS@", "none") | include $(top_srcdir)/make.tmpl | ||||||
|   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 |  | ||||||
|   | |||||||
| @@ -1,7 +0,0 @@ | |||||||
| dmeventd_lvm2_init |  | ||||||
| dmeventd_lvm2_exit |  | ||||||
| dmeventd_lvm2_lock |  | ||||||
| dmeventd_lvm2_unlock |  | ||||||
| dmeventd_lvm2_pool |  | ||||||
| dmeventd_lvm2_run |  | ||||||
| dmeventd_lvm2_command |  | ||||||
| @@ -1,31 +0,0 @@ | |||||||
| # |  | ||||||
| # Copyright (C) 2010-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) |  | ||||||
|  |  | ||||||
| install_lvm2: install_lib_shared |  | ||||||
|  |  | ||||||
| install: install_lvm2 |  | ||||||
| @@ -1,164 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2010-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "lib.h" |  | ||||||
| #include "dmeventd_lvm.h" |  | ||||||
| #include "libdevmapper-event.h" |  | ||||||
| #include "lvm2cmd.h" |  | ||||||
|  |  | ||||||
| #include <pthread.h> |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * 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; |  | ||||||
|  |  | ||||||
| DM_EVENT_LOG_FN("#lvm") |  | ||||||
|  |  | ||||||
| static void _lvm2_print_log(int level, const char *file, int line, |  | ||||||
| 			    int dm_errno_or_class, const char *msg) |  | ||||||
| { |  | ||||||
| 	print_log(level, file, line, dm_errno_or_class, "%s", msg); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Currently only one event can be processed at a time. |  | ||||||
|  */ |  | ||||||
| static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER; |  | ||||||
|  |  | ||||||
| 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); |  | ||||||
|  |  | ||||||
| 	if (!_lvm_handle) { |  | ||||||
| 		lvm2_log_fn(_lvm2_print_log); |  | ||||||
|  |  | ||||||
| 		if (!(_lvm_handle = lvm2_init())) |  | ||||||
| 			goto out; |  | ||||||
|  |  | ||||||
| 		/* |  | ||||||
| 		 * 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))) { |  | ||||||
| 			lvm2_exit(_lvm_handle); |  | ||||||
| 			_lvm_handle = NULL; |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		lvm2_disable_dmeventd_monitoring(_lvm_handle); |  | ||||||
| 		/* FIXME Temporary: move to dmeventd core */ |  | ||||||
| 		lvm2_run(_lvm_handle, "_memlock_inc"); |  | ||||||
| 		log_debug("lvm plugin initilized."); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	_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) { |  | ||||||
| 		log_debug("lvm plugin shuting down."); |  | ||||||
| 		lvm2_run(_lvm_handle, "_memlock_dec"); |  | ||||||
| 		dm_pool_destroy(_mem_pool); |  | ||||||
| 		_mem_pool = NULL; |  | ||||||
| 		lvm2_exit(_lvm_handle); |  | ||||||
| 		_lvm_handle = NULL; |  | ||||||
| 		log_debug("lvm plugin exited."); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	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) == LVM2_COMMAND_SUCCEEDED); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size, |  | ||||||
| 			  const char *cmd, const char *device) |  | ||||||
| { |  | ||||||
| 	static char _internal_prefix[] =  "_dmeventd_"; |  | ||||||
| 	char *vg = NULL, *lv = NULL, *layer; |  | ||||||
| 	int r; |  | ||||||
|  |  | ||||||
| 	if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) { |  | ||||||
| 		log_error("Unable to determine VG name from %s.", |  | ||||||
| 			  device); |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* strip off the mirror component designations */ |  | ||||||
| 	if ((layer = strstr(lv, "_mimagetmp")) || |  | ||||||
| 	    (layer = strstr(lv, "_mlog"))) |  | ||||||
| 		*layer = '\0'; |  | ||||||
|  |  | ||||||
| 	if (!strncmp(cmd, _internal_prefix, sizeof(_internal_prefix) - 1)) { |  | ||||||
| 		dmeventd_lvm2_lock(); |  | ||||||
| 		/* output of internal command passed via env var */ |  | ||||||
| 		if (!dmeventd_lvm2_run(cmd)) |  | ||||||
| 			cmd = NULL; |  | ||||||
| 		else if ((cmd = getenv(cmd))) |  | ||||||
| 			cmd = dm_pool_strdup(mem, cmd); /* copy with lock */ |  | ||||||
| 		dmeventd_lvm2_unlock(); |  | ||||||
|  |  | ||||||
| 		if (!cmd) { |  | ||||||
| 			log_error("Unable to find configured command."); |  | ||||||
| 			return 0; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv); |  | ||||||
|  |  | ||||||
| 	dm_pool_free(mem, vg); |  | ||||||
|  |  | ||||||
| 	if (r < 0) { |  | ||||||
| 		log_error("Unable to form LVM command. (too long)."); |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
| @@ -1,74 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2010-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #ifndef _DMEVENTD_LVMWRAP_H |  | ||||||
| #define _DMEVENTD_LVMWRAP_H |  | ||||||
|  |  | ||||||
| struct dm_pool; |  | ||||||
|  |  | ||||||
| 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); |  | ||||||
|  |  | ||||||
| #define dmeventd_lvm2_run_with_lock(cmdline) \ |  | ||||||
| 	({\ |  | ||||||
| 		int rc;\ |  | ||||||
| 		dmeventd_lvm2_lock();\ |  | ||||||
| 		rc = dmeventd_lvm2_run(cmdline);\ |  | ||||||
| 		dmeventd_lvm2_unlock();\ |  | ||||||
| 		rc;\ |  | ||||||
| 	}) |  | ||||||
|  |  | ||||||
| #define dmeventd_lvm2_init_with_pool(name, st) \ |  | ||||||
| 	({\ |  | ||||||
| 		struct dm_pool *mem;\ |  | ||||||
| 		st = NULL;\ |  | ||||||
| 		if (dmeventd_lvm2_init()) {\ |  | ||||||
| 			if ((mem = dm_pool_create(name, 2048)) &&\ |  | ||||||
| 			    (st = dm_pool_zalloc(mem, sizeof(*st))))\ |  | ||||||
| 				st->mem = mem;\ |  | ||||||
| 			else {\ |  | ||||||
| 				if (mem)\ |  | ||||||
| 					dm_pool_destroy(mem);\ |  | ||||||
| 				dmeventd_lvm2_exit();\ |  | ||||||
| 			}\ |  | ||||||
| 		}\ |  | ||||||
| 		st;\ |  | ||||||
| 	}) |  | ||||||
|  |  | ||||||
| #define dmeventd_lvm2_exit_with_pool(pool) \ |  | ||||||
| 	do {\ |  | ||||||
| 		dm_pool_destroy(pool->mem);\ |  | ||||||
| 		dmeventd_lvm2_exit();\ |  | ||||||
| 	} while(0) |  | ||||||
|  |  | ||||||
| #endif /* _DMEVENTD_LVMWRAP_H */ |  | ||||||
| @@ -1,8 +1,8 @@ | |||||||
| # | # | ||||||
| # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. | # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. | ||||||
| # Copyright (C) 2004-2005, 2008-2014 Red Hat, Inc. All rights reserved. | # Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | ||||||
| # | # | ||||||
| # This file is part of LVM2. | # This file is part of the LVM2. | ||||||
| # | # | ||||||
| # This copyrighted material is made available to anyone wishing to use, | # This copyrighted material is made available to anyone wishing to use, | ||||||
| # modify, copy, or redistribute it subject to the terms and conditions | # modify, copy, or redistribute it subject to the terms and conditions | ||||||
| @@ -10,28 +10,27 @@ | |||||||
| # | # | ||||||
| # You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | ||||||
| # along with this program; if not, write to the Free Software Foundation, | # along with this program; if not, write to the Free Software Foundation, | ||||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  | ||||||
| srcdir = @srcdir@ | srcdir = @srcdir@ | ||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| top_builddir = @top_builddir@ | VPATH = @srcdir@ | ||||||
|  |  | ||||||
| INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2 | INCLUDES += -I${top_srcdir}/tools | ||||||
| CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2 | CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd | ||||||
|  |  | ||||||
| SOURCES = dmeventd_mirror.c | SOURCES = dmeventd_mirror.c | ||||||
|  |  | ||||||
| LIB_NAME = libdevmapper-event-lvm2mirror | ifeq ("@LIB_SUFFIX@","dylib") | ||||||
| LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) |   LIB_SHARED = libdevmapper-event-lvm2mirror.dylib | ||||||
| LIB_VERSION = $(LIB_VERSION_LVM) | else | ||||||
|  |   LIB_SHARED = libdevmapper-event-lvm2mirror.so | ||||||
|  | endif | ||||||
|  |  | ||||||
| CFLOW_LIST = $(SOURCES) | include $(top_srcdir)/make.tmpl | ||||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow |  | ||||||
|  |  | ||||||
| include $(top_builddir)/make.tmpl | install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX) | ||||||
|  | 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ | ||||||
|  | 		$(libdir)/$<.$(LIB_VERSION) | ||||||
|  | 	$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$< | ||||||
|  |  | ||||||
| LIBS += -ldevmapper-event-lvm2 -ldevmapper |  | ||||||
|  |  | ||||||
| install_lvm2: install_dm_plugin |  | ||||||
|  |  | ||||||
| install: install_lvm2 |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved. |  * Copyright (C) 2005 Red Hat, Inc. All rights reserved. | ||||||
|  * |  * | ||||||
|  * This file is part of LVM2. |  * This file is part of LVM2. | ||||||
|  * |  * | ||||||
| @@ -9,214 +9,246 @@ | |||||||
|  * |  * | ||||||
|  * You should have received a copy of the GNU Lesser General Public License |  * You should have received a copy of the GNU Lesser General Public License | ||||||
|  * along with this program; if not, write to the Free Software Foundation, |  * along with this program; if not, write to the Free Software Foundation, | ||||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "lib.h" | #include "libdevmapper.h" | ||||||
| #include "libdevmapper-event.h" | #include "libdevmapper-event.h" | ||||||
| #include "dmeventd_lvm.h" | #include "lvm2cmd.h" | ||||||
| #include "activate.h"	/* For TARGET_NAME* */ | #include "lvm-string.h" | ||||||
|  |  | ||||||
| /* FIXME Reformat to 80 char lines. */ | #include <errno.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <pthread.h> | ||||||
|  | #include <unistd.h> | ||||||
|  |  | ||||||
|  | #include <syslog.h> /* FIXME Replace syslog with multilog */ | ||||||
|  |  | ||||||
| #define ME_IGNORE    0 | #define ME_IGNORE    0 | ||||||
| #define ME_INSYNC    1 | #define ME_INSYNC    1 | ||||||
| #define ME_FAILURE   2 | #define ME_FAILURE   2 | ||||||
|  |  | ||||||
| struct dso_state { | static pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER; | ||||||
| 	struct dm_pool *mem; |  | ||||||
| 	char cmd_lvscan[512]; |  | ||||||
| 	char cmd_lvconvert[512]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| DM_EVENT_LOG_FN("mirr") | /* FIXME: We may need to lock around operations to these */ | ||||||
|  | static int register_count = 0; | ||||||
|  | static struct dm_pool *mem_pool = NULL; | ||||||
|  |  | ||||||
| static void _process_status_code(dm_status_mirror_health_t health, | static int _get_mirror_event(char *params) | ||||||
| 				 uint32_t major, uint32_t minor, |  | ||||||
| 				 const char *dev_type, int *r) |  | ||||||
| { | { | ||||||
|  | 	int i, rtn = ME_INSYNC; | ||||||
|  | 	int max_args = 30;  /* should support at least 8-way mirrors */ | ||||||
|  | 	char *args[max_args]; | ||||||
|  | 	char *dev_status_str; | ||||||
|  | 	char *log_status_str; | ||||||
|  | 	char *sync_str; | ||||||
|  | 	char *p; | ||||||
|  | 	int log_argc, num_devs, num_failures=0; | ||||||
|  |  | ||||||
|  | 	if (max_args <= split_words(params, max_args, args)) { | ||||||
|  | 		syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long"); | ||||||
|  | 		return -E2BIG; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 *    A => Alive - No failures | 	 * Unused:  0 409600 mirror | ||||||
| 	 *    D => Dead - A write failure occurred leaving mirror out-of-sync | 	 * Used  :  2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A | ||||||
| 	 *    F => Flush failed. | 	*/ | ||||||
| 	 *    S => Sync - A sychronization failure occurred, mirror out-of-sync | 	num_devs = atoi(args[0]); | ||||||
| 	 *    R => Read - A read failure occurred, mirror data unaffected | 	dev_status_str = args[3 + num_devs]; | ||||||
| 	 *    U => Unclassified failure (bug) | 	log_argc = atoi(args[4 + num_devs]); | ||||||
| 	 */  | 	log_status_str = args[4 + num_devs + log_argc]; | ||||||
| 	switch (health) { | 	sync_str = args[1 + num_devs]; | ||||||
| 	case DM_STATUS_MIRROR_ALIVE: |  | ||||||
| 		return; |  | ||||||
| 	case DM_STATUS_MIRROR_FLUSH_FAILED: |  | ||||||
| 		log_error("%s device %u:%u flush failed.", |  | ||||||
| 			  dev_type, major, minor); |  | ||||||
| 		*r = ME_FAILURE; |  | ||||||
| 		break; |  | ||||||
| 	case DM_STATUS_MIRROR_SYNC_FAILED: |  | ||||||
| 		log_error("%s device %u:%u sync failed.", |  | ||||||
| 			  dev_type, major, minor); |  | ||||||
| 		break; |  | ||||||
| 	case DM_STATUS_MIRROR_READ_FAILED: |  | ||||||
| 		log_error("%s device %u:%u read failed.", |  | ||||||
| 			  dev_type, major, minor); |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		log_error("%s device %u:%u has failed (%c).", |  | ||||||
| 			  dev_type, major, minor, (char)health); |  | ||||||
| 		*r = ME_FAILURE; |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int _get_mirror_event(struct dso_state *state, char *params) |  | ||||||
| { |  | ||||||
| 	int r = ME_INSYNC; |  | ||||||
| 	unsigned i; |  | ||||||
| 	struct dm_status_mirror *ms; |  | ||||||
|  |  | ||||||
| 	if (!dm_get_status_mirror(state->mem, params, &ms)) { |  | ||||||
| 		log_error("Unable to parse mirror status string."); |  | ||||||
| 		return ME_IGNORE; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Check for bad mirror devices */ | 	/* Check for bad mirror devices */ | ||||||
| 	for (i = 0; i < ms->dev_count; ++i) | 	for (i = 0; i < num_devs; i++) { | ||||||
| 		_process_status_code(ms->devs[i].health, | 		if (dev_status_str[i] == 'D') { | ||||||
| 				     ms->devs[i].major, ms->devs[i].minor, | 			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]); | ||||||
| 				     i ? "Secondary mirror" : "Primary mirror", &r); | 			num_failures++; | ||||||
|  | 		} | ||||||
| 	/* Check for bad disk log device */ |  | ||||||
| 	for (i = 0; i < ms->log_count; ++i) |  | ||||||
| 		_process_status_code(ms->logs[i].health, |  | ||||||
| 				     ms->logs[i].major, ms->logs[i].minor, |  | ||||||
| 				     "Log", &r); |  | ||||||
|  |  | ||||||
| 	/* Ignore if not in-sync */ |  | ||||||
| 	if ((r == ME_INSYNC) && (ms->insync_regions != ms->total_regions)) |  | ||||||
| 		r = ME_IGNORE; |  | ||||||
|  |  | ||||||
| 	dm_pool_free(state->mem, ms); |  | ||||||
|  |  | ||||||
| 	return r; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconvert, |  | ||||||
| 				  const char *device) |  | ||||||
| { |  | ||||||
| 	if (!dmeventd_lvm2_run_with_lock(cmd_lvscan)) |  | ||||||
| 		log_warn("WARNING: Re-scan of mirrored device %s failed.", device); |  | ||||||
|  |  | ||||||
| 	/* if repair goes OK, report success even if lvscan has failed */ |  | ||||||
| 	if (!dmeventd_lvm2_run_with_lock(cmd_lvconvert)) { |  | ||||||
| 		log_error("Repair of mirrored device %s failed.", device); |  | ||||||
| 		return 0; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	log_info("Repair of mirrored device %s finished successfully.", device); | 	/* Check for bad log device */ | ||||||
|  | 	if (log_status_str[0] == 'D') { | ||||||
|  | 		syslog(LOG_ERR, "Log device, %s, has failed.\n", | ||||||
|  | 		       args[3 + num_devs + log_argc]); | ||||||
|  | 		num_failures++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return 1; | 	if (num_failures) { | ||||||
|  | 		rtn = ME_FAILURE; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	p = strstr(sync_str, "/"); | ||||||
|  | 	if (p) { | ||||||
|  | 		p[0] = '\0'; | ||||||
|  | 		if (strcmp(sync_str, p+1)) | ||||||
|  | 			rtn = ME_IGNORE; | ||||||
|  | 		p[0] = '/'; | ||||||
|  | 	} else { | ||||||
|  | 		/* | ||||||
|  | 		 * How the hell did we get this? | ||||||
|  | 		 * Might mean all our parameters are screwed. | ||||||
|  | 		 */ | ||||||
|  | 		syslog(LOG_ERR, "Unable to parse sync string."); | ||||||
|  | 		rtn = ME_IGNORE; | ||||||
|  | 	} | ||||||
|  |  out: | ||||||
|  | 	return rtn; | ||||||
| } | } | ||||||
|  |  | ||||||
| void process_event(struct dm_task *dmt, | static void _temporary_log_fn(int level, const char *file, | ||||||
| 		   enum dm_event_mask event __attribute__((unused)), | 			      int line, const char *format) | ||||||
| 		   void **user) |  | ||||||
| { | { | ||||||
| 	struct dso_state *state = *user; | 	if (!strncmp(format, "WARNING: ", 9) && (level < 5)) | ||||||
|  | 		syslog(LOG_CRIT, "%s", format); | ||||||
|  | 	else | ||||||
|  | 		syslog(LOG_DEBUG, "%s", format); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int _remove_failed_devices(const char *device) | ||||||
|  | { | ||||||
|  | 	int r; | ||||||
|  | 	void *handle; | ||||||
|  | 	int cmd_size = 256;	/* FIXME Use system restriction */ | ||||||
|  | 	char cmd_str[cmd_size]; | ||||||
|  | 	char *vg = NULL, *lv = NULL, *layer = NULL; | ||||||
|  |  | ||||||
|  | 	if (strlen(device) > 200) | ||||||
|  | 		return -ENAMETOOLONG; | ||||||
|  |  | ||||||
|  | 	if (!split_dm_name(mem_pool, device, &vg, &lv, &layer)) { | ||||||
|  | 		syslog(LOG_ERR, "Unable to determine VG name from %s", | ||||||
|  | 		       device); | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* FIXME Is any sanity-checking required on %s? */ | ||||||
|  | 	if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) { | ||||||
|  | 		/* this error should be caught above, but doesn't hurt to check again */ | ||||||
|  | 		syslog(LOG_ERR, "Unable to form LVM command: Device name too long"); | ||||||
|  | 		dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */ | ||||||
|  | 		return -ENAMETOOLONG; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	lvm2_log_fn(_temporary_log_fn); | ||||||
|  | 	handle = lvm2_init(); | ||||||
|  | 	lvm2_log_level(handle, 1); | ||||||
|  | 	r = lvm2_run(handle, cmd_str); | ||||||
|  |  | ||||||
|  | 	dm_pool_empty(mem_pool);  /* FIXME: not safe with multiple threads */ | ||||||
|  | 	return (r == 1)? 0: -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void process_event(const char *device, enum dm_event_type event) | ||||||
|  | { | ||||||
|  | 	struct dm_task *dmt; | ||||||
| 	void *next = NULL; | 	void *next = NULL; | ||||||
| 	uint64_t start, length; | 	uint64_t start, length; | ||||||
| 	char *target_type = NULL; | 	char *target_type = NULL; | ||||||
| 	char *params; | 	char *params; | ||||||
| 	const char *device = dm_task_get_name(dmt); |  | ||||||
|  | 	if (pthread_mutex_trylock(&_lock)) { | ||||||
|  | 		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting..."); | ||||||
|  | 		pthread_mutex_lock(&_lock); | ||||||
|  | 	} | ||||||
|  | 	/* FIXME Move inside libdevmapper */ | ||||||
|  | 	if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) { | ||||||
|  | 		syslog(LOG_ERR, "Unable to create dm_task.\n"); | ||||||
|  | 		goto fail; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!dm_task_set_name(dmt, device)) { | ||||||
|  | 		syslog(LOG_ERR, "Unable to set device name.\n"); | ||||||
|  | 		goto fail; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!dm_task_run(dmt)) { | ||||||
|  | 		syslog(LOG_ERR, "Unable to run task.\n"); | ||||||
|  | 		goto fail; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	do { | 	do { | ||||||
| 		next = dm_get_next_target(dmt, next, &start, &length, | 		next = dm_get_next_target(dmt, next, &start, &length, | ||||||
| 					  &target_type, ¶ms); | 					  &target_type, ¶ms); | ||||||
|  |  | ||||||
| 		if (!target_type) { | 		if (strcmp(target_type, "mirror")) { | ||||||
| 			log_info("%s mapping lost.", device); | 			syslog(LOG_INFO, "%s has unmirrored portion.\n", device); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (strcmp(target_type, TARGET_NAME_MIRROR)) { | 		switch(_get_mirror_event(params)) { | ||||||
| 			log_info("%s has unmirrored portion.", device); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		switch(_get_mirror_event(state, params)) { |  | ||||||
| 		case ME_INSYNC: | 		case ME_INSYNC: | ||||||
| 			/* FIXME: all we really know is that this | 			/* FIXME: all we really know is that this | ||||||
| 			   _part_ of the device is in sync | 			   _part_ of the device is in sync | ||||||
| 			   Also, this is not an error | 			   Also, this is not an error | ||||||
| 			*/ | 			*/ | ||||||
| 			log_notice("%s is now in-sync.", device); | 			syslog(LOG_NOTICE, "%s is now in-sync\n", device); | ||||||
| 			break; | 			break; | ||||||
| 		case ME_FAILURE: | 		case ME_FAILURE: | ||||||
| 			log_error("Device failure in %s.", device); | 			syslog(LOG_ERR, "Device failure in %s\n", device); | ||||||
| 			if (!_remove_failed_devices(state->cmd_lvscan, | 			if (_remove_failed_devices(device)) | ||||||
| 						    state->cmd_lvconvert, | 				syslog(LOG_ERR, "Failed to remove faulty devices in %s\n", | ||||||
| 						    device)) | 				       device); | ||||||
| 				/* FIXME Why are all the error return codes unused? Get rid of them? */ |  | ||||||
| 				log_error("Failed to remove faulty devices in %s.", |  | ||||||
| 					  device); |  | ||||||
| 			/* Should check before warning user that device is now linear | 			/* Should check before warning user that device is now linear | ||||||
| 			else | 			else | ||||||
| 				log_notice("%s is now a linear device.", | 				syslog(LOG_NOTICE, "%s is now a linear device.\n", | ||||||
| 					   device); | 					device); | ||||||
| 			*/ | 			*/ | ||||||
| 			break; | 			break; | ||||||
| 		case ME_IGNORE: | 		case ME_IGNORE: | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			/* FIXME Provide value then! */ | 			syslog(LOG_INFO, "Unknown event received.\n"); | ||||||
| 			log_warn("WARNING: %s received unknown event.", device); |  | ||||||
| 		} | 		} | ||||||
| 	} while (next); | 	} while (next); | ||||||
|  |  | ||||||
|  |  fail: | ||||||
|  | 	if (dmt) | ||||||
|  | 		dm_task_destroy(dmt); | ||||||
|  | 	pthread_mutex_unlock(&_lock); | ||||||
| } | } | ||||||
|  |  | ||||||
| int register_device(const char *device, | int register_device(const char *device) | ||||||
| 		    const char *uuid __attribute__((unused)), |  | ||||||
| 		    int major __attribute__((unused)), |  | ||||||
| 		    int minor __attribute__((unused)), |  | ||||||
| 		    void **user) |  | ||||||
| { | { | ||||||
| 	struct dso_state *state; | 	syslog(LOG_INFO, "Monitoring mirror device, %s for events\n", device); | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_init_with_pool("mirror_state", state)) | 	/* | ||||||
| 		goto_bad; | 	 * Need some space for allocations.  1024 should be more | ||||||
|  | 	 * than enough for what we need (device mapper name splitting) | ||||||
|  | 	 */ | ||||||
|  | 	if (!mem_pool) | ||||||
|  | 		mem_pool = dm_pool_create("mirror_dso", 1024); | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan), | 	if (!mem_pool) | ||||||
| 				   "lvscan --cache", device)) { | 		return 0; | ||||||
| 		dmeventd_lvm2_exit_with_pool(state); |  | ||||||
| 		goto_bad; | 	register_count++; | ||||||
|  |  | ||||||
|  |         return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int unregister_device(const char *device) | ||||||
|  | { | ||||||
|  | 	if (!(--register_count)) { | ||||||
|  | 		dm_pool_destroy(mem_pool); | ||||||
|  | 		mem_pool = NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert), |         return 1; | ||||||
| 				   "lvconvert --repair --use-policies", device)) { |  | ||||||
| 		dmeventd_lvm2_exit_with_pool(state); |  | ||||||
| 		goto_bad; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	*user = state; |  | ||||||
|  |  | ||||||
| 	log_info("Monitoring mirror device %s for events.", device); |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| bad: |  | ||||||
| 	log_error("Failed to monitor mirror %s.", device); |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| int unregister_device(const char *device, | /* | ||||||
| 		      const char *uuid __attribute__((unused)), |  * Overrides for Emacs so that we follow Linus's tabbing style. | ||||||
| 		      int major __attribute__((unused)), |  * Emacs will notice this stuff at the end of the file and automatically | ||||||
| 		      int minor __attribute__((unused)), |  * adjust the settings for this buffer only.  This must remain at the end | ||||||
| 		      void **user) |  * of the file. | ||||||
| { |  * --------------------------------------------------------------------------- | ||||||
| 	struct dso_state *state = *user; |  * Local variables: | ||||||
|  |  * c-file-style: "linux" | ||||||
| 	dmeventd_lvm2_exit_with_pool(state); |  * End: | ||||||
| 	log_info("No longer monitoring mirror device %s for events.", |  */ | ||||||
| 		 device); |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -1,36 +0,0 @@ | |||||||
| # |  | ||||||
| # Copyright (C) 2011-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  |  | ||||||
| srcdir = @srcdir@ |  | ||||||
| top_srcdir = @top_srcdir@ |  | ||||||
| top_builddir = @top_builddir@ |  | ||||||
|  |  | ||||||
| INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2 |  | ||||||
| CLDFLAGS += -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 |  | ||||||
| @@ -1,172 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2005-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "lib.h" |  | ||||||
| #include "defaults.h" |  | ||||||
| #include "dmeventd_lvm.h" |  | ||||||
| #include "libdevmapper-event.h" |  | ||||||
|  |  | ||||||
| /* Hold enough elements for the mximum number of RAID images */ |  | ||||||
| #define	RAID_DEVS_ELEMS	((DEFAULT_RAID_MAX_IMAGES + 63) / 64) |  | ||||||
|  |  | ||||||
| struct dso_state { |  | ||||||
| 	struct dm_pool *mem; |  | ||||||
| 	char cmd_lvscan[512]; |  | ||||||
| 	char cmd_lvconvert[512]; |  | ||||||
| 	uint64_t raid_devs[RAID_DEVS_ELEMS]; |  | ||||||
| 	int failed; |  | ||||||
| 	int warned; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| DM_EVENT_LOG_FN("raid") |  | ||||||
|  |  | ||||||
| /* FIXME Reformat to 80 char lines. */ |  | ||||||
|  |  | ||||||
| static int _process_raid_event(struct dso_state *state, char *params, const char *device) |  | ||||||
| { |  | ||||||
| 	struct dm_status_raid *status; |  | ||||||
| 	const char *d; |  | ||||||
| 	int dead = 0, r = 1; |  | ||||||
| 	uint32_t dev; |  | ||||||
|  |  | ||||||
| 	if (!dm_get_status_raid(state->mem, params, &status)) { |  | ||||||
| 		log_error("Failed to process status line for %s.", device); |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	d = status->dev_health; |  | ||||||
| 	while ((d = strchr(d, 'D'))) { |  | ||||||
| 		dev = (uint32_t)(d - status->dev_health); |  | ||||||
|  |  | ||||||
| 		if (!(state->raid_devs[dev / 64] & (UINT64_C(1) << (dev % 64)))) { |  | ||||||
| 			state->raid_devs[dev / 64] |= (UINT64_C(1) << (dev % 64)); |  | ||||||
| 			log_warn("WARNING: Device #%u of %s array, %s, has failed.", |  | ||||||
| 				 dev, status->raid_type, device); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		d++; |  | ||||||
| 		dead = 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (dead) { |  | ||||||
| 		if (status->insync_regions < status->total_regions) { |  | ||||||
| 			if (!state->warned) { |  | ||||||
| 				state->warned = 1; |  | ||||||
| 				log_warn("WARNING: waiting for resynchronization to finish " |  | ||||||
| 					 "before initiating repair on RAID device %s.", device); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			goto out; /* Not yet done syncing with accessible devices */ |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (state->failed) |  | ||||||
| 			goto out; /* already reported */ |  | ||||||
|  |  | ||||||
| 		state->failed = 1; |  | ||||||
| 		if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan)) |  | ||||||
| 			log_warn("WARNING: Re-scan of RAID device %s failed.", device); |  | ||||||
|  |  | ||||||
| 		/* if repair goes OK, report success even if lvscan has failed */ |  | ||||||
| 		if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) { |  | ||||||
| 			log_error("Repair of RAID device %s failed.", device); |  | ||||||
| 			r = 0; |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		state->failed = 0; |  | ||||||
| 		log_info("%s array, %s, is %s in-sync.", |  | ||||||
| 			 status->raid_type, device, |  | ||||||
| 			 (status->insync_regions == status->total_regions) ? "now" : "not"); |  | ||||||
| 	} |  | ||||||
| out: |  | ||||||
| 	dm_pool_free(state->mem, status); |  | ||||||
|  |  | ||||||
| 	return r; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void process_event(struct dm_task *dmt, |  | ||||||
| 		   enum dm_event_mask event __attribute__((unused)), |  | ||||||
| 		   void **user) |  | ||||||
| { |  | ||||||
| 	struct dso_state *state = *user; |  | ||||||
| 	void *next = NULL; |  | ||||||
| 	uint64_t start, length; |  | ||||||
| 	char *target_type = NULL; |  | ||||||
| 	char *params; |  | ||||||
| 	const char *device = dm_task_get_name(dmt); |  | ||||||
|  |  | ||||||
| 	do { |  | ||||||
| 		next = dm_get_next_target(dmt, next, &start, &length, |  | ||||||
| 					  &target_type, ¶ms); |  | ||||||
|  |  | ||||||
| 		if (!target_type) { |  | ||||||
| 			log_info("%s mapping lost.", device); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (strcmp(target_type, "raid")) { |  | ||||||
| 			log_info("%s has non-raid portion.", device); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (!_process_raid_event(state, params, device)) |  | ||||||
| 			log_error("Failed to process event for %s.", |  | ||||||
| 				  device); |  | ||||||
| 	} while (next); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int register_device(const char *device, |  | ||||||
| 		    const char *uuid __attribute__((unused)), |  | ||||||
| 		    int major __attribute__((unused)), |  | ||||||
| 		    int minor __attribute__((unused)), |  | ||||||
| 		    void **user) |  | ||||||
| { |  | ||||||
| 	struct dso_state *state; |  | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_init_with_pool("raid_state", state)) |  | ||||||
| 		goto_bad; |  | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan), |  | ||||||
| 				   "lvscan --cache", device) || |  | ||||||
| 	    !dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert), |  | ||||||
| 				   "lvconvert --config devices{ignore_suspended_devices=1} " |  | ||||||
| 				   "--repair --use-policies", device)) { |  | ||||||
| 		dmeventd_lvm2_exit_with_pool(state); |  | ||||||
| 		goto_bad; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	*user = state; |  | ||||||
|  |  | ||||||
| 	log_info("Monitoring RAID device %s for events.", device); |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| bad: |  | ||||||
| 	log_error("Failed to monitor RAID %s.", device); |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int unregister_device(const char *device, |  | ||||||
| 		      const char *uuid __attribute__((unused)), |  | ||||||
| 		      int major __attribute__((unused)), |  | ||||||
| 		      int minor __attribute__((unused)), |  | ||||||
| 		      void **user) |  | ||||||
| { |  | ||||||
| 	struct dso_state *state = *user; |  | ||||||
|  |  | ||||||
| 	dmeventd_lvm2_exit_with_pool(state); |  | ||||||
| 	log_info("No longer monitoring RAID device %s for events.", |  | ||||||
| 		 device); |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
| @@ -1,3 +0,0 @@ | |||||||
| process_event |  | ||||||
| register_device |  | ||||||
| unregister_device |  | ||||||
| @@ -1,33 +0,0 @@ | |||||||
| # |  | ||||||
| # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |  | ||||||
| # Copyright (C) 2004-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  |  | ||||||
| srcdir = @srcdir@ |  | ||||||
| top_srcdir = @top_srcdir@ |  | ||||||
| top_builddir = @top_builddir@ |  | ||||||
|  |  | ||||||
| INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2 |  | ||||||
| CLDFLAGS += -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 |  | ||||||
|  |  | ||||||
| install_lvm2: install_dm_plugin |  | ||||||
|  |  | ||||||
| install: install_lvm2 |  | ||||||
| @@ -1,286 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2007-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "lib.h" |  | ||||||
| #include "dmeventd_lvm.h" |  | ||||||
| #include "libdevmapper-event.h" |  | ||||||
|  |  | ||||||
| #include <sys/sysmacros.h> |  | ||||||
| #include <sys/wait.h> |  | ||||||
| #include <stdarg.h> |  | ||||||
| #include <pthread.h> |  | ||||||
|  |  | ||||||
| /* First warning when snapshot is 80% full. */ |  | ||||||
| #define WARNING_THRESH	(DM_PERCENT_1 * 80) |  | ||||||
| /* Run a check every 5%. */ |  | ||||||
| #define CHECK_STEP	(DM_PERCENT_1 *  5) |  | ||||||
| /* Do not bother checking snapshots less than 50% full. */ |  | ||||||
| #define CHECK_MINIMUM	(DM_PERCENT_1 * 50) |  | ||||||
|  |  | ||||||
| #define UMOUNT_COMMAND "/bin/umount" |  | ||||||
|  |  | ||||||
| struct dso_state { |  | ||||||
| 	struct dm_pool *mem; |  | ||||||
| 	dm_percent_t percent_check; |  | ||||||
| 	uint64_t known_size; |  | ||||||
| 	char cmd_lvextend[512]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| DM_EVENT_LOG_FN("snap") |  | ||||||
|  |  | ||||||
| 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); |  | ||||||
|                 log_sys_error("exec", cmd); |  | ||||||
|                 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) |  | ||||||
| { |  | ||||||
| 	log_debug("Extending snapshot via %s.", cmd); |  | ||||||
| 	return dmeventd_lvm2_run_with_lock(cmd); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #ifdef SNAPSHOT_REMOVE |  | ||||||
| /* Remove invalid snapshot from dm-table */ |  | ||||||
| /* Experimental for now and not used by default */ |  | ||||||
| static int _remove(const char *uuid) |  | ||||||
| { |  | ||||||
| 	int r = 1; |  | ||||||
| 	uint32_t cookie = 0; |  | ||||||
| 	struct dm_task *dmt; |  | ||||||
|  |  | ||||||
| 	if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) |  | ||||||
| 		return 0; |  | ||||||
|  |  | ||||||
| 	if (!dm_task_set_uuid(dmt, uuid)) { |  | ||||||
| 		r = 0; |  | ||||||
| 		goto_out; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	dm_task_retry_remove(dmt); |  | ||||||
|  |  | ||||||
| 	if (!dm_task_set_cookie(dmt, &cookie, 0)) { |  | ||||||
| 		r = 0; |  | ||||||
| 		goto_out; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (!dm_task_run(dmt)) { |  | ||||||
| 		r = 0; |  | ||||||
| 		goto_out; |  | ||||||
| 	} |  | ||||||
| out: |  | ||||||
| 	dm_task_destroy(dmt); |  | ||||||
|  |  | ||||||
| 	return r; |  | ||||||
| } |  | ||||||
| #endif /* SNAPSHOT_REMOVE */ |  | ||||||
|  |  | ||||||
| static void _umount(const char *device, int major, int minor) |  | ||||||
| { |  | ||||||
| 	FILE *mounts; |  | ||||||
| 	char buffer[4096]; |  | ||||||
| 	char *words[3]; |  | ||||||
| 	struct stat st; |  | ||||||
| 	const char procmounts[] = "/proc/mounts"; |  | ||||||
|  |  | ||||||
| 	if (!(mounts = fopen(procmounts, "r"))) { |  | ||||||
| 		log_sys_error("fopen", procmounts); |  | ||||||
| 		log_error("Not umounting %s.", 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) && |  | ||||||
| 		    (int) major(st.st_rdev) == major && |  | ||||||
| 		    (int) minor(st.st_rdev) == minor) { |  | ||||||
| 			log_error("Unmounting invalid snapshot %s from %s.", device, words[1]); |  | ||||||
| 			if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL)) |  | ||||||
| 				log_error("Failed to umount snapshot %s from %s: %s.", |  | ||||||
| 					  device, words[1], strerror(errno)); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (fclose(mounts)) |  | ||||||
| 		log_sys_error("close", procmounts); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void process_event(struct dm_task *dmt, |  | ||||||
| 		   enum dm_event_mask event __attribute__((unused)), |  | ||||||
| 		   void **user) |  | ||||||
| { |  | ||||||
| 	struct dso_state *state = *user; |  | ||||||
| 	void *next = NULL; |  | ||||||
| 	uint64_t start, length; |  | ||||||
| 	char *target_type = NULL; |  | ||||||
| 	char *params; |  | ||||||
| 	struct dm_status_snapshot *status = NULL; |  | ||||||
| 	const char *device = dm_task_get_name(dmt); |  | ||||||
| 	int percent; |  | ||||||
| 	struct dm_info info; |  | ||||||
|  |  | ||||||
| 	/* No longer monitoring, waiting for remove */ |  | ||||||
| 	if (!state->percent_check) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); |  | ||||||
| 	if (!target_type || strcmp(target_type, "snapshot")) { |  | ||||||
| 		log_error("Target %s is not snapshot.", target_type); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (!dm_get_status_snapshot(state->mem, params, &status)) { |  | ||||||
| 		log_error("Cannot parse snapshot %s state: %s.", device, params); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * 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->overflow || !status->total_sectors) { |  | ||||||
| 		log_warn("WARNING: Snapshot %s changed state to: %s and should be removed.", |  | ||||||
| 			 device, params); |  | ||||||
| 		state->percent_check = 0; |  | ||||||
| 		if (dm_task_get_info(dmt, &info)) |  | ||||||
| 			_umount(device, info.major, info.minor); |  | ||||||
| #ifdef SNAPSHOT_REMOVE |  | ||||||
| 		/* Maybe configurable ? */ |  | ||||||
| 		_remove(dm_task_get_uuid(dmt)); |  | ||||||
| #endif |  | ||||||
| 		pthread_kill(pthread_self(), SIGALRM); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (length <= (status->used_sectors - status->metadata_sectors)) { |  | ||||||
| 		/* TODO eventually recognize earlier when room is enough */ |  | ||||||
| 		log_info("Dropping monitoring of fully provisioned snapshot %s.", |  | ||||||
| 			 device); |  | ||||||
| 		pthread_kill(pthread_self(), SIGALRM); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Snapshot size had changed. Clear the threshold. */ |  | ||||||
| 	if (state->known_size != status->total_sectors) { |  | ||||||
| 		state->percent_check = CHECK_MINIMUM; |  | ||||||
| 		state->known_size = status->total_sectors; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	percent = dm_make_percent(status->used_sectors, status->total_sectors); |  | ||||||
| 	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. */ |  | ||||||
| 			log_warn("WARNING: Snapshot %s is now %.2f%% full.", |  | ||||||
| 				 device, dm_percent_to_float(percent)); |  | ||||||
|  |  | ||||||
| 		/* Try to extend the snapshot, in accord with user-set policies */ |  | ||||||
| 		if (!_extend(state->cmd_lvextend)) |  | ||||||
| 			log_error("Failed to extend snapshot %s.", device); |  | ||||||
| 	} |  | ||||||
| out: |  | ||||||
| 	dm_pool_free(state->mem, status); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int register_device(const char *device, |  | ||||||
| 		    const char *uuid __attribute__((unused)), |  | ||||||
| 		    int major __attribute__((unused)), |  | ||||||
| 		    int minor __attribute__((unused)), |  | ||||||
| 		    void **user) |  | ||||||
| { |  | ||||||
| 	struct dso_state *state; |  | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_init_with_pool("snapshot_state", state)) |  | ||||||
| 		goto_bad; |  | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_command(state->mem, state->cmd_lvextend, |  | ||||||
| 				   sizeof(state->cmd_lvextend), |  | ||||||
| 				   "lvextend --use-policies", device)) { |  | ||||||
| 		dmeventd_lvm2_exit_with_pool(state); |  | ||||||
| 		goto_bad; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	state->percent_check = CHECK_MINIMUM; |  | ||||||
| 	*user = state; |  | ||||||
|  |  | ||||||
| 	log_info("Monitoring snapshot %s.", device); |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| bad: |  | ||||||
| 	log_error("Failed to monitor snapshot %s.", device); |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int unregister_device(const char *device, |  | ||||||
| 		      const char *uuid __attribute__((unused)), |  | ||||||
| 		      int major __attribute__((unused)), |  | ||||||
| 		      int minor __attribute__((unused)), |  | ||||||
| 		      void **user) |  | ||||||
| { |  | ||||||
| 	struct dso_state *state = *user; |  | ||||||
|  |  | ||||||
| 	dmeventd_lvm2_exit_with_pool(state); |  | ||||||
| 	log_info("No longer monitoring snapshot %s.", device); |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
| @@ -1,3 +0,0 @@ | |||||||
| process_event |  | ||||||
| register_device |  | ||||||
| unregister_device |  | ||||||
| @@ -1,36 +0,0 @@ | |||||||
| # |  | ||||||
| # Copyright (C) 2011-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  |  | ||||||
| srcdir = @srcdir@ |  | ||||||
| top_srcdir = @top_srcdir@ |  | ||||||
| top_builddir = @top_builddir@ |  | ||||||
|  |  | ||||||
| INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2 |  | ||||||
| CLDFLAGS += -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 |  | ||||||
| @@ -1,431 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2011-2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "lib.h"	/* using here lvm log */ |  | ||||||
| #include "dmeventd_lvm.h" |  | ||||||
| #include "libdevmapper-event.h" |  | ||||||
|  |  | ||||||
| #include <sys/wait.h> |  | ||||||
| #include <stdarg.h> |  | ||||||
| #include <pthread.h> |  | ||||||
|  |  | ||||||
| /* TODO - move this mountinfo code into library to be reusable */ |  | ||||||
| #ifdef __linux__ |  | ||||||
| #  include "kdev_t.h" |  | ||||||
| #else |  | ||||||
| #  define MAJOR(x) major((x)) |  | ||||||
| #  define MINOR(x) minor((x)) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| /* First warning when thin data or metadata is 80% full. */ |  | ||||||
| #define WARNING_THRESH	(DM_PERCENT_1 * 80) |  | ||||||
| /* Umount thin LVs when thin data or metadata LV is >= |  | ||||||
|  * and lvextend --use-policies has failed. */ |  | ||||||
| #define UMOUNT_THRESH	(DM_PERCENT_1 * 95) |  | ||||||
| /* Run a check every 5%. */ |  | ||||||
| #define CHECK_STEP	(DM_PERCENT_1 *  5) |  | ||||||
| /* Do not bother checking thin data or metadata is less than 50% full. */ |  | ||||||
| #define CHECK_MINIMUM	(DM_PERCENT_1 * 50) |  | ||||||
|  |  | ||||||
| #define UMOUNT_COMMAND "/bin/umount" |  | ||||||
|  |  | ||||||
| #define MAX_FAILS	(256)  /* ~42 mins between cmd call retry with 10s delay */ |  | ||||||
|  |  | ||||||
| #define THIN_DEBUG 0 |  | ||||||
|  |  | ||||||
| struct dso_state { |  | ||||||
| 	struct dm_pool *mem; |  | ||||||
| 	int metadata_percent_check; |  | ||||||
| 	int metadata_percent; |  | ||||||
| 	int metadata_warn_once; |  | ||||||
| 	int data_percent_check; |  | ||||||
| 	int data_percent; |  | ||||||
| 	int data_warn_once; |  | ||||||
| 	uint64_t known_metadata_size; |  | ||||||
| 	uint64_t known_data_size; |  | ||||||
| 	unsigned fails; |  | ||||||
| 	unsigned max_fails; |  | ||||||
| 	int restore_sigset; |  | ||||||
| 	sigset_t old_sigset; |  | ||||||
| 	pid_t pid; |  | ||||||
| 	char **argv; |  | ||||||
| 	char cmd_str[1024]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| DM_EVENT_LOG_FN("thin") |  | ||||||
|  |  | ||||||
| #define UUID_PREFIX "LVM-" |  | ||||||
|  |  | ||||||
| static int _run_command(struct dso_state *state) |  | ||||||
| { |  | ||||||
| 	char val[3][36]; |  | ||||||
| 	char *env[] = { val[0], val[1], val[2], NULL }; |  | ||||||
| 	int i; |  | ||||||
|  |  | ||||||
| 	/* Mark for possible lvm2 command we are running from dmeventd |  | ||||||
| 	 * lvm2 will not try to talk back to dmeventd while processing it */ |  | ||||||
| 	(void) dm_snprintf(val[0], sizeof(val[0]), "LVM_RUN_BY_DMEVENTD=1"); |  | ||||||
|  |  | ||||||
| 	if (state->data_percent) { |  | ||||||
| 		/* Prepare some known data to env vars for easy use */ |  | ||||||
| 		(void) dm_snprintf(val[1], sizeof(val[1]), "DMEVENTD_THIN_POOL_DATA=%d", |  | ||||||
| 				   state->data_percent / DM_PERCENT_1); |  | ||||||
| 		(void) dm_snprintf(val[2], sizeof(val[2]), "DMEVENTD_THIN_POOL_METADATA=%d", |  | ||||||
| 				   state->metadata_percent / DM_PERCENT_1); |  | ||||||
| 	} else { |  | ||||||
| 		/* For an error event it's for a user to check status and decide */ |  | ||||||
| 		env[1] = NULL; |  | ||||||
| 		log_debug("Error event processing"); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	log_verbose("Executing command: %s", state->cmd_str); |  | ||||||
|  |  | ||||||
| 	/* TODO: |  | ||||||
| 	 *   Support parallel run of 'task' and it's waitpid maintainence |  | ||||||
| 	 *   ATM we can't handle signaling of  SIGALRM |  | ||||||
| 	 *   as signalling is not allowed while 'process_event()' is running |  | ||||||
| 	 */ |  | ||||||
| 	if (!(state->pid = fork())) { |  | ||||||
| 		/* child */ |  | ||||||
| 		(void) close(0); |  | ||||||
| 		for (i = 3; i < 255; ++i) (void) close(i); |  | ||||||
| 		execve(state->argv[0], state->argv, env); |  | ||||||
| 		_exit(errno); |  | ||||||
| 	} else if (state->pid == -1) { |  | ||||||
| 		log_error("Can't fork command %s.", state->cmd_str); |  | ||||||
| 		state->fails = 1; |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int _use_policy(struct dm_task *dmt, struct dso_state *state) |  | ||||||
| { |  | ||||||
| #if THIN_DEBUG |  | ||||||
| 	log_debug("dmeventd executes: %s.", state->cmd_str); |  | ||||||
| #endif |  | ||||||
| 	if (state->argv) |  | ||||||
| 		return _run_command(state); |  | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) { |  | ||||||
| 		log_error("Failed command for %s.", dm_task_get_name(dmt)); |  | ||||||
| 		state->fails = 1; |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	state->fails = 0; |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Check if executed command has finished |  | ||||||
|  * Only 1 command may run */ |  | ||||||
| static int _wait_for_pid(struct dso_state *state) |  | ||||||
| { |  | ||||||
| 	int status = 0; |  | ||||||
|  |  | ||||||
| 	if (state->pid == -1) |  | ||||||
| 		return 1; |  | ||||||
|  |  | ||||||
| 	if (!waitpid(state->pid, &status, WNOHANG)) |  | ||||||
| 		return 0; |  | ||||||
|  |  | ||||||
| 	/* Wait for finish */ |  | ||||||
| 	if (WIFEXITED(status)) { |  | ||||||
| 		log_verbose("Child %d exited with status %d.", |  | ||||||
| 			    state->pid, WEXITSTATUS(status)); |  | ||||||
| 		state->fails = WEXITSTATUS(status) ? 1 : 0; |  | ||||||
| 	} else { |  | ||||||
| 		if (WIFSIGNALED(status)) |  | ||||||
| 			log_verbose("Child %d was terminated with status %d.", |  | ||||||
| 				    state->pid, WTERMSIG(status)); |  | ||||||
| 		state->fails = 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	state->pid = -1; |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void process_event(struct dm_task *dmt, |  | ||||||
| 		   enum dm_event_mask event __attribute__((unused)), |  | ||||||
| 		   void **user) |  | ||||||
| { |  | ||||||
| 	const char *device = dm_task_get_name(dmt); |  | ||||||
| 	struct dso_state *state = *user; |  | ||||||
| 	struct dm_status_thin_pool *tps = NULL; |  | ||||||
| 	void *next = NULL; |  | ||||||
| 	uint64_t start, length; |  | ||||||
| 	char *target_type = NULL; |  | ||||||
| 	char *params; |  | ||||||
| 	int needs_policy = 0; |  | ||||||
| 	struct dm_task *new_dmt = NULL; |  | ||||||
|  |  | ||||||
| #if THIN_DEBUG |  | ||||||
| 	log_debug("Watch for tp-data:%.2f%%  tp-metadata:%.2f%%.", |  | ||||||
| 		  dm_percent_to_float(state->data_percent_check), |  | ||||||
| 		  dm_percent_to_float(state->metadata_percent_check)); |  | ||||||
| #endif |  | ||||||
| 	if (!_wait_for_pid(state)) { |  | ||||||
| 		log_warn("WARNING: Skipping event, child %d is still running (%s).", |  | ||||||
| 			 state->pid, state->cmd_str); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (event & DM_EVENT_DEVICE_ERROR) { |  | ||||||
| 		/* Error -> no need to check and do instant resize */ |  | ||||||
| 		state->data_percent = state->metadata_percent = 0; |  | ||||||
| 		if (_use_policy(dmt, state)) |  | ||||||
| 			goto out; |  | ||||||
|  |  | ||||||
| 		stack; |  | ||||||
|  |  | ||||||
| 		/* |  | ||||||
| 		 * Rather update oldish status |  | ||||||
| 		 * since after 'command' processing |  | ||||||
| 		 * percentage info could have changed a lot. |  | ||||||
| 		 * If we would get above UMOUNT_THRESH |  | ||||||
| 		 * we would wait for next sigalarm. |  | ||||||
| 		 */ |  | ||||||
| 		if (!(new_dmt = dm_task_create(DM_DEVICE_STATUS))) |  | ||||||
| 			goto_out; |  | ||||||
|  |  | ||||||
| 		if (!dm_task_set_uuid(new_dmt, dm_task_get_uuid(dmt))) |  | ||||||
| 			goto_out; |  | ||||||
|  |  | ||||||
| 		/* Non-blocking status read */ |  | ||||||
| 		if (!dm_task_no_flush(new_dmt)) |  | ||||||
| 			log_warn("WARNING: Can't set no_flush for dm status."); |  | ||||||
|  |  | ||||||
| 		if (!dm_task_run(new_dmt)) |  | ||||||
| 			goto_out; |  | ||||||
|  |  | ||||||
| 		dmt = new_dmt; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); |  | ||||||
|  |  | ||||||
| 	if (!target_type || (strcmp(target_type, "thin-pool") != 0)) { |  | ||||||
| 		log_error("Invalid target type."); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (!dm_get_status_thin_pool(state->mem, params, &tps)) { |  | ||||||
| 		log_error("Failed to parse status."); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| #if THIN_DEBUG |  | ||||||
| 	log_debug("Thin pool status " FMTu64 "/" FMTu64 "  " |  | ||||||
| 		  FMTu64 "/" FMTu64 ".", |  | ||||||
| 		  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; |  | ||||||
| 		state->fails = 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (state->known_data_size != tps->total_data_blocks) { |  | ||||||
| 		state->data_percent_check = CHECK_MINIMUM; |  | ||||||
| 		state->known_data_size = tps->total_data_blocks; |  | ||||||
| 		state->fails = 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Trigger action when threshold boundary is exceeded. |  | ||||||
| 	 * Report 80% threshold warning when it's used above 80%. |  | ||||||
| 	 * Only 100% is exception as it cannot be surpased so policy |  | ||||||
| 	 * action is called for:  >50%, >55% ... >95%, 100% |  | ||||||
| 	 */ |  | ||||||
| 	state->metadata_percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks); |  | ||||||
| 	if (state->metadata_percent <= WARNING_THRESH) |  | ||||||
| 		state->metadata_warn_once = 0; /* Dropped bellow threshold, reset warn once */ |  | ||||||
| 	else if (!state->metadata_warn_once++) /* Warn once when raised above threshold */ |  | ||||||
| 		log_warn("WARNING: Thin pool %s metadata is now %.2f%% full.", |  | ||||||
| 			 device, dm_percent_to_float(state->metadata_percent)); |  | ||||||
| 	if (state->metadata_percent > CHECK_MINIMUM) { |  | ||||||
| 		/* Run action when usage raised more than CHECK_STEP since the last time */ |  | ||||||
| 		if (state->metadata_percent > state->metadata_percent_check) |  | ||||||
| 			needs_policy = 1; |  | ||||||
| 		state->metadata_percent_check = (state->metadata_percent / CHECK_STEP + 1) * CHECK_STEP; |  | ||||||
| 		if (state->metadata_percent_check == DM_PERCENT_100) |  | ||||||
| 			state->metadata_percent_check--; /* Can't get bigger then 100% */ |  | ||||||
| 	} else |  | ||||||
| 		state->metadata_percent_check = CHECK_MINIMUM; |  | ||||||
|  |  | ||||||
| 	state->data_percent = dm_make_percent(tps->used_data_blocks, tps->total_data_blocks); |  | ||||||
| 	if (state->data_percent <= WARNING_THRESH) |  | ||||||
| 		state->data_warn_once = 0; |  | ||||||
| 	else if (!state->data_warn_once++) |  | ||||||
| 		log_warn("WARNING: Thin pool %s data is now %.2f%% full.", |  | ||||||
| 			 device, dm_percent_to_float(state->data_percent)); |  | ||||||
| 	if (state->data_percent > CHECK_MINIMUM) { |  | ||||||
| 		/* Run action when usage raised more than CHECK_STEP since the last time */ |  | ||||||
| 		if (state->data_percent > state->data_percent_check) |  | ||||||
| 			needs_policy = 1; |  | ||||||
| 		state->data_percent_check = (state->data_percent / CHECK_STEP + 1) * CHECK_STEP; |  | ||||||
| 		if (state->data_percent_check == DM_PERCENT_100) |  | ||||||
| 			state->data_percent_check--; /* Can't get bigger then 100% */ |  | ||||||
| 	} else |  | ||||||
| 		state->data_percent_check = CHECK_MINIMUM; |  | ||||||
|  |  | ||||||
| 	/* Reduce number of _use_policy() calls by power-of-2 factor till frequency of MAX_FAILS is reached. |  | ||||||
| 	 * Avoids too high number of error retries, yet shows some status messages in log regularly. |  | ||||||
| 	 * i.e. PV could have been pvmoved and VG/LV was locked for a while... |  | ||||||
| 	 */ |  | ||||||
| 	if (state->fails) { |  | ||||||
| 		if (state->fails++ <= state->max_fails) { |  | ||||||
| 			log_debug("Postponing frequently failing policy (%u <= %u).", |  | ||||||
| 				  state->fails - 1, state->max_fails); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		if (state->max_fails < MAX_FAILS) |  | ||||||
| 			state->max_fails <<= 1; |  | ||||||
| 		state->fails = needs_policy = 1; /* Retry failing command */ |  | ||||||
| 	} else |  | ||||||
| 		state->max_fails = 1; /* Reset on success */ |  | ||||||
|  |  | ||||||
| 	if (needs_policy) |  | ||||||
| 		_use_policy(dmt, state); |  | ||||||
| out: |  | ||||||
| 	if (tps) |  | ||||||
| 		dm_pool_free(state->mem, tps); |  | ||||||
|  |  | ||||||
| 	if (new_dmt) |  | ||||||
| 		dm_task_destroy(new_dmt); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Handle SIGCHLD for a thread */ |  | ||||||
| static void _sig_child(int signum __attribute__((unused))) |  | ||||||
| { |  | ||||||
| 	/* empty SIG_IGN */; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Setup handler for SIGCHLD when executing external command |  | ||||||
|  * to get quick 'waitpid()' reaction |  | ||||||
|  * It will interrupt syscall just like SIGALRM and |  | ||||||
|  * invoke process_event(). |  | ||||||
|  */ |  | ||||||
| static void _init_thread_signals(struct dso_state *state) |  | ||||||
| { |  | ||||||
| 	struct sigaction act = { .sa_handler = _sig_child }; |  | ||||||
| 	sigset_t my_sigset; |  | ||||||
|  |  | ||||||
| 	sigemptyset(&my_sigset); |  | ||||||
|  |  | ||||||
| 	if (sigaction(SIGCHLD, &act, NULL)) |  | ||||||
| 		log_warn("WARNING: Failed to set SIGCHLD action."); |  | ||||||
| 	else if (sigaddset(&my_sigset, SIGCHLD)) |  | ||||||
| 		log_warn("WARNING: Failed to add SIGCHLD to set."); |  | ||||||
| 	else if (pthread_sigmask(SIG_UNBLOCK, &my_sigset, &state->old_sigset)) |  | ||||||
| 		log_warn("WARNING: Failed to unblock SIGCHLD."); |  | ||||||
| 	else |  | ||||||
| 		state->restore_sigset = 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void _restore_thread_signals(struct dso_state *state) |  | ||||||
| { |  | ||||||
| 	if (state->restore_sigset && |  | ||||||
| 	    pthread_sigmask(SIG_SETMASK, &state->old_sigset, NULL)) |  | ||||||
| 		log_warn("WARNING: Failed to block SIGCHLD."); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int register_device(const char *device, |  | ||||||
| 		    const char *uuid __attribute__((unused)), |  | ||||||
| 		    int major __attribute__((unused)), |  | ||||||
| 		    int minor __attribute__((unused)), |  | ||||||
| 		    void **user) |  | ||||||
| { |  | ||||||
| 	struct dso_state *state; |  | ||||||
| 	int maxcmd; |  | ||||||
| 	char *str; |  | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_init_with_pool("thin_pool_state", state)) |  | ||||||
| 		goto_bad; |  | ||||||
|  |  | ||||||
| 	if (!dmeventd_lvm2_command(state->mem, state->cmd_str, |  | ||||||
| 				   sizeof(state->cmd_str), |  | ||||||
| 				   "_dmeventd_thin_command", device)) { |  | ||||||
| 		dmeventd_lvm2_exit_with_pool(state); |  | ||||||
| 		goto_bad; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (strncmp(state->cmd_str, "lvm ", 4)) { |  | ||||||
| 		maxcmd = 2; /* space for last NULL element */ |  | ||||||
| 		for (str = state->cmd_str; *str; str++) |  | ||||||
| 			if (*str == ' ') |  | ||||||
| 				maxcmd++; |  | ||||||
| 		if (!(str = dm_pool_strdup(state->mem, state->cmd_str)) || |  | ||||||
| 		    !(state->argv = dm_pool_zalloc(state->mem, maxcmd * sizeof(char *)))) { |  | ||||||
| 			log_error("Failed to allocate memory for command."); |  | ||||||
| 			goto bad; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		dm_split_words(str, maxcmd - 1, 0, state->argv); |  | ||||||
| 		_init_thread_signals(state); |  | ||||||
| 	} else |  | ||||||
| 		memmove(state->cmd_str, state->cmd_str + 4, strlen(state->cmd_str + 4) + 1); |  | ||||||
|  |  | ||||||
| 	state->pid = -1; |  | ||||||
| 	*user = state; |  | ||||||
|  |  | ||||||
| 	log_info("Monitoring thin pool %s.", device); |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| bad: |  | ||||||
| 	log_error("Failed to monitor thin pool %s.", device); |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int unregister_device(const char *device, |  | ||||||
| 		      const char *uuid __attribute__((unused)), |  | ||||||
| 		      int major __attribute__((unused)), |  | ||||||
| 		      int minor __attribute__((unused)), |  | ||||||
| 		      void **user) |  | ||||||
| { |  | ||||||
| 	struct dso_state *state = *user; |  | ||||||
| 	int i; |  | ||||||
|  |  | ||||||
| 	for (i = 0; !_wait_for_pid(state) && (i < 6); ++i) { |  | ||||||
| 		if (i == 0) |  | ||||||
| 			/* Give it 2 seconds, then try to terminate & kill it */ |  | ||||||
| 			log_verbose("Child %d still not finished (%s) waiting.", |  | ||||||
| 				    state->pid, state->cmd_str); |  | ||||||
| 		else if (i == 3) { |  | ||||||
| 			log_warn("WARNING: Terminating child %d.", state->pid); |  | ||||||
| 			kill(state->pid, SIGINT); |  | ||||||
| 			kill(state->pid, SIGTERM); |  | ||||||
| 		} else if (i == 5) { |  | ||||||
| 			log_warn("WARNING: Killing child %d.", state->pid); |  | ||||||
| 			kill(state->pid, SIGKILL); |  | ||||||
| 		} |  | ||||||
| 		sleep(1); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (state->pid != -1) |  | ||||||
| 		log_warn("WARNING: Cannot kill child %d!", state->pid); |  | ||||||
|  |  | ||||||
| 	_restore_thread_signals(state); |  | ||||||
|  |  | ||||||
| 	dmeventd_lvm2_exit_with_pool(state); |  | ||||||
| 	log_info("No longer monitoring thin pool %s.", device); |  | ||||||
|  |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
							
								
								
									
										1
									
								
								daemons/lvmdbusd/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								daemons/lvmdbusd/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | |||||||
| path.py |  | ||||||
| @@ -1,66 +0,0 @@ | |||||||
| # |  | ||||||
| # Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  | ||||||
|  |  | ||||||
| srcdir = @srcdir@ |  | ||||||
| top_srcdir = @top_srcdir@ |  | ||||||
| top_builddir = @top_builddir@ |  | ||||||
|  |  | ||||||
| lvmdbusdir = $(python3dir)/lvmdbusd |  | ||||||
|  |  | ||||||
| LVMDBUS_SRCDIR_FILES = \ |  | ||||||
| 	automatedproperties.py \ |  | ||||||
| 	background.py \ |  | ||||||
| 	cfg.py \ |  | ||||||
| 	cmdhandler.py \ |  | ||||||
| 	fetch.py \ |  | ||||||
| 	__init__.py \ |  | ||||||
| 	job.py \ |  | ||||||
| 	loader.py \ |  | ||||||
| 	lvmdb.py \ |  | ||||||
| 	main.py \ |  | ||||||
| 	lvm_shell_proxy.py \ |  | ||||||
| 	lv.py \ |  | ||||||
| 	manager.py \ |  | ||||||
| 	objectmanager.py \ |  | ||||||
| 	pv.py \ |  | ||||||
| 	request.py \ |  | ||||||
| 	state.py \ |  | ||||||
| 	udevwatch.py \ |  | ||||||
| 	utils.py \ |  | ||||||
| 	vg.py |  | ||||||
|  |  | ||||||
| LVMDBUS_BUILDDIR_FILES = \ |  | ||||||
| 	path.py |  | ||||||
|  |  | ||||||
| LVMDBUSD = $(srcdir)/lvmdbusd |  | ||||||
|  |  | ||||||
| include $(top_builddir)/make.tmpl |  | ||||||
|  |  | ||||||
| .PHONY: install_lvmdbusd |  | ||||||
|  |  | ||||||
| install_lvmdbusd: |  | ||||||
| 	$(INSTALL_DIR) $(sbindir) |  | ||||||
| 	$(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir) |  | ||||||
| 	$(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir) |  | ||||||
| 	(cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir)) |  | ||||||
| 	$(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir) |  | ||||||
| 	PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES) |  | ||||||
| 	$(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__ |  | ||||||
| 	$(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co] |  | ||||||
|  |  | ||||||
| install_lvm2: install_lvmdbusd |  | ||||||
|  |  | ||||||
| install: install_lvm2 |  | ||||||
|  |  | ||||||
| DISTCLEAN_TARGETS+= \ |  | ||||||
| 	$(LVMDBUS_BUILDDIR_FILES) |  | ||||||
| @@ -1,10 +0,0 @@ | |||||||
| # Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>. |  | ||||||
|  |  | ||||||
| from .main import main |  | ||||||
| @@ -1,173 +0,0 @@ | |||||||
| # Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>. |  | ||||||
|  |  | ||||||
| import dbus |  | ||||||
| import dbus.service |  | ||||||
| from . import cfg |  | ||||||
| from .utils import get_properties, add_properties, get_object_property_diff, \ |  | ||||||
| 	log_debug |  | ||||||
| from .state import State |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # noinspection PyPep8Naming,PyUnresolvedReferences |  | ||||||
| class AutomatedProperties(dbus.service.Object): |  | ||||||
| 	""" |  | ||||||
| 	This class implements the needed interfaces for: |  | ||||||
| 	org.freedesktop.DBus.Properties |  | ||||||
|  |  | ||||||
| 	Other classes inherit from it to get the same behavior |  | ||||||
| 	""" |  | ||||||
|  |  | ||||||
| 	def __init__(self, object_path, search_method=None): |  | ||||||
| 		dbus.service.Object.__init__(self, cfg.bus, object_path) |  | ||||||
| 		self._ap_interface = [] |  | ||||||
| 		self._ap_o_path = object_path |  | ||||||
| 		self._ap_search_method = search_method |  | ||||||
| 		self.state = None |  | ||||||
|  |  | ||||||
| 	def dbus_object_path(self): |  | ||||||
| 		return self._ap_o_path |  | ||||||
|  |  | ||||||
| 	def emit_data(self): |  | ||||||
| 		props = {} |  | ||||||
|  |  | ||||||
| 		for i in self.interface(): |  | ||||||
| 			props[i] = self.GetAll(i) |  | ||||||
|  |  | ||||||
| 		return self._ap_o_path, props |  | ||||||
|  |  | ||||||
| 	def set_interface(self, interface): |  | ||||||
| 		""" |  | ||||||
| 		With inheritance we can't easily tell what interfaces a class provides |  | ||||||
| 		so we will have each class that implements an interface tell the |  | ||||||
| 		base AutomatedProperties what it is they do provide.  This is kind of |  | ||||||
| 		clunky and perhaps we can figure out a better way to do this later. |  | ||||||
| 		:param interface:       An interface the object supports |  | ||||||
| 		:return: |  | ||||||
| 		""" |  | ||||||
| 		if interface not in self._ap_interface: |  | ||||||
| 			self._ap_interface.append(interface) |  | ||||||
|  |  | ||||||
| 	# noinspection PyUnusedLocal |  | ||||||
| 	def interface(self, all_interfaces=False): |  | ||||||
| 		if all_interfaces: |  | ||||||
| 			cpy = list(self._ap_interface) |  | ||||||
| 			cpy.extend( |  | ||||||
| 				["org.freedesktop.DBus.Introspectable", |  | ||||||
| 					"org.freedesktop.DBus.Properties"]) |  | ||||||
| 			return cpy |  | ||||||
|  |  | ||||||
| 		return self._ap_interface |  | ||||||
|  |  | ||||||
| 	# Properties |  | ||||||
| 	# noinspection PyUnusedLocal |  | ||||||
| 	@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, |  | ||||||
| 							in_signature='ss', out_signature='v') |  | ||||||
| 	def Get(self, interface_name, property_name): |  | ||||||
| 		value = getattr(self, property_name) |  | ||||||
| 		# Note: If we get an exception in this handler we won't know about it, |  | ||||||
| 		# only the side effect of no returned value! |  | ||||||
| 		log_debug('Get (%s), type (%s), value(%s)' % |  | ||||||
| 					(property_name, str(type(value)), str(value))) |  | ||||||
| 		return value |  | ||||||
|  |  | ||||||
| 	@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, |  | ||||||
| 							in_signature='s', out_signature='a{sv}') |  | ||||||
| 	def GetAll(self, interface_name): |  | ||||||
| 		if interface_name in self.interface(True): |  | ||||||
| 			# Using introspection, lets build this dynamically |  | ||||||
| 			properties = get_properties(self) |  | ||||||
| 			if interface_name in properties: |  | ||||||
| 				return properties[interface_name][1] |  | ||||||
| 			return {} |  | ||||||
| 		raise dbus.exceptions.DBusException( |  | ||||||
| 			self._ap_interface, |  | ||||||
| 			'The object %s does not implement the %s interface' |  | ||||||
| 			% (self.__class__, interface_name)) |  | ||||||
|  |  | ||||||
| 	@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, |  | ||||||
| 							in_signature='ssv') |  | ||||||
| 	def Set(self, interface_name, property_name, new_value): |  | ||||||
| 		setattr(self, property_name, new_value) |  | ||||||
| 		self.PropertiesChanged(interface_name, |  | ||||||
| 								{property_name: new_value}, []) |  | ||||||
|  |  | ||||||
| 	# As dbus-python does not support introspection for properties we will |  | ||||||
| 	# get the autogenerated xml and then add our wanted properties to it. |  | ||||||
| 	@dbus.service.method(dbus_interface=dbus.INTROSPECTABLE_IFACE, |  | ||||||
| 							out_signature='s') |  | ||||||
| 	def Introspect(self): |  | ||||||
| 		r = dbus.service.Object.Introspect(self, self._ap_o_path, cfg.bus) |  | ||||||
| 		# Look at the properties in the class |  | ||||||
| 		props = get_properties(self) |  | ||||||
|  |  | ||||||
| 		for int_f, v in props.items(): |  | ||||||
| 			r = add_properties(r, int_f, v[0]) |  | ||||||
|  |  | ||||||
| 		return r |  | ||||||
|  |  | ||||||
| 	@dbus.service.signal(dbus_interface=dbus.PROPERTIES_IFACE, |  | ||||||
| 							signature='sa{sv}as') |  | ||||||
| 	def PropertiesChanged(self, interface_name, changed_properties, |  | ||||||
| 							invalidated_properties): |  | ||||||
| 		log_debug(('SIGNAL: PropertiesChanged(%s, %s, %s, %s)' % |  | ||||||
| 					(str(self._ap_o_path), str(interface_name), |  | ||||||
| 					str(changed_properties), str(invalidated_properties)))) |  | ||||||
|  |  | ||||||
| 	def refresh(self, search_key=None, object_state=None): |  | ||||||
| 		""" |  | ||||||
| 		Take the values (properties) of an object and update them with what |  | ||||||
| 		lvm currently has.  You can either fetch the new ones or supply the |  | ||||||
| 		new state to be updated with |  | ||||||
| 		:param search_key: The value to use to search for |  | ||||||
| 		:param object_state: Use this as the new object state |  | ||||||
| 		""" |  | ||||||
| 		num_changed = 0 |  | ||||||
|  |  | ||||||
| 		# If we can't do a lookup, bail now, this happens if we blindly walk |  | ||||||
| 		# through all dbus objects as some don't have a search method, like |  | ||||||
| 		# 'Manager' object. |  | ||||||
| 		if not self._ap_search_method: |  | ||||||
| 			return |  | ||||||
|  |  | ||||||
| 		search = self.lvm_id |  | ||||||
| 		if search_key: |  | ||||||
| 			search = search_key |  | ||||||
|  |  | ||||||
| 		# Either we have the new object state or we need to go fetch it |  | ||||||
| 		if object_state: |  | ||||||
| 			new_state = object_state |  | ||||||
| 		else: |  | ||||||
| 			new_state = self._ap_search_method([search])[0] |  | ||||||
| 			assert isinstance(new_state, State) |  | ||||||
|  |  | ||||||
| 		assert new_state |  | ||||||
|  |  | ||||||
| 		# When we refresh an object the object identifiers might have changed |  | ||||||
| 		# because LVM allows the user to change them (name & uuid), thus if |  | ||||||
| 		# they have changed we need to update the object manager so that |  | ||||||
| 		# look-ups will happen correctly |  | ||||||
| 		old_id = self.state.identifiers() |  | ||||||
| 		new_id = new_state.identifiers() |  | ||||||
| 		if old_id[0] != new_id[0] or old_id[1] != new_id[1]: |  | ||||||
| 			cfg.om.lookup_update(self, new_id[0], new_id[1]) |  | ||||||
|  |  | ||||||
| 		# Grab the properties values, then replace the state of the object |  | ||||||
| 		# and retrieve the new values. |  | ||||||
| 		o_prop = get_properties(self) |  | ||||||
| 		self.state = new_state |  | ||||||
| 		n_prop = get_properties(self) |  | ||||||
|  |  | ||||||
| 		changed = get_object_property_diff(o_prop, n_prop) |  | ||||||
|  |  | ||||||
| 		if changed: |  | ||||||
| 			for int_f, v in changed.items(): |  | ||||||
| 				self.PropertiesChanged(int_f, v, []) |  | ||||||
| 			num_changed += 1 |  | ||||||
| 		return num_changed |  | ||||||
| @@ -1,142 +0,0 @@ | |||||||
| # Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>. |  | ||||||
|  |  | ||||||
| import subprocess |  | ||||||
| from . import cfg |  | ||||||
| from .cmdhandler import options_to_cli_args |  | ||||||
| import dbus |  | ||||||
| from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug |  | ||||||
| import os |  | ||||||
| import threading |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def pv_move_lv_cmd(move_options, lv_full_name, |  | ||||||
| 					pv_source, pv_source_range, pv_dest_range_list): |  | ||||||
| 	cmd = ['pvmove', '-i', '1'] |  | ||||||
| 	cmd.extend(options_to_cli_args(move_options)) |  | ||||||
|  |  | ||||||
| 	if lv_full_name: |  | ||||||
| 		cmd.extend(['-n', lv_full_name]) |  | ||||||
|  |  | ||||||
| 	pv_range_append(cmd, pv_source, *pv_source_range) |  | ||||||
| 	pv_dest_ranges(cmd, pv_dest_range_list) |  | ||||||
|  |  | ||||||
| 	return cmd |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def lv_merge_cmd(merge_options, lv_full_name): |  | ||||||
| 	cmd = ['lvconvert', '--merge', '-i', '1'] |  | ||||||
| 	cmd.extend(options_to_cli_args(merge_options)) |  | ||||||
| 	cmd.append(lv_full_name) |  | ||||||
| 	return cmd |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def _move_merge(interface_name, command, job_state): |  | ||||||
| 	# We need to execute these command stand alone by forking & exec'ing |  | ||||||
| 	# the command always as we will be getting periodic output from them on |  | ||||||
| 	# the status of the long running operation. |  | ||||||
| 	command.insert(0, cfg.LVM_CMD) |  | ||||||
| 	process = subprocess.Popen(command, stdout=subprocess.PIPE, |  | ||||||
| 								env=os.environ, |  | ||||||
| 								stderr=subprocess.PIPE, close_fds=True) |  | ||||||
|  |  | ||||||
| 	log_debug("Background process for %s is %d" % |  | ||||||
| 				(str(command), process.pid)) |  | ||||||
|  |  | ||||||
| 	lines_iterator = iter(process.stdout.readline, b"") |  | ||||||
| 	for line in lines_iterator: |  | ||||||
| 		line_str = line.decode("utf-8") |  | ||||||
|  |  | ||||||
| 		# Check to see if the line has the correct number of separators |  | ||||||
| 		try: |  | ||||||
| 			if line_str.count(':') == 2: |  | ||||||
| 				(device, ignore, percentage) = line_str.split(':') |  | ||||||
| 				job_state.Percent = round( |  | ||||||
| 					float(percentage.strip()[:-1]), 1) |  | ||||||
| 		except ValueError: |  | ||||||
| 			log_error("Trying to parse percentage which failed for %s" % |  | ||||||
| 				line_str) |  | ||||||
|  |  | ||||||
| 	out = process.communicate() |  | ||||||
|  |  | ||||||
| 	if process.returncode == 0: |  | ||||||
| 		job_state.Percent = 100 |  | ||||||
| 	else: |  | ||||||
| 		raise dbus.exceptions.DBusException( |  | ||||||
| 			interface_name, |  | ||||||
| 			'Exit code %s, stderr = %s' % (str(process.returncode), out[1])) |  | ||||||
|  |  | ||||||
| 	cfg.load() |  | ||||||
| 	return '/' |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def move(interface_name, lv_name, pv_src_obj, pv_source_range, |  | ||||||
| 			pv_dests_and_ranges, move_options, job_state): |  | ||||||
| 	""" |  | ||||||
| 	Common code for the pvmove handling. |  | ||||||
| 	:param interface_name:  What dbus interface we are providing for |  | ||||||
| 	:param lv_name:     Optional (None or name of LV to move) |  | ||||||
| 	:param pv_src_obj:  dbus object patch for source PV |  | ||||||
| 	:param pv_source_range: (0,0 to ignore, else start, end segments) |  | ||||||
| 	:param pv_dests_and_ranges: Array of PV object paths and start/end segs |  | ||||||
| 	:param move_options: Hash with optional arguments |  | ||||||
| 	:param job_state: Used to convey information about jobs between processes |  | ||||||
| 	:return: '/' When complete, the empty object path |  | ||||||
| 	""" |  | ||||||
| 	pv_dests = [] |  | ||||||
| 	pv_src = cfg.om.get_object_by_path(pv_src_obj) |  | ||||||
| 	if pv_src: |  | ||||||
|  |  | ||||||
| 		# Check to see if we are handling a move to a specific |  | ||||||
| 		# destination(s) |  | ||||||
| 		if len(pv_dests_and_ranges): |  | ||||||
| 			for pr in pv_dests_and_ranges: |  | ||||||
| 				pv_dbus_obj = cfg.om.get_object_by_path(pr[0]) |  | ||||||
| 				if not pv_dbus_obj: |  | ||||||
| 					raise dbus.exceptions.DBusException( |  | ||||||
| 						interface_name, |  | ||||||
| 						'PV Destination (%s) not found' % pr[0]) |  | ||||||
|  |  | ||||||
| 				pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2])) |  | ||||||
|  |  | ||||||
| 		cmd = pv_move_lv_cmd(move_options, |  | ||||||
| 								lv_name, |  | ||||||
| 								pv_src.lvm_id, |  | ||||||
| 								pv_source_range, |  | ||||||
| 								pv_dests) |  | ||||||
|  |  | ||||||
| 		return _move_merge(interface_name, cmd, job_state) |  | ||||||
| 	else: |  | ||||||
| 		raise dbus.exceptions.DBusException( |  | ||||||
| 			interface_name, 'pv_src_obj (%s) not found' % pv_src_obj) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def merge(interface_name, lv_uuid, lv_name, merge_options, job_state): |  | ||||||
| 	# Make sure we have a dbus object representing it |  | ||||||
| 	dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name) |  | ||||||
| 	if dbo: |  | ||||||
| 		cmd = lv_merge_cmd(merge_options, dbo.lvm_id) |  | ||||||
| 		return _move_merge(interface_name, cmd, job_state) |  | ||||||
| 	else: |  | ||||||
| 		raise dbus.exceptions.DBusException( |  | ||||||
| 			interface_name, |  | ||||||
| 			'LV with uuid %s and name %s not present!' % (lv_uuid, lv_name)) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def _run_cmd(req): |  | ||||||
| 	log_debug( |  | ||||||
| 		"_run_cmd: Running method: %s with args %s" % |  | ||||||
| 		(str(req.method), str(req.arguments))) |  | ||||||
| 	req.run_cmd() |  | ||||||
| 	log_debug("_run_cmd: complete!") |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def cmd_runner(request): |  | ||||||
| 	t = threading.Thread(target=_run_cmd, args=(request,)) |  | ||||||
| 	t.start() |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user