mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-10-30 20:23:49 +03:00 
			
		
		
		
	Compare commits
	
		
			2368 Commits
		
	
	
		
			dev-mcsont
			...
			old-v1_02_
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 4d418dee0e | ||
|  | 06fe319347 | ||
|  | 9dd7e3fb24 | ||
|  | d5a46396b0 | ||
|  | 5e84cb560d | ||
|  | 756c6f8560 | ||
|  | 6fa6ce35da | ||
|  | b14b97599d | ||
|  | db6f60d6fc | ||
|  | 25c348d7c8 | ||
|  | 2e4bf8b034 | ||
|  | c1490e2f7b | ||
|  | b004fe9556 | ||
|  | 67142ad046 | ||
|  | 3c3ec06b12 | ||
|  | 5b5caa8a16 | ||
|  | b2cba098bb | ||
|  | 1ec0d47f10 | ||
|  | f232606ec7 | ||
|  | fa28cea152 | ||
|  | c8da1647a1 | ||
|  | 505a0a8718 | ||
|  | 10d3496a17 | ||
|  | a13c755370 | ||
|  | 62f9996fd7 | ||
|  | edbcd8a1b2 | ||
|  | a5308d1689 | ||
|  | cbfe6e8fcc | ||
|  | 5571ff35d8 | ||
|  | 2a4819f3c8 | ||
|  | 7121866b13 | ||
|  | d6e05ad9e2 | ||
|  | 993e30a7de | ||
|  | 49cae61254 | ||
|  | 1ea4b2ea91 | ||
|  | bc1d6e1f90 | ||
|  | 9ec6e68d0c | ||
|  | 341bdc93e2 | ||
|  | 6fb3e1aa15 | ||
|  | f1f92eb2e2 | ||
|  | 8c2369d40f | ||
|  | a6d9fc58eb | ||
|  | f7cd471548 | ||
|  | 5f951faf32 | ||
|  | b228dfaf2c | ||
|  | 764858fa12 | ||
|  | 5ee976d276 | ||
|  | 8b28b6f2d3 | ||
|  | fe16df2e6f | ||
|  | 779047f8c9 | ||
|  | 094e9fb45d | ||
|  | 1458bd0e74 | ||
|  | d2cb05988d | ||
|  | 6e056767b4 | ||
|  | a10afb1b98 | ||
|  | bb6d3b6cfd | ||
|  | c75d4af4bc | ||
|  | 972dc39d00 | ||
|  | 9daac5c178 | ||
|  | dd2a3f40e1 | ||
|  | 78f76c1690 | ||
|  | 4788066a5f | ||
|  | 10e4254e7d | ||
|  | 0106e4df9d | ||
|  | 8ac718a3a2 | ||
|  | 46d45273a1 | ||
|  | 8da9ec3599 | ||
|  | 01fdf84d69 | ||
|  | cc78386e75 | ||
|  | 3755157c61 | ||
|  | 80f8436f0a | ||
|  | f88a4b7760 | ||
|  | de229b8ab0 | ||
|  | a3ba37e45e | ||
|  | 50c779b3c6 | ||
|  | 192372e1c3 | ||
|  | f88fd88c38 | ||
|  | 6e15145af1 | ||
|  | 4b5fad4e48 | ||
|  | 7a13e71c80 | ||
|  | 3c10943900 | ||
|  | 696b8811c2 | ||
|  | 9fd2c8602a | ||
|  | a3636a5af4 | ||
|  | f2e5f07718 | ||
|  | 16c6fdde60 | ||
|  | 2155c93426 | ||
|  | c394631e4c | ||
|  | 8b370b7cc1 | ||
|  | 607db9971c | ||
|  | 6768f64e2f | ||
|  | f1813b1cc6 | ||
|  | fb665bd0dd | ||
|  | 65dda2ef3d | ||
|  | b162b992af | ||
|  | 67a3a3d130 | ||
|  | 92cd9bf7d2 | ||
|  | bf97034485 | ||
|  | 1ded1fc509 | ||
|  | e0592c58b3 | ||
|  | 5ead2706b4 | ||
|  | 52ada4853c | ||
|  | c2b27a8298 | ||
|  | 3934c1d437 | ||
|  | e366b68ad3 | ||
|  | fb94fb980a | ||
|  | b10cc18f53 | ||
|  | a249de3b72 | ||
|  | d04e972d65 | ||
|  | b9f5a18a76 | ||
|  | d3f157f08a | ||
|  | 2294fdb496 | ||
|  | d7ba0e01a5 | ||
|  | b6172b53fd | ||
|  | 477ec611d5 | ||
|  | b6194edd67 | ||
|  | dcdbbb3ecb | ||
|  | 7ef99ee4e6 | ||
|  | 1ac1418286 | ||
|  | 8fc854f38e | ||
|  | 1c2360b335 | ||
|  | dd4477406b | ||
|  | 9d67bbb104 | ||
|  | d6c8e1df61 | ||
|  | 5ec7c8fece | ||
|  | 86b21eaf83 | ||
|  | 228486a971 | ||
|  | 88c0caab26 | ||
|  | 5cd4679419 | ||
|  | eeed5e0d19 | ||
|  | 369ab1e0b2 | ||
|  | 2e21519a10 | ||
|  | ecc001ed08 | ||
|  | cd96852696 | ||
|  | b9f7f30158 | ||
|  | ca5e423331 | ||
|  | fa9407089c | ||
|  | 66f28e193a | ||
|  | 0d93f89f5c | ||
|  | 154e9a2c47 | ||
|  | 84574a1257 | ||
|  | bf83527b64 | ||
|  | 12c53622a0 | ||
|  | d8f54cf891 | ||
|  | 625a671189 | ||
|  | 6ebdad3102 | ||
|  | 9a8f21aa03 | ||
|  | 291dd8edc2 | ||
|  | de4c1daf29 | ||
|  | 0b55d7d0d8 | ||
|  | 5d86fd8fdb | ||
|  | 1b76eb1f59 | ||
|  | b05678d8bf | ||
|  | 781f4971c6 | ||
|  | d02ac7b99a | ||
|  | b1b6c97f7c | ||
|  | baee28ab5c | ||
|  | 83edf68ff9 | ||
|  | c7588f91dd | ||
|  | 30b432adc5 | ||
|  | 7c9733eb5d | ||
|  | a223c3fea3 | ||
|  | d5250f4901 | ||
|  | 25f29f4712 | ||
|  | 382af5563d | ||
|  | 8cf3d165d3 | ||
|  | 0fd6ce546f | ||
|  | b881c372bc | ||
|  | 94c5e7deb0 | ||
|  | c344766f3c | ||
|  | 67895de0bc | ||
|  | ff00cb6990 | ||
|  | 2cc75c11ed | ||
|  | cd79e58eda | ||
|  | 6fa801f3d8 | ||
|  | 684eecba1d | ||
|  | da9cf7e5de | ||
|  | f57e7445fd | ||
|  | fba1388719 | ||
|  | 80ed029c17 | ||
|  | 34a74e81e3 | ||
|  | cb120ddb15 | ||
|  | f9ee4395b0 | ||
|  | 71f06d51ed | ||
|  | 217f70952f | ||
|  | f813d41a76 | ||
|  | d851289d8a | ||
|  | b115b8a2ea | ||
|  | d0f7067471 | ||
|  | be5b4c38a7 | ||
|  | d6d597e3dd | ||
|  | 84e348fade | ||
|  | 910054657e | ||
|  | 8357a11249 | ||
|  | 9b021ba057 | ||
|  | 317e588efd | ||
|  | b1d32a03c7 | ||
|  | ee6e6529ee | ||
|  | 9d944d6cf9 | ||
|  | 13635d281a | ||
|  | 2493c46970 | ||
|  | 63e4217271 | ||
|  | f4bd12e8e9 | ||
|  | df15f46900 | ||
|  | fb3a732361 | ||
|  | 2d74110feb | ||
|  | 19d102082d | ||
|  | d2af2c9487 | ||
|  | 82980149fa | ||
|  | a19bb7b909 | ||
|  | 9d98c3278d | ||
|  | 26376ac1c9 | ||
|  | 8459f99341 | ||
|  | e5bdb0e0b5 | ||
|  | 1106b7775a | ||
|  | ae2852156d | ||
|  | 44c6c36c43 | ||
|  | a81926503d | ||
|  | af13ccddda | ||
|  | 392e1bc2e8 | ||
|  | 9268d92c70 | ||
|  | bb3366c07d | ||
|  | d24d563ebc | ||
|  | 954bd9257b | ||
|  | 5d51a56c02 | ||
|  | f48648552e | ||
|  | edb9c3cc9f | ||
|  | 01dc83b936 | ||
|  | 3a8dff3a62 | ||
|  | 13b234ccba | ||
|  | e451e93664 | ||
|  | b4f9531475 | ||
|  | 3184ff75c4 | ||
|  | 43243f4d30 | ||
|  | c975a100b1 | ||
|  | 02bf389425 | ||
|  | bcb9a3dd04 | ||
|  | cce3baa275 | ||
|  | 2b48fad426 | ||
|  | d554b2bc94 | ||
|  | f66943de43 | ||
|  | 9d1e9bc2fb | ||
|  | 2d6a014920 | ||
|  | c1952bf257 | ||
|  | a10227eb03 | ||
|  | 475ae29b85 | ||
|  | 0b9cfc278b | ||
|  | b57b6b4fba | ||
|  | 7d948f7bc5 | ||
|  | 459023d171 | ||
|  | fd6570720a | ||
|  | 7831665417 | ||
|  | 7c9920d982 | ||
|  | cbdccf0a9c | ||
|  | 64fa83ec3f | ||
|  | faff865cfd | ||
|  | 742ab55a9a | ||
|  | 66e623fb2a | ||
|  | 4ab17ee965 | ||
|  | 7f48ca5132 | ||
|  | da983848b4 | ||
|  | bc03f7bad3 | ||
|  | a1c8bd3846 | ||
|  | 404bc284e0 | ||
|  | 9dee30ff0e | ||
|  | f91aadbea8 | ||
|  | aa15a10c91 | ||
|  | 5b03e36351 | ||
|  | b9ba9ffad2 | ||
|  | 642be5d16c | ||
|  | ee68d715bf | ||
|  | 224084f056 | ||
|  | 1cd8c849b8 | ||
|  | 169f68bfcd | ||
|  | d2b7cfa2d1 | ||
|  | a40c7dff5d | ||
|  | e8e00630d3 | ||
|  | e33720c854 | ||
|  | bd8a4e0d17 | ||
|  | 586a2aef76 | ||
|  | ce1d8f6754 | ||
|  | 7b0f401065 | ||
|  | 8387016eef | ||
|  | 4e1342b641 | ||
|  | e45a184d90 | ||
|  | 979e1012d2 | ||
|  | fe10a50e23 | ||
|  | 8ab6d72519 | ||
|  | 3aada6dd1d | ||
|  | 0933036366 | ||
|  | 05f5abdc06 | ||
|  | fb875e0709 | ||
|  | 9acdc2f6bf | ||
|  | 028ce4bff6 | ||
|  | 3f245ad6db | ||
|  | 23115f4116 | ||
|  | cf5f48e6cc | ||
|  | 997fa756ad | ||
|  | e23f75b1cc | ||
|  | 6531e88761 | ||
|  | e76a9c2618 | ||
|  | 45be8a836b | ||
|  | 954b6032e7 | ||
|  | bd95416f27 | ||
|  | df2577ace2 | ||
|  | 720e6558c9 | ||
|  | c239f15d8a | ||
|  | dfa1f80a57 | ||
|  | 15dfb93b17 | ||
|  | 0ec8488c2b | ||
|  | 94b2e29cb1 | ||
|  | fefa8e9b4d | ||
|  | 32c4c44812 | ||
|  | 05195e2b1d | ||
|  | 4c2ff675b8 | ||
|  | e5692a4721 | ||
|  | 312e6a0d31 | ||
|  | 5bb8efa41f | ||
|  | 949a835f4a | ||
|  | 85e6042941 | ||
|  | 3cd2f28975 | ||
|  | 2179a72c3a | ||
|  | a5f282f156 | ||
|  | 40e8631f63 | ||
|  | 9ded05bb97 | ||
|  | ec8efa35a1 | ||
|  | f72bf20482 | ||
|  | ebde2002e8 | ||
|  | 352a66f46f | ||
|  | d84c5391f7 | ||
|  | f4c582472b | ||
|  | 1485586f7e | ||
|  | d5c9024335 | ||
|  | 860cf80703 | ||
|  | 897ff3161f | ||
|  | b356b2e501 | ||
|  | 1d2733c893 | ||
|  | 32d9126094 | ||
|  | db43314e50 | ||
|  | 68d2baeb65 | ||
|  | 1fd5f562d3 | ||
|  | 48e02f2086 | ||
|  | eab7b2b581 | ||
|  | 45abade7fc | ||
|  | 5372fc4b43 | ||
|  | 4e2f240c98 | ||
|  | bb3605518d | ||
|  | 3ef6d37f27 | ||
|  | 88e9f2f7f4 | ||
|  | 704a447df9 | ||
|  | a5fcb26a33 | ||
|  | 2491a61481 | ||
|  | 91831d51ed | ||
|  | 174f0c19f7 | ||
|  | de6fadfb4f | ||
|  | f946db3e00 | ||
|  | 8d05e5bc31 | ||
|  | cfb46820e4 | ||
|  | 081f1cbcc2 | ||
|  | 7bc6da326f | ||
|  | cd95a0df7b | ||
|  | 82fa497c16 | ||
|  | 44fd345206 | ||
|  | 088e1c9db4 | ||
|  | d4f16e666e | ||
|  | 8233cfd371 | ||
|  | ff05e2e30d | ||
|  | a8ea7dd3fb | ||
|  | 96f70a5303 | ||
|  | f1604c3e69 | ||
|  | c42c8c5192 | ||
|  | 5facb53a41 | ||
|  | d039ce89af | ||
|  | bc7605103f | ||
|  | d305d655d4 | ||
|  | 4ef1220b16 | ||
|  | a4fef143cd | ||
|  | 74ecb724a9 | ||
|  | af235897ab | ||
|  | 5ec4e458b5 | ||
|  | 2dae63ce21 | ||
|  | be748fe33b | ||
|  | 7408340b6a | ||
|  | 29eb92446e | ||
|  | ae6918742e | ||
|  | 863484bb65 | ||
|  | 1cd7ebce4c | ||
|  | eef8c7862e | ||
|  | b52375d446 | ||
|  | 6e2babc2ce | ||
|  | 08e253bed1 | ||
|  | c6661477a2 | ||
|  | 415cfd99a0 | ||
|  | 8c2e37381a | ||
|  | 45df79feba | ||
|  | 5824f992b7 | ||
|  | b0b60fafd5 | ||
|  | 8d98b02ba2 | ||
|  | a93fe79bc4 | ||
|  | 4aebd7be37 | ||
|  | 3170a5db32 | ||
|  | 3605b9eef6 | ||
|  | a945f1fde2 | ||
|  | 461a997b5b | ||
|  | a80afd7b4e | ||
|  | aad2b51d85 | ||
|  | 36a9a81ff1 | ||
|  | 42c88546ae | ||
|  | 0f0e86ef9b | ||
|  | 98efd9a857 | ||
|  | a0c27d95b7 | ||
|  | 984651d99d | ||
|  | c6f7370b30 | ||
|  | 3e4b8e8985 | ||
|  | 73f08b98d2 | ||
|  | 8607a74206 | ||
|  | 8339f3ceb3 | ||
|  | c0c9f3cc19 | ||
|  | 81f4813c29 | ||
|  | 94f57745b9 | ||
|  | 54fb2ebbe0 | ||
|  | 02d122b65b | ||
|  | df0a5561a1 | ||
|  | f7c55da7d0 | ||
|  | b385f701ce | ||
|  | 05dd42f443 | ||
|  | 36d816d5cb | ||
|  | 92a6746e70 | ||
|  | 1728848a39 | ||
|  | f9eb4e7487 | ||
|  | d0b9f33aeb | ||
|  | 718583b241 | ||
|  | 6737127e9a | ||
|  | 19a7b4479b | ||
|  | c340647502 | ||
|  | 0f987d2982 | ||
|  | 52bcaed169 | ||
|  | 177bd565ac | ||
|  | c801c32fc5 | ||
|  | d090cf3058 | ||
|  | 1e4b82cc94 | ||
|  | 3426f31184 | ||
|  | b4fb7af1df | ||
|  | b36647598b | ||
|  | fd6b94f20e | ||
|  | 296dc0ed8a | ||
|  | 4f869e14d6 | ||
|  | 5704270e9d | ||
|  | 505b381e85 | ||
|  | da6cb15393 | ||
|  | 16843f6cc8 | ||
|  | 64f3ad1fd4 | ||
|  | ff4c4f99b3 | ||
|  | f5d2e09569 | ||
|  | f2bdbe0d4d | ||
|  | c51a13caa6 | ||
|  | 7840c78a23 | ||
|  | c706f3246b | ||
|  | 608eedf88d | ||
|  | a564ca82be | ||
|  | c868b1fee2 | ||
|  | 22374f718f | ||
|  | abe3cfcf41 | ||
|  | 59db4b50cd | ||
|  | bdae38765d | ||
|  | 66d3ceeb61 | ||
|  | 445dd17db3 | ||
|  | cff78a2577 | ||
|  | 6a09e64195 | ||
|  | 22eabe5eab | ||
|  | b69ba36c2d | ||
|  | 5240aad22b | ||
|  | 2897eb3cb3 | ||
|  | d3f2f00c25 | ||
|  | bacfb913a0 | ||
|  | c99d0236a0 | ||
|  | aac2b655f7 | ||
|  | 126c41e73a | ||
|  | 359ee54f0d | ||
|  | 28ab560907 | ||
|  | ead252fee4 | ||
|  | abf67914c4 | ||
|  | 127884e9dd | ||
|  | 654f5049eb | ||
|  | 979ca34259 | ||
|  | 4dd1086805 | ||
|  | 3503d4b72c | ||
|  | b8d32a0d33 | ||
|  | 45dca55fc8 | ||
|  | 445d8ecd9f | ||
|  | c980add503 | ||
|  | 133842392a | ||
|  | 8baf2ef155 | ||
|  | 20b71340bc | ||
|  | 61d8baf8b1 | ||
|  | 56a9645aa5 | ||
|  | 85877000a6 | ||
|  | 2f7d2477b6 | ||
|  | 21ea3f05f4 | ||
|  | 79d3492e90 | ||
|  | 5972777abe | ||
|  | 8e373ff868 | ||
|  | a4db92da3a | ||
|  | 9b777eb281 | ||
|  | bd3c652184 | ||
|  | 800f747570 | ||
|  | 2b8423437e | ||
|  | 8b4b6945f8 | ||
|  | e5ecfec5c4 | ||
|  | f95dbff71f | ||
|  | 098f6830a6 | ||
|  | d1ecebdb52 | ||
|  | 590b654251 | ||
|  | 3bf190c8ab | ||
|  | dcca7638e0 | ||
|  | 70e45ad37b | ||
|  | db88210289 | ||
|  | d2e0d96cc3 | ||
|  | 3feba82ccc | ||
|  | db924da231 | ||
|  | fc55ae7e6d | ||
|  | 86e757a6ad | ||
|  | 4790715cd3 | ||
|  | e7e9c60042 | ||
|  | 1c3bc52cc4 | ||
|  | 5227dff0e1 | ||
|  | 33f0b5b7c2 | ||
|  | 0a02968303 | ||
|  | f7bf658c07 | ||
|  | 8d16a0abad | ||
|  | c974b97ca3 | ||
|  | b8025bfebd | ||
|  | 30323b253f | ||
|  | 535c3ede96 | ||
|  | 89fed8ca33 | ||
|  | f43c77aaed | ||
|  | 96c676b371 | ||
|  | 113047e1a2 | ||
|  | abed57cb53 | ||
|  | c01a800a6b | ||
|  | d648832a2d | ||
|  | f06833fbd2 | ||
|  | c561addc94 | ||
|  | 702f5f1f4c | ||
|  | 1273f179e8 | ||
|  | 5d02f60bde | ||
|  | 4cf7a108e8 | ||
|  | 42635c3938 | ||
|  | ed43dc842b | ||
|  | 49d4db6cd2 | ||
|  | ea80ab2cae | ||
|  | 382e808b8d | ||
|  | 846befa7e0 | ||
|  | 74dd29f843 | ||
|  | b0473bffcb | ||
|  | 24dd9ab1a7 | ||
|  | 49d3037e87 | ||
|  | 37ad2bd4e8 | ||
|  | 7d7b332b02 | ||
|  | ac033b8612 | ||
|  | a7b98dfe25 | ||
|  | 7fb7c86c46 | ||
|  | ed036598a9 | ||
|  | 160bb70cdf | ||
|  | c2e61f3c21 | ||
|  | 18218467f3 | ||
|  | 17e298ad2a | ||
|  | d031a374f9 | ||
|  | 55f69c98cb | ||
|  | 71f2e4306d | ||
|  | f8af23a025 | ||
|  | 4ef55a6cd3 | ||
|  | 312f866723 | ||
|  | 0ebe1f6dec | ||
|  | 2ad92e0e6e | ||
|  | ac8823cdcf | ||
|  | 77565f7ee4 | ||
|  | d656d90fa8 | ||
|  | 175b3b0834 | ||
|  | 7477e6b714 | ||
|  | cd6568db69 | ||
|  | 6aff325fb2 | ||
|  | 0d603cfe9c | ||
|  | 34a1f14a17 | ||
|  | efe1c8a070 | ||
|  | 1575844344 | ||
|  | 221ac1c208 | ||
|  | 57442db759 | ||
|  | 5fdb3e7cd6 | ||
|  | 96f259726c | ||
|  | 4936efba5e | ||
|  | d5a3559a2f | ||
|  | 114a1c7f52 | ||
|  | ce5265c203 | ||
|  | 1a575d926f | ||
|  | 85c818a39e | ||
|  | 4ffa2defe4 | ||
|  | 8825157fbb | ||
|  | 966d608dc5 | ||
|  | b808c89471 | ||
|  | 75d4e6490f | ||
|  | a82775f544 | ||
|  | 6a22ad0171 | ||
|  | c854e88186 | ||
|  | d02203060c | ||
|  | cf703b0433 | ||
|  | c0197a72d3 | ||
|  | e5a543e283 | ||
|  | b8b029b7d3 | ||
|  | 370f368b1a | ||
|  | 8288b45b4f | ||
|  | fe529faf8e | ||
|  | ab931b177d | ||
|  | 9aa3465513 | ||
|  | 6c70fc1a6c | ||
|  | 1ccc39962a | ||
|  | 99c941fc85 | ||
|  | 19729fdcc2 | ||
|  | 02e17998ce | ||
|  | 459e00c67a | ||
|  | 292f665650 | ||
|  | 93bbb79569 | ||
|  | 273e724f2b | ||
|  | 5d2615c56f | ||
|  | bfaaf21330 | ||
|  | dcb8415b7a | ||
|  | 699e1c75ce | ||
|  | 465b6e613e | ||
|  | 05fa105855 | ||
|  | d7a0cdebe5 | ||
|  | b049ab31eb | ||
|  | 6db4dcff7a | ||
|  | 3eeaef00ec | ||
|  | 8bf4c38a00 | ||
|  | 3a32b09ad1 | ||
|  | 6315982752 | ||
|  | 374a171e82 | ||
|  | fc5d801f91 | ||
|  | 5146641848 | ||
|  | cdd0ac42cf | ||
|  | e5895500a2 | ||
|  | 9cb4dde3fa | ||
|  | 3c2a4370a5 | ||
|  | e7a360dd6f | ||
|  | c814c2fd35 | ||
|  | fefa7fe262 | ||
|  | 26f01a29d1 | ||
|  | 169d4090ab | ||
|  | 0b43754d60 | ||
|  | 8b3b26b813 | ||
|  | 5426af4f81 | ||
|  | 4e2c3a579d | ||
|  | 5ae2693241 | ||
|  | 41c86b0d19 | ||
|  | 40788e8c3d | ||
|  | 0d29120033 | ||
|  | 4be598f865 | ||
|  | 558a6d509e | ||
|  | 75cd02aad2 | ||
|  | e4c4451482 | ||
|  | 0671632477 | ||
|  | 54c230c264 | ||
|  | 64ba878eda | ||
|  | 01acd6dd76 | ||
|  | 9d819b52d3 | ||
|  | 37bac5cdc9 | ||
|  | 78c718c591 | ||
|  | 284b8bf6ca | ||
|  | 5a5084b837 | ||
|  | 3b8058e1f1 | ||
|  | 2a3168e0d6 | ||
|  | a8ac6e4a15 | ||
|  | 6172cf9fba | ||
|  | b728ec3909 | ||
|  | 61a53bbcff | ||
|  | 17d13dd084 | ||
|  | edcb28d591 | ||
|  | ad101119a7 | ||
|  | bc36676d31 | ||
|  | d76fe120ab | ||
|  | 2e95949b80 | ||
|  | ae14d85e24 | ||
|  | fad6304c60 | ||
|  | a4dd3c8ce9 | ||
|  | 6d1a5d45e2 | ||
|  | a6c7043e03 | ||
|  | bcc400dafa | ||
|  | 8fbedf3441 | ||
|  | 2e8a9c9874 | ||
|  | 44fc41b3e5 | ||
|  | 7212c20a1b | ||
|  | 7ff142de1c | ||
|  | e67efb199d | ||
|  | 20128bd04b | ||
|  | c0fefdde28 | ||
|  | f6ee160e66 | ||
|  | 06acc2004f | ||
|  | 43ac2ce4c8 | ||
|  | b32bf72b5f | ||
|  | c6880c957e | ||
|  | 095b71ed96 | ||
|  | 9160e496bc | ||
|  | 2a7ac78f02 | ||
|  | 64efa4627d | ||
|  | f7e35569ce | ||
|  | e8af32ec2b | ||
|  | e092ce51f6 | ||
|  | 7b78edb1b7 | ||
|  | b332e7090e | ||
|  | 67eb7723d6 | ||
|  | 251d138474 | ||
|  | 1170dfac05 | ||
|  | 4157f141c7 | ||
|  | f569abd28a | ||
|  | 088f9687c0 | ||
|  | e23df1f07a | ||
|  | c818540dfd | ||
|  | 21365cbe1a | ||
|  | 5471a80a96 | ||
|  | d7b6fa9cd0 | ||
|  | dfdc2e02ef | ||
|  | 893ec9a302 | ||
|  | 05f65c38e6 | ||
|  | 2e9d062ec0 | ||
|  | 6b0b394e61 | ||
|  | 25621396c9 | ||
|  | 82aa0271f3 | ||
|  | 653cab13f8 | ||
|  | b526f86b49 | ||
|  | 53c0f00888 | ||
|  | f0c4d9de40 | ||
|  | 03ef8cec83 | ||
|  | 85f2a2e8c2 | ||
|  | 584b3e6642 | ||
|  | 39b7ef841d | ||
|  | aa16a9098d | ||
|  | 7b8c2707bc | ||
|  | 60e26a31a7 | ||
|  | 3473c25c14 | ||
|  | e52f022026 | ||
|  | b1a7df8e43 | ||
|  | 0fd2479b7c | ||
|  | 273857f914 | ||
|  | a08b85dbc8 | ||
|  | a0aedf299a | ||
|  | 3c61426844 | ||
|  | 786f228076 | ||
|  | 004da28792 | ||
|  | 6e2be6efb6 | ||
|  | a994dfcfbc | ||
|  | 7a8ea2ac93 | ||
|  | 0da3965d19 | ||
|  | 885fd7bb46 | ||
|  | 08771f9c89 | ||
|  | 8be48195a5 | ||
|  | 98ce2d650e | ||
|  | 3af327116a | ||
|  | b75434db93 | ||
|  | 04e912aacd | ||
|  | d7be352f87 | ||
|  | 96be3ec22c | ||
|  | 32e7e0d790 | ||
|  | becc320e62 | ||
|  | 7666ed57d1 | ||
|  | 5e61d0955e | ||
|  | e8a4662ae7 | ||
|  | a48da3bd3b | ||
|  | 5f1a5d7b99 | ||
|  | 3e28a9db8f | ||
|  | ebf6071d77 | ||
|  | 47a35fb9fb | ||
|  | 48e88aba44 | ||
|  | b85f99c140 | ||
|  | 0a5e0e1f71 | ||
|  | 85dc22ebb7 | ||
|  | 5c21526009 | ||
|  | 14dff1cefc | ||
|  | 39fbb844f9 | ||
|  | ca4e0c973a | ||
|  | ecb42bee80 | ||
|  | 674ed2a9f3 | ||
|  | 252daf9717 | ||
|  | 196b8eaad3 | ||
|  | 8e526ba1bf | ||
|  | 19225828d9 | ||
|  | 7e594126be | ||
|  | d2529e6334 | ||
|  | 97344f18e2 | ||
|  | 33934db629 | ||
|  | 6c6165c9f5 | ||
|  | 853460b20d | ||
|  | cc4d9676c5 | ||
|  | 1cf1b819f4 | ||
|  | f916c66d2b | ||
|  | 550aa86b45 | ||
|  | 014e764758 | ||
|  | d1fc28432b | ||
|  | 879576f0a2 | ||
|  | 69098210be | ||
|  | 99df4f892d | ||
|  | 7bc04fbad3 | ||
|  | 8a74ce578d | ||
|  | 0805e4e5de | ||
|  | f1060fc88e | ||
|  | 7d3d3d0a3a | ||
|  | 40377032e3 | ||
|  | b2971edd7d | ||
|  | c37d723692 | ||
|  | 30f9026e1d | ||
|  | 332286072e | ||
|  | d6da172a2a | ||
|  | ebfe584afc | ||
|  | 6250023583 | ||
|  | 6b4f3d63b8 | ||
|  | 56db773a09 | ||
|  | fc6c472401 | ||
|  | 2cd42a6866 | ||
|  | 36a90c345c | ||
|  | ef1e82c72c | ||
|  | 88f9534685 | ||
|  | 68254a052a | ||
|  | 2425b3a166 | ||
|  | 5524ed753b | ||
|  | 89711723da | ||
|  | bed2740ffd | ||
|  | 751d633c3d | ||
|  | 45952cbdf2 | ||
|  | b355dd7b23 | ||
|  | 48a186f172 | ||
|  | 39dc7ec2ab | ||
|  | 2fedabd3b9 | ||
|  | 6d719e9480 | ||
|  | 05e278afda | ||
|  | 87dbf462cb | ||
|  | 40e896bc5b | ||
|  | 3e940f80c7 | ||
|  | dbf2888d43 | ||
|  | d412355324 | ||
|  | 178732217f | ||
|  | de17b95c3d | ||
|  | d14e774525 | ||
|  | ca5402a7fa | ||
|  | 7a6fa7c5b4 | ||
|  | da36c286a6 | ||
|  | d3901bcf2e | ||
|  | 94c8d4fdfb | ||
|  | ab8bdc18bb | ||
|  | c9dcd7442a | ||
|  | 34c8f13346 | ||
|  | 7a8ccda95c | ||
|  | 44a1448542 | ||
|  | c87d89ffaf | ||
|  | 0868749d42 | ||
|  | 1d40ee23f0 | ||
|  | 8893f32603 | ||
|  | adcf7e8dc3 | ||
|  | 901f7c5c36 | ||
|  | 775bb413b3 | ||
|  | 64cd5b5a46 | ||
|  | ae356609b1 | ||
|  | 6102a5d2b0 | ||
|  | f8782ee2d7 | ||
|  | 6181ec4c77 | ||
|  | e0e7a685ef | ||
|  | ae1f8cdad2 | ||
|  | a4cf792e6d | ||
|  | 89109ded53 | ||
|  | e20e52a4b2 | ||
|  | 20c4b1cbec | ||
|  | 5238b0241d | ||
|  | 9cdf6c203d | ||
|  | 839335cae6 | ||
|  | a99b2ce167 | ||
|  | b695141d87 | ||
|  | 92d5c9f866 | ||
|  | 7f18a1ffe0 | ||
|  | 8c3fdaaa62 | ||
|  | 5ac1c69710 | ||
|  | de2d5fba63 | ||
|  | 33d516748f | ||
|  | de17f6f0fd | ||
|  | 756731fc02 | ||
|  | e46be0415f | ||
|  | aa02fb50bf | ||
|  | 8b6cd9c772 | ||
|  | cdd0d3351a | ||
|  | 8b6d584529 | ||
|  | f49fdd4141 | ||
|  | b26e1be81a | ||
|  | bacab38d7f | ||
|  | 701c05ce96 | ||
|  | 438c452585 | ||
|  | 0a7a1eff3f | ||
|  | 87e743e381 | ||
|  | a03f1b3d55 | ||
|  | 2d8dc3d243 | ||
|  | b982232cc5 | ||
|  | 61c8d728ac | ||
|  | 851a2bf855 | ||
|  | e0bdde3630 | ||
|  | 6a0dcd7f0e | ||
|  | 75f0b4c879 | ||
|  | db536a9504 | ||
|  | 0fb114dede | ||
|  | e703342179 | ||
|  | 35c8f4a611 | ||
|  | 7c89ae44a9 | ||
|  | 84fe06da22 | ||
|  | 806318c8b3 | ||
|  | 3aac2e1822 | ||
|  | 168baef433 | ||
|  | 6dba6cd78d | ||
|  | 502250d08f | ||
|  | 7395f0e680 | ||
|  | 494d3fdaca | ||
|  | 7b86a157de | ||
|  | 0988c41785 | ||
|  | 522db1bf01 | ||
|  | 06f066f90d | ||
|  | f37b20677b | ||
|  | cd2eac1032 | ||
|  | 8ac38d58d7 | ||
|  | 4c80cc313a | ||
|  | 1c65fee9b4 | ||
|  | 90dda7edc1 | ||
|  | da054fae20 | ||
|  | bdb6611e30 | ||
|  | 9284f973f1 | ||
|  | 2bfd64c3c9 | ||
|  | 939d24cce5 | ||
|  | 27b0183c46 | ||
|  | d14efacac7 | ||
|  | 150a002c40 | ||
|  | ce0def3bd8 | ||
|  | ee20fa97c2 | ||
|  | 7403b7d700 | ||
|  | 87ef173e0a | ||
|  | 52a3fb6bc7 | ||
|  | 92e2a257a6 | ||
|  | 32e175752c | ||
|  | d43f7180dc | ||
|  | 0129c2b0fc | ||
|  | 4ed1990001 | ||
|  | 5bd6ab27ae | ||
|  | f3593b89fa | ||
|  | 23d84b2310 | ||
|  | fdc49402ec | ||
|  | 5457c133e1 | ||
|  | 292e588ee3 | ||
|  | 243494c25e | ||
|  | e4365f3706 | ||
|  | 310f3038d3 | ||
|  | 4e6033273d | ||
|  | 73718586d3 | ||
|  | 011abe61e8 | ||
|  | fe3a37f89d | ||
|  | 8aea44e77b | ||
|  | 5529aec0d6 | ||
|  | 369549d23f | ||
|  | 181ea9a381 | ||
|  | 76b8f2854e | ||
|  | 320e5198f9 | ||
|  | e522539e2d | ||
|  | 7c996b83d2 | ||
|  | 3dd354d7aa | ||
|  | f4ad6e2157 | ||
|  | 8b170dc2bf | ||
|  | dcb9d779bf | ||
|  | 80f736d670 | ||
|  | 8502c6da3c | ||
|  | b131449422 | ||
|  | 6eebc4a620 | ||
|  | 4661ab1179 | ||
|  | 86046445ed | ||
|  | baea9bf944 | ||
|  | 0951ee9e63 | ||
|  | 5492528287 | ||
|  | 14dbd220c2 | ||
|  | babc890c59 | ||
|  | 6f7b47ff40 | ||
|  | 3991f03202 | ||
|  | 27271d5da7 | ||
|  | 627312e1de | ||
|  | bfc9550e4e | ||
|  | 2b9c21268b | ||
|  | 3dce4ed6f1 | ||
|  | 0f16c2ea87 | ||
|  | 9a635f0686 | ||
|  | 6a0d4b2baa | ||
|  | ac017098ad | ||
|  | 98fef2640d | ||
|  | 8bb66e133a | ||
|  | 68a582901d | ||
|  | c094f4c06e | ||
|  | f7ca545544 | ||
|  | 69b4716894 | ||
|  | 7e44dcc5bf | ||
|  | ab9843e183 | ||
|  | 01af706ade | ||
|  | 9ebdb08e99 | ||
|  | a74ffe25d9 | ||
|  | 7f95e27707 | ||
|  | 1facf5bba3 | ||
|  | 03d77009eb | ||
|  | 8afd6812b5 | ||
|  | ec9ad78fcf | ||
|  | 6f4e93dc90 | ||
|  | a38e43862d | ||
|  | 39294bb037 | ||
|  | edc5e59b78 | ||
|  | c00fd9fd37 | ||
|  | b3e621dd9f | ||
|  | 6e8c49b978 | ||
|  | 398d57133d | ||
|  | 16521a6feb | ||
|  | 3ca0b37a3e | ||
|  | cf2ec1229d | ||
|  | fe9b1e5f9b | ||
|  | f5b96ddf01 | ||
|  | 2fe076fb27 | ||
|  | 99249cff04 | ||
|  | 0cdf7b0613 | ||
|  | 90bcf4f157 | ||
|  | 03c3ec4e12 | ||
|  | ca9bb20d64 | ||
|  | c6bc078fd9 | ||
|  | 2f4bd6e52c | ||
|  | 2affe53727 | ||
|  | 09654d7dd8 | ||
|  | 90a4e37815 | ||
|  | 60889c0c79 | ||
|  | 20f3408d96 | ||
|  | e9d86789db | ||
|  | 5152b7c66c | ||
|  | c494c4e12c | ||
|  | 54d58ccb7e | ||
|  | 714a77bfbe | ||
|  | d48f8bf5cc | ||
|  | 99d97754a6 | ||
|  | b9d437de2a | ||
|  | 11403f2019 | ||
|  | 1ca102d639 | ||
|  | 339ba55111 | ||
|  | 14ae59885a | ||
|  | e3ef54f99b | ||
|  | 001901f9a9 | ||
|  | 6a98f60e2e | ||
|  | 6f2e24c47d | ||
|  | aafa368923 | ||
|  | eb783cab4c | ||
|  | 6533aa865a | ||
|  | f1a1e1bc07 | ||
|  | 953f4838dd | ||
|  | 130b892d34 | ||
|  | 6ad525c77e | ||
|  | d0ca74ad27 | ||
|  | 9806f69b4d | ||
|  | 34d9b5e3d7 | ||
|  | 3bf5189d86 | ||
|  | 12e5b0681b | ||
|  | 8c0285d608 | ||
|  | 36558fa3b8 | ||
|  | 235f940cde | ||
|  | 803d61fcbc | ||
|  | ffbd7d8de4 | ||
|  | 4ed924d7c7 | ||
|  | 798dc9948b | ||
|  | 13515f7ee4 | ||
|  | ef80824c26 | ||
|  | c8503fd65e | ||
|  | b3c454fb1c | ||
|  | 1d7723e873 | ||
|  | 77100b2365 | ||
|  | 259a788134 | ||
|  | 39511455cb | ||
|  | b04c16178e | ||
|  | 49a959c06e | ||
|  | 096a8932b4 | ||
|  | e39e66df93 | ||
|  | 513633f49a | ||
|  | eb3740daaf | ||
|  | f7947b148a | ||
|  | 9a2a702f3f | ||
|  | c65d95bf29 | ||
|  | 753a5edc4f | ||
|  | 0b3f853c2d | ||
|  | 3527fcf1d5 | ||
|  | 4544a89c7a | ||
|  | ffeae9005e | ||
|  | 47217bcfb7 | ||
|  | 80ff58b57a | ||
|  | d15dd368f1 | ||
|  | 8a2ec32bd8 | ||
|  | 410496ed52 | ||
|  | b7b07552e5 | ||
|  | 44486e80d9 | ||
|  | 7890c527d8 | ||
|  | 2c82ab79a7 | ||
|  | e3ebe5fc53 | ||
|  | 0ac430892e | ||
|  | a7739c942c | ||
|  | 24581482d0 | ||
|  | 0571c3b453 | ||
|  | 73e7f5a0b0 | ||
|  | 20c0adb961 | ||
|  | a01e03562f | ||
|  | d184ed0130 | ||
|  | 089e1c2aee | ||
|  | ebab0e91ee | ||
|  | 858a2b1b88 | ||
|  | 02bd59827c | ||
|  | 4991428510 | ||
|  | 3b245f5dc1 | ||
|  | c9c81da901 | ||
|  | 4919cdc3fb | ||
|  | e90e1f577d | ||
|  | afd4284403 | ||
|  | 150b350d31 | ||
|  | 2818520bd1 | ||
|  | 2819952292 | ||
|  | 5af71af51c | ||
|  | 07a55b51df | ||
|  | 66dd68b49d | ||
|  | 9812657777 | ||
|  | 0b09312fc6 | ||
|  | d0a7ac6b74 | ||
|  | ff9a238fbd | ||
|  | 359fffa5f1 | ||
|  | 5bf92ced1a | ||
|  | 340bcc7b45 | ||
|  | ef03742bd4 | ||
|  | 20431ec16d | ||
|  | becba8157b | ||
|  | 51fd3bb0eb | ||
|  | 4bbd3acb4e | ||
|  | 3bc930ea7b | ||
|  | d1b26f8e86 | ||
|  | fdf15caaff | ||
|  | c7b4a53c0b | ||
|  | af78dc0308 | ||
|  | 5ad39493c4 | ||
|  | 61f597b408 | ||
|  | 2162825240 | ||
|  | 2b780e70d1 | ||
|  | a3823f818e | ||
|  | 1f7c47bcaf | ||
|  | ec53c365a2 | ||
|  | 793ad1f2d4 | ||
|  | 9bc733b76c | ||
|  | 21b28f0217 | ||
|  | d3e23caa52 | ||
|  | 9e7518de67 | ||
|  | 679f0047aa | ||
|  | d77d5ce14b | ||
|  | 33ec22a2af | ||
|  | 353053225f | ||
|  | b7f3d6f7f7 | ||
|  | e34577499d | ||
|  | 4cf8960c0c | ||
|  | 1f93ea0675 | ||
|  | 25b705c3a8 | ||
|  | 0725588731 | ||
|  | fc5c61cc8b | ||
|  | ac282e63c6 | ||
|  | c3941941ce | ||
|  | 46cdd53323 | ||
|  | 3ff3e302c3 | ||
|  | f2ceecf95c | ||
|  | 9314c7c881 | ||
|  | 54abb2c572 | ||
|  | 8fa3bdd025 | ||
|  | 5e7a308528 | ||
|  | 7952177786 | ||
|  | 9afbe49c84 | ||
|  | 9f06ba2db3 | ||
|  | fe55bfddcf | ||
|  | c0842e6444 | ||
|  | 3fed20d06a | ||
|  | 5e8f2e2c04 | ||
|  | e4df99ea84 | ||
|  | b3276f5f11 | ||
|  | 32667ca256 | ||
|  | bed122a170 | ||
|  | 14adc9b875 | ||
|  | a8778bbc5a | ||
|  | a54e641f44 | ||
|  | 5c99efe87a | ||
|  | 7da1d731ff | ||
|  | af9828e819 | ||
|  | 7a27136142 | ||
|  | 012ad2d423 | ||
|  | ef3bdbf4da | ||
|  | b3bb698f7b | ||
|  | 1ed5d1e4c1 | ||
|  | bdee01a03d | ||
|  | 458f7376d7 | ||
|  | cb3a00e027 | ||
|  | 482eb1f3fb | ||
|  | 6e0f638f5e | ||
|  | bab349047d | ||
|  | 28ea6b8de8 | ||
|  | 9d51bbdae8 | ||
|  | d622f79533 | ||
|  | 04c8515ad1 | ||
|  | 53bc4251d1 | ||
|  | a5a751f02f | ||
|  | 66ed5f82c4 | ||
|  | c802a9e6aa | ||
|  | 880f210946 | ||
|  | 4f9f7eb6a6 | ||
|  | f910c4a8e7 | ||
|  | 529686d965 | ||
|  | 84dfd1536f | ||
|  | 85dedc324c | ||
|  | d639237411 | ||
|  | 449aaf75f1 | ||
|  | b1fda66caa | ||
|  | 66a8e90fd9 | ||
|  | 37b487d191 | ||
|  | 6c59fe3577 | ||
|  | 1cbb70c992 | ||
|  | e06b39f882 | ||
|  | 2602b1493e | ||
|  | 989d14502d | ||
|  | f78a550282 | ||
|  | 54a1abb284 | ||
|  | 97b492a8e2 | ||
|  | 0873bd14a9 | ||
|  | eff6ba429a | ||
|  | 8c18064be4 | ||
|  | 44a1ac0cf3 | ||
|  | 28dc8d88dd | ||
|  | 2c0c2b64ba | ||
|  | bd3e0f5248 | ||
|  | cd52d98938 | ||
|  | 894c70e7f8 | ||
|  | 51d70c2edd | ||
|  | 7d4b355240 | ||
|  | 3b56193b98 | ||
|  | b16045b57d | ||
|  | 9e8b0fca5b | ||
|  | 35cf1b3b5b | ||
|  | 83f788af57 | ||
|  | 2ffe378d3f | ||
|  | 38b33a4a5e | ||
|  | 60bf9ed0a0 | ||
|  | 16adf4de1b | ||
|  | 80de983023 | ||
|  | 8703ca623f | ||
|  | 286253a73f | ||
|  | bd806a41df | ||
|  | b89c4e9002 | ||
|  | 6dbf31c0c3 | ||
|  | 060c45d8a1 | ||
|  | 33d3e82e4d | ||
|  | 4bb074514d | ||
|  | e3f8892003 | ||
|  | 9d00ad5f18 | ||
|  | dae4344850 | ||
|  | aa7f3fabe2 | ||
|  | f93434a8ce | ||
|  | 25dee56be9 | ||
|  | ce9a3f3797 | ||
|  | 11e384920a | ||
|  | a0a1f1e536 | ||
|  | 3b3d0ea9eb | ||
|  | 2f4d78286d | ||
|  | 677dc6f985 | ||
|  | d52057e732 | ||
|  | fa2a1cb1fb | ||
|  | 19a0fb04ad | ||
|  | 947352f2fe | ||
|  | adcbedb686 | ||
|  | 7732f92acd | ||
|  | ad8a001688 | ||
|  | 9121eada08 | ||
|  | 49bd4d25a2 | ||
|  | d80b4129c6 | ||
|  | 7edb4172d5 | ||
|  | c3a4677990 | ||
|  | 5cbb893a3b | ||
|  | f28a2a432b | ||
|  | 03b75a2d27 | ||
|  | 859fe69083 | ||
|  | f6f2205ddb | ||
|  | 0f9a03ef61 | ||
|  | 9aa417c084 | ||
|  | 7b70952f5d | ||
|  | edd3d07b49 | ||
|  | 5293d0a4ec | ||
|  | 3c8c7beae1 | ||
|  | 9c3ba9fdcd | ||
|  | fb1748fb0f | ||
|  | 0a109fbd03 | ||
|  | 5cf64db74e | ||
|  | 488cc94f36 | ||
|  | e15846bf79 | ||
|  | 752bd00674 | ||
|  | 7fadfcbe32 | ||
|  | 41141e75bb | ||
|  | 50f641e627 | ||
|  | c7883fd093 | ||
|  | 4fcb24b2b1 | ||
|  | 5003557935 | ||
|  | bdf1ba84da | ||
|  | b0b4def983 | ||
|  | cc184bbe9e | ||
|  | ad30c830aa | ||
|  | 1d791a8af4 | ||
|  | e63c51cd97 | ||
|  | f202e32908 | ||
|  | 26e1a08e82 | ||
|  | 4d5119d435 | ||
|  | 75e34ea62e | ||
|  | 0a183d6274 | ||
|  | 21d8060aea | ||
|  | 9cbe906f60 | ||
|  | 8ce4137399 | ||
|  | 5f8a139347 | ||
|  | 9bb009a3fe | ||
|  | 726d65923f | ||
|  | 8a6be4cb2d | ||
|  | 10b06beb8e | ||
|  | 81318c7968 | ||
|  | 47a2c1c6e5 | ||
|  | 39cee65c6b | ||
|  | 8582ec724e | ||
|  | b0139682e8 | ||
|  | d39c475a6d | ||
|  | 48f38354c6 | ||
|  | cd5a920ed5 | ||
|  | 71bc1f378d | ||
|  | 0ee6c31cff | ||
|  | af89a9971e | ||
|  | c718a8ef72 | ||
|  | 8c8ad0faf0 | ||
|  | 314d5bbb7f | ||
|  | 102255757a | ||
|  | 914067a0d0 | ||
|  | 06e3ae2536 | ||
|  | 7f9b252556 | ||
|  | 3d700e243f | ||
|  | bcfc78ce11 | ||
|  | 09241765d5 | ||
|  | 671c83c265 | ||
|  | 772d28b766 | ||
|  | c26fcea58d | ||
|  | 1e5e26dbff | ||
|  | 742fc54864 | ||
|  | 49738f43c0 | ||
|  | 9f85f61010 | ||
|  | 239f422039 | ||
|  | 67af3c37be | ||
|  | a9442385c4 | ||
|  | 8c9cd10b8b | ||
|  | 72542059dd | ||
|  | a843fc6d40 | ||
|  | 4beed60c08 | ||
|  | 4049c1e480 | ||
|  | 8449314da2 | ||
|  | 63ad057028 | ||
|  | e720464330 | ||
|  | 24036afef9 | ||
|  | c78fa1a1bc | ||
|  | faa8b9022c | ||
|  | 729bafef7a | ||
|  | 590b028632 | ||
|  | 8150d00f36 | ||
|  | 060065926f | ||
|  | 70babe8a28 | ||
|  | c36e09664f | ||
|  | a9672246f3 | ||
|  | ff571884e9 | ||
|  | 475138bceb | ||
|  | 4a8af199c2 | ||
|  | bdabf5db72 | ||
|  | 6a5f21b34e | ||
|  | d608be103c | ||
|  | 374bb5d18a | ||
|  | 031d6c25ff | ||
|  | 223fb7b075 | ||
|  | a746741971 | ||
|  | 120faf2a58 | ||
|  | 990bca0dc6 | ||
|  | 3406472db7 | ||
|  | 1bd733c9f6 | ||
|  | 238c7f982e | ||
|  | fcb81147cb | ||
|  | 1915b73783 | ||
|  | ee79e621fb | ||
|  | d203275a3b | ||
|  | 9e8a996222 | ||
|  | 0126b0b3ed | ||
|  | 458928612c | ||
|  | e33f88e28d | ||
|  | be570bbf9e | ||
|  | f59b4be110 | ||
|  | 37336e41be | ||
|  | d24a1a3f0a | ||
|  | f7258955bd | ||
|  | 2a1eae5d6f | ||
|  | 50ee0a4adb | ||
|  | 955a26584e | ||
|  | 1d3e407c8f | ||
|  | cb809c4596 | ||
|  | 53bbe2888e | ||
|  | 7246f476a5 | ||
|  | 0785d1c390 | ||
|  | 85d2c49d14 | ||
|  | 8b77d62b7f | ||
|  | 373058a32a | ||
|  | e6293c2c8c | ||
|  | eff181c959 | ||
|  | 54752c2305 | ||
|  | b4753c044f | ||
|  | 26493424ae | ||
|  | 0282fd1332 | ||
|  | b9a019a08b | ||
|  | 66f6a0e687 | ||
|  | 2dd1b9f97d | ||
|  | 89615f3045 | ||
|  | 7e46192f67 | ||
|  | e78d985cdf | ||
|  | e8c4bf56fe | ||
|  | e6aa7d323d | ||
|  | fca8e25929 | ||
|  | 8e8ac286b4 | ||
|  | 7d9770b9a2 | ||
|  | 1996230460 | ||
|  | de7897a864 | ||
|  | e2884dcdb7 | ||
|  | 544a53a42b | ||
|  | 2e4787bfc8 | ||
|  | 1829eeb171 | ||
|  | c7488e3c4a | ||
|  | 3bf9606383 | ||
|  | 4f43f18f0a | ||
|  | 5b7f197397 | ||
|  | 018141c97f | ||
|  | 4d7813e57c | ||
|  | 605c60208f | ||
|  | 884fafcc30 | ||
|  | 56baa90320 | ||
|  | 6bb20ee09e | ||
|  | 541356430c | ||
|  | 2f4d91fd69 | ||
|  | f58c5e6b30 | ||
|  | 0311d0132c | ||
|  | c946c97402 | ||
|  | 84a6f51318 | ||
|  | 24a1501b0d | ||
|  | 383b6f5fcc | ||
|  | 633dd7ff9b | ||
|  | 580624fad6 | ||
|  | a8190f7efa | ||
|  | dd2157534b | ||
|  | 38a90e7669 | ||
|  | 6bfc526dcd | ||
|  | aadb8a7405 | ||
|  | 27082bf77e | ||
|  | a2903c80cd | ||
|  | 9a77c5369c | ||
|  | 3c30741a19 | ||
|  | 7028ad4ec0 | ||
|  | 8de750c6aa | ||
|  | 04f98de9ee | ||
|  | a1a019784b | ||
|  | 4aeeae77bd | ||
|  | 651cfc2b78 | ||
|  | 2ef8af25e2 | ||
|  | 0b13852a5b | ||
|  | 13427578c9 | ||
|  | d89ca2087e | ||
|  | 8b0ea9fba6 | ||
|  | 9f0b653d5a | ||
|  | 659a339233 | ||
|  | 4c29f177a0 | ||
|  | d664e63d55 | ||
|  | 2493509dbe | ||
|  | 1c8b27f554 | ||
|  | 68297b7186 | ||
|  | 34dd8d0a91 | ||
|  | 81c44790d5 | ||
|  | d557b335cf | ||
|  | e2adc28cff | ||
|  | 0fef6a6ecc | ||
|  | f2fd4b8a1f | ||
|  | 95bd5605a8 | ||
|  | 497cca7eca | ||
|  | 54f78feedd | ||
|  | 76408e53ae | ||
|  | be19e74d30 | ||
|  | dac578a775 | ||
|  | 04732ce74b | ||
|  | a6c95a2374 | ||
|  | f68622abe9 | ||
|  | 83a9a7bdb2 | ||
|  | 6500afc0ca | ||
|  | c69b7ecc96 | ||
|  | 615ef1e2d2 | ||
|  | cf69a0cd7f | ||
|  | 06e892fb33 | ||
|  | e6c5dd6865 | ||
|  | 247efdebdb | ||
|  | 76f3792287 | ||
|  | 64d8e2c727 | ||
|  | ead0bd9cb0 | ||
|  | 66fc13b2ec | ||
|  | f3af4128b0 | ||
|  | 0e43107c87 | ||
|  | 1ee3e7997e | ||
|  | 50fd61d91f | ||
|  | e4cdc051a9 | ||
|  | 778e846e96 | ||
|  | a27759b647 | ||
|  | b75eceab41 | ||
|  | e748a5d5f4 | ||
|  | 99c5a3ae46 | ||
|  | 51da710f5a | ||
|  | 569d69b3d2 | ||
|  | 059a6b1d90 | ||
|  | 990af7548a | ||
|  | a38aefdfc8 | ||
|  | 3bcb12e7d1 | ||
|  | 7904ecb462 | ||
|  | 9ba4d45109 | ||
|  | 56b8afe19d | ||
|  | f7aed9a94c | ||
|  | e12a7e881d | ||
|  | 5afb65325d | ||
|  | 135f520f32 | ||
|  | bc251f4ff6 | ||
|  | b8769751f6 | ||
|  | eff96d839e | ||
|  | aa34c23807 | ||
|  | 195acdac8c | ||
|  | 903e03c56c | ||
|  | 0892767b8a | ||
|  | 83ebfa772c | ||
|  | 1583641322 | ||
|  | 9510e2c256 | ||
|  | a9dbabe07e | ||
|  | 12884008fa | ||
|  | 02543bad1c | ||
|  | a8c56a5251 | ||
|  | 4e5a855f3f | ||
|  | 7e497a951e | ||
|  | cd08eabbfa | ||
|  | f7e62d9f81 | ||
|  | 9a3761e86e | ||
|  | 3619a68693 | ||
|  | efaf3c3bf9 | ||
|  | 0e4e6a6f67 | ||
|  | 42458e6278 | ||
|  | 41ec995377 | ||
|  | 4f37599326 | ||
|  | 4144520e5c | ||
|  | 6c4800546c | ||
|  | 733733c8a7 | ||
|  | 2aa67cc946 | ||
|  | 9385981a9d | ||
|  | fff780035d | ||
|  | 46127e673d | ||
|  | 70df59b224 | ||
|  | 0fdbaa803f | ||
|  | 6af1830eff | ||
|  | 6f860e2bd5 | ||
|  | 20a492f7ee | ||
|  | 63875e7591 | ||
|  | 0ad98cabde | ||
|  | 668879d2e1 | ||
|  | 2e09783302 | ||
|  | 49734114b3 | ||
|  | 950d9d6ee7 | ||
|  | f7974aee2e | ||
|  | c870a82621 | ||
|  | 984929a001 | ||
|  | 7f9e2c1db8 | ||
|  | 324e8389dc | ||
|  | 6f448c5a38 | ||
|  | ec43efbb20 | ||
|  | 3ed065de37 | ||
|  | 8152f0d72c | ||
|  | f8047f4736 | ||
|  | b93c66dc2d | ||
|  | ac877b3065 | ||
|  | dee8abfdde | ||
|  | cef3841d73 | ||
|  | 3cd5e8a041 | ||
|  | 515b5f866e | ||
|  | 321f62bf92 | ||
|  | f94fa47b52 | ||
|  | c502f8a722 | ||
|  | 59b4868ac3 | ||
|  | 3634e12cce | ||
|  | 6d45445391 | ||
|  | 4f47e268cc | ||
|  | 0035b31cdb | ||
|  | f2565aee03 | ||
|  | 5bd85668dd | ||
|  | 20f990b6ce | ||
|  | 6821379586 | ||
|  | 73b040eb49 | ||
|  | 49aa4b2e1e | ||
|  | 972241c74c | ||
|  | 680750e3c2 | ||
|  | 5e7d4d9d15 | ||
|  | 1e57e60613 | ||
|  | 3ac7ce605a | ||
|  | b720dea9f0 | ||
|  | c80722aefe | ||
|  | a84fa69f28 | ||
|  | e33781e59f | ||
|  | 8824bc7ece | ||
|  | c2e3b0e448 | ||
|  | f61a38e85a | ||
|  | d23e948216 | ||
|  | 58bdaa31f0 | ||
|  | b6491d88a6 | ||
|  | f6061ba62e | ||
|  | 427899ddce | ||
|  | c4ab7d2dbd | ||
|  | 0fd2ba033f | ||
|  | ed38939a93 | ||
|  | c7ee26ce5a | ||
|  | 909b8cb303 | ||
|  | b0277370cf | ||
|  | 2ec8656bea | ||
|  | b2ef256910 | ||
|  | 63d6ce95db | ||
|  | a9532b189c | ||
|  | 844545411f | ||
|  | 4e23a2b9b8 | ||
|  | 5deba027eb | ||
|  | fc8b7efc6f | ||
|  | a1c2d9c0f3 | ||
|  | 4ca49a0501 | ||
|  | 493c53d090 | ||
|  | b27e956d35 | ||
|  | 35ebed75c6 | ||
|  | 7bfdb5f77f | ||
|  | 8d8c02317f | ||
|  | a34482feab | ||
|  | cbdc8fd4a6 | ||
|  | 8d3afaa53c | ||
|  | 7ced9ef3df | ||
|  | e8a9ae7e80 | ||
|  | 73a88ab3d3 | ||
|  | aaed82738a | ||
|  | de7f7b96db | ||
|  | 1a669b3e68 | ||
|  | 333af9b13a | ||
|  | a5bca5e240 | ||
|  | c885633e02 | ||
|  | ca7e20b7ca | ||
|  | 545e11a3d7 | ||
|  | 44f5287664 | ||
|  | cf510897f1 | ||
|  | 1d171345f8 | ||
|  | 4fa7e1cd49 | ||
|  | acd008298e | ||
|  | 83a8021515 | ||
|  | cf88dfb1db | ||
|  | 8937c4b481 | ||
|  | cc6af10a4d | ||
|  | 6d94578955 | ||
|  | 08442ab71e | ||
|  | 10d91d213f | ||
|  | b7a3b06994 | ||
|  | 5f12c37f23 | ||
|  | 585edebccd | ||
|  | 9921c62234 | ||
|  | 1ac76d2e16 | ||
|  | 6e983bf400 | ||
|  | 6a8fd4fa6e | ||
|  | 3698eaa2d2 | ||
|  | 8d97ca433c | ||
|  | 23cc65e537 | ||
|  | 2f5a3c2bbe | ||
|  | f6485616cd | ||
|  | 6544fb43d9 | ||
|  | a954b32dcc | ||
|  | 426dc7836c | ||
|  | ff941ffc16 | ||
|  | a063c201df | ||
|  | e2be3fa0aa | ||
|  | 609da6fb50 | ||
|  | fc9f3ccec3 | ||
|  | f7baa67a0a | ||
|  | e8d78c2cdb | ||
|  | 9d33366092 | ||
|  | f5d61515c2 | ||
|  | 711a04a972 | ||
|  | e5b470a3f1 | ||
|  | 31820e1e22 | ||
|  | 4849e8cd6d | ||
|  | 77e3b460aa | ||
|  | b5321001f8 | ||
|  | 38eba9f5ea | ||
|  | ea6f399454 | ||
|  | f8bf2d7b7d | ||
|  | c4856caebb | ||
|  | fc1030bb22 | ||
|  | 9eb6cad8dc | ||
|  | 0fa2a78dce | ||
|  | a56fa1558b | ||
|  | 261c73a997 | ||
|  | 929c1333ca | ||
|  | 286a79d94d | ||
|  | 8b951f99da | ||
|  | abb449bca0 | ||
|  | bd084028d1 | ||
|  | 138a27570b | ||
|  | c2ed40a74f | ||
|  | a7e7a00cab | ||
|  | 64a31ab3cd | ||
|  | 71958bc0f1 | ||
|  | 366ec35612 | ||
|  | 3738f6e8ae | ||
|  | 051a8e2af1 | ||
|  | 2f43f28d5e | ||
|  | b64769754b | ||
|  | a97daa18d1 | ||
|  | b6556dce8b | ||
|  | aa8d8bc8b5 | ||
|  | 0800dcfdc4 | ||
|  | 12b0101e94 | ||
|  | 021b391a02 | ||
|  | d11e2b6057 | ||
|  | 264d90e7e5 | ||
|  | f9f3da9e78 | ||
|  | 6435b49153 | ||
|  | f9aa2941cf | ||
|  | 5a933d4bee | ||
|  | 5536aea0df | ||
|  | 976666d216 | ||
|  | 9a5bcd4392 | ||
|  | 812060a118 | ||
|  | 089b5052e6 | ||
|  | 874e5d72f4 | ||
|  | 6b11de1329 | ||
|  | 2245a7ad8d | ||
|  | ee5ec1b870 | ||
|  | 74ccfe851b | ||
|  | e1c24bd5a2 | ||
|  | 1349b79728 | ||
|  | d294d7604c | ||
|  | 01df2cf464 | ||
|  | 45b7322488 | ||
|  | b3055e992f | ||
|  | 3da548565c | ||
|  | a975e85548 | ||
|  | c4b5ade752 | ||
|  | a4b61b0794 | ||
|  | f6011184b8 | ||
|  | 74de118c6e | ||
|  | 9c25e77c17 | ||
|  | 440113e67e | ||
|  | a11b60c445 | ||
|  | a6052681ad | ||
|  | 482d50536a | ||
|  | 25c79a4fcd | ||
|  | 02946144ac | ||
|  | 71a360e9a3 | ||
|  | f7912d88b1 | ||
|  | 975101d7d2 | ||
|  | ef58c5ff55 | ||
|  | e10221804a | ||
|  | 284ed9ee0e | ||
|  | 5d7b961997 | ||
|  | c699a5c4b4 | ||
|  | 1f4ceb89cf | ||
|  | 0934ca0040 | ||
|  | 4738f892c2 | ||
|  | 33004fcf33 | ||
|  | 34d214c166 | ||
|  | a56cd92a1e | ||
|  | 7251348507 | ||
|  | 01cd5c84d6 | ||
|  | e210599fa6 | ||
|  | dbe7cee7e9 | ||
|  | 7370d88ceb | ||
|  | 34458e0c57 | ||
|  | 05c8c3abf2 | ||
|  | e9d464b4d3 | ||
|  | 6968c3ab9b | ||
|  | 131a8a9650 | ||
|  | 379ecbf9a9 | ||
|  | 7b9dfa9a28 | ||
|  | fbd0f5eed2 | ||
|  | 5970f904ae | ||
|  | 8cbcb2868d | ||
|  | 8ff2a4b026 | ||
|  | ae14d205a5 | ||
|  | ec5d560ec5 | ||
|  | fb543b53c0 | ||
|  | 39c16422e2 | ||
|  | 4d5b273ebe | ||
|  | ed6a860fad | ||
|  | 423e579292 | ||
|  | ee11aa9e75 | ||
|  | c46d20fa92 | ||
|  | dc8d17574c | ||
|  | 5c17cd04c8 | ||
|  | 67ada02076 | ||
|  | 32d94c2eaf | ||
|  | 687b39a12a | ||
|  | 705af407bf | ||
|  | 080052da2e | ||
|  | ef735fd92a | ||
|  | 17c16dcafc | ||
|  | a89b3018fb | ||
|  | 851e2ebd32 | ||
|  | 1225ce7fe8 | ||
|  | 7e77a31b96 | ||
|  | d146b9002f | ||
|  | 1f9d567b23 | ||
|  | ed1b3a023c | ||
|  | 1ca18f501a | ||
|  | 49588ccd98 | ||
|  | 098dedc092 | ||
|  | b06f6b9545 | ||
|  | ba3cb94999 | ||
|  | 74c67fbf4b | ||
|  | 32b46e4910 | ||
|  | ecf5539ed2 | ||
|  | ac9db4e4d5 | ||
|  | 0eb96094b0 | ||
|  | 30b3ac7dc5 | ||
|  | 0092790c7d | ||
|  | 28909d8a51 | ||
|  | b20cfbb7b6 | ||
|  | 97639bd0a8 | ||
|  | 161ec73c96 | ||
|  | 957d6bea15 | ||
|  | f8b6e5b414 | ||
|  | 1ab450870e | ||
|  | de45f4884c | ||
|  | 5da1f3e7c8 | ||
|  | 983014952b | ||
|  | 55298019a3 | ||
|  | a1ffc3f271 | ||
|  | 2fb60aa997 | ||
|  | f5ec76537a | ||
|  | 728491fd2b | ||
|  | d9d3f2b9e4 | ||
|  | 3fe4864f65 | ||
|  | 0b156f22a4 | ||
|  | 35b1d93813 | ||
|  | d770851ac0 | ||
|  | 989e7b1033 | ||
|  | c4e0eb7b49 | ||
|  | 71f5d0dac7 | ||
|  | 561b0c4381 | ||
|  | 995fbc7330 | ||
|  | 10ab8949c4 | ||
|  | c441202fea | ||
|  | ca261b0bee | ||
|  | 52f3709f67 | ||
|  | c2ca6187fe | ||
|  | 671a13d295 | ||
|  | 14c3e2eccf | ||
|  | 08e5b852c2 | ||
|  | 1c9606c824 | ||
|  | 3cd47b5c9b | ||
|  | aedc729087 | ||
|  | 5f7cfa3fa9 | ||
|  | 0083f30af5 | ||
|  | 4a06f05ef5 | ||
|  | 8f37cadce8 | ||
|  | a11603ca6c | ||
|  | 86274842e9 | ||
|  | cf9c955a44 | ||
|  | 55d828c35f | ||
|  | cdff28aca6 | ||
|  | b9da39274f | ||
|  | c379aa5782 | ||
|  | 9dcabac9dd | ||
|  | 794f3a2b9f | ||
|  | 2066121b7c | ||
|  | 0c4067f143 | ||
|  | 8aa69243b7 | ||
|  | 8697263bde | ||
|  | ea25c4f65c | ||
|  | 82ac3ebd7e | ||
|  | 13cb94909c | ||
|  | b57ca2a763 | ||
|  | 83c49e9745 | ||
|  | e15771d78d | ||
|  | 6edc4920ba | ||
|  | 302bb1bd93 | ||
|  | 529b1bceee | ||
|  | 42cd47d32e | ||
|  | 711d884c2e | ||
|  | 183d1c4674 | ||
|  | faed63a0bb | ||
|  | 53bff262f8 | ||
|  | 3251a708e4 | ||
|  | b5dbdbf7b2 | ||
|  | a9649e92c9 | ||
|  | b561f1fa8b | ||
|  | cecd7491b5 | ||
|  | 55a66322b5 | ||
|  | 155c31a2d7 | ||
|  | a89ce91089 | ||
|  | b897fe6700 | ||
|  | 548a351b06 | ||
|  | 4b1da57ca1 | ||
|  | 529aec7f25 | ||
|  | 1661e545cb | ||
|  | ec71d08878 | ||
|  | ac258b7dd7 | ||
|  | 0f57876233 | ||
|  | 1d25a3693d | ||
|  | 45fa428bf1 | ||
|  | 177fa80f1a | ||
|  | 3261261bfe | ||
|  | d4de7934f8 | ||
|  | c3475af809 | ||
|  | b12f707812 | ||
|  | 22c0c34d60 | ||
|  | a60b66f230 | ||
|  | 83f6e93628 | ||
|  | 222b5f0229 | ||
|  | 30aa383e26 | ||
|  | 676b401294 | ||
|  | ebf57159de | ||
|  | 199d2aafec | ||
|  | 81952f56fd | ||
|  | c5bac82b43 | ||
|  | 081b86109c | ||
|  | 8ac2028a75 | ||
|  | 264fed1c9f | ||
|  | dd59f7b2c7 | ||
|  | 9245a760db | ||
|  | b61b32bbc3 | ||
|  | 09b3914f5d | ||
|  | fe644e4c9e | ||
|  | 7b09bf2156 | ||
|  | 987d0aae66 | ||
|  | 9cbcbc1c22 | ||
|  | cfc4e2bc60 | ||
|  | a03405fa81 | ||
|  | d5c9ccbe6e | ||
|  | e52772d65f | ||
|  | 1e3259e728 | ||
|  | e905a20a60 | ||
|  | 88e2be7a33 | ||
|  | 8939131600 | ||
|  | ba37ebff8b | ||
|  | 28f4cb7e07 | ||
|  | db1e7102cd | ||
|  | 07eb7a5830 | ||
|  | b7c6c685fa | ||
|  | 212134df70 | ||
|  | 6eeb5528f5 | ||
|  | 54fad845c9 | ||
|  | d6c0de6fc7 | ||
|  | 649c8649f7 | ||
|  | da2f53d1b1 | ||
|  | 405139e3b8 | ||
|  | 4f8d347171 | ||
|  | bf0db4876c | ||
|  | 47a14884d6 | ||
|  | 3a7bbc8b08 | ||
|  | 1b1d65372c | ||
|  | fd2faaa16e | ||
|  | 0609cdb9ea | ||
|  | d3bb140f89 | ||
|  | b31dc66628 | ||
|  | 09476171a6 | ||
|  | 33dee813b5 | ||
|  | bb4e73c40b | ||
|  | b1f23ffa94 | ||
|  | b0e8cec1e7 | ||
|  | 5077ae19bc | ||
|  | 0d8447bf59 | ||
|  | c6cf08a274 | ||
|  | dc49ae519e | ||
|  | 904539476a | ||
|  | 3fbf02dc82 | ||
|  | c9392a840d | ||
|  | d164e8ab72 | ||
|  | 6dc62c9fb6 | ||
|  | 87a9684d66 | ||
|  | 94525e2f44 | ||
|  | b408b1b3b9 | ||
|  | 27c2f09e32 | ||
|  | 19bc4d3349 | ||
|  | f2b6c424d6 | ||
|  | a49d4453e9 | ||
|  | 65e50087b9 | ||
|  | 2d90f759d9 | ||
|  | 4230ac7674 | ||
|  | d96e9182e9 | ||
|  | 68c87b9616 | ||
|  | 7f8e9a0b6d | ||
|  | 81a229f2a5 | ||
|  | 8be7ae2733 | ||
|  | 846bca4cb1 | ||
|  | f36f353789 | ||
|  | 939a2731ed | ||
|  | 835dab97ff | ||
|  | fa904b53be | ||
|  | 0ec52dddce | ||
|  | c289355a3a | ||
|  | 02a13a5a18 | ||
|  | 6cf2a0281b | ||
|  | 120d35f9af | ||
|  | 2b15d5e7b3 | ||
|  | fc167bd3f0 | ||
|  | 91b04abf05 | ||
|  | 77faac8740 | ||
|  | 43b3d54855 | ||
|  | 69e9b85700 | ||
|  | 0b6d132759 | ||
|  | 7c233c6c0c | ||
|  | c35b290fa4 | ||
|  | 3d95cfb367 | ||
|  | b90fc3a56e | ||
|  | 1ef3fdccf5 | ||
|  | 02b7f77bd8 | ||
|  | 0ac7ead922 | ||
|  | da9d0e03ce | ||
|  | 120f65f672 | ||
|  | 200a14caa4 | ||
|  | 35bf6da8e2 | ||
|  | f08f70276c | ||
|  | 1ae50fd95b | ||
|  | 40512beb47 | ||
|  | 0d7f9b2c94 | ||
|  | 52f42140a7 | ||
|  | 3f6c50297f | ||
|  | f72d80afc5 | ||
|  | 7c5cb13b22 | ||
|  | d728750eb2 | ||
|  | 02a70e5667 | ||
|  | 44e51ea5fa | ||
|  | 87e201460a | ||
|  | 039bd945e2 | ||
|  | e9e52d2b4b | ||
|  | 2bf92e7399 | ||
|  | 5b0df241f0 | ||
|  | 76f5b05eff | ||
|  | 40fb6c998f | ||
|  | 33f50a342d | ||
|  | 81523ab68a | ||
|  | 2bf8cc62cf | ||
|  | 1ae8247af3 | ||
|  | 5ef32227ec | ||
|  | 6456e773bd | ||
|  | 234fe53ca3 | ||
|  | 7c93e7a7b3 | ||
|  | 8afc6c7f4b | ||
|  | 4609d0fa3a | ||
|  | d452c035c6 | ||
|  | 45113c8f5a | ||
|  | 0acdd3c62b | ||
|  | 96d7d0a33e | ||
|  | b6b280267b | ||
|  | 6e6d253b1a | ||
|  | d92c105db2 | ||
|  | 906db728d6 | ||
|  | c4b7411565 | ||
|  | de06396046 | ||
|  | ee6bfeb8e3 | ||
|  | 058347321f | ||
|  | feefe49324 | ||
|  | 187381a9a2 | ||
|  | 993dfa4368 | ||
|  | 7e35a16440 | ||
|  | e4eeb15926 | ||
|  | 634e0db26d | ||
|  | 56855c23e1 | ||
|  | 0b00f742e3 | ||
|  | b7ab3f673c | ||
|  | be04ea1e35 | ||
|  | 1f8e695802 | ||
|  | 2d82b2c64f | ||
|  | d076caf473 | ||
|  | c7abdefa31 | ||
|  | ba772c0bca | ||
|  | 5bad234119 | ||
|  | c7e7baaf23 | ||
|  | 36658a671b | ||
|  | 045f2e10ba | ||
|  | fb5a7db66d | ||
|  | ba7d33982e | ||
|  | c62279a755 | ||
|  | 17fa1a7ffb | ||
|  | e89ceac351 | ||
|  | 0b8c30c109 | ||
|  | 9ab0f463cc | ||
|  | 6433dda7b8 | ||
|  | fa7a2f4be4 | ||
|  | ba90e16505 | ||
|  | 008f710203 | ||
|  | df2740f126 | ||
|  | 2db89d143e | ||
|  | 0525d49da3 | ||
|  | e2b0745882 | ||
|  | 92e804fc50 | ||
|  | 67abf45576 | ||
|  | d2c9c814e7 | ||
|  | 22f8881a64 | ||
|  | 4ab20322fe | ||
|  | 5370eeecea | ||
|  | ba71cb5dd7 | ||
|  | 9aad6c2c52 | ||
|  | 4d9627f20c | ||
|  | c142492e91 | ||
|  | 6bf8d9e207 | ||
|  | 4f9a6168c1 | ||
|  | 38397f99aa | ||
|  | f8686d0e75 | ||
|  | 549e3c8f9d | ||
|  | bb56225b95 | ||
|  | f00be261ba | ||
|  | 9cd94f26d0 | ||
|  | 4d8f5c80a7 | ||
|  | 24a23acc3d | ||
|  | ca8703cfd8 | ||
|  | 6dcbb5b2f8 | ||
|  | a84fdddb2a | ||
|  | 38bb2f8ceb | ||
|  | 23f5ef4345 | ||
|  | ef8a2a9054 | ||
|  | 96103d0e36 | ||
|  | ff5f6748df | ||
|  | 1c1fd6c366 | ||
|  | 32d37d00cb | ||
|  | 82f6cda966 | ||
|  | f1ff8ff0d0 | ||
|  | 756c72902f | ||
|  | 73f8f0bbd0 | ||
|  | 18ed528f5d | ||
|  | 8fd2f136bc | ||
|  | 0524b1bf67 | ||
|  | 15716f65ce | ||
|  | d46bdba332 | ||
|  | 760728110a | ||
|  | 12d0a194ca | ||
|  | 4104543508 | ||
|  | 5c211db015 | ||
|  | 2dc6180f8d | ||
|  | e222a34b69 | ||
|  | ef17d95063 | ||
|  | 853502e5d7 | ||
|  | c18e297e77 | ||
|  | c5a49599ba | ||
|  | df9da9edf5 | ||
|  | e2200fd050 | ||
|  | c6207f5d9c | ||
|  | 4302b7ff6b | ||
|  | 50a7923438 | ||
|  | ab416445c8 | ||
|  | a54698d43c | ||
|  | c5a77cc1c0 | ||
|  | a9ffa811fc | ||
|  | 080a2608e0 | ||
|  | 57f2e83d6a | ||
|  | 5b030139d3 | ||
|  | 0da1ff42d1 | ||
|  | 2c599b7baa | ||
|  | 5c8af8d21a | ||
|  | 026f3cfde2 | ||
|  | f6349180e8 | ||
|  | aa6421921c | ||
|  | 7d41d2dab2 | ||
|  | f0b4d18f93 | ||
|  | 6750f06e10 | ||
|  | b2bd38fa9e | ||
|  | 3482a01e22 | ||
|  | 6335467552 | ||
|  | 4a39e65b62 | ||
|  | c50a23e918 | ||
|  | 1e76b72b98 | ||
|  | b94cf39eef | ||
|  | fef254ffff | ||
|  | e5495863a2 | ||
|  | 3b4df2abf0 | ||
|  | aef2aee6a4 | ||
|  | d0d9519149 | ||
|  | 685df1d2c5 | ||
|  | 08e6b6f2e7 | ||
|  | 66c887d0f3 | ||
|  | 22e9960697 | ||
|  | 64aa6e1f2d | ||
|  | 7a93ed9d04 | ||
|  | a905e922e9 | ||
|  | f9f08fc720 | ||
|  | 8d402d76d0 | ||
|  | 46fda6281c | ||
|  | a14dbe1ea6 | ||
|  | 18810a4c16 | ||
|  | 147bc80dba | ||
|  | c7a484195a | ||
|  | 4968eb6503 | ||
|  | a6f2d698a9 | ||
|  | ea5ed93ea5 | ||
|  | e1140134c6 | ||
|  | 5ed11e012e | ||
|  | 5380bd39ca | ||
|  | 2ee2685688 | ||
|  | 782002245b | ||
|  | 7fc0905843 | ||
|  | 72ecb99e54 | ||
|  | c863507d08 | ||
|  | cff86c9093 | ||
|  | 0479dfcc54 | ||
|  | 68dd67f21c | ||
|  | 540f6858b5 | ||
|  | b61e791a4f | ||
|  | d0986f9482 | ||
|  | 112cb0dc28 | ||
|  | 0d3d7fdcf2 | ||
|  | 5d6b89ef3b | ||
|  | ed0b26c09e | ||
|  | ae292bd920 | ||
|  | 6c85a90723 | ||
|  | 852592066c | ||
|  | 96e1bc9b44 | ||
|  | b41d81ed31 | ||
|  | e241ec2244 | ||
|  | 16e1f1a94c | ||
|  | 7a68c42b26 | ||
|  | 37ccc2e118 | ||
|  | 4192fe1ab2 | ||
|  | d5c743d7bb | ||
|  | 11814d63e8 | ||
|  | b753656d50 | ||
|  | f7e87611fc | ||
|  | 1fb0e1900e | ||
|  | 954a9731e0 | ||
|  | 65c3364ad8 | ||
|  | 3d72b7dccc | ||
|  | 13ee569f06 | ||
|  | d79ef23a75 | ||
|  | 5d0797d4ba | ||
|  | 47a8d7475f | ||
|  | 4939053121 | ||
|  | b525bf554e | ||
|  | f00285d2b2 | ||
|  | 040f8d6eda | ||
|  | 66d905325c | ||
|  | 8b0cd95e73 | ||
|  | d867cca6d9 | ||
|  | a28f736369 | ||
|  | 5c3a71cc59 | ||
|  | cef6dadb08 | ||
|  | 36be817a3e | ||
|  | 02f571f081 | ||
|  | 157159e487 | ||
|  | 02ada9f800 | ||
|  | 6fcf9a97bb | ||
|  | 17a5d8799f | ||
|  | 31f3fe7a22 | ||
|  | 89e46d3d83 | ||
|  | 885795e67d | ||
|  | 92bfb53dd4 | ||
|  | 4cecbeb115 | ||
|  | 5971480f55 | ||
|  | 05bebea511 | ||
|  | 76fa6c5cfb | ||
|  | 633b68b518 | ||
|  | 6913d8e995 | ||
|  | f3654e6f8d | ||
|  | d685dbcf22 | ||
|  | 6a57fa079e | ||
|  | 0a91d145ba | ||
|  | c2866e799d | ||
|  | d8cffcaae7 | ||
|  | 30abca7be2 | ||
|  | edce87f3fb | ||
|  | 66bac98fc2 | ||
|  | 59156de92b | ||
|  | e0d7d10600 | ||
|  | daaf862257 | ||
|  | 9de53d4b59 | ||
|  | f1571e2d46 | ||
|  | bd28d06298 | ||
|  | a24e4655eb | ||
|  | 20a6c8d8e5 | ||
|  | 98d264faf4 | ||
|  | 321902a9b5 | ||
|  | 8df5d06f9a | ||
|  | e69ea529cc | ||
|  | 15405b1119 | ||
|  | d2f97ce2da | ||
|  | 543ca631e9 | ||
|  | f184886db1 | ||
|  | 8432ab4324 | ||
|  | 6c05b37ca3 | ||
|  | 35f4beeb47 | ||
|  | cbad7caa68 | ||
|  | b0388a4012 | ||
|  | df3fab4d55 | ||
|  | da49f88a03 | ||
|  | e28feceb06 | ||
|  | 50496a164d | ||
|  | 6f1dce1572 | ||
|  | 6847776ae7 | ||
|  | 67bd53bdd8 | ||
|  | e735abfdfd | ||
|  | 1de93a2d6d | ||
|  | 36f9e7c742 | ||
|  | 9462763bbb | ||
|  | 4ae0880ea6 | ||
|  | 6ae2b6c835 | ||
|  | a0f180fd48 | ||
|  | bf1cf89914 | ||
|  | 297a047fb4 | ||
|  | 52ffc15ffc | ||
|  | e478c9c693 | ||
|  | d004f28074 | ||
|  | bc68ed8b1d | ||
|  | 04555ae650 | ||
|  | e8f62085be | ||
|  | f430bffe2a | ||
|  | 1f0520634f | ||
|  | 902d4c31fb | ||
|  | 17364ac09f | ||
|  | 0b889f8f81 | ||
|  | 40e349ff35 | ||
|  | c943b1b1df | ||
|  | 912bc1d4e1 | ||
|  | cacb1533a3 | ||
|  | f0feaca9d7 | ||
|  | b6656f171b | ||
|  | 6206ab3931 | ||
|  | c35fc58b1f | ||
|  | deed8abed7 | ||
|  | 7151ad23f0 | ||
|  | 0166d938af | ||
|  | 6194aeddb0 | ||
|  | 903dbf2c30 | ||
|  | 9380f9ff57 | ||
|  | 259ed95486 | ||
|  | 2ebc92681e | ||
|  | 195a1ffe13 | ||
|  | a8c2978185 | ||
|  | 140f97a457 | ||
|  | 7f94445a1e | ||
|  | 82a89aec65 | ||
|  | 7e95110232 | ||
|  | ec4aaaad89 | ||
|  | 1b790fde24 | ||
|  | aaccea731e | ||
|  | 29e31d7610 | ||
|  | aa51f4a98f | ||
|  | e6ccd12f00 | ||
|  | b134315df1 | ||
|  | 7f34dffa13 | ||
|  | fa239e78c9 | ||
|  | 707a6c4d6a | ||
|  | e5da303b43 | ||
|  | 84ccd66331 | ||
|  | ad8cc2baea | ||
|  | 7c4cf70309 | ||
|  | c3211e9b4f | ||
|  | 268d94c983 | ||
|  | 0bcacbba58 | ||
|  | 8cdc26add9 | ||
|  | e0b2238886 | ||
|  | 369a2e4029 | ||
|  | c4089e3b51 | ||
|  | 9e2e9bc5b8 | ||
|  | a9e44426ed | 
							
								
								
									
										27
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,27 +0,0 @@ | ||||
| *.5 | ||||
| *.8 | ||||
| *.a | ||||
| *.d | ||||
| *.o | ||||
| *.pc | ||||
| *.pot | ||||
| *.so | ||||
| *.so.* | ||||
| *.swp | ||||
| *~ | ||||
|  | ||||
| .export.sym | ||||
| .exported_symbols_generated | ||||
| .gdb_history | ||||
|  | ||||
| Makefile | ||||
| make.tmpl | ||||
|  | ||||
| configure.h | ||||
| version.h | ||||
|  | ||||
| /autom4te.cache/ | ||||
| /config.log | ||||
| /config.status | ||||
| /cscope.out | ||||
| /tmp/ | ||||
							
								
								
									
										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. | ||||
|  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
| 		  GNU LIBRARY GENERAL PUBLIC LICENSE | ||||
| 		       Version 2, June 1991 | ||||
|  | ||||
|  Copyright (C) 1991 Free Software Foundation, Inc. | ||||
|  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
| [This is the first released version of the Lesser GPL.  It also counts | ||||
|  as the successor of the GNU Library Public License, version 2, hence | ||||
|  the version number 2.1.] | ||||
| [This is the first released version of the library GPL.  It is | ||||
|  numbered 2 because it goes with version 2 of the ordinary GPL.] | ||||
|  | ||||
| 			    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 | ||||
| free software--to make sure the software is free for all its users. | ||||
|  | ||||
|   This license, the Lesser General Public License, applies to some | ||||
| specially designated software packages--typically libraries--of the | ||||
| Free Software Foundation and other authors who decide to use it.  You | ||||
| can use it too, but we suggest you first think carefully about whether | ||||
| this license or the ordinary General Public License is the better | ||||
| strategy to use in any particular case, based on the explanations below. | ||||
|   This license, the Library General Public License, applies to some | ||||
| specially designated Free Software Foundation software, and to any | ||||
| other libraries whose authors decide to use it.  You can use it for | ||||
| your libraries, too. | ||||
|  | ||||
|   When we speak of free software, we are referring to freedom of use, | ||||
| not price.  Our General Public Licenses are designed to make sure that | ||||
| you have the freedom to distribute copies of free software (and charge | ||||
| for this service if you wish); that you receive source code or can get | ||||
| it if you want it; that you can change the software and use pieces of | ||||
| it in new free programs; and that you are informed that you can do | ||||
| these things. | ||||
|   When we speak of free software, we are referring to freedom, not | ||||
| price.  Our General Public Licenses are designed to make sure that you | ||||
| have the freedom to distribute copies of free software (and charge for | ||||
| this service if you wish), that you receive source code or can get it | ||||
| if you want it, that you can change the software or use pieces of it | ||||
| in new free programs; and that you know you can do these things. | ||||
|  | ||||
|   To protect your rights, we need to make restrictions that forbid | ||||
| distributors to deny you these rights or to ask you to surrender these | ||||
| rights.  These restrictions translate to certain responsibilities for | ||||
| you if you distribute copies of the library or if you modify it. | ||||
| anyone to deny you these rights or to ask you to surrender the rights. | ||||
| These restrictions translate to certain responsibilities for you if | ||||
| you distribute copies of the library, or if you modify it. | ||||
|  | ||||
|   For example, if you distribute copies of the library, whether gratis | ||||
| or for a fee, you must give the recipients all the rights that we gave | ||||
| you.  You must make sure that they, too, receive or can get the source | ||||
| code.  If you link other code with the library, you must provide | ||||
| complete object files to the recipients, so that they can relink them | ||||
| with the library after making changes to the library and recompiling | ||||
| code.  If you link a program with the library, you must provide | ||||
| complete object files to the recipients so that they can relink them | ||||
| with the library, after making changes to the library and recompiling | ||||
| it.  And you must show them these terms so they know their rights. | ||||
|  | ||||
|   We protect your rights with a two-step method: (1) we copyright the | ||||
| library, and (2) we offer you this license, which gives you legal | ||||
|   Our method of protecting your rights has two steps: (1) copyright | ||||
| the library, and (2) offer you this license which gives you legal | ||||
| permission to copy, distribute and/or modify the library. | ||||
|  | ||||
|   To protect each distributor, we want to make it very clear that | ||||
| there is no warranty for the free library.  Also, if the library is | ||||
| modified by someone else and passed on, the recipients should know | ||||
| that what they have is not the original version, so that the original | ||||
| author's reputation will not be affected by problems that might be | ||||
| introduced by others. | ||||
|   Also, for each distributor's protection, we want to make certain | ||||
| that everyone understands that there is no warranty for this free | ||||
| library.  If the library is modified by someone else and passed on, we | ||||
| want its recipients to know that what they have is not the original | ||||
| version, so that any problems introduced by others will not reflect on | ||||
| the original authors' reputations. | ||||
|  | ||||
|   Finally, software patents pose a constant threat to the existence of | ||||
| any free program.  We wish to make sure that a company cannot | ||||
| effectively restrict the users of a free program by obtaining a | ||||
| restrictive license from a patent holder.  Therefore, we insist that | ||||
| any patent license obtained for a version of the library must be | ||||
| consistent with the full freedom of use specified in this license. | ||||
|   Finally, any free program is threatened constantly by software | ||||
| patents.  We wish to avoid the danger that companies distributing free | ||||
| software will individually obtain patent licenses, thus in effect | ||||
| transforming the program into proprietary software.  To prevent this, | ||||
| we have made it clear that any patent must be licensed for everyone's | ||||
| free use or not licensed at all. | ||||
|  | ||||
|   Most GNU software, including some libraries, is covered by the | ||||
| ordinary GNU General Public License.  This license, the GNU Lesser | ||||
| General Public License, applies to certain designated libraries, and | ||||
| is quite different from the ordinary General Public License.  We use | ||||
| this license for certain libraries in order to permit linking those | ||||
| libraries into non-free programs. | ||||
|   Most GNU software, including some libraries, is covered by the ordinary | ||||
| GNU General Public License, which was designed for utility programs.  This | ||||
| license, the GNU Library General Public License, applies to certain | ||||
| designated libraries.  This license is quite different from the ordinary | ||||
| one; be sure to read it in full, and don't assume that anything in it is | ||||
| the same as in the ordinary license. | ||||
|  | ||||
|   When a program is linked with a library, whether statically or using | ||||
| a shared library, the combination of the two is legally speaking a | ||||
| combined work, a derivative of the original library.  The ordinary | ||||
| General Public License therefore permits such linking only if the | ||||
| entire combination fits its criteria of freedom.  The Lesser General | ||||
| Public License permits more lax criteria for linking other code with | ||||
| the library. | ||||
|   The reason we have a separate public license for some libraries is that | ||||
| they blur the distinction we usually make between modifying or adding to a | ||||
| program and simply using it.  Linking a program with a library, without | ||||
| changing the library, is in some sense simply using the library, and is | ||||
| analogous to running a utility program or application program.  However, in | ||||
| a textual and legal sense, the linked executable is a combined work, a | ||||
| derivative of the original library, and the ordinary General Public License | ||||
| treats it as such. | ||||
|  | ||||
|   We call this license the "Lesser" General Public License because it | ||||
| does Less to protect the user's freedom than the ordinary General | ||||
| Public License.  It also provides other free software developers Less | ||||
| of an advantage over competing non-free programs.  These disadvantages | ||||
| are the reason we use the ordinary General Public License for many | ||||
| libraries.  However, the Lesser license provides advantages in certain | ||||
| special circumstances. | ||||
|   Because of this blurred distinction, using the ordinary General | ||||
| Public License for libraries did not effectively promote software | ||||
| sharing, because most developers did not use the libraries.  We | ||||
| concluded that weaker conditions might promote sharing better. | ||||
|  | ||||
|   For example, on rare occasions, there may be a special need to | ||||
| encourage the widest possible use of a certain library, so that it becomes | ||||
| a de-facto standard.  To achieve this, non-free programs must be | ||||
| allowed to use the library.  A more frequent case is that a free | ||||
| library does the same job as widely used non-free libraries.  In this | ||||
| case, there is little to gain by limiting the free library to free | ||||
| software only, so we use the Lesser General Public License. | ||||
|  | ||||
|   In other cases, permission to use a particular library in non-free | ||||
| programs enables a greater number of people to use a large body of | ||||
| free software.  For example, permission to use the GNU C Library in | ||||
| non-free programs enables many more people to use the whole GNU | ||||
| operating system, as well as its variant, the GNU/Linux operating | ||||
| system. | ||||
|  | ||||
|   Although the Lesser General Public License is Less protective of the | ||||
| users' freedom, it does ensure that the user of a program that is | ||||
| linked with the Library has the freedom and the wherewithal to run | ||||
| that program using a modified version of the Library. | ||||
|   However, unrestricted linking of non-free programs would deprive the | ||||
| users of those programs of all benefit from the free status of the | ||||
| libraries themselves.  This Library General Public License is intended to | ||||
| permit developers of non-free programs to use free libraries, while | ||||
| preserving your freedom as a user of such programs to change the free | ||||
| libraries that are incorporated in them.  (We have not seen how to achieve | ||||
| this as regards changes in header files, but we have achieved it as regards | ||||
| changes in the actual functions of the Library.)  The hope is that this | ||||
| will lead to faster development of free libraries. | ||||
|  | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow.  Pay close attention to the difference between a | ||||
| "work based on the library" and a "work that uses the library".  The | ||||
| former contains code derived from the library, whereas the latter must | ||||
| be combined with the library in order to run. | ||||
| former contains code derived from the library, while the latter only | ||||
| works together with the library. | ||||
|  | ||||
|   Note that it is possible for a library to be covered by the ordinary | ||||
| General Public License rather than by this special one. | ||||
|  | ||||
| 		  GNU LESSER GENERAL PUBLIC LICENSE | ||||
| 		  GNU LIBRARY GENERAL PUBLIC LICENSE | ||||
|    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||||
|  | ||||
|   0. This License Agreement applies to any software library or other | ||||
| program which contains a notice placed by the copyright holder or | ||||
| other authorized party saying it may be distributed under the terms of | ||||
| this Lesser General Public License (also called "this License"). | ||||
| Each licensee is addressed as "you". | ||||
|   0. This License Agreement applies to any software library which | ||||
| contains a notice placed by the copyright holder or other authorized | ||||
| party saying it may be distributed under the terms of this Library | ||||
| General Public License (also called "this License").  Each licensee is | ||||
| addressed as "you". | ||||
|  | ||||
|   A "library" means a collection of software functions and/or data | ||||
| 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, | ||||
| 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 | ||||
| work containing portions of the Library, and distribute that work | ||||
| 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 | ||||
|     to use the modified definitions.) | ||||
|  | ||||
|     b) Use a suitable shared library mechanism for linking with the | ||||
|     Library.  A suitable mechanism is one that (1) uses at run time a | ||||
|     copy of the library already present on the user's computer system, | ||||
|     rather than copying library functions into the executable, and (2) | ||||
|     will operate properly with a modified version of the library, if | ||||
|     the user installs one, as long as the modified version is | ||||
|     interface-compatible with the version that the work was made with. | ||||
|  | ||||
|     c) Accompany the work with a written offer, valid for at | ||||
|     b) Accompany the work with a written offer, valid for at | ||||
|     least three years, to give the same user the materials | ||||
|     specified in Subsection 6a, above, for a charge no more | ||||
|     than the cost of performing this distribution. | ||||
|  | ||||
|     d) If distribution of the work is made by offering access to copy | ||||
|     c) If distribution of the work is made by offering access to copy | ||||
|     from a designated place, offer equivalent access to copy the above | ||||
|     specified materials from the same place. | ||||
|  | ||||
|     e) Verify that the user has already received a copy of these | ||||
|     d) Verify that the user has already received a copy of these | ||||
|     materials or that you have already sent this user a copy. | ||||
|  | ||||
|   For an executable, the required form of the "work that uses the | ||||
| Library" must include any data and utility programs needed for | ||||
| reproducing the executable from it.  However, as a special exception, | ||||
| the materials to be distributed need not include anything that is | ||||
| normally distributed (in either source or binary form) with the major | ||||
| the source code distributed need not include anything that is normally | ||||
| distributed (in either source or binary form) with the major | ||||
| components (compiler, kernel, and so on) of the operating system on | ||||
| which the executable runs, unless that component itself accompanies | ||||
| the executable. | ||||
| @@ -368,7 +348,7 @@ Library), the recipient automatically receives a license from the | ||||
| original licensor to copy, distribute, link with or modify the Library | ||||
| subject to these terms and conditions.  You may not impose any further | ||||
| restrictions on the recipients' exercise of the rights granted herein. | ||||
| You are not responsible for enforcing compliance by third parties with | ||||
| You are not responsible for enforcing compliance by third parties to | ||||
| this License. | ||||
|  | ||||
|   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. | ||||
|  | ||||
|   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, | ||||
| but may differ in detail to address new problems or concerns. | ||||
|  | ||||
| @@ -457,7 +437,7 @@ DAMAGES. | ||||
|  | ||||
| 		     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 | ||||
| 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> | ||||
|  | ||||
|     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 | ||||
|     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, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|     Lesser General Public License for more details. | ||||
|     Library General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public | ||||
|     License along with this library; if not, write to the Free Software | ||||
|     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|     You should have received a copy of the GNU Library General Public | ||||
|     License along with this library; if not, write to the Free | ||||
|     Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | ||||
|     MA 02111-1307, USA | ||||
|  | ||||
| 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 | ||||
|  | ||||
| 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. | ||||
|  | ||||
|    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: | ||||
|      ./configure --with-lvm1=none  | ||||
|  | ||||
|    To separate the LVM1 support into a shared library loaded by lvm.conf use: | ||||
|      ./configure --with-lvm1=shared | ||||
|  | ||||
|    Use ./configure --help to see other options. | ||||
|  | ||||
| 2) Build and install. | ||||
| 3) Build and install LVM2. | ||||
|  | ||||
|    Run 'make' from the top directory to build everything you configured. | ||||
|    Run 'make install' to build and install everything you configured. | ||||
|    Run 'make install' from the top directory. | ||||
|  | ||||
|    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 | ||||
|    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  | ||||
| individual commands. | ||||
|   | ||||
							
								
								
									
										176
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								Makefile.in
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | ||||
| # | ||||
| # Copyright (C) 2001-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 the LVM2. | ||||
| # | ||||
| # This copyrighted material is made available to anyone wishing to use, | ||||
| # modify, copy, or redistribute it subject to the terms and conditions | ||||
| @@ -14,173 +14,57 @@ | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| VPATH = @srcdir@ | ||||
|  | ||||
| SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools | ||||
|  | ||||
| ifeq ("@UDEV_RULES@", "yes") | ||||
|   SUBDIRS += udev | ||||
| endif | ||||
| SUBDIRS = doc include man scripts | ||||
|  | ||||
| ifeq ("@INTL@", "yes") | ||||
|   SUBDIRS += po | ||||
| endif | ||||
|  | ||||
| ifeq ("@APPLIB@", "yes") | ||||
|   SUBDIRS += liblvm | ||||
| SUBDIRS += lib tools daemons | ||||
|  | ||||
| ifeq ("@DMEVENTD@", "yes") | ||||
|   SUBDIRS += dmeventd | ||||
| endif | ||||
|  | ||||
| ifeq ("@PYTHON_BINDINGS@", "yes") | ||||
|   SUBDIRS += python | ||||
| endif | ||||
|  | ||||
| ifeq ($(MAKECMDGOALS),clean) | ||||
|   SUBDIRS += test | ||||
| endif | ||||
| # FIXME Should use intermediate Makefiles here! | ||||
| ifeq ($(MAKECMDGOALS),distclean) | ||||
|   SUBDIRS = conf include man test scripts \ | ||||
|     libdaemon lib tools daemons libdm \ | ||||
|     udev po liblvm python \ | ||||
|     unit-tests/datastruct unit-tests/mm unit-tests/regex | ||||
| tools.distclean: test.distclean | ||||
|   SUBDIRS += daemons/clvmd \ | ||||
| 	     dmeventd \ | ||||
| 	     lib/format1 \ | ||||
| 	     lib/format_pool \ | ||||
| 	     lib/locking \ | ||||
| 	     lib/mirror \ | ||||
| 	     lib/snapshot \ | ||||
| 	     po \ | ||||
| 	     test/mm test/device test/format1 test/regex test/filters | ||||
|   DISTCLEAN_TARGETS += lib/misc/configure.h | ||||
| endif | ||||
| DISTCLEAN_DIRS += lcov_reports* | ||||
| DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl | ||||
|  | ||||
| include make.tmpl | ||||
|  | ||||
| libdm: include | ||||
| libdaemon: include | ||||
| lib: libdm libdaemon | ||||
| liblvm: lib | ||||
| daemons: lib libdaemon tools | ||||
| 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 | ||||
| daemons: lib | ||||
| lib: include | ||||
| tools: lib | ||||
| dmeventd: tools | ||||
| po: tools daemons dmeventd | ||||
|  | ||||
| ifeq ("@INTL@", "yes") | ||||
| lib.pofile: include.pofile | ||||
| tools.pofile: lib.pofile | ||||
| daemons.pofile: lib.pofile | ||||
| po.pofile: tools.pofile daemons.pofile | ||||
| dmeventd.pofile: tools.pofile | ||||
| po.pofile: tools.pofile daemons.pofile dmeventd.pofile | ||||
| pofile: po.pofile | ||||
| endif | ||||
|  | ||||
| ifeq ("@PYTHON_BINDINGS@", "yes") | ||||
| python: liblvm | ||||
| endif | ||||
|  | ||||
| ifneq ("$(CFLOW_CMD)", "") | ||||
| tools.cflow: libdm.cflow lib.cflow | ||||
| daemons.cflow: tools.cflow | ||||
| cflow: include.cflow | ||||
| ifneq ("@CFLOW_CMD@", "") | ||||
| tools.cflow: lib.cflow | ||||
| cflow: tools.cflow | ||||
| endif | ||||
|  | ||||
| ifneq ("@CSCOPE_CMD@", "") | ||||
| cscope.out: | ||||
| 	@CSCOPE_CMD@ -b -R -s$(top_srcdir) | ||||
| cscope.out: tools | ||||
| 	@CSCOPE_CMD@ -b -R | ||||
| all: cscope.out | ||||
| endif | ||||
| DISTCLEAN_TARGETS += cscope.out | ||||
|  | ||||
| check check_system check_cluster check_local check_lvmetad unit: all | ||||
| 	$(MAKE) -C test $(@) | ||||
|  | ||||
| install_system_dirs: | ||||
| 	$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR) | ||||
| 	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR) | ||||
| 	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR) | ||||
| 	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR) | ||||
| 	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR) | ||||
| 	$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR) | ||||
| 	$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache | ||||
|  | ||||
| install_initscripts:  | ||||
| 	$(MAKE) -C scripts install_initscripts | ||||
|  | ||||
| install_systemd_generators: | ||||
| 	$(MAKE) -C scripts install_systemd_generators | ||||
| 	$(MAKE) -C man install_systemd_generators | ||||
|  | ||||
| install_systemd_units: | ||||
| 	$(MAKE) -C scripts install_systemd_units | ||||
|  | ||||
| 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 tools.info \ | ||||
| 	daemons/dmeventd.info daemons/clvmd.info | ||||
| CLEAN_TARGETS += $(LCOV_TRACES) | ||||
|  | ||||
| ifneq ("$(LCOV)", "") | ||||
| .PHONY: lcov-reset lcov lcov-dated $(LCOV_TRACES) | ||||
|  | ||||
| ifeq ($(MAKECMDGOALS),lcov-dated) | ||||
| LCOV_REPORTS_DIR := lcov_reports-$(shell date +%Y%m%d%k%M%S) | ||||
| lcov-dated: lcov | ||||
| else | ||||
| LCOV_REPORTS_DIR := lcov_reports | ||||
| endif | ||||
|  | ||||
| lcov-reset: | ||||
| 	$(LCOV) --zerocounters $(addprefix -d , $(basename $(LCOV_TRACES))) | ||||
|  | ||||
| # maybe use subdirs processing to create tracefiles... | ||||
| $(LCOV_TRACES): | ||||
| 	$(LCOV) -b $(basename $@) -d $(basename $@) \ | ||||
| 		--ignore-errors source -c -o - | $(SED) \ | ||||
| 		-e "s/\(dmeventd_lvm.[ch]\)/plugins\/lvm2\/\1/" \ | ||||
| 		-e "s/dmeventd_\(mirror\|snapshot\|thin\|raid\)\.c/plugins\/\1\/dmeventd_\1\.c/" \ | ||||
| 		>$@ | ||||
|  | ||||
| ifneq ("$(GENHTML)", "") | ||||
| lcov: $(LCOV_TRACES) | ||||
| 	$(RM) -r $(LCOV_REPORTS_DIR) | ||||
| 	$(MKDIR_P) $(LCOV_REPORTS_DIR) | ||||
| 	for i in $(LCOV_TRACES); do \ | ||||
| 		test -s $$i && lc="$$lc $$i"; \ | ||||
| 	done; \ | ||||
| 	test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \ | ||||
| 		-o $(LCOV_REPORTS_DIR) $$lc | ||||
| endif | ||||
|  | ||||
| endif | ||||
|  | ||||
| ifeq ("$(TESTING)", "yes") | ||||
| # testing and report generation | ||||
| RUBY=ruby1.9 -Ireport-generators/lib -Ireport-generators/test | ||||
|  | ||||
| .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 | ||||
|   | ||||
							
								
								
									
										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. | ||||
|  | ||||
| There is no warranty - see COPYING and COPYING.LIB. | ||||
|  | ||||
| Tarballs are available from: | ||||
|   ftp://sources.redhat.com/pub/lvm2/ | ||||
|   ftp://sources.redhat.com/pub/dm/ | ||||
|  | ||||
| The source code is stored in git: | ||||
|   http://git.fedorahosted.org/git/lvm2.git | ||||
|   git clone git://git.fedorahosted.org/git/lvm2.git | ||||
| To access the CVS tree use: | ||||
|   cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login | ||||
|   CVS password: cvs | ||||
|   cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 co LVM2 | ||||
|  | ||||
| Mailing list for general discussion related to LVM2: | ||||
| Mailing list for discussion/bug reports etc. | ||||
|   linux-lvm@redhat.com | ||||
|   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/linux-lvm | ||||
|  | ||||
|   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.91-git (2014-09-01) | ||||
							
								
								
									
										687
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							
							
						
						
									
										687
									
								
								WHATS_NEW_DM
									
									
									
									
									
								
							| @@ -1,687 +1,15 @@ | ||||
| Version 1.02.91 -  | ||||
| ==================================== | ||||
|   Fix dm_is_dm_major to not issue error about missing /proc lines for dm module. | ||||
|  | ||||
| Version 1.02.90 - 1st September 2014 | ||||
| ==================================== | ||||
|   Restore proper buffer size for parsing mountinfo line (1.02.89) | ||||
|  | ||||
| Version 1.02.89 - 26th August 2014 | ||||
| ================================== | ||||
|   Improve libdevmapper-event select() error handling. | ||||
|   Add extra check for matching transation_id after message submitting. | ||||
|   Add dm_report_field_string_list_unsorted for str. list report without sorting. | ||||
|   Support --deferred with dmsetup remove to defer removal of open devices. | ||||
|   Update dm-ioctl.h to include DM_DEFERRED_REMOVE flag. | ||||
|   Add support for selection to match string list subset, recognize { } operator. | ||||
|   Fix string list selection with '[value]' to not match list that's superset. | ||||
|   Fix string list selection to match whole words only, not prefixes. | ||||
|  | ||||
| Version 1.02.88 - 5th August 2014 | ||||
| ================================= | ||||
|   Add dm_tree_set_optional_uuid_suffixes to handle upgrades. | ||||
|  | ||||
| Version 1.02.87 - 23rd July 2014 | ||||
| Version 1.02.22 -  | ||||
| ================================ | ||||
|   Fix dm_report_field_string_list to handle delimiter with multiple chars. | ||||
|   Add dm_report_field_reserved_value for per-field reserved value definition. | ||||
|  | ||||
| Version 1.02.86 - 23rd June 2014 | ||||
| ================================ | ||||
|   Make "help" and "?" reporting fields implicit. | ||||
|   Recognize implicit "selected" field if using dm_report_init_with_selection. | ||||
|   Add support for implicit reporting fields which are predefined in libdm. | ||||
|   Add DM_REPORT_FIELD_TYPE_PERCENT: separate number and percent fields. | ||||
|   Add dm_percent_range_t,dm_percent_to_float,dm_make_percent to libdm for reuse. | ||||
|   Add dm_report_reserved_value to libdevmapper for reserved value definition. | ||||
|   Also display field types when listing all fields in selection help. | ||||
|   Recognize "help" keyword in selection string to show brief help for selection. | ||||
|   Always order items reported as string list field lexicographically. | ||||
|   Add dm_report_field_string_list to libdevmapper for direct string list report. | ||||
|   Add DM_REPORT_FIELD_TYPE_STRING_LIST: separate string and string list fields. | ||||
|   Add dm_str_list to libdevmapper for string list type definition and its reuse. | ||||
|   Add dmsetup -S/--select to define selection criteria for dmsetup reports. | ||||
|   Add dm_report_init_with_selection to intialize report with selection criteria. | ||||
|   Add DM_REPORT_FIELD_TYPE_SIZE: separate number and size reporting fields. | ||||
|   Use RemoveOnStop for dm-event.socket systemd unit. | ||||
|   Document env var 'DM_DEFAULT_NAME_MANGLING_MODE' in dmsetup man page. | ||||
|   Warn user about incorrect use of cookie with 'dmsetup remove --force'. | ||||
|   Also recognize 'help'/'?' as reserved sort key name to show help. | ||||
|   Add dm_units_to_factor for size unit parsing. | ||||
|   Increase bitset size for minors for thin dmeventd plugin. | ||||
|  | ||||
| Version 1.02.85 - 10th April 2014 | ||||
| ================================= | ||||
|   Check for sprintf error when building internal device path. | ||||
|   Check for sprintf error when creating path for dm control node. | ||||
|   When buffer for dm_get_library_version() is too small, return error code. | ||||
|   Always reinitialize _name_mangling_mode in dm_lib_init(). | ||||
|   Add tracking flag about implicitly added devices into dm_tree. | ||||
|   Stop timeout thread immediately when the last worker thread is finished. | ||||
|   Fix dmeventd logging with parallel wait event processing. | ||||
|   Reuse _node_send_messages() for validation of transaction_id in preload. | ||||
|   Transaction_id could be lower by one only when messages are prepared. | ||||
|   Do not call callback when preload fails. | ||||
|   Wrap is_selinux_enabled() to be called just once. | ||||
|   Use correctly signed 64b constant when working with raid volumes. | ||||
|   Exit dmeventd with pidfile cleanup instead of raising SIGKILL on DIE request. | ||||
|   Add new DM_EVENT_GET_PARAMETERS request to dmeventd protocol. | ||||
|   Do not use systemd's reload for dmeventd restart, use dmeventd -R instead. | ||||
|   Drop cryptsetup rules from 10-dm.rules - cryptsetup >= 1.1.3 sets them. | ||||
|  | ||||
| Version 1.02.84 - 20th January 2014 | ||||
| =================================== | ||||
|   Revert activation of activated nodes if a node preload callback fails. | ||||
|   Avoid busy looping on CPU when dmeventd reads event DM_WAIT_RETRY. | ||||
|   Ensure global mutex is held when working with dmeventd thread. | ||||
|   Drop taking timeout mutex for un/registering dmeventd monitor. | ||||
|   Allow section names in config file data to be quoted strings. | ||||
|   Close fifos before exiting in dmeventd restart() error path. | ||||
|   Move printf format string directly into dm_asprintf args list. | ||||
|   Catch invalid use of string sort values when reporting numerical fields. | ||||
|  | ||||
| Version 1.02.83 - 13th November 2013 | ||||
| ==================================== | ||||
|   Consistently report on stderr when device is not found for dmsetup info. | ||||
|   Skip race errors when non-udev dmsetup build runs on udev-enabled system. | ||||
|   Skip error message when holders are not present in sysfs. | ||||
|   Use __linux__ instead of linux define to make libdevmapper.h C compliant. | ||||
|   Use mutex to avoid possible race while creating/destroying memory pools. | ||||
|   Require libpthread to build now. | ||||
|  | ||||
| Version 1.02.82 - 4th October 2013 | ||||
| ================================== | ||||
|   Define symbolic names for subsystem udev flags in libdevmapper for easier use. | ||||
|   Make subsystem udev rules responsible for importing DM_SUBSYSTEM_UDEV_FLAG*. | ||||
|  | ||||
| Version 1.02.81 - 23rd September 2013 | ||||
| ===================================== | ||||
|   Tidy dmeventd fifo initialisation. | ||||
|  | ||||
| Version 1.02.80 - 20th September 2013 | ||||
| ===================================== | ||||
|   Detect invalid sector supplied to 'dmsetup message'. | ||||
|   Free any previously-set string if a dm_task_set_* function is called again. | ||||
|   Do not allow passing empty new name for dmsetup rename. | ||||
|   Display any output returned by 'dmsetup message'. | ||||
|   Add dm_task_get_message_response to libdevmapper. | ||||
|  | ||||
| Version 1.02.79 - 13th August 2013 | ||||
| ================================== | ||||
|   Create dmeventd timeout threads as "detached" so exit status is freed. | ||||
|   Add DM_ABORT_ON_INTERNAL_ERRORS env var support to abort on internal errors. | ||||
|  | ||||
| Version 1.02.78 - 24th July 2013 | ||||
| ================================ | ||||
|   Process thin messages once to active thin pool target for dm_tree. | ||||
|   Optimize out setting the same value or read_ahead. | ||||
|   Add DM_ARRAY_SIZE public macro. | ||||
|   Move syslog code out of signal handle in dmeventd. | ||||
|   Add DM_TO_STRING public macro. | ||||
|   Always return success on dmeventd -V command call. | ||||
|   Fix parsing of 64bit snapshot status in dmeventd snapshot plugin. | ||||
|   Add dm_get_status_snapshot() for parsing snapshot status. | ||||
|   Detecte mounted fs also via reading /proc/self/mountinfo. | ||||
|   Add dm_mountinfo_read() for parsing /proc/self/mountinfo. | ||||
|   Report error for nonexisting devices in dmeventd communication. | ||||
|   Prevent double free error after dmeventd call of _fill_device_data(). | ||||
|   Update dmevent structure message_data to simplify/fix error path handling. | ||||
|   Validate passed params to dm_get_status_raid/thin/thin_pool().  | ||||
|   Fix 'dmsetup splitname -o' to not fail if used without '-c' switch (1.02.68). | ||||
|   Add dm_config_write_{node_out/one_node_out} for enhanced config output. | ||||
|   Add dm_config_value_is_bool to check for boolean value in supported formats. | ||||
|   Fix config node lookup inside empty sections to not return the section itself. | ||||
|   Append discards and read-only fields to exported struct dm_status_thin_pool. | ||||
|   Fix segfault for truncated string token in config file after the first '"'. | ||||
|   Close open dmeventd FIFO file descriptors on exec (FD_CLOEXEC). | ||||
|   Fix resource leak in error path of dmeventd's umount of thin volume. | ||||
|   Automatically deactivate failed preloaded dm tree node. | ||||
|   Add DM_DISABLE_UDEV environment variable to manage dev nodes by libdm only. | ||||
|   Fix dm_task_set_cookie to properly process udev flags if udev_sync disabled. | ||||
|  | ||||
| Version 1.02.77 - 15th October 2012 | ||||
| =================================== | ||||
|   Support unmount of thin volumes from pool above thin pool threshold. | ||||
|   Update man page to reflect that dm UUIDs are being mangled as well. | ||||
|   Apply 'dmsetup mangle' for dm UUIDs besides dm names. | ||||
|   Add 'mangled_uuid' and 'unmangled_uuid' fields to dmsetup info -c -o. | ||||
|   Mangle device UUID on dm_task_set_uuid/newuuid call if necessary. | ||||
|   Add dm_task_get_uuid_mangled/unmangled to libdevmapper. | ||||
|   Always reset delay_resume_if_new flag when stacking thin pool over anything. | ||||
|   Don't create value for dm_config_node and require dm_config_create_value call. | ||||
|   Check for existing new_name for dmsetup rename. | ||||
|   Fix memory leak in dmsetup _get_split_name() error path. | ||||
|  | ||||
| Version 1.02.76 - 7th August 2012 | ||||
| ================================= | ||||
|   Add dm_vasprintf to libdevmapper. | ||||
|   Allow --noflush with dmsetup status and wait (for thin target). | ||||
|   Add dm_config_write_one_node to libdevmapper. | ||||
|   Support thin pool message release/reserve_metadata_snap in libdevmapper. | ||||
|   Support thin pool discards and external origin features in libdevmapper. | ||||
|   Add configure --enable-udev-rule-exec-detection to detect exec path in rules. | ||||
|   Use sbindir in udev rules by default and remove executable path detection. | ||||
|   Remove hard-coded paths for dmeventd fifos and use default-dm-run-dir. | ||||
|   Add configure --with-lvmetad-pidfile to remove hard-coded value. | ||||
|   Add configure --with-default-pid-dir for common directory with pid files. | ||||
|   Add configure --with-default-dm-run-dir to set run directory for dm tools. | ||||
|   Detect kernel_send() errors in cmirrord. | ||||
|   Add __attribute__ instrumentation to libdevmapper.h. | ||||
|   Print clean_bits instead of sync_bits in pull_state in cmirrord. | ||||
|   Add tests for errors from closedir(), close() in cmirrord. | ||||
|   Add documentation references in systemd units. | ||||
|   Remove veritysetup.  Now maintained with cryptsetup. | ||||
|  | ||||
| Version 1.02.75 - 8th June 2012 | ||||
| =============================== | ||||
|   Upstream source repo now fedorahosted.org git not sources.redhat.com CVS. | ||||
|   Remove unsupported udev_get_dev_path libudev call used for checking udev dir. | ||||
|   Set delay_resume_if_new on deptree snapshot origin. | ||||
|   Log value chosen in _find_config_bool like other variable types do. | ||||
|   Wait for dmeventd to exit after sending it DM_EVENT_CMD_DIE when restarting. | ||||
|   Append 'Used' to {Blk}DevNames/DevNos dmsetup report headers for clarity. | ||||
|   Add configure --with-veritysetup for independent veritysetup tool. | ||||
|   Properly support supplied dmevent path in dm_event_register_handler(). | ||||
|   Remove dmeventd fifos on exit if they are not managed by systemd. | ||||
|   Use SD_ACTIVATION environment variable in systemd units to detect systemd. | ||||
|   Only start a new dmeventd instance on restart if one was already running. | ||||
|   Extend the time waited for input from dmeventd fifo to 5 secs. (1.02.73) | ||||
|  | ||||
| Version 1.02.74 - 6th March 2012 | ||||
| ================================ | ||||
|   Check for multiply-mangled names in auto mangling mode. | ||||
|   Fix dm_task_get_name_unmangled to not unmangle already unmangled name. | ||||
|   Check whether device names are properly mangled on ioctl return. | ||||
|   Deactivation of failed thin check on thin pool returns success. | ||||
|  | ||||
| Version 1.02.73 - 3rd March 2012 | ||||
| ================================ | ||||
|   Test _thread_registry list with holding mutex in dmeventd. | ||||
|   Add dm_tree_node_set_callback() for preload and deactivation hooks. | ||||
|   Drop unsupported TRIM message for thin pool. | ||||
|   Improve logging for fifo startup in dmeventd. | ||||
|   Better detection of missing dmeventd fifo connection (1.02.71). | ||||
|   Add a few pointer validations in dmsetup. | ||||
|   Support dm_task_get_driver_version() query without version string. | ||||
|   Log failure of pthread_join when cleaning unused threads in dmeventd. | ||||
|   Fix empty string warning logic in _find_config_str. (1.02.68) | ||||
|   Fix dm_task_set_name to properly resolve path to dm name (1.02.71). | ||||
|   Add dm_strncpy() function as a faster strncpy() replacement. | ||||
|  | ||||
| Version 1.02.72 - 23rd February 2012 | ||||
| ==================================== | ||||
|   Avoid memory reallocation for dm_asprintf. | ||||
|  | ||||
| Version 1.02.71 - 20th February 2012 | ||||
| ==================================== | ||||
|   Switch to using built-in blkid in 13-dm-disk.rules. | ||||
|   Add "watch" rule to 13-dm-disk.rules. | ||||
|   Detect failing fifo and skip 20s retry communication period. | ||||
|   Add DM_DEFAULT_NAME_MANGLING_MODE environment variable as an override. | ||||
|   Add dm_lib_init to automatically initialise device-mapper library on load. | ||||
|   Replace any '\' char with '\\' in dm table specification on input. | ||||
|   Add mangle command to dmsetup to provide renaming to correct mangled form. | ||||
|   Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o. | ||||
|   Add --manglename option to dmsetup to select the name mangling mode. | ||||
|   Add dm_task_get_name_mangled/unmangled to libdevmapper. | ||||
|   Mangle device name on dm_task_set_name/newname call if necessary. | ||||
|   Add dm_set/get_name_mangling_mode to set/get name mangling in libdevmapper. | ||||
|   Add configure --with-default-name-mangling for udev-friendly dev name charset. | ||||
|   Test for parsed words in _umount() dmeventd snapshot plugin. | ||||
|   Fix memory leak in fail path of parse_loop_device_name() in dmsetup. | ||||
|   Check for missing reply_uuid in dm_event_get_registered_device(). | ||||
|   Check for allocation failure in dmeventd restart(). | ||||
|   Add few missing allocation failures tests in dmsetup. | ||||
|   Fix potential risk of writing in front of buffer in _sysfs_get_dm_name(). | ||||
|  | ||||
| Version 1.02.70 - 12th February 2012 | ||||
| ==================================== | ||||
|   Fix dm_event_get_version() check. | ||||
|   Add pointer test for dependency check in _add_dev(). | ||||
|   Validate name and uuid params of dm_tree_add_new_dev_with_udev_flags(). | ||||
|   Do not crash for dm_report_init() sort_key == NULL and behave like "". | ||||
|   Return error for failing allocation in dm_asprintf(). | ||||
|   Add missing test for failing allocation in dm_realloc() code. | ||||
|   Add test for memory allocation failures in regex matcher code. | ||||
|   Simplify dm_task_set_geometry() and use dm_asprintf(). | ||||
|   Set all parameters to 0 for dm_get_next_target() for NULL return. | ||||
|   Fix fd resource leak in error path for _udev_notify_sem_create(). | ||||
|   Leave space for '\0' for readline() call in _sysfs_get_kernel_name(). | ||||
|  | ||||
| Version 1.02.69 - 1st February 2012 | ||||
| =================================== | ||||
|   Clean up dmeventd systemd unit ordering and requirements. | ||||
|  | ||||
| Version 1.02.68 - 26th January 2012 | ||||
| =================================== | ||||
|   Reset all members of info struct in dm_tree_add_new_dev_with_udev_flags. | ||||
|   Add dmsetup wipe_table to replace table with one that uses error target. | ||||
|   Add 'blkdevname' and 'blkdevs_used' fields to dmsetup info -c -o. | ||||
|   Add 'blkdevname' option to dmsetup ls --tree to see block device names. | ||||
|   Add -o devno/blkdevname/devname to dmsetup deps and ls. | ||||
|   Add dm_device_get_name to get map name or block device name for given devno. | ||||
|   Remove empty devices when clearing left-over inactive tables in deptree. | ||||
|   Add dm_uuid_prefix/dm_set_uuid_prefix to override hard-coded LVM- prefix. | ||||
|   Improve dmsetup man page description of readahead parameter. | ||||
|   Use sysfs to set/get readahead if possible. | ||||
|   Fix lvm2-monitor init script to use normalized output when using vgs. | ||||
|   Add test for max length (DM_MAX_TYPE_NAME) of target type name. | ||||
|   Include a copy of kernel DM documentation in doc/kernel. | ||||
|   Improve man page style for dmsetup and mention more targets. | ||||
|   Fix _get_proc_number to be tolerant of malformed /proc/misc entries. | ||||
|   Fix missing thread list manipulation protection in dmeventd. | ||||
|   Add ExecReload to dm-event.service for systemd to reload dmeventd properly. | ||||
|   Add dm_config_tree_find_str_allow_empty and dm_config_find_str_allow_empty. | ||||
|   Fix compile-time pool memory locking with DEBUG_MEM. | ||||
|   Fix valgrind error reports in free of pool chunks with DEBUG_MEM. | ||||
|   Align size of structure chunk for fast pool allocator to 8 bytes. | ||||
|   Simplify some pointer operations in dm_free_aux() debug code. | ||||
|   Remove unused dbg_malloc.h file from source tree. | ||||
|   Cleanup backtraces for _create_and_load_v4(). | ||||
|   Fix alignment warning in bitcount calculation for raid segment. | ||||
|   Allocate dm_tree structure from dm_tree pool. | ||||
|   Update debug logging for _resume_node. | ||||
|   Add functions to support thin provisioning target. | ||||
|   Improve libdm-config error path reporting. | ||||
|   Update dmsetup resume man with --addnodeonresume/create options. | ||||
|   Add dependency for dm man pages to man subdirectory make all target. | ||||
|   Add dm_tree_retry_remove to use retry logic for device removal in a dm_tree. | ||||
|   Add dm_device_has_mounted_fs fn to check mounted filesystem on a device. | ||||
|   Add dm_device_has_holders fn to to check use of the device by another device. | ||||
|   Add dm_sysfs_dir to libdevmapper to retrieve sysfs location set. | ||||
|   Add dm_set_sysfs_dir to libdevmapper to set sysfs location. | ||||
|   Add --retry option for dmsetup remove to retry removal if not successful. | ||||
|   Add dm_task_retry_remove fn to use retry logic for device removal. | ||||
|   Remove unused passed parameters for _mirror_emit_segment_line(). | ||||
|   Add dm_config and string character escaping functions to libdevmapper. | ||||
|   Mark unreleased memory pools as internal error. | ||||
|  | ||||
| Version 1.02.67 - 19th August 2011 | ||||
| ================================== | ||||
|   Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked. | ||||
|  | ||||
| Version 1.02.66 - 12th August 2011 | ||||
| ================================== | ||||
|   Release geometry buffer in dm_task_destroy. | ||||
|   Update udev rules to skip DM flags decoding for removed devices. | ||||
|   Add compile-time pool memory locking options (to debug shared VG structs). | ||||
|   Remove device name prefix from dmsetup line output if -j & -m or -u supplied. | ||||
|   Remove support for the original version 1 dm ioctls. | ||||
|   Add missing check for allocation failure _create_dir_recursive(). | ||||
|   Add support for systemd file descriptor handover in dmeventd. | ||||
|   Fix memory leak in dmsetup _message() memory allocation error path. | ||||
|   Use new oom killer adjustment interface (oom_score_adj) when available. | ||||
|   Add systemd unit files for dmeventd. | ||||
|   Fix read-only identical table reload supression. | ||||
|  | ||||
| Version 1.02.65 - 8th July 2011 | ||||
| =============================== | ||||
|   Remove dev name prefix from dmsetup line output if exactly one dev requested. | ||||
|   Report internal error if suspending a device using an already-suspended dev. | ||||
|   Report error if a table load requiring target parameters has none supplied. | ||||
|   Add dmsetup --checks and dm_task_enable_checks framework to validate ioctls. | ||||
|   Add age_in_minutes parameter to dmsetup udevcomplete_all. | ||||
|   Return immediately from dm_lib_exit() if called more than once. | ||||
|   Disable udev fallback by default and add --verifyudev option to dmsetup. | ||||
|   Report internal error if any table is loaded while any dev is known suspended. | ||||
|   Add dm_get_suspended_counter() for number of devs in suspended state by lib. | ||||
|   Fix "all" report field prefix matching to include label fields with pv_all. | ||||
|   Delay resuming new preloaded mirror devices with core logs in deptree code. | ||||
|   Accept new kernel version 3 uname formats in initialisation. | ||||
|  | ||||
| Version 1.02.64 - 29th April 2011 | ||||
| ================================== | ||||
|   Require libudev >= 143 when compiling with udev support. | ||||
|   Use word alignment for dm_pool_strdup() and dm_pool_strndup(). | ||||
|   Use dm_snprintf() to fix signedness warning in dm_set_dev_dir(). | ||||
|   Use unsigned loop counter to fix signedness warning in _other_node_ops(). | ||||
|   Fix const cast in dmsetup calls of dm_report_field_string(). | ||||
|   Streamline /dev/mapper/control node code for common cases. | ||||
|   Use hard-coded dm control node device number for 2.6.36 kernels and above. | ||||
|   Improve stack debug reporting in dm_task_create(). | ||||
|   Fallback to control node creation only if node doesn't exist yet. | ||||
|   Change dm_hash binary functions to take void *key instead of char *. | ||||
|   Fix uninitialised memory use with empty params in _reload_with_suppression_v4. | ||||
|   Lower severity of selabel_lookup and matchpathcon failure to log_debug. | ||||
|   Add test for failed allocation from dm_task_set_uuid() in dmeventd. | ||||
|   Add dm_event_get_version to dmeventd for use with -R. | ||||
|   Avoid dmeventd core dumps when handling request with unknown command ID. | ||||
|   Have dmeventd -R start up even when no existing copy is running. | ||||
|   Accept multiple mapped device names on many dmsetup command lines. | ||||
|   Fix dm_udev_wait calls in dmsetup to occur before readahead display not after. | ||||
|   Include an implicit dm_task_update_nodes() within dm_udev_wait(). | ||||
|   Fix _create_and_load_v4 not to lose the --addnodeoncreate setting (1.02.62). | ||||
|   Add inactive table query support for kernel driver >= 4.11.6 (RHEL 5.7). | ||||
|   Log debug open_count in _node_has_closed_parents(). | ||||
|   Add a const to dm_report_field_string() data parameter. | ||||
|  | ||||
| Version 1.02.63 - 9th February 2011 | ||||
| =================================== | ||||
|   Reinstate DEBUG_MEM as it's part of the API. (1.02.62) | ||||
|  | ||||
| Version 1.02.62 - 4th February 2011 | ||||
| =================================== | ||||
|   Add configure --with-device-nodes-on=create for previous behaviour. | ||||
|   Move creation of device nodes from 'create' to 'resume'. | ||||
|   Add --addnodeonresume and --addnodeoncreate options to dmsetup. | ||||
|   Add dm_task_set_add_node to libdevmapper to control dev node creation time. | ||||
|   Add dm_task_secure_data to libdevmapper to wipe ioctl buffers in kernel. | ||||
|   Log debug message when expected uevent is not generated. | ||||
|   Only compile memory debugging code when DEBUG_MEM is set. | ||||
|   Set DM_UDEV_DISABLE_OTHER_RULES_FLAG for suspended DM devices in udev rules. | ||||
|   Begin a new pool object for each row in _output_as_rows() correctly. | ||||
|  | ||||
| Version 1.02.61 - 10th January 2011 | ||||
| =================================== | ||||
|   Add DM_COOKIE_AUTO_CREATE to libdevmapper.h. | ||||
|   Export DM_CONTROL_NODE_UMASK and use it while creating /dev/mapper/control. | ||||
|  | ||||
| Version 1.02.60 - 20th December 2010 | ||||
| ==================================== | ||||
|   Check for unlink failure in remove_lockfile() in dmeventd. | ||||
|   Use dm_free for dm_malloc-ed areas in _clog_ctr/_clog_dtr in cmirrord. | ||||
|   Use char* arithmetic in _process_all() & _targets() in dmsetup. | ||||
|   Change dm_regex_create() API to accept const char * const *patterns. | ||||
|   Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout. | ||||
|   Detect existence of new SELinux selabel interface during configure. | ||||
|  | ||||
| Version 1.02.59 - 6th December 2010 | ||||
| =================================== | ||||
|   Add backtraces to _process_mapper_dir and  _create_and_load_v4 error paths. | ||||
|   Remove superfluous checks for NULL before calling dm_free. | ||||
|  | ||||
| Version 1.02.58 - 22nd November 2010 | ||||
| ==================================== | ||||
|   Fix _output_field crash from field_id free with DEBUG_MEM. (1.02.57) | ||||
|  | ||||
| Version 1.02.57 - 8th November 2010 | ||||
| =================================== | ||||
|   Fix regex optimiser not to ignore RHS of OR nodes in _find_leftmost_common. | ||||
|   Add dmeventd -R to restart dmeventd without losing monitoring state. (1.02.56) | ||||
|   Fix memory leak of field_id in _output_field function. | ||||
|   Allocate buffer for reporting functions dynamically to support long outputs. | ||||
|  | ||||
| Version 1.02.56 - 25th October 2010 | ||||
| =================================== | ||||
|   Return const pointer from dm_basename() in libdevmapper. | ||||
|   Implement dmeventd -R to restart without state loss. | ||||
|   Add dm_zalloc and use it and dm_pool_zalloc throughout. | ||||
|   Add --setuuid to dmsetup rename. | ||||
|   Add dm_task_set_newuuid to set uuid of mapped device post-creation. | ||||
|  | ||||
| Version 1.02.55 - 24th September 2010 | ||||
| ===================================== | ||||
|   Fix the way regions are marked complete to avoid slow --nosync cmirror I/O. | ||||
|   Add DM_REPORT_FIELD_TYPE_ID_LEN to libdevmapper.h. | ||||
|  | ||||
| Version 1.02.54 - 18th August 2010 | ||||
| ================================== | ||||
|   Fix dm-mod autoloading logic to not assume control node is set correctly. | ||||
|   Add dmeventd/executable to lvm.conf to test alternative dmeventd. | ||||
|   Export dm_event_handler_set_dmeventd_path to override built-in dmeventd path. | ||||
|   Generate libdevmapper-event exported symbols. | ||||
|   Remove superfluous NULL pointer tests before dm_free from dmeventd. | ||||
|   Assume dm-mod autoloading support is in kernel 2.6.36 and higher, not 2.6.35. | ||||
|   Fix udev rules to support udev database content generated by older rules. | ||||
|   Reinstate detection of inappropriate uevent with DISK_RO set and suppress it. | ||||
|   Fix regex ttree off-by-one error. | ||||
|   Add --enable-valgrind-pool to configure. | ||||
|   Fix segfault in regex matcher with characters of ordinal value > 127. | ||||
|   Fix 'void*' arithmetic warnings in dbg_malloc.c and libdm-iface.c. | ||||
|   Wait for node creation before displaying debug info in dmsetup. | ||||
|   Fix return status 0 for "dmsetup info -c -o help". | ||||
|   Add check for kernel semaphore support and disable udev_sync if not available. | ||||
|  | ||||
| Version 1.02.53 - 28th July 2010 | ||||
| ================================ | ||||
|   Revert failed table load preparation after "create, load and resume". | ||||
|   Switch dmeventd to use dm_create_lockfile and drop duplicate code. | ||||
|   Add dm_create_lockfile to libdm to handle pidfiles for all daemons. | ||||
|   Replace lookup with next in struct dfa_state & calculate states on demand. | ||||
|   Improve the regex matcher, reducing the number of charset nodes used. | ||||
|   Add dm_regex_fingerprint to facilitate regex testing. | ||||
|   Skip ffs(0) in _test_word in bitset functions. | ||||
|   Use "nowatch" udev rule for inappropriate devices. | ||||
|  | ||||
| Version 1.02.52 - 6th July 2010 | ||||
| =============================== | ||||
|   Fix dmlosetup snprintf %llu compiler warning. | ||||
|   Add parentheses to some libdevmapper.h macro arguments. | ||||
|   Add printf format attributes to dm_{sn,as}printf and fix a caller. | ||||
|   Move dmeventd man page from install_lvm2 to install_device-mapper. (1.02.50) | ||||
|  | ||||
| Version 1.02.51 - 30th June 2010 | ||||
| ================================ | ||||
|   Generate libdevmapper exported symbols from header file. | ||||
|  | ||||
| Version 1.02.50 - 23rd June 2010 | ||||
| ================================ | ||||
|   Fix INTERNAL_ERROR typo in ioctl iface unknown task message. | ||||
|   Fix udev rules to handle spurious events properly. | ||||
|   Use C99 [] not [0] in dm_ulog_request struct to avoid abort when fortified. | ||||
|   Allow use of devmapper header file in C++ mode (extern "C" and __typeof__). | ||||
|   Add dmeventd man page. | ||||
|  | ||||
| Version 1.02.49 - 4th June 2010 | ||||
| =============================== | ||||
|   Support autoloading of dm-mod module for kernels from 2.6.35. | ||||
|   Document 'clear' in dmsetup man page. | ||||
|   Fix semctl parameter (union) to avoid misaligned parameter on some arches. | ||||
|   Add dm_tree_node_set_presuspend_node() to presuspend child when deactivating. | ||||
|   Initial support for replicator target. | ||||
|  | ||||
| Version 1.02.48 - 17th May 2010 | ||||
| ================================ | ||||
|   Use -d to control level of messages sent to syslog by dmeventd. | ||||
|   Change -d to -f to run dmeventd in foreground. | ||||
|   Do not print encryption key in message debug output (cryptsetup luksResume). | ||||
|   Fix dmeventd static build library dependencies. | ||||
|   Fix udev flags on remove in create_and_load error path. | ||||
|  | ||||
| Version 1.02.47 - 30th April 2010 | ||||
| ================================= | ||||
|   Add support for new IMPORT{db} udev rule. | ||||
|   Add DM_UDEV_PRIMARY_SOURCE_FLAG udev flag to recognize proper DM events. | ||||
|   Also include udev libs in libdevmapper.pc when udev_sync is enabled. | ||||
|   Cache bitset locations to speed up _calc_states. | ||||
|   Add a regex optimisation pass for shared prefixes and suffixes. | ||||
|   Add dm_bit_and and dm_bitset_equal to libdevmapper. | ||||
|   Simplify dm_bitset_create. | ||||
|   Speed up dm_bit_get_next with ffs(). | ||||
|  | ||||
| Version 1.02.46 - 14th April 2010 | ||||
| ================================= | ||||
|   Change dm_tree_deactivate_children to fail if device is open. | ||||
|   Wipe memory buffers for dm-ioctl parameters before releasing. | ||||
|   Strictly require libudev if udev_sync is used. | ||||
|   Add support for ioctl's DM_UEVENT_GENERATED_FLAG. | ||||
|  | ||||
| Version 1.02.45 - 9th March 2010 | ||||
| ================================ | ||||
|   Add --showkeys parameter description to dmsetup man page. | ||||
|   Add --help option as synonym for help command. | ||||
|  | ||||
| Version 1.02.44 - 15th February 2010 | ||||
| ==================================== | ||||
|   Add DM_UDEV_DISABLE_LIBRARY_FALLBACK udev flag to rely on udev only. | ||||
|   Export dm_udev_create_cookie function to create new cookies on demand. | ||||
|   Add --udevcookie, udevcreatecookie and udevreleasecookie to dmsetup. | ||||
|   Set udev state automatically instead of using DM_UDEV_DISABLE_CHECKING. | ||||
|  | ||||
| Version 1.02.43 - 21st January 2010 | ||||
| =================================== | ||||
|   Remove bitset, hash and pool headers superceded by libdevmapper.h. | ||||
|   Fix off-by-one error causing bad cluster mirror table construction. | ||||
|  | ||||
| Version 1.02.42 - 14th January 2010 | ||||
| =================================== | ||||
|   Add support for the "snapshot-merge" kernel target (2.6.33-rc1). | ||||
|   Introduce a third activation_priority level in dm_tree_activate_children. | ||||
|  | ||||
| Version 1.02.41 - 12th January 2010 | ||||
| =================================== | ||||
|   If DM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings. | ||||
|   Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags. | ||||
|   Add --noudevrules option for dmsetup to disable /dev node management by udev. | ||||
|   Fix 'dmsetup info -c -o all' to show all fields. | ||||
|   Return errors if dm_tree_*_children functions fail. | ||||
|   Fix coredump and memory leak for 'dmsetup help -c'. | ||||
|   Disable udev rules for change events with DISK_RO set. | ||||
|  | ||||
| Version 1.02.40 - 19th November 2009 | ||||
| ==================================== | ||||
|   Fix install_device-mapper Makefile target to not build dmeventd plugins. | ||||
|   Support udev flags even when udev_sync is disabled or not compiled in. | ||||
|   Remove 'last_rule' from udev rules: honour DM_UDEV_DISABLE_OTHER_RULES_FLAG. | ||||
|   Add dmsetup --inactive support. | ||||
|   Add dm_task_query_inactive_table to libdevmapper for kernel driver >= 4.16. | ||||
|   Fix hash lookup segfault when keys compared are different lengths. | ||||
|  | ||||
| Version 1.02.39 - 26th October 2009 | ||||
| =================================== | ||||
|   Remove strict default permissions for DM devices from 95-dm-notify.rules. | ||||
|   Add dmsetup udevflags command to decode udev flags in given cookie value. | ||||
|   Support udev flags in libdevmapper incl. dm_tree_add_new_dev_with_udev_flags. | ||||
|   Make libdm ABI consistent when built with/without selinux support. | ||||
|  | ||||
| Version 1.02.38 - 25th September 2009 | ||||
| ===================================== | ||||
|   Export DM_DEV_DIR_UMASK, the default umask for /dev directories created. | ||||
|   Handle any path supplied to dm_task_set_name by looking up in /dev/mapper. | ||||
|   Add several examples to 12-dm-permissions.rules. | ||||
|   Add splitname and --yes to dmsetup man page. | ||||
|   Fix _mirror_emit_segment_line return code. | ||||
|   Fix dmeventd _temporary_log_fn parameters. (2.02.50) | ||||
|  | ||||
| Version 1.02.37 - 15th September 2009 | ||||
| ===================================== | ||||
|   Add dmsetup manpage entries for udevcomplete_all and udevcookies. | ||||
|   Check udev is running when processing cookies and retain state internally. | ||||
|   Add y|--yes option to dmsetup for default 'yes' answer to prompts. | ||||
|   Fix tools Makefile to process dmsetup sources separately. | ||||
|   Restore umask when device node creation fails. | ||||
|   Check kernel vsn to use 'block_on_error' or 'handle_errors' in mirror table. | ||||
|   Add dm-log-userspace.h to tree for cmirrord builds. | ||||
|  | ||||
| Version 1.02.36 - 6th August 2009 | ||||
| ================================= | ||||
|   Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup. | ||||
|   Add libdevmapper functions to support synchronisation with udev. | ||||
|  | ||||
| Version 1.02.35 - 28th July 2009 | ||||
| ================================ | ||||
|   Add LOG_LINE_WITH_ERRNO macro. | ||||
|   Use log_error macro consistently throughout in place of log_err. | ||||
|  | ||||
| Version 1.02.34 - 15th July 2009 | ||||
| ================================ | ||||
|   Use _exit() not exit() after forking to avoid flushing libc buffers twice. | ||||
|   Rename plog macro to LOG_LINE & add LOG_MESG variant for dm_dump_memory_debug. | ||||
|   Change plog to use dm_log_with_errno unless deprecated dm_log_init was used. | ||||
|   Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns. | ||||
|   Fix whitespace in linear target line to fix identical table line detection. | ||||
|   Add device number to more log messages during activation. | ||||
|  | ||||
| Version 1.02.33 - 30th June 2009 | ||||
| ================================ | ||||
|   Don't fallback to default major number: use dm_task_set_major_minor. (1.02.31) | ||||
|   Do not fork daemon when dmeventd cannot be found. | ||||
|   Add crypt target handling to libdevmapper tree nodes. | ||||
|   Add splitname command to dmsetup. | ||||
|   Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports. | ||||
|   Make mempool optional in dm_split_lvm_name(). | ||||
|  | ||||
| Version 1.02.32 - 21st May 2009 | ||||
| =============================== | ||||
|   Only generate libdevmapper.a when configured to link statically. | ||||
|   Export dm_tree_node_size_changed() from libdevmapper. | ||||
|   Propagate the table size_changed property up the dm device tree. | ||||
|   Detect failure to free memory pools when releasing the library. | ||||
|   Fix segfault when getopt processes dmsetup -U, -G and -M options. | ||||
|  | ||||
| Version 1.02.31 - 3rd March 2009 | ||||
| ================================ | ||||
|   If kernel supports only one dm major number, use in place of any supplied. | ||||
|  | ||||
| Version 1.02.30 - 26th January 2009 | ||||
| ==================================== | ||||
|   Add "all" field to reports expanding to all fields of report type. | ||||
|   Enforce device name length and character limitations in libdm. | ||||
|   Replace _dm_snprintf with EMIT_PARAMS macro for creating target lines. | ||||
|  | ||||
| Version 1.02.29 - 10th November 2008 | ||||
| ==================================== | ||||
|   Merge device-mapper into the LVM2 tree. | ||||
|   Split out dm-logging.h from log.h. | ||||
|   Use lvm-types.h. | ||||
|   Add usrsbindir to configure. | ||||
|  | ||||
| Version 1.02.28 - 18th September 2008 | ||||
| ===================================== | ||||
|   Only resume devices in dm_tree_preload_children if size changes. | ||||
|   Extend deptree buffers so the largest possible device numbers fit. | ||||
|   Generate versioned libdevmapper-event.so. | ||||
|   Underline longer report help text headings. | ||||
|  | ||||
| Version 1.02.27 - 25th June 2008 | ||||
| ================================ | ||||
|   Align struct memblock in dbg_malloc for sparc. | ||||
|   Add --unquoted and --rows to dmsetup. | ||||
|   Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro. | ||||
|   Fix inverted no_flush debug message. | ||||
|   Remove --enable-jobs from configure. (Set at runtime instead.) | ||||
|   Bring configure.in and list.h into line with the lvm2 versions. | ||||
|  | ||||
| Version 1.02.26 - 6th June 2008 | ||||
| =============================== | ||||
|   Initialise params buffer to empty string in _emit_segment. | ||||
|   Skip add_dev_node when ioctls disabled. | ||||
|   Make dm_hash_iter safe against deletion. | ||||
|   Accept a NULL pointer to dm_free silently. | ||||
|   Add tables_loaded, readonly and suspended columns to reports. | ||||
|   Add --nameprefixes to dmsetup. | ||||
|   Add field name prefix option to reporting functions. | ||||
|   Calculate string size within dm_pool_grow_object. | ||||
|  | ||||
| Version 1.02.25 - 10th April 2008 | ||||
| ================================= | ||||
|   Remove redundant if-before-free tests. | ||||
|   Use log_warn for reporting field help text instead of log_print. | ||||
|   Change cluster mirror log type name (s/clustered_/clustered-/) | ||||
|  | ||||
| Version 1.02.24 - 20th December 2007 | ||||
| ==================================== | ||||
|   Fix deptree to pass new name to _resume_node after a rename. | ||||
|   Suppress other node operations if node is deleted. | ||||
|   Add node operation stack debug messages. | ||||
|   Report error when empty device name passed to readahead functions. | ||||
|   Fix minimum readahead debug message. | ||||
|  | ||||
| Version 1.02.23 - 5th December 2007 | ||||
| =================================== | ||||
|   Update dm-ioctl.h after removal of compat code. | ||||
|   Add readahead support to libdevmapper and dmsetup. | ||||
|   Fix double free in a libdevmapper-event error path. | ||||
|   Fix configure --with-dmeventd-path substitution. | ||||
|   Allow a DM_DEV_DIR environment variable to override /dev in dmsetup. | ||||
|   Create a libdevmapper.so.$LIB_VERSION symlink within the build tree. | ||||
|   Avoid static link failure with some SELinux libraries that require libpthread. | ||||
|   Remove obsolete dmfs code from tree and update INSTALL. | ||||
|  | ||||
| Version 1.02.22 - 21st August 2007 | ||||
| ================================== | ||||
|   Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1. | ||||
|   Update to use autoconf 2.61, while still supporting 2.57. | ||||
|   Avoid repeated dm_task free on some dm_event_get_registered_device errors. | ||||
|   Introduce log_sys_* macros from LVM2. | ||||
|   Export dm_fclose and dm_create_dir; remove libdm-file.h. | ||||
|   Don't log EROFS mkdir failures in _create_dir_recursive (for LVM2). | ||||
|   Add fclose wrapper dm_fclose that catches write failures (using ferror). | ||||
|   Export dm_create_dir (was create_dir) to help fix LVM2 link error | ||||
|   Don't log mkdir fail-with-EROFS, to make create_dir equiv to the one in LVM2 | ||||
|   Introduce and use log_sys_* macros from LVM2 | ||||
|   dm_fclose: new function | ||||
|   libdevmapper, dmeventd: be paranoid about detecting write failure | ||||
|  | ||||
| Version 1.02.21 - 13th July 2007 | ||||
| ================================ | ||||
|   Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout. | ||||
|   Fix dmsetup -o devno string termination. (1.02.20) | ||||
|   Fix dmsetup -o devno string termination. (1.02.20)  | ||||
|  | ||||
| Version 1.02.20 - 15th June 2007 | ||||
| ================================ | ||||
| @@ -969,3 +297,4 @@ Version 1.00.08 - 27 Feb 2004 | ||||
|   Fixed DESTDIR for make install/install_static_lib. | ||||
|   Updated README/INSTALL to reflect move to sources.redhat.com. | ||||
|   Updated autoconf files to 2003-06-17. | ||||
|  | ||||
|   | ||||
							
								
								
									
										59
									
								
								acinclude.m4
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								acinclude.m4
									
									
									
									
									
								
							| @@ -1,59 +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_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 | ||||
| ]) | ||||
							
								
								
									
										230
									
								
								aclocal.m4
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										230
									
								
								aclocal.m4
									
									
									
									
										vendored
									
									
								
							| @@ -1,230 +0,0 @@ | ||||
| # generated automatically by aclocal 1.13.4 -*- Autoconf -*- | ||||
|  | ||||
| # Copyright (C) 1996-2013 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($@)])]) | ||||
| # 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 | ||||
|  | ||||
| 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 | ||||
| # 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 | ||||
| # under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 3 of the License, or | ||||
| # This file is (in principle) common to ALL GNU software. | ||||
| # The presence of a machine in this file suggests that SOME GNU software | ||||
| # 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. | ||||
| # | ||||
| # 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. | ||||
| # 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/>. | ||||
| # | ||||
| # 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.  This Exception is an additional permission under section 7 | ||||
| # of the GNU General Public License, version 3 ("GPLv3"). | ||||
| # the same distribution terms that you use for the rest of that program. | ||||
|  | ||||
|  | ||||
| # Please send patches with a ChangeLog entry to config-patches@gnu.org. | ||||
| # Please send patches to <config-patches@gnu.org>.  Submit a context | ||||
| # diff and a properly formatted ChangeLog entry. | ||||
| # | ||||
| # Configuration subroutine to validate and canonicalize a configuration type. | ||||
| # Supply the specified configuration type as an argument. | ||||
| # 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. | ||||
|  | ||||
| # 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 | ||||
| # and recognize all the CPU types, system types and aliases | ||||
| # that are meaningful with *any* GNU software. | ||||
| @@ -68,7 +70,8 @@ Report bugs and patches to <config-patches@gnu.org>." | ||||
| version="\ | ||||
| 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 | ||||
| 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 | ||||
|   case $1 in | ||||
|     --time-stamp | --time* | -t ) | ||||
|        echo "$timestamp" ; exit ;; | ||||
|        echo "$timestamp" ; exit 0 ;; | ||||
|     --version | -v ) | ||||
|        echo "$version" ; exit ;; | ||||
|        echo "$version" ; exit 0 ;; | ||||
|     --help | --h* | -h ) | ||||
|        echo "$usage"; exit ;; | ||||
|        echo "$usage"; exit 0 ;; | ||||
|     -- )     # Stop option processing | ||||
|        shift; break ;; | ||||
|     - )	# Use stdin as input. | ||||
| @@ -96,7 +99,7 @@ while test $# -gt 0 ; do | ||||
|     *local*) | ||||
|        # First pass through any local machine types. | ||||
|        echo $1 | ||||
|        exit ;; | ||||
|        exit 0;; | ||||
|  | ||||
|     * ) | ||||
|        break ;; | ||||
| @@ -115,18 +118,10 @@ esac | ||||
| # Here we must recognize all the valid KERNEL-OS combinations. | ||||
| maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` | ||||
| case $maybe_os in | ||||
|   nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ | ||||
|   linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ | ||||
|   knetbsd*-gnu* | netbsd*-gnu* | \ | ||||
|   kopensolaris*-gnu* | \ | ||||
|   storm-chaos* | os2-emx* | rtmk-nova*) | ||||
|   nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) | ||||
|     os=-$maybe_os | ||||
|     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/-[^-]*$//'` | ||||
|     if [ $basic_machine != $1 ] | ||||
| @@ -149,13 +144,10 @@ case $os in | ||||
| 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ | ||||
| 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ | ||||
| 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ | ||||
| 	-apple | -axis | -knuth | -cray | -microblaze*) | ||||
| 	-apple | -axis) | ||||
| 		os= | ||||
| 		basic_machine=$1 | ||||
| 		;; | ||||
| 	-bluegene*) | ||||
| 		os=-cnk | ||||
| 		;; | ||||
| 	-sim | -cisco | -oki | -wec | -winbond) | ||||
| 		os= | ||||
| 		basic_machine=$1 | ||||
| @@ -170,17 +162,13 @@ case $os in | ||||
| 		os=-chorusos | ||||
| 		basic_machine=$1 | ||||
| 		;; | ||||
| 	-chorusrdb) | ||||
| 		os=-chorusrdb | ||||
|  	-chorusrdb) | ||||
|  		os=-chorusrdb | ||||
| 		basic_machine=$1 | ||||
| 		;; | ||||
|  		;; | ||||
| 	-hiux*) | ||||
| 		os=-hiuxwe2 | ||||
| 		;; | ||||
| 	-sco6) | ||||
| 		os=-sco5v6 | ||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||
| 		;; | ||||
| 	-sco5) | ||||
| 		os=-sco3.2v5 | ||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||
| @@ -197,10 +185,6 @@ case $os in | ||||
| 		# Don't forget version if it is 3.2v4 or newer. | ||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||
| 		;; | ||||
| 	-sco5v6*) | ||||
| 		# Don't forget version if it is 3.2v4 or newer. | ||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||
| 		;; | ||||
| 	-sco*) | ||||
| 		os=-sco3.2v2 | ||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||
| @@ -218,12 +202,6 @@ case $os in | ||||
| 	-isc*) | ||||
| 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` | ||||
| 		;; | ||||
| 	-lynx*178) | ||||
| 		os=-lynxos178 | ||||
| 		;; | ||||
| 	-lynx*5) | ||||
| 		os=-lynxos5 | ||||
| 		;; | ||||
| 	-lynx*) | ||||
| 		os=-lynxos | ||||
| 		;; | ||||
| @@ -248,107 +226,55 @@ case $basic_machine in | ||||
| 	# Some are omitted here because they have special meanings below. | ||||
| 	1750a | 580 \ | ||||
| 	| a29k \ | ||||
| 	| aarch64 | aarch64_be \ | ||||
| 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | ||||
| 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | ||||
| 	| am33_2.0 \ | ||||
| 	| arc | arceb \ | ||||
| 	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | ||||
| 	| avr | avr32 \ | ||||
| 	| be32 | be64 \ | ||||
| 	| bfin \ | ||||
| 	| c4x | c8051 | clipper \ | ||||
| 	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | ||||
| 	| c4x | clipper \ | ||||
| 	| d10v | d30v | dlx | dsp16xx \ | ||||
| 	| epiphany \ | ||||
| 	| fido | fr30 | frv \ | ||||
| 	| fr30 | frv \ | ||||
| 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | ||||
| 	| hexagon \ | ||||
| 	| i370 | i860 | i960 | ia64 \ | ||||
| 	| ip2k | iq2000 \ | ||||
| 	| k1om \ | ||||
| 	| le32 | le64 \ | ||||
| 	| lm32 \ | ||||
| 	| m32c | m32r | m32rle | m68000 | m68k | m88k \ | ||||
| 	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | ||||
| 	| ip2k \ | ||||
| 	| m32r | m68000 | m68k | m88k | mcore \ | ||||
| 	| mips | mipsbe | mipseb | mipsel | mipsle \ | ||||
| 	| mips16 \ | ||||
| 	| mips64 | mips64el \ | ||||
| 	| mips64octeon | mips64octeonel \ | ||||
| 	| mips64orion | mips64orionel \ | ||||
| 	| mips64r5900 | mips64r5900el \ | ||||
| 	| mips64vr | mips64vrel \ | ||||
| 	| mips64orion | mips64orionel \ | ||||
| 	| mips64vr4100 | mips64vr4100el \ | ||||
| 	| mips64vr4300 | mips64vr4300el \ | ||||
| 	| mips64vr5000 | mips64vr5000el \ | ||||
| 	| mips64vr5900 | mips64vr5900el \ | ||||
| 	| mipsisa32 | mipsisa32el \ | ||||
| 	| mipsisa32r2 | mipsisa32r2el \ | ||||
| 	| mipsisa64 | mipsisa64el \ | ||||
| 	| mipsisa64r2 | mipsisa64r2el \ | ||||
| 	| mipsisa64sb1 | mipsisa64sb1el \ | ||||
| 	| mipsisa64sr71k | mipsisa64sr71kel \ | ||||
| 	| mipsr5900 | mipsr5900el \ | ||||
| 	| mipstx39 | mipstx39el \ | ||||
| 	| mn10200 | mn10300 \ | ||||
| 	| moxie \ | ||||
| 	| mt \ | ||||
| 	| msp430 \ | ||||
| 	| nds32 | nds32le | nds32be \ | ||||
| 	| nios | nios2 | nios2eb | nios2el \ | ||||
| 	| ns16k | ns32k \ | ||||
| 	| open8 \ | ||||
| 	| or1k | or32 \ | ||||
| 	| openrisc | or32 \ | ||||
| 	| pdp10 | pdp11 | pj | pjl \ | ||||
| 	| powerpc | powerpc64 | powerpc64le | powerpcle \ | ||||
| 	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | ||||
| 	| pyramid \ | ||||
| 	| rl78 | rx \ | ||||
| 	| score \ | ||||
| 	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | ||||
| 	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | ||||
| 	| sh64 | sh64le \ | ||||
| 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | ||||
| 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | ||||
| 	| spu \ | ||||
| 	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ||||
| 	| ubicom32 \ | ||||
| 	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | ||||
| 	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | ||||
| 	| strongarm \ | ||||
| 	| tahoe | thumb | tic4x | tic80 | tron \ | ||||
| 	| v850 | v850e \ | ||||
| 	| we32k \ | ||||
| 	| x86 | xc16x | xstormy16 | xtensa \ | ||||
| 	| z8k | z80) | ||||
| 	| x86 | xscale | xstormy16 | xtensa \ | ||||
| 	| z8k) | ||||
| 		basic_machine=$basic_machine-unknown | ||||
| 		;; | ||||
| 	c54x) | ||||
| 		basic_machine=tic54x-unknown | ||||
| 		;; | ||||
| 	c55x) | ||||
| 		basic_machine=tic55x-unknown | ||||
| 		;; | ||||
| 	c6x) | ||||
| 		basic_machine=tic6x-unknown | ||||
| 		;; | ||||
| 	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) | ||||
| 	m6811 | m68hc11 | m6812 | m68hc12) | ||||
| 		# Motorola 68HC11/12. | ||||
| 		basic_machine=$basic_machine-unknown | ||||
| 		os=-none | ||||
| 		;; | ||||
| 	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' | ||||
| 	# 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. | ||||
| 	580-* \ | ||||
| 	| a29k-* \ | ||||
| 	| aarch64-* | aarch64_be-* \ | ||||
| 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | ||||
| 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | ||||
| 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | ||||
| 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | ||||
| 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \ | ||||
| 	| avr-* | avr32-* \ | ||||
| 	| be32-* | be64-* \ | ||||
| 	| bfin-* | bs2000-* \ | ||||
| 	| c[123]* | c30-* | [cjt]90-* | c4x-* \ | ||||
| 	| c8051-* | clipper-* | craynv-* | cydra-* \ | ||||
| 	| avr-* \ | ||||
| 	| bs2000-* \ | ||||
| 	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | ||||
| 	| clipper-* | cydra-* \ | ||||
| 	| d10v-* | d30v-* | dlx-* \ | ||||
| 	| elxsi-* \ | ||||
| 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | ||||
| 	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | ||||
| 	| h8300-* | h8500-* \ | ||||
| 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | ||||
| 	| hexagon-* \ | ||||
| 	| i*86-* | i860-* | i960-* | ia64-* \ | ||||
| 	| ip2k-* | iq2000-* \ | ||||
| 	| k1om-* \ | ||||
| 	| le32-* | le64-* \ | ||||
| 	| lm32-* \ | ||||
| 	| m32c-* | m32r-* | m32rle-* \ | ||||
| 	| ip2k-* \ | ||||
| 	| m32r-* \ | ||||
| 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | ||||
| 	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | ||||
| 	| microblaze-* | microblazeel-* \ | ||||
| 	| m88110-* | m88k-* | mcore-* \ | ||||
| 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | ||||
| 	| mips16-* \ | ||||
| 	| mips64-* | mips64el-* \ | ||||
| 	| mips64octeon-* | mips64octeonel-* \ | ||||
| 	| mips64orion-* | mips64orionel-* \ | ||||
| 	| mips64r5900-* | mips64r5900el-* \ | ||||
| 	| mips64vr-* | mips64vrel-* \ | ||||
| 	| mips64orion-* | mips64orionel-* \ | ||||
| 	| mips64vr4100-* | mips64vr4100el-* \ | ||||
| 	| mips64vr4300-* | mips64vr4300el-* \ | ||||
| 	| mips64vr5000-* | mips64vr5000el-* \ | ||||
| 	| mips64vr5900-* | mips64vr5900el-* \ | ||||
| 	| mipsisa32-* | mipsisa32el-* \ | ||||
| 	| mipsisa32r2-* | mipsisa32r2el-* \ | ||||
| 	| mipsisa64-* | mipsisa64el-* \ | ||||
| 	| mipsisa64r2-* | mipsisa64r2el-* \ | ||||
| 	| mipsisa64sb1-* | mipsisa64sb1el-* \ | ||||
| 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \ | ||||
| 	| mipsr5900-* | mipsr5900el-* \ | ||||
| 	| mipstx39-* | mipstx39el-* \ | ||||
| 	| mmix-* \ | ||||
| 	| mt-* \ | ||||
| 	| msp430-* \ | ||||
| 	| nds32-* | nds32le-* | nds32be-* \ | ||||
| 	| nios-* | nios2-* | nios2eb-* | nios2el-* \ | ||||
| 	| none-* | np1-* | ns16k-* | ns32k-* \ | ||||
| 	| open8-* \ | ||||
| 	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | ||||
| 	| orion-* \ | ||||
| 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | ||||
| 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | ||||
| 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | ||||
| 	| pyramid-* \ | ||||
| 	| rl78-* | romp-* | rs6000-* | rx-* \ | ||||
| 	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | ||||
| 	| romp-* | rs6000-* \ | ||||
| 	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | ||||
| 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | ||||
| 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | ||||
| 	| sparclite-* \ | ||||
| 	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | ||||
| 	| tahoe-* \ | ||||
| 	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | ||||
| 	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | ||||
| 	| tahoe-* | thumb-* \ | ||||
| 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | ||||
| 	| tile*-* \ | ||||
| 	| tron-* \ | ||||
| 	| ubicom32-* \ | ||||
| 	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | ||||
| 	| vax-* \ | ||||
| 	| v850-* | v850e-* | vax-* \ | ||||
| 	| we32k-* \ | ||||
| 	| x86-* | x86_64-* | xc16x-* | xps100-* \ | ||||
| 	| xstormy16-* | xtensa*-* \ | ||||
| 	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | ||||
| 	| xtensa-* \ | ||||
| 	| ymp-* \ | ||||
| 	| z8k-* | z80-*) | ||||
| 		;; | ||||
| 	# Recognize the basic CPU types without company name, with glob match. | ||||
| 	xtensa*) | ||||
| 		basic_machine=$basic_machine-unknown | ||||
| 	| z8k-*) | ||||
| 		;; | ||||
| 	# Recognize the various machine names and aliases which stand | ||||
| 	# for a CPU type and a company and sometimes even an OS. | ||||
| @@ -458,9 +359,6 @@ case $basic_machine in | ||||
| 		basic_machine=a29k-amd | ||||
| 		os=-udi | ||||
| 		;; | ||||
| 	abacus) | ||||
| 		basic_machine=abacus-unknown | ||||
| 		;; | ||||
| 	adobe68k) | ||||
| 		basic_machine=m68010-adobe | ||||
| 		os=-scout | ||||
| @@ -478,9 +376,6 @@ case $basic_machine in | ||||
| 	amd64) | ||||
| 		basic_machine=x86_64-pc | ||||
| 		;; | ||||
| 	amd64-*) | ||||
| 		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` | ||||
| 		;; | ||||
| 	amdahl) | ||||
| 		basic_machine=580-amdahl | ||||
| 		os=-sysv | ||||
| @@ -504,10 +399,6 @@ case $basic_machine in | ||||
| 		basic_machine=m68k-apollo | ||||
| 		os=-bsd | ||||
| 		;; | ||||
| 	aros) | ||||
| 		basic_machine=i386-pc | ||||
| 		os=-aros | ||||
| 		;; | ||||
| 	aux) | ||||
| 		basic_machine=m68k-apple | ||||
| 		os=-aux | ||||
| @@ -516,35 +407,10 @@ case $basic_machine in | ||||
| 		basic_machine=ns32k-sequent | ||||
| 		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) | ||||
| 		basic_machine=c90-cray | ||||
| 		os=-unicos | ||||
| 		;; | ||||
| 	cegcc) | ||||
| 		basic_machine=arm-unknown | ||||
| 		os=-cegcc | ||||
| 		;; | ||||
| 	convex-c1) | ||||
| 		basic_machine=c1-convex | ||||
| 		os=-bsd | ||||
| @@ -569,27 +435,12 @@ case $basic_machine in | ||||
| 		basic_machine=j90-cray | ||||
| 		os=-unicos | ||||
| 		;; | ||||
| 	craynv) | ||||
| 		basic_machine=craynv-cray | ||||
| 		os=-unicosmp | ||||
| 		;; | ||||
| 	cr16 | cr16-*) | ||||
| 		basic_machine=cr16-unknown | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	crds | unos) | ||||
| 		basic_machine=m68k-crds | ||||
| 		;; | ||||
| 	crisv32 | crisv32-* | etraxfs*) | ||||
| 		basic_machine=crisv32-axis | ||||
| 		;; | ||||
| 	cris | cris-* | etrax*) | ||||
| 		basic_machine=cris-axis | ||||
| 		;; | ||||
| 	crx) | ||||
| 		basic_machine=crx-unknown | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	da30 | da30-*) | ||||
| 		basic_machine=m68k-da30 | ||||
| 		;; | ||||
| @@ -612,14 +463,6 @@ case $basic_machine in | ||||
| 		basic_machine=m88k-motorola | ||||
| 		os=-sysv3 | ||||
| 		;; | ||||
| 	dicos) | ||||
| 		basic_machine=i686-pc | ||||
| 		os=-dicos | ||||
| 		;; | ||||
| 	djgpp) | ||||
| 		basic_machine=i586-pc | ||||
| 		os=-msdosdjgpp | ||||
| 		;; | ||||
| 	dpx20 | dpx20-*) | ||||
| 		basic_machine=rs6000-bull | ||||
| 		os=-bosx | ||||
| @@ -731,6 +574,7 @@ case $basic_machine in | ||||
| 	i370-ibm* | ibm*) | ||||
| 		basic_machine=i370-ibm | ||||
| 		;; | ||||
| # I'm not sure what "Sysv32" means.  Should this be sysv3.2? | ||||
| 	i*86v32) | ||||
| 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` | ||||
| 		os=-sysv32 | ||||
| @@ -769,14 +613,6 @@ case $basic_machine in | ||||
| 		basic_machine=m68k-isi | ||||
| 		os=-sysv | ||||
| 		;; | ||||
| 	m68knommu) | ||||
| 		basic_machine=m68k-unknown | ||||
| 		os=-linux | ||||
| 		;; | ||||
| 	m68knommu-*) | ||||
| 		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` | ||||
| 		os=-linux | ||||
| 		;; | ||||
| 	m88k-omron*) | ||||
| 		basic_machine=m88k-omron | ||||
| 		;; | ||||
| @@ -788,21 +624,10 @@ case $basic_machine in | ||||
| 		basic_machine=ns32k-utek | ||||
| 		os=-sysv | ||||
| 		;; | ||||
| 	microblaze*) | ||||
| 		basic_machine=microblaze-xilinx | ||||
| 		;; | ||||
| 	mingw64) | ||||
| 		basic_machine=x86_64-pc | ||||
| 		os=-mingw64 | ||||
| 		;; | ||||
| 	mingw32) | ||||
| 		basic_machine=i686-pc | ||||
| 		basic_machine=i386-pc | ||||
| 		os=-mingw32 | ||||
| 		;; | ||||
| 	mingw32ce) | ||||
| 		basic_machine=arm-unknown | ||||
| 		os=-mingw32ce | ||||
| 		;; | ||||
| 	miniframe) | ||||
| 		basic_machine=m68000-convergent | ||||
| 		;; | ||||
| @@ -816,6 +641,10 @@ case $basic_machine in | ||||
| 	mips3*) | ||||
| 		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown | ||||
| 		;; | ||||
| 	mmix*) | ||||
| 		basic_machine=mmix-knuth | ||||
| 		os=-mmixware | ||||
| 		;; | ||||
| 	monitor) | ||||
| 		basic_machine=m68k-rom68k | ||||
| 		os=-coff | ||||
| @@ -828,21 +657,10 @@ case $basic_machine in | ||||
| 		basic_machine=i386-pc | ||||
| 		os=-msdos | ||||
| 		;; | ||||
| 	ms1-*) | ||||
| 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` | ||||
| 		;; | ||||
| 	msys) | ||||
| 		basic_machine=i686-pc | ||||
| 		os=-msys | ||||
| 		;; | ||||
| 	mvs) | ||||
| 		basic_machine=i370-ibm | ||||
| 		os=-mvs | ||||
| 		;; | ||||
| 	nacl) | ||||
| 		basic_machine=le32-unknown | ||||
| 		os=-nacl | ||||
| 		;; | ||||
| 	ncr3000) | ||||
| 		basic_machine=i486-ncr | ||||
| 		os=-sysv4 | ||||
| @@ -907,11 +725,9 @@ case $basic_machine in | ||||
| 	np1) | ||||
| 		basic_machine=np1-gould | ||||
| 		;; | ||||
| 	neo-tandem) | ||||
| 		basic_machine=neo-tandem | ||||
| 		;; | ||||
| 	nse-tandem) | ||||
| 		basic_machine=nse-tandem | ||||
| 	nv1) | ||||
| 		basic_machine=nv1-cray | ||||
| 		os=-unicosmp | ||||
| 		;; | ||||
| 	nsr-tandem) | ||||
| 		basic_machine=nsr-tandem | ||||
| @@ -920,12 +736,9 @@ case $basic_machine in | ||||
| 		basic_machine=hppa1.1-oki | ||||
| 		os=-proelf | ||||
| 		;; | ||||
| 	openrisc | openrisc-*) | ||||
| 	or32 | or32-*) | ||||
| 		basic_machine=or32-unknown | ||||
| 		;; | ||||
| 	os400) | ||||
| 		basic_machine=powerpc-ibm | ||||
| 		os=-os400 | ||||
| 		os=-coff | ||||
| 		;; | ||||
| 	OSE68000 | ose68000) | ||||
| 		basic_machine=m68000-ericsson | ||||
| @@ -943,14 +756,6 @@ case $basic_machine in | ||||
| 		basic_machine=i860-intel | ||||
| 		os=-osf | ||||
| 		;; | ||||
| 	parisc) | ||||
| 		basic_machine=hppa-unknown | ||||
| 		os=-linux | ||||
| 		;; | ||||
| 	parisc-*) | ||||
| 		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` | ||||
| 		os=-linux | ||||
| 		;; | ||||
| 	pbd) | ||||
| 		basic_machine=sparc-tti | ||||
| 		;; | ||||
| @@ -960,12 +765,6 @@ case $basic_machine in | ||||
| 	pc532 | pc532-*) | ||||
| 		basic_machine=ns32k-pc532 | ||||
| 		;; | ||||
| 	pc98) | ||||
| 		basic_machine=i386-pc | ||||
| 		;; | ||||
| 	pc98-*) | ||||
| 		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` | ||||
| 		;; | ||||
| 	pentium | p5 | k5 | k6 | nexgen | viac3) | ||||
| 		basic_machine=i586-pc | ||||
| 		;; | ||||
| @@ -995,10 +794,9 @@ case $basic_machine in | ||||
| 		;; | ||||
| 	power)	basic_machine=power-ibm | ||||
| 		;; | ||||
| 	ppc | ppcbe)	basic_machine=powerpc-unknown | ||||
| 	ppc)	basic_machine=powerpc-unknown | ||||
| 		;; | ||||
| 	ppc-* | ppcbe-*) | ||||
| 		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` | ||||
| 	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` | ||||
| 		;; | ||||
| 	ppcle | powerpclittle | ppc-le | powerpc-little) | ||||
| 		basic_machine=powerpcle-unknown | ||||
| @@ -1023,14 +821,6 @@ case $basic_machine in | ||||
| 		basic_machine=i586-unknown | ||||
| 		os=-pw32 | ||||
| 		;; | ||||
| 	rdos | rdos64) | ||||
| 		basic_machine=x86_64-pc | ||||
| 		os=-rdos | ||||
| 		;; | ||||
| 	rdos32) | ||||
| 		basic_machine=i386-pc | ||||
| 		os=-rdos | ||||
| 		;; | ||||
| 	rom68k) | ||||
| 		basic_machine=m68k-rom68k | ||||
| 		os=-coff | ||||
| @@ -1057,10 +847,6 @@ case $basic_machine in | ||||
| 	sb1el) | ||||
| 		basic_machine=mipsisa64sb1el-unknown | ||||
| 		;; | ||||
| 	sde) | ||||
| 		basic_machine=mipsisa32-sde | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	sei) | ||||
| 		basic_machine=mips-sei | ||||
| 		os=-seiux | ||||
| @@ -1072,9 +858,6 @@ case $basic_machine in | ||||
| 		basic_machine=sh-hitachi | ||||
| 		os=-hms | ||||
| 		;; | ||||
| 	sh5el) | ||||
| 		basic_machine=sh5le-unknown | ||||
| 		;; | ||||
| 	sh64) | ||||
| 		basic_machine=sh64-unknown | ||||
| 		;; | ||||
| @@ -1096,9 +879,6 @@ case $basic_machine in | ||||
| 		basic_machine=i860-stratus | ||||
| 		os=-sysv4 | ||||
| 		;; | ||||
| 	strongarm-* | thumb-*) | ||||
| 		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` | ||||
| 		;; | ||||
| 	sun2) | ||||
| 		basic_machine=m68000-sun | ||||
| 		;; | ||||
| @@ -1155,9 +935,17 @@ case $basic_machine in | ||||
| 		basic_machine=t90-cray | ||||
| 		os=-unicos | ||||
| 		;; | ||||
| 	tile*) | ||||
| 		basic_machine=$basic_machine-unknown | ||||
| 		os=-linux-gnu | ||||
| 	tic54x | c54x*) | ||||
| 		basic_machine=tic54x-unknown | ||||
| 		os=-coff | ||||
| 		;; | ||||
| 	tic55x | c55x*) | ||||
| 		basic_machine=tic55x-unknown | ||||
| 		os=-coff | ||||
| 		;; | ||||
| 	tic6x | c6x*) | ||||
| 		basic_machine=tic6x-unknown | ||||
| 		os=-coff | ||||
| 		;; | ||||
| 	tx39) | ||||
| 		basic_machine=mipstx39-unknown | ||||
| @@ -1172,10 +960,6 @@ case $basic_machine in | ||||
| 	tower | tower-32) | ||||
| 		basic_machine=m68k-ncr | ||||
| 		;; | ||||
| 	tpf) | ||||
| 		basic_machine=s390x-ibm | ||||
| 		os=-tpf | ||||
| 		;; | ||||
| 	udi29k) | ||||
| 		basic_machine=a29k-amd | ||||
| 		os=-udi | ||||
| @@ -1219,16 +1003,9 @@ case $basic_machine in | ||||
| 		basic_machine=hppa1.1-winbond | ||||
| 		os=-proelf | ||||
| 		;; | ||||
| 	xbox) | ||||
| 		basic_machine=i686-pc | ||||
| 		os=-mingw32 | ||||
| 		;; | ||||
| 	xps | xps100) | ||||
| 		basic_machine=xps100-honeywell | ||||
| 		;; | ||||
| 	xscale-* | xscalee[bl]-*) | ||||
| 		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` | ||||
| 		;; | ||||
| 	ymp) | ||||
| 		basic_machine=ymp-cray | ||||
| 		os=-unicos | ||||
| @@ -1237,10 +1014,6 @@ case $basic_machine in | ||||
| 		basic_machine=z8k-unknown | ||||
| 		os=-sim | ||||
| 		;; | ||||
| 	z80-*-coff) | ||||
| 		basic_machine=z80-unknown | ||||
| 		os=-sim | ||||
| 		;; | ||||
| 	none) | ||||
| 		basic_machine=none-none | ||||
| 		os=-none | ||||
| @@ -1260,9 +1033,6 @@ case $basic_machine in | ||||
| 	romp) | ||||
| 		basic_machine=romp-ibm | ||||
| 		;; | ||||
| 	mmix) | ||||
| 		basic_machine=mmix-knuth | ||||
| 		;; | ||||
| 	rs6000) | ||||
| 		basic_machine=rs6000-ibm | ||||
| 		;; | ||||
| @@ -1279,10 +1049,13 @@ case $basic_machine in | ||||
| 	we32k) | ||||
| 		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 | ||||
| 		;; | ||||
| 	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) | ||||
| 	sh64) | ||||
| 		basic_machine=sh64-unknown | ||||
| 		;; | ||||
| 	sparc | sparcv9 | sparcv9b) | ||||
| 		basic_machine=sparc-sun | ||||
| 		;; | ||||
| 	cydra) | ||||
| @@ -1326,12 +1099,9 @@ esac | ||||
| if [ x"$os" != x"" ] | ||||
| then | ||||
| case $os in | ||||
| 	# First match some system type aliases | ||||
| 	# that might get confused with valid system types. | ||||
|         # First match some system type aliases | ||||
|         # that might get confused with valid system types. | ||||
| 	# -solaris* is a basic system type, with this one exception. | ||||
| 	-auroraux) | ||||
| 		os=-auroraux | ||||
| 		;; | ||||
| 	-solaris1 | -solaris1.*) | ||||
| 		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. | ||||
| 	# -sysv* is not here because it comes later, after sysvr4. | ||||
| 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | ||||
| 	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | ||||
| 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | ||||
| 	      | -sym* | -kopensolaris* | -plan9* \ | ||||
| 	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | ||||
| 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | ||||
| 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | ||||
| 	      | -aos* | -aros* \ | ||||
| 	      | -aos* \ | ||||
| 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | ||||
| 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | ||||
| 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | ||||
| 	      | -bitrig* | -openbsd* | -solidbsd* \ | ||||
| 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | ||||
| 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | ||||
| 	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | ||||
| 	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | ||||
| 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | ||||
| 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | ||||
| 	      | -chorusos* | -chorusrdb* | -cegcc* \ | ||||
| 	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | ||||
| 	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | ||||
| 	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | ||||
| 	      | -uxpv* | -beos* | -mpeix* | -udk* \ | ||||
| 	      | -chorusos* | -chorusrdb* \ | ||||
| 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | ||||
| 	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | ||||
| 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | ||||
| 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | ||||
| 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | ||||
| 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | ||||
| 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | ||||
| 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | ||||
| 	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) | ||||
| 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei*) | ||||
| 	# Remember, each alternative MUST END IN *, to match a version number. | ||||
| 		;; | ||||
| 	-qnx*) | ||||
| @@ -1394,15 +1158,12 @@ case $os in | ||||
| 		os=`echo $os | sed -e 's|nto|nto-qnx|'` | ||||
| 		;; | ||||
| 	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | ||||
| 	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | ||||
| 	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | ||||
| 	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) | ||||
| 		;; | ||||
| 	-mac*) | ||||
| 		os=`echo $os | sed -e 's|mac|macos|'` | ||||
| 		;; | ||||
| 	-linux-dietlibc) | ||||
| 		os=-linux-dietlibc | ||||
| 		;; | ||||
| 	-linux*) | ||||
| 		os=`echo $os | sed -e 's|linux|linux-gnu|'` | ||||
| 		;; | ||||
| @@ -1415,9 +1176,6 @@ case $os in | ||||
| 	-opened*) | ||||
| 		os=-openedition | ||||
| 		;; | ||||
| 	-os400*) | ||||
| 		os=-os400 | ||||
| 		;; | ||||
| 	-wince*) | ||||
| 		os=-wince | ||||
| 		;; | ||||
| @@ -1439,9 +1197,6 @@ case $os in | ||||
| 	-atheos*) | ||||
| 		os=-atheos | ||||
| 		;; | ||||
| 	-syllable*) | ||||
| 		os=-syllable | ||||
| 		;; | ||||
| 	-386bsd) | ||||
| 		os=-bsd | ||||
| 		;; | ||||
| @@ -1464,9 +1219,6 @@ case $os in | ||||
| 	-sinix*) | ||||
| 		os=-sysv4 | ||||
| 		;; | ||||
| 	-tpf*) | ||||
| 		os=-tpf | ||||
| 		;; | ||||
| 	-triton*) | ||||
| 		os=-sysv3 | ||||
| 		;; | ||||
| @@ -1500,13 +1252,8 @@ case $os in | ||||
| 	-aros*) | ||||
| 		os=-aros | ||||
| 		;; | ||||
| 	-zvmoe) | ||||
| 		os=-zvmoe | ||||
| 		;; | ||||
| 	-dicos*) | ||||
| 		os=-dicos | ||||
| 		;; | ||||
| 	-nacl*) | ||||
| 	-kaos*) | ||||
| 		os=-kaos | ||||
| 		;; | ||||
| 	-none) | ||||
| 		;; | ||||
| @@ -1530,12 +1277,6 @@ else | ||||
| # system, and we'll never get to this point. | ||||
|  | ||||
| case $basic_machine in | ||||
| 	score-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	spu-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	*-acorn) | ||||
| 		os=-riscix1.2 | ||||
| 		;; | ||||
| @@ -1545,24 +1286,9 @@ case $basic_machine in | ||||
| 	arm*-semi) | ||||
| 		os=-aout | ||||
| 		;; | ||||
| 	c4x-* | tic4x-*) | ||||
| 		os=-coff | ||||
| 		;; | ||||
| 	c8051-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	hexagon-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	tic54x-*) | ||||
| 		os=-coff | ||||
| 		;; | ||||
| 	tic55x-*) | ||||
| 		os=-coff | ||||
| 		;; | ||||
| 	tic6x-*) | ||||
| 		os=-coff | ||||
| 		;; | ||||
|     c4x-* | tic4x-*) | ||||
|         os=-coff | ||||
|         ;; | ||||
| 	# This must come before the *-dec entry. | ||||
| 	pdp10-*) | ||||
| 		os=-tops20 | ||||
| @@ -1581,22 +1307,19 @@ case $basic_machine in | ||||
| 		;; | ||||
| 	m68000-sun) | ||||
| 		os=-sunos3 | ||||
| 		# This also exists in the configure program, but was not the | ||||
| 		# default. | ||||
| 		# os=-sunos4 | ||||
| 		;; | ||||
| 	m68*-cisco) | ||||
| 		os=-aout | ||||
| 		;; | ||||
| 	mep-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	mips*-cisco) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	mips*-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	or1k-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	or32-*) | ||||
| 		os=-coff | ||||
| 		;; | ||||
| @@ -1609,15 +1332,9 @@ case $basic_machine in | ||||
| 	*-be) | ||||
| 		os=-beos | ||||
| 		;; | ||||
| 	*-haiku) | ||||
| 		os=-haiku | ||||
| 		;; | ||||
| 	*-ibm) | ||||
| 		os=-aix | ||||
| 		;; | ||||
| 	*-knuth) | ||||
| 		os=-mmixware | ||||
| 		;; | ||||
| 	*-wec) | ||||
| 		os=-proelf | ||||
| 		;; | ||||
| @@ -1720,7 +1437,7 @@ case $basic_machine in | ||||
| 			-sunos*) | ||||
| 				vendor=sun | ||||
| 				;; | ||||
| 			-cnk*|-aix*) | ||||
| 			-aix*) | ||||
| 				vendor=ibm | ||||
| 				;; | ||||
| 			-beos*) | ||||
| @@ -1750,15 +1467,9 @@ case $basic_machine in | ||||
| 			-mvs* | -opened*) | ||||
| 				vendor=ibm | ||||
| 				;; | ||||
| 			-os400*) | ||||
| 				vendor=ibm | ||||
| 				;; | ||||
| 			-ptx*) | ||||
| 				vendor=sequent | ||||
| 				;; | ||||
| 			-tpf*) | ||||
| 				vendor=ibm | ||||
| 				;; | ||||
| 			-vxsim* | -vxworks* | -windiss*) | ||||
| 				vendor=wrs | ||||
| 				;; | ||||
| @@ -1783,7 +1494,7 @@ case $basic_machine in | ||||
| esac | ||||
|  | ||||
| echo $basic_machine$os | ||||
| exit | ||||
| exit 0 | ||||
|  | ||||
| # Local variables: | ||||
| # eval: (add-hook 'write-file-hooks 'time-stamp) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| #!/bin/sh | ||||
| # 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 | ||||
| # 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. | ||||
| # | ||||
| # This script is compatible with the BSD install script, but was written | ||||
| # from scratch. | ||||
|  | ||||
| nl=' | ||||
| ' | ||||
| IFS=" ""	$nl" | ||||
| # from scratch.  It can only install one file at a time, a restriction | ||||
| # shared with many OS's install programs. | ||||
|  | ||||
| # set DOITPROG to echo to test this script | ||||
|  | ||||
| # Don't use :- since 4.3BSD and earlier shells don't like it. | ||||
| doit="${DOITPROG-}" | ||||
| 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; | ||||
| # or use environment vars. | ||||
| # put in absolute paths if you don't have them in your path; or use env. vars. | ||||
|  | ||||
| mvprog="${MVPROG-mv}" | ||||
| cpprog="${CPPROG-cp}" | ||||
| @@ -67,13 +58,10 @@ stripprog="${STRIPPROG-strip}" | ||||
| rmprog="${RMPROG-rm}" | ||||
| mkdirprog="${MKDIRPROG-mkdir}" | ||||
|  | ||||
| posix_glob= | ||||
| posix_mkdir= | ||||
|  | ||||
| # Desired mode of installed file. | ||||
| mode=0755 | ||||
|  | ||||
| chmodcmd=$chmodprog | ||||
| transformbasename= | ||||
| transform_arg= | ||||
| instcmd="$mvprog" | ||||
| chmodcmd="$chmodprog 0755" | ||||
| chowncmd= | ||||
| chgrpcmd= | ||||
| stripcmd= | ||||
| @@ -82,27 +70,22 @@ mvcmd="$mvprog" | ||||
| src= | ||||
| dst= | ||||
| dir_arg= | ||||
| dstarg= | ||||
| no_target_directory= | ||||
|  | ||||
| usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE | ||||
|    or: $0 [OPTION]... SRCFILES... DIRECTORY | ||||
|    or: $0 [OPTION]... -t DIRECTORY SRCFILES... | ||||
|    or: $0 [OPTION]... -d DIRECTORIES... | ||||
| usage="Usage: $0 [OPTION]... SRCFILE DSTFILE | ||||
|    or: $0 -d DIR1 DIR2... | ||||
|  | ||||
| In the 1st form, copy SRCFILE to DSTFILE. | ||||
| In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. | ||||
| In the 4th, create DIRECTORIES. | ||||
| In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default. | ||||
| In the second, create the directory path DIR. | ||||
|  | ||||
| Options: | ||||
| -c         (ignored) | ||||
| -b=TRANSFORMBASENAME | ||||
| -c         copy source (using $cpprog) instead of moving (using $mvprog). | ||||
| -d         create directories instead of installing files. | ||||
| -g GROUP   $chgrpprog installed files to GROUP. | ||||
| -m MODE    $chmodprog installed files to MODE. | ||||
| -o USER    $chownprog installed files to USER. | ||||
| -s         $stripprog installed files. | ||||
| -t DIRECTORY  install into DIRECTORY. | ||||
| -T         report an error if DSTFILE is a directory. | ||||
| -g GROUP   $chgrp installed files to GROUP. | ||||
| -m MODE    $chmod installed files to MODE. | ||||
| -o USER    $chown installed files to USER. | ||||
| -s         strip installed files (using $stripprog). | ||||
| -t=TRANSFORM | ||||
| --help     display this help and exit. | ||||
| --version  display version info and exit. | ||||
|  | ||||
| @@ -110,9 +93,14 @@ Environment variables override the default commands: | ||||
|   CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG | ||||
| " | ||||
|  | ||||
| while test $# -ne 0; do | ||||
| while test -n "$1"; do | ||||
|   case $1 in | ||||
|     -c) shift | ||||
|     -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | ||||
|         shift | ||||
|         continue;; | ||||
|  | ||||
|     -c) instcmd=$cpprog | ||||
|         shift | ||||
|         continue;; | ||||
|  | ||||
|     -d) dir_arg=true | ||||
| @@ -124,17 +112,11 @@ while test $# -ne 0; do | ||||
|         shift | ||||
|         continue;; | ||||
|  | ||||
|     --help) echo "$usage"; exit $?;; | ||||
|     --help) echo "$usage"; exit 0;; | ||||
|  | ||||
|     -m) mode=$2 | ||||
|     -m) chmodcmd="$chmodprog $2" | ||||
|         shift | ||||
|         shift | ||||
| 	case $mode in | ||||
| 	  *' '* | *'	'* | *' | ||||
| '*	  | *'*'* | *'?'* | *'['*) | ||||
| 	    echo "$0: invalid mode: $mode" >&2 | ||||
| 	    exit 1;; | ||||
| 	esac | ||||
|         continue;; | ||||
|  | ||||
|     -o) chowncmd="$chownprog $2" | ||||
| @@ -146,358 +128,155 @@ while test $# -ne 0; do | ||||
|         shift | ||||
|         continue;; | ||||
|  | ||||
|     -t) dstarg=$2 | ||||
| 	shift | ||||
| 	shift | ||||
| 	continue;; | ||||
|     -t=*) transformarg=`echo $1 | sed 's/-t=//'` | ||||
|         shift | ||||
|         continue;; | ||||
|  | ||||
|     -T) no_target_directory=true | ||||
| 	shift | ||||
| 	continue;; | ||||
|     --version) echo "$0 $scriptversion"; exit 0;; | ||||
|  | ||||
|     --version) echo "$0 $scriptversion"; exit $?;; | ||||
|  | ||||
|     --)	shift | ||||
| 	break;; | ||||
|  | ||||
|     -*)	echo "$0: invalid option: $1" >&2 | ||||
| 	exit 1;; | ||||
|  | ||||
|     *)  break;; | ||||
|     *)  if test -z "$src"; then | ||||
|           src=$1 | ||||
|         else | ||||
|           # this colon is to work around a 386BSD /bin/sh bug | ||||
|           : | ||||
|           dst=$1 | ||||
|         fi | ||||
|         shift | ||||
|         continue;; | ||||
|   esac | ||||
| done | ||||
|  | ||||
| if test $# -ne 0 && test -z "$dir_arg$dstarg"; then | ||||
|   # When -d is used, all remaining arguments are directories to create. | ||||
|   # When -t is used, the destination is already specified. | ||||
|   # Otherwise, the last argument is the destination.  Remove it from $@. | ||||
|   for arg | ||||
|   do | ||||
|     if test -n "$dstarg"; then | ||||
|       # $@ is not empty: it contains at least $arg. | ||||
|       set fnord "$@" "$dstarg" | ||||
|       shift # fnord | ||||
|     fi | ||||
|     shift # arg | ||||
|     dstarg=$arg | ||||
| if test -z "$src"; then | ||||
|   echo "$0: no input file specified." >&2 | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| if test -n "$dir_arg"; then | ||||
|   dst=$src | ||||
|   src= | ||||
|  | ||||
|   if test -d "$dst"; then | ||||
|     instcmd=: | ||||
|     chmodcmd= | ||||
|   else | ||||
|     instcmd=$mkdirprog | ||||
|   fi | ||||
| else | ||||
|   # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | ||||
|   # might cause directories to be created, which would be especially bad | ||||
|   # if $src (and thus $dsttmp) contains '*'. | ||||
|   if test ! -f "$src" && test ! -d "$src"; then | ||||
|     echo "$0: $src does not exist." >&2 | ||||
|     exit 1 | ||||
|   fi | ||||
|  | ||||
|   if test -z "$dst"; then | ||||
|     echo "$0: no destination specified." >&2 | ||||
|     exit 1 | ||||
|   fi | ||||
|  | ||||
|   # If destination is a directory, append the input filename; won't work | ||||
|   # if double slashes aren't ignored. | ||||
|   if test -d "$dst"; then | ||||
|     dst=$dst/`basename "$src"` | ||||
|   fi | ||||
| fi | ||||
|  | ||||
| ## this sed command emulates the dirname command | ||||
| dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | ||||
|  | ||||
| # Make sure that the destination directory exists. | ||||
| # (this part is taken from Noah Friedman's mkinstalldirs script.) | ||||
|  | ||||
| # Skip lots of stat calls in the usual case. | ||||
| if test ! -d "$dstdir"; then | ||||
|   defaultIFS=' | ||||
| 	' | ||||
|   IFS="${IFS-$defaultIFS}" | ||||
|  | ||||
|   oIFS=$IFS | ||||
|   # Some sh's can't handle IFS=/ for some reason. | ||||
|   IFS='%' | ||||
|   set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` | ||||
|   IFS=$oIFS | ||||
|  | ||||
|   pathcomp= | ||||
|  | ||||
|   while test $# -ne 0 ; do | ||||
|     pathcomp=$pathcomp$1 | ||||
|     shift | ||||
|     test -d "$pathcomp" || $mkdirprog "$pathcomp" | ||||
|     pathcomp=$pathcomp/ | ||||
|   done | ||||
| fi | ||||
|  | ||||
| if test $# -eq 0; then | ||||
|   if test -z "$dir_arg"; then | ||||
|     echo "$0: no input file specified." >&2 | ||||
|     exit 1 | ||||
|   fi | ||||
|   # It's OK to call `install-sh -d' without argument. | ||||
|   # This can happen when creating conditional directories. | ||||
|   exit 0 | ||||
| fi | ||||
| if test -n "$dir_arg"; then | ||||
|   $doit $instcmd "$dst" \ | ||||
|     && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ | ||||
|     && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ | ||||
|     && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ | ||||
|     && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } | ||||
|  | ||||
| if 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 | ||||
|  | ||||
|   # Set umask so as not to create temps with too-generous modes. | ||||
|   # However, 'strip' requires both read and write access to temps. | ||||
|   case $mode in | ||||
|     # Optimize common cases. | ||||
|     *644) cp_umask=133;; | ||||
|     *755) cp_umask=22;; | ||||
|   # Move or copy the file name to the temp name | ||||
|   $doit $instcmd "$src" "$dsttmp" && | ||||
|  | ||||
|     *[0-7]) | ||||
|       if test -z "$stripcmd"; then | ||||
| 	u_plus_rw= | ||||
|       else | ||||
| 	u_plus_rw='% 200' | ||||
|       fi | ||||
|       cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; | ||||
|     *) | ||||
|       if test -z "$stripcmd"; then | ||||
| 	u_plus_rw= | ||||
|       else | ||||
| 	u_plus_rw=,u+rw | ||||
|       fi | ||||
|       cp_umask=$mode$u_plus_rw;; | ||||
|   esac | ||||
| fi | ||||
|   # and set any options; do chmod last to preserve setuid bits. | ||||
|   # | ||||
|   # If any of these fail, we abort the whole thing.  If we want to | ||||
|   # ignore errors from any of these, just make sure not to ignore | ||||
|   # errors from the above "$doit $instcmd $src $dsttmp" command. | ||||
|   # | ||||
|   { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ | ||||
|     && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ | ||||
|     && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ | ||||
|     && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && | ||||
|  | ||||
| for src | ||||
| do | ||||
|   # Protect names starting with `-'. | ||||
|   case $src in | ||||
|     -*) src=./$src ;; | ||||
|   esac | ||||
|  | ||||
|   if test -n "$dir_arg"; then | ||||
|     dst=$src | ||||
|     dstdir=$dst | ||||
|     test -d "$dstdir" | ||||
|     dstdir_status=$? | ||||
|   else | ||||
|  | ||||
|     # Waiting for this to be detected by the "$cpprog $src $dsttmp" command | ||||
|     # might cause directories to be created, which would be especially bad | ||||
|     # if $src (and thus $dsttmp) contains '*'. | ||||
|     if test ! -f "$src" && test ! -d "$src"; then | ||||
|       echo "$0: $src does not exist." >&2 | ||||
|       exit 1 | ||||
|     fi | ||||
|  | ||||
|     if test -z "$dstarg"; then | ||||
|       echo "$0: no destination specified." >&2 | ||||
|       exit 1 | ||||
|     fi | ||||
|  | ||||
|     dst=$dstarg | ||||
|     # Protect names starting with `-'. | ||||
|     case $dst in | ||||
|       -*) dst=./$dst ;; | ||||
|     esac | ||||
|  | ||||
|     # If destination is a directory, append the input filename; won't work | ||||
|     # if double slashes aren't ignored. | ||||
|     if test -d "$dst"; then | ||||
|       if test -n "$no_target_directory"; then | ||||
| 	echo "$0: $dstarg: Is a directory" >&2 | ||||
| 	exit 1 | ||||
|       fi | ||||
|       dstdir=$dst | ||||
|       dst=$dstdir/`basename "$src"` | ||||
|       dstdir_status=0 | ||||
|     else | ||||
|       # Prefer dirname, but fall back on a substitute if dirname fails. | ||||
|       dstdir=` | ||||
| 	(dirname "$dst") 2>/dev/null || | ||||
| 	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ | ||||
| 	     X"$dst" : 'X\(//\)[^/]' \| \ | ||||
| 	     X"$dst" : 'X\(//\)$' \| \ | ||||
| 	     X"$dst" : 'X\(/\)' \| . 2>/dev/null || | ||||
| 	echo X"$dst" | | ||||
| 	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ | ||||
| 		   s//\1/ | ||||
| 		   q | ||||
| 		 } | ||||
| 		 /^X\(\/\/\)[^/].*/{ | ||||
| 		   s//\1/ | ||||
| 		   q | ||||
| 		 } | ||||
| 		 /^X\(\/\/\)$/{ | ||||
| 		   s//\1/ | ||||
| 		   q | ||||
| 		 } | ||||
| 		 /^X\(\/\).*/{ | ||||
| 		   s//\1/ | ||||
| 		   q | ||||
| 		 } | ||||
| 		 s/.*/./; q' | ||||
|       ` | ||||
|  | ||||
|       test -d "$dstdir" | ||||
|       dstdir_status=$? | ||||
|     fi | ||||
|   fi | ||||
|  | ||||
|   obsolete_mkdir_used=false | ||||
|  | ||||
|   if test $dstdir_status != 0; then | ||||
|     case $posix_mkdir in | ||||
|       '') | ||||
| 	# Create intermediate dirs using mode 755 as modified by the umask. | ||||
| 	# This is like FreeBSD 'install' as of 1997-10-28. | ||||
| 	umask=`umask` | ||||
| 	case $stripcmd.$umask in | ||||
| 	  # Optimize common cases. | ||||
| 	  *[2367][2367]) mkdir_umask=$umask;; | ||||
| 	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; | ||||
|  | ||||
| 	  *[0-7]) | ||||
| 	    mkdir_umask=`expr $umask + 22 \ | ||||
| 	      - $umask % 100 % 40 + $umask % 20 \ | ||||
| 	      - $umask % 10 % 4 + $umask % 2 | ||||
| 	    `;; | ||||
| 	  *) mkdir_umask=$umask,go-w;; | ||||
| 	esac | ||||
|  | ||||
| 	# With -d, create the new directory with the user-specified mode. | ||||
| 	# Otherwise, rely on $mkdir_umask. | ||||
| 	if test -n "$dir_arg"; then | ||||
| 	  mkdir_mode=-m$mode | ||||
| 	else | ||||
| 	  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 \ | ||||
|   # Now remove or move aside any old file at destination location.  We | ||||
|   # try this two ways since rm can't unlink itself on some systems and | ||||
|   # the destination file might be busy for other reasons.  In this case, | ||||
|   # the final cleanup might fail but the new file should still install | ||||
|   # successfully. | ||||
|   { | ||||
|     if test -f "$dstdir/$dstfile"; then | ||||
|       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ | ||||
|       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ | ||||
|       || { | ||||
| 	   # The rename failed, perhaps because mv can't rename something else | ||||
| 	   # to itself, or perhaps because mv is so ancient that it does not | ||||
| 	   # support -f. | ||||
| 	  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 | ||||
| 	  (exit 1); exit | ||||
|       } | ||||
|     else | ||||
|       : | ||||
|     fi | ||||
|   } && | ||||
|  | ||||
| 	   # Now remove or move aside any old file at destination location. | ||||
| 	   # We try this two ways since rm can't unlink itself on some | ||||
| 	   # systems and the destination file might be busy for other | ||||
| 	   # reasons.  In this case, the final cleanup might fail but the new | ||||
| 	   # file should still install successfully. | ||||
| 	   { | ||||
| 	     if test -f "$dst"; then | ||||
| 	       $doit $rmcmd -f "$dst" 2>/dev/null \ | ||||
| 	       || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \ | ||||
| 		     && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\ | ||||
| 	       || { | ||||
| 		 echo "$0: cannot unlink or rename $dst" >&2 | ||||
| 		 (exit 1); exit 1 | ||||
| 	       } | ||||
| 	     else | ||||
| 	       : | ||||
| 	     fi | ||||
| 	   } && | ||||
|   # Now rename the file to the real destination. | ||||
|   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" | ||||
| fi && | ||||
|  | ||||
| 	   # Now rename the file to the real destination. | ||||
| 	   $doit $mvcmd "$dsttmp" "$dst" | ||||
| 	 } | ||||
|     } || exit 1 | ||||
|  | ||||
|     trap '' 0 | ||||
|   fi | ||||
| done | ||||
| # The final little trick to "correctly" pass the exit status to the exit trap. | ||||
| { | ||||
|   (exit 0); exit | ||||
| } | ||||
|  | ||||
| # Local variables: | ||||
| # eval: (add-hook 'write-file-hooks 'time-stamp) | ||||
|   | ||||
| @@ -1,40 +0,0 @@ | ||||
| # | ||||
| # Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved. | ||||
| # | ||||
| # This file is part of LVM2. | ||||
| # | ||||
| # This copyrighted material is made available to anyone wishing to use, | ||||
| # modify, copy, or redistribute it subject to the terms and conditions | ||||
| # of the GNU General Public License v.2. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program; if not, write to the Free Software Foundation, | ||||
| # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
|  | ||||
| CONFSRC=example.conf | ||||
| CONFDEST=lvm.conf | ||||
|  | ||||
| PROFILE_TEMPLATES=command_profile_template.profile metadata_profile_template.profile | ||||
| PROFILES=$(PROFILE_TEMPLATES) $(srcdir)/thin-generic.profile $(srcdir)/thin-performance.profile | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| install_conf: $(CONFSRC) | ||||
| 	@if [ ! -e $(confdir)/$(CONFDEST) ]; then \ | ||||
| 		echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST)"; \ | ||||
| 		$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST); \ | ||||
| 	fi | ||||
|  | ||||
| install_profiles: $(PROFILES) | ||||
| 	$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_PROFILE_DIR) | ||||
| 	$(INSTALL_DATA) $(PROFILES) $(DESTDIR)$(DEFAULT_PROFILE_DIR)/ | ||||
|  | ||||
| install_lvm2: install_conf install_profiles | ||||
|  | ||||
| install: install_lvm2 | ||||
|  | ||||
| DISTCLEAN_TARGETS += $(CONFSRC) $(PROFILE_TEMPLATES) | ||||
| @@ -1,48 +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. | ||||
| # | ||||
| global { | ||||
| 	units="h" | ||||
| 	si_unit_consistency=1 | ||||
| 	suffix=1 | ||||
| 	lvdisplay_shows_full_device_path=0 | ||||
| } | ||||
| report { | ||||
| 	aligned=1 | ||||
| 	buffered=1 | ||||
| 	headings=1 | ||||
| 	separator=" " | ||||
| 	list_item_separator="," | ||||
| 	prefixes=0 | ||||
| 	quoted=1 | ||||
| 	colums_as_rows=0 | ||||
| 	binary_values_as_numeric=0 | ||||
| 	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" | ||||
| } | ||||
							
								
								
									
										1263
									
								
								conf/example.conf.in
									
									
									
									
									
								
							
							
						
						
									
										1263
									
								
								conf/example.conf.in
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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=64 | ||||
| } | ||||
| 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 | ||||
| } | ||||
							
								
								
									
										1883
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										1883
									
								
								configure.in
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,7 +1,7 @@ | ||||
| # | ||||
| # 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 the LVM2. | ||||
| # | ||||
| # This copyrighted material is made available to anyone wishing to use, | ||||
| # modify, copy, or redistribute it subject to the terms and conditions | ||||
| @@ -13,35 +13,11 @@ | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
|  | ||||
| .PHONY: dmeventd clvmd cmirrord lvmetad | ||||
| VPATH = @srcdir@ | ||||
|  | ||||
| ifneq ("@CLVMD@", "none") | ||||
|   SUBDIRS += clvmd | ||||
|   SUBDIRS = clvmd | ||||
| endif | ||||
|  | ||||
| ifeq ("@BUILD_CMIRRORD@", "yes") | ||||
|   SUBDIRS += cmirrord | ||||
| endif | ||||
| include $(top_srcdir)/make.tmpl | ||||
|  | ||||
| ifeq ("@BUILD_DMEVENTD@", "yes") | ||||
|   SUBDIRS += dmeventd | ||||
| ifneq ("$(CFLOW_CMD)", "") | ||||
| daemons.cflow: dmeventd.cflow | ||||
| endif | ||||
| endif | ||||
|  | ||||
| ifeq ("@BUILD_LVMETAD@", "yes") | ||||
|   SUBDIRS += lvmetad | ||||
| endif | ||||
|  | ||||
| ifeq ($(MAKECMDGOALS),distclean) | ||||
|   SUBDIRS = clvmd cmirrord dmeventd lvmetad | ||||
| endif | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| ifeq ("@BUILD_DMEVENTD@", "yes") | ||||
| device-mapper: dmeventd.device-mapper | ||||
| endif | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # | ||||
| # 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, | ||||
| # modify, copy, or redistribute it subject to the terms and conditions | ||||
| @@ -13,22 +13,7 @@ | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
|  | ||||
| CMAN_LIBS = @CMAN_LIBS@ | ||||
| CMAN_CFLAGS = @CMAN_CFLAGS@ | ||||
| CMAP_LIBS = @CMAP_LIBS@ | ||||
| CMAP_CFLAGS = @CMAP_CFLAGS@ | ||||
| CONFDB_LIBS = @CONFDB_LIBS@ | ||||
| CONFDB_CFLAGS = @CONFDB_CFLAGS@ | ||||
| CPG_LIBS = @CPG_LIBS@ | ||||
| CPG_CFLAGS = @CPG_CFLAGS@ | ||||
| DLM_LIBS = @DLM_LIBS@ | ||||
| DLM_CFLAGS = @DLM_CFLAGS@ | ||||
| QUORUM_LIBS = @QUORUM_LIBS@ | ||||
| QUORUM_CFLAGS = @QUORUM_CFLAGS@ | ||||
| SALCK_LIBS = @SALCK_LIBS@ | ||||
| SALCK_CFLAGS = @SALCK_CFLAGS@ | ||||
| VPATH = @srcdir@ | ||||
|  | ||||
| SOURCES = \ | ||||
| 	clvmd-command.c  \ | ||||
| @@ -36,72 +21,78 @@ SOURCES = \ | ||||
| 	lvm-functions.c  \ | ||||
| 	refresh_clvmd.c | ||||
|  | ||||
| ifeq ("@CLVMD@", "gulm") | ||||
| 	GULM = yes | ||||
| endif | ||||
|  | ||||
| ifeq ("@CLVMD@", "cman") | ||||
| 	CMAN = yes | ||||
| endif | ||||
|  | ||||
| ifeq ("@CLVMD@", "openais") | ||||
| 	OPENAIS = yes | ||||
| 	GULM = no | ||||
| 	CMAN = no | ||||
| endif | ||||
|  | ||||
| ifeq ("@CLVMD@", "all") | ||||
| 	GULM = yes | ||||
| 	CMAN = yes | ||||
| 	OPENAIS = no | ||||
| endif | ||||
|  | ||||
| ifeq ("@DEBUG@", "yes") | ||||
| 	DEFS += -DDEBUG | ||||
| endif | ||||
|  | ||||
| ifneq (,$(findstring cman,, "@CLVMD@,")) | ||||
| ifeq ("$(GULM)", "yes") | ||||
| 	SOURCES += clvmd-gulm.c tcp-comms.c | ||||
| 	LMLIBS += -lccs -lgulm | ||||
| 	DEFS += -DUSE_GULM | ||||
| endif | ||||
|  | ||||
| ifeq ("$(CMAN)", "yes") | ||||
| 	SOURCES += clvmd-cman.c | ||||
| 	LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS) | ||||
| 	CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS) | ||||
| 	LMLIBS += -ldlm -lcman | ||||
| 	DEFS += -DUSE_CMAN | ||||
| endif | ||||
|  | ||||
| ifneq (,$(findstring openais,, "@CLVMD@,")) | ||||
| ifeq ("$(OPENAIS)", "yes") | ||||
| 	SOURCES += clvmd-openais.c | ||||
| 	LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS) | ||||
| 	CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS) | ||||
| 	LMLIBS += -lSaLck -lcpg | ||||
| 	DEFS += -DUSE_OPENAIS | ||||
| endif | ||||
|  | ||||
| ifneq (,$(findstring corosync,, "@CLVMD@,")) | ||||
| 	SOURCES += clvmd-corosync.c | ||||
| 	LMLIBS += $(CMAP_LIBS) $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS) | ||||
| 	CFLAGS += $(CMAP_CFLAGS) $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(DLM_CFLAGS) $(QUORUM_CFLAGS) | ||||
| 	DEFS += -DUSE_COROSYNC | ||||
| endif | ||||
|  | ||||
| ifneq (,$(findstring singlenode,, "@CLVMD@,")) | ||||
| 	SOURCES += clvmd-singlenode.c | ||||
| 	DEFS += -DUSE_SINGLENODE | ||||
| endif | ||||
|  | ||||
| ifeq ($(MAKECMDGOALS),distclean) | ||||
| 	SOURCES += clvmd-cman.c | ||||
| 	SOURCES += clvmd-openais.c | ||||
| 	SOURCES += clvmd-corosync.c | ||||
| 	SOURCES += clvmd-singlenode.c | ||||
| endif | ||||
|  | ||||
| TARGETS = \ | ||||
| 	clvmd | ||||
|  | ||||
| LVMLIBS = $(LVMINTERNAL_LIBS) | ||||
| LVMLIBS = -llvm -lpthread | ||||
|  | ||||
| ifeq ("@DMEVENTD@", "yes") | ||||
| 	LVMLIBS += -ldevmapper-event | ||||
| endif | ||||
|   | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| LVMLIBS += -ldevmapper | ||||
| LIBS += $(PTHREAD_LIBS) | ||||
|  | ||||
| CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS) | ||||
| LDFLAGS += $(EXTRA_EXEC_LDFLAGS) | ||||
| DEFS += -D_REENTRANT | ||||
| CFLAGS += -fno-strict-aliasing | ||||
|  | ||||
| include $(top_srcdir)/make.tmpl | ||||
|  | ||||
| INSTALL_TARGETS = \ | ||||
| 	install_clvmd | ||||
|  | ||||
| clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a | ||||
| 	$(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \ | ||||
| clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a | ||||
| 	$(CC) -o clvmd $(OBJECTS) $(CFLAGS) $(LDFLAGS) \ | ||||
| 		$(LVMLIBS) $(LMLIBS) $(LIBS) | ||||
|  | ||||
| .PHONY: install_clvmd | ||||
|  | ||||
| install_clvmd: $(TARGETS) | ||||
| 	$(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd | ||||
| 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) clvmd \ | ||||
| 		$(sbindir)/clvmd | ||||
|  | ||||
| install: $(INSTALL_TARGETS) | ||||
|  | ||||
| install_cluster: $(INSTALL_TARGETS) | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  * | ||||
| @@ -22,40 +22,37 @@ | ||||
| #ifndef _CLVM_H | ||||
| #define _CLVM_H | ||||
|  | ||||
| #include "configure.h" | ||||
| #include <inttypes.h> | ||||
|  | ||||
| struct clvm_header { | ||||
| 	uint8_t  cmd;	        /* See below */ | ||||
| 	uint8_t  flags;	        /* See below */ | ||||
| 	uint16_t xid;	        /* Transaction ID */ | ||||
| 	uint32_t clientid;	/* Only used in Daemon->Daemon comms */ | ||||
| 	int32_t  status;	/* For replies, whether request succeeded */ | ||||
| 	uint32_t arglen;	/* Length of argument below. | ||||
| 				   If >1500 then it will be passed | ||||
| 	uint32_t arglen;	/* Length of argument below.  | ||||
| 				   If >1500 then it will be passed  | ||||
| 				   around the cluster in the system LV */ | ||||
| 	char node[1];		/* Actually a NUL-terminated string, node name. | ||||
| 				   If this is empty then the command is | ||||
| 				   forwarded to all cluster nodes unless | ||||
| 				   FLAG_LOCAL or FLAG_REMOTE is also set. */ | ||||
| 	char args[1];		/* Arguments for the command follow the | ||||
| 				   If this is empty then the command is  | ||||
| 				   forwarded to all cluster nodes unless  | ||||
| 				   FLAG_LOCAL is also set. */ | ||||
| 	char args[1];		/* Arguments for the command follow the  | ||||
| 				   node name, This member is only | ||||
| 				   valid if the node name is empty */ | ||||
| } __attribute__ ((packed)); | ||||
|  | ||||
| /* Flags */ | ||||
| #define CLVMD_FLAG_LOCAL	1	/* Only do this on the local node */ | ||||
| #define CLVMD_FLAG_SYSTEMLV	2	/* Data in system LV under my node name */ | ||||
| #define CLVMD_FLAG_NODEERRS	4	/* Reply has errors in node-specific portion */ | ||||
| #define CLVMD_FLAG_REMOTE	8	/* Do this on all nodes except for 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_NODEERRS     4       /* Reply has errors in node-specific portion */ | ||||
|  | ||||
| /* Name of the local socket to communicate between lvm and clvmd */ | ||||
| static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock"; | ||||
| /* Name of the local socket to communicate between libclvm and clvmd */ | ||||
| //static const char CLVMD_SOCKNAME[]="/var/run/clvmd"; | ||||
| static const char CLVMD_SOCKNAME[] = "\0clvmd"; | ||||
|  | ||||
| /* Internal commands & replies */ | ||||
| #define CLVMD_CMD_REPLY    1 | ||||
| #define CLVMD_CMD_VERSION  2	/* Send version around cluster when we start */ | ||||
| #define CLVMD_CMD_GOAWAY   3	/* Die if received this - we are running | ||||
| #define CLVMD_CMD_GOAWAY   3	/* Die if received this - we are running  | ||||
| 				   an incompatible version */ | ||||
| #define CLVMD_CMD_TEST     4	/* Just for mucking about */ | ||||
|  | ||||
| @@ -65,19 +62,9 @@ static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock"; | ||||
| /* Lock/Unlock commands */ | ||||
| #define CLVMD_CMD_LOCK_LV           50 | ||||
| #define CLVMD_CMD_LOCK_VG           51 | ||||
| #define CLVMD_CMD_LOCK_QUERY	    52 | ||||
|  | ||||
| /* Misc functions */ | ||||
| #define CLVMD_CMD_REFRESH	    40 | ||||
| #define CLVMD_CMD_GET_CLUSTERNAME   41 | ||||
| #define CLVMD_CMD_SET_DEBUG	    42 | ||||
| #define CLVMD_CMD_VG_BACKUP	    43 | ||||
| #define CLVMD_CMD_RESTART	    44 | ||||
| #define CLVMD_CMD_SYNC_NAMES	    45 | ||||
|  | ||||
| /* Used internally by some callers, but not part of the protocol.*/ | ||||
| #define NODE_ALL	"*" | ||||
| #define NODE_LOCAL	"." | ||||
| #define NODE_REMOTE	"^" | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -17,32 +17,42 @@ | ||||
|  * CMAN communication layer for clvmd. | ||||
|  */ | ||||
|  | ||||
| #include "clvmd-common.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 <libdlm.h> | ||||
|  | ||||
| #include "clvmd-comms.h" | ||||
| #include "clvm.h" | ||||
| #include "log.h" | ||||
| #include "clvmd.h" | ||||
| #include "lvm-functions.h" | ||||
|  | ||||
| #include <libdlm.h> | ||||
|  | ||||
| #include <syslog.h> | ||||
|  | ||||
| #define LOCKSPACE_NAME "clvmd" | ||||
|  | ||||
| struct clvmd_node | ||||
| { | ||||
| 	struct cman_node *node; | ||||
| 	int clvmd_up; | ||||
| }; | ||||
|  | ||||
| static int num_nodes; | ||||
| static struct cman_node *nodes = NULL; | ||||
| static struct cman_node this_node; | ||||
| static int count_nodes; /* size of allocated nodes array */ | ||||
| static struct dm_hash_table *node_updown_hash; | ||||
| static int max_updown_nodes = 50;	/* Current size of the allocated array */ | ||||
| /* Node up/down status, indexed by nodeid */ | ||||
| static int *node_updown = NULL; | ||||
| static dlm_lshandle_t *lockspace; | ||||
| static cman_handle_t c_handle; | ||||
|  | ||||
| @@ -62,8 +72,6 @@ struct lock_wait { | ||||
|  | ||||
| static int _init_cluster(void) | ||||
| { | ||||
| 	node_updown_hash = dm_hash_create(100); | ||||
|  | ||||
| 	/* Open the cluster communication socket */ | ||||
| 	c_handle = cman_init(NULL); | ||||
| 	if (!c_handle) { | ||||
| @@ -89,17 +97,11 @@ static int _init_cluster(void) | ||||
| 	DEBUGLOG("CMAN initialisation complete\n"); | ||||
|  | ||||
| 	/* 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) { | ||||
| 		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"); | ||||
|  | ||||
| 		syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	dlm_ls_pthread_init(lockspace); | ||||
| 	DEBUGLOG("DLM initialisation complete\n"); | ||||
| 	return 0; | ||||
| @@ -110,12 +112,12 @@ static void _cluster_init_completed(void) | ||||
| 	clvmd_cluster_init_completed(); | ||||
| } | ||||
|  | ||||
| static int _get_main_cluster_fd(void) | ||||
| static int _get_main_cluster_fd() | ||||
| { | ||||
| 	return cman_get_fd(c_handle); | ||||
| } | ||||
|  | ||||
| static int _get_num_nodes(void) | ||||
| static int _get_num_nodes() | ||||
| { | ||||
| 	int i; | ||||
| 	int nnodes = 0; | ||||
| @@ -163,10 +165,8 @@ static int _cluster_do_node_callback(struct local_client *client, | ||||
|  | ||||
| 	for (i = 0; i < _get_num_nodes(); i++) { | ||||
| 		if (nodes[i].cn_member && nodes[i].cn_nodeid) { | ||||
| 			int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int)); | ||||
|  | ||||
| 			callback(client, (char *)&nodes[i].cn_nodeid, up); | ||||
| 			if (!up) | ||||
| 			callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]); | ||||
| 			if (!node_updown[nodes[i].cn_nodeid]) | ||||
| 				somedown = -1; | ||||
| 		} | ||||
| 	} | ||||
| @@ -184,7 +184,7 @@ static void event_callback(cman_handle_t handle, void *private, int reason, int | ||||
| 		log_notice("clvmd on node %s has died\n", namebuf); | ||||
| 		DEBUGLOG("Got port closed message, removing node %s\n", namebuf); | ||||
|  | ||||
| 		dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0); | ||||
| 		node_updown[arg] = 0; | ||||
| 		break; | ||||
|  | ||||
| 	case CMAN_REASON_STATECHANGE: | ||||
| @@ -239,12 +239,28 @@ static void _add_up_node(const char *csid) | ||||
| 	/* It's up ! */ | ||||
| 	int nodeid = nodeid_from_csid(csid); | ||||
|  | ||||
| 	dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1); | ||||
| 	if (nodeid >= max_updown_nodes) { | ||||
| 	        int new_size = nodeid + 10; | ||||
| 		int *new_updown = realloc(node_updown, new_size); | ||||
|  | ||||
| 		if (new_updown) { | ||||
| 			node_updown = new_updown; | ||||
| 			max_updown_nodes = new_size; | ||||
| 			DEBUGLOG("realloced more space for nodes. now %d\n", | ||||
| 				 max_updown_nodes); | ||||
| 		} else { | ||||
| 			log_error | ||||
| 				("Realloc failed. Node status for clvmd will be wrong. quitting\n"); | ||||
| 			exit(999); | ||||
| 		} | ||||
| 	} | ||||
| 	node_updown[nodeid] = 1; | ||||
| 	DEBUGLOG("Added new node %d to updown list\n", nodeid); | ||||
| } | ||||
|  | ||||
| static void _cluster_closedown(void) | ||||
| static void _cluster_closedown() | ||||
| { | ||||
| 	unlock_all(); | ||||
| 	dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1); | ||||
| 	cman_finish(c_handle); | ||||
| } | ||||
| @@ -272,22 +288,15 @@ static void count_clvmds_running(void) | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < num_nodes; i++) { | ||||
| 		int nodeid = nodes[i].cn_nodeid; | ||||
|  | ||||
| 		if (is_listening(nodeid) == 1) | ||||
| 			dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1); | ||||
| 		else | ||||
| 			dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0); | ||||
| 		node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Get a list of active cluster members */ | ||||
| static void get_members(void) | ||||
| static void get_members() | ||||
| { | ||||
| 	int retnodes; | ||||
| 	int status; | ||||
| 	int i; | ||||
| 	int high_nodeid = 0; | ||||
|  | ||||
| 	num_nodes = cman_get_node_count(c_handle); | ||||
| 	if (num_nodes == -1) { | ||||
| @@ -316,10 +325,11 @@ static void get_members(void) | ||||
| 		exit(6); | ||||
| 	} | ||||
|  | ||||
| 	/* Get the highest nodeid */ | ||||
| 	for (i=0; i<retnodes; i++) { | ||||
| 		if (nodes[i].cn_nodeid > high_nodeid) | ||||
| 			high_nodeid = nodes[i].cn_nodeid; | ||||
| 	if (node_updown == NULL) { | ||||
| 		size_t buf_len = sizeof(int) * max(num_nodes, max_updown_nodes); | ||||
| 		node_updown = malloc(buf_len); | ||||
| 		if (node_updown) | ||||
| 			memset(node_updown, 0, buf_len); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -380,7 +390,7 @@ static int nodeid_from_csid(const char *csid) | ||||
| 	return nodeid; | ||||
| } | ||||
|  | ||||
| static int _is_quorate(void) | ||||
| static int _is_quorate() | ||||
| { | ||||
| 	return cman_is_quorate(c_handle); | ||||
| } | ||||
| @@ -478,7 +488,6 @@ static int _get_cluster_name(char *buf, int buflen) | ||||
| } | ||||
|  | ||||
| static struct cluster_ops _cluster_cman_ops = { | ||||
| 	.name                     = "cman", | ||||
| 	.cluster_init_completed   = _cluster_init_completed, | ||||
| 	.cluster_send_message     = _cluster_send_message, | ||||
| 	.name_from_csid           = _name_from_csid, | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  * | ||||
| @@ -50,19 +50,32 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| #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 <libdlm.h> | ||||
|  | ||||
| #include "list.h" | ||||
| #include "locking.h" | ||||
| #include "log.h" | ||||
| #include "lvm-functions.h" | ||||
| #include "clvmd-comms.h" | ||||
| #include "clvm.h" | ||||
| #include "clvmd.h" | ||||
| #include "lvm-globals.h" | ||||
| #include "lvm-functions.h" | ||||
|  | ||||
| #include "locking.h" | ||||
|  | ||||
| #include <sys/utsname.h> | ||||
|  | ||||
| extern struct cluster_ops *clops; | ||||
| static int restart_clvmd(void); | ||||
|  | ||||
| /* This is where all the real work happens: | ||||
|    NOTE: client will be NULL when this is executed on a remote node */ | ||||
| @@ -73,7 +86,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 status = 0; | ||||
| 	char *lockname; | ||||
| 	const char *locktype; | ||||
| 	struct utsname nodeinfo; | ||||
| 	unsigned char lock_cmd; | ||||
| 	unsigned char lock_flags; | ||||
| @@ -93,77 +105,44 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen, | ||||
| 			*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; | ||||
|  | ||||
| 	case CLVMD_CMD_LOCK_VG: | ||||
| 		lock_cmd = args[0]; | ||||
| 		lock_flags = args[1]; | ||||
| 		lockname = &args[2]; | ||||
| 		/* Check to see if the VG is in use by LVM1 */ | ||||
| 		status = do_check_lvm1(lockname); | ||||
| 		do_lock_vg(lock_cmd, lock_flags, lockname); | ||||
| 		status = do_check_lvm1(&args[2]); | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_LOCK_LV: | ||||
| 		/* This is the biggie */ | ||||
| 		lock_cmd = args[0]; | ||||
| 		lock_cmd = args[0] & 0x3F; | ||||
| 		lock_flags = args[1]; | ||||
| 		lockname = &args[2]; | ||||
| 		status = do_lock_lv(lock_cmd, lock_flags, lockname); | ||||
| 		/* Replace EIO with something less scary */ | ||||
| 		if (status == EIO) { | ||||
| 			*retlen = 1 + dm_snprintf(*buf, buflen, "%s", | ||||
| 						  get_last_lvm_error()); | ||||
| 			*retlen = | ||||
| 			    1 + snprintf(*buf, buflen, "%s", | ||||
| 					 get_last_lvm_error()); | ||||
| 			return EIO; | ||||
| 		} | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_LOCK_QUERY: | ||||
| 		lockname = &args[2]; | ||||
| 		if (buflen < 3) | ||||
| 			return EIO; | ||||
| 		if ((locktype = do_lock_query(lockname))) | ||||
| 			*retlen = 1 + dm_snprintf(*buf, buflen, "%s", locktype); | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_REFRESH: | ||||
| 		do_refresh_cache(); | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_SYNC_NAMES: | ||||
| 		lvm_do_fs_unlock(); | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_SET_DEBUG: | ||||
| 		clvmd_set_debug((debug_t) args[0]); | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_RESTART: | ||||
| 		status = restart_clvmd(); | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_GET_CLUSTERNAME: | ||||
| 		status = clops->get_cluster_name(*buf, buflen); | ||||
| 		if (!status) | ||||
| 			*retlen = strlen(*buf)+1; | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_VG_BACKUP: | ||||
| 		/* | ||||
| 		 * Do not run backup on local node, caller should do that. | ||||
| 		 */ | ||||
| 		if (!client) | ||||
| 			lvm_do_backup(&args[2]); | ||||
| 		break; | ||||
|  | ||||
| 	default: | ||||
| 		/* Won't get here because command is validated in pre_command */ | ||||
| 		break; | ||||
| @@ -171,63 +150,69 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen, | ||||
|  | ||||
| 	/* Check the status of the command and return the error text */ | ||||
| 	if (status) { | ||||
| 		*retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s", | ||||
| 						    strerror(status)) : -1); | ||||
| 		*retlen = 1 + snprintf(*buf, buflen, "%s", strerror(status)); | ||||
| 	} | ||||
|  | ||||
| 	return status; | ||||
|  | ||||
| } | ||||
|  | ||||
| static int lock_vg(struct local_client *client) | ||||
| { | ||||
| 	struct dm_hash_table *lock_hash; | ||||
| 	struct clvm_header *header = | ||||
| 		(struct clvm_header *) client->bits.localsock.cmd; | ||||
| 	unsigned char lock_cmd; | ||||
| 	int lock_mode; | ||||
| 	char *args = header->node + strlen(header->node) + 1; | ||||
| 	int lkid; | ||||
| 	int status; | ||||
| 	char *lockname; | ||||
|     struct dm_hash_table *lock_hash; | ||||
|     struct clvm_header *header = | ||||
| 	(struct clvm_header *) client->bits.localsock.cmd; | ||||
|     unsigned char lock_cmd; | ||||
|     unsigned char lock_flags; | ||||
|     char *args = header->node + strlen(header->node) + 1; | ||||
|     int lkid; | ||||
|     int status = 0; | ||||
|     char *lockname; | ||||
|  | ||||
| 	/* | ||||
| 	 * Keep a track of VG locks in our own hash table. In current | ||||
| 	 * practice there should only ever be more than two VGs locked | ||||
| 	 * if a user tries to merge lots of them at once | ||||
| 	 */ | ||||
| 	if (!client->bits.localsock.private) { | ||||
| 		if (!(lock_hash = dm_hash_create(3))) | ||||
| 			return ENOMEM; | ||||
| 		client->bits.localsock.private = (void *) lock_hash; | ||||
| 	} else | ||||
| 		lock_hash = (struct dm_hash_table *) client->bits.localsock.private; | ||||
|     /* Keep a track of VG locks in our own hash table. In current | ||||
|        practice there should only ever be more than two VGs locked | ||||
|        if a user tries to merge lots of them at once */ | ||||
|     if (client->bits.localsock.private) { | ||||
| 	lock_hash = (struct dm_hash_table *)client->bits.localsock.private; | ||||
|     } | ||||
|     else { | ||||
| 	lock_hash = dm_hash_create(3); | ||||
| 	if (!lock_hash) | ||||
| 	    return ENOMEM; | ||||
| 	client->bits.localsock.private = (void *)lock_hash; | ||||
|     } | ||||
|  | ||||
| 	lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK); | ||||
| 	lock_mode = ((int) lock_cmd & LCK_TYPE_MASK); | ||||
| 	/* lock_flags = args[1]; */ | ||||
| 	lockname = &args[2]; | ||||
| 	DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client); | ||||
|     lock_cmd = args[0] & 0x3F; | ||||
|     lock_flags = args[1]; | ||||
|     lockname = &args[2]; | ||||
|     DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client); | ||||
|  | ||||
| 	if (lock_mode == LCK_UNLOCK) { | ||||
| 		if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname))) | ||||
| 			return EINVAL; | ||||
|     if (lock_cmd == LCK_UNLOCK) { | ||||
|  | ||||
| 		if ((status = sync_unlock(lockname, lkid))) | ||||
| 			status = errno; | ||||
| 		else | ||||
| 			dm_hash_remove(lock_hash, lockname); | ||||
| 	} else { | ||||
| 		/* Read locks need to be PR; other modes get passed through */ | ||||
| 		if (lock_mode == LCK_READ) | ||||
| 			lock_mode = LCK_PREAD; | ||||
| 	lkid = (int)(long)dm_hash_lookup(lock_hash, lockname); | ||||
| 	if (lkid == 0) | ||||
| 	    return EINVAL; | ||||
|  | ||||
| 		if ((status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid))) | ||||
| 			status = errno; | ||||
| 		else if (!dm_hash_insert(lock_hash, lockname, (void *) (long) lkid)) | ||||
| 			return ENOMEM; | ||||
| 	status = sync_unlock(lockname, lkid); | ||||
| 	if (status) | ||||
| 	    status = errno; | ||||
| 	else | ||||
| 	    dm_hash_remove(lock_hash, lockname); | ||||
|     } | ||||
|     else { | ||||
| 	/* Read locks need to be PR; other modes get passed through */ | ||||
| 	if ((lock_cmd & LCK_TYPE_MASK) == LCK_READ) { | ||||
| 	    lock_cmd &= ~LCK_TYPE_MASK; | ||||
| 	    lock_cmd |= LCK_PREAD; | ||||
| 	} | ||||
| 	status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid); | ||||
| 	if (status) | ||||
| 	    status = errno; | ||||
| 	else | ||||
| 	    dm_hash_insert(lock_hash, lockname, (void *)(long)lkid); | ||||
|     } | ||||
|  | ||||
| 	return status; | ||||
|     return status; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -241,22 +226,18 @@ int do_pre_command(struct local_client *client) | ||||
| 	unsigned char lock_cmd; | ||||
| 	unsigned char lock_flags; | ||||
| 	char *args = header->node + strlen(header->node) + 1; | ||||
| 	int lockid = 0; | ||||
| 	int lockid; | ||||
| 	int status = 0; | ||||
| 	char *lockname; | ||||
|  | ||||
| 	switch (header->cmd) { | ||||
| 	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; | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_LOCK_VG: | ||||
| 		lockname = &args[2]; | ||||
| 		/* We take out a real lock unless LCK_CACHE was set */ | ||||
| 		if (!strncmp(lockname, "V_", 2) || | ||||
| 		    !strncmp(lockname, "P_#", 3)) | ||||
| 			status = lock_vg(client); | ||||
|        	        status = lock_vg(client); | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_LOCK_LV: | ||||
| @@ -268,11 +249,6 @@ int do_pre_command(struct local_client *client) | ||||
|  | ||||
| 	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: | ||||
| @@ -296,8 +272,13 @@ int do_post_command(struct local_client *client) | ||||
|  | ||||
| 	switch (header->cmd) { | ||||
| 	case CLVMD_CMD_TEST: | ||||
| 		status = sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private); | ||||
| 		client->bits.localsock.private = NULL; | ||||
| 		status = | ||||
| 		    sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private); | ||||
| 		client->bits.localsock.private = 0; | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_LOCK_VG: | ||||
| 		/* Nothing to do here */ | ||||
| 		break; | ||||
|  | ||||
| 	case CLVMD_CMD_LOCK_LV: | ||||
| @@ -306,10 +287,6 @@ int do_post_command(struct local_client *client) | ||||
| 		lockname = &args[2]; | ||||
| 		status = post_lock_lv(lock_cmd, lock_flags, lockname); | ||||
| 		break; | ||||
|  | ||||
| 	default: | ||||
| 		/* Nothing to do here */ | ||||
| 		break; | ||||
| 	} | ||||
| 	return status; | ||||
| } | ||||
| @@ -318,97 +295,21 @@ int do_post_command(struct local_client *client) | ||||
| /* Called when the client is about to be deleted */ | ||||
| void cmd_client_cleanup(struct local_client *client) | ||||
| { | ||||
|     if (client->bits.localsock.private) { | ||||
|  | ||||
| 	struct dm_hash_node *v; | ||||
| 	struct dm_hash_table *lock_hash; | ||||
| 	int lkid; | ||||
| 	char *lockname; | ||||
|  | ||||
| 	if (!client->bits.localsock.private) | ||||
| 		return; | ||||
|  | ||||
| 	lock_hash = (struct dm_hash_table *)client->bits.localsock.private; | ||||
| 	struct dm_hash_table *lock_hash = | ||||
| 	    (struct dm_hash_table *)client->bits.localsock.private; | ||||
|  | ||||
| 	dm_hash_iterate(v, lock_hash) { | ||||
| 		lkid = (int)(long)dm_hash_get_data(lock_hash, v); | ||||
| 		lockname = dm_hash_get_key(lock_hash, v); | ||||
| 		int lkid = (int)(long)dm_hash_get_data(lock_hash, v); | ||||
| 		char *lockname = dm_hash_get_key(lock_hash, v); | ||||
|  | ||||
| 		DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid); | ||||
| 		(void) sync_unlock(lockname, lkid); | ||||
| 		sync_unlock(lockname, lkid); | ||||
| 	} | ||||
|  | ||||
| 	dm_hash_destroy(lock_hash); | ||||
| 	client->bits.localsock.private = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| 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; | ||||
| 	client->bits.localsock.private = 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,32 +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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * This file must be included first by every clvmd source file. | ||||
|  */ | ||||
| #ifndef _LVM_CLVMD_COMMON_H | ||||
| #define _LVM_CLVMD_COMMON_H | ||||
|  | ||||
| #include "configure.h" | ||||
|  | ||||
| #define _REENTRANT | ||||
| #define _GNU_SOURCE | ||||
| #define _FILE_OFFSET_BITS 64 | ||||
|  | ||||
| #include "libdevmapper.h" | ||||
| #include "lvm-logging.h" | ||||
|  | ||||
| #include <unistd.h> | ||||
|  | ||||
| #endif | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  * | ||||
| @@ -23,7 +23,6 @@ | ||||
| struct local_client; | ||||
|  | ||||
| struct cluster_ops { | ||||
| 	const char *name; | ||||
| 	void (*cluster_init_completed) (void); | ||||
|  | ||||
| 	int (*cluster_send_message) (const void *buf, int msglen, | ||||
| @@ -55,6 +54,13 @@ struct cluster_ops { | ||||
|  | ||||
| }; | ||||
|  | ||||
| #ifdef USE_GULM | ||||
| #  include "tcp-comms.h" | ||||
| struct cluster_ops *init_gulm_cluster(void); | ||||
| #define MAX_CSID_LEN 			GULM_MAX_CSID_LEN | ||||
| #define MAX_CLUSTER_MEMBER_NAME_LEN	GULM_MAX_CLUSTER_MEMBER_NAME_LEN | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_CMAN | ||||
| #  include <netinet/in.h> | ||||
| #  include "libcman.h" | ||||
| @@ -71,7 +77,7 @@ struct cluster_ops *init_cman_cluster(void); | ||||
|  | ||||
| #ifdef USE_OPENAIS | ||||
| #  include <openais/saAis.h> | ||||
| #  include <corosync/totem/totem.h> | ||||
| #  include <openais/totem/totem.h> | ||||
| #  define OPENAIS_CSID_LEN (sizeof(int)) | ||||
| #  define OPENAIS_MAX_CLUSTER_MESSAGE         MESSAGE_SIZE_MAX | ||||
| #  define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH | ||||
| @@ -87,33 +93,5 @@ struct cluster_ops *init_cman_cluster(void); | ||||
| 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 | ||||
|   | ||||
| @@ -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * This provides the interface between clvmd and corosync/DLM as the cluster | ||||
|  * and lock manager. | ||||
|  */ | ||||
|  | ||||
| #include "clvmd-common.h" | ||||
|  | ||||
| #include <pthread.h> | ||||
|  | ||||
| #include "clvm.h" | ||||
| #include "clvmd-comms.h" | ||||
| #include "clvmd.h" | ||||
| #include "lvm-functions.h" | ||||
|  | ||||
| #include "locking.h" | ||||
|  | ||||
| #include <corosync/cpg.h> | ||||
| #include <corosync/quorum.h> | ||||
|  | ||||
| #ifdef HAVE_COROSYNC_CONFDB_H | ||||
| #  include <corosync/confdb.h> | ||||
| #elif defined HAVE_COROSYNC_CMAP_H | ||||
| #  include <corosync/cmap.h> | ||||
| #else | ||||
| #  error "Either HAVE_COROSYNC_CONFDB_H or HAVE_COROSYNC_CMAP_H must be defined." | ||||
| #endif | ||||
|  | ||||
| #include <libdlm.h> | ||||
|  | ||||
| #include <syslog.h> | ||||
|  | ||||
| /* Timeout value for several corosync calls */ | ||||
| #define LOCKSPACE_NAME "clvmd" | ||||
|  | ||||
| static void corosync_cpg_deliver_callback (cpg_handle_t handle, | ||||
| 				  const struct cpg_name *groupName, | ||||
| 				  uint32_t nodeid, | ||||
| 				  uint32_t pid, | ||||
| 				  void *msg, | ||||
| 				  size_t msg_len); | ||||
| static void corosync_cpg_confchg_callback(cpg_handle_t handle, | ||||
| 				 const struct cpg_name *groupName, | ||||
| 				 const struct cpg_address *member_list, size_t member_list_entries, | ||||
| 				 const struct cpg_address *left_list, size_t left_list_entries, | ||||
| 				 const struct cpg_address *joined_list, size_t joined_list_entries); | ||||
| static void _cluster_closedown(void); | ||||
|  | ||||
| /* Hash list of nodes in the cluster */ | ||||
| static struct dm_hash_table *node_hash; | ||||
|  | ||||
| /* Number of active nodes */ | ||||
| static int num_nodes; | ||||
| static unsigned int our_nodeid; | ||||
|  | ||||
| static struct local_client *cluster_client; | ||||
|  | ||||
| /* Corosync handles */ | ||||
| static cpg_handle_t cpg_handle; | ||||
| static quorum_handle_t quorum_handle; | ||||
|  | ||||
| /* DLM Handle */ | ||||
| static dlm_lshandle_t *lockspace; | ||||
|  | ||||
| static struct cpg_name cpg_group_name; | ||||
|  | ||||
| /* Corosync callback structs */ | ||||
| cpg_callbacks_t corosync_cpg_callbacks = { | ||||
| 	.cpg_deliver_fn =            corosync_cpg_deliver_callback, | ||||
| 	.cpg_confchg_fn =            corosync_cpg_confchg_callback, | ||||
| }; | ||||
|  | ||||
| quorum_callbacks_t quorum_callbacks = { | ||||
| 	.quorum_notify_fn = NULL, | ||||
| }; | ||||
|  | ||||
| struct node_info | ||||
| { | ||||
| 	enum {NODE_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; | ||||
| } | ||||
							
								
								
									
										1009
									
								
								daemons/clvmd/clvmd-gulm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1009
									
								
								daemons/clvmd/clvmd-gulm.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										13
									
								
								daemons/clvmd/clvmd-gulm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								daemons/clvmd/clvmd-gulm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
|  | ||||
| /* DLM constant that clvmd uses as a generic NONBLOCK lock flag */ | ||||
| #define LKF_NOQUEUE 1 | ||||
|  | ||||
| extern int get_next_node_csid(void **context, char *csid); | ||||
| extern void add_down_node(char *csid); | ||||
| extern int gulm_fd(void); | ||||
| extern int get_ip_address(const char *node, char *addr); | ||||
| extern void tcp_remove_client(const char *csid); | ||||
| extern int alloc_client(int fd, const char *csid, struct local_client **new_client); | ||||
|  | ||||
| void gulm_add_up_node(const char *csid); | ||||
| int gulm_name_from_csid(const char *csid, char *name); | ||||
| @@ -1,35 +1,47 @@ | ||||
| /* | ||||
|  * Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
|  * This copyrighted material is made available to anyone wishing to use, | ||||
|  * modify, copy, or redistribute it subject to the terms and conditions | ||||
|  * of the GNU Lesser General Public License v.2.1. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| /****************************************************************************** | ||||
| ******************************************************************************* | ||||
| ** | ||||
| **  Copyright (C) 2007 Red Hat, Inc. All rights reserved. | ||||
| ** | ||||
| ******************************************************************************* | ||||
| ******************************************************************************/ | ||||
|  | ||||
| /* | ||||
|  * This provides the interface between clvmd and OpenAIS as the cluster | ||||
| /* This provides the interface between clvmd and OpenAIS as the cluster | ||||
|  * and lock manager. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #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 <sys/file.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <signal.h> | ||||
| #include <fcntl.h> | ||||
| #include <string.h> | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| #include <unistd.h> | ||||
| #include <errno.h> | ||||
| #include <utmpx.h> | ||||
| #include <syslog.h> | ||||
| #include <assert.h> | ||||
| #include <libdevmapper.h> | ||||
|  | ||||
| #include <openais/saAis.h> | ||||
| #include <openais/saLck.h> | ||||
| #include <openais/cpg.h> | ||||
|  | ||||
| #include <corosync/corotypes.h> | ||||
| #include <corosync/cpg.h> | ||||
|  | ||||
| #include "list.h" | ||||
| #include "locking.h" | ||||
| #include "log.h" | ||||
| #include "clvm.h" | ||||
| #include "clvmd-comms.h" | ||||
| #include "lvm-functions.h" | ||||
| @@ -38,18 +50,22 @@ | ||||
| /* Timeout value for several openais calls */ | ||||
| #define TIMEOUT 10 | ||||
|  | ||||
| static void openais_cpg_deliver_callback (cpg_handle_t handle, | ||||
| 				  const struct cpg_name *groupName, | ||||
| static void lck_lock_callback(SaInvocationT invocation, | ||||
| 			      SaLckLockStatusT lockStatus, | ||||
| 			      SaAisErrorT error); | ||||
| static void lck_unlock_callback(SaInvocationT invocation, | ||||
| 				SaAisErrorT error); | ||||
| static void cpg_deliver_callback (cpg_handle_t handle, | ||||
| 				  struct cpg_name *groupName, | ||||
| 				  uint32_t nodeid, | ||||
| 				  uint32_t pid, | ||||
| 				  void *msg, | ||||
| 				  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); | ||||
|  | ||||
| 				  int msg_len); | ||||
| static void cpg_confchg_callback(cpg_handle_t handle, | ||||
| 				 struct cpg_name *groupName, | ||||
| 				 struct cpg_address *member_list, int member_list_entries, | ||||
| 				 struct cpg_address *left_list, int left_list_entries, | ||||
| 				 struct cpg_address *joined_list, int joined_list_entries); | ||||
| static void _cluster_closedown(void); | ||||
|  | ||||
| /* Hash list of nodes in the cluster */ | ||||
| @@ -71,9 +87,14 @@ 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, | ||||
| cpg_callbacks_t cpg_callbacks = { | ||||
| 	.cpg_deliver_fn =            cpg_deliver_callback, | ||||
| 	.cpg_confchg_fn =            cpg_confchg_callback, | ||||
| }; | ||||
|  | ||||
| SaLckCallbacksT lck_callbacks = { | ||||
|         .saLckLockGrantCallback      = lck_lock_callback, | ||||
|         .saLckResourceUnlockCallback = lck_unlock_callback | ||||
| }; | ||||
|  | ||||
| struct node_info | ||||
| @@ -89,6 +110,13 @@ struct lock_info | ||||
| 	SaNameT              lock_name; | ||||
| }; | ||||
|  | ||||
| struct lock_wait | ||||
| { | ||||
| 	pthread_cond_t cond; | ||||
| 	pthread_mutex_t mutex; | ||||
| 	int status; | ||||
| }; | ||||
|  | ||||
| /* Set errno to something approximating the right value and return 0 or -1 */ | ||||
| static int ais_to_errno(SaAisErrorT err) | ||||
| { | ||||
| @@ -181,7 +209,7 @@ static int ais_to_errno(SaAisErrorT err) | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static char *print_openais_csid(const char *csid) | ||||
| static char *print_csid(const char *csid) | ||||
| { | ||||
| 	static char buf[128]; | ||||
| 	int id; | ||||
| @@ -197,11 +225,14 @@ static int add_internal_client(int fd, fd_callback_t callback) | ||||
|  | ||||
| 	DEBUGLOG("Add_internal_client, fd = %d\n", fd); | ||||
|  | ||||
| 	if (!(client = dm_zalloc(sizeof(*client)))) { | ||||
| 	client = malloc(sizeof(struct local_client)); | ||||
| 	if (!client) | ||||
| 	{ | ||||
| 		DEBUGLOG("malloc failed\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	memset(client, 0, sizeof(struct local_client)); | ||||
| 	client->fd = fd; | ||||
| 	client->type = CLUSTER_INTERNAL; | ||||
| 	client->callback = callback; | ||||
| @@ -213,37 +244,35 @@ static int add_internal_client(int fd, fd_callback_t callback) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void openais_cpg_deliver_callback (cpg_handle_t handle, | ||||
| 				  const struct cpg_name *groupName, | ||||
| static void cpg_deliver_callback (cpg_handle_t handle, | ||||
| 				  struct cpg_name *groupName, | ||||
| 				  uint32_t nodeid, | ||||
| 				  uint32_t pid, | ||||
| 				  void *msg, | ||||
| 				  size_t msg_len) | ||||
| 				  int 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); | ||||
| 	DEBUGLOG("Got message from nodeid %d for %d. len %d\n", | ||||
| 		 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); | ||||
| 	if (target_nodeid == our_nodeid) | ||||
| 		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) | ||||
| static void cpg_confchg_callback(cpg_handle_t handle, | ||||
| 				 struct cpg_name *groupName, | ||||
| 				 struct cpg_address *member_list, int member_list_entries, | ||||
| 				 struct cpg_address *left_list, int left_list_entries, | ||||
| 				 struct cpg_address *joined_list, int joined_list_entries) | ||||
| { | ||||
| 	int i; | ||||
| 	struct node_info *ninfo; | ||||
|  | ||||
| 	DEBUGLOG("confchg callback. %" PRIsize_t " joined, " | ||||
| 		 "%" PRIsize_t " left, %" PRIsize_t " members\n", | ||||
| 	DEBUGLOG("confchg callback. %d joined, %d left, %d members\n", | ||||
| 		 joined_list_entries, left_list_entries, member_list_entries); | ||||
|  | ||||
| 	for (i=0; i<joined_list_entries; i++) { | ||||
| @@ -273,27 +302,34 @@ static void openais_cpg_confchg_callback(cpg_handle_t handle, | ||||
| 			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 = joined_list_entries; | ||||
| } | ||||
|  | ||||
| 	num_nodes = member_list_entries; | ||||
| static void lck_lock_callback(SaInvocationT invocation, | ||||
| 			      SaLckLockStatusT lockStatus, | ||||
| 			      SaAisErrorT error) | ||||
| { | ||||
| 	struct lock_wait *lwait = (struct lock_wait *)(long)invocation; | ||||
|  | ||||
| 	DEBUGLOG("lck_lock_callback, error = %d\n", error); | ||||
|  | ||||
| 	lwait->status = error; | ||||
| 	pthread_mutex_lock(&lwait->mutex); | ||||
| 	pthread_cond_signal(&lwait->cond); | ||||
| 	pthread_mutex_unlock(&lwait->mutex); | ||||
| } | ||||
|  | ||||
| static void lck_unlock_callback(SaInvocationT invocation, | ||||
| 				SaAisErrorT error) | ||||
| { | ||||
| 	struct lock_wait *lwait = (struct lock_wait *)(long)invocation; | ||||
|  | ||||
| 	DEBUGLOG("lck_unlock_callback\n"); | ||||
|  | ||||
| 	lwait->status = SA_AIS_OK; | ||||
| 	pthread_mutex_lock(&lwait->mutex); | ||||
| 	pthread_cond_signal(&lwait->cond); | ||||
| 	pthread_mutex_unlock(&lwait->mutex); | ||||
| } | ||||
|  | ||||
| static int lck_dispatch(struct local_client *client, char *buf, int len, | ||||
| @@ -314,7 +350,7 @@ static int _init_cluster(void) | ||||
| 	lock_hash = dm_hash_create(10); | ||||
|  | ||||
| 	err = cpg_initialize(&cpg_handle, | ||||
| 			     &openais_cpg_callbacks); | ||||
| 			     &cpg_callbacks); | ||||
| 	if (err != SA_AIS_OK) { | ||||
| 		syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d", | ||||
| 		       err); | ||||
| @@ -323,10 +359,10 @@ static int _init_cluster(void) | ||||
| 	} | ||||
|  | ||||
| 	err = saLckInitialize(&lck_handle, | ||||
| 					NULL, | ||||
| 			      &lck_callbacks, | ||||
| 			      &ver); | ||||
| 	if (err != SA_AIS_OK) { | ||||
| 		cpg_initialize(&cpg_handle, &openais_cpg_callbacks); | ||||
| 		cpg_initialize(&cpg_handle, &cpg_callbacks); | ||||
| 		syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d", | ||||
| 		       err); | ||||
| 		DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err); | ||||
| @@ -365,6 +401,9 @@ static int _init_cluster(void) | ||||
|  | ||||
| static void _cluster_closedown(void) | ||||
| { | ||||
| 	DEBUGLOG("cluster_closedown\n"); | ||||
| 	unlock_all(); | ||||
|  | ||||
| 	saLckFinalize(lck_handle); | ||||
| 	cpg_finalize(cpg_handle); | ||||
| } | ||||
| @@ -396,7 +435,7 @@ static int _name_from_csid(const char *csid, char *name) | ||||
| 	ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN); | ||||
| 	if (!ninfo) | ||||
| 	{ | ||||
| 		sprintf(name, "UNKNOWN %s", print_openais_csid(csid)); | ||||
| 		sprintf(name, "UNKNOWN %s", print_csid(csid)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @@ -418,7 +457,7 @@ static void _add_up_node(const char *csid) | ||||
| 	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)); | ||||
| 			 print_csid(csid)); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| @@ -436,7 +475,6 @@ static int _cluster_do_node_callback(struct local_client *master_client, | ||||
| { | ||||
| 	struct dm_hash_node *hn; | ||||
| 	struct node_info *ninfo; | ||||
| 	int somedown = 0; | ||||
|  | ||||
| 	dm_hash_iterate(hn, node_hash) | ||||
| 	{ | ||||
| @@ -450,20 +488,22 @@ static int _cluster_do_node_callback(struct local_client *master_client, | ||||
|  | ||||
| 		if (ninfo->state != NODE_DOWN) | ||||
| 			callback(master_client, csid, ninfo->state == NODE_CLVMD); | ||||
| 		if (ninfo->state != NODE_CLVMD) | ||||
| 			somedown = -1; | ||||
| 	} | ||||
| 	return somedown; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* Real locking */ | ||||
| static int _lock_resource(char *resource, int mode, int flags, int *lockid) | ||||
| { | ||||
| 	struct lock_wait lwait; | ||||
| 	struct lock_info *linfo; | ||||
| 	SaLckResourceHandleT res_handle; | ||||
| 	SaAisErrorT err; | ||||
| 	SaLckLockIdT lock_id; | ||||
| 	SaLckLockStatusT lockStatus; | ||||
|  | ||||
| 	pthread_cond_init(&lwait.cond, NULL); | ||||
| 	pthread_mutex_init(&lwait.mutex, NULL); | ||||
| 	pthread_mutex_lock(&lwait.mutex); | ||||
|  | ||||
| 	/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */ | ||||
| 	if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE; | ||||
| @@ -486,15 +526,13 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid) | ||||
| 		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) | ||||
| 	err = saLckResourceLockAsync(res_handle, | ||||
| 				     (SaInvocationT)(long)&lwait, | ||||
| 				     &lock_id, | ||||
| 				     mode, | ||||
| 				     flags, | ||||
| 				     0); | ||||
| 	if (err != SA_AIS_OK) | ||||
| 	{ | ||||
| 		free(linfo); | ||||
| 		saLckResourceClose(res_handle); | ||||
| @@ -502,43 +540,54 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid) | ||||
| 	} | ||||
|  | ||||
| 	/* Wait for it to complete */ | ||||
| 	pthread_cond_wait(&lwait.cond, &lwait.mutex); | ||||
| 	pthread_mutex_unlock(&lwait.mutex); | ||||
|  | ||||
| 	DEBUGLOG("lock_resource returning %d, lock_id=%" PRIx64 "\n", | ||||
| 		 err, lock_id); | ||||
| 	DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", lwait.status, | ||||
| 		 lock_id); | ||||
|  | ||||
| 	linfo->lock_id = lock_id; | ||||
| 	linfo->res_handle = res_handle; | ||||
|  | ||||
| 	dm_hash_insert(lock_hash, resource, linfo); | ||||
|  | ||||
| 	return ais_to_errno(err); | ||||
| 	return ais_to_errno(lwait.status); | ||||
| } | ||||
|  | ||||
|  | ||||
| static int _unlock_resource(char *resource, int lockid) | ||||
| { | ||||
| 	struct lock_wait lwait; | ||||
| 	SaAisErrorT err; | ||||
| 	struct lock_info *linfo; | ||||
|  | ||||
| 	pthread_cond_init(&lwait.cond, NULL); | ||||
| 	pthread_mutex_init(&lwait.mutex, NULL); | ||||
| 	pthread_mutex_lock(&lwait.mutex); | ||||
|  | ||||
| 	DEBUGLOG("unlock_resource %s\n", resource); | ||||
| 	linfo = dm_hash_lookup(lock_hash, resource); | ||||
| 	if (!linfo) | ||||
| 		return 0; | ||||
|  | ||||
| 	DEBUGLOG("unlock_resource: lockid: %" PRIx64 "\n", linfo->lock_id); | ||||
| 	err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END); | ||||
| 	DEBUGLOG("unlock_resource: lockid: %llx\n", linfo->lock_id); | ||||
| 	err = saLckResourceUnlockAsync((SaInvocationT)(long)&lwait, linfo->lock_id); | ||||
| 	if (err != SA_AIS_OK) | ||||
| 	{ | ||||
| 		DEBUGLOG("Unlock returned %d\n", err); | ||||
| 		return ais_to_errno(err); | ||||
| 	} | ||||
|  | ||||
| 	/* Wait for it to complete */ | ||||
| 	pthread_cond_wait(&lwait.cond, &lwait.mutex); | ||||
| 	pthread_mutex_unlock(&lwait.mutex); | ||||
|  | ||||
| 	/* Release the resource */ | ||||
| 	dm_hash_remove(lock_hash, resource); | ||||
| 	saLckResourceClose(linfo->res_handle); | ||||
| 	free(linfo); | ||||
|  | ||||
| 	return ais_to_errno(err); | ||||
| 	return ais_to_errno(lwait.status); | ||||
| } | ||||
|  | ||||
| static int _sync_lock(const char *resource, int mode, int flags, int *lockid) | ||||
| @@ -661,7 +710,6 @@ static int _get_cluster_name(char *buf, int buflen) | ||||
| } | ||||
|  | ||||
| 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, | ||||
| @@ -684,6 +732,6 @@ struct cluster_ops *init_openais_cluster(void) | ||||
| { | ||||
| 	if (!_init_cluster()) | ||||
| 		return &_cluster_openais_ops; | ||||
|  | ||||
| 	return NULL; | ||||
| 	else | ||||
| 		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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "clvmd-common.h" | ||||
|  | ||||
| #include <pthread.h> | ||||
|  | ||||
| #include "locking.h" | ||||
| #include "clvm.h" | ||||
| #include "clvmd-comms.h" | ||||
| #include "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: | ||||
| 	pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */ | ||||
|  | ||||
| 	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_mutex_unlock(&_lock_mutex); | ||||
| 	DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n", | ||||
| 		 resource, lck->lockid, _get_mode(lck->mode)); | ||||
|  | ||||
| 	return 0; | ||||
| bad: | ||||
| 	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
											
										
									
								
							| @@ -20,6 +20,9 @@ | ||||
| #define CLVMD_MINOR_VERSION 2 | ||||
| #define CLVMD_PATCH_VERSION 1 | ||||
|  | ||||
| /* Name of the cluster LVM admin lock */ | ||||
| #define ADMIN_LOCK_NAME "CLVMD_ADMIN" | ||||
|  | ||||
| /* Default time (in seconds) we will wait for all remote commands to execute | ||||
|    before declaring them dead */ | ||||
| #define DEFAULT_CMD_TIMEOUT 60 | ||||
| @@ -32,8 +35,6 @@ struct node_reply { | ||||
| 	struct node_reply *next; | ||||
| }; | ||||
|  | ||||
| typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t; | ||||
|  | ||||
| /* | ||||
|  * These exist for the use of local sockets only when we are | ||||
|  * collecting responses from all cluster nodes | ||||
| @@ -53,12 +54,13 @@ struct localsock_bits { | ||||
| 	int finished;		/* Flag to tell subthread to exit */ | ||||
| 	int all_success;	/* Set to 0 if any node (or the pre_command) | ||||
| 				   failed */ | ||||
| 	int cleanup_needed;     /* helper for cleanup_zombie */ | ||||
| 	struct local_client *pipe_client; | ||||
| 	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_cond_t cond; | ||||
|  | ||||
| 	pthread_mutex_t reply_mutex;	/* Protect reply structure */ | ||||
| }; | ||||
|  | ||||
| /* Entries for PIPE clients */ | ||||
| @@ -94,7 +96,7 @@ struct local_client { | ||||
| 	} bits; | ||||
| }; | ||||
|  | ||||
| #define DEBUGLOG(fmt, args...) debuglog(fmt, ## args) | ||||
| #define DEBUGLOG(fmt, args...) debuglog(fmt, ## args); | ||||
|  | ||||
| #ifndef max | ||||
| #define max(a,b) ((a)>(b)?(a):(b)) | ||||
| @@ -111,15 +113,11 @@ extern void cmd_client_cleanup(struct local_client *client); | ||||
| extern int add_client(struct local_client *new_client); | ||||
|  | ||||
| extern void clvmd_cluster_init_completed(void); | ||||
| extern void process_message(struct local_client *client, char *buf, | ||||
| extern void process_message(struct local_client *client, const char *buf, | ||||
| 			    int len, const char *csid); | ||||
| extern void debuglog(const char *fmt, ... ) | ||||
|   __attribute__ ((format(printf, 1, 2))); | ||||
|  | ||||
| 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_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) 2004-2010 Red Hat, Inc. All rights reserved. | ||||
|  * Copyright (C) 2004 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
| @@ -22,20 +22,16 @@ extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, | ||||
| 		       char *resource); | ||||
| extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, | ||||
| 		      char *resource); | ||||
| extern const char *do_lock_query(char *resource); | ||||
| extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, | ||||
| 			char *resource); | ||||
| extern int do_check_lvm1(const char *vgname); | ||||
| extern int do_check_lvm1(char *vgname); | ||||
| extern int do_refresh_cache(void); | ||||
| extern int init_clvm(struct dm_hash_table *excl_uuid); | ||||
| extern void destroy_lvm(void); | ||||
| extern int init_lvm(int using_gulm); | ||||
| 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 int hold_lock(char *resource, int mode, int flags); | ||||
| extern void unlock_all(void); | ||||
| extern char *get_last_lvm_error(void); | ||||
| extern void do_lock_vg(unsigned char command, unsigned char lock_flags, | ||||
| 		      char *resource); | ||||
| extern struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name); | ||||
| void lvm_do_fs_unlock(void); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. | ||||
|  * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved. | ||||
|  * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
| @@ -13,20 +13,22 @@ | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| /* FIXME Remove duplicated functions from this file. */ | ||||
|  | ||||
| /* | ||||
|  * Send a command to a running clvmd from the command-line | ||||
|  * Tell all clvmds in a cluster to refresh their toolcontext | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "clvmd-common.h" | ||||
|  | ||||
| #include "clvm.h" | ||||
| #include "refresh_clvmd.h" | ||||
|  | ||||
| #include <stddef.h> | ||||
| #include <sys/socket.h> | ||||
| #include <sys/un.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <libdevmapper.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "clvm.h" | ||||
| #include "refresh_clvmd.h" | ||||
|  | ||||
| typedef struct lvm_response { | ||||
| 	char node[255]; | ||||
| @@ -43,16 +45,11 @@ typedef struct lvm_response { | ||||
|  | ||||
| static int _clvmd_sock = -1; | ||||
|  | ||||
| /* Open connection to the clvm daemon */ | ||||
| /* Open connection to the Cluster Manager 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; | ||||
| 	} | ||||
| 	struct sockaddr_un sockaddr; | ||||
|  | ||||
| 	/* Open local socket */ | ||||
| 	if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { | ||||
| @@ -60,6 +57,11 @@ static int _open_local_sock(void) | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	memset(&sockaddr, 0, sizeof(sockaddr)); | ||||
| 	memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME)); | ||||
|  | ||||
| 	sockaddr.sun_family = AF_UNIX; | ||||
|  | ||||
| 	if (connect(local_socket,(struct sockaddr *) &sockaddr, | ||||
| 		    sizeof(sockaddr))) { | ||||
| 		int saved_errno = errno; | ||||
| @@ -77,12 +79,12 @@ static int _open_local_sock(void) | ||||
| } | ||||
|  | ||||
| /* Send a request and return the status */ | ||||
| static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response) | ||||
| static int _send_request(char *inbuf, int inlen, char **retbuf) | ||||
| { | ||||
| 	char outbuf[PIPE_BUF]; | ||||
| 	struct clvm_header *outheader = (struct clvm_header *) outbuf; | ||||
| 	int len; | ||||
| 	unsigned off; | ||||
| 	int off; | ||||
| 	int buflen; | ||||
| 	int err; | ||||
|  | ||||
| @@ -94,8 +96,6 @@ static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_res | ||||
| 		fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno)); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (no_response) | ||||
| 		return 1; | ||||
|  | ||||
| 	/* Get the response */ | ||||
|  reread: | ||||
| @@ -151,38 +151,36 @@ static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_res | ||||
|  | ||||
| /* 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) | ||||
| 			  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'; | ||||
| 	} | ||||
| 	head->arglen = len; | ||||
|  | ||||
| 	/* | ||||
| 	 * 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; | ||||
| 	if (node) { | ||||
| 		/* | ||||
| 		 * Allow a couple of special node names: | ||||
| 		 * "*" for all nodes, | ||||
| 		 * "." for the local node only | ||||
| 		 */ | ||||
| 		if (strcmp(node, "*") == 0) { | ||||
| 			head->node[0] = '\0'; | ||||
| 		} else if (strcmp(node, ".") == 0) { | ||||
| 			head->node[0] = '\0'; | ||||
| 			head->flags = CLVMD_FLAG_LOCAL; | ||||
| 		} else | ||||
| 			strcpy(head->node, node); | ||||
| 	} else | ||||
| 		strcpy(head->node, node); | ||||
| 		head->node[0] = '\0'; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Send a message to a(or all) node(s) in the cluster and wait for replies | ||||
|  */ | ||||
| static int _cluster_request(char cmd, const char *node, void *data, int len, | ||||
| 			    lvm_response_t ** response, int *num, int no_response) | ||||
| 			   lvm_response_t ** response, int *num) | ||||
| { | ||||
| 	char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1]; | ||||
| 	char *inptr; | ||||
| @@ -202,12 +200,11 @@ static int _cluster_request(char cmd, const char *node, void *data, int len, | ||||
| 		return 0; | ||||
|  | ||||
| 	_build_header(head, cmd, node, len); | ||||
| 	if (len) | ||||
| 		memcpy(head->node + strlen(head->node) + 1, data, 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) | ||||
| 			      strlen(head->node) + len, &retbuf); | ||||
| 	if (!status) | ||||
| 		goto out; | ||||
|  | ||||
| 	/* Count the number of responses we got */ | ||||
| @@ -225,14 +222,16 @@ static int _cluster_request(char cmd, const char *node, void *data, int len, | ||||
| 	 * 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))) { | ||||
| 	*response = dm_malloc(sizeof(lvm_response_t) * num_responses + | ||||
| 			    sizeof(int) * 2); | ||||
| 	if (!*response) { | ||||
| 		errno = ENOMEM; | ||||
| 		status = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	rarray = *response; | ||||
|  | ||||
| 	/* Unpack the response into an lvm_response_t array */ | ||||
| 	inptr = head->args; | ||||
| 	i = 0; | ||||
| @@ -249,9 +248,9 @@ static int _cluster_request(char cmd, const char *node, void *data, int len, | ||||
| 			int j; | ||||
| 			for (j = 0; j < i; j++) | ||||
| 				dm_free(rarray[i].response); | ||||
| 			dm_free(rarray); | ||||
| 			free(*response); | ||||
| 			errno = ENOMEM; | ||||
| 			status = 0; | ||||
| 			status = -1; | ||||
| 			goto out; | ||||
| 		} | ||||
|  | ||||
| @@ -264,7 +263,8 @@ static int _cluster_request(char cmd, const char *node, void *data, int len, | ||||
| 	*response = rarray; | ||||
|  | ||||
|       out: | ||||
| 	dm_free(retbuf); | ||||
| 	if (retbuf) | ||||
| 		dm_free(retbuf); | ||||
|  | ||||
| 	return status; | ||||
| } | ||||
| @@ -283,16 +283,16 @@ static int _cluster_free_request(lvm_response_t * response, int num) | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int refresh_clvmd(int all_nodes) | ||||
| int refresh_clvmd() | ||||
| { | ||||
| 	int num_responses; | ||||
| 	char args[1]; // No args really. | ||||
| 	lvm_response_t *response = NULL; | ||||
| 	lvm_response_t *response; | ||||
| 	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); | ||||
| 	status = _cluster_request(CLVMD_CMD_REFRESH, "*", args, 0, &response, &num_responses); | ||||
|  | ||||
| 	/* If any nodes were down then display them and return an error */ | ||||
| 	for (i = 0; i < num_responses; i++) { | ||||
| @@ -318,65 +318,3 @@ int refresh_clvmd(int all_nodes) | ||||
|  | ||||
| 	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; | ||||
| } | ||||
|   | ||||
| @@ -1,19 +1,2 @@ | ||||
| /* | ||||
|  * Copyright (C) 2007 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
|  * This copyrighted material is made available to anyone wishing to use, | ||||
|  * modify, copy, or redistribute it subject to the terms and conditions | ||||
|  * of the GNU General Public License v.2. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
|  | ||||
| int refresh_clvmd(int all_nodes); | ||||
| int restart_clvmd(int all_nodes); | ||||
| int debug_clvmd(int level, int clusterwide); | ||||
| int refresh_clvmd(void); | ||||
|  | ||||
|   | ||||
							
								
								
									
										501
									
								
								daemons/clvmd/tcp-comms.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										501
									
								
								daemons/clvmd/tcp-comms.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,501 @@ | ||||
| /****************************************************************************** | ||||
| ******************************************************************************* | ||||
| ** | ||||
| **  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(const char *c_csid) | ||||
| { | ||||
|     struct local_client *client; | ||||
|     char csid[GULM_MAX_CSID_LEN]; | ||||
|     unsigned int i; | ||||
|     memcpy(csid, c_csid, sizeof csid); | ||||
|     DEBUGLOG("tcp_remove_client\n"); | ||||
|  | ||||
|     /* Don't actually close the socket here - that's the | ||||
|        job of clvmd.c whch will do the job when it notices the | ||||
|        other end has gone. We just need to remove the client(s) from | ||||
|        the hash table so we don't try to use it for sending any more */ | ||||
|     for (i = 0; i < 2; i++) | ||||
|     { | ||||
| 	client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN); | ||||
| 	if (client) | ||||
| 	{ | ||||
| 	    dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN); | ||||
| 	    client->removeme = 1; | ||||
| 	    close(client->fd); | ||||
| 	} | ||||
| 	/* Look for a mangled one too, on the 2nd iteration. */ | ||||
| 	csid[0] ^= 0x80; | ||||
|     } | ||||
| } | ||||
|  | ||||
| int alloc_client(int fd, const char *c_csid, struct local_client **new_client) | ||||
| { | ||||
|     struct local_client *client; | ||||
|     char csid[GULM_MAX_CSID_LEN]; | ||||
|     memcpy(csid, c_csid, sizeof csid); | ||||
|  | ||||
|     DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid)); | ||||
|  | ||||
|     /* 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, const 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(const 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, const 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, const 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(const 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(const 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(const char *); | ||||
| int get_main_gulm_cluster_fd(void); | ||||
| int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, const char *csid, struct local_client **new_client); | ||||
| int gulm_cluster_send_message(void *buf, int msglen, const char *csid, const char *errtext); | ||||
| void get_our_gulm_csid(char *csid); | ||||
| int gulm_connect_csid(const char *csid, struct local_client **newclient); | ||||
| @@ -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
|  | ||||
| CPG_LIBS = @CPG_LIBS@ | ||||
| CPG_CFLAGS = @CPG_CFLAGS@ | ||||
| SACKPT_LIBS = @SACKPT_LIBS@ | ||||
| SACKPT_CFLAGS = @SACKPT_CFLAGS@ | ||||
|  | ||||
| SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c | ||||
|  | ||||
| TARGETS = cmirrord | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| LIBS += -ldevmapper | ||||
| LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS) | ||||
| CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS) $(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,256 +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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #include "logging.h" | ||||
| #include "common.h" | ||||
| #include "functions.h" | ||||
| #include "link_mon.h" | ||||
| #include "local.h" | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <sys/socket.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/wait.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| static volatile sig_atomic_t exit_now = 0; | ||||
| /* FIXME Review signal handling.  Should be volatile sig_atomic_t */ | ||||
| static sigset_t signal_mask; | ||||
| static volatile sig_atomic_t signal_received; | ||||
|  | ||||
| static void process_signals(void); | ||||
| static void daemonize(void); | ||||
| static void init_all(void); | ||||
| static void cleanup_all(void); | ||||
|  | ||||
| int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) | ||||
| { | ||||
| 	daemonize(); | ||||
|  | ||||
| 	init_all(); | ||||
|  | ||||
| 	/* Parent can now exit, we're ready to handle requests */ | ||||
| 	kill(getppid(), SIGTERM); | ||||
|  | ||||
| 	LOG_PRINT("Starting cmirrord:"); | ||||
| 	LOG_PRINT(" Built: "__DATE__" "__TIME__"\n"); | ||||
| 	LOG_DBG(" Compiled with debugging."); | ||||
|  | ||||
| 	while (!exit_now) { | ||||
| 		links_monitor(); | ||||
|  | ||||
| 		links_issue_callbacks(); | ||||
|  | ||||
| 		process_signals(); | ||||
| 	} | ||||
| 	exit(EXIT_SUCCESS); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * parent_exit_handler: exit the parent | ||||
|  * @sig: the signal | ||||
|  * | ||||
|  */ | ||||
| static void parent_exit_handler(int sig __attribute__((unused))) | ||||
| { | ||||
| 	exit_now = 1; | ||||
| } | ||||
|  | ||||
| static void sig_handler(int sig) | ||||
| { | ||||
| 	/* FIXME Races - don't touch signal_mask here. */ | ||||
| 	sigaddset(&signal_mask, sig); | ||||
| 	signal_received = 1; | ||||
| } | ||||
|  | ||||
| static void process_signal(int sig){ | ||||
| 	int r = 0; | ||||
|  | ||||
| 	switch(sig) { | ||||
| 	case SIGINT: | ||||
| 	case SIGQUIT: | ||||
| 	case SIGTERM: | ||||
| 	case SIGHUP: | ||||
| 		r += log_status(); | ||||
| 		break; | ||||
| 	case SIGUSR1: | ||||
| 	case SIGUSR2: | ||||
| 		log_debug(); | ||||
| 		/*local_debug();*/ | ||||
| 		cluster_debug(); | ||||
| 		return; | ||||
| 	default: | ||||
| 		LOG_PRINT("Unknown signal received... ignoring"); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (!r) { | ||||
| 		LOG_DBG("No current cluster logs... safe to exit."); | ||||
| 		cleanup_all(); | ||||
| 		exit(EXIT_SUCCESS); | ||||
| 	} | ||||
|  | ||||
| 	LOG_ERROR("Cluster logs exist.  Refusing to exit."); | ||||
| } | ||||
|  | ||||
| static void process_signals(void) | ||||
| { | ||||
| 	int x; | ||||
|  | ||||
| 	if (!signal_received) | ||||
| 		return; | ||||
|  | ||||
| 	signal_received = 0; | ||||
|  | ||||
| 	for (x = 1; x < _NSIG; x++) { | ||||
| 		if (sigismember(&signal_mask, x)) { | ||||
| 			sigdelset(&signal_mask, x); | ||||
| 			process_signal(x); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void remove_lockfile(void) | ||||
| { | ||||
| 	if (unlink(CMIRRORD_PIDFILE)) | ||||
| 		LOG_ERROR("Unable to remove \"" CMIRRORD_PIDFILE "\" %s", strerror(errno)); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * daemonize | ||||
|  * | ||||
|  * Performs the steps necessary to become a daemon. | ||||
|  */ | ||||
| static void daemonize(void) | ||||
| { | ||||
| 	int pid; | ||||
| 	int status; | ||||
| 	int devnull; | ||||
|  | ||||
| 	if ((devnull = open("/dev/null", O_RDWR)) == -1) { | ||||
| 		LOG_ERROR("Can't open /dev/null: %s", strerror(errno)); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
|  | ||||
| 	signal(SIGTERM, &parent_exit_handler); | ||||
|  | ||||
| 	pid = fork(); | ||||
|  | ||||
| 	if (pid < 0) { | ||||
| 		LOG_ERROR("Unable to fork()"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
|  | ||||
| 	if (pid) { | ||||
| 		/* Parent waits here for child to get going */ | ||||
| 		while (!waitpid(pid, &status, WNOHANG) && !exit_now); | ||||
| 		if (exit_now) | ||||
| 			exit(EXIT_SUCCESS); | ||||
|  | ||||
| 		switch (WEXITSTATUS(status)) { | ||||
| 		case EXIT_LOCKFILE: | ||||
| 			LOG_ERROR("Failed to create lockfile"); | ||||
| 			LOG_ERROR("Process already running?"); | ||||
| 			break; | ||||
| 		case EXIT_KERNEL_SOCKET: | ||||
| 			LOG_ERROR("Unable to create netlink socket"); | ||||
| 			break; | ||||
| 		case EXIT_KERNEL_BIND: | ||||
| 			LOG_ERROR("Unable to bind to netlink socket"); | ||||
| 			break; | ||||
| 		case EXIT_KERNEL_SETSOCKOPT: | ||||
| 			LOG_ERROR("Unable to setsockopt on netlink socket"); | ||||
| 			break; | ||||
| 		case EXIT_CLUSTER_CKPT_INIT: | ||||
| 			LOG_ERROR("Unable to initialize checkpoint service"); | ||||
| 			LOG_ERROR("Has the cluster infrastructure been started?"); | ||||
| 			break; | ||||
| 		case EXIT_FAILURE: | ||||
| 			LOG_ERROR("Failed to start: Generic error"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			LOG_ERROR("Failed to start: Unknown error"); | ||||
| 			break; | ||||
| 		} | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
|  | ||||
| 	setsid(); | ||||
| 	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); | ||||
|  | ||||
| 	(void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG); | ||||
| 	if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0) | ||||
| 		exit(EXIT_LOCKFILE); | ||||
| 	(void) dm_prepare_selinux_context(NULL, 0); | ||||
|  | ||||
| 	atexit(remove_lockfile); | ||||
|  | ||||
| 	/* FIXME Replace with sigaction. (deprecated) */ | ||||
| 	signal(SIGINT, &sig_handler); | ||||
| 	signal(SIGQUIT, &sig_handler); | ||||
| 	signal(SIGTERM, &sig_handler); | ||||
| 	signal(SIGHUP, &sig_handler); | ||||
| 	signal(SIGPIPE, SIG_IGN); | ||||
| 	signal(SIGUSR1, &sig_handler); | ||||
| 	signal(SIGUSR2, &sig_handler); | ||||
| 	sigemptyset(&signal_mask); | ||||
| 	signal_received = 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * init_all | ||||
|  * | ||||
|  * Initialize modules.  Exit on failure. | ||||
|  */ | ||||
| static void init_all(void) | ||||
| { | ||||
| 	int r; | ||||
|  | ||||
| 	if ((r = init_local()) || | ||||
| 	    (r = init_cluster())) { | ||||
| 		exit(r); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * cleanup_all | ||||
|  * | ||||
|  * Clean up before exiting | ||||
|  */ | ||||
| static void cleanup_all(void) | ||||
| { | ||||
| 	cleanup_local(); | ||||
| 	cleanup_cluster(); | ||||
| } | ||||
										
											
												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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #ifndef _LVM_CLOG_CLUSTER_H | ||||
| #define _LVM_CLOG_CLUSTER_H | ||||
|  | ||||
| #include "dm-log-userspace.h" | ||||
| #include "libdevmapper.h" | ||||
|  | ||||
| #define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */ | ||||
| #define DM_ULOG_CHECKPOINT_READY 21 | ||||
| #define DM_ULOG_MEMBER_JOIN      22 | ||||
|  | ||||
| /* | ||||
|  * There is other information in addition to what can | ||||
|  * be found in the dm_ulog_request structure that we | ||||
|  * need for processing.  'clog_request' is the wrapping | ||||
|  * structure we use to make the additional fields | ||||
|  * available. | ||||
|  */ | ||||
| struct clog_request { | ||||
| 	/* | ||||
| 	 * If we don't use a union, the structure size will | ||||
| 	 * vary between 32-bit and 64-bit machines.  So, we | ||||
| 	 * pack two 64-bit version numbers in there to force | ||||
| 	 * the size of the structure to be the same. | ||||
| 	 * | ||||
| 	 * The two version numbers also help us with endian | ||||
| 	 * issues.  The first is always little endian, while | ||||
| 	 * the second is in native format of the sending | ||||
| 	 * machine.  If the two are equal, there is no need | ||||
| 	 * to do endian conversions. | ||||
| 	 */ | ||||
| 	union { | ||||
| 		uint64_t version[2]; /* LE version and native version */ | ||||
| 		struct dm_list list; | ||||
| 	} u; | ||||
|  | ||||
| 	/* | ||||
| 	 * 'originator' is the machine from which the requests | ||||
| 	 * was made. | ||||
| 	 */ | ||||
| 	uint32_t originator; | ||||
|  | ||||
| 	/* | ||||
| 	 * 'pit_server' is the "point-in-time" server for the | ||||
| 	 * request.  (I.e.  The machine that was the server at | ||||
| 	 * the time the request was issued - only important during | ||||
| 	 * startup. | ||||
| 	 */ | ||||
| 	uint32_t pit_server; | ||||
|  | ||||
| 	/* | ||||
| 	 * The request from the kernel that is being processed | ||||
| 	 */ | ||||
| 	struct dm_ulog_request u_rq; | ||||
| }; | ||||
|  | ||||
| int init_cluster(void); | ||||
| void cleanup_cluster(void); | ||||
| void cluster_debug(void); | ||||
|  | ||||
| int create_cluster_cpg(char *uuid, uint64_t luid); | ||||
| int destroy_cluster_cpg(char *uuid); | ||||
|  | ||||
| int cluster_send(struct clog_request *rq); | ||||
|  | ||||
| #endif /* _LVM_CLOG_CLUSTER_H */ | ||||
| @@ -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #ifndef _LVM_CLOG_COMMON_H | ||||
| #define _LVM_CLOG_COMMON_H | ||||
|  | ||||
| /* | ||||
|  * If there are problems when forking off to become a daemon, | ||||
|  * the child will exist with one of these codes.  This allows | ||||
|  * the parent to know the reason for the failure and print it | ||||
|  * to the launching terminal. | ||||
|  * | ||||
|  * #define EXIT_SUCCESS 0 (from stdlib.h) | ||||
|  * #define EXIT_FAILURE 1 (from stdlib.h) | ||||
|  */ | ||||
| #define EXIT_LOCKFILE              2 | ||||
| #define EXIT_KERNEL_SOCKET         3 /* Failed netlink socket create */ | ||||
| #define EXIT_KERNEL_BIND           4 | ||||
| #define EXIT_KERNEL_SETSOCKOPT     5 | ||||
| #define EXIT_CLUSTER_CKPT_INIT     6 /* Failed to init checkpoint */ | ||||
| #define EXIT_QUEUE_NOMEM           7 | ||||
|  | ||||
| #define DM_ULOG_REQUEST_SIZE 1024 | ||||
|  | ||||
| #endif /* _LVM_CLOG_COMMON_H */ | ||||
| @@ -1,211 +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]); | ||||
| 	uint64_t unconverted_version = vp[1]; | ||||
| 	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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #ifndef _LVM_CLOG_FUNCTIONS_H | ||||
| #define _LVM_CLOG_FUNCTIONS_H | ||||
|  | ||||
| #include "dm-log-userspace.h" | ||||
| #include "cluster.h" | ||||
|  | ||||
| #define LOG_RESUMED   1 | ||||
| #define LOG_SUSPENDED 2 | ||||
|  | ||||
| int local_resume(struct dm_ulog_request *rq); | ||||
| int cluster_postsuspend(char *, uint64_t); | ||||
|  | ||||
| int do_request(struct clog_request *rq, int server); | ||||
| int push_state(const char *uuid, uint64_t luid, | ||||
| 	       const char *which, char **buf, uint32_t debug_who); | ||||
| int pull_state(const char *uuid, uint64_t luid, | ||||
| 	       const char *which, char *buf, int size); | ||||
|  | ||||
| int log_get_state(struct dm_ulog_request *rq); | ||||
| int log_status(void); | ||||
| void log_debug(void); | ||||
|  | ||||
| #endif /* _LVM_CLOG_FUNCTIONS_H */ | ||||
| @@ -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #include "logging.h" | ||||
| #include "link_mon.h" | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <poll.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| struct link_callback { | ||||
| 	int fd; | ||||
| 	const char *name; | ||||
| 	void *data; | ||||
| 	int (*callback)(void *data); | ||||
|  | ||||
| 	struct link_callback *next; | ||||
| }; | ||||
|  | ||||
| static unsigned used_pfds = 0; | ||||
| static unsigned free_pfds = 0; | ||||
| static struct pollfd *pfds = NULL; | ||||
| static struct link_callback *callbacks = NULL; | ||||
|  | ||||
| int links_register(int fd, const char *name, int (*callback)(void *data), void *data) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	struct link_callback *lc; | ||||
|  | ||||
| 	for (i = 0; i < used_pfds; i++) { | ||||
| 		if (fd == pfds[i].fd) { | ||||
| 			LOG_ERROR("links_register: Duplicate file descriptor"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	lc = malloc(sizeof(*lc)); | ||||
| 	if (!lc) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	lc->fd = fd; | ||||
| 	lc->name = name; | ||||
| 	lc->data = data; | ||||
| 	lc->callback = callback; | ||||
|  | ||||
| 	if (!free_pfds) { | ||||
| 		struct pollfd *tmp; | ||||
| 		tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1)); | ||||
| 		if (!tmp) { | ||||
| 			free(lc); | ||||
| 			return -ENOMEM; | ||||
| 		} | ||||
|  | ||||
| 		pfds = tmp; | ||||
| 		free_pfds = used_pfds + 1; | ||||
| 	} | ||||
|  | ||||
| 	free_pfds--; | ||||
| 	pfds[used_pfds].fd = fd; | ||||
| 	pfds[used_pfds].events = POLLIN; | ||||
| 	pfds[used_pfds].revents = 0; | ||||
| 	used_pfds++; | ||||
|  | ||||
| 	lc->next = callbacks; | ||||
| 	callbacks = lc; | ||||
| 	LOG_DBG("Adding %s/%d", lc->name, lc->fd); | ||||
| 	LOG_DBG(" used_pfds = %u, free_pfds = %u", | ||||
| 		used_pfds, free_pfds); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int links_unregister(int fd) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	struct link_callback *p, *c; | ||||
|  | ||||
| 	for (i = 0; i < used_pfds; i++) | ||||
| 		if (fd == pfds[i].fd) { | ||||
| 			/* entire struct is copied (overwritten) */ | ||||
| 			pfds[i] = pfds[used_pfds - 1]; | ||||
| 			used_pfds--; | ||||
| 			free_pfds++; | ||||
| 		} | ||||
|  | ||||
| 	for (p = NULL, c = callbacks; c; p = c, c = c->next) | ||||
| 		if (fd == c->fd) { | ||||
| 			LOG_DBG("Freeing up %s/%d", c->name, c->fd); | ||||
| 			LOG_DBG(" used_pfds = %u, free_pfds = %u", | ||||
| 				used_pfds, free_pfds); | ||||
| 			if (p) | ||||
| 				p->next = c->next; | ||||
| 			else | ||||
| 				callbacks = c->next; | ||||
| 			free(c); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int links_monitor(void) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	int r; | ||||
|  | ||||
| 	for (i = 0; i < used_pfds; i++) { | ||||
| 		pfds[i].revents = 0; | ||||
| 	} | ||||
|  | ||||
| 	r = poll(pfds, used_pfds, -1); | ||||
| 	if (r <= 0) | ||||
| 		return r; | ||||
|  | ||||
| 	r = 0; | ||||
| 	/* FIXME: handle POLLHUP */ | ||||
| 	for (i = 0; i < used_pfds; i++) | ||||
| 		if (pfds[i].revents & POLLIN) { | ||||
| 			LOG_DBG("Data ready on %d", pfds[i].fd); | ||||
|  | ||||
| 			/* FIXME: Add this back return 1;*/ | ||||
| 			r++; | ||||
| 		} | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| int links_issue_callbacks(void) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	struct link_callback *lc; | ||||
|  | ||||
| 	for (i = 0; i < used_pfds; i++) | ||||
| 		if (pfds[i].revents & POLLIN) | ||||
| 			for (lc = callbacks; lc; lc = lc->next) | ||||
| 				if (pfds[i].fd == lc->fd) { | ||||
| 					LOG_DBG("Issuing callback on %s/%d", | ||||
| 						lc->name, lc->fd); | ||||
| 					lc->callback(lc->data); | ||||
| 					break; | ||||
| 				} | ||||
| 	return 0; | ||||
| } | ||||
| @@ -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #ifndef _LVM_CLOG_LINK_MON_H | ||||
| #define _LVM_CLOG_LINK_MON_H | ||||
|  | ||||
| int links_register(int fd, const char *name, int (*callback)(void *data), void *data); | ||||
| int links_unregister(int fd); | ||||
| int links_monitor(void); | ||||
| int links_issue_callbacks(void); | ||||
|  | ||||
| #endif /* _LVM_CLOG_LINK_MON_H */ | ||||
| @@ -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #include "logging.h" | ||||
| #include "common.h" | ||||
| #include "functions.h" | ||||
| #include "link_mon.h" | ||||
| #include "local.h" | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <sys/socket.h> | ||||
| #include <linux/connector.h> | ||||
| #include <linux/netlink.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #ifndef CN_IDX_DM | ||||
| /* Kernel 2.6.31 is required to run this code */ | ||||
| #define CN_IDX_DM                       0x7     /* Device Mapper */ | ||||
| #define CN_VAL_DM_USERSPACE_LOG         0x1 | ||||
| #endif | ||||
|  | ||||
| static int cn_fd = -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #ifndef _LVM_CLOG_LOCAL_H | ||||
| #define _LVM_CLOG_LOCAL_H | ||||
|  | ||||
| int init_local(void); | ||||
| void cleanup_local(void); | ||||
|  | ||||
| int kernel_send(struct dm_ulog_request *rq); | ||||
|  | ||||
| #endif /* _LVM_CLOG_LOCAL_H */ | ||||
| @@ -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| #include "logging.h" | ||||
|  | ||||
| const char *__rq_types_off_by_one[] = { | ||||
| 	"DM_ULOG_CTR", | ||||
| 	"DM_ULOG_DTR", | ||||
| 	"DM_ULOG_PRESUSPEND", | ||||
| 	"DM_ULOG_POSTSUSPEND", | ||||
| 	"DM_ULOG_RESUME", | ||||
| 	"DM_ULOG_GET_REGION_SIZE", | ||||
| 	"DM_ULOG_IS_CLEAN", | ||||
| 	"DM_ULOG_IN_SYNC", | ||||
| 	"DM_ULOG_FLUSH", | ||||
| 	"DM_ULOG_MARK_REGION", | ||||
| 	"DM_ULOG_CLEAR_REGION", | ||||
| 	"DM_ULOG_GET_RESYNC_WORK", | ||||
| 	"DM_ULOG_SET_REGION_SYNC", | ||||
| 	"DM_ULOG_GET_SYNC_COUNT", | ||||
| 	"DM_ULOG_STATUS_INFO", | ||||
| 	"DM_ULOG_STATUS_TABLE", | ||||
| 	"DM_ULOG_IS_REMOTE_RECOVERING", | ||||
| 	NULL | ||||
| }; | ||||
|  | ||||
| int log_tabbing = 0; | ||||
| int log_is_open = 0; | ||||
|  | ||||
| /* | ||||
|  * Variables for various conditional logging | ||||
|  */ | ||||
| #ifdef MEMB | ||||
| int log_membership_change = 1; | ||||
| #else | ||||
| int log_membership_change = 0; | ||||
| #endif | ||||
|  | ||||
| #ifdef CKPT | ||||
| int log_checkpoint = 1; | ||||
| #else | ||||
| int log_checkpoint = 0; | ||||
| #endif | ||||
|  | ||||
| #ifdef RESEND | ||||
| int log_resend_requests = 1; | ||||
| #else | ||||
| int log_resend_requests = 0; | ||||
| #endif | ||||
| @@ -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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #ifndef _LVM_CLOG_LOGGING_H | ||||
| #define _LVM_CLOG_LOGGING_H | ||||
|  | ||||
| #define _GNU_SOURCE | ||||
| #define _FILE_OFFSET_BITS 64 | ||||
|  | ||||
| #include "configure.h" | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| #include <syslog.h> | ||||
|  | ||||
| /* SHORT_UUID - print last 8 chars of a string */ | ||||
| #define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x) | ||||
|  | ||||
| extern const char *__rq_types_off_by_one[]; | ||||
| #define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1] | ||||
|  | ||||
| extern int log_tabbing; | ||||
| extern int log_is_open; | ||||
| extern int log_membership_change; | ||||
| extern int log_checkpoint; | ||||
| extern int log_resend_requests; | ||||
|  | ||||
| #define LOG_OPEN(ident, option, facility) do { \ | ||||
| 		openlog(ident, option, facility); \ | ||||
| 		log_is_open = 1;		  \ | ||||
| 	} while (0) | ||||
|  | ||||
| #define LOG_CLOSE(void) do { \ | ||||
| 		log_is_open = 0; \ | ||||
| 		closelog();	 \ | ||||
| 	} while (0) | ||||
|  | ||||
| #define LOG_OUTPUT(level, f, arg...) do {				\ | ||||
| 		int __i;						\ | ||||
| 		char __buffer[16];					\ | ||||
| 		FILE *fp = (level > LOG_NOTICE) ? stderr : stdout;	\ | ||||
| 		if (log_is_open) {					\ | ||||
| 			for (__i = 0; (__i < log_tabbing) && (__i < 15); __i++) \ | ||||
| 				__buffer[__i] = '\t';			\ | ||||
| 			__buffer[__i] = '\0';				\ | ||||
| 			syslog(level, "%s" f "\n", __buffer, ## arg);	\ | ||||
| 		} else {						\ | ||||
| 			for (__i = 0; __i < log_tabbing; __i++)		\ | ||||
| 				fprintf(fp, "\t");			\ | ||||
| 			fprintf(fp, f "\n", ## arg);			\ | ||||
| 		}							\ | ||||
| 	} while (0) | ||||
|  | ||||
|  | ||||
| #ifdef DEBUG | ||||
| #define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg) | ||||
| #else /* DEBUG */ | ||||
| #define LOG_DBG(f, arg...) 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,19 @@ | ||||
| init_fifos | ||||
| fini_fifos | ||||
| daemon_talk | ||||
| dm_event_get_version | ||||
| dm_event_handler_create | ||||
| dm_event_handler_destroy | ||||
| dm_event_handler_set_dso | ||||
| dm_event_handler_set_dev_name | ||||
| dm_event_handler_set_uuid | ||||
| dm_event_handler_set_major | ||||
| dm_event_handler_set_minor | ||||
| dm_event_handler_set_event_mask | ||||
| dm_event_handler_get_dso | ||||
| dm_event_handler_get_devname | ||||
| dm_event_handler_get_uuid | ||||
| dm_event_handler_get_major | ||||
| dm_event_handler_get_minor | ||||
| dm_event_handler_get_event_mask | ||||
| dm_event_register_handler | ||||
| dm_event_unregister_handler | ||||
| dm_event_get_registered_device | ||||
| dm_event_handler_set_timeout | ||||
| dm_event_handler_get_timeout | ||||
|   | ||||
| @@ -1,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. | ||||
| # | ||||
| @@ -13,98 +13,71 @@ | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| VPATH = @srcdir@ | ||||
|  | ||||
| SOURCES = libdevmapper-event.c | ||||
| SOURCES2 = dmeventd.c | ||||
|  | ||||
| LIB_STATIC = libdevmapper-event.a | ||||
|  | ||||
| ifeq ("@LIB_SUFFIX@","dylib") | ||||
|   LIB_SHARED = libdevmapper-event.dylib | ||||
| else | ||||
|   LIB_SHARED = libdevmapper-event.so | ||||
| endif | ||||
|  | ||||
| TARGETS = dmeventd | ||||
| CLEAN_TARGETS = dmeventd.o | ||||
|  | ||||
| .PHONY: install_lib_dynamic install_lib_static install_include \ | ||||
| 	install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \ | ||||
| 	install_lib install_dmeventd | ||||
| include ../make.tmpl | ||||
|  | ||||
| INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic | ||||
| INSTALL_LIB_TARGETS = install_lib_dynamic | ||||
|  | ||||
| LIB_NAME = libdevmapper-event | ||||
| ifeq ("@STATIC_LINK@", "yes") | ||||
|   LIB_STATIC = $(LIB_NAME).a | ||||
|   TARGETS += $(LIB_STATIC) dmeventd.static | ||||
|   INSTALL_DMEVENTD_TARGETS += install_dmeventd_static | ||||
|   INSTALL_LIB_TARGETS += install_lib_static | ||||
| endif | ||||
|  | ||||
| LIB_VERSION = $(LIB_VERSION_DM) | ||||
| LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) | ||||
|  | ||||
| CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a | ||||
|  | ||||
| ifneq ($(MAKECMDGOALS),device-mapper) | ||||
|   SUBDIRS+=plugins | ||||
| endif | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
| CFLOW_TARGET = dmeventd | ||||
|  | ||||
| EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h | ||||
| EXPORTED_FN_PREFIX = dm_event | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| all: device-mapper | ||||
| device-mapper: $(TARGETS) | ||||
|  | ||||
| LIBS += -ldevmapper | ||||
| LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS) | ||||
|  | ||||
| CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS) | ||||
| LDFLAGS += -ldl -ldevmapper -lpthread | ||||
| CLDFLAGS += -ldl -ldevmapper -lpthread | ||||
|  | ||||
| dmeventd: $(LIB_SHARED) dmeventd.o | ||||
| 	$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \ | ||||
| 	$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic | ||||
| 	$(CC) -o $@ dmeventd.o $(CFLAGS) $(LDFLAGS) \ | ||||
| 	-L. -ldevmapper-event $(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) | ||||
| .PHONY: install_dynamic install_static install_include \ | ||||
| 	install_pkgconfig install_dmeventd | ||||
|  | ||||
| INSTALL_TYPE = install_dynamic | ||||
|  | ||||
| ifeq ("@STATIC_LINK@", "yes") | ||||
|   INSTALL_TYPE += install_static | ||||
| endif | ||||
|  | ||||
| ifeq ("@PKGCONFIG@", "yes") | ||||
|   INSTALL_LIB_TARGETS += install_pkgconfig | ||||
|   INSTALL_TYPE += install_pkgconfig | ||||
| endif | ||||
|  | ||||
| ifneq ("$(CFLOW_CMD)", "") | ||||
| CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) | ||||
| -include $(top_builddir)/libdm/libdevmapper.cflow | ||||
| -include $(top_builddir)/lib/liblvm-internal.cflow | ||||
| -include $(top_builddir)/lib/liblvm2cmd.cflow | ||||
| -include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow | ||||
| -include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow | ||||
| endif | ||||
| install: $(INSTALL_TYPE) install_include install_dmeventd | ||||
|  | ||||
| install_include: $(srcdir)/libdevmapper-event.h | ||||
| 	$(INSTALL_DATA) -D $< $(includedir)/$(<F) | ||||
| install_include: | ||||
| 	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \ | ||||
| 		$(includedir)/libdevmapper-event.h | ||||
|  | ||||
| install_pkgconfig: libdevmapper-event.pc | ||||
| 	$(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc | ||||
| install_dynamic: libdevmapper-event.$(LIB_SUFFIX) | ||||
| 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ | ||||
| 		$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) | ||||
| 	$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \ | ||||
| 		$(libdir)/libdevmapper-event.$(LIB_SUFFIX) | ||||
|  | ||||
| install_lib_dynamic: install_lib_shared | ||||
| install_dmeventd: dmeventd | ||||
| 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$< | ||||
|  | ||||
| install_lib_static: $(LIB_STATIC) | ||||
| 	$(INSTALL_DATA) -D $< $(usrlibdir)/$(<F) | ||||
| install_pkgconfig: | ||||
| 	$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \ | ||||
| 		$(usrlibdir)/pkgconfig/devmapper-event.pc | ||||
|  | ||||
| install_lib: $(INSTALL_LIB_TARGETS) | ||||
| install_static: libdevmapper-event.a | ||||
| 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \ | ||||
| 		$(libdir)/libdevmapper-event.a.$(LIB_VERSION) | ||||
| 	$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a | ||||
|  | ||||
| install_dmeventd_dynamic: dmeventd | ||||
| 	$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F) | ||||
| .PHONY: distclean_lib distclean | ||||
|  | ||||
| install_dmeventd_static: dmeventd.static | ||||
| 	$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F) | ||||
| distclean_lib:  | ||||
| 	$(RM) libdevmapper-event.pc | ||||
|  | ||||
| install_dmeventd: $(INSTALL_DMEVENTD_TARGETS) | ||||
| distclean: distclean_lib | ||||
|  | ||||
| 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,24 +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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #ifndef __DMEVENTD_DOT_H__ | ||||
| #define __DMEVENTD_DOT_H__ | ||||
|  | ||||
| /* FIXME This stuff must be configurable. */ | ||||
|  | ||||
| #define	DM_EVENT_FIFO_CLIENT	DEFAULT_DM_RUN_DIR "/dmeventd-client" | ||||
| #define	DM_EVENT_FIFO_SERVER	DEFAULT_DM_RUN_DIR "/dmeventd-server" | ||||
| #define	DM_EVENT_DAEMON		"/sbin/dmeventd" | ||||
| #define DM_EVENT_LOCKFILE	"/var/lock/dmeventd" | ||||
| #define	DM_EVENT_FIFO_CLIENT	"/var/run/dmeventd-client" | ||||
| #define	DM_EVENT_FIFO_SERVER	"/var/run/dmeventd-server" | ||||
| #define DM_EVENT_PIDFILE	"/var/run/dmeventd.pid" | ||||
|  | ||||
| #define DM_EVENT_DEFAULT_TIMEOUT 10 | ||||
|  | ||||
| @@ -32,9 +21,6 @@ enum dm_event_command { | ||||
| 	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. */ | ||||
| @@ -56,21 +42,11 @@ struct dm_event_fifos { | ||||
|  | ||||
| /*      EXIT_SUCCESS             0 -- stdlib.h */ | ||||
| /*      EXIT_FAILURE             1 -- stdlib.h */ | ||||
| /*      EXIT_LOCKFILE_INUSE      2 -- obsoleted */ | ||||
| #define EXIT_LOCKFILE_INUSE      2 | ||||
| #define EXIT_DESC_CLOSE_FAILURE  3 | ||||
| #define EXIT_DESC_OPEN_FAILURE   4 | ||||
| /*      EXIT_OPEN_PID_FAILURE    5 -- obsoleted */ | ||||
| #define EXIT_OPEN_PID_FAILURE    5 | ||||
| #define EXIT_FIFO_FAILURE        6 | ||||
| #define EXIT_CHDIR_FAILURE       7 | ||||
|  | ||||
| /* Implemented in libdevmapper-event.c, but not part of public API. */ | ||||
| // FIXME  misuse of bitmask as enum | ||||
| int daemon_talk(struct dm_event_fifos *fifos, | ||||
| 		struct dm_event_daemon_message *msg, int cmd, | ||||
| 		const char *dso_name, const char *dev_name, | ||||
| 		enum dm_event_mask evmask, uint32_t timeout); | ||||
| int init_fifos(struct dm_event_fifos *fifos); | ||||
| void fini_fifos(struct dm_event_fifos *fifos); | ||||
| int dm_event_get_version(struct dm_event_fifos *fifos, int *version); | ||||
|  | ||||
| #endif /* __DMEVENTD_DOT_H__ */ | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright (C) 2005-2007 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. | ||||
|  * | ||||
| @@ -12,7 +12,7 @@ | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "dmlib.h" | ||||
| #include "lib.h" | ||||
| #include "libdevmapper-event.h" | ||||
| //#include "libmultilog.h" | ||||
| #include "dmeventd.h" | ||||
| @@ -20,6 +20,7 @@ | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <sys/file.h> | ||||
| @@ -34,8 +35,6 @@ static int _sequence_nr = 0; | ||||
| struct dm_event_handler { | ||||
| 	char *dso; | ||||
|  | ||||
| 	char *dmeventd_path; | ||||
|  | ||||
| 	char *dev_name; | ||||
|  | ||||
| 	char *uuid; | ||||
| @@ -48,20 +47,25 @@ struct dm_event_handler { | ||||
|  | ||||
| static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh) | ||||
| { | ||||
| 	dm_free(dmevh->dev_name); | ||||
| 	dm_free(dmevh->uuid); | ||||
| 	if (dmevh->dev_name) | ||||
| 		dm_free(dmevh->dev_name); | ||||
| 	if (dmevh->uuid) | ||||
| 		dm_free(dmevh->uuid); | ||||
| 	dmevh->dev_name = dmevh->uuid = NULL; | ||||
| 	dmevh->major = dmevh->minor = 0; | ||||
| } | ||||
|  | ||||
| struct dm_event_handler *dm_event_handler_create(void) | ||||
| { | ||||
| 	struct dm_event_handler *dmevh; | ||||
| 	struct dm_event_handler *dmevh = NULL; | ||||
|  | ||||
| 	if (!(dmevh = dm_zalloc(sizeof(*dmevh)))) { | ||||
| 		log_error("Failed to allocate event handler."); | ||||
| 	if (!(dmevh = dm_malloc(sizeof(*dmevh)))) | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL; | ||||
| 	dmevh->major = dmevh->minor = 0; | ||||
| 	dmevh->mask = 0; | ||||
| 	dmevh->timeout = 0; | ||||
|  | ||||
| 	return dmevh; | ||||
| } | ||||
| @@ -69,32 +73,20 @@ struct dm_event_handler *dm_event_handler_create(void) | ||||
| void dm_event_handler_destroy(struct dm_event_handler *dmevh) | ||||
| { | ||||
| 	_dm_event_handler_clear_dev_info(dmevh); | ||||
| 	dm_free(dmevh->dso); | ||||
| 	dm_free(dmevh->dmeventd_path); | ||||
| 	if (dmevh->dso) | ||||
| 		dm_free(dmevh->dso); | ||||
| 	dm_free(dmevh); | ||||
| } | ||||
|  | ||||
| int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path) | ||||
| { | ||||
| 	if (!dmeventd_path) /* noop */ | ||||
| 		return 0; | ||||
|  | ||||
| 	dm_free(dmevh->dmeventd_path); | ||||
|  | ||||
| 	if (!(dmevh->dmeventd_path = dm_strdup(dmeventd_path))) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path) | ||||
| { | ||||
| 	if (!path) /* noop */ | ||||
| 		return 0; | ||||
| 	if (dmevh->dso) | ||||
| 		dm_free(dmevh->dso); | ||||
|  | ||||
| 	dm_free(dmevh->dso); | ||||
|  | ||||
| 	if (!(dmevh->dso = dm_strdup(path))) | ||||
| 	dmevh->dso = dm_strdup(path); | ||||
| 	if (!dmevh->dso) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	return 0; | ||||
| @@ -107,9 +99,9 @@ int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *de | ||||
|  | ||||
| 	_dm_event_handler_clear_dev_info(dmevh); | ||||
|  | ||||
| 	if (!(dmevh->dev_name = dm_strdup(dev_name))) | ||||
| 	dmevh->dev_name = dm_strdup(dev_name); | ||||
| 	if (!dmevh->dev_name) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -120,9 +112,9 @@ int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid) | ||||
|  | ||||
| 	_dm_event_handler_clear_dev_info(dmevh); | ||||
|  | ||||
| 	if (!(dmevh->uuid = dm_strdup(uuid))) | ||||
| 	dmevh->uuid = dm_strdup(uuid); | ||||
| 	if (!dmevh->dev_name) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -222,25 +214,23 @@ static int _daemon_read(struct dm_event_fifos *fifos, | ||||
| 	unsigned bytes = 0; | ||||
| 	int ret, i; | ||||
| 	fd_set fds; | ||||
| 	struct timeval tval = { 0, 0 }; | ||||
| 	size_t size = 2 * sizeof(uint32_t);	/* status + size */ | ||||
| 	uint32_t *header = alloca(size); | ||||
| 	char *buf = (char *)header; | ||||
| 	char *buf = alloca(size); | ||||
| 	int header = 1; | ||||
|  | ||||
| 	while (bytes < size) { | ||||
| 		for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) { | ||||
| 			/* Watch daemon read FIFO for input. */ | ||||
| 			struct timeval tval = { .tv_sec = 1 }; | ||||
| 			FD_ZERO(&fds); | ||||
| 			FD_SET(fifos->server, &fds); | ||||
| 			ret = select(fifos->server + 1, &fds, NULL, NULL, &tval); | ||||
| 			tval.tv_sec = 1; | ||||
| 			ret = select(fifos->server + 1, &fds, NULL, NULL, | ||||
| 				     &tval); | ||||
| 			if (ret < 0 && errno != EINTR) { | ||||
| 				log_error("Unable to read from event server"); | ||||
| 				return 0; | ||||
| 			} | ||||
| 			if ((ret == 0) && (i > 4) && !bytes) { | ||||
| 				log_error("No input from event server."); | ||||
| 				return 0; | ||||
| 			} | ||||
| 		} | ||||
| 		if (ret < 1) { | ||||
| 			log_error("Unable to read from event server."); | ||||
| @@ -258,9 +248,9 @@ static int _daemon_read(struct dm_event_fifos *fifos, | ||||
| 		} | ||||
|  | ||||
| 		bytes += ret; | ||||
| 		if (header && (bytes == 2 * sizeof(uint32_t))) { | ||||
| 			msg->cmd = ntohl(header[0]); | ||||
| 			msg->size = ntohl(header[1]); | ||||
| 		if (bytes == 2 * sizeof(uint32_t) && header) { | ||||
| 			msg->cmd = ntohl(*((uint32_t *)buf)); | ||||
| 			msg->size = ntohl(*((uint32_t *)buf + 1)); | ||||
| 			buf = msg->data = dm_malloc(msg->size); | ||||
| 			size = msg->size; | ||||
| 			bytes = 0; | ||||
| @@ -269,9 +259,11 @@ static int _daemon_read(struct dm_event_fifos *fifos, | ||||
| 	} | ||||
|  | ||||
| 	if (bytes != size) { | ||||
| 		dm_free(msg->data); | ||||
| 		if (msg->data) | ||||
| 			dm_free(msg->data); | ||||
| 		msg->data = NULL; | ||||
| 	} | ||||
|  | ||||
| 	return bytes == size; | ||||
| } | ||||
|  | ||||
| @@ -279,39 +271,32 @@ static int _daemon_read(struct dm_event_fifos *fifos, | ||||
| static int _daemon_write(struct dm_event_fifos *fifos, | ||||
| 			 struct dm_event_daemon_message *msg) | ||||
| { | ||||
| 	int ret; | ||||
| 	unsigned bytes = 0; | ||||
| 	int ret = 0; | ||||
| 	fd_set fds; | ||||
| 	size_t bytes = 0; | ||||
| 	size_t size = 2 * sizeof(uint32_t) + msg->size; | ||||
| 	uint32_t *header = alloca(size); | ||||
| 	char *buf = (char *)header; | ||||
| 	char drainbuf[128]; | ||||
|  | ||||
| 	header[0] = htonl(msg->cmd); | ||||
| 	header[1] = htonl(msg->size); | ||||
| 	size_t size = 2 * sizeof(uint32_t) + msg->size; | ||||
| 	char *buf = alloca(size); | ||||
| 	char drainbuf[128]; | ||||
| 	struct timeval tval = { 0, 0 }; | ||||
|  | ||||
| 	*((uint32_t *)buf) = htonl(msg->cmd); | ||||
| 	*((uint32_t *)buf + 1) = htonl(msg->size); | ||||
| 	memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size); | ||||
|  | ||||
| 	/* drain the answer fifo */ | ||||
| 	while (1) { | ||||
| 		struct timeval tval = { .tv_usec = 100 }; | ||||
| 		FD_ZERO(&fds); | ||||
| 		FD_SET(fifos->server, &fds); | ||||
| 		tval.tv_usec = 100; | ||||
| 		ret = select(fifos->server + 1, &fds, NULL, NULL, &tval); | ||||
| 		if (ret < 0) { | ||||
| 			if (errno == EINTR) | ||||
| 				continue; | ||||
| 		if ((ret < 0) && (errno != EINTR)) { | ||||
| 			log_error("Unable to talk to event daemon"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if (ret == 0) | ||||
| 			break; | ||||
| 		ret = read(fifos->server, drainbuf, sizeof(drainbuf)); | ||||
| 		if (ret < 0) { | ||||
| 			if ((errno == EINTR) || (errno == EAGAIN)) | ||||
| 				continue; | ||||
| 			log_error("Unable to talk to event daemon"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		read(fifos->server, drainbuf, 127); | ||||
| 	} | ||||
|  | ||||
| 	while (bytes < size) { | ||||
| @@ -326,7 +311,8 @@ static int _daemon_write(struct dm_event_fifos *fifos, | ||||
| 			} | ||||
| 		} while (ret < 1); | ||||
|  | ||||
| 		ret = write(fifos->client, buf + bytes, size - bytes); | ||||
| 		ret = write(fifos->client, ((char *) buf) + bytes, | ||||
| 			    size - bytes); | ||||
| 		if (ret < 0) { | ||||
| 			if ((errno == EINTR) || (errno == EAGAIN)) | ||||
| 				continue; | ||||
| @@ -342,11 +328,14 @@ static int _daemon_write(struct dm_event_fifos *fifos, | ||||
| 	return bytes == size; | ||||
| } | ||||
|  | ||||
| int daemon_talk(struct dm_event_fifos *fifos, | ||||
| 		struct dm_event_daemon_message *msg, int cmd, | ||||
| 		const char *dso_name, const char *dev_name, | ||||
| 		enum dm_event_mask evmask, uint32_t timeout) | ||||
| static int _daemon_talk(struct dm_event_fifos *fifos, | ||||
| 			struct dm_event_daemon_message *msg, int cmd, | ||||
| 			const char *dso_name, const char *dev_name, | ||||
| 			enum dm_event_mask evmask, uint32_t timeout) | ||||
| { | ||||
| 	const char *dso = dso_name ? dso_name : ""; | ||||
| 	const char *dev = dev_name ? dev_name : ""; | ||||
| 	const char *fmt = "%d:%d %s %s %u %" PRIu32; | ||||
| 	int msg_size; | ||||
| 	memset(msg, 0, sizeof(*msg)); | ||||
|  | ||||
| @@ -354,17 +343,14 @@ int daemon_talk(struct dm_event_fifos *fifos, | ||||
| 	 * Set command and pack the arguments | ||||
| 	 * into ASCII message string. | ||||
| 	 */ | ||||
| 	if ((msg_size = | ||||
| 	     ((cmd == DM_EVENT_CMD_HELLO) ? | ||||
| 	      dm_asprintf(&(msg->data), "%d:%d HELLO", getpid(), _sequence_nr) : | ||||
| 	      dm_asprintf(&(msg->data), "%d:%d %s %s %u %" PRIu32, | ||||
| 			  getpid(), _sequence_nr, | ||||
| 			  dso_name ? : "-", dev_name ? : "-", evmask, timeout))) | ||||
| 	    < 0) { | ||||
| 	msg->cmd = cmd; | ||||
| 	if (cmd == DM_EVENT_CMD_HELLO) | ||||
| 		fmt = "%d:%d HELLO"; | ||||
| 	if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr, | ||||
| 				    dso, dev, evmask, timeout)) < 0) { | ||||
| 		log_error("_daemon_talk: message allocation failed"); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 	msg->cmd = cmd; | ||||
| 	msg->size = msg_size; | ||||
|  | ||||
| 	/* | ||||
| @@ -374,13 +360,15 @@ int daemon_talk(struct dm_event_fifos *fifos, | ||||
| 	if (!_daemon_write(fifos, msg)) { | ||||
| 		stack; | ||||
| 		dm_free(msg->data); | ||||
| 		msg->data = NULL; | ||||
| 		msg->data = 0; | ||||
| 		return -EIO; | ||||
| 	} | ||||
|  | ||||
| 	do { | ||||
| 		dm_free(msg->data); | ||||
| 		msg->data = NULL; | ||||
|  | ||||
| 		if (msg->data) | ||||
| 			dm_free(msg->data); | ||||
| 		msg->data = 0; | ||||
|  | ||||
| 		if (!_daemon_read(fifos, msg)) { | ||||
| 			stack; | ||||
| @@ -405,13 +393,11 @@ int daemon_talk(struct dm_event_fifos *fifos, | ||||
|  * | ||||
|  * Returns: 1 on success, 0 otherwise | ||||
|  */ | ||||
| static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos) | ||||
| static int _start_daemon(struct dm_event_fifos *fifos) | ||||
| { | ||||
| 	int pid, ret = 0; | ||||
| 	int status; | ||||
| 	struct stat statbuf; | ||||
| 	char default_dmeventd_path[] = DMEVENTD_PATH; | ||||
| 	char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL }; | ||||
|  | ||||
| 	if (stat(fifos->client_path, &statbuf)) | ||||
| 		goto start_server; | ||||
| @@ -425,32 +411,28 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos) | ||||
| 	fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK); | ||||
| 	if (fifos->client >= 0) { | ||||
| 		/* server is running and listening */ | ||||
| 		if (close(fifos->client)) | ||||
| 			log_sys_debug("close", fifos->client_path); | ||||
|  | ||||
| 		close(fifos->client); | ||||
| 		return 1; | ||||
| 	} else if (errno != ENXIO) { | ||||
| 		/* problem */ | ||||
| 		log_sys_error("open", fifos->client_path); | ||||
|  | ||||
| 		log_error("%s: Can't open client fifo %s: %s", | ||||
| 			  __func__, fifos->client_path, strerror(errno)); | ||||
| 		stack; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
|       start_server: | ||||
| 	/* server is not running */ | ||||
|  | ||||
| 	if ((args[0][0] == '/') && stat(args[0], &statbuf)) { | ||||
| 		log_sys_error("stat", args[0]); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	pid = fork(); | ||||
|  | ||||
| 	if (pid < 0) | ||||
| 		log_sys_error("fork", ""); | ||||
| 		log_error("Unable to fork."); | ||||
|  | ||||
| 	else if (!pid) { | ||||
| 		execvp(args[0], args); | ||||
| 		log_error("Unable to exec dmeventd: %s", strerror(errno)); | ||||
| 		_exit(EXIT_FAILURE); | ||||
| 		execvp(DMEVENTD_PATH, NULL); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} else { | ||||
| 		if (waitpid(pid, &status, 0) < 0) | ||||
| 			log_error("Unable to start dmeventd: %s", | ||||
| @@ -464,59 +446,56 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos) | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int init_fifos(struct dm_event_fifos *fifos) | ||||
| /* Initialize client. */ | ||||
| static int _init_client(struct dm_event_fifos *fifos) | ||||
| { | ||||
| 	/* FIXME? Is fifo the most suitable method? Why not share | ||||
| 	   comms/daemon code with something else e.g. multipath? */ | ||||
|  | ||||
| 	/* init fifos */ | ||||
| 	memset(fifos, 0, sizeof(*fifos)); | ||||
| 	fifos->client_path = DM_EVENT_FIFO_CLIENT; | ||||
| 	fifos->server_path = DM_EVENT_FIFO_SERVER; | ||||
|  | ||||
| 	if (!_start_daemon(fifos)) { | ||||
| 		stack; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Open the fifo used to read from the daemon. */ | ||||
| 	if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) { | ||||
| 		log_sys_error("open", fifos->server_path); | ||||
| 		log_error("%s: open server fifo %s", | ||||
| 			  __func__, fifos->server_path); | ||||
| 		stack; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Lock out anyone else trying to do communication with the daemon. */ | ||||
| 	if (flock(fifos->server, LOCK_EX) < 0) { | ||||
| 		log_sys_error("flock", fifos->server_path); | ||||
| 		goto bad; | ||||
| 		log_error("%s: flock %s", __func__, fifos->server_path); | ||||
| 		close(fifos->server); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| /*	if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/ | ||||
| 	if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) { | ||||
| 		log_sys_error("open", fifos->client_path); | ||||
| 		goto bad; | ||||
| 		log_error("%s: Can't open client fifo %s: %s", | ||||
| 			  __func__, fifos->client_path, strerror(errno)); | ||||
| 		close(fifos->server); | ||||
| 		stack; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	return 1; | ||||
| bad: | ||||
| 	if (close(fifos->server)) | ||||
| 		log_sys_debug("close", fifos->server_path); | ||||
| 	fifos->server = -1; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* Initialize client. */ | ||||
| static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos) | ||||
| static void _dtr_client(struct dm_event_fifos *fifos) | ||||
| { | ||||
| 	if (!_start_daemon(dmeventd_path, fifos)) | ||||
| 		return_0; | ||||
| 	if (flock(fifos->server, LOCK_UN)) | ||||
| 		log_error("flock unlock %s", fifos->server_path); | ||||
|  | ||||
| 	return init_fifos(fifos); | ||||
| } | ||||
|  | ||||
| void fini_fifos(struct dm_event_fifos *fifos) | ||||
| { | ||||
| 	if (fifos->client >= 0 && close(fifos->client)) | ||||
| 		log_sys_debug("close", fifos->client_path); | ||||
|  | ||||
| 	if (fifos->server >= 0) { | ||||
| 		if (flock(fifos->server, LOCK_UN)) | ||||
| 			log_sys_debug("flock unlock", fifos->server_path); | ||||
|  | ||||
| 		if (close(fifos->server)) | ||||
| 			log_sys_debug("close", fifos->server_path); | ||||
| 	} | ||||
| 	close(fifos->client); | ||||
| 	close(fifos->server); | ||||
| } | ||||
|  | ||||
| /* Get uuid of a device */ | ||||
| @@ -530,78 +509,62 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh) | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (dmevh->uuid) { | ||||
| 		if (!dm_task_set_uuid(dmt, dmevh->uuid)) | ||||
| 			goto_bad; | ||||
| 	} else if (dmevh->dev_name) { | ||||
| 		if (!dm_task_set_name(dmt, dmevh->dev_name)) | ||||
| 			goto_bad; | ||||
| 	} else if (dmevh->major && dmevh->minor) { | ||||
| 		if (!dm_task_set_major(dmt, dmevh->major) || | ||||
| 		    !dm_task_set_minor(dmt, dmevh->minor)) | ||||
| 			goto_bad; | ||||
| 	} | ||||
| 	if (dmevh->uuid) | ||||
| 		dm_task_set_uuid(dmt, dmevh->uuid); | ||||
| 	else if (dmevh->dev_name) | ||||
| 		dm_task_set_name(dmt, dmevh->dev_name); | ||||
| 	else if (dmevh->major && dmevh->minor) { | ||||
| 		dm_task_set_major(dmt, dmevh->major); | ||||
| 		dm_task_set_minor(dmt, dmevh->minor); | ||||
|         } | ||||
|  | ||||
| 	/* FIXME Add name or uuid or devno to messages */ | ||||
| 	if (!dm_task_run(dmt)) { | ||||
| 		log_error("_get_device_info: dm_task_run() failed"); | ||||
| 		goto bad; | ||||
| 		goto failed; | ||||
| 	} | ||||
|  | ||||
| 	if (!dm_task_get_info(dmt, &info)) { | ||||
| 		log_error("_get_device_info: failed to get info for device"); | ||||
| 		goto bad; | ||||
| 		goto failed; | ||||
| 	} | ||||
|  | ||||
| 	if (!info.exists) { | ||||
| 		log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found", | ||||
| 			  dmevh->uuid ? : "", | ||||
| 			  (!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "", | ||||
| 			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? "(" : "", | ||||
| 			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? dmevh->major : 0, | ||||
| 			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ":" : "", | ||||
| 			  (!dmevh->uuid && !dmevh->dev_name && dmevh->minor > 0) ? dmevh->minor : 0, | ||||
| 			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) && dmevh->minor == 0 ? "0" : "", | ||||
| 			  (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ") " : ""); | ||||
| 		goto bad; | ||||
| 		log_error("_get_device_info: device not found"); | ||||
| 		goto failed; | ||||
| 	} | ||||
|  | ||||
| 	return dmt; | ||||
|  | ||||
|       bad: | ||||
| failed: | ||||
| 	dm_task_destroy(dmt); | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| /* Handle the event (de)registration call and return negative error codes. */ | ||||
| static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_message *msg, | ||||
| static int _do_event(int cmd, struct dm_event_daemon_message *msg, | ||||
| 		     const char *dso_name, const char *dev_name, | ||||
| 		     enum dm_event_mask evmask, uint32_t timeout) | ||||
| { | ||||
| 	int ret; | ||||
| 	struct dm_event_fifos fifos = { | ||||
| 		.server = -1, | ||||
| 		.client = -1, | ||||
| 		/* FIXME Make these either configurable or depend directly on dmeventd_path */ | ||||
| 		.client_path = DM_EVENT_FIFO_CLIENT, | ||||
| 		.server_path = DM_EVENT_FIFO_SERVER | ||||
| 	}; | ||||
| 	struct dm_event_fifos fifos; | ||||
|  | ||||
| 	if (!_init_client(dmeventd_path, &fifos)) { | ||||
| 	if (!_init_client(&fifos)) { | ||||
| 		stack; | ||||
| 		return -ESRCH; | ||||
| 	} | ||||
|  | ||||
| 	ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0); | ||||
| 	ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0); | ||||
|  | ||||
| 	dm_free(msg->data); | ||||
| 	if (msg->data) | ||||
| 		dm_free(msg->data); | ||||
| 	msg->data = 0; | ||||
|  | ||||
| 	if (!ret) | ||||
| 		ret = daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout); | ||||
| 		ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout); | ||||
|  | ||||
| 	/* what is the opposite of init? */ | ||||
| 	fini_fifos(&fifos); | ||||
| 	_dtr_client(&fifos); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
| @@ -612,21 +575,16 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh) | ||||
| 	int ret = 1, err; | ||||
| 	const char *uuid; | ||||
| 	struct dm_task *dmt; | ||||
| 	struct dm_event_daemon_message msg = { 0 }; | ||||
| 	struct dm_event_daemon_message msg = { 0, 0, NULL }; | ||||
|  | ||||
| 	if (!(dmt = _get_device_info(dmevh))) | ||||
| 		return_0; | ||||
| 	if (!(dmt = _get_device_info(dmevh))) { | ||||
| 		stack; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	uuid = dm_task_get_uuid(dmt); | ||||
|  | ||||
| 	if (!strstr(dmevh->dso, "libdevmapper-event-lvm2thin.so") && | ||||
| 	    !strstr(dmevh->dso, "libdevmapper-event-lvm2snapshot.so") && | ||||
| 	    !strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") && | ||||
| 	    !strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so")) | ||||
| 		log_warn("WARNING: %s: dmeventd plugins are deprecated", dmevh->dso); | ||||
|  | ||||
|  | ||||
| 	if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg, | ||||
| 	if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg, | ||||
| 			     dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) { | ||||
| 		log_error("%s: event registration failed: %s", | ||||
| 			  dm_task_get_name(dmt), | ||||
| @@ -634,7 +592,8 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh) | ||||
| 		ret = 0; | ||||
| 	} | ||||
|  | ||||
| 	dm_free(msg.data); | ||||
| 	if (msg.data) | ||||
| 		dm_free(msg.data); | ||||
|  | ||||
| 	dm_task_destroy(dmt); | ||||
|  | ||||
| @@ -646,14 +605,16 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh) | ||||
| 	int ret = 1, err; | ||||
| 	const char *uuid; | ||||
| 	struct dm_task *dmt; | ||||
| 	struct dm_event_daemon_message msg = { 0 }; | ||||
| 	struct dm_event_daemon_message msg = { 0, 0, NULL }; | ||||
|  | ||||
| 	if (!(dmt = _get_device_info(dmevh))) | ||||
| 		return_0; | ||||
| 	if (!(dmt = _get_device_info(dmevh))) { | ||||
| 		stack; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	uuid = dm_task_get_uuid(dmt); | ||||
|  | ||||
| 	if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg, | ||||
| 	if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg, | ||||
| 			    dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) { | ||||
| 		log_error("%s: event deregistration failed: %s", | ||||
| 			  dm_task_get_name(dmt), | ||||
| @@ -661,7 +622,8 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh) | ||||
| 		ret = 0; | ||||
| 	} | ||||
|  | ||||
| 	dm_free(msg.data); | ||||
| 	if (msg.data) | ||||
| 		dm_free(msg.data); | ||||
|  | ||||
| 	dm_task_destroy(dmt); | ||||
|  | ||||
| @@ -690,23 +652,31 @@ static char *_fetch_string(char **src, const int delimiter) | ||||
| static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name, | ||||
| 			 char **uuid, enum dm_event_mask *evmask) | ||||
| { | ||||
| 	char *id; | ||||
| 	char *id = NULL; | ||||
| 	char *p = msg->data; | ||||
|  | ||||
| 	if ((id = _fetch_string(&p, ' ')) && | ||||
| 	    (*dso_name = _fetch_string(&p, ' ')) && | ||||
| 	    (*uuid = _fetch_string(&p, ' '))) { | ||||
| 		*evmask = atoi(p); | ||||
|  | ||||
| 		dm_free(id); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	dm_free(id); | ||||
| 	if (id) | ||||
| 		dm_free(id); | ||||
| 	return -ENOMEM; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise. | ||||
|  * dm_event_get_registered_device | ||||
|  * @dso_name | ||||
|  * @device_path | ||||
|  * @mask | ||||
|  * @next | ||||
|  * | ||||
|  * Returns: 0 if handler found, error (-ENOMEM, -ENOENT) otherwise | ||||
|  */ | ||||
| int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next) | ||||
| { | ||||
| @@ -715,44 +685,36 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next) | ||||
| 	char *reply_dso = NULL, *reply_uuid = NULL; | ||||
| 	enum dm_event_mask reply_mask = 0; | ||||
| 	struct dm_task *dmt = NULL; | ||||
| 	struct dm_event_daemon_message msg = { 0 }; | ||||
| 	struct dm_info info; | ||||
| 	struct dm_event_daemon_message msg = { 0, 0, NULL }; | ||||
|  | ||||
| 	if (!(dmt = _get_device_info(dmevh))) { | ||||
| 		log_debug("Device does not exists (uuid=%s, name=%s, %d:%d).", | ||||
| 			  dmevh->uuid, dmevh->dev_name, | ||||
| 			  dmevh->major, dmevh->minor); | ||||
| 		ret = -ENODEV; | ||||
| 		goto fail; | ||||
| 		stack; | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	uuid = dm_task_get_uuid(dmt); | ||||
|  | ||||
| 	if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE : | ||||
| 		      DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path, | ||||
| 		      &msg, dmevh->dso, uuid, dmevh->mask, 0)) { | ||||
| 		log_debug("%s: device not registered.", dm_task_get_name(dmt)); | ||||
| 	if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE : | ||||
| 			     DM_EVENT_CMD_GET_REGISTERED_DEVICE, | ||||
| 			      &msg, dmevh->dso, uuid, dmevh->mask, 0))) { | ||||
| 		/* FIXME this will probably horribly break if we get | ||||
| 		   ill-formatted reply */ | ||||
| 		ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask); | ||||
| 	} else { | ||||
| 		ret = -ENOENT; | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	/* FIXME this will probably horribly break if we get | ||||
| 	   ill-formatted reply */ | ||||
| 	ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask); | ||||
|  | ||||
| 	dm_task_destroy(dmt); | ||||
| 	dmt = NULL; | ||||
|  | ||||
| 	dm_free(msg.data); | ||||
| 	msg.data = NULL; | ||||
|  | ||||
| 	_dm_event_handler_clear_dev_info(dmevh); | ||||
| 	if (!reply_uuid) { | ||||
| 		ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */ | ||||
| 		goto fail; | ||||
| 	if (msg.data) { | ||||
| 		dm_free(msg.data); | ||||
| 		msg.data = NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (!(dmevh->uuid = dm_strdup(reply_uuid))) { | ||||
| 	_dm_event_handler_clear_dev_info(dmevh); | ||||
| 	dmevh->uuid = dm_strdup(reply_uuid); | ||||
| 	if (!dmevh->uuid) { | ||||
| 		ret = -ENOMEM; | ||||
| 		goto fail; | ||||
| 	} | ||||
| @@ -765,17 +727,18 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next) | ||||
| 	dm_event_handler_set_dso(dmevh, reply_dso); | ||||
| 	dm_event_handler_set_event_mask(dmevh, reply_mask); | ||||
|  | ||||
| 	dm_free(reply_dso); | ||||
| 	reply_dso = NULL; | ||||
| 	if (reply_dso) | ||||
| 		dm_free(reply_dso); | ||||
| 	if (reply_uuid) | ||||
| 		dm_free(reply_uuid); | ||||
|  | ||||
| 	dm_free(reply_uuid); | ||||
| 	reply_uuid = NULL; | ||||
|  | ||||
| 	if (!(dmevh->dev_name = dm_strdup(dm_task_get_name(dmt)))) { | ||||
| 	dmevh->dev_name = dm_strdup(dm_task_get_name(dmt)); | ||||
| 	if (!dmevh->dev_name) { | ||||
| 		ret = -ENOMEM; | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	struct dm_info info; | ||||
| 	if (!dm_task_get_info(dmt, &info)) { | ||||
| 		ret = -1; | ||||
| 		goto fail; | ||||
| @@ -789,45 +752,17 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next) | ||||
| 	return ret; | ||||
|  | ||||
|  fail: | ||||
| 	dm_free(msg.data); | ||||
| 	dm_free(reply_dso); | ||||
| 	dm_free(reply_uuid); | ||||
| 	if (msg.data) | ||||
| 		dm_free(msg.data); | ||||
| 	if (reply_dso) | ||||
| 		dm_free(reply_dso); | ||||
| 	if (reply_uuid) | ||||
| 		dm_free(reply_uuid); | ||||
| 	_dm_event_handler_clear_dev_info(dmevh); | ||||
| 	if (dmt) | ||||
| 		dm_task_destroy(dmt); | ||||
| 	dm_task_destroy(dmt); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * You can (and have to) call this at the stage of the protocol where | ||||
|  *     daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0) | ||||
|  * | ||||
|  * would be normally sent. This call will parse the version reply from | ||||
|  * dmeventd, in addition to above call. It is not safe to call this at any | ||||
|  * other place in the protocol. | ||||
|  * | ||||
|  * This is an internal function, not exposed in the public API. | ||||
|  */ | ||||
|  | ||||
| int dm_event_get_version(struct dm_event_fifos *fifos, int *version) { | ||||
| 	char *p; | ||||
| 	struct dm_event_daemon_message msg = { 0 }; | ||||
|  | ||||
| 	if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0)) | ||||
| 		return 0; | ||||
| 	p = msg.data; | ||||
| 	*version = 0; | ||||
|  | ||||
| 	if (!p || !(p = strchr(p, ' '))) /* Message ID */ | ||||
| 		return 0; | ||||
| 	if (!(p = strchr(p + 1, ' '))) /* HELLO */ | ||||
| 		return 0; | ||||
| 	if ((p = strchr(p + 1, ' '))) /* HELLO, once more */ | ||||
| 		*version = atoi(p); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| #if 0				/* left out for now */ | ||||
|  | ||||
| static char *_skip_string(char *src, const int delimiter) | ||||
| @@ -840,7 +775,7 @@ static char *_skip_string(char *src, const int delimiter) | ||||
|  | ||||
| int dm_event_set_timeout(const char *device_path, uint32_t timeout) | ||||
| { | ||||
| 	struct dm_event_daemon_message msg = { 0 }; | ||||
| 	struct dm_event_daemon_message msg = { 0, 0, NULL }; | ||||
|  | ||||
| 	if (!device_exists(device_path)) | ||||
| 		return -ENODEV; | ||||
| @@ -852,24 +787,22 @@ int dm_event_set_timeout(const char *device_path, uint32_t timeout) | ||||
| int dm_event_get_timeout(const char *device_path, uint32_t *timeout) | ||||
| { | ||||
| 	int ret; | ||||
| 	struct dm_event_daemon_message msg = { 0 }; | ||||
| 	struct dm_event_daemon_message msg = { 0, 0, NULL }; | ||||
|  | ||||
| 	if (!device_exists(device_path)) | ||||
| 		return -ENODEV; | ||||
|  | ||||
| 	if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path, | ||||
| 			     0, 0))) { | ||||
| 		char *p = _skip_string(msg.data, ' '); | ||||
| 		if (!p) { | ||||
| 			log_error("malformed reply from dmeventd '%s'\n", | ||||
| 				  msg.data); | ||||
| 			dm_free(msg.data); | ||||
| 			return -EIO; | ||||
| 		} | ||||
| 		*timeout = atoi(p); | ||||
| 	} | ||||
| 	dm_free(msg.data); | ||||
|  | ||||
| 	if (msg.data) | ||||
| 		dm_free(msg.data); | ||||
| 	return ret; | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright (C) 2005-2007 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. | ||||
|  * | ||||
| @@ -46,9 +46,7 @@ enum dm_event_mask { | ||||
| }; | ||||
|  | ||||
| #define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK | ||||
| #define DM_EVENT_PROTOCOL_VERSION 2 | ||||
|  | ||||
| struct dm_task; | ||||
| struct dm_event_handler; | ||||
|  | ||||
| struct dm_event_handler *dm_event_handler_create(void); | ||||
| @@ -57,17 +55,12 @@ void dm_event_handler_destroy(struct dm_event_handler *dmevh); | ||||
| /* | ||||
|  * Path of shared library to handle events. | ||||
|  * | ||||
|  * All of dmeventd, dso, device_name and uuid strings are duplicated so | ||||
|  * you do not need to keep the pointers valid after the call succeeds. | ||||
|  * They may return -ENOMEM though. | ||||
|  * All of dso, device_name and uuid strings are duplicated, you do not | ||||
|  * need to keep the pointers valid after the call succeeds. Thes may | ||||
|  * return -ENOMEM though. | ||||
|  */ | ||||
| int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path); | ||||
|  | ||||
| /* | ||||
|  * Path of dmeventd binary. | ||||
|  */ | ||||
| int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path); | ||||
|  | ||||
| /* | ||||
|  * Identify the device to monitor by exactly one of device_name, uuid or | ||||
|  * device number. String arguments are duplicated, see above. | ||||
| @@ -83,7 +76,6 @@ void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout); | ||||
| /* | ||||
|  * Specify mask for events to monitor. | ||||
|  */ | ||||
| // FIXME  misuse of bitmask as enum | ||||
| void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh, | ||||
| 				     enum dm_event_mask evmask); | ||||
|  | ||||
| @@ -93,7 +85,6 @@ 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?) */ | ||||
| @@ -107,7 +98,6 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh); | ||||
|  | ||||
| /* Prototypes for DSO interface, see dmeventd.c, struct dso_data for | ||||
|    detailed descriptions. */ | ||||
| // FIXME  misuse of bitmask as enum | ||||
| void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user); | ||||
| int register_device(const char *device_name, const char *uuid, int major, int minor, void **user); | ||||
| int unregister_device(const char *device_name, const char *uuid, int major, | ||||
|   | ||||
| @@ -5,7 +5,8 @@ includedir=@includedir@ | ||||
|  | ||||
| Name: devmapper-event | ||||
| Description: device-mapper event library | ||||
| Version: @DM_LIB_PATCHLEVEL@ | ||||
| Version: @DM_LIB_VERSION@ | ||||
| Requires: devmapper | ||||
| Cflags: -I${includedir} | ||||
| 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) 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, | ||||
| # modify, copy, or redistribute it subject to the terms and conditions | ||||
| @@ -14,33 +14,9 @@ | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| VPATH = @srcdir@ | ||||
|  | ||||
| SUBDIRS += lvm2 | ||||
| SUBDIRS += mirror | ||||
|  | ||||
| ifneq ("@MIRRORS@", "none") | ||||
|   SUBDIRS += mirror | ||||
| endif | ||||
| include $(top_srcdir)/make.tmpl | ||||
|  | ||||
| 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
|  | ||||
| CLDFLAGS += -L$(top_builddir)/tools | ||||
|  | ||||
| SOURCES = dmeventd_lvm.c | ||||
|  | ||||
| LIB_SHARED = libdevmapper-event-lvm2.$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS) | ||||
|  | ||||
| install_lvm2: install_lib_shared | ||||
|  | ||||
| install: install_lvm2 | ||||
| @@ -1,176 +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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "lib.h" | ||||
| #include "log.h" | ||||
|  | ||||
| #include "lvm2cmd.h" | ||||
| #include "dmeventd_lvm.h" | ||||
|  | ||||
| #include <pthread.h> | ||||
| #include <syslog.h> | ||||
|  | ||||
| extern int dmeventd_debug; | ||||
|  | ||||
| /* | ||||
|  * register_device() is called first and performs initialisation. | ||||
|  * Only one device may be registered or unregistered at a time. | ||||
|  */ | ||||
| static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
|  | ||||
| /* | ||||
|  * Number of active registrations. | ||||
|  */ | ||||
| static int _register_count = 0; | ||||
| static struct dm_pool *_mem_pool = NULL; | ||||
| static void *_lvm_handle = NULL; | ||||
|  | ||||
| /* | ||||
|  * Currently only one event can be processed at a time. | ||||
|  */ | ||||
| static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
|  | ||||
| /* | ||||
|  * FIXME Do not pass things directly to syslog, rather use the existing logging | ||||
|  * facilities to sort logging ... however that mechanism needs to be somehow | ||||
|  * configurable and we don't have that option yet | ||||
|  */ | ||||
| static void _temporary_log_fn(int level, | ||||
| 			      const char *file __attribute__((unused)), | ||||
| 			      int line __attribute__((unused)), | ||||
| 			      int dm_errno __attribute__((unused)), | ||||
| 			      const char *message) | ||||
| { | ||||
| 	level &= ~(_LOG_STDERR | _LOG_ONCE); | ||||
|  | ||||
| 	switch (level) { | ||||
| 	case _LOG_DEBUG: | ||||
| 		if (dmeventd_debug >= 3) | ||||
| 			syslog(LOG_DEBUG, "%s", message); | ||||
| 		break; | ||||
| 	case _LOG_INFO: | ||||
| 		if (dmeventd_debug >= 2) | ||||
| 			syslog(LOG_INFO, "%s", message); | ||||
| 		break; | ||||
| 	case _LOG_NOTICE: | ||||
| 		if (dmeventd_debug >= 1) | ||||
| 			syslog(LOG_NOTICE, "%s", message); | ||||
| 		break; | ||||
| 	case _LOG_WARN: | ||||
| 		syslog(LOG_WARNING, "%s", message); | ||||
| 		break; | ||||
| 	case _LOG_ERR: | ||||
| 		syslog(LOG_ERR, "%s", message); | ||||
| 		break; | ||||
| 	default: | ||||
| 		syslog(LOG_CRIT, "%s", message); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void dmeventd_lvm2_lock(void) | ||||
| { | ||||
| 	pthread_mutex_lock(&_event_mutex); | ||||
| } | ||||
|  | ||||
| void dmeventd_lvm2_unlock(void) | ||||
| { | ||||
| 	pthread_mutex_unlock(&_event_mutex); | ||||
| } | ||||
|  | ||||
| int dmeventd_lvm2_init(void) | ||||
| { | ||||
| 	int r = 0; | ||||
|  | ||||
| 	pthread_mutex_lock(&_register_mutex); | ||||
|  | ||||
| 	/* | ||||
| 	 * Need some space for allocations.  1024 should be more | ||||
| 	 * than enough for what we need (device mapper name splitting) | ||||
| 	 */ | ||||
| 	if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024))) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!_lvm_handle) { | ||||
| 		lvm2_log_fn(_temporary_log_fn); | ||||
| 		if (!(_lvm_handle = lvm2_init())) { | ||||
| 			dm_pool_destroy(_mem_pool); | ||||
| 			_mem_pool = NULL; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		lvm2_disable_dmeventd_monitoring(_lvm_handle); | ||||
| 		/* FIXME Temporary: move to dmeventd core */ | ||||
| 		lvm2_run(_lvm_handle, "_memlock_inc"); | ||||
| 	} | ||||
|  | ||||
| 	_register_count++; | ||||
| 	r = 1; | ||||
|  | ||||
| out: | ||||
| 	pthread_mutex_unlock(&_register_mutex); | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| void dmeventd_lvm2_exit(void) | ||||
| { | ||||
| 	pthread_mutex_lock(&_register_mutex); | ||||
|  | ||||
| 	if (!--_register_count) { | ||||
| 		lvm2_run(_lvm_handle, "_memlock_dec"); | ||||
| 		dm_pool_destroy(_mem_pool); | ||||
| 		_mem_pool = NULL; | ||||
| 		lvm2_exit(_lvm_handle); | ||||
| 		_lvm_handle = NULL; | ||||
| 	} | ||||
|  | ||||
| 	pthread_mutex_unlock(&_register_mutex); | ||||
| } | ||||
|  | ||||
| struct dm_pool *dmeventd_lvm2_pool(void) | ||||
| { | ||||
| 	return _mem_pool; | ||||
| } | ||||
|  | ||||
| int dmeventd_lvm2_run(const char *cmdline) | ||||
| { | ||||
| 	return (lvm2_run(_lvm_handle, cmdline) == LVM2_COMMAND_SUCCEEDED); | ||||
| } | ||||
|  | ||||
| int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size, | ||||
| 			  const char *cmd, const char *device) | ||||
| { | ||||
| 	char *vg = NULL, *lv = NULL, *layer; | ||||
| 	int r; | ||||
|  | ||||
| 	if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) { | ||||
| 		syslog(LOG_ERR, "Unable to determine VG name from %s.\n", | ||||
| 		       device); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* strip off the mirror component designations */ | ||||
| 	if ((layer = strstr(lv, "_mimagetmp")) || | ||||
| 	    (layer = strstr(lv, "_mlog"))) | ||||
| 		*layer = '\0'; | ||||
|  | ||||
| 	r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv); | ||||
|  | ||||
| 	dm_pool_free(mem, vg); | ||||
|  | ||||
| 	if (r < 0) { | ||||
| 		syslog(LOG_ERR, "Unable to form LVM command. (too long).\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| @@ -1,42 +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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Wrappers around liblvm2cmd functions for dmeventd plug-ins. | ||||
|  * | ||||
|  * liblvm2cmd is not thread-safe so the locking in this library helps dmeventd | ||||
|  * threads to co-operate in sharing a single instance. | ||||
|  * | ||||
|  * FIXME Either support this properly as a generic liblvm2cmd wrapper or make | ||||
|  * liblvm2cmd thread-safe so this can go away. | ||||
|  */ | ||||
|  | ||||
| #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); | ||||
|  | ||||
| #endif /* _DMEVENTD_LVMWRAP_H */ | ||||
| @@ -1,8 +1,8 @@ | ||||
| # | ||||
| # 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, | ||||
| # modify, copy, or redistribute it subject to the terms and conditions | ||||
| @@ -14,24 +14,23 @@ | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| VPATH = @srcdir@ | ||||
|  | ||||
| INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2 | ||||
| CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2 | ||||
| INCLUDES += -I${top_srcdir}/tools | ||||
| CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd | ||||
|  | ||||
| SOURCES = dmeventd_mirror.c | ||||
|  | ||||
| LIB_NAME = libdevmapper-event-lvm2mirror | ||||
| LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
| ifeq ("@LIB_SUFFIX@","dylib") | ||||
|   LIB_SHARED = libdevmapper-event-lvm2mirror.dylib | ||||
| else | ||||
|   LIB_SHARED = libdevmapper-event-lvm2mirror.so | ||||
| endif | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
| include $(top_srcdir)/make.tmpl | ||||
|  | ||||
| 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-2012 Red Hat, Inc. All rights reserved. | ||||
|  * Copyright (C) 2005 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
| @@ -12,50 +12,43 @@ | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "lib.h" | ||||
| #include "lvm2cmd.h" | ||||
|  | ||||
| #include "libdevmapper-event.h" | ||||
| #include "dmeventd_lvm.h" | ||||
| #include "defaults.h" | ||||
| #include <libdevmapper.h> | ||||
| #include <libdevmapper-event.h> | ||||
| #include <errno.h> | ||||
| #include <signal.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <pthread.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include <syslog.h> /* FIXME Replace syslog with multilog */ | ||||
| /* FIXME Missing openlog? */ | ||||
| /* FIXME Replace most syslogs with log_error() style messages and add complete context. */ | ||||
| /* FIXME Reformat to 80 char lines. */ | ||||
|  | ||||
| #define ME_IGNORE    0 | ||||
| #define ME_INSYNC    1 | ||||
| #define ME_FAILURE   2 | ||||
|  | ||||
| static int _process_status_code(const char status_code, const char *dev_name, | ||||
| 				const char *dev_type, int r) | ||||
| { | ||||
| 	/* | ||||
| 	 *    A => Alive - No failures | ||||
| 	 *    D => Dead - A write failure occurred leaving mirror out-of-sync | ||||
| 	 *    F => Flush failed. | ||||
| 	 *    S => Sync - A sychronization failure occurred, mirror out-of-sync | ||||
| 	 *    R => Read - A read failure occurred, mirror data unaffected | ||||
| 	 *    U => Unclassified failure (bug) | ||||
| 	 */  | ||||
| 	if (status_code == 'F') { | ||||
| 		syslog(LOG_ERR, "%s device %s flush failed.", | ||||
| 		       dev_type, dev_name); | ||||
| 		r = ME_FAILURE; | ||||
| 	} else if (status_code == 'S') | ||||
| 		syslog(LOG_ERR, "%s device %s sync failed.", | ||||
| 		       dev_type, dev_name); | ||||
| 	else if (status_code == 'R') | ||||
| 		syslog(LOG_ERR, "%s device %s read failed.", | ||||
| 		       dev_type, dev_name); | ||||
| 	else if (status_code != 'A') { | ||||
| 		syslog(LOG_ERR, "%s device %s has failed (%c).", | ||||
| 		       dev_type, dev_name, status_code); | ||||
| 		r = ME_FAILURE; | ||||
| 	} | ||||
| /* | ||||
|  * 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; | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
| /* | ||||
|  * Number of active registrations. | ||||
|  */ | ||||
| static int _register_count = 0; | ||||
|  | ||||
| static struct dm_pool *_mem_pool = NULL; | ||||
| static void *_lvm_handle = NULL; | ||||
|  | ||||
| /* | ||||
|  * Currently only one event can be processed at a time. | ||||
|  */ | ||||
| static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
|  | ||||
| static int _get_mirror_event(char *params) | ||||
| { | ||||
| @@ -80,8 +73,7 @@ static int _get_mirror_event(char *params) | ||||
| 	if (!dm_split_words(params, 1, 0, &p)) | ||||
| 		goto out_parse; | ||||
|  | ||||
| 	if (!(num_devs = atoi(p)) || | ||||
| 	    (num_devs > DEFAULT_MIRROR_MAX_IMAGES) || (num_devs < 0)) | ||||
| 	if (!(num_devs = atoi(p))) | ||||
| 		goto out_parse; | ||||
| 	p += strlen(p) + 1; | ||||
|  | ||||
| @@ -90,7 +82,6 @@ static int _get_mirror_event(char *params) | ||||
| 	if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5) | ||||
| 		goto out_parse; | ||||
|  | ||||
| 	/* FIXME: Code differs from lib/mirror/mirrored.c */ | ||||
| 	dev_status_str = args[2 + num_devs]; | ||||
| 	log_argc = atoi(args[3 + num_devs]); | ||||
| 	log_status_str = args[3 + num_devs + log_argc]; | ||||
| @@ -98,14 +89,17 @@ static int _get_mirror_event(char *params) | ||||
|  | ||||
| 	/* Check for bad mirror devices */ | ||||
| 	for (i = 0; i < num_devs; i++) | ||||
| 		r = _process_status_code(dev_status_str[i], args[i], | ||||
| 			i ? "Secondary mirror" : "Primary mirror", r); | ||||
| 		if (dev_status_str[i] == 'D') { | ||||
| 			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]); | ||||
| 			r = ME_FAILURE; | ||||
| 		} | ||||
|  | ||||
| 	/* Check for bad disk log device */ | ||||
| 	if (log_argc > 1) | ||||
| 		r = _process_status_code(log_status_str[0], | ||||
| 					 args[2 + num_devs + log_argc], | ||||
| 					 "Log", r); | ||||
| 	if (log_argc > 1 && log_status_str[0] == 'D') { | ||||
| 		syslog(LOG_ERR, "Log device, %s, has failed.\n", | ||||
| 		       args[2 + num_devs + log_argc]); | ||||
| 		r = ME_FAILURE; | ||||
| 	} | ||||
|  | ||||
| 	if (r == ME_FAILURE) | ||||
| 		goto out; | ||||
| @@ -120,37 +114,58 @@ static int _get_mirror_event(char *params) | ||||
| 		goto out_parse; | ||||
|  | ||||
| out: | ||||
| 	dm_free(args); | ||||
| 	if (args) | ||||
| 		dm_free(args); | ||||
| 	return r; | ||||
|  | ||||
| 	 | ||||
| out_parse: | ||||
| 	dm_free(args); | ||||
| 	if (args) | ||||
| 		dm_free(args); | ||||
| 	syslog(LOG_ERR, "Unable to parse mirror status string."); | ||||
| 	return ME_IGNORE; | ||||
| } | ||||
|  | ||||
| static void _temporary_log_fn(int level, const char *file, | ||||
| 			      int line, const char *format) | ||||
| { | ||||
| 	if (!strncmp(format, "WARNING: ", 9) && (level < 5)) | ||||
| 		syslog(LOG_CRIT, "%s", format); | ||||
| 	else | ||||
| 		syslog(LOG_DEBUG, "%s", format); | ||||
| } | ||||
|  | ||||
| static int _remove_failed_devices(const char *device) | ||||
| { | ||||
| 	int r; | ||||
| #define CMD_SIZE 256	/* FIXME Use system restriction */ | ||||
| 	char cmd_str[CMD_SIZE]; | ||||
| 	char *vg = NULL, *lv = NULL, *layer = NULL; | ||||
|  | ||||
| 	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str), | ||||
| 				  "lvconvert --config devices{ignore_suspended_devices=1} " | ||||
| 				  "--repair --use-policies", device)) | ||||
| 	if (strlen(device) > 200)  /* FIXME Use real restriction */ | ||||
| 		return -ENAMETOOLONG;	/* FIXME These return code distinctions are not used so remove them! */ | ||||
|  | ||||
| 	if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) { | ||||
| 		syslog(LOG_ERR, "Unable to determine VG name from %s", | ||||
| 		       device); | ||||
| 		return -ENOMEM;	/* FIXME Replace with generic error return - reason for failure has already got logged */ | ||||
| 	} | ||||
|  | ||||
| 	/* FIXME Is any sanity-checking required on %s? */ | ||||
| 	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) { | ||||
| 		/* this error should be caught above, but doesn't hurt to check again */ | ||||
| 		syslog(LOG_ERR, "Unable to form LVM command: Device name too long"); | ||||
| 		dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */ | ||||
| 		return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */ | ||||
| 	} | ||||
|  | ||||
| 	r = dmeventd_lvm2_run(cmd_str); | ||||
| 	r = lvm2_run(_lvm_handle, cmd_str); | ||||
|  | ||||
| 	syslog(LOG_INFO, "Repair of mirrored device %s %s.", device, | ||||
| 	       (r) ? "finished successfully" : "failed"); | ||||
|  | ||||
| 	return (r) ? 0 : -1; | ||||
| 	dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */ | ||||
| 	return (r == 1) ? 0 : -1; | ||||
| } | ||||
|  | ||||
| void process_event(struct dm_task *dmt, | ||||
| 		   enum dm_event_mask event __attribute__((unused)), | ||||
| 		   void **unused __attribute__((unused))) | ||||
| void process_event(struct dm_task *dmt, enum dm_event_mask event, | ||||
| 		   void **unused __attribute((unused))) | ||||
| { | ||||
| 	void *next = NULL; | ||||
| 	uint64_t start, length; | ||||
| @@ -158,19 +173,21 @@ void process_event(struct dm_task *dmt, | ||||
| 	char *params; | ||||
| 	const char *device = dm_task_get_name(dmt); | ||||
|  | ||||
| 	dmeventd_lvm2_lock(); | ||||
|  | ||||
| 	if (pthread_mutex_trylock(&_event_mutex)) { | ||||
| 		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting..."); | ||||
| 		pthread_mutex_lock(&_event_mutex); | ||||
| 	} | ||||
| 	do { | ||||
| 		next = dm_get_next_target(dmt, next, &start, &length, | ||||
| 					  &target_type, ¶ms); | ||||
|  | ||||
| 		if (!target_type) { | ||||
| 			syslog(LOG_INFO, "%s mapping lost.", device); | ||||
| 			syslog(LOG_INFO, "%s mapping lost.\n", device); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (strcmp(target_type, "mirror")) { | ||||
| 			syslog(LOG_INFO, "%s has unmirrored portion.", device); | ||||
| 			syslog(LOG_INFO, "%s has unmirrored portion.\n", device); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| @@ -180,13 +197,13 @@ void process_event(struct dm_task *dmt, | ||||
| 			   _part_ of the device is in sync | ||||
| 			   Also, this is not an error | ||||
| 			*/ | ||||
| 			syslog(LOG_NOTICE, "%s is now in-sync.", device); | ||||
| 			syslog(LOG_NOTICE, "%s is now in-sync\n", device); | ||||
| 			break; | ||||
| 		case ME_FAILURE: | ||||
| 			syslog(LOG_ERR, "Device failure in %s.", device); | ||||
| 			syslog(LOG_ERR, "Device failure in %s\n", device); | ||||
| 			if (_remove_failed_devices(device)) | ||||
| 				/* FIXME Why are all the error return codes unused? Get rid of them? */ | ||||
| 				syslog(LOG_ERR, "Failed to remove faulty devices in %s.", | ||||
| 				syslog(LOG_ERR, "Failed to remove faulty devices in %s\n", | ||||
| 				       device); | ||||
| 			/* Should check before warning user that device is now linear | ||||
| 			else | ||||
| @@ -198,36 +215,67 @@ void process_event(struct dm_task *dmt, | ||||
| 			break; | ||||
| 		default: | ||||
| 			/* FIXME Provide value then! */ | ||||
| 			syslog(LOG_INFO, "Unknown event received."); | ||||
| 			syslog(LOG_INFO, "Unknown event received.\n"); | ||||
| 		} | ||||
| 	} while (next); | ||||
|  | ||||
| 	dmeventd_lvm2_unlock(); | ||||
| 	pthread_mutex_unlock(&_event_mutex); | ||||
| } | ||||
|  | ||||
| int register_device(const char *device, | ||||
| 		    const char *uuid __attribute__((unused)), | ||||
| 		    int major __attribute__((unused)), | ||||
| 		    int minor __attribute__((unused)), | ||||
| 		    void **unused __attribute__((unused))) | ||||
| int register_device(const char *device, const char *uuid, int major, int minor, | ||||
| 		   void **unused __attribute((unused))) | ||||
| { | ||||
| 	if (!dmeventd_lvm2_init()) | ||||
| 		return 0; | ||||
| 	int r = 0; | ||||
|  | ||||
| 	syslog(LOG_INFO, "Monitoring mirror device %s for events.", device); | ||||
| 	pthread_mutex_lock(&_register_mutex); | ||||
|  | ||||
| 	return 1; | ||||
| 	syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device); | ||||
|  | ||||
| 	/* | ||||
| 	 * Need some space for allocations.  1024 should be more | ||||
| 	 * than enough for what we need (device mapper name splitting) | ||||
| 	 */ | ||||
| 	if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024))) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!_lvm_handle) { | ||||
| 		lvm2_log_fn(_temporary_log_fn); | ||||
| 		if (!(_lvm_handle = lvm2_init())) { | ||||
| 			dm_pool_destroy(_mem_pool); | ||||
| 			_mem_pool = NULL; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS); | ||||
| 		/* FIXME Temporary: move to dmeventd core */ | ||||
| 		lvm2_run(_lvm_handle, "_memlock_inc"); | ||||
| 	} | ||||
|  | ||||
| 	_register_count++; | ||||
| 	r = 1; | ||||
|  | ||||
| out: | ||||
| 	pthread_mutex_unlock(&_register_mutex); | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| int unregister_device(const char *device, | ||||
| 		      const char *uuid __attribute__((unused)), | ||||
| 		      int major __attribute__((unused)), | ||||
| 		      int minor __attribute__((unused)), | ||||
| 		      void **unused __attribute__((unused))) | ||||
| int unregister_device(const char *device, const char *uuid, int major, int minor, | ||||
| 		   void **unused __attribute((unused))) | ||||
| { | ||||
| 	syslog(LOG_INFO, "No longer monitoring mirror device %s for events.", | ||||
| 	pthread_mutex_lock(&_register_mutex); | ||||
|  | ||||
| 	syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n", | ||||
| 	       device); | ||||
| 	dmeventd_lvm2_exit(); | ||||
|  | ||||
| 	if (!--_register_count) { | ||||
| 		dm_pool_destroy(_mem_pool); | ||||
| 		_mem_pool = NULL; | ||||
| 		lvm2_run(_lvm_handle, "_memlock_dec"); | ||||
| 		lvm2_exit(_lvm_handle); | ||||
| 		_lvm_handle = NULL; | ||||
| 	} | ||||
|  | ||||
| 	pthread_mutex_unlock(&_register_mutex); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|   | ||||
| @@ -1,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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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,180 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
|  * This copyrighted material is made available to anyone wishing to use, | ||||
|  * modify, copy, or redistribute it subject to the terms and conditions | ||||
|  * of the GNU Lesser General Public License v.2.1. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "lib.h" | ||||
|  | ||||
| #include "libdevmapper-event.h" | ||||
| #include "dmeventd_lvm.h" | ||||
|  | ||||
| #include <syslog.h> /* FIXME Replace syslog with multilog */ | ||||
| /* FIXME Missing openlog? */ | ||||
| /* FIXME Replace most syslogs with log_error() style messages and add complete context. */ | ||||
| /* FIXME Reformat to 80 char lines. */ | ||||
|  | ||||
| /* | ||||
|  * run_repair is a close copy to | ||||
|  * plugins/mirror/dmeventd_mirror.c:_remove_failed_devices() | ||||
|  */ | ||||
| static int run_repair(const char *device) | ||||
| { | ||||
| 	int r; | ||||
| #define CMD_SIZE 256	/* FIXME Use system restriction */ | ||||
| 	char cmd_str[CMD_SIZE]; | ||||
|  | ||||
| 	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str), | ||||
| 				  "lvscan --cache", device)) | ||||
| 		return -1; | ||||
|  | ||||
| 	r = dmeventd_lvm2_run(cmd_str); | ||||
|  | ||||
| 	if (!r) | ||||
| 		syslog(LOG_INFO, "Re-scan of RAID device %s failed.", device); | ||||
|  | ||||
| 	if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str), | ||||
| 				  "lvconvert --config devices{ignore_suspended_devices=1} " | ||||
| 				  "--repair --use-policies", device)) | ||||
| 		return -1; | ||||
|  | ||||
| 	/* if repair goes OK, report success even if lvscan has failed */ | ||||
| 	r = dmeventd_lvm2_run(cmd_str); | ||||
|  | ||||
| 	if (!r) | ||||
| 		syslog(LOG_INFO, "Repair of RAID device %s failed.", device); | ||||
|  | ||||
| 	return (r) ? 0 : -1; | ||||
| } | ||||
|  | ||||
| static int _process_raid_event(char *params, const char *device) | ||||
| { | ||||
| 	int i, n, failure = 0; | ||||
| 	char *p, *a[4]; | ||||
| 	char *raid_type; | ||||
| 	char *num_devices; | ||||
| 	char *health_chars; | ||||
| 	char *resync_ratio; | ||||
|  | ||||
| 	/* | ||||
| 	 * RAID parms:     <raid_type> <#raid_disks> \ | ||||
| 	 *                 <health chars> <resync ratio> | ||||
| 	 */ | ||||
| 	if (!dm_split_words(params, 4, 0, a)) { | ||||
| 		syslog(LOG_ERR, "Failed to process status line for %s\n", | ||||
| 		       device); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	raid_type = a[0]; | ||||
| 	num_devices = a[1]; | ||||
| 	health_chars = a[2]; | ||||
| 	resync_ratio = a[3]; | ||||
|  | ||||
| 	if (!(n = atoi(num_devices))) { | ||||
| 		syslog(LOG_ERR, "Failed to parse number of devices for %s: %s", | ||||
| 		       device, num_devices); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < n; i++) { | ||||
| 		switch (health_chars[i]) { | ||||
| 		case 'A': | ||||
| 			/* Device is 'A'live and well */ | ||||
| 		case 'a': | ||||
| 			/* Device is 'a'live, but not yet in-sync */ | ||||
| 			break; | ||||
| 		case 'D': | ||||
| 			syslog(LOG_ERR, | ||||
| 			       "Device #%d of %s array, %s, has failed.", | ||||
| 			       i, raid_type, device); | ||||
| 			failure++; | ||||
| 			break; | ||||
| 		default: | ||||
| 			/* Unhandled character returned from kernel */ | ||||
| 			break; | ||||
| 		} | ||||
| 		if (failure) | ||||
| 			return run_repair(device); | ||||
| 	} | ||||
|  | ||||
| 	p = strstr(resync_ratio, "/"); | ||||
| 	if (!p) { | ||||
| 		syslog(LOG_ERR, "Failed to parse resync_ratio for %s: %s", | ||||
| 		       device, resync_ratio); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	p[0] = '\0'; | ||||
| 	syslog(LOG_INFO, "%s array, %s, is %s in-sync.", | ||||
| 	       raid_type, device, strcmp(resync_ratio, p+1) ? "not" : "now"); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void process_event(struct dm_task *dmt, | ||||
| 		   enum dm_event_mask event __attribute__((unused)), | ||||
| 		   void **unused __attribute__((unused))) | ||||
| { | ||||
| 	void *next = NULL; | ||||
| 	uint64_t start, length; | ||||
| 	char *target_type = NULL; | ||||
| 	char *params; | ||||
| 	const char *device = dm_task_get_name(dmt); | ||||
|  | ||||
| 	dmeventd_lvm2_lock(); | ||||
|  | ||||
| 	do { | ||||
| 		next = dm_get_next_target(dmt, next, &start, &length, | ||||
| 					  &target_type, ¶ms); | ||||
|  | ||||
| 		if (!target_type) { | ||||
| 			syslog(LOG_INFO, "%s mapping lost.", device); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (strcmp(target_type, "raid")) { | ||||
| 			syslog(LOG_INFO, "%s has non-raid portion.", device); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (_process_raid_event(params, device)) | ||||
| 			syslog(LOG_ERR, "Failed to process event for %s", | ||||
| 			       device); | ||||
| 	} while (next); | ||||
|  | ||||
| 	dmeventd_lvm2_unlock(); | ||||
| } | ||||
|  | ||||
| int register_device(const char *device, | ||||
| 		    const char *uuid __attribute__((unused)), | ||||
| 		    int major __attribute__((unused)), | ||||
| 		    int minor __attribute__((unused)), | ||||
| 		    void **unused __attribute__((unused))) | ||||
| { | ||||
| 	if (!dmeventd_lvm2_init()) | ||||
| 		return 0; | ||||
|  | ||||
| 	syslog(LOG_INFO, "Monitoring RAID device %s for events.", device); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| int unregister_device(const char *device, | ||||
| 		      const char *uuid __attribute__((unused)), | ||||
| 		      int major __attribute__((unused)), | ||||
| 		      int minor __attribute__((unused)), | ||||
| 		      void **unused __attribute__((unused))) | ||||
| { | ||||
| 	syslog(LOG_INFO, "No longer monitoring RAID device %s for events.", | ||||
| 	       device); | ||||
| 	dmeventd_lvm2_exit(); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| process_event | ||||
| register_device | ||||
| unregister_device | ||||
| @@ -1,247 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2007-2011 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
|  * This copyrighted material is made available to anyone wishing to use, | ||||
|  * modify, copy, or redistribute it subject to the terms and conditions | ||||
|  * of the GNU Lesser General Public License v.2.1. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "lib.h" | ||||
|  | ||||
| #include "libdevmapper-event.h" | ||||
| #include "dmeventd_lvm.h" | ||||
|  | ||||
| #include <sys/wait.h> | ||||
| #include <syslog.h> /* FIXME Replace syslog with multilog */ | ||||
| #include <stdarg.h> | ||||
| /* FIXME Missing openlog? */ | ||||
|  | ||||
| /* First warning when snapshot is 80% full. */ | ||||
| #define WARNING_THRESH 80 | ||||
| /* Run a check every 5%. */ | ||||
| #define CHECK_STEP 5 | ||||
| /* Do not bother checking snapshots less than 50% full. */ | ||||
| #define CHECK_MINIMUM 50 | ||||
|  | ||||
| #define UMOUNT_COMMAND "/bin/umount" | ||||
|  | ||||
| struct dso_state { | ||||
| 	struct dm_pool *mem; | ||||
| 	int percent_check; | ||||
| 	uint64_t known_size; | ||||
| 	char cmd_str[1024]; | ||||
| }; | ||||
|  | ||||
| static int _run(const char *cmd, ...) | ||||
| { | ||||
|         va_list ap; | ||||
|         int argc = 1; /* for argv[0], i.e. cmd */ | ||||
|         int i = 0; | ||||
|         const char **argv; | ||||
|         pid_t pid = fork(); | ||||
|         int status; | ||||
|  | ||||
|         if (pid == 0) { /* child */ | ||||
|                 va_start(ap, cmd); | ||||
|                 while (va_arg(ap, const char *)) | ||||
|                         ++ argc; | ||||
|                 va_end(ap); | ||||
|  | ||||
|                 /* + 1 for the terminating NULL */ | ||||
|                 argv = alloca(sizeof(const char *) * (argc + 1)); | ||||
|  | ||||
|                 argv[0] = cmd; | ||||
|                 va_start(ap, cmd); | ||||
|                 while ((argv[++i] = va_arg(ap, const char *))); | ||||
|                 va_end(ap); | ||||
|  | ||||
|                 execvp(cmd, (char **)argv); | ||||
|                 syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno)); | ||||
|                 exit(127); | ||||
|         } | ||||
|  | ||||
|         if (pid > 0) { /* parent */ | ||||
|                 if (waitpid(pid, &status, 0) != pid) | ||||
|                         return 0; /* waitpid failed */ | ||||
|                 if (!WIFEXITED(status) || WEXITSTATUS(status)) | ||||
|                         return 0; /* the child failed */ | ||||
|         } | ||||
|  | ||||
|         if (pid < 0) | ||||
|                 return 0; /* fork failed */ | ||||
|  | ||||
|         return 1; /* all good */ | ||||
| } | ||||
|  | ||||
| static int _extend(const char *cmd) | ||||
| { | ||||
| 	return dmeventd_lvm2_run(cmd); | ||||
| } | ||||
|  | ||||
| static void _umount(const char *device, int major, int minor) | ||||
| { | ||||
| 	FILE *mounts; | ||||
| 	char buffer[4096]; | ||||
| 	char *words[3]; | ||||
| 	struct stat st; | ||||
|  | ||||
| 	if (!(mounts = fopen("/proc/mounts", "r"))) { | ||||
| 		syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	while (!feof(mounts)) { | ||||
| 		/* read a line of /proc/mounts */ | ||||
| 		if (!fgets(buffer, sizeof(buffer), mounts)) | ||||
| 			break; /* eof, likely */ | ||||
|  | ||||
| 		/* words[0] is the mount point and words[1] is the device path */ | ||||
| 		if (dm_split_words(buffer, 3, 0, words) < 2) | ||||
| 			continue; | ||||
|  | ||||
| 		/* find the major/minor of the device */ | ||||
| 		if (stat(words[0], &st)) | ||||
| 			continue; /* can't stat, skip this one */ | ||||
|  | ||||
| 		if (S_ISBLK(st.st_mode) && | ||||
| 		    major(st.st_rdev) == major && | ||||
| 		    minor(st.st_rdev) == minor) { | ||||
| 			syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.\n", device, words[1]); | ||||
|                         if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL)) | ||||
|                                 syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.\n", | ||||
|                                        device, words[1], strerror(errno)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (fclose(mounts)) | ||||
| 		syslog(LOG_ERR, "Failed to close /proc/mounts.\n"); | ||||
| } | ||||
|  | ||||
| void process_event(struct dm_task *dmt, | ||||
| 		   enum dm_event_mask event __attribute__((unused)), | ||||
| 		   void **private) | ||||
| { | ||||
| 	void *next = NULL; | ||||
| 	uint64_t start, length; | ||||
| 	char *target_type = NULL; | ||||
| 	char *params; | ||||
| 	struct dm_status_snapshot *status = NULL; | ||||
| 	const char *device = dm_task_get_name(dmt); | ||||
| 	int percent; | ||||
| 	struct dso_state *state = *private; | ||||
|  | ||||
| 	/* No longer monitoring, waiting for remove */ | ||||
| 	if (!state->percent_check) | ||||
| 		return; | ||||
|  | ||||
| 	dmeventd_lvm2_lock(); | ||||
|  | ||||
| 	dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); | ||||
| 	if (!target_type) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!dm_get_status_snapshot(state->mem, params, &status)) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (status->invalid) { | ||||
| 		struct dm_info info; | ||||
| 		if (dm_task_get_info(dmt, &info)) { | ||||
| 			dmeventd_lvm2_unlock(); | ||||
| 			_umount(device, info.major, info.minor); | ||||
| 			return; | ||||
| 		} /* else; too bad, but this is best-effort thing... */ | ||||
| 	} | ||||
|  | ||||
| 	/* Snapshot size had changed. Clear the threshold. */ | ||||
| 	if (state->known_size != status->total_sectors) { | ||||
| 		state->percent_check = CHECK_MINIMUM; | ||||
| 		state->known_size = status->total_sectors; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * 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->total_sectors) { | ||||
| 		syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params); | ||||
| 		state->percent_check = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	percent = (int) (100 * 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. */ | ||||
| 			syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent); | ||||
| 		/* Try to extend the snapshot, in accord with user-set policies */ | ||||
| 		if (!_extend(state->cmd_str)) | ||||
| 			syslog(LOG_ERR, "Failed to extend snapshot %s.\n", device); | ||||
| 	} | ||||
|  | ||||
| out: | ||||
| 	if (status) | ||||
| 		dm_pool_free(state->mem, status); | ||||
| 	dmeventd_lvm2_unlock(); | ||||
| } | ||||
|  | ||||
| int register_device(const char *device, | ||||
| 		    const char *uuid __attribute__((unused)), | ||||
| 		    int major __attribute__((unused)), | ||||
| 		    int minor __attribute__((unused)), | ||||
| 		    void **private) | ||||
| { | ||||
| 	struct dm_pool *statemem = NULL; | ||||
| 	struct dso_state *state; | ||||
|  | ||||
| 	if (!dmeventd_lvm2_init()) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!(statemem = dm_pool_create("snapshot_state", 512)) || | ||||
| 	    !(state = dm_pool_zalloc(statemem, sizeof(*state)))) | ||||
| 		goto bad; | ||||
|  | ||||
| 	if (!dmeventd_lvm2_command(statemem, state->cmd_str, | ||||
| 				   sizeof(state->cmd_str), | ||||
| 				   "lvextend --use-policies", device)) | ||||
| 		goto bad; | ||||
|  | ||||
| 	state->mem = statemem; | ||||
| 	state->percent_check = CHECK_MINIMUM; | ||||
| 	*private = state; | ||||
|  | ||||
| 	syslog(LOG_INFO, "Monitoring snapshot %s\n", device); | ||||
|  | ||||
| 	return 1; | ||||
| bad: | ||||
| 	if (statemem) | ||||
| 		dm_pool_destroy(statemem); | ||||
| 	dmeventd_lvm2_exit(); | ||||
| out: | ||||
| 	syslog(LOG_ERR, "Failed to monitor snapshot %s.\n", device); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int unregister_device(const char *device, | ||||
| 		      const char *uuid __attribute__((unused)), | ||||
| 		      int major __attribute__((unused)), | ||||
| 		      int minor __attribute__((unused)), | ||||
| 		      void **private) | ||||
| { | ||||
| 	struct dso_state *state = *private; | ||||
|  | ||||
| 	syslog(LOG_INFO, "No longer monitoring snapshot %s\n", device); | ||||
| 	dm_pool_destroy(state->mem); | ||||
| 	dmeventd_lvm2_exit(); | ||||
|  | ||||
| 	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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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,401 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2011-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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "lib.h" | ||||
|  | ||||
| #include "libdevmapper-event.h" | ||||
| #include "dmeventd_lvm.h" | ||||
|  | ||||
| #include <sys/wait.h> | ||||
| #include <syslog.h> /* FIXME Replace syslog with multilog */ | ||||
| #include <stdarg.h> | ||||
| /* FIXME Missing openlog? */ | ||||
|  | ||||
| /* First warning when thin is 80% full. */ | ||||
| #define WARNING_THRESH 80 | ||||
| /* Run a check every 5%. */ | ||||
| #define CHECK_STEP 5 | ||||
| /* Do not bother checking thins less than 50% full. */ | ||||
| #define CHECK_MINIMUM 50 | ||||
|  | ||||
| #define UMOUNT_COMMAND "/bin/umount" | ||||
|  | ||||
| #define THIN_DEBUG 0 | ||||
|  | ||||
| struct dso_state { | ||||
| 	struct dm_pool *mem; | ||||
| 	int metadata_percent_check; | ||||
| 	int data_percent_check; | ||||
| 	uint64_t known_metadata_size; | ||||
| 	uint64_t known_data_size; | ||||
| 	char cmd_str[1024]; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* 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)) | ||||
| #  define MKDEV(x,y) makedev((x),(y)) | ||||
| #endif | ||||
|  | ||||
| /* Get dependencies for device, and try to find matching device */ | ||||
| static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor) | ||||
| { | ||||
| 	struct dm_task *dmt; | ||||
| 	const struct dm_deps *deps; | ||||
| 	struct dm_info info; | ||||
| 	int major, minor; | ||||
| 	int r = 0; | ||||
|  | ||||
| 	if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (!dm_task_set_name(dmt, name)) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!dm_task_no_open_count(dmt)) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!dm_task_run(dmt)) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!dm_task_get_info(dmt, &info)) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!(deps = dm_task_get_deps(dmt))) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!info.exists || deps->count != 1) | ||||
| 		goto out; | ||||
|  | ||||
| 	major = (int) MAJOR(deps->device[0]); | ||||
| 	minor = (int) MINOR(deps->device[0]); | ||||
| 	if ((major != tp_major) || (minor != tp_minor)) | ||||
| 		goto out; | ||||
|  | ||||
| 	*dev_minor = info.minor; | ||||
|  | ||||
| #if THIN_DEBUG | ||||
| 	{ | ||||
| 		char dev_name[PATH_MAX]; | ||||
| 		if (dm_device_get_name(major, minor, 0, dev_name, sizeof(dev_name))) | ||||
| 			syslog(LOG_DEBUG, "Found %s (%u:%u) depends on %s", | ||||
| 			       name, major, *dev_minor, dev_name); | ||||
| 	} | ||||
| #endif | ||||
| 	r = 1; | ||||
| out: | ||||
| 	dm_task_destroy(dmt); | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| /* Get all active devices */ | ||||
| static int _find_all_devs(dm_bitset_t bs, int tp_major, int tp_minor) | ||||
| { | ||||
| 	struct dm_task *dmt; | ||||
| 	struct dm_names *names; | ||||
| 	unsigned next = 0; | ||||
| 	int minor, r = 1; | ||||
|  | ||||
| 	if (!(dmt = dm_task_create(DM_DEVICE_LIST))) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (!dm_task_run(dmt)) { | ||||
| 		r = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (!(names = dm_task_get_names(dmt))) { | ||||
| 		r = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (!names->dev) | ||||
| 		goto out; | ||||
|  | ||||
| 	do { | ||||
| 		names = (struct dm_names *)((char *) names + next); | ||||
| 		if (_has_deps(names->name, tp_major, tp_minor, &minor)) | ||||
| 			dm_bit_set(bs, minor); | ||||
| 		next = names->next; | ||||
| 	} while (next); | ||||
|  | ||||
| out: | ||||
| 	dm_task_destroy(dmt); | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| static int _extend(struct dso_state *state) | ||||
| { | ||||
| #if THIN_DEBUG | ||||
| 	syslog(LOG_INFO, "dmeventd executes: %s.\n", state->cmd_str); | ||||
| #endif | ||||
| 	return dmeventd_lvm2_run(state->cmd_str); | ||||
| } | ||||
|  | ||||
| static int _run(const char *cmd, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	int argc = 1; /* for argv[0], i.e. cmd */ | ||||
| 	int i = 0; | ||||
| 	const char **argv; | ||||
| 	pid_t pid = fork(); | ||||
| 	int status; | ||||
|  | ||||
| 	if (pid == 0) { /* child */ | ||||
| 		va_start(ap, cmd); | ||||
| 		while (va_arg(ap, const char *)) | ||||
| 			++argc; | ||||
| 		va_end(ap); | ||||
|  | ||||
| 		/* + 1 for the terminating NULL */ | ||||
| 		argv = alloca(sizeof(const char *) * (argc + 1)); | ||||
|  | ||||
| 		argv[0] = cmd; | ||||
|                 va_start(ap, cmd); | ||||
| 		while ((argv[++i] = va_arg(ap, const char *))); | ||||
| 		va_end(ap); | ||||
|  | ||||
| 		execvp(cmd, (char **)argv); | ||||
| 		syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno)); | ||||
| 		exit(127); | ||||
| 	} | ||||
|  | ||||
| 	if (pid > 0) { /* parent */ | ||||
| 		if (waitpid(pid, &status, 0) != pid) | ||||
| 			return 0; /* waitpid failed */ | ||||
| 		if (!WIFEXITED(status) || WEXITSTATUS(status)) | ||||
| 			return 0; /* the child failed */ | ||||
| 	} | ||||
|  | ||||
| 	if (pid < 0) | ||||
| 		return 0; /* fork failed */ | ||||
|  | ||||
| 	return 1; /* all good */ | ||||
| } | ||||
|  | ||||
| struct mountinfo_s { | ||||
| 	struct dm_info info; | ||||
| 	dm_bitset_t minors; /* Bitset for active thin pool minors */ | ||||
| 	const char *device; | ||||
| }; | ||||
|  | ||||
| static int _umount_device(char *buffer, unsigned major, unsigned minor, | ||||
| 			  char *target, void *cb_data) | ||||
| { | ||||
| 	struct mountinfo_s *data = cb_data; | ||||
|  | ||||
| 	if ((major == data->info.major) && dm_bit(data->minors, minor)) { | ||||
| 		syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n", | ||||
| 		       data->device, target); | ||||
| 		if (!_run(UMOUNT_COMMAND, "-fl", target, NULL)) | ||||
| 			syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n", | ||||
| 			       data->device, target, strerror(errno)); | ||||
| 	} | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Find all thin pool users and try to umount them. | ||||
|  * TODO: work with read-only thin pool support | ||||
|  */ | ||||
| static void _umount(struct dm_task *dmt, const char *device) | ||||
| { | ||||
| 	/* TODO: Convert to use hash to reduce memory usage */ | ||||
| 	static const size_t MINORS = (1U << 20); /* 20 bit */ | ||||
| 	struct mountinfo_s data = { | ||||
| 		.device = device, | ||||
| 	}; | ||||
|  | ||||
| 	if (!dm_task_get_info(dmt, &data.info)) | ||||
| 		return; | ||||
|  | ||||
| 	dmeventd_lvm2_unlock(); | ||||
|  | ||||
| 	if (!(data.minors = dm_bitset_create(NULL, MINORS))) { | ||||
| 		syslog(LOG_ERR, "Failed to allocate bitset. Not unmounting %s.\n", device); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) { | ||||
| 		syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (!dm_mountinfo_read(_umount_device, &data)) { | ||||
| 		syslog(LOG_ERR, "Could not parse mountinfo file.\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| out: | ||||
| 	if (data.minors) | ||||
| 		dm_bitset_destroy(data.minors); | ||||
| 	dmeventd_lvm2_lock(); | ||||
| } | ||||
|  | ||||
| void process_event(struct dm_task *dmt, | ||||
| 		   enum dm_event_mask event __attribute__((unused)), | ||||
| 		   void **private) | ||||
| { | ||||
| 	const char *device = dm_task_get_name(dmt); | ||||
| 	int percent; | ||||
| 	struct dso_state *state = *private; | ||||
| 	struct dm_status_thin_pool *tps = NULL; | ||||
| 	void *next = NULL; | ||||
| 	uint64_t start, length; | ||||
| 	char *target_type = NULL; | ||||
| 	char *params; | ||||
|  | ||||
| #if 0 | ||||
| 	/* No longer monitoring, waiting for remove */ | ||||
| 	if (!state->meta_percent_check && !state->data_percent_check) | ||||
| 		return; | ||||
| #endif | ||||
| 	dmeventd_lvm2_lock(); | ||||
|  | ||||
| 	dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); | ||||
|  | ||||
| 	if (!target_type || (strcmp(target_type, "thin-pool") != 0)) { | ||||
| 		syslog(LOG_ERR, "Invalid target type.\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (!dm_get_status_thin_pool(state->mem, params, &tps)) { | ||||
| 		syslog(LOG_ERR, "Failed to parse status.\n"); | ||||
| 		_umount(dmt, device); | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| #if THIN_DEBUG | ||||
| 	syslog(LOG_INFO, "%p: Got status %" PRIu64 " / %" PRIu64 | ||||
| 	       " %" PRIu64  " / %" PRIu64 ".\n", state, | ||||
| 	       tps->used_metadata_blocks, tps->total_metadata_blocks, | ||||
| 	       tps->used_data_blocks, tps->total_data_blocks); | ||||
| #endif | ||||
|  | ||||
| 	/* Thin pool size had changed. Clear the threshold. */ | ||||
| 	if (state->known_metadata_size != tps->total_metadata_blocks) { | ||||
| 		state->metadata_percent_check = CHECK_MINIMUM; | ||||
| 		state->known_metadata_size = tps->total_metadata_blocks; | ||||
| 	} | ||||
|  | ||||
| 	if (state->known_data_size != tps->total_data_blocks) { | ||||
| 		state->data_percent_check = CHECK_MINIMUM; | ||||
| 		state->known_data_size = tps->total_data_blocks; | ||||
| 	} | ||||
|  | ||||
| 	percent = 100 * tps->used_metadata_blocks / tps->total_metadata_blocks; | ||||
| 	if (percent >= state->metadata_percent_check) { | ||||
| 		/* | ||||
| 		 * Usage has raised more than CHECK_STEP since the last | ||||
| 		 * time. Run actions. | ||||
| 		 */ | ||||
| 		state->metadata_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP; | ||||
|  | ||||
| 		/* FIXME: extension of metadata needs to be written! */ | ||||
| 		if (percent >= WARNING_THRESH) /* Print a warning to syslog. */ | ||||
| 			syslog(LOG_WARNING, "Thin metadata %s is now %i%% full.\n", | ||||
| 			       device, percent); | ||||
| 		 /* Try to extend the metadata, in accord with user-set policies */ | ||||
| 		if (!_extend(state)) { | ||||
| 			syslog(LOG_ERR, "Failed to extend thin metadata %s.\n", | ||||
| 			       device); | ||||
| 			_umount(dmt, device); | ||||
| 		} | ||||
| 		/* FIXME: hmm READ-ONLY switch should happen in error path */ | ||||
| 	} | ||||
|  | ||||
| 	percent = 100 * tps->used_data_blocks / tps->total_data_blocks; | ||||
| 	if (percent >= state->data_percent_check) { | ||||
| 		/* | ||||
| 		 * Usage has raised more than CHECK_STEP since | ||||
| 		 * the last time. Run actions. | ||||
| 		 */ | ||||
| 		state->data_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP; | ||||
|  | ||||
| 		if (percent >= WARNING_THRESH) /* Print a warning to syslog. */ | ||||
| 			syslog(LOG_WARNING, "Thin %s is now %i%% full.\n", device, percent); | ||||
| 		/* Try to extend the thin data, in accord with user-set policies */ | ||||
| 		if (!_extend(state)) { | ||||
| 			syslog(LOG_ERR, "Failed to extend thin %s.\n", device); | ||||
| 			state->data_percent_check = 0; | ||||
| 			_umount(dmt, device); | ||||
| 		} | ||||
| 		/* FIXME: hmm READ-ONLY switch should happen in error path */ | ||||
| 	} | ||||
| out: | ||||
| 	if (tps) | ||||
| 		dm_pool_free(state->mem, tps); | ||||
|  | ||||
| 	dmeventd_lvm2_unlock(); | ||||
| } | ||||
|  | ||||
| int register_device(const char *device, | ||||
| 		    const char *uuid __attribute__((unused)), | ||||
| 		    int major __attribute__((unused)), | ||||
| 		    int minor __attribute__((unused)), | ||||
| 		    void **private) | ||||
| { | ||||
| 	struct dm_pool *statemem = NULL; | ||||
| 	struct dso_state *state; | ||||
|  | ||||
| 	if (!dmeventd_lvm2_init()) | ||||
| 		goto bad; | ||||
|  | ||||
| 	if (!(statemem = dm_pool_create("thin_pool_state", 2048)) || | ||||
| 	    !(state = dm_pool_zalloc(statemem, sizeof(*state))) || | ||||
| 	    !dmeventd_lvm2_command(statemem, state->cmd_str, | ||||
| 				   sizeof(state->cmd_str), | ||||
| 				   "lvextend --use-policies", | ||||
| 				   device)) { | ||||
| 		if (statemem) | ||||
| 			dm_pool_destroy(statemem); | ||||
| 		dmeventd_lvm2_exit(); | ||||
| 		goto bad; | ||||
| 	} | ||||
|  | ||||
| 	state->mem = statemem; | ||||
| 	state->metadata_percent_check = CHECK_MINIMUM; | ||||
| 	state->data_percent_check = CHECK_MINIMUM; | ||||
| 	*private = state; | ||||
|  | ||||
| 	syslog(LOG_INFO, "Monitoring thin %s.\n", device); | ||||
|  | ||||
| 	return 1; | ||||
| bad: | ||||
| 	syslog(LOG_ERR, "Failed to monitor thin %s.\n", device); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int unregister_device(const char *device, | ||||
| 		      const char *uuid __attribute__((unused)), | ||||
| 		      int major __attribute__((unused)), | ||||
| 		      int minor __attribute__((unused)), | ||||
| 		      void **private) | ||||
| { | ||||
| 	struct dso_state *state = *private; | ||||
|  | ||||
| 	syslog(LOG_INFO, "No longer monitoring thin %s.\n", device); | ||||
| 	dm_pool_destroy(state->mem); | ||||
| 	dmeventd_lvm2_exit(); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| @@ -1,60 +0,0 @@ | ||||
| # | ||||
| # Copyright (C) 2011-2012 Red Hat, Inc. | ||||
| # | ||||
| # This file is part of LVM2. | ||||
| # | ||||
| # This copyrighted material is made available to anyone wishing to use, | ||||
| # modify, copy, or redistribute it subject to the terms and conditions | ||||
| # of the GNU Lesser General Public License v.2.1. | ||||
| # | ||||
| # You should have received a copy of the GNU Lesser General Public License | ||||
| # along with this program; if not, write to the Free Software Foundation, | ||||
| # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
|  | ||||
| SOURCES = lvmetad-core.c | ||||
| SOURCES2 = testclient.c | ||||
|  | ||||
| TARGETS = lvmetad lvmetad-testclient | ||||
|  | ||||
| .PHONY: install_lvmetad | ||||
|  | ||||
| CFLOW_LIST = $(SOURCES) | ||||
| CFLOW_LIST_TARGET = $(LIB_NAME).cflow | ||||
| CFLOW_TARGET = lvmetad | ||||
|  | ||||
| include $(top_builddir)/make.tmpl | ||||
|  | ||||
| INCLUDES += -I$(top_srcdir)/libdaemon/server | ||||
| LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper | ||||
|  | ||||
| LIBS += $(PTHREAD_LIBS) | ||||
|  | ||||
| LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) | ||||
| CLDFLAGS += -L$(top_builddir)/libdaemon/server | ||||
| CFLAGS += $(EXTRA_EXEC_CFLAGS) | ||||
|  | ||||
| lvmetad: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \ | ||||
| 		    $(top_builddir)/libdaemon/server/libdaemonserver.a | ||||
| 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \ | ||||
| 	$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic | ||||
|  | ||||
| # TODO: No idea. No idea how to test either. | ||||
| #ifneq ("$(CFLOW_CMD)", "") | ||||
| #CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) | ||||
| #-include $(top_builddir)/libdm/libdevmapper.cflow | ||||
| #-include $(top_builddir)/lib/liblvm-internal.cflow | ||||
| #-include $(top_builddir)/lib/liblvm2cmd.cflow | ||||
| #-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow | ||||
| #-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow | ||||
| #endif | ||||
|  | ||||
| install_lvmetad: lvmetad | ||||
| 	$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F) | ||||
|  | ||||
| install_lvm2: install_lvmetad | ||||
|  | ||||
| install: install_lvm2 | ||||
| @@ -1,83 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2011-2012 Red Hat, Inc. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
|  * This copyrighted material is made available to anyone wishing to use, | ||||
|  * modify, copy, or redistribute it subject to the terms and conditions | ||||
|  * of the GNU Lesser General Public License v.2.1. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #ifndef _LVM_LVMETAD_CLIENT_H | ||||
| #define _LVM_LVMETAD_CLIENT_H | ||||
|  | ||||
| #include "daemon-client.h" | ||||
|  | ||||
| #define LVMETAD_SOCKET DEFAULT_RUN_DIR "/lvmetad.socket" | ||||
|  | ||||
| struct volume_group; | ||||
|  | ||||
| /* Different types of replies we may get from lvmetad. */ | ||||
|  | ||||
| typedef struct { | ||||
| 	daemon_reply r; | ||||
| 	const char **uuids; /* NULL terminated array */ | ||||
| } lvmetad_uuidlist; | ||||
|  | ||||
| typedef struct { | ||||
| 	daemon_reply r; | ||||
| 	struct dm_config_tree *cft; | ||||
| } lvmetad_vg; | ||||
|  | ||||
| /* Get a list of VG UUIDs that match a given VG name. */ | ||||
| lvmetad_uuidlist lvmetad_lookup_vgname(daemon_handle h, const char *name); | ||||
|  | ||||
| /* Get the metadata of a single VG, identified by UUID. */ | ||||
| lvmetad_vg lvmetad_get_vg(daemon_handle h, const char *uuid); | ||||
|  | ||||
| /* | ||||
|  * Add and remove PVs on demand. Udev-driven systems will use this interface | ||||
|  * instead of scanning. | ||||
|  */ | ||||
| daemon_reply lvmetad_add_pv(daemon_handle h, const char *pv_uuid, const char *mda_content); | ||||
| daemon_reply lvmetad_remove_pv(daemon_handle h, const char *pv_uuid); | ||||
|  | ||||
| /* Trigger a full disk scan, throwing away all caches. XXX do we eventually want | ||||
|  * this? Probably not yet, anyway. | ||||
|  *     daemon_reply lvmetad_rescan(daemon_handle h); | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Update the version of metadata of a volume group. The VG has to be locked for | ||||
|  * writing for this, and the VG metadata here has to match whatever has been | ||||
|  * written to the disk (under this lock). This initially avoids the requirement | ||||
|  * for lvmetad to write to disk (in later revisions, lvmetad_supersede_vg may | ||||
|  * also do the writing, or we probably add another function to do that). | ||||
|  */ | ||||
| daemon_reply lvmetad_supersede_vg(daemon_handle h, struct volume_group *vg); | ||||
|  | ||||
| /* Wrappers to open/close connection */ | ||||
|  | ||||
| static inline daemon_handle lvmetad_open(const char *socket) | ||||
| { | ||||
| 	daemon_info lvmetad_info = { | ||||
| 		.path = "lvmetad", | ||||
| 		.socket = socket ?: LVMETAD_SOCKET, | ||||
| 		.protocol = "lvmetad", | ||||
| 		.protocol_version = 1, | ||||
| 		.autostart = 0 | ||||
| 	}; | ||||
|  | ||||
| 	return daemon_open(lvmetad_info); | ||||
| } | ||||
|  | ||||
| static inline void lvmetad_close(daemon_handle h) | ||||
| { | ||||
| 	return daemon_close(h); | ||||
| } | ||||
|  | ||||
| #endif | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,16 +0,0 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| export LD_LIBRARY_PATH="$1" | ||||
|  | ||||
| test -n "$2" && { | ||||
|     rm -f /var/run/lvmetad.{socket,pid} | ||||
|     chmod +rx lvmetad | ||||
|     valgrind ./lvmetad -f & | ||||
|     PID=$! | ||||
|     sleep 1 | ||||
|     ./testclient | ||||
|     kill $PID | ||||
|     exit 0 | ||||
| } | ||||
|  | ||||
| sudo ./test.sh "$1" . | ||||
| @@ -1,127 +0,0 @@ | ||||
| #include "lvmetad-client.h" | ||||
| #include "label.h" | ||||
| #include "lvmcache.h" | ||||
| #include "metadata.h" | ||||
|  | ||||
| const char *uuid1 = "abcd-efgh"; | ||||
| const char *uuid2 = "bbcd-efgh"; | ||||
| const char *vgid = "yada-yada"; | ||||
| const char *uuid3 = "cbcd-efgh"; | ||||
|  | ||||
| const char *metadata2 = "{\n" | ||||
| 	"id = \"yada-yada\"\n" | ||||
| 	"seqno = 15\n" | ||||
| 	"status = [\"READ\", \"WRITE\"]\n" | ||||
| 	"flags = []\n" | ||||
| 	"extent_size = 8192\n" | ||||
| 	"physical_volumes {\n" | ||||
| 	"    pv0 {\n" | ||||
| 	"        id = \"abcd-efgh\"\n" | ||||
| 	"    }\n" | ||||
| 	"    pv1 {\n" | ||||
| 	"        id = \"bbcd-efgh\"\n" | ||||
| 	"    }\n" | ||||
| 	"    pv2 {\n" | ||||
| 	"        id = \"cbcd-efgh\"\n" | ||||
| 	"    }\n" | ||||
| 	"}\n" | ||||
| 	"}\n"; | ||||
|  | ||||
| void _handle_reply(daemon_reply reply) { | ||||
| 	const char *repl = daemon_reply_str(reply, "response", NULL); | ||||
| 	const char *status = daemon_reply_str(reply, "status", NULL); | ||||
| 	const char *vgid = daemon_reply_str(reply, "vgid", NULL); | ||||
|  | ||||
| 	fprintf(stderr, "[C] REPLY: %s\n", repl); | ||||
| 	if (!strcmp(repl, "failed")) | ||||
| 		fprintf(stderr, "[C] REASON: %s\n", daemon_reply_str(reply, "reason", "unknown")); | ||||
| 	if (vgid) | ||||
| 		fprintf(stderr, "[C] VGID: %s\n", vgid); | ||||
| 	if (status) | ||||
| 		fprintf(stderr, "[C] STATUS: %s\n", status); | ||||
| 	daemon_reply_destroy(reply); | ||||
| } | ||||
|  | ||||
| void _pv_add(daemon_handle h, const char *uuid, const char *metadata) | ||||
| { | ||||
| 	daemon_reply reply = daemon_send_simple(h, "pv_add", "uuid = %s", uuid, | ||||
| 						             "metadata = %b", metadata, | ||||
| 						             NULL); | ||||
| 	_handle_reply(reply); | ||||
| } | ||||
|  | ||||
| int scan(daemon_handle h, char *fn) { | ||||
| 	struct device *dev = dev_cache_get(fn, NULL); | ||||
|  | ||||
| 	struct label *label; | ||||
| 	if (!label_read(dev, &label, 0)) { | ||||
| 		fprintf(stderr, "[C] no label found on %s\n", fn); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	char uuid[64]; | ||||
| 	id_write_format(dev->pvid, uuid, 64); | ||||
| 	fprintf(stderr, "[C] found PV: %s\n", uuid); | ||||
| 	struct lvmcache_info *info = (struct lvmcache_info *) label->info; | ||||
| 	struct physical_volume pv = { 0, }; | ||||
|  | ||||
| 	if (!(info->fmt->ops->pv_read(info->fmt, dev_name(dev), &pv, 0))) { | ||||
| 		fprintf(stderr, "[C] Failed to read PV %s", dev_name(dev)); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	struct format_instance_ctx fic; | ||||
| 	struct format_instance *fid = info->fmt->ops->create_instance(info->fmt, &fic); | ||||
| 	struct metadata_area *mda; | ||||
| 	struct volume_group *vg = NULL; | ||||
| 	dm_list_iterate_items(mda, &info->mdas) { | ||||
| 		struct volume_group *this = mda->ops->vg_read(fid, "", mda); | ||||
| 		if (this && !vg || this->seqno > vg->seqno) | ||||
| 			vg = this; | ||||
| 	} | ||||
| 	if (vg) { | ||||
| 		char *buf = NULL; | ||||
| 		/* TODO. This is not entirely correct, since export_vg_to_buffer | ||||
| 		 * adds trailing garbage to the buffer. We may need to use | ||||
| 		 * export_vg_to_config_tree and format the buffer ourselves. It | ||||
| 		 * does, however, work for now, since the garbage is well | ||||
| 		 * formatted and has no conflicting keys with the rest of the | ||||
| 		 * request.  */ | ||||
| 		export_vg_to_buffer(vg, &buf); | ||||
| 		daemon_reply reply = | ||||
| 			daemon_send_simple(h, "pv_add", "uuid = %s", uuid, | ||||
| 					      "metadata = %b", strchr(buf, '{'), | ||||
| 					      NULL); | ||||
| 		_handle_reply(reply); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void _dump_vg(daemon_handle h, const char *uuid) | ||||
| { | ||||
| 	daemon_reply reply = daemon_send_simple(h, "vg_by_uuid", "uuid = %s", uuid, NULL); | ||||
| 	fprintf(stderr, "[C] reply buffer: %s\n", reply.buffer); | ||||
| 	daemon_reply_destroy(reply); | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) { | ||||
| 	daemon_handle h = lvmetad_open(); | ||||
|  | ||||
| 	if (argc > 1) { | ||||
| 		int i; | ||||
| 		struct cmd_context *cmd = create_toolcontext(0, NULL, 0, 0); | ||||
| 		for (i = 1; i < argc; ++i) { | ||||
| 			const char *uuid = NULL; | ||||
| 			scan(h, argv[i]); | ||||
| 		} | ||||
| 		destroy_toolcontext(cmd); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	_pv_add(h, uuid1, NULL); | ||||
| 	_pv_add(h, uuid2, metadata2); | ||||
| 	_dump_vg(h, vgid); | ||||
| 	_pv_add(h, uuid3, NULL); | ||||
|  | ||||
| 	daemon_close(h); | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										6
									
								
								debian/README.Debian
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								debian/README.Debian
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| LVM2 requires the device-mapper kernel module (dm-mod).  This is | ||||
| available as a kernel patch for 2.4 (in kernel-patch-device-mapper), and | ||||
| is distributed with linux 2.5 and above.  The LVM1 kernel module (lvm-mod) | ||||
| will not work with lvm2 packages.  dm-mod and lvm-mod may both be loaded | ||||
| in the kernel at the same time with no problems.  Without dm-mod, this | ||||
| package is pretty useless. | ||||
							
								
								
									
										82
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| lvm2 (1.95.15-1) unstable; urgency=low | ||||
|    | ||||
|   * New upstream release. | ||||
|   * Remove undocumented manpage symlinks. | ||||
|   * Update description to be more informative.  (Closes: #173499) | ||||
|   * Add kernel-patch-device-mapper suggestion. | ||||
|   * Update standards version. | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Sun, 16 Feb 2002 04:21:26 -0400 | ||||
|  | ||||
| lvm2 (1.95.11-1) unstable; urgency=low | ||||
|  | ||||
|   * New upstream release.  (Closes: #171436) | ||||
|   * Removed TODO and INTRO from debian/docs; added WHATS_NEW. | ||||
|   * Remove vgcfgrestore.8 undocumented symlink. | ||||
|   * Added a README.Debian, mentioning the device-mapper kernel module | ||||
|     requirement that lvm2 has.  (Closes: #171674, #163020) | ||||
|   * Get rid of debian/conffiles (debhelper's smart enough to figure that out). | ||||
|   * debian/copyright fix to appease lintian. | ||||
|   * Fix typo in tools/commands.h that caused /usr/sbin/; to be created. | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Mon,  9 Dec 2002 02:51:02 -0400 | ||||
|  | ||||
| lvm2 (1.95.10-2) unstable; urgency=low | ||||
|  | ||||
|   * Fix software raid problems by ensuring lvm init script runs after | ||||
|     raidtools init script.  (Closes: #152569) | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Tue,  3 Sep 2002 04:05:43 -0400 | ||||
|  | ||||
| lvm2 (1.95.10-1) unstable; urgency=low | ||||
|  | ||||
|   * New upstream release (Beta 3.2). | ||||
|   * Change all references to /dev/device-mapper/control to | ||||
|     /dev/mapper/control. | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Sun,  1 Sep 2002 18:55:12 -0400 | ||||
|  | ||||
| lvm2 (0.95.05-3) unstable; urgency=low | ||||
|  | ||||
|   * Get rid of awk dependency in init script.  (Closes: #146257) | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Sun, 12 May 2002 04:39:06 -0500 | ||||
|  | ||||
| lvm2 (0.95.05-2) unstable; urgency=low | ||||
|  | ||||
|   * Use ${shlibs:Depends} in Depends. | ||||
|   * Get rid of postinst/postrm scripts, use debhelper's init script instead. | ||||
|   * Add Conflicts against lvm10, lvm-common. | ||||
|   * Fix endian issues on big-endian machines. | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Thu,  2 May 2002 23:53:53 -0500 | ||||
|  | ||||
| lvm2 (0.95.05-1) unstable; urgency=low | ||||
|  | ||||
|   * New release (Beta2). | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Thu, 25 Apr 2002 00:37:41 -0500 | ||||
|  | ||||
| lvm2 (0.95.04cvs20020306-1) unstable; urgency=low | ||||
|  | ||||
|   * CVS updated. | ||||
|   * Convert from debian native package. | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Wed,  6 Mar 2002 00:43:21 -0500 | ||||
|  | ||||
| lvm2 (0.95.04cvs20020304) unstable; urgency=low | ||||
|  | ||||
|   * CVS updated. | ||||
|   * Enhance init script; create devmapper control device, etc. | ||||
|   * Add dmsetup as a suggestion. | ||||
|   * Add /etc/lvm/lvm.conf conffile. | ||||
|   * Add undocumented(7) for the commands missing manpages. | ||||
|    | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Mon,  4 Mar 2002 04:51:26 -0500 | ||||
|  | ||||
| lvm2 (0.95.02cvs20020220) unstable; urgency=low | ||||
|  | ||||
|   * Initial Release. | ||||
|  | ||||
|  -- Andres Salomon <dilinger@mp3revolution.net>  Wed, 20 Feb 2002 03:17:25 -0500 | ||||
|  | ||||
							
								
								
									
										24
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| Source: lvm2 | ||||
| Section: admin | ||||
| Priority: optional | ||||
| Maintainer: Andres Salomon <dilinger@mp3revolution.net> | ||||
| Build-Depends: debhelper (>> 3.0.0), libdevmapper-dev (>= 0.96.04), libreadline4-dev | ||||
| Standards-Version: 3.5.8.0 | ||||
|  | ||||
| Package: lvm2 | ||||
| Architecture: any | ||||
| Depends: ${shlibs:Depends} | ||||
| Conflicts: lvm10, lvm-common | ||||
| Replaces: lvm10, lvm-common | ||||
| Provides: lvm-binaries | ||||
| Suggests: dmsetup, kernel-patch-device-mapper | ||||
| Description: The Linux Logical Volume Manager | ||||
|  This is LVM2, the rewrite of The Linux Logical Volume Manager.  LVM | ||||
|  supports enterprise level volume management of disk and disk subsystems | ||||
|  by grouping arbitrary disks into volume groups. The total capacity of | ||||
|  volume groups can be allocated to logical volumes, which are accessed as | ||||
|  regular block devices. | ||||
|  . | ||||
|  LVM2 is currently stable, but has some unimplemented features (most notably, | ||||
|  pvmove and e2fsadm).  It is not yet recommended for production use.  It is | ||||
|  backwards-compatible with LVM1 (lvm10), and requires Linux kernel 2.4. | ||||
							
								
								
									
										25
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| This package was debianized by Andres Salomon <dilinger@mp3revolution.net> on | ||||
| Wed, 20 Feb 2002 03:17:25 -0500. | ||||
|  | ||||
| It was downloaded from http://www.sistina.com/products_lvm.htm | ||||
|  | ||||
| Upstream Author: LVM Development Team | ||||
|  | ||||
| Copyright (c) 2001-2002 LVM Development Team | ||||
|  | ||||
| LVM2 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. | ||||
|  | ||||
| LVM2 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 | ||||
|  | ||||
| On Debian systems, the full text of the GPL can be found in | ||||
| /usr/share/common-licenses/GPL | ||||
							
								
								
									
										4
									
								
								debian/dirs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								debian/dirs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| etc/lvm | ||||
| usr/share/man/man5 | ||||
| usr/share/man/man8 | ||||
| sbin | ||||
							
								
								
									
										5
									
								
								debian/docs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								debian/docs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| BUGS | ||||
| README | ||||
| VERSION | ||||
| WHATS_NEW | ||||
| doc/* | ||||
							
								
								
									
										64
									
								
								debian/init.d
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								debian/init.d
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| #! /bin/sh | ||||
| # | ||||
| # lvm2		This script handles LVM2 initialization/shutdown. | ||||
| # | ||||
| #		Written by Andres Salomon <dilinger@mp3revolution.net>. | ||||
| # | ||||
|  | ||||
| PATH=/sbin:/bin:/usr/sbin:/usr/bin | ||||
| NAME=lvm2 | ||||
| DESC=LVM | ||||
|  | ||||
| test -x /sbin/vgchange || exit 0 | ||||
| modprobe dm-mod >/dev/null 2>&1 | ||||
|  | ||||
| # Create necessary files in /dev for device-mapper | ||||
| create_devfiles() { | ||||
| 	DIR="/dev/mapper" | ||||
| 	FILE="$DIR/control" | ||||
| 	major=$(grep "[0-9] misc$" /proc/devices | sed 's/[ ]\+misc//') | ||||
| 	minor=$(grep "[0-9] device-mapper$" /proc/misc | sed 's/[ ]\+device-mapper//') | ||||
|  | ||||
| 	if test ! -d $DIR; then | ||||
| 		mkdir --mode=755 $DIR >/dev/null 2>&1 | ||||
| 	fi | ||||
|  | ||||
| 	if test ! -c $FILE -a ! -z "$minor"; then | ||||
| 		mknod --mode=600 $FILE c $major $minor >/dev/null 2>&1 | ||||
| 	fi | ||||
| } | ||||
|  | ||||
| case "$1" in | ||||
|   start) | ||||
| 	echo -n "Initializing $DESC: " | ||||
| 	create_devfiles | ||||
| 	vgchange -a y | ||||
|  | ||||
| #	# Mount all LVM devices | ||||
| #	for vg in $( vgchange -a y 2>/dev/null | grep active | awk -F\" '{print $2}' ); do | ||||
| #		MTPT=$( grep $vg /etc/fstab | awk '{print $2}' ) | ||||
| #		mount $MTPT | ||||
| #	done | ||||
| 	echo "$NAME." | ||||
| 	;; | ||||
|   stop) | ||||
| 	echo -n "Shutting down $DESC: " | ||||
| 	# We don't really try all that hard to shut it down; far too many | ||||
| 	# things that can keep it from successfully shutting down. | ||||
| 	vgchange -a n | ||||
| 	echo "$NAME." | ||||
| 	;; | ||||
|   restart|force-reload) | ||||
| 	echo -n "Restarting $DESC: " | ||||
| 	vgchange -a n | ||||
| 	sleep 1 | ||||
| 	vgchange -a y | ||||
| 	echo "$NAME." | ||||
| 	;; | ||||
|   *) | ||||
| 	echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2 | ||||
| 	exit 1 | ||||
| 	;; | ||||
| esac | ||||
|  | ||||
| exit 0 | ||||
							
								
								
									
										26
									
								
								debian/manpages
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								debian/manpages
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| debian/lvm2/usr/share/man/man5/lvm.conf.5 | ||||
| debian/lvm2/usr/share/man/man8/lvchange.8 | ||||
| debian/lvm2/usr/share/man/man8/lvcreate.8 | ||||
| debian/lvm2/usr/share/man/man8/lvdisplay.8 | ||||
| debian/lvm2/usr/share/man/man8/lvextend.8 | ||||
| debian/lvm2/usr/share/man/man8/lvm.8 | ||||
| debian/lvm2/usr/share/man/man8/lvmchange.8 | ||||
| debian/lvm2/usr/share/man/man8/lvreduce.8 | ||||
| debian/lvm2/usr/share/man/man8/lvremove.8 | ||||
| debian/lvm2/usr/share/man/man8/lvrename.8 | ||||
| debian/lvm2/usr/share/man/man8/lvscan.8 | ||||
| debian/lvm2/usr/share/man/man8/pvchange.8 | ||||
| debian/lvm2/usr/share/man/man8/pvcreate.8 | ||||
| debian/lvm2/usr/share/man/man8/pvdisplay.8 | ||||
| debian/lvm2/usr/share/man/man8/pvscan.8 | ||||
| debian/lvm2/usr/share/man/man8/vgcfgbackup.8 | ||||
| debian/lvm2/usr/share/man/man8/vgchange.8 | ||||
| debian/lvm2/usr/share/man/man8/vgck.8 | ||||
| debian/lvm2/usr/share/man/man8/vgcreate.8 | ||||
| debian/lvm2/usr/share/man/man8/vgdisplay.8 | ||||
| debian/lvm2/usr/share/man/man8/vgextend.8 | ||||
| debian/lvm2/usr/share/man/man8/vgmerge.8 | ||||
| debian/lvm2/usr/share/man/man8/vgreduce.8 | ||||
| debian/lvm2/usr/share/man/man8/vgremove.8 | ||||
| debian/lvm2/usr/share/man/man8/vgrename.8 | ||||
| debian/lvm2/usr/share/man/man8/vgscan.8 | ||||
							
								
								
									
										119
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										119
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| #!/usr/bin/make -f | ||||
| # Sample debian/rules that uses debhelper.  | ||||
| # GNU copyright 1997 by Joey Hess. | ||||
| # | ||||
| # This version is for a hypothetical package that builds an | ||||
| # architecture-dependant package, as well as an architecture-independent | ||||
| # package. | ||||
|  | ||||
| # Uncomment this to turn on verbose mode.  | ||||
| #export DH_VERBOSE=1 | ||||
|  | ||||
| # This is the debhelper compatibility version to use. | ||||
| export DH_COMPAT=3 | ||||
|  | ||||
| # These are used for cross-compiling and for saving the configure script | ||||
| # from having to guess our platform (since we know it already) | ||||
| DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) | ||||
| DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) | ||||
|  | ||||
| ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) | ||||
| 	CFLAGS += -g | ||||
| endif | ||||
| ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) | ||||
| 	INSTALL_PROGRAM += -s | ||||
| endif | ||||
|  | ||||
| configure: configure-stamp | ||||
| configure-stamp: | ||||
| 	dh_testdir | ||||
| 	# Add here commands to configure the package. | ||||
| 	./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/ --mandir=\$${prefix}/usr/share/man --infodir=\$${prefix}/usr/share/info | ||||
|  | ||||
| 	touch configure-stamp | ||||
|  | ||||
| build-arch: configure-stamp build-arch-stamp | ||||
| build-arch-stamp: | ||||
| 	dh_testdir | ||||
|  | ||||
| 	# Add here command to compile/build the package. | ||||
| 	$(MAKE) | ||||
|  | ||||
| 	touch build-arch-stamp | ||||
|  | ||||
| build-indep: configure-stamp build-indep-stamp | ||||
| build-indep-stamp: | ||||
| 	dh_testdir | ||||
|  | ||||
| 	# Add here command to compile/build the arch indep package. | ||||
| 	# It's ok not to do anything here, if you don't need to build | ||||
| 	#  anything for this package. | ||||
| 	#/usr/bin/docbook-to-man debian/lvm2.sgml > lvm2.1 | ||||
|  | ||||
| 	touch build-indep-stamp | ||||
|  | ||||
| build: build-arch build-indep | ||||
|  | ||||
| clean: | ||||
| 	dh_testdir | ||||
| 	dh_testroot | ||||
| 	rm -f build-stamp configure-stamp | ||||
|  | ||||
| 	# Add here commands to clean up after the build process. | ||||
| 	-$(MAKE) distclean | ||||
| 	-test -r /usr/share/misc/config.sub && \ | ||||
| 	  cp -f /usr/share/misc/config.sub config.sub | ||||
| 	-test -r /usr/share/misc/config.guess && \ | ||||
| 	  cp -f /usr/share/misc/config.guess config.guess | ||||
|  | ||||
|  | ||||
| 	dh_clean | ||||
|  | ||||
| install: DH_OPTIONS= | ||||
| install: build | ||||
| 	dh_testdir | ||||
| 	dh_testroot | ||||
| 	dh_clean -k | ||||
| 	dh_installdirs | ||||
|  | ||||
| 	# Add here commands to install the package into debian/lvm2. | ||||
| 	$(MAKE) install prefix=$(CURDIR)/debian/lvm2 | ||||
| 	install -m 0644 doc/example.conf debian/lvm2/etc/lvm/lvm.conf | ||||
|  | ||||
|  | ||||
| # Build architecture-independent files here. | ||||
| # Pass -i to all debhelper commands in this target to reduce clutter. | ||||
| binary-indep: build install | ||||
| # nada. | ||||
|  | ||||
| # Build architecture-dependent files here. | ||||
| binary-arch: build install | ||||
| 	dh_testdir | ||||
| 	dh_testroot | ||||
|  | ||||
| #	dh_installdebconf | ||||
| 	dh_installdocs | ||||
| 	dh_installexamples | ||||
| #	dh_installlogrotate -a | ||||
| #	dh_installemacsen -a | ||||
| #	dh_installpam -a | ||||
| #	dh_installmime -a | ||||
| 	dh_installinit --update-rcd-params="start 26 S . start 50 0 6 ." | ||||
| 	dh_installcron | ||||
| 	dh_installman | ||||
| 	dh_installinfo  | ||||
| 	dh_installchangelogs | ||||
| 	dh_strip | ||||
| 	dh_link | ||||
| 	dh_compress | ||||
| 	dh_fixperms | ||||
| 	dh_makeshlibs | ||||
| 	dh_installdeb | ||||
| #	dh_perl -a | ||||
| 	dh_shlibdeps | ||||
| 	dh_gencontrol | ||||
| 	dh_md5sums | ||||
| 	dh_builddeb | ||||
|  | ||||
| binary: binary-indep binary-arch | ||||
| .PHONY: build clean binary-indep binary-arch binary install configure | ||||
| @@ -1,7 +1,8 @@ | ||||
| #
 | ||||
| # Copyright (C) 2011 Red Hat, Inc. All rights reserved.
 | ||||
| # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | ||||
| # Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | ||||
| #
 | ||||
| # This file is part of LVM2.
 | ||||
| # This 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
 | ||||
| @@ -13,13 +14,9 @@ | ||||
| 
 | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| VPATH = @srcdir@ | ||||
| 
 | ||||
| SOURCES = thin.c | ||||
| SUBDIRS += mirror | ||||
| 
 | ||||
| LIB_SHARED = liblvm2thin.$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
| include $(top_srcdir)/make.tmpl | ||||
| 
 | ||||
| include $(top_builddir)/make.tmpl | ||||
| 
 | ||||
| install: install_lib_shared_plugin | ||||
| @@ -1,6 +1,6 @@ | ||||
| #
 | ||||
| # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
 | ||||
| # Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
 | ||||
| # Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 | ||||
| #
 | ||||
| # This file is part of the LVM2.
 | ||||
| #
 | ||||
| @@ -14,20 +14,23 @@ | ||||
| 
 | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| VPATH = @srcdir@ | ||||
| 
 | ||||
| INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2 | ||||
| CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2 | ||||
| INCLUDES += -I${top_srcdir}/tools | ||||
| CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd | ||||
| 
 | ||||
| SOURCES = dmeventd_snapshot.c | ||||
| SOURCES = dmeventd_mirror.c | ||||
| 
 | ||||
| LIB_SHARED = libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
| ifeq ("@LIB_SUFFIX@","dylib") | ||||
|   LIB_SHARED = libdevmapper-event-lvm2mirror.dylib | ||||
| else | ||||
|   LIB_SHARED = libdevmapper-event-lvm2mirror.so | ||||
| endif | ||||
| 
 | ||||
| include $(top_builddir)/make.tmpl | ||||
| include $(top_srcdir)/make.tmpl | ||||
| 
 | ||||
| LIBS += -ldevmapper-event-lvm2 -ldevmapper | ||||
| install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX) | ||||
| 	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
 | ||||
| 		$(libdir)/$<.$(LIB_VERSION) | ||||
| 	$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$< | ||||
| 
 | ||||
| install_lvm2: install_dm_plugin | ||||
| 
 | ||||
| install: install_lvm2 | ||||
							
								
								
									
										281
									
								
								dmeventd/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								dmeventd/mirror/dmeventd_mirror.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,281 @@ | ||||
| /* | ||||
|  * Copyright (C) 2005 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
|  * This copyrighted material is made available to anyone wishing to use, | ||||
|  * modify, copy, or redistribute it subject to the terms and conditions | ||||
|  * of the GNU Lesser General Public License v.2.1. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
|  | ||||
| #include "lvm2cmd.h" | ||||
|  | ||||
| #include <libdevmapper.h> | ||||
| #include <libdevmapper-event.h> | ||||
| #include <errno.h> | ||||
| #include <signal.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <pthread.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include <syslog.h> /* FIXME Replace syslog with multilog */ | ||||
| /* FIXME Missing openlog? */ | ||||
|  | ||||
| #define ME_IGNORE    0 | ||||
| #define ME_INSYNC    1 | ||||
| #define ME_FAILURE   2 | ||||
|  | ||||
| /* | ||||
|  * register_device() is called first and performs initialisation. | ||||
|  * Only one device may be registered or unregistered at a time. | ||||
|  */ | ||||
| static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
|  | ||||
| /* | ||||
|  * Number of active registrations. | ||||
|  */ | ||||
| static int _register_count = 0; | ||||
|  | ||||
| static struct dm_pool *_mem_pool = NULL; | ||||
| static void *_lvm_handle = NULL; | ||||
|  | ||||
| /* | ||||
|  * Currently only one event can be processed at a time. | ||||
|  */ | ||||
| static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
|  | ||||
| static int _get_mirror_event(char *params) | ||||
| { | ||||
| 	int i, r = ME_INSYNC; | ||||
| 	char **args = NULL; | ||||
| 	char *dev_status_str; | ||||
| 	char *log_status_str; | ||||
| 	char *sync_str; | ||||
| 	char *p = NULL; | ||||
| 	int log_argc, num_devs; | ||||
|  | ||||
| 	/* | ||||
| 	 * dm core parms:	     0 409600 mirror | ||||
| 	 * Mirror core parms:	     2 253:4 253:5 400/400 | ||||
| 	 * New-style failure params: 1 AA | ||||
| 	 * New-style log params:     3 cluster 253:3 A | ||||
| 	 *			 or  3 disk 253:3 A | ||||
| 	 *			 or  1 core | ||||
| 	 */ | ||||
|  | ||||
| 	/* number of devices */ | ||||
| 	if (!dm_split_words(params, 1, 0, &p)) | ||||
| 		goto out_parse; | ||||
|  | ||||
| 	if (!(num_devs = atoi(p))) | ||||
| 		goto out_parse; | ||||
| 	p += strlen(p) + 1; | ||||
|  | ||||
| 	/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */ | ||||
| 	args = dm_malloc((num_devs + 7) * sizeof(char *)); | ||||
| 	if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5) | ||||
| 		goto out_parse; | ||||
|  | ||||
| 	dev_status_str = args[2 + num_devs]; | ||||
| 	log_argc = atoi(args[3 + num_devs]); | ||||
| 	log_status_str = args[3 + num_devs + log_argc]; | ||||
| 	sync_str = args[num_devs]; | ||||
|  | ||||
| 	/* Check for bad mirror devices */ | ||||
| 	for (i = 0; i < num_devs; i++) | ||||
| 		if (dev_status_str[i] == 'D') { | ||||
| 			syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]); | ||||
| 			r = ME_FAILURE; | ||||
| 		} | ||||
|  | ||||
| 	/* Check for bad disk log device */ | ||||
| 	if (log_argc > 1 && log_status_str[0] == 'D') { | ||||
| 		syslog(LOG_ERR, "Log device, %s, has failed.\n", | ||||
| 		       args[2 + num_devs + log_argc]); | ||||
| 		r = ME_FAILURE; | ||||
| 	} | ||||
|  | ||||
| 	if (r == ME_FAILURE) | ||||
| 		goto out; | ||||
|  | ||||
| 	p = strstr(sync_str, "/"); | ||||
| 	if (p) { | ||||
| 		p[0] = '\0'; | ||||
| 		if (strcmp(sync_str, p+1)) | ||||
| 			r = ME_IGNORE; | ||||
| 		p[0] = '/'; | ||||
| 	} else | ||||
| 		goto out_parse; | ||||
|  | ||||
| out: | ||||
| 	if (args) | ||||
| 		dm_free(args); | ||||
| 	return r; | ||||
| 	 | ||||
| out_parse: | ||||
| 	if (args) | ||||
| 		dm_free(args); | ||||
| 	syslog(LOG_ERR, "Unable to parse mirror status string."); | ||||
| 	return ME_IGNORE; | ||||
| } | ||||
|  | ||||
| static void _temporary_log_fn(int level, const char *file, | ||||
| 			      int line, const char *format) | ||||
| { | ||||
| 	if (!strncmp(format, "WARNING: ", 9) && (level < 5)) | ||||
| 		syslog(LOG_CRIT, "%s", format); | ||||
| 	else | ||||
| 		syslog(LOG_DEBUG, "%s", format); | ||||
| } | ||||
|  | ||||
| static int _remove_failed_devices(const char *device) | ||||
| { | ||||
| 	int r; | ||||
| #define CMD_SIZE 256	/* FIXME Use system restriction */ | ||||
| 	char cmd_str[CMD_SIZE]; | ||||
| 	char *vg = NULL, *lv = NULL, *layer = NULL; | ||||
|  | ||||
| 	if (strlen(device) > 200)  /* FIXME Use real restriction */ | ||||
| 		return -ENAMETOOLONG;	/* FIXME These return code distinctions are not used so remove them! */ | ||||
|  | ||||
| 	if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) { | ||||
| 		syslog(LOG_ERR, "Unable to determine VG name from %s", | ||||
| 		       device); | ||||
| 		return -ENOMEM;	/* FIXME Replace with generic error return - reason for failure has already got logged */ | ||||
| 	} | ||||
|  | ||||
| 	/* FIXME Is any sanity-checking required on %s? */ | ||||
| 	if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) { | ||||
| 		/* this error should be caught above, but doesn't hurt to check again */ | ||||
| 		syslog(LOG_ERR, "Unable to form LVM command: Device name too long"); | ||||
| 		dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */ | ||||
| 		return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */ | ||||
| 	} | ||||
|  | ||||
| 	r = lvm2_run(_lvm_handle, cmd_str); | ||||
|  | ||||
| 	dm_pool_empty(_mem_pool);  /* FIXME: not safe with multiple threads */ | ||||
| 	return (r == 1) ? 0 : -1; | ||||
| } | ||||
|  | ||||
| void process_event(struct dm_task *dmt, enum dm_event_mask event, | ||||
| 		   void **unused __attribute((unused))) | ||||
| { | ||||
| 	void *next = NULL; | ||||
| 	uint64_t start, length; | ||||
| 	char *target_type = NULL; | ||||
| 	char *params; | ||||
| 	const char *device = dm_task_get_name(dmt); | ||||
|  | ||||
| 	if (pthread_mutex_trylock(&_event_mutex)) { | ||||
| 		syslog(LOG_NOTICE, "Another thread is handling an event.  Waiting..."); | ||||
| 		pthread_mutex_lock(&_event_mutex); | ||||
| 	} | ||||
| 	do { | ||||
| 		next = dm_get_next_target(dmt, next, &start, &length, | ||||
| 					  &target_type, ¶ms); | ||||
|  | ||||
| 		if (!target_type) { | ||||
| 			syslog(LOG_INFO, "%s mapping lost.\n", device); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (strcmp(target_type, "mirror")) { | ||||
| 			syslog(LOG_INFO, "%s has unmirrored portion.\n", device); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		switch(_get_mirror_event(params)) { | ||||
| 		case ME_INSYNC: | ||||
| 			/* FIXME: all we really know is that this | ||||
| 			   _part_ of the device is in sync | ||||
| 			   Also, this is not an error | ||||
| 			*/ | ||||
| 			syslog(LOG_NOTICE, "%s is now in-sync\n", device); | ||||
| 			break; | ||||
| 		case ME_FAILURE: | ||||
| 			syslog(LOG_ERR, "Device failure in %s\n", device); | ||||
| 			if (_remove_failed_devices(device)) | ||||
| 				/* FIXME Why are all the error return codes unused? Get rid of them? */ | ||||
| 				syslog(LOG_ERR, "Failed to remove faulty devices in %s\n", | ||||
| 				       device); | ||||
| 			/* Should check before warning user that device is now linear | ||||
| 			else | ||||
| 				syslog(LOG_NOTICE, "%s is now a linear device.\n", | ||||
| 					device); | ||||
| 			*/ | ||||
| 			break; | ||||
| 		case ME_IGNORE: | ||||
| 			break; | ||||
| 		default: | ||||
| 			/* FIXME Provide value then! */ | ||||
| 			syslog(LOG_INFO, "Unknown event received.\n"); | ||||
| 		} | ||||
| 	} while (next); | ||||
|  | ||||
| 	pthread_mutex_unlock(&_event_mutex); | ||||
| } | ||||
|  | ||||
| int register_device(const char *device, const char *uuid, int major, int minor, | ||||
| 		   void **unused __attribute((unused))) | ||||
| { | ||||
| 	int r = 0; | ||||
|  | ||||
| 	pthread_mutex_lock(&_register_mutex); | ||||
|  | ||||
| 	syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device); | ||||
|  | ||||
| 	/* | ||||
| 	 * Need some space for allocations.  1024 should be more | ||||
| 	 * than enough for what we need (device mapper name splitting) | ||||
| 	 */ | ||||
| 	if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024))) | ||||
| 		goto out; | ||||
|  | ||||
| 	if (!_lvm_handle) { | ||||
| 		lvm2_log_fn(_temporary_log_fn); | ||||
| 		if (!(_lvm_handle = lvm2_init())) { | ||||
| 			dm_pool_destroy(_mem_pool); | ||||
| 			_mem_pool = NULL; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS); | ||||
| 		/* FIXME Temporary: move to dmeventd core */ | ||||
| 		lvm2_run(_lvm_handle, "_memlock_inc"); | ||||
| 	} | ||||
|  | ||||
| 	_register_count++; | ||||
| 	r = 1; | ||||
|  | ||||
| out: | ||||
| 	pthread_mutex_unlock(&_register_mutex); | ||||
|  | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| int unregister_device(const char *device, const char *uuid, int major, int minor, | ||||
| 		   void **unused __attribute((unused))) | ||||
| { | ||||
| 	pthread_mutex_lock(&_register_mutex); | ||||
|  | ||||
| 	syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n", | ||||
| 	       device); | ||||
|  | ||||
| 	if (!--_register_count) { | ||||
| 		dm_pool_destroy(_mem_pool); | ||||
| 		_mem_pool = NULL; | ||||
| 		lvm2_run(_lvm_handle, "_memlock_dec"); | ||||
| 		lvm2_exit(_lvm_handle); | ||||
| 		_lvm_handle = NULL; | ||||
| 	} | ||||
|  | ||||
| 	pthread_mutex_unlock(&_register_mutex); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
							
								
								
									
										1
									
								
								doc/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								doc/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | ||||
| example.conf | ||||
| @@ -1,8 +1,7 @@ | ||||
| #
 | ||||
| # 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 the LVM2.
 | ||||
| #
 | ||||
| # This copyrighted material is made available to anyone wishing to use,
 | ||||
| # modify, copy, or redistribute it subject to the terms and conditions
 | ||||
| @@ -14,13 +13,17 @@ | ||||
| 
 | ||||
| srcdir = @srcdir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| top_builddir = @top_builddir@ | ||||
| VPATH = @srcdir@ | ||||
| 
 | ||||
| SOURCES = raid.c | ||||
| CONFSRC=example.conf | ||||
| CONFDEST=lvm.conf | ||||
| 
 | ||||
| LIB_SHARED = liblvm2raid.$(LIB_SUFFIX) | ||||
| LIB_VERSION = $(LIB_VERSION_LVM) | ||||
| include $(top_srcdir)/make.tmpl | ||||
| 
 | ||||
| include $(top_builddir)/make.tmpl | ||||
| install: | ||||
| 	@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
 | ||||
| 		echo "Installing $(CONFSRC) as $(confdir)/$(CONFDEST)"; \
 | ||||
| 		@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $(CONFSRC) \
 | ||||
| 			$(confdir)/$(CONFDEST); \
 | ||||
| 	fi | ||||
| 
 | ||||
| install: install_lvm2_plugin | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user