mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-23 23:33:15 +03:00
Compare commits
5292 Commits
dev-mcsont
...
v2_02_83
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60963d276e | ||
|
|
b44de841ff | ||
|
|
c45e064975 | ||
|
|
559d2923a7 | ||
|
|
a683b0c993 | ||
|
|
1ce9f8621b | ||
|
|
84f191ce5a | ||
|
|
577c542adc | ||
|
|
a0866f0990 | ||
|
|
29c9aced14 | ||
|
|
c154d18b11 | ||
|
|
6ed7b4d790 | ||
|
|
73300f8977 | ||
|
|
fc585fc2fb | ||
|
|
713b630c66 | ||
|
|
3d3f093b8c | ||
|
|
9e12eb1cf5 | ||
|
|
5c3949eac3 | ||
|
|
d4fd789d78 | ||
|
|
197d68a4d0 | ||
|
|
4ae7c94196 | ||
|
|
248426e1ee | ||
|
|
b9d4336960 | ||
|
|
c60ff20842 | ||
|
|
e4b7c72b3a | ||
|
|
6cbcd683ba | ||
|
|
e50edb8410 | ||
|
|
5b8845974c | ||
|
|
2169ecd063 | ||
|
|
74c10192aa | ||
|
|
cb3031b7fe | ||
|
|
61e665d65b | ||
|
|
2d8c68d097 | ||
|
|
9bcd306c02 | ||
|
|
4fa5445562 | ||
|
|
76b030d82e | ||
|
|
2fef22fa85 | ||
|
|
8440981845 | ||
|
|
5ba08f195a | ||
|
|
342e9fee4a | ||
|
|
0db2d39105 | ||
|
|
27e49620ec | ||
|
|
f2439f2096 | ||
|
|
3289982950 | ||
|
|
f18ec47d42 | ||
|
|
37f5c45dd5 | ||
|
|
fdd24fd4e5 | ||
|
|
66a6d5c073 | ||
|
|
73b81bcd35 | ||
|
|
4dff097f66 | ||
|
|
ea0c01a2dd | ||
|
|
e1ad66800a | ||
|
|
f0306e63b2 | ||
|
|
4dca082776 | ||
|
|
4efa0617b9 | ||
|
|
3216fba3ca | ||
|
|
e954736299 | ||
|
|
c7e561d33d | ||
|
|
ce94c7ea73 | ||
|
|
6789424259 | ||
|
|
7a18ae6da4 | ||
|
|
5f2829b0a0 | ||
|
|
49376579bf | ||
|
|
8a3e1de5c8 | ||
|
|
6470c383b2 | ||
|
|
cbfb6504a8 | ||
|
|
a4cdc80836 | ||
|
|
b598e9482d | ||
|
|
0c83d60688 | ||
|
|
d2a3f3afa1 | ||
|
|
f1e5f9d8d5 | ||
|
|
92c39fea53 | ||
|
|
d67ac7ed5c | ||
|
|
9e397d92f5 | ||
|
|
f40795a119 | ||
|
|
8d4f93634f | ||
|
|
c141fe1c44 | ||
|
|
2e776f6b50 | ||
|
|
437dac07eb | ||
|
|
77e3610e1a | ||
|
|
a23f91ad2f | ||
|
|
4fef104bf1 | ||
|
|
57f8bc3081 | ||
|
|
40fbdb71bd | ||
|
|
7cbf6fa3a6 | ||
|
|
019423f769 | ||
|
|
4114ac5d22 | ||
|
|
1a2e58b067 | ||
|
|
9ce215ed01 | ||
|
|
ad7bccb8ea | ||
|
|
3621b75306 | ||
|
|
14908e3a3b | ||
|
|
7ce032b99d | ||
|
|
dcaf6313af | ||
|
|
b74d30d55a | ||
|
|
9c705ce71e | ||
|
|
16af1b083b | ||
|
|
f4d63e9e58 | ||
|
|
cae4882865 | ||
|
|
9d4bb244e3 | ||
|
|
41b1b9487c | ||
|
|
6c1db4a7d6 | ||
|
|
7b0c0103a9 | ||
|
|
ef6ec3f737 | ||
|
|
78269c2110 | ||
|
|
eb91c54467 | ||
|
|
56b6c12e8a | ||
|
|
6507ce98df | ||
|
|
2fbadde558 | ||
|
|
5a363d74f2 | ||
|
|
b2817688ac | ||
|
|
659b348a44 | ||
|
|
6990a8c942 | ||
|
|
98b4ee635d | ||
|
|
7d048d52f6 | ||
|
|
41fb54489f | ||
|
|
3be9ec308a | ||
|
|
f120a17b1d | ||
|
|
fc7054c150 | ||
|
|
cde70f94db | ||
|
|
8f0f328dbf | ||
|
|
10e3bdcce3 | ||
|
|
bc036c01cb | ||
|
|
c14f565d18 | ||
|
|
f56007d95f | ||
|
|
65599cfb58 | ||
|
|
39b2b95477 | ||
|
|
e65561feae | ||
|
|
2a2170efc0 | ||
|
|
adb5fb90b1 | ||
|
|
ad9e16c198 | ||
|
|
96a20ae9d4 | ||
|
|
0cadf7ba66 | ||
|
|
bb5ccf8869 | ||
|
|
57d19b3f1b | ||
|
|
e45d947322 | ||
|
|
b44cdfc143 | ||
|
|
385933819e | ||
|
|
58e3ba19a2 | ||
|
|
0f3ab63a24 | ||
|
|
2697eddcba | ||
|
|
90ba925a19 | ||
|
|
b5d23f1591 | ||
|
|
e6f0290d9f | ||
|
|
23a3de988f | ||
|
|
c4fc6c2381 | ||
|
|
9bc24aea56 | ||
|
|
8392d2853e | ||
|
|
28708849a9 | ||
|
|
9f1538687a | ||
|
|
0ae26564ce | ||
|
|
9c146b8a6f | ||
|
|
2913ac8b4e | ||
|
|
6556fcc3fc | ||
|
|
1c6b3062bf | ||
|
|
b00600c247 | ||
|
|
97d680c924 | ||
|
|
8f606cf0f6 | ||
|
|
c05aa13dcf | ||
|
|
12389f2089 | ||
|
|
b3cb194c03 | ||
|
|
1ea4c6d449 | ||
|
|
e5526cb27e | ||
|
|
8a8a182679 | ||
|
|
2f19cff4df | ||
|
|
0bceef8c78 | ||
|
|
40eee88b06 | ||
|
|
0c79543cfe | ||
|
|
6ea66f6925 | ||
|
|
8891680304 | ||
|
|
1f80f8f371 | ||
|
|
d2fefb2e80 | ||
|
|
b3032f918e | ||
|
|
bb37f26bbf | ||
|
|
e805bfb103 | ||
|
|
a1cbc61c34 | ||
|
|
e3deef3baa | ||
|
|
4b81bb549d | ||
|
|
c0274f4018 | ||
|
|
46ac061fb3 | ||
|
|
5e4a1476b3 | ||
|
|
3415f08149 | ||
|
|
c384ad4074 | ||
|
|
8a9dbd13e7 | ||
|
|
1e2f3763cb | ||
|
|
bc9b386f80 | ||
|
|
b4940ed53c | ||
|
|
1e9221af45 | ||
|
|
200675b506 | ||
|
|
6424bd9e6d | ||
|
|
7ce425114e | ||
|
|
b0e9ba5f4b | ||
|
|
7837f37e21 | ||
|
|
966bfcef27 | ||
|
|
70ebb39097 | ||
|
|
60d340b387 | ||
|
|
22812bc83c | ||
|
|
83c37777f1 | ||
|
|
a200f50bbe | ||
|
|
a2f563f84f | ||
|
|
d5c94a08a7 | ||
|
|
9fc47d67df | ||
|
|
c697497923 | ||
|
|
b13837c2c0 | ||
|
|
5eb6300c77 | ||
|
|
a1b86401a5 | ||
|
|
5dcb17df67 | ||
|
|
5b94a87589 | ||
|
|
3698ce35b1 | ||
|
|
e6ce16ae13 | ||
|
|
7e8110ec50 | ||
|
|
482cef7121 | ||
|
|
3c3e95a5a8 | ||
|
|
e0a4b67e11 | ||
|
|
56c7200837 | ||
|
|
0381e82b54 | ||
|
|
28b075f78d | ||
|
|
4f4c217659 | ||
|
|
55d9104463 | ||
|
|
be2679a691 | ||
|
|
69281c1eab | ||
|
|
ea249ebca7 | ||
|
|
e60fe35e6b | ||
|
|
a1945b9f12 | ||
|
|
d41c8aed57 | ||
|
|
fbf215ade2 | ||
|
|
5b679c060d | ||
|
|
acb88b5339 | ||
|
|
c3d7df946e | ||
|
|
1dea3b9fab | ||
|
|
3801cb524c | ||
|
|
001b2c264b | ||
|
|
f1e5a95d89 | ||
|
|
8779301c8d | ||
|
|
2ac0e8f989 | ||
|
|
f912e2c887 | ||
|
|
732528e1c0 | ||
|
|
90222d0232 | ||
|
|
85933f336c | ||
|
|
dc60e49a4d | ||
|
|
d1626c2433 | ||
|
|
2b3e80e233 | ||
|
|
0eb26e4582 | ||
|
|
79a9cb910a | ||
|
|
5b958643be | ||
|
|
6e17f8809d | ||
|
|
75ab0236a9 | ||
|
|
4928dded55 | ||
|
|
61325c32b0 | ||
|
|
4f2136c654 | ||
|
|
9489a09e01 | ||
|
|
b55eb45e6a | ||
|
|
294097601d | ||
|
|
92afd60d92 | ||
|
|
6bb64bc0b7 | ||
|
|
16138ebca3 | ||
|
|
bcf4cf83e4 | ||
|
|
5d3834485e | ||
|
|
4bd06a929d | ||
|
|
9f8d31c4a2 | ||
|
|
e01d8e9702 | ||
|
|
212f7e0409 | ||
|
|
676492a634 | ||
|
|
39311f404e | ||
|
|
60b5c7dab1 | ||
|
|
fe80296ff0 | ||
|
|
e945819706 | ||
|
|
caad1b4ff9 | ||
|
|
2286995abd | ||
|
|
3548ba3827 | ||
|
|
de2c6ce36e | ||
|
|
af1144cac0 | ||
|
|
4894259eca | ||
|
|
ab3b542a18 | ||
|
|
262ff6e9d3 | ||
|
|
968c382706 | ||
|
|
d99a0313a7 | ||
|
|
ad2a90ccc6 | ||
|
|
64013278fb | ||
|
|
86a974c3c3 | ||
|
|
f56361e29f | ||
|
|
b53badf298 | ||
|
|
93bd371b57 | ||
|
|
3bb9c8e43e | ||
|
|
09c6b90d76 | ||
|
|
032a206a83 | ||
|
|
735d51276c | ||
|
|
bc91078978 | ||
|
|
8179a2dc9c | ||
|
|
ab98a1c5dc | ||
|
|
d9f958852c | ||
|
|
27b0895f6d | ||
|
|
fec4084b90 | ||
|
|
9a9d7c1c55 | ||
|
|
0f287ed3dd | ||
|
|
cf048beade | ||
|
|
558c22a454 | ||
|
|
683f33139e | ||
|
|
810abed9ea | ||
|
|
9bd893bbc7 | ||
|
|
abf79b3678 | ||
|
|
290d1d8c3f | ||
|
|
f1ec47e131 | ||
|
|
0e36229da2 | ||
|
|
5d5d6e4d4a | ||
|
|
543f8e8cca | ||
|
|
d5f5a46b33 | ||
|
|
ac146fc759 | ||
|
|
5b5c981c13 | ||
|
|
fbe2b85f22 | ||
|
|
377a39fcaf | ||
|
|
6674b9a66f | ||
|
|
73ac1ba150 | ||
|
|
fa3bfb017b | ||
|
|
c755772a23 | ||
|
|
441a1d7ee2 | ||
|
|
f6318121f4 | ||
|
|
88943533dd | ||
|
|
fba05d7ba1 | ||
|
|
d302389b9f | ||
|
|
14ccfd53b5 | ||
|
|
e0256ba49a | ||
|
|
22f922671e | ||
|
|
589f03e91a | ||
|
|
759241e905 | ||
|
|
b68cb6026e | ||
|
|
b1b18e183c | ||
|
|
64cdefc540 | ||
|
|
52aa8cabe3 | ||
|
|
e420410f9a | ||
|
|
45f69c7d5f | ||
|
|
612b90ba52 | ||
|
|
ae0ac24fdd | ||
|
|
4e51f802a0 | ||
|
|
e4c3b136f5 | ||
|
|
f1329d4511 | ||
|
|
ee5f8f12bf | ||
|
|
cb41445647 | ||
|
|
6d518948a9 | ||
|
|
45628f9813 | ||
|
|
affe488e93 | ||
|
|
c294dbb4c8 | ||
|
|
a60e991ee7 | ||
|
|
3cfab15e8a | ||
|
|
eb8af4be25 | ||
|
|
014546ad62 | ||
|
|
e2240edafc | ||
|
|
e4d6cfc013 | ||
|
|
79e3827207 | ||
|
|
ba29d593b9 | ||
|
|
b53f7f9993 | ||
|
|
e6e871afbe | ||
|
|
45edc2ae3f | ||
|
|
d54db5013b | ||
|
|
5426e85284 | ||
|
|
81631b1986 | ||
|
|
df1b244fda | ||
|
|
004cda1b64 | ||
|
|
97c6592073 | ||
|
|
949b8c519b | ||
|
|
e59624d6e9 | ||
|
|
74b228ee94 | ||
|
|
1565532bc7 | ||
|
|
21a17f291c | ||
|
|
919568a223 | ||
|
|
ec81f7151d | ||
|
|
46eae0cdd8 | ||
|
|
e5ecec8140 | ||
|
|
401f9e0eaf | ||
|
|
06769c9ccd | ||
|
|
009e7950bf | ||
|
|
66ad893ca4 | ||
|
|
15f4b08f94 | ||
|
|
9b4b94edc0 | ||
|
|
476099efc1 | ||
|
|
cab4c903d0 | ||
|
|
d9da96c8ad | ||
|
|
d9ea736248 | ||
|
|
b4dc68ba50 | ||
|
|
786f8576e3 | ||
|
|
ec739277a1 | ||
|
|
8376fd198f | ||
|
|
39429d3905 | ||
|
|
4fb84eedfe | ||
|
|
1a64b3c812 | ||
|
|
66c590c89c | ||
|
|
821c266f1d | ||
|
|
4e63287d75 | ||
|
|
7f5ac28c78 | ||
|
|
52cd4a5893 | ||
|
|
04c5af2130 | ||
|
|
52893778f8 | ||
|
|
600e67b17a | ||
|
|
2da49b93bd | ||
|
|
a65df0e598 | ||
|
|
54d4416ef8 | ||
|
|
42a7af1632 | ||
|
|
cfbbf34d6a | ||
|
|
5b35bbdf1b | ||
|
|
0c46d48e40 | ||
|
|
e78ad5f175 | ||
|
|
09c2296a9a | ||
|
|
55a3cf7ecd | ||
|
|
180705e9eb | ||
|
|
f5cf560a3c | ||
|
|
1e11b5dd7c | ||
|
|
f201c75a24 | ||
|
|
41219737ad | ||
|
|
35d1b6665c | ||
|
|
0543201db1 | ||
|
|
8e4da1d397 | ||
|
|
2977bfa721 | ||
|
|
5fa92bf619 | ||
|
|
3e37822415 | ||
|
|
4d65f59824 | ||
|
|
cd5829fc42 | ||
|
|
86b056872d | ||
|
|
b1007b02c0 | ||
|
|
d3126d15cf | ||
|
|
d61ed147ac | ||
|
|
b1f3aa2920 | ||
|
|
8ad3bb1462 | ||
|
|
b91a077d23 | ||
|
|
3df29c1667 | ||
|
|
abf6c8eb4d | ||
|
|
cffd634681 | ||
|
|
e72e8cc71f | ||
|
|
8eaef39b33 | ||
|
|
1588334093 | ||
|
|
6f4fb574ec | ||
|
|
64cc7834a8 | ||
|
|
11e2edcf5f | ||
|
|
f900ddb544 | ||
|
|
4f60a6ea02 | ||
|
|
dc1bc980d0 | ||
|
|
3d3ae02e62 | ||
|
|
a70a110f31 | ||
|
|
05d3869acf | ||
|
|
72489fb458 | ||
|
|
fe8b1db933 | ||
|
|
8fdd90eb40 | ||
|
|
564a356f09 | ||
|
|
3927137203 | ||
|
|
f826ad5c89 | ||
|
|
517ee7f6c3 | ||
|
|
99cc41356c | ||
|
|
e76736cf55 | ||
|
|
2a7bbc7e46 | ||
|
|
bda6449118 | ||
|
|
e6166e4498 | ||
|
|
80a878ade5 | ||
|
|
bbf2fcf17a | ||
|
|
c1d266bd9a | ||
|
|
7a7f3f2f5b | ||
|
|
0371941707 | ||
|
|
6f449e65a4 | ||
|
|
5491f09bab | ||
|
|
6949ec443e | ||
|
|
47ca8f9c12 | ||
|
|
ba303a615b | ||
|
|
350582bc7b | ||
|
|
b9836e714a | ||
|
|
aae30e6db5 | ||
|
|
86e46f17de | ||
|
|
fbc263659b | ||
|
|
8c8a7cbba4 | ||
|
|
f5e3cd0dbf | ||
|
|
24c1a0954b | ||
|
|
f05cf23b89 | ||
|
|
90c883c201 | ||
|
|
2d0b95cd49 | ||
|
|
e2bc7a277e | ||
|
|
adbd3e478b | ||
|
|
7b0804c22f | ||
|
|
47dfe904ab | ||
|
|
7f5b44b423 | ||
|
|
c16ca69070 | ||
|
|
394c628931 | ||
|
|
43695024af | ||
|
|
1678de7f51 | ||
|
|
063436c82b | ||
|
|
59585550a7 | ||
|
|
51e294c501 | ||
|
|
22ffec640d | ||
|
|
7ab3c4c091 | ||
|
|
19934a59b2 | ||
|
|
f3645e3f4b | ||
|
|
d818035d3a | ||
|
|
0cce8cfbaa | ||
|
|
3e132d71f5 | ||
|
|
2b3a4adff8 | ||
|
|
de49d45568 | ||
|
|
de5337b187 | ||
|
|
f0e82e4473 | ||
|
|
5a00c29f8a | ||
|
|
dd5d9aa6bc | ||
|
|
40f03c4c2c | ||
|
|
1aaf8d589f | ||
|
|
1b87c6ade7 | ||
|
|
d52e9c7704 | ||
|
|
9c7425eee4 | ||
|
|
7cd8b4410e | ||
|
|
c63e78714a | ||
|
|
2b34836c61 | ||
|
|
32d1d7b23f | ||
|
|
e7773faa8d | ||
|
|
b7c2a2b709 | ||
|
|
67ef389a69 | ||
|
|
7c1903a0c3 | ||
|
|
c8563cac0a | ||
|
|
42c4a7757d | ||
|
|
8b007b358e | ||
|
|
5cd2cfc203 | ||
|
|
a7ca42cb22 | ||
|
|
f562bcedef | ||
|
|
a8dc5260b7 | ||
|
|
d33d0b01bf | ||
|
|
4a5195c38a | ||
|
|
0864378250 | ||
|
|
855e4aac41 | ||
|
|
5f8a3896dc | ||
|
|
903bfcaf4b | ||
|
|
fcf46a9a42 | ||
|
|
1d1db98a2e | ||
|
|
51c8e01575 | ||
|
|
b87c774102 | ||
|
|
6aa05bdc37 | ||
|
|
4abee1da76 | ||
|
|
2106e8f031 | ||
|
|
4befd355b3 | ||
|
|
a544f403a2 | ||
|
|
8f1afa1766 | ||
|
|
c0789ae1b4 | ||
|
|
9934a167a2 | ||
|
|
798ffad9a9 | ||
|
|
fb3b7f2274 | ||
|
|
23dd62ec54 | ||
|
|
a1affa1dc3 | ||
|
|
23633cf632 | ||
|
|
472bd55757 | ||
|
|
2de4f65474 | ||
|
|
38befc5ded | ||
|
|
5f9d855d3e | ||
|
|
3c5d941945 | ||
|
|
2f54dbd28c | ||
|
|
b2b6c18db3 | ||
|
|
33e7126ba5 | ||
|
|
2ab98aa919 | ||
|
|
9ba875e502 | ||
|
|
2dcdb807f8 | ||
|
|
56fe3c6176 | ||
|
|
321b26f3d4 | ||
|
|
ad37ab272a | ||
|
|
d5feddb0a0 | ||
|
|
88ae26178c | ||
|
|
e06357084e | ||
|
|
2e52c46165 | ||
|
|
a82cf6080e | ||
|
|
78f321b32c | ||
|
|
3113200309 | ||
|
|
4a854b2927 | ||
|
|
a5e61545e4 | ||
|
|
17a259e894 | ||
|
|
f5fb224254 | ||
|
|
fe07d17374 | ||
|
|
8d983d6f2d | ||
|
|
2c028990b4 | ||
|
|
35af86cef2 | ||
|
|
659f47f76a | ||
|
|
b489acb578 | ||
|
|
e34342c1f3 | ||
|
|
1f6952ba81 | ||
|
|
d2f48d07bb | ||
|
|
e9306bead5 | ||
|
|
a3bdff883b | ||
|
|
ddedf42d21 | ||
|
|
b3e684d1fe | ||
|
|
b3a13b17cb | ||
|
|
90b4fce199 | ||
|
|
2d3164a59f | ||
|
|
37ee12b2eb | ||
|
|
d8d4a1d694 | ||
|
|
0b18937cbe | ||
|
|
264091a239 | ||
|
|
d324fd94df | ||
|
|
15352cd86e | ||
|
|
69ca87abad | ||
|
|
e0c8e7c740 | ||
|
|
8a9f96b21c | ||
|
|
bfb05107e3 | ||
|
|
1e699db631 | ||
|
|
f3953f9a15 | ||
|
|
7c7f889b1e | ||
|
|
f437c92b00 | ||
|
|
44dd5c38e2 | ||
|
|
e0132ef4cb | ||
|
|
94cb2db723 | ||
|
|
52cf11338e | ||
|
|
c4cce91dce | ||
|
|
23aa1c6524 | ||
|
|
9de129d5b2 | ||
|
|
9d4cb8e97a | ||
|
|
c1589415f0 | ||
|
|
389cbc3686 | ||
|
|
2508b4000b | ||
|
|
e5164acc9c | ||
|
|
71ee58b6bb | ||
|
|
3512a6ad0b | ||
|
|
b02de599a0 | ||
|
|
38c6e8faf6 | ||
|
|
431ca070a4 | ||
|
|
ed2630dce5 | ||
|
|
5a2c9c9cee | ||
|
|
a7184430f1 | ||
|
|
2e83fee74c | ||
|
|
bbe29582cb | ||
|
|
76470d9608 | ||
|
|
715c4ca4cd | ||
|
|
c097423d77 | ||
|
|
54637fa44d | ||
|
|
c192e88bcd | ||
|
|
19a12b28bc | ||
|
|
d55a7f18b0 | ||
|
|
4008a5fbf9 | ||
|
|
e260f729da | ||
|
|
17cffe2bf9 | ||
|
|
d1b068a68a | ||
|
|
a5053f6ada | ||
|
|
261a3e7e78 | ||
|
|
36e28d4b4b | ||
|
|
cbc562a636 | ||
|
|
51c4e1ea4b | ||
|
|
c8f03c38fe | ||
|
|
4107d4d24d | ||
|
|
f0c79d95f5 | ||
|
|
d13b495217 | ||
|
|
549e1dfb0d | ||
|
|
e260ecef0b | ||
|
|
b16b4d92a7 | ||
|
|
c2584edbdb | ||
|
|
aa00196b6f | ||
|
|
75e3996d36 | ||
|
|
d50f13b90d | ||
|
|
652e9c00c5 | ||
|
|
fdcf749779 | ||
|
|
ed38f47f23 | ||
|
|
3b0585be3b | ||
|
|
ebe1a8080c | ||
|
|
593bb6470b | ||
|
|
6ce45042ef | ||
|
|
f615e84381 | ||
|
|
bfaf1a4ecc | ||
|
|
bc1a30f542 | ||
|
|
28e0d5dd64 | ||
|
|
ffdd12841e | ||
|
|
4b660a89d9 | ||
|
|
48386caec5 | ||
|
|
996360df6b | ||
|
|
fe260a26ed | ||
|
|
457bc4fb63 | ||
|
|
eeb7ce60ae | ||
|
|
e52586db1c | ||
|
|
6cb9642200 | ||
|
|
7ebd46ee53 | ||
|
|
d575dfe440 | ||
|
|
074c1880ff | ||
|
|
b53c1011fc | ||
|
|
11f35d31d9 | ||
|
|
36d07a5cea | ||
|
|
12910a5a29 | ||
|
|
eb93c134a7 | ||
|
|
493ad74331 | ||
|
|
a563816d3a | ||
|
|
43526902ae | ||
|
|
b6ec0f9b92 | ||
|
|
4e7f1a3a9d | ||
|
|
50e879ef56 | ||
|
|
06468b9049 | ||
|
|
2bdbceca91 | ||
|
|
d34d85efdd | ||
|
|
7e3278ae8f | ||
|
|
bca7c09e6c | ||
|
|
2e163858fc | ||
|
|
0ad2a4c72f | ||
|
|
b69ca133af | ||
|
|
d4f0f090c0 | ||
|
|
e56f421490 | ||
|
|
c9b93bf65a | ||
|
|
9b8ce15725 | ||
|
|
014e7daa36 | ||
|
|
306e3b86f1 | ||
|
|
ce7cf5f46b | ||
|
|
3c3b5e0dbf | ||
|
|
0fc136fcc7 | ||
|
|
80328439be | ||
|
|
3c649de483 | ||
|
|
184ca578a0 | ||
|
|
3643acadac | ||
|
|
1c78aa19ff | ||
|
|
a64fec0722 | ||
|
|
962811198f | ||
|
|
378c3b1641 | ||
|
|
34c937510d | ||
|
|
e924e9cfb2 | ||
|
|
8f0fa65379 | ||
|
|
00268c1b82 | ||
|
|
7ab37c0ffc | ||
|
|
4cae37c340 | ||
|
|
63f8ad01b2 | ||
|
|
1a6159aca5 | ||
|
|
60e9c014a2 | ||
|
|
8f3295456d | ||
|
|
78df2efac2 | ||
|
|
546357eaeb | ||
|
|
50552f3fd5 | ||
|
|
7d62ac4b34 | ||
|
|
beb14c3fa7 | ||
|
|
a15d3d8dcc | ||
|
|
9c7755c862 | ||
|
|
866553e76f | ||
|
|
f8f2be527f | ||
|
|
88880e1f89 | ||
|
|
3cce4419c2 | ||
|
|
bc59859a59 | ||
|
|
ecf06d3a49 | ||
|
|
d48af1520d | ||
|
|
aa9797fa3c | ||
|
|
44a82780b9 | ||
|
|
c76681596e | ||
|
|
3ce8520c5e | ||
|
|
01f5823ee4 | ||
|
|
c7ec3c65f4 | ||
|
|
d01b8d03db | ||
|
|
41ff900c99 | ||
|
|
9ca07f4298 | ||
|
|
0e93522190 | ||
|
|
ebd1d49150 | ||
|
|
057462c4e6 | ||
|
|
b5e36cb96b | ||
|
|
f58ca71942 | ||
|
|
262a39dfd0 | ||
|
|
d531d56dbb | ||
|
|
8b78a832fa | ||
|
|
8c19b52bda | ||
|
|
a7237281ea | ||
|
|
0b6ee2252c | ||
|
|
a9ffbb0803 | ||
|
|
224457fb0f | ||
|
|
cacbf14d8e | ||
|
|
b00dc7153a | ||
|
|
9dbad2f74d | ||
|
|
97617cfc76 | ||
|
|
735cac19f2 | ||
|
|
3755951091 | ||
|
|
60af6fb0a2 | ||
|
|
333cf73ceb | ||
|
|
bc653452a7 | ||
|
|
ca92b9a5f0 | ||
|
|
afe102c0fe | ||
|
|
fa7fa300e3 | ||
|
|
3c2b019578 | ||
|
|
87003ba5b1 | ||
|
|
bf7d3d2208 | ||
|
|
4e553333d9 | ||
|
|
954df8f3d7 | ||
|
|
078573dc2c | ||
|
|
c4655582e6 | ||
|
|
360f97c31d | ||
|
|
f20300cc8b | ||
|
|
f687bd63b8 | ||
|
|
b68340f6d9 | ||
|
|
c5eb266a80 | ||
|
|
04f3cea84a | ||
|
|
c1fe5092c3 | ||
|
|
5257248ed9 | ||
|
|
780010a268 | ||
|
|
8571d54f61 | ||
|
|
13fed1e445 | ||
|
|
2179ff624c | ||
|
|
8b3434061e | ||
|
|
68a6a348b5 | ||
|
|
d8659175cd | ||
|
|
1431ddad9c | ||
|
|
5f860775c8 | ||
|
|
65f5ed533f | ||
|
|
c4276aad11 | ||
|
|
d4ae0dedf2 | ||
|
|
312a15d24e | ||
|
|
bc1024812a | ||
|
|
451be927a8 | ||
|
|
4839e5d913 | ||
|
|
874d697f4c | ||
|
|
f80cbe8c33 | ||
|
|
154a7af5ee | ||
|
|
cea69ab9d0 | ||
|
|
6b3f81e647 | ||
|
|
fbee662499 | ||
|
|
eedf87f891 | ||
|
|
89cb3a410a | ||
|
|
ae1ec1b418 | ||
|
|
c357c91b7d | ||
|
|
b3f073c48c | ||
|
|
cd8ffd8725 | ||
|
|
bbe4a85be1 | ||
|
|
7e6f58c0a9 | ||
|
|
275654210d | ||
|
|
f649252de9 | ||
|
|
d3ce80e544 | ||
|
|
ea956b4f6c | ||
|
|
ada4c61860 | ||
|
|
9bcaa94756 | ||
|
|
49a81e190e | ||
|
|
5303eca8fa | ||
|
|
1b37183e74 | ||
|
|
09f17bf72d | ||
|
|
449ffc7b05 | ||
|
|
bea9cf6725 | ||
|
|
a0c7ead88f | ||
|
|
3eb97ffa25 | ||
|
|
48d651f492 | ||
|
|
0d272a6964 | ||
|
|
578c4098e6 | ||
|
|
c34cb6adcf | ||
|
|
cb5d05fd34 | ||
|
|
5899d9b442 | ||
|
|
40026b0762 | ||
|
|
83b4f8366a | ||
|
|
8e50c4e4bb | ||
|
|
2b129732b0 | ||
|
|
8cf86745c2 | ||
|
|
5ee39f1a1d | ||
|
|
8c998ebbed | ||
|
|
e2eb9b24b7 | ||
|
|
374e3502fe | ||
|
|
1ad6e72ade | ||
|
|
d7eaafe9c1 | ||
|
|
2400150734 | ||
|
|
8ad2a270f4 | ||
|
|
73a006403f | ||
|
|
a3513577f0 | ||
|
|
29ad12df51 | ||
|
|
e0dd25f92b | ||
|
|
81c155b465 | ||
|
|
ae11cc6731 | ||
|
|
b0b0c853c7 | ||
|
|
8701c4f50c | ||
|
|
627d5adc63 | ||
|
|
7a5a31888a | ||
|
|
3d64743851 | ||
|
|
16d704877d | ||
|
|
3e320285a1 | ||
|
|
3215d89e97 | ||
|
|
b7983d4fe2 | ||
|
|
6120f4c507 | ||
|
|
ac24748b47 | ||
|
|
4c449886f6 | ||
|
|
cd3475a8cb | ||
|
|
03c5c5fbe7 | ||
|
|
9d3faa4753 | ||
|
|
20399b50d6 | ||
|
|
93c1312901 | ||
|
|
4bde7fc926 | ||
|
|
68086fdde4 | ||
|
|
005ad96068 | ||
|
|
6c1beb94dc | ||
|
|
fa0ec772d5 | ||
|
|
661e73d9a6 | ||
|
|
db85b2ddc7 | ||
|
|
4f732b1989 | ||
|
|
78b8276111 | ||
|
|
6ef6b6af40 | ||
|
|
f45bbeb497 | ||
|
|
4eb71369ed | ||
|
|
bc11c3a1d7 | ||
|
|
dd8ac54678 | ||
|
|
15d7886699 | ||
|
|
68c7b86df1 | ||
|
|
6c8454e4e2 | ||
|
|
a249779692 | ||
|
|
876b6416ab | ||
|
|
1e5d79dce1 | ||
|
|
bd8eec0a1e | ||
|
|
e7075c4366 | ||
|
|
532834cbc2 | ||
|
|
d5857e6d48 | ||
|
|
b004ea2d7f | ||
|
|
205ca4f8a7 | ||
|
|
4a76f5c764 | ||
|
|
a32e8441d0 | ||
|
|
4d6089c042 | ||
|
|
7929929979 | ||
|
|
9ba50046cf | ||
|
|
aa3bdb1911 | ||
|
|
5ce8c9ae77 | ||
|
|
9d8d6b1d18 | ||
|
|
52b8978a47 | ||
|
|
442fd05339 | ||
|
|
4c952f0af4 | ||
|
|
cf90b03ce4 | ||
|
|
d4de2a7aa4 | ||
|
|
e37b173f13 | ||
|
|
b5d88e683f | ||
|
|
23dd4773d4 | ||
|
|
b7af7c9c43 | ||
|
|
9d3955daf2 | ||
|
|
063083a203 | ||
|
|
46886164dd | ||
|
|
ea04c0775c | ||
|
|
d29aa4764e | ||
|
|
203d1d8371 | ||
|
|
2eb4099563 | ||
|
|
7cd66377ef | ||
|
|
1f9d50fa3f | ||
|
|
be29e5ab62 | ||
|
|
24d8818933 | ||
|
|
803380c203 | ||
|
|
1569059b2b | ||
|
|
8fb6bd930b | ||
|
|
c7cc4b7ac2 | ||
|
|
201d0e940b | ||
|
|
3fcd56034a | ||
|
|
51d222469c | ||
|
|
742d1e9424 | ||
|
|
a04f401227 | ||
|
|
62699dc3fd | ||
|
|
01645a7eae | ||
|
|
b17939f74e | ||
|
|
aa60387ecc | ||
|
|
4b801e21e3 | ||
|
|
c198ca0285 | ||
|
|
a312fc8eb9 | ||
|
|
10b62fb0e8 | ||
|
|
2c12325d63 | ||
|
|
2d8b9935a1 | ||
|
|
647d948562 | ||
|
|
73d1626ddc | ||
|
|
b7445913cc | ||
|
|
6f7ca25c9b | ||
|
|
4487c42de2 | ||
|
|
bfbad87685 | ||
|
|
65f0ca65f1 | ||
|
|
d0720d5638 | ||
|
|
5d7fd71373 | ||
|
|
efe3e72ed0 | ||
|
|
85f56aef97 | ||
|
|
5ac0fdd924 | ||
|
|
b33c7a4597 | ||
|
|
788b9bfdc7 | ||
|
|
41cc3b216d | ||
|
|
dcb7878842 | ||
|
|
b5e83471bc | ||
|
|
bfdc05ec71 | ||
|
|
1d7ecbe9a0 | ||
|
|
9e30a829d5 | ||
|
|
698dfbf953 | ||
|
|
83fbb1ec11 | ||
|
|
19d0f2b57c | ||
|
|
05d40b3142 | ||
|
|
d94fc9ce62 | ||
|
|
ba9550f473 | ||
|
|
28e1e7fd07 | ||
|
|
904e38837e | ||
|
|
697c5de267 | ||
|
|
bfa9c7bcfb | ||
|
|
2f81a05ce5 | ||
|
|
7b994976e3 | ||
|
|
662d1021e6 | ||
|
|
2db34bd266 | ||
|
|
f3491d93a0 | ||
|
|
337abee8f8 | ||
|
|
34573cf6a5 | ||
|
|
491ef790c2 | ||
|
|
2e9ae681c5 | ||
|
|
a02f7ab0cb | ||
|
|
e0b190c111 | ||
|
|
56fa3ac1b0 | ||
|
|
5bcbeca8e7 | ||
|
|
adc1729212 | ||
|
|
fd7ae0cdf4 | ||
|
|
fdef9679b6 | ||
|
|
dcecda51d8 | ||
|
|
687603a144 | ||
|
|
acb04c003e | ||
|
|
86b10089aa | ||
|
|
7b030379ec | ||
|
|
5e8c230d1f | ||
|
|
8c2890cf1d | ||
|
|
8e9da71c32 | ||
|
|
13deb51d3e | ||
|
|
2c9ffffdca | ||
|
|
13a9bce647 | ||
|
|
dbb3cfe05e | ||
|
|
674baa8143 | ||
|
|
db482f3e1c | ||
|
|
6a5a0222d7 | ||
|
|
4512267bf1 | ||
|
|
54555a6fab | ||
|
|
ae2353caf8 | ||
|
|
4eae19ed75 | ||
|
|
e6ec837203 | ||
|
|
b37f7c4b7b | ||
|
|
4b8340327c | ||
|
|
92e4442d4a | ||
|
|
2517f9adf2 | ||
|
|
9bad64ff72 | ||
|
|
d1b147e2bb | ||
|
|
1b7730c76a | ||
|
|
28801f7470 | ||
|
|
f4c43c11c9 | ||
|
|
fde4a8e1b5 | ||
|
|
abb193533c | ||
|
|
775fac97d3 | ||
|
|
3963c01760 | ||
|
|
1e01a63685 | ||
|
|
235ca704b1 | ||
|
|
5685ba7918 | ||
|
|
f0d1c085b9 | ||
|
|
45490081c7 | ||
|
|
a3503d13e5 | ||
|
|
3ed4d07d3a | ||
|
|
06e0023c2c | ||
|
|
b22e0a3ecb | ||
|
|
0802006ea7 | ||
|
|
29a21d1627 | ||
|
|
a0074aa07e | ||
|
|
4e8859d851 | ||
|
|
562ae607d2 | ||
|
|
2426656b07 | ||
|
|
898d3c655d | ||
|
|
855e554051 | ||
|
|
4aac2c543b | ||
|
|
78024e7be6 | ||
|
|
18f0009a41 | ||
|
|
1cf64de2bf | ||
|
|
b1d6be8ec6 | ||
|
|
137a25906d | ||
|
|
2b298cbb32 | ||
|
|
5361b5de37 | ||
|
|
f1fee292e4 | ||
|
|
9c9b1f5bc8 | ||
|
|
7e64d04db1 | ||
|
|
2355f677fb | ||
|
|
e42bb91382 | ||
|
|
28aa06675f | ||
|
|
6e86d0bb03 | ||
|
|
4342431e39 | ||
|
|
7452298131 | ||
|
|
e4be66b1ac | ||
|
|
f829547a13 | ||
|
|
ea64fe3b51 | ||
|
|
f293d0b951 | ||
|
|
1967fd2429 | ||
|
|
0fec0340c2 | ||
|
|
bed67320b1 | ||
|
|
8544e24770 | ||
|
|
727b7b7e8c | ||
|
|
bd39789144 | ||
|
|
eb10fc962b | ||
|
|
3318c41356 | ||
|
|
dc2c0b1d51 | ||
|
|
1de8da23f5 | ||
|
|
340fa684af | ||
|
|
34f06fa400 | ||
|
|
5b5337e4af | ||
|
|
d01de820d7 | ||
|
|
5aeea69c01 | ||
|
|
8f6c0b24d8 | ||
|
|
b8eddf1bdc | ||
|
|
1469dc216a | ||
|
|
3306ae2f42 | ||
|
|
a89db8e69c | ||
|
|
8c6f06eb34 | ||
|
|
fe3ed2b871 | ||
|
|
71cb3fc201 | ||
|
|
f9554c7d27 | ||
|
|
384f2fc38b | ||
|
|
cd50107ae1 | ||
|
|
94466645ee | ||
|
|
1acb442f60 | ||
|
|
cff0a562fd | ||
|
|
299db29482 | ||
|
|
cc5045d8ca | ||
|
|
940c32c5dd | ||
|
|
14ad41a065 | ||
|
|
7eaf1f294d | ||
|
|
eb7692743f | ||
|
|
7aa470c8d0 | ||
|
|
4237ca85f5 | ||
|
|
99cdfa1e71 | ||
|
|
39f92f3cfd | ||
|
|
9cc29191d4 | ||
|
|
de33332491 | ||
|
|
f9ddafdc21 | ||
|
|
fdefd5eff9 | ||
|
|
e9e5dbb628 | ||
|
|
0e57141bb5 | ||
|
|
842a3664f0 | ||
|
|
6cf89391b6 | ||
|
|
ca5fd21509 | ||
|
|
d14471e44d | ||
|
|
5197fd72c4 | ||
|
|
c17ac96509 | ||
|
|
4acb30c464 | ||
|
|
d61f611adc | ||
|
|
b19719801b | ||
|
|
83a2bc8ec4 | ||
|
|
aab6f07d14 | ||
|
|
db8748cefd | ||
|
|
23b3f55bfb | ||
|
|
e6573a9bed | ||
|
|
d6a19426c7 | ||
|
|
9426d45cde | ||
|
|
48d0cd3564 | ||
|
|
89f61acf2c | ||
|
|
985d87b5eb | ||
|
|
0be2dfefdb | ||
|
|
89f30d2df7 | ||
|
|
0b648ce87b | ||
|
|
0c897ecefd | ||
|
|
f2a6d937a6 | ||
|
|
76f4498303 | ||
|
|
5451f79f55 | ||
|
|
4e69ed9c98 | ||
|
|
75f55c758c | ||
|
|
f9d1b67e86 | ||
|
|
04ecf25522 | ||
|
|
52b51b70eb | ||
|
|
3fdc1390fe | ||
|
|
f309bd12c7 | ||
|
|
d388f94c7f | ||
|
|
0f878a226d | ||
|
|
a38f899d7e | ||
|
|
6c09d7b60c | ||
|
|
8cb8f65010 | ||
|
|
49437d9a07 | ||
|
|
69962eae7c | ||
|
|
c440f39874 | ||
|
|
40090be220 | ||
|
|
281a92bf74 | ||
|
|
bbacb7fff0 | ||
|
|
cccdc3eea0 | ||
|
|
aa9c970f97 | ||
|
|
4f81adb3c9 | ||
|
|
b8f75d74ae | ||
|
|
befffd65bf | ||
|
|
610cd1a531 | ||
|
|
08d06030dc | ||
|
|
083687d0fd | ||
|
|
f874581701 | ||
|
|
e66d76ac5a | ||
|
|
5d7ad8ae75 | ||
|
|
99ab428344 | ||
|
|
eaef92b02f | ||
|
|
4982eabe07 | ||
|
|
c66ce519f4 | ||
|
|
e74208778d | ||
|
|
67a0635e75 | ||
|
|
def0511361 | ||
|
|
29b8138482 | ||
|
|
c6ee487cfc | ||
|
|
1a6df48bd0 | ||
|
|
6cdf300933 | ||
|
|
5365974d6c | ||
|
|
f1acefd241 | ||
|
|
079fec6c5a | ||
|
|
14258c93de | ||
|
|
03315d77f1 | ||
|
|
34843e7d6c | ||
|
|
4efa67c4ec | ||
|
|
2419c1c540 | ||
|
|
34055f40ac | ||
|
|
276d32973f | ||
|
|
f3c51a049d | ||
|
|
21573cd4f0 | ||
|
|
f25325f4bb | ||
|
|
5b12edfb34 | ||
|
|
4697026132 | ||
|
|
6c39b8f4f0 | ||
|
|
4a9af35527 | ||
|
|
881056af0b | ||
|
|
e5df490d5e | ||
|
|
7c0d6057c5 | ||
|
|
3e5a54a791 | ||
|
|
dbfd6e0d12 | ||
|
|
f607a0a0a6 | ||
|
|
b15ada28ed | ||
|
|
6610f9bdbc | ||
|
|
5f87626377 | ||
|
|
54834a1761 | ||
|
|
adf7081163 | ||
|
|
a50b7c55d3 | ||
|
|
f4f171e04d | ||
|
|
d5ea20a6eb | ||
|
|
5584f2ae46 | ||
|
|
b79d8b1ff0 | ||
|
|
1c33c0027f | ||
|
|
aef0a98840 | ||
|
|
9d23a04c0e | ||
|
|
453bab220b | ||
|
|
448f8c4240 | ||
|
|
5a414c6ad1 | ||
|
|
65a942f01f | ||
|
|
6df32fed62 | ||
|
|
1199b48cd7 | ||
|
|
c493f56e1b | ||
|
|
2e65b8ce5f | ||
|
|
42a6d954d3 | ||
|
|
8f73b4c3ae | ||
|
|
adcd06fccb | ||
|
|
c40380f72a | ||
|
|
8e44e884a2 | ||
|
|
e2368be912 | ||
|
|
7986fd4db7 | ||
|
|
6107f4a02a | ||
|
|
2ce63814e9 | ||
|
|
8ba508f8f7 | ||
|
|
2100490424 | ||
|
|
7e7639e39a | ||
|
|
3555d0ecd5 | ||
|
|
ecb9a01cfa | ||
|
|
ca352ebfba | ||
|
|
29c73eb67b | ||
|
|
2a598ff24d | ||
|
|
f6d5837e5e | ||
|
|
dac8cee72c | ||
|
|
e01a2f8324 | ||
|
|
a092ccb82b | ||
|
|
e894d07b92 | ||
|
|
befef6eb00 | ||
|
|
162224979d | ||
|
|
a90f6e2dda | ||
|
|
e449bfd741 | ||
|
|
8ecc1eb99d | ||
|
|
1fb910411e | ||
|
|
3141b86d01 | ||
|
|
f8ff64c87e | ||
|
|
c71b834aad | ||
|
|
a78e7d0287 | ||
|
|
09cf0fe6b9 | ||
|
|
13713bc147 | ||
|
|
9c17cf4edf | ||
|
|
938b25b986 | ||
|
|
040b76f1e6 | ||
|
|
66226207ce | ||
|
|
999b4168c1 | ||
|
|
9bfc452487 | ||
|
|
df675ed9fb | ||
|
|
4a13ae4c95 | ||
|
|
5287c71d68 | ||
|
|
827f1a3d30 | ||
|
|
f6d95e19c4 | ||
|
|
3eb93f161f | ||
|
|
801eff0c52 | ||
|
|
c1993e76c2 | ||
|
|
c23f56b9cb | ||
|
|
44e17e2aa9 | ||
|
|
84758667c1 | ||
|
|
8c71113cd6 | ||
|
|
79ba99811c | ||
|
|
55a664d6fd | ||
|
|
b4affd607d | ||
|
|
c7007c98d7 | ||
|
|
fa684a97da | ||
|
|
cad03afc54 | ||
|
|
fe6d782751 | ||
|
|
dfe517cfbe | ||
|
|
46ab95f24c | ||
|
|
9a57ea4c4a | ||
|
|
5fc98ffa69 | ||
|
|
814eb397e1 | ||
|
|
77f030956c | ||
|
|
ab7ad3451d | ||
|
|
1107f82824 | ||
|
|
2bc2378033 | ||
|
|
676e214f34 | ||
|
|
7df1ccbf91 | ||
|
|
82d3ee5454 | ||
|
|
fcb6fb00e0 | ||
|
|
4e09e6ca10 | ||
|
|
af6dd44048 | ||
|
|
d30ec9fd1e | ||
|
|
16ee54ad23 | ||
|
|
627409ec38 | ||
|
|
4ead572462 | ||
|
|
42783a54db | ||
|
|
84763527c5 | ||
|
|
1744c1c2ba | ||
|
|
7ef5fbdbe6 | ||
|
|
b1482c52b7 | ||
|
|
7b0d61b96d | ||
|
|
951b974c4d | ||
|
|
975b3c3428 | ||
|
|
f0420012e6 | ||
|
|
30e5413e2b | ||
|
|
5077a1bb83 | ||
|
|
a8ed16de33 | ||
|
|
ee0a4914d5 | ||
|
|
8b70a0d0b7 | ||
|
|
8e7c6b60fb | ||
|
|
fbb0bb63e7 | ||
|
|
46dc1b6e99 | ||
|
|
82b34e06f2 | ||
|
|
bc178df8f0 | ||
|
|
d5a3de5a97 | ||
|
|
b8774d7aac | ||
|
|
891246562f | ||
|
|
e53a955115 | ||
|
|
1ec6812246 | ||
|
|
e896691b0f | ||
|
|
fbe92a13c0 | ||
|
|
94a434e9e7 | ||
|
|
e829c626da | ||
|
|
837adeea7f | ||
|
|
65d6350d36 | ||
|
|
ba99186951 | ||
|
|
b3975f5098 | ||
|
|
b90f909289 | ||
|
|
d098e4def6 | ||
|
|
835b0d9f62 | ||
|
|
9fea2798e3 | ||
|
|
394cae5d21 | ||
|
|
7996aae5e9 | ||
|
|
9788b9d7a9 | ||
|
|
6f5e1c3d73 | ||
|
|
d4421b12ba | ||
|
|
099b03f038 | ||
|
|
f84d2eeec9 | ||
|
|
f02531802c | ||
|
|
375cb5c31d | ||
|
|
8f2ba4ec3c | ||
|
|
9935d1183a | ||
|
|
aff8e77bec | ||
|
|
c9fd743c65 | ||
|
|
7a4fa925fc | ||
|
|
ff442c1e28 | ||
|
|
5cedaa972a | ||
|
|
2c8f647e0c | ||
|
|
3be5edae0e | ||
|
|
1078f24d5a | ||
|
|
c02cc5321a | ||
|
|
e60a7ff1d0 | ||
|
|
91de7311d7 | ||
|
|
e357c9fc0c | ||
|
|
ec4daa5936 | ||
|
|
2743fb9771 | ||
|
|
88c4802bdc | ||
|
|
a47e422715 | ||
|
|
3a9ab631e5 | ||
|
|
9ca5118a68 | ||
|
|
d6053080f8 | ||
|
|
b1f8076da0 | ||
|
|
abc760c8e4 | ||
|
|
0331a34d58 | ||
|
|
98af0ba143 | ||
|
|
157810ea3d | ||
|
|
448e4251f8 | ||
|
|
81ce20d616 | ||
|
|
3e9ab41e76 | ||
|
|
a3c8fbc6b6 | ||
|
|
e9dc6880af | ||
|
|
25fb2c4fb6 | ||
|
|
97d28ae4d7 | ||
|
|
b5bad15dae | ||
|
|
3098ef4a6e | ||
|
|
e354b1210e | ||
|
|
895b6ff719 | ||
|
|
0a22655ff3 | ||
|
|
8def378b5e | ||
|
|
7ab8b44b6c | ||
|
|
335fe09d70 | ||
|
|
523a7ed7d3 | ||
|
|
f69e8e3606 | ||
|
|
3516797b49 | ||
|
|
1683e94f0c | ||
|
|
1d249195a4 | ||
|
|
2f7ee08288 | ||
|
|
e0772fb301 | ||
|
|
78bdbce2fd | ||
|
|
5a5fed28fa | ||
|
|
5818b6efb8 | ||
|
|
53a66492e8 | ||
|
|
b17ddc26c0 | ||
|
|
b7e19d2fe3 | ||
|
|
d8130a99b4 | ||
|
|
8c654aeebe | ||
|
|
bad318d451 | ||
|
|
11d2997e44 | ||
|
|
2d75d2e76e | ||
|
|
6074f58641 | ||
|
|
48de09c279 | ||
|
|
032c2cb462 | ||
|
|
2008367883 | ||
|
|
165d88cfd8 | ||
|
|
0c0e1fbbeb | ||
|
|
3559e20dab | ||
|
|
e400f6eab9 | ||
|
|
cffffe0c2e | ||
|
|
70fcdb495a | ||
|
|
c1b2049df9 | ||
|
|
f6cabc78c0 | ||
|
|
b8526452b5 | ||
|
|
a1cefb3e17 | ||
|
|
def0f38f3d | ||
|
|
58a8b00086 | ||
|
|
50a27398b0 | ||
|
|
eab7cba1f3 | ||
|
|
83774ba6ae | ||
|
|
ab700b4ea3 | ||
|
|
bf7936d494 | ||
|
|
14f627329d | ||
|
|
829c996611 | ||
|
|
dff2e8ecb4 | ||
|
|
7c79b1c7c5 | ||
|
|
a390fac356 | ||
|
|
9a43e67347 | ||
|
|
b0d08c572a | ||
|
|
ee4eb0aa6f | ||
|
|
07e27cac02 | ||
|
|
cdc905cc16 | ||
|
|
88b0c82a0d | ||
|
|
01d3349587 | ||
|
|
cf7f096db7 | ||
|
|
21ed352ac5 | ||
|
|
f8a4f79277 | ||
|
|
16d385ac6a | ||
|
|
3dc1945b44 | ||
|
|
3c7db9e986 | ||
|
|
44e1f095d1 | ||
|
|
90c39b8371 | ||
|
|
17b7944ac2 | ||
|
|
bbf486f890 | ||
|
|
20faa956a8 | ||
|
|
74a4e04185 | ||
|
|
b102455b57 | ||
|
|
c2235a0baa | ||
|
|
c36d2b02a3 | ||
|
|
4eb8d86346 | ||
|
|
1b33fbf98b | ||
|
|
3f74391b87 | ||
|
|
93c954dae1 | ||
|
|
f736563a7a | ||
|
|
0350c4f0f6 | ||
|
|
0c0caf0272 | ||
|
|
9abd966a80 | ||
|
|
a1dbd7156c | ||
|
|
b74e5b870c | ||
|
|
bcb021296f | ||
|
|
dcf907f36d | ||
|
|
972b11e39e | ||
|
|
10fffe842b | ||
|
|
963cf98df1 | ||
|
|
0f64ddf2fb | ||
|
|
3fa82818b9 | ||
|
|
c48ba4464c | ||
|
|
2d1118a26f | ||
|
|
53560b8e0b | ||
|
|
3f647cdf32 | ||
|
|
9a0dc6d522 | ||
|
|
c819525e81 | ||
|
|
4024ad5eb2 | ||
|
|
2c0df9552f | ||
|
|
9359586fde | ||
|
|
68069c70e1 | ||
|
|
6a00ceeb66 | ||
|
|
8143f55488 | ||
|
|
03e03fb7a1 | ||
|
|
b13b8c1882 | ||
|
|
02a2afb64f | ||
|
|
ae8e907d72 | ||
|
|
f042834068 | ||
|
|
63130374b9 | ||
|
|
ac01d56747 | ||
|
|
6f751afae4 | ||
|
|
8fd85fb6e6 | ||
|
|
1dbfe1e856 | ||
|
|
d3fd4c0381 | ||
|
|
0e20e05795 | ||
|
|
3bb0dc03af | ||
|
|
4257485ff2 | ||
|
|
f69b7a58f2 | ||
|
|
fd4fe42013 | ||
|
|
930820b738 | ||
|
|
06cc081ca2 | ||
|
|
ee9bf16d1a | ||
|
|
f08e65fd04 | ||
|
|
877de45d6e | ||
|
|
5a4813d336 | ||
|
|
6dc818deb1 | ||
|
|
4b2bf06873 | ||
|
|
839af3e90e | ||
|
|
c059cdd0f2 | ||
|
|
0ba837e163 | ||
|
|
1ddcf370a7 | ||
|
|
e0559e4fda | ||
|
|
eeefbfd38d | ||
|
|
60ba4943ec | ||
|
|
ba4ac17425 | ||
|
|
3965d3ba83 | ||
|
|
3435f24770 | ||
|
|
31672ff60e | ||
|
|
6e619f8927 | ||
|
|
2ccdb165e3 | ||
|
|
db8eab04e3 | ||
|
|
4e2e8954dc | ||
|
|
a25fe81b9e | ||
|
|
bce3ac2c73 | ||
|
|
52b70fbbfa | ||
|
|
08b540dd78 | ||
|
|
22e91979bb | ||
|
|
e3730ecfc3 | ||
|
|
9cfc9b3ee2 | ||
|
|
c0ff3805c8 | ||
|
|
49ebd19ab1 | ||
|
|
79bcc98e9b | ||
|
|
a58980fe82 | ||
|
|
fe67a86a5f | ||
|
|
4d85bb13d1 | ||
|
|
0501c06745 | ||
|
|
abb2e6ea9b | ||
|
|
a99a30d720 | ||
|
|
0670c8f60f | ||
|
|
dfdcb92f3d | ||
|
|
bc9b5706e9 | ||
|
|
64c37a20d1 | ||
|
|
6d2d4f72ac | ||
|
|
4c151970e6 | ||
|
|
e65e815aae | ||
|
|
db3fb23de4 | ||
|
|
5c9adc4052 | ||
|
|
b8c8c29ee4 | ||
|
|
47c0c71e19 | ||
|
|
7d26a86071 | ||
|
|
556d880951 | ||
|
|
4ee50ed6de | ||
|
|
b1b5a9d8fa | ||
|
|
62d8848bee | ||
|
|
c63b16cf75 | ||
|
|
d32a6f15bf | ||
|
|
918abadb6c | ||
|
|
7f5adb135d | ||
|
|
b1ce301520 | ||
|
|
cd93201e46 | ||
|
|
c9aaf5fb24 | ||
|
|
fdf1e32962 | ||
|
|
36d336618e | ||
|
|
013f27e3e6 | ||
|
|
1b3f8a4c18 | ||
|
|
dd8ef51fa1 | ||
|
|
11e8d26606 | ||
|
|
1e954bc8ef | ||
|
|
720eb0e91c | ||
|
|
106763ef9a | ||
|
|
10019a9d96 | ||
|
|
4515bcf289 | ||
|
|
aa8728a2ab | ||
|
|
f2d3b3661b | ||
|
|
24b598b1be | ||
|
|
0d98ee8916 | ||
|
|
3eca5ad9a1 | ||
|
|
ed2465fd30 | ||
|
|
6d21e61889 | ||
|
|
983312d14d | ||
|
|
2e1271fe36 | ||
|
|
15e53c9839 | ||
|
|
115d48497e | ||
|
|
a31948f3b7 | ||
|
|
a12106eb52 | ||
|
|
dd9f42172f | ||
|
|
3d8e149668 | ||
|
|
f557647525 | ||
|
|
1efaf2cde0 | ||
|
|
202aea4dda | ||
|
|
eaefa1ac5d | ||
|
|
fd49174b1a | ||
|
|
342605bb44 | ||
|
|
a9851f5e95 | ||
|
|
848b39b5a0 | ||
|
|
de372ce095 | ||
|
|
8bbae4b10b | ||
|
|
cff2eda198 | ||
|
|
7a75b47da6 | ||
|
|
79430340e5 | ||
|
|
4494c25df7 | ||
|
|
763d659ee2 | ||
|
|
54086f86d2 | ||
|
|
9195a23c95 | ||
|
|
739ba0fbcc | ||
|
|
93ac41e917 | ||
|
|
1928af2a42 | ||
|
|
45e6585e77 | ||
|
|
8d6fbe1a89 | ||
|
|
375b420c35 | ||
|
|
887b48bd1d | ||
|
|
0794a2e526 | ||
|
|
a859e44630 | ||
|
|
1c1a248277 | ||
|
|
e0e2165c8e | ||
|
|
957f8315e3 | ||
|
|
d279ed7dd6 | ||
|
|
827480b9d6 | ||
|
|
1a0af097a6 | ||
|
|
d408fc2864 | ||
|
|
bba03eef2f | ||
|
|
352f7d7f2b | ||
|
|
0f07768d6b | ||
|
|
a6a2be6e37 | ||
|
|
e840cc8b91 | ||
|
|
ff17105386 | ||
|
|
d82f7b9205 | ||
|
|
01b09aab43 | ||
|
|
f0153d801e | ||
|
|
319b2d8f32 | ||
|
|
419675cd2b | ||
|
|
9dd273626a | ||
|
|
2997acf9dc | ||
|
|
1ee9677b8a | ||
|
|
9c14c897f5 | ||
|
|
dc3e37956b | ||
|
|
eb283dcbc6 | ||
|
|
fec2b39df3 | ||
|
|
1e1b8cc2d5 | ||
|
|
8a902d7e58 | ||
|
|
1a0d994305 | ||
|
|
597986b711 | ||
|
|
ba0a843482 | ||
|
|
0ad0f9e094 | ||
|
|
f93a548fe2 | ||
|
|
84b0920fe0 | ||
|
|
a3d7f70d45 | ||
|
|
99b7ce7bf5 | ||
|
|
819e3b9661 | ||
|
|
cac468586a | ||
|
|
afc8c05f7f | ||
|
|
886e528490 | ||
|
|
06691a0794 | ||
|
|
c61da238e1 | ||
|
|
e07419b4ba | ||
|
|
cecc0e9dc8 | ||
|
|
4d4d7c1fb3 | ||
|
|
e50e7ee119 | ||
|
|
0d15d01b45 | ||
|
|
7972728e7c | ||
|
|
d4d430ee80 | ||
|
|
b2155fde1a | ||
|
|
0033b9eeb5 | ||
|
|
3d25b06fbc | ||
|
|
32752bc3dd | ||
|
|
f1fd43b61c | ||
|
|
38fda754a1 | ||
|
|
dc4e40a2f6 | ||
|
|
9abda62c5b | ||
|
|
cd5c37fe1c | ||
|
|
bce8cac1f4 | ||
|
|
4171d0c301 | ||
|
|
2edd956853 | ||
|
|
d77b03d6c9 | ||
|
|
4d5a88661f | ||
|
|
0b9b1ccd0b | ||
|
|
d5ef8e037d | ||
|
|
fd09a32d5e | ||
|
|
afc5de69d4 | ||
|
|
2adec6ef66 | ||
|
|
5829d87313 | ||
|
|
4422423315 | ||
|
|
6c88b6c660 | ||
|
|
ccca1401ae | ||
|
|
39270f9647 | ||
|
|
3b6a147653 | ||
|
|
fd69075a8b | ||
|
|
dfed228991 | ||
|
|
5403c6122c | ||
|
|
ec76533493 | ||
|
|
fbdc356b7c | ||
|
|
709e1afd31 | ||
|
|
217bbd0dcb | ||
|
|
e32f9edc3d | ||
|
|
282029eb45 | ||
|
|
0ae88174b8 | ||
|
|
42fdc445d0 | ||
|
|
48416fcdc1 | ||
|
|
5dab79f1c7 | ||
|
|
cfe2d71862 | ||
|
|
db03ac1596 | ||
|
|
36a1405360 | ||
|
|
85d1fe36e1 | ||
|
|
0148ff5ea2 | ||
|
|
89f096d68e | ||
|
|
db9a15e2fa | ||
|
|
84ae15e8d1 | ||
|
|
f69451140f | ||
|
|
ca897d8d15 | ||
|
|
4cacc0ee7d | ||
|
|
93148f9334 | ||
|
|
9ae2f02842 | ||
|
|
bc63df367d | ||
|
|
3f76b672f2 | ||
|
|
c79f1d5f37 | ||
|
|
db023c4448 | ||
|
|
48f66c5cb4 | ||
|
|
f54cd61ba6 | ||
|
|
011ec46dae | ||
|
|
6c91562aa9 | ||
|
|
a3ce036dc0 | ||
|
|
c82ecd6656 | ||
|
|
7ce37c9842 | ||
|
|
6e4baa664d | ||
|
|
59ffb010c4 | ||
|
|
2edb216b24 | ||
|
|
7835e2a762 | ||
|
|
f8c9d0c018 | ||
|
|
2965b52563 | ||
|
|
05762487ff | ||
|
|
b2380fcc48 | ||
|
|
40ec4f631c | ||
|
|
f9238f838c | ||
|
|
3dd756c2c1 | ||
|
|
a92bdc094d | ||
|
|
9b367aa0a1 | ||
|
|
2201a47d95 | ||
|
|
bdb578fda2 | ||
|
|
6765f24184 | ||
|
|
5ec0df6fe1 | ||
|
|
594fbed146 | ||
|
|
20e2e324e1 | ||
|
|
f33e774f4b | ||
|
|
dbdce70a8e | ||
|
|
b41f609fe4 | ||
|
|
424f396e42 | ||
|
|
b1c01d2ac9 | ||
|
|
fed21338fc | ||
|
|
987fe8b638 | ||
|
|
535c4372ca | ||
|
|
ac1f36ae76 | ||
|
|
b1442a1a97 | ||
|
|
6628e7769e | ||
|
|
5fadbc7f97 | ||
|
|
095026b459 | ||
|
|
496c8d01fa | ||
|
|
63574298ce | ||
|
|
8c1a5f033e | ||
|
|
7e3141512a | ||
|
|
c4510327d4 | ||
|
|
88fc2bb3e1 | ||
|
|
75a6913f4e | ||
|
|
97472070c3 | ||
|
|
5d4fd6055e | ||
|
|
83f4e5b457 | ||
|
|
1523a4953f | ||
|
|
429139be78 | ||
|
|
0307c0366a | ||
|
|
f698db8346 | ||
|
|
b690ccfc20 | ||
|
|
86e97d9f87 | ||
|
|
4a7a570953 | ||
|
|
0b1ce57fd1 | ||
|
|
eb39bfad81 | ||
|
|
77533a2090 | ||
|
|
414bc9cc44 | ||
|
|
180d55d135 | ||
|
|
458baea830 | ||
|
|
aaeec65415 | ||
|
|
3a821c040e | ||
|
|
31fdb438bb | ||
|
|
8db00f063d | ||
|
|
8cca58b800 | ||
|
|
9f2e60598d | ||
|
|
78af10f81b | ||
|
|
025ac59005 | ||
|
|
2b9605e8f5 | ||
|
|
333091a0d3 | ||
|
|
012ff9982c | ||
|
|
887e1d5d61 | ||
|
|
3aca463e7e | ||
|
|
b7255dac54 | ||
|
|
a3158f498f | ||
|
|
95ff997d1d | ||
|
|
80520d4ed7 | ||
|
|
1fbf5728e1 | ||
|
|
216b6b3efd | ||
|
|
557f287005 | ||
|
|
7548112578 | ||
|
|
323685d4c9 | ||
|
|
4900b15a65 | ||
|
|
adc02e52ad | ||
|
|
4bc79321a7 | ||
|
|
c0d270947f | ||
|
|
8b4677dca3 | ||
|
|
44482a809e | ||
|
|
90d8fab02e | ||
|
|
337d248c5d | ||
|
|
62a636c887 | ||
|
|
bbd12ca7aa | ||
|
|
02f858e5c9 | ||
|
|
536a126886 | ||
|
|
2a42fdea85 | ||
|
|
eb77e55fe6 | ||
|
|
edd643b226 | ||
|
|
4f7f3b5a50 | ||
|
|
1b611e7cd8 | ||
|
|
5454ec8f9b | ||
|
|
d2d528d214 | ||
|
|
a00d4b7845 | ||
|
|
0eeefc4c0d | ||
|
|
0d8600ed6d | ||
|
|
35cf511d45 | ||
|
|
b88fe43808 | ||
|
|
9c72fc1d2b | ||
|
|
e176789891 | ||
|
|
5e3369aba3 | ||
|
|
7b0fcd79a0 | ||
|
|
0ed40c04c7 | ||
|
|
7da36611dc | ||
|
|
49aeee3017 | ||
|
|
571cd5a94f | ||
|
|
a044570365 | ||
|
|
c18595ce31 | ||
|
|
a06d6839e1 | ||
|
|
22ba3c7b41 | ||
|
|
e84ecd9e42 | ||
|
|
db5e7962c9 | ||
|
|
4782f379e2 | ||
|
|
8762b5aad4 | ||
|
|
147d76d2aa | ||
|
|
a5aedfee75 | ||
|
|
2a4c743edd | ||
|
|
a9d820ed2f | ||
|
|
fa059a59a8 | ||
|
|
dc8f5ef279 | ||
|
|
e5e30dc73d | ||
|
|
ae94917e76 | ||
|
|
fedb3704f3 | ||
|
|
ea18f8e19b | ||
|
|
cd93b0470b | ||
|
|
4665b5aecf | ||
|
|
1f9b9c6235 | ||
|
|
3f4c43456f | ||
|
|
10a3ba33a5 | ||
|
|
db0beacf02 | ||
|
|
a07023d613 | ||
|
|
900c634af1 | ||
|
|
48d9b570b9 | ||
|
|
207ddca859 | ||
|
|
823b00705e | ||
|
|
4fb0ddedc7 | ||
|
|
31b3571d31 | ||
|
|
ee373a2721 | ||
|
|
685bc7ae83 | ||
|
|
bc6772282f | ||
|
|
d0d0c1e5e5 | ||
|
|
1ed598ada6 | ||
|
|
b003ae7270 | ||
|
|
18a4a3e21c | ||
|
|
72a41480ba | ||
|
|
6e221abda6 | ||
|
|
e7d8b84581 | ||
|
|
7a84430e84 | ||
|
|
7e7274b002 | ||
|
|
e27183d54f | ||
|
|
f49c31ddb2 | ||
|
|
ac959238aa | ||
|
|
563b6561a5 | ||
|
|
bc26690cbf | ||
|
|
4f56896f60 | ||
|
|
5158d34c2d | ||
|
|
5c63f0b7e3 | ||
|
|
1b3fa825f3 | ||
|
|
ef182f4b64 | ||
|
|
b706479c9b | ||
|
|
751c4fe7ef | ||
|
|
d09baef532 | ||
|
|
778244e436 | ||
|
|
f6cf83aebf | ||
|
|
e6901382a6 | ||
|
|
75c22b585e | ||
|
|
5018d3b5cb | ||
|
|
9eeacf2cfc | ||
|
|
9c25d59b82 | ||
|
|
4550133c81 | ||
|
|
8a5921e4bc | ||
|
|
470aa36c91 | ||
|
|
1fbcff5fcc | ||
|
|
6fb06af9ff | ||
|
|
62941d65a9 | ||
|
|
18fe170698 | ||
|
|
c2cd4d5d15 | ||
|
|
69da2ac0c7 | ||
|
|
e08e69719d | ||
|
|
5628024d45 | ||
|
|
9d46d25d03 | ||
|
|
836326f31e | ||
|
|
34fe80f9d9 | ||
|
|
15ae133662 | ||
|
|
c405a5d5b3 | ||
|
|
7acff3b938 | ||
|
|
7099be8f44 | ||
|
|
86e8c36a75 | ||
|
|
bc6fe86faa | ||
|
|
3bcab11310 | ||
|
|
3c8b92675f | ||
|
|
0f19d74cb1 | ||
|
|
d796a2a768 | ||
|
|
f962adbb52 | ||
|
|
3479d0ee30 | ||
|
|
70a0590ece | ||
|
|
8414c57026 | ||
|
|
ae2e7f0603 | ||
|
|
7177c3b393 | ||
|
|
11f40ba93b | ||
|
|
273511037a | ||
|
|
56d64f23bf | ||
|
|
cfbeca5e65 | ||
|
|
aaf9b56084 | ||
|
|
e0a953e27e | ||
|
|
f7c1e5f60d | ||
|
|
84bf81ac31 | ||
|
|
6a67a8c574 | ||
|
|
0fad9eaee4 | ||
|
|
d64d33ed07 | ||
|
|
0e8fdf49d0 | ||
|
|
f147256697 | ||
|
|
dbe275ce72 | ||
|
|
649cd608c1 | ||
|
|
87c63e995b | ||
|
|
cd49c5bf66 | ||
|
|
c3ca9468d1 | ||
|
|
89576aa2c1 | ||
|
|
630dbab749 | ||
|
|
8e95a2a603 | ||
|
|
6a1c94d48d | ||
|
|
578a9a3332 | ||
|
|
122fe8a20d | ||
|
|
d32f607aba | ||
|
|
25d9591416 | ||
|
|
33f41cc68b | ||
|
|
d8bee53822 | ||
|
|
0866f47904 | ||
|
|
d230325569 | ||
|
|
8e7930a604 | ||
|
|
1dde89db69 | ||
|
|
350d0a6495 | ||
|
|
42e922d587 | ||
|
|
57c002f324 | ||
|
|
e5fb684ac1 | ||
|
|
84abdc7b2d | ||
|
|
db79a4a14b | ||
|
|
f1b30c5aff | ||
|
|
4db2593801 | ||
|
|
ad685d2153 | ||
|
|
cf9dd7cf5e | ||
|
|
f10d82dc30 | ||
|
|
5ec942fb2a | ||
|
|
2897cfb556 | ||
|
|
5484869af9 | ||
|
|
90cc3a0f05 | ||
|
|
99e45f71c2 | ||
|
|
488d246ada | ||
|
|
8189910b5a | ||
|
|
de317b8e01 | ||
|
|
436cf94595 | ||
|
|
145c999762 | ||
|
|
c82b46032a | ||
|
|
cf9fa94eaa | ||
|
|
d5139fef22 | ||
|
|
f8964db41c | ||
|
|
052169695c | ||
|
|
f9a8a94fd1 | ||
|
|
880d9bb33f | ||
|
|
68aa3eb1b9 | ||
|
|
39dbb9dad8 | ||
|
|
ac7acf2441 | ||
|
|
87ce5770b7 | ||
|
|
24f3c8c29e | ||
|
|
cf578d50ec | ||
|
|
6c2e4110ad | ||
|
|
01280bbd06 | ||
|
|
0f1b7a527b | ||
|
|
965c7e1200 | ||
|
|
abea4f481c | ||
|
|
71191eae5c | ||
|
|
03d4efc5c0 | ||
|
|
22c38019b2 | ||
|
|
7cd8194c99 | ||
|
|
b4747ad67f | ||
|
|
bb6db55686 | ||
|
|
244cd8f94f | ||
|
|
ba856910e0 | ||
|
|
d00e023894 | ||
|
|
86b4b128a9 | ||
|
|
35bd06a9a0 | ||
|
|
bdc7574fd5 | ||
|
|
a7cac2463c | ||
|
|
474bc8823e | ||
|
|
95f6b0c06e | ||
|
|
dc205333cd | ||
|
|
4de96ea715 | ||
|
|
c94f02648c | ||
|
|
2ba0dd20fb | ||
|
|
389dc22856 | ||
|
|
823c8af1ab | ||
|
|
286562d202 | ||
|
|
b83a1876ba | ||
|
|
ed2a931ae3 | ||
|
|
f77190f477 | ||
|
|
2d3335fa48 | ||
|
|
d52b3fd3fe | ||
|
|
5a945afdc6 | ||
|
|
8b65ad0237 | ||
|
|
6d74246c91 | ||
|
|
9d81c953c3 | ||
|
|
97e41de23f | ||
|
|
d57543b220 | ||
|
|
13cd91bffb | ||
|
|
2d170dfed8 | ||
|
|
744ac0eb81 | ||
|
|
057983ce3e | ||
|
|
aadc34ab4d | ||
|
|
d9c4af46ed | ||
|
|
cdd0024bad | ||
|
|
6e331c523f | ||
|
|
f7712c77b8 | ||
|
|
fd436c316a | ||
|
|
7120f7df54 | ||
|
|
1d30bf8af4 | ||
|
|
40c70e12dd | ||
|
|
31b6eb916f | ||
|
|
09e7a582de | ||
|
|
b8aec00dee | ||
|
|
174f5a3a49 | ||
|
|
758d469679 | ||
|
|
542bdaa740 | ||
|
|
14bd66805e | ||
|
|
01c2d76c54 | ||
|
|
40cd0b1dd2 | ||
|
|
5dad791818 | ||
|
|
3743a6858b | ||
|
|
409a8d3678 | ||
|
|
94084178d9 | ||
|
|
3c80245275 | ||
|
|
16c4b2a572 | ||
|
|
0cf1e72ed1 | ||
|
|
029346d322 | ||
|
|
9e959f9bdd | ||
|
|
3ec8c63e28 | ||
|
|
ceeb1eca9d | ||
|
|
5800560602 | ||
|
|
a840a56e02 | ||
|
|
8704f4e24e | ||
|
|
459a5a5b1f | ||
|
|
afc28c54ac | ||
|
|
6772b45ea6 | ||
|
|
7defd4dab0 | ||
|
|
db326a14b3 | ||
|
|
0abf2e237e | ||
|
|
d3a2b52363 | ||
|
|
de81594179 | ||
|
|
06bdf8b461 | ||
|
|
d784303591 | ||
|
|
52d2c31427 | ||
|
|
9bc8e56458 | ||
|
|
489c728793 | ||
|
|
01eaadfa53 | ||
|
|
dddd2f9202 | ||
|
|
31709134c9 | ||
|
|
456efad714 | ||
|
|
2112fc571a | ||
|
|
0c4379ff0f | ||
|
|
a690b36478 | ||
|
|
6f5ed95f71 | ||
|
|
251ee5f5a2 | ||
|
|
9ab1d88a91 | ||
|
|
5d3d9f57fe | ||
|
|
0889882255 | ||
|
|
2a1f78f95a | ||
|
|
6faaa1a0cc | ||
|
|
77dd12a028 | ||
|
|
6a954445f1 | ||
|
|
9500e898c6 | ||
|
|
c5989d4350 | ||
|
|
8f782be41d | ||
|
|
afcc447a64 | ||
|
|
8cfcba83ae | ||
|
|
a8315726ce | ||
|
|
da668c80b2 | ||
|
|
55455ac21f | ||
|
|
74adacf96a | ||
|
|
a384b41308 | ||
|
|
048a329afc | ||
|
|
3c3d16e794 | ||
|
|
d95b544dfd | ||
|
|
5d9ea7b91b | ||
|
|
500289229a | ||
|
|
21d62387ae | ||
|
|
3bbfb30dcb | ||
|
|
819fbc6ed5 | ||
|
|
53e7c8fa34 | ||
|
|
35d13cad96 | ||
|
|
c190fc702e | ||
|
|
cd0ed7b509 | ||
|
|
24af685db1 | ||
|
|
d7553ded6c | ||
|
|
884d5a7fc8 | ||
|
|
a920074468 | ||
|
|
5ab342e298 | ||
|
|
c99f525821 | ||
|
|
dff004d695 | ||
|
|
6f53e4b536 | ||
|
|
9d3fe84135 | ||
|
|
e5f7ae3878 | ||
|
|
97162d9a53 | ||
|
|
d0b99cb260 | ||
|
|
fa22cc2e20 | ||
|
|
9904255490 | ||
|
|
f75c15b477 | ||
|
|
9404dcab69 | ||
|
|
c4d4403955 | ||
|
|
a0bb2dc907 | ||
|
|
ed774a5691 | ||
|
|
78cedddbde | ||
|
|
3640dc2fa3 | ||
|
|
d3c619e3d3 | ||
|
|
c158759c11 | ||
|
|
b49362420c | ||
|
|
aab76646ee | ||
|
|
259245d412 | ||
|
|
717180a8eb | ||
|
|
12811483be | ||
|
|
822aa2a352 | ||
|
|
9d788d4d9c | ||
|
|
d405cb8dd9 | ||
|
|
5d3e57094a | ||
|
|
e28d3f8cbd | ||
|
|
182494a5b7 | ||
|
|
9487820c32 | ||
|
|
03d00c16f8 | ||
|
|
57a38a00d9 | ||
|
|
779b8679fd | ||
|
|
d0143d6f3e | ||
|
|
7917c3fc15 | ||
|
|
81de913b77 | ||
|
|
0e3798cadb | ||
|
|
7447482608 | ||
|
|
f9b185caa5 | ||
|
|
4761ce4b45 | ||
|
|
9f31af4c20 | ||
|
|
ab448cdb57 | ||
|
|
22c4076818 | ||
|
|
6e8bd97709 | ||
|
|
7dd128a1a8 | ||
|
|
dfd422a386 | ||
|
|
6f434cd94a | ||
|
|
a82f2fec18 | ||
|
|
234115f384 | ||
|
|
c522618a4b | ||
|
|
1c65c56970 | ||
|
|
c6cff13038 | ||
|
|
f25b101161 | ||
|
|
6a866e208f | ||
|
|
11b1e5abd7 | ||
|
|
f44c387988 | ||
|
|
b6629080ee | ||
|
|
4022dd564b | ||
|
|
c848ce66c5 | ||
|
|
26b4c34778 | ||
|
|
7eff83d689 | ||
|
|
125fb7fbdb | ||
|
|
01be5511e5 | ||
|
|
4b45c6e35a | ||
|
|
7f831c1f4d | ||
|
|
d6778847c9 | ||
|
|
9a96645b53 | ||
|
|
ffa1b19e26 | ||
|
|
6f98b140a8 | ||
|
|
e83d1a26e6 | ||
|
|
b237d68c47 | ||
|
|
1027762816 | ||
|
|
42893fc3bd | ||
|
|
a479761be5 | ||
|
|
6d7265d966 | ||
|
|
32048b7658 | ||
|
|
08f79c6b93 | ||
|
|
699a2268d6 | ||
|
|
410f9c485e | ||
|
|
8561e5e38e | ||
|
|
17617fe839 | ||
|
|
7f4173ab22 | ||
|
|
84236edaf8 | ||
|
|
370dc2d727 | ||
|
|
211b07a2e2 | ||
|
|
9f67ba6a38 | ||
|
|
03798fd604 | ||
|
|
7bb4897b9f | ||
|
|
4b0e97e666 | ||
|
|
5b655dd4cd | ||
|
|
023a61c0e5 | ||
|
|
38cc6383b7 | ||
|
|
77ac863bb8 | ||
|
|
fdab219755 | ||
|
|
f31e8d08cd | ||
|
|
224c8ec0fa | ||
|
|
309c19ef63 | ||
|
|
13aad7e8b4 | ||
|
|
6f36d0d06c | ||
|
|
76d734a4bd | ||
|
|
b14f29b5b7 | ||
|
|
c57b30e342 | ||
|
|
f6023a7c76 | ||
|
|
6357a2d9b8 | ||
|
|
7e3a1a8b18 | ||
|
|
5f1b8f71f3 | ||
|
|
cca8bb9092 | ||
|
|
647314d3cc | ||
|
|
30e6773617 | ||
|
|
08774dc558 | ||
|
|
481618826d | ||
|
|
befcada36a | ||
|
|
b71bf9332c | ||
|
|
1303c93139 | ||
|
|
29c8c75492 | ||
|
|
862d83c691 | ||
|
|
f18eeb4da8 | ||
|
|
d40fed016f | ||
|
|
76dc3ddf56 | ||
|
|
d80d9a4c4e | ||
|
|
281ee1c2bf | ||
|
|
65e976198e | ||
|
|
a0d668e850 | ||
|
|
f7d624e684 | ||
|
|
f5c395adb2 | ||
|
|
09192b4d6e | ||
|
|
74ec3783e7 | ||
|
|
1c38ce8245 | ||
|
|
702cfe15be | ||
|
|
54d790828f | ||
|
|
aff35fea29 | ||
|
|
25a82bcbe3 | ||
|
|
cb58100587 | ||
|
|
9fbe96fd7c | ||
|
|
98cd400443 | ||
|
|
873e699f6d | ||
|
|
9a8f6c824f | ||
|
|
a98888ad07 | ||
|
|
db98500b72 | ||
|
|
3feee09cfe | ||
|
|
4a1cd0d391 | ||
|
|
edb5071d3b | ||
|
|
e9509aa5e6 | ||
|
|
5e6ca1b72d | ||
|
|
543bf2ffbd | ||
|
|
15a7a4c38b | ||
|
|
640d07bf35 | ||
|
|
e5ecc2b942 | ||
|
|
cfd8fe40f4 | ||
|
|
abba6e0642 | ||
|
|
ec94fb89a2 | ||
|
|
bb167efa7b | ||
|
|
2a550ef96d | ||
|
|
03ed7d73fc | ||
|
|
446852db3b | ||
|
|
7c90b57e87 | ||
|
|
6339e2588b | ||
|
|
af6687405b | ||
|
|
a2bfad1c29 | ||
|
|
645aa55abc | ||
|
|
05329c885a | ||
|
|
b3fed93a74 | ||
|
|
2c6fad0ea7 | ||
|
|
57854c2231 | ||
|
|
a8cf4293e0 | ||
|
|
ba70dce803 | ||
|
|
5b4c3ace56 | ||
|
|
2ade7a15e2 | ||
|
|
e83f71d678 | ||
|
|
412c91cb6b | ||
|
|
aa44167319 | ||
|
|
dd5700e8b3 | ||
|
|
ef7fc430d7 | ||
|
|
f1bcb6c634 | ||
|
|
4a4eb17d08 | ||
|
|
8afc267c68 | ||
|
|
6457ab31b6 | ||
|
|
306dfa2043 | ||
|
|
424bdade0b | ||
|
|
10857e3321 | ||
|
|
85a4e47879 | ||
|
|
759e49f025 | ||
|
|
43924e31b8 | ||
|
|
3b34fcf59f | ||
|
|
ba7253eaf7 | ||
|
|
be23682a30 | ||
|
|
3a5dce4c92 | ||
|
|
22d7e60d0e | ||
|
|
5752156c9e | ||
|
|
a30215a530 | ||
|
|
f9c8c1b964 | ||
|
|
5650f67ef5 | ||
|
|
5ec25dfb94 | ||
|
|
ef16682725 | ||
|
|
883486cc67 | ||
|
|
f367f9b747 | ||
|
|
a3d987fa73 | ||
|
|
2d48685673 | ||
|
|
9b21ace1e9 | ||
|
|
be2c03fa96 | ||
|
|
f5585e9252 | ||
|
|
4d534dd7e4 | ||
|
|
c8584e1cce | ||
|
|
84a1de464c | ||
|
|
3966f3d319 | ||
|
|
e6166cf711 | ||
|
|
2285712834 | ||
|
|
53cb6128e8 | ||
|
|
8c317baf19 | ||
|
|
8cac933c71 | ||
|
|
03e61a4bf8 | ||
|
|
71446a76b2 | ||
|
|
28db8d6c7c | ||
|
|
786e33d7d5 | ||
|
|
b140d6c50e | ||
|
|
64a95abdee | ||
|
|
57f926be17 | ||
|
|
4933b67959 | ||
|
|
370b4f1b9e | ||
|
|
f3b7baa84e | ||
|
|
eafdb2c807 | ||
|
|
a91fa821ab | ||
|
|
37ef162cda | ||
|
|
770928acfc | ||
|
|
d0f3570219 | ||
|
|
3d07c2605f | ||
|
|
c350798528 | ||
|
|
6bc3cc0bec | ||
|
|
2e3e5fcc81 | ||
|
|
dfdb10f6de | ||
|
|
5cbe5909eb | ||
|
|
04d52b450b | ||
|
|
a586a89547 | ||
|
|
1905eacf15 | ||
|
|
858ec0d740 | ||
|
|
76cfd406ca | ||
|
|
9dbaad859d | ||
|
|
95d43e17b3 | ||
|
|
09a2dff8de | ||
|
|
57208f879a | ||
|
|
149638431d | ||
|
|
30d2940c67 | ||
|
|
5ee86fc5d0 | ||
|
|
a03d0e2c3f | ||
|
|
8bd367d58d | ||
|
|
bc633e03aa | ||
|
|
797d0f1ef1 | ||
|
|
1be3e86aa0 | ||
|
|
e56dd38021 | ||
|
|
410904bef1 | ||
|
|
026cc120e7 | ||
|
|
ef2fda05cf | ||
|
|
92277e3ae2 | ||
|
|
fbc34d70b0 | ||
|
|
91dcddbdf7 | ||
|
|
874f42ad6c | ||
|
|
1989ef4ebc | ||
|
|
4f4c72c065 | ||
|
|
666cc72661 | ||
|
|
4524e8f5c9 | ||
|
|
bd07a29886 | ||
|
|
a0d865492e | ||
|
|
de27790de8 | ||
|
|
9c910b7be2 | ||
|
|
7f23ab94e2 | ||
|
|
77dc036c8f | ||
|
|
aa6e8d82ce | ||
|
|
3010285bb3 | ||
|
|
aaad3252f8 | ||
|
|
9065f534d8 | ||
|
|
52361c94e5 | ||
|
|
798be60fef | ||
|
|
6294154b15 | ||
|
|
6594fe077d | ||
|
|
582706cde6 | ||
|
|
6537cbdc17 | ||
|
|
53959459bb | ||
|
|
22d6121099 | ||
|
|
48d7f6f2f4 | ||
|
|
9fd4ddc490 | ||
|
|
a4d2fddbb2 | ||
|
|
c54a3f2721 | ||
|
|
04c0dba697 | ||
|
|
5406e3b7c5 | ||
|
|
6b624b7d00 | ||
|
|
2d364d4d80 | ||
|
|
1f27bf3774 | ||
|
|
d30a2653b5 | ||
|
|
3086822cd2 | ||
|
|
2c08336490 | ||
|
|
5936ac58c2 | ||
|
|
ded77e3f5c | ||
|
|
8a29df0a6c | ||
|
|
9db22babaf | ||
|
|
c318c5ed61 | ||
|
|
61243c65cd | ||
|
|
4a5d5cb462 | ||
|
|
cbf1447ebd | ||
|
|
30104441bf | ||
|
|
b4a70804f0 | ||
|
|
74f6707bde | ||
|
|
223eb8c84d | ||
|
|
107d000606 | ||
|
|
43e05607af | ||
|
|
55793452d5 | ||
|
|
686ba37255 | ||
|
|
03ed19dad5 | ||
|
|
ad2b6e5de1 | ||
|
|
767676d6ff | ||
|
|
bc7a54c615 | ||
|
|
1bda393678 | ||
|
|
bb5495c6bd | ||
|
|
484f905749 | ||
|
|
e0d61a4336 | ||
|
|
e643a16ba5 | ||
|
|
98fadec2b6 | ||
|
|
14f464ecb0 | ||
|
|
2ecdaf9bd4 | ||
|
|
707c898f66 | ||
|
|
69e4400774 | ||
|
|
695efde68d | ||
|
|
0c4b769011 | ||
|
|
e53eff0634 | ||
|
|
6c75243a06 | ||
|
|
efde37880b | ||
|
|
7d8f6381be | ||
|
|
3c361e3393 | ||
|
|
8440ecef5e | ||
|
|
6401f1b1c9 | ||
|
|
7487a7c988 | ||
|
|
f44584fa10 | ||
|
|
7b32165614 | ||
|
|
b0dc94d187 | ||
|
|
0383c4e1d8 | ||
|
|
a8c5758222 | ||
|
|
a7fabfd8cb | ||
|
|
5d5b575d16 | ||
|
|
ac1373653c | ||
|
|
b097aa787b | ||
|
|
723be0fe69 | ||
|
|
f0597a03de | ||
|
|
65f0656f54 | ||
|
|
507ece15a5 | ||
|
|
30be4d1613 | ||
|
|
366e89bda0 | ||
|
|
f159c3f768 | ||
|
|
8506d1d567 | ||
|
|
111829da46 | ||
|
|
605798073e | ||
|
|
8320f2b094 | ||
|
|
df0d8d809b | ||
|
|
062886df64 | ||
|
|
148ea3aaa8 | ||
|
|
ab5f66c13a | ||
|
|
e65ffb8e68 | ||
|
|
949c1ab517 | ||
|
|
946d8ee046 | ||
|
|
c54a8a2e10 | ||
|
|
31177e4f85 | ||
|
|
750f81b4b5 | ||
|
|
987ff02a45 | ||
|
|
f5adaf813c | ||
|
|
78ff7dc7f0 | ||
|
|
d1fced3324 | ||
|
|
e7df9c289b | ||
|
|
a78d7231a9 | ||
|
|
ba7ae0002e | ||
|
|
a090f7b839 | ||
|
|
34ed15a987 | ||
|
|
cacec4c910 | ||
|
|
3e47d4e65b | ||
|
|
8b42fa150b | ||
|
|
60e660b9c7 | ||
|
|
fe74f013e3 | ||
|
|
24c0c70f90 | ||
|
|
757f91ca89 | ||
|
|
5c34f7847e | ||
|
|
de456f014e | ||
|
|
d29565066d | ||
|
|
4d52c9233b | ||
|
|
6da1ca0cb9 | ||
|
|
2f02f1518a | ||
|
|
e8863707de | ||
|
|
6a336dfc69 | ||
|
|
35dec1b9e4 | ||
|
|
f148280c99 | ||
|
|
599fe39749 | ||
|
|
44f3fcb238 | ||
|
|
af40fdb285 | ||
|
|
9daf8b825c | ||
|
|
ef5d8ce367 | ||
|
|
4a199ab23b | ||
|
|
6f0f5a569d | ||
|
|
3172fbfde6 | ||
|
|
e97a07a505 | ||
|
|
6579ad92da | ||
|
|
ec2fad0cfa | ||
|
|
6196ac7995 | ||
|
|
095a861018 | ||
|
|
2449ed7765 | ||
|
|
117a0408d6 | ||
|
|
a54b0223a3 | ||
|
|
44ee708ba5 | ||
|
|
58a20d0fb6 | ||
|
|
063078a02d | ||
|
|
01402fea50 | ||
|
|
b7fc2d1147 | ||
|
|
43eeb7011c | ||
|
|
d7901a4220 | ||
|
|
0c6271dabc | ||
|
|
2d4cf0c9f5 | ||
|
|
0646d0dd91 | ||
|
|
83e54b45a5 | ||
|
|
5cd87d3d27 | ||
|
|
689d8a80b5 | ||
|
|
b1d82a92e7 | ||
|
|
4d65627a50 | ||
|
|
ce3a68d817 | ||
|
|
409725be24 | ||
|
|
b74f74a0d7 | ||
|
|
719d554430 | ||
|
|
13f54f4521 | ||
|
|
57dfc9cf42 | ||
|
|
57244a6823 | ||
|
|
8bdde01bef | ||
|
|
09bbd5a472 | ||
|
|
9154a74400 | ||
|
|
1399b84b32 | ||
|
|
2ddbb3a8fa | ||
|
|
e46a6d1cc1 | ||
|
|
b698ab9011 | ||
|
|
0a2572a5eb | ||
|
|
77d049cc3d | ||
|
|
7b8f053be2 | ||
|
|
2c850d5293 | ||
|
|
4056bbf10b | ||
|
|
896b04a846 | ||
|
|
93cda8b6ec | ||
|
|
bb5e930684 | ||
|
|
43761fed2a | ||
|
|
a636299680 | ||
|
|
08e5bd5b72 | ||
|
|
2f057bef5e | ||
|
|
5ab4f21444 | ||
|
|
9ec26ed481 | ||
|
|
29c9df1389 | ||
|
|
867e9c51d4 | ||
|
|
0170f7b42a | ||
|
|
74bb6ead95 | ||
|
|
303388e5cb | ||
|
|
8388779937 | ||
|
|
fc7dfca452 | ||
|
|
e5a1db2392 | ||
|
|
6790656af6 | ||
|
|
b7477bdc15 | ||
|
|
ffc61f31de | ||
|
|
e612871ea7 | ||
|
|
7f40f09f10 | ||
|
|
456e42257c | ||
|
|
8618c271cf | ||
|
|
72ca1ccc23 | ||
|
|
075b4bef3f | ||
|
|
b59fce4393 | ||
|
|
8674a25eb8 | ||
|
|
10bf8fd2cd | ||
|
|
57cb22ff3c | ||
|
|
0162abdcae | ||
|
|
5801171518 | ||
|
|
bf1edbd1e2 | ||
|
|
a8484d987d | ||
|
|
9b2147f608 | ||
|
|
32530b378e | ||
|
|
a42905efa6 | ||
|
|
c59745f9dd | ||
|
|
b4ad9a5d08 | ||
|
|
3ead7a38b1 | ||
|
|
bf90435200 | ||
|
|
9c181fa3d3 | ||
|
|
3af0b1eb90 | ||
|
|
7110c318ee | ||
|
|
49a552ccdc | ||
|
|
57685f17a9 | ||
|
|
a1c09a463f | ||
|
|
194121760a | ||
|
|
6a987d46bf | ||
|
|
e3db0b39b9 | ||
|
|
4d4f0ee188 | ||
|
|
ac7334c167 | ||
|
|
e7bdd69af0 | ||
|
|
fefc655969 | ||
|
|
4dceaef60e | ||
|
|
6fc10dd3ae | ||
|
|
1ecd05a584 | ||
|
|
976acaca31 | ||
|
|
b4e5131d59 | ||
|
|
49f7cfefd7 | ||
|
|
fc365092f6 | ||
|
|
7f26240442 | ||
|
|
db559bb20a | ||
|
|
52850faa15 | ||
|
|
57d9a6c836 | ||
|
|
752c880bfc | ||
|
|
d83a354781 | ||
|
|
17dd81336d | ||
|
|
eaa46a2575 | ||
|
|
fc0ec1e71e | ||
|
|
fb2f92df1d | ||
|
|
74adbb77b7 | ||
|
|
788e544e1d | ||
|
|
368a0d4d2d | ||
|
|
962b7222d0 | ||
|
|
17c1f54369 | ||
|
|
33ae38e71b | ||
|
|
ef58af4bf1 | ||
|
|
3fad2db2f8 | ||
|
|
9feaeb28ca | ||
|
|
0075364715 | ||
|
|
99c5da5da5 | ||
|
|
22c957bc20 | ||
|
|
3316d59910 | ||
|
|
a109ce1eca | ||
|
|
e581a78d65 | ||
|
|
3c78f9900c | ||
|
|
bd606943e6 | ||
|
|
6381666df4 | ||
|
|
736f1aa301 | ||
|
|
b1a4eac7a8 | ||
|
|
8226a5276b | ||
|
|
77ad0bb12e | ||
|
|
9412b42206 | ||
|
|
2a91d87074 | ||
|
|
4a23617d79 | ||
|
|
0e2ceed74d | ||
|
|
ed56aed8eb | ||
|
|
8d909cbdc0 | ||
|
|
bf98943cbb | ||
|
|
6ff4552be2 | ||
|
|
1c7eb79370 | ||
|
|
f095a75f1e | ||
|
|
f70af6018c | ||
|
|
71b3b1ff4c | ||
|
|
d9fefa0c6c | ||
|
|
3bfe922381 | ||
|
|
a85cf17bf1 | ||
|
|
dbb5a09918 | ||
|
|
93e5097f20 | ||
|
|
dd53f2dc83 | ||
|
|
2b83c80593 | ||
|
|
6930f60c06 | ||
|
|
376b76e75c | ||
|
|
1ddd4509dc | ||
|
|
6af3f4f4cf | ||
|
|
6726c5f958 | ||
|
|
d5a9c43cb2 | ||
|
|
19a5a6a4eb | ||
|
|
617a599ee9 | ||
|
|
25e2d4da44 | ||
|
|
ad2e7218cb | ||
|
|
917637fa9b | ||
|
|
b595ee1c0b | ||
|
|
c8260a4a56 | ||
|
|
d2eaff3204 | ||
|
|
b65f5a844f | ||
|
|
95a69f99ba | ||
|
|
71d609895a | ||
|
|
9229630447 | ||
|
|
eb18a0b7dc | ||
|
|
05ed5c0d74 | ||
|
|
41330ecc5e | ||
|
|
16fbcc6e36 | ||
|
|
d87da9c7de | ||
|
|
94563b6017 | ||
|
|
34d22f7047 | ||
|
|
e24d996fbe | ||
|
|
9b52617919 | ||
|
|
efc1d46c89 | ||
|
|
9397833ceb | ||
|
|
e9433e83cd | ||
|
|
f3c58100a0 | ||
|
|
8900231d99 | ||
|
|
c7a63b8a2b | ||
|
|
90e90672a4 | ||
|
|
fa51e5c762 | ||
|
|
911f55d005 | ||
|
|
d30eb4e570 | ||
|
|
67bcfb6947 | ||
|
|
3915a61b1e | ||
|
|
c170d321e8 | ||
|
|
2802c476ee | ||
|
|
1050cebf7f | ||
|
|
dad73465fc | ||
|
|
8e2ac98fe2 | ||
|
|
9aaf0c36d5 | ||
|
|
1cb07e9cfd | ||
|
|
f1ccdf25b1 | ||
|
|
6dca497b27 | ||
|
|
42a83262a1 | ||
|
|
63ee9cbee6 | ||
|
|
3862f8ca7c | ||
|
|
4ada7cffd0 | ||
|
|
a664ce4298 | ||
|
|
8d7b6c6905 | ||
|
|
16d22d404a | ||
|
|
ccb24d5779 | ||
|
|
8795b45cb4 | ||
|
|
628d3bff45 | ||
|
|
0336bc9de9 | ||
|
|
033cb21797 | ||
|
|
09b98a45df | ||
|
|
38857ba29e | ||
|
|
1c7520ec8f | ||
|
|
362b9769b2 | ||
|
|
b2d68bd3d2 | ||
|
|
0dc7e635d4 | ||
|
|
80e070a857 | ||
|
|
cc203245e4 | ||
|
|
2f9a65fc93 | ||
|
|
62738e8001 | ||
|
|
5ecacf0c7f | ||
|
|
06b103c8d4 | ||
|
|
d473b7bca8 | ||
|
|
50a1e81ba7 | ||
|
|
d9885b1b64 | ||
|
|
0a9c8cada2 | ||
|
|
60f55f8461 | ||
|
|
7bedaea38f | ||
|
|
9e4b87e798 | ||
|
|
95bf59095c | ||
|
|
e0f34a9720 | ||
|
|
f3797c2a8e | ||
|
|
30cbcccc80 | ||
|
|
f49c0d696f | ||
|
|
71f564ee5b | ||
|
|
4b0950aba5 | ||
|
|
8c3af822ec | ||
|
|
878a207d19 | ||
|
|
0537ad860a | ||
|
|
2cdbbb1aea | ||
|
|
7af977d36b | ||
|
|
9afff4cf30 | ||
|
|
48ba9734aa | ||
|
|
897fc59f72 | ||
|
|
947e44ae67 | ||
|
|
e44843beba | ||
|
|
147482ea69 | ||
|
|
09091c5cf8 | ||
|
|
50827a5f69 | ||
|
|
2d6444c924 | ||
|
|
1d2675d9aa | ||
|
|
ad98990a8e | ||
|
|
8e58c143f2 | ||
|
|
556a4a2395 | ||
|
|
5be987b40f | ||
|
|
066bc35e69 | ||
|
|
403779437c | ||
|
|
fb806f61d4 | ||
|
|
6ce306661c | ||
|
|
3c08ff94d4 | ||
|
|
a6afae2356 | ||
|
|
0eea7070a7 | ||
|
|
105c2b1eea | ||
|
|
82bb0e8dda | ||
|
|
8c01179075 | ||
|
|
c9d9a96630 | ||
|
|
8f21c9a920 | ||
|
|
0ba7d05ea7 | ||
|
|
5a4c5b4155 | ||
|
|
55323fb497 | ||
|
|
7c082d2471 | ||
|
|
f3cafcf983 | ||
|
|
75073e4aa6 | ||
|
|
a3c23f650c | ||
|
|
0545cd5879 | ||
|
|
c96506f22c | ||
|
|
49b2006824 | ||
|
|
8c6f96faab | ||
|
|
a0e648abfd | ||
|
|
6350cd12fc | ||
|
|
f2fab0677b | ||
|
|
edffc52927 | ||
|
|
d6e5e3d103 | ||
|
|
5be7a0ebf7 | ||
|
|
7f722fe7d3 | ||
|
|
a01732ee9b | ||
|
|
85ac11b69b | ||
|
|
590cfb77a5 | ||
|
|
f01dd16a27 | ||
|
|
df49287e5f | ||
|
|
c8ec8391ee | ||
|
|
3499e48064 | ||
|
|
2e379cb8a5 | ||
|
|
f8ee3c2369 | ||
|
|
c74fa11518 | ||
|
|
ceec4455df | ||
|
|
17c9975c0b | ||
|
|
6c1cdff912 | ||
|
|
79f53f569d | ||
|
|
ccb85cc719 | ||
|
|
c0eff8a07f | ||
|
|
954626f157 | ||
|
|
17e7dfa4bd | ||
|
|
971f233fb7 | ||
|
|
b12bc692af | ||
|
|
730301b34d | ||
|
|
c443bcf43c | ||
|
|
b77e7eeddc | ||
|
|
031b7b57a1 | ||
|
|
5123fab525 | ||
|
|
705b96c6f9 | ||
|
|
9ec582002b | ||
|
|
ee79277774 | ||
|
|
db02dc218e | ||
|
|
b66ce1089e | ||
|
|
ec0e70b599 | ||
|
|
a273482f9d | ||
|
|
76cf8c4cf7 | ||
|
|
9691ecc839 | ||
|
|
59b2a86359 | ||
|
|
fe7cd72cff | ||
|
|
f0761fc570 | ||
|
|
90990aa19d | ||
|
|
a3d3ce82e4 | ||
|
|
b8e48113a3 | ||
|
|
d4b1003a97 | ||
|
|
efd83567c9 | ||
|
|
5563f373f7 | ||
|
|
15a36619fe | ||
|
|
38e54b626e | ||
|
|
8aa30fb56a | ||
|
|
b764becd1b | ||
|
|
219370932e | ||
|
|
90afae186c | ||
|
|
84e49a809d | ||
|
|
1cfb9ff46a | ||
|
|
f35026c74f | ||
|
|
5f2d3da8c5 | ||
|
|
4e61f32a28 | ||
|
|
d7814c7011 | ||
|
|
aa40668e84 | ||
|
|
3767e6e96f | ||
|
|
44976cef6c | ||
|
|
eba4417947 | ||
|
|
c99204d370 | ||
|
|
1bfc4335bb | ||
|
|
6b9c7485f1 | ||
|
|
737f3d78f2 | ||
|
|
b1d5e1b5e3 | ||
|
|
8d92a5cc14 | ||
|
|
fc455df92c | ||
|
|
c0076ebfa1 | ||
|
|
5d607aa3cd | ||
|
|
fa1b9a4098 | ||
|
|
c8c4dbb409 | ||
|
|
16628e6cea | ||
|
|
7067c12991 | ||
|
|
7b47e241e0 | ||
|
|
d1e46207a5 | ||
|
|
2a04b97cbd | ||
|
|
e6c8ef59e0 | ||
|
|
d3380f41de | ||
|
|
4ef1633969 | ||
|
|
57e593aab2 | ||
|
|
6461caacbb | ||
|
|
e5531e2a93 | ||
|
|
329402a614 | ||
|
|
4656ed462e | ||
|
|
96ddad91a9 | ||
|
|
5eb40588d2 | ||
|
|
58def149aa | ||
|
|
0ee5743d75 | ||
|
|
7c266f3e81 | ||
|
|
d7ce981cd1 | ||
|
|
eadadf6299 | ||
|
|
8ac9fabd07 | ||
|
|
44c2b4b281 | ||
|
|
4cd97611e5 | ||
|
|
da27380ab5 | ||
|
|
756e539661 | ||
|
|
cde44e3172 | ||
|
|
e79a4b34b0 | ||
|
|
e9f0bdd72c | ||
|
|
d080291150 | ||
|
|
06c69c56ba | ||
|
|
d79710ba9d | ||
|
|
c9bc7dd0b6 | ||
|
|
ebc26c7421 | ||
|
|
3769425f6b | ||
|
|
a50957443e | ||
|
|
63fa007af0 | ||
|
|
a6a52a128b | ||
|
|
1ad58e1121 | ||
|
|
3f507a26fb | ||
|
|
bfc368764a | ||
|
|
53fbce932b | ||
|
|
a94195c6cd | ||
|
|
626c6d1124 | ||
|
|
471ab92bbb | ||
|
|
fbccd12924 | ||
|
|
e5928bbaea | ||
|
|
3c1597bc67 | ||
|
|
295019815e | ||
|
|
654a391250 | ||
|
|
9ee1465d3c | ||
|
|
52197cf4d2 | ||
|
|
cfbb2afac5 | ||
|
|
8f154f65f9 | ||
|
|
7454664997 | ||
|
|
3393b7aedd | ||
|
|
133ccc95b5 | ||
|
|
c392ff1cd3 | ||
|
|
30a0f831a5 | ||
|
|
541ea4dc63 | ||
|
|
afc5e0e3e5 | ||
|
|
bcb31df10d | ||
|
|
2192c4e269 | ||
|
|
eec17858c4 | ||
|
|
6d696706be | ||
|
|
8cd88b6051 | ||
|
|
9dbf53fdb9 | ||
|
|
38b6963c8b | ||
|
|
7b6248983d | ||
|
|
4d418dee0e | ||
|
|
06fe319347 | ||
|
|
9dd7e3fb24 | ||
|
|
d5a46396b0 | ||
|
|
5e84cb560d | ||
|
|
756c6f8560 | ||
|
|
6fa6ce35da | ||
|
|
b14b97599d | ||
|
|
db6f60d6fc | ||
|
|
25c348d7c8 | ||
|
|
2e4bf8b034 | ||
|
|
c1490e2f7b | ||
|
|
b004fe9556 | ||
|
|
67142ad046 | ||
|
|
3c3ec06b12 | ||
|
|
5b5caa8a16 | ||
|
|
b2cba098bb | ||
|
|
1ec0d47f10 | ||
|
|
f232606ec7 | ||
|
|
fa28cea152 | ||
|
|
c8da1647a1 | ||
|
|
505a0a8718 | ||
|
|
10d3496a17 | ||
|
|
a13c755370 | ||
|
|
62f9996fd7 | ||
|
|
edbcd8a1b2 | ||
|
|
a5308d1689 | ||
|
|
cbfe6e8fcc | ||
|
|
5571ff35d8 | ||
|
|
2a4819f3c8 | ||
|
|
7121866b13 | ||
|
|
d6e05ad9e2 | ||
|
|
993e30a7de | ||
|
|
49cae61254 | ||
|
|
1ea4b2ea91 | ||
|
|
bc1d6e1f90 | ||
|
|
9ec6e68d0c | ||
|
|
341bdc93e2 | ||
|
|
6fb3e1aa15 | ||
|
|
f1f92eb2e2 | ||
|
|
8c2369d40f | ||
|
|
a6d9fc58eb | ||
|
|
f7cd471548 | ||
|
|
5f951faf32 | ||
|
|
b228dfaf2c | ||
|
|
764858fa12 | ||
|
|
5ee976d276 | ||
|
|
8b28b6f2d3 | ||
|
|
fe16df2e6f | ||
|
|
779047f8c9 | ||
|
|
094e9fb45d | ||
|
|
1458bd0e74 | ||
|
|
d2cb05988d | ||
|
|
6e056767b4 | ||
|
|
a10afb1b98 | ||
|
|
bb6d3b6cfd | ||
|
|
c75d4af4bc | ||
|
|
972dc39d00 | ||
|
|
9daac5c178 | ||
|
|
dd2a3f40e1 | ||
|
|
78f76c1690 | ||
|
|
4788066a5f | ||
|
|
10e4254e7d | ||
|
|
0106e4df9d | ||
|
|
8ac718a3a2 | ||
|
|
46d45273a1 | ||
|
|
8da9ec3599 | ||
|
|
01fdf84d69 | ||
|
|
cc78386e75 | ||
|
|
3755157c61 | ||
|
|
80f8436f0a | ||
|
|
f88a4b7760 | ||
|
|
de229b8ab0 | ||
|
|
a3ba37e45e | ||
|
|
50c779b3c6 | ||
|
|
192372e1c3 | ||
|
|
f88fd88c38 | ||
|
|
6e15145af1 | ||
|
|
4b5fad4e48 | ||
|
|
7a13e71c80 | ||
|
|
3c10943900 | ||
|
|
696b8811c2 | ||
|
|
9fd2c8602a | ||
|
|
a3636a5af4 | ||
|
|
f2e5f07718 | ||
|
|
16c6fdde60 | ||
|
|
2155c93426 | ||
|
|
c394631e4c | ||
|
|
8b370b7cc1 | ||
|
|
607db9971c | ||
|
|
6768f64e2f | ||
|
|
f1813b1cc6 | ||
|
|
fb665bd0dd | ||
|
|
65dda2ef3d | ||
|
|
b162b992af | ||
|
|
67a3a3d130 | ||
|
|
92cd9bf7d2 | ||
|
|
bf97034485 | ||
|
|
1ded1fc509 | ||
|
|
e0592c58b3 | ||
|
|
5ead2706b4 | ||
|
|
52ada4853c | ||
|
|
c2b27a8298 | ||
|
|
3934c1d437 | ||
|
|
e366b68ad3 | ||
|
|
fb94fb980a | ||
|
|
b10cc18f53 | ||
|
|
a249de3b72 | ||
|
|
d04e972d65 | ||
|
|
b9f5a18a76 | ||
|
|
d3f157f08a | ||
|
|
2294fdb496 | ||
|
|
d7ba0e01a5 | ||
|
|
b6172b53fd | ||
|
|
477ec611d5 | ||
|
|
b6194edd67 | ||
|
|
dcdbbb3ecb | ||
|
|
7ef99ee4e6 | ||
|
|
1ac1418286 | ||
|
|
8fc854f38e | ||
|
|
1c2360b335 | ||
|
|
dd4477406b | ||
|
|
9d67bbb104 | ||
|
|
d6c8e1df61 | ||
|
|
5ec7c8fece | ||
|
|
86b21eaf83 | ||
|
|
228486a971 | ||
|
|
88c0caab26 | ||
|
|
5cd4679419 | ||
|
|
eeed5e0d19 | ||
|
|
369ab1e0b2 | ||
|
|
2e21519a10 | ||
|
|
ecc001ed08 | ||
|
|
cd96852696 | ||
|
|
b9f7f30158 | ||
|
|
ca5e423331 | ||
|
|
fa9407089c | ||
|
|
66f28e193a | ||
|
|
0d93f89f5c | ||
|
|
154e9a2c47 | ||
|
|
84574a1257 | ||
|
|
bf83527b64 | ||
|
|
12c53622a0 | ||
|
|
d8f54cf891 | ||
|
|
625a671189 | ||
|
|
6ebdad3102 | ||
|
|
9a8f21aa03 | ||
|
|
291dd8edc2 | ||
|
|
de4c1daf29 | ||
|
|
0b55d7d0d8 | ||
|
|
5d86fd8fdb | ||
|
|
1b76eb1f59 | ||
|
|
b05678d8bf | ||
|
|
781f4971c6 | ||
|
|
d02ac7b99a | ||
|
|
b1b6c97f7c | ||
|
|
baee28ab5c | ||
|
|
83edf68ff9 | ||
|
|
c7588f91dd | ||
|
|
30b432adc5 | ||
|
|
7c9733eb5d | ||
|
|
a223c3fea3 | ||
|
|
d5250f4901 | ||
|
|
25f29f4712 | ||
|
|
382af5563d | ||
|
|
8cf3d165d3 | ||
|
|
0fd6ce546f | ||
|
|
b881c372bc | ||
|
|
94c5e7deb0 | ||
|
|
c344766f3c | ||
|
|
67895de0bc | ||
|
|
ff00cb6990 | ||
|
|
2cc75c11ed | ||
|
|
cd79e58eda | ||
|
|
6fa801f3d8 | ||
|
|
684eecba1d | ||
|
|
da9cf7e5de | ||
|
|
f57e7445fd | ||
|
|
fba1388719 | ||
|
|
80ed029c17 | ||
|
|
34a74e81e3 | ||
|
|
cb120ddb15 | ||
|
|
f9ee4395b0 | ||
|
|
71f06d51ed | ||
|
|
217f70952f | ||
|
|
f813d41a76 | ||
|
|
d851289d8a | ||
|
|
b115b8a2ea | ||
|
|
d0f7067471 | ||
|
|
be5b4c38a7 | ||
|
|
d6d597e3dd | ||
|
|
84e348fade | ||
|
|
910054657e | ||
|
|
8357a11249 | ||
|
|
9b021ba057 | ||
|
|
317e588efd | ||
|
|
b1d32a03c7 | ||
|
|
ee6e6529ee | ||
|
|
9d944d6cf9 | ||
|
|
13635d281a | ||
|
|
2493c46970 | ||
|
|
63e4217271 | ||
|
|
f4bd12e8e9 | ||
|
|
df15f46900 | ||
|
|
fb3a732361 | ||
|
|
2d74110feb | ||
|
|
19d102082d | ||
|
|
d2af2c9487 | ||
|
|
82980149fa | ||
|
|
a19bb7b909 | ||
|
|
9d98c3278d | ||
|
|
26376ac1c9 | ||
|
|
8459f99341 | ||
|
|
e5bdb0e0b5 | ||
|
|
1106b7775a | ||
|
|
ae2852156d | ||
|
|
44c6c36c43 | ||
|
|
a81926503d | ||
|
|
af13ccddda | ||
|
|
392e1bc2e8 | ||
|
|
9268d92c70 | ||
|
|
bb3366c07d | ||
|
|
d24d563ebc | ||
|
|
954bd9257b | ||
|
|
5d51a56c02 | ||
|
|
f48648552e | ||
|
|
edb9c3cc9f | ||
|
|
01dc83b936 | ||
|
|
3a8dff3a62 | ||
|
|
13b234ccba | ||
|
|
e451e93664 | ||
|
|
b4f9531475 | ||
|
|
3184ff75c4 | ||
|
|
43243f4d30 | ||
|
|
c975a100b1 | ||
|
|
02bf389425 | ||
|
|
bcb9a3dd04 | ||
|
|
cce3baa275 | ||
|
|
2b48fad426 | ||
|
|
d554b2bc94 | ||
|
|
f66943de43 | ||
|
|
9d1e9bc2fb | ||
|
|
2d6a014920 | ||
|
|
c1952bf257 | ||
|
|
a10227eb03 | ||
|
|
475ae29b85 | ||
|
|
0b9cfc278b | ||
|
|
b57b6b4fba | ||
|
|
7d948f7bc5 | ||
|
|
459023d171 | ||
|
|
fd6570720a | ||
|
|
7831665417 | ||
|
|
7c9920d982 | ||
|
|
cbdccf0a9c | ||
|
|
64fa83ec3f | ||
|
|
faff865cfd | ||
|
|
742ab55a9a | ||
|
|
66e623fb2a | ||
|
|
4ab17ee965 | ||
|
|
7f48ca5132 | ||
|
|
da983848b4 | ||
|
|
bc03f7bad3 | ||
|
|
a1c8bd3846 | ||
|
|
404bc284e0 | ||
|
|
9dee30ff0e | ||
|
|
f91aadbea8 | ||
|
|
aa15a10c91 | ||
|
|
5b03e36351 | ||
|
|
b9ba9ffad2 | ||
|
|
642be5d16c | ||
|
|
ee68d715bf | ||
|
|
224084f056 | ||
|
|
1cd8c849b8 | ||
|
|
169f68bfcd | ||
|
|
d2b7cfa2d1 | ||
|
|
a40c7dff5d | ||
|
|
e8e00630d3 | ||
|
|
e33720c854 | ||
|
|
bd8a4e0d17 | ||
|
|
586a2aef76 | ||
|
|
ce1d8f6754 | ||
|
|
7b0f401065 | ||
|
|
8387016eef | ||
|
|
4e1342b641 | ||
|
|
e45a184d90 | ||
|
|
979e1012d2 | ||
|
|
fe10a50e23 | ||
|
|
8ab6d72519 | ||
|
|
3aada6dd1d | ||
|
|
0933036366 | ||
|
|
05f5abdc06 | ||
|
|
fb875e0709 | ||
|
|
9acdc2f6bf | ||
|
|
028ce4bff6 | ||
|
|
3f245ad6db | ||
|
|
23115f4116 | ||
|
|
cf5f48e6cc | ||
|
|
997fa756ad | ||
|
|
e23f75b1cc | ||
|
|
6531e88761 | ||
|
|
e76a9c2618 | ||
|
|
45be8a836b | ||
|
|
954b6032e7 | ||
|
|
bd95416f27 | ||
|
|
df2577ace2 | ||
|
|
720e6558c9 | ||
|
|
c239f15d8a | ||
|
|
dfa1f80a57 | ||
|
|
15dfb93b17 | ||
|
|
0ec8488c2b | ||
|
|
94b2e29cb1 | ||
|
|
fefa8e9b4d | ||
|
|
32c4c44812 | ||
|
|
05195e2b1d | ||
|
|
4c2ff675b8 | ||
|
|
e5692a4721 | ||
|
|
312e6a0d31 | ||
|
|
5bb8efa41f | ||
|
|
949a835f4a | ||
|
|
85e6042941 | ||
|
|
3cd2f28975 | ||
|
|
2179a72c3a | ||
|
|
a5f282f156 | ||
|
|
40e8631f63 | ||
|
|
9ded05bb97 | ||
|
|
ec8efa35a1 | ||
|
|
f72bf20482 | ||
|
|
ebde2002e8 | ||
|
|
352a66f46f | ||
|
|
d84c5391f7 | ||
|
|
f4c582472b | ||
|
|
1485586f7e | ||
|
|
d5c9024335 | ||
|
|
860cf80703 | ||
|
|
897ff3161f | ||
|
|
b356b2e501 | ||
|
|
1d2733c893 | ||
|
|
32d9126094 | ||
|
|
db43314e50 | ||
|
|
68d2baeb65 | ||
|
|
1fd5f562d3 | ||
|
|
48e02f2086 | ||
|
|
eab7b2b581 | ||
|
|
45abade7fc | ||
|
|
5372fc4b43 | ||
|
|
4e2f240c98 | ||
|
|
bb3605518d | ||
|
|
3ef6d37f27 | ||
|
|
88e9f2f7f4 | ||
|
|
704a447df9 | ||
|
|
a5fcb26a33 | ||
|
|
2491a61481 | ||
|
|
91831d51ed | ||
|
|
174f0c19f7 | ||
|
|
de6fadfb4f | ||
|
|
f946db3e00 | ||
|
|
8d05e5bc31 | ||
|
|
cfb46820e4 | ||
|
|
081f1cbcc2 | ||
|
|
7bc6da326f | ||
|
|
cd95a0df7b | ||
|
|
82fa497c16 | ||
|
|
44fd345206 | ||
|
|
088e1c9db4 | ||
|
|
d4f16e666e | ||
|
|
8233cfd371 | ||
|
|
ff05e2e30d | ||
|
|
a8ea7dd3fb | ||
|
|
96f70a5303 | ||
|
|
f1604c3e69 | ||
|
|
c42c8c5192 | ||
|
|
5facb53a41 | ||
|
|
d039ce89af | ||
|
|
bc7605103f | ||
|
|
d305d655d4 | ||
|
|
4ef1220b16 | ||
|
|
a4fef143cd | ||
|
|
74ecb724a9 | ||
|
|
af235897ab | ||
|
|
5ec4e458b5 | ||
|
|
2dae63ce21 | ||
|
|
be748fe33b | ||
|
|
7408340b6a | ||
|
|
29eb92446e | ||
|
|
ae6918742e | ||
|
|
863484bb65 | ||
|
|
1cd7ebce4c | ||
|
|
eef8c7862e | ||
|
|
b52375d446 | ||
|
|
6e2babc2ce | ||
|
|
08e253bed1 | ||
|
|
c6661477a2 | ||
|
|
415cfd99a0 | ||
|
|
8c2e37381a | ||
|
|
45df79feba | ||
|
|
5824f992b7 | ||
|
|
b0b60fafd5 | ||
|
|
8d98b02ba2 | ||
|
|
a93fe79bc4 | ||
|
|
4aebd7be37 | ||
|
|
3170a5db32 | ||
|
|
3605b9eef6 | ||
|
|
a945f1fde2 | ||
|
|
461a997b5b | ||
|
|
a80afd7b4e | ||
|
|
aad2b51d85 | ||
|
|
36a9a81ff1 | ||
|
|
42c88546ae | ||
|
|
0f0e86ef9b | ||
|
|
98efd9a857 | ||
|
|
a0c27d95b7 | ||
|
|
984651d99d | ||
|
|
c6f7370b30 | ||
|
|
3e4b8e8985 | ||
|
|
73f08b98d2 | ||
|
|
8607a74206 | ||
|
|
8339f3ceb3 | ||
|
|
c0c9f3cc19 | ||
|
|
81f4813c29 | ||
|
|
94f57745b9 | ||
|
|
54fb2ebbe0 | ||
|
|
02d122b65b | ||
|
|
df0a5561a1 | ||
|
|
f7c55da7d0 | ||
|
|
b385f701ce | ||
|
|
05dd42f443 | ||
|
|
36d816d5cb | ||
|
|
92a6746e70 | ||
|
|
1728848a39 | ||
|
|
f9eb4e7487 | ||
|
|
d0b9f33aeb | ||
|
|
718583b241 | ||
|
|
6737127e9a | ||
|
|
19a7b4479b | ||
|
|
c340647502 | ||
|
|
0f987d2982 | ||
|
|
52bcaed169 | ||
|
|
177bd565ac | ||
|
|
c801c32fc5 | ||
|
|
d090cf3058 | ||
|
|
1e4b82cc94 | ||
|
|
3426f31184 | ||
|
|
b4fb7af1df | ||
|
|
b36647598b | ||
|
|
fd6b94f20e | ||
|
|
296dc0ed8a | ||
|
|
4f869e14d6 | ||
|
|
5704270e9d | ||
|
|
505b381e85 | ||
|
|
da6cb15393 | ||
|
|
16843f6cc8 | ||
|
|
64f3ad1fd4 | ||
|
|
ff4c4f99b3 | ||
|
|
f5d2e09569 | ||
|
|
f2bdbe0d4d | ||
|
|
c51a13caa6 | ||
|
|
7840c78a23 | ||
|
|
c706f3246b | ||
|
|
608eedf88d | ||
|
|
a564ca82be | ||
|
|
c868b1fee2 | ||
|
|
22374f718f | ||
|
|
abe3cfcf41 | ||
|
|
59db4b50cd | ||
|
|
bdae38765d | ||
|
|
66d3ceeb61 | ||
|
|
445dd17db3 | ||
|
|
cff78a2577 | ||
|
|
6a09e64195 | ||
|
|
22eabe5eab | ||
|
|
b69ba36c2d | ||
|
|
5240aad22b | ||
|
|
2897eb3cb3 | ||
|
|
d3f2f00c25 | ||
|
|
bacfb913a0 | ||
|
|
c99d0236a0 | ||
|
|
aac2b655f7 | ||
|
|
126c41e73a | ||
|
|
359ee54f0d | ||
|
|
28ab560907 | ||
|
|
ead252fee4 | ||
|
|
abf67914c4 | ||
|
|
127884e9dd | ||
|
|
654f5049eb | ||
|
|
979ca34259 | ||
|
|
4dd1086805 | ||
|
|
3503d4b72c | ||
|
|
b8d32a0d33 | ||
|
|
45dca55fc8 | ||
|
|
445d8ecd9f | ||
|
|
c980add503 | ||
|
|
133842392a | ||
|
|
8baf2ef155 | ||
|
|
20b71340bc | ||
|
|
61d8baf8b1 | ||
|
|
56a9645aa5 | ||
|
|
85877000a6 | ||
|
|
2f7d2477b6 | ||
|
|
21ea3f05f4 | ||
|
|
79d3492e90 | ||
|
|
5972777abe | ||
|
|
8e373ff868 | ||
|
|
a4db92da3a | ||
|
|
9b777eb281 | ||
|
|
bd3c652184 | ||
|
|
800f747570 | ||
|
|
2b8423437e | ||
|
|
8b4b6945f8 | ||
|
|
e5ecfec5c4 | ||
|
|
f95dbff71f | ||
|
|
098f6830a6 | ||
|
|
d1ecebdb52 | ||
|
|
590b654251 | ||
|
|
3bf190c8ab | ||
|
|
dcca7638e0 | ||
|
|
70e45ad37b | ||
|
|
db88210289 | ||
|
|
d2e0d96cc3 | ||
|
|
3feba82ccc | ||
|
|
db924da231 | ||
|
|
fc55ae7e6d | ||
|
|
86e757a6ad | ||
|
|
4790715cd3 | ||
|
|
e7e9c60042 | ||
|
|
1c3bc52cc4 | ||
|
|
5227dff0e1 | ||
|
|
33f0b5b7c2 | ||
|
|
0a02968303 | ||
|
|
f7bf658c07 | ||
|
|
8d16a0abad | ||
|
|
c974b97ca3 | ||
|
|
b8025bfebd | ||
|
|
30323b253f | ||
|
|
535c3ede96 | ||
|
|
89fed8ca33 | ||
|
|
f43c77aaed | ||
|
|
96c676b371 | ||
|
|
113047e1a2 | ||
|
|
abed57cb53 | ||
|
|
c01a800a6b | ||
|
|
d648832a2d | ||
|
|
f06833fbd2 | ||
|
|
c561addc94 | ||
|
|
702f5f1f4c | ||
|
|
1273f179e8 | ||
|
|
5d02f60bde | ||
|
|
4cf7a108e8 | ||
|
|
42635c3938 | ||
|
|
ed43dc842b | ||
|
|
49d4db6cd2 | ||
|
|
ea80ab2cae | ||
|
|
382e808b8d | ||
|
|
846befa7e0 | ||
|
|
74dd29f843 | ||
|
|
b0473bffcb | ||
|
|
24dd9ab1a7 | ||
|
|
49d3037e87 | ||
|
|
37ad2bd4e8 | ||
|
|
7d7b332b02 | ||
|
|
ac033b8612 | ||
|
|
a7b98dfe25 | ||
|
|
7fb7c86c46 | ||
|
|
ed036598a9 | ||
|
|
160bb70cdf | ||
|
|
c2e61f3c21 | ||
|
|
18218467f3 | ||
|
|
17e298ad2a | ||
|
|
d031a374f9 | ||
|
|
55f69c98cb | ||
|
|
71f2e4306d | ||
|
|
f8af23a025 | ||
|
|
4ef55a6cd3 | ||
|
|
312f866723 | ||
|
|
0ebe1f6dec | ||
|
|
2ad92e0e6e | ||
|
|
ac8823cdcf | ||
|
|
77565f7ee4 | ||
|
|
d656d90fa8 | ||
|
|
175b3b0834 | ||
|
|
7477e6b714 | ||
|
|
cd6568db69 | ||
|
|
6aff325fb2 | ||
|
|
0d603cfe9c | ||
|
|
34a1f14a17 | ||
|
|
efe1c8a070 | ||
|
|
1575844344 | ||
|
|
221ac1c208 | ||
|
|
57442db759 | ||
|
|
5fdb3e7cd6 | ||
|
|
96f259726c | ||
|
|
4936efba5e | ||
|
|
d5a3559a2f | ||
|
|
114a1c7f52 | ||
|
|
ce5265c203 | ||
|
|
1a575d926f | ||
|
|
85c818a39e | ||
|
|
4ffa2defe4 | ||
|
|
8825157fbb | ||
|
|
966d608dc5 | ||
|
|
b808c89471 | ||
|
|
75d4e6490f | ||
|
|
a82775f544 | ||
|
|
6a22ad0171 | ||
|
|
c854e88186 | ||
|
|
d02203060c | ||
|
|
cf703b0433 | ||
|
|
c0197a72d3 | ||
|
|
e5a543e283 | ||
|
|
b8b029b7d3 | ||
|
|
370f368b1a | ||
|
|
8288b45b4f | ||
|
|
fe529faf8e | ||
|
|
ab931b177d | ||
|
|
9aa3465513 | ||
|
|
6c70fc1a6c | ||
|
|
1ccc39962a | ||
|
|
99c941fc85 | ||
|
|
19729fdcc2 | ||
|
|
02e17998ce | ||
|
|
459e00c67a | ||
|
|
292f665650 | ||
|
|
93bbb79569 | ||
|
|
273e724f2b | ||
|
|
5d2615c56f | ||
|
|
bfaaf21330 | ||
|
|
dcb8415b7a | ||
|
|
699e1c75ce | ||
|
|
465b6e613e | ||
|
|
05fa105855 | ||
|
|
d7a0cdebe5 | ||
|
|
b049ab31eb | ||
|
|
6db4dcff7a | ||
|
|
3eeaef00ec | ||
|
|
8bf4c38a00 | ||
|
|
3a32b09ad1 | ||
|
|
6315982752 | ||
|
|
374a171e82 | ||
|
|
fc5d801f91 | ||
|
|
5146641848 | ||
|
|
cdd0ac42cf | ||
|
|
e5895500a2 | ||
|
|
9cb4dde3fa | ||
|
|
3c2a4370a5 | ||
|
|
e7a360dd6f | ||
|
|
c814c2fd35 | ||
|
|
fefa7fe262 | ||
|
|
26f01a29d1 | ||
|
|
169d4090ab | ||
|
|
0b43754d60 | ||
|
|
8b3b26b813 | ||
|
|
5426af4f81 | ||
|
|
4e2c3a579d | ||
|
|
5ae2693241 | ||
|
|
41c86b0d19 | ||
|
|
40788e8c3d | ||
|
|
0d29120033 | ||
|
|
4be598f865 | ||
|
|
558a6d509e | ||
|
|
75cd02aad2 | ||
|
|
e4c4451482 | ||
|
|
0671632477 | ||
|
|
54c230c264 | ||
|
|
64ba878eda | ||
|
|
01acd6dd76 | ||
|
|
9d819b52d3 | ||
|
|
37bac5cdc9 | ||
|
|
78c718c591 | ||
|
|
284b8bf6ca | ||
|
|
5a5084b837 | ||
|
|
3b8058e1f1 | ||
|
|
2a3168e0d6 | ||
|
|
a8ac6e4a15 | ||
|
|
6172cf9fba | ||
|
|
b728ec3909 | ||
|
|
61a53bbcff | ||
|
|
17d13dd084 | ||
|
|
edcb28d591 | ||
|
|
ad101119a7 | ||
|
|
bc36676d31 | ||
|
|
d76fe120ab | ||
|
|
2e95949b80 | ||
|
|
ae14d85e24 | ||
|
|
fad6304c60 | ||
|
|
a4dd3c8ce9 | ||
|
|
6d1a5d45e2 | ||
|
|
a6c7043e03 | ||
|
|
bcc400dafa | ||
|
|
8fbedf3441 | ||
|
|
2e8a9c9874 | ||
|
|
44fc41b3e5 | ||
|
|
7212c20a1b | ||
|
|
7ff142de1c | ||
|
|
e67efb199d | ||
|
|
20128bd04b | ||
|
|
c0fefdde28 | ||
|
|
f6ee160e66 | ||
|
|
06acc2004f | ||
|
|
43ac2ce4c8 | ||
|
|
b32bf72b5f | ||
|
|
c6880c957e | ||
|
|
095b71ed96 | ||
|
|
9160e496bc | ||
|
|
2a7ac78f02 | ||
|
|
64efa4627d | ||
|
|
f7e35569ce | ||
|
|
e8af32ec2b | ||
|
|
e092ce51f6 | ||
|
|
7b78edb1b7 | ||
|
|
b332e7090e | ||
|
|
67eb7723d6 | ||
|
|
251d138474 | ||
|
|
1170dfac05 | ||
|
|
4157f141c7 | ||
|
|
f569abd28a | ||
|
|
088f9687c0 | ||
|
|
e23df1f07a | ||
|
|
c818540dfd | ||
|
|
21365cbe1a | ||
|
|
5471a80a96 | ||
|
|
d7b6fa9cd0 | ||
|
|
dfdc2e02ef | ||
|
|
893ec9a302 | ||
|
|
05f65c38e6 | ||
|
|
2e9d062ec0 | ||
|
|
6b0b394e61 | ||
|
|
25621396c9 | ||
|
|
82aa0271f3 | ||
|
|
653cab13f8 | ||
|
|
b526f86b49 | ||
|
|
53c0f00888 | ||
|
|
f0c4d9de40 | ||
|
|
03ef8cec83 | ||
|
|
85f2a2e8c2 | ||
|
|
584b3e6642 | ||
|
|
39b7ef841d | ||
|
|
aa16a9098d | ||
|
|
7b8c2707bc | ||
|
|
60e26a31a7 | ||
|
|
3473c25c14 | ||
|
|
e52f022026 | ||
|
|
b1a7df8e43 | ||
|
|
0fd2479b7c | ||
|
|
273857f914 | ||
|
|
a08b85dbc8 | ||
|
|
a0aedf299a | ||
|
|
3c61426844 | ||
|
|
786f228076 | ||
|
|
004da28792 | ||
|
|
6e2be6efb6 | ||
|
|
a994dfcfbc | ||
|
|
7a8ea2ac93 | ||
|
|
0da3965d19 | ||
|
|
885fd7bb46 | ||
|
|
08771f9c89 | ||
|
|
8be48195a5 | ||
|
|
98ce2d650e | ||
|
|
3af327116a | ||
|
|
b75434db93 | ||
|
|
04e912aacd | ||
|
|
d7be352f87 | ||
|
|
96be3ec22c | ||
|
|
32e7e0d790 | ||
|
|
becc320e62 | ||
|
|
7666ed57d1 | ||
|
|
5e61d0955e | ||
|
|
e8a4662ae7 | ||
|
|
a48da3bd3b | ||
|
|
5f1a5d7b99 | ||
|
|
3e28a9db8f | ||
|
|
ebf6071d77 | ||
|
|
47a35fb9fb | ||
|
|
48e88aba44 | ||
|
|
b85f99c140 | ||
|
|
0a5e0e1f71 | ||
|
|
85dc22ebb7 | ||
|
|
5c21526009 | ||
|
|
14dff1cefc | ||
|
|
39fbb844f9 | ||
|
|
ca4e0c973a | ||
|
|
ecb42bee80 | ||
|
|
674ed2a9f3 | ||
|
|
252daf9717 | ||
|
|
196b8eaad3 | ||
|
|
8e526ba1bf | ||
|
|
19225828d9 | ||
|
|
7e594126be | ||
|
|
d2529e6334 | ||
|
|
97344f18e2 | ||
|
|
33934db629 | ||
|
|
6c6165c9f5 | ||
|
|
853460b20d | ||
|
|
cc4d9676c5 | ||
|
|
1cf1b819f4 | ||
|
|
f916c66d2b | ||
|
|
550aa86b45 | ||
|
|
014e764758 | ||
|
|
d1fc28432b | ||
|
|
879576f0a2 | ||
|
|
69098210be | ||
|
|
99df4f892d | ||
|
|
7bc04fbad3 | ||
|
|
8a74ce578d | ||
|
|
0805e4e5de | ||
|
|
f1060fc88e | ||
|
|
7d3d3d0a3a | ||
|
|
40377032e3 | ||
|
|
b2971edd7d | ||
|
|
c37d723692 | ||
|
|
30f9026e1d | ||
|
|
332286072e | ||
|
|
d6da172a2a | ||
|
|
ebfe584afc | ||
|
|
6250023583 | ||
|
|
6b4f3d63b8 | ||
|
|
56db773a09 | ||
|
|
fc6c472401 | ||
|
|
2cd42a6866 | ||
|
|
36a90c345c | ||
|
|
ef1e82c72c | ||
|
|
88f9534685 | ||
|
|
68254a052a | ||
|
|
2425b3a166 | ||
|
|
5524ed753b | ||
|
|
89711723da | ||
|
|
bed2740ffd | ||
|
|
751d633c3d | ||
|
|
45952cbdf2 | ||
|
|
b355dd7b23 | ||
|
|
48a186f172 | ||
|
|
39dc7ec2ab | ||
|
|
2fedabd3b9 | ||
|
|
6d719e9480 | ||
|
|
05e278afda | ||
|
|
87dbf462cb | ||
|
|
40e896bc5b | ||
|
|
3e940f80c7 | ||
|
|
dbf2888d43 | ||
|
|
d412355324 | ||
|
|
178732217f | ||
|
|
de17b95c3d | ||
|
|
d14e774525 | ||
|
|
ca5402a7fa | ||
|
|
7a6fa7c5b4 | ||
|
|
da36c286a6 | ||
|
|
d3901bcf2e | ||
|
|
94c8d4fdfb | ||
|
|
ab8bdc18bb | ||
|
|
c9dcd7442a | ||
|
|
34c8f13346 | ||
|
|
7a8ccda95c | ||
|
|
44a1448542 | ||
|
|
c87d89ffaf | ||
|
|
0868749d42 | ||
|
|
1d40ee23f0 | ||
|
|
8893f32603 | ||
|
|
adcf7e8dc3 | ||
|
|
901f7c5c36 | ||
|
|
775bb413b3 | ||
|
|
64cd5b5a46 | ||
|
|
ae356609b1 | ||
|
|
6102a5d2b0 | ||
|
|
f8782ee2d7 | ||
|
|
6181ec4c77 | ||
|
|
e0e7a685ef | ||
|
|
ae1f8cdad2 | ||
|
|
a4cf792e6d | ||
|
|
89109ded53 | ||
|
|
e20e52a4b2 | ||
|
|
20c4b1cbec | ||
|
|
5238b0241d | ||
|
|
9cdf6c203d | ||
|
|
839335cae6 | ||
|
|
a99b2ce167 | ||
|
|
b695141d87 | ||
|
|
92d5c9f866 | ||
|
|
7f18a1ffe0 | ||
|
|
8c3fdaaa62 | ||
|
|
5ac1c69710 | ||
|
|
de2d5fba63 | ||
|
|
33d516748f | ||
|
|
de17f6f0fd | ||
|
|
756731fc02 | ||
|
|
e46be0415f | ||
|
|
aa02fb50bf | ||
|
|
8b6cd9c772 | ||
|
|
cdd0d3351a | ||
|
|
8b6d584529 | ||
|
|
f49fdd4141 | ||
|
|
b26e1be81a | ||
|
|
bacab38d7f | ||
|
|
701c05ce96 | ||
|
|
438c452585 | ||
|
|
0a7a1eff3f | ||
|
|
87e743e381 | ||
|
|
a03f1b3d55 | ||
|
|
2d8dc3d243 | ||
|
|
b982232cc5 | ||
|
|
61c8d728ac | ||
|
|
851a2bf855 | ||
|
|
e0bdde3630 | ||
|
|
6a0dcd7f0e | ||
|
|
75f0b4c879 | ||
|
|
db536a9504 | ||
|
|
0fb114dede | ||
|
|
e703342179 | ||
|
|
35c8f4a611 | ||
|
|
7c89ae44a9 | ||
|
|
84fe06da22 | ||
|
|
806318c8b3 | ||
|
|
3aac2e1822 | ||
|
|
168baef433 | ||
|
|
6dba6cd78d | ||
|
|
502250d08f | ||
|
|
7395f0e680 | ||
|
|
494d3fdaca | ||
|
|
7b86a157de | ||
|
|
0988c41785 | ||
|
|
522db1bf01 | ||
|
|
06f066f90d | ||
|
|
f37b20677b | ||
|
|
cd2eac1032 | ||
|
|
8ac38d58d7 | ||
|
|
4c80cc313a | ||
|
|
1c65fee9b4 | ||
|
|
90dda7edc1 | ||
|
|
da054fae20 | ||
|
|
bdb6611e30 | ||
|
|
9284f973f1 | ||
|
|
2bfd64c3c9 | ||
|
|
939d24cce5 | ||
|
|
27b0183c46 | ||
|
|
d14efacac7 | ||
|
|
150a002c40 | ||
|
|
ce0def3bd8 | ||
|
|
ee20fa97c2 | ||
|
|
7403b7d700 | ||
|
|
87ef173e0a | ||
|
|
52a3fb6bc7 | ||
|
|
92e2a257a6 | ||
|
|
32e175752c | ||
|
|
d43f7180dc | ||
|
|
0129c2b0fc | ||
|
|
4ed1990001 | ||
|
|
5bd6ab27ae | ||
|
|
f3593b89fa | ||
|
|
23d84b2310 | ||
|
|
fdc49402ec | ||
|
|
5457c133e1 | ||
|
|
292e588ee3 | ||
|
|
243494c25e | ||
|
|
e4365f3706 | ||
|
|
310f3038d3 | ||
|
|
4e6033273d | ||
|
|
73718586d3 | ||
|
|
011abe61e8 | ||
|
|
fe3a37f89d | ||
|
|
8aea44e77b | ||
|
|
5529aec0d6 | ||
|
|
369549d23f | ||
|
|
181ea9a381 | ||
|
|
76b8f2854e | ||
|
|
320e5198f9 | ||
|
|
e522539e2d | ||
|
|
7c996b83d2 | ||
|
|
3dd354d7aa | ||
|
|
f4ad6e2157 | ||
|
|
8b170dc2bf | ||
|
|
dcb9d779bf | ||
|
|
80f736d670 | ||
|
|
8502c6da3c | ||
|
|
b131449422 | ||
|
|
6eebc4a620 | ||
|
|
4661ab1179 | ||
|
|
86046445ed | ||
|
|
baea9bf944 | ||
|
|
0951ee9e63 | ||
|
|
5492528287 | ||
|
|
14dbd220c2 | ||
|
|
babc890c59 | ||
|
|
6f7b47ff40 | ||
|
|
3991f03202 | ||
|
|
27271d5da7 | ||
|
|
627312e1de | ||
|
|
bfc9550e4e | ||
|
|
2b9c21268b | ||
|
|
3dce4ed6f1 | ||
|
|
0f16c2ea87 | ||
|
|
9a635f0686 | ||
|
|
6a0d4b2baa | ||
|
|
ac017098ad | ||
|
|
98fef2640d | ||
|
|
8bb66e133a | ||
|
|
68a582901d | ||
|
|
c094f4c06e | ||
|
|
f7ca545544 | ||
|
|
69b4716894 | ||
|
|
7e44dcc5bf | ||
|
|
ab9843e183 | ||
|
|
01af706ade | ||
|
|
9ebdb08e99 | ||
|
|
a74ffe25d9 | ||
|
|
7f95e27707 | ||
|
|
1facf5bba3 | ||
|
|
03d77009eb | ||
|
|
8afd6812b5 | ||
|
|
ec9ad78fcf | ||
|
|
6f4e93dc90 | ||
|
|
a38e43862d | ||
|
|
39294bb037 | ||
|
|
edc5e59b78 | ||
|
|
c00fd9fd37 | ||
|
|
b3e621dd9f | ||
|
|
6e8c49b978 | ||
|
|
398d57133d | ||
|
|
16521a6feb | ||
|
|
3ca0b37a3e | ||
|
|
cf2ec1229d | ||
|
|
fe9b1e5f9b | ||
|
|
f5b96ddf01 | ||
|
|
2fe076fb27 | ||
|
|
99249cff04 | ||
|
|
0cdf7b0613 | ||
|
|
90bcf4f157 | ||
|
|
03c3ec4e12 | ||
|
|
ca9bb20d64 | ||
|
|
c6bc078fd9 | ||
|
|
2f4bd6e52c | ||
|
|
2affe53727 | ||
|
|
09654d7dd8 | ||
|
|
90a4e37815 | ||
|
|
60889c0c79 | ||
|
|
20f3408d96 | ||
|
|
e9d86789db | ||
|
|
5152b7c66c | ||
|
|
c494c4e12c | ||
|
|
54d58ccb7e | ||
|
|
714a77bfbe | ||
|
|
d48f8bf5cc | ||
|
|
99d97754a6 | ||
|
|
b9d437de2a | ||
|
|
11403f2019 | ||
|
|
1ca102d639 | ||
|
|
339ba55111 | ||
|
|
14ae59885a | ||
|
|
e3ef54f99b | ||
|
|
001901f9a9 | ||
|
|
6a98f60e2e | ||
|
|
6f2e24c47d | ||
|
|
aafa368923 | ||
|
|
eb783cab4c | ||
|
|
6533aa865a | ||
|
|
f1a1e1bc07 | ||
|
|
953f4838dd | ||
|
|
130b892d34 | ||
|
|
6ad525c77e | ||
|
|
d0ca74ad27 | ||
|
|
9806f69b4d | ||
|
|
34d9b5e3d7 | ||
|
|
3bf5189d86 | ||
|
|
12e5b0681b | ||
|
|
8c0285d608 | ||
|
|
36558fa3b8 | ||
|
|
235f940cde | ||
|
|
803d61fcbc | ||
|
|
ffbd7d8de4 | ||
|
|
4ed924d7c7 | ||
|
|
798dc9948b | ||
|
|
13515f7ee4 | ||
|
|
ef80824c26 | ||
|
|
c8503fd65e | ||
|
|
b3c454fb1c | ||
|
|
1d7723e873 | ||
|
|
77100b2365 | ||
|
|
259a788134 | ||
|
|
39511455cb | ||
|
|
b04c16178e | ||
|
|
49a959c06e | ||
|
|
096a8932b4 | ||
|
|
e39e66df93 | ||
|
|
513633f49a | ||
|
|
eb3740daaf | ||
|
|
f7947b148a | ||
|
|
9a2a702f3f | ||
|
|
c65d95bf29 | ||
|
|
753a5edc4f | ||
|
|
0b3f853c2d | ||
|
|
3527fcf1d5 | ||
|
|
4544a89c7a | ||
|
|
ffeae9005e | ||
|
|
47217bcfb7 | ||
|
|
80ff58b57a | ||
|
|
d15dd368f1 | ||
|
|
8a2ec32bd8 | ||
|
|
410496ed52 | ||
|
|
b7b07552e5 | ||
|
|
44486e80d9 | ||
|
|
7890c527d8 | ||
|
|
2c82ab79a7 | ||
|
|
e3ebe5fc53 | ||
|
|
0ac430892e | ||
|
|
a7739c942c | ||
|
|
24581482d0 | ||
|
|
0571c3b453 | ||
|
|
73e7f5a0b0 | ||
|
|
20c0adb961 | ||
|
|
a01e03562f | ||
|
|
d184ed0130 | ||
|
|
089e1c2aee | ||
|
|
ebab0e91ee | ||
|
|
858a2b1b88 | ||
|
|
02bd59827c | ||
|
|
4991428510 | ||
|
|
3b245f5dc1 | ||
|
|
c9c81da901 | ||
|
|
4919cdc3fb | ||
|
|
e90e1f577d | ||
|
|
afd4284403 | ||
|
|
150b350d31 | ||
|
|
2818520bd1 | ||
|
|
2819952292 | ||
|
|
5af71af51c | ||
|
|
07a55b51df | ||
|
|
66dd68b49d | ||
|
|
9812657777 | ||
|
|
0b09312fc6 | ||
|
|
d0a7ac6b74 | ||
|
|
ff9a238fbd | ||
|
|
359fffa5f1 | ||
|
|
5bf92ced1a | ||
|
|
340bcc7b45 | ||
|
|
ef03742bd4 | ||
|
|
20431ec16d | ||
|
|
becba8157b | ||
|
|
51fd3bb0eb | ||
|
|
4bbd3acb4e | ||
|
|
3bc930ea7b | ||
|
|
d1b26f8e86 | ||
|
|
fdf15caaff | ||
|
|
c7b4a53c0b | ||
|
|
af78dc0308 | ||
|
|
5ad39493c4 | ||
|
|
61f597b408 | ||
|
|
2162825240 | ||
|
|
2b780e70d1 | ||
|
|
a3823f818e | ||
|
|
1f7c47bcaf | ||
|
|
ec53c365a2 | ||
|
|
793ad1f2d4 | ||
|
|
9bc733b76c | ||
|
|
21b28f0217 | ||
|
|
d3e23caa52 | ||
|
|
9e7518de67 | ||
|
|
679f0047aa | ||
|
|
d77d5ce14b | ||
|
|
33ec22a2af | ||
|
|
353053225f | ||
|
|
b7f3d6f7f7 | ||
|
|
e34577499d | ||
|
|
4cf8960c0c | ||
|
|
1f93ea0675 | ||
|
|
25b705c3a8 | ||
|
|
0725588731 | ||
|
|
fc5c61cc8b | ||
|
|
ac282e63c6 | ||
|
|
c3941941ce | ||
|
|
46cdd53323 | ||
|
|
3ff3e302c3 | ||
|
|
f2ceecf95c | ||
|
|
9314c7c881 | ||
|
|
54abb2c572 | ||
|
|
8fa3bdd025 | ||
|
|
5e7a308528 | ||
|
|
7952177786 | ||
|
|
9afbe49c84 | ||
|
|
9f06ba2db3 | ||
|
|
fe55bfddcf | ||
|
|
c0842e6444 | ||
|
|
3fed20d06a | ||
|
|
5e8f2e2c04 | ||
|
|
e4df99ea84 | ||
|
|
b3276f5f11 | ||
|
|
32667ca256 | ||
|
|
bed122a170 | ||
|
|
14adc9b875 | ||
|
|
a8778bbc5a | ||
|
|
a54e641f44 | ||
|
|
5c99efe87a | ||
|
|
7da1d731ff | ||
|
|
af9828e819 | ||
|
|
7a27136142 | ||
|
|
012ad2d423 | ||
|
|
ef3bdbf4da | ||
|
|
b3bb698f7b | ||
|
|
1ed5d1e4c1 | ||
|
|
bdee01a03d | ||
|
|
458f7376d7 | ||
|
|
cb3a00e027 | ||
|
|
482eb1f3fb | ||
|
|
6e0f638f5e | ||
|
|
bab349047d | ||
|
|
28ea6b8de8 | ||
|
|
9d51bbdae8 | ||
|
|
d622f79533 | ||
|
|
04c8515ad1 | ||
|
|
53bc4251d1 | ||
|
|
a5a751f02f | ||
|
|
66ed5f82c4 | ||
|
|
c802a9e6aa | ||
|
|
880f210946 | ||
|
|
4f9f7eb6a6 | ||
|
|
f910c4a8e7 | ||
|
|
529686d965 | ||
|
|
84dfd1536f | ||
|
|
85dedc324c | ||
|
|
d639237411 | ||
|
|
449aaf75f1 | ||
|
|
b1fda66caa | ||
|
|
66a8e90fd9 | ||
|
|
37b487d191 | ||
|
|
6c59fe3577 | ||
|
|
1cbb70c992 | ||
|
|
e06b39f882 | ||
|
|
2602b1493e | ||
|
|
989d14502d | ||
|
|
f78a550282 | ||
|
|
54a1abb284 | ||
|
|
97b492a8e2 | ||
|
|
0873bd14a9 | ||
|
|
eff6ba429a | ||
|
|
8c18064be4 | ||
|
|
44a1ac0cf3 | ||
|
|
28dc8d88dd | ||
|
|
2c0c2b64ba | ||
|
|
bd3e0f5248 | ||
|
|
cd52d98938 | ||
|
|
894c70e7f8 | ||
|
|
51d70c2edd | ||
|
|
7d4b355240 | ||
|
|
3b56193b98 | ||
|
|
b16045b57d | ||
|
|
9e8b0fca5b | ||
|
|
35cf1b3b5b | ||
|
|
83f788af57 | ||
|
|
2ffe378d3f | ||
|
|
38b33a4a5e | ||
|
|
60bf9ed0a0 | ||
|
|
16adf4de1b | ||
|
|
80de983023 | ||
|
|
8703ca623f | ||
|
|
286253a73f | ||
|
|
bd806a41df | ||
|
|
b89c4e9002 | ||
|
|
6dbf31c0c3 | ||
|
|
060c45d8a1 | ||
|
|
33d3e82e4d | ||
|
|
4bb074514d | ||
|
|
e3f8892003 | ||
|
|
9d00ad5f18 | ||
|
|
dae4344850 | ||
|
|
aa7f3fabe2 | ||
|
|
f93434a8ce | ||
|
|
25dee56be9 | ||
|
|
ce9a3f3797 | ||
|
|
11e384920a | ||
|
|
a0a1f1e536 | ||
|
|
3b3d0ea9eb | ||
|
|
2f4d78286d | ||
|
|
677dc6f985 | ||
|
|
d52057e732 | ||
|
|
fa2a1cb1fb | ||
|
|
19a0fb04ad | ||
|
|
947352f2fe | ||
|
|
adcbedb686 | ||
|
|
7732f92acd | ||
|
|
ad8a001688 | ||
|
|
9121eada08 | ||
|
|
49bd4d25a2 | ||
|
|
d80b4129c6 | ||
|
|
7edb4172d5 | ||
|
|
c3a4677990 | ||
|
|
5cbb893a3b | ||
|
|
f28a2a432b | ||
|
|
03b75a2d27 | ||
|
|
859fe69083 | ||
|
|
f6f2205ddb | ||
|
|
0f9a03ef61 | ||
|
|
9aa417c084 | ||
|
|
7b70952f5d | ||
|
|
edd3d07b49 | ||
|
|
5293d0a4ec | ||
|
|
3c8c7beae1 | ||
|
|
9c3ba9fdcd | ||
|
|
fb1748fb0f | ||
|
|
0a109fbd03 | ||
|
|
5cf64db74e | ||
|
|
488cc94f36 | ||
|
|
e15846bf79 | ||
|
|
752bd00674 | ||
|
|
7fadfcbe32 | ||
|
|
41141e75bb | ||
|
|
50f641e627 | ||
|
|
c7883fd093 | ||
|
|
4fcb24b2b1 | ||
|
|
5003557935 | ||
|
|
bdf1ba84da | ||
|
|
b0b4def983 | ||
|
|
cc184bbe9e | ||
|
|
ad30c830aa | ||
|
|
1d791a8af4 | ||
|
|
e63c51cd97 | ||
|
|
f202e32908 | ||
|
|
26e1a08e82 | ||
|
|
4d5119d435 | ||
|
|
75e34ea62e | ||
|
|
0a183d6274 | ||
|
|
21d8060aea | ||
|
|
9cbe906f60 | ||
|
|
8ce4137399 | ||
|
|
5f8a139347 | ||
|
|
9bb009a3fe | ||
|
|
726d65923f | ||
|
|
8a6be4cb2d | ||
|
|
10b06beb8e | ||
|
|
81318c7968 | ||
|
|
47a2c1c6e5 | ||
|
|
39cee65c6b | ||
|
|
8582ec724e | ||
|
|
b0139682e8 | ||
|
|
d39c475a6d | ||
|
|
48f38354c6 | ||
|
|
cd5a920ed5 | ||
|
|
71bc1f378d | ||
|
|
0ee6c31cff | ||
|
|
af89a9971e | ||
|
|
c718a8ef72 | ||
|
|
8c8ad0faf0 | ||
|
|
314d5bbb7f | ||
|
|
102255757a | ||
|
|
914067a0d0 | ||
|
|
06e3ae2536 | ||
|
|
7f9b252556 | ||
|
|
3d700e243f | ||
|
|
bcfc78ce11 | ||
|
|
09241765d5 | ||
|
|
671c83c265 | ||
|
|
772d28b766 | ||
|
|
c26fcea58d | ||
|
|
1e5e26dbff | ||
|
|
742fc54864 | ||
|
|
49738f43c0 | ||
|
|
9f85f61010 | ||
|
|
239f422039 | ||
|
|
67af3c37be | ||
|
|
a9442385c4 | ||
|
|
8c9cd10b8b | ||
|
|
72542059dd | ||
|
|
a843fc6d40 | ||
|
|
4beed60c08 | ||
|
|
4049c1e480 | ||
|
|
8449314da2 | ||
|
|
63ad057028 | ||
|
|
e720464330 | ||
|
|
24036afef9 | ||
|
|
c78fa1a1bc | ||
|
|
faa8b9022c | ||
|
|
729bafef7a | ||
|
|
590b028632 | ||
|
|
8150d00f36 | ||
|
|
060065926f | ||
|
|
70babe8a28 | ||
|
|
c36e09664f | ||
|
|
a9672246f3 | ||
|
|
ff571884e9 | ||
|
|
475138bceb | ||
|
|
4a8af199c2 | ||
|
|
bdabf5db72 | ||
|
|
6a5f21b34e | ||
|
|
d608be103c | ||
|
|
374bb5d18a | ||
|
|
031d6c25ff | ||
|
|
223fb7b075 | ||
|
|
a746741971 | ||
|
|
120faf2a58 | ||
|
|
990bca0dc6 | ||
|
|
3406472db7 | ||
|
|
1bd733c9f6 | ||
|
|
238c7f982e | ||
|
|
fcb81147cb | ||
|
|
1915b73783 | ||
|
|
ee79e621fb | ||
|
|
d203275a3b | ||
|
|
9e8a996222 | ||
|
|
0126b0b3ed | ||
|
|
458928612c | ||
|
|
e33f88e28d | ||
|
|
be570bbf9e | ||
|
|
f59b4be110 | ||
|
|
37336e41be | ||
|
|
d24a1a3f0a | ||
|
|
f7258955bd | ||
|
|
2a1eae5d6f | ||
|
|
50ee0a4adb | ||
|
|
955a26584e | ||
|
|
1d3e407c8f | ||
|
|
cb809c4596 | ||
|
|
53bbe2888e | ||
|
|
7246f476a5 | ||
|
|
0785d1c390 | ||
|
|
85d2c49d14 | ||
|
|
8b77d62b7f | ||
|
|
373058a32a | ||
|
|
e6293c2c8c | ||
|
|
eff181c959 | ||
|
|
54752c2305 | ||
|
|
b4753c044f | ||
|
|
26493424ae | ||
|
|
0282fd1332 | ||
|
|
b9a019a08b | ||
|
|
66f6a0e687 | ||
|
|
2dd1b9f97d | ||
|
|
89615f3045 | ||
|
|
7e46192f67 | ||
|
|
e78d985cdf | ||
|
|
e8c4bf56fe | ||
|
|
e6aa7d323d | ||
|
|
fca8e25929 | ||
|
|
8e8ac286b4 | ||
|
|
7d9770b9a2 | ||
|
|
1996230460 | ||
|
|
de7897a864 | ||
|
|
e2884dcdb7 | ||
|
|
544a53a42b | ||
|
|
2e4787bfc8 | ||
|
|
1829eeb171 | ||
|
|
c7488e3c4a | ||
|
|
3bf9606383 | ||
|
|
4f43f18f0a | ||
|
|
5b7f197397 | ||
|
|
018141c97f | ||
|
|
4d7813e57c | ||
|
|
605c60208f | ||
|
|
884fafcc30 | ||
|
|
56baa90320 | ||
|
|
6bb20ee09e | ||
|
|
541356430c | ||
|
|
2f4d91fd69 | ||
|
|
f58c5e6b30 | ||
|
|
0311d0132c | ||
|
|
c946c97402 | ||
|
|
84a6f51318 | ||
|
|
24a1501b0d | ||
|
|
383b6f5fcc | ||
|
|
633dd7ff9b | ||
|
|
580624fad6 | ||
|
|
a8190f7efa | ||
|
|
dd2157534b | ||
|
|
38a90e7669 | ||
|
|
6bfc526dcd | ||
|
|
aadb8a7405 | ||
|
|
27082bf77e | ||
|
|
a2903c80cd | ||
|
|
9a77c5369c | ||
|
|
3c30741a19 | ||
|
|
7028ad4ec0 | ||
|
|
8de750c6aa | ||
|
|
04f98de9ee | ||
|
|
a1a019784b | ||
|
|
4aeeae77bd | ||
|
|
651cfc2b78 | ||
|
|
2ef8af25e2 | ||
|
|
0b13852a5b | ||
|
|
13427578c9 | ||
|
|
d89ca2087e | ||
|
|
8b0ea9fba6 | ||
|
|
9f0b653d5a | ||
|
|
659a339233 | ||
|
|
4c29f177a0 | ||
|
|
d664e63d55 | ||
|
|
2493509dbe | ||
|
|
1c8b27f554 | ||
|
|
68297b7186 | ||
|
|
34dd8d0a91 | ||
|
|
81c44790d5 | ||
|
|
d557b335cf | ||
|
|
e2adc28cff | ||
|
|
0fef6a6ecc | ||
|
|
f2fd4b8a1f | ||
|
|
95bd5605a8 | ||
|
|
497cca7eca | ||
|
|
54f78feedd | ||
|
|
76408e53ae | ||
|
|
be19e74d30 | ||
|
|
dac578a775 | ||
|
|
04732ce74b | ||
|
|
a6c95a2374 | ||
|
|
f68622abe9 | ||
|
|
83a9a7bdb2 | ||
|
|
6500afc0ca | ||
|
|
c69b7ecc96 | ||
|
|
615ef1e2d2 | ||
|
|
cf69a0cd7f | ||
|
|
06e892fb33 | ||
|
|
e6c5dd6865 | ||
|
|
247efdebdb | ||
|
|
76f3792287 | ||
|
|
64d8e2c727 | ||
|
|
ead0bd9cb0 | ||
|
|
66fc13b2ec | ||
|
|
f3af4128b0 | ||
|
|
0e43107c87 | ||
|
|
1ee3e7997e | ||
|
|
50fd61d91f | ||
|
|
e4cdc051a9 | ||
|
|
778e846e96 | ||
|
|
a27759b647 | ||
|
|
b75eceab41 | ||
|
|
e748a5d5f4 | ||
|
|
99c5a3ae46 | ||
|
|
51da710f5a | ||
|
|
569d69b3d2 | ||
|
|
059a6b1d90 | ||
|
|
990af7548a | ||
|
|
a38aefdfc8 | ||
|
|
3bcb12e7d1 | ||
|
|
7904ecb462 | ||
|
|
9ba4d45109 | ||
|
|
56b8afe19d | ||
|
|
f7aed9a94c | ||
|
|
e12a7e881d | ||
|
|
5afb65325d | ||
|
|
135f520f32 | ||
|
|
bc251f4ff6 | ||
|
|
b8769751f6 | ||
|
|
eff96d839e | ||
|
|
aa34c23807 | ||
|
|
195acdac8c | ||
|
|
903e03c56c | ||
|
|
0892767b8a | ||
|
|
83ebfa772c | ||
|
|
1583641322 | ||
|
|
9510e2c256 | ||
|
|
a9dbabe07e | ||
|
|
12884008fa | ||
|
|
02543bad1c | ||
|
|
a8c56a5251 | ||
|
|
4e5a855f3f | ||
|
|
7e497a951e | ||
|
|
cd08eabbfa | ||
|
|
f7e62d9f81 | ||
|
|
9a3761e86e | ||
|
|
3619a68693 | ||
|
|
efaf3c3bf9 | ||
|
|
0e4e6a6f67 | ||
|
|
42458e6278 | ||
|
|
41ec995377 | ||
|
|
4f37599326 | ||
|
|
4144520e5c | ||
|
|
6c4800546c | ||
|
|
733733c8a7 | ||
|
|
2aa67cc946 | ||
|
|
9385981a9d | ||
|
|
fff780035d | ||
|
|
46127e673d | ||
|
|
70df59b224 | ||
|
|
0fdbaa803f | ||
|
|
6af1830eff | ||
|
|
6f860e2bd5 | ||
|
|
20a492f7ee | ||
|
|
63875e7591 | ||
|
|
0ad98cabde | ||
|
|
668879d2e1 | ||
|
|
2e09783302 | ||
|
|
49734114b3 | ||
|
|
950d9d6ee7 | ||
|
|
f7974aee2e | ||
|
|
c870a82621 | ||
|
|
984929a001 | ||
|
|
7f9e2c1db8 | ||
|
|
324e8389dc | ||
|
|
6f448c5a38 | ||
|
|
ec43efbb20 | ||
|
|
3ed065de37 | ||
|
|
8152f0d72c | ||
|
|
f8047f4736 | ||
|
|
b93c66dc2d | ||
|
|
ac877b3065 | ||
|
|
dee8abfdde | ||
|
|
cef3841d73 | ||
|
|
3cd5e8a041 | ||
|
|
515b5f866e | ||
|
|
321f62bf92 | ||
|
|
f94fa47b52 | ||
|
|
c502f8a722 | ||
|
|
59b4868ac3 | ||
|
|
3634e12cce | ||
|
|
6d45445391 | ||
|
|
4f47e268cc | ||
|
|
0035b31cdb | ||
|
|
f2565aee03 | ||
|
|
5bd85668dd | ||
|
|
20f990b6ce | ||
|
|
6821379586 | ||
|
|
73b040eb49 | ||
|
|
49aa4b2e1e | ||
|
|
972241c74c | ||
|
|
680750e3c2 | ||
|
|
5e7d4d9d15 | ||
|
|
1e57e60613 | ||
|
|
3ac7ce605a | ||
|
|
b720dea9f0 | ||
|
|
c80722aefe | ||
|
|
a84fa69f28 | ||
|
|
e33781e59f | ||
|
|
8824bc7ece | ||
|
|
c2e3b0e448 | ||
|
|
f61a38e85a | ||
|
|
d23e948216 | ||
|
|
58bdaa31f0 | ||
|
|
b6491d88a6 | ||
|
|
f6061ba62e | ||
|
|
427899ddce | ||
|
|
c4ab7d2dbd | ||
|
|
0fd2ba033f | ||
|
|
ed38939a93 | ||
|
|
c7ee26ce5a | ||
|
|
909b8cb303 | ||
|
|
b0277370cf | ||
|
|
2ec8656bea | ||
|
|
b2ef256910 | ||
|
|
63d6ce95db | ||
|
|
a9532b189c | ||
|
|
844545411f | ||
|
|
4e23a2b9b8 | ||
|
|
5deba027eb | ||
|
|
fc8b7efc6f | ||
|
|
a1c2d9c0f3 | ||
|
|
4ca49a0501 | ||
|
|
493c53d090 | ||
|
|
b27e956d35 | ||
|
|
35ebed75c6 | ||
|
|
7bfdb5f77f | ||
|
|
8d8c02317f | ||
|
|
a34482feab | ||
|
|
cbdc8fd4a6 | ||
|
|
8d3afaa53c | ||
|
|
7ced9ef3df | ||
|
|
e8a9ae7e80 | ||
|
|
73a88ab3d3 | ||
|
|
aaed82738a | ||
|
|
de7f7b96db | ||
|
|
1a669b3e68 | ||
|
|
333af9b13a | ||
|
|
a5bca5e240 | ||
|
|
c885633e02 | ||
|
|
ca7e20b7ca | ||
|
|
545e11a3d7 | ||
|
|
44f5287664 | ||
|
|
cf510897f1 | ||
|
|
1d171345f8 | ||
|
|
4fa7e1cd49 | ||
|
|
acd008298e | ||
|
|
83a8021515 | ||
|
|
cf88dfb1db | ||
|
|
8937c4b481 | ||
|
|
cc6af10a4d | ||
|
|
6d94578955 | ||
|
|
08442ab71e | ||
|
|
10d91d213f | ||
|
|
b7a3b06994 | ||
|
|
5f12c37f23 | ||
|
|
585edebccd | ||
|
|
9921c62234 | ||
|
|
1ac76d2e16 | ||
|
|
6e983bf400 | ||
|
|
6a8fd4fa6e | ||
|
|
3698eaa2d2 | ||
|
|
8d97ca433c | ||
|
|
23cc65e537 | ||
|
|
2f5a3c2bbe | ||
|
|
f6485616cd | ||
|
|
6544fb43d9 | ||
|
|
a954b32dcc | ||
|
|
426dc7836c | ||
|
|
ff941ffc16 | ||
|
|
a063c201df | ||
|
|
e2be3fa0aa | ||
|
|
609da6fb50 | ||
|
|
fc9f3ccec3 | ||
|
|
f7baa67a0a | ||
|
|
e8d78c2cdb | ||
|
|
9d33366092 | ||
|
|
f5d61515c2 | ||
|
|
711a04a972 | ||
|
|
e5b470a3f1 | ||
|
|
31820e1e22 | ||
|
|
4849e8cd6d | ||
|
|
77e3b460aa | ||
|
|
b5321001f8 | ||
|
|
38eba9f5ea | ||
|
|
ea6f399454 | ||
|
|
f8bf2d7b7d | ||
|
|
c4856caebb | ||
|
|
fc1030bb22 | ||
|
|
9eb6cad8dc | ||
|
|
0fa2a78dce | ||
|
|
a56fa1558b | ||
|
|
261c73a997 | ||
|
|
929c1333ca | ||
|
|
286a79d94d | ||
|
|
8b951f99da | ||
|
|
abb449bca0 | ||
|
|
bd084028d1 | ||
|
|
138a27570b | ||
|
|
c2ed40a74f | ||
|
|
a7e7a00cab | ||
|
|
64a31ab3cd | ||
|
|
71958bc0f1 | ||
|
|
366ec35612 | ||
|
|
3738f6e8ae | ||
|
|
051a8e2af1 | ||
|
|
2f43f28d5e | ||
|
|
b64769754b | ||
|
|
a97daa18d1 | ||
|
|
b6556dce8b | ||
|
|
aa8d8bc8b5 | ||
|
|
0800dcfdc4 | ||
|
|
12b0101e94 | ||
|
|
021b391a02 | ||
|
|
d11e2b6057 | ||
|
|
264d90e7e5 | ||
|
|
f9f3da9e78 | ||
|
|
6435b49153 | ||
|
|
f9aa2941cf | ||
|
|
5a933d4bee | ||
|
|
5536aea0df | ||
|
|
976666d216 | ||
|
|
9a5bcd4392 | ||
|
|
812060a118 | ||
|
|
089b5052e6 | ||
|
|
874e5d72f4 | ||
|
|
6b11de1329 | ||
|
|
2245a7ad8d | ||
|
|
ee5ec1b870 | ||
|
|
74ccfe851b | ||
|
|
e1c24bd5a2 | ||
|
|
1349b79728 | ||
|
|
d294d7604c | ||
|
|
01df2cf464 | ||
|
|
45b7322488 | ||
|
|
b3055e992f | ||
|
|
3da548565c | ||
|
|
a975e85548 | ||
|
|
c4b5ade752 | ||
|
|
a4b61b0794 | ||
|
|
f6011184b8 | ||
|
|
74de118c6e | ||
|
|
9c25e77c17 | ||
|
|
440113e67e | ||
|
|
a11b60c445 | ||
|
|
a6052681ad | ||
|
|
482d50536a | ||
|
|
25c79a4fcd | ||
|
|
02946144ac | ||
|
|
71a360e9a3 | ||
|
|
f7912d88b1 | ||
|
|
975101d7d2 | ||
|
|
ef58c5ff55 | ||
|
|
e10221804a | ||
|
|
284ed9ee0e | ||
|
|
5d7b961997 | ||
|
|
c699a5c4b4 | ||
|
|
1f4ceb89cf | ||
|
|
0934ca0040 | ||
|
|
4738f892c2 | ||
|
|
33004fcf33 | ||
|
|
34d214c166 | ||
|
|
a56cd92a1e | ||
|
|
7251348507 | ||
|
|
01cd5c84d6 | ||
|
|
e210599fa6 | ||
|
|
dbe7cee7e9 | ||
|
|
7370d88ceb | ||
|
|
34458e0c57 | ||
|
|
05c8c3abf2 | ||
|
|
e9d464b4d3 | ||
|
|
6968c3ab9b | ||
|
|
131a8a9650 | ||
|
|
379ecbf9a9 | ||
|
|
7b9dfa9a28 | ||
|
|
fbd0f5eed2 | ||
|
|
5970f904ae | ||
|
|
8cbcb2868d | ||
|
|
8ff2a4b026 | ||
|
|
ae14d205a5 | ||
|
|
ec5d560ec5 | ||
|
|
fb543b53c0 | ||
|
|
39c16422e2 | ||
|
|
4d5b273ebe | ||
|
|
ed6a860fad | ||
|
|
423e579292 | ||
|
|
ee11aa9e75 | ||
|
|
c46d20fa92 | ||
|
|
dc8d17574c | ||
|
|
5c17cd04c8 | ||
|
|
67ada02076 | ||
|
|
32d94c2eaf | ||
|
|
687b39a12a | ||
|
|
705af407bf | ||
|
|
080052da2e | ||
|
|
ef735fd92a | ||
|
|
17c16dcafc | ||
|
|
a89b3018fb | ||
|
|
851e2ebd32 | ||
|
|
1225ce7fe8 | ||
|
|
7e77a31b96 | ||
|
|
d146b9002f | ||
|
|
1f9d567b23 | ||
|
|
ed1b3a023c | ||
|
|
1ca18f501a | ||
|
|
49588ccd98 | ||
|
|
098dedc092 | ||
|
|
b06f6b9545 | ||
|
|
ba3cb94999 | ||
|
|
74c67fbf4b | ||
|
|
32b46e4910 | ||
|
|
ecf5539ed2 | ||
|
|
ac9db4e4d5 | ||
|
|
0eb96094b0 | ||
|
|
30b3ac7dc5 | ||
|
|
0092790c7d | ||
|
|
28909d8a51 | ||
|
|
b20cfbb7b6 | ||
|
|
97639bd0a8 | ||
|
|
161ec73c96 | ||
|
|
957d6bea15 | ||
|
|
f8b6e5b414 | ||
|
|
1ab450870e | ||
|
|
de45f4884c | ||
|
|
5da1f3e7c8 | ||
|
|
983014952b | ||
|
|
55298019a3 | ||
|
|
a1ffc3f271 | ||
|
|
2fb60aa997 | ||
|
|
f5ec76537a | ||
|
|
728491fd2b | ||
|
|
d9d3f2b9e4 | ||
|
|
3fe4864f65 | ||
|
|
0b156f22a4 | ||
|
|
35b1d93813 | ||
|
|
d770851ac0 | ||
|
|
989e7b1033 | ||
|
|
c4e0eb7b49 | ||
|
|
71f5d0dac7 | ||
|
|
561b0c4381 | ||
|
|
995fbc7330 | ||
|
|
10ab8949c4 | ||
|
|
c441202fea | ||
|
|
ca261b0bee | ||
|
|
52f3709f67 | ||
|
|
c2ca6187fe | ||
|
|
671a13d295 | ||
|
|
14c3e2eccf | ||
|
|
08e5b852c2 | ||
|
|
1c9606c824 | ||
|
|
3cd47b5c9b | ||
|
|
aedc729087 | ||
|
|
5f7cfa3fa9 | ||
|
|
0083f30af5 | ||
|
|
4a06f05ef5 | ||
|
|
8f37cadce8 | ||
|
|
a11603ca6c | ||
|
|
86274842e9 | ||
|
|
cf9c955a44 | ||
|
|
55d828c35f | ||
|
|
cdff28aca6 | ||
|
|
b9da39274f | ||
|
|
c379aa5782 | ||
|
|
9dcabac9dd | ||
|
|
794f3a2b9f | ||
|
|
2066121b7c | ||
|
|
0c4067f143 | ||
|
|
8aa69243b7 | ||
|
|
8697263bde | ||
|
|
ea25c4f65c | ||
|
|
82ac3ebd7e | ||
|
|
13cb94909c | ||
|
|
b57ca2a763 | ||
|
|
83c49e9745 | ||
|
|
e15771d78d | ||
|
|
6edc4920ba | ||
|
|
302bb1bd93 | ||
|
|
529b1bceee | ||
|
|
42cd47d32e | ||
|
|
711d884c2e | ||
|
|
183d1c4674 | ||
|
|
faed63a0bb | ||
|
|
53bff262f8 | ||
|
|
3251a708e4 | ||
|
|
b5dbdbf7b2 | ||
|
|
a9649e92c9 | ||
|
|
b561f1fa8b | ||
|
|
cecd7491b5 | ||
|
|
55a66322b5 | ||
|
|
155c31a2d7 | ||
|
|
a89ce91089 | ||
|
|
b897fe6700 | ||
|
|
548a351b06 | ||
|
|
4b1da57ca1 | ||
|
|
529aec7f25 | ||
|
|
1661e545cb | ||
|
|
ec71d08878 | ||
|
|
ac258b7dd7 | ||
|
|
0f57876233 | ||
|
|
1d25a3693d | ||
|
|
45fa428bf1 | ||
|
|
177fa80f1a | ||
|
|
3261261bfe | ||
|
|
d4de7934f8 | ||
|
|
c3475af809 | ||
|
|
b12f707812 | ||
|
|
22c0c34d60 | ||
|
|
a60b66f230 | ||
|
|
83f6e93628 | ||
|
|
222b5f0229 | ||
|
|
30aa383e26 | ||
|
|
676b401294 | ||
|
|
ebf57159de | ||
|
|
199d2aafec | ||
|
|
81952f56fd | ||
|
|
c5bac82b43 | ||
|
|
081b86109c | ||
|
|
8ac2028a75 | ||
|
|
264fed1c9f | ||
|
|
dd59f7b2c7 | ||
|
|
9245a760db | ||
|
|
b61b32bbc3 | ||
|
|
09b3914f5d | ||
|
|
fe644e4c9e | ||
|
|
7b09bf2156 | ||
|
|
987d0aae66 | ||
|
|
9cbcbc1c22 | ||
|
|
cfc4e2bc60 | ||
|
|
a03405fa81 | ||
|
|
d5c9ccbe6e | ||
|
|
e52772d65f | ||
|
|
1e3259e728 | ||
|
|
e905a20a60 | ||
|
|
88e2be7a33 | ||
|
|
8939131600 | ||
|
|
ba37ebff8b | ||
|
|
28f4cb7e07 | ||
|
|
db1e7102cd | ||
|
|
07eb7a5830 | ||
|
|
b7c6c685fa | ||
|
|
212134df70 | ||
|
|
6eeb5528f5 | ||
|
|
54fad845c9 | ||
|
|
d6c0de6fc7 | ||
|
|
649c8649f7 | ||
|
|
da2f53d1b1 | ||
|
|
405139e3b8 | ||
|
|
4f8d347171 | ||
|
|
bf0db4876c | ||
|
|
47a14884d6 | ||
|
|
3a7bbc8b08 | ||
|
|
1b1d65372c | ||
|
|
fd2faaa16e | ||
|
|
0609cdb9ea | ||
|
|
d3bb140f89 | ||
|
|
b31dc66628 | ||
|
|
09476171a6 | ||
|
|
33dee813b5 | ||
|
|
bb4e73c40b | ||
|
|
b1f23ffa94 | ||
|
|
b0e8cec1e7 | ||
|
|
5077ae19bc | ||
|
|
0d8447bf59 | ||
|
|
c6cf08a274 | ||
|
|
dc49ae519e | ||
|
|
904539476a | ||
|
|
3fbf02dc82 | ||
|
|
c9392a840d | ||
|
|
d164e8ab72 | ||
|
|
6dc62c9fb6 | ||
|
|
87a9684d66 | ||
|
|
94525e2f44 | ||
|
|
b408b1b3b9 | ||
|
|
27c2f09e32 | ||
|
|
19bc4d3349 | ||
|
|
f2b6c424d6 | ||
|
|
a49d4453e9 | ||
|
|
65e50087b9 | ||
|
|
2d90f759d9 | ||
|
|
4230ac7674 | ||
|
|
d96e9182e9 | ||
|
|
68c87b9616 | ||
|
|
7f8e9a0b6d | ||
|
|
81a229f2a5 | ||
|
|
8be7ae2733 | ||
|
|
846bca4cb1 | ||
|
|
f36f353789 | ||
|
|
939a2731ed | ||
|
|
835dab97ff | ||
|
|
fa904b53be | ||
|
|
0ec52dddce | ||
|
|
c289355a3a | ||
|
|
02a13a5a18 | ||
|
|
6cf2a0281b | ||
|
|
120d35f9af | ||
|
|
2b15d5e7b3 | ||
|
|
fc167bd3f0 | ||
|
|
91b04abf05 | ||
|
|
77faac8740 | ||
|
|
43b3d54855 | ||
|
|
69e9b85700 | ||
|
|
0b6d132759 | ||
|
|
7c233c6c0c | ||
|
|
c35b290fa4 | ||
|
|
3d95cfb367 | ||
|
|
b90fc3a56e | ||
|
|
1ef3fdccf5 | ||
|
|
02b7f77bd8 | ||
|
|
0ac7ead922 | ||
|
|
da9d0e03ce | ||
|
|
120f65f672 | ||
|
|
200a14caa4 | ||
|
|
35bf6da8e2 | ||
|
|
f08f70276c | ||
|
|
1ae50fd95b | ||
|
|
40512beb47 | ||
|
|
0d7f9b2c94 | ||
|
|
52f42140a7 | ||
|
|
3f6c50297f | ||
|
|
f72d80afc5 | ||
|
|
7c5cb13b22 | ||
|
|
d728750eb2 | ||
|
|
02a70e5667 | ||
|
|
44e51ea5fa | ||
|
|
87e201460a | ||
|
|
039bd945e2 | ||
|
|
e9e52d2b4b | ||
|
|
2bf92e7399 | ||
|
|
5b0df241f0 | ||
|
|
76f5b05eff | ||
|
|
40fb6c998f | ||
|
|
33f50a342d | ||
|
|
81523ab68a | ||
|
|
2bf8cc62cf | ||
|
|
1ae8247af3 | ||
|
|
5ef32227ec | ||
|
|
6456e773bd | ||
|
|
234fe53ca3 | ||
|
|
7c93e7a7b3 | ||
|
|
8afc6c7f4b | ||
|
|
4609d0fa3a | ||
|
|
d452c035c6 | ||
|
|
45113c8f5a | ||
|
|
0acdd3c62b | ||
|
|
96d7d0a33e | ||
|
|
b6b280267b | ||
|
|
6e6d253b1a | ||
|
|
d92c105db2 | ||
|
|
906db728d6 | ||
|
|
c4b7411565 | ||
|
|
de06396046 | ||
|
|
ee6bfeb8e3 | ||
|
|
058347321f | ||
|
|
feefe49324 | ||
|
|
187381a9a2 | ||
|
|
993dfa4368 | ||
|
|
7e35a16440 | ||
|
|
e4eeb15926 | ||
|
|
634e0db26d | ||
|
|
56855c23e1 | ||
|
|
0b00f742e3 | ||
|
|
b7ab3f673c | ||
|
|
be04ea1e35 | ||
|
|
1f8e695802 | ||
|
|
2d82b2c64f | ||
|
|
d076caf473 | ||
|
|
c7abdefa31 | ||
|
|
ba772c0bca | ||
|
|
5bad234119 | ||
|
|
c7e7baaf23 | ||
|
|
36658a671b | ||
|
|
045f2e10ba | ||
|
|
fb5a7db66d | ||
|
|
ba7d33982e | ||
|
|
c62279a755 | ||
|
|
17fa1a7ffb | ||
|
|
e89ceac351 | ||
|
|
0b8c30c109 | ||
|
|
9ab0f463cc | ||
|
|
6433dda7b8 | ||
|
|
fa7a2f4be4 | ||
|
|
ba90e16505 | ||
|
|
008f710203 | ||
|
|
df2740f126 | ||
|
|
2db89d143e | ||
|
|
0525d49da3 | ||
|
|
e2b0745882 | ||
|
|
92e804fc50 | ||
|
|
67abf45576 | ||
|
|
d2c9c814e7 | ||
|
|
22f8881a64 | ||
|
|
4ab20322fe | ||
|
|
5370eeecea | ||
|
|
ba71cb5dd7 | ||
|
|
9aad6c2c52 | ||
|
|
4d9627f20c | ||
|
|
c142492e91 | ||
|
|
6bf8d9e207 | ||
|
|
4f9a6168c1 | ||
|
|
38397f99aa | ||
|
|
f8686d0e75 | ||
|
|
549e3c8f9d | ||
|
|
bb56225b95 | ||
|
|
f00be261ba | ||
|
|
9cd94f26d0 | ||
|
|
4d8f5c80a7 | ||
|
|
24a23acc3d | ||
|
|
ca8703cfd8 | ||
|
|
6dcbb5b2f8 | ||
|
|
a84fdddb2a | ||
|
|
38bb2f8ceb | ||
|
|
23f5ef4345 | ||
|
|
ef8a2a9054 | ||
|
|
96103d0e36 | ||
|
|
ff5f6748df | ||
|
|
1c1fd6c366 | ||
|
|
32d37d00cb | ||
|
|
82f6cda966 | ||
|
|
f1ff8ff0d0 | ||
|
|
756c72902f | ||
|
|
73f8f0bbd0 | ||
|
|
18ed528f5d | ||
|
|
8fd2f136bc | ||
|
|
0524b1bf67 | ||
|
|
15716f65ce | ||
|
|
d46bdba332 | ||
|
|
760728110a | ||
|
|
12d0a194ca | ||
|
|
4104543508 | ||
|
|
5c211db015 | ||
|
|
2dc6180f8d | ||
|
|
e222a34b69 | ||
|
|
ef17d95063 | ||
|
|
853502e5d7 | ||
|
|
c18e297e77 | ||
|
|
c5a49599ba | ||
|
|
df9da9edf5 | ||
|
|
e2200fd050 | ||
|
|
c6207f5d9c | ||
|
|
4302b7ff6b | ||
|
|
50a7923438 | ||
|
|
ab416445c8 | ||
|
|
a54698d43c | ||
|
|
c5a77cc1c0 | ||
|
|
a9ffa811fc | ||
|
|
080a2608e0 | ||
|
|
57f2e83d6a | ||
|
|
5b030139d3 | ||
|
|
0da1ff42d1 | ||
|
|
2c599b7baa | ||
|
|
5c8af8d21a | ||
|
|
026f3cfde2 | ||
|
|
f6349180e8 | ||
|
|
aa6421921c | ||
|
|
7d41d2dab2 | ||
|
|
f0b4d18f93 | ||
|
|
6750f06e10 | ||
|
|
b2bd38fa9e | ||
|
|
3482a01e22 | ||
|
|
6335467552 | ||
|
|
4a39e65b62 | ||
|
|
c50a23e918 | ||
|
|
1e76b72b98 | ||
|
|
b94cf39eef | ||
|
|
fef254ffff | ||
|
|
e5495863a2 | ||
|
|
3b4df2abf0 | ||
|
|
aef2aee6a4 | ||
|
|
d0d9519149 | ||
|
|
685df1d2c5 | ||
|
|
08e6b6f2e7 | ||
|
|
66c887d0f3 | ||
|
|
22e9960697 | ||
|
|
64aa6e1f2d | ||
|
|
7a93ed9d04 | ||
|
|
a905e922e9 | ||
|
|
f9f08fc720 | ||
|
|
8d402d76d0 | ||
|
|
46fda6281c | ||
|
|
a14dbe1ea6 | ||
|
|
18810a4c16 | ||
|
|
147bc80dba | ||
|
|
c7a484195a | ||
|
|
4968eb6503 | ||
|
|
a6f2d698a9 | ||
|
|
ea5ed93ea5 | ||
|
|
e1140134c6 | ||
|
|
5ed11e012e | ||
|
|
5380bd39ca | ||
|
|
2ee2685688 | ||
|
|
782002245b | ||
|
|
7fc0905843 | ||
|
|
72ecb99e54 | ||
|
|
c863507d08 | ||
|
|
cff86c9093 | ||
|
|
0479dfcc54 | ||
|
|
68dd67f21c | ||
|
|
540f6858b5 | ||
|
|
b61e791a4f | ||
|
|
d0986f9482 | ||
|
|
112cb0dc28 | ||
|
|
0d3d7fdcf2 | ||
|
|
5d6b89ef3b | ||
|
|
ed0b26c09e | ||
|
|
ae292bd920 | ||
|
|
6c85a90723 | ||
|
|
852592066c | ||
|
|
96e1bc9b44 | ||
|
|
b41d81ed31 | ||
|
|
e241ec2244 | ||
|
|
16e1f1a94c | ||
|
|
7a68c42b26 | ||
|
|
37ccc2e118 | ||
|
|
4192fe1ab2 | ||
|
|
d5c743d7bb | ||
|
|
11814d63e8 | ||
|
|
b753656d50 | ||
|
|
f7e87611fc | ||
|
|
1fb0e1900e | ||
|
|
954a9731e0 | ||
|
|
65c3364ad8 | ||
|
|
3d72b7dccc | ||
|
|
13ee569f06 | ||
|
|
d79ef23a75 | ||
|
|
5d0797d4ba | ||
|
|
47a8d7475f | ||
|
|
4939053121 | ||
|
|
b525bf554e | ||
|
|
f00285d2b2 | ||
|
|
040f8d6eda | ||
|
|
66d905325c | ||
|
|
8b0cd95e73 | ||
|
|
d867cca6d9 | ||
|
|
a28f736369 | ||
|
|
5c3a71cc59 | ||
|
|
cef6dadb08 | ||
|
|
36be817a3e | ||
|
|
02f571f081 | ||
|
|
157159e487 | ||
|
|
02ada9f800 | ||
|
|
6fcf9a97bb | ||
|
|
17a5d8799f | ||
|
|
31f3fe7a22 | ||
|
|
89e46d3d83 | ||
|
|
885795e67d | ||
|
|
92bfb53dd4 | ||
|
|
4cecbeb115 | ||
|
|
5971480f55 | ||
|
|
05bebea511 | ||
|
|
76fa6c5cfb | ||
|
|
633b68b518 | ||
|
|
6913d8e995 | ||
|
|
f3654e6f8d | ||
|
|
d685dbcf22 | ||
|
|
6a57fa079e | ||
|
|
0a91d145ba | ||
|
|
c2866e799d | ||
|
|
d8cffcaae7 | ||
|
|
30abca7be2 | ||
|
|
edce87f3fb | ||
|
|
66bac98fc2 | ||
|
|
59156de92b | ||
|
|
e0d7d10600 | ||
|
|
daaf862257 | ||
|
|
9de53d4b59 | ||
|
|
f1571e2d46 | ||
|
|
bd28d06298 | ||
|
|
a24e4655eb | ||
|
|
20a6c8d8e5 | ||
|
|
98d264faf4 | ||
|
|
321902a9b5 | ||
|
|
8df5d06f9a | ||
|
|
e69ea529cc | ||
|
|
15405b1119 | ||
|
|
d2f97ce2da | ||
|
|
543ca631e9 | ||
|
|
f184886db1 | ||
|
|
8432ab4324 | ||
|
|
6c05b37ca3 | ||
|
|
35f4beeb47 | ||
|
|
cbad7caa68 | ||
|
|
b0388a4012 | ||
|
|
df3fab4d55 | ||
|
|
da49f88a03 | ||
|
|
e28feceb06 | ||
|
|
50496a164d | ||
|
|
6f1dce1572 | ||
|
|
6847776ae7 | ||
|
|
67bd53bdd8 | ||
|
|
e735abfdfd | ||
|
|
1de93a2d6d | ||
|
|
36f9e7c742 | ||
|
|
9462763bbb | ||
|
|
4ae0880ea6 | ||
|
|
6ae2b6c835 | ||
|
|
a0f180fd48 | ||
|
|
bf1cf89914 | ||
|
|
297a047fb4 | ||
|
|
52ffc15ffc | ||
|
|
e478c9c693 | ||
|
|
d004f28074 | ||
|
|
bc68ed8b1d | ||
|
|
04555ae650 | ||
|
|
e8f62085be | ||
|
|
f430bffe2a | ||
|
|
1f0520634f | ||
|
|
902d4c31fb | ||
|
|
17364ac09f | ||
|
|
0b889f8f81 | ||
|
|
40e349ff35 | ||
|
|
c943b1b1df | ||
|
|
912bc1d4e1 | ||
|
|
cacb1533a3 | ||
|
|
f0feaca9d7 | ||
|
|
b6656f171b | ||
|
|
6206ab3931 | ||
|
|
c35fc58b1f | ||
|
|
deed8abed7 | ||
|
|
7151ad23f0 | ||
|
|
0166d938af | ||
|
|
6194aeddb0 | ||
|
|
903dbf2c30 | ||
|
|
9380f9ff57 | ||
|
|
259ed95486 | ||
|
|
2ebc92681e | ||
|
|
195a1ffe13 | ||
|
|
a8c2978185 | ||
|
|
140f97a457 | ||
|
|
7f94445a1e | ||
|
|
82a89aec65 | ||
|
|
7e95110232 | ||
|
|
ec4aaaad89 | ||
|
|
1b790fde24 | ||
|
|
aaccea731e | ||
|
|
29e31d7610 | ||
|
|
aa51f4a98f | ||
|
|
e6ccd12f00 | ||
|
|
b134315df1 | ||
|
|
7f34dffa13 | ||
|
|
fa239e78c9 | ||
|
|
707a6c4d6a | ||
|
|
e5da303b43 | ||
|
|
84ccd66331 | ||
|
|
ad8cc2baea | ||
|
|
7c4cf70309 | ||
|
|
c3211e9b4f | ||
|
|
268d94c983 | ||
|
|
0bcacbba58 | ||
|
|
8cdc26add9 | ||
|
|
e0b2238886 | ||
|
|
369a2e4029 | ||
|
|
c4089e3b51 | ||
|
|
9e2e9bc5b8 | ||
|
|
a9e44426ed |
340
COPYING
Normal file
340
COPYING
Normal file
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
504
COPYING.LIB
Normal file
504
COPYING.LIB
Normal file
@@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
31
INSTALL
Normal file
31
INSTALL
Normal file
@@ -0,0 +1,31 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
1) Generate custom makefiles.
|
||||
|
||||
Run the 'configure' script from the top directory.
|
||||
|
||||
If you don't want to include the LVM1 backwards-compatibility code use:
|
||||
./configure --with-lvm1=none
|
||||
|
||||
To separate the LVM1 support into a shared library loaded by lvm.conf use:
|
||||
./configure --with-lvm1=shared
|
||||
|
||||
Use ./configure --help to see other options.
|
||||
|
||||
2) Build and install.
|
||||
|
||||
Run 'make' from the top directory to build everything you configured.
|
||||
Run 'make install' to build and install everything you configured.
|
||||
|
||||
If you only want the device-mapper libraries and tools use
|
||||
'make device-mapper' or 'make install_device-mapper'.
|
||||
|
||||
3) If using LVM2, create a configuration file.
|
||||
|
||||
The tools will work fine without a configuration file being
|
||||
present, but you ought to review the example file in doc/example.conf.
|
||||
|
||||
Please also refer to the WHATS_NEW file and the manual pages for the
|
||||
individual commands.
|
||||
|
||||
156
Makefile.in
Normal file
156
Makefile.in
Normal file
@@ -0,0 +1,156 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SUBDIRS = doc include man scripts
|
||||
|
||||
ifeq ("@UDEV_RULES@", "yes")
|
||||
SUBDIRS += udev
|
||||
endif
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
SUBDIRS += po
|
||||
endif
|
||||
|
||||
SUBDIRS += lib tools daemons libdm
|
||||
|
||||
ifeq ("@APPLIB@", "yes")
|
||||
SUBDIRS += liblvm
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS = doc include man scripts \
|
||||
lib tools daemons libdm \
|
||||
udev po liblvm test/api test
|
||||
endif
|
||||
DISTCLEAN_DIRS += lcov_reports*
|
||||
DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
|
||||
|
||||
include make.tmpl
|
||||
|
||||
libdm: include
|
||||
lib: libdm
|
||||
liblvm: lib
|
||||
daemons: lib tools
|
||||
tools: lib device-mapper
|
||||
po: tools daemons
|
||||
|
||||
lib.device-mapper: include.device-mapper
|
||||
libdm.device-mapper: include.device-mapper
|
||||
liblvm.device-mapper: include.device-mapper
|
||||
daemons.device-mapper: libdm.device-mapper
|
||||
tools.device-mapper: libdm.device-mapper
|
||||
device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
lib.pofile: include.pofile
|
||||
tools.pofile: lib.pofile
|
||||
daemons.pofile: lib.pofile
|
||||
po.pofile: tools.pofile daemons.pofile
|
||||
pofile: po.pofile
|
||||
endif
|
||||
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
tools.cflow: libdm.cflow lib.cflow
|
||||
daemons.cflow: tools.cflow
|
||||
cflow: include.cflow
|
||||
endif
|
||||
|
||||
ifneq ("@CSCOPE_CMD@", "")
|
||||
cscope.out:
|
||||
@CSCOPE_CMD@ -b -R -s$(top_srcdir)
|
||||
all: cscope.out
|
||||
endif
|
||||
DISTCLEAN_TARGETS += cscope.out
|
||||
|
||||
check check_cluster check_local: 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
|
||||
|
||||
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 $(top_srcdir)/$(basename $@) \
|
||||
-d $(basename $@) -c -o - | $(SED) \
|
||||
-e "s/\(dmeventd_lvm.[ch]\)/plugins\/lvm2\/\1/" \
|
||||
-e "s/\(dmeventd_mirror.c\)/plugins\/mirror\/\1/" \
|
||||
-e "s/\(dmeventd_snapshot.c\)/plugins\/snapshot\/\1/" \
|
||||
>$@
|
||||
|
||||
ifneq ("$(GENHTML)", "")
|
||||
lcov: $(LCOV_TRACES)
|
||||
$(RM) -r $(LCOV_REPORTS_DIR)
|
||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||
for i in $(LCOV_TRACES); do \
|
||||
test -s $$i && lc="$$lc $$i"; \
|
||||
done; \
|
||||
test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
|
||||
-o $(LCOV_REPORTS_DIR) $$lc
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifeq ("$(TESTING)", "yes")
|
||||
# testing and report generation
|
||||
RUBY=ruby1.9 -Ireport-generators/lib -Ireport-generators/test
|
||||
|
||||
.PHONEY: unit-test ruby-test test-programs
|
||||
|
||||
# FIXME: put dependencies on libdm and liblvm
|
||||
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
|
||||
29
README
29
README
@@ -1,2 +1,27 @@
|
||||
This is pretty much empty so far...if you can't see subdirectories,
|
||||
try 'cvs -f update'
|
||||
This tree contains the LVM2 and device-mapper tools and libraries.
|
||||
|
||||
For more information about LVM2 read the changelog in the WHATS_NEW file.
|
||||
Installation instructions are in INSTALL.
|
||||
|
||||
There is no warranty - see COPYING and COPYING.LIB.
|
||||
|
||||
Tarballs are available from:
|
||||
ftp://sources.redhat.com/pub/lvm2/
|
||||
|
||||
To access the CVS tree use:
|
||||
cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
|
||||
CVS password: cvs
|
||||
cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 co LVM2
|
||||
|
||||
Mailing list for general discussion related to LVM2:
|
||||
linux-lvm@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||
|
||||
Mailing list for LVM2 development, patches and commits:
|
||||
lvm-devel@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||
|
||||
Mailing list for device-mapper development, including kernel patches
|
||||
and multipath-tools:
|
||||
dm-devel@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/dm-devel
|
||||
|
||||
1
VERSION_DM
Normal file
1
VERSION_DM
Normal file
@@ -0,0 +1 @@
|
||||
1.02.62-cvs (2011-02-04)
|
||||
610
WHATS_NEW_DM
Normal file
610
WHATS_NEW_DM
Normal file
@@ -0,0 +1,610 @@
|
||||
Version 1.02.62 - 4th February 2011
|
||||
===================================
|
||||
Add configure --with-device-nodes-on=create for previous behaviour.
|
||||
Move creation of device nodes from 'create' to 'resume'.
|
||||
Add --addnodeonresume and --addnodeoncreate options to dmsetup.
|
||||
Add dm_task_set_add_node to libdevmapper to control dev node creation time.
|
||||
Add dm_task_secure_data to libdevmapper to wipe ioctl buffers in kernel.
|
||||
Log debug message when expected uevent is not generated.
|
||||
Only compile memory debugging code when DEBUG_MEM is set.
|
||||
Set DM_UDEV_DISABLE_OTHER_RULES_FLAG for suspended DM devices in udev rules.
|
||||
Begin a new pool object for each row in _output_as_rows() correctly.
|
||||
|
||||
Version 1.02.61 - 10th January 2011
|
||||
===================================
|
||||
Add DM_COOKIE_AUTO_CREATE to libdevmapper.h.
|
||||
Export DM_CONTROL_NODE_UMASK and use it while creating /dev/mapper/control.
|
||||
|
||||
Version 1.02.60 - 20th December 2010
|
||||
====================================
|
||||
Check for unlink failure in remove_lockfile() in dmeventd.
|
||||
Use dm_free for dm_malloc-ed areas in _clog_ctr/_clog_dtr in cmirrord.
|
||||
Use char* arithmetic in _process_all() & _targets() in dmsetup.
|
||||
Change dm_regex_create() API to accept const char * const *patterns.
|
||||
Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
|
||||
Detect existence of new SELinux selabel interface during configure.
|
||||
|
||||
Version 1.02.59 - 6th December 2010
|
||||
===================================
|
||||
Add backtraces to _process_mapper_dir and _create_and_load_v4 error paths.
|
||||
Remove superfluous checks for NULL before calling dm_free.
|
||||
|
||||
Version 1.02.58 - 22nd November 2010
|
||||
====================================
|
||||
Fix _output_field crash from field_id free with DEBUG_MEM. (1.02.57)
|
||||
|
||||
Version 1.02.57 - 8th November 2010
|
||||
===================================
|
||||
Fix regex optimiser not to ignore RHS of OR nodes in _find_leftmost_common.
|
||||
Add dmeventd -R to restart dmeventd without losing monitoring state. (1.02.56)
|
||||
Fix memory leak of field_id in _output_field function.
|
||||
Allocate buffer for reporting functions dynamically to support long outputs.
|
||||
|
||||
Version 1.02.56 - 25th October 2010
|
||||
===================================
|
||||
Return const pointer from dm_basename() in libdevmapper.
|
||||
Implement dmeventd -R to restart without state loss.
|
||||
Add dm_zalloc and use it and dm_pool_zalloc throughout.
|
||||
Add --setuuid to dmsetup rename.
|
||||
Add dm_task_set_newuuid to set uuid of mapped device post-creation.
|
||||
|
||||
Version 1.02.55 - 24th September 2010
|
||||
=====================================
|
||||
Fix the way regions are marked complete to avoid slow --nosync cmirror I/O.
|
||||
Add DM_REPORT_FIELD_TYPE_ID_LEN to libdevmapper.h.
|
||||
|
||||
Version 1.02.54 - 18th August 2010
|
||||
==================================
|
||||
Fix dm-mod autoloading logic to not assume control node is set correctly.
|
||||
Add dmeventd/executable to lvm.conf to test alternative dmeventd.
|
||||
Export dm_event_handler_set_dmeventd_path to override built-in dmeventd path.
|
||||
Generate libdevmapper-event exported symbols.
|
||||
Remove superfluous NULL pointer tests before dm_free from dmeventd.
|
||||
Assume dm-mod autoloading support is in kernel 2.6.36 and higher, not 2.6.35.
|
||||
Fix udev rules to support udev database content generated by older rules.
|
||||
Reinstate detection of inappropriate uevent with DISK_RO set and suppress it.
|
||||
Fix regex ttree off-by-one error.
|
||||
Add --enable-valgrind-pool to configure.
|
||||
Fix segfault in regex matcher with characters of ordinal value > 127.
|
||||
Fix 'void*' arithmetic warnings in dbg_malloc.c and libdm-iface.c.
|
||||
Wait for node creation before displaying debug info in dmsetup.
|
||||
Fix return status 0 for "dmsetup info -c -o help".
|
||||
Add check for kernel semaphore support and disable udev_sync if not available.
|
||||
|
||||
Version 1.02.53 - 28th July 2010
|
||||
================================
|
||||
Revert failed table load preparation after "create, load and resume".
|
||||
Switch dmeventd to use dm_create_lockfile and drop duplicate code.
|
||||
Add dm_create_lockfile to libdm to handle pidfiles for all daemons.
|
||||
Replace lookup with next in struct dfa_state & calculate states on demand.
|
||||
Improve the regex matcher, reducing the number of charset nodes used.
|
||||
Add dm_regex_fingerprint to facilitate regex testing.
|
||||
Skip ffs(0) in _test_word in bitset functions.
|
||||
Use "nowatch" udev rule for inappropriate devices.
|
||||
|
||||
Version 1.02.52 - 6th July 2010
|
||||
===============================
|
||||
Fix dmlosetup snprintf %llu compiler warning.
|
||||
Add parentheses to some libdevmapper.h macro arguments.
|
||||
Add printf format attributes to dm_{sn,as}printf and fix a caller.
|
||||
Move dmeventd man page from install_lvm2 to install_device-mapper. (1.02.50)
|
||||
|
||||
Version 1.02.51 - 30th June 2010
|
||||
================================
|
||||
Generate libdevmapper exported symbols from header file.
|
||||
|
||||
Version 1.02.50 - 23rd June 2010
|
||||
================================
|
||||
Fix INTERNAL_ERROR typo in ioctl iface unknown task message.
|
||||
Fix udev rules to handle spurious events properly.
|
||||
Use C99 [] not [0] in dm_ulog_request struct to avoid abort when fortified.
|
||||
Allow use of devmapper header file in C++ mode (extern "C" and __typeof__).
|
||||
Add dmeventd man page.
|
||||
|
||||
Version 1.02.49 - 4th June 2010
|
||||
===============================
|
||||
Support autoloading of dm-mod module for kernels from 2.6.35.
|
||||
Document 'clear' in dmsetup man page.
|
||||
Fix semctl parameter (union) to avoid misaligned parameter on some arches.
|
||||
Add dm_tree_node_set_presuspend_node() to presuspend child when deactivating.
|
||||
Initial support for replicator target.
|
||||
|
||||
Version 1.02.48 - 17th May 2010
|
||||
================================
|
||||
Use -d to control level of messages sent to syslog by dmeventd.
|
||||
Change -d to -f to run dmeventd in foreground.
|
||||
Do not print encryption key in message debug output (cryptsetup luksResume).
|
||||
Fix dmeventd static build library dependencies.
|
||||
Fix udev flags on remove in create_and_load error path.
|
||||
|
||||
Version 1.02.47 - 30th April 2010
|
||||
=================================
|
||||
Add support for new IMPORT{db} udev rule.
|
||||
Add DM_UDEV_PRIMARY_SOURCE_FLAG udev flag to recognize proper DM events.
|
||||
Also include udev libs in libdevmapper.pc when udev_sync is enabled.
|
||||
Cache bitset locations to speed up _calc_states.
|
||||
Add a regex optimisation pass for shared prefixes and suffixes.
|
||||
Add dm_bit_and and dm_bitset_equal to libdevmapper.
|
||||
Simplify dm_bitset_create.
|
||||
Speed up dm_bit_get_next with ffs().
|
||||
|
||||
Version 1.02.46 - 14th April 2010
|
||||
=================================
|
||||
Change dm_tree_deactivate_children to fail if device is open.
|
||||
Wipe memory buffers for dm-ioctl parameters before releasing.
|
||||
Strictly require libudev if udev_sync is used.
|
||||
Add support for ioctl's DM_UEVENT_GENERATED_FLAG.
|
||||
|
||||
Version 1.02.45 - 9th March 2010
|
||||
================================
|
||||
Add --showkeys parameter description to dmsetup man page.
|
||||
Add --help option as synonym for help command.
|
||||
|
||||
Version 1.02.44 - 15th February 2010
|
||||
====================================
|
||||
Add DM_UDEV_DISABLE_LIBRARY_FALLBACK udev flag to rely on udev only.
|
||||
Export dm_udev_create_cookie function to create new cookies on demand.
|
||||
Add --udevcookie, udevcreatecookie and udevreleasecookie to dmsetup.
|
||||
Set udev state automatically instead of using DM_UDEV_DISABLE_CHECKING.
|
||||
|
||||
Version 1.02.43 - 21st January 2010
|
||||
===================================
|
||||
Remove bitset, hash and pool headers superceded by libdevmapper.h.
|
||||
Fix off-by-one error causing bad cluster mirror table construction.
|
||||
|
||||
Version 1.02.42 - 14th January 2010
|
||||
===================================
|
||||
Add support for the "snapshot-merge" kernel target (2.6.33-rc1).
|
||||
Introduce a third activation_priority level in dm_tree_activate_children.
|
||||
|
||||
Version 1.02.41 - 12th January 2010
|
||||
===================================
|
||||
If DM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings.
|
||||
Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags.
|
||||
Add --noudevrules option for dmsetup to disable /dev node management by udev.
|
||||
Fix 'dmsetup info -c -o all' to show all fields.
|
||||
Return errors if dm_tree_*_children functions fail.
|
||||
Fix coredump and memory leak for 'dmsetup help -c'.
|
||||
Disable udev rules for change events with DISK_RO set.
|
||||
|
||||
Version 1.02.40 - 19th November 2009
|
||||
====================================
|
||||
Fix install_device-mapper Makefile target to not build dmeventd plugins.
|
||||
Support udev flags even when udev_sync is disabled or not compiled in.
|
||||
Remove 'last_rule' from udev rules: honour DM_UDEV_DISABLE_OTHER_RULES_FLAG.
|
||||
Add dmsetup --inactive support.
|
||||
Add dm_task_query_inactive_table to libdevmapper for kernel driver >= 4.16.
|
||||
Fix hash lookup segfault when keys compared are different lengths.
|
||||
|
||||
Version 1.02.39 - 26th October 2009
|
||||
===================================
|
||||
Remove strict default permissions for DM devices from 95-dm-notify.rules.
|
||||
Add dmsetup udevflags command to decode udev flags in given cookie value.
|
||||
Support udev flags in libdevmapper incl. dm_tree_add_new_dev_with_udev_flags.
|
||||
Make libdm ABI consistent when built with/without selinux support.
|
||||
|
||||
Version 1.02.38 - 25th September 2009
|
||||
=====================================
|
||||
Export DM_DEV_DIR_UMASK, the default umask for /dev directories created.
|
||||
Handle any path supplied to dm_task_set_name by looking up in /dev/mapper.
|
||||
Add several examples to 12-dm-permissions.rules.
|
||||
Add splitname and --yes to dmsetup man page.
|
||||
Fix _mirror_emit_segment_line return code.
|
||||
Fix dmeventd _temporary_log_fn parameters. (2.02.50)
|
||||
|
||||
Version 1.02.37 - 15th September 2009
|
||||
=====================================
|
||||
Add dmsetup manpage entries for udevcomplete_all and udevcookies.
|
||||
Check udev is running when processing cookies and retain state internally.
|
||||
Add y|--yes option to dmsetup for default 'yes' answer to prompts.
|
||||
Fix tools Makefile to process dmsetup sources separately.
|
||||
Restore umask when device node creation fails.
|
||||
Check kernel vsn to use 'block_on_error' or 'handle_errors' in mirror table.
|
||||
Add dm-log-userspace.h to tree for cmirrord builds.
|
||||
|
||||
Version 1.02.36 - 6th August 2009
|
||||
=================================
|
||||
Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
|
||||
Add libdevmapper functions to support synchronisation with udev.
|
||||
|
||||
Version 1.02.35 - 28th July 2009
|
||||
================================
|
||||
Add LOG_LINE_WITH_ERRNO macro.
|
||||
Use log_error macro consistently throughout in place of log_err.
|
||||
|
||||
Version 1.02.34 - 15th July 2009
|
||||
================================
|
||||
Use _exit() not exit() after forking to avoid flushing libc buffers twice.
|
||||
Rename plog macro to LOG_LINE & add LOG_MESG variant for dm_dump_memory_debug.
|
||||
Change plog to use dm_log_with_errno unless deprecated dm_log_init was used.
|
||||
Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns.
|
||||
Fix whitespace in linear target line to fix identical table line detection.
|
||||
Add device number to more log messages during activation.
|
||||
|
||||
Version 1.02.33 - 30th June 2009
|
||||
================================
|
||||
Don't fallback to default major number: use dm_task_set_major_minor. (1.02.31)
|
||||
Do not fork daemon when dmeventd cannot be found.
|
||||
Add crypt target handling to libdevmapper tree nodes.
|
||||
Add splitname command to dmsetup.
|
||||
Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports.
|
||||
Make mempool optional in dm_split_lvm_name().
|
||||
|
||||
Version 1.02.32 - 21st May 2009
|
||||
===============================
|
||||
Only generate libdevmapper.a when configured to link statically.
|
||||
Export dm_tree_node_size_changed() from libdevmapper.
|
||||
Propagate the table size_changed property up the dm device tree.
|
||||
Detect failure to free memory pools when releasing the library.
|
||||
Fix segfault when getopt processes dmsetup -U, -G and -M options.
|
||||
|
||||
Version 1.02.31 - 3rd March 2009
|
||||
================================
|
||||
If kernel supports only one dm major number, use in place of any supplied.
|
||||
|
||||
Version 1.02.30 - 26th January 2009
|
||||
====================================
|
||||
Add "all" field to reports expanding to all fields of report type.
|
||||
Enforce device name length and character limitations in libdm.
|
||||
Replace _dm_snprintf with EMIT_PARAMS macro for creating target lines.
|
||||
|
||||
Version 1.02.29 - 10th November 2008
|
||||
====================================
|
||||
Merge device-mapper into the LVM2 tree.
|
||||
Split out dm-logging.h from log.h.
|
||||
Use lvm-types.h.
|
||||
Add usrsbindir to configure.
|
||||
|
||||
Version 1.02.28 - 18th September 2008
|
||||
=====================================
|
||||
Only resume devices in dm_tree_preload_children if size changes.
|
||||
Extend deptree buffers so the largest possible device numbers fit.
|
||||
Generate versioned libdevmapper-event.so.
|
||||
Underline longer report help text headings.
|
||||
|
||||
Version 1.02.27 - 25th June 2008
|
||||
================================
|
||||
Align struct memblock in dbg_malloc for sparc.
|
||||
Add --unquoted and --rows to dmsetup.
|
||||
Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro.
|
||||
Fix inverted no_flush debug message.
|
||||
Remove --enable-jobs from configure. (Set at runtime instead.)
|
||||
Bring configure.in and list.h into line with the lvm2 versions.
|
||||
|
||||
Version 1.02.26 - 6th June 2008
|
||||
===============================
|
||||
Initialise params buffer to empty string in _emit_segment.
|
||||
Skip add_dev_node when ioctls disabled.
|
||||
Make dm_hash_iter safe against deletion.
|
||||
Accept a NULL pointer to dm_free silently.
|
||||
Add tables_loaded, readonly and suspended columns to reports.
|
||||
Add --nameprefixes to dmsetup.
|
||||
Add field name prefix option to reporting functions.
|
||||
Calculate string size within dm_pool_grow_object.
|
||||
|
||||
Version 1.02.25 - 10th April 2008
|
||||
=================================
|
||||
Remove redundant if-before-free tests.
|
||||
Use log_warn for reporting field help text instead of log_print.
|
||||
Change cluster mirror log type name (s/clustered_/clustered-/)
|
||||
|
||||
Version 1.02.24 - 20th December 2007
|
||||
====================================
|
||||
Fix deptree to pass new name to _resume_node after a rename.
|
||||
Suppress other node operations if node is deleted.
|
||||
Add node operation stack debug messages.
|
||||
Report error when empty device name passed to readahead functions.
|
||||
Fix minimum readahead debug message.
|
||||
|
||||
Version 1.02.23 - 5th December 2007
|
||||
===================================
|
||||
Update dm-ioctl.h after removal of compat code.
|
||||
Add readahead support to libdevmapper and dmsetup.
|
||||
Fix double free in a libdevmapper-event error path.
|
||||
Fix configure --with-dmeventd-path substitution.
|
||||
Allow a DM_DEV_DIR environment variable to override /dev in dmsetup.
|
||||
Create a libdevmapper.so.$LIB_VERSION symlink within the build tree.
|
||||
Avoid static link failure with some SELinux libraries that require libpthread.
|
||||
Remove obsolete dmfs code from tree and update INSTALL.
|
||||
|
||||
Version 1.02.22 - 21st August 2007
|
||||
==================================
|
||||
Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
|
||||
Update to use autoconf 2.61, while still supporting 2.57.
|
||||
Avoid repeated dm_task free on some dm_event_get_registered_device errors.
|
||||
Introduce log_sys_* macros from LVM2.
|
||||
Export dm_fclose and dm_create_dir; remove libdm-file.h.
|
||||
Don't log EROFS mkdir failures in _create_dir_recursive (for LVM2).
|
||||
Add fclose wrapper dm_fclose that catches write failures (using ferror).
|
||||
|
||||
Version 1.02.21 - 13th July 2007
|
||||
================================
|
||||
Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout.
|
||||
Fix dmsetup -o devno string termination. (1.02.20)
|
||||
|
||||
Version 1.02.20 - 15th June 2007
|
||||
================================
|
||||
Fix default dmsetup report buffering and add --unbuffered.
|
||||
Add tree-based and dependency fields to dmsetup reports.
|
||||
|
||||
Version 1.02.19 - 27th April 2007
|
||||
=================================
|
||||
Standardise protective include file #defines.
|
||||
Add regex functions to library.
|
||||
Avoid trailing separator in reports when there are hidden sort fields.
|
||||
Fix segfault in 'dmsetup status' without --showkeys against crypt target.
|
||||
Deal with some more compiler warnings.
|
||||
Introduce _add_field() and _is_same_field() to libdm-report.c.
|
||||
Fix some libdevmapper-event and dmeventd memory leaks.
|
||||
Remove unnecessary memset() return value checks.
|
||||
Fix a few leaks in reporting error paths. [1.02.15+]
|
||||
|
||||
Version 1.02.18 - 13th February 2007
|
||||
====================================
|
||||
Improve dmeventd messaging protocol: drain pipe and tag messages.
|
||||
|
||||
Version 1.02.17 - 29th January 2007
|
||||
===================================
|
||||
Add recent reporting options to dmsetup man page.
|
||||
Revise some report fields names.
|
||||
Add dmsetup 'help' command and update usage text.
|
||||
Use fixed-size fields in report interface and reorder.
|
||||
|
||||
Version 1.02.16 - 25th January 2007
|
||||
===================================
|
||||
Add some missing close() and fclose() return value checks.
|
||||
Migrate dmsetup column-based output over to new libdevmapper report framework.
|
||||
Add descriptions to reporting field definitions.
|
||||
Add a dso-private variable to dmeventd dso interface.
|
||||
Add dm_event_handler_[gs]et_timeout functions.
|
||||
Streamline dm_report_field_* interface.
|
||||
Add cmdline debug & version options to dmeventd.
|
||||
Add DM_LIB_VERSION definition to configure.h.
|
||||
Suppress 'Unrecognised field' error if report field is 'help'.
|
||||
Add --separator and --sort to dmsetup (unused).
|
||||
Make alignment flag optional when specifying report fields.
|
||||
|
||||
Version 1.02.15 - 17th January 2007
|
||||
===================================
|
||||
Add basic reporting functions to libdevmapper.
|
||||
Fix a malloc error path in dmsetup message.
|
||||
More libdevmapper-event interface changes and fixes.
|
||||
Rename dm_saprintf() to dm_asprintf().
|
||||
Report error if NULL pointer is supplied to dm_strdup_aux().
|
||||
Reinstate dm_event_get_registered_device.
|
||||
|
||||
Version 1.02.14 - 11th January 2007
|
||||
===================================
|
||||
Add dm_saprintf().
|
||||
Use CFLAGS when linking so mixed sparc builds can supply -m64.
|
||||
Add dm_tree_use_no_flush_suspend().
|
||||
Lots of dmevent changes including revised interface.
|
||||
Export dm_basename().
|
||||
Cope with a trailing space when comparing tables prior to possible reload.
|
||||
Fix dmeventd to cope if monitored device disappears.
|
||||
|
||||
Version 1.02.13 - 28 Nov 2006
|
||||
=============================
|
||||
Update dmsetup man page (setgeometry & message).
|
||||
Fix dmsetup free after getline with debug.
|
||||
Suppress encryption key in 'dmsetup table' output unless --showkeys supplied.
|
||||
|
||||
Version 1.02.12 - 13 Oct 2006
|
||||
=============================
|
||||
Avoid deptree attempting to suspend a device that's already suspended.
|
||||
|
||||
Version 1.02.11 - 12 Oct 2006
|
||||
==============================
|
||||
Add suspend noflush support.
|
||||
Add basic dmsetup loop support.
|
||||
Switch dmsetup to use dm_malloc and dm_free.
|
||||
|
||||
Version 1.02.10 - 19 Sep 2006
|
||||
=============================
|
||||
Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
|
||||
Reorder mm bounds_check code to reduce window for a dmeventd race.
|
||||
|
||||
Version 1.02.09 - 15 Aug 2006
|
||||
=============================
|
||||
Add --table argument to dmsetup for a one-line table.
|
||||
Abort if errors are found during cmdline option processing.
|
||||
Add lockfs indicator to debug output.
|
||||
|
||||
Version 1.02.08 - 17 July 2006
|
||||
==============================
|
||||
Append full patch to check in emails.
|
||||
Avoid duplicate dmeventd subdir with 'make distclean'.
|
||||
Update dmsetup man page.
|
||||
Add --force to dmsetup remove* to load error target.
|
||||
dmsetup remove_all also performs mknodes.
|
||||
Don't suppress identical table reloads if permission changes.
|
||||
Fix corelog segment line.
|
||||
Suppress some compiler warnings.
|
||||
|
||||
Version 1.02.07 - 11 May 2006
|
||||
=============================
|
||||
Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
|
||||
Avoid a dmeventd compiler warning.
|
||||
|
||||
Version 1.02.06 - 10 May 2006
|
||||
=============================
|
||||
Move DEFS into configure.h.
|
||||
Fix leaks in error paths found by coverity.
|
||||
Remove dmsetup line buffer limitation.
|
||||
|
||||
Version 1.02.05 - 19 Apr 2006
|
||||
=============================
|
||||
Separate install_include target in makefiles.
|
||||
Separate out DEFS from CFLAGS.
|
||||
Support pkg-config.
|
||||
Check for libsepol.
|
||||
|
||||
Version 1.02.04 - 14 Apr 2006
|
||||
=============================
|
||||
Bring dmsetup man page up-to-date.
|
||||
Use name-based device refs if kernel doesn't support device number refs.
|
||||
Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
|
||||
If _create_and_load_v4 fails part way through, revert the creation.
|
||||
dmeventd thread/fifo fixes.
|
||||
Add file & line to dm_strdup_aux().
|
||||
Add setgeometry.
|
||||
|
||||
Version 1.02.03 - 7 Feb 2006
|
||||
============================
|
||||
Add exported functions to set uid, gid and mode.
|
||||
Rename _log to dm_log and export.
|
||||
Add dm_tree_skip_lockfs.
|
||||
Fix dm_strdup debug definition.
|
||||
Fix hash function to avoid using a negative array offset.
|
||||
Don't inline _find in hash.c and tidy signed/unsigned etc.
|
||||
Fix libdevmapper.h #endif.
|
||||
Fix dmsetup version driver version.
|
||||
Add sync, nosync and block_on_error mirror log parameters.
|
||||
Add hweight32.
|
||||
Fix dmeventd build.
|
||||
|
||||
Version 1.02.02 - 2 Dec 2005
|
||||
============================
|
||||
dmeventd added.
|
||||
Export dm_task_update_nodes.
|
||||
Use names instead of numbers in messages when ioctls fail.
|
||||
|
||||
Version 1.02.01 - 23 Nov 2005
|
||||
=============================
|
||||
Resume snapshot-origins last.
|
||||
Drop leading zeros from dm_format_dev.
|
||||
Suppress attempt to reload identical table.
|
||||
Additional LVM- prefix matching for transitional period.
|
||||
|
||||
Version 1.02.00 - 10 Nov 2005
|
||||
=============================
|
||||
Added activation functions to library.
|
||||
Added return macros.
|
||||
Also suppress error if device doesn't exist with DM_DEVICE_STATUS.
|
||||
Export dm_set_selinux_context().
|
||||
Add dm_driver_version().
|
||||
Added dependency tree functions to library.
|
||||
Added hash, bitset, pool, dbg_malloc to library.
|
||||
Added ls --tree to dmsetup.
|
||||
Added dmsetup --nolockfs support for suspend/reload.
|
||||
|
||||
Version 1.01.05 - 26 Sep 2005
|
||||
=============================
|
||||
Resync list.h with LVM2.
|
||||
Remember increased buffer size and use for subsequent calls.
|
||||
On 'buffer full' condition, double buffer size and repeat ioctl.
|
||||
Fix termination of getopt_long() option array.
|
||||
Report 'buffer full' condition with v4 ioctl as well as with v1.
|
||||
|
||||
Version 1.01.04 - 2 Aug 2005
|
||||
============================
|
||||
Fix dmsetup ls -j and status --target with empty table.
|
||||
|
||||
Version 1.01.03 - 13 Jun 2005
|
||||
=============================
|
||||
Use matchpathcon mode parameter.
|
||||
Fix configure script to re-enable selinux.
|
||||
|
||||
Version 1.01.02 - 17 May 2005
|
||||
=============================
|
||||
Call dm_lib_exit() and dm_lib_release() automatically now.
|
||||
Add --target <target_type> filter to dmsetup table/status/ls.
|
||||
Add --exec <command> to dmsetup ls.
|
||||
Fix dmsetup getopt_long usage.
|
||||
|
||||
Version 1.01.01 - 29 Mar 2005
|
||||
=============================
|
||||
Update dmsetup man page.
|
||||
Drop-in devmap_name replacement.
|
||||
Add option to compile without ioctl for testing.
|
||||
Fix DM_LIB_VERSION sed.
|
||||
|
||||
Version 1.01.00 - 17 Jan 2005
|
||||
=============================
|
||||
Add dm_task_no_open_count() to skip getting open_count.
|
||||
|
||||
Version 1.00.21 - 7 Jan 2005
|
||||
============================
|
||||
Fix /proc/devices parsing.
|
||||
|
||||
Version 1.00.20 - 6 Jan 2005
|
||||
============================
|
||||
Attempt to fix /dev/mapper/control transparently if it's wrong.
|
||||
Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
|
||||
Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
|
||||
Add --noheadings columns option for colon-separated dmsetup output.
|
||||
Support device referencing by uuid or major/minor.
|
||||
Warn if kernel data didn't fit in buffer.
|
||||
Fix a printf.
|
||||
|
||||
Version 1.00.19 - 3 July 2004
|
||||
=============================
|
||||
More autoconf fixes.
|
||||
Fix a dmsetup newline.
|
||||
Fix device number handling for 2.6 kernels.
|
||||
|
||||
Version 1.00.18 - 20 Jun 2004
|
||||
=============================
|
||||
Fix a uuid free in libdm-iface.
|
||||
Fix a targets string size calc in driver.
|
||||
Add -c to dmsetup for column-based output.
|
||||
Add target message-passing ioctl.
|
||||
|
||||
Version 1.00.17 - 17 Apr 2004
|
||||
=============================
|
||||
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
|
||||
Fix library selinux linking.
|
||||
|
||||
Version 1.00.16 - 16 Apr 2004
|
||||
=============================
|
||||
Ignore error setting selinux file context if fs doesn't support it.
|
||||
|
||||
Version 1.00.15 - 7 Apr 2004
|
||||
============================
|
||||
Fix status overflow check in kernel patches.
|
||||
|
||||
Version 1.00.14 - 6 Apr 2004
|
||||
============================
|
||||
Fix static selinux build.
|
||||
|
||||
Version 1.00.13 - 6 Apr 2004
|
||||
============================
|
||||
Add some basic selinux support.
|
||||
|
||||
Version 1.00.12 - 6 Apr 2004
|
||||
============================
|
||||
Fix dmsetup.static install.
|
||||
|
||||
Version 1.00.11 - 5 Apr 2004
|
||||
============================
|
||||
configure --enable-static_link does static build in addition to dynamic.
|
||||
Moved Makefile library targets definition into template.
|
||||
|
||||
Version 1.00.10 - 2 Apr 2004
|
||||
============================
|
||||
Fix DESTDIR handling.
|
||||
Static build installs to dmsetup.static.
|
||||
Basic support for internationalisation.
|
||||
Minor Makefile tidy-ups/fixes.
|
||||
|
||||
Version 1.00.09 - 31 Mar 2004
|
||||
=============================
|
||||
Update copyright notices to Red Hat.
|
||||
Move full mknodes functionality from dmsetup into libdevmapper.
|
||||
Avoid sscanf %as for uClibc compatibility.
|
||||
Cope if DM_LIST_VERSIONS is not defined.
|
||||
Add DM_LIST_VERSIONS functionality to kernel patches.
|
||||
Generate new kernel patches for 2.4.26-rc1.
|
||||
|
||||
Version 1.00.08 - 27 Feb 2004
|
||||
=============================
|
||||
Added 'dmsetup targets'.
|
||||
Added event_nr support to 'dmsetup wait'.
|
||||
Updated dmsetup man page.
|
||||
Allow logging function to be reset to use internal one.
|
||||
Bring log macros in line with LVM2 ones.
|
||||
Added 'make install_static_lib' which installs libdevmapper.a.
|
||||
Made configure/makefiles closer to LVM2 versions.
|
||||
Fixed DESTDIR for make install/install_static_lib.
|
||||
Updated README/INSTALL to reflect move to sources.redhat.com.
|
||||
Updated autoconf files to 2003-06-17.
|
||||
171
aclocal.m4
vendored
Normal file
171
aclocal.m4
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
# serial 1 (pkg-config-0.24)
|
||||
#
|
||||
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
# ----------------------------------
|
||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
|
||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
|
||||
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
|
||||
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
|
||||
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi[]dnl
|
||||
])# PKG_PROG_PKG_CONFIG
|
||||
|
||||
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
# Check to see whether a particular set of modules exists. Similar
|
||||
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||
#
|
||||
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
# only at the first occurence in configure.ac, so if the first place
|
||||
# it's called might be skipped (such as if it is within an "if", you
|
||||
# have to call PKG_CHECK_EXISTS manually
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||
m4_default([$2], [:])
|
||||
m4_ifvaln([$3], [else
|
||||
$3])dnl
|
||||
fi])
|
||||
|
||||
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||
# ---------------------------------------------
|
||||
m4_define([_PKG_CONFIG],
|
||||
[if test -n "$$1"; then
|
||||
pkg_cv_[]$1="$$1"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
PKG_CHECK_EXISTS([$3],
|
||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
|
||||
[pkg_failed=yes])
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi[]dnl
|
||||
])# _PKG_CONFIG
|
||||
|
||||
# _PKG_SHORT_ERRORS_SUPPORTED
|
||||
# -----------------------------
|
||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi[]dnl
|
||||
])# _PKG_SHORT_ERRORS_SUPPORTED
|
||||
|
||||
|
||||
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
# [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
#
|
||||
# Note that if there is a possibility the first call to
|
||||
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||
#
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([PKG_CHECK_MODULES],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||
|
||||
pkg_failed=no
|
||||
AC_MSG_CHECKING([for $1])
|
||||
|
||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||
|
||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.])
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
AC_MSG_RESULT([no])
|
||||
_PKG_SHORT_ERRORS_SUPPORTED
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
|
||||
else
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
m4_default([$4], [AC_MSG_ERROR(
|
||||
[Package requirements ($2) were not met:
|
||||
|
||||
$$1_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
_PKG_TEXT])
|
||||
])
|
||||
elif test $pkg_failed = untried; then
|
||||
AC_MSG_RESULT([no])
|
||||
m4_default([$4], [AC_MSG_FAILURE(
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])
|
||||
])
|
||||
else
|
||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||
AC_MSG_RESULT([yes])
|
||||
$3
|
||||
fi[]dnl
|
||||
])# PKG_CHECK_MODULES
|
||||
|
||||
1463
autoconf/config.guess
vendored
1463
autoconf/config.guess
vendored
File diff suppressed because it is too large
Load Diff
777
autoconf/config.sub
vendored
777
autoconf/config.sub
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,36 +1,62 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
|
||||
scriptversion=2006-10-14.15
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
@@ -41,211 +67,441 @@ stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
posix_glob=
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
chgrpcmd=
|
||||
stripcmd=
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dstarg=
|
||||
no_target_directory=
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
Options:
|
||||
-c (ignored)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
-m) mode=$2
|
||||
shift
|
||||
shift
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
continue;;
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
-t) dstarg=$2
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
-T) no_target_directory=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dstarg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dstarg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dstarg=$arg
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
if test -z "$dir_arg"; then
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src ;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dstarg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dstarg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst ;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dstarg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix=/ ;;
|
||||
-*) prefix=./ ;;
|
||||
*) prefix= ;;
|
||||
esac
|
||||
|
||||
case $posix_glob in
|
||||
'')
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=true
|
||||
else
|
||||
posix_glob=false
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob && set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob && set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test -z "$d" && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
true
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
# Now rename the file to the real destination.
|
||||
{ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
|
||||
|| {
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
if test -f "$dst"; then
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null \
|
||||
|| { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
|
||||
&& { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
} || exit 1
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
|
||||
1431
configure.in
Normal file
1431
configure.in
Normal file
File diff suppressed because it is too large
Load Diff
43
daemons/Makefile.in
Normal file
43
daemons/Makefile.in
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# 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@
|
||||
|
||||
.PHONY: dmeventd clvmd cmirrord
|
||||
|
||||
ifneq ("@CLVMD@", "none")
|
||||
SUBDIRS = clvmd
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_CMIRRORD@", "yes")
|
||||
SUBDIRS += cmirrord
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
SUBDIRS += dmeventd
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
daemons.cflow: dmeventd.cflow
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS = clvmd cmirrord dmeventd
|
||||
endif
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
device-mapper: dmeventd.device-mapper
|
||||
endif
|
||||
117
daemons/clvmd/Makefile.in
Normal file
117
daemons/clvmd/Makefile.in
Normal file
@@ -0,0 +1,117 @@
|
||||
#
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
CCS_LIBS = @CCS_LIBS@
|
||||
CCS_CFLAGS = @CCS_CFLAGS@
|
||||
CMAN_LIBS = @CMAN_LIBS@
|
||||
CMAN_CFLAGS = @CMAN_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@
|
||||
GULM_LIBS = @GULM_LIBS@
|
||||
GULM_CFLAGS = @GULM_CFLAGS@
|
||||
QUORUM_LIBS = @QUORUM_LIBS@
|
||||
QUORUM_CFLAGS = @QUORUM_CFLAGS@
|
||||
SALCK_LIBS = @SALCK_LIBS@
|
||||
SALCK_CFLAGS = @SALCK_CFLAGS@
|
||||
|
||||
SOURCES = \
|
||||
clvmd-command.c \
|
||||
clvmd.c \
|
||||
lvm-functions.c \
|
||||
refresh_clvmd.c
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
DEFS += -DDEBUG
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring gulm,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-gulm.c tcp-comms.c
|
||||
LMLIBS += $(CCS_LIBS) $(GULM_LIBS)
|
||||
CFLAGS += $(CCS_CFLAGS) $(GULM_CFLAGS)
|
||||
DEFS += -DUSE_GULM
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring cman,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-cman.c
|
||||
LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
|
||||
CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS)
|
||||
DEFS += -DUSE_CMAN
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring openais,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-openais.c
|
||||
LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS)
|
||||
CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS)
|
||||
DEFS += -DUSE_OPENAIS
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring corosync,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-corosync.c
|
||||
LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS)
|
||||
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-gulm.c tcp-comms.c
|
||||
SOURCES += clvmd-cman.c
|
||||
SOURCES += clvmd-openais.c
|
||||
SOURCES += clvmd-corosync.c
|
||||
SOURCES += clvmd-singlenode.c
|
||||
endif
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
LVMLIBS = $(LVMINTERNAL_LIBS)
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
LVMLIBS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LVMLIBS += -ldevmapper
|
||||
LIBS += $(PTHREAD_LIBS)
|
||||
|
||||
DEFS += -D_REENTRANT
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \
|
||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
.PHONY: install_clvmd
|
||||
|
||||
install_clvmd: $(TARGETS)
|
||||
$(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd
|
||||
|
||||
install: $(INSTALL_TARGETS)
|
||||
|
||||
install_cluster: $(INSTALL_TARGETS)
|
||||
75
daemons/clvmd/clvm.h
Normal file
75
daemons/clvmd/clvm.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Definitions for CLVMD server and clients */
|
||||
|
||||
/*
|
||||
* The protocol spoken over the cluster and across the local socket.
|
||||
*/
|
||||
|
||||
#ifndef _CLVM_H
|
||||
#define _CLVM_H
|
||||
|
||||
#include "configure.h"
|
||||
|
||||
struct clvm_header {
|
||||
uint8_t cmd; /* See below */
|
||||
uint8_t flags; /* See below */
|
||||
uint16_t xid; /* Transaction ID */
|
||||
uint32_t clientid; /* Only used in Daemon->Daemon comms */
|
||||
int32_t status; /* For replies, whether request succeeded */
|
||||
uint32_t arglen; /* Length of argument below.
|
||||
If >1500 then it will be passed
|
||||
around the cluster in the system LV */
|
||||
char node[1]; /* Actually a NUL-terminated string, node name.
|
||||
If this is empty then the command is
|
||||
forwarded to all cluster nodes unless
|
||||
FLAG_LOCAL is also set. */
|
||||
char args[1]; /* Arguments for the command follow the
|
||||
node name, This member is only
|
||||
valid if the node name is empty */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Flags */
|
||||
#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
|
||||
#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
|
||||
#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */
|
||||
|
||||
/* Name of the local socket to communicate between lvm and clvmd */
|
||||
static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock";
|
||||
|
||||
/* Internal commands & replies */
|
||||
#define CLVMD_CMD_REPLY 1
|
||||
#define CLVMD_CMD_VERSION 2 /* Send version around cluster when we start */
|
||||
#define CLVMD_CMD_GOAWAY 3 /* Die if received this - we are running
|
||||
an incompatible version */
|
||||
#define CLVMD_CMD_TEST 4 /* Just for mucking about */
|
||||
|
||||
#define CLVMD_CMD_LOCK 30
|
||||
#define CLVMD_CMD_UNLOCK 31
|
||||
|
||||
/* Lock/Unlock commands */
|
||||
#define CLVMD_CMD_LOCK_LV 50
|
||||
#define CLVMD_CMD_LOCK_VG 51
|
||||
#define CLVMD_CMD_LOCK_QUERY 52
|
||||
|
||||
/* Misc functions */
|
||||
#define CLVMD_CMD_REFRESH 40
|
||||
#define CLVMD_CMD_GET_CLUSTERNAME 41
|
||||
#define CLVMD_CMD_SET_DEBUG 42
|
||||
#define CLVMD_CMD_VG_BACKUP 43
|
||||
#define CLVMD_CMD_RESTART 44
|
||||
#define CLVMD_CMD_SYNC_NAMES 45
|
||||
#endif
|
||||
505
daemons/clvmd/clvmd-cman.c
Normal file
505
daemons/clvmd/clvmd-cman.c
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* CMAN communication layer for clvmd.
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
#include <libdlm.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
struct clvmd_node
|
||||
{
|
||||
struct cman_node *node;
|
||||
int clvmd_up;
|
||||
};
|
||||
|
||||
static int num_nodes;
|
||||
static struct cman_node *nodes = NULL;
|
||||
static struct cman_node this_node;
|
||||
static int count_nodes; /* size of allocated nodes array */
|
||||
static struct dm_hash_table *node_updown_hash;
|
||||
static dlm_lshandle_t *lockspace;
|
||||
static cman_handle_t c_handle;
|
||||
|
||||
static void count_clvmds_running(void);
|
||||
static void get_members(void);
|
||||
static int nodeid_from_csid(const char *csid);
|
||||
static int name_from_nodeid(int nodeid, char *name);
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
|
||||
static void data_callback(cman_handle_t handle, void *private,
|
||||
char *buf, int len, uint8_t port, int nodeid);
|
||||
|
||||
struct lock_wait {
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
struct dlm_lksb lksb;
|
||||
};
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
node_updown_hash = dm_hash_create(100);
|
||||
|
||||
/* Open the cluster communication socket */
|
||||
c_handle = cman_init(NULL);
|
||||
if (!c_handle) {
|
||||
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
|
||||
return -1;
|
||||
}
|
||||
DEBUGLOG("Connected to CMAN\n");
|
||||
|
||||
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
|
||||
syslog(LOG_ERR, "Can't bind cluster socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cman_start_notification(c_handle, event_callback)) {
|
||||
syslog(LOG_ERR, "Can't start cluster event listening");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the cluster members list */
|
||||
get_members();
|
||||
count_clvmds_running();
|
||||
|
||||
DEBUGLOG("CMAN initialisation complete\n");
|
||||
|
||||
/* Create a lockspace for LV & VG locks to live in */
|
||||
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
|
||||
if (!lockspace) {
|
||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
||||
if (!lockspace) {
|
||||
syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
|
||||
return -1;
|
||||
}
|
||||
DEBUGLOG("Created DLM lockspace for CLVMD.\n");
|
||||
} else
|
||||
DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
|
||||
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
DEBUGLOG("DLM initialisation complete\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_init_completed(void)
|
||||
{
|
||||
clvmd_cluster_init_completed();
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd()
|
||||
{
|
||||
return cman_get_fd(c_handle);
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
int i;
|
||||
int nnodes = 0;
|
||||
|
||||
/* return number of ACTIVE nodes */
|
||||
for (i=0; i<num_nodes; i++) {
|
||||
if (nodes[i].cn_member && nodes[i].cn_nodeid)
|
||||
nnodes++;
|
||||
}
|
||||
return nnodes;
|
||||
}
|
||||
|
||||
/* send_message with the fd check removed */
|
||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
||||
const char *errtext)
|
||||
{
|
||||
int nodeid = 0;
|
||||
|
||||
if (csid)
|
||||
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
|
||||
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
|
||||
{
|
||||
log_error("%s", errtext);
|
||||
}
|
||||
return msglen;
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
if (this_node.cn_nodeid == 0) {
|
||||
cman_get_node(c_handle, 0, &this_node);
|
||||
}
|
||||
memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
|
||||
static int _cluster_do_node_callback(struct local_client *client,
|
||||
void (*callback) (struct local_client *,
|
||||
const char *,
|
||||
int))
|
||||
{
|
||||
int i;
|
||||
int somedown = 0;
|
||||
|
||||
for (i = 0; i < _get_num_nodes(); i++) {
|
||||
if (nodes[i].cn_member && nodes[i].cn_nodeid) {
|
||||
int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
|
||||
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, up);
|
||||
if (!up)
|
||||
somedown = -1;
|
||||
}
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Process OOB messages from the cluster socket */
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
|
||||
{
|
||||
char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
|
||||
switch (reason) {
|
||||
case CMAN_REASON_PORTCLOSED:
|
||||
name_from_nodeid(arg, namebuf);
|
||||
log_notice("clvmd on node %s has died\n", namebuf);
|
||||
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
|
||||
|
||||
dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
|
||||
break;
|
||||
|
||||
case CMAN_REASON_STATECHANGE:
|
||||
DEBUGLOG("Got state change message, re-reading members list\n");
|
||||
get_members();
|
||||
break;
|
||||
|
||||
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
|
||||
case CMAN_REASON_PORTOPENED:
|
||||
/* Ignore this, wait for startup message from clvmd itself */
|
||||
break;
|
||||
|
||||
case CMAN_REASON_TRY_SHUTDOWN:
|
||||
DEBUGLOG("Got try shutdown, sending OK\n");
|
||||
cman_replyto_shutdown(c_handle, 1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* ERROR */
|
||||
DEBUGLOG("Got unknown event callback message: %d\n", reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct local_client *cman_client;
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
|
||||
/* Save this for data_callback */
|
||||
cman_client = fd;
|
||||
|
||||
/* We never return a new client */
|
||||
*new_client = NULL;
|
||||
|
||||
return cman_dispatch(c_handle, 0);
|
||||
}
|
||||
|
||||
|
||||
static void data_callback(cman_handle_t handle, void *private,
|
||||
char *buf, int len, uint8_t port, int nodeid)
|
||||
{
|
||||
/* Ignore looped back messages */
|
||||
if (nodeid == this_node.cn_nodeid)
|
||||
return;
|
||||
process_message(cman_client, buf, len, (char *)&nodeid);
|
||||
}
|
||||
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
/* It's up ! */
|
||||
int nodeid = nodeid_from_csid(csid);
|
||||
|
||||
dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
|
||||
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
||||
}
|
||||
|
||||
static void _cluster_closedown()
|
||||
{
|
||||
destroy_lvhash();
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
cman_finish(c_handle);
|
||||
}
|
||||
|
||||
static int is_listening(int nodeid)
|
||||
{
|
||||
int status;
|
||||
|
||||
do {
|
||||
status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
|
||||
if (status < 0 && errno == EBUSY) { /* Don't busywait */
|
||||
sleep(1);
|
||||
errno = EBUSY; /* In case sleep trashes it */
|
||||
}
|
||||
}
|
||||
while (status < 0 && errno == EBUSY);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Populate the list of CLVMDs running.
|
||||
called only at startup time */
|
||||
static void count_clvmds_running(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
int nodeid = nodes[i].cn_nodeid;
|
||||
|
||||
if (is_listening(nodeid) == 1)
|
||||
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
|
||||
else
|
||||
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a list of active cluster members */
|
||||
static void get_members()
|
||||
{
|
||||
int retnodes;
|
||||
int status;
|
||||
int i;
|
||||
int high_nodeid = 0;
|
||||
|
||||
num_nodes = cman_get_node_count(c_handle);
|
||||
if (num_nodes == -1) {
|
||||
log_error("Unable to get node count");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not enough room for new nodes list ? */
|
||||
if (num_nodes > count_nodes && nodes) {
|
||||
free(nodes);
|
||||
nodes = NULL;
|
||||
}
|
||||
|
||||
if (nodes == NULL) {
|
||||
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||
nodes = malloc(count_nodes * sizeof(struct cman_node));
|
||||
if (!nodes) {
|
||||
log_error("Unable to allocate nodes array\n");
|
||||
exit(5);
|
||||
}
|
||||
}
|
||||
|
||||
status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
|
||||
if (status < 0) {
|
||||
log_error("Unable to get node details");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
/* Get the highest nodeid */
|
||||
for (i=0; i<retnodes; i++) {
|
||||
if (nodes[i].cn_nodeid > high_nodeid)
|
||||
high_nodeid = nodes[i].cn_nodeid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert a node name to a CSID */
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (strcmp(name, nodes[i].cn_name) == 0) {
|
||||
memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a CSID to a node name */
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
|
||||
strcpy(name, nodes[i].cn_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Who?? */
|
||||
strcpy(name, "Unknown");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a node ID to a node name */
|
||||
static int name_from_nodeid(int nodeid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (nodeid == nodes[i].cn_nodeid) {
|
||||
strcpy(name, nodes[i].cn_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Who?? */
|
||||
strcpy(name, "Unknown");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a CSID to a node ID */
|
||||
static int nodeid_from_csid(const char *csid)
|
||||
{
|
||||
int nodeid;
|
||||
|
||||
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
|
||||
return nodeid;
|
||||
}
|
||||
|
||||
static int _is_quorate()
|
||||
{
|
||||
return cman_is_quorate(c_handle);
|
||||
}
|
||||
|
||||
static void sync_ast_routine(void *arg)
|
||||
{
|
||||
struct lock_wait *lwait = arg;
|
||||
|
||||
pthread_mutex_lock(&lwait->mutex);
|
||||
pthread_cond_signal(&lwait->cond);
|
||||
pthread_mutex_unlock(&lwait->mutex);
|
||||
}
|
||||
|
||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
|
||||
if (!lockid) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
|
||||
/* Conversions need the lockid in the LKSB */
|
||||
if (flags & LKF_CONVERT)
|
||||
lwait.lksb.sb_lkid = *lockid;
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
status = dlm_ls_lock(lockspace,
|
||||
mode,
|
||||
&lwait.lksb,
|
||||
flags,
|
||||
resource,
|
||||
strlen(resource),
|
||||
0, sync_ast_routine, &lwait, NULL, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
*lockid = lwait.lksb.sb_lkid;
|
||||
|
||||
errno = lwait.lksb.sb_status;
|
||||
DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
|
||||
if (lwait.lksb.sb_status)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
|
||||
DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
errno = lwait.lksb.sb_status;
|
||||
if (lwait.lksb.sb_status != EUNLOCK)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
cman_cluster_t cluster_info;
|
||||
int status;
|
||||
|
||||
status = cman_get_cluster(c_handle, &cluster_info);
|
||||
if (!status) {
|
||||
strncpy(buf, cluster_info.ci_name, buflen);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_cman_ops = {
|
||||
.cluster_init_completed = _cluster_init_completed,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _sync_lock,
|
||||
.sync_unlock = _sync_unlock,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_cman_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_cman_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
423
daemons/clvmd/clvmd-command.c
Normal file
423
daemons/clvmd/clvmd-command.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
CLVMD Cluster LVM daemon command processor.
|
||||
|
||||
To add commands to the daemon simply add a processor in do_command and return
|
||||
and messages back in buf and the length in *retlen. The initial value of
|
||||
buflen is the maximum size of the buffer. if buf is not large enough then it
|
||||
may be reallocated by the functions in here to a suitable size bearing in
|
||||
mind that anything larger than the passed-in size will have to be returned
|
||||
using the system LV and so performance will suffer.
|
||||
|
||||
The status return will be negated and passed back to the originating node.
|
||||
|
||||
pre- and post- command routines are called only on the local node. The
|
||||
purpose is primarily to get and release locks, though the pre- routine should
|
||||
also do any other local setups required by the command (if any) and can
|
||||
return a failure code that prevents the command from being distributed around
|
||||
the cluster
|
||||
|
||||
The pre- and post- routines are run in their own thread so can block as long
|
||||
they like, do_command is run in the main clvmd thread so should not block for
|
||||
too long. If the pre-command returns an error code (!=0) then the command
|
||||
will not be propogated around the cluster but the post-command WILL be called
|
||||
|
||||
Also note that the pre and post routine are *always* called on the local
|
||||
node, even if the command to be executed was only requested to run on a
|
||||
remote node. It may peek inside the client structure to check the status of
|
||||
the command.
|
||||
|
||||
The clients of the daemon must, naturally, understand the return messages and
|
||||
codes.
|
||||
|
||||
Routines in here may only READ the values in the client structure passed in
|
||||
apart from client->private which they are free to do what they like with.
|
||||
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
#include "locking.h"
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
extern struct cluster_ops *clops;
|
||||
static int restart_clvmd(void);
|
||||
|
||||
/* This is where all the real work happens:
|
||||
NOTE: client will be NULL when this is executed on a remote node */
|
||||
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
char **buf, int buflen, int *retlen)
|
||||
{
|
||||
char *args = msg->node + strlen(msg->node) + 1;
|
||||
int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
const char *locktype;
|
||||
struct utsname nodeinfo;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
|
||||
/* Do the command */
|
||||
switch (msg->cmd) {
|
||||
/* Just a test message */
|
||||
case CLVMD_CMD_TEST:
|
||||
if (arglen > buflen) {
|
||||
char *new_buf;
|
||||
buflen = arglen + 200;
|
||||
new_buf = realloc(*buf, buflen);
|
||||
if (new_buf == NULL) {
|
||||
status = errno;
|
||||
free (*buf);
|
||||
}
|
||||
*buf = new_buf;
|
||||
}
|
||||
if (*buf) {
|
||||
uname(&nodeinfo);
|
||||
*retlen = 1 + dm_snprintf(*buf, buflen,
|
||||
"TEST from %s: %s v%s",
|
||||
nodeinfo.nodename, args,
|
||||
nodeinfo.release);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
/* Check to see if the VG is in use by LVM1 */
|
||||
status = do_check_lvm1(lockname);
|
||||
do_lock_vg(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
/* This is the biggie */
|
||||
lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
|
||||
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());
|
||||
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(args[0]);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_RESTART:
|
||||
status = restart_clvmd();
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
status = clops->get_cluster_name(*buf, buflen);
|
||||
if (!status)
|
||||
*retlen = strlen(*buf)+1;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
/*
|
||||
* Do not run backup on local node, caller should do that.
|
||||
*/
|
||||
if (!client)
|
||||
lvm_do_backup(&args[2]);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Won't get here because command is validated in pre_command */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check the status of the command and return the error text */
|
||||
if (status) {
|
||||
*retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s",
|
||||
strerror(status)) : -1);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
static int lock_vg(struct local_client *client)
|
||||
{
|
||||
struct dm_hash_table *lock_hash;
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
int lock_mode;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
int lkid;
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
|
||||
/* Keep a track of VG locks in our own hash table. In current
|
||||
practice there should only ever be more than two VGs locked
|
||||
if a user tries to merge lots of them at once */
|
||||
if (client->bits.localsock.private) {
|
||||
lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
|
||||
}
|
||||
else {
|
||||
lock_hash = dm_hash_create(3);
|
||||
if (!lock_hash)
|
||||
return ENOMEM;
|
||||
client->bits.localsock.private = (void *)lock_hash;
|
||||
}
|
||||
|
||||
lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
|
||||
lock_mode = ((int)lock_cmd & LCK_TYPE_MASK);
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||
|
||||
if (lock_mode == LCK_UNLOCK) {
|
||||
|
||||
lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
|
||||
if (lkid == 0)
|
||||
return EINVAL;
|
||||
|
||||
status = sync_unlock(lockname, lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
dm_hash_remove(lock_hash, lockname);
|
||||
}
|
||||
else {
|
||||
/* Read locks need to be PR; other modes get passed through */
|
||||
if (lock_mode == LCK_READ)
|
||||
lock_mode = LCK_PREAD;
|
||||
status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
dm_hash_insert(lock_hash, lockname, (void *)(long)lkid);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Pre-command is a good place to get locks that are needed only for the duration
|
||||
of the commands around the cluster (don't forget to free them in post-command),
|
||||
and to sanity check the command arguments */
|
||||
int do_pre_command(struct local_client *client)
|
||||
{
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
int lockid;
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
|
||||
switch (header->cmd) {
|
||||
case CLVMD_CMD_TEST:
|
||||
status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
|
||||
client->bits.localsock.private = (void *)(long)lockid;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
lockname = &args[2];
|
||||
/* We take out a real lock unless LCK_CACHE was set */
|
||||
if (!strncmp(lockname, "V_", 2) ||
|
||||
!strncmp(lockname, "P_#", 3))
|
||||
status = lock_vg(client);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_REFRESH:
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
case CLVMD_CMD_SET_DEBUG:
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
case CLVMD_CMD_SYNC_NAMES:
|
||||
case CLVMD_CMD_LOCK_QUERY:
|
||||
case CLVMD_CMD_RESTART:
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Unknown command %d received\n", header->cmd);
|
||||
status = EINVAL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Note that the post-command routine is called even if the pre-command or the real command
|
||||
failed */
|
||||
int do_post_command(struct local_client *client)
|
||||
{
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
int status = 0;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
char *lockname;
|
||||
|
||||
switch (header->cmd) {
|
||||
case CLVMD_CMD_TEST:
|
||||
status =
|
||||
sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
||||
client->bits.localsock.private = 0;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
status = post_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Called when the client is about to be deleted */
|
||||
void cmd_client_cleanup(struct local_client *client)
|
||||
{
|
||||
if (client->bits.localsock.private) {
|
||||
|
||||
struct dm_hash_node *v;
|
||||
struct dm_hash_table *lock_hash =
|
||||
(struct dm_hash_table *)client->bits.localsock.private;
|
||||
|
||||
dm_hash_iterate(v, lock_hash) {
|
||||
int lkid = (int)(long)dm_hash_get_data(lock_hash, v);
|
||||
char *lockname = dm_hash_get_key(lock_hash, v);
|
||||
|
||||
DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
|
||||
sync_unlock(lockname, lkid);
|
||||
}
|
||||
|
||||
dm_hash_destroy(lock_hash);
|
||||
client->bits.localsock.private = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int restart_clvmd(void)
|
||||
{
|
||||
char **argv = NULL;
|
||||
char *debug_arg = NULL, *lv_name;
|
||||
int i, argc = 0, max_locks = 0;
|
||||
struct dm_hash_node *hn = NULL;
|
||||
|
||||
DEBUGLOG("clvmd restart requested\n");
|
||||
|
||||
/* Count exclusively-open LVs */
|
||||
hn = NULL;
|
||||
do {
|
||||
hn = get_next_excl_lock(hn, &lv_name);
|
||||
if (lv_name)
|
||||
max_locks++;
|
||||
} while (hn && *lv_name);
|
||||
|
||||
/* clvmd + locks (-E uuid) + debug (-d X) + NULL */
|
||||
argv = malloc((max_locks * 2 + 4) * sizeof(*argv));
|
||||
if (!argv)
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* Build the command-line
|
||||
*/
|
||||
argv[argc++] = strdup("clvmd");
|
||||
if (!argv[0])
|
||||
goto_out;
|
||||
|
||||
/* Propogate debug options */
|
||||
if (clvmd_get_debug()) {
|
||||
if (!(debug_arg = malloc(16)) ||
|
||||
dm_snprintf(debug_arg, 16, "-d%d", (int)clvmd_get_debug()) < 0)
|
||||
goto_out;
|
||||
argv[argc++] = debug_arg;
|
||||
debug_arg = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: specify used cluster backend
|
||||
* argv[argc++] = strdup("-Isinglenode");
|
||||
*/
|
||||
|
||||
/* Now add the exclusively-open LVs */
|
||||
do {
|
||||
hn = get_next_excl_lock(hn, &lv_name);
|
||||
if (lv_name) {
|
||||
argv[argc] = strdup("-E");
|
||||
if (!argv[argc++])
|
||||
goto_out;
|
||||
argv[argc] = strdup(lv_name);
|
||||
if (!argv[argc++])
|
||||
goto_out;
|
||||
|
||||
DEBUGLOG("excl lock: %s\n", lv_name);
|
||||
hn = get_next_excl_lock(hn, &lv_name);
|
||||
}
|
||||
} while (hn && *lv_name);
|
||||
argv[argc++] = NULL;
|
||||
|
||||
/* Exec new clvmd */
|
||||
DEBUGLOG("--- Restarting %s ---\n", CLVMD_PATH);
|
||||
/* NOTE: This will fail when downgrading! */
|
||||
execve(CLVMD_PATH, argv, NULL);
|
||||
out:
|
||||
/* We failed */
|
||||
DEBUGLOG("Restart of clvmd failed.\n");
|
||||
|
||||
for (i = 0; i < argc && argv[i]; i++)
|
||||
free(argv[i]);
|
||||
free(argv);
|
||||
free(debug_arg);
|
||||
|
||||
return EIO;
|
||||
}
|
||||
33
daemons/clvmd/clvmd-common.h
Normal file
33
daemons/clvmd/clvmd-common.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file must be included first by every clvmd source file.
|
||||
*/
|
||||
#ifndef _LVM_CLVMD_COMMON_H
|
||||
#define _LVM_CLVMD_COMMON_H
|
||||
|
||||
#include "configure.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "libdevmapper.h"
|
||||
|
||||
#include "lvm-logging.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#endif
|
||||
125
daemons/clvmd/clvmd-comms.h
Normal file
125
daemons/clvmd/clvmd-comms.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-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 General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Abstraction layer for clvmd cluster communications
|
||||
*/
|
||||
|
||||
#ifndef _CLVMD_COMMS_H
|
||||
#define _CLVMD_COMMS_H
|
||||
|
||||
struct local_client;
|
||||
|
||||
struct cluster_ops {
|
||||
void (*cluster_init_completed) (void);
|
||||
|
||||
int (*cluster_send_message) (const void *buf, int msglen,
|
||||
const char *csid,
|
||||
const char *errtext);
|
||||
int (*name_from_csid) (const char *csid, char *name);
|
||||
int (*csid_from_name) (char *csid, const char *name);
|
||||
int (*get_num_nodes) (void);
|
||||
int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client);
|
||||
int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */
|
||||
int (*cluster_do_node_callback) (struct local_client *client,
|
||||
void (*callback) (struct local_client *,
|
||||
const char *csid,
|
||||
int node_up));
|
||||
int (*is_quorate) (void);
|
||||
|
||||
void (*get_our_csid) (char *csid);
|
||||
void (*add_up_node) (const char *csid);
|
||||
void (*reread_config) (void);
|
||||
void (*cluster_closedown) (void);
|
||||
|
||||
int (*get_cluster_name)(char *buf, int buflen);
|
||||
|
||||
int (*sync_lock) (const char *resource, int mode,
|
||||
int flags, int *lockid);
|
||||
int (*sync_unlock) (const char *resource, int lockid);
|
||||
|
||||
};
|
||||
|
||||
#ifdef USE_GULM
|
||||
# include "tcp-comms.h"
|
||||
struct cluster_ops *init_gulm_cluster(void);
|
||||
#define MAX_CSID_LEN GULM_MAX_CSID_LEN
|
||||
#define MAX_CLUSTER_MEMBER_NAME_LEN GULM_MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
#endif
|
||||
|
||||
#ifdef USE_CMAN
|
||||
# include <netinet/in.h>
|
||||
# include "libcman.h"
|
||||
# define CMAN_MAX_CSID_LEN 4
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
|
||||
# endif
|
||||
# undef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE 1500
|
||||
# define CLUSTER_PORT_CLVMD 11
|
||||
struct cluster_ops *init_cman_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENAIS
|
||||
# include <openais/saAis.h>
|
||||
# include <corosync/totem/totem.h>
|
||||
# define OPENAIS_CSID_LEN (sizeof(int))
|
||||
# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
|
||||
# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
|
||||
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
|
||||
# endif
|
||||
# ifndef CMAN_MAX_CLUSTER_MESSAGE
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
|
||||
# endif
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN sizeof(int)
|
||||
# endif
|
||||
struct cluster_ops *init_openais_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_COROSYNC
|
||||
# include <corosync/corotypes.h>
|
||||
# define COROSYNC_CSID_LEN (sizeof(int))
|
||||
# define COROSYNC_MAX_CLUSTER_MESSAGE 65535
|
||||
# define COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
|
||||
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
|
||||
# endif
|
||||
# ifndef CMAN_MAX_CLUSTER_MESSAGE
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE 65535
|
||||
# endif
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN sizeof(int)
|
||||
# endif
|
||||
struct cluster_ops *init_corosync_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SINGLENODE
|
||||
# define SINGLENODE_CSID_LEN (sizeof(int))
|
||||
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN 64
|
||||
# endif
|
||||
# define SINGLENODE_MAX_CLUSTER_MESSAGE 65535
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN sizeof(int)
|
||||
# endif
|
||||
struct cluster_ops *init_singlenode_cluster(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
625
daemons/clvmd/clvmd-corosync.c
Normal file
625
daemons/clvmd/clvmd-corosync.c
Normal file
@@ -0,0 +1,625 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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>
|
||||
#include <corosync/confdb.h>
|
||||
#include <libdlm.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
/* Timeout value for several corosync calls */
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len);
|
||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries);
|
||||
static void _cluster_closedown(void);
|
||||
|
||||
/* Hash list of nodes in the cluster */
|
||||
static struct dm_hash_table *node_hash;
|
||||
|
||||
/* Number of active nodes */
|
||||
static int num_nodes;
|
||||
static unsigned int our_nodeid;
|
||||
|
||||
static struct local_client *cluster_client;
|
||||
|
||||
/* Corosync handles */
|
||||
static cpg_handle_t cpg_handle;
|
||||
static quorum_handle_t quorum_handle;
|
||||
|
||||
/* DLM Handle */
|
||||
static dlm_lshandle_t *lockspace;
|
||||
|
||||
static struct cpg_name cpg_group_name;
|
||||
|
||||
/* Corosync callback structs */
|
||||
cpg_callbacks_t corosync_cpg_callbacks = {
|
||||
.cpg_deliver_fn = corosync_cpg_deliver_callback,
|
||||
.cpg_confchg_fn = corosync_cpg_confchg_callback,
|
||||
};
|
||||
|
||||
quorum_callbacks_t quorum_callbacks = {
|
||||
.quorum_notify_fn = NULL,
|
||||
};
|
||||
|
||||
struct node_info
|
||||
{
|
||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
int nodeid;
|
||||
};
|
||||
|
||||
|
||||
/* Set errno to something approximating the right value and return 0 or -1 */
|
||||
static int cs_to_errno(cs_error_t err)
|
||||
{
|
||||
switch(err)
|
||||
{
|
||||
case CS_OK:
|
||||
return 0;
|
||||
case CS_ERR_LIBRARY:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_VERSION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_INIT:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_TIMEOUT:
|
||||
errno = ETIME;
|
||||
break;
|
||||
case CS_ERR_TRY_AGAIN:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
case CS_ERR_INVALID_PARAM:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_NO_MEMORY:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case CS_ERR_BAD_HANDLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_BUSY:
|
||||
errno = EBUSY;
|
||||
break;
|
||||
case CS_ERR_ACCESS:
|
||||
errno = EPERM;
|
||||
break;
|
||||
case CS_ERR_NOT_EXIST:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case CS_ERR_NAME_TOO_LONG:
|
||||
errno = ENAMETOOLONG;
|
||||
break;
|
||||
case CS_ERR_EXIST:
|
||||
errno = EEXIST;
|
||||
break;
|
||||
case CS_ERR_NO_SPACE:
|
||||
errno = ENOSPC;
|
||||
break;
|
||||
case CS_ERR_INTERRUPT:
|
||||
errno = EINTR;
|
||||
break;
|
||||
case CS_ERR_NAME_NOT_FOUND:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case CS_ERR_NO_RESOURCES:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case CS_ERR_NOT_SUPPORTED:
|
||||
errno = EOPNOTSUPP;
|
||||
break;
|
||||
case CS_ERR_BAD_OPERATION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_FAILED_OPERATION:
|
||||
errno = EIO;
|
||||
break;
|
||||
case CS_ERR_MESSAGE_ERROR:
|
||||
errno = EIO;
|
||||
break;
|
||||
case CS_ERR_QUEUE_FULL:
|
||||
errno = EXFULL;
|
||||
break;
|
||||
case CS_ERR_QUEUE_NOT_AVAILABLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_BAD_FLAGS:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_TOO_BIG:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case CS_ERR_NO_SECTIONS:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *print_corosync_csid(const char *csid)
|
||||
{
|
||||
static char buf[128];
|
||||
int id;
|
||||
|
||||
memcpy(&id, csid, sizeof(int));
|
||||
sprintf(buf, "%d", id);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len)
|
||||
{
|
||||
int target_nodeid;
|
||||
|
||||
memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
|
||||
|
||||
DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
|
||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
||||
|
||||
if (nodeid != our_nodeid)
|
||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
||||
process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
|
||||
msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
|
||||
}
|
||||
|
||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
||||
{
|
||||
int i;
|
||||
struct node_info *ninfo;
|
||||
|
||||
DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n",
|
||||
joined_list_entries, left_list_entries, member_list_entries);
|
||||
|
||||
for (i=0; i<joined_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&joined_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = joined_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
COROSYNC_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
for (i=0; i<left_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&left_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (ninfo)
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
for (i=0; i<member_list_entries; i++) {
|
||||
if (member_list[i].nodeid == 0) continue;
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&member_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = member_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
COROSYNC_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
cs_error_t err;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
err = quorum_initialize(&quorum_handle,
|
||||
&quorum_callbacks);
|
||||
if (err != CS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
/* Create a lockspace for LV & VG locks to live in */
|
||||
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
|
||||
if (!lockspace) {
|
||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
||||
if (!lockspace) {
|
||||
syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
|
||||
return -1;
|
||||
}
|
||||
DEBUGLOG("Created DLM lockspace for CLVMD.\n");
|
||||
} else
|
||||
DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
|
||||
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
DEBUGLOG("DLM initialisation complete\n");
|
||||
|
||||
/* Connect to the clvmd group */
|
||||
strcpy((char *)cpg_group_name.value, "clvmd");
|
||||
cpg_group_name.length = strlen((char *)cpg_group_name.value);
|
||||
err = cpg_join(cpg_handle, &cpg_group_name);
|
||||
if (err != CS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
syslog(LOG_ERR, "Cannot join clvmd process group");
|
||||
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
err = cpg_local_get(cpg_handle,
|
||||
&our_nodeid);
|
||||
if (err != CS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
syslog(LOG_ERR, "Cannot get local node id\n");
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
DEBUGLOG("Our local node id is %d\n", our_nodeid);
|
||||
|
||||
DEBUGLOG("Connected to Corosync\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
destroy_lvhash();
|
||||
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
memcpy(csid, &our_nodeid, sizeof(int));
|
||||
}
|
||||
|
||||
/* Corosync doesn't really have nmode names so we
|
||||
just use the node ID in hex instead */
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
int nodeid;
|
||||
struct node_info *ninfo;
|
||||
|
||||
if (sscanf(name, "%x", &nodeid) == 1) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (ninfo)
|
||||
return nodeid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
sprintf(name, "UNKNOWN %s", print_corosync_csid(csid));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(name, "%x", ninfo->nodeid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
|
||||
print_corosync_csid(csid));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGLOG("corosync_add_up_node %d\n", ninfo->nodeid);
|
||||
|
||||
ninfo->state = NODE_CLVMD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *,
|
||||
const char *csid, int node_up))
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
char csid[COROSYNC_CSID_LEN];
|
||||
|
||||
ninfo = dm_hash_get_data(node_hash, hn);
|
||||
memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN);
|
||||
|
||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
||||
ninfo->state);
|
||||
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
struct dlm_lksb lksb;
|
||||
int err;
|
||||
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
||||
|
||||
if (flags & LKF_CONVERT)
|
||||
lksb.sb_lkid = *lockid;
|
||||
|
||||
err = dlm_ls_lock_wait(lockspace,
|
||||
mode,
|
||||
&lksb,
|
||||
flags,
|
||||
resource,
|
||||
strlen(resource),
|
||||
0,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_lock returned %d\n", errno);
|
||||
return err;
|
||||
}
|
||||
if (lksb.sb_status != 0)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
|
||||
errno = lksb.sb_status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
|
||||
|
||||
*lockid = lksb.sb_lkid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int _unlock_resource(const char *resource, int lockid)
|
||||
{
|
||||
struct dlm_lksb lksb;
|
||||
int err;
|
||||
|
||||
DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
|
||||
lksb.sb_lkid = lockid;
|
||||
|
||||
err = dlm_ls_unlock_wait(lockspace,
|
||||
lockid,
|
||||
0,
|
||||
&lksb);
|
||||
if (err != 0)
|
||||
{
|
||||
DEBUGLOG("Unlock returned %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (lksb.sb_status != EUNLOCK)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
|
||||
errno = lksb.sb_status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _is_quorate()
|
||||
{
|
||||
int quorate;
|
||||
if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
|
||||
return quorate;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd(void)
|
||||
{
|
||||
int select_fd;
|
||||
|
||||
cpg_fd_get(cpg_handle, &select_fd);
|
||||
return select_fd;
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
cluster_client = fd;
|
||||
*new_client = NULL;
|
||||
cpg_dispatch(cpg_handle, CS_DISPATCH_ONE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
||||
const char *errtext)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
cs_error_t err;
|
||||
int target_node;
|
||||
|
||||
if (csid)
|
||||
memcpy(&target_node, csid, COROSYNC_CSID_LEN);
|
||||
else
|
||||
target_node = 0;
|
||||
|
||||
iov[0].iov_base = &target_node;
|
||||
iov[0].iov_len = sizeof(int);
|
||||
iov[1].iov_base = (char *)buf;
|
||||
iov[1].iov_len = msglen;
|
||||
|
||||
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_corosync_ops = {
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.reread_config = NULL,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _lock_resource,
|
||||
.sync_unlock = _unlock_resource,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_corosync_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_corosync_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
1010
daemons/clvmd/clvmd-gulm.c
Normal file
1010
daemons/clvmd/clvmd-gulm.c
Normal file
File diff suppressed because it is too large
Load Diff
9
daemons/clvmd/clvmd-gulm.h
Normal file
9
daemons/clvmd/clvmd-gulm.h
Normal file
@@ -0,0 +1,9 @@
|
||||
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);
|
||||
693
daemons/clvmd/clvmd-openais.c
Normal file
693
daemons/clvmd/clvmd-openais.c
Normal file
@@ -0,0 +1,693 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This provides the interface between clvmd and OpenAIS as the cluster
|
||||
* and lock manager.
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <openais/saAis.h>
|
||||
#include <openais/saLck.h>
|
||||
|
||||
#include <corosync/corotypes.h>
|
||||
#include <corosync/cpg.h>
|
||||
|
||||
#include "locking.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvmd.h"
|
||||
|
||||
/* Timeout value for several openais calls */
|
||||
#define TIMEOUT 10
|
||||
|
||||
static void openais_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len);
|
||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries);
|
||||
|
||||
static void _cluster_closedown(void);
|
||||
|
||||
/* Hash list of nodes in the cluster */
|
||||
static struct dm_hash_table *node_hash;
|
||||
|
||||
/* For associating lock IDs & resource handles */
|
||||
static struct dm_hash_table *lock_hash;
|
||||
|
||||
/* Number of active nodes */
|
||||
static int num_nodes;
|
||||
static unsigned int our_nodeid;
|
||||
|
||||
static struct local_client *cluster_client;
|
||||
|
||||
/* OpenAIS handles */
|
||||
static cpg_handle_t cpg_handle;
|
||||
static SaLckHandleT lck_handle;
|
||||
|
||||
static struct cpg_name cpg_group_name;
|
||||
|
||||
/* Openais callback structs */
|
||||
cpg_callbacks_t openais_cpg_callbacks = {
|
||||
.cpg_deliver_fn = openais_cpg_deliver_callback,
|
||||
.cpg_confchg_fn = openais_cpg_confchg_callback,
|
||||
};
|
||||
|
||||
struct node_info
|
||||
{
|
||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
int nodeid;
|
||||
};
|
||||
|
||||
struct lock_info
|
||||
{
|
||||
SaLckResourceHandleT res_handle;
|
||||
SaLckLockIdT lock_id;
|
||||
SaNameT lock_name;
|
||||
};
|
||||
|
||||
/* Set errno to something approximating the right value and return 0 or -1 */
|
||||
static int ais_to_errno(SaAisErrorT err)
|
||||
{
|
||||
switch(err)
|
||||
{
|
||||
case SA_AIS_OK:
|
||||
return 0;
|
||||
case SA_AIS_ERR_LIBRARY:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case SA_AIS_ERR_VERSION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case SA_AIS_ERR_INIT:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case SA_AIS_ERR_TIMEOUT:
|
||||
errno = ETIME;
|
||||
break;
|
||||
case SA_AIS_ERR_TRY_AGAIN:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
case SA_AIS_ERR_INVALID_PARAM:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case SA_AIS_ERR_NO_MEMORY:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case SA_AIS_ERR_BAD_HANDLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case SA_AIS_ERR_BUSY:
|
||||
errno = EBUSY;
|
||||
break;
|
||||
case SA_AIS_ERR_ACCESS:
|
||||
errno = EPERM;
|
||||
break;
|
||||
case SA_AIS_ERR_NOT_EXIST:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case SA_AIS_ERR_NAME_TOO_LONG:
|
||||
errno = ENAMETOOLONG;
|
||||
break;
|
||||
case SA_AIS_ERR_EXIST:
|
||||
errno = EEXIST;
|
||||
break;
|
||||
case SA_AIS_ERR_NO_SPACE:
|
||||
errno = ENOSPC;
|
||||
break;
|
||||
case SA_AIS_ERR_INTERRUPT:
|
||||
errno = EINTR;
|
||||
break;
|
||||
case SA_AIS_ERR_NAME_NOT_FOUND:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case SA_AIS_ERR_NO_RESOURCES:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case SA_AIS_ERR_NOT_SUPPORTED:
|
||||
errno = EOPNOTSUPP;
|
||||
break;
|
||||
case SA_AIS_ERR_BAD_OPERATION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case SA_AIS_ERR_FAILED_OPERATION:
|
||||
errno = EIO;
|
||||
break;
|
||||
case SA_AIS_ERR_MESSAGE_ERROR:
|
||||
errno = EIO;
|
||||
break;
|
||||
case SA_AIS_ERR_QUEUE_FULL:
|
||||
errno = EXFULL;
|
||||
break;
|
||||
case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case SA_AIS_ERR_BAD_FLAGS:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case SA_AIS_ERR_TOO_BIG:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case SA_AIS_ERR_NO_SECTIONS:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *print_openais_csid(const char *csid)
|
||||
{
|
||||
static char buf[128];
|
||||
int id;
|
||||
|
||||
memcpy(&id, csid, sizeof(int));
|
||||
sprintf(buf, "%d", id);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int add_internal_client(int fd, fd_callback_t callback)
|
||||
{
|
||||
struct local_client *client;
|
||||
|
||||
DEBUGLOG("Add_internal_client, fd = %d\n", fd);
|
||||
|
||||
client = malloc(sizeof(struct local_client));
|
||||
if (!client)
|
||||
{
|
||||
DEBUGLOG("malloc failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(client, 0, sizeof(struct local_client));
|
||||
client->fd = fd;
|
||||
client->type = CLUSTER_INTERNAL;
|
||||
client->callback = callback;
|
||||
add_client(client);
|
||||
|
||||
/* Set Close-on-exec */
|
||||
fcntl(fd, F_SETFD, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void openais_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len)
|
||||
{
|
||||
int target_nodeid;
|
||||
|
||||
memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
|
||||
|
||||
DEBUGLOG("%u got message from nodeid %d for %d. len %d\n",
|
||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
||||
|
||||
if (nodeid != our_nodeid)
|
||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
||||
process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
|
||||
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
|
||||
}
|
||||
|
||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
||||
{
|
||||
int i;
|
||||
struct node_info *ninfo;
|
||||
|
||||
DEBUGLOG("confchg callback. %d joined, %d left, %d members\n",
|
||||
joined_list_entries, left_list_entries, member_list_entries);
|
||||
|
||||
for (i=0; i<joined_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&joined_list[i].nodeid,
|
||||
OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = joined_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
OPENAIS_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
for (i=0; i<left_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&left_list[i].nodeid,
|
||||
OPENAIS_CSID_LEN);
|
||||
if (ninfo)
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
for (i=0; i<member_list_entries; i++) {
|
||||
if (member_list[i].nodeid == 0) continue;
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&member_list[i].nodeid,
|
||||
OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = member_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
OPENAIS_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
static int lck_dispatch(struct local_client *client, char *buf, int len,
|
||||
const char *csid, struct local_client **new_client)
|
||||
{
|
||||
*new_client = NULL;
|
||||
saLckDispatch(lck_handle, SA_DISPATCH_ONE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
SaAisErrorT err;
|
||||
SaVersionT ver = { 'B', 1, 1 };
|
||||
int select_fd;
|
||||
|
||||
node_hash = dm_hash_create(100);
|
||||
lock_hash = dm_hash_create(10);
|
||||
|
||||
err = cpg_initialize(&cpg_handle,
|
||||
&openais_cpg_callbacks);
|
||||
if (err != SA_AIS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
err = saLckInitialize(&lck_handle,
|
||||
NULL,
|
||||
&ver);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_initialize(&cpg_handle, &openais_cpg_callbacks);
|
||||
syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* Connect to the clvmd group */
|
||||
strcpy((char *)cpg_group_name.value, "clvmd");
|
||||
cpg_group_name.length = strlen((char *)cpg_group_name.value);
|
||||
err = cpg_join(cpg_handle, &cpg_group_name);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
saLckFinalize(lck_handle);
|
||||
syslog(LOG_ERR, "Cannot join clvmd process group");
|
||||
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
err = cpg_local_get(cpg_handle,
|
||||
&our_nodeid);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
saLckFinalize(lck_handle);
|
||||
syslog(LOG_ERR, "Cannot get local node id\n");
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
DEBUGLOG("Our local node id is %d\n", our_nodeid);
|
||||
|
||||
saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
|
||||
add_internal_client(select_fd, lck_dispatch);
|
||||
|
||||
DEBUGLOG("Connected to OpenAIS\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
destroy_lvhash();
|
||||
|
||||
saLckFinalize(lck_handle);
|
||||
cpg_finalize(cpg_handle);
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
memcpy(csid, &our_nodeid, sizeof(int));
|
||||
}
|
||||
|
||||
/* OpenAIS doesn't really have nmode names so we
|
||||
just use the node ID in hex instead */
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
int nodeid;
|
||||
struct node_info *ninfo;
|
||||
|
||||
if (sscanf(name, "%x", &nodeid) == 1) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
||||
if (ninfo)
|
||||
return nodeid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
sprintf(name, "UNKNOWN %s", print_openais_csid(csid));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(name, "%x", ninfo->nodeid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
|
||||
print_openais_csid(csid));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
|
||||
|
||||
ninfo->state = NODE_CLVMD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *,
|
||||
const char *csid, int node_up))
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
char csid[OPENAIS_CSID_LEN];
|
||||
|
||||
ninfo = dm_hash_get_data(node_hash, hn);
|
||||
memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
|
||||
|
||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
||||
ninfo->state);
|
||||
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
struct lock_info *linfo;
|
||||
SaLckResourceHandleT res_handle;
|
||||
SaAisErrorT err;
|
||||
SaLckLockIdT lock_id;
|
||||
SaLckLockStatusT lockStatus;
|
||||
|
||||
/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
|
||||
if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
|
||||
|
||||
linfo = malloc(sizeof(struct lock_info));
|
||||
if (!linfo)
|
||||
return -1;
|
||||
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
||||
|
||||
linfo->lock_name.length = strlen(resource)+1;
|
||||
strcpy((char *)linfo->lock_name.value, resource);
|
||||
|
||||
err = saLckResourceOpen(lck_handle, &linfo->lock_name,
|
||||
SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
|
||||
if (err != SA_AIS_OK)
|
||||
{
|
||||
DEBUGLOG("ResourceOpen returned %d\n", err);
|
||||
free(linfo);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
err = saLckResourceLock(
|
||||
res_handle,
|
||||
&lock_id,
|
||||
mode,
|
||||
flags,
|
||||
0,
|
||||
SA_TIME_END,
|
||||
&lockStatus);
|
||||
if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
|
||||
{
|
||||
free(linfo);
|
||||
saLckResourceClose(res_handle);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* Wait for it to complete */
|
||||
|
||||
DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", err,
|
||||
lock_id);
|
||||
|
||||
linfo->lock_id = lock_id;
|
||||
linfo->res_handle = res_handle;
|
||||
|
||||
dm_hash_insert(lock_hash, resource, linfo);
|
||||
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
|
||||
static int _unlock_resource(char *resource, int lockid)
|
||||
{
|
||||
SaAisErrorT err;
|
||||
struct lock_info *linfo;
|
||||
|
||||
DEBUGLOG("unlock_resource %s\n", resource);
|
||||
linfo = dm_hash_lookup(lock_hash, resource);
|
||||
if (!linfo)
|
||||
return 0;
|
||||
|
||||
DEBUGLOG("unlock_resource: lockid: %llx\n", linfo->lock_id);
|
||||
err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
|
||||
if (err != SA_AIS_OK)
|
||||
{
|
||||
DEBUGLOG("Unlock returned %d\n", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* Release the resource */
|
||||
dm_hash_remove(lock_hash, resource);
|
||||
saLckResourceClose(linfo->res_handle);
|
||||
free(linfo);
|
||||
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
char lock1[strlen(resource)+3];
|
||||
char lock2[strlen(resource)+3];
|
||||
|
||||
snprintf(lock1, sizeof(lock1), "%s-1", resource);
|
||||
snprintf(lock2, sizeof(lock2), "%s-2", resource);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case LCK_EXCL:
|
||||
status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
/* If we can't get this lock too then bail out */
|
||||
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
|
||||
lockid);
|
||||
if (status == SA_LCK_LOCK_NOT_QUEUED)
|
||||
{
|
||||
_unlock_resource(lock1, *lockid);
|
||||
status = -1;
|
||||
errno = EAGAIN;
|
||||
}
|
||||
break;
|
||||
|
||||
case LCK_PREAD:
|
||||
case LCK_READ:
|
||||
status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
_unlock_resource(lock2, *lockid);
|
||||
break;
|
||||
|
||||
case LCK_WRITE:
|
||||
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
_unlock_resource(lock1, *lockid);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = -1;
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
out:
|
||||
*lockid = mode;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int _sync_unlock(const char *resource, int lockid)
|
||||
{
|
||||
int status = 0;
|
||||
char lock1[strlen(resource)+3];
|
||||
char lock2[strlen(resource)+3];
|
||||
|
||||
snprintf(lock1, sizeof(lock1), "%s-1", resource);
|
||||
snprintf(lock2, sizeof(lock2), "%s-2", resource);
|
||||
|
||||
_unlock_resource(lock1, lockid);
|
||||
_unlock_resource(lock2, lockid);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* We are always quorate ! */
|
||||
static int _is_quorate()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd(void)
|
||||
{
|
||||
int select_fd;
|
||||
|
||||
cpg_fd_get(cpg_handle, &select_fd);
|
||||
return select_fd;
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
cluster_client = fd;
|
||||
*new_client = NULL;
|
||||
cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
||||
const char *errtext)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
SaAisErrorT err;
|
||||
int target_node;
|
||||
|
||||
if (csid)
|
||||
memcpy(&target_node, csid, OPENAIS_CSID_LEN);
|
||||
else
|
||||
target_node = 0;
|
||||
|
||||
iov[0].iov_base = &target_node;
|
||||
iov[0].iov_len = sizeof(int);
|
||||
iov[1].iov_base = (char *)buf;
|
||||
iov[1].iov_len = msglen;
|
||||
|
||||
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* We don't have a cluster name to report here */
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
strncpy(buf, "OpenAIS", buflen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_openais_ops = {
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.reread_config = NULL,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _sync_lock,
|
||||
.sync_unlock = _sync_unlock,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_openais_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_openais_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
287
daemons/clvmd/clvmd-singlenode.c
Normal file
287
daemons/clvmd/clvmd-singlenode.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "locking.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvmd.h"
|
||||
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock";
|
||||
static int listen_fd = -1;
|
||||
|
||||
static void close_comms(void)
|
||||
{
|
||||
if (listen_fd != -1 && close(listen_fd))
|
||||
stack;
|
||||
(void)unlink(SINGLENODE_CLVMD_SOCKNAME);
|
||||
listen_fd = -1;
|
||||
}
|
||||
|
||||
static int init_comms(void)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
mode_t old_mask;
|
||||
|
||||
close_comms();
|
||||
|
||||
(void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK);
|
||||
old_mask = umask(0077);
|
||||
|
||||
listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (listen_fd < 0) {
|
||||
DEBUGLOG("Can't create local socket: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
/* Set Close-on-exec */
|
||||
fcntl(listen_fd, F_SETFD, 1);
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
memcpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
|
||||
sizeof(SINGLENODE_CLVMD_SOCKNAME));
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
DEBUGLOG("Can't bind local socket: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
if (listen(listen_fd, 10) < 0) {
|
||||
DEBUGLOG("Can't listen local socket: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
error:
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
close_comms();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = init_comms();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
DEBUGLOG("Single-node cluster initialised.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
close_comms();
|
||||
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
destroy_lvhash();
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
int nodeid = 1;
|
||||
memcpy(csid, &nodeid, sizeof(int));
|
||||
}
|
||||
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
sprintf(name, "SINGLENODE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_num_nodes(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *,
|
||||
const char *csid, int node_up))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _lock_file(const char *file, uint32_t flags);
|
||||
|
||||
static int *_locks = NULL;
|
||||
static char **_resources = NULL;
|
||||
static int _lock_max = 1;
|
||||
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int *_locks_1;
|
||||
char **_resources_1;
|
||||
int i, j;
|
||||
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n",
|
||||
resource, flags, mode);
|
||||
|
||||
retry:
|
||||
pthread_mutex_lock(&_lock_mutex);
|
||||
|
||||
/* look for an existing lock for this resource */
|
||||
for (i = 1; i < _lock_max; ++i) {
|
||||
if (!_resources[i])
|
||||
break;
|
||||
if (!strcmp(_resources[i], resource)) {
|
||||
if ((_locks[i] & LCK_TYPE_MASK) == LCK_WRITE ||
|
||||
(_locks[i] & LCK_TYPE_MASK) == LCK_EXCL) {
|
||||
DEBUGLOG("%s already write/exclusively locked...\n", resource);
|
||||
goto maybe_retry;
|
||||
}
|
||||
if ((mode & LCK_TYPE_MASK) == LCK_WRITE ||
|
||||
(mode & LCK_TYPE_MASK) == LCK_EXCL) {
|
||||
DEBUGLOG("%s already locked and WRITE/EXCL lock requested...\n",
|
||||
resource);
|
||||
goto maybe_retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == _lock_max) { /* out of lock slots, extend */
|
||||
_locks_1 = dm_realloc(_locks, 2 * _lock_max * sizeof(int));
|
||||
if (!_locks_1)
|
||||
return 1; /* fail */
|
||||
_locks = _locks_1;
|
||||
_resources_1 = dm_realloc(_resources, 2 * _lock_max * sizeof(char *));
|
||||
if (!_resources_1) {
|
||||
/* _locks may get realloc'd twice, but that should be safe */
|
||||
return 1; /* fail */
|
||||
}
|
||||
_resources = _resources_1;
|
||||
/* clear the new resource entries */
|
||||
for (j = _lock_max; j < 2 * _lock_max; ++j)
|
||||
_resources[j] = NULL;
|
||||
_lock_max = 2 * _lock_max;
|
||||
}
|
||||
|
||||
/* resource is not currently locked, grab it */
|
||||
|
||||
*lockid = i;
|
||||
_locks[i] = mode;
|
||||
_resources[i] = dm_strdup(resource);
|
||||
|
||||
DEBUGLOG("%s locked -> %d\n", resource, i);
|
||||
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
return 0;
|
||||
maybe_retry:
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
if (!(flags & LCK_NONBLOCK)) {
|
||||
usleep(10000);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return 1; /* fail */
|
||||
}
|
||||
|
||||
static int _unlock_resource(const char *resource, int lockid)
|
||||
{
|
||||
DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
|
||||
if(!_resources[lockid]) {
|
||||
DEBUGLOG("(%s) %d not locked\n", resource, lockid);
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(_resources[lockid], resource)) {
|
||||
DEBUGLOG("%d has wrong resource (requested %s, got %s)\n",
|
||||
lockid, resource, _resources[lockid]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dm_free(_resources[lockid]);
|
||||
_resources[lockid] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _is_quorate(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd(void)
|
||||
{
|
||||
return listen_fd;
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cluster_send_message(const void *buf, int msglen,
|
||||
const char *csid,
|
||||
const char *errtext)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
strncpy(buf, "localcluster", buflen);
|
||||
buf[buflen - 1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_singlenode_ops = {
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.reread_config = NULL,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _lock_resource,
|
||||
.sync_unlock = _unlock_resource,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_singlenode_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_singlenode_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
2259
daemons/clvmd/clvmd.c
Normal file
2259
daemons/clvmd/clvmd.c
Normal file
File diff suppressed because it is too large
Load Diff
126
daemons/clvmd/clvmd.h
Normal file
126
daemons/clvmd/clvmd.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _CLVMD_H
|
||||
#define _CLVMD_H
|
||||
|
||||
#define CLVMD_MAJOR_VERSION 0
|
||||
#define CLVMD_MINOR_VERSION 2
|
||||
#define CLVMD_PATCH_VERSION 1
|
||||
|
||||
/* Default time (in seconds) we will wait for all remote commands to execute
|
||||
before declaring them dead */
|
||||
#define DEFAULT_CMD_TIMEOUT 60
|
||||
|
||||
/* One of these for each reply we get from command execution on a node */
|
||||
struct node_reply {
|
||||
char node[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
char *replymsg;
|
||||
int status;
|
||||
struct node_reply *next;
|
||||
};
|
||||
|
||||
typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t;
|
||||
|
||||
/*
|
||||
* These exist for the use of local sockets only when we are
|
||||
* collecting responses from all cluster nodes
|
||||
*/
|
||||
struct localsock_bits {
|
||||
struct node_reply *replies;
|
||||
int num_replies;
|
||||
int expected_replies;
|
||||
time_t sent_time; /* So we can check for timeouts */
|
||||
int in_progress; /* Only execute one cmd at a time per client */
|
||||
int sent_out; /* Flag to indicate that a command was sent
|
||||
to remote nodes */
|
||||
void *private; /* Private area for command processor use */
|
||||
void *cmd; /* Whole command as passed down local socket */
|
||||
int cmd_len; /* Length of above */
|
||||
int pipe; /* Pipe to send PRE completion status down */
|
||||
int finished; /* Flag to tell subthread to exit */
|
||||
int all_success; /* Set to 0 if any node (or the pre_command)
|
||||
failed */
|
||||
struct local_client *pipe_client;
|
||||
pthread_t threadid;
|
||||
enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
|
||||
pthread_mutex_t mutex; /* Main thread and worker synchronisation */
|
||||
pthread_cond_t cond;
|
||||
|
||||
pthread_mutex_t reply_mutex; /* Protect reply structure */
|
||||
};
|
||||
|
||||
/* Entries for PIPE clients */
|
||||
struct pipe_bits {
|
||||
struct local_client *client; /* Actual (localsock) client */
|
||||
pthread_t threadid; /* Our own copy of the thread id */
|
||||
};
|
||||
|
||||
/* Entries for Network socket clients */
|
||||
struct netsock_bits {
|
||||
void *private;
|
||||
int flags;
|
||||
};
|
||||
|
||||
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client ** new_client);
|
||||
|
||||
/* One of these for each fd we are listening on */
|
||||
struct local_client {
|
||||
int fd;
|
||||
enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
|
||||
LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
|
||||
struct local_client *next;
|
||||
unsigned short xid;
|
||||
fd_callback_t callback;
|
||||
uint8_t removeme;
|
||||
|
||||
union {
|
||||
struct localsock_bits localsock;
|
||||
struct pipe_bits pipe;
|
||||
struct netsock_bits net;
|
||||
} bits;
|
||||
};
|
||||
|
||||
#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args);
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
/* The real command processor is in clvmd-command.c */
|
||||
extern int do_command(struct local_client *client, struct clvm_header *msg,
|
||||
int msglen, char **buf, int buflen, int *retlen);
|
||||
|
||||
/* Pre and post command routines are called only on the local node */
|
||||
extern int do_pre_command(struct local_client *client);
|
||||
extern int do_post_command(struct local_client *client);
|
||||
extern void cmd_client_cleanup(struct local_client *client);
|
||||
extern int add_client(struct local_client *new_client);
|
||||
|
||||
extern void clvmd_cluster_init_completed(void);
|
||||
extern void process_message(struct local_client *client, 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 sync_lock(const char *resource, int mode, int flags, int *lockid);
|
||||
int sync_unlock(const char *resource, int lockid);
|
||||
|
||||
#endif
|
||||
955
daemons/clvmd/lvm-functions.c
Normal file
955
daemons/clvmd/lvm-functions.c
Normal file
@@ -0,0 +1,955 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "lvm-types.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
/* LVM2 headers */
|
||||
#include "toolcontext.h"
|
||||
#include "lvmcache.h"
|
||||
#include "lvm-globals.h"
|
||||
#include "activate.h"
|
||||
#include "archiver.h"
|
||||
#include "memlock.h"
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
static struct cmd_context *cmd = NULL;
|
||||
static struct dm_hash_table *lv_hash = NULL;
|
||||
static pthread_mutex_t lv_hash_lock;
|
||||
static pthread_mutex_t lvm_lock;
|
||||
static char last_error[1024];
|
||||
|
||||
struct lv_info {
|
||||
int lock_id;
|
||||
int lock_mode;
|
||||
};
|
||||
|
||||
static const char *decode_full_locking_cmd(uint32_t cmdl)
|
||||
{
|
||||
static char buf[128];
|
||||
const char *type;
|
||||
const char *scope;
|
||||
const char *command;
|
||||
|
||||
switch (cmdl & LCK_TYPE_MASK) {
|
||||
case LCK_NULL:
|
||||
type = "NULL";
|
||||
break;
|
||||
case LCK_READ:
|
||||
type = "READ";
|
||||
break;
|
||||
case LCK_PREAD:
|
||||
type = "PREAD";
|
||||
break;
|
||||
case LCK_WRITE:
|
||||
type = "WRITE";
|
||||
break;
|
||||
case LCK_EXCL:
|
||||
type = "EXCL";
|
||||
break;
|
||||
case LCK_UNLOCK:
|
||||
type = "UNLOCK";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmdl & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
scope = "VG";
|
||||
command = "LCK_VG";
|
||||
break;
|
||||
case LCK_LV:
|
||||
scope = "LV";
|
||||
switch (cmdl & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE & LCK_MASK:
|
||||
command = "LCK_LV_EXCLUSIVE";
|
||||
break;
|
||||
case LCK_LV_SUSPEND & LCK_MASK:
|
||||
command = "LCK_LV_SUSPEND";
|
||||
break;
|
||||
case LCK_LV_RESUME & LCK_MASK:
|
||||
command = "LCK_LV_RESUME";
|
||||
break;
|
||||
case LCK_LV_ACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_ACTIVATE";
|
||||
break;
|
||||
case LCK_LV_DEACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_DEACTIVATE";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
scope = "unknown";
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buf, "0x%x %s (%s|%s%s%s%s%s%s)", cmdl, command, type, scope,
|
||||
cmdl & LCK_NONBLOCK ? "|NONBLOCK" : "",
|
||||
cmdl & LCK_HOLD ? "|HOLD" : "",
|
||||
cmdl & LCK_LOCAL ? "|LOCAL" : "",
|
||||
cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
|
||||
cmdl & LCK_CACHE ? "|CACHE" : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only processes 8 bits: excludes LCK_CACHE.
|
||||
*/
|
||||
static const char *decode_locking_cmd(unsigned char cmdl)
|
||||
{
|
||||
return decode_full_locking_cmd((uint32_t) cmdl);
|
||||
}
|
||||
|
||||
static const char *decode_flags(unsigned char flags)
|
||||
{
|
||||
static char buf[128];
|
||||
int len;
|
||||
|
||||
len = sprintf(buf, "0x%x ( %s%s%s%s%s)", flags,
|
||||
flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE|" : "",
|
||||
flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC|" : "",
|
||||
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
|
||||
flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
|
||||
flags & LCK_CONVERT ? "CONVERT|" : "");
|
||||
|
||||
if (len > 1)
|
||||
buf[len - 2] = ' ';
|
||||
else
|
||||
buf[0] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *get_last_lvm_error()
|
||||
{
|
||||
return last_error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash lock info helpers
|
||||
*/
|
||||
static struct lv_info *lookup_info(const char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = dm_hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
|
||||
return lvi;
|
||||
}
|
||||
|
||||
static void insert_info(const char *resource, struct lv_info *lvi)
|
||||
{
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
dm_hash_insert(lv_hash, resource, lvi);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
static void remove_info(const char *resource)
|
||||
{
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
dm_hash_remove(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the mode a lock is currently held at (or -1 if not held)
|
||||
*/
|
||||
static int get_current_lock(char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
if ((lvi = lookup_info(resource)))
|
||||
return lvi->lock_mode;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void init_lvhash()
|
||||
{
|
||||
/* Create hash table for keeping LV locks & status */
|
||||
lv_hash = dm_hash_create(1024);
|
||||
pthread_mutex_init(&lv_hash_lock, NULL);
|
||||
pthread_mutex_init(&lvm_lock, NULL);
|
||||
}
|
||||
|
||||
/* Called at shutdown to tidy the lockspace */
|
||||
void destroy_lvhash()
|
||||
{
|
||||
struct dm_hash_node *v;
|
||||
struct lv_info *lvi;
|
||||
char *resource;
|
||||
int status;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
|
||||
dm_hash_iterate(v, lv_hash) {
|
||||
lvi = dm_hash_get_data(lv_hash, v);
|
||||
resource = dm_hash_get_key(lv_hash, v);
|
||||
|
||||
if ((status = sync_unlock(resource, lvi->lock_id)))
|
||||
DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
|
||||
status, strerror(errno));
|
||||
free(lvi);
|
||||
}
|
||||
|
||||
dm_hash_destroy(lv_hash);
|
||||
lv_hash = NULL;
|
||||
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
/* Gets a real lock and keeps the info in the hash table */
|
||||
static int hold_lock(char *resource, int mode, int flags)
|
||||
{
|
||||
int status;
|
||||
int saved_errno;
|
||||
struct lv_info *lvi;
|
||||
|
||||
/* Mask off invalid options */
|
||||
flags &= LCKF_NOQUEUE | LCKF_CONVERT;
|
||||
|
||||
lvi = lookup_info(resource);
|
||||
|
||||
if (lvi) {
|
||||
if (lvi->lock_mode == mode) {
|
||||
DEBUGLOG("hold_lock, lock mode %d already held\n",
|
||||
mode);
|
||||
return 0;
|
||||
}
|
||||
if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
|
||||
DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
|
||||
"ignoring LCK_WRITE request");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only allow explicit conversions */
|
||||
if (lvi && !(flags & LCKF_CONVERT)) {
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
if (lvi) {
|
||||
/* Already exists - convert it */
|
||||
status =
|
||||
sync_lock(resource, mode, flags, &lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status)
|
||||
lvi->lock_mode = mode;
|
||||
|
||||
if (status) {
|
||||
DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
|
||||
strerror(errno));
|
||||
}
|
||||
errno = saved_errno;
|
||||
} else {
|
||||
lvi = malloc(sizeof(struct lv_info));
|
||||
if (!lvi)
|
||||
return -1;
|
||||
|
||||
lvi->lock_mode = mode;
|
||||
status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (status) {
|
||||
free(lvi);
|
||||
DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
|
||||
strerror(errno));
|
||||
} else
|
||||
insert_info(resource, lvi);
|
||||
|
||||
errno = saved_errno;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Unlock and remove it from the hash table */
|
||||
static int hold_unlock(char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
int status;
|
||||
int saved_errno;
|
||||
|
||||
if (!(lvi = lookup_info(resource))) {
|
||||
DEBUGLOG("hold_unlock, lock not already held\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = sync_unlock(resource, lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status) {
|
||||
remove_info(resource);
|
||||
free(lvi);
|
||||
} else {
|
||||
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Watch the return codes here.
|
||||
liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
|
||||
libdlm API functions return 0 for success, -1 for failure and do set errno.
|
||||
These functions here return 0 for success or >0 for failure (where the retcode is errno)
|
||||
*/
|
||||
|
||||
/* Activate LV exclusive or non-exclusive */
|
||||
static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
|
||||
{
|
||||
int oldmode;
|
||||
int status;
|
||||
int activate_lv;
|
||||
int exclusive = 0;
|
||||
struct lvinfo lvi;
|
||||
|
||||
/* Is it already open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == mode && (lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_activate_lv, lock already held at %d\n", oldmode);
|
||||
return 0; /* Nothing to do */
|
||||
}
|
||||
|
||||
/* Does the config file want us to activate this LV ? */
|
||||
if (!lv_activation_filter(cmd, resource, &activate_lv))
|
||||
return EIO;
|
||||
|
||||
if (!activate_lv)
|
||||
return 0; /* Success, we did nothing! */
|
||||
|
||||
/* Do we need to activate exclusively? */
|
||||
if ((activate_lv == 2) || (mode == LCK_EXCL)) {
|
||||
exclusive = 1;
|
||||
mode = LCK_EXCL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get the lock if it's a clustered volume group.
|
||||
* Use lock conversion only if requested, to prevent implicit conversion
|
||||
* of exclusive lock to shared one during activation.
|
||||
*/
|
||||
if (lock_flags & LCK_CLUSTER_VG) {
|
||||
status = hold_lock(resource, mode, LCKF_NOQUEUE | (lock_flags & LCK_CONVERT ? LCKF_CONVERT:0));
|
||||
if (status) {
|
||||
/* Return an LVM-sensible error for this.
|
||||
* Forcing EIO makes the upper level return this text
|
||||
* rather than the strerror text for EAGAIN.
|
||||
*/
|
||||
if (errno == EAGAIN) {
|
||||
sprintf(last_error, "Volume is busy on another node");
|
||||
errno = EIO;
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's suspended then resume it */
|
||||
if (!lv_info_by_lvid(cmd, resource, 0, &lvi, 0, 0))
|
||||
goto error;
|
||||
|
||||
if (lvi.suspended) {
|
||||
memlock_inc(cmd);
|
||||
if (!lv_resume(cmd, resource, 0)) {
|
||||
memlock_dec(cmd);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now activate it */
|
||||
if (!lv_activate(cmd, resource, exclusive))
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (oldmode == -1 || oldmode != mode)
|
||||
(void)hold_unlock(resource);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
/* Resume the LV if it was active */
|
||||
static int do_resume_lv(char *resource, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_resume_lv, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
|
||||
if (!lv_resume_if_active(cmd, resource, (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0))
|
||||
return EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Suspend the device if active */
|
||||
static int do_suspend_lv(char *resource, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode;
|
||||
struct lvinfo lvi;
|
||||
unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_suspend_lv, lock not already held\n");
|
||||
return 0; /* Not active, so it's OK */
|
||||
}
|
||||
|
||||
/* Only suspend it if it exists */
|
||||
if (!lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0))
|
||||
return EIO;
|
||||
|
||||
if (lvi.exists && !lv_suspend_if_active(cmd, resource, origin_only))
|
||||
return EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_deactivate_lv(char *resource, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode;
|
||||
int status;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_deactivate_lock, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
|
||||
if (!lv_deactivate(cmd, resource))
|
||||
return EIO;
|
||||
|
||||
if (lock_flags & LCK_CLUSTER_VG) {
|
||||
status = hold_unlock(resource);
|
||||
if (status)
|
||||
return errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *do_lock_query(char *resource)
|
||||
{
|
||||
int mode;
|
||||
const char *type = NULL;
|
||||
|
||||
mode = get_current_lock(resource);
|
||||
switch (mode) {
|
||||
case LCK_NULL: type = "NL"; break;
|
||||
case LCK_READ: type = "CR"; break;
|
||||
case LCK_PREAD:type = "PR"; break;
|
||||
case LCK_WRITE:type = "PW"; break;
|
||||
case LCK_EXCL: type = "EX"; break;
|
||||
}
|
||||
|
||||
DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "?");
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* This is the LOCK_LV part that happens on all nodes in the cluster -
|
||||
it is responsible for the interaction with device-mapper and LVM */
|
||||
int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, memlock = %d\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags), memlock());
|
||||
|
||||
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||
/* Reinitialise various settings inc. logging, filters */
|
||||
if (do_refresh_cache()) {
|
||||
log_error("Updated config file invalid. Aborting.");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||
init_mirror_in_sync(1);
|
||||
|
||||
if (lock_flags & LCK_DMEVENTD_MONITOR_MODE)
|
||||
init_dmeventd_monitor(1);
|
||||
else
|
||||
init_dmeventd_monitor(0);
|
||||
|
||||
cmd->partial_activation = (lock_flags & LCK_PARTIAL_MODE) ? 1 : 0;
|
||||
|
||||
/* clvmd should never try to read suspended device */
|
||||
init_ignore_suspended_devices(1);
|
||||
|
||||
switch (command & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, lock_flags, LCK_EXCL);
|
||||
break;
|
||||
|
||||
case LCK_LV_SUSPEND:
|
||||
status = do_suspend_lv(resource, lock_flags);
|
||||
break;
|
||||
|
||||
case LCK_UNLOCK:
|
||||
case LCK_LV_RESUME: /* if active */
|
||||
status = do_resume_lv(resource, lock_flags);
|
||||
break;
|
||||
|
||||
case LCK_LV_ACTIVATE:
|
||||
status = do_activate_lv(resource, lock_flags, LCK_READ);
|
||||
break;
|
||||
|
||||
case LCK_LV_DEACTIVATE:
|
||||
status = do_deactivate_lv(resource, lock_flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUGLOG("Invalid LV command 0x%x\n", command);
|
||||
status = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||
init_mirror_in_sync(0);
|
||||
|
||||
cmd->partial_activation = 0;
|
||||
|
||||
/* clean the pool for another command */
|
||||
dm_pool_empty(cmd->mem);
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
|
||||
DEBUGLOG("Command return is %d, memlock is %d\n", status, memlock());
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
|
||||
int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
|
||||
lock out on this node (because we are the node modifying the metadata)
|
||||
before suspending cluster-wide.
|
||||
LCKF_CONVERT is used always, local node is going to modify metadata
|
||||
*/
|
||||
if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND &&
|
||||
(lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
if (hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT))
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
|
||||
int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
char *resource)
|
||||
{
|
||||
int status;
|
||||
unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
|
||||
|
||||
/* Opposite of above, done on resume after a metadata update */
|
||||
if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME &&
|
||||
(lock_flags & LCK_CLUSTER_VG)) {
|
||||
int oldmode;
|
||||
|
||||
DEBUGLOG
|
||||
("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
/* If the lock state is PW then restore it to what it was */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == LCK_WRITE) {
|
||||
struct lvinfo lvi;
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
status = lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0);
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
if (!status)
|
||||
return EIO;
|
||||
|
||||
if (lvi.exists) {
|
||||
if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
|
||||
return errno;
|
||||
} else if (hold_unlock(resource))
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if a VG is in use by LVM1 so we don't stomp on it */
|
||||
int do_check_lvm1(const char *vgname)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = check_lvm1_vg_inactive(cmd, vgname);
|
||||
|
||||
return status == 1 ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
int do_refresh_cache()
|
||||
{
|
||||
DEBUGLOG("Refreshing context\n");
|
||||
log_notice("Refreshing context");
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
|
||||
if (!refresh_toolcontext(cmd)) {
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
init_full_scan_done(0);
|
||||
init_ignore_suspended_devices(1);
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
|
||||
that might be hanging around if we died for any reason
|
||||
*/
|
||||
static void drop_vg_locks(void)
|
||||
{
|
||||
char vg[128];
|
||||
char line[255];
|
||||
FILE *vgs =
|
||||
popen
|
||||
(LVM_PATH " pvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_name", "r");
|
||||
|
||||
sync_unlock("P_" VG_ORPHANS, LCK_EXCL);
|
||||
sync_unlock("P_" VG_GLOBAL, LCK_EXCL);
|
||||
|
||||
if (!vgs)
|
||||
return;
|
||||
|
||||
while (fgets(line, sizeof(line), vgs)) {
|
||||
char *vgend;
|
||||
char *vgstart;
|
||||
|
||||
if (line[strlen(line)-1] == '\n')
|
||||
line[strlen(line)-1] = '\0';
|
||||
|
||||
vgstart = line + strspn(line, " ");
|
||||
vgend = vgstart + strcspn(vgstart, " ");
|
||||
*vgend = '\0';
|
||||
|
||||
if (strncmp(vgstart, "WARNING:", 8) == 0)
|
||||
continue;
|
||||
|
||||
sprintf(vg, "V_%s", vgstart);
|
||||
sync_unlock(vg, LCK_EXCL);
|
||||
|
||||
}
|
||||
if (fclose(vgs))
|
||||
DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle VG lock - drop metadata or update lvmcache state
|
||||
*/
|
||||
void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
uint32_t lock_cmd = command;
|
||||
char *vgname = resource + 2;
|
||||
|
||||
lock_cmd &= (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_HOLD);
|
||||
|
||||
/*
|
||||
* Check if LCK_CACHE should be set. All P_ locks except # are cache related.
|
||||
*/
|
||||
if (strncmp(resource, "P_#", 3) && !strncmp(resource, "P_", 2))
|
||||
lock_cmd |= LCK_CACHE;
|
||||
|
||||
DEBUGLOG("do_lock_vg: resource '%s', cmd = %s, flags = %s, memlock = %d\n",
|
||||
resource, decode_full_locking_cmd(lock_cmd), decode_flags(lock_flags), memlock());
|
||||
|
||||
/* P_#global causes a full cache refresh */
|
||||
if (!strcmp(resource, "P_" VG_GLOBAL)) {
|
||||
do_refresh_cache();
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
switch (lock_cmd) {
|
||||
case LCK_VG_COMMIT:
|
||||
DEBUGLOG("vg_commit notification for VG %s\n", vgname);
|
||||
lvmcache_commit_metadata(vgname);
|
||||
break;
|
||||
case LCK_VG_REVERT:
|
||||
DEBUGLOG("vg_revert notification for VG %s\n", vgname);
|
||||
lvmcache_drop_metadata(vgname, 1);
|
||||
break;
|
||||
case LCK_VG_DROP_CACHE:
|
||||
default:
|
||||
DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
|
||||
lvmcache_drop_metadata(vgname, 0);
|
||||
}
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the uuid with the list of exclusive locks that clvmd
|
||||
* held before it was restarted, so we can get the right kind
|
||||
* of lock now we are restarting.
|
||||
*/
|
||||
static int was_ex_lock(char *uuid, char **argv)
|
||||
{
|
||||
int optnum = 0;
|
||||
char *opt = argv[optnum];
|
||||
|
||||
while (opt) {
|
||||
if (strcmp(opt, "-E") == 0) {
|
||||
opt = argv[++optnum];
|
||||
if (opt && (strcmp(opt, uuid) == 0)) {
|
||||
DEBUGLOG("Lock %s is exclusive\n", uuid);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
opt = argv[++optnum];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ideally, clvmd should be started before any LVs are active
|
||||
* but this may not be the case...
|
||||
* I suppose this also comes in handy if clvmd crashes, not that it would!
|
||||
*/
|
||||
static void *get_initial_state(char **argv)
|
||||
{
|
||||
int lock_mode;
|
||||
char lv[64], vg[64], flags[25], vg_flags[25];
|
||||
char uuid[65];
|
||||
char line[255];
|
||||
FILE *lvs =
|
||||
popen
|
||||
(LVM_PATH " lvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
|
||||
"r");
|
||||
|
||||
if (!lvs)
|
||||
return NULL;
|
||||
|
||||
while (fgets(line, sizeof(line), lvs)) {
|
||||
if (sscanf(line, "%s %s %s %s\n", vg, lv, flags, vg_flags) == 4) {
|
||||
|
||||
/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
|
||||
if (strlen(vg) == 38 && /* is is a valid UUID ? */
|
||||
(flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */
|
||||
vg_flags[5] == 'c') { /* is it clustered ? */
|
||||
/* Convert hyphen-separated UUIDs into one */
|
||||
memcpy(&uuid[0], &vg[0], 6);
|
||||
memcpy(&uuid[6], &vg[7], 4);
|
||||
memcpy(&uuid[10], &vg[12], 4);
|
||||
memcpy(&uuid[14], &vg[17], 4);
|
||||
memcpy(&uuid[18], &vg[22], 4);
|
||||
memcpy(&uuid[22], &vg[27], 4);
|
||||
memcpy(&uuid[26], &vg[32], 6);
|
||||
memcpy(&uuid[32], &lv[0], 6);
|
||||
memcpy(&uuid[38], &lv[7], 4);
|
||||
memcpy(&uuid[42], &lv[12], 4);
|
||||
memcpy(&uuid[46], &lv[17], 4);
|
||||
memcpy(&uuid[50], &lv[22], 4);
|
||||
memcpy(&uuid[54], &lv[27], 4);
|
||||
memcpy(&uuid[58], &lv[32], 6);
|
||||
uuid[64] = '\0';
|
||||
|
||||
lock_mode = LCK_READ;
|
||||
|
||||
/* Look for this lock in the list of EX locks
|
||||
we were passed on the command-line */
|
||||
if (was_ex_lock(uuid, argv))
|
||||
lock_mode = LCK_EXCL;
|
||||
|
||||
DEBUGLOG("getting initial lock for %s\n", uuid);
|
||||
hold_lock(uuid, lock_mode, LCKF_NOQUEUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fclose(lvs))
|
||||
DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void lvm2_log_fn(int level, const char *file, int line, int dm_errno,
|
||||
const char *message)
|
||||
{
|
||||
|
||||
/* Send messages to the normal LVM2 logging system too,
|
||||
so we get debug output when it's asked for.
|
||||
We need to NULL the function ptr otherwise it will just call
|
||||
back into here! */
|
||||
init_log_fn(NULL);
|
||||
print_log(level, file, line, dm_errno, "%s", message);
|
||||
init_log_fn(lvm2_log_fn);
|
||||
|
||||
/*
|
||||
* Ignore non-error messages, but store the latest one for returning
|
||||
* to the user.
|
||||
*/
|
||||
if (level != _LOG_ERR && level != _LOG_FATAL)
|
||||
return;
|
||||
|
||||
strncpy(last_error, message, sizeof(last_error));
|
||||
last_error[sizeof(last_error)-1] = '\0';
|
||||
}
|
||||
|
||||
/* This checks some basic cluster-LVM configuration stuff */
|
||||
static void check_config(void)
|
||||
{
|
||||
int locking_type;
|
||||
|
||||
locking_type = find_config_tree_int(cmd, "global/locking_type", 1);
|
||||
|
||||
if (locking_type == 3) /* compiled-in cluster support */
|
||||
return;
|
||||
|
||||
if (locking_type == 2) { /* External library, check name */
|
||||
const char *libname;
|
||||
|
||||
libname = find_config_tree_str(cmd, "global/locking_library",
|
||||
"");
|
||||
if (strstr(libname, "liblvm2clusterlock.so"))
|
||||
return;
|
||||
|
||||
log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
|
||||
return;
|
||||
}
|
||||
log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
|
||||
}
|
||||
|
||||
/* Backups up the LVM metadata if it's changed */
|
||||
void lvm_do_backup(const char *vgname)
|
||||
{
|
||||
struct volume_group * vg;
|
||||
int consistent = 0;
|
||||
|
||||
DEBUGLOG("Triggering backup of VG metadata for %s.\n", vgname);
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
|
||||
vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, 1, &consistent);
|
||||
|
||||
if (vg && consistent)
|
||||
check_current_backup(vg);
|
||||
else
|
||||
log_error("Error backing up metadata, can't find VG for group %s", vgname);
|
||||
|
||||
free_vg(vg);
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
*name = NULL;
|
||||
if (!v)
|
||||
v = dm_hash_get_first(lv_hash);
|
||||
|
||||
do {
|
||||
if (v) {
|
||||
lvi = dm_hash_get_data(lv_hash, v);
|
||||
DEBUGLOG("Looking for EX locks. found %x mode %d\n", lvi->lock_id, lvi->lock_mode);
|
||||
|
||||
if (lvi->lock_mode == LCK_EXCL) {
|
||||
*name = dm_hash_get_key(lv_hash, v);
|
||||
}
|
||||
v = dm_hash_get_next(lv_hash, v);
|
||||
}
|
||||
} while (v && !*name);
|
||||
|
||||
if (*name)
|
||||
DEBUGLOG("returning EXclusive UUID %s\n", *name);
|
||||
return v;
|
||||
}
|
||||
|
||||
void lvm_do_fs_unlock(void)
|
||||
{
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
DEBUGLOG("Syncing device names\n");
|
||||
fs_unlock();
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
/* Called to initialise the LVM context of the daemon */
|
||||
int init_clvm(int using_gulm, char **argv)
|
||||
{
|
||||
if (!(cmd = create_toolcontext(1, NULL))) {
|
||||
log_error("Failed to allocate command context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stored_errno()) {
|
||||
destroy_toolcontext(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
|
||||
init_syslog(LOG_DAEMON);
|
||||
openlog("clvmd", LOG_PID, LOG_DAEMON);
|
||||
cmd->cmd_line = "clvmd";
|
||||
|
||||
/* Check lvm.conf is setup for cluster-LVM */
|
||||
check_config();
|
||||
init_ignore_suspended_devices(1);
|
||||
|
||||
/* Remove any non-LV locks that may have been left around */
|
||||
if (using_gulm)
|
||||
drop_vg_locks();
|
||||
|
||||
get_initial_state(argv);
|
||||
|
||||
/* Trap log messages so we can pass them back to the user */
|
||||
init_log_fn(lvm2_log_fn);
|
||||
memlock_inc_daemon(cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void destroy_lvm(void)
|
||||
{
|
||||
if (cmd) {
|
||||
memlock_dec_daemon(cmd);
|
||||
destroy_toolcontext(cmd);
|
||||
}
|
||||
cmd = NULL;
|
||||
}
|
||||
41
daemons/clvmd/lvm-functions.h
Normal file
41
daemons/clvmd/lvm-functions.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Functions in lvm-functions.c */
|
||||
|
||||
#ifndef _LVM_FUNCTIONS_H
|
||||
#define _LVM_FUNCTIONS_H
|
||||
|
||||
extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern const char *do_lock_query(char *resource);
|
||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_check_lvm1(const char *vgname);
|
||||
extern int do_refresh_cache(void);
|
||||
extern int init_clvm(int using_gulm, char **argv);
|
||||
extern void destroy_lvm(void);
|
||||
extern void init_lvhash(void);
|
||||
extern void destroy_lvhash(void);
|
||||
extern void lvm_do_backup(const char *vgname);
|
||||
extern char *get_last_lvm_error(void);
|
||||
extern void do_lock_vg(unsigned char command, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name);
|
||||
void lvm_do_fs_unlock(void);
|
||||
|
||||
#endif
|
||||
380
daemons/clvmd/refresh_clvmd.c
Normal file
380
daemons/clvmd/refresh_clvmd.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send a command to a running clvmd from the command-line
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include "clvm.h"
|
||||
#include "refresh_clvmd.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
typedef struct lvm_response {
|
||||
char node[255];
|
||||
char *response;
|
||||
int status;
|
||||
int len;
|
||||
} lvm_response_t;
|
||||
|
||||
/*
|
||||
* This gets stuck at the start of memory we allocate so we
|
||||
* can sanity-check it at deallocation time
|
||||
*/
|
||||
#define LVM_SIGNATURE 0x434C564D
|
||||
|
||||
static int _clvmd_sock = -1;
|
||||
|
||||
/* Open connection to the clvm daemon */
|
||||
static int _open_local_sock(void)
|
||||
{
|
||||
int local_socket;
|
||||
struct sockaddr_un sockaddr;
|
||||
|
||||
/* Open local socket */
|
||||
if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||
fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
|
||||
|
||||
sockaddr.sun_family = AF_UNIX;
|
||||
|
||||
if (connect(local_socket,(struct sockaddr *) &sockaddr,
|
||||
sizeof(sockaddr))) {
|
||||
int saved_errno = errno;
|
||||
|
||||
fprintf(stderr, "connect() failed on local socket: %s\n",
|
||||
strerror(errno));
|
||||
if (close(local_socket))
|
||||
return -1;
|
||||
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return local_socket;
|
||||
}
|
||||
|
||||
/* Send a request and return the status */
|
||||
static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response)
|
||||
{
|
||||
char outbuf[PIPE_BUF];
|
||||
struct clvm_header *outheader = (struct clvm_header *) outbuf;
|
||||
int len;
|
||||
int off;
|
||||
int buflen;
|
||||
int err;
|
||||
|
||||
/* Send it to CLVMD */
|
||||
rewrite:
|
||||
if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
|
||||
if (err == -1 && errno == EINTR)
|
||||
goto rewrite;
|
||||
fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (no_response)
|
||||
return 1;
|
||||
|
||||
/* Get the response */
|
||||
reread:
|
||||
if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
|
||||
if (errno == EINTR)
|
||||
goto reread;
|
||||
fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
fprintf(stderr, "EOF reading CLVMD");
|
||||
errno = ENOTCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
buflen = len + outheader->arglen;
|
||||
*retbuf = dm_malloc(buflen);
|
||||
if (!*retbuf) {
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the header */
|
||||
memcpy(*retbuf, outbuf, len);
|
||||
outheader = (struct clvm_header *) *retbuf;
|
||||
|
||||
/* Read the returned values */
|
||||
off = 1; /* we've already read the first byte */
|
||||
while (off <= outheader->arglen && len > 0) {
|
||||
len = read(_clvmd_sock, outheader->args + off,
|
||||
buflen - off - offsetof(struct clvm_header, args));
|
||||
if (len > 0)
|
||||
off += len;
|
||||
}
|
||||
|
||||
/* Was it an error ? */
|
||||
if (outheader->status != 0) {
|
||||
errno = outheader->status;
|
||||
|
||||
/* Only return an error here if there are no node-specific
|
||||
errors present in the message that might have more detail */
|
||||
if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
|
||||
fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Build the structure header and parse-out wildcard node names */
|
||||
static void _build_header(struct clvm_header *head, int cmd, const char *node,
|
||||
int len)
|
||||
{
|
||||
head->cmd = cmd;
|
||||
head->status = 0;
|
||||
head->flags = 0;
|
||||
head->clientid = 0;
|
||||
head->arglen = len;
|
||||
|
||||
if (node) {
|
||||
/*
|
||||
* Allow a couple of special node names:
|
||||
* "*" for all nodes,
|
||||
* "." for the local node only
|
||||
*/
|
||||
if (strcmp(node, "*") == 0) {
|
||||
head->node[0] = '\0';
|
||||
} else if (strcmp(node, ".") == 0) {
|
||||
head->node[0] = '\0';
|
||||
head->flags = CLVMD_FLAG_LOCAL;
|
||||
} else
|
||||
strcpy(head->node, node);
|
||||
} else
|
||||
head->node[0] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a message to a(or all) node(s) in the cluster and wait for replies
|
||||
*/
|
||||
static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num, int no_response)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
char *inptr;
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
int i;
|
||||
int num_responses = 0;
|
||||
struct clvm_header *head = (struct clvm_header *) outbuf;
|
||||
lvm_response_t *rarray;
|
||||
|
||||
*num = 0;
|
||||
|
||||
if (_clvmd_sock == -1)
|
||||
_clvmd_sock = _open_local_sock();
|
||||
|
||||
if (_clvmd_sock == -1)
|
||||
return 0;
|
||||
|
||||
_build_header(head, cmd, node, len);
|
||||
memcpy(head->node + strlen(head->node) + 1, data, len);
|
||||
|
||||
status = _send_request(outbuf, sizeof(struct clvm_header) +
|
||||
strlen(head->node) + len, &retbuf, no_response);
|
||||
if (!status || no_response)
|
||||
goto out;
|
||||
|
||||
/* Count the number of responses we got */
|
||||
head = (struct clvm_header *) retbuf;
|
||||
inptr = head->args;
|
||||
while (inptr[0]) {
|
||||
num_responses++;
|
||||
inptr += strlen(inptr) + 1;
|
||||
inptr += sizeof(int);
|
||||
inptr += strlen(inptr) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate response array.
|
||||
* With an extra pair of INTs on the front to sanity
|
||||
* check the pointer when we are given it back to free
|
||||
*/
|
||||
*response = dm_malloc(sizeof(lvm_response_t) * num_responses +
|
||||
sizeof(int) * 2);
|
||||
if (!*response) {
|
||||
errno = ENOMEM;
|
||||
status = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rarray = *response;
|
||||
|
||||
/* Unpack the response into an lvm_response_t array */
|
||||
inptr = head->args;
|
||||
i = 0;
|
||||
while (inptr[0]) {
|
||||
strcpy(rarray[i].node, inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
|
||||
memcpy(&rarray[i].status, inptr, sizeof(int));
|
||||
inptr += sizeof(int);
|
||||
|
||||
rarray[i].response = dm_malloc(strlen(inptr) + 1);
|
||||
if (rarray[i].response == NULL) {
|
||||
/* Free up everything else and return error */
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
dm_free(rarray[i].response);
|
||||
free(*response);
|
||||
errno = ENOMEM;
|
||||
status = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
strcpy(rarray[i].response, inptr);
|
||||
rarray[i].len = strlen(inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
i++;
|
||||
}
|
||||
*num = num_responses;
|
||||
*response = rarray;
|
||||
|
||||
out:
|
||||
if (retbuf)
|
||||
dm_free(retbuf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Free reply array */
|
||||
static int _cluster_free_request(lvm_response_t * response, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
dm_free(response[i].response);
|
||||
}
|
||||
|
||||
dm_free(response);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int refresh_clvmd(int all_nodes)
|
||||
{
|
||||
int num_responses;
|
||||
char args[1]; // No args really.
|
||||
lvm_response_t *response = NULL;
|
||||
int saved_errno;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes?"*":".", args, 0, &response, &num_responses, 0);
|
||||
|
||||
/* If any nodes were down then display them and return an error */
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status == EHOSTDOWN) {
|
||||
fprintf(stderr, "clvmd not running on node %s",
|
||||
response[i].node);
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
} else if (response[i].status) {
|
||||
fprintf(stderr, "Error resetting node %s: %s",
|
||||
response[i].node,
|
||||
response[i].response[0] ?
|
||||
response[i].response :
|
||||
strerror(response[i].status));
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
}
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
_cluster_free_request(response, num_responses);
|
||||
errno = saved_errno;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int restart_clvmd(int all_nodes)
|
||||
{
|
||||
int dummy, status;
|
||||
|
||||
status = _cluster_request(CLVMD_CMD_RESTART, all_nodes?"*":".", 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 = "*";
|
||||
else
|
||||
nodes = ".";
|
||||
|
||||
status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0);
|
||||
|
||||
/* If any nodes were down then display them and return an error */
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status == EHOSTDOWN) {
|
||||
fprintf(stderr, "clvmd not running on node %s",
|
||||
response[i].node);
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
} else if (response[i].status) {
|
||||
fprintf(stderr, "Error setting debug on node %s: %s",
|
||||
response[i].node,
|
||||
response[i].response[0] ?
|
||||
response[i].response :
|
||||
strerror(response[i].status));
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
}
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
_cluster_free_request(response, num_responses);
|
||||
errno = saved_errno;
|
||||
|
||||
return status;
|
||||
}
|
||||
19
daemons/clvmd/refresh_clvmd.h
Normal file
19
daemons/clvmd/refresh_clvmd.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
int refresh_clvmd(int all_nodes);
|
||||
int restart_clvmd(int all_nodes);
|
||||
int debug_clvmd(int level, int clusterwide);
|
||||
|
||||
502
daemons/clvmd/tcp-comms.c
Normal file
502
daemons/clvmd/tcp-comms.c
Normal file
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2003 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This provides the 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 "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <netdb.h>
|
||||
#include <assert.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);
|
||||
38
daemons/cmirrord/Makefile.in
Normal file
38
daemons/cmirrord/Makefile.in
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
CPG_LIBS = @CPG_LIBS@
|
||||
CPG_CFLAGS = @CPG_CFLAGS@
|
||||
SACKPT_LIBS = @SACKPT_LIBS@
|
||||
SACKPT_CFLAGS = @SACKPT_CFLAGS@
|
||||
|
||||
SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
|
||||
|
||||
TARGETS = cmirrord
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper
|
||||
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
|
||||
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS)
|
||||
|
||||
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
install: $(TARGETS)
|
||||
$(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
|
||||
234
daemons/cmirrord/clogd.c
Normal file
234
daemons/cmirrord/clogd.c
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
unlink(CMIRRORD_PIDFILE);
|
||||
}
|
||||
|
||||
/*
|
||||
* daemonize
|
||||
*
|
||||
* Performs the steps necessary to become a daemon.
|
||||
*/
|
||||
static void daemonize(void)
|
||||
{
|
||||
int pid;
|
||||
int status;
|
||||
|
||||
signal(SIGTERM, &parent_exit_handler);
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
LOG_ERROR("Unable to fork()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid) {
|
||||
/* Parent waits here for child to get going */
|
||||
while (!waitpid(pid, &status, WNOHANG) && !exit_now);
|
||||
if (exit_now)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
switch (WEXITSTATUS(status)) {
|
||||
case EXIT_LOCKFILE:
|
||||
LOG_ERROR("Failed to create lockfile");
|
||||
LOG_ERROR("Process already running?");
|
||||
break;
|
||||
case EXIT_KERNEL_SOCKET:
|
||||
LOG_ERROR("Unable to create netlink socket");
|
||||
break;
|
||||
case EXIT_KERNEL_BIND:
|
||||
LOG_ERROR("Unable to bind to netlink socket");
|
||||
break;
|
||||
case EXIT_KERNEL_SETSOCKOPT:
|
||||
LOG_ERROR("Unable to setsockopt on netlink socket");
|
||||
break;
|
||||
case EXIT_CLUSTER_CKPT_INIT:
|
||||
LOG_ERROR("Unable to initialize checkpoint service");
|
||||
LOG_ERROR("Has the cluster infrastructure been started?");
|
||||
break;
|
||||
case EXIT_FAILURE:
|
||||
LOG_ERROR("Failed to start: Generic error");
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Failed to start: Unknown error");
|
||||
break;
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
setsid();
|
||||
chdir("/");
|
||||
umask(0);
|
||||
|
||||
close(0); close(1); close(2);
|
||||
open("/dev/null", O_RDONLY); /* reopen stdin */
|
||||
open("/dev/null", O_WRONLY); /* reopen stdout */
|
||||
open("/dev/null", O_WRONLY); /* reopen stderr */
|
||||
|
||||
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();
|
||||
}
|
||||
1661
daemons/cmirrord/cluster.c
Normal file
1661
daemons/cmirrord/cluster.c
Normal file
File diff suppressed because it is too large
Load Diff
76
daemons/cmirrord/cluster.h
Normal file
76
daemons/cmirrord/cluster.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_CLUSTER_H
|
||||
#define _LVM_CLOG_CLUSTER_H
|
||||
|
||||
#include "dm-log-userspace.h"
|
||||
#include "libdevmapper.h"
|
||||
|
||||
#define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */
|
||||
#define DM_ULOG_CHECKPOINT_READY 21
|
||||
#define DM_ULOG_MEMBER_JOIN 22
|
||||
|
||||
/*
|
||||
* There is other information in addition to what can
|
||||
* be found in the dm_ulog_request structure that we
|
||||
* need for processing. 'clog_request' is the wrapping
|
||||
* structure we use to make the additional fields
|
||||
* available.
|
||||
*/
|
||||
struct clog_request {
|
||||
/*
|
||||
* If we don't use a union, the structure size will
|
||||
* vary between 32-bit and 64-bit machines. So, we
|
||||
* pack two 64-bit version numbers in there to force
|
||||
* the size of the structure to be the same.
|
||||
*
|
||||
* The two version numbers also help us with endian
|
||||
* issues. The first is always little endian, while
|
||||
* the second is in native format of the sending
|
||||
* machine. If the two are equal, there is no need
|
||||
* to do endian conversions.
|
||||
*/
|
||||
union {
|
||||
uint64_t version[2]; /* LE version and native version */
|
||||
struct dm_list list;
|
||||
} u;
|
||||
|
||||
/*
|
||||
* 'originator' is the machine from which the requests
|
||||
* was made.
|
||||
*/
|
||||
uint32_t originator;
|
||||
|
||||
/*
|
||||
* 'pit_server' is the "point-in-time" server for the
|
||||
* request. (I.e. The machine that was the server at
|
||||
* the time the request was issued - only important during
|
||||
* startup.
|
||||
*/
|
||||
uint32_t pit_server;
|
||||
|
||||
/*
|
||||
* The request from the kernel that is being processed
|
||||
*/
|
||||
struct dm_ulog_request u_rq;
|
||||
};
|
||||
|
||||
int init_cluster(void);
|
||||
void cleanup_cluster(void);
|
||||
void cluster_debug(void);
|
||||
|
||||
int create_cluster_cpg(char *uuid, uint64_t luid);
|
||||
int destroy_cluster_cpg(char *uuid);
|
||||
|
||||
int cluster_send(struct clog_request *rq);
|
||||
|
||||
#endif /* _LVM_CLOG_CLUSTER_H */
|
||||
33
daemons/cmirrord/common.h
Normal file
33
daemons/cmirrord/common.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_COMMON_H
|
||||
#define _LVM_CLOG_COMMON_H
|
||||
|
||||
/*
|
||||
* If there are problems when forking off to become a daemon,
|
||||
* the child will exist with one of these codes. This allows
|
||||
* the parent to know the reason for the failure and print it
|
||||
* to the launching terminal.
|
||||
*
|
||||
* #define EXIT_SUCCESS 0 (from stdlib.h)
|
||||
* #define EXIT_FAILURE 1 (from stdlib.h)
|
||||
*/
|
||||
#define EXIT_LOCKFILE 2
|
||||
#define EXIT_KERNEL_SOCKET 3 /* Failed netlink socket create */
|
||||
#define EXIT_KERNEL_BIND 4
|
||||
#define EXIT_KERNEL_SETSOCKOPT 5
|
||||
#define EXIT_CLUSTER_CKPT_INIT 6 /* Failed to init checkpoint */
|
||||
#define EXIT_QUEUE_NOMEM 7
|
||||
|
||||
#define DM_ULOG_REQUEST_SIZE 1024
|
||||
|
||||
#endif /* _LVM_CLOG_COMMON_H */
|
||||
210
daemons/cmirrord/compat.c
Normal file
210
daemons/cmirrord/compat.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "cluster.h"
|
||||
#include "compat.h"
|
||||
#include "xlate.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Older versions of the log daemon communicate with different
|
||||
* versions of the inter-machine communication structure, which
|
||||
* varies in size and fields. The older versions append the
|
||||
* standard upstream version of the structure to every request.
|
||||
* COMPAT_OFFSET is where the upstream structure starts.
|
||||
*/
|
||||
#define COMPAT_OFFSET 256
|
||||
|
||||
static void v5_data_endian_switch(struct clog_request *rq, int to_network __attribute__((unused)))
|
||||
{
|
||||
int i, end;
|
||||
int64_t *pi64;
|
||||
uint64_t *pu64;
|
||||
uint32_t rq_type = rq->u_rq.request_type & ~DM_ULOG_RESPONSE;
|
||||
|
||||
if (rq->u_rq.request_type & DM_ULOG_RESPONSE) {
|
||||
switch (rq_type) {
|
||||
case DM_ULOG_CTR:
|
||||
case DM_ULOG_DTR:
|
||||
LOG_ERROR("Invalid response type in endian switch");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
case DM_ULOG_PRESUSPEND:
|
||||
case DM_ULOG_POSTSUSPEND:
|
||||
case DM_ULOG_RESUME:
|
||||
case DM_ULOG_FLUSH:
|
||||
case DM_ULOG_MARK_REGION:
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
case DM_ULOG_SET_REGION_SYNC:
|
||||
case DM_ULOG_CHECKPOINT_READY:
|
||||
case DM_ULOG_MEMBER_JOIN:
|
||||
case DM_ULOG_STATUS_INFO:
|
||||
case DM_ULOG_STATUS_TABLE:
|
||||
/* No outbound data */
|
||||
break;
|
||||
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
pi64 = (int64_t *)rq->u_rq.data;
|
||||
*pi64 = xlate64(*pi64);
|
||||
break;
|
||||
case DM_ULOG_GET_RESYNC_WORK:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
pi64 = (int64_t *)rq->u_rq.data;
|
||||
pu64 = ((uint64_t *)rq->u_rq.data) + 1;
|
||||
*pi64 = xlate64(*pi64);
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown request type, %u", rq_type);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
switch (rq_type) {
|
||||
case DM_ULOG_CTR:
|
||||
case DM_ULOG_DTR:
|
||||
LOG_ERROR("Invalid request type in endian switch");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
case DM_ULOG_PRESUSPEND:
|
||||
case DM_ULOG_POSTSUSPEND:
|
||||
case DM_ULOG_RESUME:
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_FLUSH:
|
||||
case DM_ULOG_GET_RESYNC_WORK:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
case DM_ULOG_STATUS_INFO:
|
||||
case DM_ULOG_STATUS_TABLE:
|
||||
case DM_ULOG_CHECKPOINT_READY:
|
||||
case DM_ULOG_MEMBER_JOIN:
|
||||
/* No incoming data */
|
||||
break;
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
case DM_ULOG_MARK_REGION:
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
end = rq->u_rq.data_size/sizeof(uint64_t);
|
||||
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
for (i = 0; i < end; i++)
|
||||
pu64[i] = xlate64(pu64[i]);
|
||||
break;
|
||||
case DM_ULOG_SET_REGION_SYNC:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
pi64 = ((int64_t *)rq->u_rq.data) + 1;
|
||||
*pu64 = xlate64(*pu64);
|
||||
*pi64 = xlate64(*pi64);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown request type, %u", rq_type);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int v5_endian_to_network(struct clog_request *rq)
|
||||
{
|
||||
int size;
|
||||
struct dm_ulog_request *u_rq = &rq->u_rq;
|
||||
|
||||
size = sizeof(*rq) + u_rq->data_size;
|
||||
|
||||
u_rq->error = xlate32(u_rq->error);
|
||||
u_rq->seq = xlate32(u_rq->seq);
|
||||
u_rq->request_type = xlate32(u_rq->request_type);
|
||||
u_rq->data_size = xlate64(u_rq->data_size);
|
||||
|
||||
rq->originator = xlate32(rq->originator);
|
||||
|
||||
v5_data_endian_switch(rq, 1);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int clog_request_to_network(struct clog_request *rq)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* FIXME: Remove this safety check */
|
||||
if (rq->u.version[0] != xlate64(rq->u.version[1])) {
|
||||
LOG_ERROR("Programmer error: version[0] must be LE");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Are we already running in the endian mode we send
|
||||
* over the wire?
|
||||
*/
|
||||
if (rq->u.version[0] == rq->u.version[1])
|
||||
return 0;
|
||||
|
||||
r = v5_endian_to_network(rq);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int v5_endian_from_network(struct clog_request *rq)
|
||||
{
|
||||
int size;
|
||||
struct dm_ulog_request *u_rq = &rq->u_rq;
|
||||
|
||||
u_rq->error = xlate32(u_rq->error);
|
||||
u_rq->seq = xlate32(u_rq->seq);
|
||||
u_rq->request_type = xlate32(u_rq->request_type);
|
||||
u_rq->data_size = xlate64(u_rq->data_size);
|
||||
|
||||
rq->originator = xlate32(rq->originator);
|
||||
|
||||
size = sizeof(*rq) + u_rq->data_size;
|
||||
|
||||
v5_data_endian_switch(rq, 0);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int clog_request_from_network(void *data, size_t data_len)
|
||||
{
|
||||
uint64_t *vp = data;
|
||||
uint64_t version = xlate64(vp[0]);
|
||||
uint64_t unconverted_version = vp[1];
|
||||
struct clog_request *rq = data;
|
||||
|
||||
switch (version) {
|
||||
case 5: /* Upstream */
|
||||
if (version == unconverted_version)
|
||||
return 0;
|
||||
break;
|
||||
case 4: /* RHEL 5.[45] */
|
||||
case 3: /* RHEL 5.3 */
|
||||
case 2: /* RHEL 5.2 */
|
||||
/* FIXME: still need to account for payload */
|
||||
if (data_len < (COMPAT_OFFSET + sizeof(*rq)))
|
||||
return -ENOSPC;
|
||||
|
||||
rq = (struct clog_request *)((char *)data + COMPAT_OFFSET);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unable to process cluster message: "
|
||||
"Incompatible version");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
v5_endian_from_network(rq);
|
||||
return 0;
|
||||
}
|
||||
25
daemons/cmirrord/compat.h
Normal file
25
daemons/cmirrord/compat.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*/
|
||||
#ifndef _LVM_CLOG_COMPAT_H
|
||||
#define _LVM_CLOG_COMPAT_H
|
||||
|
||||
/*
|
||||
* The intermachine communication structure version are:
|
||||
* 0: Unused
|
||||
* 1: Never in the wild
|
||||
* 2: RHEL 5.2
|
||||
* 3: RHEL 5.3
|
||||
* 4: RHEL 5.4, RHEL 5.5
|
||||
* 5: RHEL 6, Current Upstream Format
|
||||
*/
|
||||
#define CLOG_TFR_VERSION 5
|
||||
|
||||
int clog_request_to_network(struct clog_request *rq);
|
||||
int clog_request_from_network(void *data, size_t data_len);
|
||||
|
||||
#endif /* _LVM_CLOG_COMPAT_H */
|
||||
1937
daemons/cmirrord/functions.c
Normal file
1937
daemons/cmirrord/functions.c
Normal file
File diff suppressed because it is too large
Load Diff
34
daemons/cmirrord/functions.h
Normal file
34
daemons/cmirrord/functions.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_FUNCTIONS_H
|
||||
#define _LVM_CLOG_FUNCTIONS_H
|
||||
|
||||
#include "dm-log-userspace.h"
|
||||
#include "cluster.h"
|
||||
|
||||
#define LOG_RESUMED 1
|
||||
#define LOG_SUSPENDED 2
|
||||
|
||||
int local_resume(struct dm_ulog_request *rq);
|
||||
int cluster_postsuspend(char *, uint64_t);
|
||||
|
||||
int do_request(struct clog_request *rq, int server);
|
||||
int push_state(const char *uuid, uint64_t luid,
|
||||
const char *which, char **buf, uint32_t debug_who);
|
||||
int pull_state(const char *uuid, uint64_t luid,
|
||||
const char *which, char *buf, int size);
|
||||
|
||||
int log_get_state(struct dm_ulog_request *rq);
|
||||
int log_status(void);
|
||||
void log_debug(void);
|
||||
|
||||
#endif /* _LVM_CLOG_FUNCTIONS_H */
|
||||
151
daemons/cmirrord/link_mon.c
Normal file
151
daemons/cmirrord/link_mon.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "link_mon.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct link_callback {
|
||||
int fd;
|
||||
const char *name;
|
||||
void *data;
|
||||
int (*callback)(void *data);
|
||||
|
||||
struct link_callback *next;
|
||||
};
|
||||
|
||||
static unsigned used_pfds = 0;
|
||||
static unsigned free_pfds = 0;
|
||||
static struct pollfd *pfds = NULL;
|
||||
static struct link_callback *callbacks = NULL;
|
||||
|
||||
int links_register(int fd, const char *name, int (*callback)(void *data), void *data)
|
||||
{
|
||||
unsigned i;
|
||||
struct link_callback *lc;
|
||||
|
||||
for (i = 0; i < used_pfds; i++) {
|
||||
if (fd == pfds[i].fd) {
|
||||
LOG_ERROR("links_register: Duplicate file descriptor");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
lc = malloc(sizeof(*lc));
|
||||
if (!lc)
|
||||
return -ENOMEM;
|
||||
|
||||
lc->fd = fd;
|
||||
lc->name = name;
|
||||
lc->data = data;
|
||||
lc->callback = callback;
|
||||
|
||||
if (!free_pfds) {
|
||||
struct pollfd *tmp;
|
||||
tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1));
|
||||
if (!tmp) {
|
||||
free(lc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pfds = tmp;
|
||||
free_pfds = used_pfds + 1;
|
||||
}
|
||||
|
||||
free_pfds--;
|
||||
pfds[used_pfds].fd = fd;
|
||||
pfds[used_pfds].events = POLLIN;
|
||||
pfds[used_pfds].revents = 0;
|
||||
used_pfds++;
|
||||
|
||||
lc->next = callbacks;
|
||||
callbacks = lc;
|
||||
LOG_DBG("Adding %s/%d", lc->name, lc->fd);
|
||||
LOG_DBG(" used_pfds = %u, free_pfds = %u",
|
||||
used_pfds, free_pfds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int links_unregister(int fd)
|
||||
{
|
||||
unsigned i;
|
||||
struct link_callback *p, *c;
|
||||
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (fd == pfds[i].fd) {
|
||||
/* entire struct is copied (overwritten) */
|
||||
pfds[i] = pfds[used_pfds - 1];
|
||||
used_pfds--;
|
||||
free_pfds++;
|
||||
}
|
||||
|
||||
for (p = NULL, c = callbacks; c; p = c, c = c->next)
|
||||
if (fd == c->fd) {
|
||||
LOG_DBG("Freeing up %s/%d", c->name, c->fd);
|
||||
LOG_DBG(" used_pfds = %u, free_pfds = %u",
|
||||
used_pfds, free_pfds);
|
||||
if (p)
|
||||
p->next = c->next;
|
||||
else
|
||||
callbacks = c->next;
|
||||
free(c);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int links_monitor(void)
|
||||
{
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
for (i = 0; i < used_pfds; i++) {
|
||||
pfds[i].revents = 0;
|
||||
}
|
||||
|
||||
r = poll(pfds, used_pfds, -1);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = 0;
|
||||
/* FIXME: handle POLLHUP */
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (pfds[i].revents & POLLIN) {
|
||||
LOG_DBG("Data ready on %d", pfds[i].fd);
|
||||
|
||||
/* FIXME: Add this back return 1;*/
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int links_issue_callbacks(void)
|
||||
{
|
||||
unsigned i;
|
||||
struct link_callback *lc;
|
||||
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (pfds[i].revents & POLLIN)
|
||||
for (lc = callbacks; lc; lc = lc->next)
|
||||
if (pfds[i].fd == lc->fd) {
|
||||
LOG_DBG("Issuing callback on %s/%d",
|
||||
lc->name, lc->fd);
|
||||
lc->callback(lc->data);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
20
daemons/cmirrord/link_mon.h
Normal file
20
daemons/cmirrord/link_mon.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_LINK_MON_H
|
||||
#define _LVM_CLOG_LINK_MON_H
|
||||
|
||||
int links_register(int fd, const char *name, int (*callback)(void *data), void *data);
|
||||
int links_unregister(int fd);
|
||||
int links_monitor(void);
|
||||
int links_issue_callbacks(void);
|
||||
|
||||
#endif /* _LVM_CLOG_LINK_MON_H */
|
||||
416
daemons/cmirrord/local.c
Normal file
416
daemons/cmirrord/local.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "common.h"
|
||||
#include "functions.h"
|
||||
#include "link_mon.h"
|
||||
#include "local.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/connector.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef CN_IDX_DM
|
||||
/* Kernel 2.6.31 is required to run this code */
|
||||
#define CN_IDX_DM 0x7 /* Device Mapper */
|
||||
#define CN_VAL_DM_USERSPACE_LOG 0x1
|
||||
#endif
|
||||
|
||||
static int cn_fd; /* Connector (netlink) socket fd */
|
||||
static char recv_buf[2048];
|
||||
static char send_buf[2048];
|
||||
|
||||
|
||||
/* FIXME: merge this function with kernel_send_helper */
|
||||
static int kernel_ack(uint32_t seq, int error)
|
||||
{
|
||||
int r;
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)send_buf;
|
||||
struct cn_msg *msg = NLMSG_DATA(nlh);
|
||||
|
||||
if (error < 0) {
|
||||
LOG_ERROR("Programmer error: error codes must be positive");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
nlh->nlmsg_seq = 0;
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
msg->len = 0;
|
||||
msg->id.idx = CN_IDX_DM;
|
||||
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
|
||||
msg->seq = seq;
|
||||
msg->ack = error;
|
||||
|
||||
r = send(cn_fd, nlh, NLMSG_LENGTH(sizeof(struct cn_msg)), 0);
|
||||
/* FIXME: do better error processing */
|
||||
if (r <= 0)
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* kernel_recv
|
||||
* @rq: the newly allocated request from kernel
|
||||
*
|
||||
* Read requests from the kernel and allocate space for the new request.
|
||||
* If there is no request from the kernel, *rq is NULL.
|
||||
*
|
||||
* This function is not thread safe due to returned stack pointer. In fact,
|
||||
* the returned pointer must not be in-use when this function is called again.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on error
|
||||
*/
|
||||
static int kernel_recv(struct clog_request **rq)
|
||||
{
|
||||
int r = 0;
|
||||
ssize_t len;
|
||||
char *foo;
|
||||
struct cn_msg *msg;
|
||||
struct dm_ulog_request *u_rq;
|
||||
struct nlmsghdr *nlmsg_h;
|
||||
|
||||
*rq = NULL;
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
|
||||
len = recv(cn_fd, recv_buf, sizeof(recv_buf), 0);
|
||||
if (len < 0) {
|
||||
LOG_ERROR("Failed to recv message from kernel");
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nlmsg_h = (struct nlmsghdr *)recv_buf;
|
||||
switch (nlmsg_h->nlmsg_type) {
|
||||
case NLMSG_ERROR:
|
||||
LOG_ERROR("Unable to recv message from kernel: NLMSG_ERROR");
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
case NLMSG_DONE:
|
||||
msg = (struct cn_msg *)NLMSG_DATA((struct nlmsghdr *)recv_buf);
|
||||
len -= (ssize_t)sizeof(struct nlmsghdr);
|
||||
|
||||
if (len < (ssize_t)sizeof(struct cn_msg)) {
|
||||
LOG_ERROR("Incomplete request from kernel received");
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (msg->len > DM_ULOG_REQUEST_SIZE) {
|
||||
LOG_ERROR("Not enough space to receive kernel request (%d/%d)",
|
||||
msg->len, DM_ULOG_REQUEST_SIZE);
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!msg->len)
|
||||
LOG_ERROR("Zero length message received");
|
||||
|
||||
len -= (ssize_t)sizeof(struct cn_msg);
|
||||
|
||||
if (len < msg->len)
|
||||
LOG_ERROR("len = %zd, msg->len = %" PRIu16, len, msg->len);
|
||||
|
||||
msg->data[msg->len] = '\0'; /* Cleaner way to ensure this? */
|
||||
u_rq = (struct dm_ulog_request *)msg->data;
|
||||
|
||||
if (!u_rq->request_type) {
|
||||
LOG_DBG("Bad transmission, requesting resend [%u]",
|
||||
msg->seq);
|
||||
r = -EAGAIN;
|
||||
|
||||
if (kernel_ack(msg->seq, EAGAIN)) {
|
||||
LOG_ERROR("Failed to NACK kernel transmission [%u]",
|
||||
msg->seq);
|
||||
r = -EBADE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we've got sizeof(struct cn_msg) + sizeof(struct nlmsghdr)
|
||||
* worth of space that precede the request structure from the
|
||||
* kernel. Since that space isn't going to be used again, we
|
||||
* can take it for our purposes; rather than allocating a whole
|
||||
* new structure and doing a memcpy.
|
||||
*
|
||||
* We should really make sure 'clog_request' doesn't grow
|
||||
* beyond what is available to us, but we need only check it
|
||||
* once... perhaps at compile time?
|
||||
*/
|
||||
foo = (char *)u_rq;
|
||||
foo -= (sizeof(struct clog_request) - sizeof(struct dm_ulog_request));
|
||||
*rq = (struct clog_request *) foo;
|
||||
|
||||
/* Clear the wrapper container fields */
|
||||
memset(*rq, 0, (size_t)((char *)u_rq - (char *)(*rq)));
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown nlmsg_type");
|
||||
r = -EBADE;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (r)
|
||||
*rq = NULL;
|
||||
|
||||
return (r == -EAGAIN) ? 0 : r;
|
||||
}
|
||||
|
||||
static int kernel_send_helper(void *data, uint16_t out_size)
|
||||
{
|
||||
int r;
|
||||
struct nlmsghdr *nlh;
|
||||
struct cn_msg *msg;
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
nlh = (struct nlmsghdr *)send_buf;
|
||||
nlh->nlmsg_seq = 0; /* FIXME: Is this used? */
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(out_size + sizeof(struct cn_msg));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
msg = NLMSG_DATA(nlh);
|
||||
memcpy(msg->data, data, out_size);
|
||||
msg->len = out_size;
|
||||
msg->id.idx = CN_IDX_DM;
|
||||
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
|
||||
msg->seq = 0;
|
||||
|
||||
r = send(cn_fd, nlh, NLMSG_LENGTH(out_size + sizeof(struct cn_msg)), 0);
|
||||
/* FIXME: do better error processing */
|
||||
if (r <= 0)
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_local_work
|
||||
*
|
||||
* Any processing errors are placed in the 'rq'
|
||||
* structure to be reported back to the kernel.
|
||||
* It may be pointless for this function to
|
||||
* return an int.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
static int do_local_work(void *data __attribute__((unused)))
|
||||
{
|
||||
int r;
|
||||
struct clog_request *rq;
|
||||
struct dm_ulog_request *u_rq = NULL;
|
||||
|
||||
r = kernel_recv(&rq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!rq)
|
||||
return 0;
|
||||
|
||||
u_rq = &rq->u_rq;
|
||||
LOG_DBG("[%s] Request from kernel received: [%s/%u]",
|
||||
SHORT_UUID(u_rq->uuid), RQ_TYPE(u_rq->request_type),
|
||||
u_rq->seq);
|
||||
switch (u_rq->request_type) {
|
||||
case DM_ULOG_CTR:
|
||||
case DM_ULOG_DTR:
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
case DM_ULOG_STATUS_INFO:
|
||||
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_IS_REMOTE_RECOVERING:
|
||||
case DM_ULOG_POSTSUSPEND:
|
||||
r = cluster_send(rq);
|
||||
if (r) {
|
||||
u_rq->data_size = 0;
|
||||
u_rq->error = r;
|
||||
kernel_send(u_rq);
|
||||
}
|
||||
|
||||
break;
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
r = kernel_ack(u_rq->seq, 0);
|
||||
|
||||
r = cluster_send(rq);
|
||||
if (r) {
|
||||
/*
|
||||
* FIXME: store error for delivery on flush
|
||||
* This would allow us to optimize MARK_REGION
|
||||
* too.
|
||||
*/
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Invalid log request received (%u), ignoring.",
|
||||
u_rq->request_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (r && !u_rq->error)
|
||||
u_rq->error = r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* kernel_send
|
||||
* @u_rq: result to pass back to kernel
|
||||
*
|
||||
* This function returns the u_rq structure
|
||||
* (containing the results) to the kernel.
|
||||
* It then frees the structure.
|
||||
*
|
||||
* WARNING: should the structure be freed if
|
||||
* there is an error? I vote 'yes'. If the
|
||||
* kernel doesn't get the response, it should
|
||||
* resend the request.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
int kernel_send(struct dm_ulog_request *u_rq)
|
||||
{
|
||||
int r;
|
||||
uint16_t size;
|
||||
|
||||
if (!u_rq)
|
||||
return -EINVAL;
|
||||
|
||||
size = (uint16_t)(sizeof(struct dm_ulog_request) + u_rq->data_size);
|
||||
|
||||
if (!u_rq->data_size && !u_rq->error) {
|
||||
/* An ACK is all that is needed */
|
||||
|
||||
/* FIXME: add ACK code */
|
||||
} else if (size > DM_ULOG_REQUEST_SIZE) {
|
||||
/*
|
||||
* If we gotten here, we've already overrun
|
||||
* our allotted space somewhere.
|
||||
*
|
||||
* We must do something, because the kernel
|
||||
* is waiting for a response.
|
||||
*/
|
||||
LOG_ERROR("Not enough space to respond to server");
|
||||
u_rq->error = -ENOSPC;
|
||||
size = sizeof(struct dm_ulog_request);
|
||||
}
|
||||
|
||||
r = kernel_send_helper(u_rq, size);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to send msg to kernel.");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_local
|
||||
*
|
||||
* Initialize kernel communication socket (netlink)
|
||||
*
|
||||
* Returns: 0 on success, values from common.h on failure
|
||||
*/
|
||||
int init_local(void)
|
||||
{
|
||||
int r = 0;
|
||||
unsigned opt;
|
||||
struct sockaddr_nl addr;
|
||||
|
||||
cn_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||
if (cn_fd < 0)
|
||||
return EXIT_KERNEL_SOCKET;
|
||||
|
||||
/* memset to fix valgrind complaint */
|
||||
memset(&addr, 0, sizeof(struct sockaddr_nl));
|
||||
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = CN_IDX_DM;
|
||||
addr.nl_pid = 0;
|
||||
|
||||
r = bind(cn_fd, (struct sockaddr *) &addr, sizeof(addr));
|
||||
if (r < 0) {
|
||||
close(cn_fd);
|
||||
return EXIT_KERNEL_BIND;
|
||||
}
|
||||
|
||||
opt = addr.nl_groups;
|
||||
r = setsockopt(cn_fd, 270, NETLINK_ADD_MEMBERSHIP, &opt, sizeof(opt));
|
||||
if (r) {
|
||||
close(cn_fd);
|
||||
return EXIT_KERNEL_SETSOCKOPT;
|
||||
}
|
||||
|
||||
/*
|
||||
r = fcntl(cn_fd, F_SETFL, FNDELAY);
|
||||
*/
|
||||
|
||||
links_register(cn_fd, "local", do_local_work, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup_local
|
||||
*
|
||||
* Clean up before exiting
|
||||
*/
|
||||
void cleanup_local(void)
|
||||
{
|
||||
links_unregister(cn_fd);
|
||||
close(cn_fd);
|
||||
}
|
||||
20
daemons/cmirrord/local.h
Normal file
20
daemons/cmirrord/local.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_LOCAL_H
|
||||
#define _LVM_CLOG_LOCAL_H
|
||||
|
||||
int init_local(void);
|
||||
void cleanup_local(void);
|
||||
|
||||
int kernel_send(struct dm_ulog_request *rq);
|
||||
|
||||
#endif /* _LVM_CLOG_LOCAL_H */
|
||||
57
daemons/cmirrord/logging.c
Normal file
57
daemons/cmirrord/logging.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
|
||||
const char *__rq_types_off_by_one[] = {
|
||||
"DM_ULOG_CTR",
|
||||
"DM_ULOG_DTR",
|
||||
"DM_ULOG_PRESUSPEND",
|
||||
"DM_ULOG_POSTSUSPEND",
|
||||
"DM_ULOG_RESUME",
|
||||
"DM_ULOG_GET_REGION_SIZE",
|
||||
"DM_ULOG_IS_CLEAN",
|
||||
"DM_ULOG_IN_SYNC",
|
||||
"DM_ULOG_FLUSH",
|
||||
"DM_ULOG_MARK_REGION",
|
||||
"DM_ULOG_CLEAR_REGION",
|
||||
"DM_ULOG_GET_RESYNC_WORK",
|
||||
"DM_ULOG_SET_REGION_SYNC",
|
||||
"DM_ULOG_GET_SYNC_COUNT",
|
||||
"DM_ULOG_STATUS_INFO",
|
||||
"DM_ULOG_STATUS_TABLE",
|
||||
"DM_ULOG_IS_REMOTE_RECOVERING",
|
||||
NULL
|
||||
};
|
||||
|
||||
int log_tabbing = 0;
|
||||
int log_is_open = 0;
|
||||
|
||||
/*
|
||||
* Variables for various conditional logging
|
||||
*/
|
||||
#ifdef MEMB
|
||||
int log_membership_change = 1;
|
||||
#else
|
||||
int log_membership_change = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CKPT
|
||||
int log_checkpoint = 1;
|
||||
#else
|
||||
int log_checkpoint = 0;
|
||||
#endif
|
||||
|
||||
#ifdef RESEND
|
||||
int log_resend_requests = 1;
|
||||
#else
|
||||
int log_resend_requests = 0;
|
||||
#endif
|
||||
77
daemons/cmirrord/logging.h
Normal file
77
daemons/cmirrord/logging.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_CLOG_LOGGING_H
|
||||
#define _LVM_CLOG_LOGGING_H
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "configure.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/* SHORT_UUID - print last 8 chars of a string */
|
||||
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
|
||||
|
||||
extern const char *__rq_types_off_by_one[];
|
||||
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
|
||||
|
||||
extern int log_tabbing;
|
||||
extern int log_is_open;
|
||||
extern int log_membership_change;
|
||||
extern int log_checkpoint;
|
||||
extern int log_resend_requests;
|
||||
|
||||
#define LOG_OPEN(ident, option, facility) do { \
|
||||
openlog(ident, option, facility); \
|
||||
log_is_open = 1; \
|
||||
} while (0)
|
||||
|
||||
#define LOG_CLOSE(void) do { \
|
||||
log_is_open = 0; \
|
||||
closelog(); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_OUTPUT(level, f, arg...) do { \
|
||||
int __i; \
|
||||
char __buffer[16]; \
|
||||
FILE *fp = (level > LOG_NOTICE) ? stderr : stdout; \
|
||||
if (log_is_open) { \
|
||||
for (__i = 0; (__i < log_tabbing) && (__i < 15); __i++) \
|
||||
__buffer[__i] = '\t'; \
|
||||
__buffer[__i] = '\0'; \
|
||||
syslog(level, "%s" f "\n", __buffer, ## arg); \
|
||||
} else { \
|
||||
for (__i = 0; __i < log_tabbing; __i++) \
|
||||
fprintf(fp, "\t"); \
|
||||
fprintf(fp, f "\n", ## arg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
|
||||
#else /* DEBUG */
|
||||
#define LOG_DBG(f, arg...)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define LOG_COND(__X, f, arg...) do {\
|
||||
if (__X) { \
|
||||
LOG_OUTPUT(LOG_NOTICE, f, ## arg); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_PRINT(f, arg...) LOG_OUTPUT(LOG_NOTICE, f, ## arg)
|
||||
#define LOG_ERROR(f, arg...) LOG_OUTPUT(LOG_ERR, f, ## arg)
|
||||
|
||||
#endif /* _LVM_CLOG_LOGGING_H */
|
||||
3
daemons/dmeventd/.exported_symbols
Normal file
3
daemons/dmeventd/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
init_fifos
|
||||
fini_fifos
|
||||
daemon_talk
|
||||
108
daemons/dmeventd/Makefile.in
Normal file
108
daemons/dmeventd/Makefile.in
Normal file
@@ -0,0 +1,108 @@
|
||||
#
|
||||
# Copyright (C) 2005-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the device-mapper userspace tools.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU Lesser General Public License v.2.1.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SOURCES = libdevmapper-event.c
|
||||
SOURCES2 = dmeventd.c
|
||||
|
||||
TARGETS = dmeventd
|
||||
|
||||
.PHONY: install_lib_dynamic install_lib_static install_include \
|
||||
install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
|
||||
install_lib install_dmeventd
|
||||
|
||||
INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic
|
||||
INSTALL_LIB_TARGETS = install_lib_dynamic
|
||||
|
||||
LIB_NAME = libdevmapper-event
|
||||
ifeq ("@STATIC_LINK@", "yes")
|
||||
LIB_STATIC = $(LIB_NAME).a
|
||||
TARGETS += $(LIB_STATIC) dmeventd.static
|
||||
INSTALL_DMEVENTD_TARGETS += install_dmeventd_static
|
||||
INSTALL_LIB_TARGETS += install_lib_static
|
||||
endif
|
||||
|
||||
LIB_VERSION = $(LIB_VERSION_DM)
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
|
||||
CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a
|
||||
|
||||
ifneq ($(MAKECMDGOALS),device-mapper)
|
||||
SUBDIRS+=plugins
|
||||
endif
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
CFLOW_TARGET = dmeventd
|
||||
|
||||
EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
|
||||
EXPORTED_FN_PREFIX = dm_event
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
all: device-mapper
|
||||
device-mapper: $(TARGETS)
|
||||
|
||||
LIBS += -ldevmapper
|
||||
LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS)
|
||||
|
||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -L. -o $@ dmeventd.o \
|
||||
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
|
||||
dmeventd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
|
||||
|
||||
ifeq ("@PKGCONFIG@", "yes")
|
||||
INSTALL_LIB_TARGETS += install_pkgconfig
|
||||
endif
|
||||
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
-include $(top_builddir)/libdm/libdevmapper.cflow
|
||||
-include $(top_builddir)/lib/liblvm-internal.cflow
|
||||
-include $(top_builddir)/lib/liblvm2cmd.cflow
|
||||
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
|
||||
-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
|
||||
endif
|
||||
|
||||
install_include: $(srcdir)/libdevmapper-event.h
|
||||
$(INSTALL_DATA) -D $< $(includedir)/$(<F)
|
||||
|
||||
install_pkgconfig: libdevmapper-event.pc
|
||||
$(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
|
||||
|
||||
install_lib_dynamic: install_lib_shared
|
||||
|
||||
install_lib_static: $(LIB_STATIC)
|
||||
$(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
|
||||
|
||||
install_lib: $(INSTALL_LIB_TARGETS)
|
||||
|
||||
install_dmeventd_dynamic: dmeventd
|
||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
||||
install_dmeventd_static: dmeventd.static
|
||||
$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
|
||||
|
||||
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
|
||||
|
||||
install: install_include install_lib install_dmeventd
|
||||
|
||||
install_device-mapper: install_include install_lib install_dmeventd
|
||||
|
||||
DISTCLEAN_TARGETS += libdevmapper-event.pc .exported_symbols_generated
|
||||
1863
daemons/dmeventd/dmeventd.c
Normal file
1863
daemons/dmeventd/dmeventd.c
Normal file
File diff suppressed because it is too large
Load Diff
73
daemons/dmeventd/dmeventd.h
Normal file
73
daemons/dmeventd/dmeventd.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __DMEVENTD_DOT_H__
|
||||
#define __DMEVENTD_DOT_H__
|
||||
|
||||
/* FIXME This stuff must be configurable. */
|
||||
|
||||
#define DM_EVENT_FIFO_CLIENT "/var/run/dmeventd-client"
|
||||
#define DM_EVENT_FIFO_SERVER "/var/run/dmeventd-server"
|
||||
|
||||
#define DM_EVENT_DEFAULT_TIMEOUT 10
|
||||
|
||||
/* Commands for the daemon passed in the message below. */
|
||||
enum dm_event_command {
|
||||
DM_EVENT_CMD_ACTIVE = 1,
|
||||
DM_EVENT_CMD_REGISTER_FOR_EVENT,
|
||||
DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
|
||||
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
|
||||
DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
|
||||
DM_EVENT_CMD_SET_TIMEOUT,
|
||||
DM_EVENT_CMD_GET_TIMEOUT,
|
||||
DM_EVENT_CMD_HELLO,
|
||||
DM_EVENT_CMD_DIE,
|
||||
DM_EVENT_CMD_GET_STATUS,
|
||||
};
|
||||
|
||||
/* Message passed between client and daemon. */
|
||||
struct dm_event_daemon_message {
|
||||
uint32_t cmd;
|
||||
uint32_t size;
|
||||
char *data;
|
||||
};
|
||||
|
||||
/* FIXME Is this meant to be exported? I can't see where the
|
||||
interface uses it. */
|
||||
/* Fifos for client/daemon communication. */
|
||||
struct dm_event_fifos {
|
||||
int client;
|
||||
int server;
|
||||
const char *client_path;
|
||||
const char *server_path;
|
||||
};
|
||||
|
||||
/* EXIT_SUCCESS 0 -- stdlib.h */
|
||||
/* EXIT_FAILURE 1 -- stdlib.h */
|
||||
/* EXIT_LOCKFILE_INUSE 2 -- obsoleted */
|
||||
#define EXIT_DESC_CLOSE_FAILURE 3
|
||||
#define EXIT_DESC_OPEN_FAILURE 4
|
||||
/* EXIT_OPEN_PID_FAILURE 5 -- obsoleted */
|
||||
#define EXIT_FIFO_FAILURE 6
|
||||
#define EXIT_CHDIR_FAILURE 7
|
||||
|
||||
/* Implemented in libdevmapper-event.c, but not part of public API. */
|
||||
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);
|
||||
|
||||
#endif /* __DMEVENTD_DOT_H__ */
|
||||
827
daemons/dmeventd/libdevmapper-event.c
Normal file
827
daemons/dmeventd/libdevmapper-event.c
Normal file
@@ -0,0 +1,827 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "dmlib.h"
|
||||
#include "libdevmapper-event.h"
|
||||
//#include "libmultilog.h"
|
||||
#include "dmeventd.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h> /* for htonl, ntohl */
|
||||
|
||||
static int _sequence_nr = 0;
|
||||
|
||||
struct dm_event_handler {
|
||||
char *dso;
|
||||
|
||||
char *dmeventd_path;
|
||||
|
||||
char *dev_name;
|
||||
|
||||
char *uuid;
|
||||
int major;
|
||||
int minor;
|
||||
uint32_t timeout;
|
||||
|
||||
enum dm_event_mask mask;
|
||||
};
|
||||
|
||||
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
|
||||
{
|
||||
dm_free(dmevh->dev_name);
|
||||
dm_free(dmevh->uuid);
|
||||
dmevh->dev_name = dmevh->uuid = NULL;
|
||||
dmevh->major = dmevh->minor = 0;
|
||||
}
|
||||
|
||||
struct dm_event_handler *dm_event_handler_create(void)
|
||||
{
|
||||
struct dm_event_handler *dmevh = NULL;
|
||||
|
||||
if (!(dmevh = dm_malloc(sizeof(*dmevh))))
|
||||
return NULL;
|
||||
|
||||
dmevh->dmeventd_path = NULL;
|
||||
dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;
|
||||
dmevh->major = dmevh->minor = 0;
|
||||
dmevh->mask = 0;
|
||||
dmevh->timeout = 0;
|
||||
|
||||
return dmevh;
|
||||
}
|
||||
|
||||
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
|
||||
{
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
dm_free(dmevh->dso);
|
||||
dm_free(dmevh->dmeventd_path);
|
||||
dm_free(dmevh);
|
||||
}
|
||||
|
||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
|
||||
{
|
||||
if (!dmeventd_path) /* noop */
|
||||
return 0;
|
||||
|
||||
dm_free(dmevh->dmeventd_path);
|
||||
|
||||
dmevh->dmeventd_path = dm_strdup(dmeventd_path);
|
||||
if (!dmevh->dmeventd_path)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
|
||||
{
|
||||
if (!path) /* noop */
|
||||
return 0;
|
||||
dm_free(dmevh->dso);
|
||||
|
||||
dmevh->dso = dm_strdup(path);
|
||||
if (!dmevh->dso)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
|
||||
{
|
||||
if (!dev_name)
|
||||
return 0;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
|
||||
dmevh->dev_name = dm_strdup(dev_name);
|
||||
if (!dmevh->dev_name)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
|
||||
{
|
||||
if (!uuid)
|
||||
return 0;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
|
||||
dmevh->uuid = dm_strdup(uuid);
|
||||
if (!dmevh->uuid)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
|
||||
{
|
||||
int minor = dmevh->minor;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
|
||||
dmevh->major = major;
|
||||
dmevh->minor = minor;
|
||||
}
|
||||
|
||||
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
|
||||
{
|
||||
int major = dmevh->major;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
|
||||
dmevh->major = major;
|
||||
dmevh->minor = minor;
|
||||
}
|
||||
|
||||
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
|
||||
enum dm_event_mask evmask)
|
||||
{
|
||||
dmevh->mask = evmask;
|
||||
}
|
||||
|
||||
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
|
||||
{
|
||||
dmevh->timeout = timeout;
|
||||
}
|
||||
|
||||
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->dso;
|
||||
}
|
||||
|
||||
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->dev_name;
|
||||
}
|
||||
|
||||
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->uuid;
|
||||
}
|
||||
|
||||
int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->major;
|
||||
}
|
||||
|
||||
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->minor;
|
||||
}
|
||||
|
||||
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->timeout;
|
||||
}
|
||||
|
||||
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->mask;
|
||||
}
|
||||
|
||||
static int _check_message_id(struct dm_event_daemon_message *msg)
|
||||
{
|
||||
int pid, seq_nr;
|
||||
|
||||
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
|
||||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
|
||||
log_error("Ignoring out-of-sequence reply from dmeventd. "
|
||||
"Expected %d:%d but received %s", getpid(),
|
||||
_sequence_nr, msg->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* daemon_read
|
||||
* @fifos
|
||||
* @msg
|
||||
*
|
||||
* Read message from daemon.
|
||||
*
|
||||
* Returns: 0 on failure, 1 on success
|
||||
*/
|
||||
static int _daemon_read(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
int ret, i;
|
||||
fd_set fds;
|
||||
struct timeval tval = { 0, 0 };
|
||||
size_t size = 2 * sizeof(uint32_t); /* status + size */
|
||||
uint32_t *header = alloca(size);
|
||||
char *buf = (char *)header;
|
||||
|
||||
while (bytes < size) {
|
||||
for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
|
||||
/* Watch daemon read FIFO for input. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->server, &fds);
|
||||
tval.tv_sec = 1;
|
||||
ret = select(fifos->server + 1, &fds, NULL, NULL,
|
||||
&tval);
|
||||
if (ret < 0 && errno != EINTR) {
|
||||
log_error("Unable to read from event server");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (ret < 1) {
|
||||
log_error("Unable to read from event server.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = read(fifos->server, buf + bytes, size);
|
||||
if (ret < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
else {
|
||||
log_error("Unable to read from event server.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytes += ret;
|
||||
if (header && (bytes == 2 * sizeof(uint32_t))) {
|
||||
msg->cmd = ntohl(header[0]);
|
||||
msg->size = ntohl(header[1]);
|
||||
buf = msg->data = dm_malloc(msg->size);
|
||||
size = msg->size;
|
||||
bytes = 0;
|
||||
header = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes != size) {
|
||||
dm_free(msg->data);
|
||||
msg->data = NULL;
|
||||
}
|
||||
return bytes == size;
|
||||
}
|
||||
|
||||
/* Write message to daemon. */
|
||||
static int _daemon_write(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
int ret = 0;
|
||||
fd_set fds;
|
||||
|
||||
size_t size = 2 * sizeof(uint32_t) + msg->size;
|
||||
uint32_t *header = alloca(size);
|
||||
char *buf = (char *)header;
|
||||
char drainbuf[128];
|
||||
struct timeval tval = { 0, 0 };
|
||||
|
||||
header[0] = htonl(msg->cmd);
|
||||
header[1] = htonl(msg->size);
|
||||
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
|
||||
|
||||
/* drain the answer fifo */
|
||||
while (1) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->server, &fds);
|
||||
tval.tv_usec = 100;
|
||||
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
|
||||
if ((ret < 0) && (errno != EINTR)) {
|
||||
log_error("Unable to talk to event daemon");
|
||||
return 0;
|
||||
}
|
||||
if (ret == 0)
|
||||
break;
|
||||
read(fifos->server, drainbuf, 127);
|
||||
}
|
||||
|
||||
while (bytes < size) {
|
||||
do {
|
||||
/* Watch daemon write FIFO to be ready for output. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->client, &fds);
|
||||
ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
|
||||
if ((ret < 0) && (errno != EINTR)) {
|
||||
log_error("Unable to talk to event daemon");
|
||||
return 0;
|
||||
}
|
||||
} while (ret < 1);
|
||||
|
||||
ret = write(fifos->client, buf + bytes, size - bytes);
|
||||
if (ret < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
else {
|
||||
log_error("Unable to talk to event daemon");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytes += ret;
|
||||
}
|
||||
|
||||
return bytes == size;
|
||||
}
|
||||
|
||||
int daemon_talk(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg, int cmd,
|
||||
const char *dso_name, const char *dev_name,
|
||||
enum dm_event_mask evmask, uint32_t timeout)
|
||||
{
|
||||
const char *dso = dso_name ? dso_name : "-";
|
||||
const char *dev = dev_name ? dev_name : "-";
|
||||
const char *fmt = "%d:%d %s %s %u %" PRIu32;
|
||||
int msg_size;
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
|
||||
/*
|
||||
* Set command and pack the arguments
|
||||
* into ASCII message string.
|
||||
*/
|
||||
msg->cmd = cmd;
|
||||
if (cmd == DM_EVENT_CMD_HELLO)
|
||||
fmt = "%d:%d HELLO";
|
||||
if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
|
||||
dso, dev, evmask, timeout)) < 0) {
|
||||
log_error("_daemon_talk: message allocation failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
msg->size = msg_size;
|
||||
|
||||
/*
|
||||
* Write command and message to and
|
||||
* read status return code from daemon.
|
||||
*/
|
||||
if (!_daemon_write(fifos, msg)) {
|
||||
stack;
|
||||
dm_free(msg->data);
|
||||
msg->data = 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
dm_free(msg->data);
|
||||
msg->data = 0;
|
||||
|
||||
if (!_daemon_read(fifos, msg)) {
|
||||
stack;
|
||||
return -EIO;
|
||||
}
|
||||
} while (!_check_message_id(msg));
|
||||
|
||||
_sequence_nr++;
|
||||
|
||||
return (int32_t) msg->cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* start_daemon
|
||||
*
|
||||
* This function forks off a process (dmeventd) that will handle
|
||||
* the events. I am currently test opening one of the fifos to
|
||||
* ensure that the daemon is running and listening... I thought
|
||||
* this would be less expensive than fork/exec'ing every time.
|
||||
* Perhaps there is an even quicker/better way (no, checking the
|
||||
* lock file is _not_ a better way).
|
||||
*
|
||||
* Returns: 1 on success, 0 otherwise
|
||||
*/
|
||||
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
{
|
||||
int pid, ret = 0;
|
||||
int status;
|
||||
struct stat statbuf;
|
||||
char default_dmeventd_path[] = DMEVENTD_PATH;
|
||||
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
|
||||
|
||||
if (stat(fifos->client_path, &statbuf))
|
||||
goto start_server;
|
||||
|
||||
if (!S_ISFIFO(statbuf.st_mode)) {
|
||||
log_error("%s is not a fifo.", fifos->client_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Anyone listening? If not, errno will be ENXIO */
|
||||
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
|
||||
if (fifos->client >= 0) {
|
||||
/* server is running and listening */
|
||||
|
||||
close(fifos->client);
|
||||
return 1;
|
||||
} else if (errno != ENXIO) {
|
||||
/* problem */
|
||||
|
||||
log_error("%s: Can't open client fifo %s: %s",
|
||||
__func__, fifos->client_path, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
start_server:
|
||||
/* server is not running */
|
||||
|
||||
if (!strncmp(DMEVENTD_PATH, "/", 1) && stat(DMEVENTD_PATH, &statbuf)) {
|
||||
log_error("Unable to find dmeventd.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0)
|
||||
log_error("Unable to fork.");
|
||||
|
||||
else if (!pid) {
|
||||
execvp(args[0], args);
|
||||
log_error("Unable to exec dmeventd: %s", strerror(errno));
|
||||
_exit(EXIT_FAILURE);
|
||||
} else {
|
||||
if (waitpid(pid, &status, 0) < 0)
|
||||
log_error("Unable to start dmeventd: %s",
|
||||
strerror(errno));
|
||||
else if (WEXITSTATUS(status))
|
||||
log_error("Unable to start dmeventd.");
|
||||
else
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int init_fifos(struct dm_event_fifos *fifos)
|
||||
{
|
||||
/* FIXME? Is fifo the most suitable method? Why not share
|
||||
comms/daemon code with something else e.g. multipath? */
|
||||
|
||||
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||
|
||||
/* Open the fifo used to read from the daemon. */
|
||||
if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
|
||||
log_error("%s: open server fifo %s",
|
||||
__func__, fifos->server_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Lock out anyone else trying to do communication with the daemon. */
|
||||
if (flock(fifos->server, LOCK_EX) < 0) {
|
||||
log_error("%s: flock %s", __func__, fifos->server_path);
|
||||
close(fifos->server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
|
||||
if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
|
||||
log_error("%s: Can't open client fifo %s: %s",
|
||||
__func__, fifos->client_path, strerror(errno));
|
||||
close(fifos->server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize client. */
|
||||
static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
{
|
||||
/* init fifos */
|
||||
memset(fifos, 0, sizeof(*fifos));
|
||||
|
||||
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||
|
||||
if (!_start_daemon(dmeventd_path, fifos))
|
||||
return_0;
|
||||
|
||||
return init_fifos(fifos);
|
||||
}
|
||||
|
||||
void fini_fifos(struct dm_event_fifos *fifos)
|
||||
{
|
||||
if (flock(fifos->server, LOCK_UN))
|
||||
log_error("flock unlock %s", fifos->server_path);
|
||||
|
||||
close(fifos->client);
|
||||
close(fifos->server);
|
||||
}
|
||||
|
||||
/* Get uuid of a device */
|
||||
static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
|
||||
log_error("_get_device_info: dm_task creation for info failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmevh->uuid) {
|
||||
if (!dm_task_set_uuid(dmt, dmevh->uuid))
|
||||
goto_bad;
|
||||
} else if (dmevh->dev_name) {
|
||||
if (!dm_task_set_name(dmt, dmevh->dev_name))
|
||||
goto_bad;
|
||||
} else if (dmevh->major && dmevh->minor) {
|
||||
if (!dm_task_set_major(dmt, dmevh->major) ||
|
||||
!dm_task_set_minor(dmt, dmevh->minor))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
/* FIXME Add name or uuid or devno to messages */
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("_get_device_info: dm_task_run() failed");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!dm_task_get_info(dmt, &info)) {
|
||||
log_error("_get_device_info: failed to get info for device");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!info.exists) {
|
||||
log_error("_get_device_info: device not found");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return dmt;
|
||||
|
||||
bad:
|
||||
dm_task_destroy(dmt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle the event (de)registration call and return negative error codes. */
|
||||
static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_message *msg,
|
||||
const char *dso_name, const char *dev_name,
|
||||
enum dm_event_mask evmask, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct dm_event_fifos fifos;
|
||||
|
||||
if (!_init_client(dmeventd_path, &fifos)) {
|
||||
stack;
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
||||
|
||||
dm_free(msg->data);
|
||||
msg->data = 0;
|
||||
|
||||
if (!ret)
|
||||
ret = daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
|
||||
|
||||
/* what is the opposite of init? */
|
||||
fini_fifos(&fifos);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* External library interface. */
|
||||
int dm_event_register_handler(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
int ret = 1, err;
|
||||
const char *uuid;
|
||||
struct dm_task *dmt;
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (!(dmt = _get_device_info(dmevh))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uuid = dm_task_get_uuid(dmt);
|
||||
|
||||
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
|
||||
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
||||
log_error("%s: event registration failed: %s",
|
||||
dm_task_get_name(dmt),
|
||||
msg.data ? msg.data : strerror(-err));
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dm_free(msg.data);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
int ret = 1, err;
|
||||
const char *uuid;
|
||||
struct dm_task *dmt;
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (!(dmt = _get_device_info(dmevh))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uuid = dm_task_get_uuid(dmt);
|
||||
|
||||
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
|
||||
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
||||
log_error("%s: event deregistration failed: %s",
|
||||
dm_task_get_name(dmt),
|
||||
msg.data ? msg.data : strerror(-err));
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dm_free(msg.data);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Fetch a string off src and duplicate it into *dest. */
|
||||
/* FIXME: move to separate module to share with the daemon. */
|
||||
static char *_fetch_string(char **src, const int delimiter)
|
||||
{
|
||||
char *p, *ret;
|
||||
|
||||
if ((p = strchr(*src, delimiter)))
|
||||
*p = 0;
|
||||
|
||||
if ((ret = dm_strdup(*src)))
|
||||
*src += strlen(ret) + 1;
|
||||
|
||||
if (p)
|
||||
*p = delimiter;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Parse a device message from the daemon. */
|
||||
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
|
||||
char **uuid, enum dm_event_mask *evmask)
|
||||
{
|
||||
char *id = NULL;
|
||||
char *p = msg->data;
|
||||
|
||||
if ((id = _fetch_string(&p, ' ')) &&
|
||||
(*dso_name = _fetch_string(&p, ' ')) &&
|
||||
(*uuid = _fetch_string(&p, ' '))) {
|
||||
*evmask = atoi(p);
|
||||
|
||||
dm_free(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (id)
|
||||
dm_free(id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise.
|
||||
*/
|
||||
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
||||
{
|
||||
int ret = 0;
|
||||
const char *uuid = NULL;
|
||||
char *reply_dso = NULL, *reply_uuid = NULL;
|
||||
enum dm_event_mask reply_mask = 0;
|
||||
struct dm_task *dmt = NULL;
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
struct dm_info info;
|
||||
|
||||
if (!(dmt = _get_device_info(dmevh))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uuid = dm_task_get_uuid(dmt);
|
||||
|
||||
if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
|
||||
DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
|
||||
&msg, dmevh->dso, uuid, dmevh->mask, 0)) {
|
||||
ret = -ENOENT;
|
||||
stack;
|
||||
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);
|
||||
dmevh->uuid = dm_strdup(reply_uuid);
|
||||
if (!dmevh->uuid) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(dmt = _get_device_info(dmevh))) {
|
||||
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dm_event_handler_set_dso(dmevh, reply_dso);
|
||||
dm_event_handler_set_event_mask(dmevh, reply_mask);
|
||||
|
||||
dm_free(reply_dso);
|
||||
reply_dso = NULL;
|
||||
|
||||
dm_free(reply_uuid);
|
||||
reply_uuid = NULL;
|
||||
|
||||
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
|
||||
if (!dmevh->dev_name) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_get_info(dmt, &info)) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dmevh->major = info.major;
|
||||
dmevh->minor = info.minor;
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
dm_free(msg.data);
|
||||
dm_free(reply_dso);
|
||||
dm_free(reply_uuid);
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0 /* left out for now */
|
||||
|
||||
static char *_skip_string(char *src, const int delimiter)
|
||||
{
|
||||
src = srtchr(src, delimiter);
|
||||
if (src && *(src + 1))
|
||||
return src + 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
|
||||
{
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (!device_exists(device_path))
|
||||
return -ENODEV;
|
||||
|
||||
return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
|
||||
NULL, device_path, 0, timeout);
|
||||
}
|
||||
|
||||
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
|
||||
{
|
||||
int ret;
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (!device_exists(device_path))
|
||||
return -ENODEV;
|
||||
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
|
||||
0, 0))) {
|
||||
char *p = _skip_string(msg.data, ' ');
|
||||
if (!p) {
|
||||
log_error("malformed reply from dmeventd '%s'\n",
|
||||
msg.data);
|
||||
return -EIO;
|
||||
}
|
||||
*timeout = atoi(p);
|
||||
}
|
||||
if (msg.data)
|
||||
dm_free(msg.data);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
111
daemons/dmeventd/libdevmapper-event.h
Normal file
111
daemons/dmeventd/libdevmapper-event.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note that this file is released only as part of a technology preview
|
||||
* and its contents may change in future updates in ways that do not
|
||||
* preserve compatibility.
|
||||
*/
|
||||
|
||||
#ifndef LIB_DMEVENT_H
|
||||
#define LIB_DMEVENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Event library interface.
|
||||
*/
|
||||
|
||||
enum dm_event_mask {
|
||||
DM_EVENT_SETTINGS_MASK = 0x0000FF,
|
||||
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
|
||||
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
|
||||
|
||||
DM_EVENT_ERROR_MASK = 0x00FF00,
|
||||
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
|
||||
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
|
||||
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
|
||||
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
|
||||
|
||||
DM_EVENT_STATUS_MASK = 0xFF0000,
|
||||
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
|
||||
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
|
||||
|
||||
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
|
||||
};
|
||||
|
||||
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
|
||||
|
||||
struct dm_event_handler;
|
||||
|
||||
struct dm_event_handler *dm_event_handler_create(void);
|
||||
void dm_event_handler_destroy(struct dm_event_handler *dmevh);
|
||||
|
||||
/*
|
||||
* Path of shared library to handle events.
|
||||
*
|
||||
* All of dmeventd, dso, device_name and uuid strings are duplicated so
|
||||
* you do not need to keep the pointers valid after the call succeeds.
|
||||
* They may return -ENOMEM though.
|
||||
*/
|
||||
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
|
||||
|
||||
/*
|
||||
* Path of dmeventd binary.
|
||||
*/
|
||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path);
|
||||
|
||||
/*
|
||||
* Identify the device to monitor by exactly one of device_name, uuid or
|
||||
* device number. String arguments are duplicated, see above.
|
||||
*/
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
|
||||
|
||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
|
||||
|
||||
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
|
||||
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
|
||||
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
|
||||
|
||||
/*
|
||||
* Specify mask for events to monitor.
|
||||
*/
|
||||
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
|
||||
enum dm_event_mask evmask);
|
||||
|
||||
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
|
||||
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
|
||||
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
|
||||
int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
|
||||
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
|
||||
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
|
||||
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
|
||||
|
||||
/* FIXME Review interface (what about this next thing?) */
|
||||
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
|
||||
|
||||
/*
|
||||
* Initiate monitoring using dmeventd.
|
||||
*/
|
||||
int dm_event_register_handler(const struct dm_event_handler *dmevh);
|
||||
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
|
||||
|
||||
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
|
||||
detailed descriptions. */
|
||||
void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
|
||||
int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
|
||||
int unregister_device(const char *device_name, const char *uuid, int major,
|
||||
int minor, void **user);
|
||||
|
||||
#endif
|
||||
11
daemons/dmeventd/libdevmapper-event.pc.in
Normal file
11
daemons/dmeventd/libdevmapper-event.pc.in
Normal file
@@ -0,0 +1,11 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: devmapper-event
|
||||
Description: device-mapper event library
|
||||
Version: @DM_LIB_PATCHLEVEL@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -ldevmapper-event
|
||||
Requires.private: devmapper
|
||||
25
daemons/dmeventd/plugins/Makefile.in
Normal file
25
daemons/dmeventd/plugins/Makefile.in
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SUBDIRS += lvm2 mirror snapshot
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
mirror: lvm2
|
||||
snapshot: lvm2
|
||||
|
||||
6
daemons/dmeventd/plugins/lvm2/.exported_symbols
Normal file
6
daemons/dmeventd/plugins/lvm2/.exported_symbols
Normal file
@@ -0,0 +1,6 @@
|
||||
dmeventd_lvm2_init
|
||||
dmeventd_lvm2_exit
|
||||
dmeventd_lvm2_lock
|
||||
dmeventd_lvm2_unlock
|
||||
dmeventd_lvm2_pool
|
||||
dmeventd_lvm2_run
|
||||
33
daemons/dmeventd/plugins/lvm2/Makefile.in
Normal file
33
daemons/dmeventd/plugins/lvm2/Makefile.in
Normal file
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU 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
|
||||
|
||||
DISTCLEAN_TARGETS += .exported_symbols_generated
|
||||
152
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
Normal file
152
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <syslog.h>
|
||||
|
||||
extern int dmeventd_debug;
|
||||
|
||||
/*
|
||||
* register_device() is called first and performs initialisation.
|
||||
* Only one device may be registered or unregistered at a time.
|
||||
*/
|
||||
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
* Number of active registrations.
|
||||
*/
|
||||
static int _register_count = 0;
|
||||
static struct dm_pool *_mem_pool = NULL;
|
||||
static void *_lvm_handle = NULL;
|
||||
|
||||
/*
|
||||
* Currently only one event can be processed at a time.
|
||||
*/
|
||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
* FIXME Do not pass things directly to syslog, rather use the existing logging
|
||||
* facilities to sort logging ... however that mechanism needs to be somehow
|
||||
* configurable and we don't have that option yet
|
||||
*/
|
||||
static void _temporary_log_fn(int level,
|
||||
const char *file __attribute__((unused)),
|
||||
int line __attribute__((unused)),
|
||||
int dm_errno __attribute__((unused)),
|
||||
const char *message)
|
||||
{
|
||||
level &= ~(_LOG_STDERR | _LOG_ONCE);
|
||||
|
||||
switch (level) {
|
||||
case _LOG_DEBUG:
|
||||
if (dmeventd_debug >= 3)
|
||||
syslog(LOG_DEBUG, "%s", message);
|
||||
break;
|
||||
case _LOG_INFO:
|
||||
if (dmeventd_debug >= 2)
|
||||
syslog(LOG_INFO, "%s", message);
|
||||
break;
|
||||
case _LOG_NOTICE:
|
||||
if (dmeventd_debug >= 1)
|
||||
syslog(LOG_NOTICE, "%s", message);
|
||||
break;
|
||||
case _LOG_WARN:
|
||||
syslog(LOG_WARNING, "%s", message);
|
||||
break;
|
||||
case _LOG_ERR:
|
||||
syslog(LOG_ERR, "%s", message);
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_CRIT, "%s", message);
|
||||
}
|
||||
}
|
||||
|
||||
void dmeventd_lvm2_lock(void)
|
||||
{
|
||||
if (pthread_mutex_trylock(&_event_mutex)) {
|
||||
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
|
||||
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;
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
|
||||
39
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h
Normal file
39
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Wrappers around liblvm2cmd functions for dmeventd plug-ins.
|
||||
*
|
||||
* liblvm2cmd is not thread-safe so the locking in this library helps dmeventd
|
||||
* threads to co-operate in sharing a single instance.
|
||||
*
|
||||
* FIXME Either support this properly as a generic liblvm2cmd wrapper or make
|
||||
* liblvm2cmd thread-safe so this can go away.
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
|
||||
#ifndef _DMEVENTD_LVMWRAP_H
|
||||
#define _DMEVENTD_LVMWRAP_H
|
||||
|
||||
int dmeventd_lvm2_init(void);
|
||||
void dmeventd_lvm2_exit(void);
|
||||
int dmeventd_lvm2_run(const char *cmdline);
|
||||
|
||||
void dmeventd_lvm2_lock(void);
|
||||
void dmeventd_lvm2_unlock(void);
|
||||
|
||||
struct dm_pool *dmeventd_lvm2_pool(void);
|
||||
|
||||
#endif /* _DMEVENTD_LVMWRAP_H */
|
||||
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
39
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
39
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2008-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@
|
||||
|
||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
LIB_NAME = libdevmapper-event-lvm2mirror
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
install: install_lvm2
|
||||
|
||||
DISTCLEAN_TARGETS += .exported_symbols_generated
|
||||
245
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
245
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (C) 2005-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 "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
/* FIXME Missing openlog? */
|
||||
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
|
||||
/* FIXME Reformat to 80 char lines. */
|
||||
|
||||
#define ME_IGNORE 0
|
||||
#define ME_INSYNC 1
|
||||
#define ME_FAILURE 2
|
||||
|
||||
static int _process_status_code(const char status_code, const char *dev_name,
|
||||
const char *dev_type, int r)
|
||||
{
|
||||
/*
|
||||
* A => Alive - No failures
|
||||
* D => Dead - A write failure occurred leaving mirror out-of-sync
|
||||
* F => Flush failed.
|
||||
* S => Sync - A sychronization failure occurred, mirror out-of-sync
|
||||
* R => Read - A read failure occurred, mirror data unaffected
|
||||
* U => Unclassified failure (bug)
|
||||
*/
|
||||
if (status_code == 'F') {
|
||||
syslog(LOG_ERR, "%s device %s flush failed.",
|
||||
dev_type, dev_name);
|
||||
r = ME_FAILURE;
|
||||
} else if (status_code == 'S')
|
||||
syslog(LOG_ERR, "%s device %s sync failed.",
|
||||
dev_type, dev_name);
|
||||
else if (status_code == 'R')
|
||||
syslog(LOG_ERR, "%s device %s read failed.",
|
||||
dev_type, dev_name);
|
||||
else if (status_code != 'A') {
|
||||
syslog(LOG_ERR, "%s device %s has failed (%c).",
|
||||
dev_type, dev_name, status_code);
|
||||
r = ME_FAILURE;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
{
|
||||
int i, r = ME_INSYNC;
|
||||
char **args = NULL;
|
||||
char *dev_status_str;
|
||||
char *log_status_str;
|
||||
char *sync_str;
|
||||
char *p = NULL;
|
||||
int log_argc, num_devs;
|
||||
|
||||
/*
|
||||
* dm core parms: 0 409600 mirror
|
||||
* Mirror core parms: 2 253:4 253:5 400/400
|
||||
* New-style failure params: 1 AA
|
||||
* New-style log params: 3 cluster 253:3 A
|
||||
* or 3 disk 253:3 A
|
||||
* or 1 core
|
||||
*/
|
||||
|
||||
/* number of devices */
|
||||
if (!dm_split_words(params, 1, 0, &p))
|
||||
goto out_parse;
|
||||
|
||||
if (!(num_devs = atoi(p)))
|
||||
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++)
|
||||
r = _process_status_code(dev_status_str[i], args[i],
|
||||
i ? "Secondary mirror" : "Primary mirror", r);
|
||||
|
||||
/* Check for bad disk log device */
|
||||
if (log_argc > 1)
|
||||
r = _process_status_code(log_status_str[0],
|
||||
args[2 + num_devs + log_argc],
|
||||
"Log", r);
|
||||
|
||||
if (r == ME_FAILURE)
|
||||
goto out;
|
||||
|
||||
p = strstr(sync_str, "/");
|
||||
if (p) {
|
||||
p[0] = '\0';
|
||||
if (strcmp(sync_str, p+1))
|
||||
r = ME_IGNORE;
|
||||
p[0] = '/';
|
||||
} else
|
||||
goto out_parse;
|
||||
|
||||
out:
|
||||
dm_free(args);
|
||||
return r;
|
||||
|
||||
out_parse:
|
||||
dm_free(args);
|
||||
syslog(LOG_ERR, "Unable to parse mirror status string.");
|
||||
return ME_IGNORE;
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
{
|
||||
int r;
|
||||
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
||||
char cmd_str[CMD_SIZE];
|
||||
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(dmeventd_lvm2_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 */
|
||||
}
|
||||
|
||||
/* strip off the mirror component designations */
|
||||
layer = strstr(lv, "_mlog");
|
||||
if (layer)
|
||||
*layer = '\0';
|
||||
|
||||
/* FIXME Is any sanity-checking required on %s? */
|
||||
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "lvconvert --config devices{ignore_suspended_devices=1} --repair --use-policies %s/%s", vg, lv)) {
|
||||
/* 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.");
|
||||
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||
}
|
||||
|
||||
r = dmeventd_lvm2_run(cmd_str);
|
||||
|
||||
syslog(LOG_INFO, "Repair of mirrored LV %s/%s %s.", vg, lv,
|
||||
(r == ECMD_PROCESSED) ? "finished successfully" : "failed");
|
||||
|
||||
return (r == ECMD_PROCESSED) ? 0 : -1;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **unused __attribute__((unused)))
|
||||
{
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
|
||||
dmeventd_lvm2_lock();
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (!target_type) {
|
||||
syslog(LOG_INFO, "%s mapping lost.", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(target_type, "mirror")) {
|
||||
syslog(LOG_INFO, "%s has unmirrored portion.", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_get_mirror_event(params)) {
|
||||
case ME_INSYNC:
|
||||
/* FIXME: all we really know is that this
|
||||
_part_ of the device is in sync
|
||||
Also, this is not an error
|
||||
*/
|
||||
syslog(LOG_NOTICE, "%s is now in-sync.", device);
|
||||
break;
|
||||
case ME_FAILURE:
|
||||
syslog(LOG_ERR, "Device failure in %s.", device);
|
||||
if (_remove_failed_devices(device))
|
||||
/* FIXME Why are all the error return codes unused? Get rid of them? */
|
||||
syslog(LOG_ERR, "Failed to remove faulty devices in %s.",
|
||||
device);
|
||||
/* Should check before warning user that device is now linear
|
||||
else
|
||||
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||
device);
|
||||
*/
|
||||
break;
|
||||
case ME_IGNORE:
|
||||
break;
|
||||
default:
|
||||
/* FIXME Provide value then! */
|
||||
syslog(LOG_INFO, "Unknown event received.");
|
||||
}
|
||||
} while (next);
|
||||
|
||||
dmeventd_lvm2_unlock();
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **unused __attribute__((unused)))
|
||||
{
|
||||
int r = dmeventd_lvm2_init();
|
||||
syslog(LOG_INFO, "Monitoring mirror device %s for events.", device);
|
||||
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)))
|
||||
{
|
||||
syslog(LOG_INFO, "No longer monitoring mirror device %s for events.",
|
||||
device);
|
||||
dmeventd_lvm2_exit();
|
||||
return 1;
|
||||
}
|
||||
3
daemons/dmeventd/plugins/snapshot/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/snapshot/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
35
daemons/dmeventd/plugins/snapshot/Makefile.in
Normal file
35
daemons/dmeventd/plugins/snapshot/Makefile.in
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||
|
||||
SOURCES = dmeventd_snapshot.c
|
||||
|
||||
LIB_SHARED = libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
install: install_lvm2
|
||||
|
||||
DISTCLEAN_TARGETS += .exported_symbols_generated
|
||||
262
daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
Normal file
262
daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2007-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 "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
/* FIXME Missing openlog? */
|
||||
|
||||
/* First warning when snapshot is 80% full. */
|
||||
#define WARNING_THRESH 80
|
||||
/* Run a check every 5%. */
|
||||
#define CHECK_STEP 5
|
||||
/* Do not bother checking snapshots less than 50% full. */
|
||||
#define CHECK_MINIMUM 50
|
||||
|
||||
#define UMOUNT_COMMAND "/bin/umount"
|
||||
|
||||
struct snap_status {
|
||||
int invalid;
|
||||
int used;
|
||||
int max;
|
||||
};
|
||||
|
||||
/* FIXME possibly reconcile this with target_percent when we gain
|
||||
access to regular LVM library here. */
|
||||
static void _parse_snapshot_params(char *params, struct snap_status *status)
|
||||
{
|
||||
char *p;
|
||||
/*
|
||||
* xx/xx -- fractions used/max
|
||||
* Invalid -- snapshot invalidated
|
||||
* Unknown -- status unknown
|
||||
*/
|
||||
status->used = status->max = 0;
|
||||
|
||||
if (!strncmp(params, "Invalid", 7)) {
|
||||
status->invalid = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we return without setting non-zero max, the parent is
|
||||
* responsible for reporting errors.
|
||||
*/
|
||||
if (!strncmp(params, "Unknown", 7))
|
||||
return;
|
||||
|
||||
if (!(p = strstr(params, "/")))
|
||||
return;
|
||||
|
||||
*p = '\0';
|
||||
p++;
|
||||
|
||||
status->used = atoi(params);
|
||||
status->max = atoi(p);
|
||||
}
|
||||
|
||||
static int _run(const char *cmd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int argc = 1; /* for argv[0], i.e. cmd */
|
||||
int i = 0;
|
||||
const char **argv;
|
||||
pid_t pid = fork();
|
||||
int status;
|
||||
|
||||
if (pid == 0) { /* child */
|
||||
va_start(ap, cmd);
|
||||
while (va_arg(ap, const char *))
|
||||
++ argc;
|
||||
va_end(ap);
|
||||
|
||||
/* + 1 for the terminating NULL */
|
||||
argv = alloca(sizeof(const char *) * (argc + 1));
|
||||
|
||||
argv[0] = cmd;
|
||||
va_start(ap, cmd);
|
||||
while ((argv[++i] = va_arg(ap, const char *)));
|
||||
va_end(ap);
|
||||
|
||||
execvp(cmd, (char **)argv);
|
||||
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
|
||||
exit(127);
|
||||
}
|
||||
|
||||
if (pid > 0) { /* parent */
|
||||
if (waitpid(pid, &status, 0) != pid)
|
||||
return 0; /* waitpid failed */
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status))
|
||||
return 0; /* the child failed */
|
||||
}
|
||||
|
||||
if (pid < 0)
|
||||
return 0; /* fork failed */
|
||||
|
||||
return 1; /* all good */
|
||||
}
|
||||
|
||||
static int _extend(const char *device)
|
||||
{
|
||||
char *vg = NULL, *lv = NULL, *layer = NULL;
|
||||
char cmd_str[1024];
|
||||
int r = 0;
|
||||
|
||||
if (!dm_split_lvm_name(dmeventd_lvm2_pool(), device, &vg, &lv, &layer)) {
|
||||
syslog(LOG_ERR, "Unable to determine VG name from %s.", device);
|
||||
return 0;
|
||||
}
|
||||
if (sizeof(cmd_str) <= snprintf(cmd_str, sizeof(cmd_str),
|
||||
"lvextend --use-policies %s/%s", vg, lv)) {
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = dmeventd_lvm2_run(cmd_str);
|
||||
syslog(LOG_INFO, "Extension of snapshot %s/%s %s.", vg, lv,
|
||||
(r == ECMD_PROCESSED) ? "finished successfully" : "failed");
|
||||
return r == ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static void _umount(const char *device, int major, int minor)
|
||||
{
|
||||
FILE *mounts;
|
||||
char buffer[4096];
|
||||
char *words[3];
|
||||
struct stat st;
|
||||
|
||||
if (!(mounts = fopen("/proc/mounts", "r"))) {
|
||||
syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device);
|
||||
return;
|
||||
}
|
||||
|
||||
while (!feof(mounts)) {
|
||||
/* read a line of /proc/mounts */
|
||||
if (!fgets(buffer, sizeof(buffer), mounts))
|
||||
break; /* eof, likely */
|
||||
|
||||
/* words[0] is the mount point and words[1] is the device path */
|
||||
dm_split_words(buffer, 3, 0, words);
|
||||
|
||||
/* find the major/minor of the device */
|
||||
if (stat(words[0], &st))
|
||||
continue; /* can't stat, skip this one */
|
||||
|
||||
if (S_ISBLK(st.st_mode) &&
|
||||
major(st.st_rdev) == major &&
|
||||
minor(st.st_rdev) == minor) {
|
||||
syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.", device, words[1]);
|
||||
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
|
||||
syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.",
|
||||
device, words[1], strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(mounts))
|
||||
syslog(LOG_ERR, "Failed to close /proc/mounts.\n");
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **private)
|
||||
{
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
struct snap_status status = { 0 };
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
int percent, *percent_check = (int*)private;
|
||||
|
||||
/* No longer monitoring, waiting for remove */
|
||||
if (!*percent_check)
|
||||
return;
|
||||
|
||||
dmeventd_lvm2_lock();
|
||||
|
||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
if (!target_type)
|
||||
goto out;
|
||||
|
||||
_parse_snapshot_params(params, &status);
|
||||
|
||||
if (status.invalid) {
|
||||
syslog(LOG_ERR, "Trying to umount invalid snapshot %s...\n", device);
|
||||
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... */
|
||||
}
|
||||
|
||||
/*
|
||||
* If the snapshot has been invalidated or we failed to parse
|
||||
* the status string. Report the full status string to syslog.
|
||||
*/
|
||||
if (status.invalid || !status.max) {
|
||||
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
|
||||
*percent_check = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
percent = 100 * status.used / status.max;
|
||||
if (percent >= *percent_check) {
|
||||
/* Usage has raised more than CHECK_STEP since the last
|
||||
time. Run actions. */
|
||||
*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(device))
|
||||
syslog(LOG_ERR, "Failed to extend snapshot %s.", device);
|
||||
}
|
||||
out:
|
||||
dmeventd_lvm2_unlock();
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **private)
|
||||
{
|
||||
int *percent_check = (int*)private;
|
||||
int r = dmeventd_lvm2_init();
|
||||
|
||||
*percent_check = CHECK_MINIMUM;
|
||||
|
||||
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
|
||||
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)))
|
||||
{
|
||||
syslog(LOG_INFO, "No longer monitoring snapshot %s\n",
|
||||
device);
|
||||
dmeventd_lvm2_exit();
|
||||
return 1;
|
||||
}
|
||||
31
doc/Makefile.in
Normal file
31
doc/Makefile.in
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
CONFSRC=example.conf
|
||||
CONFDEST=lvm.conf
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
install_lvm2: $(CONFSRC)
|
||||
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||
echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST)"; \
|
||||
$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST); \
|
||||
fi
|
||||
|
||||
install: install_lvm2
|
||||
|
||||
DISTCLEAN_TARGETS += $(CONFSRC)
|
||||
@@ -1 +0,0 @@
|
||||
Wow! This is really incredible documentation!
|
||||
577
doc/example.conf.in
Normal file
577
doc/example.conf.in
Normal file
@@ -0,0 +1,577 @@
|
||||
# This is an example configuration file for the LVM2 system.
|
||||
# It contains the default settings that would be used if there was no
|
||||
# @DEFAULT_SYS_DIR@/lvm.conf file.
|
||||
#
|
||||
# Refer to 'man lvm.conf' for further information including the file layout.
|
||||
#
|
||||
# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set
|
||||
# the environment variable LVM_SYSTEM_DIR before running the tools.
|
||||
|
||||
|
||||
# This section allows you to configure which block devices should
|
||||
# be used by the LVM system.
|
||||
devices {
|
||||
|
||||
# Where do you want your volume groups to appear ?
|
||||
dir = "/dev"
|
||||
|
||||
# An array of directories that contain the device nodes you wish
|
||||
# to use with LVM2.
|
||||
scan = [ "/dev" ]
|
||||
|
||||
# If several entries in the scanned directories correspond to the
|
||||
# same block device and the tools need to display a name for device,
|
||||
# all the pathnames are matched against each item in the following
|
||||
# list of regular expressions in turn and the first match is used.
|
||||
preferred_names = [ ]
|
||||
|
||||
# Try to avoid using undescriptive /dev/dm-N names, if present.
|
||||
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
|
||||
|
||||
# A filter that tells LVM2 to only use a restricted set of devices.
|
||||
# The filter consists of an array of regular expressions. These
|
||||
# expressions can be delimited by a character of your choice, and
|
||||
# prefixed with either an 'a' (for accept) or 'r' (for reject).
|
||||
# The first expression found to match a device name determines if
|
||||
# the device will be accepted or rejected (ignored). Devices that
|
||||
# don't match any patterns are accepted.
|
||||
|
||||
# Be careful if there there are symbolic links or multiple filesystem
|
||||
# entries for the same device as each name is checked separately against
|
||||
# the list of patterns. The effect is that if any name matches any 'a'
|
||||
# pattern, the device is accepted; otherwise if any name matches any 'r'
|
||||
# pattern it is rejected; otherwise it is accepted.
|
||||
|
||||
# Don't have more than one filter line active at once: only one gets used.
|
||||
|
||||
# Run vgscan after you change this parameter to ensure that
|
||||
# the cache file gets regenerated (see below).
|
||||
# If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
|
||||
|
||||
|
||||
# By default we accept every block device:
|
||||
filter = [ "a/.*/" ]
|
||||
|
||||
# Exclude the cdrom drive
|
||||
# filter = [ "r|/dev/cdrom|" ]
|
||||
|
||||
# When testing I like to work with just loopback devices:
|
||||
# filter = [ "a/loop/", "r/.*/" ]
|
||||
|
||||
# Or maybe all loops and ide drives except hdc:
|
||||
# filter =[ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
|
||||
|
||||
# Use anchors if you want to be really specific
|
||||
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
|
||||
|
||||
# The results of the filtering are cached on disk to avoid
|
||||
# rescanning dud devices (which can take a very long time).
|
||||
# By default this cache is stored in the @DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@ directory
|
||||
# in a file called '.cache'.
|
||||
# It is safe to delete the contents: the tools regenerate it.
|
||||
# (The old setting 'cache' is still respected if neither of
|
||||
# these new ones is present.)
|
||||
cache_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@"
|
||||
cache_file_prefix = ""
|
||||
|
||||
# You can turn off writing this cache file by setting this to 0.
|
||||
write_cache_state = 1
|
||||
|
||||
# Advanced settings.
|
||||
|
||||
# List of pairs of additional acceptable block device types found
|
||||
# in /proc/devices with maximum (non-zero) number of partitions.
|
||||
# types = [ "fd", 16 ]
|
||||
|
||||
# If sysfs is mounted (2.6 kernels) restrict device scanning to
|
||||
# the block devices it believes are valid.
|
||||
# 1 enables; 0 disables.
|
||||
sysfs_scan = 1
|
||||
|
||||
# By default, LVM2 will ignore devices used as components of
|
||||
# software RAID (md) devices by looking for md superblocks.
|
||||
# 1 enables; 0 disables.
|
||||
md_component_detection = 1
|
||||
|
||||
# By default, if a PV is placed directly upon an md device, LVM2
|
||||
# will align its data blocks with the md device's stripe-width.
|
||||
# 1 enables; 0 disables.
|
||||
md_chunk_alignment = 1
|
||||
|
||||
# Default alignment of the start of a data area in MB. If set to 0,
|
||||
# a value of 64KB will be used. Set to 1 for 1MiB, 2 for 2MiB, etc.
|
||||
# default_data_alignment = @DEFAULT_DATA_ALIGNMENT@
|
||||
|
||||
# By default, the start of a PV's data area will be a multiple of
|
||||
# the 'minimum_io_size' or 'optimal_io_size' exposed in sysfs.
|
||||
# - minimum_io_size - the smallest request the device can perform
|
||||
# w/o incurring a read-modify-write penalty (e.g. MD's chunk size)
|
||||
# - optimal_io_size - the device's preferred unit of receiving I/O
|
||||
# (e.g. MD's stripe width)
|
||||
# minimum_io_size is used if optimal_io_size is undefined (0).
|
||||
# If md_chunk_alignment is enabled, that detects the optimal_io_size.
|
||||
# This setting takes precedence over md_chunk_alignment.
|
||||
# 1 enables; 0 disables.
|
||||
data_alignment_detection = 1
|
||||
|
||||
# Alignment (in KB) of start of data area when creating a new PV.
|
||||
# md_chunk_alignment and data_alignment_detection are disabled if set.
|
||||
# Set to 0 for the default alignment (see: data_alignment_default)
|
||||
# or page size, if larger.
|
||||
data_alignment = 0
|
||||
|
||||
# By default, the start of the PV's aligned data area will be shifted by
|
||||
# the 'alignment_offset' exposed in sysfs. This offset is often 0 but
|
||||
# may be non-zero; e.g.: certain 4KB sector drives that compensate for
|
||||
# windows partitioning will have an alignment_offset of 3584 bytes
|
||||
# (sector 7 is the lowest aligned logical block, the 4KB sectors start
|
||||
# at LBA -1, and consequently sector 63 is aligned on a 4KB boundary).
|
||||
# But note that pvcreate --dataalignmentoffset will skip this detection.
|
||||
# 1 enables; 0 disables.
|
||||
data_alignment_offset_detection = 1
|
||||
|
||||
# If, while scanning the system for PVs, LVM2 encounters a device-mapper
|
||||
# device that has its I/O suspended, it waits for it to become accessible.
|
||||
# Set this to 1 to skip such devices. This should only be needed
|
||||
# in recovery situations.
|
||||
ignore_suspended_devices = 0
|
||||
|
||||
# During each LVM operation errors received from each device are counted.
|
||||
# If the counter of a particular device exceeds the limit set here, no
|
||||
# further I/O is sent to that device for the remainder of the respective
|
||||
# operation. Setting the parameter to 0 disables the counters altogether.
|
||||
disable_after_error_count = 0
|
||||
|
||||
# Allow use of pvcreate --uuid without requiring --restorefile.
|
||||
require_restorefile_with_uuid = 1
|
||||
}
|
||||
|
||||
# This section allows you to configure the way in which LVM selects
|
||||
# free space for its Logical Volumes.
|
||||
#allocation {
|
||||
# When searching for free space to extend an LV, the "cling"
|
||||
# allocation policy will choose space on the same PVs as the last
|
||||
# segment of the existing LV. If there is insufficient space and a
|
||||
# list of tags is defined here, it will check whether any of them are
|
||||
# attached to the PVs concerned and then seek to match those PV tags
|
||||
# between existing extents and new extents.
|
||||
# Use the special tag "@*" as a wildcard to match any PV tag.
|
||||
#
|
||||
# Example: LVs are mirrored between two sites within a single VG.
|
||||
# PVs are tagged with either @site1 or @site2 to indicate where
|
||||
# they are situated.
|
||||
#
|
||||
# cling_tag_list = [ "@site1", "@site2" ]
|
||||
# cling_tag_list = [ "@*" ]
|
||||
#}
|
||||
|
||||
# This section that allows you to configure the nature of the
|
||||
# information that LVM2 reports.
|
||||
log {
|
||||
|
||||
# Controls the messages sent to stdout or stderr.
|
||||
# There are three levels of verbosity, 3 being the most verbose.
|
||||
verbose = 0
|
||||
|
||||
# Should we send log messages through syslog?
|
||||
# 1 is yes; 0 is no.
|
||||
syslog = 1
|
||||
|
||||
# Should we log error and debug messages to a file?
|
||||
# By default there is no log file.
|
||||
#file = "/var/log/lvm2.log"
|
||||
|
||||
# Should we overwrite the log file each time the program is run?
|
||||
# By default we append.
|
||||
overwrite = 0
|
||||
|
||||
# What level of log messages should we send to the log file and/or syslog?
|
||||
# There are 6 syslog-like log levels currently in use - 2 to 7 inclusive.
|
||||
# 7 is the most verbose (LOG_DEBUG).
|
||||
level = 0
|
||||
|
||||
# Format of output messages
|
||||
# Whether or not (1 or 0) to indent messages according to their severity
|
||||
indent = 1
|
||||
|
||||
# Whether or not (1 or 0) to display the command name on each line output
|
||||
command_names = 0
|
||||
|
||||
# A prefix to use before the message text (but after the command name,
|
||||
# if selected). Default is two spaces, so you can see/grep the severity
|
||||
# of each message.
|
||||
prefix = " "
|
||||
|
||||
# To make the messages look similar to the original LVM tools use:
|
||||
# indent = 0
|
||||
# command_names = 1
|
||||
# prefix = " -- "
|
||||
|
||||
# Set this if you want log messages during activation.
|
||||
# Don't use this in low memory situations (can deadlock).
|
||||
# activation = 0
|
||||
}
|
||||
|
||||
# Configuration of metadata backups and archiving. In LVM2 when we
|
||||
# talk about a 'backup' we mean making a copy of the metadata for the
|
||||
# *current* system. The 'archive' contains old metadata configurations.
|
||||
# Backups are stored in a human readeable text format.
|
||||
backup {
|
||||
|
||||
# Should we maintain a backup of the current metadata configuration ?
|
||||
# Use 1 for Yes; 0 for No.
|
||||
# Think very hard before turning this off!
|
||||
backup = 1
|
||||
|
||||
# Where shall we keep it ?
|
||||
# Remember to back up this directory regularly!
|
||||
backup_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_BACKUP_SUBDIR@"
|
||||
|
||||
# Should we maintain an archive of old metadata configurations.
|
||||
# Use 1 for Yes; 0 for No.
|
||||
# On by default. Think very hard before turning this off.
|
||||
archive = 1
|
||||
|
||||
# Where should archived files go ?
|
||||
# Remember to back up this directory regularly!
|
||||
archive_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_ARCHIVE_SUBDIR@"
|
||||
|
||||
# What is the minimum number of archive files you wish to keep ?
|
||||
retain_min = 10
|
||||
|
||||
# What is the minimum time you wish to keep an archive file for ?
|
||||
retain_days = 30
|
||||
}
|
||||
|
||||
# Settings for the running LVM2 in shell (readline) mode.
|
||||
shell {
|
||||
|
||||
# Number of lines of history to store in ~/.lvm_history
|
||||
history_size = 100
|
||||
}
|
||||
|
||||
|
||||
# Miscellaneous global LVM2 settings
|
||||
global {
|
||||
|
||||
# The file creation mask for any files and directories created.
|
||||
# Interpreted as octal if the first digit is zero.
|
||||
umask = 077
|
||||
|
||||
# Allow other users to read the files
|
||||
#umask = 022
|
||||
|
||||
# Enabling test mode means that no changes to the on disk metadata
|
||||
# will be made. Equivalent to having the -t option on every
|
||||
# command. Defaults to off.
|
||||
test = 0
|
||||
|
||||
# Default value for --units argument
|
||||
units = "h"
|
||||
|
||||
# Since version 2.02.54, the tools distinguish between powers of
|
||||
# 1024 bytes (e.g. KiB, MiB, GiB) and powers of 1000 bytes (e.g.
|
||||
# KB, MB, GB).
|
||||
# If you have scripts that depend on the old behaviour, set this to 0
|
||||
# temporarily until you update them.
|
||||
si_unit_consistency = 1
|
||||
|
||||
# Whether or not to communicate with the kernel device-mapper.
|
||||
# Set to 0 if you want to use the tools to manipulate LVM metadata
|
||||
# without activating any logical volumes.
|
||||
# If the device-mapper kernel driver is not present in your kernel
|
||||
# setting this to 0 should suppress the error messages.
|
||||
activation = 1
|
||||
|
||||
# If we can't communicate with device-mapper, should we try running
|
||||
# the LVM1 tools?
|
||||
# This option only applies to 2.4 kernels and is provided to help you
|
||||
# switch between device-mapper kernels and LVM1 kernels.
|
||||
# The LVM1 tools need to be installed with .lvm1 suffices
|
||||
# e.g. vgscan.lvm1 and they will stop working after you start using
|
||||
# the new lvm2 on-disk metadata format.
|
||||
# The default value is set when the tools are built.
|
||||
# fallback_to_lvm1 = 0
|
||||
|
||||
# The default metadata format that commands should use - "lvm1" or "lvm2".
|
||||
# The command line override is -M1 or -M2.
|
||||
# Defaults to "lvm2".
|
||||
# format = "lvm2"
|
||||
|
||||
# Location of proc filesystem
|
||||
proc = "/proc"
|
||||
|
||||
# Type of locking to use. Defaults to local file-based locking (1).
|
||||
# Turn locking off by setting to 0 (dangerous: risks metadata corruption
|
||||
# if LVM2 commands get run concurrently).
|
||||
# Type 2 uses the external shared library locking_library.
|
||||
# Type 3 uses built-in clustered locking.
|
||||
# Type 4 uses read-only locking which forbids any operations that might
|
||||
# change metadata.
|
||||
locking_type = 1
|
||||
|
||||
# Set to 0 to fail when a lock request cannot be satisfied immediately.
|
||||
wait_for_locks = 1
|
||||
|
||||
# If using external locking (type 2) and initialisation fails,
|
||||
# with this set to 1 an attempt will be made to use the built-in
|
||||
# clustered locking.
|
||||
# If you are using a customised locking_library you should set this to 0.
|
||||
fallback_to_clustered_locking = 1
|
||||
|
||||
# If an attempt to initialise type 2 or type 3 locking failed, perhaps
|
||||
# because cluster components such as clvmd are not running, with this set
|
||||
# to 1 an attempt will be made to use local file-based locking (type 1).
|
||||
# If this succeeds, only commands against local volume groups will proceed.
|
||||
# Volume Groups marked as clustered will be ignored.
|
||||
fallback_to_local_locking = 1
|
||||
|
||||
# Local non-LV directory that holds file-based locks while commands are
|
||||
# in progress. A directory like /tmp that may get wiped on reboot is OK.
|
||||
locking_dir = "@DEFAULT_LOCK_DIR@"
|
||||
|
||||
# Whenever there are competing read-only and read-write access requests for
|
||||
# a volume group's metadata, instead of always granting the read-only
|
||||
# requests immediately, delay them to allow the read-write requests to be
|
||||
# serviced. Without this setting, write access may be stalled by a high
|
||||
# volume of read-only requests.
|
||||
# NB. This option only affects locking_type = 1 viz. local file-based
|
||||
# locking.
|
||||
prioritise_write_locks = 1
|
||||
|
||||
# Other entries can go here to allow you to load shared libraries
|
||||
# e.g. if support for LVM1 metadata was compiled as a shared library use
|
||||
# format_libraries = "liblvm2format1.so"
|
||||
# Full pathnames can be given.
|
||||
|
||||
# Search this directory first for shared libraries.
|
||||
# library_dir = "/lib"
|
||||
|
||||
# The external locking library to load if locking_type is set to 2.
|
||||
# locking_library = "liblvm2clusterlock.so"
|
||||
|
||||
# Treat any internal errors as fatal errors, aborting the process that
|
||||
# encountered the internal error. Please only enable for debugging.
|
||||
abort_on_internal_errors = 0
|
||||
|
||||
# If set to 1, no operations that change on-disk metadata will be permitted.
|
||||
# Additionally, read-only commands that encounter metadata in need of repair
|
||||
# will still be allowed to proceed exactly as if the repair had been
|
||||
# performed (except for the unchanged vg_seqno).
|
||||
# Inappropriate use could mess up your system, so seek advice first!
|
||||
metadata_read_only = 0
|
||||
}
|
||||
|
||||
activation {
|
||||
# Set to 0 to disable udev synchronisation (if compiled into the binaries).
|
||||
# Processes will not wait for notification from udev.
|
||||
# They will continue irrespective of any possible udev processing
|
||||
# in the background. You should only use this if udev is not running
|
||||
# or has rules that ignore the devices LVM2 creates.
|
||||
# The command line argument --nodevsync takes precedence over this setting.
|
||||
# If set to 1 when udev is not running, and there are LVM2 processes
|
||||
# waiting for udev, run 'dmsetup udevcomplete_all' manually to wake them up.
|
||||
udev_sync = 1
|
||||
|
||||
# Set to 0 to disable the udev rules installed by LVM2 (if built with
|
||||
# --enable-udev_rules). LVM2 will then manage the /dev nodes and symlinks
|
||||
# for active logical volumes directly itself.
|
||||
# N.B. Manual intervention may be required if this setting is changed
|
||||
# while any logical volumes are active.
|
||||
udev_rules = 1
|
||||
|
||||
# How to fill in missing stripes if activating an incomplete volume.
|
||||
# Using "error" will make inaccessible parts of the device return
|
||||
# I/O errors on access. You can instead use a device path, in which
|
||||
# case, that device will be used to in place of missing stripes.
|
||||
# But note that using anything other than "error" with mirrored
|
||||
# or snapshotted volumes is likely to result in data corruption.
|
||||
missing_stripe_filler = "error"
|
||||
|
||||
# How much stack (in KB) to reserve for use while devices suspended
|
||||
reserved_stack = 256
|
||||
|
||||
# How much memory (in KB) to reserve for use while devices suspended
|
||||
reserved_memory = 8192
|
||||
|
||||
# Nice value used while devices suspended
|
||||
process_priority = -18
|
||||
|
||||
# If volume_list is defined, each LV is only activated if there is a
|
||||
# match against the list.
|
||||
# "vgname" and "vgname/lvname" are matched exactly.
|
||||
# "@tag" matches any tag set in the LV or VG.
|
||||
# "@*" matches if any tag defined on the host is also set in the LV or VG
|
||||
#
|
||||
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
|
||||
# Size (in KB) of each copy operation when mirroring
|
||||
mirror_region_size = 512
|
||||
|
||||
# Setting to use when there is no readahead value stored in the metadata.
|
||||
#
|
||||
# "none" - Disable readahead.
|
||||
# "auto" - Use default value chosen by kernel.
|
||||
readahead = "auto"
|
||||
|
||||
# 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
|
||||
# how a device failure affecting a mirror is handled.
|
||||
# A mirror is composed of mirror images (copies) and a log.
|
||||
# A disk log ensures that a mirror does not need to be re-synced
|
||||
# (all copies made the same) every time a machine reboots or crashes.
|
||||
#
|
||||
# In the event of a failure, the specified policy will be used to determine
|
||||
# what happens. This applies to automatic repairs (when the mirror is being
|
||||
# monitored by dmeventd) and to manual lvconvert --repair when
|
||||
# --use-policies is given.
|
||||
#
|
||||
# "remove" - Simply remove the faulty device and run without it. If
|
||||
# the log device fails, the mirror would convert to using
|
||||
# an in-memory log. This means the mirror will not
|
||||
# remember its sync status across crashes/reboots and
|
||||
# the entire mirror will be re-synced. If a
|
||||
# mirror image fails, the mirror will convert to a
|
||||
# non-mirrored device if there is only one remaining good
|
||||
# copy.
|
||||
#
|
||||
# "allocate" - Remove the faulty device and try to allocate space on
|
||||
# a new device to be a replacement for the failed device.
|
||||
# Using this policy for the log is fast and maintains the
|
||||
# ability to remember sync state through crashes/reboots.
|
||||
# Using this policy for a mirror device is slow, as it
|
||||
# requires the mirror to resynchronize the devices, but it
|
||||
# will preserve the mirror characteristic of the device.
|
||||
# This policy acts like "remove" if no suitable device and
|
||||
# space can be allocated for the replacement.
|
||||
#
|
||||
# "allocate_anywhere" - Not yet implemented. Useful to place the log device
|
||||
# temporarily on same physical volume as one of the mirror
|
||||
# images. This policy is not recommended for mirror devices
|
||||
# since it would break the redundant nature of the mirror. This
|
||||
# policy acts like "remove" if no suitable device and space can
|
||||
# be allocated for the replacement.
|
||||
|
||||
mirror_log_fault_policy = "allocate"
|
||||
mirror_image_fault_policy = "remove"
|
||||
|
||||
# 'snapshot_autoextend_threshold' and 'snapshot_autoextend_percent' define
|
||||
# how to handle automatic snapshot extension. The former defines when the
|
||||
# snapshot should be extended: when its space usage exceeds this many
|
||||
# percent. The latter defines how much extra space should be allocated for
|
||||
# the snapshot, in percent of its current size.
|
||||
#
|
||||
# For example, if you set snapshot_autoextend_threshold to 70 and
|
||||
# snapshot_autoextend_percent to 20, whenever a snapshot exceeds 70% usage,
|
||||
# it will be extended by another 20%. For a 1G snapshot, using up 700M will
|
||||
# trigger a resize to 1.2G. When the usage exceeds 840M, the snapshot will
|
||||
# be extended to 1.44G, and so on.
|
||||
#
|
||||
# Setting snapshot_autoextend_threshold to 100 disables automatic
|
||||
# extensions. The minimum value is 50 (A setting below 50 will be treated
|
||||
# as 50).
|
||||
|
||||
snapshot_autoextend_threshold = 100
|
||||
snapshot_autoextend_percent = 20
|
||||
|
||||
# While activating devices, I/O to devices being (re)configured is
|
||||
# suspended, and as a precaution against deadlocks, LVM2 needs to pin
|
||||
# any memory it is using so it is not paged out. Groups of pages that
|
||||
# are known not to be accessed during activation need not be pinned
|
||||
# into memory. Each string listed in this setting is compared against
|
||||
# each line in /proc/self/maps, and the pages corresponding to any
|
||||
# lines that match are not pinned. On some systems locale-archive was
|
||||
# found to make up over 80% of the memory used by the process.
|
||||
# mlock_filter = [ "locale/locale-archive", "gconv/gconv-modules.cache" ]
|
||||
|
||||
# Set to 1 to revert to the default behaviour prior to version 2.02.62
|
||||
# which used mlockall() to pin the whole process's memory while activating
|
||||
# devices.
|
||||
use_mlockall = 0
|
||||
|
||||
# Monitoring is enabled by default when activating logical volumes.
|
||||
# Set to 0 to disable monitoring or use the --ignoremonitoring option.
|
||||
monitoring = 1
|
||||
|
||||
# When pvmove or lvconvert must wait for the kernel to finish
|
||||
# synchronising or merging data, they check and report progress
|
||||
# at intervals of this number of seconds. The default is 15 seconds.
|
||||
# If this is set to 0 and there is only one thing to wait for, there
|
||||
# are no progress reports, but the process is awoken immediately the
|
||||
# operation is complete.
|
||||
polling_interval = 15
|
||||
}
|
||||
|
||||
|
||||
####################
|
||||
# Advanced section #
|
||||
####################
|
||||
|
||||
# Metadata settings
|
||||
#
|
||||
# metadata {
|
||||
# Default number of copies of metadata to hold on each PV. 0, 1 or 2.
|
||||
# You might want to override it from the command line with 0
|
||||
# when running pvcreate on new PVs which are to be added to large VGs.
|
||||
|
||||
# pvmetadatacopies = 1
|
||||
|
||||
# Default number of copies of metadata to maintain for each VG.
|
||||
# If set to a non-zero value, LVM automatically chooses which of
|
||||
# the available metadata areas to use to achieve the requested
|
||||
# number of copies of the VG metadata. If you set a value larger
|
||||
# than the the total number of metadata areas available then
|
||||
# metadata is stored in them all.
|
||||
# The default value of 0 ("unmanaged") disables this automatic
|
||||
# management and allows you to control which metadata areas
|
||||
# are used at the individual PV level using 'pvchange
|
||||
# --metadataignore y/n'.
|
||||
|
||||
# vgmetadatacopies = 0
|
||||
|
||||
# Approximate default size of on-disk metadata areas in sectors.
|
||||
# You should increase this if you have large volume groups or
|
||||
# you want to retain a large on-disk history of your metadata changes.
|
||||
|
||||
# pvmetadatasize = 255
|
||||
|
||||
# List of directories holding live copies of text format metadata.
|
||||
# These directories must not be on logical volumes!
|
||||
# It's possible to use LVM2 with a couple of directories here,
|
||||
# preferably on different (non-LV) filesystems, and with no other
|
||||
# on-disk metadata (pvmetadatacopies = 0). Or this can be in
|
||||
# addition to on-disk metadata areas.
|
||||
# The feature was originally added to simplify testing and is not
|
||||
# supported under low memory situations - the machine could lock up.
|
||||
#
|
||||
# Never edit any files in these directories by hand unless you
|
||||
# you are absolutely sure you know what you are doing! Use
|
||||
# the supplied toolset to make changes (e.g. vgcfgrestore).
|
||||
|
||||
# dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
|
||||
#}
|
||||
|
||||
# Event daemon
|
||||
#
|
||||
dmeventd {
|
||||
# mirror_library is the library used when monitoring a mirror device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2mirror.so" attempts to recover from
|
||||
# failures. It removes failed devices from a volume group and
|
||||
# reconfigures a mirror as necessary. If no mirror library is
|
||||
# provided, mirrors are not monitored through dmeventd.
|
||||
|
||||
mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||
|
||||
# snapshot_library is the library used when monitoring a snapshot device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2snapshot.so" monitors the filling of
|
||||
# snapshots and emits a warning through syslog when the use of
|
||||
# the snapshot exceeds 80%. The warning is repeated when 85%, 90% and
|
||||
# 95% of the snapshot is filled.
|
||||
|
||||
snapshot_library = "libdevmapper-event-lvm2snapshot.so"
|
||||
|
||||
# Full path of the dmeventd binary.
|
||||
#
|
||||
# executable = "@DMEVENTD_PATH@"
|
||||
}
|
||||
49
doc/example_cmdlib.c
Normal file
49
doc/example_cmdlib.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* All output gets passed to this function line-by-line */
|
||||
void test_log_fn(int level, const char *file, int line,
|
||||
int dm_errno, const char *format)
|
||||
{
|
||||
/* Extract and process output here rather than printing it */
|
||||
|
||||
if (level != 4)
|
||||
return;
|
||||
|
||||
printf("%s\n", format);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *handle;
|
||||
int r;
|
||||
|
||||
lvm2_log_fn(test_log_fn);
|
||||
|
||||
handle = lvm2_init();
|
||||
|
||||
lvm2_log_level(handle, 1);
|
||||
r = lvm2_run(handle, "vgs --noheadings vg1");
|
||||
|
||||
/* More commands here */
|
||||
|
||||
lvm2_exit(handle);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
221
doc/lvm_fault_handling.txt
Normal file
221
doc/lvm_fault_handling.txt
Normal file
@@ -0,0 +1,221 @@
|
||||
LVM device fault handling
|
||||
=========================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
This document is to serve as the definitive source for information
|
||||
regarding the policies and procedures surrounding device failures
|
||||
in LVM. It codifies LVM's responses to device failures as well as
|
||||
the responsibilities of administrators.
|
||||
|
||||
Device failures can be permanent or transient. A permanent failure
|
||||
is one where a device becomes inaccessible and will never be
|
||||
revived. A transient failure is a failure that can be recovered
|
||||
from (e.g. a power failure, intermittent network outage, block
|
||||
relocation, etc). The policies for handling both types of failures
|
||||
is described herein.
|
||||
|
||||
Available Operations During a Device Failure
|
||||
--------------------------------------------
|
||||
When there is a device failure, LVM behaves somewhat differently because
|
||||
only a subset of the available devices will be found for the particular
|
||||
volume group. The number of operations available to the administrator
|
||||
is diminished. It is not possible to create new logical volumes while
|
||||
PVs cannot be accessed, for example. Operations that create, convert, or
|
||||
resize logical volumes are disallowed, such as:
|
||||
- lvcreate
|
||||
- lvresize
|
||||
- lvreduce
|
||||
- lvextend
|
||||
- lvconvert (unless '--repair' is used)
|
||||
Operations that activate, deactivate, remove, report, or repair logical
|
||||
volumes are allowed, such as:
|
||||
- lvremove
|
||||
- vgremove (will remove all LVs, but not the VG until consistent)
|
||||
- pvs
|
||||
- vgs
|
||||
- lvs
|
||||
- lvchange -a [yn]
|
||||
- vgchange -a [yn]
|
||||
Operations specific to the handling of failed devices are allowed and
|
||||
are as follows:
|
||||
|
||||
- 'vgreduce --removemissing <VG>': This action is designed to remove
|
||||
the reference of a failed device from the LVM metadata stored on the
|
||||
remaining devices. If there are (portions of) logical volumes on the
|
||||
failed devices, the ability of the operation to proceed will depend
|
||||
on the type of logical volumes found. If an image (i.e leg or side)
|
||||
of a mirror is located on the device, that image/leg of the mirror
|
||||
is eliminated along with the failed device. The result of such a
|
||||
mirror reduction could be a no-longer-redundant linear device. If
|
||||
a linear, stripe, or snapshot device is located on the failed device
|
||||
the command will not proceed without a '--force' option. The result
|
||||
of using the '--force' option is the entire removal and complete
|
||||
loss of the non-redundant logical volume. Once this operation is
|
||||
complete, the volume group will again have a complete and consistent
|
||||
view of the devices it contains. Thus, all operations will be
|
||||
permitted - including creation, conversion, and resizing operations.
|
||||
|
||||
- 'lvconvert --repair <VG/LV>': This action is designed specifically
|
||||
to operate on mirrored logical volumes. It is used on logical volumes
|
||||
individually and does not remove the faulty device from the volume
|
||||
group. If, for example, a failed device happened to contain the
|
||||
images of four distinct mirrors, it would be necessary to run
|
||||
'lvconvert --repair' on each of them. The ultimate result is to leave
|
||||
the faulty device in the volume group, but have no logical volumes
|
||||
referencing it. In addition to removing mirror images that reside
|
||||
on failed devices, 'lvconvert --repair' can also replace the failed
|
||||
device if there are spare devices available in the volume group. The
|
||||
user is prompted whether to simply remove the failed portions of the
|
||||
mirror or to also allocate a replacement, if run from the command-line.
|
||||
Optionally, the '--use-policies' flag can be specified which will
|
||||
cause the operation not to prompt the user, but instead respect
|
||||
the policies outlined in the LVM configuration file - usually,
|
||||
/etc/lvm/lvm.conf. Once this operation is complete, mirrored logical
|
||||
volumes will be consistent and I/O will be allowed to continue.
|
||||
However, the volume group will still be inconsistent - due to the
|
||||
refernced-but-missing device/PV - and operations will still be
|
||||
restricted to the aformentioned actions until either the device is
|
||||
restored or 'vgreduce --removemissing' is run.
|
||||
|
||||
Device Revival (transient failures):
|
||||
------------------------------------
|
||||
During a device failure, the above section describes what limitations
|
||||
a user can expect. However, if the device returns after a period of
|
||||
time, what to expect will depend on what has happened during the time
|
||||
period when the device was failed. If no automated actions (described
|
||||
below) or user actions were necessary or performed, then no change in
|
||||
operations or logical volume layout will occur. However, if an
|
||||
automated action or one of the aforementioned repair commands was
|
||||
manually run, the returning device will be perceived as having stale
|
||||
LVM metadata. In this case, the user can expect to see a warning
|
||||
concerning inconsistent metadata. The metadata on the returning
|
||||
device will be automatically replaced with the latest copy of the
|
||||
LVM metadata - restoring consistency. Note, while most LVM commands
|
||||
will automatically update the metadata on a restored devices, the
|
||||
following possible exceptions exist:
|
||||
- pvs (when it does not read/update VG metadata)
|
||||
|
||||
Automated Target Response to Failures:
|
||||
--------------------------------------
|
||||
The only LVM target type (i.e. "personality") that has an automated
|
||||
response to failures is a mirrored logical volume. The other target
|
||||
types (linear, stripe, snapshot, etc) will simply propagate the failure.
|
||||
[A snapshot becomes invalid if its underlying device fails, but the
|
||||
origin will remain valid - presuming the origin device has not failed.]
|
||||
There are three types of errors that a mirror can suffer - read, write,
|
||||
and resynchronization errors. Each is described in depth below.
|
||||
|
||||
Mirror read failures:
|
||||
If a mirror is 'in-sync' (i.e. all images have been initialized and
|
||||
are identical), a read failure will only produce a warning. Data is
|
||||
simply pulled from one of the other images and the fault is recorded.
|
||||
Sometimes - like in the case of bad block relocation - read errors can
|
||||
be recovered from by the storage hardware. Therefore, it is up to the
|
||||
user to decide whether to reconfigure the mirror and remove the device
|
||||
that caused the error. Managing the composition of a mirror is done with
|
||||
'lvconvert' and removing a device from a volume group can be done with
|
||||
'vgreduce'.
|
||||
|
||||
If a mirror is not 'in-sync', a read failure will produce an I/O error.
|
||||
This error will propagate all the way up to the applications above the
|
||||
logical volume (e.g. the file system). No automatic intervention will
|
||||
take place in this case either. It is up to the user to decide what
|
||||
can be done/salvaged in this senario. If the user is confident that the
|
||||
images of the mirror are the same (or they are willing to simply attempt
|
||||
to retreive whatever data they can), 'lvconvert' can be used to eliminate
|
||||
the failed image and proceed.
|
||||
|
||||
Mirror resynchronization errors:
|
||||
A resynchronization error is one that occurs when trying to initialize
|
||||
all mirror images to be the same. It can happen due to a failure to
|
||||
read the primary image (the image considered to have the 'good' data), or
|
||||
due to a failure to write the secondary images. This type of failure
|
||||
only produces a warning, and it is up to the user to take action in this
|
||||
case. If the error is transient, the user can simply reactivate the
|
||||
mirrored logical volume to make another attempt at resynchronization.
|
||||
If attempts to finish resynchronization fail, 'lvconvert' can be used to
|
||||
remove the faulty device from the mirror.
|
||||
|
||||
TODO...
|
||||
Some sort of response to this type of error could be automated.
|
||||
Since this document is the definitive source for how to handle device
|
||||
failures, the process should be defined here. If the process is defined
|
||||
but not implemented, it should be noted as such. One idea might be to
|
||||
make a single attempt to suspend/resume the mirror in an attempt to
|
||||
redo the sync operation that failed. On the other hand, if there is
|
||||
a permanent failure, it may simply be best to wait for the user or the
|
||||
automated response that is sure to follow from a write failure.
|
||||
...TODO
|
||||
|
||||
Mirror write failures:
|
||||
When a write error occurs on a mirror constituent device, an attempt
|
||||
to handle the failure is automatically made. This is done by calling
|
||||
'lvconvert --repair --use-policies'. The policies implied by this
|
||||
command are set in the LVM configuration file. They are:
|
||||
- mirror_log_fault_policy: This defines what action should be taken
|
||||
if the device containing the log fails. The available options are
|
||||
"remove" and "allocate". Either of these options will cause the
|
||||
faulty log device to be removed from the mirror. The "allocate"
|
||||
policy will attempt the further action of trying to replace the
|
||||
failed disk log by using space that might be available in the
|
||||
volume group. If the allocation fails (or the "remove" policy
|
||||
is specified), the mirror log will be maintained in memory. Should
|
||||
the machine be rebooted or the logical volume deactivated, a
|
||||
complete resynchronization of the mirror will be necessary upon
|
||||
the follow activation - such is the nature of a mirror with a 'core'
|
||||
log. The default policy for handling log failures is "allocate".
|
||||
The service disruption incurred by replacing the failed log is
|
||||
negligible, while the benefits of having persistent log is
|
||||
pronounced.
|
||||
- mirror_image_fault_policy: This defines what action should be taken
|
||||
if a device containing an image fails. Again, the available options
|
||||
are "remove" and "allocate". Both of these options will cause the
|
||||
faulty image device to be removed - adjusting the logical volume
|
||||
accordingly. For example, if one image of a 2-way mirror fails, the
|
||||
mirror will be converted to a linear device. If one image of a
|
||||
3-way mirror fails, the mirror will be converted to a 2-way mirror.
|
||||
The "allocate" policy takes the further action of trying to replace
|
||||
the failed image using space that is available in the volume group.
|
||||
Replacing a failed mirror image will incure the cost of
|
||||
resynchronizing - degrading the performance of the mirror. The
|
||||
default policy for handling an image failure is "remove". This
|
||||
allows the mirror to still function, but gives the administrator the
|
||||
choice of when to incure the extra performance costs of replacing
|
||||
the failed image.
|
||||
|
||||
TODO...
|
||||
The appropriate time to take permanent corrective action on a mirror
|
||||
should be driven by policy. There should be a directive that takes
|
||||
a time or percentage argument. Something like the following:
|
||||
- mirror_fault_policy_WHEN = "10sec"/"10%"
|
||||
A time value would signal the amount of time to wait for transient
|
||||
failures to resolve themselves. The percentage value would signal the
|
||||
amount a mirror could become out-of-sync before the faulty device is
|
||||
removed.
|
||||
|
||||
A mirror cannot be used unless /some/ corrective action is taken,
|
||||
however. One option is to replace the failed mirror image with an
|
||||
error target, forgo the use of 'handle_errors', and simply let the
|
||||
out-of-sync regions accumulate and be tracked by the log. Mirrors
|
||||
that have more than 2 images would have to "stack" to perform the
|
||||
tracking, as each failed image would have to be associated with a
|
||||
log. If the failure is transient, the device would replace the
|
||||
error target that was holding its spot and the log that was tracking
|
||||
the deltas would be used to quickly restore the portions that changed.
|
||||
|
||||
One unresolved issue with the above scheme is how to know which
|
||||
regions of the mirror are out-of-sync when a problem occurs. When
|
||||
a write failure occurs in the kernel, the log will contain those
|
||||
regions that are not in-sync. If the log is a disk log, that log
|
||||
could continue to be used to track differences. However, if the
|
||||
log was a core log - or if the log device failed at the same time
|
||||
as an image device - there would be no way to determine which
|
||||
regions are out-of-sync to begin with as we start to track the
|
||||
deltas for the failed image. I don't have a solution for this
|
||||
problem other than to only be able to handle errors in this way
|
||||
if conditions are right. These issues will have to be ironed out
|
||||
before proceeding. This could be another case, where it is better
|
||||
to handle failures in the kernel by allowing the kernel to store
|
||||
updates in various metadata areas.
|
||||
...TODO
|
||||
52
doc/pvmove_outline.txt
Normal file
52
doc/pvmove_outline.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
Let's say we have an LV, made up of three segments of different PV's,
|
||||
I've also added in the device major:minor as this will be useful
|
||||
later:
|
||||
|
||||
+-----------------------------+
|
||||
| PV1 | PV2 | PV3 | 254:3
|
||||
+----------+---------+--------+
|
||||
|
||||
|
||||
Now our hero decides to PV move PV2 to PV4:
|
||||
|
||||
1. Suspend our LV (254:3), this starts queueing all io, and flushes
|
||||
all pending io. Once the suspend has completed we are free to change
|
||||
the mapping table.
|
||||
|
||||
2. Set up *another* (254:4) device with the mapping table of our LV.
|
||||
|
||||
3. Load a new mapping table into (254:3) that has identity targets for
|
||||
parts that aren't moving, and a mirror target for parts that are.
|
||||
|
||||
4. Unsuspend (254:3)
|
||||
|
||||
So now we have:
|
||||
destination of copy
|
||||
+--------------------->--------------+
|
||||
| |
|
||||
+-----------------------------+ + -----------+
|
||||
| Identity | mirror | Ident. | 254:3 | PV4 |
|
||||
+----------+---------+--------+ +------------+
|
||||
| | |
|
||||
\/ \/ \/
|
||||
+-----------------------------+
|
||||
| PV1 | PV2 | PV3 | 254:4
|
||||
+----------+---------+--------+
|
||||
|
||||
Any writes to segment2 of the LV get intercepted by the mirror target
|
||||
who checks that that chunk has been copied to the new destination, if
|
||||
it hasn't it queues the initial copy and defers the current io until
|
||||
it has finished. Then the current io is written to *both* PV2 and the
|
||||
PV4.
|
||||
|
||||
5. When the copying has completed 254:3 is suspended/pending flushed.
|
||||
|
||||
6. 254:4 is taken down
|
||||
|
||||
7. metadata is updated on disk
|
||||
|
||||
8. 254:3 has new mapping table loaded:
|
||||
|
||||
+-----------------------------+
|
||||
| PV1 | PV4 | PV3 | 254:3
|
||||
+----------+---------+--------+
|
||||
165
doc/tagging.txt
Normal file
165
doc/tagging.txt
Normal file
@@ -0,0 +1,165 @@
|
||||
Tagging aims
|
||||
============
|
||||
1) Ability to attach an unordered list of tags to LVM metadata objects.
|
||||
2) Ability to add or remove tags easily.
|
||||
3) Ability to select LVM objects for processing according to presence/absence
|
||||
of specific tags.
|
||||
4) Ability to control through the config file which VGs/LVs are activated
|
||||
on different machines using names or tags.
|
||||
5) Ability to overlay settings from different config files e.g. override
|
||||
some settings in a global config file locally.
|
||||
|
||||
Clarifications
|
||||
==============
|
||||
1) Tag character set: A-Za-z0-9_+.-
|
||||
Can't start with hyphen & max length is 128 (NAME_LEN).
|
||||
2) LVM object types that can be tagged:
|
||||
VG, LV, LV segment
|
||||
PV - tags are stored in VG metadata so disappear when PV becomes orphaned
|
||||
Snapshots can't be tagged, but their origin may be.
|
||||
3) A tag can be used in place of any command line LVM object reference that
|
||||
accepts (a) a list of objects; or (b) a single object as long as the
|
||||
tag expands to a single object. This is not supported everywhere yet.
|
||||
Duplicate arguments in a list after argument expansion may get removed
|
||||
retaining the first copy of each argument.
|
||||
4) Wherever there may be ambiguity of argument type, a tag must be prefixed
|
||||
by '@'; elsewhere an '@' prefix is optional.
|
||||
5) LVM1 objects cannot be tagged, as the disk format doesn't support it.
|
||||
6) Tags can be added or removed with --addtag or --deltag.
|
||||
|
||||
Config file Extensions
|
||||
======================
|
||||
To define host tags in config file:
|
||||
|
||||
tags {
|
||||
# Set a tag with the hostname
|
||||
hosttags = 1
|
||||
|
||||
tag1 { }
|
||||
|
||||
tag2 {
|
||||
# If no exact match, tag is not set.
|
||||
host_list = [ "hostname", "dbase" ]
|
||||
}
|
||||
}
|
||||
|
||||
Activation config file example
|
||||
==============================
|
||||
activation {
|
||||
volume_list = [ "vg1/lvol0", "@database" ]
|
||||
}
|
||||
|
||||
Matches against vgname, vgname/lvname or @tag set in *metadata*.
|
||||
@* matches exactly against *any* tag set on the host.
|
||||
The VG or LV only gets activated if a metadata tag matches.
|
||||
The default if there is no match is not to activate.
|
||||
If volume_list is not present and any tags are defined on the host
|
||||
then it only activates if a host tag matches a metadata tag.
|
||||
If volume_list is not present and no tags are defined on the host
|
||||
then it does activate.
|
||||
|
||||
Multiple config files
|
||||
=====================
|
||||
(a) lvm.conf
|
||||
(b) lvm_<host_tag>.conf
|
||||
|
||||
At startup, load lvm.conf.
|
||||
Process tag settings.
|
||||
If any host tags were defined, load lvm_tag.conf for each tag, if present.
|
||||
|
||||
When searching for a specific config file entry, search order is (b)
|
||||
then (a), stopping at the first match.
|
||||
Within (b) use reverse order tags got set, so file for last tag set is
|
||||
searched first.
|
||||
New tags set in (b) *do* trigger additional config file loads.
|
||||
|
||||
Usage Examples
|
||||
==============
|
||||
1) Simple activation control via metadata with static config files
|
||||
|
||||
lvm.conf: (Identical on every machine - global settings)
|
||||
tags {
|
||||
hostname_tags = 1
|
||||
}
|
||||
|
||||
From any machine in the cluster, add db1 to the list of machines that
|
||||
activate vg1/lvol2:
|
||||
|
||||
lvchange --tag @db1 vg1/lvol2
|
||||
(followed by lvchange -ay to actually activate it)
|
||||
|
||||
|
||||
2) Multiple hosts.
|
||||
|
||||
Activate vg1 only on the database hosts, db1 and db2.
|
||||
Activate vg2 only on the fileserver host fs1.
|
||||
Activate nothing initially on the fileserver backup host fsb1, but be
|
||||
prepared for it to take over from fs1.
|
||||
|
||||
Option (i) - centralised admin, static configuration replicated between hosts
|
||||
# Add @database tag to vg1's metadata
|
||||
vgchange --tag @database vg1
|
||||
|
||||
# Add @fileserver tag to vg2's metadata
|
||||
vgchange --tag @fileserver vg2
|
||||
|
||||
lvm.conf: (Identical on every machine)
|
||||
tags {
|
||||
database {
|
||||
host_list = [ "db1", "db2" ]
|
||||
}
|
||||
fileserver {
|
||||
host_list = [ "fs1" ]
|
||||
}
|
||||
fileserverbackup {
|
||||
host_list = [ "fsb1" ]
|
||||
}
|
||||
}
|
||||
|
||||
activation {
|
||||
# Only activate if host has a tag that matches a metadata tag
|
||||
volume_list = [ "@*" ]
|
||||
}
|
||||
|
||||
In the event of the fileserver host going down, vg2 can be brought up
|
||||
on fsb1 by running *on any node* 'vgchange --tag @fileserverbackup vg2'
|
||||
followed by 'vgchange -ay vg2'
|
||||
|
||||
|
||||
Option (ii) - localised admin & configuation
|
||||
(i.e. each host holds *locally* which classes of volumes to activate)
|
||||
# Add @database tag to vg1's metadata
|
||||
vgchange --tag @database vg1
|
||||
|
||||
# Add @fileserver tag to vg2's metadata
|
||||
vgchange --tag @fileserver vg2
|
||||
|
||||
lvm.conf: (Identical on every machine - global settings)
|
||||
tags {
|
||||
hosttags = 1
|
||||
}
|
||||
|
||||
lvm_db1.conf: (only needs to be on db1 - could be symlink to lvm_db.conf)
|
||||
activation {
|
||||
volume_list = [ "@database" ]
|
||||
}
|
||||
|
||||
lvm_db2.conf: (only needs to be on db2 - could be symlink to lvm_db.conf)
|
||||
activation {
|
||||
volume_list = [ "@database" ]
|
||||
}
|
||||
|
||||
lvm_fs1.conf: (only needs to be on fs1 - could be symlink to lvm_fs.conf)
|
||||
activation {
|
||||
volume_list = [ "@fileserver" ]
|
||||
}
|
||||
|
||||
If fileserver goes down, to bring a spare machine fsb1 in as fileserver,
|
||||
create lvm_fsb1.conf on fsb1 (or symlink to lvm_fs.conf):
|
||||
|
||||
activation {
|
||||
volume_list = [ "@fileserver" ]
|
||||
}
|
||||
|
||||
and run 'vgchange -ay vg2' or 'vgchange -ay @fileserver'
|
||||
|
||||
41
doc/testing.txt
Normal file
41
doc/testing.txt
Normal file
@@ -0,0 +1,41 @@
|
||||
Here's how I test new LVM2 builds without interfering with the stable
|
||||
LVM2 that is running the LV's on my development box.
|
||||
|
||||
1) Create a set of loopback devices.
|
||||
|
||||
2) Create a new directory to contain the LVM2 configuration files for
|
||||
this setup. (I use /etc/lvm_loops)
|
||||
|
||||
3) Write a suitable lvm.conf file, this goes in the directory you just
|
||||
created. eg, my /etc/lvm_loops/lvm.conf looks like:
|
||||
|
||||
log {
|
||||
file="/tmp/lvm2_loop.log"
|
||||
level=9
|
||||
verbose=0
|
||||
overwrite=1
|
||||
}
|
||||
|
||||
devices {
|
||||
scan = "/dev"
|
||||
filter = ["a/loop/", "r/.*/"]
|
||||
}
|
||||
|
||||
|
||||
The important thing to note is the devices section which makes sure
|
||||
that only the loopback devices are considered for LVM2 operations.
|
||||
|
||||
4) When you want to use this test setup just set the environment
|
||||
variable LVM_SYSTEM_DIR to point to your config directory
|
||||
(/etc/lvm_loops in my case).
|
||||
|
||||
5) It's a good idea to do a vgscan to initialise the filters:
|
||||
|
||||
export LVM_SYSTEM_DIR=/etc/lvm_loops
|
||||
./lvm vgscan
|
||||
|
||||
where ./lvm is the new build of LVM2 that I'm trying out.
|
||||
|
||||
7) Test away. Make sure that you are explicit about which lvm
|
||||
executable you want to execute (eg, ./lvm if you are in
|
||||
LVM2/tools).
|
||||
@@ -1 +0,0 @@
|
||||
The driver directory
|
||||
67
include/.symlinks.in
Normal file
67
include/.symlinks.in
Normal file
@@ -0,0 +1,67 @@
|
||||
@top_srcdir@/daemons/clvmd/clvm.h
|
||||
@top_srcdir@/daemons/dmeventd/libdevmapper-event.h
|
||||
@top_srcdir@/liblvm/lvm2app.h
|
||||
@top_srcdir@/lib/activate/activate.h
|
||||
@top_srcdir@/lib/activate/targets.h
|
||||
@top_srcdir@/lib/cache/lvmcache.h
|
||||
@top_srcdir@/lib/commands/errors.h
|
||||
@top_srcdir@/lib/commands/toolcontext.h
|
||||
@top_srcdir@/lib/config/config.h
|
||||
@top_srcdir@/lib/config/defaults.h
|
||||
@top_srcdir@/lib/datastruct/btree.h
|
||||
@top_srcdir@/lib/datastruct/lvm-types.h
|
||||
@top_srcdir@/lib/datastruct/str_list.h
|
||||
@top_srcdir@/lib/device/dev-cache.h
|
||||
@top_srcdir@/lib/device/device.h
|
||||
@top_srcdir@/lib/display/display.h
|
||||
@top_srcdir@/lib/filters/filter-composite.h
|
||||
@top_srcdir@/lib/filters/filter-md.h
|
||||
@top_srcdir@/lib/filters/filter-persistent.h
|
||||
@top_srcdir@/lib/filters/filter-regex.h
|
||||
@top_srcdir@/lib/filters/filter-sysfs.h
|
||||
@top_srcdir@/lib/filters/filter.h
|
||||
@top_srcdir@/lib/format1/format1.h
|
||||
@top_srcdir@/lib/format_pool/format_pool.h
|
||||
@top_srcdir@/lib/format_text/archiver.h
|
||||
@top_srcdir@/lib/format_text/format-text.h
|
||||
@top_srcdir@/lib/format_text/text_export.h
|
||||
@top_srcdir@/lib/format_text/text_import.h
|
||||
@top_srcdir@/lib/label/label.h
|
||||
@top_srcdir@/lib/locking/locking.h
|
||||
@top_srcdir@/lib/log/log.h
|
||||
@top_srcdir@/lib/log/lvm-logging.h
|
||||
@top_srcdir@/lib/metadata/lv.h
|
||||
@top_srcdir@/lib/metadata/lv_alloc.h
|
||||
@top_srcdir@/lib/metadata/metadata.h
|
||||
@top_srcdir@/lib/metadata/metadata-exported.h
|
||||
@top_srcdir@/lib/metadata/pv.h
|
||||
@top_srcdir@/lib/metadata/pv_alloc.h
|
||||
@top_srcdir@/lib/metadata/segtype.h
|
||||
@top_srcdir@/lib/metadata/vg.h
|
||||
@top_srcdir@/lib/mm/memlock.h
|
||||
@top_srcdir@/lib/mm/xlate.h
|
||||
@top_builddir@/lib/misc/configure.h
|
||||
@top_srcdir@/lib/misc/crc.h
|
||||
@top_srcdir@/lib/misc/intl.h
|
||||
@top_srcdir@/lib/misc/util.h
|
||||
@top_srcdir@/lib/misc/last-path-component.h
|
||||
@top_srcdir@/lib/misc/lib.h
|
||||
@top_srcdir@/lib/misc/lvm-exec.h
|
||||
@top_srcdir@/lib/misc/lvm-file.h
|
||||
@top_srcdir@/lib/misc/lvm-globals.h
|
||||
@top_srcdir@/lib/misc/lvm-string.h
|
||||
@top_builddir@/lib/misc/lvm-version.h
|
||||
@top_srcdir@/lib/misc/lvm-wrappers.h
|
||||
@top_srcdir@/lib/misc/lvm-percent.h
|
||||
@top_srcdir@/lib/misc/sharedlib.h
|
||||
@top_srcdir@/lib/report/properties.h
|
||||
@top_srcdir@/lib/report/report.h
|
||||
@top_srcdir@/lib/uuid/uuid.h
|
||||
@top_srcdir@/libdm/libdevmapper.h
|
||||
@top_srcdir@/libdm/misc/dm-ioctl.h
|
||||
@top_srcdir@/libdm/misc/dm-logging.h
|
||||
@top_srcdir@/libdm/misc/dm-log-userspace.h
|
||||
@top_srcdir@/libdm/misc/dmlib.h
|
||||
@top_srcdir@/libdm/misc/kdev_t.h
|
||||
@top_srcdir@/po/pogen.h
|
||||
@top_srcdir@/tools/lvm2cmd.h
|
||||
35
include/Makefile.in
Normal file
35
include/Makefile.in
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
all: .symlinks_created
|
||||
|
||||
.symlinks_created: .symlinks
|
||||
find . -maxdepth 1 -type l -exec $(RM) \{\} \;
|
||||
for i in `cat $<`; do $(LN_S) $$i ; done
|
||||
touch $@
|
||||
|
||||
pofile: all
|
||||
|
||||
device-mapper: all
|
||||
|
||||
cflow: all
|
||||
|
||||
DISTCLEAN_TARGETS += $(shell find . -maxdepth 1 -type l)
|
||||
DISTCLEAN_TARGETS += .include_symlinks .symlinks_created .symlinks
|
||||
184
lib/Makefile.in
Normal file
184
lib/Makefile.in
Normal file
@@ -0,0 +1,184 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
ifeq ("@LVM1@", "shared")
|
||||
SUBDIRS = format1
|
||||
endif
|
||||
|
||||
ifeq ("@POOL@", "shared")
|
||||
SUBDIRS += format_pool
|
||||
endif
|
||||
|
||||
ifeq ("@SNAPSHOTS@", "shared")
|
||||
SUBDIRS += snapshot
|
||||
endif
|
||||
|
||||
ifeq ("@MIRRORS@", "shared")
|
||||
SUBDIRS += mirror
|
||||
endif
|
||||
|
||||
ifeq ("@REPLICATORS@", "shared")
|
||||
SUBDIRS += replicator
|
||||
endif
|
||||
|
||||
SOURCES =\
|
||||
activate/activate.c \
|
||||
cache/lvmcache.c \
|
||||
commands/toolcontext.c \
|
||||
config/config.c \
|
||||
datastruct/btree.c \
|
||||
datastruct/str_list.c \
|
||||
device/dev-cache.c \
|
||||
device/dev-io.c \
|
||||
device/dev-md.c \
|
||||
device/dev-swap.c \
|
||||
device/dev-luks.c \
|
||||
device/device.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
unknown/unknown.c \
|
||||
filters/filter-composite.c \
|
||||
filters/filter-persistent.c \
|
||||
filters/filter-regex.c \
|
||||
filters/filter-sysfs.c \
|
||||
filters/filter-md.c \
|
||||
filters/filter.c \
|
||||
format_text/archive.c \
|
||||
format_text/archiver.c \
|
||||
format_text/export.c \
|
||||
format_text/flags.c \
|
||||
format_text/format-text.c \
|
||||
format_text/import.c \
|
||||
format_text/import_vsn1.c \
|
||||
format_text/tags.c \
|
||||
format_text/text_label.c \
|
||||
freeseg/freeseg.c \
|
||||
label/label.c \
|
||||
locking/file_locking.c \
|
||||
locking/locking.c \
|
||||
locking/no_locking.c \
|
||||
log/log.c \
|
||||
metadata/lv.c \
|
||||
metadata/lv_manip.c \
|
||||
metadata/merge.c \
|
||||
metadata/metadata.c \
|
||||
metadata/mirror.c \
|
||||
metadata/pv.c \
|
||||
metadata/pv_manip.c \
|
||||
metadata/pv_map.c \
|
||||
metadata/replicator_manip.c \
|
||||
metadata/segtype.c \
|
||||
metadata/snapshot_manip.c \
|
||||
metadata/vg.c \
|
||||
misc/crc.c \
|
||||
misc/lvm-exec.c \
|
||||
misc/lvm-file.c \
|
||||
misc/lvm-globals.c \
|
||||
misc/lvm-string.c \
|
||||
misc/lvm-wrappers.c \
|
||||
misc/lvm-percent.c \
|
||||
misc/util.c \
|
||||
mm/memlock.c \
|
||||
report/properties.c \
|
||||
report/report.c \
|
||||
striped/striped.c \
|
||||
uuid/uuid.c \
|
||||
zero/zero.c
|
||||
|
||||
ifeq ("@HAVE_REALTIME@", "yes")
|
||||
SOURCES +=\
|
||||
misc/timestamp.c
|
||||
endif
|
||||
|
||||
ifeq ("@LVM1@", "internal")
|
||||
SOURCES +=\
|
||||
format1/disk-rep.c \
|
||||
format1/format1.c \
|
||||
format1/import-export.c \
|
||||
format1/import-extents.c \
|
||||
format1/layout.c \
|
||||
format1/lvm1-label.c \
|
||||
format1/vg_number.c
|
||||
endif
|
||||
|
||||
ifeq ("@POOL@", "internal")
|
||||
SOURCES +=\
|
||||
format_pool/disk_rep.c \
|
||||
format_pool/format_pool.c \
|
||||
format_pool/import_export.c \
|
||||
format_pool/pool_label.c
|
||||
endif
|
||||
|
||||
ifeq ("@CLUSTER@", "internal")
|
||||
SOURCES += locking/cluster_locking.c
|
||||
endif
|
||||
|
||||
ifeq ("@CLUSTER@", "shared")
|
||||
SUBDIRS += locking
|
||||
endif
|
||||
|
||||
ifeq ("@SNAPSHOTS@", "internal")
|
||||
SOURCES += snapshot/snapshot.c
|
||||
endif
|
||||
|
||||
ifeq ("@MIRRORS@", "internal")
|
||||
SOURCES += mirror/mirrored.c
|
||||
endif
|
||||
|
||||
ifeq ("@REPLICATORS@", "internal")
|
||||
SOURCES += replicator/replicator.c
|
||||
endif
|
||||
|
||||
ifeq ("@DEVMAPPER@", "yes")
|
||||
SOURCES +=\
|
||||
activate/dev_manager.c \
|
||||
activate/fs.c
|
||||
endif
|
||||
|
||||
ifeq ("@HAVE_LIBDL@", "yes")
|
||||
SOURCES +=\
|
||||
locking/external_locking.c \
|
||||
misc/sharedlib.c
|
||||
endif
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd
|
||||
LIBS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
LIB_NAME = liblvm-internal
|
||||
LIB_STATIC = $(LIB_NAME).a
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS =\
|
||||
format1 \
|
||||
format_pool \
|
||||
snapshot \
|
||||
mirror \
|
||||
replicator \
|
||||
locking
|
||||
endif
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
$(SUBDIRS): $(LIB_STATIC)
|
||||
|
||||
DISTCLEAN_TARGETS += misc/configure.h misc/lvm-version.h
|
||||
@@ -1 +0,0 @@
|
||||
Base library directory
|
||||
1463
lib/activate/activate.c
Normal file
1463
lib/activate/activate.c
Normal file
File diff suppressed because it is too large
Load Diff
131
lib/activate/activate.h
Normal file
131
lib/activate/activate.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef LVM_ACTIVATE_H
|
||||
#define LVM_ACTIVATE_H
|
||||
|
||||
#include "metadata-exported.h"
|
||||
|
||||
struct lvinfo {
|
||||
int exists;
|
||||
int suspended;
|
||||
unsigned int open_count;
|
||||
int major;
|
||||
int minor;
|
||||
int read_only;
|
||||
int live_table;
|
||||
int inactive_table;
|
||||
uint32_t read_ahead;
|
||||
};
|
||||
|
||||
/* target attribute flags */
|
||||
#define MIRROR_LOG_CLUSTERED 0x00000001U
|
||||
|
||||
void set_activation(int activation);
|
||||
int activation(void);
|
||||
|
||||
int driver_version(char *version, size_t size);
|
||||
int library_version(char *version, size_t size);
|
||||
int lvm1_present(struct cmd_context *cmd);
|
||||
|
||||
int module_present(struct cmd_context *cmd, const char *target_name);
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe);
|
||||
int target_version(const char *target_name, uint32_t *maj,
|
||||
uint32_t *min, uint32_t *patchlevel);
|
||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
|
||||
struct dm_list *modules);
|
||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
struct dm_list *modules);
|
||||
|
||||
void activation_release(void);
|
||||
void activation_exit(void);
|
||||
|
||||
/* int lv_suspend(struct cmd_context *cmd, const char *lvid_s); */
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only);
|
||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only);
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only);
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive);
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int exclusive);
|
||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
* Returns 1 if info structure has been populated, else 0.
|
||||
*/
|
||||
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
unsigned origin_only, struct lvinfo *info,
|
||||
int with_open_count, int with_read_ahead);
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only,
|
||||
struct lvinfo *info, int with_open_count, int with_read_ahead);
|
||||
|
||||
/*
|
||||
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
|
||||
*/
|
||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv);
|
||||
|
||||
int lv_check_transient(struct logical_volume *lv);
|
||||
/*
|
||||
* Returns 1 if percent has been set, else 0.
|
||||
*/
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, percent_t *percent);
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, percent_t *percent, uint32_t *event_nr);
|
||||
|
||||
/*
|
||||
* Return number of LVs in the VG that are active.
|
||||
*/
|
||||
int lvs_in_vg_activated(struct volume_group *vg);
|
||||
int lvs_in_vg_opened(const struct volume_group *vg);
|
||||
|
||||
int lv_is_active(struct logical_volume *lv);
|
||||
int lv_is_active_exclusive_locally(struct logical_volume *lv);
|
||||
int lv_is_active_exclusive_remotely(struct logical_volume *lv);
|
||||
|
||||
int lv_has_target_type(struct dm_pool *mem, struct logical_volume *lv,
|
||||
const char *layer, const char *target_type);
|
||||
|
||||
int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
unsigned origin_only, int do_reg);
|
||||
|
||||
#ifdef DMEVENTD
|
||||
# include "libdevmapper-event.h"
|
||||
char *get_monitor_dso_path(struct cmd_context *cmd, const char *libpath);
|
||||
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *libpath,
|
||||
struct logical_volume *lv, int *pending);
|
||||
int target_register_events(struct cmd_context *cmd, const char *dso, struct logical_volume *lv,
|
||||
int evmask __attribute__((unused)), int set, int timeout);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns 1 if PV has a dependency tree that uses anything in VG.
|
||||
*/
|
||||
int pv_uses_vg(struct physical_volume *pv,
|
||||
struct volume_group *vg);
|
||||
|
||||
/*
|
||||
* Returns 1 if mapped device is not suspended.
|
||||
*/
|
||||
int device_is_usable(struct device *dev);
|
||||
|
||||
/*
|
||||
* Declaration moved here from fs.h to keep header fs.h hidden
|
||||
*/
|
||||
void fs_unlock(void);
|
||||
|
||||
#endif
|
||||
1816
lib/activate/dev_manager.c
Normal file
1816
lib/activate/dev_manager.c
Normal file
File diff suppressed because it is too large
Load Diff
71
lib/activate/dev_manager.h
Normal file
71
lib/activate/dev_manager.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU 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_DEV_MANAGER_H
|
||||
#define _LVM_DEV_MANAGER_H
|
||||
|
||||
#include "metadata-exported.h"
|
||||
|
||||
struct logical_volume;
|
||||
struct volume_group;
|
||||
struct cmd_context;
|
||||
struct dev_manager;
|
||||
struct dm_info;
|
||||
struct device;
|
||||
|
||||
/*
|
||||
* Constructor and destructor.
|
||||
*/
|
||||
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||
const char *vg_name);
|
||||
void dev_manager_destroy(struct dev_manager *dm);
|
||||
void dev_manager_release(void);
|
||||
void dev_manager_exit(void);
|
||||
|
||||
/*
|
||||
* The device handler is responsible for creating all the layered
|
||||
* dm devices, and ensuring that all constraints are maintained
|
||||
* (eg, an origin is created before its snapshot, but is not
|
||||
* unsuspended until the snapshot is also created.)
|
||||
*/
|
||||
int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
const char *layer,
|
||||
int with_open_count, int with_read_ahead,
|
||||
struct dm_info *info, uint32_t *read_ahead);
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
percent_t *percent);
|
||||
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
const struct logical_volume *lv, int wait,
|
||||
percent_t *percent, uint32_t *event_nr);
|
||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
|
||||
unsigned origin_only, int lockfs, int flush_required);
|
||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv, unsigned origin_only);
|
||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv,
|
||||
unsigned origin_only, int *flush_required);
|
||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_transient(struct dev_manager *dm, struct logical_volume *lv) __attribute__((nonnull(1, 2)));
|
||||
|
||||
int dev_manager_mknodes(const struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
* Put the desired changes into effect.
|
||||
*/
|
||||
int dev_manager_execute(struct dev_manager *dm);
|
||||
|
||||
int dev_manager_device_uses_vg(struct device *dev,
|
||||
struct volume_group *vg);
|
||||
|
||||
#endif
|
||||
506
lib/activate/fs.c
Normal file
506
lib/activate/fs.c
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of 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 "fs.h"
|
||||
#include "activate.h"
|
||||
#include "toolcontext.h"
|
||||
#include "lvm-string.h"
|
||||
#include "lvm-file.h"
|
||||
#include "memlock.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
|
||||
/*
|
||||
* Library cookie to combine multiple fs transactions.
|
||||
* Supports to wait for udev device settle only when needed.
|
||||
*/
|
||||
static uint32_t _fs_cookie = DM_COOKIE_AUTO_CREATE;
|
||||
|
||||
static int _mk_dir(const char *dev_dir, const char *vg_name)
|
||||
{
|
||||
char vg_path[PATH_MAX];
|
||||
mode_t old_umask;
|
||||
|
||||
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
dev_dir, vg_name) == -1) {
|
||||
log_error("Couldn't construct name of volume "
|
||||
"group directory.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dir_exists(vg_path))
|
||||
return 1;
|
||||
|
||||
log_very_verbose("Creating directory %s", vg_path);
|
||||
|
||||
(void) dm_prepare_selinux_context(vg_path, S_IFDIR);
|
||||
old_umask = umask(DM_DEV_DIR_UMASK);
|
||||
if (mkdir(vg_path, 0777)) {
|
||||
log_sys_error("mkdir", vg_path);
|
||||
umask(old_umask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
umask(old_umask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _rm_dir(const char *dev_dir, const char *vg_name)
|
||||
{
|
||||
char vg_path[PATH_MAX];
|
||||
|
||||
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
dev_dir, vg_name) == -1) {
|
||||
log_error("Couldn't construct name of volume "
|
||||
"group directory.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
|
||||
log_very_verbose("Removing directory %s", vg_path);
|
||||
rmdir(vg_path);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _rm_blks(const char *dir)
|
||||
{
|
||||
const char *name;
|
||||
char path[PATH_MAX];
|
||||
struct dirent *dirent;
|
||||
struct stat buf;
|
||||
DIR *d;
|
||||
|
||||
if (!(d = opendir(dir))) {
|
||||
log_sys_error("opendir", dir);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((dirent = readdir(d))) {
|
||||
name = dirent->d_name;
|
||||
|
||||
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
||||
continue;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
|
||||
log_error("Couldn't create path for %s", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!lstat(path, &buf)) {
|
||||
if (!S_ISBLK(buf.st_mode))
|
||||
continue;
|
||||
log_very_verbose("Removing %s", path);
|
||||
if (unlink(path) < 0)
|
||||
log_sys_error("unlink", path);
|
||||
}
|
||||
}
|
||||
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", dir);
|
||||
}
|
||||
|
||||
static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, const char *dev, int check_udev)
|
||||
{
|
||||
char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX];
|
||||
char vg_path[PATH_MAX];
|
||||
struct stat buf, buf_lp;
|
||||
|
||||
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
dev_dir, vg_name) == -1) {
|
||||
log_error("Couldn't create path for volume group dir %s",
|
||||
vg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
|
||||
lv_name) == -1) {
|
||||
log_error("Couldn't create source pathname for "
|
||||
"logical volume link %s", lv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_snprintf(link_path, sizeof(link_path), "%s/%s",
|
||||
dm_dir(), dev) == -1) {
|
||||
log_error("Couldn't create destination pathname for "
|
||||
"logical volume link for %s", lv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
|
||||
vg_path) == -1) {
|
||||
log_error("Couldn't create pathname for LVM1 group file for %s",
|
||||
vg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* To reach this point, the VG must have been locked.
|
||||
* As locking fails if the VG is active under LVM1, it's
|
||||
* now safe to remove any LVM1 devices we find here
|
||||
* (as well as any existing LVM2 symlink). */
|
||||
if (!lstat(lvm1_group_path, &buf)) {
|
||||
if (!S_ISCHR(buf.st_mode)) {
|
||||
log_error("Non-LVM1 character device found at %s",
|
||||
lvm1_group_path);
|
||||
} else {
|
||||
_rm_blks(vg_path);
|
||||
|
||||
log_very_verbose("Removing %s", lvm1_group_path);
|
||||
if (unlink(lvm1_group_path) < 0)
|
||||
log_sys_error("unlink", lvm1_group_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lstat(lv_path, &buf)) {
|
||||
if (!S_ISLNK(buf.st_mode) && !S_ISBLK(buf.st_mode)) {
|
||||
log_error("Symbolic link %s not created: file exists",
|
||||
link_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_udev_get_sync_support() && udev_checking() && check_udev) {
|
||||
/* Check udev created the correct link. */
|
||||
if (!stat(link_path, &buf_lp) &&
|
||||
!stat(lv_path, &buf)) {
|
||||
if (buf_lp.st_rdev == buf.st_rdev)
|
||||
return 1;
|
||||
else
|
||||
log_warn("Symlink %s that should have been "
|
||||
"created by udev does not have "
|
||||
"correct target. Falling back to "
|
||||
"direct link creation", lv_path);
|
||||
} else
|
||||
log_warn("Symlink %s that should have been "
|
||||
"created by udev could not be checked "
|
||||
"for its correctness. Falling back to "
|
||||
"direct link creation.", lv_path);
|
||||
|
||||
}
|
||||
|
||||
log_very_verbose("Removing %s", lv_path);
|
||||
if (unlink(lv_path) < 0) {
|
||||
log_sys_error("unlink", lv_path);
|
||||
return 0;
|
||||
}
|
||||
} else if (dm_udev_get_sync_support() && udev_checking() && check_udev)
|
||||
log_warn("The link %s should had been created by udev "
|
||||
"but it was not found. Falling back to "
|
||||
"direct link creation.", lv_path);
|
||||
|
||||
log_very_verbose("Linking %s -> %s", lv_path, link_path);
|
||||
|
||||
(void) dm_prepare_selinux_context(lv_path, S_IFLNK);
|
||||
if (symlink(link_path, lv_path) < 0) {
|
||||
log_sys_error("symlink", lv_path);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _rm_link(const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, int check_udev)
|
||||
{
|
||||
struct stat buf;
|
||||
char lv_path[PATH_MAX];
|
||||
|
||||
if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
|
||||
dev_dir, vg_name, lv_name) == -1) {
|
||||
log_error("Couldn't determine link pathname.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lstat(lv_path, &buf) && errno == ENOENT)
|
||||
return 1;
|
||||
else if (dm_udev_get_sync_support() && udev_checking() && check_udev)
|
||||
log_warn("The link %s should have been removed by udev "
|
||||
"but it is still present. Falling back to "
|
||||
"direct link removal.", lv_path);
|
||||
|
||||
if (!S_ISLNK(buf.st_mode)) {
|
||||
log_error("%s not symbolic link - not removing", lv_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Removing link %s", lv_path);
|
||||
if (unlink(lv_path) < 0) {
|
||||
log_sys_error("unlink", lv_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
FS_ADD,
|
||||
FS_DEL,
|
||||
FS_RENAME,
|
||||
NUM_FS_OPS
|
||||
} fs_op_t;
|
||||
|
||||
static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, const char *dev,
|
||||
const char *old_lv_name, int check_udev)
|
||||
{
|
||||
switch (type) {
|
||||
case FS_ADD:
|
||||
if (!_mk_dir(dev_dir, vg_name) ||
|
||||
!_mk_link(dev_dir, vg_name, lv_name, dev, check_udev))
|
||||
return_0;
|
||||
break;
|
||||
case FS_DEL:
|
||||
if (!_rm_link(dev_dir, vg_name, lv_name, check_udev) ||
|
||||
!_rm_dir(dev_dir, vg_name))
|
||||
return_0;
|
||||
break;
|
||||
/* FIXME Use rename() */
|
||||
case FS_RENAME:
|
||||
if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name,
|
||||
check_udev))
|
||||
stack;
|
||||
|
||||
if (!_mk_link(dev_dir, vg_name, lv_name, dev, check_udev))
|
||||
stack;
|
||||
default:
|
||||
; /* NOTREACHED */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static DM_LIST_INIT(_fs_ops);
|
||||
/*
|
||||
* Count number of stacked fs_op_t operations to allow to skip dm_list search.
|
||||
* FIXME: handling of FS_RENAME
|
||||
*/
|
||||
static int _count_fs_ops[NUM_FS_OPS];
|
||||
|
||||
struct fs_op_parms {
|
||||
struct dm_list list;
|
||||
fs_op_t type;
|
||||
int check_udev;
|
||||
char *dev_dir;
|
||||
char *vg_name;
|
||||
char *lv_name;
|
||||
char *dev;
|
||||
char *old_lv_name;
|
||||
char names[0];
|
||||
};
|
||||
|
||||
static void _store_str(char **pos, char **ptr, const char *str)
|
||||
{
|
||||
strcpy(*pos, str);
|
||||
*ptr = *pos;
|
||||
*pos += strlen(*ptr) + 1;
|
||||
}
|
||||
|
||||
static void _del_fs_op(struct fs_op_parms *fsp)
|
||||
{
|
||||
_count_fs_ops[fsp->type]--;
|
||||
dm_list_del(&fsp->list);
|
||||
dm_free(fsp);
|
||||
}
|
||||
|
||||
/* Check if there is other the type of fs operation stacked */
|
||||
static int _other_fs_ops(fs_op_t type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_FS_OPS; i++)
|
||||
if (type != i && _count_fs_ops[i])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if udev is supposed to create nodes */
|
||||
static int _check_udev(int check_udev)
|
||||
{
|
||||
return check_udev && dm_udev_get_sync_support() && dm_udev_get_checking();
|
||||
}
|
||||
|
||||
/* FIXME: duplication of the code from libdm-common.c */
|
||||
static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, const char *dev,
|
||||
const char *old_lv_name, int check_udev)
|
||||
{
|
||||
struct dm_list *fsph, *fspht;
|
||||
struct fs_op_parms *fsp;
|
||||
size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) +
|
||||
strlen(dev) + strlen(old_lv_name) + 5;
|
||||
char *pos;
|
||||
|
||||
if ((type == FS_DEL) && _other_fs_ops(type))
|
||||
/*
|
||||
* Ignore any outstanding operations on the fs_op if deleting it.
|
||||
*/
|
||||
dm_list_iterate_safe(fsph, fspht, &_fs_ops) {
|
||||
fsp = dm_list_item(fsph, struct fs_op_parms);
|
||||
if (!strcmp(lv_name, fsp->lv_name) &&
|
||||
!strcmp(vg_name, fsp->vg_name)) {
|
||||
_del_fs_op(fsp);
|
||||
if (!_other_fs_ops(type))
|
||||
break; /* no other non DEL ops */
|
||||
}
|
||||
}
|
||||
else if ((type == FS_ADD) && _count_fs_ops[FS_DEL] && _check_udev(check_udev))
|
||||
/*
|
||||
* If udev is running ignore previous DEL operation on added fs_op.
|
||||
* (No other operations for this device then DEL could be stacked here).
|
||||
*/
|
||||
dm_list_iterate_safe(fsph, fspht, &_fs_ops) {
|
||||
fsp = dm_list_item(fsph, struct fs_op_parms);
|
||||
if ((fsp->type == FS_DEL) &&
|
||||
!strcmp(lv_name, fsp->lv_name) &&
|
||||
!strcmp(vg_name, fsp->vg_name)) {
|
||||
_del_fs_op(fsp);
|
||||
break; /* no other DEL ops */
|
||||
}
|
||||
}
|
||||
else if ((type == FS_RENAME) && _check_udev(check_udev))
|
||||
/*
|
||||
* If udev is running ignore any outstanding operations if renaming it.
|
||||
*
|
||||
* Currently RENAME operation happens through 'suspend -> resume'.
|
||||
* On 'resume' device is added with read_ahead settings, so it
|
||||
* safe to remove any stacked ADD, RENAME, READ_AHEAD operation
|
||||
* There cannot be any DEL operation on the renamed device.
|
||||
*/
|
||||
dm_list_iterate_safe(fsph, fspht, &_fs_ops) {
|
||||
fsp = dm_list_item(fsph, struct fs_op_parms);
|
||||
if (!strcmp(old_lv_name, fsp->lv_name) &&
|
||||
!strcmp(vg_name, fsp->vg_name))
|
||||
_del_fs_op(fsp);
|
||||
}
|
||||
|
||||
if (!(fsp = dm_malloc(sizeof(*fsp) + len))) {
|
||||
log_error("No space to stack fs operation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos = fsp->names;
|
||||
fsp->type = type;
|
||||
fsp->check_udev = check_udev;
|
||||
|
||||
_store_str(&pos, &fsp->dev_dir, dev_dir);
|
||||
_store_str(&pos, &fsp->vg_name, vg_name);
|
||||
_store_str(&pos, &fsp->lv_name, lv_name);
|
||||
_store_str(&pos, &fsp->dev, dev);
|
||||
_store_str(&pos, &fsp->old_lv_name, old_lv_name);
|
||||
|
||||
_count_fs_ops[type]++;
|
||||
dm_list_add(&_fs_ops, &fsp->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _pop_fs_ops(void)
|
||||
{
|
||||
struct dm_list *fsph, *fspht;
|
||||
struct fs_op_parms *fsp;
|
||||
|
||||
dm_list_iterate_safe(fsph, fspht, &_fs_ops) {
|
||||
fsp = dm_list_item(fsph, struct fs_op_parms);
|
||||
_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
|
||||
fsp->dev, fsp->old_lv_name, fsp->check_udev);
|
||||
_del_fs_op(fsp);
|
||||
}
|
||||
}
|
||||
|
||||
static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, const char *dev, const char *old_lv_name,
|
||||
int check_udev)
|
||||
{
|
||||
if (memlock()) {
|
||||
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
|
||||
old_lv_name, check_udev))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return _do_fs_op(type, dev_dir, vg_name, lv_name, dev,
|
||||
old_lv_name, check_udev);
|
||||
}
|
||||
|
||||
int fs_add_lv(const struct logical_volume *lv, const char *dev)
|
||||
{
|
||||
return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, "", lv->vg->cmd->current_settings.udev_rules);
|
||||
}
|
||||
|
||||
int fs_del_lv(const struct logical_volume *lv)
|
||||
{
|
||||
return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
"", "", lv->vg->cmd->current_settings.udev_rules);
|
||||
}
|
||||
|
||||
int fs_del_lv_byname(const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, int check_udev)
|
||||
{
|
||||
return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "", check_udev);
|
||||
}
|
||||
|
||||
int fs_rename_lv(struct logical_volume *lv, const char *dev,
|
||||
const char *old_vgname, const char *old_lvname)
|
||||
{
|
||||
if (strcmp(old_vgname, lv->vg->name)) {
|
||||
return
|
||||
(_fs_op(FS_DEL, lv->vg->cmd->dev_dir, old_vgname,
|
||||
old_lvname, "", "", lv->vg->cmd->current_settings.udev_rules) &&
|
||||
_fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
lv->name, dev, "", lv->vg->cmd->current_settings.udev_rules));
|
||||
}
|
||||
else
|
||||
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, old_lvname, lv->vg->cmd->current_settings.udev_rules);
|
||||
}
|
||||
|
||||
void fs_unlock(void)
|
||||
{
|
||||
if (!memlock()) {
|
||||
log_debug("Syncing device names");
|
||||
/* Wait for all processed udev devices */
|
||||
if (!dm_udev_wait(_fs_cookie))
|
||||
stack;
|
||||
_fs_cookie = DM_COOKIE_AUTO_CREATE; /* Reset cookie */
|
||||
dm_lib_release();
|
||||
_pop_fs_ops();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t fs_get_cookie(void)
|
||||
{
|
||||
return _fs_cookie;
|
||||
}
|
||||
|
||||
void fs_set_cookie(uint32_t cookie)
|
||||
{
|
||||
_fs_cookie = cookie;
|
||||
}
|
||||
|
||||
int fs_has_non_delete_ops(void)
|
||||
{
|
||||
return _other_fs_ops(FS_DEL);
|
||||
}
|
||||
37
lib/activate/fs.h
Normal file
37
lib/activate/fs.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FS_H
|
||||
#define _LVM_FS_H
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
/*
|
||||
* These calls, private to the activate unit, set
|
||||
* up the volume group directory in /dev and the
|
||||
* symbolic links to the dm device.
|
||||
*/
|
||||
int fs_add_lv(const struct logical_volume *lv, const char *dev);
|
||||
int fs_del_lv(const struct logical_volume *lv);
|
||||
int fs_del_lv_byname(const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, int check_udev);
|
||||
int fs_rename_lv(struct logical_volume *lv, const char *dev,
|
||||
const char *old_vgname, const char *old_lvname);
|
||||
/* void fs_unlock(void); moved to activate.h */
|
||||
uint32_t fs_get_cookie(void);
|
||||
void fs_set_cookie(uint32_t cookie);
|
||||
int fs_has_non_delete_ops(void);
|
||||
|
||||
#endif
|
||||
32
lib/activate/targets.h
Normal file
32
lib/activate/targets.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU 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_TARGETS_H
|
||||
#define _LVM_TARGETS_H
|
||||
|
||||
struct dev_manager;
|
||||
struct lv_segment;
|
||||
|
||||
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos,
|
||||
int start_area, int areas);
|
||||
|
||||
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
struct dm_tree_node *node, uint32_t start_area, uint32_t areas);
|
||||
|
||||
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
|
||||
size_t bufsize, const char *desc);
|
||||
|
||||
#endif
|
||||
1459
lib/cache/lvmcache.c
vendored
Normal file
1459
lib/cache/lvmcache.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
127
lib/cache/lvmcache.h
vendored
Normal file
127
lib/cache/lvmcache.h
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 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
|
||||
*/
|
||||
|
||||
#ifndef _LVM_CACHE_H
|
||||
#define _LVM_CACHE_H
|
||||
|
||||
#include "dev-cache.h"
|
||||
#include "uuid.h"
|
||||
#include "label.h"
|
||||
#include "locking.h"
|
||||
|
||||
#define ORPHAN_PREFIX VG_ORPHANS
|
||||
#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "_" fmt
|
||||
|
||||
#define CACHE_INVALID 0x00000001
|
||||
#define CACHE_LOCKED 0x00000002
|
||||
|
||||
/* LVM specific per-volume info */
|
||||
/* Eventual replacement for struct physical_volume perhaps? */
|
||||
|
||||
struct cmd_context;
|
||||
struct format_type;
|
||||
struct volume_group;
|
||||
struct config_tree;
|
||||
|
||||
/* One per VG */
|
||||
struct lvmcache_vginfo {
|
||||
struct dm_list list; /* Join these vginfos together */
|
||||
struct dm_list infos; /* List head for lvmcache_infos */
|
||||
const struct format_type *fmt;
|
||||
char *vgname; /* "" == orphan */
|
||||
uint32_t status;
|
||||
char vgid[ID_LEN + 1];
|
||||
char _padding[7];
|
||||
struct lvmcache_vginfo *next; /* Another VG with same name? */
|
||||
char *creation_host;
|
||||
char *vgmetadata; /* Copy of VG metadata as format_text string */
|
||||
struct config_tree *cft; /* Config tree created from vgmetadata */
|
||||
/* Lifetime is directly tied to vgmetadata */
|
||||
unsigned precommitted; /* Is vgmetadata live or precommitted? */
|
||||
};
|
||||
|
||||
/* One per device */
|
||||
struct lvmcache_info {
|
||||
struct dm_list list; /* Join VG members together */
|
||||
struct dm_list mdas; /* list head for metadata areas */
|
||||
struct dm_list das; /* list head for data areas */
|
||||
struct lvmcache_vginfo *vginfo; /* NULL == unknown */
|
||||
struct label *label;
|
||||
const struct format_type *fmt;
|
||||
struct device *dev;
|
||||
uint64_t device_size; /* Bytes */
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
int lvmcache_init(void);
|
||||
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
|
||||
|
||||
/* Set full_scan to 1 to reread every filtered device label or
|
||||
* 2 to rescan /dev for new devices */
|
||||
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
/* Add/delete a device */
|
||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
struct device *dev,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus);
|
||||
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
|
||||
void lvmcache_del(struct lvmcache_info *info);
|
||||
|
||||
/* Update things */
|
||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *hostname);
|
||||
int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted);
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
|
||||
void lvmcache_unlock_vgname(const char *vgname);
|
||||
int lvmcache_verify_lock_order(const char *vgname);
|
||||
|
||||
/* Queries */
|
||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels);
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
|
||||
const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
|
||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||
struct device *device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
|
||||
unsigned *scan_done_once);
|
||||
const char *pvid_from_devname(struct cmd_context *cmd,
|
||||
const char *dev_name);
|
||||
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
|
||||
int vgs_locked(void);
|
||||
int vgname_is_locked(const char *vgname);
|
||||
|
||||
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
|
||||
/* If include_internal is not set, return only proper vg names. */
|
||||
struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd,
|
||||
int include_internal);
|
||||
|
||||
/* Returns list of struct str_lists containing pool-allocated copy of vgids */
|
||||
/* If include_internal is not set, return only proper vg ids. */
|
||||
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
|
||||
int include_internal);
|
||||
|
||||
/* Returns list of struct str_lists containing pool-allocated copy of pvids */
|
||||
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid);
|
||||
|
||||
/* Returns cached volume group metadata. */
|
||||
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
|
||||
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
|
||||
void lvmcache_commit_metadata(const char *vgname);
|
||||
|
||||
#endif
|
||||
26
lib/commands/errors.h
Normal file
26
lib/commands/errors.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU 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_ERRORS_H
|
||||
#define _LVM_ERRORS_H
|
||||
|
||||
#define ECMD_PROCESSED 1
|
||||
#define ENO_SUCH_CMD 2
|
||||
#define EINVALID_CMD_LINE 3
|
||||
#define ECMD_FAILED 5
|
||||
|
||||
/* FIXME Also returned by cmdlib. */
|
||||
|
||||
#endif
|
||||
1400
lib/commands/toolcontext.c
Normal file
1400
lib/commands/toolcontext.c
Normal file
File diff suppressed because it is too large
Load Diff
121
lib/commands/toolcontext.h
Normal file
121
lib/commands/toolcontext.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-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
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TOOLCONTEXT_H
|
||||
#define _LVM_TOOLCONTEXT_H
|
||||
|
||||
#include "dev-cache.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* Config options that can be changed while commands are processed
|
||||
*/
|
||||
struct config_info {
|
||||
int debug;
|
||||
int verbose;
|
||||
int test;
|
||||
int syslog;
|
||||
int activation;
|
||||
int suffix;
|
||||
int archive; /* should we archive ? */
|
||||
int backup; /* should we backup ? */
|
||||
int read_ahead; /* DM_READ_AHEAD_NONE or _AUTO */
|
||||
int udev_rules;
|
||||
int udev_sync;
|
||||
int cache_vgmetadata;
|
||||
const char *msg_prefix;
|
||||
const char *fmt_name;
|
||||
uint64_t unit_factor;
|
||||
int cmd_name; /* Show command name? */
|
||||
mode_t umask;
|
||||
char unit_type;
|
||||
char _padding[1];
|
||||
};
|
||||
|
||||
struct config_tree;
|
||||
struct archive_params;
|
||||
struct backup_params;
|
||||
struct arg_values;
|
||||
|
||||
/* FIXME Split into tool & library contexts */
|
||||
/* command-instance-related variables needed by library */
|
||||
struct cmd_context {
|
||||
struct dm_pool *libmem; /* For permanent config data */
|
||||
struct dm_pool *mem; /* Transient: Cleared between each command */
|
||||
|
||||
const struct format_type *fmt; /* Current format to use by default */
|
||||
struct format_type *fmt_backup; /* Format to use for backups */
|
||||
|
||||
struct dm_list formats; /* Available formats */
|
||||
struct dm_list segtypes; /* Available segment types */
|
||||
const char *hostname;
|
||||
const char *kernel_vsn;
|
||||
|
||||
unsigned rand_seed;
|
||||
const char *cmd_line;
|
||||
struct command *command;
|
||||
char **argv;
|
||||
struct arg_values *arg_values;
|
||||
struct dm_list arg_value_groups;
|
||||
unsigned is_long_lived:1; /* Optimises persistent_filter handling */
|
||||
unsigned handles_missing_pvs:1;
|
||||
unsigned handles_unknown_segments:1;
|
||||
unsigned partial_activation:1;
|
||||
unsigned si_unit_consistency:1;
|
||||
unsigned metadata_read_only:1;
|
||||
|
||||
unsigned independent_metadata_areas:1; /* Active formats have MDAs outside PVs */
|
||||
|
||||
struct dev_filter *filter;
|
||||
int dump_filter; /* Dump filter when exiting? */
|
||||
|
||||
struct dm_list config_files;
|
||||
int config_valid;
|
||||
struct config_tree *cft;
|
||||
struct config_tree *cft_override;
|
||||
struct config_info default_settings;
|
||||
struct config_info current_settings;
|
||||
|
||||
struct archive_params *archive_params;
|
||||
struct backup_params *backup_params;
|
||||
const char *stripe_filler;
|
||||
|
||||
/* List of defined tags */
|
||||
struct dm_list tags;
|
||||
int hosttags;
|
||||
|
||||
char system_dir[PATH_MAX];
|
||||
char dev_dir[PATH_MAX];
|
||||
char proc_dir[PATH_MAX];
|
||||
char sysfs_dir[PATH_MAX]; /* FIXME Use global value instead. */
|
||||
};
|
||||
|
||||
/*
|
||||
* system_dir may be NULL to use the default value.
|
||||
* The environment variable LVM_SYSTEM_DIR always takes precedence.
|
||||
*/
|
||||
struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
const char *system_dir);
|
||||
void destroy_toolcontext(struct cmd_context *cmd);
|
||||
int refresh_toolcontext(struct cmd_context *cmd);
|
||||
int refresh_filters(struct cmd_context *cmd);
|
||||
int config_files_changed(struct cmd_context *cmd);
|
||||
int init_lvmcache_orphans(struct cmd_context *cmd);
|
||||
|
||||
struct format_type *get_format_by_name(struct cmd_context *cmd, const char *format);
|
||||
|
||||
#endif
|
||||
1384
lib/config/config.c
Normal file
1384
lib/config/config.c
Normal file
File diff suppressed because it is too large
Load Diff
123
lib/config/config.h
Normal file
123
lib/config/config.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_CONFIG_H
|
||||
#define _LVM_CONFIG_H
|
||||
|
||||
#include "lvm-types.h"
|
||||
|
||||
struct device;
|
||||
struct cmd_context;
|
||||
|
||||
enum {
|
||||
CFG_STRING,
|
||||
CFG_FLOAT,
|
||||
CFG_INT,
|
||||
CFG_EMPTY_ARRAY
|
||||
};
|
||||
|
||||
struct config_value {
|
||||
int type;
|
||||
union {
|
||||
int64_t i;
|
||||
float r;
|
||||
const char *str;
|
||||
} v;
|
||||
struct config_value *next; /* for arrays */
|
||||
};
|
||||
|
||||
struct config_node {
|
||||
const char *key;
|
||||
struct config_node *parent, *sib, *child;
|
||||
struct config_value *v;
|
||||
};
|
||||
|
||||
struct config_tree {
|
||||
struct config_node *root;
|
||||
};
|
||||
|
||||
struct config_tree_list {
|
||||
struct dm_list list;
|
||||
struct config_tree *cft;
|
||||
};
|
||||
|
||||
struct config_tree *create_config_tree(const char *filename, int keep_open);
|
||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
|
||||
const char *config_settings);
|
||||
int override_config_tree_from_string(struct cmd_context *cmd,
|
||||
const char *config_settings);
|
||||
void destroy_config_tree(struct config_tree *cft);
|
||||
|
||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_t size);
|
||||
|
||||
int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum);
|
||||
|
||||
int read_config_file(struct config_tree *cft);
|
||||
int write_config_file(struct config_tree *cft, const char *file,
|
||||
int argc, char **argv);
|
||||
|
||||
typedef int (*putline_fn)(const char *line, void *baton);
|
||||
int write_config_node(const struct config_node *cn, putline_fn putline, void *baton);
|
||||
|
||||
time_t config_file_timestamp(struct config_tree *cft);
|
||||
int config_file_changed(struct config_tree *cft);
|
||||
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
|
||||
struct config_tree *newdata);
|
||||
|
||||
const struct config_node *find_config_node(const struct config_node *cn,
|
||||
const char *path);
|
||||
const char *find_config_str(const struct config_node *cn, const char *path,
|
||||
const char *fail);
|
||||
int find_config_int(const struct config_node *cn, const char *path, int fail);
|
||||
float find_config_float(const struct config_node *cn, const char *path,
|
||||
float fail);
|
||||
|
||||
/*
|
||||
* These versions check an override tree, if present, first.
|
||||
*/
|
||||
const struct config_node *find_config_tree_node(struct cmd_context *cmd,
|
||||
const char *path);
|
||||
const char *find_config_tree_str(struct cmd_context *cmd,
|
||||
const char *path, const char *fail);
|
||||
int find_config_tree_int(struct cmd_context *cmd, const char *path,
|
||||
int fail);
|
||||
float find_config_tree_float(struct cmd_context *cmd, const char *path,
|
||||
float fail);
|
||||
|
||||
/*
|
||||
* Understands (0, ~0), (y, n), (yes, no), (on,
|
||||
* off), (true, false).
|
||||
*/
|
||||
int find_config_bool(const struct config_node *cn, const char *path, int fail);
|
||||
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail);
|
||||
|
||||
int get_config_uint32(const struct config_node *cn, const char *path,
|
||||
uint32_t *result);
|
||||
|
||||
int get_config_uint64(const struct config_node *cn, const char *path,
|
||||
uint64_t *result);
|
||||
|
||||
int get_config_str(const struct config_node *cn, const char *path,
|
||||
const char **result);
|
||||
|
||||
unsigned maybe_config_section(const char *str, unsigned len);
|
||||
|
||||
const char *config_parent_name(const struct config_node *n);
|
||||
|
||||
struct config_node *clone_config_node(struct dm_pool *mem, const struct config_node *cn,
|
||||
int siblings);
|
||||
#endif
|
||||
155
lib/config/defaults.h
Normal file
155
lib/config/defaults.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-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
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEFAULTS_H
|
||||
#define _LVM_DEFAULTS_H
|
||||
|
||||
#define DEFAULT_PE_ALIGN 2048
|
||||
#define DEFAULT_PE_ALIGN_OLD 128
|
||||
|
||||
#define DEFAULT_ARCHIVE_ENABLED 1
|
||||
#define DEFAULT_BACKUP_ENABLED 1
|
||||
|
||||
#define DEFAULT_CACHE_FILE_PREFIX ""
|
||||
|
||||
#define DEFAULT_ARCHIVE_DAYS 30
|
||||
#define DEFAULT_ARCHIVE_NUMBER 10
|
||||
|
||||
#define DEFAULT_DEV_DIR "/dev"
|
||||
#define DEFAULT_PROC_DIR "/proc"
|
||||
#define DEFAULT_SYSFS_SCAN 1
|
||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
|
||||
#define DEFAULT_MD_CHUNK_ALIGNMENT 1
|
||||
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
|
||||
#define DEFAULT_DISABLE_AFTER_ERROR_COUNT 0
|
||||
#define DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID 1
|
||||
#define DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION 1
|
||||
#define DEFAULT_DATA_ALIGNMENT_DETECTION 1
|
||||
|
||||
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
|
||||
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
|
||||
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
|
||||
#define DEFAULT_WAIT_FOR_LOCKS 1
|
||||
#define DEFAULT_PRIORITISE_WRITE_LOCKS 1
|
||||
#define DEFAULT_USE_MLOCKALL 0
|
||||
#define DEFAULT_METADATA_READ_ONLY 0
|
||||
|
||||
#define DEFAULT_MIRRORLOG "disk"
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
#define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove"
|
||||
#define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */
|
||||
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
|
||||
#define DEFAULT_DMEVENTD_SNAPSHOT_LIB "libdevmapper-event-lvm2snapshot.so"
|
||||
#define DEFAULT_DMEVENTD_MONITOR 1
|
||||
#define DEFAULT_BACKGROUND_POLLING 1
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
||||
#ifdef LVM1_FALLBACK
|
||||
# define DEFAULT_FALLBACK_TO_LVM1 1
|
||||
#else
|
||||
# define DEFAULT_FALLBACK_TO_LVM1 0
|
||||
#endif
|
||||
|
||||
#define DEFAULT_FORMAT "lvm2"
|
||||
|
||||
#define DEFAULT_STRIPESIZE 64 /* KB */
|
||||
#define DEFAULT_PVMETADATAIGNORE 0
|
||||
#define DEFAULT_PVMETADATAIGNORE_STR "n"
|
||||
#define DEFAULT_PVMETADATASIZE 255
|
||||
#define DEFAULT_PVMETADATACOPIES 1
|
||||
#define DEFAULT_VGMETADATACOPIES 0
|
||||
#define DEFAULT_LABELSECTOR UINT64_C(1)
|
||||
#define DEFAULT_READ_AHEAD "auto"
|
||||
#define DEFAULT_UDEV_RULES 1
|
||||
#define DEFAULT_UDEV_SYNC 0
|
||||
#define DEFAULT_EXTENT_SIZE 4096 /* In KB */
|
||||
#define DEFAULT_MAX_PV 0
|
||||
#define DEFAULT_MAX_LV 0
|
||||
#define DEFAULT_ALLOC_POLICY ALLOC_NORMAL
|
||||
#define DEFAULT_CLUSTERED 0
|
||||
|
||||
#define DEFAULT_MSG_PREFIX " "
|
||||
#define DEFAULT_CMD_NAME 0
|
||||
#define DEFAULT_OVERWRITE 0
|
||||
|
||||
#ifndef DEFAULT_LOG_FACILITY
|
||||
# define DEFAULT_LOG_FACILITY LOG_USER
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SYSLOG 1
|
||||
#define DEFAULT_VERBOSE 0
|
||||
#define DEFAULT_LOGLEVEL 0
|
||||
#define DEFAULT_INDENT 1
|
||||
#define DEFAULT_ABORT_ON_INTERNAL_ERRORS 0
|
||||
#define DEFAULT_UNITS "h"
|
||||
#define DEFAULT_SUFFIX 1
|
||||
#define DEFAULT_HOSTTAGS 0
|
||||
|
||||
#ifndef DEFAULT_SI_UNIT_CONSISTENCY
|
||||
# define DEFAULT_SI_UNIT_CONSISTENCY 1
|
||||
#endif
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
# define DEFAULT_ACTIVATION 1
|
||||
# define DEFAULT_RESERVED_MEMORY 8192
|
||||
# define DEFAULT_RESERVED_STACK 256
|
||||
# define DEFAULT_PROCESS_PRIORITY -18
|
||||
#else
|
||||
# define DEFAULT_ACTIVATION 0
|
||||
#endif
|
||||
|
||||
#define DEFAULT_STRIPE_FILLER "error"
|
||||
#define DEFAULT_MIRROR_REGION_SIZE 512 /* KB */
|
||||
#define DEFAULT_INTERVAL 15
|
||||
|
||||
#ifdef READLINE_SUPPORT
|
||||
# define DEFAULT_MAX_HISTORY 100
|
||||
#endif
|
||||
|
||||
#define DEFAULT_MAX_ERROR_COUNT NO_DEV_ERROR_COUNT_LIMIT
|
||||
|
||||
#define DEFAULT_REP_ALIGNED 1
|
||||
#define DEFAULT_REP_BUFFERED 1
|
||||
#define DEFAULT_REP_COLUMNS_AS_ROWS 0
|
||||
#define DEFAULT_REP_HEADINGS 1
|
||||
#define DEFAULT_REP_PREFIXES 0
|
||||
#define DEFAULT_REP_QUOTED 1
|
||||
#define DEFAULT_REP_SEPARATOR " "
|
||||
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent,convert_lv"
|
||||
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
|
||||
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
|
||||
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
|
||||
#define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
|
||||
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,convert_lv,lv_uuid"
|
||||
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
|
||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
|
||||
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
|
||||
#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
|
||||
|
||||
#define DEFAULT_LVS_SORT "vg_name,lv_name"
|
||||
#define DEFAULT_VGS_SORT "vg_name"
|
||||
#define DEFAULT_PVS_SORT "pv_name"
|
||||
#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
|
||||
#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
|
||||
|
||||
#define DEFAULT_MIRROR_DEVICE_FAULT_POLICY "remove"
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
#define DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD 100
|
||||
#define DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT 20
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
137
lib/datastruct/btree.c
Normal file
137
lib/datastruct/btree.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "btree.h"
|
||||
|
||||
struct node {
|
||||
uint32_t key;
|
||||
struct node *l, *r, *p;
|
||||
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct btree {
|
||||
struct dm_pool *mem;
|
||||
struct node *root;
|
||||
};
|
||||
|
||||
struct btree *btree_create(struct dm_pool *mem)
|
||||
{
|
||||
struct btree *t = dm_pool_alloc(mem, sizeof(*t));
|
||||
|
||||
if (t) {
|
||||
t->mem = mem;
|
||||
t->root = NULL;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shuffle the bits in a key, to try and remove
|
||||
* any ordering.
|
||||
*/
|
||||
static uint32_t _shuffle(uint32_t k)
|
||||
{
|
||||
#if 1
|
||||
return ((k & 0xff) << 24 |
|
||||
(k & 0xff00) << 8 |
|
||||
(k & 0xff0000) >> 8 | (k & 0xff000000) >> 24);
|
||||
#else
|
||||
return k;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct node **_lookup(struct node *const *c, uint32_t key,
|
||||
struct node **p)
|
||||
{
|
||||
*p = NULL;
|
||||
while (*c) {
|
||||
*p = *c;
|
||||
if ((*c)->key == key)
|
||||
break;
|
||||
|
||||
if (key < (*c)->key)
|
||||
c = &(*c)->l;
|
||||
|
||||
else
|
||||
c = &(*c)->r;
|
||||
}
|
||||
|
||||
return (struct node **)c;
|
||||
}
|
||||
|
||||
void *btree_lookup(const struct btree *t, uint32_t k)
|
||||
{
|
||||
uint32_t key = _shuffle(k);
|
||||
struct node *p, **c = _lookup(&t->root, key, &p);
|
||||
return (*c) ? (*c)->data : NULL;
|
||||
}
|
||||
|
||||
int btree_insert(struct btree *t, uint32_t k, void *data)
|
||||
{
|
||||
uint32_t key = _shuffle(k);
|
||||
struct node *p, **c = _lookup(&t->root, key, &p), *n;
|
||||
|
||||
if (!*c) {
|
||||
if (!(n = dm_pool_alloc(t->mem, sizeof(*n))))
|
||||
return_0;
|
||||
|
||||
n->key = key;
|
||||
n->data = data;
|
||||
n->l = n->r = NULL;
|
||||
n->p = p;
|
||||
|
||||
*c = n;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *btree_get_data(const struct btree_iter *it)
|
||||
{
|
||||
return ((const struct node *) it)->data;
|
||||
}
|
||||
|
||||
static struct node *_left(struct node *n)
|
||||
{
|
||||
while (n->l)
|
||||
n = n->l;
|
||||
return n;
|
||||
}
|
||||
|
||||
struct btree_iter *btree_first(const struct btree *t)
|
||||
{
|
||||
if (!t->root)
|
||||
return NULL;
|
||||
|
||||
return (struct btree_iter *) _left(t->root);
|
||||
}
|
||||
|
||||
struct btree_iter *btree_next(const struct btree_iter *it)
|
||||
{
|
||||
struct node *n = (struct node *) it;
|
||||
uint32_t k = n->key;
|
||||
|
||||
if (n->r)
|
||||
return (struct btree_iter *) _left(n->r);
|
||||
|
||||
do
|
||||
n = n->p;
|
||||
while (n && k > n->key);
|
||||
|
||||
return (struct btree_iter *) n;
|
||||
}
|
||||
32
lib/datastruct/btree.h
Normal file
32
lib/datastruct/btree.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU 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_BTREE_H
|
||||
#define _LVM_BTREE_H
|
||||
|
||||
struct btree;
|
||||
|
||||
struct btree *btree_create(struct dm_pool *mem);
|
||||
|
||||
void *btree_lookup(const struct btree *t, uint32_t k);
|
||||
int btree_insert(struct btree *t, uint32_t k, void *data);
|
||||
|
||||
struct btree_iter;
|
||||
void *btree_get_data(const struct btree_iter *it);
|
||||
|
||||
struct btree_iter *btree_first(const struct btree *t);
|
||||
struct btree_iter *btree_next(const struct btree_iter *it);
|
||||
|
||||
#endif
|
||||
32
lib/datastruct/lvm-types.h
Normal file
32
lib/datastruct/lvm-types.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TYPES_H
|
||||
#define _LVM_TYPES_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/* Define some portable printing types */
|
||||
#define PRIsize_t "zu"
|
||||
#define PRIptrdiff_t "td"
|
||||
#define PRIpid_t PRId32
|
||||
|
||||
struct str_list {
|
||||
struct dm_list list;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
#endif
|
||||
127
lib/datastruct/str_list.c
Normal file
127
lib/datastruct/str_list.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU 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 "str_list.h"
|
||||
|
||||
struct dm_list *str_list_create(struct dm_pool *mem)
|
||||
{
|
||||
struct dm_list *sl;
|
||||
|
||||
if (!(sl = dm_pool_alloc(mem, sizeof(struct dm_list)))) {
|
||||
log_errno(ENOMEM, "str_list allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dm_list_init(sl);
|
||||
|
||||
return sl;
|
||||
}
|
||||
|
||||
int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
|
||||
{
|
||||
struct str_list *sln;
|
||||
|
||||
if (!str)
|
||||
return_0;
|
||||
|
||||
/* Already in list? */
|
||||
if (str_list_match_item(sll, str))
|
||||
return 1;
|
||||
|
||||
if (!(sln = dm_pool_alloc(mem, sizeof(*sln))))
|
||||
return_0;
|
||||
|
||||
sln->str = str;
|
||||
dm_list_add(sll, &sln->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int str_list_del(struct dm_list *sll, const char *str)
|
||||
{
|
||||
struct dm_list *slh, *slht;
|
||||
|
||||
dm_list_iterate_safe(slh, slht, sll) {
|
||||
if (!strcmp(str, dm_list_item(slh, struct str_list)->str))
|
||||
dm_list_del(slh);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
|
||||
const struct dm_list *sllold)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
dm_list_init(sllnew);
|
||||
|
||||
dm_list_iterate_items(sl, sllold) {
|
||||
if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is item on list?
|
||||
*/
|
||||
int str_list_match_item(const struct dm_list *sll, const char *str)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
dm_list_iterate_items(sl, sll)
|
||||
if (!strcmp(str, sl->str))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is at least one item on both lists?
|
||||
* If tag_matched is non-NULL, it is set to the tag that matched.
|
||||
*/
|
||||
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, const char **tag_matched)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
dm_list_iterate_items(sl, sll)
|
||||
if (str_list_match_item(sll2, sl->str)) {
|
||||
if (tag_matched)
|
||||
*tag_matched = sl->str;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do both lists contain the same set of items?
|
||||
*/
|
||||
int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
if (dm_list_size(sll) != dm_list_size(sll2))
|
||||
return 0;
|
||||
|
||||
dm_list_iterate_items(sl, sll)
|
||||
if (!str_list_match_item(sll2, sl->str))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user