mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-10 08:23:48 +03:00
Compare commits
7600 Commits
v1_00_05
...
dev-mornfa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c9eddbab5 | ||
|
|
a2d9a818cf | ||
|
|
e83984dca5 | ||
|
|
f4d8d73ad3 | ||
|
|
0217311997 | ||
|
|
4db47137a4 | ||
|
|
4e9bbccb33 | ||
|
|
93108125ac | ||
|
|
d17cbf112b | ||
|
|
d838501c44 | ||
|
|
db59f5661c | ||
|
|
8e5d18afd3 | ||
|
|
ec5f5564de | ||
|
|
1650e1467c | ||
|
|
94d9562bea | ||
|
|
57795df365 | ||
|
|
0f49180ea7 | ||
|
|
eb2c68590b | ||
|
|
803b7af706 | ||
|
|
f05c5a97c3 | ||
|
|
4a657a13b1 | ||
|
|
5467a3b2b7 | ||
|
|
20868482dd | ||
|
|
8c6f3006e7 | ||
|
|
65a0650135 | ||
|
|
7c89cbf03a | ||
|
|
53fbf2bea3 | ||
|
|
28160cb04a | ||
|
|
e4cb88009a | ||
|
|
249ea4c34c | ||
|
|
1f73e992ef | ||
|
|
e7878da921 | ||
|
|
05bf4b8cc3 | ||
|
|
c5f7d401e5 | ||
|
|
db2b65704c | ||
|
|
e9e7421c8e | ||
|
|
274eae592f | ||
|
|
1c83c15963 | ||
|
|
31f3274ed8 | ||
|
|
e5baaf4ac9 | ||
|
|
e01fbd9d8d | ||
|
|
562c678ee2 | ||
|
|
7061b74ec6 | ||
|
|
09cc5f65db | ||
|
|
6f9366696c | ||
|
|
a766ea16b8 | ||
|
|
cd9350198e | ||
|
|
e4dfa785d1 | ||
|
|
b08c346489 | ||
|
|
3ced1bf694 | ||
|
|
bd3ece0128 | ||
|
|
eb7e206a73 | ||
|
|
59962d8d3e | ||
|
|
39705ed201 | ||
|
|
56779c32c5 | ||
|
|
99f0483580 | ||
|
|
c5c452a137 | ||
|
|
2f1a571c97 | ||
|
|
55f42944bd | ||
|
|
5e7cdd60f0 | ||
|
|
798ed9ea1c | ||
|
|
6ad17fd712 | ||
|
|
be25f7ac83 | ||
|
|
732859d21f | ||
|
|
9966842810 | ||
|
|
77952151af | ||
|
|
e992cb253c | ||
|
|
06e8ff29ff | ||
|
|
cb587fd100 | ||
|
|
4707ac7200 | ||
|
|
3ba3bc0d66 | ||
|
|
58a2e5e2df | ||
|
|
8cbacd2474 | ||
|
|
2ada982e73 | ||
|
|
810bc4f8c1 | ||
|
|
7fab9a9dda | ||
|
|
1f30e5a052 | ||
|
|
d96b854ac0 | ||
|
|
fca5acd072 | ||
|
|
06ac797f42 | ||
|
|
b3b551a93e | ||
|
|
cb0d817fb5 | ||
|
|
4777eb6872 | ||
|
|
4f6c2951d6 | ||
|
|
f12d88f840 | ||
|
|
2fbe1e6e00 | ||
|
|
2e4a66a761 | ||
|
|
c6cf2ed7fd | ||
|
|
8ad7865b42 | ||
|
|
6fc67f5509 | ||
|
|
55fe07ad98 | ||
|
|
e926f22457 | ||
|
|
4407133113 | ||
|
|
3d0cb0611e | ||
|
|
4741e449e6 | ||
|
|
f7d5511876 | ||
|
|
deb3c93a19 | ||
|
|
986a50e4a1 | ||
|
|
2d3700ba42 | ||
|
|
d2d71330c3 | ||
|
|
dacc340cc8 | ||
|
|
f319a61e9c | ||
|
|
2ac217d408 | ||
|
|
baf9ef2047 | ||
|
|
f39f5b86c3 | ||
|
|
c1eb17ab07 | ||
|
|
a5ad1ee858 | ||
|
|
8d004b5127 | ||
|
|
8b18ab76d2 | ||
|
|
3f7de58e96 | ||
|
|
f84f12a6a3 | ||
|
|
d51b7e5404 | ||
|
|
320d7f3596 | ||
|
|
23775c8fe8 | ||
|
|
67fc56f5ca | ||
|
|
c7c5a840c1 | ||
|
|
68ef288901 | ||
|
|
1445d40794 | ||
|
|
45eeb70b02 | ||
|
|
2925023411 | ||
|
|
35ab841ecf | ||
|
|
a12f92c494 | ||
|
|
994c32272e | ||
|
|
9cdcde494f | ||
|
|
5a751ad703 | ||
|
|
855175fa26 | ||
|
|
d38af2857f | ||
|
|
4eb8db26ac | ||
|
|
4e1ac7faf1 | ||
|
|
dfca5dac9c | ||
|
|
dd4fdce16c | ||
|
|
1951798d72 | ||
|
|
5e7eae59da | ||
|
|
8f1dd00c36 | ||
|
|
a2b76a6f02 | ||
|
|
17a6915054 | ||
|
|
78a42bac15 | ||
|
|
24f8daa13d | ||
|
|
9e24d563c6 | ||
|
|
4ca6a4105d | ||
|
|
f787b575b5 | ||
|
|
377e06b0f8 | ||
|
|
bee3f4b930 | ||
|
|
8184a57c2b | ||
|
|
5ea466673a | ||
|
|
45f396f2a0 | ||
|
|
ba3cee3630 | ||
|
|
5070ffbca7 | ||
|
|
61d0ae7019 | ||
|
|
0125518d6d | ||
|
|
c9d8d22224 | ||
|
|
764195207d | ||
|
|
2ccb9eb861 | ||
|
|
2e0740f7ef | ||
|
|
dce8d06af7 | ||
|
|
9495a3d807 | ||
|
|
c363c74a25 | ||
|
|
58734d2538 | ||
|
|
a81a2406f1 | ||
|
|
698137ec38 | ||
|
|
2e39392daf | ||
|
|
4cce09dbdb | ||
|
|
719e908bc0 | ||
|
|
faeea37057 | ||
|
|
ff64e3500f | ||
|
|
e7ccad2ef0 | ||
|
|
91c9771fc3 | ||
|
|
cbcbb67731 | ||
|
|
95d28735ea | ||
|
|
38f8f4a958 | ||
|
|
c22e925ce4 | ||
|
|
ddafa0115e | ||
|
|
3fd0242a0a | ||
|
|
72921d7922 | ||
|
|
95372a852b | ||
|
|
382fc878d7 | ||
|
|
00ed6759c8 | ||
|
|
6ac4cba276 | ||
|
|
d24c01a414 | ||
|
|
435e0bb608 | ||
|
|
b57b394ebb | ||
|
|
2edf488b38 | ||
|
|
5c93f3997b | ||
|
|
32ae07cef1 | ||
|
|
784867d5bd | ||
|
|
ea36d0501e | ||
|
|
7e5e2dd4ee | ||
|
|
59878d0129 | ||
|
|
5b6bab2e30 | ||
|
|
562ad293fd | ||
|
|
9cf00666b3 | ||
|
|
0191d99906 | ||
|
|
f572bf987e | ||
|
|
82eee72019 | ||
|
|
b36a776a7f | ||
|
|
f06dd8725a | ||
|
|
b9fe52e811 | ||
|
|
293a06c39a | ||
|
|
521a0a3323 | ||
|
|
cbfb5a98b5 | ||
|
|
69ae454d4d | ||
|
|
31c24dd9f2 | ||
|
|
ed6f3945fd | ||
|
|
6b777ccbb5 | ||
|
|
f88690221b | ||
|
|
03b5c51730 | ||
|
|
7d6991e900 | ||
|
|
7fd04bd93a | ||
|
|
088d88cfe2 | ||
|
|
e29cd366a2 | ||
|
|
34350963d1 | ||
|
|
245b85692e | ||
|
|
e38aaddb5e | ||
|
|
296385c0f3 | ||
|
|
386886f71c | ||
|
|
a3d891a290 | ||
|
|
e947c362dd | ||
|
|
6ea68f233c | ||
|
|
6c81cd26cc | ||
|
|
a9d0e25627 | ||
|
|
9d5a3c16dd | ||
|
|
b3776468fa | ||
|
|
28a5f6bc38 | ||
|
|
ea69cda4b0 | ||
|
|
86f65a3f2b | ||
|
|
b778653f03 | ||
|
|
9dbe25709e | ||
|
|
60c5d4c42f | ||
|
|
6d8de3638c | ||
|
|
6692b17777 | ||
|
|
71f4934500 | ||
|
|
b73de73151 | ||
|
|
2cba0ea9f9 | ||
|
|
30c13eff37 | ||
|
|
386f3d5a5e | ||
|
|
87331dc419 | ||
|
|
d023b2d12f | ||
|
|
3679bb1cd9 | ||
|
|
0631d233d8 | ||
|
|
520cc9a7f8 | ||
|
|
78b23f3595 | ||
|
|
6a995bac43 | ||
|
|
ae6fae9b26 | ||
|
|
bbc6378b73 | ||
|
|
3ab46449f4 | ||
|
|
303e86adc8 | ||
|
|
70f57996b3 | ||
|
|
dc2ce71313 | ||
|
|
bd0ee420b5 | ||
|
|
845852d6b4 | ||
|
|
0e4ffd9d3b | ||
|
|
a7d6a612b8 | ||
|
|
722ca363f0 | ||
|
|
e566faaae6 | ||
|
|
d97605beaf | ||
|
|
7910b6c0ba | ||
|
|
c984d8fbab | ||
|
|
416eb4b9b3 | ||
|
|
a5b9b4bf02 | ||
|
|
11eaf1c98c | ||
|
|
9d445f371c | ||
|
|
15115b61c0 | ||
|
|
be5ad90703 | ||
|
|
d3b8f270ea | ||
|
|
7cd25062ac | ||
|
|
d7ea12f222 | ||
|
|
6d74ff2bf8 | ||
|
|
ddeb37f282 | ||
|
|
f5cd9c3563 | ||
|
|
a4870c79ca | ||
|
|
153ce89af3 | ||
|
|
b37a0a39e3 | ||
|
|
d2eae42c0e | ||
|
|
c1becaefe5 | ||
|
|
8ed0b6f312 | ||
|
|
4af4241ba4 | ||
|
|
ca7abbce8a | ||
|
|
4f439707fd | ||
|
|
9f433e6ee3 | ||
|
|
38e7b37c89 | ||
|
|
801d4f96a8 | ||
|
|
37ffe6a13a | ||
|
|
c8242e5cf4 | ||
|
|
a3cfe9d9b7 | ||
|
|
2be83f4543 | ||
|
|
f7da1caf8d | ||
|
|
8bcc1da2f3 | ||
|
|
142c4bf9f0 | ||
|
|
1e4a9534f4 | ||
|
|
15fdd5c90d | ||
|
|
6fc596ca90 | ||
|
|
2b760a7fa7 | ||
|
|
9602e68577 | ||
|
|
06abb2dd4c | ||
|
|
7f747a0d73 | ||
|
|
b617109fff | ||
|
|
48e1ae7f6a | ||
|
|
41e7f45258 | ||
|
|
981962b339 | ||
|
|
6d760b2c63 | ||
|
|
a527a3b8c2 | ||
|
|
ad85b0c526 | ||
|
|
756bcabbfe | ||
|
|
970dfbcd69 | ||
|
|
0379c480e0 | ||
|
|
86e528c667 | ||
|
|
69099e7ef5 | ||
|
|
5294a6f77a | ||
|
|
fae1a611d2 | ||
|
|
ed23da95b6 | ||
|
|
6f9e26f5c0 | ||
|
|
401c9aba4a | ||
|
|
3e8dbfaecf | ||
|
|
4008f4f891 | ||
|
|
e012d0635d | ||
|
|
ba3f37c9e4 | ||
|
|
399fc1bb33 | ||
|
|
a4269aadf3 | ||
|
|
788ac7fa54 | ||
|
|
ff5612c0c3 | ||
|
|
740ab81d03 | ||
|
|
575c4ed964 | ||
|
|
21f6511bc2 | ||
|
|
13835d04ac | ||
|
|
0396ade38b | ||
|
|
a266154e1f | ||
|
|
8ab4334505 | ||
|
|
1b05438fcb | ||
|
|
8b8065a870 | ||
|
|
1d774e5667 | ||
|
|
03be45ac0a | ||
|
|
0958905b1b | ||
|
|
0e3093979e | ||
|
|
58b61c252a | ||
|
|
0db733f18a | ||
|
|
90467a1412 | ||
|
|
e8025aa67a | ||
|
|
c089029b70 | ||
|
|
b19f840af8 | ||
|
|
e5709a32be | ||
|
|
f14f2d4378 | ||
|
|
cad22be394 | ||
|
|
b38ba27083 | ||
|
|
ff5c1c576c | ||
|
|
17be6d5210 | ||
|
|
ed65860861 | ||
|
|
ec49f07b0d | ||
|
|
f942ae4a7a | ||
|
|
1ec6a59dcf | ||
|
|
3835755259 | ||
|
|
35a4d70aad | ||
|
|
e2be2652ad | ||
|
|
a530c70b21 | ||
|
|
5ec20e267f | ||
|
|
99018b37ee | ||
|
|
97f8454ecc | ||
|
|
ade2f47829 | ||
|
|
dde5a6c52b | ||
|
|
f0da2842cf | ||
|
|
0be8a9126f | ||
|
|
6987a353de | ||
|
|
c5e2f08cf9 | ||
|
|
0dc6ba8309 | ||
|
|
9ec474f38a | ||
|
|
83978cdec8 | ||
|
|
ed9751d9fa | ||
|
|
b13d45d21d | ||
|
|
4891a735d3 | ||
|
|
fb8cc7c63f | ||
|
|
2be940e549 | ||
|
|
0387e70d76 | ||
|
|
09b7ceea95 | ||
|
|
c7a7fd0a12 | ||
|
|
8c49aa79e7 | ||
|
|
1ef9831018 | ||
|
|
953080e4fc | ||
|
|
683b1f0625 | ||
|
|
668b669d5b | ||
|
|
60668f823e | ||
|
|
b3e9a09abe | ||
|
|
fb0cee9a66 | ||
|
|
400f644286 | ||
|
|
d5697b29ee | ||
|
|
5ef6ca00b9 | ||
|
|
999952c5b9 | ||
|
|
c907ee0351 | ||
|
|
a7893ae858 | ||
|
|
bf1cf1459f | ||
|
|
1794f777f4 | ||
|
|
b21d3e3592 | ||
|
|
b786096863 | ||
|
|
f4137640f6 | ||
|
|
2e96ea4a89 | ||
|
|
cf5242a670 | ||
|
|
2c3bbf0a6c | ||
|
|
54c73b7723 | ||
|
|
7a34db0cfd | ||
|
|
fefb2f03c3 | ||
|
|
fc2644ae71 | ||
|
|
7c7672b3c0 | ||
|
|
aa07de5a50 | ||
|
|
360c569ce8 | ||
|
|
09d77d0c94 | ||
|
|
983f0b46f2 | ||
|
|
7c59199d49 | ||
|
|
bbff143d54 | ||
|
|
291909ecaf | ||
|
|
10492b238d | ||
|
|
2fdd0840d5 | ||
|
|
b248ba0a39 | ||
|
|
9fd7ac7d03 | ||
|
|
b873fc54ba | ||
|
|
e191780947 | ||
|
|
6db461e3b0 | ||
|
|
8073ce1690 | ||
|
|
a820a68619 | ||
|
|
fc849a9eeb | ||
|
|
13fe333b54 | ||
|
|
5f5a5d1f53 | ||
|
|
bc7d3b74f1 | ||
|
|
c7c53ad41d | ||
|
|
0e47639a44 | ||
|
|
bf2741376d | ||
|
|
e431b19bac | ||
|
|
f260f99d57 | ||
|
|
b89963a7c3 | ||
|
|
10ba799ab0 | ||
|
|
12b631a676 | ||
|
|
84a4d4b970 | ||
|
|
831ce3cda9 | ||
|
|
67379a3ffd | ||
|
|
7519d881ef | ||
|
|
ea6a8078b4 | ||
|
|
5afa2ffcaa | ||
|
|
3ff080c591 | ||
|
|
8290de964f | ||
|
|
895ee61642 | ||
|
|
d365bfe7e9 | ||
|
|
d864c6eacd | ||
|
|
4573877186 | ||
|
|
b3899056d9 | ||
|
|
faa9a52085 | ||
|
|
2fc1fc3a93 | ||
|
|
c93659e0e0 | ||
|
|
4dace48f51 | ||
|
|
08ba1b4472 | ||
|
|
78dafcba99 | ||
|
|
3ed2c32e0a | ||
|
|
a0e60d27ff | ||
|
|
2393b468a4 | ||
|
|
9bb210192d | ||
|
|
3972bd98fb | ||
|
|
c6f2821b9f | ||
|
|
16060b101b | ||
|
|
a6f53b5c0d | ||
|
|
920352da70 | ||
|
|
6595cae6e9 | ||
|
|
4379365cae | ||
|
|
5df6ec24bf | ||
|
|
9effc6ab31 | ||
|
|
88c547d1ca | ||
|
|
7c7ab99843 | ||
|
|
feea5003cc | ||
|
|
98124361ae | ||
|
|
bb867abe11 | ||
|
|
45b1fcdb4e | ||
|
|
0f155e699c | ||
|
|
d9cc3f3acb | ||
|
|
31d8c3ee85 | ||
|
|
ee7143cd02 | ||
|
|
4d7a4554f4 | ||
|
|
2679c68689 | ||
|
|
a70d6b350f | ||
|
|
c698ee14bb | ||
|
|
f8781ea6a0 | ||
|
|
141f26035d | ||
|
|
3058f662cf | ||
|
|
be291e1064 | ||
|
|
abb07a1b5e | ||
|
|
5a958655dd | ||
|
|
d6d207006a | ||
|
|
f2a5d3ae3a | ||
|
|
5c792f620b | ||
|
|
c4dcbf67a3 | ||
|
|
28776b9526 | ||
|
|
9ee071705b | ||
|
|
ee3cfa4184 | ||
|
|
4022fd3e79 | ||
|
|
8557b412f6 | ||
|
|
413d91dc29 | ||
|
|
a63b46bf36 | ||
|
|
b165e9f3f8 | ||
|
|
b07df8850a | ||
|
|
0a46160d94 | ||
|
|
316ce655a3 | ||
|
|
57460fe5a8 | ||
|
|
deea86c7f4 | ||
|
|
2ba9fb4019 | ||
|
|
14283662b9 | ||
|
|
9db5217a31 | ||
|
|
876514eb34 | ||
|
|
d4eded9fd6 | ||
|
|
b6512b10ae | ||
|
|
ca09c9ab4c | ||
|
|
b296e30f98 | ||
|
|
3501f17fd0 | ||
|
|
3af43af493 | ||
|
|
a5306421dd | ||
|
|
470d1a2f54 | ||
|
|
788b7a6a2b | ||
|
|
842167eb17 | ||
|
|
8dccbae35e | ||
|
|
7e71ecbaf6 | ||
|
|
a621795a3c | ||
|
|
12f5c3f726 | ||
|
|
b0f48b9533 | ||
|
|
f65754e6fc | ||
|
|
71d718a4a4 | ||
|
|
622fb968a2 | ||
|
|
6e523f01d0 | ||
|
|
d760669e80 | ||
|
|
1997149263 | ||
|
|
329d10268c | ||
|
|
ff752c60df | ||
|
|
439989adab | ||
|
|
d7b3179669 | ||
|
|
93d7d3ed2c | ||
|
|
cdb7502e54 | ||
|
|
d414fe28fa | ||
|
|
f0d34f383d | ||
|
|
9ff2f1a3db | ||
|
|
06243be91b | ||
|
|
665b6b308e | ||
|
|
556d2c920a | ||
|
|
39468b73a3 | ||
|
|
d5f2e6223f | ||
|
|
138b4e1719 | ||
|
|
a19a595343 | ||
|
|
4b4c2833d9 | ||
|
|
cc9c02fe68 | ||
|
|
7a64fff948 | ||
|
|
ee4c75c8b7 | ||
|
|
3877ccfe1b | ||
|
|
582a344cd6 | ||
|
|
40182cbd82 | ||
|
|
ff13206c7e | ||
|
|
5b07bd3f91 | ||
|
|
6e312c56ad | ||
|
|
0dfafd77d4 | ||
|
|
e702073235 | ||
|
|
7f4f7f70ce | ||
|
|
39f3c9de0b | ||
|
|
1da6c1495a | ||
|
|
9efd3fb604 | ||
|
|
a27650cc98 | ||
|
|
e9f83147d5 | ||
|
|
d442c3ef0c | ||
|
|
4648d33d07 | ||
|
|
cf8e1a0093 | ||
|
|
1946a45329 | ||
|
|
21c401006c | ||
|
|
739092e64a | ||
|
|
1f30e048bd | ||
|
|
98bcfdca83 | ||
|
|
886656e4ac | ||
|
|
662a2122f6 | ||
|
|
4ece923a4b | ||
|
|
7a2a1a7456 | ||
|
|
3124840185 | ||
|
|
5f5832e318 | ||
|
|
f8e287cca2 | ||
|
|
9f96286c29 | ||
|
|
1ff2245c23 | ||
|
|
c731bb1ee1 | ||
|
|
d2d6663428 | ||
|
|
e7d3553906 | ||
|
|
2d7a8b4531 | ||
|
|
0a87fed794 | ||
|
|
ca0c8673b2 | ||
|
|
c9f56d639b | ||
|
|
c7b17836ea | ||
|
|
ceb79c9a50 | ||
|
|
2276379a71 | ||
|
|
ea14d5159c | ||
|
|
72d82e21d4 | ||
|
|
012d273ede | ||
|
|
376cb3fe64 | ||
|
|
17901569da | ||
|
|
9d0dc63c8b | ||
|
|
2e04681248 | ||
|
|
290ae4791e | ||
|
|
b737ff01e4 | ||
|
|
2a6712ddef | ||
|
|
116bcb3ea4 | ||
|
|
5cdd7848f4 | ||
|
|
6d75ff138c | ||
|
|
3127160626 | ||
|
|
4ededc698f | ||
|
|
a2d9b1a7e9 | ||
|
|
05131f5853 | ||
|
|
cdb0339319 | ||
|
|
b49b98d50c | ||
|
|
c3eb3a7687 | ||
|
|
1b01a2f65a | ||
|
|
967b5eb1f3 | ||
|
|
847e2856a2 | ||
|
|
2a70e98b05 | ||
|
|
c68c157573 | ||
|
|
5a3c597fd5 | ||
|
|
e52d316751 | ||
|
|
92330ba9c8 | ||
|
|
3acc85caa8 | ||
|
|
438e0050df | ||
|
|
4047e4dfb1 | ||
|
|
99d1e264a8 | ||
|
|
329c46d36e | ||
|
|
7b300a803c | ||
|
|
109b3bb49b | ||
|
|
0de57b98bf | ||
|
|
eb08f86521 | ||
|
|
c6f680ee49 | ||
|
|
5d0e7fb4ed | ||
|
|
57c0f72b1d | ||
|
|
4698fb0543 | ||
|
|
243cd3fd2c | ||
|
|
132306c888 | ||
|
|
fd417db274 | ||
|
|
15891d366d | ||
|
|
195fe03075 | ||
|
|
449c092010 | ||
|
|
90191e6ff2 | ||
|
|
14d2b5a13f | ||
|
|
c8ad1f3e3a | ||
|
|
93f36fb77f | ||
|
|
bd67a3151a | ||
|
|
ff86c6ed00 | ||
|
|
ba309e0da5 | ||
|
|
b0b507b197 | ||
|
|
286cd2006b | ||
|
|
6d0abc6b48 | ||
|
|
b1640df5e6 | ||
|
|
b9ae22d758 | ||
|
|
7e318dad42 | ||
|
|
59ca324c35 | ||
|
|
ed53b4b674 | ||
|
|
3685701529 | ||
|
|
8edc0e450d | ||
|
|
00877fe47b | ||
|
|
54c24193f5 | ||
|
|
80bf4eb035 | ||
|
|
b8a6efbcc0 | ||
|
|
1f1c664b78 | ||
|
|
de3b1c4506 | ||
|
|
b61be64370 | ||
|
|
7ecccc3099 | ||
|
|
701b4a8363 | ||
|
|
df452b47a1 | ||
|
|
3a6bea990b | ||
|
|
597590da74 | ||
|
|
1ca813083f | ||
|
|
b51241a346 | ||
|
|
d01f8ee684 | ||
|
|
e4fdfa9d31 | ||
|
|
0650a16a22 | ||
|
|
7b5ea9a5a8 | ||
|
|
adfa778a58 | ||
|
|
4dab0d3175 | ||
|
|
016997acaf | ||
|
|
6e55201144 | ||
|
|
3843f54974 | ||
|
|
55c9286dea | ||
|
|
49ae67cba3 | ||
|
|
9952331d5d | ||
|
|
286f298bb7 | ||
|
|
e309586aeb | ||
|
|
c6cc871df8 | ||
|
|
fa68466e90 | ||
|
|
d3e67ba8ca | ||
|
|
f64f22e2d6 | ||
|
|
8791d01fee | ||
|
|
e0c2211c34 | ||
|
|
88ae884095 | ||
|
|
4b48b62ab0 | ||
|
|
3227cd8aac | ||
|
|
e39de22822 | ||
|
|
20ca6d6545 | ||
|
|
6997943f22 | ||
|
|
4dbf872a9f | ||
|
|
25ae0b39b7 | ||
|
|
186a2772e8 | ||
|
|
45db25817f | ||
|
|
9161308252 | ||
|
|
e0bc3cf1a0 | ||
|
|
7803756e97 | ||
|
|
599f18db8a | ||
|
|
81e89c0647 | ||
|
|
a05ac83641 | ||
|
|
1b60789020 | ||
|
|
5555d2a000 | ||
|
|
407198e17d | ||
|
|
753cb9204d | ||
|
|
5e36b86c46 | ||
|
|
8d5ae472e5 | ||
|
|
48367c5be9 | ||
|
|
46b9cc1248 | ||
|
|
ebbf7d8e68 | ||
|
|
260e8f2476 | ||
|
|
c4db22bd4f | ||
|
|
dcd4afc716 | ||
|
|
00d9bf8107 | ||
|
|
3f5cdf20cd | ||
|
|
35ebc5d343 | ||
|
|
07e4ac7b00 | ||
|
|
cd8ea8b437 | ||
|
|
8767435ef8 | ||
|
|
bf81d5607a | ||
|
|
7168880caa | ||
|
|
149ab6921e | ||
|
|
1d0a2b919f | ||
|
|
d84e1ae5f2 | ||
|
|
a54285a715 | ||
|
|
ec8f377748 | ||
|
|
2cec4b4a77 | ||
|
|
2f201d0e5e | ||
|
|
2d5adc5823 | ||
|
|
f6a3ef4490 | ||
|
|
a2f4ccd839 | ||
|
|
c9b9077b44 | ||
|
|
d2df8dddc8 | ||
|
|
215a314f19 | ||
|
|
95ced7a7be | ||
|
|
2729720fd3 | ||
|
|
07a25c249b | ||
|
|
e59f6981e6 | ||
|
|
a5ddb347e5 | ||
|
|
5723db017a | ||
|
|
e6f8d86409 | ||
|
|
9a96f930a7 | ||
|
|
c8591b2ac7 | ||
|
|
6fc4c99b2f | ||
|
|
6bd3864b41 | ||
|
|
e9f9c6be26 | ||
|
|
2539769356 | ||
|
|
192fa11dab | ||
|
|
6f3cd63551 | ||
|
|
da42ee3a1f | ||
|
|
461eb1ac6a | ||
|
|
ac8a931889 | ||
|
|
ba222c6e35 | ||
|
|
865b9d3701 | ||
|
|
fb4584b83d | ||
|
|
e77803edc9 | ||
|
|
2f99e5e35a | ||
|
|
2955f13ecc | ||
|
|
05fb515863 | ||
|
|
d41ad502b8 | ||
|
|
8dade001b8 | ||
|
|
dd5b2974c0 | ||
|
|
f3c20bf7e6 | ||
|
|
389498764a | ||
|
|
e892557ac6 | ||
|
|
9f01f1453c | ||
|
|
a35e45a79e | ||
|
|
a2a37f8fee | ||
|
|
d644d4e14e | ||
|
|
b680b09bc8 | ||
|
|
206ff950ba | ||
|
|
d459f6b32a | ||
|
|
bb2a2bb3ff | ||
|
|
859165e005 | ||
|
|
64a3ac8f51 | ||
|
|
06738cac05 | ||
|
|
8cdb78d0dd | ||
|
|
8db4540263 | ||
|
|
9bb148ff4e | ||
|
|
1dffc9bcb0 | ||
|
|
313a71048e | ||
|
|
ec50952652 | ||
|
|
6fa1d69804 | ||
|
|
56d49cbf13 | ||
|
|
12a15f939c | ||
|
|
03885b6863 | ||
|
|
f1aabd5c60 | ||
|
|
61712a1f0d | ||
|
|
b96c213356 | ||
|
|
0dc622c777 | ||
|
|
e0ed1b458d | ||
|
|
8b59522d67 | ||
|
|
8a689fd04d | ||
|
|
01cfbe14f1 | ||
|
|
51514ae62f | ||
|
|
086829459b | ||
|
|
81c215de54 | ||
|
|
8c3e4b43f1 | ||
|
|
767ce95a11 | ||
|
|
59f8c1767d | ||
|
|
ec808a033b | ||
|
|
9c17acdfe8 | ||
|
|
0a9f894ff0 | ||
|
|
98f2e3d974 | ||
|
|
fccc6ea295 | ||
|
|
eb2d70293d | ||
|
|
1e4e9548b1 | ||
|
|
b22835dd68 | ||
|
|
bf29fa49d3 | ||
|
|
e5b9338ada | ||
|
|
34fbbfe34e | ||
|
|
ac6e1e3e8d | ||
|
|
c70037445a | ||
|
|
dfd024d3a8 | ||
|
|
2bfb3e519a | ||
|
|
d6f894edf8 | ||
|
|
dd11efb673 | ||
|
|
e7a71d030a | ||
|
|
8262a3f6ca | ||
|
|
a326be8f48 | ||
|
|
a8f352fd56 | ||
|
|
d13f356bf5 | ||
|
|
0be6c87a56 | ||
|
|
067184f32d | ||
|
|
c62f9f0b2f | ||
|
|
1a53400723 | ||
|
|
0efcdc3ad9 | ||
|
|
8ae2ca5ff7 | ||
|
|
973cfb19b7 | ||
|
|
23957e16d5 | ||
|
|
e38e9e588e | ||
|
|
a7feae8a6e | ||
|
|
187486c7bb | ||
|
|
83eeeb59ed | ||
|
|
1c1487659e | ||
|
|
c63b155d16 | ||
|
|
5dc27b75eb | ||
|
|
6fc1f948c2 | ||
|
|
c6f3701a71 | ||
|
|
9bdff1ee5c | ||
|
|
30bd294fc6 | ||
|
|
c0b5886f18 | ||
|
|
bad8b5848f | ||
|
|
68d84fa3eb | ||
|
|
9a2b6bda59 | ||
|
|
cb08b8eb7e | ||
|
|
6e826bb6a4 | ||
|
|
ebd9225245 | ||
|
|
543eaed88c | ||
|
|
8a81716325 | ||
|
|
a59c3731c3 | ||
|
|
9e072e7072 | ||
|
|
61a1effcf1 | ||
|
|
46e9aac160 | ||
|
|
945058e844 | ||
|
|
be36c0ec49 | ||
|
|
3d5d5196d0 | ||
|
|
3be9089cd3 | ||
|
|
4007e0d139 | ||
|
|
6bbbcf42f8 | ||
|
|
ddb31b62e5 | ||
|
|
dcd90bc501 | ||
|
|
3366541aab | ||
|
|
62a40438ab | ||
|
|
836bafac6e | ||
|
|
3d962ed68f | ||
|
|
7076d1439b | ||
|
|
2dba563206 | ||
|
|
0fc9a3dce3 | ||
|
|
2caa558e7c | ||
|
|
5da4d94adc | ||
|
|
4ea8533f30 | ||
|
|
fbd89d3a1a | ||
|
|
86bdfb3722 | ||
|
|
467f454c09 | ||
|
|
1d6a2c7326 | ||
|
|
0b17a75f13 | ||
|
|
516b79299a | ||
|
|
8100989dbb | ||
|
|
ef199faeda | ||
|
|
758f674240 | ||
|
|
37672e676d | ||
|
|
761407217a | ||
|
|
fad6a65f3c | ||
|
|
171d7d5793 | ||
|
|
e79d64b52b | ||
|
|
358b3ce26b | ||
|
|
d837eebdcc | ||
|
|
6bf324c4fd | ||
|
|
351be15dc4 | ||
|
|
cce2475889 | ||
|
|
fd818eb3aa | ||
|
|
7755376d7c | ||
|
|
803b1056ca | ||
|
|
a9382908ae | ||
|
|
5ee11ece1a | ||
|
|
f1d117f9f9 | ||
|
|
7720ed7037 | ||
|
|
dc7b1640ed | ||
|
|
08e846e3d9 | ||
|
|
909887be5e | ||
|
|
ea91741212 | ||
|
|
813a1868c6 | ||
|
|
2c49a5a7cc | ||
|
|
e866931169 | ||
|
|
f61cacad16 | ||
|
|
93945bb616 | ||
|
|
88bba90e6e | ||
|
|
c02af0773f | ||
|
|
bba1e4d11f | ||
|
|
5ae6946e11 | ||
|
|
65cfc5d16d | ||
|
|
0f2bbb8763 | ||
|
|
e19271418c | ||
|
|
0d3ce181e1 | ||
|
|
78d8e56a8e | ||
|
|
32e7600cbd | ||
|
|
aa9ebf4494 | ||
|
|
f6632c1ef4 | ||
|
|
2c2bb4a458 | ||
|
|
ff58a4b099 | ||
|
|
7991a9636e | ||
|
|
32b7eb9b6b | ||
|
|
aeb7a93796 | ||
|
|
34a45b0029 | ||
|
|
a17ac481ab | ||
|
|
6185506b85 | ||
|
|
fa25bdc3ef | ||
|
|
d36313a418 | ||
|
|
ce05af1d32 | ||
|
|
ea44a7d759 | ||
|
|
243a5ba90f | ||
|
|
b343d75a5a | ||
|
|
aeaec150c0 | ||
|
|
ad5c0b5525 | ||
|
|
90423c1200 | ||
|
|
975b5b42d2 | ||
|
|
20c40a0807 | ||
|
|
1518c7aac2 | ||
|
|
ba428469e6 | ||
|
|
4961c3b4af | ||
|
|
921a46446d | ||
|
|
17f5531df0 | ||
|
|
d18c70b4df | ||
|
|
462de06d96 | ||
|
|
b3103ef328 | ||
|
|
1e6a29dbee | ||
|
|
487c65373b | ||
|
|
98c92abf4e | ||
|
|
01c62d8f9d | ||
|
|
35216ca66c | ||
|
|
59a5361fc4 | ||
|
|
113f2a0113 | ||
|
|
37160ef249 | ||
|
|
05babeeef5 | ||
|
|
02b351ad95 | ||
|
|
edb42ac367 | ||
|
|
f194dabb09 | ||
|
|
0438b15353 | ||
|
|
8d2c7d28cc | ||
|
|
7162a25b0b | ||
|
|
ffe898ca9f | ||
|
|
6c7a6c07ee | ||
|
|
4bcaf8086e | ||
|
|
865738f271 | ||
|
|
9c159ea320 | ||
|
|
79c42c6600 | ||
|
|
d742cdf327 | ||
|
|
7e35dfff3d | ||
|
|
1babf24949 | ||
|
|
d06f64dd29 | ||
|
|
6a5706a3a5 | ||
|
|
b804340f01 | ||
|
|
e70d12be9e | ||
|
|
6ddce3b6a7 | ||
|
|
79e4194e59 | ||
|
|
475c751076 | ||
|
|
099aca0311 | ||
|
|
96b93199a0 | ||
|
|
ec19a5a62f | ||
|
|
7038d527a6 | ||
|
|
d2ebc1dfa0 | ||
|
|
52f76a7682 | ||
|
|
0ab5e0e280 | ||
|
|
1281a5e3d5 | ||
|
|
cf518842b4 | ||
|
|
dc1be80b26 | ||
|
|
bead3fc2c0 | ||
|
|
de3692152f | ||
|
|
46e681ca62 | ||
|
|
f3c177312f | ||
|
|
c452307543 | ||
|
|
bea2f61935 | ||
|
|
8cf54e6e13 | ||
|
|
823268475c | ||
|
|
2ce9693341 | ||
|
|
d17cd1c385 | ||
|
|
310f54439c | ||
|
|
c219934a87 | ||
|
|
84e16ecdb5 | ||
|
|
3bd9048854 | ||
|
|
f874903a35 | ||
|
|
521ddeaecc | ||
|
|
f9467799c1 | ||
|
|
ce1c28af19 | ||
|
|
2455ce226d | ||
|
|
24ab6328f7 | ||
|
|
62e38da133 | ||
|
|
5b613cff97 | ||
|
|
996fe0a836 | ||
|
|
059e87ce7b | ||
|
|
b8dd440097 | ||
|
|
7126d8c21b | ||
|
|
e980d54371 | ||
|
|
ec6559c93e | ||
|
|
6d41ef6ce5 | ||
|
|
ed997ca884 | ||
|
|
5bba2cc74b | ||
|
|
a73128132c | ||
|
|
2c806677ba | ||
|
|
03b18d96ad | ||
|
|
832a1e7395 | ||
|
|
d6f989d1ee | ||
|
|
e13efd652c | ||
|
|
dc9ef7a028 | ||
|
|
ebf5552754 | ||
|
|
c682e83760 | ||
|
|
fbf6b89a84 | ||
|
|
54b2aadf40 | ||
|
|
9e23089757 | ||
|
|
870353f9d1 | ||
|
|
0650d875e8 | ||
|
|
58afa3e7fb | ||
|
|
dec6a245a9 | ||
|
|
d13b5db28e | ||
|
|
bd046f0201 | ||
|
|
c19d86338d | ||
|
|
e5d399f667 | ||
|
|
4d44893d60 | ||
|
|
a46cc72fd2 | ||
|
|
89bce34cfb | ||
|
|
0475b86268 | ||
|
|
6f8bd07b40 | ||
|
|
696052b78e | ||
|
|
782a37e411 | ||
|
|
25b25bd1a2 | ||
|
|
792343a694 | ||
|
|
5627fc8e7b | ||
|
|
c57a9960b5 | ||
|
|
f380cd7d98 | ||
|
|
d2a3352755 | ||
|
|
b9141fcefa | ||
|
|
a68f04f41c | ||
|
|
c5b8faf3b1 | ||
|
|
8918bf2430 | ||
|
|
75f8f3ce8b | ||
|
|
530efdb525 | ||
|
|
ceec205594 | ||
|
|
9737943c4c | ||
|
|
d2e33bed94 | ||
|
|
25555737bd | ||
|
|
e1153fd385 | ||
|
|
0c35eb915c | ||
|
|
6fa41e8a21 | ||
|
|
3af1ebe31e | ||
|
|
8df2c89cd4 | ||
|
|
24d39aa142 | ||
|
|
7e25b8f932 | ||
|
|
93b087da97 | ||
|
|
c608e46675 | ||
|
|
d5fddeb208 | ||
|
|
efe228a42e | ||
|
|
56ca71bd8e | ||
|
|
7e9fbf5518 | ||
|
|
6857e761cf | ||
|
|
1943ff9910 | ||
|
|
98b4241b2f | ||
|
|
f0582ee661 | ||
|
|
e6fa4a095e | ||
|
|
8c3c020a56 | ||
|
|
97c2309e19 | ||
|
|
a30491b25f | ||
|
|
32c84c8f3d | ||
|
|
dc4a15bb69 | ||
|
|
2a11eea2e1 | ||
|
|
dc5ba5c392 | ||
|
|
726cf41b80 | ||
|
|
3f694b1265 | ||
|
|
71f3bbd53f | ||
|
|
d0a3aa04c8 | ||
|
|
b3d10d7bf1 | ||
|
|
499a161640 | ||
|
|
980cf7959c | ||
|
|
b83e114008 | ||
|
|
2960604178 | ||
|
|
c817e60796 | ||
|
|
219e040062 | ||
|
|
ba337a5f3e | ||
|
|
9cc66e6f8b | ||
|
|
1a4b6136be | ||
|
|
f9fc7d8da4 | ||
|
|
b5184347b6 | ||
|
|
f72b184e3e | ||
|
|
b6c5ea358e | ||
|
|
870762d8e3 | ||
|
|
d4836062ff | ||
|
|
f84d6048cf | ||
|
|
edfff8a26a | ||
|
|
52e8e908d6 | ||
|
|
ce700e70d2 | ||
|
|
840bc23ee1 | ||
|
|
dac3c36feb | ||
|
|
43a44a1e2a | ||
|
|
f5b077a388 | ||
|
|
dae0822698 | ||
|
|
182d1f60d2 | ||
|
|
da532741c9 | ||
|
|
2c893455ad | ||
|
|
7044863afc | ||
|
|
9bdfb30720 | ||
|
|
d860272b00 | ||
|
|
0da6c851bd | ||
|
|
4417a8bd40 | ||
|
|
e8eb64c878 | ||
|
|
0e92b70f71 | ||
|
|
7a5a5cb06f | ||
|
|
972282bfbc | ||
|
|
daa0000a47 | ||
|
|
971248911b | ||
|
|
6dd70f472a | ||
|
|
815aa3555f | ||
|
|
b559a1e6f0 | ||
|
|
36c90588fc | ||
|
|
64a20df41c | ||
|
|
ff455b1806 | ||
|
|
d81498a824 | ||
|
|
386220ada2 | ||
|
|
9a0cf1ad84 | ||
|
|
ea7b3d8fd7 | ||
|
|
1ea2c6a2f6 | ||
|
|
da3a375f7a | ||
|
|
12dba91d9d | ||
|
|
23ce26fe22 | ||
|
|
80202ecd98 | ||
|
|
5b29e2ac60 | ||
|
|
1fa8ddaf51 | ||
|
|
a7a66f4b6d | ||
|
|
616c6208aa | ||
|
|
3b4be8a99d | ||
|
|
05bfdefdf8 | ||
|
|
3eb23ab3d2 | ||
|
|
4491acea0b | ||
|
|
d4aa0496fb | ||
|
|
0f49ede3b1 | ||
|
|
573e57f83f | ||
|
|
69a82801ef | ||
|
|
bd364a70b5 | ||
|
|
2e8c7f2975 | ||
|
|
55761e14af | ||
|
|
c64d7cd381 | ||
|
|
53f3ebce92 | ||
|
|
351aefc8a0 | ||
|
|
e22fddbff6 | ||
|
|
a635143d62 | ||
|
|
ad48a46fc9 | ||
|
|
96f82296ae | ||
|
|
1456c3b298 | ||
|
|
a30832cedd | ||
|
|
a693b8d2cb | ||
|
|
c71b47b9e6 | ||
|
|
382a1a6bea | ||
|
|
99e2a2e156 | ||
|
|
172c87f7ca | ||
|
|
5e4f234918 | ||
|
|
e587cb6ac5 | ||
|
|
424f6dc4ad | ||
|
|
e66b3e8e3b | ||
|
|
73e62cdc11 | ||
|
|
74b5744b4b | ||
|
|
65d01ed981 | ||
|
|
3e74542b5d | ||
|
|
daaea2ef94 | ||
|
|
cbe6bcd593 | ||
|
|
bed744c15d | ||
|
|
fde44d055b | ||
|
|
52f2f3eae4 | ||
|
|
65079de265 | ||
|
|
960ee343f3 | ||
|
|
f9411bb2af | ||
|
|
874a4fd80d | ||
|
|
bbf98c19a8 | ||
|
|
820aa36192 | ||
|
|
69ad7c1aff | ||
|
|
75fad6eaa7 | ||
|
|
94424fabd0 | ||
|
|
0a182731e4 | ||
|
|
79b3966a34 | ||
|
|
b719e3d323 | ||
|
|
ba14fff2af | ||
|
|
f3f6c17250 | ||
|
|
2a434c479d | ||
|
|
10670c641b | ||
|
|
72b50d7fd2 | ||
|
|
8380b37529 | ||
|
|
4d95ccc696 | ||
|
|
3b5834d78b | ||
|
|
2c711a2502 | ||
|
|
36ddbdbbe2 | ||
|
|
c046a59e7f | ||
|
|
511a5f3ad8 | ||
|
|
5726f4aaac | ||
|
|
872b97a752 | ||
|
|
6e41729eb8 | ||
|
|
0fbbc6ce13 | ||
|
|
8e5f7cf3dc | ||
|
|
5fa417a9c0 | ||
|
|
b93c1332d1 | ||
|
|
a7e2da0585 | ||
|
|
cdcf7aaf07 | ||
|
|
94f88a4f14 | ||
|
|
a13efe5665 | ||
|
|
d707e133d3 | ||
|
|
9278655de1 | ||
|
|
462835faa0 | ||
|
|
33dea28e23 | ||
|
|
7ffca95bb6 | ||
|
|
eae8784ae2 | ||
|
|
d75c5f06f0 | ||
|
|
a6292f2a6d | ||
|
|
3a8b6a9948 | ||
|
|
84fd8ea4bd | ||
|
|
b63b775143 | ||
|
|
ebc9abf6c0 | ||
|
|
0154bcf0a7 | ||
|
|
1a39fa0073 | ||
|
|
02aeb23f1f | ||
|
|
b6e97cea2c | ||
|
|
5dfd775384 | ||
|
|
cd4c26a27f | ||
|
|
f9bd70878b | ||
|
|
ee54e43702 | ||
|
|
12ac6f9f11 | ||
|
|
7b408a08ef | ||
|
|
3959c60250 | ||
|
|
cd466297f4 | ||
|
|
2a57a934bb | ||
|
|
c8250560cd | ||
|
|
b167ca28b0 | ||
|
|
42b5c54092 | ||
|
|
ab852ffe66 | ||
|
|
dfb679e5c7 | ||
|
|
b627165a75 | ||
|
|
489bf2fbdf | ||
|
|
8d2d4f2026 | ||
|
|
1368dc905a | ||
|
|
72abf1d880 | ||
|
|
f2e3d659ea | ||
|
|
b6d7a48480 | ||
|
|
15fd61e492 | ||
|
|
400dede7a6 | ||
|
|
91c631c558 | ||
|
|
599771c9b0 | ||
|
|
7012268499 | ||
|
|
6255e1b5f0 | ||
|
|
eb2dd721ab | ||
|
|
a1991f101d | ||
|
|
b475be8d77 | ||
|
|
b39b36eeb5 | ||
|
|
42beb34826 | ||
|
|
4125cf5067 | ||
|
|
96bffe6a4a | ||
|
|
254944d890 | ||
|
|
b45035ee14 | ||
|
|
209da6efee | ||
|
|
a980f56d2a | ||
|
|
1ef10bd81a | ||
|
|
fc5c61df97 | ||
|
|
0e6cacbbb6 | ||
|
|
e6771e50a9 | ||
|
|
d85050930b | ||
|
|
5f3191097d | ||
|
|
6e2761e928 | ||
|
|
a2167d2d1d | ||
|
|
b185993628 | ||
|
|
ca12090800 | ||
|
|
e8905d9816 | ||
|
|
a16915cb0b | ||
|
|
10e80a212f | ||
|
|
9b1fe5a062 | ||
|
|
c3f0ed04a6 | ||
|
|
89764fd494 | ||
|
|
c771a70882 | ||
|
|
3dadb176ce | ||
|
|
2258242f6c | ||
|
|
efc8ca105d | ||
|
|
78c3b21bfa | ||
|
|
1dede50c85 | ||
|
|
c0663a97a5 | ||
|
|
3c4be983d5 | ||
|
|
0926438aad | ||
|
|
d55aa53816 | ||
|
|
5c8b148605 | ||
|
|
c217690f4c | ||
|
|
bdba904d7c | ||
|
|
4173a22832 | ||
|
|
3f61871f38 | ||
|
|
6cf3274732 | ||
|
|
095d95d0a8 | ||
|
|
46c67b5279 | ||
|
|
d5617bccab | ||
|
|
d38de32b40 | ||
|
|
00ab1e3f8b | ||
|
|
5c9eae9647 | ||
|
|
cab1c8ade1 | ||
|
|
f5bfc8b10d | ||
|
|
fc0f2d5031 | ||
|
|
27e21a4adc | ||
|
|
d658922f36 | ||
|
|
23e34c729b | ||
|
|
861c624acb | ||
|
|
c54998209d | ||
|
|
9ab9d4ac0a | ||
|
|
18b3d24692 | ||
|
|
d4016dd4d0 | ||
|
|
9a471aea06 | ||
|
|
6515946e4d | ||
|
|
f881095a69 | ||
|
|
43254b1185 | ||
|
|
b2b316ab51 | ||
|
|
fd7d09e39a | ||
|
|
25d1410592 | ||
|
|
2f65269b77 | ||
|
|
80b21b0b50 | ||
|
|
c101e3b086 | ||
|
|
f82bddb76c | ||
|
|
e58b5dd8e8 | ||
|
|
53d7985fa1 | ||
|
|
76ee08995e | ||
|
|
6336898318 | ||
|
|
d8106dfee2 | ||
|
|
9568f1b5c3 | ||
|
|
5fd459f0ab | ||
|
|
64e353daec | ||
|
|
2465451549 | ||
|
|
e38b557a74 | ||
|
|
8a35706cb1 | ||
|
|
26a3549fa0 | ||
|
|
cf1b05e7dd | ||
|
|
3556560b38 | ||
|
|
d528658f97 | ||
|
|
f43c89bf71 | ||
|
|
d540685159 | ||
|
|
a7d2f7795a | ||
|
|
8f95d94b4f | ||
|
|
5d5c80ace7 | ||
|
|
b5ca3d1ed0 | ||
|
|
a18dcfb533 | ||
|
|
1e482f7ca6 | ||
|
|
e33fd978a8 | ||
|
|
17c3e42b21 | ||
|
|
2e5ff5d11c | ||
|
|
7afa7b079c | ||
|
|
f9fb138bdd | ||
|
|
e49622ef17 | ||
|
|
044abcf91b | ||
|
|
4fbde0143a | ||
|
|
1aae627433 | ||
|
|
ed1289140e | ||
|
|
8527b92738 | ||
|
|
59e1bb62de | ||
|
|
301e821d3b | ||
|
|
61d8cb80e4 | ||
|
|
351bf47486 | ||
|
|
5339307ca7 | ||
|
|
538d5e81a7 | ||
|
|
5146908366 | ||
|
|
b062ee2826 | ||
|
|
0e0f706f2e | ||
|
|
34507894e9 | ||
|
|
c0fcaacb8d | ||
|
|
2bc1d7598e | ||
|
|
169470b621 | ||
|
|
d3b4a0f322 | ||
|
|
0190769d4f | ||
|
|
0d59090eaf | ||
|
|
f582793f1b | ||
|
|
077c4d1a35 | ||
|
|
61158adbcf | ||
|
|
99a150fc26 | ||
|
|
66e5b7f53c | ||
|
|
90b7423846 | ||
|
|
f401655ee8 | ||
|
|
845b1df617 | ||
|
|
32e53e506d | ||
|
|
c6958856f8 | ||
|
|
4e73e7ac16 | ||
|
|
a8215f3774 | ||
|
|
11e520256b | ||
|
|
509278c7d2 | ||
|
|
426fc74255 | ||
|
|
06c51c80d7 | ||
|
|
3324f8f4b8 | ||
|
|
864ec23ec0 | ||
|
|
5da88e5ba4 | ||
|
|
8d21033e52 | ||
|
|
289ed221d0 | ||
|
|
898fec25e5 | ||
|
|
594753751a | ||
|
|
585aaa922f | ||
|
|
3cc78c578a | ||
|
|
87415ed135 | ||
|
|
7a5b7def16 | ||
|
|
909bf00ab4 | ||
|
|
0644371f09 | ||
|
|
d098140177 | ||
|
|
707c49ab77 | ||
|
|
a8402e1978 | ||
|
|
bc5fe20e33 | ||
|
|
9711057499 | ||
|
|
d34991ed97 | ||
|
|
a927e401f1 | ||
|
|
9981b8be03 | ||
|
|
73d6bf290e | ||
|
|
8de2ef4f3b | ||
|
|
485922fe20 | ||
|
|
9a4b04139d | ||
|
|
2ba1e8fccc | ||
|
|
0c506d9a40 | ||
|
|
910440212b | ||
|
|
8dd6036da4 | ||
|
|
b4a39a569a | ||
|
|
8d7da8864e | ||
|
|
9fb16c608d | ||
|
|
5a036adb32 | ||
|
|
4b42d7ae98 | ||
|
|
4b795cc3a0 | ||
|
|
a532faa7b7 | ||
|
|
c122e5e7a3 | ||
|
|
fe456c33a4 | ||
|
|
c571aeae6f | ||
|
|
d6a05ea5e6 | ||
|
|
c2bd285160 | ||
|
|
c6856ef42b | ||
|
|
58ea7af08c | ||
|
|
8e4a96dcb1 | ||
|
|
12494fd3e5 | ||
|
|
9493f1df09 | ||
|
|
f2a3f0fe3d | ||
|
|
cfe1ec8d1f | ||
|
|
d4fed28523 | ||
|
|
bf75c30493 | ||
|
|
647c8edf82 | ||
|
|
749c2dc4ab | ||
|
|
5392675f4c | ||
|
|
900f5f8187 | ||
|
|
8deeeb07ea | ||
|
|
37f274ced9 | ||
|
|
e8a40f6571 | ||
|
|
e858ac1546 | ||
|
|
91e4512619 | ||
|
|
5f129d15b1 | ||
|
|
8542953f74 | ||
|
|
3de08fc9de | ||
|
|
25de8ca372 | ||
|
|
ed2368538a | ||
|
|
8ec016236a | ||
|
|
fb7817fe7c | ||
|
|
5680d14ecd | ||
|
|
bf09a32006 | ||
|
|
2ce5ca4375 | ||
|
|
dd0c58c69b | ||
|
|
3af072cc63 | ||
|
|
651ef6be82 | ||
|
|
5e62f7038f | ||
|
|
6744c143a5 | ||
|
|
630b4c2111 | ||
|
|
64f1fd749f | ||
|
|
a3390bb507 | ||
|
|
0abb3d7c11 | ||
|
|
d1b36fbe7f | ||
|
|
07113beea3 | ||
|
|
7891cead11 | ||
|
|
54feef9366 | ||
|
|
0641b3883d | ||
|
|
6e89eb9a52 | ||
|
|
f201498f99 | ||
|
|
39fc633957 | ||
|
|
3d9513ced4 | ||
|
|
a538e369db | ||
|
|
95308c5f58 | ||
|
|
74e53e8bc0 | ||
|
|
eeaf162626 | ||
|
|
52f3043f15 | ||
|
|
6b58c79603 | ||
|
|
65b977f249 | ||
|
|
485cac0e86 | ||
|
|
44190723a8 | ||
|
|
bac10d6aa3 | ||
|
|
3da4ed712e | ||
|
|
65e88e6b3c | ||
|
|
97d7e5aedb | ||
|
|
e903e37d0a | ||
|
|
08525624be | ||
|
|
11721819a7 | ||
|
|
87371d48cc | ||
|
|
4079a8f298 | ||
|
|
7060c9d942 | ||
|
|
83baa0b778 | ||
|
|
bd15208cd7 | ||
|
|
b8cac455bd | ||
|
|
19e3f8c30b | ||
|
|
13dc67cda7 | ||
|
|
1cae10a36c | ||
|
|
9aa24bd034 | ||
|
|
267a575768 | ||
|
|
466a8ebf9d | ||
|
|
92384bfd0b | ||
|
|
73b7bf961b | ||
|
|
a0c4e85c48 | ||
|
|
2e732e9628 | ||
|
|
4d25c81bdd | ||
|
|
f8aee4460a | ||
|
|
dc964ab0d3 | ||
|
|
daa39a1f64 | ||
|
|
1f5c98270d | ||
|
|
8626490ca7 | ||
|
|
25de9addb6 | ||
|
|
8997872656 | ||
|
|
7654abc26f | ||
|
|
bbcd37e4b8 | ||
|
|
f0df05e1dd | ||
|
|
96279ac1c0 | ||
|
|
f8d46bd256 | ||
|
|
ade2b9345f | ||
|
|
8009588314 | ||
|
|
070f717131 | ||
|
|
5cc2f9a257 | ||
|
|
620ff9e967 | ||
|
|
0968dfcd03 | ||
|
|
daa10ad0fd | ||
|
|
e5b12b305f | ||
|
|
ed32476c67 | ||
|
|
a1d5aaf725 | ||
|
|
2721175d55 | ||
|
|
2b71bcd0cb | ||
|
|
c590a9cdbc | ||
|
|
dd3bb2bac3 | ||
|
|
2fa836e843 | ||
|
|
bd4b840879 | ||
|
|
4ce43894d2 | ||
|
|
5a6ae6f5aa | ||
|
|
7ad1c43b48 | ||
|
|
35d462dafc | ||
|
|
e4eaed8136 | ||
|
|
682309e0b8 | ||
|
|
eafbdf3029 | ||
|
|
faf7c493f8 | ||
|
|
f2c56bc3b6 | ||
|
|
72ff89d279 | ||
|
|
c13f82579c | ||
|
|
cb8c101885 | ||
|
|
c6676c2e57 | ||
|
|
fd6a1bfb74 | ||
|
|
d0d516eb5e | ||
|
|
9e453cab1c | ||
|
|
aef13649ea | ||
|
|
c35bcc8bdf | ||
|
|
dc225f58a9 | ||
|
|
5d8f78a6c0 | ||
|
|
f4c77bd0e3 | ||
|
|
06b8248d63 | ||
|
|
dbd60cf576 | ||
|
|
f0c9160df4 | ||
|
|
4d925f5785 | ||
|
|
3bc417488d | ||
|
|
4d83891a67 | ||
|
|
e597d5a487 | ||
|
|
3bdcf7c5e6 | ||
|
|
df0200e510 | ||
|
|
e3359201cf | ||
|
|
909bc0fff1 | ||
|
|
3d6782b3ff | ||
|
|
f857b3064f | ||
|
|
ac08d9c028 | ||
|
|
22f40c4efe | ||
|
|
e9156c2bb9 | ||
|
|
79c1f9fcf4 | ||
|
|
7b199dc599 | ||
|
|
d1a259d867 | ||
|
|
3f53c059e9 | ||
|
|
789fa12d62 | ||
|
|
d495dd40b2 | ||
|
|
2a0d806b3c | ||
|
|
759b9592ba | ||
|
|
11f64f0aeb | ||
|
|
8de912b677 | ||
|
|
3dcce042f6 | ||
|
|
97d0f72c92 | ||
|
|
660a42bc78 | ||
|
|
b04e977851 | ||
|
|
6825ae1e28 | ||
|
|
c266d0611a | ||
|
|
61cf772e70 | ||
|
|
dc0582ce0a | ||
|
|
41f09f7124 | ||
|
|
92cdc25882 | ||
|
|
1f7edce804 | ||
|
|
a25434a3a3 | ||
|
|
25e6ab87d8 | ||
|
|
5668fe04d9 | ||
|
|
5668fd6a7a | ||
|
|
df6b1b8fe6 | ||
|
|
ad2432dc68 | ||
|
|
a551de6152 | ||
|
|
3b032963d5 | ||
|
|
6635332e1b | ||
|
|
0395dd2250 | ||
|
|
7f815706ca | ||
|
|
5ba3b21921 | ||
|
|
7a6600b148 | ||
|
|
1ba44957bf | ||
|
|
8a706f836d | ||
|
|
96de8adcc9 | ||
|
|
61a45c7b3a | ||
|
|
da0ec96159 | ||
|
|
0448a9265a | ||
|
|
dde1ca1ef1 | ||
|
|
57f4dfc653 | ||
|
|
d4f134b8f6 | ||
|
|
8187aff8b9 | ||
|
|
efe62a3411 | ||
|
|
df251f14dc | ||
|
|
3df790d9fd | ||
|
|
2abe28a8c6 | ||
|
|
de75bc6688 | ||
|
|
4007ac814f | ||
|
|
409bf6e6d8 | ||
|
|
5940327f3a | ||
|
|
a4c1c0d26f | ||
|
|
f60175c308 | ||
|
|
d3582e0252 | ||
|
|
a80192b6a7 | ||
|
|
b19f01212e | ||
|
|
6c0b0e5d9a | ||
|
|
83c606ae30 | ||
|
|
a391248427 | ||
|
|
151ed8d935 | ||
|
|
565a4bfc49 | ||
|
|
ad9c59e2e9 | ||
|
|
c540e5d1b8 | ||
|
|
460c599143 | ||
|
|
c0b9c64a77 | ||
|
|
01ef6510b0 | ||
|
|
04a4715cb8 | ||
|
|
d35a117e4b | ||
|
|
a00cb3a6b0 | ||
|
|
e0ea24be1f | ||
|
|
97bde15a9f | ||
|
|
a5a31ce947 | ||
|
|
9a8f192a38 | ||
|
|
1419bf1c98 | ||
|
|
87663d5f88 | ||
|
|
38796c3d47 | ||
|
|
643d3e8134 | ||
|
|
834d5d70d1 | ||
|
|
aebf2d5cdc | ||
|
|
4251236efc | ||
|
|
ee05be0872 | ||
|
|
9aedb1431f | ||
|
|
10d0d9c7c4 | ||
|
|
74e72bd75d | ||
|
|
1c26860d82 | ||
|
|
0ed2af7fb1 | ||
|
|
d71fd30e5d | ||
|
|
7c67d33dd4 | ||
|
|
1d526c8585 | ||
|
|
c3e5b4976d | ||
|
|
7ae124743e | ||
|
|
807a5a7b13 | ||
|
|
d2c25f02e8 | ||
|
|
60444f8bff | ||
|
|
5ce39c67e5 | ||
|
|
347e1afd53 | ||
|
|
354a2a6769 | ||
|
|
f45106b726 | ||
|
|
90d106ef19 | ||
|
|
f1ab501a58 | ||
|
|
102dd99ca4 | ||
|
|
d040c17000 | ||
|
|
a4b6b51757 | ||
|
|
00e72fcfee | ||
|
|
9e5486bb65 | ||
|
|
13dd31381c | ||
|
|
518164ce96 | ||
|
|
d2c116058e | ||
|
|
a039e204e7 | ||
|
|
e8ee29e9c1 | ||
|
|
d36644c20d | ||
|
|
349b204bc2 | ||
|
|
87d8e3c33b | ||
|
|
75a59aabb3 | ||
|
|
efa3621a59 | ||
|
|
766d22825b | ||
|
|
598c92ff5c | ||
|
|
a54dbfb2b3 | ||
|
|
9fa1d30a1c | ||
|
|
787200efd6 | ||
|
|
125712bea0 | ||
|
|
14254bd0be | ||
|
|
07e237d6f4 | ||
|
|
047e4cd2f5 | ||
|
|
355b2224b2 | ||
|
|
f989a55539 | ||
|
|
40c85cf1d7 | ||
|
|
f79f7250ce | ||
|
|
f1f42ab732 | ||
|
|
a944480b9b | ||
|
|
f5d39ec97a | ||
|
|
d9bba4f16f | ||
|
|
da1350d420 | ||
|
|
bfcaa5a4ed | ||
|
|
8f8c5580fd | ||
|
|
b28088f0e4 | ||
|
|
ce840163c0 | ||
|
|
08885c4b92 | ||
|
|
4eeff46bf2 | ||
|
|
13e3c25ade | ||
|
|
4026cb6fd1 | ||
|
|
967f2d4510 | ||
|
|
53c09bce42 | ||
|
|
d2010960c9 | ||
|
|
dd96ceda43 | ||
|
|
438f53af63 | ||
|
|
8122e7caab | ||
|
|
5f3f06db66 | ||
|
|
11dd5cf2aa | ||
|
|
de154812a9 | ||
|
|
6d40458530 | ||
|
|
1b8724d866 | ||
|
|
eb607100ef | ||
|
|
a514067448 | ||
|
|
63b8ed7c37 | ||
|
|
5170efd1ee | ||
|
|
c89f44ed85 | ||
|
|
a6d50bef2f | ||
|
|
bf93b4ddfe | ||
|
|
b91e3e9083 | ||
|
|
4a0c6df8df | ||
|
|
94147f3f29 | ||
|
|
e377b78095 | ||
|
|
22ff84ca31 | ||
|
|
fd7d4adc57 | ||
|
|
fd84d71122 | ||
|
|
44dfb51f2a | ||
|
|
b18e1fd50e | ||
|
|
89880365fc | ||
|
|
6fe315d412 | ||
|
|
c81a322337 | ||
|
|
e24be2abe4 | ||
|
|
886d005616 | ||
|
|
3e25de05a9 | ||
|
|
37341289e6 | ||
|
|
462579d54e | ||
|
|
9cb27929e9 | ||
|
|
46f0efbfce | ||
|
|
c94c47abd7 | ||
|
|
f5e43f061a | ||
|
|
0c89ef513a | ||
|
|
8171b93700 | ||
|
|
cc9dc919e6 | ||
|
|
6d0aa801a0 | ||
|
|
08c50a291e | ||
|
|
eeef355887 | ||
|
|
5081181b5d | ||
|
|
dbb48de507 | ||
|
|
4c259ae945 | ||
|
|
52e3f9dd5e | ||
|
|
ef78ebf35a | ||
|
|
1abaaab1bc | ||
|
|
8010df8b8a | ||
|
|
0d505fb408 | ||
|
|
59cf7b6f6c | ||
|
|
4144938350 | ||
|
|
beecb1e160 | ||
|
|
f32b76a193 | ||
|
|
77f771ebc3 | ||
|
|
bb6f9b10db | ||
|
|
5a7926c7d9 | ||
|
|
b88362ff95 | ||
|
|
2ef5b7cca6 | ||
|
|
e9047f4f9c | ||
|
|
b647de3e07 | ||
|
|
7b83071708 | ||
|
|
dd44cccefe | ||
|
|
afadb4628e | ||
|
|
e866a22916 | ||
|
|
9ac61d2ba2 | ||
|
|
58366c058e | ||
|
|
0945b313bf | ||
|
|
7aa56e8f90 | ||
|
|
49cd515cd2 | ||
|
|
c05144b9ec | ||
|
|
c82c2bebed | ||
|
|
fe8f5dbeb7 | ||
|
|
673c8d01e6 | ||
|
|
da23255cc9 | ||
|
|
79b9c65b6b | ||
|
|
1ca0eea5bb | ||
|
|
441edcb50a | ||
|
|
4ea01630ae | ||
|
|
08a95743a2 | ||
|
|
3caa77f831 | ||
|
|
2d70959c86 | ||
|
|
466098cd1c | ||
|
|
97a4b5165e | ||
|
|
c0de52fd2d | ||
|
|
a53037f2c5 | ||
|
|
e68a6fbf20 | ||
|
|
6e4e30827d | ||
|
|
d008fc86a0 | ||
|
|
cdd508233c | ||
|
|
615534d305 | ||
|
|
68e89ab2d2 | ||
|
|
316d14d45f | ||
|
|
04e647aa84 | ||
|
|
c033ea0170 | ||
|
|
e59e2f7c3c | ||
|
|
d35188058b | ||
|
|
11bfaa1df8 | ||
|
|
6fbf1c6b56 | ||
|
|
42914557d5 | ||
|
|
e82bd6249b | ||
|
|
9d32170d5c | ||
|
|
f9b92564a7 | ||
|
|
3ba4a19510 | ||
|
|
c544c6b07e | ||
|
|
c31d14d786 | ||
|
|
2df01a9d3f | ||
|
|
1d64dcfbf7 | ||
|
|
d854bae8a9 | ||
|
|
40e5fd8b3a | ||
|
|
c3d985c3ad | ||
|
|
ba7df3de88 | ||
|
|
499091c061 | ||
|
|
415c0690af | ||
|
|
3250b38583 | ||
|
|
97db301ad4 | ||
|
|
a2facf4ad4 | ||
|
|
f439e65b64 | ||
|
|
6d04311efa | ||
|
|
a324baf6a1 | ||
|
|
63d32fb6a6 | ||
|
|
f1c2a5af58 | ||
|
|
4903b85d23 | ||
|
|
c4323a0f4b | ||
|
|
358fddb467 | ||
|
|
62675fdc93 | ||
|
|
4536abf08a | ||
|
|
d8b1aa198b | ||
|
|
6b2717ae83 | ||
|
|
34ae78d203 | ||
|
|
a22515c87f | ||
|
|
5bedb7a5e0 | ||
|
|
2100c90dd7 | ||
|
|
4afdf187a1 | ||
|
|
40dbaac892 | ||
|
|
b2fa9b43dc | ||
|
|
4aebd52c4c | ||
|
|
85ee8e10db | ||
|
|
cf98c05082 | ||
|
|
031c986ea8 | ||
|
|
ed463ccf51 | ||
|
|
bb115a7a6c | ||
|
|
2836eabc9e | ||
|
|
47d7f00e16 | ||
|
|
d183554c72 | ||
|
|
34338a3406 | ||
|
|
26303811a4 | ||
|
|
fc438d74b7 | ||
|
|
3041b72f06 | ||
|
|
ff58e019d8 | ||
|
|
66d9675559 | ||
|
|
530b00a652 | ||
|
|
077a6755ff | ||
|
|
789f9c55e5 | ||
|
|
e01bcc6884 | ||
|
|
05960a0c55 | ||
|
|
5ddda8cd56 | ||
|
|
13db59839c | ||
|
|
7cf607705b | ||
|
|
2061c0ec24 | ||
|
|
cf9927697b | ||
|
|
0127a9a525 | ||
|
|
b23975ee28 | ||
|
|
425862fb95 | ||
|
|
71c556f785 | ||
|
|
586f310618 | ||
|
|
6fb5fbbabf | ||
|
|
5dfa0945cb | ||
|
|
fb2f985dfe | ||
|
|
765918a528 | ||
|
|
33d6fe9bd0 | ||
|
|
cac52ca4ce | ||
|
|
c212019f3a | ||
|
|
3c614ef1c1 | ||
|
|
7d47d109b9 | ||
|
|
6e5c1f7579 | ||
|
|
395d204d9c | ||
|
|
5071d9eceb | ||
|
|
1d9c083fcc | ||
|
|
059ee25951 | ||
|
|
9474992482 | ||
|
|
600dbd3b27 | ||
|
|
d3efe22fa2 | ||
|
|
830df40482 | ||
|
|
c2ca1a707a | ||
|
|
bc0a902434 | ||
|
|
fba6c62b84 | ||
|
|
0cfb99d385 | ||
|
|
dcbf5a3b5d | ||
|
|
cd7bca83e1 | ||
|
|
652e0757c9 | ||
|
|
a720420466 | ||
|
|
42e23dbf6c | ||
|
|
50ff3c076e | ||
|
|
4eb53158e5 | ||
|
|
c33d33bab7 | ||
|
|
2ef620ec7f | ||
|
|
0a305e9666 | ||
|
|
cc6032956f | ||
|
|
3c238baf03 | ||
|
|
7411a44871 | ||
|
|
aa6599e687 | ||
|
|
9796bd4db6 | ||
|
|
252853560c | ||
|
|
372e9b3d64 | ||
|
|
aac236f4a8 | ||
|
|
542b0d0a65 | ||
|
|
2710477deb | ||
|
|
9c1f6bc985 | ||
|
|
a1adf38cab | ||
|
|
80869133f2 | ||
|
|
8e97096fa2 | ||
|
|
4ebbd137de | ||
|
|
4ded6393df | ||
|
|
11853cd95a | ||
|
|
6585b5a197 | ||
|
|
9f65343fa6 | ||
|
|
b6793963e9 | ||
|
|
730cfc74b8 | ||
|
|
574f7c61da | ||
|
|
3151e0995a | ||
|
|
1485b6fc93 | ||
|
|
d8ff1b1efb | ||
|
|
a73e9a6cfa | ||
|
|
32b7009196 | ||
|
|
c9ff339c23 | ||
|
|
ee840ff14c | ||
|
|
c837830f6a | ||
|
|
a6fc6250e0 | ||
|
|
f5f3defc02 | ||
|
|
86b15c7c90 | ||
|
|
3a8eb3870e | ||
|
|
f92e31558b | ||
|
|
2aef1b08f0 | ||
|
|
b5750a61f1 | ||
|
|
67d60b0365 | ||
|
|
fbbd54d123 | ||
|
|
ba45e1fdee | ||
|
|
075658c066 | ||
|
|
2243718fae | ||
|
|
b3c42d7cc1 | ||
|
|
0f2a4ca2b5 | ||
|
|
812e10ac60 | ||
|
|
e04640b421 | ||
|
|
181b1f9fec | ||
|
|
e21ef74f11 | ||
|
|
afc438a5ab | ||
|
|
5f30b9f4c8 | ||
|
|
1a3d96757e | ||
|
|
14e012871f | ||
|
|
f96cf55d36 | ||
|
|
5ffa914c59 | ||
|
|
10e002742b | ||
|
|
456d357692 | ||
|
|
23ad430648 | ||
|
|
1d7649f36b | ||
|
|
7cc4a70487 | ||
|
|
e189a84f57 | ||
|
|
174ccd3561 | ||
|
|
efdaae8312 | ||
|
|
600dc4168c | ||
|
|
9591e7ede1 | ||
|
|
63576b1202 | ||
|
|
48c9c491b0 | ||
|
|
88fca3eff4 | ||
|
|
0b1a308797 | ||
|
|
7b5e4dcf1f | ||
|
|
101ce82afa | ||
|
|
4d40a6f53c | ||
|
|
a320aeb30f | ||
|
|
55f83c4399 | ||
|
|
9032898eb1 | ||
|
|
0437bccc3c | ||
|
|
94bb67ab37 | ||
|
|
aaca7f111f | ||
|
|
55e300716f | ||
|
|
9925977b07 | ||
|
|
4fcbeed6ef | ||
|
|
308963261c | ||
|
|
ea32ca07e7 | ||
|
|
5c1706e3ef | ||
|
|
140615dafb | ||
|
|
f4249251cb | ||
|
|
9e0edb7ee5 | ||
|
|
6adbb95b82 | ||
|
|
9e277b9e2c | ||
|
|
901e7257d1 | ||
|
|
b1db4dd13e | ||
|
|
418663b61c | ||
|
|
bebe60b70c | ||
|
|
93a98c2672 | ||
|
|
f50a76379a | ||
|
|
f3d8974dc9 | ||
|
|
c6168a14c9 | ||
|
|
3c9ff9e142 | ||
|
|
81beded3af | ||
|
|
2b6ccfa30b | ||
|
|
6d25c0d26f | ||
|
|
53dd32f41d | ||
|
|
6f14cd22fd | ||
|
|
acf3616b3a | ||
|
|
92658f5661 | ||
|
|
7df72b3c88 | ||
|
|
98a0fa72be | ||
|
|
1840aa0974 | ||
|
|
83e797bc52 | ||
|
|
29f2c5ada6 | ||
|
|
0a99713ea4 | ||
|
|
df390f1799 | ||
|
|
cd72be458c | ||
|
|
f4ba9c5d1e | ||
|
|
4fb39ae074 | ||
|
|
851b1a9606 | ||
|
|
96e7ca3c78 | ||
|
|
b39fdcf45b | ||
|
|
fa380602cf | ||
|
|
aa809cb877 | ||
|
|
afc8a3b104 | ||
|
|
bb056af3c9 | ||
|
|
f221800b25 | ||
|
|
f7a80fd8e3 | ||
|
|
554923e0ae | ||
|
|
fc7ff7647f | ||
|
|
69ff428151 | ||
|
|
7c1a2417f5 | ||
|
|
0ebd0960b4 | ||
|
|
3cac20f850 | ||
|
|
2aa785c85f | ||
|
|
453cdee51c | ||
|
|
677ec408bf | ||
|
|
1fd2dac60b | ||
|
|
c08c564e21 | ||
|
|
10c7d802a0 | ||
|
|
1623abd61b | ||
|
|
035eb2f078 | ||
|
|
564360c195 | ||
|
|
2576974c21 | ||
|
|
2d56f030f0 | ||
|
|
953c6d9643 | ||
|
|
972d37f570 | ||
|
|
e692de88b8 | ||
|
|
f631b2edb9 | ||
|
|
33bd9138fa | ||
|
|
abb30dbf2d | ||
|
|
0b70507434 | ||
|
|
ba7d33be9c | ||
|
|
5ec549ca5a | ||
|
|
dc85d3fb57 | ||
|
|
73ffd6e748 | ||
|
|
d7448a721b | ||
|
|
04507b0ace | ||
|
|
56517bad21 | ||
|
|
f03e3ac15b | ||
|
|
5fb0c20297 | ||
|
|
8dad498967 | ||
|
|
ed6ff5d2b3 | ||
|
|
b00711e312 | ||
|
|
eee66d2a80 | ||
|
|
833a287337 | ||
|
|
5510b4e7d7 | ||
|
|
20ffd91347 | ||
|
|
e93eb11d92 | ||
|
|
76b09bb328 | ||
|
|
213e1a2113 | ||
|
|
3fcaa826f4 | ||
|
|
ce562b276f | ||
|
|
16a0f230b9 | ||
|
|
9cca916815 | ||
|
|
acb1e1d355 | ||
|
|
254dafcfab | ||
|
|
a086d55ba8 | ||
|
|
b3886cb12f | ||
|
|
4cda44bfb9 | ||
|
|
c0a1ec237f | ||
|
|
919ab56b6d | ||
|
|
9ecab00d26 | ||
|
|
9cda028a96 | ||
|
|
96c4abee62 | ||
|
|
2c56f60db4 | ||
|
|
86ba564a9e | ||
|
|
900a267655 | ||
|
|
c52a2a4e91 | ||
|
|
d93275eb0d | ||
|
|
a1bf82a2df | ||
|
|
edcda01a1e | ||
|
|
40059f18d9 | ||
|
|
71b29ddcc4 | ||
|
|
a1e22157d3 | ||
|
|
954dc4e8a6 | ||
|
|
1af48ed7c6 | ||
|
|
5c246f4876 | ||
|
|
b680d5bf7b | ||
|
|
cf83eac6fe | ||
|
|
ffcb1b9c2c | ||
|
|
727373c176 | ||
|
|
fdc8670327 | ||
|
|
116362d11b | ||
|
|
e6f24a5225 | ||
|
|
96077265c4 | ||
|
|
192ec18c76 | ||
|
|
db22d9b978 | ||
|
|
c67d2b4dd4 | ||
|
|
a1eba521e3 | ||
|
|
2c5827076b | ||
|
|
6b7fe2852a | ||
|
|
040cdff1d4 | ||
|
|
45109d497c | ||
|
|
e42cb2f892 | ||
|
|
532e6c8ae3 | ||
|
|
fe93c99ad9 | ||
|
|
968cdc0066 | ||
|
|
29684f590c | ||
|
|
2c67b829a5 | ||
|
|
91d865cab5 | ||
|
|
e6609094f7 | ||
|
|
3d04380691 | ||
|
|
d992bbbaa3 | ||
|
|
a66bff47f1 | ||
|
|
197b5e6dc7 | ||
|
|
df336e72d2 | ||
|
|
81e269fe15 | ||
|
|
01fb91c615 | ||
|
|
e3cce4b66a | ||
|
|
142d2e8740 | ||
|
|
73b01e9660 | ||
|
|
b8bdd780d8 | ||
|
|
1bedd3a97b | ||
|
|
6076185b70 | ||
|
|
6460d5a405 | ||
|
|
36089b2236 | ||
|
|
3aef5ae7fb | ||
|
|
7f0d89f8b4 | ||
|
|
aaf92617b0 | ||
|
|
f77736cab5 | ||
|
|
2d1175a895 | ||
|
|
60c10a45ce | ||
|
|
114faabf04 | ||
|
|
9c58641e74 | ||
|
|
76c13d16eb | ||
|
|
be226be635 | ||
|
|
58bdd1654b | ||
|
|
09c4fd3f55 | ||
|
|
1ee8a40305 | ||
|
|
5ef2808bc7 | ||
|
|
dc4150e018 | ||
|
|
129526b826 | ||
|
|
681858db90 | ||
|
|
52a5cd31c4 | ||
|
|
547d3f13ab | ||
|
|
b8ccce3500 | ||
|
|
612e606392 | ||
|
|
844b75f4d6 | ||
|
|
e1cb521dd9 | ||
|
|
c9c1730705 | ||
|
|
218f657794 | ||
|
|
2011571bf5 | ||
|
|
0b1a79bf1f | ||
|
|
ab999c86cc | ||
|
|
1e094d3428 | ||
|
|
ff4479414c | ||
|
|
e8d4946ec7 | ||
|
|
2feb2a66fd | ||
|
|
84f48499a3 | ||
|
|
1307ddf4cf | ||
|
|
293481107f | ||
|
|
a1bec4e685 | ||
|
|
56f5b12eed | ||
|
|
a6f38f9d6a | ||
|
|
8c162552d7 | ||
|
|
027a55d0fb | ||
|
|
36b9ec636d | ||
|
|
1092ae2dbe | ||
|
|
442dbf9ad8 | ||
|
|
0a1d29b1d3 | ||
|
|
4ee2b4965f | ||
|
|
825b169e22 | ||
|
|
8b6ce11d02 | ||
|
|
3019419e95 | ||
|
|
9cfdf8031e | ||
|
|
2f25c320fb | ||
|
|
ee12300a56 | ||
|
|
e134ce7c3c | ||
|
|
5a47eb762a | ||
|
|
5446fc8cea | ||
|
|
2bd6583a34 | ||
|
|
affd9c086d | ||
|
|
688be28794 | ||
|
|
55f6627427 | ||
|
|
e7f77b36f5 | ||
|
|
90c9d95c15 | ||
|
|
26e000eecf | ||
|
|
6a9646d1ce | ||
|
|
8595f0c6ac | ||
|
|
eb36643cb7 | ||
|
|
d75045cfb3 | ||
|
|
faa6ac9439 | ||
|
|
119dd6604e | ||
|
|
be3510b204 | ||
|
|
301c2b8822 | ||
|
|
0263cd7bbc | ||
|
|
c17d430b1f | ||
|
|
61394ca4aa | ||
|
|
15b9215534 | ||
|
|
0b100565ae | ||
|
|
85a1ca1c4b | ||
|
|
63284817c7 | ||
|
|
11bffd7d25 | ||
|
|
d0e3d474d1 | ||
|
|
6ae59c32a0 | ||
|
|
a912d581c4 | ||
|
|
8f91593c25 | ||
|
|
e3dd1c81e9 | ||
|
|
16d0725dd3 | ||
|
|
11ec59c8d5 | ||
|
|
cbedb99e4c | ||
|
|
0cb777d642 | ||
|
|
9afafc7a3c | ||
|
|
36653e8903 | ||
|
|
ebcbe00d17 | ||
|
|
eba7348340 | ||
|
|
683ef85a1e | ||
|
|
059afedcab | ||
|
|
07e711ecaa | ||
|
|
da721ac1ef | ||
|
|
150e43a05c | ||
|
|
3b97e8d643 | ||
|
|
1a52fa6858 | ||
|
|
92ffcda183 | ||
|
|
4b8f066c19 | ||
|
|
4a304dc1d8 | ||
|
|
f74bd57ec9 | ||
|
|
38b0564cab | ||
|
|
ea4a41e961 | ||
|
|
93cca5c1c8 | ||
|
|
7d9c99e8e7 | ||
|
|
c901a92aa5 | ||
|
|
e924615f32 | ||
|
|
812f4ca12a | ||
|
|
9c0035c129 | ||
|
|
51aed1992f | ||
|
|
6bdc80743e | ||
|
|
cb2396730a | ||
|
|
17ad2b1115 | ||
|
|
903d7db050 | ||
|
|
94d91fdda1 | ||
|
|
617b900d85 | ||
|
|
981895a860 | ||
|
|
8d5d20a526 | ||
|
|
305816232d | ||
|
|
6e0b348d34 | ||
|
|
56280d0d3a | ||
|
|
f8b78ec613 | ||
|
|
c0c21864c6 | ||
|
|
88129db5e1 | ||
|
|
716c4ebe52 | ||
|
|
a8d13f9499 | ||
|
|
faf2288895 | ||
|
|
eb4188830e | ||
|
|
45afc15547 | ||
|
|
0a62e0145a | ||
|
|
476ef1886f | ||
|
|
aec2115410 | ||
|
|
2f321615f2 | ||
|
|
4ebc6404ee | ||
|
|
ab8b85fb80 | ||
|
|
44376ffe22 | ||
|
|
b1bcff7424 | ||
|
|
794e94fe16 | ||
|
|
9dd091e4f4 | ||
|
|
c054e7cc56 | ||
|
|
21849a8587 | ||
|
|
228fbb6f84 | ||
|
|
84d2039b7f | ||
|
|
d79ce8aa05 | ||
|
|
94a0d58cd1 | ||
|
|
7ad6a7d911 | ||
|
|
db76c0d09e | ||
|
|
8f400f5a25 | ||
|
|
d5e9ddaaee | ||
|
|
2fdd451b19 | ||
|
|
0ea1e5c109 | ||
|
|
a74fe591c9 | ||
|
|
d0df875d48 | ||
|
|
6c7b95f281 | ||
|
|
fe7a45c331 | ||
|
|
a1dbe74c4c | ||
|
|
27ff8813da | ||
|
|
880507498a | ||
|
|
09d288535b | ||
|
|
fa6a525c2d | ||
|
|
f5f6dcbc62 | ||
|
|
2b29daaaa6 | ||
|
|
135af49da5 | ||
|
|
3a00204a23 | ||
|
|
16f000bcb4 | ||
|
|
401a40d941 | ||
|
|
56cab8cc03 | ||
|
|
c221ae8cdb | ||
|
|
12e36e7ea7 | ||
|
|
fccfa9e929 | ||
|
|
9dc3afb1fa | ||
|
|
42715fa173 | ||
|
|
bc773e60e1 | ||
|
|
e7cb9788c4 | ||
|
|
d6833cc7fa | ||
|
|
116cbc267c | ||
|
|
1e88b1125a | ||
|
|
733b05a693 | ||
|
|
194afbe34d | ||
|
|
2c3190b237 | ||
|
|
8f7cff6aec | ||
|
|
6bd4a36dde | ||
|
|
8f0b0fea66 | ||
|
|
a222da0456 | ||
|
|
fdc5e381d8 | ||
|
|
667d14e377 | ||
|
|
bc49609c6f | ||
|
|
7fa7632dc7 | ||
|
|
7f8badfe5e | ||
|
|
a5c6acf22a | ||
|
|
65fc4dae3a | ||
|
|
3e3591904b | ||
|
|
a1d4ec1d6e | ||
|
|
23fb1fbd48 | ||
|
|
4b79aeb0ea | ||
|
|
67199cac4f | ||
|
|
c446a0fffd | ||
|
|
16b1fe4a08 | ||
|
|
cef065f63f | ||
|
|
b51cd542be | ||
|
|
74863007ee | ||
|
|
679830cf58 | ||
|
|
dbc8e5098c | ||
|
|
af7697efbe | ||
|
|
4c29343443 | ||
|
|
92e6277c28 | ||
|
|
4299c31d26 | ||
|
|
59762452a0 | ||
|
|
01794a7891 | ||
|
|
e84c7c7c63 | ||
|
|
6184b70cf7 | ||
|
|
888d273f9a | ||
|
|
8f506ae67b | ||
|
|
84b6fab321 | ||
|
|
424873390b | ||
|
|
96eda8b9b3 | ||
|
|
b1b38215ba | ||
|
|
c6e087d54a | ||
|
|
d044827d9a | ||
|
|
a8de276520 | ||
|
|
fd1aaee33f | ||
|
|
b84bb4d9c2 | ||
|
|
6a095ca99f | ||
|
|
025e69a15a | ||
|
|
2a66b79d55 | ||
|
|
22ba1e8ee6 | ||
|
|
22b06cdcce | ||
|
|
ad50450a22 | ||
|
|
0825c244dd | ||
|
|
606d085835 | ||
|
|
937a21f0d2 | ||
|
|
f6fdfd56e4 | ||
|
|
b3c6850b1c | ||
|
|
95d3c5f7e1 | ||
|
|
2dd15068fb | ||
|
|
6feecf76d4 | ||
|
|
12fbaae042 | ||
|
|
349da06cfa | ||
|
|
a592016297 | ||
|
|
0011955f3a | ||
|
|
dbb55cb3e1 | ||
|
|
235ea42e59 | ||
|
|
be294072a1 | ||
|
|
f11781c50e | ||
|
|
21ee9f3234 | ||
|
|
a1da766a21 | ||
|
|
55be86d4c7 | ||
|
|
2479e17526 | ||
|
|
62fbc0a033 | ||
|
|
b2c682e462 | ||
|
|
ff4a77c5ca | ||
|
|
0a9b444a60 | ||
|
|
4b1232984b | ||
|
|
7871d2c8e7 | ||
|
|
327dbf1078 | ||
|
|
2d6e83ea19 | ||
|
|
5fc79ef6dc | ||
|
|
5c4622fd2a | ||
|
|
e485801d49 | ||
|
|
20b7fe3379 | ||
|
|
006e5fa0ea | ||
|
|
de0ae6a18f | ||
|
|
1936d75b3c | ||
|
|
a5d006d515 | ||
|
|
4522d931f6 | ||
|
|
5d6a6bdf7b | ||
|
|
5e79ce33d6 | ||
|
|
7271b0afea | ||
|
|
da6e9afebf | ||
|
|
92ebc9219e | ||
|
|
1b7c4b9bce | ||
|
|
63bd9ec3ff | ||
|
|
76e0e1d0eb | ||
|
|
f25f57ae75 | ||
|
|
8d5391f1c3 | ||
|
|
9a09ca42d2 | ||
|
|
fadd934150 | ||
|
|
0ddb15964a | ||
|
|
2ae2ca89bf | ||
|
|
bd43da4f9d | ||
|
|
4388a09b0f | ||
|
|
3812984422 | ||
|
|
1102378e1c | ||
|
|
8382fc3e85 | ||
|
|
1febdf9a37 | ||
|
|
fe71257ebd | ||
|
|
c37f0c7d7c | ||
|
|
49e859e5a7 | ||
|
|
ad18cacfa9 | ||
|
|
b7149bbe45 | ||
|
|
e1916ebbcd | ||
|
|
446e4a6a79 | ||
|
|
952cd45167 | ||
|
|
6bc840fd2a | ||
|
|
4675e4f17d | ||
|
|
bb86f0a22a | ||
|
|
f2554b9d2a | ||
|
|
5702dffbc3 | ||
|
|
35ce2b332b | ||
|
|
9d3be13f4f | ||
|
|
f7e7f3e3ed | ||
|
|
a91a9dfaf8 | ||
|
|
9376ec18cd | ||
|
|
9b30dfb967 | ||
|
|
9e06310aab | ||
|
|
d40d166f91 | ||
|
|
9d9de35dca | ||
|
|
66781f5d5a | ||
|
|
303923fbf1 | ||
|
|
ba96eb24fa | ||
|
|
9366d4e391 | ||
|
|
ec2ce68847 | ||
|
|
760d1fac55 | ||
|
|
0281405a4d | ||
|
|
bebfa29b48 | ||
|
|
22bb69eb99 | ||
|
|
af979c3b2d | ||
|
|
8961b1d503 | ||
|
|
ebfe96cad5 | ||
|
|
d6d4e462a4 | ||
|
|
75b2f3507a | ||
|
|
7e0db38528 | ||
|
|
cb12e3fc9f | ||
|
|
c0920fbf2a | ||
|
|
dd1f2c0959 | ||
|
|
91106a4a2d | ||
|
|
7dfce0e467 | ||
|
|
bda30a59b9 | ||
|
|
caa443ae49 | ||
|
|
4f8eeb2a06 | ||
|
|
6ba68e2a84 | ||
|
|
5f4dc7f957 | ||
|
|
acb037657c | ||
|
|
706edf60d5 | ||
|
|
32342298e1 | ||
|
|
1fbc1dec0e | ||
|
|
2b82bd79f5 | ||
|
|
e8bed35ddf | ||
|
|
54fca7b1ca | ||
|
|
122ba73eaf | ||
|
|
9d03132282 | ||
|
|
ea7c621b0a | ||
|
|
98e6fdec8b | ||
|
|
414813e349 | ||
|
|
166597d998 | ||
|
|
250238d04c | ||
|
|
5bd1cb414b | ||
|
|
062181292a | ||
|
|
e3552d738c | ||
|
|
1d2f212a3d | ||
|
|
2937b51eaa | ||
|
|
c8c4eda71f | ||
|
|
bf8ea32876 | ||
|
|
973db2a823 | ||
|
|
8865a4c19e | ||
|
|
5b8abb1240 | ||
|
|
81e606ab2c | ||
|
|
14caa4a2d0 | ||
|
|
a8d4cd68eb | ||
|
|
41cf252f0b | ||
|
|
8191fe4f4a | ||
|
|
0669d21847 | ||
|
|
97e8048e05 | ||
|
|
1415afcdba | ||
|
|
2e3be4f3fd | ||
|
|
b20e74d5d6 | ||
|
|
4cb0f557d9 | ||
|
|
5f3325fcf1 | ||
|
|
21ba805499 | ||
|
|
693ec4b404 | ||
|
|
cbecd3cd11 | ||
|
|
2e8d681cf2 | ||
|
|
dce59eb407 | ||
|
|
a8cc07b564 | ||
|
|
73e3226012 | ||
|
|
201222ebad | ||
|
|
1b88184104 | ||
|
|
99aacef51c | ||
|
|
8661190736 | ||
|
|
a2f5ce8181 | ||
|
|
964916f8f3 | ||
|
|
a680e90fb0 | ||
|
|
0bc382eae4 | ||
|
|
f2afa4f21d | ||
|
|
5219fe3ca8 | ||
|
|
14b0c96bc7 | ||
|
|
46f84d5cb9 | ||
|
|
9d6d98c900 | ||
|
|
e8ec0ba2e3 | ||
|
|
2044eacc7e | ||
|
|
aaa7f4c966 | ||
|
|
f46de65682 | ||
|
|
0a178d853a | ||
|
|
7d11d708d8 | ||
|
|
b2594b047b | ||
|
|
728074ac83 | ||
|
|
9cd9dab06a | ||
|
|
663886b954 | ||
|
|
2151f044e8 | ||
|
|
ef3d8e18d3 | ||
|
|
dd5b5fb794 | ||
|
|
f6531a5f00 | ||
|
|
55429cde3c | ||
|
|
4543dac58e | ||
|
|
b2b27cd7f4 | ||
|
|
5de70620ef | ||
|
|
c1abd569f2 | ||
|
|
ecc511167a | ||
|
|
cbff112651 | ||
|
|
50814ddb75 | ||
|
|
eeaf3ba70a | ||
|
|
fd82d8c129 | ||
|
|
10955b8289 | ||
|
|
adc78505f3 | ||
|
|
f8452d8cfd | ||
|
|
64dff85ce4 | ||
|
|
f0fffb8c6f | ||
|
|
a9d6333bd6 | ||
|
|
1ef6fb2f58 | ||
|
|
b500eddad1 | ||
|
|
eb82bd0525 | ||
|
|
5a976864ee | ||
|
|
37ddf2594a | ||
|
|
ae1a833000 | ||
|
|
962e678174 | ||
|
|
e702a9c7ed | ||
|
|
f7e3a19f75 | ||
|
|
e40d44be8d | ||
|
|
afcae0664e | ||
|
|
335d694791 | ||
|
|
31ed6045f9 | ||
|
|
4b429b6c33 | ||
|
|
2955b913ea | ||
|
|
13047cca5a | ||
|
|
4886fa2105 | ||
|
|
2bea18e504 | ||
|
|
a83c7816e4 | ||
|
|
176bbea069 | ||
|
|
621a3ac994 | ||
|
|
fe9ac4d3f4 | ||
|
|
63b8dfbde7 | ||
|
|
b2959bde18 | ||
|
|
0396ddf30d | ||
|
|
9b2800e861 | ||
|
|
07d7f642f8 | ||
|
|
3deeab58c7 | ||
|
|
44110cd33e | ||
|
|
d0604a856d | ||
|
|
2ecd717dc4 | ||
|
|
419d5219cb | ||
|
|
6426e5d3e6 | ||
|
|
84cc478cc4 | ||
|
|
3a32d104bd | ||
|
|
962ebfe4b4 | ||
|
|
178ff2becc | ||
|
|
8328e5f094 | ||
|
|
36a4698683 | ||
|
|
779c11004a | ||
|
|
68c5e7d2df | ||
|
|
dd68ee88ea | ||
|
|
4e92d7c9ae | ||
|
|
3c1febe0a8 | ||
|
|
a90221d824 | ||
|
|
2aa06d73ca | ||
|
|
3f329bd02c | ||
|
|
7ce5ac0f03 | ||
|
|
d35c864521 | ||
|
|
91e56ffb29 | ||
|
|
faa1268182 | ||
|
|
a636bccaba | ||
|
|
1e34e243a9 | ||
|
|
6cb77b0269 | ||
|
|
710784945c | ||
|
|
aa4f87d6e3 | ||
|
|
321ae653b6 | ||
|
|
30b36dc0e8 | ||
|
|
0775e8060e | ||
|
|
fc218865bf | ||
|
|
eacd3a0916 | ||
|
|
3cb3f15cf2 | ||
|
|
d80f8cf41b | ||
|
|
1b7750c4bd | ||
|
|
b83af51668 | ||
|
|
c748bda186 | ||
|
|
727d065f6e | ||
|
|
06808d3357 | ||
|
|
12873010e5 | ||
|
|
60fc088d70 | ||
|
|
d53d92f2e1 | ||
|
|
f1fc310730 | ||
|
|
6103254393 | ||
|
|
1d85ae71a0 | ||
|
|
59571213ef | ||
|
|
eb166dbc88 | ||
|
|
d95a85ca36 | ||
|
|
f7311db64f | ||
|
|
8f1ead4640 | ||
|
|
d28c8ccfbd | ||
|
|
123b90ce05 | ||
|
|
06ee3f7259 | ||
|
|
a341cab721 | ||
|
|
501d5786a9 | ||
|
|
5f13cafaca | ||
|
|
d1ad03efce | ||
|
|
78725dd13a | ||
|
|
57a8279442 | ||
|
|
2c33c8b80c | ||
|
|
e3e64c8ea4 | ||
|
|
9443b5d4cd | ||
|
|
336d41d685 | ||
|
|
2db2b7f1ca | ||
|
|
0c59a030c3 | ||
|
|
976b95d929 | ||
|
|
d9583b8708 | ||
|
|
042312952c | ||
|
|
7c9fd3ea84 | ||
|
|
bbdd3d40bd | ||
|
|
b8281ca1e4 | ||
|
|
49908a9a33 | ||
|
|
7dddc57bde | ||
|
|
f70468ce0b | ||
|
|
98351ffbd5 | ||
|
|
8b86e09ffa | ||
|
|
1c45bab17f | ||
|
|
613a177a6f | ||
|
|
2eba846043 | ||
|
|
d88090b0ae | ||
|
|
40c6c80723 | ||
|
|
e27833fb9c | ||
|
|
af579eccc3 | ||
|
|
29636f38e3 | ||
|
|
802e252b29 | ||
|
|
a88a278698 | ||
|
|
6a4b036c2f | ||
|
|
bd79af9f05 | ||
|
|
01143a9313 | ||
|
|
55b94bf393 | ||
|
|
0d9ed7ade3 | ||
|
|
685940c01c | ||
|
|
fd86754329 | ||
|
|
829fe014a5 | ||
|
|
3a6e5f36f9 | ||
|
|
f42b2d4bbf | ||
|
|
637ac19e60 | ||
|
|
b0485a996f | ||
|
|
ac0252ca07 | ||
|
|
0ca1492ca5 | ||
|
|
d06b88437e | ||
|
|
5936dd0381 | ||
|
|
4df3d5ad25 | ||
|
|
f9bbf60213 | ||
|
|
b184f791d4 | ||
|
|
1cd292af8f | ||
|
|
1f4f0d1926 | ||
|
|
5d74ec6400 | ||
|
|
b1ef78d000 | ||
|
|
c508945ca9 | ||
|
|
f15033c0e1 | ||
|
|
254d672dcc | ||
|
|
f4fd41552d | ||
|
|
4bbadbe1cf | ||
|
|
14663348d0 | ||
|
|
e32e2eb011 | ||
|
|
b88b638d6e | ||
|
|
b171907fc5 | ||
|
|
f42b708eae | ||
|
|
81f0124a58 | ||
|
|
3d7e8602ed | ||
|
|
1ebbfd9958 | ||
|
|
c631be7684 | ||
|
|
c7df0240f9 | ||
|
|
f6b1c45bf1 | ||
|
|
8a075c6123 | ||
|
|
46d4a6acf8 | ||
|
|
44a31a9c2f | ||
|
|
87368c35b9 | ||
|
|
bad35c6554 | ||
|
|
0cb07b65f3 | ||
|
|
980d2d8683 | ||
|
|
ec8a4dac46 | ||
|
|
a171bb6e85 | ||
|
|
064ed484b4 | ||
|
|
70431c8146 | ||
|
|
48ae64529a | ||
|
|
97709450ca | ||
|
|
d20ce59b80 | ||
|
|
dc8478458e | ||
|
|
34cbedceaf | ||
|
|
ba6662c5d6 | ||
|
|
068fed4534 | ||
|
|
6ec8c52201 | ||
|
|
a71d6051ed | ||
|
|
fc86426b56 | ||
|
|
c7af31dbd7 | ||
|
|
5c8cba0b47 | ||
|
|
3cc126e478 | ||
|
|
c89bc357e1 | ||
|
|
34b6075d68 | ||
|
|
e9848871d6 | ||
|
|
cf704d22b6 | ||
|
|
9c179ef418 | ||
|
|
762812e71c | ||
|
|
4e19541b8d | ||
|
|
fea55602c5 | ||
|
|
7063efe1bd | ||
|
|
4efb1d9cbb | ||
|
|
aa06d91972 | ||
|
|
614469b544 | ||
|
|
cc171eb8ee | ||
|
|
1af822bff0 | ||
|
|
fc65b9038e | ||
|
|
d6fbd0db32 | ||
|
|
7bdc15c8bb | ||
|
|
d5722ebb21 | ||
|
|
69d67dc2ca | ||
|
|
586b56b18c | ||
|
|
727f7bfa49 | ||
|
|
c37a14506a | ||
|
|
cca6ab596f | ||
|
|
2d5e2b52ca | ||
|
|
7dbfd06d99 | ||
|
|
523fad915b | ||
|
|
88b97d8f30 | ||
|
|
53670b18f5 | ||
|
|
c496bc13e2 | ||
|
|
22149572e8 | ||
|
|
2d6fcbf67d | ||
|
|
85ed403002 | ||
|
|
f92b4f9482 | ||
|
|
85a80e0505 | ||
|
|
ed878c8a9a | ||
|
|
d1e8046f56 | ||
|
|
470c18847d | ||
|
|
d0191bf9f4 | ||
|
|
1fad9a68ae | ||
|
|
f069a14ca7 | ||
|
|
2d7614322e | ||
|
|
a6a66e7c83 | ||
|
|
b045f4fe9a | ||
|
|
2565ffad25 | ||
|
|
9ac9e06b5c | ||
|
|
b123a82d73 | ||
|
|
dff224669d | ||
|
|
dc39d2a66e | ||
|
|
626242c1bd | ||
|
|
f21beaf20c | ||
|
|
f3ad0dcfde | ||
|
|
0ae41c4412 | ||
|
|
52e1564fdd | ||
|
|
fae2c49259 | ||
|
|
7def56f1e4 | ||
|
|
95aa395ddd | ||
|
|
45035ffa1a | ||
|
|
8d2d4f1fa0 | ||
|
|
498747d792 | ||
|
|
851aaf4ecc | ||
|
|
57d31c99cc | ||
|
|
14a9722185 | ||
|
|
97df4e4675 | ||
|
|
59f8043d7c | ||
|
|
30168792f4 | ||
|
|
3eadbbeb12 | ||
|
|
c10f7fd039 | ||
|
|
9f926fd060 | ||
|
|
0a89c2307e | ||
|
|
56081fe97b | ||
|
|
c8675c4933 | ||
|
|
d87427446c | ||
|
|
cbd41292a4 | ||
|
|
efaaf3146d | ||
|
|
0dfae7e47a | ||
|
|
1342414a8d | ||
|
|
3015a9ab9c | ||
|
|
380cd989ac | ||
|
|
c133a264b0 | ||
|
|
7a7392e151 | ||
|
|
aba2aca3a4 | ||
|
|
0146f0de8b | ||
|
|
2d696f9efc | ||
|
|
7622f31210 | ||
|
|
9bd6940fff | ||
|
|
b1f08e51cc | ||
|
|
07c7f12deb | ||
|
|
936541ec56 | ||
|
|
e9438785b1 | ||
|
|
65ce9feb72 | ||
|
|
8bae0a1ecf | ||
|
|
64f95b40ca | ||
|
|
cdb675c02b | ||
|
|
e12a5243c9 | ||
|
|
f89f7955fc | ||
|
|
111c120e00 | ||
|
|
09ba95b266 | ||
|
|
4cc5adf46c | ||
|
|
8b90730e41 | ||
|
|
82c99fb63f | ||
|
|
b5097c8462 | ||
|
|
e78d473b43 | ||
|
|
81bf06ea38 | ||
|
|
9baacefc77 | ||
|
|
65d20c2f32 | ||
|
|
405c4a45d8 | ||
|
|
54b362f9b0 | ||
|
|
5b39a977ca | ||
|
|
ed72f7e13a | ||
|
|
aab1bfd693 | ||
|
|
529edb1853 | ||
|
|
2ef5d30611 | ||
|
|
900f77b71e | ||
|
|
fee2e890af | ||
|
|
96412de6a9 | ||
|
|
4adf163d13 | ||
|
|
66392e6660 | ||
|
|
15106c5064 | ||
|
|
80b99da822 | ||
|
|
1033d12040 | ||
|
|
60f425d1b3 | ||
|
|
48c245884e | ||
|
|
ceb0db233a | ||
|
|
c42b084793 | ||
|
|
8c013d78b6 | ||
|
|
8c4e8a185a | ||
|
|
8e3da446f4 | ||
|
|
da42be4d8d | ||
|
|
3122f963b0 | ||
|
|
fefa43235f | ||
|
|
a93fb6299f | ||
|
|
fde1354775 | ||
|
|
f77fb62b2a | ||
|
|
d01a6a2c5c | ||
|
|
08f1ddea6c | ||
|
|
3e404aea3a | ||
|
|
80e569104b | ||
|
|
aa5734f2a3 | ||
|
|
a5fb2bbff3 | ||
|
|
dce204cec5 | ||
|
|
764eb41086 | ||
|
|
14db805f14 | ||
|
|
da038ccb4b | ||
|
|
97c80eca63 | ||
|
|
37036b0215 | ||
|
|
4ec2ae8632 | ||
|
|
981adf4837 | ||
|
|
71082be43a | ||
|
|
69e80c9eee | ||
|
|
96c3c4645f | ||
|
|
90b96af68f | ||
|
|
7041b476ac | ||
|
|
05d2c210e1 | ||
|
|
02adb0cd9d | ||
|
|
7f7af46862 | ||
|
|
6aecef2c04 | ||
|
|
d28ed36f3c | ||
|
|
6c8655ce9b | ||
|
|
68f4e0c734 | ||
|
|
0db1bbc3c3 | ||
|
|
643f234119 | ||
|
|
0e35954fc5 | ||
|
|
9a54c1a79b | ||
|
|
8c54f1a949 | ||
|
|
d911ec67a9 | ||
|
|
44cd0f4780 | ||
|
|
db3c1ac1c8 | ||
|
|
d99d4bd026 | ||
|
|
1c0c6cc812 | ||
|
|
d0709eed62 | ||
|
|
9b95a5a939 | ||
|
|
b5243aac02 | ||
|
|
185ac73d18 | ||
|
|
89dd7d5275 | ||
|
|
22a8592301 | ||
|
|
4e7aebddfd | ||
|
|
3a3281c195 | ||
|
|
02317333db | ||
|
|
6472c7e11f | ||
|
|
77d308ef77 | ||
|
|
12eadbabdd | ||
|
|
3b9d1b1a96 | ||
|
|
d8886386bd | ||
|
|
40b4d1c3ae | ||
|
|
23177eda88 | ||
|
|
d67c40f9e8 | ||
|
|
efe75fd705 | ||
|
|
a6c4427188 | ||
|
|
c304818d39 | ||
|
|
ef7b409966 | ||
|
|
67b91d0848 | ||
|
|
4e11851795 | ||
|
|
6117bfc0af | ||
|
|
647c64c796 | ||
|
|
9fdadfc3cf | ||
|
|
2dbb08a4fe | ||
|
|
296d0c0b42 | ||
|
|
7985f80c63 | ||
|
|
7f119c2236 | ||
|
|
a5bf70018b | ||
|
|
6af5155529 | ||
|
|
d37dd5b2d3 | ||
|
|
710c9373bf | ||
|
|
a375ced300 | ||
|
|
559aee44ab | ||
|
|
5778fdeeb8 | ||
|
|
fa832e3a55 | ||
|
|
6f0a72fb75 | ||
|
|
763888abef | ||
|
|
18787def0b | ||
|
|
7815d8263a | ||
|
|
292358a517 | ||
|
|
a9d8bf269a | ||
|
|
7088fb9260 | ||
|
|
458a107e86 | ||
|
|
c6c031e4a1 | ||
|
|
a09a8efb66 | ||
|
|
f61cd7b249 | ||
|
|
9e111ef67a | ||
|
|
60a5f61fc8 | ||
|
|
1b54343328 | ||
|
|
1779cc34d1 | ||
|
|
3534fb40df | ||
|
|
7042e06a2a | ||
|
|
821f0cc5ea | ||
|
|
88d7dc1af8 | ||
|
|
bc963e745c | ||
|
|
c6894cf031 | ||
|
|
0f2f8a5c3a | ||
|
|
77e0ed4be7 | ||
|
|
69d1732334 | ||
|
|
bb723d7897 | ||
|
|
f9c307cd07 | ||
|
|
e6bd367b57 | ||
|
|
2f8e0473f4 | ||
|
|
88fc1b143e | ||
|
|
cdbe475fe3 | ||
|
|
9ccac021a7 | ||
|
|
f55a20eb36 | ||
|
|
6b596f685f | ||
|
|
ef4fa155a5 | ||
|
|
29f24d4634 | ||
|
|
a6b36a5901 | ||
|
|
09e0f43ba0 | ||
|
|
da0b4d8770 | ||
|
|
96597c2eab | ||
|
|
322c5868b3 | ||
|
|
d144d5eeb7 | ||
|
|
7c604e7649 | ||
|
|
eddb91d1e7 | ||
|
|
0da9500f13 | ||
|
|
68c31a2a36 | ||
|
|
e6f716f551 | ||
|
|
8b2055719d | ||
|
|
9bce3d3bcf | ||
|
|
4de36d0072 | ||
|
|
c78b0274ba | ||
|
|
d301e5917f | ||
|
|
2e08761496 | ||
|
|
a8dfed8267 | ||
|
|
fb99185a60 | ||
|
|
98f5d4ad4b | ||
|
|
1ed3c7cc63 | ||
|
|
d2cd8375ff | ||
|
|
85691c0afb | ||
|
|
acc70bce86 | ||
|
|
be2d9395c7 | ||
|
|
3ba8ffe741 | ||
|
|
eba612b4c5 | ||
|
|
42f7fd0590 | ||
|
|
7c15f34267 | ||
|
|
07ae1d4943 | ||
|
|
99cd5c7098 | ||
|
|
b6c8580d4d | ||
|
|
f9e177d281 | ||
|
|
58f55600d0 | ||
|
|
eac8de9bfb | ||
|
|
21a5699f12 | ||
|
|
a7d355a28c | ||
|
|
548cc88947 | ||
|
|
b4ee00356b | ||
|
|
aec39dcc34 | ||
|
|
566515c095 | ||
|
|
2995925278 | ||
|
|
f6da9ca88a | ||
|
|
4df5235d15 | ||
|
|
d2031f6a16 | ||
|
|
c5782bcf15 | ||
|
|
50b906abaa | ||
|
|
9e0521ebb0 | ||
|
|
c9c7d25c35 | ||
|
|
cee2f123a4 | ||
|
|
5908a590db | ||
|
|
a9b601e2be | ||
|
|
4c10ab5627 | ||
|
|
a5e1488414 | ||
|
|
1a526b3c9d | ||
|
|
8d6e0c9562 | ||
|
|
850fa8233f | ||
|
|
0337d99198 | ||
|
|
b5c2529bf8 | ||
|
|
31943693c7 | ||
|
|
e9a87f2e16 | ||
|
|
e3a1fc8af3 | ||
|
|
d01888706d | ||
|
|
ee83186ecc | ||
|
|
03023d3965 | ||
|
|
1a3b58545b | ||
|
|
d781e714b5 | ||
|
|
c0ea4c94a1 | ||
|
|
30a653105c | ||
|
|
ba61f84874 | ||
|
|
ed122a962d | ||
|
|
3014fad054 | ||
|
|
5782a38543 | ||
|
|
8e0ef70c96 | ||
|
|
8a65725195 | ||
|
|
84fa520c03 | ||
|
|
1493f24e3e | ||
|
|
d345bf2cd3 | ||
|
|
1a36448da3 | ||
|
|
4ef2bf27a7 | ||
|
|
8eed925e17 | ||
|
|
591fc4d2d1 | ||
|
|
df7edc00b8 | ||
|
|
3ed801fb95 | ||
|
|
dc7d777606 | ||
|
|
9249fb12b8 | ||
|
|
b5f33faf9f | ||
|
|
f467cd17a1 | ||
|
|
2ad07c0716 | ||
|
|
65928349e7 | ||
|
|
f6d7e637c3 | ||
|
|
49e7eb3570 | ||
|
|
4c77dcc4ea | ||
|
|
0e6270e308 | ||
|
|
6222635b38 | ||
|
|
12569ccb03 | ||
|
|
0a02d30ea4 | ||
|
|
e86e45f7ea | ||
|
|
651cae3c5c | ||
|
|
1207106fbc | ||
|
|
8fea97b7e7 | ||
|
|
f3ef15ef6b | ||
|
|
76d1aec8e0 | ||
|
|
b262f3e19e | ||
|
|
04a6dd7731 | ||
|
|
0e83352280 | ||
|
|
ead120ebee | ||
|
|
85409909aa | ||
|
|
21c56e377b | ||
|
|
0506f410ea | ||
|
|
ae6164cee3 | ||
|
|
3e730d4769 | ||
|
|
3399ae320a | ||
|
|
da05c479a9 | ||
|
|
52edfba95b | ||
|
|
a5f0b044bf | ||
|
|
24a57a0b95 | ||
|
|
8f4a9e6a3e | ||
|
|
0a6ddb393f | ||
|
|
a616c0de2e | ||
|
|
0d23926e4e | ||
|
|
1a832398a7 | ||
|
|
dd2a0e940d | ||
|
|
cfb203e14d | ||
|
|
dd4097a6a4 | ||
|
|
1d837442bf | ||
|
|
34220fe292 | ||
|
|
8c965cafb7 | ||
|
|
fa305e2ec6 | ||
|
|
24d21cfcee | ||
|
|
350232370f | ||
|
|
a988efda46 | ||
|
|
3ab04a088c | ||
|
|
a932c2b61f | ||
|
|
bdadde2f7a | ||
|
|
e2d136477b | ||
|
|
048124728d | ||
|
|
ea9e387f87 | ||
|
|
b8fb120ee0 | ||
|
|
b449f0a188 | ||
|
|
7515338726 | ||
|
|
28e2b5b213 | ||
|
|
b1d188894e | ||
|
|
9ad39e546b | ||
|
|
1540955fc6 | ||
|
|
d74800fd23 | ||
|
|
685d9e615b | ||
|
|
15bd6a29b9 | ||
|
|
0e7c1ee3e7 | ||
|
|
85ab113b31 | ||
|
|
e598348504 | ||
|
|
6c53c22139 | ||
|
|
69638ad6b1 | ||
|
|
4aa8216d7e | ||
|
|
dfafb8fb20 | ||
|
|
fff111fe22 | ||
|
|
75e69cd1b2 | ||
|
|
f7f0854eca | ||
|
|
e73debb2db | ||
|
|
047f82ee26 | ||
|
|
75b55f1136 | ||
|
|
1e9ed439d4 | ||
|
|
3806ab6f1f | ||
|
|
1b281f408d | ||
|
|
1641fdf90c | ||
|
|
0b0caec5f6 | ||
|
|
b52496b7af | ||
|
|
d50c6d4bf5 | ||
|
|
3283f817eb | ||
|
|
180b3dea11 | ||
|
|
2f01958e3e | ||
|
|
9409998d71 | ||
|
|
209c58bb35 | ||
|
|
e92d87cef6 | ||
|
|
bde29bc4fa | ||
|
|
5cb00fe6cd | ||
|
|
3ceb76089c | ||
|
|
d6b9d2cbc3 | ||
|
|
aaa2e0468f | ||
|
|
c7fe469700 | ||
|
|
5ff4274f9b | ||
|
|
244646902c | ||
|
|
7147cd9fe5 | ||
|
|
8889fda53d | ||
|
|
9783e5ae7b | ||
|
|
4fd3355e7e | ||
|
|
54d7741a3e | ||
|
|
6c6ce2ba0e | ||
|
|
c64f9e63eb | ||
|
|
942d6ef29f | ||
|
|
8b7fc0da11 | ||
|
|
56a5925aed | ||
|
|
d7c9d72390 | ||
|
|
b9c4fc2498 | ||
|
|
21e2ab0e67 | ||
|
|
4ed099bafa | ||
|
|
257848229d | ||
|
|
60267bdce8 | ||
|
|
d6d08486c8 | ||
|
|
6ddb5ecd72 | ||
|
|
1f661c5dd8 | ||
|
|
616eda51e3 | ||
|
|
e07803f976 | ||
|
|
92f67fed0a | ||
|
|
d9c67df256 | ||
|
|
6753ff894f | ||
|
|
0e8134800e | ||
|
|
6d3dd87bba | ||
|
|
cab2199de8 | ||
|
|
e8e7a84c64 | ||
|
|
dbd20bbdb7 | ||
|
|
705cf58916 | ||
|
|
3c76d9abaf | ||
|
|
66f79d05eb | ||
|
|
0fad905483 | ||
|
|
b2bd4e2d8d | ||
|
|
4bd1ac728c | ||
|
|
ff403ee29f | ||
|
|
3332edacb9 | ||
|
|
c407d2bd11 | ||
|
|
49ada7a2c3 | ||
|
|
c3b712f8a0 | ||
|
|
ee90b8197f | ||
|
|
a120520fa2 | ||
|
|
d9933eaf1b | ||
|
|
2b707b6806 | ||
|
|
175b8684a0 | ||
|
|
da336123c2 | ||
|
|
72ab7270e0 | ||
|
|
5e3285ef49 | ||
|
|
298ec21e29 | ||
|
|
81182ac07a | ||
|
|
5227ae5388 | ||
|
|
c474c0827b | ||
|
|
6008aabe91 | ||
|
|
adfdf8bb1e | ||
|
|
32c1ea2549 | ||
|
|
a11ad9cc7b | ||
|
|
3972d7a2a4 | ||
|
|
9c29f2f509 | ||
|
|
fadbec996f | ||
|
|
2e79014bbe | ||
|
|
212510fdf8 | ||
|
|
e98c922ec5 | ||
|
|
a86107dfb1 | ||
|
|
1e696b0c15 | ||
|
|
c6469d46dd | ||
|
|
bda3982016 | ||
|
|
cb296d5bb5 | ||
|
|
e6f562ab77 | ||
|
|
6c4f65fecd | ||
|
|
2f31756149 | ||
|
|
6ea4f7dfc0 | ||
|
|
b409df00a9 | ||
|
|
fc63498c49 | ||
|
|
af46c894d0 | ||
|
|
11647ad01c | ||
|
|
0adfbfd5ea | ||
|
|
8cfd64de78 | ||
|
|
a6a4941504 | ||
|
|
f6644ff8fe | ||
|
|
94b713df08 | ||
|
|
e4594d9c23 | ||
|
|
a2263de0a3 | ||
|
|
2f938809c4 | ||
|
|
d78af3f646 | ||
|
|
0128c3703a | ||
|
|
cad4999faa | ||
|
|
468667effa | ||
|
|
99224dfeac | ||
|
|
cd7d2bc5e4 | ||
|
|
68176be18e | ||
|
|
59131572d5 | ||
|
|
31f8085a1b | ||
|
|
88e3d4e262 | ||
|
|
400502f7e6 | ||
|
|
bedabf92f3 | ||
|
|
b7d23b7943 | ||
|
|
0693099223 | ||
|
|
d5fdc8e8ab | ||
|
|
23b059e7b7 | ||
|
|
c737d34804 | ||
|
|
1485ce69c4 | ||
|
|
fddc256a02 | ||
|
|
7cbd4a743e | ||
|
|
9a62f0d59a | ||
|
|
1969deb742 | ||
|
|
4d0e07a799 | ||
|
|
b3302a0c3c | ||
|
|
aab7a3978b | ||
|
|
18e0f9342d | ||
|
|
09d11ca3d8 | ||
|
|
e6ff36ab61 | ||
|
|
3103d5e2d9 | ||
|
|
f55021f487 | ||
|
|
36bc6c3d19 | ||
|
|
4c68b2cb9c | ||
|
|
fb3bcb9f74 | ||
|
|
ed5686d981 | ||
|
|
e096611c96 | ||
|
|
c48d915f11 | ||
|
|
065988dcd7 | ||
|
|
d2aa9707de | ||
|
|
f3b0e21c20 | ||
|
|
6d25082d65 | ||
|
|
9891603994 | ||
|
|
e199542bd3 | ||
|
|
3a615fa11f | ||
|
|
deb4382dd0 | ||
|
|
bf1152ff75 | ||
|
|
9e82787da2 | ||
|
|
b4a9a2d313 | ||
|
|
36e9d03d1b | ||
|
|
53ad3cad14 | ||
|
|
fd4728e194 | ||
|
|
e83968fa28 | ||
|
|
6a27e819d7 | ||
|
|
d27c8b5660 | ||
|
|
6ec52a01ee | ||
|
|
ddf19eae0f | ||
|
|
46bd6d7a2f | ||
|
|
abb9fb8370 | ||
|
|
39b6ac476d | ||
|
|
0c67893ce9 | ||
|
|
e7159c828b | ||
|
|
d723636d52 | ||
|
|
a1192f17ba | ||
|
|
0640232acd | ||
|
|
258db3ad8e | ||
|
|
a39d299df4 | ||
|
|
43e3c22ae4 | ||
|
|
7ca751c78d | ||
|
|
697f5db331 | ||
|
|
bce2869d92 | ||
|
|
d7cbaae1fd | ||
|
|
6733116a19 | ||
|
|
0423887528 | ||
|
|
80b96a8974 | ||
|
|
c8b0988586 | ||
|
|
d59a2b6109 | ||
|
|
655849fb14 | ||
|
|
71cb54406a | ||
|
|
0f587ff6dc | ||
|
|
85ce90a6f3 | ||
|
|
975f35501a | ||
|
|
3c4a088312 | ||
|
|
0f632bf218 | ||
|
|
38737f138e | ||
|
|
5de52e34f0 | ||
|
|
3f67b36b35 | ||
|
|
985c7ae39c | ||
|
|
3e5c09fc04 | ||
|
|
5e40d5bf01 | ||
|
|
532142d214 | ||
|
|
dee5782e76 | ||
|
|
1dee5eb625 | ||
|
|
a3a50148fb | ||
|
|
eb256dbb6b | ||
|
|
b73c18242e | ||
|
|
c9895ac01e | ||
|
|
1e070872a3 | ||
|
|
613eea2da4 | ||
|
|
051e55b12b | ||
|
|
b7be589ed0 | ||
|
|
b41f5924bf | ||
|
|
1a91d0914e | ||
|
|
08db4eeb51 | ||
|
|
24bf45e606 | ||
|
|
a6fd031927 | ||
|
|
2384a25499 | ||
|
|
5a4760792f | ||
|
|
7a369d3704 | ||
|
|
217cb1aa84 | ||
|
|
7b0f529d3e | ||
|
|
d20956dcb1 | ||
|
|
2abbc07f3c | ||
|
|
8ca4d4436d | ||
|
|
b8175c33da | ||
|
|
a7ca334681 | ||
|
|
0aae84f9a2 | ||
|
|
dc49eeb6a3 | ||
|
|
c1a3bffdae | ||
|
|
86ef0fc9dd | ||
|
|
1239365201 | ||
|
|
a570dca703 | ||
|
|
f4cea344b1 | ||
|
|
8d6722c8ad | ||
|
|
4c42d18e0c | ||
|
|
08ebb57c9b | ||
|
|
a6bc975a24 | ||
|
|
a2b6bbdfb2 | ||
|
|
310efa7b96 | ||
|
|
36f9d53b60 | ||
|
|
2e08dbcb65 | ||
|
|
5161ecb98d | ||
|
|
91345610f8 | ||
|
|
ac3691f70e | ||
|
|
8b373275a2 | ||
|
|
7b45e46aa3 | ||
|
|
fd817ff34a | ||
|
|
94ff21b4f1 | ||
|
|
0699572d23 | ||
|
|
15fdc8d3ee | ||
|
|
1091650a79 | ||
|
|
c7ee154ba9 | ||
|
|
e2e67c87f5 | ||
|
|
649c45078f | ||
|
|
a09aa49783 | ||
|
|
d0af5def87 | ||
|
|
917c57e77b | ||
|
|
acb4b5e4de | ||
|
|
0a5182fc97 | ||
|
|
f168869702 | ||
|
|
b1f9a2f5d1 | ||
|
|
38220f9fe9 | ||
|
|
11c289c27a | ||
|
|
cccae7e633 | ||
|
|
770dc81b8e | ||
|
|
ec7a713558 | ||
|
|
75b8a10e4a | ||
|
|
4c4de324b8 | ||
|
|
ba8fd82a9c | ||
|
|
415feb2f44 | ||
|
|
d0c3da55a0 | ||
|
|
f518aadf43 | ||
|
|
f0f43bc093 | ||
|
|
4e27a85a2b | ||
|
|
c948101ccd | ||
|
|
ab5933d4ac | ||
|
|
26ade5f27e | ||
|
|
c900819b4e | ||
|
|
18b82048e4 | ||
|
|
db724a449b | ||
|
|
19a2c6e0a7 | ||
|
|
f8f6ec92b1 | ||
|
|
9f0a5c1d26 | ||
|
|
f30875dbc6 | ||
|
|
539f4a7728 | ||
|
|
f0f0b802d1 | ||
|
|
c927452439 | ||
|
|
0c330786f5 | ||
|
|
76602ee8ef | ||
|
|
87d73a9b85 | ||
|
|
814aebc4e9 | ||
|
|
c2fa9fa909 | ||
|
|
e24fb506a5 | ||
|
|
c485fe183e | ||
|
|
16d9293bd7 | ||
|
|
630e13edd8 | ||
|
|
65752052e1 | ||
|
|
ab9663f394 | ||
|
|
1a443ddd20 | ||
|
|
322633e1f5 | ||
|
|
3fe35b3283 | ||
|
|
d8c4949f3e | ||
|
|
a6ca9ac0bc | ||
|
|
a8ab586770 | ||
|
|
ccc2e192a0 | ||
|
|
3c23ff0f2e | ||
|
|
cd69ee7453 | ||
|
|
aee205752a | ||
|
|
e17bcc7432 | ||
|
|
f59b0f3e07 | ||
|
|
2fbeba9c32 | ||
|
|
4bdebfd151 | ||
|
|
a5ec3e3827 | ||
|
|
943c443426 | ||
|
|
97d91b30e6 | ||
|
|
6371bcbe55 | ||
|
|
13d8501f1c | ||
|
|
9e7b0091bb | ||
|
|
c97cbf8c08 | ||
|
|
00da033166 | ||
|
|
d251e86856 | ||
|
|
c8a5d26667 | ||
|
|
4979d41a98 | ||
|
|
d98d855918 | ||
|
|
810349313a | ||
|
|
88c4995d1d | ||
|
|
b9259173d0 | ||
|
|
5ef2c36a6b | ||
|
|
b7117425ab | ||
|
|
be40fe90ae | ||
|
|
3c134e0165 | ||
|
|
f0e073fcdc | ||
|
|
acbb93a383 | ||
|
|
5ffe56d800 | ||
|
|
629efc6a89 | ||
|
|
ed3329eb45 | ||
|
|
a5ce579672 | ||
|
|
15816a3b8c | ||
|
|
d6bf26af8e | ||
|
|
57f5ec5d6c | ||
|
|
d57c51d963 | ||
|
|
50ba52456e | ||
|
|
234b12480e | ||
|
|
0ade9a8b37 | ||
|
|
abdd429f35 | ||
|
|
04fa77c3be | ||
|
|
5bc2af2688 | ||
|
|
ddd6c357ba | ||
|
|
8caf272a93 | ||
|
|
46cabd8a2e | ||
|
|
30265f6ad2 | ||
|
|
9dc28ab802 | ||
|
|
b34f3ea13f | ||
|
|
f972c51364 | ||
|
|
a1b40be081 | ||
|
|
4b373907f6 | ||
|
|
e01bdd2fab | ||
|
|
9b5fd08d26 | ||
|
|
b1ef9cd0ad | ||
|
|
635983c449 | ||
|
|
43d99aab6c | ||
|
|
794b3b1605 | ||
|
|
9a2cde9519 | ||
|
|
537f7456e2 | ||
|
|
ff26b68abc | ||
|
|
5cb0d45d18 | ||
|
|
81d19574f7 | ||
|
|
676b511245 | ||
|
|
257bb03948 | ||
|
|
98d85f25be | ||
|
|
59dd86581a | ||
|
|
86dce60ffe | ||
|
|
fff0de4865 | ||
|
|
1014cf876a | ||
|
|
d3d98fdc1e | ||
|
|
a7ca101517 | ||
|
|
1d749d01fb | ||
|
|
2b1446c7d6 | ||
|
|
488298a5af | ||
|
|
d40821aabc | ||
|
|
dfcb905db0 | ||
|
|
13acd33b2f | ||
|
|
e408cf6906 | ||
|
|
13ecd94aef | ||
|
|
fc6dc34429 | ||
|
|
9bad95bd95 | ||
|
|
acdd91b3ce | ||
|
|
cf760281f0 | ||
|
|
c75ebae789 | ||
|
|
49095061cd | ||
|
|
8e8f77f8f3 | ||
|
|
fd6ca7415f | ||
|
|
fc0c0cb075 | ||
|
|
7a96516819 | ||
|
|
81410c8f09 | ||
|
|
f7729ec651 | ||
|
|
667c6be176 | ||
|
|
98998134de | ||
|
|
3c4310d6ef | ||
|
|
6c1c02dc52 | ||
|
|
7fef83d687 | ||
|
|
c9362fe854 | ||
|
|
c2b22f5633 | ||
|
|
27318b98a1 | ||
|
|
3579eeb2b0 | ||
|
|
eb9454ab68 | ||
|
|
e47a591d76 | ||
|
|
ed2bef01e5 | ||
|
|
e30f6c899d | ||
|
|
49b95a5e21 | ||
|
|
80b664f571 | ||
|
|
8dc351e8d4 | ||
|
|
73c47fae21 | ||
|
|
bf76ebd01a | ||
|
|
fc28b13c7d | ||
|
|
04bde319a9 | ||
|
|
f7b692d29f | ||
|
|
5a4eeb69c4 | ||
|
|
4269e36315 | ||
|
|
5f31bc7926 | ||
|
|
5eb7dfddeb | ||
|
|
43b24f7c61 | ||
|
|
c52678ee9b | ||
|
|
c79b425135 | ||
|
|
a39ac3e11b | ||
|
|
c582e3c039 | ||
|
|
28c3f0354a | ||
|
|
3a8d01b6e1 | ||
|
|
df06d9ac7a | ||
|
|
a0be44c727 | ||
|
|
c45af88a83 | ||
|
|
3b6a076e1e | ||
|
|
3869eff08d | ||
|
|
154b64d7a5 | ||
|
|
0b2d216f8e | ||
|
|
c21b944a35 | ||
|
|
aa6f4e51a7 | ||
|
|
68e8f5a4a2 | ||
|
|
109e6334b0 | ||
|
|
726355fef0 | ||
|
|
b6baf165c7 | ||
|
|
d7e70d2557 | ||
|
|
f3ac7d1b82 | ||
|
|
3f5cc86aa4 | ||
|
|
12b646541b | ||
|
|
6275dd8126 | ||
|
|
673421ffc2 | ||
|
|
e55df6fee5 | ||
|
|
e995e713f9 | ||
|
|
94d4a90f27 | ||
|
|
ccd6d287eb | ||
|
|
beacd0b303 | ||
|
|
68427c03e9 | ||
|
|
0878503f0f | ||
|
|
55313cb6bf | ||
|
|
4df024c40c | ||
|
|
0366ff6fb0 | ||
|
|
a750353641 | ||
|
|
d2b43c4b34 | ||
|
|
b422bb2187 | ||
|
|
23f4aabd69 | ||
|
|
77dd1c0e5f | ||
|
|
f070e0d9e8 | ||
|
|
72e0743621 | ||
|
|
c9f27b1ca1 | ||
|
|
5f6519758f | ||
|
|
eaac0790f5 | ||
|
|
56bb994166 | ||
|
|
d011e2cc11 | ||
|
|
77a4260fe8 | ||
|
|
62ecac8187 | ||
|
|
cda69e17ef | ||
|
|
4998a0041f | ||
|
|
387f47078c | ||
|
|
a362bb23c0 | ||
|
|
ea8acabe26 | ||
|
|
1e13fa7a6a | ||
|
|
c75550f5ba | ||
|
|
876835f2f1 | ||
|
|
2c352d7b1e | ||
|
|
f760f97a1f | ||
|
|
dd7f4abd9f | ||
|
|
f407c8afd0 | ||
|
|
03984e05a3 | ||
|
|
bf8c8a6d61 | ||
|
|
5d196aa430 | ||
|
|
255fc32087 | ||
|
|
5b7f6ad698 | ||
|
|
56b3d20462 | ||
|
|
df13cf08d5 | ||
|
|
b7eb2ad04d | ||
|
|
68085c93b0 | ||
|
|
2ca6b865f6 | ||
|
|
7a8fa6aaab | ||
|
|
0e06c92fdf | ||
|
|
c9118a1d20 | ||
|
|
d37be0b865 | ||
|
|
ac85c2e75b | ||
|
|
d7f44761ab | ||
|
|
4b1687fb74 | ||
|
|
60494fe74b | ||
|
|
eb75125539 | ||
|
|
0c409a58ee | ||
|
|
cfe30f1df3 | ||
|
|
aa02928ff7 | ||
|
|
fbcb06145b | ||
|
|
dff5da2d64 | ||
|
|
3dfeaca59b | ||
|
|
207542b40e | ||
|
|
550cae2340 | ||
|
|
b1ebf028de | ||
|
|
735308699c | ||
|
|
685be1dc7a | ||
|
|
c8d8f74188 | ||
|
|
2df53fc3d0 | ||
|
|
34de60e4d4 | ||
|
|
adee669441 | ||
|
|
452bbb87a9 | ||
|
|
0fa0e6addf | ||
|
|
27132718d4 | ||
|
|
85fabd8116 | ||
|
|
4b3efd3537 | ||
|
|
4499aa2ea5 | ||
|
|
cc31b2bd3f | ||
|
|
7251c8f3a5 | ||
|
|
f9f8cd08b3 | ||
|
|
f72a06ccf7 | ||
|
|
6911c90074 | ||
|
|
0d408f0c43 | ||
|
|
59baeb838c | ||
|
|
05d08428b3 | ||
|
|
7a3263f2a0 | ||
|
|
63ae0d1464 | ||
|
|
29f011314d | ||
|
|
b917086464 | ||
|
|
fec4de9563 | ||
|
|
60184834b5 | ||
|
|
6c8ffd0362 | ||
|
|
08e64ce5e9 | ||
|
|
e4e8cf3b59 | ||
|
|
c053fb62bc | ||
|
|
0548bcc2dc | ||
|
|
f1a4ec40fc | ||
|
|
99a304bc17 | ||
|
|
42812732a3 | ||
|
|
1bedaf742a | ||
|
|
a124554ded | ||
|
|
be46b5e5a8 | ||
|
|
5800aa5c07 | ||
|
|
16e033b91a | ||
|
|
ccb601a3cb | ||
|
|
32780caae3 | ||
|
|
a2552d4f59 | ||
|
|
b1bee9cd52 | ||
|
|
13b665e481 | ||
|
|
2b2c5617d6 | ||
|
|
fed0e904f2 | ||
|
|
0025670dc9 | ||
|
|
cd501dd440 | ||
|
|
e1ab01e3ad | ||
|
|
155c608cd3 | ||
|
|
6b8304ab43 | ||
|
|
a4893bc377 | ||
|
|
b315fcaba6 | ||
|
|
938cf35994 | ||
|
|
31b2e7ed94 | ||
|
|
c7dbfb43c4 | ||
|
|
4e11dfe3ca | ||
|
|
e2683aafe6 | ||
|
|
090585a8f4 | ||
|
|
2f1d6f7f0c | ||
|
|
e7a5c8cf3d | ||
|
|
810e831816 | ||
|
|
4514bdcfa2 | ||
|
|
c85222c461 | ||
|
|
39b1e58979 | ||
|
|
b9ac4b0cf8 | ||
|
|
20babc7b4f | ||
|
|
f145ddc9e7 | ||
|
|
584d1fb7d1 | ||
|
|
9c20c7af59 | ||
|
|
9c19bfad07 | ||
|
|
9abf5e70be | ||
|
|
6ddadf4023 | ||
|
|
ba3851fda6 | ||
|
|
d2e3654f88 | ||
|
|
83faae091d | ||
|
|
a8fb89adaf | ||
|
|
badfe1cfd2 | ||
|
|
7fb52b9c39 | ||
|
|
61c146fb97 | ||
|
|
eb82f939ee | ||
|
|
1ace1b5ddf | ||
|
|
a42efe6bdf | ||
|
|
2a924b3eaf | ||
|
|
c6ea6bf5b7 | ||
|
|
accb17389c | ||
|
|
06f97f3be3 | ||
|
|
fc7ad9d4c7 | ||
|
|
dfe786c218 | ||
|
|
0e6c4e93da | ||
|
|
29aa56df68 | ||
|
|
1ef6c6b107 | ||
|
|
75b37a1147 | ||
|
|
4059d2219c | ||
|
|
cf177380b5 | ||
|
|
178dcb065e | ||
|
|
e5fa2e4492 | ||
|
|
ebc9a27ad5 | ||
|
|
b040e267a2 | ||
|
|
7c638cc236 | ||
|
|
421671b1c2 | ||
|
|
5a3bd51380 | ||
|
|
23087fc917 | ||
|
|
984abde146 | ||
|
|
4424497f65 | ||
|
|
a3a02a2f42 | ||
|
|
cb63efc6f9 | ||
|
|
06bb53b1e8 | ||
|
|
3687de1b8c | ||
|
|
772f7d4188 | ||
|
|
f16aea9ebd | ||
|
|
5f1f31f942 | ||
|
|
70a0e7aba6 | ||
|
|
241e84f79d | ||
|
|
6ce24f679a | ||
|
|
1e2ed180ca | ||
|
|
b4048242f5 | ||
|
|
a1bb606aab | ||
|
|
39dabc84cf | ||
|
|
ae1e83aa94 | ||
|
|
902c4069dc | ||
|
|
89044bc0fe | ||
|
|
c503c83c78 | ||
|
|
2cec0e4562 | ||
|
|
79aa89a62a | ||
|
|
b34447e233 | ||
|
|
21e094d9df | ||
|
|
0ddb66efba | ||
|
|
b8a7da0133 | ||
|
|
a7dfe4f24d | ||
|
|
0175de7f11 | ||
|
|
2ce3412b46 | ||
|
|
2e201936e4 | ||
|
|
f900ba63fa | ||
|
|
879624f591 | ||
|
|
36a1d8166c | ||
|
|
c24a4ff2cc | ||
|
|
29123aa652 | ||
|
|
acb4073eed | ||
|
|
a80fc69320 | ||
|
|
437219e27d | ||
|
|
cf65a124e6 | ||
|
|
e1b8a236b7 | ||
|
|
db8b5af9d9 | ||
|
|
1ae301590b | ||
|
|
c561e477db | ||
|
|
680617f50b | ||
|
|
5f3dc21dba | ||
|
|
29846c24a8 | ||
|
|
3d32c5f88b | ||
|
|
78ad1549a5 | ||
|
|
4b12fa1377 | ||
|
|
42dd692bea | ||
|
|
1d707156cc | ||
|
|
8e4858ccd1 | ||
|
|
aad0d06cf9 | ||
|
|
5b6fad120f | ||
|
|
93bbc31c83 | ||
|
|
724de2791e | ||
|
|
64a950108c | ||
|
|
89a6cdfd4c | ||
|
|
05e59bf3fa | ||
|
|
a0f9708e49 | ||
|
|
d557773841 | ||
|
|
673ecf73cf | ||
|
|
95eaa68309 | ||
|
|
ec0b34a9ca | ||
|
|
c9b9c79b03 | ||
|
|
2b33edfcf7 | ||
|
|
536f0e0881 | ||
|
|
9bc9dacc1e | ||
|
|
42870d441d | ||
|
|
c0b23a1491 | ||
|
|
1178220354 | ||
|
|
96e46b8edb | ||
|
|
6c7bde0bba | ||
|
|
3c74075fb1 | ||
|
|
3545e55a01 | ||
|
|
5738c54f77 | ||
|
|
cf8ee443e5 | ||
|
|
d9be54adb3 | ||
|
|
0c29b5cb89 | ||
|
|
595eaf925c | ||
|
|
5a446cfbb9 | ||
|
|
68fac97a07 | ||
|
|
2ae1562664 | ||
|
|
786e32bfa0 | ||
|
|
663bf8f7f6 | ||
|
|
d0800aba01 | ||
|
|
6087b1581d | ||
|
|
4b7033d3f1 | ||
|
|
266214db84 | ||
|
|
90c8088760 | ||
|
|
a4cc1ef5d9 | ||
|
|
651ff9b328 | ||
|
|
905240f91d | ||
|
|
fca434258a | ||
|
|
a0b0df936b | ||
|
|
8c7946664c | ||
|
|
97cf20174d | ||
|
|
221b941eb5 | ||
|
|
e94a31b2c6 | ||
|
|
f83332a0d5 | ||
|
|
9b77df2ae7 | ||
|
|
93d1fdba4b | ||
|
|
fd8563328c | ||
|
|
9a9026c29f | ||
|
|
3649fa9e41 | ||
|
|
e2ac2ad9bc | ||
|
|
46b50a2520 | ||
|
|
e83484c216 | ||
|
|
25eac61778 | ||
|
|
b0081c3778 | ||
|
|
2433909e20 | ||
|
|
5e9891477a | ||
|
|
e5ee502092 | ||
|
|
4071b6a401 | ||
|
|
5f1c57d008 | ||
|
|
428743a380 | ||
|
|
b153cf3169 | ||
|
|
a5609e3086 | ||
|
|
43a1ea4e2f | ||
|
|
d50795ed09 | ||
|
|
940077d030 | ||
|
|
3de6df8410 | ||
|
|
b40b65fb3c | ||
|
|
90aa7de640 | ||
|
|
3d9c2d86b0 | ||
|
|
7c86e3909c | ||
|
|
af9ded781d | ||
|
|
115bc65bae | ||
|
|
ae4ca998a3 | ||
|
|
eb7c87e90d | ||
|
|
392b185173 | ||
|
|
d1c45aa74f | ||
|
|
501fda8056 | ||
|
|
ab2d981a97 | ||
|
|
9cc31e6dff | ||
|
|
5bad8ac847 | ||
|
|
73e48198f0 | ||
|
|
5d311afba2 | ||
|
|
5863975c29 | ||
|
|
2bda19e999 | ||
|
|
74aa6b5620 | ||
|
|
c99b9fa946 | ||
|
|
f8d076d827 | ||
|
|
8c222979e5 | ||
|
|
ac7d720725 | ||
|
|
b45e346f7a | ||
|
|
66fd45290c | ||
|
|
a946372e50 | ||
|
|
226e79e7b7 | ||
|
|
3c0cfa8f3c | ||
|
|
c2d4398d47 | ||
|
|
3d37e976bf | ||
|
|
c7a3cc0a9b | ||
|
|
afa8ea4078 | ||
|
|
162aefe84b | ||
|
|
03c65b7ade | ||
|
|
cdc8e54e3d | ||
|
|
454bd4dc3b | ||
|
|
3c14bcca33 | ||
|
|
8f26e18c13 | ||
|
|
ea30184099 | ||
|
|
5d5e2bf8f6 | ||
|
|
004c103c20 | ||
|
|
e0e7fb8418 | ||
|
|
5d370b1bdd | ||
|
|
7510963fbf | ||
|
|
2834bc8ee3 | ||
|
|
acac361359 | ||
|
|
defed336ae | ||
|
|
c808baef08 | ||
|
|
b521cadd66 | ||
|
|
a5a6597a7e | ||
|
|
adfb0e348d | ||
|
|
7cec175dfc | ||
|
|
79e5594fe5 | ||
|
|
b23fadb965 | ||
|
|
9486d01416 | ||
|
|
c3fd683fa4 | ||
|
|
e637f732ed | ||
|
|
f9ff23dffe | ||
|
|
2be430435f | ||
|
|
1879e85672 | ||
|
|
fa5617d7f5 | ||
|
|
ee1e49ec53 | ||
|
|
56aba8dc9d | ||
|
|
a83b7adc28 | ||
|
|
61b61849eb | ||
|
|
f3bc056a44 | ||
|
|
49886d0982 | ||
|
|
cf8235e0aa | ||
|
|
c48b10050a | ||
|
|
83a3c60506 | ||
|
|
252239bdac | ||
|
|
f9e17e36aa | ||
|
|
2ad32d9518 | ||
|
|
aaa01e3488 | ||
|
|
a74be32bf6 | ||
|
|
5e82475490 | ||
|
|
f86117e3d5 | ||
|
|
b59c9854e8 | ||
|
|
b42929dca7 | ||
|
|
f5cb304acb | ||
|
|
d25584e4fb | ||
|
|
7aa72b6820 | ||
|
|
0e867038da | ||
|
|
e516e0708c | ||
|
|
098c16c9df | ||
|
|
e92d56a94d | ||
|
|
bb2a46b218 | ||
|
|
2aabcc1c1c | ||
|
|
57b660356e | ||
|
|
70c0c29145 | ||
|
|
bd90c6b2c2 | ||
|
|
2c0dfdf839 | ||
|
|
b634751cc4 | ||
|
|
4d8c4ea7e6 | ||
|
|
9607eba5c2 | ||
|
|
78ce7acc0c | ||
|
|
a5f46f6a22 | ||
|
|
5d518f1f18 | ||
|
|
377b6a5843 | ||
|
|
733bd656b2 | ||
|
|
04b2a4bdcf | ||
|
|
d01a37f597 | ||
|
|
c8a4e489c1 | ||
|
|
ad273af9c7 | ||
|
|
2143b169b1 | ||
|
|
8b9e515185 | ||
|
|
f15a2320bd | ||
|
|
82c445b01d | ||
|
|
9b6f239159 | ||
|
|
e3d384af5b | ||
|
|
018eceb66b | ||
|
|
3543c9b320 | ||
|
|
9e813cc93b | ||
|
|
664ef2f993 | ||
|
|
28ae3fe772 | ||
|
|
8762493eb8 | ||
|
|
b0928986bf | ||
|
|
d49aa42eec | ||
|
|
29c70fbd86 | ||
|
|
5c8922b724 | ||
|
|
1df7ef9a05 | ||
|
|
afcd9399a9 | ||
|
|
d48b3d26c9 | ||
|
|
e3f0940aae | ||
|
|
9ac1af7160 | ||
|
|
88e3ced7df | ||
|
|
f4edfec799 | ||
|
|
f7bc94ac3a | ||
|
|
98418e2b6e | ||
|
|
9c2e73fdd2 | ||
|
|
42a871b3df | ||
|
|
d4b311970d | ||
|
|
a44d004684 | ||
|
|
df621aa30b | ||
|
|
5f16e04b77 | ||
|
|
b3417a320e | ||
|
|
dce56c9761 | ||
|
|
9085c301e0 | ||
|
|
776ac1562e | ||
|
|
ee7e183f7e | ||
|
|
c533b9a305 | ||
|
|
ed8031de4f | ||
|
|
dfe213f804 | ||
|
|
1bd72d90a4 | ||
|
|
0589e19fd7 | ||
|
|
f6b1eaf700 | ||
|
|
c8fb043a01 | ||
|
|
efd7d4c20f | ||
|
|
9c492aeecd | ||
|
|
7d55939138 | ||
|
|
0e5c15a1ba | ||
|
|
2642ef553a | ||
|
|
63b186b6f7 | ||
|
|
bd1dcfbe96 | ||
|
|
a57262a7ee | ||
|
|
f864285b3a | ||
|
|
648fa396d9 | ||
|
|
2572832e0c | ||
|
|
93e025dcc4 | ||
|
|
5ed9395077 | ||
|
|
4e57aae3a7 | ||
|
|
1efda0fbb9 | ||
|
|
0185663b88 | ||
|
|
befeabb45a | ||
|
|
8bcb96836d | ||
|
|
90e0faf3db | ||
|
|
81bbb483f4 | ||
|
|
83f25cd121 | ||
|
|
8b3755a679 | ||
|
|
483a7cb6d5 | ||
|
|
8c38c9642c | ||
|
|
a66c95ce44 | ||
|
|
599e07d2e0 | ||
|
|
ce611945ad | ||
|
|
7a35a9f5d8 | ||
|
|
9963d0710e | ||
|
|
c42b235610 | ||
|
|
e6479dff9f | ||
|
|
81779abd54 | ||
|
|
7a0b0db17e | ||
|
|
8842d526b2 | ||
|
|
8675b317ff | ||
|
|
9091827c46 | ||
|
|
c9b4604ba6 | ||
|
|
bae6bc62bd | ||
|
|
aa496e4c23 | ||
|
|
89777f9cec | ||
|
|
9d5a318ac6 | ||
|
|
d4b6a8aa2a | ||
|
|
beeba64080 | ||
|
|
1cc59fa4ac | ||
|
|
2918b433a3 | ||
|
|
c07d773e67 | ||
|
|
fce6fb489f | ||
|
|
0b7cc76a9d | ||
|
|
e6923120b9 | ||
|
|
ad534f790e | ||
|
|
fe63e644d9 | ||
|
|
122ccd0d04 | ||
|
|
fd443e0245 | ||
|
|
e9344c9174 | ||
|
|
1936861b9a | ||
|
|
a831b4920f | ||
|
|
f032ed7498 | ||
|
|
6c6c821445 | ||
|
|
357ed599ec | ||
|
|
5f055102fa | ||
|
|
7516d78193 | ||
|
|
f6ffb81bf8 | ||
|
|
eefacdfa04 | ||
|
|
729f472c04 | ||
|
|
7004662395 | ||
|
|
c47ad88392 | ||
|
|
340b6b0fb1 | ||
|
|
bf45614685 | ||
|
|
3d52ff1a75 | ||
|
|
ba15f0316a | ||
|
|
8a68d95466 | ||
|
|
2d346fb714 | ||
|
|
df4b9706da | ||
|
|
31add81f69 | ||
|
|
a9f628b78d | ||
|
|
41a3c26f07 | ||
|
|
b68cc09932 | ||
|
|
3dcd5b3017 | ||
|
|
2d5ba1f2d1 | ||
|
|
69c7e1f754 | ||
|
|
6111e048a3 | ||
|
|
2206eb2409 | ||
|
|
c791c54e5b | ||
|
|
e0bd7c7645 | ||
|
|
a0b1b1872e | ||
|
|
9fac443591 | ||
|
|
d917192f00 | ||
|
|
d614646157 | ||
|
|
b8f47d5f69 | ||
|
|
99a5d8a9c4 | ||
|
|
26d7762bda | ||
|
|
7476b50218 | ||
|
|
a7aa8b16d0 | ||
|
|
eac6599c5e | ||
|
|
9386a68477 | ||
|
|
e7c3fdd048 | ||
|
|
d2ee20a42a | ||
|
|
746bb69067 | ||
|
|
0d7bacf56e | ||
|
|
ee2e742ae3 | ||
|
|
21a98eda88 | ||
|
|
6ee7d2aa53 | ||
|
|
51dfb124e1 | ||
|
|
19089ba331 | ||
|
|
b5fd1544d5 | ||
|
|
1a4366df60 | ||
|
|
213c999a92 | ||
|
|
1f74536332 | ||
|
|
8b6501e6e9 | ||
|
|
8d9fb97582 | ||
|
|
7beb03dd2a | ||
|
|
867ff24616 | ||
|
|
ff6ed274a9 | ||
|
|
930a1434ac | ||
|
|
9c5a7b0481 | ||
|
|
39d6ccdfc7 | ||
|
|
cec2a2dacc | ||
|
|
ffc12b3fc1 | ||
|
|
6452d4ae9d | ||
|
|
5b57e82508 | ||
|
|
f012e6a1a0 | ||
|
|
3395d72881 | ||
|
|
f4b2b84904 | ||
|
|
7f355587f5 | ||
|
|
c944836420 | ||
|
|
c4c107f215 | ||
|
|
85d2f1811a | ||
|
|
a4f5a4cc2d | ||
|
|
b85357cd0c | ||
|
|
7fa91ec044 | ||
|
|
03660b3045 | ||
|
|
42ae96fa3d | ||
|
|
a6ad9c6166 | ||
|
|
a9cb6969b0 | ||
|
|
f1c90ec108 | ||
|
|
08f0d365fd | ||
|
|
d09a7dfc6e | ||
|
|
25497e2fa5 | ||
|
|
7fdf112457 | ||
|
|
0d107e7014 | ||
|
|
10a27bdfb6 | ||
|
|
5d623bde94 | ||
|
|
dba458ae9a | ||
|
|
a88bfbcb13 | ||
|
|
3f6a21ead4 | ||
|
|
b1278ba1b8 | ||
|
|
de5dfec56b | ||
|
|
9af5a142d0 | ||
|
|
4a86bafbcc | ||
|
|
2c3093af7c | ||
|
|
e0f4404a29 | ||
|
|
6e7d597a50 | ||
|
|
0f66b7086b | ||
|
|
62406f5408 | ||
|
|
f882633886 | ||
|
|
71e41d9139 | ||
|
|
e5c935bd12 | ||
|
|
4c35d6dee6 | ||
|
|
b251e09035 | ||
|
|
cd082bbea7 | ||
|
|
6b6f59da79 | ||
|
|
dd1d42d5d0 | ||
|
|
3d425215a8 | ||
|
|
503f62808e | ||
|
|
609faae9a5 | ||
|
|
6cf4278659 | ||
|
|
4c611a220a | ||
|
|
1ad6d98bbe | ||
|
|
c1060e13a7 | ||
|
|
bb6a3a9608 | ||
|
|
4b2cae463e | ||
|
|
b09a20e537 | ||
|
|
6e10090b58 | ||
|
|
f1adcde4bc | ||
|
|
542d034441 | ||
|
|
819f14eaf4 | ||
|
|
b91eb158d4 | ||
|
|
a2214e5509 | ||
|
|
542ef24d9f | ||
|
|
13e8c7e434 | ||
|
|
b8b3508c59 | ||
|
|
4397ad387e | ||
|
|
e50c61d8fa | ||
|
|
476d463348 | ||
|
|
c6b235efc8 | ||
|
|
4f9012704c | ||
|
|
f7c76e3878 | ||
|
|
96d0004d12 | ||
|
|
2f5a1df42c | ||
|
|
024e2cd0e6 | ||
|
|
6391d03f54 | ||
|
|
be0938ad3c | ||
|
|
8742213863 | ||
|
|
01b988cfd8 | ||
|
|
a330337af2 | ||
|
|
1f164ad9d0 | ||
|
|
1bf740434a | ||
|
|
01fb9ca9a0 | ||
|
|
8bc510ba12 | ||
|
|
9242380c2f | ||
|
|
38ddfe7be5 | ||
|
|
2565a5e528 | ||
|
|
5cc66af8d6 | ||
|
|
11ee855e40 | ||
|
|
fe2b3ea0d4 | ||
|
|
41c97745a6 | ||
|
|
37093b1d17 | ||
|
|
d39e1be45c | ||
|
|
6c1e32c0e0 | ||
|
|
12ca060e9f | ||
|
|
33048414d4 | ||
|
|
6efacee75c | ||
|
|
9567c70939 | ||
|
|
285375e6c3 | ||
|
|
f3a56d49e3 | ||
|
|
07b0c948ee | ||
|
|
b4a2de670a | ||
|
|
12b1f31cbb | ||
|
|
2d37634918 | ||
|
|
a908d0030c | ||
|
|
66086ce962 | ||
|
|
89b7d5cb4c | ||
|
|
6f4a82b3f4 | ||
|
|
f91635a1bd | ||
|
|
9c155e14a2 | ||
|
|
c26488d348 | ||
|
|
896fc66e32 | ||
|
|
9767eb448d | ||
|
|
dbbf3d1bb8 | ||
|
|
3ea4ef7421 | ||
|
|
c9ee46569c | ||
|
|
b6deac338f | ||
|
|
771e191e99 | ||
|
|
31f55a07db | ||
|
|
59d06d4dc7 | ||
|
|
c1fdeec999 | ||
|
|
eca971ca6c | ||
|
|
5cffbf0bb0 | ||
|
|
a0a95f8a66 | ||
|
|
613a355c4b | ||
|
|
5746e2e769 | ||
|
|
ca51e5d9ec | ||
|
|
ea0e5e6ea8 | ||
|
|
99113cc588 | ||
|
|
154753db8b | ||
|
|
36a1d9e9b4 | ||
|
|
ea91a71bb9 | ||
|
|
fcc2a694eb | ||
|
|
4884e0e217 | ||
|
|
49c27642d4 | ||
|
|
c658240217 | ||
|
|
572fefeb90 | ||
|
|
4b896598c7 | ||
|
|
25a2e7b80e | ||
|
|
58e57a05c0 | ||
|
|
450928e304 | ||
|
|
6ac30c94f2 | ||
|
|
49b9da5a56 | ||
|
|
d396100278 | ||
|
|
a01e55b6ec | ||
|
|
eb91c4eee3 | ||
|
|
e471c8eaef | ||
|
|
fa6dca9f28 | ||
|
|
8dd0ae923b | ||
|
|
ac0034c20f | ||
|
|
94994d7e74 | ||
|
|
65edd11bfb | ||
|
|
e1b0dce76e | ||
|
|
0a5e42897e | ||
|
|
761e574190 | ||
|
|
970f241c52 | ||
|
|
82cf926094 | ||
|
|
afd9ba98c1 | ||
|
|
59d8429cb3 | ||
|
|
b14c5af76d | ||
|
|
0b706ac672 | ||
|
|
494b4cec7b | ||
|
|
d60f341d96 | ||
|
|
4b13d5a823 | ||
|
|
3a5d73beb0 | ||
|
|
cfebc626b6 | ||
|
|
5a820745ce | ||
|
|
b44e3bdc86 | ||
|
|
2f9a9d1a7f | ||
|
|
920e68d603 | ||
|
|
1cbdc00ecc | ||
|
|
96e09924da | ||
|
|
0b502933c5 | ||
|
|
19363a13b1 | ||
|
|
be82186cba | ||
|
|
aa1bcec8d2 | ||
|
|
45aff0a2bb | ||
|
|
614e02904a | ||
|
|
031966bdb0 | ||
|
|
31424a53ee | ||
|
|
eb7d3facea | ||
|
|
5c93cdba2d | ||
|
|
610646095b | ||
|
|
14f5aa2753 | ||
|
|
c5185d4c03 | ||
|
|
1fa92933b5 | ||
|
|
4afec75e94 | ||
|
|
e08ad14696 | ||
|
|
7833b01291 | ||
|
|
87f42fda5e | ||
|
|
7f54ef36dc | ||
|
|
bf3423d355 | ||
|
|
2dce31a16a | ||
|
|
3802b91a4a | ||
|
|
eb23252b61 | ||
|
|
54120cb254 | ||
|
|
e1ea382999 | ||
|
|
eeadae1b6a | ||
|
|
d85cf5d14d | ||
|
|
40907c2928 | ||
|
|
cd978f74da | ||
|
|
efa62ff443 | ||
|
|
293b6f7eaa | ||
|
|
dfbc015c69 | ||
|
|
e5656d86d2 | ||
|
|
9b76dcc190 | ||
|
|
8f3fd69ffa | ||
|
|
c4ff133840 | ||
|
|
d66abfb82a | ||
|
|
81c7482974 | ||
|
|
96bfa40b47 | ||
|
|
1cc75dfb53 | ||
|
|
19061a1a15 | ||
|
|
043b13625b | ||
|
|
405366fd48 | ||
|
|
fc310448c0 | ||
|
|
095bbca691 | ||
|
|
8e1d5615b4 | ||
|
|
d828b9a4d7 | ||
|
|
6fe905c705 | ||
|
|
1b25b6e009 | ||
|
|
6ce8f8d553 | ||
|
|
9bcd5c2ffc | ||
|
|
beeae21dbb | ||
|
|
772cac09e3 | ||
|
|
bef749c942 | ||
|
|
0377a6de21 | ||
|
|
e24f357c23 | ||
|
|
6d1208546d | ||
|
|
2691077d90 | ||
|
|
e69246e1b7 | ||
|
|
fe41c21be9 | ||
|
|
ec5703ea07 | ||
|
|
212a510f04 | ||
|
|
3330038ebc | ||
|
|
8f85721f00 | ||
|
|
aa8111b3cd | ||
|
|
0ef8308f1b | ||
|
|
c35df82da9 | ||
|
|
fbd97a3425 | ||
|
|
36881b0133 | ||
|
|
6a8feb3c26 | ||
|
|
1d13e51826 | ||
|
|
1b2e147cc8 | ||
|
|
a9d72f0e9d | ||
|
|
3402ccd488 | ||
|
|
d917c98cd8 | ||
|
|
f5ac9a9495 | ||
|
|
d726767f14 | ||
|
|
7f436a0f39 | ||
|
|
470304e2a2 | ||
|
|
01a3cb443e | ||
|
|
47e1baf1e4 | ||
|
|
d0e0cb9973 | ||
|
|
fac0314c58 | ||
|
|
4df86ce1ac | ||
|
|
77986fa71a | ||
|
|
227301e041 | ||
|
|
e0c64c6c35 | ||
|
|
0bf8455b64 | ||
|
|
436cd05156 | ||
|
|
fe3a28e2cc | ||
|
|
ab5be5f065 | ||
|
|
c3b50730b8 | ||
|
|
3361724033 | ||
|
|
81680dce3c | ||
|
|
2b23864219 | ||
|
|
ed82bfd2ba | ||
|
|
8a4e6cac0a | ||
|
|
bc175d2870 | ||
|
|
e2997b7328 | ||
|
|
83d026861c | ||
|
|
7b1c853bd9 | ||
|
|
edf47283de | ||
|
|
b36d715a92 | ||
|
|
82c29eedc0 | ||
|
|
c8669f6b13 | ||
|
|
049cbb75b8 | ||
|
|
5f4b7a2644 | ||
|
|
0241c10fd6 | ||
|
|
ec6a6fbef2 | ||
|
|
7ac8b7c340 | ||
|
|
47870122d7 | ||
|
|
8929ce6651 | ||
|
|
47c0f6ae76 | ||
|
|
277534474e | ||
|
|
45bec96725 | ||
|
|
62b248d2ed | ||
|
|
98bea5edbf | ||
|
|
9b99f3337b | ||
|
|
fec1903f58 | ||
|
|
fc5e78cf5e | ||
|
|
0f817d38f7 | ||
|
|
3dfe4e29af | ||
|
|
9c61679e6f | ||
|
|
0f1917afa7 | ||
|
|
d3e282c9d8 | ||
|
|
2095de1af2 | ||
|
|
ea0cdd28c1 | ||
|
|
284f4496c3 | ||
|
|
92a4d6b28a | ||
|
|
cd96532e78 | ||
|
|
76cc7b2754 | ||
|
|
4631e58782 | ||
|
|
fd5c5a9703 | ||
|
|
4ff2b4ee5d | ||
|
|
432d4b9f6e | ||
|
|
544deede49 | ||
|
|
b8fa516016 | ||
|
|
ff2f094761 | ||
|
|
bc92cde62c | ||
|
|
8544a8a254 | ||
|
|
302125622a | ||
|
|
a40fb438e6 | ||
|
|
f653fb2b07 | ||
|
|
c6a808f1a7 | ||
|
|
f2042acc7f | ||
|
|
6f3c1dcee7 | ||
|
|
c0f61d7d22 | ||
|
|
b40b5ecc0b | ||
|
|
583ee60169 | ||
|
|
9c961554c4 | ||
|
|
6baf973742 | ||
|
|
1a0280b313 | ||
|
|
813db2c158 | ||
|
|
422c49558f | ||
|
|
bf180e98f4 | ||
|
|
67d66d3225 | ||
|
|
9bbd343f3a | ||
|
|
2815870302 | ||
|
|
cde6f0b767 | ||
|
|
1c96ddd735 | ||
|
|
1f1aaf43ea | ||
|
|
219b480da1 | ||
|
|
c926ea5cc4 | ||
|
|
e9f57f2beb | ||
|
|
0ce31ccc15 | ||
|
|
bf0378593c | ||
|
|
c48e40391b | ||
|
|
326902f0c7 | ||
|
|
de28fed87b | ||
|
|
6cca7a9fd6 | ||
|
|
da1ba4ed88 | ||
|
|
d6b42282c7 | ||
|
|
42dee539e2 | ||
|
|
6d1b3b5385 | ||
|
|
0c8bdaf33c | ||
|
|
ed96a9feb4 | ||
|
|
3ad47d16ab | ||
|
|
0296197999 | ||
|
|
c5c13fe776 | ||
|
|
0fa2c4ed7f | ||
|
|
c030183316 | ||
|
|
0fb1762159 | ||
|
|
539f903fd2 | ||
|
|
7b6c011c54 | ||
|
|
24bf9537a7 | ||
|
|
ffa9b6a571 | ||
|
|
9db16312b8 | ||
|
|
9a04baa27c | ||
|
|
3368322e0d | ||
|
|
f059ab7150 | ||
|
|
a51b3f838d | ||
|
|
4fa2c7f8b6 | ||
|
|
058f3d3523 | ||
|
|
b0eb2d3ac5 | ||
|
|
6f4c0fb93d | ||
|
|
fb19b83ff2 | ||
|
|
4242655be1 | ||
|
|
f80091eea3 | ||
|
|
66a706be6a | ||
|
|
c7e363f98a | ||
|
|
d17a8e365d | ||
|
|
b721056e04 | ||
|
|
8d2f8d7b6b | ||
|
|
b47952641a | ||
|
|
9d9589d173 | ||
|
|
89ef434fe0 | ||
|
|
615de1b59b | ||
|
|
e2675481f0 | ||
|
|
18dcfb6987 | ||
|
|
acc4138895 | ||
|
|
edd86b1fe4 | ||
|
|
75ad714362 | ||
|
|
2de380336d | ||
|
|
07698bfd56 | ||
|
|
98cd0c141c | ||
|
|
3015b03df2 | ||
|
|
da52655315 | ||
|
|
cee9a8d87e | ||
|
|
a9145575f2 | ||
|
|
82dcb097c4 | ||
|
|
f302d21406 | ||
|
|
571168690b | ||
|
|
0499fb88d6 | ||
|
|
23cf7bc97c | ||
|
|
cc44e17c5e | ||
|
|
8cd284edab | ||
|
|
40387549dd | ||
|
|
7314bc1d45 | ||
|
|
8d514d66e1 | ||
|
|
5e57517055 | ||
|
|
f622b0de34 | ||
|
|
b6f3ef938a | ||
|
|
024acb0335 | ||
|
|
b362d126ef | ||
|
|
7ceca1a286 | ||
|
|
136e519985 | ||
|
|
fe2b20db56 | ||
|
|
1066b93ade | ||
|
|
3a91213caf | ||
|
|
e7513be20c | ||
|
|
b39e32266a | ||
|
|
5b45c0728f | ||
|
|
77b69aa724 | ||
|
|
7f78616f3d | ||
|
|
a479de2e75 | ||
|
|
56d8844068 | ||
|
|
e50d0e97b1 | ||
|
|
4c2389c80a | ||
|
|
0016dd21e6 | ||
|
|
503612687e | ||
|
|
d4b9af444c | ||
|
|
2c44337bd5 | ||
|
|
28f60ff82f | ||
|
|
3e5b6ed214 | ||
|
|
965566dcf0 | ||
|
|
7e3fe8305d | ||
|
|
597c3f8e0f | ||
|
|
24bbc4d71e | ||
|
|
0782ad5002 | ||
|
|
f58b35b5a4 | ||
|
|
2cde7dfdb3 | ||
|
|
04f06bc91c | ||
|
|
0f2c248eee | ||
|
|
47ba0ed497 | ||
|
|
b7edb5bfa7 | ||
|
|
44e63d973f | ||
|
|
93bd259b8b | ||
|
|
f6fc418d32 | ||
|
|
31156722b3 | ||
|
|
c249597fa7 | ||
|
|
301fd74ecf | ||
|
|
e8e8fa1ed7 | ||
|
|
fcc5d4434a | ||
|
|
cf66732d19 | ||
|
|
84b9ec9733 | ||
|
|
0b1bf1f56b | ||
|
|
10a9579a63 | ||
|
|
4a0651146c | ||
|
|
d480ed4100 | ||
|
|
5e4b145370 | ||
|
|
14c9a9aec7 | ||
|
|
9e71c18092 | ||
|
|
4422220970 | ||
|
|
a64041bbee | ||
|
|
5da4feac0e | ||
|
|
3935c3ecd6 | ||
|
|
08b959a50b | ||
|
|
4249331805 | ||
|
|
f6d7cec859 | ||
|
|
ffc4a05bda | ||
|
|
bdfff63ae2 | ||
|
|
5951ef331a | ||
|
|
68f2de6d4a | ||
|
|
620efe9ce7 | ||
|
|
14ddc57fc3 | ||
|
|
3740ffa6e0 | ||
|
|
9c4bf5db4a | ||
|
|
2adafc1699 | ||
|
|
dc60e9156a | ||
|
|
44d1f953e0 | ||
|
|
0246f5078f | ||
|
|
7eb1c3ed92 | ||
|
|
e9815c4ea6 | ||
|
|
167ff7f677 | ||
|
|
bf9d3f1012 | ||
|
|
f934b7ec0c | ||
|
|
93127c20e8 | ||
|
|
e011f1770c | ||
|
|
45911e4588 | ||
|
|
a85552b73b | ||
|
|
4ca35186c4 | ||
|
|
ba925bddf1 | ||
|
|
a32ff29cd8 | ||
|
|
b68d755f77 | ||
|
|
bae6646b68 | ||
|
|
9352a2fdad | ||
|
|
061fa9c4c5 | ||
|
|
affecdc5fc | ||
|
|
550463b5e1 | ||
|
|
ed8c4d9961 | ||
|
|
b906150a32 | ||
|
|
ecf4eb2273 | ||
|
|
1ce760cb73 | ||
|
|
a240207505 | ||
|
|
6e410af1d6 | ||
|
|
87ec948433 | ||
|
|
cda354087f | ||
|
|
47d331d3bb | ||
|
|
01b1d604b6 | ||
|
|
f3fc238668 | ||
|
|
8c5bcdabab | ||
|
|
86fb36e2b0 | ||
|
|
3c2086efdd | ||
|
|
f6700b450e | ||
|
|
a77f5bf258 | ||
|
|
7a71d71a94 | ||
|
|
225ad19114 | ||
|
|
df6936c9e1 | ||
|
|
3776c4941a | ||
|
|
839e2e92e2 | ||
|
|
324e23b72d | ||
|
|
4bb7a2f523 | ||
|
|
08b481bbc5 | ||
|
|
bb875bb9e4 | ||
|
|
a0e00ccf3f | ||
|
|
91e9ae2629 | ||
|
|
df9c7546a2 | ||
|
|
74f36b9308 | ||
|
|
7d7d93ac6c | ||
|
|
3a2fb07349 | ||
|
|
18c8a64d3c | ||
|
|
9c520b114a | ||
|
|
8ed917d287 | ||
|
|
2380eaf981 | ||
|
|
8695f2cecb | ||
|
|
cfeb1d3442 | ||
|
|
e2313de3fd | ||
|
|
050f5d8955 | ||
|
|
fa69afe329 | ||
|
|
70d4d231fa | ||
|
|
747b3cfefa | ||
|
|
6b7d2770f7 | ||
|
|
a4a1cd76ba | ||
|
|
f88fd44680 | ||
|
|
f84d52765c | ||
|
|
38a8b563bf | ||
|
|
8df4c3748a | ||
|
|
a3925393ba | ||
|
|
47535347c0 | ||
|
|
74b91fad28 | ||
|
|
1e9b55801e | ||
|
|
1e35409b82 | ||
|
|
b145d876a4 | ||
|
|
d774b86ce2 | ||
|
|
3cbf52c97d | ||
|
|
e2151fb4af | ||
|
|
3b36a5f1c5 | ||
|
|
e2ebc2a08d | ||
|
|
b7961bdb2f | ||
|
|
56738d9383 | ||
|
|
bc9481770a | ||
|
|
9125b72b15 | ||
|
|
131bc6f091 | ||
|
|
021317a547 | ||
|
|
a6d9d66dcc | ||
|
|
32a478cb1f | ||
|
|
1b8b624661 | ||
|
|
29f7cbdabf | ||
|
|
6ce652e3ec | ||
|
|
73e08af01a | ||
|
|
65a431fe1f | ||
|
|
0e74f8fc65 | ||
|
|
3cf01067cf | ||
|
|
8bb4eab0d7 | ||
|
|
bc1024f8bc | ||
|
|
0ad6b7e212 | ||
|
|
1a02e2e43b | ||
|
|
495a551e06 | ||
|
|
ca822ab44e | ||
|
|
08c1745893 | ||
|
|
06e459df4b | ||
|
|
ea7cfb003f | ||
|
|
f2d0cc63fd | ||
|
|
61bc35aa12 | ||
|
|
7d400bc787 | ||
|
|
57376069bd | ||
|
|
3ea8df93b1 | ||
|
|
2b6589c0d7 | ||
|
|
fa53d359d5 | ||
|
|
4833ac3d3d | ||
|
|
d2edd6ac07 | ||
|
|
239c4fe6db | ||
|
|
82185ada82 | ||
|
|
0745f76ebe | ||
|
|
bc437feded | ||
|
|
367a0ac052 | ||
|
|
8153260792 | ||
|
|
2a9a80c9bb | ||
|
|
f4fa433eff | ||
|
|
20ee0a0609 | ||
|
|
1b52334772 | ||
|
|
5556819ac8 | ||
|
|
c454025a0f | ||
|
|
fddafd5125 | ||
|
|
59743245b4 | ||
|
|
6db4136358 | ||
|
|
1049bc2f9c | ||
|
|
b6943304c9 | ||
|
|
36081ccf2d | ||
|
|
937a25249f | ||
|
|
5bb4711b22 | ||
|
|
6e1898a5a2 | ||
|
|
9070816ebb | ||
|
|
aa882ea539 | ||
|
|
ca8d363d2c | ||
|
|
1f787aca28 | ||
|
|
30ef4c738a | ||
|
|
f1839ac87c | ||
|
|
15db00b53e | ||
|
|
274788b4a5 | ||
|
|
2d415cf9f8 | ||
|
|
626dd7a5fe | ||
|
|
65b19284b5 | ||
|
|
d179cc7a55 | ||
|
|
aa4d1e3106 | ||
|
|
2c189a57f4 | ||
|
|
f3c3494c86 | ||
|
|
7515a2cacc | ||
|
|
5f2c195933 | ||
|
|
dacf86a12d | ||
|
|
0187112396 | ||
|
|
d74e028d7c | ||
|
|
d0191583e8 | ||
|
|
ac27ef2593 | ||
|
|
b1f8aa24ca | ||
|
|
dc868e56c9 | ||
|
|
c8c24ccd23 | ||
|
|
e0a728aada | ||
|
|
a639a1f2b9 | ||
|
|
25a9fda4f6 | ||
|
|
d47bc3821c | ||
|
|
88f2c815e3 | ||
|
|
56637f2a85 | ||
|
|
3a30d1db20 | ||
|
|
a3678fa186 | ||
|
|
d9c8469363 | ||
|
|
afbf31eba9 | ||
|
|
80b7fe0e88 | ||
|
|
3a152aea38 | ||
|
|
fb7487a9aa | ||
|
|
bfadd2133e | ||
|
|
424dd43e6f | ||
|
|
034ceb60ab | ||
|
|
2bd5b63f4a | ||
|
|
8bea657cac | ||
|
|
aa76972385 | ||
|
|
ec40d92889 | ||
|
|
bccf22f6b4 | ||
|
|
9df5c6e987 | ||
|
|
0f4355d518 | ||
|
|
db6056516e | ||
|
|
697e3bb2df | ||
|
|
0b1a6c4b0f | ||
|
|
cbb0489782 | ||
|
|
167c1633f2 | ||
|
|
644d83fb04 | ||
|
|
179b9822b4 | ||
|
|
f0dfe9dcda | ||
|
|
d0de492ff3 | ||
|
|
57d0dc0db2 | ||
|
|
12ea7cb133 | ||
|
|
e350c2f648 | ||
|
|
bdf8c02f80 | ||
|
|
e4b34bfad0 | ||
|
|
4bfa132445 | ||
|
|
ad134662a2 | ||
|
|
dcd5353502 | ||
|
|
50fd61eb8d | ||
|
|
b2d6cb06c5 | ||
|
|
de24008109 | ||
|
|
0a5b690b70 | ||
|
|
bdce11cb30 | ||
|
|
b947f34393 | ||
|
|
ace5664e7d | ||
|
|
25fbec5be1 | ||
|
|
fc54be1062 | ||
|
|
3dfd8f12dc | ||
|
|
98fd1ce332 | ||
|
|
3d6af3e35e | ||
|
|
5e91e174d3 | ||
|
|
b1bf5f1738 | ||
|
|
1a20d53171 | ||
|
|
3835ad6b1c | ||
|
|
d9c0105fef | ||
|
|
d3ccaf8ae5 | ||
|
|
f7da1f8177 | ||
|
|
eddc0f3307 | ||
|
|
04ed52f6a0 | ||
|
|
9ad2ba2a1f | ||
|
|
d474909a58 | ||
|
|
746e7dc42e | ||
|
|
b5618c07d8 | ||
|
|
505e6bc117 | ||
|
|
8e8baf89c0 | ||
|
|
029d4de4be | ||
|
|
7eb03d6c5c | ||
|
|
9ba7d6d08b | ||
|
|
fd1b118942 | ||
|
|
a93ae114b8 | ||
|
|
14004cf20c | ||
|
|
82bacfc3b2 | ||
|
|
dd540781dc | ||
|
|
f419a87150 | ||
|
|
c791f186ce | ||
|
|
f44e3ff46a | ||
|
|
7e305eda2f | ||
|
|
f6a88f3236 | ||
|
|
082628eb2c | ||
|
|
a34eecedc2 | ||
|
|
581b17def2 | ||
|
|
adb578238d | ||
|
|
c4afaa05a4 | ||
|
|
8b1ae3c140 | ||
|
|
657d4df010 | ||
|
|
6920681cab | ||
|
|
c5421d1554 | ||
|
|
5ca6698f12 | ||
|
|
a6b0b935f6 | ||
|
|
f72dd2c732 | ||
|
|
3a370b7350 | ||
|
|
3af1fa76eb | ||
|
|
0b2a795ece | ||
|
|
55ea8590ae | ||
|
|
3cde54c50e | ||
|
|
9d527965a3 | ||
|
|
c21b4393ed | ||
|
|
3cffaedad0 | ||
|
|
2e050bfc36 | ||
|
|
985ca02b6a | ||
|
|
8965ff4bcf | ||
|
|
3998882f2f | ||
|
|
ec49b413c6 | ||
|
|
d37beb92db | ||
|
|
eec663aa3b | ||
|
|
f2696211dc | ||
|
|
5656911ae7 | ||
|
|
85f5392e52 | ||
|
|
eb273c7c65 | ||
|
|
178e1df257 | ||
|
|
f99a79b64a | ||
|
|
e80512dd52 | ||
|
|
9ac3596d63 | ||
|
|
54396b890d | ||
|
|
e8d3d71e23 | ||
|
|
6eb44b5091 | ||
|
|
ad607a23f1 | ||
|
|
d334793f2a | ||
|
|
8bf70e11ee | ||
|
|
5619c629f6 | ||
|
|
9da5d7ac02 | ||
|
|
d2901a62a4 | ||
|
|
ec074fcf64 | ||
|
|
906935e580 | ||
|
|
c6cb6ddfb2 | ||
|
|
ea0e92830a | ||
|
|
810e500118 | ||
|
|
bae74dff07 | ||
|
|
bf7dea978e | ||
|
|
cbfbc6766e | ||
|
|
e283bda91d | ||
|
|
d0bf2f3fa0 | ||
|
|
6e210a6c54 | ||
|
|
33842916b0 | ||
|
|
611c0689fc | ||
|
|
9332d2cb9d | ||
|
|
a16d7d46dd | ||
|
|
2aa5120e82 | ||
|
|
4f618eba00 | ||
|
|
8e32e58e00 | ||
|
|
052bbfba3a | ||
|
|
43aa463780 | ||
|
|
293db73c76 | ||
|
|
83465fde9b | ||
|
|
7750a1ade6 | ||
|
|
c206c19c19 | ||
|
|
8a4c2b13bd | ||
|
|
dff4e43269 | ||
|
|
ec977d4c4f | ||
|
|
7284f3f966 | ||
|
|
ed070f4105 | ||
|
|
ad8f37df1b | ||
|
|
dc2bdce11e | ||
|
|
94d271ff7b | ||
|
|
d4ce89d9da | ||
|
|
bcacf9d0e3 | ||
|
|
66db5dd894 | ||
|
|
7eda3692f6 | ||
|
|
3fa875dd79 | ||
|
|
da73d34264 | ||
|
|
a8bffd6c70 | ||
|
|
8f613692fd | ||
|
|
c383a8717b | ||
|
|
81625d8f65 | ||
|
|
60be88a0a6 | ||
|
|
4c0f4125ec | ||
|
|
39d3ec0b51 | ||
|
|
448ef456ff | ||
|
|
4349becadc | ||
|
|
a34a6a3f71 | ||
|
|
9790f608e9 | ||
|
|
b1ec1f87a4 | ||
|
|
bcc4a38c1a | ||
|
|
814d9d5bd0 | ||
|
|
bb097a97ea | ||
|
|
17dd04ca1f | ||
|
|
08152c90f2 | ||
|
|
57b2c9d339 | ||
|
|
f2f1da1831 | ||
|
|
12aa1a24e8 | ||
|
|
894c6af744 | ||
|
|
4e9083db10 | ||
|
|
16e2a5aa3b | ||
|
|
2871881859 | ||
|
|
67cdbd7e4d | ||
|
|
c51b9fff19 | ||
|
|
962b2a559d | ||
|
|
8abe9ec33d | ||
|
|
0dff5864a9 | ||
|
|
5dc6c0de80 | ||
|
|
eb63c265db | ||
|
|
3d13b4677d | ||
|
|
311961fdb8 | ||
|
|
ec2bd20886 | ||
|
|
d39a99b2da | ||
|
|
77ec1997b3 | ||
|
|
c1df0103c2 | ||
|
|
c1f2ce3938 | ||
|
|
1ce224d13f | ||
|
|
5a3f869f7e | ||
|
|
8a19ebf4fb | ||
|
|
ad1fc08312 | ||
|
|
51581d4dfb | ||
|
|
6903d5b2fe | ||
|
|
0293b5f110 | ||
|
|
0e0a6eb6cf | ||
|
|
7644c656d8 | ||
|
|
aced269ac3 | ||
|
|
9f2d46513c | ||
|
|
378bbe63f3 | ||
|
|
0c06de632a | ||
|
|
cea51b32fc | ||
|
|
bdb91441f2 | ||
|
|
3650e518e7 | ||
|
|
6860fecb81 | ||
|
|
db24ceca33 | ||
|
|
58a63ae973 | ||
|
|
5cf3c51857 | ||
|
|
f43c66368b | ||
|
|
5aed321d7b | ||
|
|
ed903fae04 | ||
|
|
70955d40a1 | ||
|
|
9e6c1edc88 | ||
|
|
79182305ef | ||
|
|
d865615e9a | ||
|
|
ba4d6ad8ea | ||
|
|
c394e2c5b6 | ||
|
|
17431cddac | ||
|
|
876003dc44 | ||
|
|
c014417c46 | ||
|
|
171b53fb25 | ||
|
|
e344497277 | ||
|
|
7d18ea22eb | ||
|
|
72baf0c345 | ||
|
|
fb3226a3ed | ||
|
|
6ab424acda | ||
|
|
5f3a3e312c | ||
|
|
f6dd48b08a | ||
|
|
a1ff319fda | ||
|
|
8868a4ffc2 | ||
|
|
d6d4661517 | ||
|
|
f9ddc76399 | ||
|
|
272465eab4 | ||
|
|
b8daca8570 | ||
|
|
3853d11fc8 | ||
|
|
746a2cdbaf | ||
|
|
6fcfb4048b | ||
|
|
dc5f6f1b4f | ||
|
|
f1bf446893 | ||
|
|
2b0968b795 | ||
|
|
c9ea4988df | ||
|
|
4d8033dc84 | ||
|
|
114557c04b | ||
|
|
06ea7eaa27 | ||
|
|
4a898ae95b | ||
|
|
a98a2d4a4e | ||
|
|
67961c7c10 | ||
|
|
0ed230fa43 | ||
|
|
7415ef77a1 | ||
|
|
51fa42daf5 | ||
|
|
1c1b068ff8 | ||
|
|
50c41b09cd | ||
|
|
a95892f77d | ||
|
|
48d9a74d16 | ||
|
|
8a77dd46ca | ||
|
|
76690e3aea | ||
|
|
ba0c495db7 | ||
|
|
b9c69aa63a | ||
|
|
67eae34e4a | ||
|
|
1620864c35 | ||
|
|
2b3dda7f72 | ||
|
|
31e9db2690 | ||
|
|
ac089d9015 | ||
|
|
a69ab65278 | ||
|
|
72199adfc3 | ||
|
|
e8a4c1701a | ||
|
|
d7b5bfc293 | ||
|
|
f29e7ac504 | ||
|
|
1995c9ffb5 | ||
|
|
dd007cfdd5 | ||
|
|
fc795d8701 | ||
|
|
bafa2f39cf | ||
|
|
4a41a93a7a | ||
|
|
3a2234162d | ||
|
|
ce9636b26f | ||
|
|
482904cf86 | ||
|
|
5e856ed1b9 | ||
|
|
b680c5c677 | ||
|
|
9b6135dca4 | ||
|
|
de4ddace2e | ||
|
|
3410687443 | ||
|
|
8611f8851e | ||
|
|
a8524c3942 | ||
|
|
9a22e746b5 | ||
|
|
0ba25de173 | ||
|
|
fec8f8382a | ||
|
|
8a0a9a93d9 | ||
|
|
ec0b80be6b | ||
|
|
3303289137 | ||
|
|
f2aae88a7c | ||
|
|
0b7d16bc09 | ||
|
|
fd0af4bd29 | ||
|
|
15d2547427 | ||
|
|
1d4e9f245b | ||
|
|
e81af2f3fe | ||
|
|
2d1eead2e8 | ||
|
|
69506f1dc4 | ||
|
|
ca592a2745 | ||
|
|
52b8440916 | ||
|
|
cd1a7e80c0 | ||
|
|
940d710ece | ||
|
|
3da4613d7b | ||
|
|
94e33a6ca3 | ||
|
|
cd1525ac51 | ||
|
|
3e50ea9eef | ||
|
|
a68d8ec833 | ||
|
|
b6f4f0c748 | ||
|
|
57d921e953 | ||
|
|
37034fb826 | ||
|
|
c6f8ef3814 | ||
|
|
fed2f391ff | ||
|
|
e5f7352bef | ||
|
|
223c62e7b7 | ||
|
|
96b250d625 | ||
|
|
204a12e594 | ||
|
|
9a17ce30a0 | ||
|
|
a6b22cf317 | ||
|
|
6dd60469ba | ||
|
|
6c3dc20388 | ||
|
|
46355000d1 | ||
|
|
df322f0ba1 | ||
|
|
14772580cd | ||
|
|
b4068515e8 | ||
|
|
19c865437a | ||
|
|
00a7c302ea | ||
|
|
40ec927b3f | ||
|
|
180b4569e2 | ||
|
|
1f2ed21dde | ||
|
|
fd4ff5d201 | ||
|
|
2b0249ec42 | ||
|
|
b7940c98c1 | ||
|
|
612548c04d | ||
|
|
d38bf3616c | ||
|
|
9c1dbeb3f1 | ||
|
|
8b98c12815 | ||
|
|
e1d586d70e | ||
|
|
47c06763b7 | ||
|
|
951e1064c9 | ||
|
|
0f8387c2d6 | ||
|
|
0283c439ec | ||
|
|
1b8de4cb25 | ||
|
|
70d9f98ed3 | ||
|
|
9ea1d647af | ||
|
|
8fd14f09e2 | ||
|
|
6aca8e9297 | ||
|
|
5ca98cc229 | ||
|
|
6c1d30b737 | ||
|
|
06b8fee542 | ||
|
|
4df0c15074 | ||
|
|
d634df5764 | ||
|
|
06f595c3c3 | ||
|
|
4ab5b20654 | ||
|
|
0fc5422941 | ||
|
|
216283b651 | ||
|
|
da08e40f8f | ||
|
|
cd3ae9bc99 | ||
|
|
61b54e9509 | ||
|
|
bf4f5b21a4 | ||
|
|
0b0c2117af | ||
|
|
f18ef24471 | ||
|
|
479921f1ef | ||
|
|
37ffe07697 | ||
|
|
f955ed718f | ||
|
|
01c2ec4be5 | ||
|
|
60c453a2e2 | ||
|
|
6dc5dab07b | ||
|
|
7f8f8bfa09 | ||
|
|
dfef7f6942 | ||
|
|
d6e11b43fd | ||
|
|
d3a356b455 | ||
|
|
33dc8c4e56 | ||
|
|
8bcd888dbc | ||
|
|
53a2f094fb | ||
|
|
9dba0bab82 | ||
|
|
09339e2b53 | ||
|
|
f0f8fbc623 | ||
|
|
78ecdf8d65 | ||
|
|
d5f554ab4f | ||
|
|
13aba0817b | ||
|
|
533a024a35 | ||
|
|
9eea0107ba | ||
|
|
7d6a7e7d3b | ||
|
|
66e941e83f | ||
|
|
3851b7a364 | ||
|
|
a0fe21ccb6 | ||
|
|
45ea446910 | ||
|
|
b45b846449 | ||
|
|
1102c4ee95 | ||
|
|
406a97546a | ||
|
|
e38a476e72 | ||
|
|
c6ea067fed | ||
|
|
4463d20448 | ||
|
|
2b849ab4d1 | ||
|
|
98e542d718 | ||
|
|
a2cb3d17a7 | ||
|
|
f603fe64bd | ||
|
|
e4e02000ba | ||
|
|
230948b96a | ||
|
|
d2fb8b66d7 | ||
|
|
5982271096 | ||
|
|
e935d21752 | ||
|
|
f608f30407 | ||
|
|
88fc506bf0 | ||
|
|
3b3948f1d2 | ||
|
|
ea041b12f1 | ||
|
|
21bc366486 | ||
|
|
d65b20980b | ||
|
|
91953ca3aa | ||
|
|
edb3374d32 | ||
|
|
1f84815c12 | ||
|
|
16669b5aa0 | ||
|
|
6d7a6c4cf4 | ||
|
|
3d33abbb8c | ||
|
|
9cab88c59f | ||
|
|
147d5faccf | ||
|
|
be6845999b | ||
|
|
724ce8347b | ||
|
|
cc78b9800d | ||
|
|
9eb05d9761 | ||
|
|
f8a9724fdb | ||
|
|
be313b1300 | ||
|
|
7a197a6220 | ||
|
|
b5cef7be3c | ||
|
|
62af220c9e | ||
|
|
64119287c3 | ||
|
|
a6d4f21cdb | ||
|
|
6a6342f775 | ||
|
|
be51e010b4 | ||
|
|
2835f025b6 | ||
|
|
4f4d5fdc67 | ||
|
|
08c9ff434b | ||
|
|
41a94b5400 | ||
|
|
48bb503f12 | ||
|
|
f58224119c | ||
|
|
e5e120a502 | ||
|
|
ee80c0f0e3 | ||
|
|
b7449ebc37 | ||
|
|
27c7135097 | ||
|
|
b7cd307f9b | ||
|
|
674cfe8071 | ||
|
|
19583d115c | ||
|
|
579d086d7a | ||
|
|
5efd97f108 | ||
|
|
b58a94fed4 | ||
|
|
941e4f5567 | ||
|
|
3f311f1daa | ||
|
|
1c200869d9 | ||
|
|
87518d850b | ||
|
|
3579b652e7 | ||
|
|
1a5d6bd23d | ||
|
|
3c11686036 | ||
|
|
f28fd56f76 | ||
|
|
0c3cd7e292 | ||
|
|
b07dabbe80 | ||
|
|
7a22df7be3 | ||
|
|
0c8b215a60 | ||
|
|
d2f218cc46 | ||
|
|
4f629c3bba | ||
|
|
891c3d298b | ||
|
|
8a0de6c333 | ||
|
|
622703467c | ||
|
|
6c35e3c84c | ||
|
|
bbcd24607c | ||
|
|
e732de541e | ||
|
|
c93e6b5f79 | ||
|
|
57015b12e2 | ||
|
|
35b13fdb5e | ||
|
|
03eee0e2ed | ||
|
|
f5840016f3 | ||
|
|
6fb02eb2d9 | ||
|
|
5b7d162947 | ||
|
|
d1158c75e8 | ||
|
|
a7ed0103ef | ||
|
|
10fb6b1b93 | ||
|
|
33e5601937 | ||
|
|
0c795e2e18 | ||
|
|
30303765a3 | ||
|
|
c254039677 | ||
|
|
b3ae66ae58 | ||
|
|
3c21da1797 | ||
|
|
eac952f3fe | ||
|
|
19fa139341 | ||
|
|
fb697f281b | ||
|
|
d27e123310 | ||
|
|
68c87619bd | ||
|
|
fba549f8c2 | ||
|
|
ea8a12dbc1 | ||
|
|
32998a5e4f | ||
|
|
13835b5f6c | ||
|
|
b9567c9561 | ||
|
|
e7ddf4168d | ||
|
|
ba117ad80e | ||
|
|
933b1e9b8f | ||
|
|
8e2f036193 | ||
|
|
ef4ed892da | ||
|
|
64f0efd33f | ||
|
|
86df68f370 | ||
|
|
d6b1de30fe | ||
|
|
69483a8aaf | ||
|
|
1f54709ee6 | ||
|
|
53c774b948 | ||
|
|
ff77bb1ab6 | ||
|
|
6dee7d312a | ||
|
|
817afaad5e | ||
|
|
8f1fb4ada0 | ||
|
|
117d85978a | ||
|
|
1471bc871b | ||
|
|
7379c67839 | ||
|
|
fcd444b4e1 | ||
|
|
3df2c388b1 | ||
|
|
b5c344937b | ||
|
|
f3864a94d2 | ||
|
|
8ef3cec1f8 | ||
|
|
7a6571fe05 | ||
|
|
7f5f9b02e2 | ||
|
|
c29f3efd43 | ||
|
|
b7dd5ac374 | ||
|
|
9dcbe73897 | ||
|
|
becc177dac | ||
|
|
70121705ba | ||
|
|
1f72bbcaa7 | ||
|
|
ec26c285c2 | ||
|
|
aeea47205b | ||
|
|
fb6ca78e05 | ||
|
|
dd04871295 | ||
|
|
f1f4c1ea50 | ||
|
|
7da624db7b | ||
|
|
b496210d9a | ||
|
|
fc2063b660 | ||
|
|
0e2f6120ee | ||
|
|
4e5f3e7331 | ||
|
|
41d8dcd802 | ||
|
|
944cac939c | ||
|
|
c221b0bc21 | ||
|
|
7da954d191 | ||
|
|
13209bad59 | ||
|
|
3008bc4432 | ||
|
|
dda1e6c983 | ||
|
|
5a4ba89aad | ||
|
|
4baa42be1c | ||
|
|
f224389af3 | ||
|
|
e6775a4c88 | ||
|
|
59231b568a | ||
|
|
5efa3f1edf | ||
|
|
b3b0f199ae | ||
|
|
76b74ab11f | ||
|
|
e1cd6dbc07 | ||
|
|
f46af53ea3 | ||
|
|
ffd5c5c86c | ||
|
|
e3a12d14e6 | ||
|
|
19eb95f72f | ||
|
|
7c03887b7a | ||
|
|
42c798229f | ||
|
|
e6edd1d7af | ||
|
|
38862fcd3f | ||
|
|
44566dd46d | ||
|
|
1bf5aae913 | ||
|
|
af998ff6c2 | ||
|
|
d59b2474e1 | ||
|
|
8d2b0f24d3 | ||
|
|
30b95041de | ||
|
|
4f2f566b06 | ||
|
|
867c3249cb | ||
|
|
28d1c4d7e2 | ||
|
|
084a8bdcbc | ||
|
|
d915579c6b | ||
|
|
15309c57bd | ||
|
|
69e0f4039f | ||
|
|
05aa860fd7 | ||
|
|
6e23a8aa20 | ||
|
|
17a6fc0b45 | ||
|
|
727f266227 | ||
|
|
0b65565e6b | ||
|
|
89f2bf252e | ||
|
|
864c77a0a7 | ||
|
|
7b74504f40 | ||
|
|
0329281b49 | ||
|
|
662e0238f0 | ||
|
|
cc5a4e1d38 | ||
|
|
02c83d6edf | ||
|
|
b4fb5226c0 | ||
|
|
5d06515c0b | ||
|
|
851002b87d | ||
|
|
a8f51fa2ae | ||
|
|
91dc07af67 | ||
|
|
eca7ef180c | ||
|
|
c2784df48f | ||
|
|
d330e660ee | ||
|
|
74e2acb680 | ||
|
|
5d47ed1161 | ||
|
|
b9b260119f | ||
|
|
9397354a33 | ||
|
|
13e5d2420d | ||
|
|
22826bdac6 | ||
|
|
b45c9f49d0 | ||
|
|
8fe54fddba | ||
|
|
af91456949 | ||
|
|
87cec8eb5e | ||
|
|
f359c9b80f | ||
|
|
0558b9284e | ||
|
|
012869d6d2 | ||
|
|
2f2c993235 | ||
|
|
187c689f1c | ||
|
|
d8ff86fd09 | ||
|
|
e09dfed899 | ||
|
|
37fb985a82 | ||
|
|
112d09deb1 | ||
|
|
aa350ef426 | ||
|
|
612209c8d9 | ||
|
|
f21f60d5ff | ||
|
|
319e74e2da | ||
|
|
ce4c33102f | ||
|
|
3a7ec38f5a | ||
|
|
096470d41a | ||
|
|
34c710712d | ||
|
|
85a0cecf68 | ||
|
|
b6ebe41ace | ||
|
|
64d7041264 | ||
|
|
e3f6460b0d | ||
|
|
95b424702a | ||
|
|
9f069f7bef | ||
|
|
4bbfe1cf5b | ||
|
|
898b3d4d78 | ||
|
|
fce67134f3 | ||
|
|
67fa4fd49e | ||
|
|
667eb7758d | ||
|
|
aca043364e | ||
|
|
41aec14ed5 | ||
|
|
f247a4e76f | ||
|
|
820810da65 | ||
|
|
2e1b92e3ea | ||
|
|
232da7ecc7 | ||
|
|
00fc37f183 | ||
|
|
20db8ffcae | ||
|
|
24f4552bbe | ||
|
|
d336842067 | ||
|
|
57fc4cc0b6 | ||
|
|
5c46d66871 | ||
|
|
66ed1bc5e1 | ||
|
|
85feafd996 | ||
|
|
3329c69865 | ||
|
|
d28dfb5720 | ||
|
|
dd9927bcde | ||
|
|
f72de1dc1c | ||
|
|
147b7d5eac | ||
|
|
7fee061a6d | ||
|
|
4dcaa2300c | ||
|
|
8a37910d51 | ||
|
|
8bbec04d5b | ||
|
|
919ab64fdb | ||
|
|
fcdf2e09a2 | ||
|
|
866a1a0836 | ||
|
|
10232bd991 | ||
|
|
09e206d393 | ||
|
|
122337ba0d | ||
|
|
594a27942b | ||
|
|
03c6979264 | ||
|
|
07473c2be3 | ||
|
|
c3afa8dff4 | ||
|
|
6a91a99b1b | ||
|
|
0e2084da9c | ||
|
|
c63c19a73e | ||
|
|
e430b424df | ||
|
|
5611829c89 | ||
|
|
f6af1a67b5 | ||
|
|
74885e2203 | ||
|
|
e125e1547f | ||
|
|
d838a1e314 | ||
|
|
61997bb9bb | ||
|
|
d5ec3c8889 | ||
|
|
528329f199 | ||
|
|
b1ab8b00b8 | ||
|
|
6ae178f91c | ||
|
|
25f063d8b7 | ||
|
|
b2486b3d7d | ||
|
|
c7a5306039 | ||
|
|
02059c81e7 | ||
|
|
931d24a4b1 | ||
|
|
080f3fa1e0 | ||
|
|
8ef6eb30d9 | ||
|
|
c8ee38201d | ||
|
|
99a4014f06 | ||
|
|
96710ad8dd | ||
|
|
6b36e863cb | ||
|
|
3165248642 | ||
|
|
7cc6c5d79a | ||
|
|
65e635b685 | ||
|
|
3b007b270d | ||
|
|
4594807a24 | ||
|
|
fb12fd445a | ||
|
|
e0096cabef | ||
|
|
2eeb2a1f54 | ||
|
|
7c0cd2730c | ||
|
|
7cb5941799 | ||
|
|
e62436fc70 | ||
|
|
33f732c5e9 | ||
|
|
b9ffd32cd3 | ||
|
|
616c3eccfd | ||
|
|
5b95f17814 | ||
|
|
6032a223f4 | ||
|
|
aa8a4d96bd | ||
|
|
0ce83a83f0 | ||
|
|
0c8569edea | ||
|
|
1a42d65aa7 | ||
|
|
dced155411 | ||
|
|
67e6c7e73d | ||
|
|
5b61ca7281 | ||
|
|
948ee3e396 | ||
|
|
699b275aea | ||
|
|
e3e6eba1aa | ||
|
|
47436a42df | ||
|
|
193992de35 | ||
|
|
b3bafefd83 | ||
|
|
a951e97ae9 | ||
|
|
0357f18ef0 | ||
|
|
4dc0ec2253 | ||
|
|
6c48fe7433 | ||
|
|
a16f48e31a | ||
|
|
736751930f | ||
|
|
bd8be78c09 | ||
|
|
9a81f9fe3f | ||
|
|
794aa5063c | ||
|
|
3488c9b338 | ||
|
|
2b183d7261 | ||
|
|
d9cc917396 | ||
|
|
066ac2ef50 | ||
|
|
1bee228cd1 | ||
|
|
efecd5c15b | ||
|
|
9ce2c9bfc1 | ||
|
|
55b5ce8710 | ||
|
|
4eee576490 | ||
|
|
86eeeb5f3f | ||
|
|
253751656b | ||
|
|
ba4f5d8080 | ||
|
|
9f7e77099b | ||
|
|
15545b91dc | ||
|
|
b65e33f442 | ||
|
|
deb202bd42 | ||
|
|
3b2765395d | ||
|
|
9f74b2fc3c | ||
|
|
be0e37715e | ||
|
|
f96cde8cbd | ||
|
|
a89d601463 | ||
|
|
581e811187 | ||
|
|
c1c16a8f01 | ||
|
|
66b511a6de | ||
|
|
4d2a8d8231 | ||
|
|
1c3c2df9e9 | ||
|
|
df52a8b52a | ||
|
|
c89024511b | ||
|
|
7d1c3fcd12 | ||
|
|
ffe524cc30 | ||
|
|
7f31917dc3 | ||
|
|
013577fb6a | ||
|
|
99d00efa02 | ||
|
|
56b7f2686e | ||
|
|
4098f6282c | ||
|
|
99f247f887 | ||
|
|
e51d50a11e | ||
|
|
b23f88bff8 | ||
|
|
7dd05dd468 | ||
|
|
04e023be19 | ||
|
|
2bdc8e1252 | ||
|
|
77fcc2076a | ||
|
|
9766c3c960 | ||
|
|
981bf64fda | ||
|
|
475be6ab45 | ||
|
|
b16b9c2bf1 | ||
|
|
7c5ec12630 | ||
|
|
38a5f0b6e8 | ||
|
|
266f30e5e1 | ||
|
|
0b0fd3306d | ||
|
|
e663b4e856 | ||
|
|
04dabc1562 | ||
|
|
a590f3b6a3 | ||
|
|
a8e13f0505 | ||
|
|
905bdb2455 | ||
|
|
b700541f3b | ||
|
|
805dad5940 | ||
|
|
89a4e806e9 | ||
|
|
3d978351b3 | ||
|
|
181b5f0011 | ||
|
|
4c69dc9551 | ||
|
|
b504894ad4 | ||
|
|
988651541d | ||
|
|
9dd3071462 | ||
|
|
1e2f720a76 | ||
|
|
eb1cf4ae7e | ||
|
|
f916f0a7b7 | ||
|
|
78ee671f9b | ||
|
|
efa483c599 | ||
|
|
de5c82a0d9 | ||
|
|
4a2ca1b998 | ||
|
|
b4e2a0e179 | ||
|
|
ab507e894c | ||
|
|
5faf02761f | ||
|
|
b42eb4c376 | ||
|
|
80592d845d | ||
|
|
b6f8552074 | ||
|
|
7dce16f234 | ||
|
|
b4ccb00b36 | ||
|
|
68d7c0e601 | ||
|
|
705eabf721 | ||
|
|
bb15688511 | ||
|
|
d547cbb00d | ||
|
|
44e0456766 | ||
|
|
e37a241536 | ||
|
|
209f03f2b6 | ||
|
|
8d18637eca | ||
|
|
929210542f | ||
|
|
2a7f7fc1c9 | ||
|
|
7089e02ce1 | ||
|
|
dc9dcb3d35 | ||
|
|
6ad43b9bd9 | ||
|
|
13583874fc | ||
|
|
d57e608ac4 | ||
|
|
cf824a692d | ||
|
|
6c81ed26f0 | ||
|
|
1baed0e1ae | ||
|
|
f67c0fd5f7 | ||
|
|
8b1a3214b5 | ||
|
|
34fadac485 | ||
|
|
5095de5177 | ||
|
|
e0a266927d | ||
|
|
d1a1e1a319 | ||
|
|
71fc020669 | ||
|
|
19513ad89e | ||
|
|
13ba0f9492 | ||
|
|
3ccf241d54 | ||
|
|
c27dca1a1b | ||
|
|
6fb265fa3b | ||
|
|
bbb068562e | ||
|
|
d9c6bbab80 | ||
|
|
fe748f0092 | ||
|
|
dc4d7417f7 | ||
|
|
a45da5f676 | ||
|
|
1c792fad4f | ||
|
|
08c060cf38 | ||
|
|
b499b916ca | ||
|
|
09a929fc92 | ||
|
|
8810d0811a | ||
|
|
0550c1b618 | ||
|
|
9e063b223e | ||
|
|
7d7736b7b4 | ||
|
|
4af059bd85 | ||
|
|
9380176b04 | ||
|
|
48432c882e | ||
|
|
d6a93541b6 | ||
|
|
d68336a52f | ||
|
|
6711231a13 | ||
|
|
ade81b8aed | ||
|
|
10eb720306 | ||
|
|
086b63ca05 | ||
|
|
94d501edd9 | ||
|
|
b5d761e1d2 | ||
|
|
ee37789be0 | ||
|
|
916490f8bf | ||
|
|
e95d828454 | ||
|
|
64c8457976 | ||
|
|
a9a6934bf9 | ||
|
|
89529aa077 | ||
|
|
61160049ea | ||
|
|
d2aef510a4 | ||
|
|
8df67fbf36 | ||
|
|
438abca889 | ||
|
|
433b160fad | ||
|
|
9cd3426d3a | ||
|
|
e3ad1d19d5 | ||
|
|
8b0d546f4c | ||
|
|
b813f533f8 | ||
|
|
7a21367d97 | ||
|
|
cecdabd9c4 | ||
|
|
443a8f76c6 | ||
|
|
fe686a5180 | ||
|
|
874255ff5f | ||
|
|
bd72209b93 | ||
|
|
332a8007be | ||
|
|
813f844bdc | ||
|
|
f2f8855b76 | ||
|
|
1f84f09381 | ||
|
|
0b431b8a17 | ||
|
|
e67ed94b3e | ||
|
|
f1dc5cc99b | ||
|
|
43137a6b7f | ||
|
|
1d1cbf65eb | ||
|
|
1ea19b10bd | ||
|
|
ad65c5f135 | ||
|
|
def6f767c3 | ||
|
|
4bfab20a41 | ||
|
|
2415c1ef87 | ||
|
|
284a2c910f | ||
|
|
fa76197d4c | ||
|
|
acc6edf0ab | ||
|
|
8bdecd551b | ||
|
|
8228b50882 | ||
|
|
9f100d6028 | ||
|
|
4cd33f98a4 | ||
|
|
a5005145da | ||
|
|
5f5bcb3fa8 | ||
|
|
4aae724656 | ||
|
|
83de5aa60e | ||
|
|
aba30ebcdb | ||
|
|
f7dd14588f | ||
|
|
2293567c8c | ||
|
|
311d6d811b | ||
|
|
20b4c02b89 | ||
|
|
366a68282f | ||
|
|
476d09d072 | ||
|
|
8c4e429574 | ||
|
|
324d0b9742 | ||
|
|
396cbbdea1 | ||
|
|
3e3d5d8593 | ||
|
|
6560de21e2 | ||
|
|
2bfdaded01 | ||
|
|
d9ac88a501 | ||
|
|
de82843391 | ||
|
|
49fba23c81 | ||
|
|
aeb2c277a8 | ||
|
|
9723090c92 | ||
|
|
2a99b5b816 | ||
|
|
526a3c2186 | ||
|
|
532dae4854 | ||
|
|
9e39d1db58 | ||
|
|
f17f6814c9 | ||
|
|
5c9d70c955 | ||
|
|
898e6f8e41 | ||
|
|
a54b98e5ef | ||
|
|
f6e0780246 | ||
|
|
6657d5b66b | ||
|
|
4b52511f50 | ||
|
|
2c7fbadeef | ||
|
|
eba586f053 | ||
|
|
7dc850db3e | ||
|
|
72b2cb613a | ||
|
|
b810c54700 | ||
|
|
98513c2729 | ||
|
|
12de747d3a | ||
|
|
8b4273d298 | ||
|
|
5c24f56b46 | ||
|
|
2f1489a673 | ||
|
|
089ae9a58e | ||
|
|
dfb5da937e | ||
|
|
e24e713001 | ||
|
|
81b4308bde | ||
|
|
12ccdb25e4 | ||
|
|
6aa17fe8d2 | ||
|
|
26b2524996 | ||
|
|
16959f2f01 | ||
|
|
e9fb04c750 | ||
|
|
05ffaffe0c | ||
|
|
c1d0a12121 | ||
|
|
c05fbac29a | ||
|
|
9e8a7c7dab | ||
|
|
13eadfc95a | ||
|
|
b4cbeca164 | ||
|
|
126a5696f2 | ||
|
|
a0e9de70a7 | ||
|
|
06541daa12 | ||
|
|
a669fcc59b | ||
|
|
0c8ff3ad63 | ||
|
|
8a2fc58645 | ||
|
|
d81e3d0bad | ||
|
|
3ab3766f62 | ||
|
|
7fae84d715 | ||
|
|
dbd3026f8a | ||
|
|
f855ac3807 | ||
|
|
2ab16287e6 | ||
|
|
a5fe5a7cdd | ||
|
|
e8db70239e | ||
|
|
5dbc1f263a | ||
|
|
f084e627cc | ||
|
|
f9c232c2ee | ||
|
|
cced28dac3 | ||
|
|
a14aa9d8c3 | ||
|
|
ace652e673 | ||
|
|
d79e9d0d61 | ||
|
|
76f97cd75d | ||
|
|
823a36448f | ||
|
|
472ac5bdd5 | ||
|
|
2cd0aa727a | ||
|
|
7810d55dfc | ||
|
|
1c8b86c7d5 | ||
|
|
1a01b0c103 | ||
|
|
99048d18b9 | ||
|
|
73f378f226 | ||
|
|
a31676722b | ||
|
|
70ca1c94f1 | ||
|
|
e7f55bb4c0 | ||
|
|
5fe8ef27da | ||
|
|
9f5d8283a9 | ||
|
|
9ab7701215 | ||
|
|
d6207798e6 | ||
|
|
f4db3724f9 | ||
|
|
6ef080af04 | ||
|
|
435c852fb8 | ||
|
|
ed2b1bc5eb | ||
|
|
2d2b610fb9 | ||
|
|
b5f9086099 | ||
|
|
67b25ed49f | ||
|
|
7ffe8aab61 | ||
|
|
90a34450e5 | ||
|
|
768255c061 | ||
|
|
a0d0eda9b3 | ||
|
|
d8f0eeb039 | ||
|
|
4206c3db2e | ||
|
|
e408d62eaf | ||
|
|
93dc5190bc | ||
|
|
b5d8ff1014 | ||
|
|
f0c9fe0105 | ||
|
|
c1c065a3a5 | ||
|
|
044810c229 | ||
|
|
e4c11ad108 | ||
|
|
5e3bd86778 | ||
|
|
c55b141005 | ||
|
|
db204c51a6 | ||
|
|
1ff0ef6945 | ||
|
|
6463fa2993 | ||
|
|
fc2b1f2ce9 | ||
|
|
f0b4c52d4a | ||
|
|
17840c21c3 | ||
|
|
7000cdb5ea | ||
|
|
3bee15b0fb | ||
|
|
cb49c5a03f | ||
|
|
8b888354c8 | ||
|
|
1b6e5052c9 | ||
|
|
132a76156e | ||
|
|
54d9d3cf3c | ||
|
|
ed09d7e394 | ||
|
|
c507b684ce | ||
|
|
fe94f9f170 | ||
|
|
b6b0c621f6 | ||
|
|
079ac15ece | ||
|
|
e7ab6006c5 | ||
|
|
1c9b9a5ecf | ||
|
|
7a3fb6b20a | ||
|
|
bfe2b5480e | ||
|
|
c9dcba6b16 | ||
|
|
2e6d308465 | ||
|
|
fd4808fe8c | ||
|
|
3fc3e48c44 | ||
|
|
74892f5c3d | ||
|
|
7f0ada9b09 | ||
|
|
ce7ed2c0a9 | ||
|
|
bbf83db14a | ||
|
|
cad9fac9c6 | ||
|
|
b541308454 | ||
|
|
dbcb64b80f | ||
|
|
e66f1197d6 | ||
|
|
e412000122 | ||
|
|
e64934773b | ||
|
|
3c588200fe | ||
|
|
16da207de2 | ||
|
|
15d91f5a68 | ||
|
|
06f62ad1e4 | ||
|
|
c6b966c8ee | ||
|
|
bbdff85a9c | ||
|
|
105c631eab | ||
|
|
dd3ec4e87a | ||
|
|
774ed5fc39 | ||
|
|
842392c23c | ||
|
|
e2619d9ec1 | ||
|
|
7424de5b77 | ||
|
|
c27920b1ca | ||
|
|
e3195fecf1 | ||
|
|
c0a33e10ae | ||
|
|
2fb492f665 | ||
|
|
c00f802202 | ||
|
|
ebf78e7d19 | ||
|
|
cbe19a568c | ||
|
|
20e5495ebd | ||
|
|
ef8bc786a7 | ||
|
|
f3ce273f23 | ||
|
|
349216a6b5 | ||
|
|
56c282920c | ||
|
|
b9641812a5 | ||
|
|
7707ea90f4 | ||
|
|
ec289b64b9 | ||
|
|
87f98002b5 | ||
|
|
749caf947d | ||
|
|
0636699cf9 | ||
|
|
5dd9b4656f | ||
|
|
bf9c60feb5 | ||
|
|
91a7cf559d | ||
|
|
0c32d9dbef | ||
|
|
da5edd8ebe | ||
|
|
e422819389 | ||
|
|
b79c897ea1 | ||
|
|
47b59176e0 | ||
|
|
e6a6954ef1 | ||
|
|
e178963c0b | ||
|
|
abbca21248 | ||
|
|
24b026e333 | ||
|
|
908db0785f | ||
|
|
b4f1578fc2 | ||
|
|
ad6b0ebb73 | ||
|
|
e88f56d9da | ||
|
|
436d36943d | ||
|
|
c650c19805 | ||
|
|
5f4b2acfe5 | ||
|
|
165e4a112b | ||
|
|
2b367220f3 | ||
|
|
7a5933259f | ||
|
|
c5735ce162 | ||
|
|
faf07d358f | ||
|
|
57a1aa48d6 | ||
|
|
3bf5f6f575 | ||
|
|
fea5c22b7c | ||
|
|
1817dbaf60 | ||
|
|
a78c760922 | ||
|
|
d31718600b | ||
|
|
e6c20c6100 | ||
|
|
5727a8fa85 | ||
|
|
5f5355cbf5 | ||
|
|
b7c18fecfd | ||
|
|
22c0314758 | ||
|
|
7a419a5d48 | ||
|
|
872dea0401 | ||
|
|
268e8dd406 | ||
|
|
1a44c009b0 | ||
|
|
633f889c34 | ||
|
|
19f792df43 | ||
|
|
697e09df50 | ||
|
|
9e356e11e0 | ||
|
|
f9a8e6ee3b | ||
|
|
d5aeb4bc34 | ||
|
|
2b69db1f25 | ||
|
|
878467cd7c | ||
|
|
76c8ddc094 | ||
|
|
b427ecee79 | ||
|
|
690a5da2e7 | ||
|
|
db208f51fd | ||
|
|
352a99b95a | ||
|
|
57d5318d32 | ||
|
|
3aeb569036 | ||
|
|
ffbfce30b5 | ||
|
|
78aa12e1dc | ||
|
|
31b5c6e65c | ||
|
|
9011aed958 | ||
|
|
bc70fb17c0 | ||
|
|
3618f6eba7 | ||
|
|
03b49fe193 | ||
|
|
a6d97ede7b | ||
|
|
0c5a80f6f0 | ||
|
|
06820362bd | ||
|
|
a38bf76bab | ||
|
|
9fdc84c328 | ||
|
|
3e8c6b731a | ||
|
|
619449b4ca | ||
|
|
d0d5ddda3b | ||
|
|
3e8479bdf6 | ||
|
|
ffc88f2eeb | ||
|
|
f894b4b1b7 | ||
|
|
a653923fe7 | ||
|
|
191abde97e | ||
|
|
2262b32057 | ||
|
|
a3f6b2ce79 | ||
|
|
58d83f1a94 | ||
|
|
9aa2fec047 | ||
|
|
3d0480ed27 | ||
|
|
72a444276f | ||
|
|
9b02bdbce0 | ||
|
|
9c9e30cd6d | ||
|
|
0858a99287 | ||
|
|
07c5c47875 | ||
|
|
2b96712ab7 | ||
|
|
b277f1e95d | ||
|
|
d7c1c43d44 | ||
|
|
88d2bdc668 | ||
|
|
540b379902 | ||
|
|
4afac84c54 | ||
|
|
59a2bf62f0 | ||
|
|
d54d93ab2e | ||
|
|
4e16b1e7ad | ||
|
|
68366c99b2 | ||
|
|
72a16423d2 | ||
|
|
7c2ef08367 | ||
|
|
dbb43034e6 | ||
|
|
40ec1e8a36 | ||
|
|
ae9c3f1664 | ||
|
|
b496a6b227 | ||
|
|
69cfb9203b | ||
|
|
721b61a43f | ||
|
|
b2cba8eda6 | ||
|
|
fd0eec20b7 | ||
|
|
fe6c78629d | ||
|
|
3d38769798 | ||
|
|
2d9e596fe6 | ||
|
|
4c60a35226 | ||
|
|
0fb173aa3a | ||
|
|
07d318310b | ||
|
|
fb9d44daf1 | ||
|
|
bfd31e94d5 | ||
|
|
197632009b | ||
|
|
0c09c9d943 | ||
|
|
4bf57acec8 | ||
|
|
4bb7474e8a | ||
|
|
e817a0b35c | ||
|
|
0b63cc1ea0 | ||
|
|
398c74b263 | ||
|
|
3bb7a8c89d | ||
|
|
a3e9d7199b | ||
|
|
190f6945ee | ||
|
|
7b68df96dc | ||
|
|
78a352c2eb | ||
|
|
a4be2c013c | ||
|
|
a9b5af1d62 | ||
|
|
d07af06363 | ||
|
|
91eb42bed6 | ||
|
|
a7c3ee3805 | ||
|
|
cc4a9ff522 | ||
|
|
d87b3a613f | ||
|
|
050a892fef | ||
|
|
42043c23b2 | ||
|
|
0440a206dc | ||
|
|
10b44b2d4a | ||
|
|
4f8781051a | ||
|
|
f1a8b66758 | ||
|
|
7bfd1238ce | ||
|
|
fbb77ddb23 | ||
|
|
b6d69d0c1e | ||
|
|
f92853b475 | ||
|
|
1956b7be26 | ||
|
|
5e947dac48 | ||
|
|
470b46cee1 | ||
|
|
3a373791b8 | ||
|
|
5e2a6b8f74 | ||
|
|
56c3d1f7fc | ||
|
|
c8c07bbedc | ||
|
|
5a3f4a794d | ||
|
|
42401a6537 | ||
|
|
37e8356be3 | ||
|
|
c71d140252 | ||
|
|
30202196f0 | ||
|
|
931fc37bc9 | ||
|
|
eeee8cfd31 | ||
|
|
5469414bf8 | ||
|
|
5748cb17f8 | ||
|
|
8b80d2a57c | ||
|
|
1a1f3d3efe | ||
|
|
f5190ed40c | ||
|
|
ffb0e5387b | ||
|
|
c77de77790 | ||
|
|
5c9a54e480 | ||
|
|
8211a13ce0 | ||
|
|
60f13f01d2 | ||
|
|
8e6230ddd9 | ||
|
|
bd236f658d | ||
|
|
3f910647c3 | ||
|
|
9e0419057c | ||
|
|
21ca3b1227 | ||
|
|
d910e40de6 | ||
|
|
e7c47a5dad | ||
|
|
7ac8c2389f | ||
|
|
24e654645f | ||
|
|
b7c70050d6 | ||
|
|
2272500bc8 | ||
|
|
ebf21d3f93 | ||
|
|
67f109504e | ||
|
|
0888dc43cf | ||
|
|
fece730645 | ||
|
|
17ae61cce5 | ||
|
|
7f2def9e6d | ||
|
|
c64ed88c34 | ||
|
|
ff94922937 | ||
|
|
bca1803fea | ||
|
|
c44c04a6d7 | ||
|
|
bbdd74e0fa | ||
|
|
c708ec79b1 | ||
|
|
4d12267641 | ||
|
|
32469fb25c | ||
|
|
b8e2ad3db9 | ||
|
|
f60f128448 | ||
|
|
cbac299f5b | ||
|
|
40773cd620 | ||
|
|
1862e88ffa | ||
|
|
cd4355d8f4 | ||
|
|
f81656fd48 | ||
|
|
abe198c0e8 | ||
|
|
15db9fcfbf | ||
|
|
1d76599a94 | ||
|
|
088e6e29da | ||
|
|
4396ee160a | ||
|
|
64f4fd6e2b | ||
|
|
33c1c56800 | ||
|
|
1e8221b3ad | ||
|
|
c4763cf8c9 | ||
|
|
d4d51bd6d3 | ||
|
|
4ba6f5d078 | ||
|
|
d54da54d67 | ||
|
|
96c5c1f9ea | ||
|
|
b0e25eef22 | ||
|
|
871e7fcd1a | ||
|
|
db6c5ba5b2 | ||
|
|
42712811e3 | ||
|
|
e4fe47bc19 | ||
|
|
b0c36cbd57 | ||
|
|
22c1a65f74 | ||
|
|
e40d124e14 | ||
|
|
c54a940540 | ||
|
|
41d7e56a02 | ||
|
|
cc39455372 | ||
|
|
30bda7761e | ||
|
|
66278a80b1 | ||
|
|
f1379332dc | ||
|
|
ef9188078d | ||
|
|
2b7e4013cd | ||
|
|
072893aabd | ||
|
|
3a6edbed16 | ||
|
|
69b2cc0ee0 | ||
|
|
0c86ac44a9 | ||
|
|
90395b8d53 | ||
|
|
864de9cee1 | ||
|
|
367b9cb1f5 | ||
|
|
b12f3c5b9d | ||
|
|
9d1db8278a | ||
|
|
06cc0dade2 | ||
|
|
1128f56b1e | ||
|
|
1165258cda | ||
|
|
4a0623f909 | ||
|
|
37baa58625 | ||
|
|
0a0f13e600 | ||
|
|
a478de3db6 | ||
|
|
11270d07bf | ||
|
|
9629f7a992 | ||
|
|
e015b627c6 | ||
|
|
43c7c10b56 | ||
|
|
969e08da0f | ||
|
|
fd1712ecbe | ||
|
|
57490a97aa | ||
|
|
c8f9c82dae | ||
|
|
343a8c920d | ||
|
|
e5b836d2d6 | ||
|
|
162d85b97b | ||
|
|
200ef4db90 | ||
|
|
0aa8e5be94 | ||
|
|
779b7713cf | ||
|
|
02c6d3f251 | ||
|
|
7e0b7fd0e5 | ||
|
|
e5def0bab5 | ||
|
|
1cbfe69961 | ||
|
|
47de39908b | ||
|
|
a6c23d8b8b | ||
|
|
5cd6bbbff1 | ||
|
|
b9565b406a | ||
|
|
8f5d81cbc8 | ||
|
|
3329bbfdf3 | ||
|
|
4c90852192 | ||
|
|
9a56fc818a | ||
|
|
432cd1e47a | ||
|
|
aa70fe8b71 | ||
|
|
f3b0ea286a | ||
|
|
eb3037ddbd | ||
|
|
a00bfcc8b2 | ||
|
|
ce1aa2c3ff | ||
|
|
8b307a08cb | ||
|
|
8e3a97baf2 | ||
|
|
c9808c329d | ||
|
|
65c591696a | ||
|
|
a3dfa1c7d5 | ||
|
|
50e3a3f334 | ||
|
|
f1b2dad435 | ||
|
|
6b71063b6d | ||
|
|
ceda2b1426 | ||
|
|
5937664052 | ||
|
|
2cf7b80d8f | ||
|
|
3ef1aceed6 | ||
|
|
421c2a6aed | ||
|
|
d9656543ee | ||
|
|
28b4320c7f | ||
|
|
939a307df2 | ||
|
|
77b97aca9d | ||
|
|
07a2b9f899 | ||
|
|
274c88be9f | ||
|
|
3d2aecf0ae | ||
|
|
4608bcdccf | ||
|
|
51c2a81360 | ||
|
|
7851b13bc4 | ||
|
|
9549da2743 | ||
|
|
4e224cf079 | ||
|
|
c9f9a8b2b3 | ||
|
|
2efec8b23e | ||
|
|
c1c0d0ac28 | ||
|
|
a918e733d8 | ||
|
|
dbe0c8075e | ||
|
|
6f4d25ec7f | ||
|
|
eaafeaaa09 | ||
|
|
ed2799e7fe | ||
|
|
894a05fffa | ||
|
|
da73b38d1a | ||
|
|
52f9afec22 | ||
|
|
c44c015a2d | ||
|
|
5d0b9f475a | ||
|
|
68e4adb561 | ||
|
|
3f7f3fe415 | ||
|
|
c45a8a2c1c | ||
|
|
73a9487f33 | ||
|
|
34d9b43122 | ||
|
|
b97db6c7e3 | ||
|
|
3833b9ccd6 | ||
|
|
c080b46039 | ||
|
|
e5bb96fe3c | ||
|
|
73543ee70d | ||
|
|
5c7fc7c4f7 | ||
|
|
e9c761b869 | ||
|
|
8e2dd0dfb2 | ||
|
|
bfe848e1e9 | ||
|
|
968b11a909 | ||
|
|
b7b17625ef | ||
|
|
72fdf10ac6 | ||
|
|
4f6c33c818 | ||
|
|
eaf48efc9c | ||
|
|
b9fb9b206e | ||
|
|
99dffafbb2 | ||
|
|
7b1f32dc5a | ||
|
|
f34c169a1b | ||
|
|
235592e9e8 | ||
|
|
6b70629cc9 | ||
|
|
2245e1c41f | ||
|
|
0d19475588 | ||
|
|
67443faddb | ||
|
|
a057a834b7 | ||
|
|
7a594c2acc | ||
|
|
365274fa12 | ||
|
|
7e9e95024a | ||
|
|
c0c6850bc0 | ||
|
|
01a0beedce | ||
|
|
bc0d0ce072 | ||
|
|
165f49ba1d | ||
|
|
f6ab00eb54 | ||
|
|
57b083718d | ||
|
|
d46fd67fb6 | ||
|
|
db1cd37745 | ||
|
|
8c9a1d6a3d | ||
|
|
9ec484617a | ||
|
|
158fe3d365 | ||
|
|
e848b4f4c6 | ||
|
|
9a2abb82e1 | ||
|
|
5e94864311 | ||
|
|
6aad654559 | ||
|
|
388b4373f3 | ||
|
|
c4bb9aa60c | ||
|
|
09a7dce6be | ||
|
|
21c42c7fea | ||
|
|
80b048951e | ||
|
|
db7e9905c1 | ||
|
|
39de4a2a56 | ||
|
|
838ebb8378 | ||
|
|
0ef6cc3f82 | ||
|
|
66f0408473 | ||
|
|
ce6410ac18 | ||
|
|
bbdab3fc9e | ||
|
|
a266258f4c | ||
|
|
57b8df3e45 | ||
|
|
e3cca74ba5 | ||
|
|
c3a4c63c15 | ||
|
|
2e6051674b | ||
|
|
7f1e8db796 | ||
|
|
a614641aeb | ||
|
|
4d5d5a90bd | ||
|
|
bd46a496c7 | ||
|
|
d528aaa63f | ||
|
|
8a9351000e | ||
|
|
cc6a1c6a1e | ||
|
|
985ef4617f | ||
|
|
82416639c4 | ||
|
|
5ab925debf | ||
|
|
b2dd0bb1d0 | ||
|
|
0ec78e9862 | ||
|
|
c27dc4e757 | ||
|
|
ccce4dc0ee | ||
|
|
65b0b42f47 | ||
|
|
63bea03ed1 | ||
|
|
bb7b7c6d5f | ||
|
|
fcac0642c9 | ||
|
|
d6cf43252e | ||
|
|
b55c16aaf6 | ||
|
|
badd6fb7ba | ||
|
|
b1098701ec | ||
|
|
76bcada934 | ||
|
|
cb8920e642 | ||
|
|
45ae32da38 | ||
|
|
56f5c04d5b | ||
|
|
3d4159b6bf | ||
|
|
bfd4b01407 | ||
|
|
8d81a737a4 | ||
|
|
e5011ba8bf | ||
|
|
3f096a6c45 | ||
|
|
2d7f9f0b39 | ||
|
|
cf54177475 | ||
|
|
896318f475 | ||
|
|
b44dc25ed9 | ||
|
|
c3c9d9b04e | ||
|
|
0c4f1a94c1 | ||
|
|
f4ae9ae153 | ||
|
|
d5ec0504f5 | ||
|
|
8ef0b7b9ef | ||
|
|
167babfedb | ||
|
|
985f52fe34 | ||
|
|
421bb2e9bf | ||
|
|
be495a46bf | ||
|
|
56942c3f2a | ||
|
|
f2b2f485a5 | ||
|
|
f663e437de | ||
|
|
2b176f9034 | ||
|
|
c4ddb31abf | ||
|
|
e26c4fd2a2 | ||
|
|
5b3d93c86d | ||
|
|
47ded66e9c | ||
|
|
ae0f5bc26a | ||
|
|
7f64c8e5fa | ||
|
|
60bd717971 | ||
|
|
19d1e7102c | ||
|
|
156dd4f1ec | ||
|
|
17d1ae7ee2 | ||
|
|
b9ade4bc21 | ||
|
|
00b47204e0 | ||
|
|
05503c5e95 | ||
|
|
68eb9e3b1f | ||
|
|
075ab744c5 | ||
|
|
953ab8a351 | ||
|
|
6e047bb56b | ||
|
|
b588726e9f | ||
|
|
f15c75cbec | ||
|
|
28acccca2a | ||
|
|
ada2643387 | ||
|
|
9c2f42bd76 | ||
|
|
311cea83c5 | ||
|
|
acac21c462 | ||
|
|
cab8ea7c62 | ||
|
|
cf076dd366 | ||
|
|
9bd40d31d7 | ||
|
|
ceec24d27f | ||
|
|
392b28ec5c | ||
|
|
bcd4e5d50d | ||
|
|
eabaa3398b | ||
|
|
1c31f23f56 | ||
|
|
a303dcde2a | ||
|
|
5fd24a89ec | ||
|
|
3b55d30002 | ||
|
|
ad6254c546 | ||
|
|
0c41517c9d | ||
|
|
3bbe373576 | ||
|
|
824d251972 | ||
|
|
2f7b799f89 | ||
|
|
8bad033938 | ||
|
|
8630c7fb37 | ||
|
|
8ce0cbdaab | ||
|
|
a0154cd9e7 | ||
|
|
a58fef6faa | ||
|
|
80992638e1 | ||
|
|
3e5cc2beb9 | ||
|
|
2e15e5e45d | ||
|
|
88be836f39 | ||
|
|
11a4112cb9 | ||
|
|
d3c8211fef | ||
|
|
244a32b3d5 | ||
|
|
3360958232 | ||
|
|
809fae91cf | ||
|
|
c29d24650d | ||
|
|
01c263e9fe | ||
|
|
8d267798db | ||
|
|
374df1cf8e | ||
|
|
b86ef8e2cb | ||
|
|
32c5ad86ab | ||
|
|
3f48434eb6 | ||
|
|
b7d0982ae7 | ||
|
|
1a9ea74d2d | ||
|
|
5145e6e550 | ||
|
|
62cec9b225 | ||
|
|
603292735e | ||
|
|
d8ac0fbcbf | ||
|
|
8c670f8349 | ||
|
|
30bab85be1 | ||
|
|
2ea0f30ffa | ||
|
|
7d36b514d8 | ||
|
|
abaf083ddc | ||
|
|
ea556d1ffe | ||
|
|
bfa258b3e7 | ||
|
|
7f0dc9c4cb | ||
|
|
199fa12a3b | ||
|
|
36cfd88743 | ||
|
|
29e94d9531 | ||
|
|
a0a23eff4b | ||
|
|
b61702ce8c | ||
|
|
63aead84ee | ||
|
|
e0a86d8c18 | ||
|
|
369028100b | ||
|
|
241913fe60 | ||
|
|
1a51586c0c | ||
|
|
f75c11ed27 | ||
|
|
6925cbe624 | ||
|
|
ff4b8b64c8 | ||
|
|
1832f310ac | ||
|
|
1d2ebf6281 | ||
|
|
9c333277cc | ||
|
|
736e31313c | ||
|
|
e176106f14 | ||
|
|
e3adcd79d3 | ||
|
|
21cd8adc80 | ||
|
|
0e3d94526a | ||
|
|
fc52c6d5dd | ||
|
|
ea601b75e2 | ||
|
|
224565478c | ||
|
|
cb919290c2 | ||
|
|
23289e6d14 | ||
|
|
5668c1abad | ||
|
|
0b2b87b717 | ||
|
|
4922197a33 | ||
|
|
6ec6994107 | ||
|
|
25579907fc | ||
|
|
470a1e923c | ||
|
|
74583a91fe | ||
|
|
93f0ca8650 | ||
|
|
a38df97fb8 | ||
|
|
96185e9ca1 | ||
|
|
01c6121ba5 | ||
|
|
121c5c060b | ||
|
|
a218a29c49 | ||
|
|
4563e03633 | ||
|
|
627f730e18 | ||
|
|
0a62c911d1 | ||
|
|
4a7f3eb274 | ||
|
|
c7a7f85737 | ||
|
|
c8f601b30f | ||
|
|
d5d70df747 | ||
|
|
e5b281256b | ||
|
|
7d1552c9de | ||
|
|
0d0b335763 | ||
|
|
036f273ad0 | ||
|
|
ae69d47087 | ||
|
|
f4a0e78d85 | ||
|
|
4dfd146aa4 | ||
|
|
1aa08175ac | ||
|
|
fb53aa7bc6 | ||
|
|
35030bb0fe | ||
|
|
c5ff6dfa74 | ||
|
|
4ea7e4b8cc | ||
|
|
0172d4f725 | ||
|
|
8398c19ca4 | ||
|
|
d68a82ecbd | ||
|
|
3aa078436a | ||
|
|
5181ba8f70 | ||
|
|
b31a37d7d3 | ||
|
|
ef6c23b600 | ||
|
|
6b493d0771 | ||
|
|
a03065dc17 | ||
|
|
d65239a21a | ||
|
|
fa2b1b3472 | ||
|
|
3b8fe25248 | ||
|
|
cd24222379 | ||
|
|
0aefdd3863 | ||
|
|
6606c3ae81 | ||
|
|
6105d3a821 | ||
|
|
8b67f40de2 | ||
|
|
8b07664860 | ||
|
|
f09fe0ad0f | ||
|
|
685d88b26a | ||
|
|
6dee988083 | ||
|
|
22eb54036f | ||
|
|
a78374ae0d | ||
|
|
120943341c | ||
|
|
8e1e14ee8a | ||
|
|
71b9fadf65 | ||
|
|
f22969328b | ||
|
|
2534fa5203 | ||
|
|
93af0a4a51 | ||
|
|
2da02bbd16 | ||
|
|
ff6d21103b | ||
|
|
05896e787c | ||
|
|
4291ce3cac | ||
|
|
d1f4953ad4 | ||
|
|
c1f5052199 | ||
|
|
b65b777d2a | ||
|
|
23670fbe43 | ||
|
|
192b1759ca | ||
|
|
4bd9480dce | ||
|
|
09c1404182 | ||
|
|
79982c59a0 | ||
|
|
aff059ecc2 | ||
|
|
8106cdd570 | ||
|
|
84510264cd | ||
|
|
040cfcf89c | ||
|
|
c55d22dc0b | ||
|
|
acd03445c3 | ||
|
|
7fa2d1a092 | ||
|
|
e56ff0333d | ||
|
|
d24fb77c03 | ||
|
|
12da72adeb | ||
|
|
f2046e0aeb | ||
|
|
68df28296d | ||
|
|
c9f25410c9 | ||
|
|
639c84c193 | ||
|
|
658b58129b | ||
|
|
814643d8a2 | ||
|
|
de17d760ba | ||
|
|
a0313876e7 | ||
|
|
cf6dd25126 | ||
|
|
5071196631 | ||
|
|
02cb3ccdc4 | ||
|
|
a5777ba3f7 | ||
|
|
3b9c074a19 | ||
|
|
49c33cb9e5 | ||
|
|
ec36089afd | ||
|
|
5c9e27f347 | ||
|
|
c2b067912b | ||
|
|
69792976e4 | ||
|
|
08c419da66 | ||
|
|
68c07aeeb3 | ||
|
|
a43a1312d2 | ||
|
|
6e4b011dac | ||
|
|
a8537e6f59 | ||
|
|
c1c0685e34 | ||
|
|
cc2b3c68cc | ||
|
|
04c7da67ab | ||
|
|
82c86650e1 | ||
|
|
cf37d5c7ab | ||
|
|
bd094b5d1d | ||
|
|
e6b80c41b2 | ||
|
|
15e6db353d | ||
|
|
cc8f6e3dbc | ||
|
|
397b239bdf | ||
|
|
1f86c3397e | ||
|
|
607131b624 | ||
|
|
ace13d2ca4 | ||
|
|
50b39413ac | ||
|
|
e19f549a11 | ||
|
|
b2bb72641f | ||
|
|
2d8612c8ae | ||
|
|
de3cac3d2c | ||
|
|
f74d51d975 | ||
|
|
ee8518bd9c | ||
|
|
17823680fc | ||
|
|
5a8fa8c91f | ||
|
|
27642fade0 | ||
|
|
034db45e26 | ||
|
|
c01f85420e | ||
|
|
8c0388e487 | ||
|
|
2864846d91 | ||
|
|
f7dd6d8446 | ||
|
|
b8a20fc82a | ||
|
|
b65acfc6de | ||
|
|
12bb377f9b | ||
|
|
6078f63801 | ||
|
|
02ceef1225 | ||
|
|
2dc95e1c41 | ||
|
|
40e975869b | ||
|
|
3eb135f550 | ||
|
|
2de96f501a | ||
|
|
8fd6f4b6fb | ||
|
|
4af5827d07 | ||
|
|
fee16e1049 | ||
|
|
207aa8a131 | ||
|
|
cfb7bfc7d9 | ||
|
|
0cf96f33ea | ||
|
|
e8fad838b9 | ||
|
|
81c15e1f11 | ||
|
|
dcc31da516 | ||
|
|
c7ee8edc33 | ||
|
|
b53a9efda3 | ||
|
|
ada0dc4234 | ||
|
|
e807ead2f7 | ||
|
|
ac21f47034 | ||
|
|
f2b7349e2f | ||
|
|
13057fe53f | ||
|
|
aa37899857 | ||
|
|
188b5fa337 | ||
|
|
842a35c7ca | ||
|
|
845eabd2dc | ||
|
|
ec1994f3e7 | ||
|
|
b2a849142b | ||
|
|
5b6a23726a | ||
|
|
85c1926171 | ||
|
|
a7617ea224 | ||
|
|
fdd4f3c005 | ||
|
|
d0afc2c8b7 | ||
|
|
96bea84664 | ||
|
|
fe22eb84e6 | ||
|
|
57c74fb5af | ||
|
|
8387b47352 | ||
|
|
364a71ca82 | ||
|
|
6a5b803539 | ||
|
|
89716a336b | ||
|
|
f1e6be4be1 | ||
|
|
8fd3c219fd | ||
|
|
c2f387296e | ||
|
|
29ebccc3e2 | ||
|
|
8b7a435dee | ||
|
|
e2ac5517a9 | ||
|
|
4c22730b53 | ||
|
|
9a90f1aba6 | ||
|
|
36cf79384f | ||
|
|
28cb0299c1 | ||
|
|
5518374bd9 | ||
|
|
21a1fa4701 | ||
|
|
50785e12df | ||
|
|
10f57523d9 | ||
|
|
a08e1c6376 | ||
|
|
eaabdc26ce | ||
|
|
0cd797ec46 | ||
|
|
0b946db909 | ||
|
|
a12c4af876 | ||
|
|
05f000b18e | ||
|
|
27ab6e0f86 | ||
|
|
b8f6e20aa5 | ||
|
|
914c97239f | ||
|
|
8ac9712539 | ||
|
|
d71bfabe39 | ||
|
|
46a68b7dd6 | ||
|
|
13601dbfe8 | ||
|
|
46a29c0212 | ||
|
|
361e5e3fac | ||
|
|
982cb02dfb | ||
|
|
6e03b44cc8 | ||
|
|
31abe57cd6 | ||
|
|
3a61b05422 | ||
|
|
44c319cf0d | ||
|
|
8b99c8b6ec | ||
|
|
2fc3a4576f | ||
|
|
9a5e05a406 | ||
|
|
9019ed2e77 | ||
|
|
b9e67d4f46 | ||
|
|
3ba1348cd5 | ||
|
|
541f875372 | ||
|
|
d7ef2ca7cd | ||
|
|
43ecb8ffe4 | ||
|
|
6faef15ecd | ||
|
|
3a55f5d548 | ||
|
|
10b29b8d2d | ||
|
|
7512e5a202 | ||
|
|
8afb045af2 | ||
|
|
f32e9b2fa8 | ||
|
|
97d344e2cb | ||
|
|
5053603d2a | ||
|
|
7b44156315 | ||
|
|
9d6e5a6387 | ||
|
|
4b7af6da11 | ||
|
|
5507448b95 | ||
|
|
027be073b3 | ||
|
|
6910c129a9 | ||
|
|
8563ab0304 | ||
|
|
fe451a01e8 | ||
|
|
662b119be6 | ||
|
|
5ac5a99961 | ||
|
|
fb78c7a14d | ||
|
|
eb8ae8e837 | ||
|
|
b8c919b402 | ||
|
|
098102afc0 | ||
|
|
a3f950d56f | ||
|
|
a9953411a8 | ||
|
|
75833edb80 | ||
|
|
d9e14671aa | ||
|
|
9a079266dd | ||
|
|
356409734e | ||
|
|
41d02bc385 | ||
|
|
010c07de20 | ||
|
|
b896caa19b | ||
|
|
5beb6fab74 | ||
|
|
258c50db74 | ||
|
|
446155d94f | ||
|
|
0e69d32bed | ||
|
|
be5027f695 | ||
|
|
abc6d41532 | ||
|
|
27f364af95 | ||
|
|
34e0f798e3 | ||
|
|
12428fceee | ||
|
|
6a149cba6b | ||
|
|
8aa577ad34 | ||
|
|
1fa74f62e8 | ||
|
|
26e7f2e0c4 | ||
|
|
3a1703294b | ||
|
|
55d68d2ab3 | ||
|
|
712a874f07 | ||
|
|
c46867e1d6 | ||
|
|
7d4d197eac | ||
|
|
7e4867f743 | ||
|
|
c0002e576e | ||
|
|
efb63f4740 | ||
|
|
41102098e5 | ||
|
|
98f29da3ec | ||
|
|
661c2f2dca | ||
|
|
a0568eca2b | ||
|
|
39662e362a | ||
|
|
487662054d | ||
|
|
79be52c881 | ||
|
|
a421f74371 | ||
|
|
8ae908a085 | ||
|
|
711f7fc681 | ||
|
|
07f9ce4b9e | ||
|
|
e9ea1fb3bf | ||
|
|
04e8cd96f3 | ||
|
|
199e490e7d | ||
|
|
4970ebfb92 | ||
|
|
c68e513814 | ||
|
|
f3f3424f9a | ||
|
|
fdf481c665 | ||
|
|
d0df19e8a3 | ||
|
|
f3993cac4a | ||
|
|
4aae68792c | ||
|
|
4e268ceacb | ||
|
|
4086fb2620 | ||
|
|
8ef2b021ed | ||
|
|
4c64ed4ced | ||
|
|
eb537fa130 | ||
|
|
83bbbb0fb4 | ||
|
|
69e2befd15 | ||
|
|
0fc1d0788d | ||
|
|
28879d4174 | ||
|
|
457a47f19f | ||
|
|
987c4c1519 | ||
|
|
8a95d67e26 | ||
|
|
3982f8136b | ||
|
|
a14e14efdd | ||
|
|
a648372757 | ||
|
|
15b38fa8dd | ||
|
|
11779747ef | ||
|
|
eeae337844 | ||
|
|
aa83fd4ebb | ||
|
|
00958b5818 | ||
|
|
c80325cae4 | ||
|
|
62ef058497 | ||
|
|
8b46b545c6 | ||
|
|
66a8d8b4b2 | ||
|
|
22d2827b41 | ||
|
|
8c54f03db8 | ||
|
|
50d7e96c6d | ||
|
|
c3aa104a8d | ||
|
|
5a52dca9c2 | ||
|
|
d1d9800ef1 | ||
|
|
74b27447c1 | ||
|
|
34917a5373 | ||
|
|
40c44db720 | ||
|
|
f2187638dc | ||
|
|
ca94915779 | ||
|
|
50762c2186 | ||
|
|
4efe1861c3 | ||
|
|
d43773d634 | ||
|
|
faaedea286 | ||
|
|
9b58b71c84 | ||
|
|
6086b60455 | ||
|
|
7cbf161f72 | ||
|
|
22a0881ded | ||
|
|
8c0aaf9326 | ||
|
|
da253e3aac | ||
|
|
f55f988643 | ||
|
|
b1545f2985 | ||
|
|
07bb413a8f | ||
|
|
ffa879d092 | ||
|
|
ffb070297a | ||
|
|
7a0ed4a40c | ||
|
|
6b3b4a250b | ||
|
|
12caf445d4 | ||
|
|
fdf8038fe5 | ||
|
|
7cc602c800 | ||
|
|
291906a208 | ||
|
|
097d49e73d | ||
|
|
407332cb9a | ||
|
|
48450b8f43 | ||
|
|
38f3949b25 | ||
|
|
48ad31920d | ||
|
|
0dbd22124b | ||
|
|
7df3006c6b | ||
|
|
547afddbab | ||
|
|
b40b90f035 | ||
|
|
18f3ec8297 | ||
|
|
2f92106107 | ||
|
|
aefa3c6d82 | ||
|
|
da84226b8b | ||
|
|
fbbe942c45 | ||
|
|
d4e5f63e96 | ||
|
|
70d6838fb0 | ||
|
|
61e9603be5 | ||
|
|
401ae21308 | ||
|
|
b7b1de1219 | ||
|
|
fa6a82c9af | ||
|
|
5f05971a84 | ||
|
|
2a670fac46 | ||
|
|
25c65f5c0f | ||
|
|
c826c0d17c | ||
|
|
1f835295d8 | ||
|
|
d327698491 | ||
|
|
6106741bea | ||
|
|
6e0fa64c7b | ||
|
|
310a81c90c | ||
|
|
da676a58ca | ||
|
|
99b1e8f19f | ||
|
|
031079703f | ||
|
|
39ed033adb | ||
|
|
92ad2d555b | ||
|
|
1951dba955 | ||
|
|
64ad493eac | ||
|
|
29152f6ef0 | ||
|
|
fccc39a3a7 | ||
|
|
0474ad51c2 | ||
|
|
a07e27374d | ||
|
|
8ac9aae78a | ||
|
|
3fb25e3f0f | ||
|
|
c5e08c6c83 | ||
|
|
5be981bab5 | ||
|
|
fc7a62f325 | ||
|
|
b9923fe3f2 | ||
|
|
b7749b7a96 | ||
|
|
f6524657fa | ||
|
|
05dba2d9c0 | ||
|
|
fa3d8bc745 | ||
|
|
68a0d76b93 | ||
|
|
0d339ebaac | ||
|
|
1feb031a88 | ||
|
|
6b4c9ff740 | ||
|
|
e1f93d52e3 | ||
|
|
6e2ff7fb35 | ||
|
|
8877446463 | ||
|
|
c5516a256a | ||
|
|
1524c1a471 | ||
|
|
25b733809a | ||
|
|
f06bdc437d | ||
|
|
e3528bcda7 | ||
|
|
e82f37cbbf | ||
|
|
671b6aa602 | ||
|
|
de3bec7f81 | ||
|
|
69e8a53ee4 | ||
|
|
0e06dd31fd | ||
|
|
d6a766f138 | ||
|
|
70d7918634 | ||
|
|
6fa3c2d5ce | ||
|
|
7e3d403b88 | ||
|
|
63def4e716 | ||
|
|
584404f8f4 | ||
|
|
426bc429ef | ||
|
|
f31c47ade8 | ||
|
|
2fab033e9b | ||
|
|
c34d34e6a0 | ||
|
|
ab053ad6c1 | ||
|
|
ae70673752 | ||
|
|
8856889d10 | ||
|
|
607bcd61d0 | ||
|
|
7bb6856a7e | ||
|
|
8573c6bcac | ||
|
|
4bb3eccf2b | ||
|
|
e04c519896 | ||
|
|
c1b5fc6673 | ||
|
|
79bb0a97a2 | ||
|
|
158510ad42 | ||
|
|
9585e50fef | ||
|
|
902098d615 | ||
|
|
2ed2a72439 | ||
|
|
a76ba817a8 | ||
|
|
20ce742691 | ||
|
|
a69de4919b | ||
|
|
a6bf4bcfa2 | ||
|
|
568d7229bf | ||
|
|
14a9cda63b | ||
|
|
4cc8088251 | ||
|
|
20c5fcf764 | ||
|
|
c22c93f0b6 | ||
|
|
d8e7d77316 | ||
|
|
6eb746e187 | ||
|
|
b2de0b7d44 | ||
|
|
dd420615d5 | ||
|
|
1703d66a82 | ||
|
|
7c8bd3fcd0 | ||
|
|
ad21a5585c | ||
|
|
251502f9a1 | ||
|
|
bb13858120 | ||
|
|
2ec94d4daf | ||
|
|
41967a0276 | ||
|
|
be326a2f1b | ||
|
|
323a167b49 | ||
|
|
fd6932b18b | ||
|
|
5295f36cb4 | ||
|
|
4526747997 | ||
|
|
d0cd6e2244 | ||
|
|
e09a7b5787 | ||
|
|
11d2da4036 | ||
|
|
0fe3a2c512 | ||
|
|
eea1d6932c | ||
|
|
9f7b698007 | ||
|
|
1ca81fafd0 | ||
|
|
761e0a63e1 | ||
|
|
c021b9bb83 | ||
|
|
15c325f06a | ||
|
|
2731508b34 | ||
|
|
8478180d9e | ||
|
|
fdec53fb9c | ||
|
|
d30321a6cf | ||
|
|
3bf898526a | ||
|
|
3a84c18bdd | ||
|
|
9db196e6c5 | ||
|
|
623df7a068 | ||
|
|
0706555513 | ||
|
|
8c013da41f | ||
|
|
6ed0234393 | ||
|
|
50270f1fdf | ||
|
|
f4cbeaf0ac | ||
|
|
b8583f6f9f | ||
|
|
841da63e77 | ||
|
|
6761081ab4 | ||
|
|
349f09e401 | ||
|
|
de6c918392 | ||
|
|
c15334eb4e | ||
|
|
9c42e035a0 | ||
|
|
999e584511 | ||
|
|
fc28b60f9c | ||
|
|
413cc9189e | ||
|
|
ca73e23fd0 | ||
|
|
7b9e789f9c | ||
|
|
b00094bdeb | ||
|
|
7e682f4f93 | ||
|
|
bb403f3361 | ||
|
|
ebae1dc0c6 | ||
|
|
6f3a8d5bd3 | ||
|
|
187cf4c97d | ||
|
|
257ec146b2 | ||
|
|
b5ed53273a | ||
|
|
dc511e9ecb | ||
|
|
e680d3190f | ||
|
|
0e32e054df | ||
|
|
6633e1b863 | ||
|
|
d57efea5c1 | ||
|
|
26075f7a47 | ||
|
|
cc8b2cd706 | ||
|
|
14a81c5a03 | ||
|
|
078cab224b | ||
|
|
bf1b684e2e | ||
|
|
b6afcf6458 | ||
|
|
a45f546fe0 | ||
|
|
48cbf485b6 | ||
|
|
0012e43bab | ||
|
|
5986ec940f | ||
|
|
d7783cc8b8 | ||
|
|
0eb83127ef | ||
|
|
e1d93eb457 | ||
|
|
052360e901 | ||
|
|
fc18023a9b | ||
|
|
f48d3bcbd0 | ||
|
|
e56598a84d | ||
|
|
0d3075f5ba | ||
|
|
69019d6e9e | ||
|
|
df89b641bb | ||
|
|
00a9d5417a | ||
|
|
e5e5d6decd | ||
|
|
294ddff8a6 | ||
|
|
0a9f8bcf97 | ||
|
|
7d68b08028 | ||
|
|
f09d2b350f | ||
|
|
fdc7af232a | ||
|
|
6fda126dd7 | ||
|
|
60274aba6e | ||
|
|
8d6a8717bb | ||
|
|
33e8b747ac | ||
|
|
a62ee8ad27 | ||
|
|
6d52fb460b | ||
|
|
7d0e6e800e | ||
|
|
713599407c | ||
|
|
03888774a5 | ||
|
|
d1ad45cc41 | ||
|
|
075ffca52a | ||
|
|
627c0f05ef | ||
|
|
59d6420b9a | ||
|
|
e74999af51 | ||
|
|
af7bbe5a6c | ||
|
|
df396c4ad8 | ||
|
|
d6750e9d76 | ||
|
|
812c699c8d | ||
|
|
dcde8bf026 | ||
|
|
cb0cc2999a | ||
|
|
257f5ca091 | ||
|
|
cabd882ced | ||
|
|
f593440b7b | ||
|
|
d2c3c0505c | ||
|
|
12a6fcd3a8 | ||
|
|
7ae5a778d5 | ||
|
|
08907484f5 | ||
|
|
851866d2fc | ||
|
|
93d6fa7d0d | ||
|
|
2235e241cc | ||
|
|
df91af9141 | ||
|
|
f53c6aa66e | ||
|
|
14936c751e | ||
|
|
2f069a65d0 | ||
|
|
cd7018fd2c | ||
|
|
f7ff4d005f | ||
|
|
6db767961b | ||
|
|
594cc87acf | ||
|
|
4b2ec1929a | ||
|
|
154ca4b837 | ||
|
|
1176eb2597 | ||
|
|
2fb0db7710 | ||
|
|
265d372f94 | ||
|
|
db454fc8dc | ||
|
|
77712b1ecb | ||
|
|
b5e9efd3db | ||
|
|
d8fb03c714 | ||
|
|
3d2d379ce4 | ||
|
|
c50c2886f7 | ||
|
|
b849de1d18 | ||
|
|
7743c8685e | ||
|
|
ff783e52c9 | ||
|
|
58c18efc07 | ||
|
|
b2207a1c40 | ||
|
|
0d89ea9918 | ||
|
|
2fe9b1387b | ||
|
|
0cf2445bb7 | ||
|
|
168b7bf9e2 | ||
|
|
9b88d8b78d | ||
|
|
ba76e378e9 | ||
|
|
333658d5f8 | ||
|
|
f552ba4b74 | ||
|
|
aa5c5673be | ||
|
|
397423242e | ||
|
|
610c25e8b1 | ||
|
|
d518bc39f3 | ||
|
|
de9e7edaff | ||
|
|
58f323bc80 | ||
|
|
b9dc2b7ea2 | ||
|
|
22d79852ea | ||
|
|
40df115bf5 | ||
|
|
7a403967d5 | ||
|
|
5556a49278 | ||
|
|
6c31864f5f | ||
|
|
d4eb499101 | ||
|
|
397e38c6e6 | ||
|
|
9f6f4d1e09 | ||
|
|
c490c2f281 | ||
|
|
75e4d06ade | ||
|
|
f868d63582 | ||
|
|
b926605531 | ||
|
|
4d67a0787f | ||
|
|
cc282870dd | ||
|
|
751acb3800 | ||
|
|
94722ba71f | ||
|
|
e586401ecb | ||
|
|
752e80cd5a | ||
|
|
7fbaf10a79 | ||
|
|
d29265b97d | ||
|
|
12137231d3 | ||
|
|
682c0fef74 | ||
|
|
0e63603659 | ||
|
|
2cf9604929 | ||
|
|
4af6dc9663 | ||
|
|
6fb1d0e114 | ||
|
|
b0d2c42f9a | ||
|
|
a9c0e97ca9 | ||
|
|
fae0c5764f | ||
|
|
444b7d2360 | ||
|
|
ad837a06e5 | ||
|
|
00ee56e232 | ||
|
|
add7dc2d5a | ||
|
|
d2b0e8b1c3 | ||
|
|
c05bd98104 | ||
|
|
9fea277554 | ||
|
|
93ea39697f | ||
|
|
3c06874035 | ||
|
|
d738054256 | ||
|
|
22d1879c60 | ||
|
|
4103182568 | ||
|
|
5c83f05e81 | ||
|
|
e0d452a032 | ||
|
|
deb8a3b7c9 | ||
|
|
48a00f1320 | ||
|
|
288adea256 | ||
|
|
d33f2e9f5a | ||
|
|
f2f2634990 | ||
|
|
6198a4102c | ||
|
|
6036e5e0f7 | ||
|
|
c9dbb9efe7 | ||
|
|
406d287ae1 | ||
|
|
9056f65b0c | ||
|
|
ea31a9b09c | ||
|
|
1ed34e88aa | ||
|
|
4c0d6e283a | ||
|
|
ee27c57b58 | ||
|
|
493656dd3c | ||
|
|
391f02b1b5 | ||
|
|
e3851db216 | ||
|
|
4a624ca055 | ||
|
|
c6cc24ea3f | ||
|
|
7e56005011 | ||
|
|
2801ddcacc | ||
|
|
cf633b70c2 | ||
|
|
f8427641b0 | ||
|
|
b80f32dd0a | ||
|
|
fc63d04f42 | ||
|
|
dad43063f8 | ||
|
|
88cc3edf2e | ||
|
|
9b6934ba33 | ||
|
|
9b5db6c270 | ||
|
|
e2031c81b5 | ||
|
|
dff36d2a77 | ||
|
|
952d12a5f5 | ||
|
|
4bbf2c3418 | ||
|
|
9588155a4e | ||
|
|
da1224a01c | ||
|
|
ab1885c8aa | ||
|
|
614a4508e6 | ||
|
|
89f1e3ddf0 | ||
|
|
d413c0ce38 | ||
|
|
67fb2a39a7 | ||
|
|
83912faa1d | ||
|
|
8deaf0d253 | ||
|
|
145eef414b | ||
|
|
18ce960755 | ||
|
|
ae21c2cc8b | ||
|
|
ea5b424e04 | ||
|
|
372a431135 | ||
|
|
12e8972ba1 | ||
|
|
2bc25b546a | ||
|
|
75e5ea90c2 | ||
|
|
3daa9f6e53 | ||
|
|
5a72a50367 | ||
|
|
16ab7a0da2 | ||
|
|
f5549805b6 | ||
|
|
197c3f2ab4 | ||
|
|
330c46317c | ||
|
|
3eb1b74b29 | ||
|
|
e59204fc22 | ||
|
|
922ce479b4 | ||
|
|
136e98d26e | ||
|
|
d315fcb94a | ||
|
|
9640f93d8c | ||
|
|
b94703a187 | ||
|
|
6e16088e24 | ||
|
|
eefe4b2097 | ||
|
|
5671fce111 | ||
|
|
756668473c | ||
|
|
f17673f1d0 | ||
|
|
f1568304e0 | ||
|
|
ba57d1f89b | ||
|
|
470933a480 | ||
|
|
48b512b964 | ||
|
|
43693cbeb8 | ||
|
|
cc21948339 | ||
|
|
129c5d50a1 | ||
|
|
41b2fd5f4d | ||
|
|
4624c6f845 | ||
|
|
67e4897b2c | ||
|
|
ef91884ba8 | ||
|
|
ab7193d15e | ||
|
|
529d473095 | ||
|
|
6c94692bc6 | ||
|
|
52f71ce77b | ||
|
|
4b4035101b | ||
|
|
9737eb0f94 | ||
|
|
2041d905a9 | ||
|
|
493793dcbc | ||
|
|
9f44467d44 | ||
|
|
8cdf0a831c | ||
|
|
e8bacbc465 | ||
|
|
af09a138ce | ||
|
|
1cb025cede | ||
|
|
9f23b355f7 | ||
|
|
2d1988923c | ||
|
|
ba2e78ff36 | ||
|
|
39b633c1de | ||
|
|
27f6cd0a88 | ||
|
|
3813dd120e | ||
|
|
8a6d1dd408 | ||
|
|
df520f1265 | ||
|
|
515df8784a | ||
|
|
6b4657e81f | ||
|
|
839f595181 | ||
|
|
18d5a38594 | ||
|
|
75f7aa5563 | ||
|
|
faa556e759 | ||
|
|
394fae7fc5 | ||
|
|
0803634cd1 | ||
|
|
8a14dc290a | ||
|
|
c155eb83c2 | ||
|
|
2fbe588881 | ||
|
|
5aed44459e | ||
|
|
8a51c23765 | ||
|
|
f4a7ce7c49 | ||
|
|
5b82db9a17 | ||
|
|
c41413c499 | ||
|
|
370e18e437 | ||
|
|
57ba050c58 | ||
|
|
d96dea9abf | ||
|
|
a76318a698 | ||
|
|
3dd5cbe54f | ||
|
|
db73838ca4 | ||
|
|
52864eda2e | ||
|
|
b74c8033a2 | ||
|
|
b6af4a0aab | ||
|
|
a8bc68638c | ||
|
|
a9c5b0dee6 | ||
|
|
638754e559 | ||
|
|
9ade33a235 | ||
|
|
8f849d9977 | ||
|
|
a9a572e8a1 | ||
|
|
b546cd6d69 | ||
|
|
a299e38810 | ||
|
|
85028e021c | ||
|
|
a03f232063 | ||
|
|
7a61472a0a | ||
|
|
c0ca88c287 | ||
|
|
488a58a998 | ||
|
|
74af29faae | ||
|
|
d5880f97c5 | ||
|
|
6d780d957c | ||
|
|
1215c28438 | ||
|
|
8f47e5794b | ||
|
|
c2d72fd402 | ||
|
|
6c4ee29605 | ||
|
|
3c762e6d4e | ||
|
|
14c61d2d24 | ||
|
|
252c7708f5 | ||
|
|
579944d327 | ||
|
|
170f08cee0 | ||
|
|
4a8d120415 | ||
|
|
f8107626d0 | ||
|
|
b9adad95c8 | ||
|
|
5875c0fce5 | ||
|
|
39497a4479 | ||
|
|
adbc44560b | ||
|
|
da4e57f2ba | ||
|
|
0bab65915d | ||
|
|
52dc213926 | ||
|
|
79b0c9f89a | ||
|
|
f95627cf8a | ||
|
|
6b35c7eb9d | ||
|
|
3390d370d0 | ||
|
|
79437c2734 | ||
|
|
23687ed34d | ||
|
|
592e834cd1 | ||
|
|
58486cf9f5 | ||
|
|
60140607cf | ||
|
|
3080a75445 | ||
|
|
ab2799eb14 | ||
|
|
70ec07dd37 | ||
|
|
897058e5c6 | ||
|
|
6f842a9b05 | ||
|
|
f2ec0e072e | ||
|
|
8f8cf896d6 | ||
|
|
8c2fd26dfa | ||
|
|
ff5dabd5a0 | ||
|
|
ecea68d270 | ||
|
|
e7e8c033b5 | ||
|
|
b39c635675 | ||
|
|
d04ef4c26d | ||
|
|
19df7116c6 | ||
|
|
0d3593f5c1 | ||
|
|
7c77eca4f7 | ||
|
|
a7af42f14c | ||
|
|
ef8a0eae5c | ||
|
|
7f3859bb5c | ||
|
|
8a5ff3ee29 | ||
|
|
30ce2faf21 | ||
|
|
0bd968df25 | ||
|
|
fe827798fa | ||
|
|
79cf96de20 | ||
|
|
afe46c849b | ||
|
|
f96175e75e | ||
|
|
5f68d85896 | ||
|
|
d9bc7ffe61 | ||
|
|
2fa9bf7052 | ||
|
|
78125be9c2 | ||
|
|
1a5123da94 | ||
|
|
5389c987a3 | ||
|
|
79b5666abe | ||
|
|
9b7742bb36 | ||
|
|
6e74833c6c | ||
|
|
5238b63f1a | ||
|
|
e55ae5d32e | ||
|
|
bb2250f097 | ||
|
|
29aa6d5850 | ||
|
|
78fc479a69 | ||
|
|
e68b5e3029 | ||
|
|
30f7ee62e8 | ||
|
|
03a8a07d67 | ||
|
|
d53f88d7af | ||
|
|
4daacc38cb | ||
|
|
cf4a4a1fa8 | ||
|
|
ac61645c2d | ||
|
|
f7cbb38dbb | ||
|
|
277237805a | ||
|
|
09bc639dbf | ||
|
|
66b0745933 | ||
|
|
f7a14956d8 | ||
|
|
2107f48208 | ||
|
|
3c02236767 | ||
|
|
32ddb2ed5f | ||
|
|
e55ef72786 | ||
|
|
7858f6fb16 | ||
|
|
4f0a4a6a7a | ||
|
|
94b8220f6a | ||
|
|
f90fc5faf0 | ||
|
|
4f7a219dac | ||
|
|
fbdb7953db | ||
|
|
33eee90ad2 | ||
|
|
334edc6802 | ||
|
|
2ba80b436f | ||
|
|
801495c0f7 | ||
|
|
01c4ac1315 | ||
|
|
37ed70b9ea | ||
|
|
4429597ece | ||
|
|
642c2e964b | ||
|
|
c84cc3847c | ||
|
|
2cffd7d4e1 | ||
|
|
15e35a737c | ||
|
|
ed0502e98b | ||
|
|
dd4e3f9efc | ||
|
|
1138def67f | ||
|
|
242019fdf4 | ||
|
|
80f9662b05 | ||
|
|
9277853f07 | ||
|
|
ab269099a7 | ||
|
|
f047219b23 | ||
|
|
ae2bb66535 | ||
|
|
0a5e4a1442 | ||
|
|
1b9fcf48b1 | ||
|
|
b892f8ecb6 | ||
|
|
0fc8bab82a | ||
|
|
34e1c94be1 | ||
|
|
dc6e03dc5b | ||
|
|
a352490f88 | ||
|
|
cfd658dab0 | ||
|
|
952152fd96 | ||
|
|
03aedda156 | ||
|
|
aebf566c17 | ||
|
|
4bc89a2b98 | ||
|
|
d7c5efe663 | ||
|
|
a4c0d9c2e4 | ||
|
|
c9a97a795a | ||
|
|
c3ceee769f | ||
|
|
5e610278ad | ||
|
|
c7f0b573ac | ||
|
|
3cfae6cfce | ||
|
|
11f0a12ed8 | ||
|
|
b27957a686 | ||
|
|
890b537974 | ||
|
|
d360f957c0 | ||
|
|
ab367a0678 | ||
|
|
e1e529fae1 | ||
|
|
d2393d23ee | ||
|
|
cc2124ce7d | ||
|
|
64b6e4e4b3 | ||
|
|
6215194e2b | ||
|
|
4790fce2ad | ||
|
|
68c14b47aa | ||
|
|
9d3bf3e2c1 | ||
|
|
05d8ef6f90 | ||
|
|
014a5c0bf0 | ||
|
|
10a6939753 | ||
|
|
20a2b71c9c | ||
|
|
7e38924de5 | ||
|
|
63408276f9 | ||
|
|
12eabe3031 | ||
|
|
5f16718b19 | ||
|
|
c4151d1aa4 | ||
|
|
9a48f4b6a3 | ||
|
|
98af757b00 | ||
|
|
291ec3b6c0 | ||
|
|
d1b28647ed | ||
|
|
cd77c5a7b7 | ||
|
|
e7af89f900 | ||
|
|
8f8a968dc2 | ||
|
|
0bc4573221 | ||
|
|
646b19ce77 | ||
|
|
ef938d5aad | ||
|
|
14ce9d49f1 | ||
|
|
33f5321c39 | ||
|
|
b6c041d752 | ||
|
|
fc4a099514 | ||
|
|
a381c45a6e | ||
|
|
d36240499b | ||
|
|
e58cb41e7e | ||
|
|
dfe0a65d93 | ||
|
|
60b134b53c | ||
|
|
ffb3162116 | ||
|
|
aa290eb285 | ||
|
|
df2e0dc751 | ||
|
|
550380f9c8 | ||
|
|
ca8f8837c2 | ||
|
|
0c947f7619 | ||
|
|
8a482590fa | ||
|
|
9711fef759 | ||
|
|
2cb6249206 | ||
|
|
48c4f95d4d | ||
|
|
0d5f9868b8 | ||
|
|
cfcca2168f | ||
|
|
72a5e12b5c | ||
|
|
03505a0f58 | ||
|
|
57613d7345 | ||
|
|
6e91eeef13 | ||
|
|
c4bf9638e3 | ||
|
|
7f64636f5f | ||
|
|
1eabbe1ad7 | ||
|
|
e8220912e9 | ||
|
|
6b6a344e09 | ||
|
|
383d1752fa | ||
|
|
68cb51e7dd | ||
|
|
ece1fe835c | ||
|
|
ab47fb661f | ||
|
|
491ae26f6c | ||
|
|
161720b500 | ||
|
|
dcca4d2081 | ||
|
|
2d9133bbbd | ||
|
|
758b8b4ba0 | ||
|
|
aed3f57b3b | ||
|
|
398c218b03 | ||
|
|
023c303501 | ||
|
|
7ca11f8f96 | ||
|
|
e3de4ba830 | ||
|
|
0db56c6b55 | ||
|
|
90ae9fe928 | ||
|
|
214e32c96e | ||
|
|
4d468cffcd | ||
|
|
88835ab641 | ||
|
|
13c7b701b7 | ||
|
|
e0e049f537 | ||
|
|
de9acc04f6 | ||
|
|
6320fd9e52 | ||
|
|
755590409e | ||
|
|
11d9c9f2a5 | ||
|
|
39b3b91755 | ||
|
|
a82ba3827c | ||
|
|
0dc2a4d6e4 | ||
|
|
e15559aa3c | ||
|
|
5cffeebbaa | ||
|
|
bb29623852 | ||
|
|
b1713d284d | ||
|
|
f2473d0efe | ||
|
|
83545752cf | ||
|
|
87e8aeca40 | ||
|
|
7a8c751a8f | ||
|
|
47bd29840d | ||
|
|
4c9c080e07 | ||
|
|
677a06d5fd | ||
|
|
8892d6e748 | ||
|
|
c8ca2a2993 | ||
|
|
67905e0d59 | ||
|
|
f5f8443131 | ||
|
|
43b7b8cf69 | ||
|
|
721128e86d | ||
|
|
a25004545e | ||
|
|
9761650d1f | ||
|
|
e0304b58e3 | ||
|
|
812efa0f48 | ||
|
|
d81ec60d19 | ||
|
|
25d42d50a8 | ||
|
|
df765ac1c8 | ||
|
|
06985de900 | ||
|
|
9d3f8b7144 | ||
|
|
064c620fb0 | ||
|
|
f09fdc28fa | ||
|
|
b82172a98a | ||
|
|
ee1f91bf27 | ||
|
|
3840b20ac9 | ||
|
|
7eee377db5 | ||
|
|
a74c0f91ef | ||
|
|
fa7e9d6177 | ||
|
|
e6efb2b0bd | ||
|
|
5bdbd4b380 | ||
|
|
b39630bdb7 | ||
|
|
317919c7c6 | ||
|
|
150df6632d | ||
|
|
6ec06e777f | ||
|
|
8696e06602 | ||
|
|
fbad1c90a1 | ||
|
|
b8e4e502d3 | ||
|
|
9e300c8427 | ||
|
|
fa2c452669 | ||
|
|
e7ae85737b | ||
|
|
5806470df7 | ||
|
|
1f6db21f32 | ||
|
|
28f5d16b4f | ||
|
|
552c2479aa | ||
|
|
74a54dc297 | ||
|
|
2f15b18f93 | ||
|
|
58f5fa84f3 | ||
|
|
ce0bb59d12 | ||
|
|
91933eb69b | ||
|
|
6c796c3903 | ||
|
|
9263388a70 | ||
|
|
a5072db62a | ||
|
|
b8ef655fb7 | ||
|
|
fa42e6493d | ||
|
|
d41d4056ca | ||
|
|
03aee97527 | ||
|
|
84ad4dabe2 | ||
|
|
dc1acd03f8 | ||
|
|
2099052b83 | ||
|
|
30a9f48024 | ||
|
|
7bf5c85a05 | ||
|
|
ac4fc0b84d | ||
|
|
2f1a7a61fc | ||
|
|
2b83ef25c5 | ||
|
|
1655d99716 | ||
|
|
f9e8171a44 | ||
|
|
cd624d3a4f | ||
|
|
dd19ef9dd0 | ||
|
|
d91ed719e9 | ||
|
|
0153e94a50 | ||
|
|
2eca35b6d6 | ||
|
|
269930c0da | ||
|
|
27829d8063 | ||
|
|
5d910431cf | ||
|
|
c5ecb802fc | ||
|
|
1589a7a4f8 | ||
|
|
795ca3e5b8 | ||
|
|
b5ab48be2a | ||
|
|
961c946a6d | ||
|
|
257ef2ba58 | ||
|
|
8402493a28 | ||
|
|
04c89ae74c | ||
|
|
70c9968eaf | ||
|
|
5fe98688bb | ||
|
|
6371de51da | ||
|
|
6c15d652d4 | ||
|
|
c1a727359e | ||
|
|
abe3914e87 | ||
|
|
b28dfc0655 | ||
|
|
ec3c205f2d | ||
|
|
e33e89637c | ||
|
|
44206f5e75 | ||
|
|
7439f2e6c0 | ||
|
|
25f2335b7d | ||
|
|
a71f36113c | ||
|
|
ab05a11ef5 | ||
|
|
397f76ad31 | ||
|
|
710bb6996d | ||
|
|
7c913930fe | ||
|
|
8424428faf | ||
|
|
749e7c1bb4 | ||
|
|
d8d1435e15 | ||
|
|
0d2348d9c7 | ||
|
|
dea83b3f4c | ||
|
|
de37c802d7 | ||
|
|
875fa752a0 | ||
|
|
fb170684a0 | ||
|
|
9b90e8ee2c | ||
|
|
df18917b3c | ||
|
|
1736f166bc | ||
|
|
9f1da34243 | ||
|
|
45ee3251a4 | ||
|
|
9a193e5eb5 | ||
|
|
e6b6c6a9cf | ||
|
|
765d06119f | ||
|
|
fd36a66ccc | ||
|
|
31e6faf89f | ||
|
|
d0bed0c40a | ||
|
|
e81b9387b1 | ||
|
|
d9c3226ee2 | ||
|
|
19e1b15feb | ||
|
|
cf65de45b9 | ||
|
|
fee7b9e6a5 | ||
|
|
cb68f33cf3 | ||
|
|
576d347777 | ||
|
|
f34029a1ee | ||
|
|
e8cd263509 | ||
|
|
7c045c523b | ||
|
|
5c8de1dbd5 | ||
|
|
2565c99f8b | ||
|
|
758af97c3b | ||
|
|
1476903a5e | ||
|
|
3f03a60736 | ||
|
|
8784319622 | ||
|
|
e69ce84e34 | ||
|
|
a612e52245 | ||
|
|
5cdd74f2e9 | ||
|
|
f058895e26 | ||
|
|
a46d94071b | ||
|
|
0f29dc2f2d | ||
|
|
4183d3fe6c | ||
|
|
78512ae004 | ||
|
|
7567dd82cb | ||
|
|
61059614b7 | ||
|
|
0399f4cd61 | ||
|
|
5410a899ef | ||
|
|
a18deda24b | ||
|
|
2e95662387 | ||
|
|
ff8cfdb092 | ||
|
|
bfba809c79 | ||
|
|
0d3e8e743a | ||
|
|
4ca4476320 | ||
|
|
d43ba2a775 | ||
|
|
95d3ba14eb | ||
|
|
3cf3ab579e | ||
|
|
0bdf99c171 | ||
|
|
1a6f055682 | ||
|
|
016cf45775 | ||
|
|
4a6a800fd8 | ||
|
|
4dd99b7623 | ||
|
|
71d325549f | ||
|
|
75d6c8c9f6 | ||
|
|
a548e9cc40 | ||
|
|
9d4aaf49c1 | ||
|
|
e753457e7d | ||
|
|
8f8fbdc399 | ||
|
|
5c45d98645 | ||
|
|
a53d451f30 | ||
|
|
83b2c0d30a | ||
|
|
7af02225cc | ||
|
|
c0068bdd4f | ||
|
|
e16c478a25 | ||
|
|
bb6ddc2de7 | ||
|
|
a88c46c2d8 | ||
|
|
f924ff0059 | ||
|
|
fbc4a8894f | ||
|
|
8b0affe220 | ||
|
|
1993c0acc2 | ||
|
|
12a8b590e0 | ||
|
|
fb037af2b3 | ||
|
|
d43feea5fa | ||
|
|
df88dece8b | ||
|
|
537d817f8a | ||
|
|
9404455a07 | ||
|
|
da44380f86 | ||
|
|
bf235aa693 | ||
|
|
d534900b91 | ||
|
|
a2f6acada0 | ||
|
|
05434129e0 | ||
|
|
c34ef2dc3c | ||
|
|
c34356ba58 |
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
*.5
|
||||
*.8
|
||||
*.a
|
||||
*.d
|
||||
*.o
|
||||
*.pc
|
||||
*.pot
|
||||
*.so
|
||||
*.so.*
|
||||
*.swp
|
||||
*~
|
||||
|
||||
.export.sym
|
||||
.exported_symbols_generated
|
||||
.gdb_history
|
||||
|
||||
Makefile
|
||||
make.tmpl
|
||||
|
||||
configure.h
|
||||
version.h
|
||||
|
||||
/autom4te.cache/
|
||||
/config.log
|
||||
/config.status
|
||||
/cscope.out
|
||||
/tmp/
|
||||
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.
|
||||
|
||||
184
Makefile.in
Normal file
184
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@
|
||||
|
||||
SUBDIRS = doc include man
|
||||
|
||||
ifeq ("@UDEV_RULES@", "yes")
|
||||
SUBDIRS += udev
|
||||
endif
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
SUBDIRS += po
|
||||
endif
|
||||
|
||||
SUBDIRS += lib tools daemons libdm libdaemon
|
||||
|
||||
ifeq ("@APPLIB@", "yes")
|
||||
SUBDIRS += liblvm
|
||||
endif
|
||||
|
||||
ifeq ("@PYTHON_BINDINGS@", "yes")
|
||||
SUBDIRS += python
|
||||
endif
|
||||
|
||||
SUBDIRS += scripts
|
||||
|
||||
# FIXME Should use intermediate Makefiles here!
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS = doc include man test scripts \
|
||||
libdaemon lib tools daemons libdm \
|
||||
udev po liblvm python \
|
||||
unit-tests/datastruct unit-tests/mm unit-tests/regex
|
||||
tools.distclean: test.distclean
|
||||
endif
|
||||
DISTCLEAN_DIRS += lcov_reports*
|
||||
DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
|
||||
|
||||
include make.tmpl
|
||||
|
||||
libdm: include
|
||||
lib: libdm libdaemon
|
||||
liblvm: lib
|
||||
daemons: lib libdaemon tools
|
||||
tools: lib libdaemon device-mapper
|
||||
po: tools daemons
|
||||
scripts: liblvm libdm
|
||||
|
||||
lib.device-mapper: include.device-mapper
|
||||
libdm.device-mapper: include.device-mapper
|
||||
liblvm.device-mapper: include.device-mapper
|
||||
daemons.device-mapper: libdm.device-mapper
|
||||
tools.device-mapper: libdm.device-mapper
|
||||
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
|
||||
|
||||
ifeq ("@PYTHON_BINDINGS@", "yes")
|
||||
python: liblvm
|
||||
endif
|
||||
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
tools.cflow: libdm.cflow lib.cflow
|
||||
daemons.cflow: tools.cflow
|
||||
cflow: include.cflow
|
||||
endif
|
||||
|
||||
ifneq ("@CSCOPE_CMD@", "")
|
||||
cscope.out:
|
||||
@CSCOPE_CMD@ -b -R -s$(top_srcdir)
|
||||
all: cscope.out
|
||||
endif
|
||||
DISTCLEAN_TARGETS += cscope.out
|
||||
|
||||
check check_cluster check_local check_lvmetad unit: all
|
||||
$(MAKE) -C test $(@)
|
||||
|
||||
install_system_dirs:
|
||||
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
|
||||
$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
|
||||
|
||||
install_initscripts:
|
||||
$(MAKE) -C scripts install_initscripts
|
||||
|
||||
install_systemd_generators:
|
||||
$(MAKE) -C scripts install_systemd_generators
|
||||
|
||||
install_systemd_units:
|
||||
$(MAKE) -C scripts install_systemd_units
|
||||
|
||||
ifeq ("@PYTHON_BINDINGS@", "yes")
|
||||
install_python_bindings:
|
||||
$(MAKE) -C liblvm/python install_python_bindings
|
||||
endif
|
||||
|
||||
install_tmpfiles_configuration:
|
||||
$(MAKE) -C scripts install_tmpfiles_configuration
|
||||
|
||||
LCOV_TRACES = libdm.info lib.info tools.info \
|
||||
daemons/dmeventd.info daemons/clvmd.info
|
||||
CLEAN_TARGETS += $(LCOV_TRACES)
|
||||
|
||||
ifneq ("$(LCOV)", "")
|
||||
.PHONY: lcov-reset lcov lcov-dated $(LCOV_TRACES)
|
||||
|
||||
ifeq ($(MAKECMDGOALS),lcov-dated)
|
||||
LCOV_REPORTS_DIR := lcov_reports-$(shell date +%Y%m%d%k%M%S)
|
||||
lcov-dated: lcov
|
||||
else
|
||||
LCOV_REPORTS_DIR := lcov_reports
|
||||
endif
|
||||
|
||||
lcov-reset:
|
||||
$(LCOV) --zerocounters $(addprefix -d , $(basename $(LCOV_TRACES)))
|
||||
|
||||
# maybe use subdirs processing to create tracefiles...
|
||||
$(LCOV_TRACES):
|
||||
$(LCOV) -b $(basename $@) -d $(basename $@) \
|
||||
--ignore-errors source -c -o - | $(SED) \
|
||||
-e "s/\(dmeventd_lvm.[ch]\)/plugins\/lvm2\/\1/" \
|
||||
-e "s/dmeventd_\(mirror\|snapshot\|thin\|raid\)\.c/plugins\/\1\/dmeventd_\1\.c/" \
|
||||
>$@
|
||||
|
||||
ifneq ("$(GENHTML)", "")
|
||||
lcov: $(LCOV_TRACES)
|
||||
$(RM) -r $(LCOV_REPORTS_DIR)
|
||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||
for i in $(LCOV_TRACES); do \
|
||||
test -s $$i && lc="$$lc $$i"; \
|
||||
done; \
|
||||
test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
|
||||
-o $(LCOV_REPORTS_DIR) $$lc
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifeq ("$(TESTING)", "yes")
|
||||
# testing and report generation
|
||||
RUBY=ruby1.9 -Ireport-generators/lib -Ireport-generators/test
|
||||
|
||||
.PHONY: unit-test ruby-test test-programs
|
||||
|
||||
# FIXME: put dependencies on libdm and liblvm
|
||||
# FIXME: Should be handled by Makefiles in subdirs, not here at top level.
|
||||
test-programs:
|
||||
cd unit-tests/regex && $(MAKE)
|
||||
cd unit-tests/datastruct && $(MAKE)
|
||||
cd unit-tests/mm && $(MAKE)
|
||||
|
||||
unit-test: test-programs
|
||||
$(RUBY) report-generators/unit_test.rb $(shell find . -name TESTS)
|
||||
$(RUBY) report-generators/title_page.rb
|
||||
|
||||
memcheck: test-programs
|
||||
$(RUBY) report-generators/memcheck.rb $(shell find . -name TESTS)
|
||||
$(RUBY) report-generators/title_page.rb
|
||||
|
||||
ruby-test:
|
||||
$(RUBY) report-generators/test/ts.rb
|
||||
endif
|
||||
35
README
35
README
@@ -1,2 +1,33 @@
|
||||
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/
|
||||
|
||||
The source code is stored in git:
|
||||
http://git.fedorahosted.org/git/lvm2.git
|
||||
git clone git://git.fedorahosted.org/git/lvm2.git
|
||||
|
||||
Mailing list for general discussion related to LVM2:
|
||||
linux-lvm@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||
|
||||
Mailing lists for LVM2 development, patches and commits:
|
||||
lvm-devel@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||
|
||||
lvm2-commits@lists.fedorahosted.org (Read-only archive of commits)
|
||||
Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits
|
||||
|
||||
Mailing list for device-mapper development, including kernel patches
|
||||
and multipath-tools:
|
||||
dm-devel@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/dm-devel
|
||||
|
||||
The source code repository used until 7th June 2012 is accessible here:
|
||||
http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2.
|
||||
|
||||
|
||||
1
VERSION_DM
Normal file
1
VERSION_DM
Normal file
@@ -0,0 +1 @@
|
||||
1.02.78-git (2012-10-22)
|
||||
854
WHATS_NEW_DM
Normal file
854
WHATS_NEW_DM
Normal file
@@ -0,0 +1,854 @@
|
||||
Version 1.02.78 -
|
||||
===================================
|
||||
Add DM_TO_STRING public macro.
|
||||
Always return success on dmeventd -V command call.
|
||||
Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
|
||||
Add dm_get_status_snapshot() for parsing snapshot status.
|
||||
Detecte mounted fs also via reading /proc/self/mountinfo.
|
||||
Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
|
||||
Report error for nonexisting devices in dmeventd communication.
|
||||
Prevent double free error after dmeventd call of _fill_device_data().
|
||||
Update dmevent structure message_data to simplify/fix error path handling.
|
||||
Validate passed params to dm_get_status_raid/thin/thin_pool().
|
||||
Fix 'dmsetup splitname -o' to not fail if used without '-c' switch (1.02.68).
|
||||
Add dm_config_write_{node_out/one_node_out} for enhanced config output.
|
||||
Add dm_config_value_is_bool to check for boolean value in supported formats.
|
||||
Fix config node lookup inside empty sections to not return the section itself.
|
||||
Extend support for status info of thin pool target.
|
||||
Fix segfault for truncated string token in config file after the first '"'.
|
||||
Close open dmeventd FIFO file descriptors on exec (FD_CLOEXEC).
|
||||
Fix resource leak in error path of dmeventd's umount of thin volume.
|
||||
Automatically deactivate failed preloaded dm tree node.
|
||||
Add DM_DISABLE_UDEV environment variable to manage dev nodes by libdm only.
|
||||
Fix dm_task_set_cookie to properly process udev flags if udev_sync disabled.
|
||||
|
||||
Version 1.02.77 - 15th October 2012
|
||||
===================================
|
||||
Support unmount of thin volumes from pool above thin pool threshold.
|
||||
Update man page to reflect that dm UUIDs are being mangled as well.
|
||||
Apply 'dmsetup mangle' for dm UUIDs besides dm names.
|
||||
Add 'mangled_uuid' and 'unmangled_uuid' fields to dmsetup info -c -o.
|
||||
Mangle device UUID on dm_task_set_uuid/newuuid call if necessary.
|
||||
Add dm_task_get_uuid_mangled/unmangled to libdevmapper.
|
||||
Always reset delay_resume_if_new flag when stacking thin pool over anything.
|
||||
Don't create value for dm_config_node and require dm_config_create_value call.
|
||||
Check for existing new_name for dmsetup rename.
|
||||
Fix memory leak in dmsetup _get_split_name() error path.
|
||||
|
||||
Version 1.02.76 - 7th August 2012
|
||||
=================================
|
||||
Add dm_vasprintf to libdevmapper.
|
||||
Allow --noflush with dmsetup status and wait (for thin target).
|
||||
Add dm_config_write_one_node to libdevmapper.
|
||||
Support thin pool message release/reserve_metadata_snap in libdevmapper.
|
||||
Support thin pool discards and external origin features in libdevmapper.
|
||||
Add configure --enable-udev-rule-exec-detection to detect exec path in rules.
|
||||
Use sbindir in udev rules by default and remove executable path detection.
|
||||
Remove hard-coded paths for dmeventd fifos and use default-dm-run-dir.
|
||||
Add configure --with-lvmetad-pidfile to remove hard-coded value.
|
||||
Add configure --with-default-pid-dir for common directory with pid files.
|
||||
Add configure --with-default-dm-run-dir to set run directory for dm tools.
|
||||
Detect kernel_send() errors in cmirrord.
|
||||
Add __attribute__ instrumentation to libdevmapper.h.
|
||||
Print clean_bits instead of sync_bits in pull_state in cmirrord.
|
||||
Add tests for errors from closedir(), close() in cmirrord.
|
||||
Add documentation references in systemd units.
|
||||
Remove veritysetup. Now maintained with cryptsetup.
|
||||
|
||||
Version 1.02.75 - 8th June 2012
|
||||
===============================
|
||||
Upstream source repo now fedorahosted.org git not sources.redhat.com CVS.
|
||||
Remove unsupported udev_get_dev_path libudev call used for checking udev dir.
|
||||
Set delay_resume_if_new on deptree snapshot origin.
|
||||
Log value chosen in _find_config_bool like other variable types do.
|
||||
Wait for dmeventd to exit after sending it DM_EVENT_CMD_DIE when restarting.
|
||||
Append 'Used' to {Blk}DevNames/DevNos dmsetup report headers for clarity.
|
||||
Add configure --with-veritysetup for independent veritysetup tool.
|
||||
Properly support supplied dmevent path in dm_event_register_handler().
|
||||
Remove dmeventd fifos on exit if they are not managed by systemd.
|
||||
Use SD_ACTIVATION environment variable in systemd units to detect systemd.
|
||||
Only start a new dmeventd instance on restart if one was already running.
|
||||
Extend the time waited for input from dmeventd fifo to 5 secs. (1.02.73)
|
||||
|
||||
Version 1.02.74 - 6th March 2012
|
||||
================================
|
||||
Check for multiply-mangled names in auto mangling mode.
|
||||
Fix dm_task_get_name_unmangled to not unmangle already unmangled name.
|
||||
Check whether device names are properly mangled on ioctl return.
|
||||
Deactivation of failed thin check on thin pool returns success.
|
||||
|
||||
Version 1.02.73 - 3rd March 2012
|
||||
================================
|
||||
Test _thread_registry list with holding mutex in dmeventd.
|
||||
Add dm_tree_node_set_callback() for preload and deactivation hooks.
|
||||
Drop unsupported TRIM message for thin pool.
|
||||
Improve logging for fifo startup in dmeventd.
|
||||
Better detection of missing dmeventd fifo connection (1.02.71).
|
||||
Add a few pointer validations in dmsetup.
|
||||
Support dm_task_get_driver_version() query without version string.
|
||||
Log failure of pthread_join when cleaning unused threads in dmeventd.
|
||||
Fix empty string warning logic in _find_config_str. (1.02.68)
|
||||
Fix dm_task_set_name to properly resolve path to dm name (1.02.71).
|
||||
Add dm_strncpy() function as a faster strncpy() replacement.
|
||||
|
||||
Version 1.02.72 - 23rd February 2012
|
||||
====================================
|
||||
Avoid memory reallocation for dm_asprintf.
|
||||
|
||||
Version 1.02.71 - 20th February 2012
|
||||
====================================
|
||||
Switch to using built-in blkid in 13-dm-disk.rules.
|
||||
Add "watch" rule to 13-dm-disk.rules.
|
||||
Detect failing fifo and skip 20s retry communication period.
|
||||
Add DM_DEFAULT_NAME_MANGLING_MODE environment variable as an override.
|
||||
Add dm_lib_init to automatically initialise device-mapper library on load.
|
||||
Replace any '\' char with '\\' in dm table specification on input.
|
||||
Add mangle command to dmsetup to provide renaming to correct mangled form.
|
||||
Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o.
|
||||
Add --manglename option to dmsetup to select the name mangling mode.
|
||||
Add dm_task_get_name_mangled/unmangled to libdevmapper.
|
||||
Mangle device name on dm_task_set_name/newname call if necessary.
|
||||
Add dm_set/get_name_mangling_mode to set/get name mangling in libdevmapper.
|
||||
Add configure --with-default-name-mangling for udev-friendly dev name charset.
|
||||
Test for parsed words in _umount() dmeventd snapshot plugin.
|
||||
Fix memory leak in fail path of parse_loop_device_name() in dmsetup.
|
||||
Check for missing reply_uuid in dm_event_get_registered_device().
|
||||
Check for allocation failure in dmeventd restart().
|
||||
Add few missing allocation failures tests in dmsetup.
|
||||
Fix potential risk of writing in front of buffer in _sysfs_get_dm_name().
|
||||
|
||||
Version 1.02.70 - 12th February 2012
|
||||
====================================
|
||||
Fix dm_event_get_version() check.
|
||||
Add pointer test for dependency check in _add_dev().
|
||||
Validate name and uuid params of dm_tree_add_new_dev_with_udev_flags().
|
||||
Do not crash for dm_report_init() sort_key == NULL and behave like "".
|
||||
Return error for failing allocation in dm_asprintf().
|
||||
Add missing test for failing allocation in dm_realloc() code.
|
||||
Add test for memory allocation failures in regex matcher code.
|
||||
Simplify dm_task_set_geometry() and use dm_asprintf().
|
||||
Set all parameters to 0 for dm_get_next_target() for NULL return.
|
||||
Fix fd resource leak in error path for _udev_notify_sem_create().
|
||||
Leave space for '\0' for readline() call in _sysfs_get_kernel_name().
|
||||
|
||||
Version 1.02.69 - 1st February 2012
|
||||
===================================
|
||||
Clean up dmeventd systemd unit ordering and requirements.
|
||||
|
||||
Version 1.02.68 - 26th January 2012
|
||||
===================================
|
||||
Reset all members of info struct in dm_tree_add_new_dev_with_udev_flags.
|
||||
Add dmsetup wipe_table to replace table with one that uses error target.
|
||||
Add 'blkdevname' and 'blkdevs_used' fields to dmsetup info -c -o.
|
||||
Add 'blkdevname' option to dmsetup ls --tree to see block device names.
|
||||
Add -o devno/blkdevname/devname to dmsetup deps and ls.
|
||||
Add dm_device_get_name to get map name or block device name for given devno.
|
||||
Remove empty devices when clearing left-over inactive tables in deptree.
|
||||
Add dm_uuid_prefix/dm_set_uuid_prefix to override hard-coded LVM- prefix.
|
||||
Improve dmsetup man page description of readahead parameter.
|
||||
Use sysfs to set/get readahead if possible.
|
||||
Fix lvm2-monitor init script to use normalized output when using vgs.
|
||||
Add test for max length (DM_MAX_TYPE_NAME) of target type name.
|
||||
Include a copy of kernel DM documentation in doc/kernel.
|
||||
Improve man page style for dmsetup and mention more targets.
|
||||
Fix _get_proc_number to be tolerant of malformed /proc/misc entries.
|
||||
Fix missing thread list manipulation protection in dmeventd.
|
||||
Add ExecReload to dm-event.service for systemd to reload dmeventd properly.
|
||||
Add dm_config_tree_find_str_allow_empty and dm_config_find_str_allow_empty.
|
||||
Fix compile-time pool memory locking with DEBUG_MEM.
|
||||
Fix valgrind error reports in free of pool chunks with DEBUG_MEM.
|
||||
Align size of structure chunk for fast pool allocator to 8 bytes.
|
||||
Simplify some pointer operations in dm_free_aux() debug code.
|
||||
Remove unused dbg_malloc.h file from source tree.
|
||||
Cleanup backtraces for _create_and_load_v4().
|
||||
Fix alignment warning in bitcount calculation for raid segment.
|
||||
Allocate dm_tree structure from dm_tree pool.
|
||||
Update debug logging for _resume_node.
|
||||
Add functions to support thin provisioning target.
|
||||
Improve libdm-config error path reporting.
|
||||
Update dmsetup resume man with --addnodeonresume/create options.
|
||||
Add dependency for dm man pages to man subdirectory make all target.
|
||||
Add dm_tree_retry_remove to use retry logic for device removal in a dm_tree.
|
||||
Add dm_device_has_mounted_fs fn to check mounted filesystem on a device.
|
||||
Add dm_device_has_holders fn to to check use of the device by another device.
|
||||
Add dm_sysfs_dir to libdevmapper to retrieve sysfs location set.
|
||||
Add dm_set_sysfs_dir to libdevmapper to set sysfs location.
|
||||
Add --retry option for dmsetup remove to retry removal if not successful.
|
||||
Add dm_task_retry_remove fn to use retry logic for device removal.
|
||||
Remove unused passed parameters for _mirror_emit_segment_line().
|
||||
Add dm_config and string character escaping functions to libdevmapper.
|
||||
Mark unreleased memory pools as internal error.
|
||||
|
||||
Version 1.02.67 - 19th August 2011
|
||||
==================================
|
||||
Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked.
|
||||
|
||||
Version 1.02.66 - 12th August 2011
|
||||
==================================
|
||||
Release geometry buffer in dm_task_destroy.
|
||||
Update udev rules to skip DM flags decoding for removed devices.
|
||||
Add compile-time pool memory locking options (to debug shared VG structs).
|
||||
Remove device name prefix from dmsetup line output if -j & -m or -u supplied.
|
||||
Remove support for the original version 1 dm ioctls.
|
||||
Add missing check for allocation failure _create_dir_recursive().
|
||||
Add support for systemd file descriptor handover in dmeventd.
|
||||
Fix memory leak in dmsetup _message() memory allocation error path.
|
||||
Use new oom killer adjustment interface (oom_score_adj) when available.
|
||||
Add systemd unit files for dmeventd.
|
||||
Fix read-only identical table reload supression.
|
||||
|
||||
Version 1.02.65 - 8th July 2011
|
||||
===============================
|
||||
Remove dev name prefix from dmsetup line output if exactly one dev requested.
|
||||
Report internal error if suspending a device using an already-suspended dev.
|
||||
Report error if a table load requiring target parameters has none supplied.
|
||||
Add dmsetup --checks and dm_task_enable_checks framework to validate ioctls.
|
||||
Add age_in_minutes parameter to dmsetup udevcomplete_all.
|
||||
Return immediately from dm_lib_exit() if called more than once.
|
||||
Disable udev fallback by default and add --verifyudev option to dmsetup.
|
||||
Report internal error if any table is loaded while any dev is known suspended.
|
||||
Add dm_get_suspended_counter() for number of devs in suspended state by lib.
|
||||
Fix "all" report field prefix matching to include label fields with pv_all.
|
||||
Delay resuming new preloaded mirror devices with core logs in deptree code.
|
||||
Accept new kernel version 3 uname formats in initialisation.
|
||||
|
||||
Version 1.02.64 - 29th April 2011
|
||||
==================================
|
||||
Require libudev >= 143 when compiling with udev support.
|
||||
Use word alignment for dm_pool_strdup() and dm_pool_strndup().
|
||||
Use dm_snprintf() to fix signedness warning in dm_set_dev_dir().
|
||||
Use unsigned loop counter to fix signedness warning in _other_node_ops().
|
||||
Fix const cast in dmsetup calls of dm_report_field_string().
|
||||
Streamline /dev/mapper/control node code for common cases.
|
||||
Use hard-coded dm control node device number for 2.6.36 kernels and above.
|
||||
Improve stack debug reporting in dm_task_create().
|
||||
Fallback to control node creation only if node doesn't exist yet.
|
||||
Change dm_hash binary functions to take void *key instead of char *.
|
||||
Fix uninitialised memory use with empty params in _reload_with_suppression_v4.
|
||||
Lower severity of selabel_lookup and matchpathcon failure to log_debug.
|
||||
Add test for failed allocation from dm_task_set_uuid() in dmeventd.
|
||||
Add dm_event_get_version to dmeventd for use with -R.
|
||||
Avoid dmeventd core dumps when handling request with unknown command ID.
|
||||
Have dmeventd -R start up even when no existing copy is running.
|
||||
Accept multiple mapped device names on many dmsetup command lines.
|
||||
Fix dm_udev_wait calls in dmsetup to occur before readahead display not after.
|
||||
Include an implicit dm_task_update_nodes() within dm_udev_wait().
|
||||
Fix _create_and_load_v4 not to lose the --addnodeoncreate setting (1.02.62).
|
||||
Add inactive table query support for kernel driver >= 4.11.6 (RHEL 5.7).
|
||||
Log debug open_count in _node_has_closed_parents().
|
||||
Add a const to dm_report_field_string() data parameter.
|
||||
|
||||
Version 1.02.63 - 9th February 2011
|
||||
===================================
|
||||
Reinstate DEBUG_MEM as it's part of the API. (1.02.62)
|
||||
|
||||
Version 1.02.62 - 4th February 2011
|
||||
===================================
|
||||
Add configure --with-device-nodes-on=create for previous behaviour.
|
||||
Move creation of device nodes from 'create' to 'resume'.
|
||||
Add --addnodeonresume and --addnodeoncreate options to dmsetup.
|
||||
Add dm_task_set_add_node to libdevmapper to control dev node creation time.
|
||||
Add dm_task_secure_data to libdevmapper to wipe ioctl buffers in kernel.
|
||||
Log debug message when expected uevent is not generated.
|
||||
Only compile memory debugging code when DEBUG_MEM is set.
|
||||
Set DM_UDEV_DISABLE_OTHER_RULES_FLAG for suspended DM devices in udev rules.
|
||||
Begin a new pool object for each row in _output_as_rows() correctly.
|
||||
|
||||
Version 1.02.61 - 10th January 2011
|
||||
===================================
|
||||
Add DM_COOKIE_AUTO_CREATE to libdevmapper.h.
|
||||
Export DM_CONTROL_NODE_UMASK and use it while creating /dev/mapper/control.
|
||||
|
||||
Version 1.02.60 - 20th December 2010
|
||||
====================================
|
||||
Check for unlink failure in remove_lockfile() in dmeventd.
|
||||
Use dm_free for dm_malloc-ed areas in _clog_ctr/_clog_dtr in cmirrord.
|
||||
Use char* arithmetic in _process_all() & _targets() in dmsetup.
|
||||
Change dm_regex_create() API to accept const char * const *patterns.
|
||||
Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
|
||||
Detect existence of new SELinux selabel interface during configure.
|
||||
|
||||
Version 1.02.59 - 6th December 2010
|
||||
===================================
|
||||
Add backtraces to _process_mapper_dir and _create_and_load_v4 error paths.
|
||||
Remove superfluous checks for NULL before calling dm_free.
|
||||
|
||||
Version 1.02.58 - 22nd November 2010
|
||||
====================================
|
||||
Fix _output_field crash from field_id free with DEBUG_MEM. (1.02.57)
|
||||
|
||||
Version 1.02.57 - 8th November 2010
|
||||
===================================
|
||||
Fix regex optimiser not to ignore RHS of OR nodes in _find_leftmost_common.
|
||||
Add dmeventd -R to restart dmeventd without losing monitoring state. (1.02.56)
|
||||
Fix memory leak of field_id in _output_field function.
|
||||
Allocate buffer for reporting functions dynamically to support long outputs.
|
||||
|
||||
Version 1.02.56 - 25th October 2010
|
||||
===================================
|
||||
Return const pointer from dm_basename() in libdevmapper.
|
||||
Implement dmeventd -R to restart without state loss.
|
||||
Add dm_zalloc and use it and dm_pool_zalloc throughout.
|
||||
Add --setuuid to dmsetup rename.
|
||||
Add dm_task_set_newuuid to set uuid of mapped device post-creation.
|
||||
|
||||
Version 1.02.55 - 24th September 2010
|
||||
=====================================
|
||||
Fix the way regions are marked complete to avoid slow --nosync cmirror I/O.
|
||||
Add DM_REPORT_FIELD_TYPE_ID_LEN to libdevmapper.h.
|
||||
|
||||
Version 1.02.54 - 18th August 2010
|
||||
==================================
|
||||
Fix dm-mod autoloading logic to not assume control node is set correctly.
|
||||
Add dmeventd/executable to lvm.conf to test alternative dmeventd.
|
||||
Export dm_event_handler_set_dmeventd_path to override built-in dmeventd path.
|
||||
Generate libdevmapper-event exported symbols.
|
||||
Remove superfluous NULL pointer tests before dm_free from dmeventd.
|
||||
Assume dm-mod autoloading support is in kernel 2.6.36 and higher, not 2.6.35.
|
||||
Fix udev rules to support udev database content generated by older rules.
|
||||
Reinstate detection of inappropriate uevent with DISK_RO set and suppress it.
|
||||
Fix regex ttree off-by-one error.
|
||||
Add --enable-valgrind-pool to configure.
|
||||
Fix segfault in regex matcher with characters of ordinal value > 127.
|
||||
Fix 'void*' arithmetic warnings in dbg_malloc.c and libdm-iface.c.
|
||||
Wait for node creation before displaying debug info in dmsetup.
|
||||
Fix return status 0 for "dmsetup info -c -o help".
|
||||
Add check for kernel semaphore support and disable udev_sync if not available.
|
||||
|
||||
Version 1.02.53 - 28th July 2010
|
||||
================================
|
||||
Revert failed table load preparation after "create, load and resume".
|
||||
Switch dmeventd to use dm_create_lockfile and drop duplicate code.
|
||||
Add dm_create_lockfile to libdm to handle pidfiles for all daemons.
|
||||
Replace lookup with next in struct dfa_state & calculate states on demand.
|
||||
Improve the regex matcher, reducing the number of charset nodes used.
|
||||
Add dm_regex_fingerprint to facilitate regex testing.
|
||||
Skip ffs(0) in _test_word in bitset functions.
|
||||
Use "nowatch" udev rule for inappropriate devices.
|
||||
|
||||
Version 1.02.52 - 6th July 2010
|
||||
===============================
|
||||
Fix dmlosetup snprintf %llu compiler warning.
|
||||
Add parentheses to some libdevmapper.h macro arguments.
|
||||
Add printf format attributes to dm_{sn,as}printf and fix a caller.
|
||||
Move dmeventd man page from install_lvm2 to install_device-mapper. (1.02.50)
|
||||
|
||||
Version 1.02.51 - 30th June 2010
|
||||
================================
|
||||
Generate libdevmapper exported symbols from header file.
|
||||
|
||||
Version 1.02.50 - 23rd June 2010
|
||||
================================
|
||||
Fix INTERNAL_ERROR typo in ioctl iface unknown task message.
|
||||
Fix udev rules to handle spurious events properly.
|
||||
Use C99 [] not [0] in dm_ulog_request struct to avoid abort when fortified.
|
||||
Allow use of devmapper header file in C++ mode (extern "C" and __typeof__).
|
||||
Add dmeventd man page.
|
||||
|
||||
Version 1.02.49 - 4th June 2010
|
||||
===============================
|
||||
Support autoloading of dm-mod module for kernels from 2.6.35.
|
||||
Document 'clear' in dmsetup man page.
|
||||
Fix semctl parameter (union) to avoid misaligned parameter on some arches.
|
||||
Add dm_tree_node_set_presuspend_node() to presuspend child when deactivating.
|
||||
Initial support for replicator target.
|
||||
|
||||
Version 1.02.48 - 17th May 2010
|
||||
================================
|
||||
Use -d to control level of messages sent to syslog by dmeventd.
|
||||
Change -d to -f to run dmeventd in foreground.
|
||||
Do not print encryption key in message debug output (cryptsetup luksResume).
|
||||
Fix dmeventd static build library dependencies.
|
||||
Fix udev flags on remove in create_and_load error path.
|
||||
|
||||
Version 1.02.47 - 30th April 2010
|
||||
=================================
|
||||
Add support for new IMPORT{db} udev rule.
|
||||
Add DM_UDEV_PRIMARY_SOURCE_FLAG udev flag to recognize proper DM events.
|
||||
Also include udev libs in libdevmapper.pc when udev_sync is enabled.
|
||||
Cache bitset locations to speed up _calc_states.
|
||||
Add a regex optimisation pass for shared prefixes and suffixes.
|
||||
Add dm_bit_and and dm_bitset_equal to libdevmapper.
|
||||
Simplify dm_bitset_create.
|
||||
Speed up dm_bit_get_next with ffs().
|
||||
|
||||
Version 1.02.46 - 14th April 2010
|
||||
=================================
|
||||
Change dm_tree_deactivate_children to fail if device is open.
|
||||
Wipe memory buffers for dm-ioctl parameters before releasing.
|
||||
Strictly require libudev if udev_sync is used.
|
||||
Add support for ioctl's DM_UEVENT_GENERATED_FLAG.
|
||||
|
||||
Version 1.02.45 - 9th March 2010
|
||||
================================
|
||||
Add --showkeys parameter description to dmsetup man page.
|
||||
Add --help option as synonym for help command.
|
||||
|
||||
Version 1.02.44 - 15th February 2010
|
||||
====================================
|
||||
Add DM_UDEV_DISABLE_LIBRARY_FALLBACK udev flag to rely on udev only.
|
||||
Export dm_udev_create_cookie function to create new cookies on demand.
|
||||
Add --udevcookie, udevcreatecookie and udevreleasecookie to dmsetup.
|
||||
Set udev state automatically instead of using DM_UDEV_DISABLE_CHECKING.
|
||||
|
||||
Version 1.02.43 - 21st January 2010
|
||||
===================================
|
||||
Remove bitset, hash and pool headers superceded by libdevmapper.h.
|
||||
Fix off-by-one error causing bad cluster mirror table construction.
|
||||
|
||||
Version 1.02.42 - 14th January 2010
|
||||
===================================
|
||||
Add support for the "snapshot-merge" kernel target (2.6.33-rc1).
|
||||
Introduce a third activation_priority level in dm_tree_activate_children.
|
||||
|
||||
Version 1.02.41 - 12th January 2010
|
||||
===================================
|
||||
If DM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings.
|
||||
Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags.
|
||||
Add --noudevrules option for dmsetup to disable /dev node management by udev.
|
||||
Fix 'dmsetup info -c -o all' to show all fields.
|
||||
Return errors if dm_tree_*_children functions fail.
|
||||
Fix coredump and memory leak for 'dmsetup help -c'.
|
||||
Disable udev rules for change events with DISK_RO set.
|
||||
|
||||
Version 1.02.40 - 19th November 2009
|
||||
====================================
|
||||
Fix install_device-mapper Makefile target to not build dmeventd plugins.
|
||||
Support udev flags even when udev_sync is disabled or not compiled in.
|
||||
Remove 'last_rule' from udev rules: honour DM_UDEV_DISABLE_OTHER_RULES_FLAG.
|
||||
Add dmsetup --inactive support.
|
||||
Add dm_task_query_inactive_table to libdevmapper for kernel driver >= 4.16.
|
||||
Fix hash lookup segfault when keys compared are different lengths.
|
||||
|
||||
Version 1.02.39 - 26th October 2009
|
||||
===================================
|
||||
Remove strict default permissions for DM devices from 95-dm-notify.rules.
|
||||
Add dmsetup udevflags command to decode udev flags in given cookie value.
|
||||
Support udev flags in libdevmapper incl. dm_tree_add_new_dev_with_udev_flags.
|
||||
Make libdm ABI consistent when built with/without selinux support.
|
||||
|
||||
Version 1.02.38 - 25th September 2009
|
||||
=====================================
|
||||
Export DM_DEV_DIR_UMASK, the default umask for /dev directories created.
|
||||
Handle any path supplied to dm_task_set_name by looking up in /dev/mapper.
|
||||
Add several examples to 12-dm-permissions.rules.
|
||||
Add splitname and --yes to dmsetup man page.
|
||||
Fix _mirror_emit_segment_line return code.
|
||||
Fix dmeventd _temporary_log_fn parameters. (2.02.50)
|
||||
|
||||
Version 1.02.37 - 15th September 2009
|
||||
=====================================
|
||||
Add dmsetup manpage entries for udevcomplete_all and udevcookies.
|
||||
Check udev is running when processing cookies and retain state internally.
|
||||
Add y|--yes option to dmsetup for default 'yes' answer to prompts.
|
||||
Fix tools Makefile to process dmsetup sources separately.
|
||||
Restore umask when device node creation fails.
|
||||
Check kernel vsn to use 'block_on_error' or 'handle_errors' in mirror table.
|
||||
Add dm-log-userspace.h to tree for cmirrord builds.
|
||||
|
||||
Version 1.02.36 - 6th August 2009
|
||||
=================================
|
||||
Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
|
||||
Add libdevmapper functions to support synchronisation with udev.
|
||||
|
||||
Version 1.02.35 - 28th July 2009
|
||||
================================
|
||||
Add LOG_LINE_WITH_ERRNO macro.
|
||||
Use log_error macro consistently throughout in place of log_err.
|
||||
|
||||
Version 1.02.34 - 15th July 2009
|
||||
================================
|
||||
Use _exit() not exit() after forking to avoid flushing libc buffers twice.
|
||||
Rename plog macro to LOG_LINE & add LOG_MESG variant for dm_dump_memory_debug.
|
||||
Change plog to use dm_log_with_errno unless deprecated dm_log_init was used.
|
||||
Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns.
|
||||
Fix whitespace in linear target line to fix identical table line detection.
|
||||
Add device number to more log messages during activation.
|
||||
|
||||
Version 1.02.33 - 30th June 2009
|
||||
================================
|
||||
Don't fallback to default major number: use dm_task_set_major_minor. (1.02.31)
|
||||
Do not fork daemon when dmeventd cannot be found.
|
||||
Add crypt target handling to libdevmapper tree nodes.
|
||||
Add splitname command to dmsetup.
|
||||
Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports.
|
||||
Make mempool optional in dm_split_lvm_name().
|
||||
|
||||
Version 1.02.32 - 21st May 2009
|
||||
===============================
|
||||
Only generate libdevmapper.a when configured to link statically.
|
||||
Export dm_tree_node_size_changed() from libdevmapper.
|
||||
Propagate the table size_changed property up the dm device tree.
|
||||
Detect failure to free memory pools when releasing the library.
|
||||
Fix segfault when getopt processes dmsetup -U, -G and -M options.
|
||||
|
||||
Version 1.02.31 - 3rd March 2009
|
||||
================================
|
||||
If kernel supports only one dm major number, use in place of any supplied.
|
||||
|
||||
Version 1.02.30 - 26th January 2009
|
||||
====================================
|
||||
Add "all" field to reports expanding to all fields of report type.
|
||||
Enforce device name length and character limitations in libdm.
|
||||
Replace _dm_snprintf with EMIT_PARAMS macro for creating target lines.
|
||||
|
||||
Version 1.02.29 - 10th November 2008
|
||||
====================================
|
||||
Merge device-mapper into the LVM2 tree.
|
||||
Split out dm-logging.h from log.h.
|
||||
Use lvm-types.h.
|
||||
Add usrsbindir to configure.
|
||||
|
||||
Version 1.02.28 - 18th September 2008
|
||||
=====================================
|
||||
Only resume devices in dm_tree_preload_children if size changes.
|
||||
Extend deptree buffers so the largest possible device numbers fit.
|
||||
Generate versioned libdevmapper-event.so.
|
||||
Underline longer report help text headings.
|
||||
|
||||
Version 1.02.27 - 25th June 2008
|
||||
================================
|
||||
Align struct memblock in dbg_malloc for sparc.
|
||||
Add --unquoted and --rows to dmsetup.
|
||||
Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro.
|
||||
Fix inverted no_flush debug message.
|
||||
Remove --enable-jobs from configure. (Set at runtime instead.)
|
||||
Bring configure.in and list.h into line with the lvm2 versions.
|
||||
|
||||
Version 1.02.26 - 6th June 2008
|
||||
===============================
|
||||
Initialise params buffer to empty string in _emit_segment.
|
||||
Skip add_dev_node when ioctls disabled.
|
||||
Make dm_hash_iter safe against deletion.
|
||||
Accept a NULL pointer to dm_free silently.
|
||||
Add tables_loaded, readonly and suspended columns to reports.
|
||||
Add --nameprefixes to dmsetup.
|
||||
Add field name prefix option to reporting functions.
|
||||
Calculate string size within dm_pool_grow_object.
|
||||
|
||||
Version 1.02.25 - 10th April 2008
|
||||
=================================
|
||||
Remove redundant if-before-free tests.
|
||||
Use log_warn for reporting field help text instead of log_print.
|
||||
Change cluster mirror log type name (s/clustered_/clustered-/)
|
||||
|
||||
Version 1.02.24 - 20th December 2007
|
||||
====================================
|
||||
Fix deptree to pass new name to _resume_node after a rename.
|
||||
Suppress other node operations if node is deleted.
|
||||
Add node operation stack debug messages.
|
||||
Report error when empty device name passed to readahead functions.
|
||||
Fix minimum readahead debug message.
|
||||
|
||||
Version 1.02.23 - 5th December 2007
|
||||
===================================
|
||||
Update dm-ioctl.h after removal of compat code.
|
||||
Add readahead support to libdevmapper and dmsetup.
|
||||
Fix double free in a libdevmapper-event error path.
|
||||
Fix configure --with-dmeventd-path substitution.
|
||||
Allow a DM_DEV_DIR environment variable to override /dev in dmsetup.
|
||||
Create a libdevmapper.so.$LIB_VERSION symlink within the build tree.
|
||||
Avoid static link failure with some SELinux libraries that require libpthread.
|
||||
Remove obsolete dmfs code from tree and update INSTALL.
|
||||
|
||||
Version 1.02.22 - 21st August 2007
|
||||
==================================
|
||||
Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
|
||||
Update to use autoconf 2.61, while still supporting 2.57.
|
||||
Avoid repeated dm_task free on some dm_event_get_registered_device errors.
|
||||
Introduce log_sys_* macros from LVM2.
|
||||
Export dm_fclose and dm_create_dir; remove libdm-file.h.
|
||||
Don't log EROFS mkdir failures in _create_dir_recursive (for LVM2).
|
||||
Add fclose wrapper dm_fclose that catches write failures (using ferror).
|
||||
|
||||
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
|
||||
|
||||
1443
autoconf/config.guess
vendored
1443
autoconf/config.guess
vendored
File diff suppressed because it is too large
Load Diff
745
autoconf/config.sub
vendored
745
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
|
||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
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.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
-c) shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
shift
|
||||
shift
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
-t) dstarg=$2
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
-T) no_target_directory=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
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
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[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
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
# 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 [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
if test -z "$dstarg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
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
|
||||
dst=$dstarg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst ;;
|
||||
esac
|
||||
|
||||
if [ -d $dst ]
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dstarg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
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
|
||||
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
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
# 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.
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
case $dstdir in
|
||||
/*) prefix=/ ;;
|
||||
-*) prefix=./ ;;
|
||||
*) prefix= ;;
|
||||
esac
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
case $posix_glob in
|
||||
'')
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=true
|
||||
else
|
||||
posix_glob=false
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob && set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob && set +f
|
||||
IFS=$oIFS
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
{ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
|
||||
|| {
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
if test -f "$dst"; then
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null \
|
||||
|| { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
|
||||
&& { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
} || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
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 we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
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 rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
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:
|
||||
|
||||
1685
configure.in
Normal file
1685
configure.in
Normal file
File diff suppressed because it is too large
Load Diff
47
daemons/Makefile.in
Normal file
47
daemons/Makefile.in
Normal file
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
ifeq ("@BUILD_LVMETAD@", "yes")
|
||||
SUBDIRS += lvmetad
|
||||
endif
|
||||
|
||||
.PHONY: dmeventd clvmd cmirrord lvmetad
|
||||
|
||||
ifneq ("@CLVMD@", "none")
|
||||
SUBDIRS += clvmd
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_CMIRRORD@", "yes")
|
||||
SUBDIRS += cmirrord
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
SUBDIRS += dmeventd
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
daemons.cflow: dmeventd.cflow
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS = clvmd cmirrord dmeventd lvmetad
|
||||
endif
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
device-mapper: dmeventd.device-mapper
|
||||
endif
|
||||
107
daemons/clvmd/Makefile.in
Normal file
107
daemons/clvmd/Makefile.in
Normal file
@@ -0,0 +1,107 @@
|
||||
#
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
CMAN_LIBS = @CMAN_LIBS@
|
||||
CMAN_CFLAGS = @CMAN_CFLAGS@
|
||||
CMAP_LIBS = @CMAP_LIBS@
|
||||
CMAP_CFLAGS = @CMAP_CFLAGS@
|
||||
CONFDB_LIBS = @CONFDB_LIBS@
|
||||
CONFDB_CFLAGS = @CONFDB_CFLAGS@
|
||||
CPG_LIBS = @CPG_LIBS@
|
||||
CPG_CFLAGS = @CPG_CFLAGS@
|
||||
DLM_LIBS = @DLM_LIBS@
|
||||
DLM_CFLAGS = @DLM_CFLAGS@
|
||||
QUORUM_LIBS = @QUORUM_LIBS@
|
||||
QUORUM_CFLAGS = @QUORUM_CFLAGS@
|
||||
SALCK_LIBS = @SALCK_LIBS@
|
||||
SALCK_CFLAGS = @SALCK_CFLAGS@
|
||||
|
||||
SOURCES = \
|
||||
clvmd-command.c \
|
||||
clvmd.c \
|
||||
lvm-functions.c \
|
||||
refresh_clvmd.c
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
DEFS += -DDEBUG
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring cman,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-cman.c
|
||||
LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
|
||||
CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS)
|
||||
DEFS += -DUSE_CMAN
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring openais,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-openais.c
|
||||
LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS)
|
||||
CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS)
|
||||
DEFS += -DUSE_OPENAIS
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring corosync,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-corosync.c
|
||||
LMLIBS += $(CMAP_LIBS) $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS)
|
||||
CFLAGS += $(CMAP_CFLAGS) $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(DLM_CFLAGS) $(QUORUM_CFLAGS)
|
||||
DEFS += -DUSE_COROSYNC
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring singlenode,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-singlenode.c
|
||||
DEFS += -DUSE_SINGLENODE
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SOURCES += clvmd-cman.c
|
||||
SOURCES += clvmd-openais.c
|
||||
SOURCES += clvmd-corosync.c
|
||||
SOURCES += clvmd-singlenode.c
|
||||
endif
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
LVMLIBS = $(LVMINTERNAL_LIBS)
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
LVMLIBS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LVMLIBS += -ldevmapper
|
||||
LIBS += $(PTHREAD_LIBS)
|
||||
|
||||
DEFS += -D_REENTRANT
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \
|
||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
.PHONY: install_clvmd
|
||||
|
||||
install_clvmd: $(TARGETS)
|
||||
$(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd
|
||||
|
||||
install: $(INSTALL_TARGETS)
|
||||
|
||||
install_cluster: $(INSTALL_TARGETS)
|
||||
82
daemons/clvmd/clvm.h
Normal file
82
daemons/clvmd/clvm.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Definitions for CLVMD server and clients */
|
||||
|
||||
/*
|
||||
* The protocol spoken over the cluster and across the local socket.
|
||||
*/
|
||||
|
||||
#ifndef _CLVM_H
|
||||
#define _CLVM_H
|
||||
|
||||
#include "configure.h"
|
||||
|
||||
struct clvm_header {
|
||||
uint8_t cmd; /* See below */
|
||||
uint8_t flags; /* See below */
|
||||
uint16_t xid; /* Transaction ID */
|
||||
uint32_t clientid; /* Only used in Daemon->Daemon comms */
|
||||
int32_t status; /* For replies, whether request succeeded */
|
||||
uint32_t arglen; /* Length of argument below.
|
||||
If >1500 then it will be passed
|
||||
around the cluster in the system LV */
|
||||
char node[1]; /* Actually a NUL-terminated string, node name.
|
||||
If this is empty then the command is
|
||||
forwarded to all cluster nodes unless
|
||||
FLAG_LOCAL or FLAG_REMOTE is also set. */
|
||||
char args[1]; /* Arguments for the command follow the
|
||||
node name, This member is only
|
||||
valid if the node name is empty */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Flags */
|
||||
#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
|
||||
#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
|
||||
#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */
|
||||
#define CLVMD_FLAG_REMOTE 8 /* Do this on all nodes except for the local node */
|
||||
|
||||
/* Name of the local socket to communicate between lvm and clvmd */
|
||||
static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock";
|
||||
|
||||
/* Internal commands & replies */
|
||||
#define CLVMD_CMD_REPLY 1
|
||||
#define CLVMD_CMD_VERSION 2 /* Send version around cluster when we start */
|
||||
#define CLVMD_CMD_GOAWAY 3 /* Die if received this - we are running
|
||||
an incompatible version */
|
||||
#define CLVMD_CMD_TEST 4 /* Just for mucking about */
|
||||
|
||||
#define CLVMD_CMD_LOCK 30
|
||||
#define CLVMD_CMD_UNLOCK 31
|
||||
|
||||
/* Lock/Unlock commands */
|
||||
#define CLVMD_CMD_LOCK_LV 50
|
||||
#define CLVMD_CMD_LOCK_VG 51
|
||||
#define CLVMD_CMD_LOCK_QUERY 52
|
||||
|
||||
/* Misc functions */
|
||||
#define CLVMD_CMD_REFRESH 40
|
||||
#define CLVMD_CMD_GET_CLUSTERNAME 41
|
||||
#define CLVMD_CMD_SET_DEBUG 42
|
||||
#define CLVMD_CMD_VG_BACKUP 43
|
||||
#define CLVMD_CMD_RESTART 44
|
||||
#define CLVMD_CMD_SYNC_NAMES 45
|
||||
|
||||
/* Used internally by some callers, but not part of the protocol.*/
|
||||
#define NODE_ALL "*"
|
||||
#define NODE_LOCAL "."
|
||||
#define NODE_REMOTE "^"
|
||||
|
||||
#endif
|
||||
506
daemons/clvmd/clvmd-cman.c
Normal file
506
daemons/clvmd/clvmd-cman.c
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* CMAN communication layer for clvmd.
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
#include <libdlm.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
struct clvmd_node
|
||||
{
|
||||
struct cman_node *node;
|
||||
int clvmd_up;
|
||||
};
|
||||
|
||||
static int num_nodes;
|
||||
static struct cman_node *nodes = NULL;
|
||||
static struct cman_node this_node;
|
||||
static int count_nodes; /* size of allocated nodes array */
|
||||
static struct dm_hash_table *node_updown_hash;
|
||||
static dlm_lshandle_t *lockspace;
|
||||
static cman_handle_t c_handle;
|
||||
|
||||
static void count_clvmds_running(void);
|
||||
static void get_members(void);
|
||||
static int nodeid_from_csid(const char *csid);
|
||||
static int name_from_nodeid(int nodeid, char *name);
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
|
||||
static void data_callback(cman_handle_t handle, void *private,
|
||||
char *buf, int len, uint8_t port, int nodeid);
|
||||
|
||||
struct lock_wait {
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
struct dlm_lksb lksb;
|
||||
};
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
node_updown_hash = dm_hash_create(100);
|
||||
|
||||
/* Open the cluster communication socket */
|
||||
c_handle = cman_init(NULL);
|
||||
if (!c_handle) {
|
||||
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
|
||||
return -1;
|
||||
}
|
||||
DEBUGLOG("Connected to CMAN\n");
|
||||
|
||||
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
|
||||
syslog(LOG_ERR, "Can't bind cluster socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cman_start_notification(c_handle, event_callback)) {
|
||||
syslog(LOG_ERR, "Can't start cluster event listening");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the cluster members list */
|
||||
get_members();
|
||||
count_clvmds_running();
|
||||
|
||||
DEBUGLOG("CMAN initialisation complete\n");
|
||||
|
||||
/* Create a lockspace for LV & VG locks to live in */
|
||||
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
|
||||
if (!lockspace) {
|
||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
||||
if (!lockspace) {
|
||||
syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
|
||||
return -1;
|
||||
}
|
||||
DEBUGLOG("Created DLM lockspace for CLVMD.\n");
|
||||
} else
|
||||
DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
|
||||
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
DEBUGLOG("DLM initialisation complete\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_init_completed(void)
|
||||
{
|
||||
clvmd_cluster_init_completed();
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd()
|
||||
{
|
||||
return cman_get_fd(c_handle);
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
int i;
|
||||
int nnodes = 0;
|
||||
|
||||
/* return number of ACTIVE nodes */
|
||||
for (i=0; i<num_nodes; i++) {
|
||||
if (nodes[i].cn_member && nodes[i].cn_nodeid)
|
||||
nnodes++;
|
||||
}
|
||||
return nnodes;
|
||||
}
|
||||
|
||||
/* send_message with the fd check removed */
|
||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
||||
const char *errtext)
|
||||
{
|
||||
int nodeid = 0;
|
||||
|
||||
if (csid)
|
||||
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
|
||||
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
|
||||
{
|
||||
log_error("%s", errtext);
|
||||
}
|
||||
return msglen;
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
if (this_node.cn_nodeid == 0) {
|
||||
cman_get_node(c_handle, 0, &this_node);
|
||||
}
|
||||
memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
|
||||
static int _cluster_do_node_callback(struct local_client *client,
|
||||
void (*callback) (struct local_client *,
|
||||
const char *,
|
||||
int))
|
||||
{
|
||||
int i;
|
||||
int somedown = 0;
|
||||
|
||||
for (i = 0; i < _get_num_nodes(); i++) {
|
||||
if (nodes[i].cn_member && nodes[i].cn_nodeid) {
|
||||
int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
|
||||
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, up);
|
||||
if (!up)
|
||||
somedown = -1;
|
||||
}
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Process OOB messages from the cluster socket */
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
|
||||
{
|
||||
char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
|
||||
switch (reason) {
|
||||
case CMAN_REASON_PORTCLOSED:
|
||||
name_from_nodeid(arg, namebuf);
|
||||
log_notice("clvmd on node %s has died\n", namebuf);
|
||||
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
|
||||
|
||||
dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
|
||||
break;
|
||||
|
||||
case CMAN_REASON_STATECHANGE:
|
||||
DEBUGLOG("Got state change message, re-reading members list\n");
|
||||
get_members();
|
||||
break;
|
||||
|
||||
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
|
||||
case CMAN_REASON_PORTOPENED:
|
||||
/* Ignore this, wait for startup message from clvmd itself */
|
||||
break;
|
||||
|
||||
case CMAN_REASON_TRY_SHUTDOWN:
|
||||
DEBUGLOG("Got try shutdown, sending OK\n");
|
||||
cman_replyto_shutdown(c_handle, 1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* ERROR */
|
||||
DEBUGLOG("Got unknown event callback message: %d\n", reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct local_client *cman_client;
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
|
||||
/* Save this for data_callback */
|
||||
cman_client = fd;
|
||||
|
||||
/* We never return a new client */
|
||||
*new_client = NULL;
|
||||
|
||||
return cman_dispatch(c_handle, 0);
|
||||
}
|
||||
|
||||
|
||||
static void data_callback(cman_handle_t handle, void *private,
|
||||
char *buf, int len, uint8_t port, int nodeid)
|
||||
{
|
||||
/* Ignore looped back messages */
|
||||
if (nodeid == this_node.cn_nodeid)
|
||||
return;
|
||||
process_message(cman_client, buf, len, (char *)&nodeid);
|
||||
}
|
||||
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
/* It's up ! */
|
||||
int nodeid = nodeid_from_csid(csid);
|
||||
|
||||
dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
|
||||
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
||||
}
|
||||
|
||||
static void _cluster_closedown()
|
||||
{
|
||||
destroy_lvhash();
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
cman_finish(c_handle);
|
||||
}
|
||||
|
||||
static int is_listening(int nodeid)
|
||||
{
|
||||
int status;
|
||||
|
||||
do {
|
||||
status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
|
||||
if (status < 0 && errno == EBUSY) { /* Don't busywait */
|
||||
sleep(1);
|
||||
errno = EBUSY; /* In case sleep trashes it */
|
||||
}
|
||||
}
|
||||
while (status < 0 && errno == EBUSY);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Populate the list of CLVMDs running.
|
||||
called only at startup time */
|
||||
static void count_clvmds_running(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
int nodeid = nodes[i].cn_nodeid;
|
||||
|
||||
if (is_listening(nodeid) == 1)
|
||||
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
|
||||
else
|
||||
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a list of active cluster members */
|
||||
static void get_members()
|
||||
{
|
||||
int retnodes;
|
||||
int status;
|
||||
int i;
|
||||
int high_nodeid = 0;
|
||||
|
||||
num_nodes = cman_get_node_count(c_handle);
|
||||
if (num_nodes == -1) {
|
||||
log_error("Unable to get node count");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not enough room for new nodes list ? */
|
||||
if (num_nodes > count_nodes && nodes) {
|
||||
free(nodes);
|
||||
nodes = NULL;
|
||||
}
|
||||
|
||||
if (nodes == NULL) {
|
||||
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||
nodes = malloc(count_nodes * sizeof(struct cman_node));
|
||||
if (!nodes) {
|
||||
log_error("Unable to allocate nodes array\n");
|
||||
exit(5);
|
||||
}
|
||||
}
|
||||
|
||||
status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
|
||||
if (status < 0) {
|
||||
log_error("Unable to get node details");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
/* Get the highest nodeid */
|
||||
for (i=0; i<retnodes; i++) {
|
||||
if (nodes[i].cn_nodeid > high_nodeid)
|
||||
high_nodeid = nodes[i].cn_nodeid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert a node name to a CSID */
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (strcmp(name, nodes[i].cn_name) == 0) {
|
||||
memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a CSID to a node name */
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
|
||||
strcpy(name, nodes[i].cn_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Who?? */
|
||||
strcpy(name, "Unknown");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a node ID to a node name */
|
||||
static int name_from_nodeid(int nodeid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (nodeid == nodes[i].cn_nodeid) {
|
||||
strcpy(name, nodes[i].cn_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Who?? */
|
||||
strcpy(name, "Unknown");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a CSID to a node ID */
|
||||
static int nodeid_from_csid(const char *csid)
|
||||
{
|
||||
int nodeid;
|
||||
|
||||
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
|
||||
return nodeid;
|
||||
}
|
||||
|
||||
static int _is_quorate()
|
||||
{
|
||||
return cman_is_quorate(c_handle);
|
||||
}
|
||||
|
||||
static void sync_ast_routine(void *arg)
|
||||
{
|
||||
struct lock_wait *lwait = arg;
|
||||
|
||||
pthread_mutex_lock(&lwait->mutex);
|
||||
pthread_cond_signal(&lwait->cond);
|
||||
pthread_mutex_unlock(&lwait->mutex);
|
||||
}
|
||||
|
||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
|
||||
if (!lockid) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
|
||||
/* Conversions need the lockid in the LKSB */
|
||||
if (flags & LKF_CONVERT)
|
||||
lwait.lksb.sb_lkid = *lockid;
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
status = dlm_ls_lock(lockspace,
|
||||
mode,
|
||||
&lwait.lksb,
|
||||
flags,
|
||||
resource,
|
||||
strlen(resource),
|
||||
0, sync_ast_routine, &lwait, NULL, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
*lockid = lwait.lksb.sb_lkid;
|
||||
|
||||
errno = lwait.lksb.sb_status;
|
||||
DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
|
||||
if (lwait.lksb.sb_status)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
|
||||
DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
errno = lwait.lksb.sb_status;
|
||||
if (lwait.lksb.sb_status != EUNLOCK)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
cman_cluster_t cluster_info;
|
||||
int status;
|
||||
|
||||
status = cman_get_cluster(c_handle, &cluster_info);
|
||||
if (!status) {
|
||||
strncpy(buf, cluster_info.ci_name, buflen);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_cman_ops = {
|
||||
.name = "cman",
|
||||
.cluster_init_completed = _cluster_init_completed,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _sync_lock,
|
||||
.sync_unlock = _sync_unlock,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_cman_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_cman_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
435
daemons/clvmd/clvmd-command.c
Normal file
435
daemons/clvmd/clvmd-command.c
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
CLVMD Cluster LVM daemon command processor.
|
||||
|
||||
To add commands to the daemon simply add a processor in do_command and return
|
||||
and messages back in buf and the length in *retlen. The initial value of
|
||||
buflen is the maximum size of the buffer. if buf is not large enough then it
|
||||
may be reallocated by the functions in here to a suitable size bearing in
|
||||
mind that anything larger than the passed-in size will have to be returned
|
||||
using the system LV and so performance will suffer.
|
||||
|
||||
The status return will be negated and passed back to the originating node.
|
||||
|
||||
pre- and post- command routines are called only on the local node. The
|
||||
purpose is primarily to get and release locks, though the pre- routine should
|
||||
also do any other local setups required by the command (if any) and can
|
||||
return a failure code that prevents the command from being distributed around
|
||||
the cluster
|
||||
|
||||
The pre- and post- routines are run in their own thread so can block as long
|
||||
they like, do_command is run in the main clvmd thread so should not block for
|
||||
too long. If the pre-command returns an error code (!=0) then the command
|
||||
will not be propogated around the cluster but the post-command WILL be called
|
||||
|
||||
Also note that the pre and post routine are *always* called on the local
|
||||
node, even if the command to be executed was only requested to run on a
|
||||
remote node. It may peek inside the client structure to check the status of
|
||||
the command.
|
||||
|
||||
The clients of the daemon must, naturally, understand the return messages and
|
||||
codes.
|
||||
|
||||
Routines in here may only READ the values in the client structure passed in
|
||||
apart from client->private which they are free to do what they like with.
|
||||
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-globals.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
#include "locking.h"
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
extern struct cluster_ops *clops;
|
||||
static int restart_clvmd(void);
|
||||
|
||||
/* This is where all the real work happens:
|
||||
NOTE: client will be NULL when this is executed on a remote node */
|
||||
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
char **buf, int buflen, int *retlen)
|
||||
{
|
||||
char *args = msg->node + strlen(msg->node) + 1;
|
||||
int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
const char *locktype;
|
||||
struct utsname nodeinfo;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
|
||||
/* Reset test mode before we start */
|
||||
init_test(0);
|
||||
|
||||
/* Do the command */
|
||||
switch (msg->cmd) {
|
||||
/* Just a test message */
|
||||
case CLVMD_CMD_TEST:
|
||||
if (arglen > buflen) {
|
||||
char *new_buf;
|
||||
buflen = arglen + 200;
|
||||
new_buf = realloc(*buf, buflen);
|
||||
if (new_buf == NULL) {
|
||||
status = errno;
|
||||
free (*buf);
|
||||
}
|
||||
*buf = new_buf;
|
||||
}
|
||||
if (*buf) {
|
||||
if (uname(&nodeinfo))
|
||||
memset(&nodeinfo, 0, sizeof(nodeinfo));
|
||||
|
||||
*retlen = 1 + dm_snprintf(*buf, buflen,
|
||||
"TEST from %s: %s v%s",
|
||||
nodeinfo.nodename, args,
|
||||
nodeinfo.release);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
/* Check to see if the VG is in use by LVM1 */
|
||||
status = do_check_lvm1(lockname);
|
||||
if (lock_flags & LCK_TEST_MODE)
|
||||
init_test(1);
|
||||
do_lock_vg(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
/* This is the biggie */
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
if (lock_flags & LCK_TEST_MODE)
|
||||
init_test(1);
|
||||
status = do_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
/* Replace EIO with something less scary */
|
||||
if (status == EIO) {
|
||||
*retlen = 1 + dm_snprintf(*buf, buflen, "%s",
|
||||
get_last_lvm_error());
|
||||
return EIO;
|
||||
}
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_QUERY:
|
||||
lockname = &args[2];
|
||||
if (buflen < 3)
|
||||
return EIO;
|
||||
if ((locktype = do_lock_query(lockname)))
|
||||
*retlen = 1 + dm_snprintf(*buf, buflen, "%s", locktype);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_REFRESH:
|
||||
do_refresh_cache();
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_SYNC_NAMES:
|
||||
lvm_do_fs_unlock();
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_SET_DEBUG:
|
||||
clvmd_set_debug((debug_t) args[0]);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_RESTART:
|
||||
status = restart_clvmd();
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
status = clops->get_cluster_name(*buf, buflen);
|
||||
if (!status)
|
||||
*retlen = strlen(*buf)+1;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
/*
|
||||
* Do not run backup on local node, caller should do that.
|
||||
*/
|
||||
if (!client)
|
||||
lvm_do_backup(&args[2]);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Won't get here because command is validated in pre_command */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check the status of the command and return the error text */
|
||||
if (status) {
|
||||
*retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s",
|
||||
strerror(status)) : -1);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
static int lock_vg(struct local_client *client)
|
||||
{
|
||||
struct dm_hash_table *lock_hash;
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
unsigned char lock_cmd;
|
||||
int lock_mode;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
int lkid;
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
|
||||
/* Keep a track of VG locks in our own hash table. In current
|
||||
practice there should only ever be more than two VGs locked
|
||||
if a user tries to merge lots of them at once */
|
||||
if (client->bits.localsock.private) {
|
||||
lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
|
||||
}
|
||||
else {
|
||||
lock_hash = dm_hash_create(3);
|
||||
if (!lock_hash)
|
||||
return ENOMEM;
|
||||
client->bits.localsock.private = (void *)lock_hash;
|
||||
}
|
||||
|
||||
lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
|
||||
lock_mode = ((int)lock_cmd & LCK_TYPE_MASK);
|
||||
/* lock_flags = args[1]; */
|
||||
lockname = &args[2];
|
||||
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||
|
||||
if (lock_mode == LCK_UNLOCK) {
|
||||
|
||||
lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
|
||||
if (lkid == 0)
|
||||
return EINVAL;
|
||||
|
||||
status = sync_unlock(lockname, lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
dm_hash_remove(lock_hash, lockname);
|
||||
}
|
||||
else {
|
||||
/* Read locks need to be PR; other modes get passed through */
|
||||
if (lock_mode == LCK_READ)
|
||||
lock_mode = LCK_PREAD;
|
||||
status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
if (!dm_hash_insert(lock_hash, lockname, (void *)(long)lkid))
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Pre-command is a good place to get locks that are needed only for the duration
|
||||
of the commands around the cluster (don't forget to free them in post-command),
|
||||
and to sanity check the command arguments */
|
||||
int do_pre_command(struct local_client *client)
|
||||
{
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
int lockid = 0;
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
|
||||
init_test(0);
|
||||
switch (header->cmd) {
|
||||
case CLVMD_CMD_TEST:
|
||||
status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
|
||||
client->bits.localsock.private = (void *)(long)lockid;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
lockname = &args[2];
|
||||
/* We take out a real lock unless LCK_CACHE was set */
|
||||
if (!strncmp(lockname, "V_", 2) ||
|
||||
!strncmp(lockname, "P_#", 3))
|
||||
status = lock_vg(client);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
if (lock_flags & LCK_TEST_MODE)
|
||||
init_test(1);
|
||||
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_REFRESH:
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
case CLVMD_CMD_SET_DEBUG:
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
case CLVMD_CMD_SYNC_NAMES:
|
||||
case CLVMD_CMD_LOCK_QUERY:
|
||||
case CLVMD_CMD_RESTART:
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Unknown command %d received\n", header->cmd);
|
||||
status = EINVAL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Note that the post-command routine is called even if the pre-command or the real command
|
||||
failed */
|
||||
int do_post_command(struct local_client *client)
|
||||
{
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
int status = 0;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
char *lockname;
|
||||
|
||||
init_test(0);
|
||||
switch (header->cmd) {
|
||||
case CLVMD_CMD_TEST:
|
||||
status =
|
||||
sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
||||
client->bits.localsock.private = 0;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
if (lock_flags & LCK_TEST_MODE)
|
||||
init_test(1);
|
||||
status = post_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Called when the client is about to be deleted */
|
||||
void cmd_client_cleanup(struct local_client *client)
|
||||
{
|
||||
struct dm_hash_node *v;
|
||||
struct dm_hash_table *lock_hash;
|
||||
int lkid;
|
||||
char *lockname;
|
||||
|
||||
if (!client->bits.localsock.private)
|
||||
return;
|
||||
|
||||
lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
|
||||
|
||||
dm_hash_iterate(v, lock_hash) {
|
||||
lkid = (int)(long)dm_hash_get_data(lock_hash, v);
|
||||
lockname = dm_hash_get_key(lock_hash, v);
|
||||
DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
|
||||
(void) sync_unlock(lockname, lkid);
|
||||
}
|
||||
|
||||
dm_hash_destroy(lock_hash);
|
||||
client->bits.localsock.private = 0;
|
||||
}
|
||||
|
||||
|
||||
static int restart_clvmd(void)
|
||||
{
|
||||
const char **argv;
|
||||
char *lv_name;
|
||||
int argc = 0, max_locks = 0;
|
||||
struct dm_hash_node *hn = NULL;
|
||||
char debug_arg[16];
|
||||
const char *clvmd = getenv("LVM_CLVMD_BINARY") ? : CLVMD_PATH;
|
||||
|
||||
DEBUGLOG("clvmd restart requested\n");
|
||||
|
||||
/* Count exclusively-open LVs */
|
||||
do {
|
||||
hn = get_next_excl_lock(hn, &lv_name);
|
||||
if (lv_name) {
|
||||
max_locks++;
|
||||
if (!*lv_name)
|
||||
break; /* FIXME: Is this error ? */
|
||||
}
|
||||
} while (hn);
|
||||
|
||||
/* clvmd + locks (-E uuid) + debug (-d X) + NULL */
|
||||
if (!(argv = malloc((max_locks * 2 + 6) * sizeof(*argv))))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* Build the command-line
|
||||
*/
|
||||
argv[argc++] = "clvmd";
|
||||
|
||||
/* Propagate debug options */
|
||||
if (clvmd_get_debug()) {
|
||||
if (dm_snprintf(debug_arg, sizeof(debug_arg), "-d%u", clvmd_get_debug()) < 0)
|
||||
goto_out;
|
||||
argv[argc++] = debug_arg;
|
||||
}
|
||||
|
||||
/* Propagate foreground options */
|
||||
if (clvmd_get_foreground())
|
||||
argv[argc++] = "-f";
|
||||
|
||||
argv[argc++] = "-I";
|
||||
argv[argc++] = clops->name;
|
||||
|
||||
/* Now add the exclusively-open LVs */
|
||||
hn = NULL;
|
||||
do {
|
||||
hn = get_next_excl_lock(hn, &lv_name);
|
||||
if (lv_name) {
|
||||
if (!*lv_name)
|
||||
break; /* FIXME: Is this error ? */
|
||||
argv[argc++] = "-E";
|
||||
argv[argc++] = lv_name;
|
||||
DEBUGLOG("excl lock: %s\n", lv_name);
|
||||
}
|
||||
} while (hn);
|
||||
argv[argc] = NULL;
|
||||
|
||||
/* Exec new clvmd */
|
||||
DEBUGLOG("--- Restarting %s ---\n", clvmd);
|
||||
for (argc = 1; argv[argc]; argc++) DEBUGLOG("--- %d: %s\n", argc, argv[argc]);
|
||||
|
||||
/* NOTE: This will fail when downgrading! */
|
||||
execvp(clvmd, (char **)argv);
|
||||
out:
|
||||
/* We failed */
|
||||
DEBUGLOG("Restart of clvmd failed.\n");
|
||||
|
||||
free(argv);
|
||||
|
||||
return EIO;
|
||||
}
|
||||
33
daemons/clvmd/clvmd-common.h
Normal file
33
daemons/clvmd/clvmd-common.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file must be included first by every clvmd source file.
|
||||
*/
|
||||
#ifndef _LVM_CLVMD_COMMON_H
|
||||
#define _LVM_CLVMD_COMMON_H
|
||||
|
||||
#include "configure.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "libdevmapper.h"
|
||||
|
||||
#include "lvm-logging.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#endif
|
||||
119
daemons/clvmd/clvmd-comms.h
Normal file
119
daemons/clvmd/clvmd-comms.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Abstraction layer for clvmd cluster communications
|
||||
*/
|
||||
|
||||
#ifndef _CLVMD_COMMS_H
|
||||
#define _CLVMD_COMMS_H
|
||||
|
||||
struct local_client;
|
||||
|
||||
struct cluster_ops {
|
||||
const char *name;
|
||||
void (*cluster_init_completed) (void);
|
||||
|
||||
int (*cluster_send_message) (const void *buf, int msglen,
|
||||
const char *csid,
|
||||
const char *errtext);
|
||||
int (*name_from_csid) (const char *csid, char *name);
|
||||
int (*csid_from_name) (char *csid, const char *name);
|
||||
int (*get_num_nodes) (void);
|
||||
int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client);
|
||||
int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */
|
||||
int (*cluster_do_node_callback) (struct local_client *client,
|
||||
void (*callback) (struct local_client *,
|
||||
const char *csid,
|
||||
int node_up));
|
||||
int (*is_quorate) (void);
|
||||
|
||||
void (*get_our_csid) (char *csid);
|
||||
void (*add_up_node) (const char *csid);
|
||||
void (*reread_config) (void);
|
||||
void (*cluster_closedown) (void);
|
||||
|
||||
int (*get_cluster_name)(char *buf, int buflen);
|
||||
|
||||
int (*sync_lock) (const char *resource, int mode,
|
||||
int flags, int *lockid);
|
||||
int (*sync_unlock) (const char *resource, int lockid);
|
||||
|
||||
};
|
||||
|
||||
#ifdef USE_CMAN
|
||||
# include <netinet/in.h>
|
||||
# include "libcman.h"
|
||||
# define CMAN_MAX_CSID_LEN 4
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
|
||||
# endif
|
||||
# undef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE 1500
|
||||
# define CLUSTER_PORT_CLVMD 11
|
||||
struct cluster_ops *init_cman_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENAIS
|
||||
# include <openais/saAis.h>
|
||||
# include <corosync/totem/totem.h>
|
||||
# define OPENAIS_CSID_LEN (sizeof(int))
|
||||
# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
|
||||
# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
|
||||
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
|
||||
# endif
|
||||
# ifndef CMAN_MAX_CLUSTER_MESSAGE
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
|
||||
# endif
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN sizeof(int)
|
||||
# endif
|
||||
struct cluster_ops *init_openais_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_COROSYNC
|
||||
# include <corosync/corotypes.h>
|
||||
# define COROSYNC_CSID_LEN (sizeof(int))
|
||||
# define COROSYNC_MAX_CLUSTER_MESSAGE 65535
|
||||
# define COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
|
||||
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
|
||||
# endif
|
||||
# ifndef CMAN_MAX_CLUSTER_MESSAGE
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE 65535
|
||||
# endif
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN sizeof(int)
|
||||
# endif
|
||||
struct cluster_ops *init_corosync_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SINGLENODE
|
||||
# define SINGLENODE_CSID_LEN (sizeof(int))
|
||||
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN 64
|
||||
# endif
|
||||
# define SINGLENODE_MAX_CLUSTER_MESSAGE 65535
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN sizeof(int)
|
||||
# endif
|
||||
struct cluster_ops *init_singlenode_cluster(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
684
daemons/clvmd/clvmd-corosync.c
Normal file
684
daemons/clvmd/clvmd-corosync.c
Normal file
@@ -0,0 +1,684 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This provides the interface between clvmd and corosync/DLM as the cluster
|
||||
* and lock manager.
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
#include "locking.h"
|
||||
|
||||
#include <corosync/cpg.h>
|
||||
#include <corosync/quorum.h>
|
||||
|
||||
#ifdef HAVE_COROSYNC_CONFDB_H
|
||||
# include <corosync/confdb.h>
|
||||
#elif defined HAVE_COROSYNC_CMAP_H
|
||||
# include <corosync/cmap.h>
|
||||
#else
|
||||
# error "Either HAVE_COROSYNC_CONFDB_H or HAVE_COROSYNC_CMAP_H must be defined."
|
||||
#endif
|
||||
|
||||
#include <libdlm.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
/* Timeout value for several corosync calls */
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len);
|
||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries);
|
||||
static void _cluster_closedown(void);
|
||||
|
||||
/* Hash list of nodes in the cluster */
|
||||
static struct dm_hash_table *node_hash;
|
||||
|
||||
/* Number of active nodes */
|
||||
static int num_nodes;
|
||||
static unsigned int our_nodeid;
|
||||
|
||||
static struct local_client *cluster_client;
|
||||
|
||||
/* Corosync handles */
|
||||
static cpg_handle_t cpg_handle;
|
||||
static quorum_handle_t quorum_handle;
|
||||
|
||||
/* DLM Handle */
|
||||
static dlm_lshandle_t *lockspace;
|
||||
|
||||
static struct cpg_name cpg_group_name;
|
||||
|
||||
/* Corosync callback structs */
|
||||
cpg_callbacks_t corosync_cpg_callbacks = {
|
||||
.cpg_deliver_fn = corosync_cpg_deliver_callback,
|
||||
.cpg_confchg_fn = corosync_cpg_confchg_callback,
|
||||
};
|
||||
|
||||
quorum_callbacks_t quorum_callbacks = {
|
||||
.quorum_notify_fn = NULL,
|
||||
};
|
||||
|
||||
struct node_info
|
||||
{
|
||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
int nodeid;
|
||||
};
|
||||
|
||||
|
||||
/* Set errno to something approximating the right value and return 0 or -1 */
|
||||
static int cs_to_errno(cs_error_t err)
|
||||
{
|
||||
switch(err)
|
||||
{
|
||||
case CS_OK:
|
||||
return 0;
|
||||
case CS_ERR_LIBRARY:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_VERSION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_INIT:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_TIMEOUT:
|
||||
errno = ETIME;
|
||||
break;
|
||||
case CS_ERR_TRY_AGAIN:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
case CS_ERR_INVALID_PARAM:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_NO_MEMORY:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case CS_ERR_BAD_HANDLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_BUSY:
|
||||
errno = EBUSY;
|
||||
break;
|
||||
case CS_ERR_ACCESS:
|
||||
errno = EPERM;
|
||||
break;
|
||||
case CS_ERR_NOT_EXIST:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case CS_ERR_NAME_TOO_LONG:
|
||||
errno = ENAMETOOLONG;
|
||||
break;
|
||||
case CS_ERR_EXIST:
|
||||
errno = EEXIST;
|
||||
break;
|
||||
case CS_ERR_NO_SPACE:
|
||||
errno = ENOSPC;
|
||||
break;
|
||||
case CS_ERR_INTERRUPT:
|
||||
errno = EINTR;
|
||||
break;
|
||||
case CS_ERR_NAME_NOT_FOUND:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case CS_ERR_NO_RESOURCES:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case CS_ERR_NOT_SUPPORTED:
|
||||
errno = EOPNOTSUPP;
|
||||
break;
|
||||
case CS_ERR_BAD_OPERATION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_FAILED_OPERATION:
|
||||
errno = EIO;
|
||||
break;
|
||||
case CS_ERR_MESSAGE_ERROR:
|
||||
errno = EIO;
|
||||
break;
|
||||
case CS_ERR_QUEUE_FULL:
|
||||
errno = EXFULL;
|
||||
break;
|
||||
case CS_ERR_QUEUE_NOT_AVAILABLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_BAD_FLAGS:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_TOO_BIG:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case CS_ERR_NO_SECTIONS:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *print_corosync_csid(const char *csid)
|
||||
{
|
||||
static char buf[128];
|
||||
int id;
|
||||
|
||||
memcpy(&id, csid, sizeof(int));
|
||||
sprintf(buf, "%d", id);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len)
|
||||
{
|
||||
int target_nodeid;
|
||||
|
||||
memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
|
||||
|
||||
DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
|
||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
||||
|
||||
if (nodeid != our_nodeid)
|
||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
||||
process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
|
||||
msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
|
||||
}
|
||||
|
||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
||||
{
|
||||
int i;
|
||||
struct node_info *ninfo;
|
||||
|
||||
DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n",
|
||||
joined_list_entries, left_list_entries, member_list_entries);
|
||||
|
||||
for (i=0; i<joined_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&joined_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = joined_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
COROSYNC_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
for (i=0; i<left_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&left_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (ninfo)
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
for (i=0; i<member_list_entries; i++) {
|
||||
if (member_list[i].nodeid == 0) continue;
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&member_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = member_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
COROSYNC_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
cs_error_t err;
|
||||
|
||||
#ifdef QUORUM_SET /* corosync/quorum.h */
|
||||
uint32_t quorum_type;
|
||||
#endif
|
||||
|
||||
node_hash = dm_hash_create(100);
|
||||
|
||||
err = cpg_initialize(&cpg_handle,
|
||||
&corosync_cpg_callbacks);
|
||||
if (err != CS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
#ifdef QUORUM_SET
|
||||
err = quorum_initialize(&quorum_handle,
|
||||
&quorum_callbacks,
|
||||
&quorum_type);
|
||||
|
||||
if (quorum_type != QUORUM_SET) {
|
||||
syslog(LOG_ERR, "Corosync quorum service is not configured");
|
||||
DEBUGLOG("Corosync quorum service is not configured");
|
||||
return EINVAL;
|
||||
}
|
||||
#else
|
||||
err = quorum_initialize(&quorum_handle,
|
||||
&quorum_callbacks);
|
||||
#endif
|
||||
|
||||
if (err != CS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
/* Create a lockspace for LV & VG locks to live in */
|
||||
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
|
||||
if (!lockspace) {
|
||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
||||
if (!lockspace) {
|
||||
syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
|
||||
return -1;
|
||||
}
|
||||
DEBUGLOG("Created DLM lockspace for CLVMD.\n");
|
||||
} else
|
||||
DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
|
||||
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
DEBUGLOG("DLM initialisation complete\n");
|
||||
|
||||
/* Connect to the clvmd group */
|
||||
strcpy((char *)cpg_group_name.value, "clvmd");
|
||||
cpg_group_name.length = strlen((char *)cpg_group_name.value);
|
||||
err = cpg_join(cpg_handle, &cpg_group_name);
|
||||
if (err != CS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
syslog(LOG_ERR, "Cannot join clvmd process group");
|
||||
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
err = cpg_local_get(cpg_handle,
|
||||
&our_nodeid);
|
||||
if (err != CS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
syslog(LOG_ERR, "Cannot get local node id\n");
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
DEBUGLOG("Our local node id is %d\n", our_nodeid);
|
||||
|
||||
DEBUGLOG("Connected to Corosync\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
destroy_lvhash();
|
||||
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
memcpy(csid, &our_nodeid, sizeof(int));
|
||||
}
|
||||
|
||||
/* Corosync doesn't really have nmode names so we
|
||||
just use the node ID in hex instead */
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
int nodeid;
|
||||
struct node_info *ninfo;
|
||||
|
||||
if (sscanf(name, "%x", &nodeid) == 1) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (ninfo)
|
||||
return nodeid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
sprintf(name, "UNKNOWN %s", print_corosync_csid(csid));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(name, "%x", ninfo->nodeid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
|
||||
print_corosync_csid(csid));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGLOG("corosync_add_up_node %d\n", ninfo->nodeid);
|
||||
|
||||
ninfo->state = NODE_CLVMD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *,
|
||||
const char *csid, int node_up))
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
char csid[COROSYNC_CSID_LEN];
|
||||
|
||||
ninfo = dm_hash_get_data(node_hash, hn);
|
||||
memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN);
|
||||
|
||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
||||
ninfo->state);
|
||||
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
struct dlm_lksb lksb;
|
||||
int err;
|
||||
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
||||
|
||||
if (flags & LKF_CONVERT)
|
||||
lksb.sb_lkid = *lockid;
|
||||
|
||||
err = dlm_ls_lock_wait(lockspace,
|
||||
mode,
|
||||
&lksb,
|
||||
flags,
|
||||
resource,
|
||||
strlen(resource),
|
||||
0,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_lock returned %d\n", errno);
|
||||
return err;
|
||||
}
|
||||
if (lksb.sb_status != 0)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
|
||||
errno = lksb.sb_status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
|
||||
|
||||
*lockid = lksb.sb_lkid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int _unlock_resource(const char *resource, int lockid)
|
||||
{
|
||||
struct dlm_lksb lksb;
|
||||
int err;
|
||||
|
||||
DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
|
||||
lksb.sb_lkid = lockid;
|
||||
|
||||
err = dlm_ls_unlock_wait(lockspace,
|
||||
lockid,
|
||||
0,
|
||||
&lksb);
|
||||
if (err != 0)
|
||||
{
|
||||
DEBUGLOG("Unlock returned %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (lksb.sb_status != EUNLOCK)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
|
||||
errno = lksb.sb_status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _is_quorate()
|
||||
{
|
||||
int quorate;
|
||||
if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
|
||||
return quorate;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd(void)
|
||||
{
|
||||
int select_fd;
|
||||
|
||||
cpg_fd_get(cpg_handle, &select_fd);
|
||||
return select_fd;
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
cluster_client = fd;
|
||||
*new_client = NULL;
|
||||
cpg_dispatch(cpg_handle, CS_DISPATCH_ONE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
||||
const char *errtext)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
cs_error_t err;
|
||||
int target_node;
|
||||
|
||||
if (csid)
|
||||
memcpy(&target_node, csid, COROSYNC_CSID_LEN);
|
||||
else
|
||||
target_node = 0;
|
||||
|
||||
iov[0].iov_base = &target_node;
|
||||
iov[0].iov_len = sizeof(int);
|
||||
iov[1].iov_base = (char *)buf;
|
||||
iov[1].iov_len = msglen;
|
||||
|
||||
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
#ifdef HAVE_COROSYNC_CONFDB_H
|
||||
/*
|
||||
* We are not necessarily connected to a Red Hat Cluster system,
|
||||
* but if we are, this returns the cluster name from cluster.conf.
|
||||
* I've used confdb rather than ccs to reduce the inter-package
|
||||
* dependancies as well as to allow people to set a cluster name
|
||||
* for themselves even if they are not running on RH cluster.
|
||||
*/
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
confdb_handle_t handle;
|
||||
int result;
|
||||
size_t namelen = buflen;
|
||||
hdb_handle_t cluster_handle;
|
||||
confdb_callbacks_t callbacks = {
|
||||
.confdb_key_change_notify_fn = NULL,
|
||||
.confdb_object_create_change_notify_fn = NULL,
|
||||
.confdb_object_delete_change_notify_fn = NULL
|
||||
};
|
||||
|
||||
/* This is a default in case everything else fails */
|
||||
strncpy(buf, "Corosync", buflen);
|
||||
|
||||
/* Look for a cluster name in confdb */
|
||||
result = confdb_initialize (&handle, &callbacks);
|
||||
if (result != CS_OK)
|
||||
return 0;
|
||||
|
||||
result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
result = confdb_key_get(handle, cluster_handle, (void *)"name", strlen("name"), buf, &namelen);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
buf[namelen] = '\0';
|
||||
|
||||
out:
|
||||
confdb_finalize(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined HAVE_COROSYNC_CMAP_H
|
||||
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
cmap_handle_t cmap_handle = 0;
|
||||
int result;
|
||||
char *name = NULL;
|
||||
|
||||
/* This is a default in case everything else fails */
|
||||
strncpy(buf, "Corosync", buflen);
|
||||
|
||||
/* Look for a cluster name in cmap */
|
||||
result = cmap_initialize(&cmap_handle);
|
||||
if (result != CS_OK)
|
||||
return 0;
|
||||
|
||||
result = cmap_get_string(cmap_handle, "totem.cluster_name", &name);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
strncpy(buf, name, buflen - 1);
|
||||
|
||||
out:
|
||||
if (name)
|
||||
free(name);
|
||||
cmap_finalize(cmap_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static struct cluster_ops _cluster_corosync_ops = {
|
||||
.name = "corosync",
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.reread_config = NULL,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _lock_resource,
|
||||
.sync_unlock = _unlock_resource,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_corosync_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_corosync_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
694
daemons/clvmd/clvmd-openais.c
Normal file
694
daemons/clvmd/clvmd-openais.c
Normal file
@@ -0,0 +1,694 @@
|
||||
/*
|
||||
* 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 = calloc(1, sizeof(struct local_client));
|
||||
if (!client)
|
||||
{
|
||||
DEBUGLOG("malloc failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
client->fd = fd;
|
||||
client->type = CLUSTER_INTERNAL;
|
||||
client->callback = callback;
|
||||
add_client(client);
|
||||
|
||||
/* Set Close-on-exec */
|
||||
fcntl(fd, F_SETFD, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void openais_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len)
|
||||
{
|
||||
int target_nodeid;
|
||||
|
||||
memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
|
||||
|
||||
DEBUGLOG("%u got message from nodeid %d for %d. len %" PRIsize_t "\n",
|
||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
||||
|
||||
if (nodeid != our_nodeid)
|
||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
||||
process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
|
||||
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
|
||||
}
|
||||
|
||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
||||
{
|
||||
int i;
|
||||
struct node_info *ninfo;
|
||||
|
||||
DEBUGLOG("confchg callback. %" PRIsize_t " joined, "
|
||||
"%" PRIsize_t " left, %" PRIsize_t " members\n",
|
||||
joined_list_entries, left_list_entries, member_list_entries);
|
||||
|
||||
for (i=0; i<joined_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&joined_list[i].nodeid,
|
||||
OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = joined_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
OPENAIS_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
for (i=0; i<left_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&left_list[i].nodeid,
|
||||
OPENAIS_CSID_LEN);
|
||||
if (ninfo)
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
for (i=0; i<member_list_entries; i++) {
|
||||
if (member_list[i].nodeid == 0) continue;
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&member_list[i].nodeid,
|
||||
OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = member_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
OPENAIS_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
static int lck_dispatch(struct local_client *client, char *buf, int len,
|
||||
const char *csid, struct local_client **new_client)
|
||||
{
|
||||
*new_client = NULL;
|
||||
saLckDispatch(lck_handle, SA_DISPATCH_ONE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
SaAisErrorT err;
|
||||
SaVersionT ver = { 'B', 1, 1 };
|
||||
int select_fd;
|
||||
|
||||
node_hash = dm_hash_create(100);
|
||||
lock_hash = dm_hash_create(10);
|
||||
|
||||
err = cpg_initialize(&cpg_handle,
|
||||
&openais_cpg_callbacks);
|
||||
if (err != SA_AIS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
err = saLckInitialize(&lck_handle,
|
||||
NULL,
|
||||
&ver);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_initialize(&cpg_handle, &openais_cpg_callbacks);
|
||||
syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* Connect to the clvmd group */
|
||||
strcpy((char *)cpg_group_name.value, "clvmd");
|
||||
cpg_group_name.length = strlen((char *)cpg_group_name.value);
|
||||
err = cpg_join(cpg_handle, &cpg_group_name);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
saLckFinalize(lck_handle);
|
||||
syslog(LOG_ERR, "Cannot join clvmd process group");
|
||||
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
err = cpg_local_get(cpg_handle,
|
||||
&our_nodeid);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
saLckFinalize(lck_handle);
|
||||
syslog(LOG_ERR, "Cannot get local node id\n");
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
DEBUGLOG("Our local node id is %d\n", our_nodeid);
|
||||
|
||||
saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
|
||||
add_internal_client(select_fd, lck_dispatch);
|
||||
|
||||
DEBUGLOG("Connected to OpenAIS\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
destroy_lvhash();
|
||||
|
||||
saLckFinalize(lck_handle);
|
||||
cpg_finalize(cpg_handle);
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
memcpy(csid, &our_nodeid, sizeof(int));
|
||||
}
|
||||
|
||||
/* OpenAIS doesn't really have nmode names so we
|
||||
just use the node ID in hex instead */
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
int nodeid;
|
||||
struct node_info *ninfo;
|
||||
|
||||
if (sscanf(name, "%x", &nodeid) == 1) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
||||
if (ninfo)
|
||||
return nodeid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
sprintf(name, "UNKNOWN %s", print_openais_csid(csid));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(name, "%x", ninfo->nodeid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
|
||||
print_openais_csid(csid));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
|
||||
|
||||
ninfo->state = NODE_CLVMD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *,
|
||||
const char *csid, int node_up))
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
char csid[OPENAIS_CSID_LEN];
|
||||
|
||||
ninfo = dm_hash_get_data(node_hash, hn);
|
||||
memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
|
||||
|
||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
||||
ninfo->state);
|
||||
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
struct lock_info *linfo;
|
||||
SaLckResourceHandleT res_handle;
|
||||
SaAisErrorT err;
|
||||
SaLckLockIdT lock_id;
|
||||
SaLckLockStatusT lockStatus;
|
||||
|
||||
/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
|
||||
if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
|
||||
|
||||
linfo = malloc(sizeof(struct lock_info));
|
||||
if (!linfo)
|
||||
return -1;
|
||||
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
||||
|
||||
linfo->lock_name.length = strlen(resource)+1;
|
||||
strcpy((char *)linfo->lock_name.value, resource);
|
||||
|
||||
err = saLckResourceOpen(lck_handle, &linfo->lock_name,
|
||||
SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
|
||||
if (err != SA_AIS_OK)
|
||||
{
|
||||
DEBUGLOG("ResourceOpen returned %d\n", err);
|
||||
free(linfo);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
err = saLckResourceLock(
|
||||
res_handle,
|
||||
&lock_id,
|
||||
mode,
|
||||
flags,
|
||||
0,
|
||||
SA_TIME_END,
|
||||
&lockStatus);
|
||||
if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
|
||||
{
|
||||
free(linfo);
|
||||
saLckResourceClose(res_handle);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* Wait for it to complete */
|
||||
|
||||
DEBUGLOG("lock_resource returning %d, lock_id=%" PRIx64 "\n",
|
||||
err, lock_id);
|
||||
|
||||
linfo->lock_id = lock_id;
|
||||
linfo->res_handle = res_handle;
|
||||
|
||||
dm_hash_insert(lock_hash, resource, linfo);
|
||||
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
|
||||
static int _unlock_resource(char *resource, int lockid)
|
||||
{
|
||||
SaAisErrorT err;
|
||||
struct lock_info *linfo;
|
||||
|
||||
DEBUGLOG("unlock_resource %s\n", resource);
|
||||
linfo = dm_hash_lookup(lock_hash, resource);
|
||||
if (!linfo)
|
||||
return 0;
|
||||
|
||||
DEBUGLOG("unlock_resource: lockid: %" PRIx64 "\n", linfo->lock_id);
|
||||
err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
|
||||
if (err != SA_AIS_OK)
|
||||
{
|
||||
DEBUGLOG("Unlock returned %d\n", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* Release the resource */
|
||||
dm_hash_remove(lock_hash, resource);
|
||||
saLckResourceClose(linfo->res_handle);
|
||||
free(linfo);
|
||||
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
char lock1[strlen(resource)+3];
|
||||
char lock2[strlen(resource)+3];
|
||||
|
||||
snprintf(lock1, sizeof(lock1), "%s-1", resource);
|
||||
snprintf(lock2, sizeof(lock2), "%s-2", resource);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case LCK_EXCL:
|
||||
status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
/* If we can't get this lock too then bail out */
|
||||
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
|
||||
lockid);
|
||||
if (status == SA_LCK_LOCK_NOT_QUEUED)
|
||||
{
|
||||
_unlock_resource(lock1, *lockid);
|
||||
status = -1;
|
||||
errno = EAGAIN;
|
||||
}
|
||||
break;
|
||||
|
||||
case LCK_PREAD:
|
||||
case LCK_READ:
|
||||
status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
_unlock_resource(lock2, *lockid);
|
||||
break;
|
||||
|
||||
case LCK_WRITE:
|
||||
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
_unlock_resource(lock1, *lockid);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = -1;
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
out:
|
||||
*lockid = mode;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int _sync_unlock(const char *resource, int lockid)
|
||||
{
|
||||
int status = 0;
|
||||
char lock1[strlen(resource)+3];
|
||||
char lock2[strlen(resource)+3];
|
||||
|
||||
snprintf(lock1, sizeof(lock1), "%s-1", resource);
|
||||
snprintf(lock2, sizeof(lock2), "%s-2", resource);
|
||||
|
||||
_unlock_resource(lock1, lockid);
|
||||
_unlock_resource(lock2, lockid);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* We are always quorate ! */
|
||||
static int _is_quorate()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd(void)
|
||||
{
|
||||
int select_fd;
|
||||
|
||||
cpg_fd_get(cpg_handle, &select_fd);
|
||||
return select_fd;
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
cluster_client = fd;
|
||||
*new_client = NULL;
|
||||
cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
||||
const char *errtext)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
SaAisErrorT err;
|
||||
int target_node;
|
||||
|
||||
if (csid)
|
||||
memcpy(&target_node, csid, OPENAIS_CSID_LEN);
|
||||
else
|
||||
target_node = 0;
|
||||
|
||||
iov[0].iov_base = &target_node;
|
||||
iov[0].iov_len = sizeof(int);
|
||||
iov[1].iov_base = (char *)buf;
|
||||
iov[1].iov_len = msglen;
|
||||
|
||||
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* We don't have a cluster name to report here */
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
strncpy(buf, "OpenAIS", buflen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_openais_ops = {
|
||||
.name = "openais",
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.reread_config = NULL,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _sync_lock,
|
||||
.sync_unlock = _sync_unlock,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_openais_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_openais_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
316
daemons/clvmd/clvmd-singlenode.c
Normal file
316
daemons/clvmd/clvmd-singlenode.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "locking.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvmd.h"
|
||||
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock";
|
||||
static int listen_fd = -1;
|
||||
|
||||
static struct dm_hash_table *_locks;
|
||||
static int _lockid;
|
||||
|
||||
struct lock {
|
||||
int lockid;
|
||||
int mode;
|
||||
int excl;
|
||||
};
|
||||
|
||||
static void close_comms(void)
|
||||
{
|
||||
if (listen_fd != -1 && close(listen_fd))
|
||||
stack;
|
||||
(void)unlink(SINGLENODE_CLVMD_SOCKNAME);
|
||||
listen_fd = -1;
|
||||
}
|
||||
|
||||
static int init_comms(void)
|
||||
{
|
||||
mode_t old_mask;
|
||||
struct sockaddr_un addr = { .sun_family = AF_UNIX };
|
||||
|
||||
if (!dm_strncpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
|
||||
sizeof(addr.sun_path))) {
|
||||
DEBUGLOG("%s: singlenode socket name too long.",
|
||||
SINGLENODE_CLVMD_SOCKNAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close_comms();
|
||||
|
||||
(void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK);
|
||||
old_mask = umask(0077);
|
||||
|
||||
listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (listen_fd < 0) {
|
||||
DEBUGLOG("Can't create local socket: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
/* Set Close-on-exec */
|
||||
if (fcntl(listen_fd, F_SETFD, 1)) {
|
||||
DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
DEBUGLOG("Can't bind local socket: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
if (listen(listen_fd, 10) < 0) {
|
||||
DEBUGLOG("Can't listen local socket: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
error:
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
close_comms();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!(_locks = dm_hash_create(128))) {
|
||||
DEBUGLOG("Failed to allocate single-node hash table.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = init_comms();
|
||||
if (r) {
|
||||
dm_hash_destroy(_locks);
|
||||
return r;
|
||||
}
|
||||
|
||||
DEBUGLOG("Single-node cluster initialised.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
close_comms();
|
||||
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
destroy_lvhash();
|
||||
dm_hash_destroy(_locks);
|
||||
_locks = NULL;
|
||||
_lockid = 0;
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
int nodeid = 1;
|
||||
memcpy(csid, &nodeid, sizeof(int));
|
||||
}
|
||||
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
strcpy(name, "SINGLENODE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_num_nodes(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *,
|
||||
const char *csid, int node_up))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _lock_file(const char *file, uint32_t flags);
|
||||
|
||||
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
/* Using one common condition for all locks for simplicity */
|
||||
static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
struct lock *lck;
|
||||
|
||||
DEBUGLOG("Locking resource %s, flags=%d, mode=%d\n",
|
||||
resource, flags, mode);
|
||||
|
||||
mode &= LCK_TYPE_MASK;
|
||||
pthread_mutex_lock(&_lock_mutex);
|
||||
retry:
|
||||
if (!(lck = dm_hash_lookup(_locks, resource))) {
|
||||
/* Add new locked resource */
|
||||
if (!(lck = dm_zalloc(sizeof(struct lock))) ||
|
||||
!dm_hash_insert(_locks, resource, lck))
|
||||
goto bad;
|
||||
|
||||
lck->lockid = ++_lockid;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Update/convert lock */
|
||||
if (flags == LCKF_CONVERT) {
|
||||
if (lck->excl)
|
||||
mode = LCK_EXCL;
|
||||
} else if ((lck->mode == LCK_WRITE) || (lck->mode == LCK_EXCL)) {
|
||||
DEBUGLOG("Resource %s already %s locked (%d)...\n", resource,
|
||||
(lck->mode == LCK_WRITE) ? "write" : "exclusively", lck->lockid);
|
||||
goto maybe_retry;
|
||||
} else if (lck->mode > mode) {
|
||||
DEBUGLOG("Resource %s already locked and %s lock requested...\n",
|
||||
resource,
|
||||
(mode == LCK_READ) ? "READ" :
|
||||
(mode == LCK_WRITE) ? "WRITE" : "EXCLUSIVE");
|
||||
goto maybe_retry;
|
||||
}
|
||||
|
||||
out:
|
||||
*lockid = lck->lockid;
|
||||
lck->mode = mode;
|
||||
lck->excl |= (mode == LCK_EXCL);
|
||||
DEBUGLOG("Locked resource %s, lockid=%d, mode=%d\n", resource, lck->lockid, mode);
|
||||
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
maybe_retry:
|
||||
if (!(flags & LCK_NONBLOCK)) {
|
||||
pthread_cond_wait(&_lock_cond, &_lock_mutex);
|
||||
DEBUGLOG("Resource %s RETRYING lock...\n", resource);
|
||||
goto retry;
|
||||
}
|
||||
bad:
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
DEBUGLOG("Failed to lock resource %s\n", resource);
|
||||
|
||||
return 1; /* fail */
|
||||
}
|
||||
|
||||
static int _unlock_resource(const char *resource, int lockid)
|
||||
{
|
||||
struct lock *lck;
|
||||
|
||||
if (lockid < 0) {
|
||||
DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
|
||||
resource, lockid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
|
||||
pthread_mutex_lock(&_lock_mutex);
|
||||
|
||||
if (!(lck = dm_hash_lookup(_locks, resource))) {
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
DEBUGLOG("Resource %s, lockid=%d is not locked.\n", resource, lockid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lck->lockid != lockid) {
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
DEBUGLOG("Resource %s has wrong lockid %d, expected %d.\n",
|
||||
resource, lck->lockid, lockid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dm_hash_remove(_locks, resource);
|
||||
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
|
||||
pthread_mutex_unlock(&_lock_mutex);
|
||||
dm_free(lck);
|
||||
|
||||
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)
|
||||
{
|
||||
return dm_strncpy(buf, "localcluster", buflen) ? 0 : 1;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_singlenode_ops = {
|
||||
.name = "singlenode",
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.reread_config = NULL,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _lock_resource,
|
||||
.sync_unlock = _unlock_resource,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_singlenode_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_singlenode_ops;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
2353
daemons/clvmd/clvmd.c
Normal file
2353
daemons/clvmd/clvmd.c
Normal file
File diff suppressed because it is too large
Load Diff
127
daemons/clvmd/clvmd.h
Normal file
127
daemons/clvmd/clvmd.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _CLVMD_H
|
||||
#define _CLVMD_H
|
||||
|
||||
#define CLVMD_MAJOR_VERSION 0
|
||||
#define CLVMD_MINOR_VERSION 2
|
||||
#define CLVMD_PATCH_VERSION 1
|
||||
|
||||
/* Default time (in seconds) we will wait for all remote commands to execute
|
||||
before declaring them dead */
|
||||
#define DEFAULT_CMD_TIMEOUT 60
|
||||
|
||||
/* One of these for each reply we get from command execution on a node */
|
||||
struct node_reply {
|
||||
char node[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
char *replymsg;
|
||||
int status;
|
||||
struct node_reply *next;
|
||||
};
|
||||
|
||||
typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t;
|
||||
|
||||
/*
|
||||
* These exist for the use of local sockets only when we are
|
||||
* collecting responses from all cluster nodes
|
||||
*/
|
||||
struct localsock_bits {
|
||||
struct node_reply *replies;
|
||||
int num_replies;
|
||||
int expected_replies;
|
||||
time_t sent_time; /* So we can check for timeouts */
|
||||
int in_progress; /* Only execute one cmd at a time per client */
|
||||
int sent_out; /* Flag to indicate that a command was sent
|
||||
to remote nodes */
|
||||
void *private; /* Private area for command processor use */
|
||||
void *cmd; /* Whole command as passed down local socket */
|
||||
int cmd_len; /* Length of above */
|
||||
int pipe; /* Pipe to send PRE completion status down */
|
||||
int finished; /* Flag to tell subthread to exit */
|
||||
int all_success; /* Set to 0 if any node (or the pre_command)
|
||||
failed */
|
||||
struct local_client *pipe_client;
|
||||
pthread_t threadid;
|
||||
enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
|
||||
pthread_mutex_t mutex; /* Main thread and worker synchronisation */
|
||||
pthread_cond_t cond;
|
||||
|
||||
pthread_mutex_t reply_mutex; /* Protect reply structure */
|
||||
};
|
||||
|
||||
/* Entries for PIPE clients */
|
||||
struct pipe_bits {
|
||||
struct local_client *client; /* Actual (localsock) client */
|
||||
pthread_t threadid; /* Our own copy of the thread id */
|
||||
};
|
||||
|
||||
/* Entries for Network socket clients */
|
||||
struct netsock_bits {
|
||||
void *private;
|
||||
int flags;
|
||||
};
|
||||
|
||||
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client ** new_client);
|
||||
|
||||
/* One of these for each fd we are listening on */
|
||||
struct local_client {
|
||||
int fd;
|
||||
enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
|
||||
LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
|
||||
struct local_client *next;
|
||||
unsigned short xid;
|
||||
fd_callback_t callback;
|
||||
uint8_t removeme;
|
||||
|
||||
union {
|
||||
struct localsock_bits localsock;
|
||||
struct pipe_bits pipe;
|
||||
struct netsock_bits net;
|
||||
} bits;
|
||||
};
|
||||
|
||||
#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args)
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
/* The real command processor is in clvmd-command.c */
|
||||
extern int do_command(struct local_client *client, struct clvm_header *msg,
|
||||
int msglen, char **buf, int buflen, int *retlen);
|
||||
|
||||
/* Pre and post command routines are called only on the local node */
|
||||
extern int do_pre_command(struct local_client *client);
|
||||
extern int do_post_command(struct local_client *client);
|
||||
extern void cmd_client_cleanup(struct local_client *client);
|
||||
extern int add_client(struct local_client *new_client);
|
||||
|
||||
extern void clvmd_cluster_init_completed(void);
|
||||
extern void process_message(struct local_client *client, char *buf,
|
||||
int len, const char *csid);
|
||||
extern void debuglog(const char *fmt, ... )
|
||||
__attribute__ ((format(printf, 1, 2)));
|
||||
|
||||
void clvmd_set_debug(debug_t new_de);
|
||||
debug_t clvmd_get_debug(void);
|
||||
int clvmd_get_foreground(void);
|
||||
|
||||
int sync_lock(const char *resource, int mode, int flags, int *lockid);
|
||||
int sync_unlock(const char *resource, int lockid);
|
||||
|
||||
#endif
|
||||
921
daemons/clvmd/lvm-functions.c
Normal file
921
daemons/clvmd/lvm-functions.c
Normal file
@@ -0,0 +1,921 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "lvm-types.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
/* LVM2 headers */
|
||||
#include "toolcontext.h"
|
||||
#include "lvmcache.h"
|
||||
#include "lvm-globals.h"
|
||||
#include "activate.h"
|
||||
#include "archiver.h"
|
||||
#include "memlock.h"
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
static struct cmd_context *cmd = NULL;
|
||||
static struct dm_hash_table *lv_hash = NULL;
|
||||
static pthread_mutex_t lv_hash_lock;
|
||||
static pthread_mutex_t lvm_lock;
|
||||
static char last_error[1024];
|
||||
|
||||
struct lv_info {
|
||||
int lock_id;
|
||||
int lock_mode;
|
||||
};
|
||||
|
||||
static const char *decode_full_locking_cmd(uint32_t cmdl)
|
||||
{
|
||||
static char buf[128];
|
||||
const char *type;
|
||||
const char *scope;
|
||||
const char *command;
|
||||
|
||||
switch (cmdl & LCK_TYPE_MASK) {
|
||||
case LCK_NULL:
|
||||
type = "NULL";
|
||||
break;
|
||||
case LCK_READ:
|
||||
type = "READ";
|
||||
break;
|
||||
case LCK_PREAD:
|
||||
type = "PREAD";
|
||||
break;
|
||||
case LCK_WRITE:
|
||||
type = "WRITE";
|
||||
break;
|
||||
case LCK_EXCL:
|
||||
type = "EXCL";
|
||||
break;
|
||||
case LCK_UNLOCK:
|
||||
type = "UNLOCK";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmdl & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
scope = "VG";
|
||||
command = "LCK_VG";
|
||||
break;
|
||||
case LCK_LV:
|
||||
scope = "LV";
|
||||
switch (cmdl & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE & LCK_MASK:
|
||||
command = "LCK_LV_EXCLUSIVE";
|
||||
break;
|
||||
case LCK_LV_SUSPEND & LCK_MASK:
|
||||
command = "LCK_LV_SUSPEND";
|
||||
break;
|
||||
case LCK_LV_RESUME & LCK_MASK:
|
||||
command = "LCK_LV_RESUME";
|
||||
break;
|
||||
case LCK_LV_ACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_ACTIVATE";
|
||||
break;
|
||||
case LCK_LV_DEACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_DEACTIVATE";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
scope = "unknown";
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buf, "0x%x %s (%s|%s%s%s%s%s)", cmdl, command, type, scope,
|
||||
cmdl & LCK_NONBLOCK ? "|NONBLOCK" : "",
|
||||
cmdl & LCK_HOLD ? "|HOLD" : "",
|
||||
cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
|
||||
cmdl & LCK_CACHE ? "|CACHE" : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only processes 8 bits: excludes LCK_CACHE.
|
||||
*/
|
||||
static const char *decode_locking_cmd(unsigned char cmdl)
|
||||
{
|
||||
return decode_full_locking_cmd((uint32_t) cmdl);
|
||||
}
|
||||
|
||||
static const char *decode_flags(unsigned char flags)
|
||||
{
|
||||
static char buf[128];
|
||||
int len;
|
||||
|
||||
len = sprintf(buf, "0x%x ( %s%s%s%s%s%s%s)", flags,
|
||||
flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE|" : "",
|
||||
flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC|" : "",
|
||||
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
|
||||
flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
|
||||
flags & LCK_TEST_MODE ? "TEST|" : "",
|
||||
flags & LCK_CONVERT ? "CONVERT|" : "",
|
||||
flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "");
|
||||
|
||||
if (len > 1)
|
||||
buf[len - 2] = ' ';
|
||||
else
|
||||
buf[0] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *get_last_lvm_error(void)
|
||||
{
|
||||
return last_error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash lock info helpers
|
||||
*/
|
||||
static struct lv_info *lookup_info(const char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = dm_hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
|
||||
return lvi;
|
||||
}
|
||||
|
||||
static int insert_info(const char *resource, struct lv_info *lvi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
ret = dm_hash_insert(lv_hash, resource, lvi);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void remove_info(const char *resource)
|
||||
{
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
dm_hash_remove(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the mode a lock is currently held at (or -1 if not held)
|
||||
*/
|
||||
static int get_current_lock(char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
if ((lvi = lookup_info(resource)))
|
||||
return lvi->lock_mode;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void init_lvhash(void)
|
||||
{
|
||||
/* Create hash table for keeping LV locks & status */
|
||||
lv_hash = dm_hash_create(1024);
|
||||
pthread_mutex_init(&lv_hash_lock, NULL);
|
||||
pthread_mutex_init(&lvm_lock, NULL);
|
||||
}
|
||||
|
||||
/* Called at shutdown to tidy the lockspace */
|
||||
void destroy_lvhash(void)
|
||||
{
|
||||
struct dm_hash_node *v;
|
||||
struct lv_info *lvi;
|
||||
char *resource;
|
||||
int status;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
|
||||
dm_hash_iterate(v, lv_hash) {
|
||||
lvi = dm_hash_get_data(lv_hash, v);
|
||||
resource = dm_hash_get_key(lv_hash, v);
|
||||
|
||||
if ((status = sync_unlock(resource, lvi->lock_id)))
|
||||
DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
|
||||
status, strerror(errno));
|
||||
free(lvi);
|
||||
}
|
||||
|
||||
dm_hash_destroy(lv_hash);
|
||||
lv_hash = NULL;
|
||||
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
/* Gets a real lock and keeps the info in the hash table */
|
||||
static int hold_lock(char *resource, int mode, int flags)
|
||||
{
|
||||
int status;
|
||||
int saved_errno;
|
||||
struct lv_info *lvi;
|
||||
|
||||
if (test_mode())
|
||||
return 0;
|
||||
|
||||
/* Mask off invalid options */
|
||||
flags &= LCKF_NOQUEUE | LCKF_CONVERT;
|
||||
|
||||
lvi = lookup_info(resource);
|
||||
|
||||
if (lvi) {
|
||||
if (lvi->lock_mode == mode) {
|
||||
DEBUGLOG("hold_lock, lock mode %d already held\n",
|
||||
mode);
|
||||
return 0;
|
||||
}
|
||||
if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
|
||||
DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
|
||||
"ignoring LCK_WRITE request");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only allow explicit conversions */
|
||||
if (lvi && !(flags & LCKF_CONVERT)) {
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
if (lvi) {
|
||||
/* Already exists - convert it */
|
||||
status =
|
||||
sync_lock(resource, mode, flags, &lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status)
|
||||
lvi->lock_mode = mode;
|
||||
|
||||
if (status) {
|
||||
DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
|
||||
strerror(errno));
|
||||
}
|
||||
errno = saved_errno;
|
||||
} else {
|
||||
lvi = malloc(sizeof(struct lv_info));
|
||||
if (!lvi) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
lvi->lock_mode = mode;
|
||||
status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (status) {
|
||||
free(lvi);
|
||||
DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
|
||||
strerror(errno));
|
||||
} else
|
||||
if (!insert_info(resource, lvi)) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Unlock and remove it from the hash table */
|
||||
static int hold_unlock(char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
int status;
|
||||
int saved_errno;
|
||||
|
||||
if (test_mode())
|
||||
return 0;
|
||||
|
||||
if (!(lvi = lookup_info(resource))) {
|
||||
DEBUGLOG("hold_unlock, lock not already held\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = sync_unlock(resource, lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status) {
|
||||
remove_info(resource);
|
||||
free(lvi);
|
||||
} else {
|
||||
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Watch the return codes here.
|
||||
liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
|
||||
libdlm API functions return 0 for success, -1 for failure and do set errno.
|
||||
These functions here return 0 for success or >0 for failure (where the retcode is errno)
|
||||
*/
|
||||
|
||||
/* Activate LV exclusive or non-exclusive */
|
||||
static int do_activate_lv(char *resource, unsigned char command, unsigned char lock_flags, int mode)
|
||||
{
|
||||
int oldmode;
|
||||
int status;
|
||||
int activate_lv;
|
||||
int exclusive = 0;
|
||||
struct lvinfo lvi;
|
||||
|
||||
/* Is it already open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == mode && (command & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_activate_lv, lock already held at %d\n", oldmode);
|
||||
return 0; /* Nothing to do */
|
||||
}
|
||||
|
||||
/* Does the config file want us to activate this LV ? */
|
||||
if (!lv_activation_filter(cmd, resource, &activate_lv))
|
||||
return EIO;
|
||||
|
||||
if (!activate_lv)
|
||||
return 0; /* Success, we did nothing! */
|
||||
|
||||
/* Do we need to activate exclusively? */
|
||||
if ((activate_lv == 2) || (mode == LCK_EXCL)) {
|
||||
exclusive = 1;
|
||||
mode = LCK_EXCL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get the lock if it's a clustered volume group.
|
||||
* Use lock conversion only if requested, to prevent implicit conversion
|
||||
* of exclusive lock to shared one during activation.
|
||||
*/
|
||||
if (command & LCK_CLUSTER_VG) {
|
||||
status = hold_lock(resource, mode, LCKF_NOQUEUE | (lock_flags & LCK_CONVERT ? LCKF_CONVERT:0));
|
||||
if (status) {
|
||||
/* Return an LVM-sensible error for this.
|
||||
* Forcing EIO makes the upper level return this text
|
||||
* rather than the strerror text for EAGAIN.
|
||||
*/
|
||||
if (errno == EAGAIN) {
|
||||
sprintf(last_error, "Volume is busy on another node");
|
||||
errno = EIO;
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's suspended then resume it */
|
||||
if (!lv_info_by_lvid(cmd, resource, 0, &lvi, 0, 0))
|
||||
goto error;
|
||||
|
||||
if (lvi.suspended) {
|
||||
critical_section_inc(cmd, "resuming");
|
||||
if (!lv_resume(cmd, resource, 0)) {
|
||||
critical_section_dec(cmd, "resumed");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now activate it */
|
||||
if (!lv_activate(cmd, resource, exclusive))
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (oldmode == -1 || oldmode != mode)
|
||||
(void)hold_unlock(resource);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
/* Resume the LV if it was active */
|
||||
static int do_resume_lv(char *resource, unsigned char command, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode, origin_only, exclusive, revert;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_resume_lv, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
|
||||
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
|
||||
revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0;
|
||||
|
||||
if (!lv_resume_if_active(cmd, resource, origin_only, exclusive, revert))
|
||||
return EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Suspend the device if active */
|
||||
static int do_suspend_lv(char *resource, unsigned char command, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode;
|
||||
unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
|
||||
unsigned exclusive;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_suspend_lv, lock not already held\n");
|
||||
return 0; /* Not active, so it's OK */
|
||||
}
|
||||
|
||||
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
|
||||
|
||||
/* Always call lv_suspend to read commited and precommited data */
|
||||
if (!lv_suspend_if_active(cmd, resource, origin_only, exclusive))
|
||||
return EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_deactivate_lv(char *resource, unsigned char command, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode;
|
||||
int status;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_deactivate_lock, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
|
||||
if (!lv_deactivate(cmd, resource))
|
||||
return EIO;
|
||||
|
||||
if (command & LCK_CLUSTER_VG) {
|
||||
status = hold_unlock(resource);
|
||||
if (status)
|
||||
return errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *do_lock_query(char *resource)
|
||||
{
|
||||
int mode;
|
||||
const char *type = NULL;
|
||||
|
||||
mode = get_current_lock(resource);
|
||||
switch (mode) {
|
||||
case LCK_NULL: type = "NL"; break;
|
||||
case LCK_READ: type = "CR"; break;
|
||||
case LCK_PREAD:type = "PR"; break;
|
||||
case LCK_WRITE:type = "PW"; break;
|
||||
case LCK_EXCL: type = "EX"; break;
|
||||
}
|
||||
|
||||
DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "?");
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* This is the LOCK_LV part that happens on all nodes in the cluster -
|
||||
it is responsible for the interaction with device-mapper and LVM */
|
||||
int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags), critical_section());
|
||||
|
||||
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||
/* Reinitialise various settings inc. logging, filters */
|
||||
if (do_refresh_cache()) {
|
||||
log_error("Updated config file invalid. Aborting.");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||
init_mirror_in_sync(1);
|
||||
|
||||
if (lock_flags & LCK_DMEVENTD_MONITOR_IGNORE)
|
||||
init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
|
||||
else {
|
||||
if (lock_flags & LCK_DMEVENTD_MONITOR_MODE)
|
||||
init_dmeventd_monitor(1);
|
||||
else
|
||||
init_dmeventd_monitor(0);
|
||||
}
|
||||
|
||||
cmd->partial_activation = (lock_flags & LCK_PARTIAL_MODE) ? 1 : 0;
|
||||
|
||||
/* clvmd should never try to read suspended device */
|
||||
init_ignore_suspended_devices(1);
|
||||
|
||||
switch (command & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, command, lock_flags, LCK_EXCL);
|
||||
break;
|
||||
|
||||
case LCK_LV_SUSPEND:
|
||||
status = do_suspend_lv(resource, command, lock_flags);
|
||||
break;
|
||||
|
||||
case LCK_UNLOCK:
|
||||
case LCK_LV_RESUME: /* if active */
|
||||
status = do_resume_lv(resource, command, lock_flags);
|
||||
break;
|
||||
|
||||
case LCK_LV_ACTIVATE:
|
||||
status = do_activate_lv(resource, command, lock_flags, LCK_READ);
|
||||
break;
|
||||
|
||||
case LCK_LV_DEACTIVATE:
|
||||
status = do_deactivate_lv(resource, command, lock_flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUGLOG("Invalid LV command 0x%x\n", command);
|
||||
status = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||
init_mirror_in_sync(0);
|
||||
|
||||
cmd->partial_activation = 0;
|
||||
|
||||
/* clean the pool for another command */
|
||||
dm_pool_empty(cmd->mem);
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
|
||||
DEBUGLOG("Command return is %d, critical_section is %d\n", status, critical_section());
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
|
||||
int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
|
||||
lock out on this node (because we are the node modifying the metadata)
|
||||
before suspending cluster-wide.
|
||||
LCKF_CONVERT is used always, local node is going to modify metadata
|
||||
*/
|
||||
if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND &&
|
||||
(command & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
if (hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT))
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
|
||||
int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
char *resource)
|
||||
{
|
||||
int status;
|
||||
unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
|
||||
|
||||
/* Opposite of above, done on resume after a metadata update */
|
||||
if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME &&
|
||||
(command & LCK_CLUSTER_VG)) {
|
||||
int oldmode;
|
||||
|
||||
DEBUGLOG
|
||||
("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
/* If the lock state is PW then restore it to what it was */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == LCK_WRITE) {
|
||||
struct lvinfo lvi;
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
status = lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0);
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
if (!status)
|
||||
return EIO;
|
||||
|
||||
if (lvi.exists) {
|
||||
if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
|
||||
return errno;
|
||||
} else if (hold_unlock(resource))
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if a VG is in use by LVM1 so we don't stomp on it */
|
||||
int do_check_lvm1(const char *vgname)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = check_lvm1_vg_inactive(cmd, vgname);
|
||||
|
||||
return status == 1 ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
int do_refresh_cache(void)
|
||||
{
|
||||
DEBUGLOG("Refreshing context\n");
|
||||
log_notice("Refreshing context");
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
|
||||
if (!refresh_toolcontext(cmd)) {
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
init_full_scan_done(0);
|
||||
init_ignore_suspended_devices(1);
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle VG lock - drop metadata or update lvmcache state
|
||||
*/
|
||||
void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
uint32_t lock_cmd = command;
|
||||
char *vgname = resource + 2;
|
||||
|
||||
lock_cmd &= (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_HOLD);
|
||||
|
||||
/*
|
||||
* Check if LCK_CACHE should be set. All P_ locks except # are cache related.
|
||||
*/
|
||||
if (strncmp(resource, "P_#", 3) && !strncmp(resource, "P_", 2))
|
||||
lock_cmd |= LCK_CACHE;
|
||||
|
||||
DEBUGLOG("do_lock_vg: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
|
||||
resource, decode_full_locking_cmd(lock_cmd), decode_flags(lock_flags), critical_section());
|
||||
|
||||
/* P_#global causes a full cache refresh */
|
||||
if (!strcmp(resource, "P_" VG_GLOBAL)) {
|
||||
do_refresh_cache();
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
switch (lock_cmd) {
|
||||
case LCK_VG_COMMIT:
|
||||
DEBUGLOG("vg_commit notification for VG %s\n", vgname);
|
||||
lvmcache_commit_metadata(vgname);
|
||||
break;
|
||||
case LCK_VG_REVERT:
|
||||
DEBUGLOG("vg_revert notification for VG %s\n", vgname);
|
||||
lvmcache_drop_metadata(vgname, 1);
|
||||
break;
|
||||
case LCK_VG_DROP_CACHE:
|
||||
default:
|
||||
DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
|
||||
lvmcache_drop_metadata(vgname, 0);
|
||||
}
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ideally, clvmd should be started before any LVs are active
|
||||
* but this may not be the case...
|
||||
* I suppose this also comes in handy if clvmd crashes, not that it would!
|
||||
*/
|
||||
static int get_initial_state(struct dm_hash_table *excl_uuid)
|
||||
{
|
||||
int lock_mode;
|
||||
char lv[64], vg[64], flags[25], vg_flags[25];
|
||||
char uuid[65];
|
||||
char line[255];
|
||||
char *lvs_cmd;
|
||||
const char *lvm_binary = getenv("LVM_BINARY") ? : LVM_PATH;
|
||||
FILE *lvs;
|
||||
|
||||
if (dm_asprintf(&lvs_cmd, "%s lvs --config 'log{command_names=0 prefix=\"\"}' "
|
||||
"--nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
|
||||
lvm_binary) < 0)
|
||||
return_0;
|
||||
|
||||
/* FIXME: Maybe link and use liblvm2cmd directly instead of fork */
|
||||
if (!(lvs = popen(lvs_cmd, "r"))) {
|
||||
dm_free(lvs_cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), lvs)) {
|
||||
if (sscanf(line, "%64s %64s %25s %25s\n", vg, lv, flags, vg_flags) == 4) {
|
||||
|
||||
/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
|
||||
if (strlen(vg) == 38 && /* is is a valid UUID ? */
|
||||
(flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */
|
||||
vg_flags[5] == 'c') { /* is it clustered ? */
|
||||
/* Convert hyphen-separated UUIDs into one */
|
||||
memcpy(&uuid[0], &vg[0], 6);
|
||||
memcpy(&uuid[6], &vg[7], 4);
|
||||
memcpy(&uuid[10], &vg[12], 4);
|
||||
memcpy(&uuid[14], &vg[17], 4);
|
||||
memcpy(&uuid[18], &vg[22], 4);
|
||||
memcpy(&uuid[22], &vg[27], 4);
|
||||
memcpy(&uuid[26], &vg[32], 6);
|
||||
memcpy(&uuid[32], &lv[0], 6);
|
||||
memcpy(&uuid[38], &lv[7], 4);
|
||||
memcpy(&uuid[42], &lv[12], 4);
|
||||
memcpy(&uuid[46], &lv[17], 4);
|
||||
memcpy(&uuid[50], &lv[22], 4);
|
||||
memcpy(&uuid[54], &lv[27], 4);
|
||||
memcpy(&uuid[58], &lv[32], 6);
|
||||
uuid[64] = '\0';
|
||||
|
||||
/* Look for this lock in the list of EX locks
|
||||
we were passed on the command-line */
|
||||
lock_mode = (dm_hash_lookup(excl_uuid, uuid)) ?
|
||||
LCK_EXCL : LCK_READ;
|
||||
|
||||
DEBUGLOG("getting initial lock for %s\n", uuid);
|
||||
if (hold_lock(uuid, lock_mode, LCKF_NOQUEUE))
|
||||
DEBUGLOG("Failed to hold lock %s\n", uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pclose(lvs))
|
||||
DEBUGLOG("lvs pclose failed: %s\n", strerror(errno));
|
||||
|
||||
dm_free(lvs_cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void lvm2_log_fn(int level, const char *file, int line, int dm_errno,
|
||||
const char *message)
|
||||
{
|
||||
|
||||
/* Send messages to the normal LVM2 logging system too,
|
||||
so we get debug output when it's asked for.
|
||||
We need to NULL the function ptr otherwise it will just call
|
||||
back into here! */
|
||||
init_log_fn(NULL);
|
||||
print_log(level, file, line, dm_errno, "%s", message);
|
||||
init_log_fn(lvm2_log_fn);
|
||||
|
||||
/*
|
||||
* Ignore non-error messages, but store the latest one for returning
|
||||
* to the user.
|
||||
*/
|
||||
if (level != _LOG_ERR && level != _LOG_FATAL)
|
||||
return;
|
||||
|
||||
strncpy(last_error, message, sizeof(last_error));
|
||||
last_error[sizeof(last_error)-1] = '\0';
|
||||
}
|
||||
|
||||
/* This checks some basic cluster-LVM configuration stuff */
|
||||
static void check_config(void)
|
||||
{
|
||||
int locking_type;
|
||||
|
||||
locking_type = find_config_tree_int(cmd, global_locking_type_CFG);
|
||||
|
||||
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_CFG);
|
||||
if (libname && strstr(libname, "liblvm2clusterlock.so"))
|
||||
return;
|
||||
|
||||
log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
|
||||
return;
|
||||
}
|
||||
log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
|
||||
}
|
||||
|
||||
/* Backups up the LVM metadata if it's changed */
|
||||
void lvm_do_backup(const char *vgname)
|
||||
{
|
||||
struct volume_group * vg;
|
||||
int consistent = 0;
|
||||
|
||||
DEBUGLOG("Triggering backup of VG metadata for %s.\n", vgname);
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
|
||||
vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, 1, &consistent);
|
||||
|
||||
if (vg && consistent)
|
||||
check_current_backup(vg);
|
||||
else
|
||||
log_error("Error backing up metadata, can't find VG for group %s", vgname);
|
||||
|
||||
release_vg(vg);
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
*name = NULL;
|
||||
if (!v)
|
||||
v = dm_hash_get_first(lv_hash);
|
||||
|
||||
do {
|
||||
if (v) {
|
||||
lvi = dm_hash_get_data(lv_hash, v);
|
||||
DEBUGLOG("Looking for EX locks. found %x mode %d\n", lvi->lock_id, lvi->lock_mode);
|
||||
|
||||
if (lvi->lock_mode == LCK_EXCL) {
|
||||
*name = dm_hash_get_key(lv_hash, v);
|
||||
}
|
||||
v = dm_hash_get_next(lv_hash, v);
|
||||
}
|
||||
} while (v && !*name);
|
||||
|
||||
if (*name)
|
||||
DEBUGLOG("returning EXclusive UUID %s\n", *name);
|
||||
return v;
|
||||
}
|
||||
|
||||
void lvm_do_fs_unlock(void)
|
||||
{
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
DEBUGLOG("Syncing device names\n");
|
||||
fs_unlock();
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
/* Called to initialise the LVM context of the daemon */
|
||||
int init_clvm(struct dm_hash_table *excl_uuid)
|
||||
{
|
||||
/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
|
||||
init_syslog(LOG_DAEMON);
|
||||
openlog("clvmd", LOG_PID, LOG_DAEMON);
|
||||
|
||||
/* Initialise already held locks */
|
||||
if (!get_initial_state(excl_uuid))
|
||||
log_error("Cannot load initial lock states.");
|
||||
|
||||
if (!(cmd = create_toolcontext(1, NULL, 0, 1))) {
|
||||
log_error("Failed to allocate command context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stored_errno()) {
|
||||
destroy_toolcontext(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd->cmd_line = "clvmd";
|
||||
|
||||
/* Check lvm.conf is setup for cluster-LVM */
|
||||
check_config();
|
||||
init_ignore_suspended_devices(1);
|
||||
|
||||
/* Trap log messages so we can pass them back to the user */
|
||||
init_log_fn(lvm2_log_fn);
|
||||
memlock_inc_daemon(cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void destroy_lvm(void)
|
||||
{
|
||||
if (cmd) {
|
||||
memlock_dec_daemon(cmd);
|
||||
destroy_toolcontext(cmd);
|
||||
}
|
||||
cmd = NULL;
|
||||
}
|
||||
41
daemons/clvmd/lvm-functions.h
Normal file
41
daemons/clvmd/lvm-functions.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Functions in lvm-functions.c */
|
||||
|
||||
#ifndef _LVM_FUNCTIONS_H
|
||||
#define _LVM_FUNCTIONS_H
|
||||
|
||||
extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern const char *do_lock_query(char *resource);
|
||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_check_lvm1(const char *vgname);
|
||||
extern int do_refresh_cache(void);
|
||||
extern int init_clvm(struct dm_hash_table *excl_uuid);
|
||||
extern void destroy_lvm(void);
|
||||
extern void init_lvhash(void);
|
||||
extern void destroy_lvhash(void);
|
||||
extern void lvm_do_backup(const char *vgname);
|
||||
extern char *get_last_lvm_error(void);
|
||||
extern void do_lock_vg(unsigned char command, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name);
|
||||
void lvm_do_fs_unlock(void);
|
||||
|
||||
#endif
|
||||
382
daemons/clvmd/refresh_clvmd.c
Normal file
382
daemons/clvmd/refresh_clvmd.c
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* FIXME Remove duplicated functions from this file. */
|
||||
|
||||
/*
|
||||
* Send a command to a running clvmd from the command-line
|
||||
*/
|
||||
|
||||
#include "clvmd-common.h"
|
||||
|
||||
#include "clvm.h"
|
||||
#include "refresh_clvmd.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
typedef struct lvm_response {
|
||||
char node[255];
|
||||
char *response;
|
||||
int status;
|
||||
int len;
|
||||
} lvm_response_t;
|
||||
|
||||
/*
|
||||
* This gets stuck at the start of memory we allocate so we
|
||||
* can sanity-check it at deallocation time
|
||||
*/
|
||||
#define LVM_SIGNATURE 0x434C564D
|
||||
|
||||
static int _clvmd_sock = -1;
|
||||
|
||||
/* Open connection to the clvm daemon */
|
||||
static int _open_local_sock(void)
|
||||
{
|
||||
int local_socket;
|
||||
struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
|
||||
|
||||
if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
|
||||
fprintf(stderr, "%s: clvmd socket name too long.", CLVMD_SOCKNAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Open local socket */
|
||||
if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||
fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(local_socket,(struct sockaddr *) &sockaddr,
|
||||
sizeof(sockaddr))) {
|
||||
int saved_errno = errno;
|
||||
|
||||
fprintf(stderr, "connect() failed on local socket: %s\n",
|
||||
strerror(errno));
|
||||
if (close(local_socket))
|
||||
return -1;
|
||||
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return local_socket;
|
||||
}
|
||||
|
||||
/* Send a request and return the status */
|
||||
static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response)
|
||||
{
|
||||
char outbuf[PIPE_BUF];
|
||||
struct clvm_header *outheader = (struct clvm_header *) outbuf;
|
||||
int len;
|
||||
unsigned off;
|
||||
int buflen;
|
||||
int err;
|
||||
|
||||
/* Send it to CLVMD */
|
||||
rewrite:
|
||||
if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
|
||||
if (err == -1 && errno == EINTR)
|
||||
goto rewrite;
|
||||
fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (no_response)
|
||||
return 1;
|
||||
|
||||
/* Get the response */
|
||||
reread:
|
||||
if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
|
||||
if (errno == EINTR)
|
||||
goto reread;
|
||||
fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
fprintf(stderr, "EOF reading CLVMD");
|
||||
errno = ENOTCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
buflen = len + outheader->arglen;
|
||||
*retbuf = dm_malloc(buflen);
|
||||
if (!*retbuf) {
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the header */
|
||||
memcpy(*retbuf, outbuf, len);
|
||||
outheader = (struct clvm_header *) *retbuf;
|
||||
|
||||
/* Read the returned values */
|
||||
off = 1; /* we've already read the first byte */
|
||||
while (off <= outheader->arglen && len > 0) {
|
||||
len = read(_clvmd_sock, outheader->args + off,
|
||||
buflen - off - offsetof(struct clvm_header, args));
|
||||
if (len > 0)
|
||||
off += len;
|
||||
}
|
||||
|
||||
/* Was it an error ? */
|
||||
if (outheader->status != 0) {
|
||||
errno = outheader->status;
|
||||
|
||||
/* Only return an error here if there are no node-specific
|
||||
errors present in the message that might have more detail */
|
||||
if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
|
||||
fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Build the structure header and parse-out wildcard node names */
|
||||
static void _build_header(struct clvm_header *head, int cmd, const char *node,
|
||||
unsigned int len)
|
||||
{
|
||||
head->cmd = cmd;
|
||||
head->status = 0;
|
||||
head->flags = 0;
|
||||
head->xid = 0;
|
||||
head->clientid = 0;
|
||||
if (len)
|
||||
/* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */
|
||||
head->arglen = len - 1;
|
||||
else {
|
||||
head->arglen = 0;
|
||||
*head->args = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate special node names.
|
||||
*/
|
||||
if (!node || !strcmp(node, NODE_ALL))
|
||||
head->node[0] = '\0';
|
||||
else if (!strcmp(node, NODE_LOCAL)) {
|
||||
head->node[0] = '\0';
|
||||
head->flags = CLVMD_FLAG_LOCAL;
|
||||
} else
|
||||
strcpy(head->node, node);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a message to a(or all) node(s) in the cluster and wait for replies
|
||||
*/
|
||||
static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num, int no_response)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
char *inptr;
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
int i;
|
||||
int num_responses = 0;
|
||||
struct clvm_header *head = (struct clvm_header *) outbuf;
|
||||
lvm_response_t *rarray;
|
||||
|
||||
*num = 0;
|
||||
|
||||
if (_clvmd_sock == -1)
|
||||
_clvmd_sock = _open_local_sock();
|
||||
|
||||
if (_clvmd_sock == -1)
|
||||
return 0;
|
||||
|
||||
_build_header(head, cmd, node, len);
|
||||
if (len)
|
||||
memcpy(head->node + strlen(head->node) + 1, data, len);
|
||||
|
||||
status = _send_request(outbuf, sizeof(struct clvm_header) +
|
||||
strlen(head->node) + len, &retbuf, no_response);
|
||||
if (!status || no_response)
|
||||
goto out;
|
||||
|
||||
/* Count the number of responses we got */
|
||||
head = (struct clvm_header *) retbuf;
|
||||
inptr = head->args;
|
||||
while (inptr[0]) {
|
||||
num_responses++;
|
||||
inptr += strlen(inptr) + 1;
|
||||
inptr += sizeof(int);
|
||||
inptr += strlen(inptr) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate response array.
|
||||
* With an extra pair of INTs on the front to sanity
|
||||
* check the pointer when we are given it back to free
|
||||
*/
|
||||
*response = NULL;
|
||||
if (!(rarray = dm_malloc(sizeof(lvm_response_t) * num_responses +
|
||||
sizeof(int) * 2))) {
|
||||
errno = ENOMEM;
|
||||
status = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Unpack the response into an lvm_response_t array */
|
||||
inptr = head->args;
|
||||
i = 0;
|
||||
while (inptr[0]) {
|
||||
strcpy(rarray[i].node, inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
|
||||
memcpy(&rarray[i].status, inptr, sizeof(int));
|
||||
inptr += sizeof(int);
|
||||
|
||||
rarray[i].response = dm_malloc(strlen(inptr) + 1);
|
||||
if (rarray[i].response == NULL) {
|
||||
/* Free up everything else and return error */
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
dm_free(rarray[i].response);
|
||||
dm_free(rarray);
|
||||
errno = ENOMEM;
|
||||
status = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
strcpy(rarray[i].response, inptr);
|
||||
rarray[i].len = strlen(inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
i++;
|
||||
}
|
||||
*num = num_responses;
|
||||
*response = rarray;
|
||||
|
||||
out:
|
||||
dm_free(retbuf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Free reply array */
|
||||
static int _cluster_free_request(lvm_response_t * response, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
dm_free(response[i].response);
|
||||
}
|
||||
|
||||
dm_free(response);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int refresh_clvmd(int all_nodes)
|
||||
{
|
||||
int num_responses;
|
||||
char args[1]; // No args really.
|
||||
lvm_response_t *response = NULL;
|
||||
int saved_errno;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes ? NODE_ALL : NODE_LOCAL, args, 0, &response, &num_responses, 0);
|
||||
|
||||
/* If any nodes were down then display them and return an error */
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status == EHOSTDOWN) {
|
||||
fprintf(stderr, "clvmd not running on node %s",
|
||||
response[i].node);
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
} else if (response[i].status) {
|
||||
fprintf(stderr, "Error resetting node %s: %s",
|
||||
response[i].node,
|
||||
response[i].response[0] ?
|
||||
response[i].response :
|
||||
strerror(response[i].status));
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
}
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
_cluster_free_request(response, num_responses);
|
||||
errno = saved_errno;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int restart_clvmd(int all_nodes)
|
||||
{
|
||||
int dummy, status;
|
||||
|
||||
status = _cluster_request(CLVMD_CMD_RESTART, all_nodes ? NODE_ALL : NODE_LOCAL, NULL, 0, NULL, &dummy, 1);
|
||||
|
||||
/*
|
||||
* FIXME: we cannot receive response, clvmd re-exec before it.
|
||||
* but also should not close socket too early (the whole rq is dropped then).
|
||||
* FIXME: This should be handled this way:
|
||||
* - client waits for RESTART ack (and socket close)
|
||||
* - server restarts
|
||||
* - client checks that server is ready again (VERSION command?)
|
||||
*/
|
||||
usleep(500000);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int debug_clvmd(int level, int clusterwide)
|
||||
{
|
||||
int num_responses;
|
||||
char args[1];
|
||||
const char *nodes;
|
||||
lvm_response_t *response = NULL;
|
||||
int saved_errno;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
args[0] = level;
|
||||
if (clusterwide)
|
||||
nodes = NODE_ALL;
|
||||
else
|
||||
nodes = NODE_LOCAL;
|
||||
|
||||
status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0);
|
||||
|
||||
/* If any nodes were down then display them and return an error */
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status == EHOSTDOWN) {
|
||||
fprintf(stderr, "clvmd not running on node %s",
|
||||
response[i].node);
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
} else if (response[i].status) {
|
||||
fprintf(stderr, "Error setting debug on node %s: %s",
|
||||
response[i].node,
|
||||
response[i].response[0] ?
|
||||
response[i].response :
|
||||
strerror(response[i].status));
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
}
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
_cluster_free_request(response, num_responses);
|
||||
errno = saved_errno;
|
||||
|
||||
return status;
|
||||
}
|
||||
19
daemons/clvmd/refresh_clvmd.h
Normal file
19
daemons/clvmd/refresh_clvmd.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
int refresh_clvmd(int all_nodes);
|
||||
int restart_clvmd(int all_nodes);
|
||||
int debug_clvmd(int level, int clusterwide);
|
||||
|
||||
38
daemons/cmirrord/Makefile.in
Normal file
38
daemons/cmirrord/Makefile.in
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
CPG_LIBS = @CPG_LIBS@
|
||||
CPG_CFLAGS = @CPG_CFLAGS@
|
||||
SACKPT_LIBS = @SACKPT_LIBS@
|
||||
SACKPT_CFLAGS = @SACKPT_CFLAGS@
|
||||
|
||||
SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
|
||||
|
||||
TARGETS = cmirrord
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper
|
||||
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
|
||||
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS)
|
||||
|
||||
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
install: $(TARGETS)
|
||||
$(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
|
||||
250
daemons/cmirrord/clogd.c
Normal file
250
daemons/cmirrord/clogd.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "common.h"
|
||||
#include "functions.h"
|
||||
#include "link_mon.h"
|
||||
#include "local.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static volatile sig_atomic_t exit_now = 0;
|
||||
/* FIXME Review signal handling. Should be volatile sig_atomic_t */
|
||||
static sigset_t signal_mask;
|
||||
static volatile sig_atomic_t signal_received;
|
||||
|
||||
static void process_signals(void);
|
||||
static void daemonize(void);
|
||||
static void init_all(void);
|
||||
static void cleanup_all(void);
|
||||
|
||||
int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||
{
|
||||
daemonize();
|
||||
|
||||
init_all();
|
||||
|
||||
/* Parent can now exit, we're ready to handle requests */
|
||||
kill(getppid(), SIGTERM);
|
||||
|
||||
LOG_PRINT("Starting cmirrord:");
|
||||
LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
|
||||
LOG_DBG(" Compiled with debugging.");
|
||||
|
||||
while (!exit_now) {
|
||||
links_monitor();
|
||||
|
||||
links_issue_callbacks();
|
||||
|
||||
process_signals();
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* parent_exit_handler: exit the parent
|
||||
* @sig: the signal
|
||||
*
|
||||
*/
|
||||
static void parent_exit_handler(int sig __attribute__((unused)))
|
||||
{
|
||||
exit_now = 1;
|
||||
}
|
||||
|
||||
static void sig_handler(int sig)
|
||||
{
|
||||
/* FIXME Races - don't touch signal_mask here. */
|
||||
sigaddset(&signal_mask, sig);
|
||||
signal_received = 1;
|
||||
}
|
||||
|
||||
static void process_signal(int sig){
|
||||
int r = 0;
|
||||
|
||||
switch(sig) {
|
||||
case SIGINT:
|
||||
case SIGQUIT:
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
r += log_status();
|
||||
break;
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
log_debug();
|
||||
/*local_debug();*/
|
||||
cluster_debug();
|
||||
return;
|
||||
default:
|
||||
LOG_PRINT("Unknown signal received... ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
LOG_DBG("No current cluster logs... safe to exit.");
|
||||
cleanup_all();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
LOG_ERROR("Cluster logs exist. Refusing to exit.");
|
||||
}
|
||||
|
||||
static void process_signals(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
if (!signal_received)
|
||||
return;
|
||||
|
||||
signal_received = 0;
|
||||
|
||||
for (x = 1; x < _NSIG; x++) {
|
||||
if (sigismember(&signal_mask, x)) {
|
||||
sigdelset(&signal_mask, x);
|
||||
process_signal(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_lockfile(void)
|
||||
{
|
||||
if (unlink(CMIRRORD_PIDFILE))
|
||||
LOG_ERROR("Unable to remove \"" CMIRRORD_PIDFILE "\" %s", strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
* daemonize
|
||||
*
|
||||
* Performs the steps necessary to become a daemon.
|
||||
*/
|
||||
static void daemonize(void)
|
||||
{
|
||||
int pid;
|
||||
int status;
|
||||
int devnull;
|
||||
|
||||
if ((devnull = open("/dev/null", O_RDWR)) == -1) {
|
||||
LOG_ERROR("Can't open /dev/null: %s", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
signal(SIGTERM, &parent_exit_handler);
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
LOG_ERROR("Unable to fork()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid) {
|
||||
/* Parent waits here for child to get going */
|
||||
while (!waitpid(pid, &status, WNOHANG) && !exit_now);
|
||||
if (exit_now)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
switch (WEXITSTATUS(status)) {
|
||||
case EXIT_LOCKFILE:
|
||||
LOG_ERROR("Failed to create lockfile");
|
||||
LOG_ERROR("Process already running?");
|
||||
break;
|
||||
case EXIT_KERNEL_SOCKET:
|
||||
LOG_ERROR("Unable to create netlink socket");
|
||||
break;
|
||||
case EXIT_KERNEL_BIND:
|
||||
LOG_ERROR("Unable to bind to netlink socket");
|
||||
break;
|
||||
case EXIT_KERNEL_SETSOCKOPT:
|
||||
LOG_ERROR("Unable to setsockopt on netlink socket");
|
||||
break;
|
||||
case EXIT_CLUSTER_CKPT_INIT:
|
||||
LOG_ERROR("Unable to initialize checkpoint service");
|
||||
LOG_ERROR("Has the cluster infrastructure been started?");
|
||||
break;
|
||||
case EXIT_FAILURE:
|
||||
LOG_ERROR("Failed to start: Generic error");
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Failed to start: Unknown error");
|
||||
break;
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
setsid();
|
||||
if (chdir("/")) {
|
||||
LOG_ERROR("Failed to chdir /: %s", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
umask(0);
|
||||
|
||||
if (close(0) || close(1) || close(2)) {
|
||||
LOG_ERROR("Failed to close terminal FDs");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((dup2(devnull, 0) < 0) || /* reopen stdin */
|
||||
(dup2(devnull, 1) < 0) || /* reopen stdout */
|
||||
(dup2(devnull, 2) < 0)) /* reopen stderr */
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
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();
|
||||
}
|
||||
1758
daemons/cmirrord/cluster.c
Normal file
1758
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 */
|
||||
1955
daemons/cmirrord/functions.c
Normal file
1955
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 */
|
||||
424
daemons/cmirrord/local.c
Normal file
424
daemons/cmirrord/local.c
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "common.h"
|
||||
#include "functions.h"
|
||||
#include "link_mon.h"
|
||||
#include "local.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/connector.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef CN_IDX_DM
|
||||
/* Kernel 2.6.31 is required to run this code */
|
||||
#define CN_IDX_DM 0x7 /* Device Mapper */
|
||||
#define CN_VAL_DM_USERSPACE_LOG 0x1
|
||||
#endif
|
||||
|
||||
static int cn_fd = -1; /* Connector (netlink) socket fd */
|
||||
static char recv_buf[2048];
|
||||
static char send_buf[2048];
|
||||
|
||||
|
||||
/* FIXME: merge this function with kernel_send_helper */
|
||||
static int kernel_ack(uint32_t seq, int error)
|
||||
{
|
||||
int r;
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)send_buf;
|
||||
struct cn_msg *msg = NLMSG_DATA(nlh);
|
||||
|
||||
if (error < 0) {
|
||||
LOG_ERROR("Programmer error: error codes must be positive");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
nlh->nlmsg_seq = 0;
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
msg->len = 0;
|
||||
msg->id.idx = CN_IDX_DM;
|
||||
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
|
||||
msg->seq = seq;
|
||||
msg->ack = error;
|
||||
|
||||
r = send(cn_fd, nlh, NLMSG_LENGTH(sizeof(struct cn_msg)), 0);
|
||||
/* FIXME: do better error processing */
|
||||
if (r <= 0)
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* kernel_recv
|
||||
* @rq: the newly allocated request from kernel
|
||||
*
|
||||
* Read requests from the kernel and allocate space for the new request.
|
||||
* If there is no request from the kernel, *rq is NULL.
|
||||
*
|
||||
* This function is not thread safe due to returned stack pointer. In fact,
|
||||
* the returned pointer must not be in-use when this function is called again.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on error
|
||||
*/
|
||||
static int kernel_recv(struct clog_request **rq)
|
||||
{
|
||||
int r = 0;
|
||||
ssize_t len;
|
||||
char *foo;
|
||||
struct cn_msg *msg;
|
||||
struct dm_ulog_request *u_rq;
|
||||
struct nlmsghdr *nlmsg_h;
|
||||
|
||||
*rq = NULL;
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
|
||||
len = recv(cn_fd, recv_buf, sizeof(recv_buf), 0);
|
||||
if (len < 0) {
|
||||
LOG_ERROR("Failed to recv message from kernel");
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nlmsg_h = (struct nlmsghdr *)recv_buf;
|
||||
switch (nlmsg_h->nlmsg_type) {
|
||||
case NLMSG_ERROR:
|
||||
LOG_ERROR("Unable to recv message from kernel: NLMSG_ERROR");
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
case NLMSG_DONE:
|
||||
msg = (struct cn_msg *)NLMSG_DATA((struct nlmsghdr *)recv_buf);
|
||||
len -= (ssize_t)sizeof(struct nlmsghdr);
|
||||
|
||||
if (len < (ssize_t)sizeof(struct cn_msg)) {
|
||||
LOG_ERROR("Incomplete request from kernel received");
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (msg->len > DM_ULOG_REQUEST_SIZE) {
|
||||
LOG_ERROR("Not enough space to receive kernel request (%d/%d)",
|
||||
msg->len, DM_ULOG_REQUEST_SIZE);
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!msg->len)
|
||||
LOG_ERROR("Zero length message received");
|
||||
|
||||
len -= (ssize_t)sizeof(struct cn_msg);
|
||||
|
||||
if (len < msg->len)
|
||||
LOG_ERROR("len = %zd, msg->len = %" PRIu16, len, msg->len);
|
||||
|
||||
msg->data[msg->len] = '\0'; /* Cleaner way to ensure this? */
|
||||
u_rq = (struct dm_ulog_request *)msg->data;
|
||||
|
||||
if (!u_rq->request_type) {
|
||||
LOG_DBG("Bad transmission, requesting resend [%u]",
|
||||
msg->seq);
|
||||
r = -EAGAIN;
|
||||
|
||||
if (kernel_ack(msg->seq, EAGAIN)) {
|
||||
LOG_ERROR("Failed to NACK kernel transmission [%u]",
|
||||
msg->seq);
|
||||
r = -EBADE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we've got sizeof(struct cn_msg) + sizeof(struct nlmsghdr)
|
||||
* worth of space that precede the request structure from the
|
||||
* kernel. Since that space isn't going to be used again, we
|
||||
* can take it for our purposes; rather than allocating a whole
|
||||
* new structure and doing a memcpy.
|
||||
*
|
||||
* We should really make sure 'clog_request' doesn't grow
|
||||
* beyond what is available to us, but we need only check it
|
||||
* once... perhaps at compile time?
|
||||
*/
|
||||
foo = (char *)u_rq;
|
||||
foo -= (sizeof(struct clog_request) - sizeof(struct dm_ulog_request));
|
||||
*rq = (struct clog_request *) foo;
|
||||
|
||||
/* Clear the wrapper container fields */
|
||||
memset(*rq, 0, (size_t)((char *)u_rq - (char *)(*rq)));
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown nlmsg_type");
|
||||
r = -EBADE;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (r)
|
||||
*rq = NULL;
|
||||
|
||||
return (r == -EAGAIN) ? 0 : r;
|
||||
}
|
||||
|
||||
static int kernel_send_helper(void *data, uint16_t out_size)
|
||||
{
|
||||
int r;
|
||||
struct nlmsghdr *nlh;
|
||||
struct cn_msg *msg;
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
nlh = (struct nlmsghdr *)send_buf;
|
||||
nlh->nlmsg_seq = 0; /* FIXME: Is this used? */
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(out_size + sizeof(struct cn_msg));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
msg = NLMSG_DATA(nlh);
|
||||
memcpy(msg->data, data, out_size);
|
||||
msg->len = out_size;
|
||||
msg->id.idx = CN_IDX_DM;
|
||||
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
|
||||
msg->seq = 0;
|
||||
|
||||
r = send(cn_fd, nlh, NLMSG_LENGTH(out_size + sizeof(struct cn_msg)), 0);
|
||||
/* FIXME: do better error processing */
|
||||
if (r <= 0)
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_local_work
|
||||
*
|
||||
* Any processing errors are placed in the 'rq'
|
||||
* structure to be reported back to the kernel.
|
||||
* It may be pointless for this function to
|
||||
* return an int.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
static int do_local_work(void *data __attribute__((unused)))
|
||||
{
|
||||
int r;
|
||||
struct clog_request *rq;
|
||||
struct dm_ulog_request *u_rq = NULL;
|
||||
|
||||
r = kernel_recv(&rq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!rq)
|
||||
return 0;
|
||||
|
||||
u_rq = &rq->u_rq;
|
||||
LOG_DBG("[%s] Request from kernel received: [%s/%u]",
|
||||
SHORT_UUID(u_rq->uuid), RQ_TYPE(u_rq->request_type),
|
||||
u_rq->seq);
|
||||
switch (u_rq->request_type) {
|
||||
case DM_ULOG_CTR:
|
||||
case DM_ULOG_DTR:
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
case DM_ULOG_STATUS_TABLE:
|
||||
case DM_ULOG_PRESUSPEND:
|
||||
/* We do not specify ourselves as server here */
|
||||
r = do_request(rq, 0);
|
||||
if (r)
|
||||
LOG_DBG("Returning failed request to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
r = kernel_send(u_rq);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to respond to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
|
||||
break;
|
||||
case DM_ULOG_RESUME:
|
||||
/*
|
||||
* Resume is a special case that requires a local
|
||||
* component to join the CPG, and a cluster component
|
||||
* to handle the request.
|
||||
*/
|
||||
r = local_resume(u_rq);
|
||||
if (r) {
|
||||
LOG_DBG("Returning failed request to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
r = kernel_send(u_rq);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to respond to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
break;
|
||||
}
|
||||
/* ELSE, fall through */
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_FLUSH:
|
||||
case DM_ULOG_MARK_REGION:
|
||||
case DM_ULOG_GET_RESYNC_WORK:
|
||||
case DM_ULOG_SET_REGION_SYNC:
|
||||
case DM_ULOG_STATUS_INFO:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
case DM_ULOG_POSTSUSPEND:
|
||||
r = cluster_send(rq);
|
||||
if (r) {
|
||||
u_rq->data_size = 0;
|
||||
u_rq->error = r;
|
||||
if (kernel_send(u_rq))
|
||||
LOG_ERROR("Failed to respond to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
}
|
||||
|
||||
break;
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
r = kernel_ack(u_rq->seq, 0);
|
||||
|
||||
r = cluster_send(rq);
|
||||
if (r) {
|
||||
/*
|
||||
* FIXME: store error for delivery on flush
|
||||
* This would allow us to optimize MARK_REGION
|
||||
* too.
|
||||
*/
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Invalid log request received (%u), ignoring.",
|
||||
u_rq->request_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (r && !u_rq->error)
|
||||
u_rq->error = r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* kernel_send
|
||||
* @u_rq: result to pass back to kernel
|
||||
*
|
||||
* This function returns the u_rq structure
|
||||
* (containing the results) to the kernel.
|
||||
* It then frees the structure.
|
||||
*
|
||||
* WARNING: should the structure be freed if
|
||||
* there is an error? I vote 'yes'. If the
|
||||
* kernel doesn't get the response, it should
|
||||
* resend the request.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
int kernel_send(struct dm_ulog_request *u_rq)
|
||||
{
|
||||
int r;
|
||||
uint16_t size;
|
||||
|
||||
if (!u_rq)
|
||||
return -EINVAL;
|
||||
|
||||
size = (uint16_t)(sizeof(struct dm_ulog_request) + u_rq->data_size);
|
||||
|
||||
if (!u_rq->data_size && !u_rq->error) {
|
||||
/* An ACK is all that is needed */
|
||||
|
||||
/* FIXME: add ACK code */
|
||||
} else if (size > DM_ULOG_REQUEST_SIZE) {
|
||||
/*
|
||||
* If we gotten here, we've already overrun
|
||||
* our allotted space somewhere.
|
||||
*
|
||||
* We must do something, because the kernel
|
||||
* is waiting for a response.
|
||||
*/
|
||||
LOG_ERROR("Not enough space to respond to server");
|
||||
u_rq->error = -ENOSPC;
|
||||
size = sizeof(struct dm_ulog_request);
|
||||
}
|
||||
|
||||
r = kernel_send_helper(u_rq, size);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to send msg to kernel.");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_local
|
||||
*
|
||||
* Initialize kernel communication socket (netlink)
|
||||
*
|
||||
* Returns: 0 on success, values from common.h on failure
|
||||
*/
|
||||
int init_local(void)
|
||||
{
|
||||
int r = 0;
|
||||
unsigned opt;
|
||||
struct sockaddr_nl addr;
|
||||
|
||||
cn_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||
if (cn_fd < 0)
|
||||
return EXIT_KERNEL_SOCKET;
|
||||
|
||||
/* memset to fix valgrind complaint */
|
||||
memset(&addr, 0, sizeof(struct sockaddr_nl));
|
||||
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = CN_IDX_DM;
|
||||
addr.nl_pid = 0;
|
||||
|
||||
r = bind(cn_fd, (struct sockaddr *) &addr, sizeof(addr));
|
||||
if (r < 0) {
|
||||
if (close(cn_fd))
|
||||
LOG_ERROR("Failed to close socket: %s",
|
||||
strerror(errno));
|
||||
return EXIT_KERNEL_BIND;
|
||||
}
|
||||
|
||||
opt = addr.nl_groups;
|
||||
r = setsockopt(cn_fd, 270, NETLINK_ADD_MEMBERSHIP, &opt, sizeof(opt));
|
||||
if (r) {
|
||||
if (close(cn_fd))
|
||||
LOG_ERROR("Failed to close socket: %s",
|
||||
strerror(errno));
|
||||
return EXIT_KERNEL_SETSOCKOPT;
|
||||
}
|
||||
|
||||
/*
|
||||
r = fcntl(cn_fd, F_SETFL, FNDELAY);
|
||||
*/
|
||||
|
||||
links_register(cn_fd, "local", do_local_work, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup_local
|
||||
*
|
||||
* Clean up before exiting
|
||||
*/
|
||||
void cleanup_local(void)
|
||||
{
|
||||
links_unregister(cn_fd);
|
||||
if (cn_fd >= 0 && close(cn_fd))
|
||||
LOG_ERROR("Failed to close socket: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
20
daemons/cmirrord/local.h
Normal file
20
daemons/cmirrord/local.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_LOCAL_H
|
||||
#define _LVM_CLOG_LOCAL_H
|
||||
|
||||
int init_local(void);
|
||||
void cleanup_local(void);
|
||||
|
||||
int kernel_send(struct dm_ulog_request *rq);
|
||||
|
||||
#endif /* _LVM_CLOG_LOCAL_H */
|
||||
57
daemons/cmirrord/logging.c
Normal file
57
daemons/cmirrord/logging.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
|
||||
const char *__rq_types_off_by_one[] = {
|
||||
"DM_ULOG_CTR",
|
||||
"DM_ULOG_DTR",
|
||||
"DM_ULOG_PRESUSPEND",
|
||||
"DM_ULOG_POSTSUSPEND",
|
||||
"DM_ULOG_RESUME",
|
||||
"DM_ULOG_GET_REGION_SIZE",
|
||||
"DM_ULOG_IS_CLEAN",
|
||||
"DM_ULOG_IN_SYNC",
|
||||
"DM_ULOG_FLUSH",
|
||||
"DM_ULOG_MARK_REGION",
|
||||
"DM_ULOG_CLEAR_REGION",
|
||||
"DM_ULOG_GET_RESYNC_WORK",
|
||||
"DM_ULOG_SET_REGION_SYNC",
|
||||
"DM_ULOG_GET_SYNC_COUNT",
|
||||
"DM_ULOG_STATUS_INFO",
|
||||
"DM_ULOG_STATUS_TABLE",
|
||||
"DM_ULOG_IS_REMOTE_RECOVERING",
|
||||
NULL
|
||||
};
|
||||
|
||||
int log_tabbing = 0;
|
||||
int log_is_open = 0;
|
||||
|
||||
/*
|
||||
* Variables for various conditional logging
|
||||
*/
|
||||
#ifdef MEMB
|
||||
int log_membership_change = 1;
|
||||
#else
|
||||
int log_membership_change = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CKPT
|
||||
int log_checkpoint = 1;
|
||||
#else
|
||||
int log_checkpoint = 0;
|
||||
#endif
|
||||
|
||||
#ifdef RESEND
|
||||
int log_resend_requests = 1;
|
||||
#else
|
||||
int log_resend_requests = 0;
|
||||
#endif
|
||||
77
daemons/cmirrord/logging.h
Normal file
77
daemons/cmirrord/logging.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_CLOG_LOGGING_H
|
||||
#define _LVM_CLOG_LOGGING_H
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "configure.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/* SHORT_UUID - print last 8 chars of a string */
|
||||
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
|
||||
|
||||
extern const char *__rq_types_off_by_one[];
|
||||
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
|
||||
|
||||
extern int log_tabbing;
|
||||
extern int log_is_open;
|
||||
extern int log_membership_change;
|
||||
extern int log_checkpoint;
|
||||
extern int log_resend_requests;
|
||||
|
||||
#define LOG_OPEN(ident, option, facility) do { \
|
||||
openlog(ident, option, facility); \
|
||||
log_is_open = 1; \
|
||||
} while (0)
|
||||
|
||||
#define LOG_CLOSE(void) do { \
|
||||
log_is_open = 0; \
|
||||
closelog(); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_OUTPUT(level, f, arg...) do { \
|
||||
int __i; \
|
||||
char __buffer[16]; \
|
||||
FILE *fp = (level > LOG_NOTICE) ? stderr : stdout; \
|
||||
if (log_is_open) { \
|
||||
for (__i = 0; (__i < log_tabbing) && (__i < 15); __i++) \
|
||||
__buffer[__i] = '\t'; \
|
||||
__buffer[__i] = '\0'; \
|
||||
syslog(level, "%s" f "\n", __buffer, ## arg); \
|
||||
} else { \
|
||||
for (__i = 0; __i < log_tabbing; __i++) \
|
||||
fprintf(fp, "\t"); \
|
||||
fprintf(fp, f "\n", ## arg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
|
||||
#else /* DEBUG */
|
||||
#define LOG_DBG(f, arg...)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define LOG_COND(__X, f, arg...) do {\
|
||||
if (__X) { \
|
||||
LOG_OUTPUT(LOG_NOTICE, f, ## arg); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_PRINT(f, arg...) LOG_OUTPUT(LOG_NOTICE, f, ## arg)
|
||||
#define LOG_ERROR(f, arg...) LOG_OUTPUT(LOG_ERR, f, ## arg)
|
||||
|
||||
#endif /* _LVM_CLOG_LOGGING_H */
|
||||
4
daemons/dmeventd/.exported_symbols
Normal file
4
daemons/dmeventd/.exported_symbols
Normal file
@@ -0,0 +1,4 @@
|
||||
init_fifos
|
||||
fini_fifos
|
||||
daemon_talk
|
||||
dm_event_get_version
|
||||
108
daemons/dmeventd/Makefile.in
Normal file
108
daemons/dmeventd/Makefile.in
Normal file
@@ -0,0 +1,108 @@
|
||||
#
|
||||
# Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the device-mapper userspace tools.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU Lesser General Public License v.2.1.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SOURCES = libdevmapper-event.c
|
||||
SOURCES2 = dmeventd.c
|
||||
|
||||
TARGETS = dmeventd
|
||||
|
||||
.PHONY: install_lib_dynamic install_lib_static install_include \
|
||||
install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
|
||||
install_lib install_dmeventd
|
||||
|
||||
INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic
|
||||
INSTALL_LIB_TARGETS = install_lib_dynamic
|
||||
|
||||
LIB_NAME = libdevmapper-event
|
||||
ifeq ("@STATIC_LINK@", "yes")
|
||||
LIB_STATIC = $(LIB_NAME).a
|
||||
TARGETS += $(LIB_STATIC) dmeventd.static
|
||||
INSTALL_DMEVENTD_TARGETS += install_dmeventd_static
|
||||
INSTALL_LIB_TARGETS += install_lib_static
|
||||
endif
|
||||
|
||||
LIB_VERSION = $(LIB_VERSION_DM)
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
|
||||
CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a
|
||||
|
||||
ifneq ($(MAKECMDGOALS),device-mapper)
|
||||
SUBDIRS+=plugins
|
||||
endif
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
CFLOW_TARGET = dmeventd
|
||||
|
||||
EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
|
||||
EXPORTED_FN_PREFIX = dm_event
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
all: device-mapper
|
||||
device-mapper: $(TARGETS)
|
||||
|
||||
LIBS += -ldevmapper
|
||||
LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS)
|
||||
|
||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \
|
||||
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
|
||||
dmeventd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
|
||||
|
||||
ifeq ("@PKGCONFIG@", "yes")
|
||||
INSTALL_LIB_TARGETS += install_pkgconfig
|
||||
endif
|
||||
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
-include $(top_builddir)/libdm/libdevmapper.cflow
|
||||
-include $(top_builddir)/lib/liblvm-internal.cflow
|
||||
-include $(top_builddir)/lib/liblvm2cmd.cflow
|
||||
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
|
||||
-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
|
||||
endif
|
||||
|
||||
install_include: $(srcdir)/libdevmapper-event.h
|
||||
$(INSTALL_DATA) -D $< $(includedir)/$(<F)
|
||||
|
||||
install_pkgconfig: libdevmapper-event.pc
|
||||
$(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
|
||||
|
||||
install_lib_dynamic: install_lib_shared
|
||||
|
||||
install_lib_static: $(LIB_STATIC)
|
||||
$(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
|
||||
|
||||
install_lib: $(INSTALL_LIB_TARGETS)
|
||||
|
||||
install_dmeventd_dynamic: dmeventd
|
||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
||||
install_dmeventd_static: dmeventd.static
|
||||
$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
|
||||
|
||||
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
|
||||
|
||||
install: install_include install_lib install_dmeventd
|
||||
|
||||
install_device-mapper: install_include install_lib install_dmeventd
|
||||
|
||||
DISTCLEAN_TARGETS += libdevmapper-event.pc
|
||||
2032
daemons/dmeventd/dmeventd.c
Normal file
2032
daemons/dmeventd/dmeventd.c
Normal file
File diff suppressed because it is too large
Load Diff
75
daemons/dmeventd/dmeventd.h
Normal file
75
daemons/dmeventd/dmeventd.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __DMEVENTD_DOT_H__
|
||||
#define __DMEVENTD_DOT_H__
|
||||
|
||||
/* FIXME This stuff must be configurable. */
|
||||
|
||||
#define DM_EVENT_FIFO_CLIENT DEFAULT_DM_RUN_DIR "/dmeventd-client"
|
||||
#define DM_EVENT_FIFO_SERVER DEFAULT_DM_RUN_DIR "/dmeventd-server"
|
||||
|
||||
#define DM_EVENT_DEFAULT_TIMEOUT 10
|
||||
|
||||
/* Commands for the daemon passed in the message below. */
|
||||
enum dm_event_command {
|
||||
DM_EVENT_CMD_ACTIVE = 1,
|
||||
DM_EVENT_CMD_REGISTER_FOR_EVENT,
|
||||
DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
|
||||
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
|
||||
DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
|
||||
DM_EVENT_CMD_SET_TIMEOUT,
|
||||
DM_EVENT_CMD_GET_TIMEOUT,
|
||||
DM_EVENT_CMD_HELLO,
|
||||
DM_EVENT_CMD_DIE,
|
||||
DM_EVENT_CMD_GET_STATUS,
|
||||
};
|
||||
|
||||
/* Message passed between client and daemon. */
|
||||
struct dm_event_daemon_message {
|
||||
uint32_t cmd;
|
||||
uint32_t size;
|
||||
char *data;
|
||||
};
|
||||
|
||||
/* FIXME Is this meant to be exported? I can't see where the
|
||||
interface uses it. */
|
||||
/* Fifos for client/daemon communication. */
|
||||
struct dm_event_fifos {
|
||||
int client;
|
||||
int server;
|
||||
const char *client_path;
|
||||
const char *server_path;
|
||||
};
|
||||
|
||||
/* EXIT_SUCCESS 0 -- stdlib.h */
|
||||
/* EXIT_FAILURE 1 -- stdlib.h */
|
||||
/* EXIT_LOCKFILE_INUSE 2 -- obsoleted */
|
||||
#define EXIT_DESC_CLOSE_FAILURE 3
|
||||
#define EXIT_DESC_OPEN_FAILURE 4
|
||||
/* EXIT_OPEN_PID_FAILURE 5 -- obsoleted */
|
||||
#define EXIT_FIFO_FAILURE 6
|
||||
#define EXIT_CHDIR_FAILURE 7
|
||||
|
||||
/* Implemented in libdevmapper-event.c, but not part of public API. */
|
||||
// FIXME misuse of bitmask as enum
|
||||
int daemon_talk(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg, int cmd,
|
||||
const char *dso_name, const char *dev_name,
|
||||
enum dm_event_mask evmask, uint32_t timeout);
|
||||
int init_fifos(struct dm_event_fifos *fifos);
|
||||
void fini_fifos(struct dm_event_fifos *fifos);
|
||||
int dm_event_get_version(struct dm_event_fifos *fifos, int *version);
|
||||
|
||||
#endif /* __DMEVENTD_DOT_H__ */
|
||||
873
daemons/dmeventd/libdevmapper-event.c
Normal file
873
daemons/dmeventd/libdevmapper-event.c
Normal file
@@ -0,0 +1,873 @@
|
||||
/*
|
||||
* 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_zalloc(sizeof(*dmevh)))) {
|
||||
log_error("Failed to allocate event handler.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dmevh;
|
||||
}
|
||||
|
||||
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
|
||||
{
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
dm_free(dmevh->dso);
|
||||
dm_free(dmevh->dmeventd_path);
|
||||
dm_free(dmevh);
|
||||
}
|
||||
|
||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
|
||||
{
|
||||
if (!dmeventd_path) /* noop */
|
||||
return 0;
|
||||
|
||||
dm_free(dmevh->dmeventd_path);
|
||||
|
||||
dmevh->dmeventd_path = dm_strdup(dmeventd_path);
|
||||
if (!dmevh->dmeventd_path)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
|
||||
{
|
||||
if (!path) /* noop */
|
||||
return 0;
|
||||
dm_free(dmevh->dso);
|
||||
|
||||
dmevh->dso = dm_strdup(path);
|
||||
if (!dmevh->dso)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
|
||||
{
|
||||
if (!dev_name)
|
||||
return 0;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
|
||||
dmevh->dev_name = dm_strdup(dev_name);
|
||||
if (!dmevh->dev_name)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
|
||||
{
|
||||
if (!uuid)
|
||||
return 0;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
|
||||
dmevh->uuid = dm_strdup(uuid);
|
||||
if (!dmevh->uuid)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
|
||||
{
|
||||
int minor = dmevh->minor;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
|
||||
dmevh->major = major;
|
||||
dmevh->minor = minor;
|
||||
}
|
||||
|
||||
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
|
||||
{
|
||||
int major = dmevh->major;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
|
||||
dmevh->major = major;
|
||||
dmevh->minor = minor;
|
||||
}
|
||||
|
||||
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
|
||||
enum dm_event_mask evmask)
|
||||
{
|
||||
dmevh->mask = evmask;
|
||||
}
|
||||
|
||||
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
|
||||
{
|
||||
dmevh->timeout = timeout;
|
||||
}
|
||||
|
||||
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->dso;
|
||||
}
|
||||
|
||||
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->dev_name;
|
||||
}
|
||||
|
||||
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->uuid;
|
||||
}
|
||||
|
||||
int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->major;
|
||||
}
|
||||
|
||||
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->minor;
|
||||
}
|
||||
|
||||
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->timeout;
|
||||
}
|
||||
|
||||
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
return dmevh->mask;
|
||||
}
|
||||
|
||||
static int _check_message_id(struct dm_event_daemon_message *msg)
|
||||
{
|
||||
int pid, seq_nr;
|
||||
|
||||
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
|
||||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
|
||||
log_error("Ignoring out-of-sequence reply from dmeventd. "
|
||||
"Expected %d:%d but received %s", getpid(),
|
||||
_sequence_nr, msg->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* daemon_read
|
||||
* @fifos
|
||||
* @msg
|
||||
*
|
||||
* Read message from daemon.
|
||||
*
|
||||
* Returns: 0 on failure, 1 on success
|
||||
*/
|
||||
static int _daemon_read(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
int ret, i;
|
||||
fd_set fds;
|
||||
struct timeval tval = { 0, 0 };
|
||||
size_t size = 2 * sizeof(uint32_t); /* status + size */
|
||||
uint32_t *header = alloca(size);
|
||||
char *buf = (char *)header;
|
||||
|
||||
while (bytes < size) {
|
||||
for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
|
||||
/* Watch daemon read FIFO for input. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->server, &fds);
|
||||
tval.tv_sec = 1;
|
||||
ret = select(fifos->server + 1, &fds, NULL, NULL,
|
||||
&tval);
|
||||
if (ret < 0 && errno != EINTR) {
|
||||
log_error("Unable to read from event server");
|
||||
return 0;
|
||||
}
|
||||
if ((ret == 0) && (i > 4) && !bytes) {
|
||||
log_error("No input from event server.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (ret < 1) {
|
||||
log_error("Unable to read from event server.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = read(fifos->server, buf + bytes, size);
|
||||
if (ret < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
else {
|
||||
log_error("Unable to read from event server.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytes += ret;
|
||||
if (header && (bytes == 2 * sizeof(uint32_t))) {
|
||||
msg->cmd = ntohl(header[0]);
|
||||
msg->size = ntohl(header[1]);
|
||||
buf = msg->data = dm_malloc(msg->size);
|
||||
size = msg->size;
|
||||
bytes = 0;
|
||||
header = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes != size) {
|
||||
dm_free(msg->data);
|
||||
msg->data = NULL;
|
||||
}
|
||||
return bytes == size;
|
||||
}
|
||||
|
||||
/* Write message to daemon. */
|
||||
static int _daemon_write(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
int ret = 0;
|
||||
fd_set fds;
|
||||
|
||||
size_t size = 2 * sizeof(uint32_t) + msg->size;
|
||||
uint32_t *header = alloca(size);
|
||||
char *buf = (char *)header;
|
||||
char drainbuf[128];
|
||||
struct timeval tval = { 0, 0 };
|
||||
|
||||
header[0] = htonl(msg->cmd);
|
||||
header[1] = htonl(msg->size);
|
||||
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
|
||||
|
||||
/* drain the answer fifo */
|
||||
while (1) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->server, &fds);
|
||||
tval.tv_usec = 100;
|
||||
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
|
||||
if ((ret < 0) && (errno != EINTR)) {
|
||||
log_error("Unable to talk to event daemon");
|
||||
return 0;
|
||||
}
|
||||
if (ret == 0)
|
||||
break;
|
||||
ret = read(fifos->server, drainbuf, 127);
|
||||
}
|
||||
|
||||
while (bytes < size) {
|
||||
do {
|
||||
/* Watch daemon write FIFO to be ready for output. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->client, &fds);
|
||||
ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
|
||||
if ((ret < 0) && (errno != EINTR)) {
|
||||
log_error("Unable to talk to event daemon");
|
||||
return 0;
|
||||
}
|
||||
} while (ret < 1);
|
||||
|
||||
ret = write(fifos->client, buf + bytes, size - bytes);
|
||||
if (ret < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
else {
|
||||
log_error("Unable to talk to event daemon");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytes += ret;
|
||||
}
|
||||
|
||||
return bytes == size;
|
||||
}
|
||||
|
||||
int daemon_talk(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg, int cmd,
|
||||
const char *dso_name, const char *dev_name,
|
||||
enum dm_event_mask evmask, uint32_t timeout)
|
||||
{
|
||||
const char *dso = dso_name ? dso_name : "-";
|
||||
const char *dev = dev_name ? dev_name : "-";
|
||||
const char *fmt = "%d:%d %s %s %u %" PRIu32;
|
||||
int msg_size;
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
|
||||
/*
|
||||
* Set command and pack the arguments
|
||||
* into ASCII message string.
|
||||
*/
|
||||
msg->cmd = cmd;
|
||||
if (cmd == DM_EVENT_CMD_HELLO)
|
||||
fmt = "%d:%d HELLO";
|
||||
if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
|
||||
dso, dev, evmask, timeout)) < 0) {
|
||||
log_error("_daemon_talk: message allocation failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
msg->size = msg_size;
|
||||
|
||||
/*
|
||||
* Write command and message to and
|
||||
* read status return code from daemon.
|
||||
*/
|
||||
if (!_daemon_write(fifos, msg)) {
|
||||
stack;
|
||||
dm_free(msg->data);
|
||||
msg->data = 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
dm_free(msg->data);
|
||||
msg->data = 0;
|
||||
|
||||
if (!_daemon_read(fifos, msg)) {
|
||||
stack;
|
||||
return -EIO;
|
||||
}
|
||||
} while (!_check_message_id(msg));
|
||||
|
||||
_sequence_nr++;
|
||||
|
||||
return (int32_t) msg->cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* start_daemon
|
||||
*
|
||||
* This function forks off a process (dmeventd) that will handle
|
||||
* the events. I am currently test opening one of the fifos to
|
||||
* ensure that the daemon is running and listening... I thought
|
||||
* this would be less expensive than fork/exec'ing every time.
|
||||
* Perhaps there is an even quicker/better way (no, checking the
|
||||
* lock file is _not_ a better way).
|
||||
*
|
||||
* Returns: 1 on success, 0 otherwise
|
||||
*/
|
||||
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
{
|
||||
int pid, ret = 0;
|
||||
int status;
|
||||
struct stat statbuf;
|
||||
char default_dmeventd_path[] = DMEVENTD_PATH;
|
||||
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
|
||||
|
||||
if (stat(fifos->client_path, &statbuf))
|
||||
goto start_server;
|
||||
|
||||
if (!S_ISFIFO(statbuf.st_mode)) {
|
||||
log_error("%s is not a fifo.", fifos->client_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Anyone listening? If not, errno will be ENXIO */
|
||||
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
|
||||
if (fifos->client >= 0) {
|
||||
/* server is running and listening */
|
||||
if (close(fifos->client))
|
||||
log_sys_error("close", fifos->client_path);
|
||||
return 1;
|
||||
} else if (errno != ENXIO) {
|
||||
/* problem */
|
||||
log_sys_error("open", fifos->client_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
start_server:
|
||||
/* server is not running */
|
||||
|
||||
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
|
||||
log_sys_error("stat", args[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0)
|
||||
log_sys_error("fork", "");
|
||||
|
||||
else if (!pid) {
|
||||
execvp(args[0], args);
|
||||
log_error("Unable to exec dmeventd: %s", strerror(errno));
|
||||
_exit(EXIT_FAILURE);
|
||||
} else {
|
||||
if (waitpid(pid, &status, 0) < 0)
|
||||
log_error("Unable to start dmeventd: %s",
|
||||
strerror(errno));
|
||||
else if (WEXITSTATUS(status))
|
||||
log_error("Unable to start dmeventd.");
|
||||
else
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int init_fifos(struct dm_event_fifos *fifos)
|
||||
{
|
||||
/* FIXME? Is fifo the most suitable method? Why not share
|
||||
comms/daemon code with something else e.g. multipath? */
|
||||
|
||||
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||
|
||||
/* Open the fifo used to read from the daemon. */
|
||||
if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
|
||||
log_sys_error("open", fifos->server_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Lock out anyone else trying to do communication with the daemon. */
|
||||
if (flock(fifos->server, LOCK_EX) < 0) {
|
||||
log_sys_error("flock", fifos->server_path);
|
||||
if (close(fifos->server))
|
||||
log_sys_error("close", fifos->server_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
|
||||
if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
|
||||
log_sys_error("open", fifos->client_path);
|
||||
if (close(fifos->server))
|
||||
log_sys_error("close", fifos->server_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize client. */
|
||||
static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
{
|
||||
/* init fifos */
|
||||
memset(fifos, 0, sizeof(*fifos));
|
||||
|
||||
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||
|
||||
if (!_start_daemon(dmeventd_path, fifos))
|
||||
return_0;
|
||||
|
||||
return init_fifos(fifos);
|
||||
}
|
||||
|
||||
void fini_fifos(struct dm_event_fifos *fifos)
|
||||
{
|
||||
if (flock(fifos->server, LOCK_UN))
|
||||
log_error("flock unlock %s", fifos->server_path);
|
||||
|
||||
if (close(fifos->client))
|
||||
log_sys_error("close", fifos->client_path);
|
||||
if (close(fifos->server))
|
||||
log_sys_error("close", fifos->server_path);
|
||||
}
|
||||
|
||||
/* Get uuid of a device */
|
||||
static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
|
||||
log_error("_get_device_info: dm_task creation for info failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmevh->uuid) {
|
||||
if (!dm_task_set_uuid(dmt, dmevh->uuid))
|
||||
goto_bad;
|
||||
} else if (dmevh->dev_name) {
|
||||
if (!dm_task_set_name(dmt, dmevh->dev_name))
|
||||
goto_bad;
|
||||
} else if (dmevh->major && dmevh->minor) {
|
||||
if (!dm_task_set_major(dmt, dmevh->major) ||
|
||||
!dm_task_set_minor(dmt, dmevh->minor))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
/* FIXME Add name or uuid or devno to messages */
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("_get_device_info: dm_task_run() failed");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!dm_task_get_info(dmt, &info)) {
|
||||
log_error("_get_device_info: failed to get info for device");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!info.exists) {
|
||||
log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found",
|
||||
dmevh->uuid ? : "",
|
||||
(!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "",
|
||||
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? "(" : "",
|
||||
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? dmevh->major : 0,
|
||||
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ":" : "",
|
||||
(!dmevh->uuid && !dmevh->dev_name && dmevh->minor > 0) ? dmevh->minor : 0,
|
||||
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) && dmevh->minor == 0 ? "0" : "",
|
||||
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ") " : "");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
||||
return dmt;
|
||||
|
||||
bad:
|
||||
dm_task_destroy(dmt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle the event (de)registration call and return negative error codes. */
|
||||
static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_message *msg,
|
||||
const char *dso_name, const char *dev_name,
|
||||
enum dm_event_mask evmask, uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
struct dm_event_fifos fifos;
|
||||
|
||||
if (!_init_client(dmeventd_path, &fifos)) {
|
||||
stack;
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
||||
|
||||
dm_free(msg->data);
|
||||
msg->data = 0;
|
||||
|
||||
if (!ret)
|
||||
ret = daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
|
||||
|
||||
/* what is the opposite of init? */
|
||||
fini_fifos(&fifos);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* External library interface. */
|
||||
int dm_event_register_handler(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
int ret = 1, err;
|
||||
const char *uuid;
|
||||
struct dm_task *dmt;
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (!(dmt = _get_device_info(dmevh))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uuid = dm_task_get_uuid(dmt);
|
||||
|
||||
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
|
||||
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
||||
log_error("%s: event registration failed: %s",
|
||||
dm_task_get_name(dmt),
|
||||
msg.data ? msg.data : strerror(-err));
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dm_free(msg.data);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
|
||||
{
|
||||
int ret = 1, err;
|
||||
const char *uuid;
|
||||
struct dm_task *dmt;
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (!(dmt = _get_device_info(dmevh))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uuid = dm_task_get_uuid(dmt);
|
||||
|
||||
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
|
||||
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
||||
log_error("%s: event deregistration failed: %s",
|
||||
dm_task_get_name(dmt),
|
||||
msg.data ? msg.data : strerror(-err));
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dm_free(msg.data);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Fetch a string off src and duplicate it into *dest. */
|
||||
/* FIXME: move to separate module to share with the daemon. */
|
||||
static char *_fetch_string(char **src, const int delimiter)
|
||||
{
|
||||
char *p, *ret;
|
||||
|
||||
if ((p = strchr(*src, delimiter)))
|
||||
*p = 0;
|
||||
|
||||
if ((ret = dm_strdup(*src)))
|
||||
*src += strlen(ret) + 1;
|
||||
|
||||
if (p)
|
||||
*p = delimiter;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Parse a device message from the daemon. */
|
||||
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
|
||||
char **uuid, enum dm_event_mask *evmask)
|
||||
{
|
||||
char *id = NULL;
|
||||
char *p = msg->data;
|
||||
|
||||
if ((id = _fetch_string(&p, ' ')) &&
|
||||
(*dso_name = _fetch_string(&p, ' ')) &&
|
||||
(*uuid = _fetch_string(&p, ' '))) {
|
||||
*evmask = atoi(p);
|
||||
|
||||
dm_free(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (id)
|
||||
dm_free(id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise.
|
||||
*/
|
||||
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
||||
{
|
||||
int ret = 0;
|
||||
const char *uuid = NULL;
|
||||
char *reply_dso = NULL, *reply_uuid = NULL;
|
||||
enum dm_event_mask reply_mask = 0;
|
||||
struct dm_task *dmt = NULL;
|
||||
struct dm_event_daemon_message msg = { 0 };
|
||||
struct dm_info info;
|
||||
|
||||
if (!(dmt = _get_device_info(dmevh))) {
|
||||
log_debug("Device does not exists (uuid=%s, name=%s, %d:%d).",
|
||||
dmevh->uuid, dmevh->dev_name,
|
||||
dmevh->major, dmevh->minor);
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uuid = dm_task_get_uuid(dmt);
|
||||
|
||||
if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
|
||||
DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
|
||||
&msg, dmevh->dso, uuid, dmevh->mask, 0)) {
|
||||
log_debug("%s: device not registered.", dm_task_get_name(dmt));
|
||||
ret = -ENOENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* FIXME this will probably horribly break if we get
|
||||
ill-formatted reply */
|
||||
ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
dmt = NULL;
|
||||
|
||||
dm_free(msg.data);
|
||||
msg.data = NULL;
|
||||
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
if (!reply_uuid) {
|
||||
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
|
||||
goto fail;
|
||||
}
|
||||
dmevh->uuid = dm_strdup(reply_uuid);
|
||||
if (!dmevh->uuid) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(dmt = _get_device_info(dmevh))) {
|
||||
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dm_event_handler_set_dso(dmevh, reply_dso);
|
||||
dm_event_handler_set_event_mask(dmevh, reply_mask);
|
||||
|
||||
dm_free(reply_dso);
|
||||
reply_dso = NULL;
|
||||
|
||||
dm_free(reply_uuid);
|
||||
reply_uuid = NULL;
|
||||
|
||||
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
|
||||
if (!dmevh->dev_name) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_get_info(dmt, &info)) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dmevh->major = info.major;
|
||||
dmevh->minor = info.minor;
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
dm_free(msg.data);
|
||||
dm_free(reply_dso);
|
||||
dm_free(reply_uuid);
|
||||
_dm_event_handler_clear_dev_info(dmevh);
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* You can (and have to) call this at the stage of the protocol where
|
||||
* daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0)
|
||||
*
|
||||
* would be normally sent. This call will parse the version reply from
|
||||
* dmeventd, in addition to above call. It is not safe to call this at any
|
||||
* other place in the protocol.
|
||||
*
|
||||
* This is an internal function, not exposed in the public API.
|
||||
*/
|
||||
|
||||
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
|
||||
char *p;
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
|
||||
return 0;
|
||||
p = msg.data;
|
||||
*version = 0;
|
||||
|
||||
if (!p || !(p = strchr(p, ' '))) /* Message ID */
|
||||
return 0;
|
||||
if (!(p = strchr(p + 1, ' '))) /* HELLO */
|
||||
return 0;
|
||||
if ((p = strchr(p + 1, ' '))) /* HELLO, once more */
|
||||
*version = atoi(p);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0 /* left out for now */
|
||||
|
||||
static char *_skip_string(char *src, const int delimiter)
|
||||
{
|
||||
src = srtchr(src, delimiter);
|
||||
if (src && *(src + 1))
|
||||
return src + 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
|
||||
{
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (!device_exists(device_path))
|
||||
return -ENODEV;
|
||||
|
||||
return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
|
||||
NULL, device_path, 0, timeout);
|
||||
}
|
||||
|
||||
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
|
||||
{
|
||||
int ret;
|
||||
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||
|
||||
if (!device_exists(device_path))
|
||||
return -ENODEV;
|
||||
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
|
||||
0, 0))) {
|
||||
char *p = _skip_string(msg.data, ' ');
|
||||
if (!p) {
|
||||
log_error("malformed reply from dmeventd '%s'\n",
|
||||
msg.data);
|
||||
return -EIO;
|
||||
}
|
||||
*timeout = atoi(p);
|
||||
}
|
||||
if (msg.data)
|
||||
dm_free(msg.data);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
115
daemons/dmeventd/libdevmapper-event.h
Normal file
115
daemons/dmeventd/libdevmapper-event.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note that this file is released only as part of a technology preview
|
||||
* and its contents may change in future updates in ways that do not
|
||||
* preserve compatibility.
|
||||
*/
|
||||
|
||||
#ifndef LIB_DMEVENT_H
|
||||
#define LIB_DMEVENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Event library interface.
|
||||
*/
|
||||
|
||||
enum dm_event_mask {
|
||||
DM_EVENT_SETTINGS_MASK = 0x0000FF,
|
||||
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
|
||||
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
|
||||
|
||||
DM_EVENT_ERROR_MASK = 0x00FF00,
|
||||
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
|
||||
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
|
||||
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
|
||||
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
|
||||
|
||||
DM_EVENT_STATUS_MASK = 0xFF0000,
|
||||
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
|
||||
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
|
||||
|
||||
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
|
||||
};
|
||||
|
||||
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
|
||||
#define DM_EVENT_PROTOCOL_VERSION 1
|
||||
|
||||
struct dm_event_handler;
|
||||
|
||||
struct dm_event_handler *dm_event_handler_create(void);
|
||||
void dm_event_handler_destroy(struct dm_event_handler *dmevh);
|
||||
|
||||
/*
|
||||
* Path of shared library to handle events.
|
||||
*
|
||||
* All of dmeventd, dso, device_name and uuid strings are duplicated so
|
||||
* you do not need to keep the pointers valid after the call succeeds.
|
||||
* They may return -ENOMEM though.
|
||||
*/
|
||||
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
|
||||
|
||||
/*
|
||||
* Path of dmeventd binary.
|
||||
*/
|
||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path);
|
||||
|
||||
/*
|
||||
* Identify the device to monitor by exactly one of device_name, uuid or
|
||||
* device number. String arguments are duplicated, see above.
|
||||
*/
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
|
||||
|
||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
|
||||
|
||||
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
|
||||
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
|
||||
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
|
||||
|
||||
/*
|
||||
* Specify mask for events to monitor.
|
||||
*/
|
||||
// FIXME misuse of bitmask as enum
|
||||
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
|
||||
enum dm_event_mask evmask);
|
||||
|
||||
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
|
||||
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
|
||||
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
|
||||
int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
|
||||
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
|
||||
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
|
||||
// FIXME misuse of bitmask as enum
|
||||
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
|
||||
|
||||
/* FIXME Review interface (what about this next thing?) */
|
||||
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
|
||||
|
||||
/*
|
||||
* Initiate monitoring using dmeventd.
|
||||
*/
|
||||
int dm_event_register_handler(const struct dm_event_handler *dmevh);
|
||||
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
|
||||
|
||||
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
|
||||
detailed descriptions. */
|
||||
// FIXME misuse of bitmask as enum
|
||||
void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
|
||||
int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
|
||||
int unregister_device(const char *device_name, const char *uuid, int major,
|
||||
int minor, void **user);
|
||||
|
||||
#endif
|
||||
11
daemons/dmeventd/libdevmapper-event.pc.in
Normal file
11
daemons/dmeventd/libdevmapper-event.pc.in
Normal file
@@ -0,0 +1,11 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: devmapper-event
|
||||
Description: device-mapper event library
|
||||
Version: @DM_LIB_PATCHLEVEL@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -ldevmapper-event
|
||||
Requires.private: devmapper
|
||||
46
daemons/dmeventd/plugins/Makefile.in
Normal file
46
daemons/dmeventd/plugins/Makefile.in
Normal file
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2011 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SUBDIRS += lvm2
|
||||
|
||||
ifneq ("@MIRRORS@", "none")
|
||||
SUBDIRS += mirror
|
||||
endif
|
||||
|
||||
ifneq ("@SNAPSHOTS@", "none")
|
||||
SUBDIRS += snapshot
|
||||
endif
|
||||
|
||||
ifneq ("@RAID@", "none")
|
||||
SUBDIRS += raid
|
||||
endif
|
||||
|
||||
ifneq ("@THIN@", "none")
|
||||
SUBDIRS += thin
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS = lvm2 mirror snapshot raid thin
|
||||
endif
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
snapshot: lvm2
|
||||
mirror: lvm2
|
||||
raid: lvm2
|
||||
thin: lvm2
|
||||
7
daemons/dmeventd/plugins/lvm2/.exported_symbols
Normal file
7
daemons/dmeventd/plugins/lvm2/.exported_symbols
Normal file
@@ -0,0 +1,7 @@
|
||||
dmeventd_lvm2_init
|
||||
dmeventd_lvm2_exit
|
||||
dmeventd_lvm2_lock
|
||||
dmeventd_lvm2_unlock
|
||||
dmeventd_lvm2_pool
|
||||
dmeventd_lvm2_run
|
||||
dmeventd_lvm2_command
|
||||
31
daemons/dmeventd/plugins/lvm2/Makefile.in
Normal file
31
daemons/dmeventd/plugins/lvm2/Makefile.in
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
CLDFLAGS += -L$(top_builddir)/tools
|
||||
|
||||
SOURCES = dmeventd_lvm.c
|
||||
|
||||
LIB_SHARED = libdevmapper-event-lvm2.$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS) $(DAEMON_LIBS)
|
||||
|
||||
install_lvm2: install_lib_shared
|
||||
|
||||
install: install_lvm2
|
||||
176
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
Normal file
176
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <syslog.h>
|
||||
|
||||
extern int dmeventd_debug;
|
||||
|
||||
/*
|
||||
* register_device() is called first and performs initialisation.
|
||||
* Only one device may be registered or unregistered at a time.
|
||||
*/
|
||||
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
* Number of active registrations.
|
||||
*/
|
||||
static int _register_count = 0;
|
||||
static struct dm_pool *_mem_pool = NULL;
|
||||
static void *_lvm_handle = NULL;
|
||||
|
||||
/*
|
||||
* Currently only one event can be processed at a time.
|
||||
*/
|
||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
* FIXME Do not pass things directly to syslog, rather use the existing logging
|
||||
* facilities to sort logging ... however that mechanism needs to be somehow
|
||||
* configurable and we don't have that option yet
|
||||
*/
|
||||
static void _temporary_log_fn(int level,
|
||||
const char *file __attribute__((unused)),
|
||||
int line __attribute__((unused)),
|
||||
int dm_errno __attribute__((unused)),
|
||||
const char *message)
|
||||
{
|
||||
level &= ~(_LOG_STDERR | _LOG_ONCE);
|
||||
|
||||
switch (level) {
|
||||
case _LOG_DEBUG:
|
||||
if (dmeventd_debug >= 3)
|
||||
syslog(LOG_DEBUG, "%s", message);
|
||||
break;
|
||||
case _LOG_INFO:
|
||||
if (dmeventd_debug >= 2)
|
||||
syslog(LOG_INFO, "%s", message);
|
||||
break;
|
||||
case _LOG_NOTICE:
|
||||
if (dmeventd_debug >= 1)
|
||||
syslog(LOG_NOTICE, "%s", message);
|
||||
break;
|
||||
case _LOG_WARN:
|
||||
syslog(LOG_WARNING, "%s", message);
|
||||
break;
|
||||
case _LOG_ERR:
|
||||
syslog(LOG_ERR, "%s", message);
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_CRIT, "%s", message);
|
||||
}
|
||||
}
|
||||
|
||||
void dmeventd_lvm2_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&_event_mutex);
|
||||
}
|
||||
|
||||
void dmeventd_lvm2_unlock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int dmeventd_lvm2_init(void)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
/*
|
||||
* Need some space for allocations. 1024 should be more
|
||||
* than enough for what we need (device mapper name splitting)
|
||||
*/
|
||||
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
|
||||
goto out;
|
||||
|
||||
if (!_lvm_handle) {
|
||||
lvm2_log_fn(_temporary_log_fn);
|
||||
if (!(_lvm_handle = lvm2_init())) {
|
||||
dm_pool_destroy(_mem_pool);
|
||||
_mem_pool = NULL;
|
||||
goto out;
|
||||
}
|
||||
lvm2_disable_dmeventd_monitoring(_lvm_handle);
|
||||
/* FIXME Temporary: move to dmeventd core */
|
||||
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||
}
|
||||
|
||||
_register_count++;
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
pthread_mutex_unlock(&_register_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
void dmeventd_lvm2_exit(void)
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
if (!--_register_count) {
|
||||
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||
dm_pool_destroy(_mem_pool);
|
||||
_mem_pool = NULL;
|
||||
lvm2_exit(_lvm_handle);
|
||||
_lvm_handle = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_register_mutex);
|
||||
}
|
||||
|
||||
struct dm_pool *dmeventd_lvm2_pool(void)
|
||||
{
|
||||
return _mem_pool;
|
||||
}
|
||||
|
||||
int dmeventd_lvm2_run(const char *cmdline)
|
||||
{
|
||||
return lvm2_run(_lvm_handle, cmdline);
|
||||
}
|
||||
|
||||
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
|
||||
const char *cmd, const char *device)
|
||||
{
|
||||
char *vg = NULL, *lv = NULL, *layer;
|
||||
int r;
|
||||
|
||||
if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
|
||||
syslog(LOG_ERR, "Unable to determine VG name from %s.\n",
|
||||
device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* strip off the mirror component designations */
|
||||
layer = strstr(lv, "_mlog");
|
||||
if (layer)
|
||||
*layer = '\0';
|
||||
|
||||
r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv);
|
||||
|
||||
dm_pool_free(mem, vg);
|
||||
|
||||
if (r < 0) {
|
||||
syslog(LOG_ERR, "Unable to form LVM command. (too long).\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
42
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h
Normal file
42
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Wrappers around liblvm2cmd functions for dmeventd plug-ins.
|
||||
*
|
||||
* liblvm2cmd is not thread-safe so the locking in this library helps dmeventd
|
||||
* threads to co-operate in sharing a single instance.
|
||||
*
|
||||
* FIXME Either support this properly as a generic liblvm2cmd wrapper or make
|
||||
* liblvm2cmd thread-safe so this can go away.
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
|
||||
#ifndef _DMEVENTD_LVMWRAP_H
|
||||
#define _DMEVENTD_LVMWRAP_H
|
||||
|
||||
int dmeventd_lvm2_init(void);
|
||||
void dmeventd_lvm2_exit(void);
|
||||
int dmeventd_lvm2_run(const char *cmdline);
|
||||
|
||||
void dmeventd_lvm2_lock(void);
|
||||
void dmeventd_lvm2_unlock(void);
|
||||
|
||||
struct dm_pool *dmeventd_lvm2_pool(void);
|
||||
|
||||
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
|
||||
const char *cmd, const char *device);
|
||||
|
||||
#endif /* _DMEVENTD_LVMWRAP_H */
|
||||
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
37
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
37
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2008-2011 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
LIB_NAME = libdevmapper-event-lvm2mirror
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper $(DAEMON_LIBS)
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
install: install_lvm2
|
||||
235
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
235
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
#include "defaults.h"
|
||||
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
/* FIXME Missing openlog? */
|
||||
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
|
||||
/* FIXME Reformat to 80 char lines. */
|
||||
|
||||
#define ME_IGNORE 0
|
||||
#define ME_INSYNC 1
|
||||
#define ME_FAILURE 2
|
||||
|
||||
static int _process_status_code(const char status_code, const char *dev_name,
|
||||
const char *dev_type, int r)
|
||||
{
|
||||
/*
|
||||
* A => Alive - No failures
|
||||
* D => Dead - A write failure occurred leaving mirror out-of-sync
|
||||
* F => Flush failed.
|
||||
* S => Sync - A sychronization failure occurred, mirror out-of-sync
|
||||
* R => Read - A read failure occurred, mirror data unaffected
|
||||
* U => Unclassified failure (bug)
|
||||
*/
|
||||
if (status_code == 'F') {
|
||||
syslog(LOG_ERR, "%s device %s flush failed.",
|
||||
dev_type, dev_name);
|
||||
r = ME_FAILURE;
|
||||
} else if (status_code == 'S')
|
||||
syslog(LOG_ERR, "%s device %s sync failed.",
|
||||
dev_type, dev_name);
|
||||
else if (status_code == 'R')
|
||||
syslog(LOG_ERR, "%s device %s read failed.",
|
||||
dev_type, dev_name);
|
||||
else if (status_code != 'A') {
|
||||
syslog(LOG_ERR, "%s device %s has failed (%c).",
|
||||
dev_type, dev_name, status_code);
|
||||
r = ME_FAILURE;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
{
|
||||
int i, r = ME_INSYNC;
|
||||
char **args = NULL;
|
||||
char *dev_status_str;
|
||||
char *log_status_str;
|
||||
char *sync_str;
|
||||
char *p = NULL;
|
||||
int log_argc, num_devs;
|
||||
|
||||
/*
|
||||
* dm core parms: 0 409600 mirror
|
||||
* Mirror core parms: 2 253:4 253:5 400/400
|
||||
* New-style failure params: 1 AA
|
||||
* New-style log params: 3 cluster 253:3 A
|
||||
* or 3 disk 253:3 A
|
||||
* or 1 core
|
||||
*/
|
||||
|
||||
/* number of devices */
|
||||
if (!dm_split_words(params, 1, 0, &p))
|
||||
goto out_parse;
|
||||
|
||||
if (!(num_devs = atoi(p)) ||
|
||||
(num_devs > DEFAULT_MIRROR_MAX_IMAGES) || (num_devs < 0))
|
||||
goto out_parse;
|
||||
p += strlen(p) + 1;
|
||||
|
||||
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
|
||||
args = dm_malloc((num_devs + 7) * sizeof(char *));
|
||||
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
|
||||
goto out_parse;
|
||||
|
||||
/* FIXME: Code differs from lib/mirror/mirrored.c */
|
||||
dev_status_str = args[2 + num_devs];
|
||||
log_argc = atoi(args[3 + num_devs]);
|
||||
log_status_str = args[3 + num_devs + log_argc];
|
||||
sync_str = args[num_devs];
|
||||
|
||||
/* Check for bad mirror devices */
|
||||
for (i = 0; i < num_devs; i++)
|
||||
r = _process_status_code(dev_status_str[i], args[i],
|
||||
i ? "Secondary mirror" : "Primary mirror", r);
|
||||
|
||||
/* Check for bad disk log device */
|
||||
if (log_argc > 1)
|
||||
r = _process_status_code(log_status_str[0],
|
||||
args[2 + num_devs + log_argc],
|
||||
"Log", r);
|
||||
|
||||
if (r == ME_FAILURE)
|
||||
goto out;
|
||||
|
||||
p = strstr(sync_str, "/");
|
||||
if (p) {
|
||||
p[0] = '\0';
|
||||
if (strcmp(sync_str, p+1))
|
||||
r = ME_IGNORE;
|
||||
p[0] = '/';
|
||||
} else
|
||||
goto out_parse;
|
||||
|
||||
out:
|
||||
dm_free(args);
|
||||
return r;
|
||||
|
||||
out_parse:
|
||||
dm_free(args);
|
||||
syslog(LOG_ERR, "Unable to parse mirror status string.");
|
||||
return ME_IGNORE;
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
{
|
||||
int r;
|
||||
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
||||
char cmd_str[CMD_SIZE];
|
||||
|
||||
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
|
||||
"lvconvert --config devices{ignore_suspended_devices=1} "
|
||||
"--repair --use-policies", device))
|
||||
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||
|
||||
r = dmeventd_lvm2_run(cmd_str);
|
||||
|
||||
syslog(LOG_INFO, "Repair of mirrored device %s %s.", device,
|
||||
(r == ECMD_PROCESSED) ? "finished successfully" : "failed");
|
||||
|
||||
return (r == ECMD_PROCESSED) ? 0 : -1;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **unused __attribute__((unused)))
|
||||
{
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
|
||||
dmeventd_lvm2_lock();
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (!target_type) {
|
||||
syslog(LOG_INFO, "%s mapping lost.", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(target_type, "mirror")) {
|
||||
syslog(LOG_INFO, "%s has unmirrored portion.", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_get_mirror_event(params)) {
|
||||
case ME_INSYNC:
|
||||
/* FIXME: all we really know is that this
|
||||
_part_ of the device is in sync
|
||||
Also, this is not an error
|
||||
*/
|
||||
syslog(LOG_NOTICE, "%s is now in-sync.", device);
|
||||
break;
|
||||
case ME_FAILURE:
|
||||
syslog(LOG_ERR, "Device failure in %s.", device);
|
||||
if (_remove_failed_devices(device))
|
||||
/* FIXME Why are all the error return codes unused? Get rid of them? */
|
||||
syslog(LOG_ERR, "Failed to remove faulty devices in %s.",
|
||||
device);
|
||||
/* Should check before warning user that device is now linear
|
||||
else
|
||||
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||
device);
|
||||
*/
|
||||
break;
|
||||
case ME_IGNORE:
|
||||
break;
|
||||
default:
|
||||
/* FIXME Provide value then! */
|
||||
syslog(LOG_INFO, "Unknown event received.");
|
||||
}
|
||||
} while (next);
|
||||
|
||||
dmeventd_lvm2_unlock();
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **unused __attribute__((unused)))
|
||||
{
|
||||
if (!dmeventd_lvm2_init())
|
||||
return 0;
|
||||
|
||||
syslog(LOG_INFO, "Monitoring mirror device %s for events.", device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **unused __attribute__((unused)))
|
||||
{
|
||||
syslog(LOG_INFO, "No longer monitoring mirror device %s for events.",
|
||||
device);
|
||||
dmeventd_lvm2_exit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
3
daemons/dmeventd/plugins/raid/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/raid/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
36
daemons/dmeventd/plugins/raid/Makefile.in
Normal file
36
daemons/dmeventd/plugins/raid/Makefile.in
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||
|
||||
SOURCES = dmeventd_raid.c
|
||||
|
||||
LIB_NAME = libdevmapper-event-lvm2raid
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
install: install_lvm2
|
||||
172
daemons/dmeventd/plugins/raid/dmeventd_raid.c
Normal file
172
daemons/dmeventd/plugins/raid/dmeventd_raid.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
/* FIXME Missing openlog? */
|
||||
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
|
||||
/* FIXME Reformat to 80 char lines. */
|
||||
|
||||
/*
|
||||
* run_repair is a close copy to
|
||||
* plugins/mirror/dmeventd_mirror.c:_remove_failed_devices()
|
||||
*/
|
||||
static int run_repair(const char *device)
|
||||
{
|
||||
int r;
|
||||
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
||||
char cmd_str[CMD_SIZE];
|
||||
|
||||
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
|
||||
"lvconvert --config devices{ignore_suspended_devices=1} "
|
||||
"--repair --use-policies", device))
|
||||
return -1;
|
||||
|
||||
r = dmeventd_lvm2_run(cmd_str);
|
||||
|
||||
if (r != ECMD_PROCESSED)
|
||||
syslog(LOG_INFO, "Repair of RAID device %s failed.", device);
|
||||
|
||||
return (r == ECMD_PROCESSED) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int _process_raid_event(char *params, const char *device)
|
||||
{
|
||||
int i, n, failure = 0;
|
||||
char *p, *a[4];
|
||||
char *raid_type;
|
||||
char *num_devices;
|
||||
char *health_chars;
|
||||
char *resync_ratio;
|
||||
|
||||
/*
|
||||
* RAID parms: <raid_type> <#raid_disks> \
|
||||
* <health chars> <resync ratio>
|
||||
*/
|
||||
if (!dm_split_words(params, 4, 0, a)) {
|
||||
syslog(LOG_ERR, "Failed to process status line for %s\n",
|
||||
device);
|
||||
return -EINVAL;
|
||||
}
|
||||
raid_type = a[0];
|
||||
num_devices = a[1];
|
||||
health_chars = a[2];
|
||||
resync_ratio = a[3];
|
||||
|
||||
if (!(n = atoi(num_devices))) {
|
||||
syslog(LOG_ERR, "Failed to parse number of devices for %s: %s",
|
||||
device, num_devices);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
switch (health_chars[i]) {
|
||||
case 'A':
|
||||
/* Device is 'A'live and well */
|
||||
case 'a':
|
||||
/* Device is 'a'live, but not yet in-sync */
|
||||
break;
|
||||
case 'D':
|
||||
syslog(LOG_ERR,
|
||||
"Device #%d of %s array, %s, has failed.",
|
||||
i, raid_type, device);
|
||||
failure++;
|
||||
break;
|
||||
default:
|
||||
/* Unhandled character returned from kernel */
|
||||
break;
|
||||
}
|
||||
if (failure)
|
||||
return run_repair(device);
|
||||
}
|
||||
|
||||
p = strstr(resync_ratio, "/");
|
||||
if (!p) {
|
||||
syslog(LOG_ERR, "Failed to parse resync_ratio for %s: %s",
|
||||
device, resync_ratio);
|
||||
return -EINVAL;
|
||||
}
|
||||
p[0] = '\0';
|
||||
syslog(LOG_INFO, "%s array, %s, is %s in-sync.",
|
||||
raid_type, device, strcmp(resync_ratio, p+1) ? "not" : "now");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **unused __attribute__((unused)))
|
||||
{
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
|
||||
dmeventd_lvm2_lock();
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (!target_type) {
|
||||
syslog(LOG_INFO, "%s mapping lost.", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(target_type, "raid")) {
|
||||
syslog(LOG_INFO, "%s has non-raid portion.", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_process_raid_event(params, device))
|
||||
syslog(LOG_ERR, "Failed to process event for %s",
|
||||
device);
|
||||
} while (next);
|
||||
|
||||
dmeventd_lvm2_unlock();
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **unused __attribute__((unused)))
|
||||
{
|
||||
if (!dmeventd_lvm2_init())
|
||||
return 0;
|
||||
|
||||
syslog(LOG_INFO, "Monitoring RAID device %s for events.", device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **unused __attribute__((unused)))
|
||||
{
|
||||
syslog(LOG_INFO, "No longer monitoring RAID device %s for events.",
|
||||
device);
|
||||
dmeventd_lvm2_exit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
3
daemons/dmeventd/plugins/snapshot/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/snapshot/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
33
daemons/dmeventd/plugins/snapshot/Makefile.in
Normal file
33
daemons/dmeventd/plugins/snapshot/Makefile.in
Normal file
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||
|
||||
SOURCES = dmeventd_snapshot.c
|
||||
|
||||
LIB_SHARED = libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper $(DAEMON_LIBS)
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
install: install_lvm2
|
||||
248
daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
Normal file
248
daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2011 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
|
||||
#include <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 dso_state {
|
||||
struct dm_pool *mem;
|
||||
int percent_check;
|
||||
uint64_t known_size;
|
||||
char cmd_str[1024];
|
||||
};
|
||||
|
||||
static int _run(const char *cmd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int argc = 1; /* for argv[0], i.e. cmd */
|
||||
int i = 0;
|
||||
const char **argv;
|
||||
pid_t pid = fork();
|
||||
int status;
|
||||
|
||||
if (pid == 0) { /* child */
|
||||
va_start(ap, cmd);
|
||||
while (va_arg(ap, const char *))
|
||||
++ argc;
|
||||
va_end(ap);
|
||||
|
||||
/* + 1 for the terminating NULL */
|
||||
argv = alloca(sizeof(const char *) * (argc + 1));
|
||||
|
||||
argv[0] = cmd;
|
||||
va_start(ap, cmd);
|
||||
while ((argv[++i] = va_arg(ap, const char *)));
|
||||
va_end(ap);
|
||||
|
||||
execvp(cmd, (char **)argv);
|
||||
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
|
||||
exit(127);
|
||||
}
|
||||
|
||||
if (pid > 0) { /* parent */
|
||||
if (waitpid(pid, &status, 0) != pid)
|
||||
return 0; /* waitpid failed */
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status))
|
||||
return 0; /* the child failed */
|
||||
}
|
||||
|
||||
if (pid < 0)
|
||||
return 0; /* fork failed */
|
||||
|
||||
return 1; /* all good */
|
||||
}
|
||||
|
||||
static int _extend(const char *cmd)
|
||||
{
|
||||
return dmeventd_lvm2_run(cmd) == ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static void _umount(const char *device, int major, int minor)
|
||||
{
|
||||
FILE *mounts;
|
||||
char buffer[4096];
|
||||
char *words[3];
|
||||
struct stat st;
|
||||
|
||||
if (!(mounts = fopen("/proc/mounts", "r"))) {
|
||||
syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device);
|
||||
return;
|
||||
}
|
||||
|
||||
while (!feof(mounts)) {
|
||||
/* read a line of /proc/mounts */
|
||||
if (!fgets(buffer, sizeof(buffer), mounts))
|
||||
break; /* eof, likely */
|
||||
|
||||
/* words[0] is the mount point and words[1] is the device path */
|
||||
if (dm_split_words(buffer, 3, 0, words) < 2)
|
||||
continue;
|
||||
|
||||
/* find the major/minor of the device */
|
||||
if (stat(words[0], &st))
|
||||
continue; /* can't stat, skip this one */
|
||||
|
||||
if (S_ISBLK(st.st_mode) &&
|
||||
major(st.st_rdev) == major &&
|
||||
minor(st.st_rdev) == minor) {
|
||||
syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.\n", device, words[1]);
|
||||
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
|
||||
syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.\n",
|
||||
device, words[1], strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(mounts))
|
||||
syslog(LOG_ERR, "Failed to close /proc/mounts.\n");
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **private)
|
||||
{
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
struct dm_status_snapshot *status = NULL;
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
int percent;
|
||||
struct dso_state *state = *private;
|
||||
|
||||
/* No longer monitoring, waiting for remove */
|
||||
if (!state->percent_check)
|
||||
return;
|
||||
|
||||
dmeventd_lvm2_lock();
|
||||
|
||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
if (!target_type)
|
||||
goto out;
|
||||
|
||||
if (!dm_get_status_snapshot(state->mem, params, &status))
|
||||
goto out;
|
||||
|
||||
if (status->invalid) {
|
||||
struct dm_info info;
|
||||
if (dm_task_get_info(dmt, &info)) {
|
||||
dmeventd_lvm2_unlock();
|
||||
_umount(device, info.major, info.minor);
|
||||
return;
|
||||
} /* else; too bad, but this is best-effort thing... */
|
||||
}
|
||||
|
||||
/* Snapshot size had changed. Clear the threshold. */
|
||||
if (state->known_size != status->total_sectors) {
|
||||
state->percent_check = CHECK_MINIMUM;
|
||||
state->known_size = status->total_sectors;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the snapshot has been invalidated or we failed to parse
|
||||
* the status string. Report the full status string to syslog.
|
||||
*/
|
||||
if (status->invalid || !status->total_sectors) {
|
||||
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
|
||||
state->percent_check = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
percent = (int) (100 * status->used_sectors / status->total_sectors);
|
||||
if (percent >= state->percent_check) {
|
||||
/* Usage has raised more than CHECK_STEP since the last
|
||||
time. Run actions. */
|
||||
state->percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
|
||||
|
||||
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
|
||||
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
|
||||
/* Try to extend the snapshot, in accord with user-set policies */
|
||||
if (!_extend(state->cmd_str))
|
||||
syslog(LOG_ERR, "Failed to extend snapshot %s.\n", device);
|
||||
}
|
||||
|
||||
out:
|
||||
if (status)
|
||||
dm_pool_free(state->mem, status);
|
||||
dmeventd_lvm2_unlock();
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **private)
|
||||
{
|
||||
struct dm_pool *statemem = NULL;
|
||||
struct dso_state *state;
|
||||
|
||||
if (!dmeventd_lvm2_init())
|
||||
goto out;
|
||||
|
||||
if (!(statemem = dm_pool_create("snapshot_state", 512)) ||
|
||||
!(state = dm_pool_zalloc(statemem, sizeof(*state))))
|
||||
goto bad;
|
||||
|
||||
if (!dmeventd_lvm2_command(statemem, state->cmd_str,
|
||||
sizeof(state->cmd_str),
|
||||
"lvextend --use-policies", device))
|
||||
goto bad;
|
||||
|
||||
state->mem = statemem;
|
||||
state->percent_check = CHECK_MINIMUM;
|
||||
*private = state;
|
||||
|
||||
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
|
||||
|
||||
return 1;
|
||||
bad:
|
||||
if (statemem)
|
||||
dm_pool_destroy(statemem);
|
||||
dmeventd_lvm2_exit();
|
||||
out:
|
||||
syslog(LOG_ERR, "Failed to monitor snapshot %s.\n", device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **private)
|
||||
{
|
||||
struct dso_state *state = *private;
|
||||
|
||||
syslog(LOG_INFO, "No longer monitoring snapshot %s\n", device);
|
||||
dm_pool_destroy(state->mem);
|
||||
dmeventd_lvm2_exit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
3
daemons/dmeventd/plugins/thin/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/thin/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
36
daemons/dmeventd/plugins/thin/Makefile.in
Normal file
36
daemons/dmeventd/plugins/thin/Makefile.in
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||
|
||||
SOURCES = dmeventd_thin.c
|
||||
|
||||
LIB_NAME = libdevmapper-event-lvm2thin
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
install: install_lvm2
|
||||
401
daemons/dmeventd/plugins/thin/dmeventd_thin.c
Normal file
401
daemons/dmeventd/plugins/thin/dmeventd_thin.c
Normal file
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
/* FIXME Missing openlog? */
|
||||
|
||||
/* First warning when thin is 80% full. */
|
||||
#define WARNING_THRESH 80
|
||||
/* Run a check every 5%. */
|
||||
#define CHECK_STEP 5
|
||||
/* Do not bother checking thins less than 50% full. */
|
||||
#define CHECK_MINIMUM 50
|
||||
|
||||
#define UMOUNT_COMMAND "/bin/umount"
|
||||
|
||||
#define THIN_DEBUG 0
|
||||
|
||||
struct dso_state {
|
||||
struct dm_pool *mem;
|
||||
int metadata_percent_check;
|
||||
int data_percent_check;
|
||||
uint64_t known_metadata_size;
|
||||
uint64_t known_data_size;
|
||||
char cmd_str[1024];
|
||||
};
|
||||
|
||||
|
||||
/* TODO - move this mountinfo code into library to be reusable */
|
||||
#ifdef linux
|
||||
# include "kdev_t.h"
|
||||
#else
|
||||
# define MAJOR(x) major((x))
|
||||
# define MINOR(x) minor((x))
|
||||
# define MKDEV(x,y) makedev((x),(y))
|
||||
#endif
|
||||
|
||||
/* Get dependencies for device, and try to find matching device */
|
||||
static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
const struct dm_deps *deps;
|
||||
struct dm_info info;
|
||||
int major, minor;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_name(dmt, name))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info))
|
||||
goto out;
|
||||
|
||||
if (!(deps = dm_task_get_deps(dmt)))
|
||||
goto out;
|
||||
|
||||
if (!info.exists || deps->count != 1)
|
||||
goto out;
|
||||
|
||||
major = (int) MAJOR(deps->device[0]);
|
||||
minor = (int) MINOR(deps->device[0]);
|
||||
if ((major != tp_major) || (minor != tp_minor))
|
||||
goto out;
|
||||
|
||||
*dev_minor = info.minor;
|
||||
|
||||
#if THIN_DEBUG
|
||||
{
|
||||
char dev_name[PATH_MAX];
|
||||
if (dm_device_get_name(major, minor, 0, dev_name, sizeof(dev_name)))
|
||||
syslog(LOG_DEBUG, "Found %s (%u:%u) depends on %s",
|
||||
name, major, *dev_minor, dev_name);
|
||||
}
|
||||
#endif
|
||||
r = 1;
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Get all active devices */
|
||||
static int _find_all_devs(dm_bitset_t bs, int tp_major, int tp_minor)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
struct dm_names *names;
|
||||
unsigned next = 0;
|
||||
int minor, r = 1;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(names = dm_task_get_names(dmt))) {
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!names->dev)
|
||||
goto out;
|
||||
|
||||
do {
|
||||
names = (struct dm_names *)((char *) names + next);
|
||||
if (_has_deps(names->name, tp_major, tp_minor, &minor))
|
||||
dm_bit_set(bs, minor);
|
||||
next = names->next;
|
||||
} while (next);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _extend(struct dso_state *state)
|
||||
{
|
||||
#if THIN_DEBUG
|
||||
syslog(LOG_INFO, "dmeventd executes: %s.\n", state->cmd_str);
|
||||
#endif
|
||||
return (dmeventd_lvm2_run(state->cmd_str) == ECMD_PROCESSED);
|
||||
}
|
||||
|
||||
static int _run(const char *cmd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int argc = 1; /* for argv[0], i.e. cmd */
|
||||
int i = 0;
|
||||
const char **argv;
|
||||
pid_t pid = fork();
|
||||
int status;
|
||||
|
||||
if (pid == 0) { /* child */
|
||||
va_start(ap, cmd);
|
||||
while (va_arg(ap, const char *))
|
||||
++argc;
|
||||
va_end(ap);
|
||||
|
||||
/* + 1 for the terminating NULL */
|
||||
argv = alloca(sizeof(const char *) * (argc + 1));
|
||||
|
||||
argv[0] = cmd;
|
||||
va_start(ap, cmd);
|
||||
while ((argv[++i] = va_arg(ap, const char *)));
|
||||
va_end(ap);
|
||||
|
||||
execvp(cmd, (char **)argv);
|
||||
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
|
||||
exit(127);
|
||||
}
|
||||
|
||||
if (pid > 0) { /* parent */
|
||||
if (waitpid(pid, &status, 0) != pid)
|
||||
return 0; /* waitpid failed */
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status))
|
||||
return 0; /* the child failed */
|
||||
}
|
||||
|
||||
if (pid < 0)
|
||||
return 0; /* fork failed */
|
||||
|
||||
return 1; /* all good */
|
||||
}
|
||||
|
||||
struct mountinfo_s {
|
||||
struct dm_info info;
|
||||
dm_bitset_t minors; /* Bitset for active thin pool minors */
|
||||
const char *device;
|
||||
};
|
||||
|
||||
static int _umount_device(char *buffer, unsigned major, unsigned minor,
|
||||
char *target, void *cb_data)
|
||||
{
|
||||
struct mountinfo_s *data = cb_data;
|
||||
|
||||
if ((major == data->info.major) && dm_bit(data->minors, minor)) {
|
||||
syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n",
|
||||
data->device, target);
|
||||
if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
|
||||
syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
|
||||
data->device, target, strerror(errno));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find all thin pool users and try to umount them.
|
||||
* TODO: work with read-only thin pool support
|
||||
*/
|
||||
static void _umount(struct dm_task *dmt, const char *device)
|
||||
{
|
||||
static const size_t MINORS = 4096;
|
||||
struct mountinfo_s data = {
|
||||
.device = device,
|
||||
};
|
||||
|
||||
if (!dm_task_get_info(dmt, &data.info))
|
||||
return;
|
||||
|
||||
dmeventd_lvm2_unlock();
|
||||
|
||||
if (!(data.minors = dm_bitset_create(NULL, MINORS))) {
|
||||
syslog(LOG_ERR, "Failed to allocate bitset. Not unmounting %s.\n", device);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) {
|
||||
syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dm_mountinfo_read(_umount_device, &data)) {
|
||||
syslog(LOG_ERR, "Could not parse mountinfo file.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (data.minors)
|
||||
dm_bitset_destroy(data.minors);
|
||||
dmeventd_lvm2_lock();
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **private)
|
||||
{
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
int percent;
|
||||
struct dso_state *state = *private;
|
||||
struct dm_status_thin_pool *tps = NULL;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
|
||||
#if 0
|
||||
/* No longer monitoring, waiting for remove */
|
||||
if (!state->meta_percent_check && !state->data_percent_check)
|
||||
return;
|
||||
#endif
|
||||
dmeventd_lvm2_lock();
|
||||
|
||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
|
||||
if (!target_type || (strcmp(target_type, "thin-pool") != 0)) {
|
||||
syslog(LOG_ERR, "Invalid target type.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
|
||||
syslog(LOG_ERR, "Failed to parse status.\n");
|
||||
_umount(dmt, device);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if THIN_DEBUG
|
||||
syslog(LOG_INFO, "%p: Got status %" PRIu64 " / %" PRIu64
|
||||
" %" PRIu64 " / %" PRIu64 ".\n", state,
|
||||
tps->used_metadata_blocks, tps->total_metadata_blocks,
|
||||
tps->used_data_blocks, tps->total_data_blocks);
|
||||
#endif
|
||||
|
||||
/* Thin pool size had changed. Clear the threshold. */
|
||||
if (state->known_metadata_size != tps->total_metadata_blocks) {
|
||||
state->metadata_percent_check = CHECK_MINIMUM;
|
||||
state->known_metadata_size = tps->total_metadata_blocks;
|
||||
}
|
||||
|
||||
if (state->known_data_size != tps->total_data_blocks) {
|
||||
state->data_percent_check = CHECK_MINIMUM;
|
||||
state->known_data_size = tps->total_data_blocks;
|
||||
}
|
||||
|
||||
percent = 100 * tps->used_metadata_blocks / tps->total_metadata_blocks;
|
||||
if (percent >= state->metadata_percent_check) {
|
||||
/*
|
||||
* Usage has raised more than CHECK_STEP since the last
|
||||
* time. Run actions.
|
||||
*/
|
||||
state->metadata_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
|
||||
|
||||
/* FIXME: extension of metadata needs to be written! */
|
||||
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
|
||||
syslog(LOG_WARNING, "Thin metadata %s is now %i%% full.\n",
|
||||
device, percent);
|
||||
/* Try to extend the metadata, in accord with user-set policies */
|
||||
if (!_extend(state)) {
|
||||
syslog(LOG_ERR, "Failed to extend thin metadata %s.\n",
|
||||
device);
|
||||
_umount(dmt, device);
|
||||
}
|
||||
/* FIXME: hmm READ-ONLY switch should happen in error path */
|
||||
}
|
||||
|
||||
percent = 100 * tps->used_data_blocks / tps->total_data_blocks;
|
||||
if (percent >= state->data_percent_check) {
|
||||
/*
|
||||
* Usage has raised more than CHECK_STEP since
|
||||
* the last time. Run actions.
|
||||
*/
|
||||
state->data_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
|
||||
|
||||
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
|
||||
syslog(LOG_WARNING, "Thin %s is now %i%% full.\n", device, percent);
|
||||
/* Try to extend the thin data, in accord with user-set policies */
|
||||
if (!_extend(state)) {
|
||||
syslog(LOG_ERR, "Failed to extend thin %s.\n", device);
|
||||
state->data_percent_check = 0;
|
||||
_umount(dmt, device);
|
||||
}
|
||||
/* FIXME: hmm READ-ONLY switch should happen in error path */
|
||||
}
|
||||
out:
|
||||
if (tps)
|
||||
dm_pool_free(state->mem, tps);
|
||||
|
||||
dmeventd_lvm2_unlock();
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **private)
|
||||
{
|
||||
struct dm_pool *statemem = NULL;
|
||||
struct dso_state *state;
|
||||
|
||||
if (!dmeventd_lvm2_init())
|
||||
goto bad;
|
||||
|
||||
if (!(statemem = dm_pool_create("thin_pool_state", 2048)) ||
|
||||
!(state = dm_pool_zalloc(statemem, sizeof(*state))) ||
|
||||
!dmeventd_lvm2_command(statemem, state->cmd_str,
|
||||
sizeof(state->cmd_str),
|
||||
"lvextend --use-policies",
|
||||
device)) {
|
||||
if (statemem)
|
||||
dm_pool_destroy(statemem);
|
||||
dmeventd_lvm2_exit();
|
||||
goto bad;
|
||||
}
|
||||
|
||||
state->mem = statemem;
|
||||
state->metadata_percent_check = CHECK_MINIMUM;
|
||||
state->data_percent_check = CHECK_MINIMUM;
|
||||
*private = state;
|
||||
|
||||
syslog(LOG_INFO, "Monitoring thin %s.\n", device);
|
||||
|
||||
return 1;
|
||||
bad:
|
||||
syslog(LOG_ERR, "Failed to monitor thin %s.\n", device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute__((unused)),
|
||||
int major __attribute__((unused)),
|
||||
int minor __attribute__((unused)),
|
||||
void **private)
|
||||
{
|
||||
struct dso_state *state = *private;
|
||||
|
||||
syslog(LOG_INFO, "No longer monitoring thin %s.\n", device);
|
||||
dm_pool_destroy(state->mem);
|
||||
dmeventd_lvm2_exit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
59
daemons/lvmetad/Makefile.in
Normal file
59
daemons/lvmetad/Makefile.in
Normal file
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# Copyright (C) 2011-2012 Red Hat, Inc.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU Lesser General Public License v.2.1.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SOURCES = lvmetad-core.c
|
||||
SOURCES2 = testclient.c
|
||||
|
||||
TARGETS = lvmetad lvmetad-testclient
|
||||
|
||||
.PHONY: install_lvmetad
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
CFLOW_TARGET = lvmetad
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||
LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
|
||||
|
||||
LIBS += $(PTHREAD_LIBS)
|
||||
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server
|
||||
CLDFLAGS += -L$(top_builddir)/libdaemon/server
|
||||
|
||||
lvmetad: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
||||
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
# TODO: No idea. No idea how to test either.
|
||||
#ifneq ("$(CFLOW_CMD)", "")
|
||||
#CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
#-include $(top_builddir)/libdm/libdevmapper.cflow
|
||||
#-include $(top_builddir)/lib/liblvm-internal.cflow
|
||||
#-include $(top_builddir)/lib/liblvm2cmd.cflow
|
||||
#-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
|
||||
#-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
|
||||
#endif
|
||||
|
||||
install_lvmetad: lvmetad
|
||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
||||
install_lvm2: install_lvmetad
|
||||
|
||||
install: install_lvm2
|
||||
81
daemons/lvmetad/lvmetad-client.h
Normal file
81
daemons/lvmetad/lvmetad-client.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Red Hat, Inc.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LVMETAD_CLIENT_H
|
||||
#define _LVM_LVMETAD_CLIENT_H
|
||||
|
||||
#include "daemon-client.h"
|
||||
|
||||
struct volume_group;
|
||||
|
||||
/* Different types of replies we may get from lvmetad. */
|
||||
|
||||
typedef struct {
|
||||
daemon_reply r;
|
||||
const char **uuids; /* NULL terminated array */
|
||||
} lvmetad_uuidlist;
|
||||
|
||||
typedef struct {
|
||||
daemon_reply r;
|
||||
struct dm_config_tree *cft;
|
||||
} lvmetad_vg;
|
||||
|
||||
/* Get a list of VG UUIDs that match a given VG name. */
|
||||
lvmetad_uuidlist lvmetad_lookup_vgname(daemon_handle h, const char *name);
|
||||
|
||||
/* Get the metadata of a single VG, identified by UUID. */
|
||||
lvmetad_vg lvmetad_get_vg(daemon_handle h, const char *uuid);
|
||||
|
||||
/*
|
||||
* Add and remove PVs on demand. Udev-driven systems will use this interface
|
||||
* instead of scanning.
|
||||
*/
|
||||
daemon_reply lvmetad_add_pv(daemon_handle h, const char *pv_uuid, const char *mda_content);
|
||||
daemon_reply lvmetad_remove_pv(daemon_handle h, const char *pv_uuid);
|
||||
|
||||
/* Trigger a full disk scan, throwing away all caches. XXX do we eventually want
|
||||
* this? Probably not yet, anyway.
|
||||
* daemon_reply lvmetad_rescan(daemon_handle h);
|
||||
*/
|
||||
|
||||
/*
|
||||
* Update the version of metadata of a volume group. The VG has to be locked for
|
||||
* writing for this, and the VG metadata here has to match whatever has been
|
||||
* written to the disk (under this lock). This initially avoids the requirement
|
||||
* for lvmetad to write to disk (in later revisions, lvmetad_supersede_vg may
|
||||
* also do the writing, or we probably add another function to do that).
|
||||
*/
|
||||
daemon_reply lvmetad_supersede_vg(daemon_handle h, struct volume_group *vg);
|
||||
|
||||
/* Wrappers to open/close connection */
|
||||
|
||||
static inline daemon_handle lvmetad_open(const char *socket)
|
||||
{
|
||||
daemon_info lvmetad_info = {
|
||||
.path = "lvmetad",
|
||||
.socket = socket ?: DEFAULT_RUN_DIR "/lvmetad.socket",
|
||||
.protocol = "lvmetad",
|
||||
.protocol_version = 1,
|
||||
.autostart = 0
|
||||
};
|
||||
|
||||
return daemon_open(lvmetad_info);
|
||||
}
|
||||
|
||||
static inline void lvmetad_close(daemon_handle h)
|
||||
{
|
||||
return daemon_close(h);
|
||||
}
|
||||
|
||||
#endif
|
||||
1227
daemons/lvmetad/lvmetad-core.c
Normal file
1227
daemons/lvmetad/lvmetad-core.c
Normal file
File diff suppressed because it is too large
Load Diff
16
daemons/lvmetad/test.sh
Executable file
16
daemons/lvmetad/test.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
export LD_LIBRARY_PATH="$1"
|
||||
|
||||
test -n "$2" && {
|
||||
rm -f /var/run/lvmetad.{socket,pid}
|
||||
chmod +rx lvmetad
|
||||
valgrind ./lvmetad -f &
|
||||
PID=$!
|
||||
sleep 1
|
||||
./testclient
|
||||
kill $PID
|
||||
exit 0
|
||||
}
|
||||
|
||||
sudo ./test.sh "$1" .
|
||||
127
daemons/lvmetad/testclient.c
Normal file
127
daemons/lvmetad/testclient.c
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "lvmetad-client.h"
|
||||
#include "label.h"
|
||||
#include "lvmcache.h"
|
||||
#include "metadata.h"
|
||||
|
||||
const char *uuid1 = "abcd-efgh";
|
||||
const char *uuid2 = "bbcd-efgh";
|
||||
const char *vgid = "yada-yada";
|
||||
const char *uuid3 = "cbcd-efgh";
|
||||
|
||||
const char *metadata2 = "{\n"
|
||||
"id = \"yada-yada\"\n"
|
||||
"seqno = 15\n"
|
||||
"status = [\"READ\", \"WRITE\"]\n"
|
||||
"flags = []\n"
|
||||
"extent_size = 8192\n"
|
||||
"physical_volumes {\n"
|
||||
" pv0 {\n"
|
||||
" id = \"abcd-efgh\"\n"
|
||||
" }\n"
|
||||
" pv1 {\n"
|
||||
" id = \"bbcd-efgh\"\n"
|
||||
" }\n"
|
||||
" pv2 {\n"
|
||||
" id = \"cbcd-efgh\"\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"}\n";
|
||||
|
||||
void _handle_reply(daemon_reply reply) {
|
||||
const char *repl = daemon_reply_str(reply, "response", NULL);
|
||||
const char *status = daemon_reply_str(reply, "status", NULL);
|
||||
const char *vgid = daemon_reply_str(reply, "vgid", NULL);
|
||||
|
||||
fprintf(stderr, "[C] REPLY: %s\n", repl);
|
||||
if (!strcmp(repl, "failed"))
|
||||
fprintf(stderr, "[C] REASON: %s\n", daemon_reply_str(reply, "reason", "unknown"));
|
||||
if (vgid)
|
||||
fprintf(stderr, "[C] VGID: %s\n", vgid);
|
||||
if (status)
|
||||
fprintf(stderr, "[C] STATUS: %s\n", status);
|
||||
daemon_reply_destroy(reply);
|
||||
}
|
||||
|
||||
void _pv_add(daemon_handle h, const char *uuid, const char *metadata)
|
||||
{
|
||||
daemon_reply reply = daemon_send_simple(h, "pv_add", "uuid = %s", uuid,
|
||||
"metadata = %b", metadata,
|
||||
NULL);
|
||||
_handle_reply(reply);
|
||||
}
|
||||
|
||||
int scan(daemon_handle h, char *fn) {
|
||||
struct device *dev = dev_cache_get(fn, NULL);
|
||||
|
||||
struct label *label;
|
||||
if (!label_read(dev, &label, 0)) {
|
||||
fprintf(stderr, "[C] no label found on %s\n", fn);
|
||||
return;
|
||||
}
|
||||
|
||||
char uuid[64];
|
||||
id_write_format(dev->pvid, uuid, 64);
|
||||
fprintf(stderr, "[C] found PV: %s\n", uuid);
|
||||
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
|
||||
struct physical_volume pv = { 0, };
|
||||
|
||||
if (!(info->fmt->ops->pv_read(info->fmt, dev_name(dev), &pv, 0))) {
|
||||
fprintf(stderr, "[C] Failed to read PV %s", dev_name(dev));
|
||||
return;
|
||||
}
|
||||
|
||||
struct format_instance_ctx fic;
|
||||
struct format_instance *fid = info->fmt->ops->create_instance(info->fmt, &fic);
|
||||
struct metadata_area *mda;
|
||||
struct volume_group *vg = NULL;
|
||||
dm_list_iterate_items(mda, &info->mdas) {
|
||||
struct volume_group *this = mda->ops->vg_read(fid, "", mda);
|
||||
if (this && !vg || this->seqno > vg->seqno)
|
||||
vg = this;
|
||||
}
|
||||
if (vg) {
|
||||
char *buf = NULL;
|
||||
/* TODO. This is not entirely correct, since export_vg_to_buffer
|
||||
* adds trailing garbage to the buffer. We may need to use
|
||||
* export_vg_to_config_tree and format the buffer ourselves. It
|
||||
* does, however, work for now, since the garbage is well
|
||||
* formatted and has no conflicting keys with the rest of the
|
||||
* request. */
|
||||
export_vg_to_buffer(vg, &buf);
|
||||
daemon_reply reply =
|
||||
daemon_send_simple(h, "pv_add", "uuid = %s", uuid,
|
||||
"metadata = %b", strchr(buf, '{'),
|
||||
NULL);
|
||||
_handle_reply(reply);
|
||||
}
|
||||
}
|
||||
|
||||
void _dump_vg(daemon_handle h, const char *uuid)
|
||||
{
|
||||
daemon_reply reply = daemon_send_simple(h, "vg_by_uuid", "uuid = %s", uuid, NULL);
|
||||
fprintf(stderr, "[C] reply buffer: %s\n", reply.buffer);
|
||||
daemon_reply_destroy(reply);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
daemon_handle h = lvmetad_open();
|
||||
|
||||
if (argc > 1) {
|
||||
int i;
|
||||
struct cmd_context *cmd = create_toolcontext(0, NULL, 0, 0);
|
||||
for (i = 1; i < argc; ++i) {
|
||||
const char *uuid = NULL;
|
||||
scan(h, argv[i]);
|
||||
}
|
||||
destroy_toolcontext(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_pv_add(h, uuid1, NULL);
|
||||
_pv_add(h, uuid2, metadata2);
|
||||
_dump_vg(h, vgid);
|
||||
_pv_add(h, uuid3, NULL);
|
||||
|
||||
daemon_close(h);
|
||||
return 0;
|
||||
}
|
||||
1
doc/.gitignore
vendored
Normal file
1
doc/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
example.conf
|
||||
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!
|
||||
893
doc/example.conf.in
Normal file
893
doc/example.conf.in
Normal file
@@ -0,0 +1,893 @@
|
||||
# This is an example configuration file for the LVM2 system.
|
||||
# It contains the default settings that would be used if there was no
|
||||
# @DEFAULT_SYS_DIR@/lvm.conf file.
|
||||
#
|
||||
# Refer to 'man lvm.conf' for further information including the file layout.
|
||||
#
|
||||
# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set
|
||||
# the environment variable LVM_SYSTEM_DIR before running the tools.
|
||||
#
|
||||
# N.B. Take care that each setting only appears once if uncommenting
|
||||
# example settings in this file.
|
||||
|
||||
# This section allows you to set the way the configuration settings are handled.
|
||||
config {
|
||||
|
||||
# If enabled, any LVM2 configuration mismatch is reported.
|
||||
# This implies checking that the configuration key is understood
|
||||
# by LVM2 and that the value of the key is of a proper type.
|
||||
# If disabled, any configuration mismatch is ignored and default
|
||||
# value is used instead without any warning (a message about the
|
||||
# configuration key not being found is issued in verbose mode only).
|
||||
checks = 1
|
||||
|
||||
# If enabled, any configuration mismatch aborts the LVM2 process.
|
||||
abort_on_errors = 0
|
||||
}
|
||||
|
||||
# This section allows you to configure which block devices should
|
||||
# be used by the LVM system.
|
||||
devices {
|
||||
|
||||
# Where do you want your volume groups to appear ?
|
||||
dir = "/dev"
|
||||
|
||||
# An array of directories that contain the device nodes you wish
|
||||
# to use with LVM2.
|
||||
scan = [ "/dev" ]
|
||||
|
||||
# If set, the cache of block device nodes with all associated symlinks
|
||||
# will be constructed out of the existing udev database content.
|
||||
# This avoids using and opening any inapplicable non-block devices or
|
||||
# subdirectories found in the device directory. This setting is applied
|
||||
# to udev-managed device directory only, other directories will be scanned
|
||||
# fully. LVM2 needs to be compiled with udev support for this setting to
|
||||
# take effect. N.B. Any device node or symlink not managed by udev in
|
||||
# udev directory will be ignored with this setting on.
|
||||
obtain_device_list_from_udev = 1
|
||||
|
||||
# If several entries in the scanned directories correspond to the
|
||||
# same block device and the tools need to display a name for device,
|
||||
# all the pathnames are matched against each item in the following
|
||||
# list of regular expressions in turn and the first match is used.
|
||||
preferred_names = [ ]
|
||||
|
||||
# Try to avoid using undescriptive /dev/dm-N names, if present.
|
||||
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
|
||||
|
||||
# A filter that tells LVM2 to only use a restricted set of devices.
|
||||
# The filter consists of an array of regular expressions. These
|
||||
# expressions can be delimited by a character of your choice, and
|
||||
# prefixed with either an 'a' (for accept) or 'r' (for reject).
|
||||
# The first expression found to match a device name determines if
|
||||
# the device will be accepted or rejected (ignored). Devices that
|
||||
# don't match any patterns are accepted.
|
||||
|
||||
# Be careful if there there are symbolic links or multiple filesystem
|
||||
# entries for the same device as each name is checked separately against
|
||||
# the list of patterns. The effect is that if the first pattern in the
|
||||
# list to match a name is an 'a' pattern for any of the names, the device
|
||||
# is accepted; otherwise if the first pattern in the list to match a name
|
||||
# is an 'r' pattern for any of the names it is rejected; otherwise it is
|
||||
# accepted.
|
||||
|
||||
# Don't have more than one filter line active at once: only one gets used.
|
||||
|
||||
# Run vgscan after you change this parameter to ensure that
|
||||
# the cache file gets regenerated (see below).
|
||||
# If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
|
||||
|
||||
|
||||
# By default we accept every block device:
|
||||
filter = [ "a/.*/" ]
|
||||
|
||||
# Exclude the cdrom drive
|
||||
# filter = [ "r|/dev/cdrom|" ]
|
||||
|
||||
# When testing I like to work with just loopback devices:
|
||||
# filter = [ "a/loop/", "r/.*/" ]
|
||||
|
||||
# Or maybe all loops and ide drives except hdc:
|
||||
# filter =[ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
|
||||
|
||||
# Use anchors if you want to be really specific
|
||||
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
|
||||
|
||||
# Since "filter" is often overriden from command line, it is not suitable
|
||||
# for system-wide device filtering (udev rules, lvmetad). To hide devices
|
||||
# from LVM-specific udev processing and/or from lvmetad, you need to set
|
||||
# global_filter. The syntax is the same as for normal "filter"
|
||||
# above. Devices that fail the global_filter are not even opened by LVM.
|
||||
|
||||
# global_filter = []
|
||||
|
||||
# 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.)
|
||||
# N.B. If obtain_device_list_from_udev is set to 1 the list of
|
||||
# devices is instead obtained from udev and any existing .cache
|
||||
# file is removed.
|
||||
cache_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@"
|
||||
cache_file_prefix = ""
|
||||
|
||||
# You can turn off writing this cache file by setting this to 0.
|
||||
write_cache_state = 1
|
||||
|
||||
# Advanced settings.
|
||||
|
||||
# List of pairs of additional acceptable block device types found
|
||||
# in /proc/devices with maximum (non-zero) number of partitions.
|
||||
# types = [ "fd", 16 ]
|
||||
|
||||
# If sysfs is mounted (2.6 kernels) restrict device scanning to
|
||||
# the block devices it believes are valid.
|
||||
# 1 enables; 0 disables.
|
||||
sysfs_scan = 1
|
||||
|
||||
# By default, LVM2 will ignore devices used as component paths
|
||||
# of device-mapper multipath devices.
|
||||
# 1 enables; 0 disables.
|
||||
multipath_component_detection = 1
|
||||
|
||||
# By default, LVM2 will ignore devices used as components of
|
||||
# software RAID (md) devices by looking for md superblocks.
|
||||
# 1 enables; 0 disables.
|
||||
md_component_detection = 1
|
||||
|
||||
# By default, if a PV is placed directly upon an md device, LVM2
|
||||
# will align its data blocks with the md device's stripe-width.
|
||||
# 1 enables; 0 disables.
|
||||
md_chunk_alignment = 1
|
||||
|
||||
# Default alignment of the start of a data area in MB. If set to 0,
|
||||
# a value of 64KB will be used. Set to 1 for 1MiB, 2 for 2MiB, etc.
|
||||
# default_data_alignment = @DEFAULT_DATA_ALIGNMENT@
|
||||
|
||||
# By default, the start of a PV's data area will be a multiple of
|
||||
# the 'minimum_io_size' or 'optimal_io_size' exposed in sysfs.
|
||||
# - minimum_io_size - the smallest request the device can perform
|
||||
# w/o incurring a read-modify-write penalty (e.g. MD's chunk size)
|
||||
# - optimal_io_size - the device's preferred unit of receiving I/O
|
||||
# (e.g. MD's stripe width)
|
||||
# minimum_io_size is used if optimal_io_size is undefined (0).
|
||||
# If md_chunk_alignment is enabled, that detects the optimal_io_size.
|
||||
# This setting takes precedence over md_chunk_alignment.
|
||||
# 1 enables; 0 disables.
|
||||
data_alignment_detection = 1
|
||||
|
||||
# Alignment (in KB) of start of data area when creating a new PV.
|
||||
# md_chunk_alignment and data_alignment_detection are disabled if set.
|
||||
# Set to 0 for the default alignment (see: data_alignment_default)
|
||||
# or page size, if larger.
|
||||
data_alignment = 0
|
||||
|
||||
# By default, the start of the PV's aligned data area will be shifted by
|
||||
# the 'alignment_offset' exposed in sysfs. This offset is often 0 but
|
||||
# may be non-zero; e.g.: certain 4KB sector drives that compensate for
|
||||
# windows partitioning will have an alignment_offset of 3584 bytes
|
||||
# (sector 7 is the lowest aligned logical block, the 4KB sectors start
|
||||
# at LBA -1, and consequently sector 63 is aligned on a 4KB boundary).
|
||||
# But note that pvcreate --dataalignmentoffset will skip this detection.
|
||||
# 1 enables; 0 disables.
|
||||
data_alignment_offset_detection = 1
|
||||
|
||||
# If, while scanning the system for PVs, LVM2 encounters a device-mapper
|
||||
# device that has its I/O suspended, it waits for it to become accessible.
|
||||
# Set this to 1 to skip such devices. This should only be needed
|
||||
# in recovery situations.
|
||||
ignore_suspended_devices = 0
|
||||
|
||||
# During each LVM operation errors received from each device are counted.
|
||||
# If the counter of a particular device exceeds the limit set here, no
|
||||
# further I/O is sent to that device for the remainder of the respective
|
||||
# operation. Setting the parameter to 0 disables the counters altogether.
|
||||
disable_after_error_count = 0
|
||||
|
||||
# Allow use of pvcreate --uuid without requiring --restorefile.
|
||||
require_restorefile_with_uuid = 1
|
||||
|
||||
# Minimum size (in KB) of block devices which can be used as PVs.
|
||||
# In a clustered environment all nodes must use the same value.
|
||||
# Any value smaller than 512KB is ignored.
|
||||
|
||||
# Ignore devices smaller than 2MB such as floppy drives.
|
||||
pv_min_size = 2048
|
||||
|
||||
# The original built-in setting was 512 up to and including version 2.02.84.
|
||||
# pv_min_size = 512
|
||||
|
||||
# Issue discards to a logical volumes's underlying physical volume(s) when
|
||||
# the logical volume is no longer using the physical volumes' space (e.g.
|
||||
# lvremove, lvreduce, etc). Discards inform the storage that a region is
|
||||
# no longer in use. Storage that supports discards advertise the protocol
|
||||
# specific way discards should be issued by the kernel (TRIM, UNMAP, or
|
||||
# WRITE SAME with UNMAP bit set). Not all storage will support or benefit
|
||||
# from discards but SSDs and thinly provisioned LUNs generally do. If set
|
||||
# to 1, discards will only be issued if both the storage and kernel provide
|
||||
# support.
|
||||
# 1 enables; 0 disables.
|
||||
issue_discards = 0
|
||||
}
|
||||
|
||||
# This section allows you to configure the way in which LVM selects
|
||||
# free space for its Logical Volumes.
|
||||
allocation {
|
||||
|
||||
# When searching for free space to extend an LV, the "cling"
|
||||
# allocation policy will choose space on the same PVs as the last
|
||||
# segment of the existing LV. If there is insufficient space and a
|
||||
# list of tags is defined here, it will check whether any of them are
|
||||
# attached to the PVs concerned and then seek to match those PV tags
|
||||
# between existing extents and new extents.
|
||||
# Use the special tag "@*" as a wildcard to match any PV tag.
|
||||
|
||||
# Example: LVs are mirrored between two sites within a single VG.
|
||||
# PVs are tagged with either @site1 or @site2 to indicate where
|
||||
# they are situated.
|
||||
|
||||
# cling_tag_list = [ "@site1", "@site2" ]
|
||||
# cling_tag_list = [ "@*" ]
|
||||
|
||||
# Changes made in version 2.02.85 extended the reach of the 'cling'
|
||||
# policies to detect more situations where data can be grouped
|
||||
# onto the same disks. Set this to 0 to revert to the previous
|
||||
# algorithm.
|
||||
maximise_cling = 1
|
||||
|
||||
# Set to 1 to guarantee that mirror logs will always be placed on
|
||||
# different PVs from the mirror images. This was the default
|
||||
# until version 2.02.85.
|
||||
mirror_logs_require_separate_pvs = 0
|
||||
|
||||
# Set to 1 to guarantee that thin pool metadata will always
|
||||
# be placed on different PVs from the pool data.
|
||||
thin_pool_metadata_require_separate_pvs = 0
|
||||
|
||||
# Specify the minimal chunk size (in KB) for thin pool volumes.
|
||||
# Use of the larger chunk size may improve perfomance for plain
|
||||
# thin volumes, however using them for snapshot volumes is less efficient,
|
||||
# as it consumes more space and takes extra time for copying.
|
||||
# When unset, lvm tries to estimate chunk size starting from 64KB
|
||||
# Supported values are in range from 64 to 1048576.
|
||||
# thin_pool_chunk_size = 64
|
||||
|
||||
# Specify discards behavior of the thin pool volume.
|
||||
# Select one of "ignore", "nopassdown", "passdown"
|
||||
# thin_pool_discards = "passdown"
|
||||
|
||||
# Set to 0, to disable zeroing of thin pool data chunks before their
|
||||
# first use.
|
||||
# N.B. zeroing larger thin pool chunk size degrades performance.
|
||||
# thin_pool_zero = 1
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
# Set to 1 to suppress all non-essential messages from stdout.
|
||||
# This has the same effect as -qq.
|
||||
# When this is set, the following commands still produce output:
|
||||
# dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
|
||||
# pvs, version, vgcfgrestore -l, vgdisplay, vgs.
|
||||
# Non-essential messages are shifted from log level 4 to log level 5
|
||||
# for syslog and lvm2_log_fn purposes.
|
||||
# Any 'yes' or 'no' questions not overridden by other arguments
|
||||
# are suppressed and default to 'no'.
|
||||
silent = 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
|
||||
|
||||
# Some debugging messages are assigned to a class and only appear
|
||||
# in debug output if the class is listed here.
|
||||
# Classes currently available:
|
||||
# memory, devices, activation, allocation, lvmetad, metadata, cache,
|
||||
# locking
|
||||
# Use "all" to see everything.
|
||||
debug_classes = [ "memory", "devices", "activation", "allocation",
|
||||
"lvmetad", "metadata", "cache", "locking" ]
|
||||
}
|
||||
|
||||
# Configuration of metadata backups and archiving. In LVM2 when we
|
||||
# talk about a 'backup' we mean making a copy of the metadata for the
|
||||
# *current* system. The 'archive' contains old metadata configurations.
|
||||
# Backups are stored in a human readeable text format.
|
||||
backup {
|
||||
|
||||
# Should we maintain a backup of the current metadata configuration ?
|
||||
# Use 1 for Yes; 0 for No.
|
||||
# Think very hard before turning this off!
|
||||
backup = 1
|
||||
|
||||
# Where shall we keep it ?
|
||||
# Remember to back up this directory regularly!
|
||||
backup_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_BACKUP_SUBDIR@"
|
||||
|
||||
# Should we maintain an archive of old metadata configurations.
|
||||
# Use 1 for Yes; 0 for No.
|
||||
# On by default. Think very hard before turning this off.
|
||||
archive = 1
|
||||
|
||||
# Where should archived files go ?
|
||||
# Remember to back up this directory regularly!
|
||||
archive_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_ARCHIVE_SUBDIR@"
|
||||
|
||||
# What is the minimum number of archive files you wish to keep ?
|
||||
retain_min = 10
|
||||
|
||||
# What is the minimum time you wish to keep an archive file for ?
|
||||
retain_days = 30
|
||||
}
|
||||
|
||||
# Settings for the running LVM2 in shell (readline) mode.
|
||||
shell {
|
||||
|
||||
# Number of lines of history to store in ~/.lvm_history
|
||||
history_size = 100
|
||||
}
|
||||
|
||||
|
||||
# Miscellaneous global LVM2 settings
|
||||
global {
|
||||
# The file creation mask for any files and directories created.
|
||||
# Interpreted as octal if the first digit is zero.
|
||||
umask = 077
|
||||
|
||||
# Allow other users to read the files
|
||||
#umask = 022
|
||||
|
||||
# Enabling test mode means that no changes to the on disk metadata
|
||||
# will be made. Equivalent to having the -t option on every
|
||||
# command. Defaults to off.
|
||||
test = 0
|
||||
|
||||
# Default value for --units argument
|
||||
units = "h"
|
||||
|
||||
# Since version 2.02.54, the tools distinguish between powers of
|
||||
# 1024 bytes (e.g. KiB, MiB, GiB) and powers of 1000 bytes (e.g.
|
||||
# KB, MB, GB).
|
||||
# If you have scripts that depend on the old behaviour, set this to 0
|
||||
# temporarily until you update them.
|
||||
si_unit_consistency = 1
|
||||
|
||||
# Whether or not to communicate with the kernel device-mapper.
|
||||
# Set to 0 if you want to use the tools to manipulate LVM metadata
|
||||
# without activating any logical volumes.
|
||||
# If the device-mapper kernel driver is not present in your kernel
|
||||
# setting this to 0 should suppress the error messages.
|
||||
activation = 1
|
||||
|
||||
# If we can't communicate with device-mapper, should we try running
|
||||
# the LVM1 tools?
|
||||
# This option only applies to 2.4 kernels and is provided to help you
|
||||
# switch between device-mapper kernels and LVM1 kernels.
|
||||
# The LVM1 tools need to be installed with .lvm1 suffices
|
||||
# e.g. vgscan.lvm1 and they will stop working after you start using
|
||||
# the new lvm2 on-disk metadata format.
|
||||
# The default value is set when the tools are built.
|
||||
# fallback_to_lvm1 = 0
|
||||
|
||||
# The default metadata format that commands should use - "lvm1" or "lvm2".
|
||||
# The command line override is -M1 or -M2.
|
||||
# Defaults to "lvm2".
|
||||
# format = "lvm2"
|
||||
|
||||
# Location of proc filesystem
|
||||
proc = "/proc"
|
||||
|
||||
# Type of locking to use. Defaults to local file-based locking (1).
|
||||
# Turn locking off by setting to 0 (dangerous: risks metadata corruption
|
||||
# if LVM2 commands get run concurrently).
|
||||
# Type 2 uses the external shared library locking_library.
|
||||
# Type 3 uses built-in clustered locking.
|
||||
# Type 4 uses read-only locking which forbids any operations that might
|
||||
# change metadata.
|
||||
locking_type = 1
|
||||
|
||||
# Set to 0 to fail when a lock request cannot be satisfied immediately.
|
||||
wait_for_locks = 1
|
||||
|
||||
# If using external locking (type 2) and initialisation fails,
|
||||
# with this set to 1 an attempt will be made to use the built-in
|
||||
# clustered locking.
|
||||
# If you are using a customised locking_library you should set this to 0.
|
||||
fallback_to_clustered_locking = 1
|
||||
|
||||
# If an attempt to initialise type 2 or type 3 locking failed, perhaps
|
||||
# because cluster components such as clvmd are not running, with this set
|
||||
# to 1 an attempt will be made to use local file-based locking (type 1).
|
||||
# If this succeeds, only commands against local volume groups will proceed.
|
||||
# Volume Groups marked as clustered will be ignored.
|
||||
fallback_to_local_locking = 1
|
||||
|
||||
# Local non-LV directory that holds file-based locks while commands are
|
||||
# in progress. A directory like /tmp that may get wiped on reboot is OK.
|
||||
locking_dir = "@DEFAULT_LOCK_DIR@"
|
||||
|
||||
# Whenever there are competing read-only and read-write access requests for
|
||||
# a volume group's metadata, instead of always granting the read-only
|
||||
# requests immediately, delay them to allow the read-write requests to be
|
||||
# serviced. Without this setting, write access may be stalled by a high
|
||||
# volume of read-only requests.
|
||||
# NB. This option only affects locking_type = 1 viz. local file-based
|
||||
# locking.
|
||||
prioritise_write_locks = 1
|
||||
|
||||
# Other entries can go here to allow you to load shared libraries
|
||||
# e.g. if support for LVM1 metadata was compiled as a shared library use
|
||||
# format_libraries = "liblvm2format1.so"
|
||||
# Full pathnames can be given.
|
||||
|
||||
# Search this directory first for shared libraries.
|
||||
# library_dir = "/lib"
|
||||
|
||||
# The external locking library to load if locking_type is set to 2.
|
||||
# locking_library = "liblvm2clusterlock.so"
|
||||
|
||||
# Treat any internal errors as fatal errors, aborting the process that
|
||||
# encountered the internal error. Please only enable for debugging.
|
||||
abort_on_internal_errors = 0
|
||||
|
||||
# Check whether CRC is matching when parsed VG is used multiple times.
|
||||
# This is useful to catch unexpected internal cached volume group
|
||||
# structure modification. Please only enable for debugging.
|
||||
detect_internal_vg_cache_corruption = 0
|
||||
|
||||
# If set to 1, no operations that change on-disk metadata will be permitted.
|
||||
# Additionally, read-only commands that encounter metadata in need of repair
|
||||
# will still be allowed to proceed exactly as if the repair had been
|
||||
# performed (except for the unchanged vg_seqno).
|
||||
# Inappropriate use could mess up your system, so seek advice first!
|
||||
metadata_read_only = 0
|
||||
|
||||
# 'mirror_segtype_default' defines which segtype will be used when the
|
||||
# shorthand '-m' option is used for mirroring. The possible options are:
|
||||
#
|
||||
# "mirror" - The original RAID1 implementation provided by LVM2/DM. It is
|
||||
# characterized by a flexible log solution (core, disk, mirrored)
|
||||
# and by the necessity to block I/O while reconfiguring in the
|
||||
# event of a failure.
|
||||
#
|
||||
# There is an inherent race in the dmeventd failure handling
|
||||
# logic with snapshots of devices using this type of RAID1 that
|
||||
# in the worst case could cause a deadlock.
|
||||
# Ref: https://bugzilla.redhat.com/show_bug.cgi?id=817130#c10
|
||||
#
|
||||
# "raid1" - This implementation leverages MD's RAID1 personality through
|
||||
# device-mapper. It is characterized by a lack of log options.
|
||||
# (A log is always allocated for every device and they are placed
|
||||
# on the same device as the image - no separate devices are
|
||||
# required.) This mirror implementation does not require I/O
|
||||
# to be blocked in the kernel in the event of a failure.
|
||||
# This mirror implementation is not cluster-aware and cannot be
|
||||
# used in a shared (active/active) fashion in a cluster.
|
||||
#
|
||||
# Specify the '--type <mirror|raid1>' option to override this default
|
||||
# setting.
|
||||
mirror_segtype_default = "mirror"
|
||||
|
||||
# 'raid10_segtype_default' determines the segment types used by default
|
||||
# when the '--stripes/-i' and '--mirrors/-m' arguments are both specified
|
||||
# during the creation of a logical volume.
|
||||
# Possible settings include:
|
||||
#
|
||||
# "raid10" - This implementation leverages MD's RAID10 personality through
|
||||
# device-mapper.
|
||||
#
|
||||
# "mirror" - LVM will layer the 'mirror' and 'stripe' segment types. It
|
||||
# will do this by creating a mirror on top of striped sub-LVs;
|
||||
# effectively creating a RAID 0+1 array. This is suboptimal
|
||||
# in terms of providing redunancy and performance. Changing to
|
||||
# this setting is not advised.
|
||||
# Specify the '--type <raid10|mirror>' option to override this default
|
||||
# setting.
|
||||
raid10_segtype_default = "mirror"
|
||||
|
||||
# The default format for displaying LV names in lvdisplay was changed
|
||||
# in version 2.02.89 to show the LV name and path separately.
|
||||
# Previously this was always shown as /dev/vgname/lvname even when that
|
||||
# was never a valid path in the /dev filesystem.
|
||||
# Set to 1 to reinstate the previous format.
|
||||
#
|
||||
# lvdisplay_shows_full_device_path = 0
|
||||
|
||||
# Whether to use (trust) a running instance of lvmetad. If this is set to
|
||||
# 0, all commands fall back to the usual scanning mechanisms. When set to 1
|
||||
# *and* when lvmetad is running (it is not auto-started), the volume group
|
||||
# metadata and PV state flags are obtained from the lvmetad instance and no
|
||||
# scanning is done by the individual commands. In a setup with lvmetad,
|
||||
# lvmetad udev rules *must* be set up for LVM to work correctly. Without
|
||||
# proper udev rules, all changes in block device configuration will be
|
||||
# *ignored* until a manual 'pvscan --cache' is performed.
|
||||
#
|
||||
# If lvmetad has been running while use_lvmetad was 0, it MUST be stopped
|
||||
# before changing use_lvmetad to 1 and started again afterwards.
|
||||
use_lvmetad = 0
|
||||
|
||||
# Full path of the utility called to check that a thin metadata device
|
||||
# is in a state that allows it to be used.
|
||||
# Each time a thin pool needs to be activated or after it is deactivated
|
||||
# this utility is executed. The activation will only proceed if the utility
|
||||
# has an exit status of 0.
|
||||
# Set to "" to skip this check. (Not recommended.)
|
||||
# The thin tools are available as part of the device-mapper-persistent-data
|
||||
# package from https://github.com/jthornber/thin-provisioning-tools.
|
||||
#
|
||||
thin_check_executable = "@THIN_CHECK_CMD@"
|
||||
|
||||
# String with options passed with thin_check command. By default,
|
||||
# option '-q' is for quiet output.
|
||||
thin_check_options = [ "-q" ]
|
||||
|
||||
# If set, given features are not used by thin driver.
|
||||
# This can be helpful not just for testing, but i.e. allows to avoid
|
||||
# using problematic implementation of some thin feature.
|
||||
# Features:
|
||||
# block_size
|
||||
# discards
|
||||
# discards_non_power_2
|
||||
#
|
||||
# thin_disabled_features = [ "discards", "block_size" ]
|
||||
}
|
||||
|
||||
activation {
|
||||
# Set to 1 to perform internal checks on the operations issued to
|
||||
# libdevmapper. Useful for debugging problems with activation.
|
||||
# Some of the checks may be expensive, so it's best to use this
|
||||
# only when there seems to be a problem.
|
||||
checks = 0
|
||||
|
||||
# Set to 0 to disable udev synchronisation (if compiled into the binaries).
|
||||
# Processes will not wait for notification from udev.
|
||||
# They will continue irrespective of any possible udev processing
|
||||
# in the background. You should only use this if udev is not running
|
||||
# or has rules that ignore the devices LVM2 creates.
|
||||
# The command line argument --nodevsync takes precedence over this setting.
|
||||
# If set to 1 when udev is not running, and there are LVM2 processes
|
||||
# waiting for udev, run 'dmsetup udevcomplete_all' manually to wake them up.
|
||||
udev_sync = 1
|
||||
|
||||
# Set to 0 to disable the udev rules installed by LVM2 (if built with
|
||||
# --enable-udev_rules). LVM2 will then manage the /dev nodes and symlinks
|
||||
# for active logical volumes directly itself.
|
||||
# N.B. Manual intervention may be required if this setting is changed
|
||||
# while any logical volumes are active.
|
||||
udev_rules = 1
|
||||
|
||||
# Set to 1 for LVM2 to verify operations performed by udev. This turns on
|
||||
# additional checks (and if necessary, repairs) on entries in the device
|
||||
# directory after udev has completed processing its events.
|
||||
# Useful for diagnosing problems with LVM2/udev interactions.
|
||||
verify_udev_operations = 0
|
||||
|
||||
# If set to 1 and if deactivation of an LV fails, perhaps because
|
||||
# a process run from a quick udev rule temporarily opened the device,
|
||||
# retry the operation for a few seconds before failing.
|
||||
retry_deactivation = 1
|
||||
|
||||
# How to fill in missing stripes if activating an incomplete volume.
|
||||
# Using "error" will make inaccessible parts of the device return
|
||||
# I/O errors on access. You can instead use a device path, in which
|
||||
# case, that device will be used to in place of missing stripes.
|
||||
# But note that using anything other than "error" with mirrored
|
||||
# or snapshotted volumes is likely to result in data corruption.
|
||||
missing_stripe_filler = "error"
|
||||
|
||||
# The linear target is an optimised version of the striped target
|
||||
# that only handles a single stripe. Set this to 0 to disable this
|
||||
# optimisation and always use the striped target.
|
||||
use_linear_target = 1
|
||||
|
||||
# How much stack (in KB) to reserve for use while devices suspended
|
||||
# Prior to version 2.02.89 this used to be set to 256KB
|
||||
reserved_stack = 64
|
||||
|
||||
# How much memory (in KB) to reserve for use while devices suspended
|
||||
reserved_memory = 8192
|
||||
|
||||
# Nice value used while devices suspended
|
||||
process_priority = -18
|
||||
|
||||
# If volume_list is defined, each LV is only activated if there is a
|
||||
# match against the list.
|
||||
#
|
||||
# "vgname" and "vgname/lvname" are matched exactly.
|
||||
# "@tag" matches any tag set in the LV or VG.
|
||||
# "@*" matches if any tag defined on the host is also set in the LV or VG
|
||||
#
|
||||
# If any host tags exist but volume_list is not defined, a default
|
||||
# single-entry list containing "@*" is assumed.
|
||||
#
|
||||
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
|
||||
# If auto_activation_volume_list is defined, each LV that is to be
|
||||
# activated with the autoactivation option (--activate ay/-a ay)
|
||||
# is first checked against the list. If it does not match, the LV
|
||||
# is not activated. This list is checked as well as volume_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
|
||||
#
|
||||
# auto_activation_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
|
||||
# If read_only_volume_list is defined, each LV that is to be activated
|
||||
# is checked against the list, and if it matches, it as activated
|
||||
# in read-only mode. (This overrides '--permission rw' stored in the
|
||||
# metadata.)
|
||||
#
|
||||
# "vgname" and "vgname/lvname" are matched exactly.
|
||||
# "@tag" matches any tag set in the LV or VG.
|
||||
# "@*" matches if any tag defined on the host is also set in the LV or VG
|
||||
#
|
||||
# read_only_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
|
||||
# For RAID or 'mirror' segment types, 'raid_region_size' is the
|
||||
# size (in kiB) of each:
|
||||
# - synchronization operation when initializing
|
||||
# - each copy operation when performing a 'pvmove' (using 'mirror' segtype)
|
||||
# This setting has replaced 'mirror_region_size' since version 2.02.99
|
||||
raid_region_size = 512
|
||||
|
||||
# Setting to use when there is no readahead value stored in the metadata.
|
||||
#
|
||||
# "none" - Disable readahead.
|
||||
# "auto" - Use default value chosen by kernel.
|
||||
readahead = "auto"
|
||||
|
||||
# 'raid_fault_policy' defines how a device failure in a RAID logical
|
||||
# volume is handled. This includes logical volumes that have the following
|
||||
# segment types: raid1, raid4, raid5*, and raid6*.
|
||||
#
|
||||
# In the event of a failure, the following policies will determine what
|
||||
# actions are performed during the automated response to failures (when
|
||||
# dmeventd is monitoring the RAID logical volume) and when 'lvconvert' is
|
||||
# called manually with the options '--repair' and '--use-policies'.
|
||||
#
|
||||
# "warn" - Use the system log to warn the user that a device in the RAID
|
||||
# logical volume has failed. It is left to the user to run
|
||||
# 'lvconvert --repair' manually to remove or replace the failed
|
||||
# device. As long as the number of failed devices does not
|
||||
# exceed the redundancy of the logical volume (1 device for
|
||||
# raid4/5, 2 for raid6, etc) the logical volume will remain
|
||||
# usable.
|
||||
#
|
||||
# "allocate" - Attempt to use any extra physical volumes in the volume
|
||||
# group as spares and replace faulty devices.
|
||||
#
|
||||
raid_fault_policy = "warn"
|
||||
|
||||
# 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
|
||||
# how a device failure affecting a mirror (of "mirror" segment type) is
|
||||
# handled. A mirror is composed of mirror images (copies) and a log.
|
||||
# A disk log ensures that a mirror does not need to be re-synced
|
||||
# (all copies made the same) every time a machine reboots or crashes.
|
||||
#
|
||||
# In the event of a failure, the specified policy will be used to determine
|
||||
# what happens. This applies to automatic repairs (when the mirror is being
|
||||
# monitored by dmeventd) and to manual lvconvert --repair when
|
||||
# --use-policies is given.
|
||||
#
|
||||
# "remove" - Simply remove the faulty device and run without it. If
|
||||
# the log device fails, the mirror would convert to using
|
||||
# an in-memory log. This means the mirror will not
|
||||
# remember its sync status across crashes/reboots and
|
||||
# the entire mirror will be re-synced. If a
|
||||
# mirror image fails, the mirror will convert to a
|
||||
# non-mirrored device if there is only one remaining good
|
||||
# copy.
|
||||
#
|
||||
# "allocate" - Remove the faulty device and try to allocate space on
|
||||
# a new device to be a replacement for the failed device.
|
||||
# Using this policy for the log is fast and maintains the
|
||||
# ability to remember sync state through crashes/reboots.
|
||||
# Using this policy for a mirror device is slow, as it
|
||||
# requires the mirror to resynchronize the devices, but it
|
||||
# will preserve the mirror characteristic of the device.
|
||||
# This policy acts like "remove" if no suitable device and
|
||||
# space can be allocated for the replacement.
|
||||
#
|
||||
# "allocate_anywhere" - Not yet implemented. Useful to place the log device
|
||||
# temporarily on same physical volume as one of the mirror
|
||||
# images. This policy is not recommended for mirror devices
|
||||
# since it would break the redundant nature of the mirror. This
|
||||
# policy acts like "remove" if no suitable device and space can
|
||||
# be allocated for the replacement.
|
||||
|
||||
mirror_log_fault_policy = "allocate"
|
||||
mirror_image_fault_policy = "remove"
|
||||
|
||||
# 'snapshot_autoextend_threshold' and 'snapshot_autoextend_percent' define
|
||||
# how to handle automatic snapshot extension. The former defines when the
|
||||
# snapshot should be extended: when its space usage exceeds this many
|
||||
# percent. The latter defines how much extra space should be allocated for
|
||||
# the snapshot, in percent of its current size.
|
||||
#
|
||||
# For example, if you set snapshot_autoextend_threshold to 70 and
|
||||
# snapshot_autoextend_percent to 20, whenever a snapshot exceeds 70% usage,
|
||||
# it will be extended by another 20%. For a 1G snapshot, using up 700M will
|
||||
# trigger a resize to 1.2G. When the usage exceeds 840M, the snapshot will
|
||||
# be extended to 1.44G, and so on.
|
||||
#
|
||||
# Setting snapshot_autoextend_threshold to 100 disables automatic
|
||||
# extensions. The minimum value is 50 (A setting below 50 will be treated
|
||||
# as 50).
|
||||
|
||||
snapshot_autoextend_threshold = 100
|
||||
snapshot_autoextend_percent = 20
|
||||
|
||||
# 'thin_pool_autoextend_threshold' and 'thin_pool_autoextend_percent' define
|
||||
# how to handle automatic pool extension. The former defines when the
|
||||
# pool should be extended: when its space usage exceeds this many
|
||||
# percent. The latter defines how much extra space should be allocated for
|
||||
# the pool, in percent of its current size.
|
||||
#
|
||||
# For example, if you set thin_pool_autoextend_threshold to 70 and
|
||||
# thin_pool_autoextend_percent to 20, whenever a pool exceeds 70% usage,
|
||||
# it will be extended by another 20%. For a 1G pool, using up 700M will
|
||||
# trigger a resize to 1.2G. When the usage exceeds 840M, the pool will
|
||||
# be extended to 1.44G, and so on.
|
||||
#
|
||||
# Setting thin_pool_autoextend_threshold to 100 disables automatic
|
||||
# extensions. The minimum value is 50 (A setting below 50 will be treated
|
||||
# as 50).
|
||||
|
||||
thin_pool_autoextend_threshold = 100
|
||||
thin_pool_autoextend_percent = 20
|
||||
|
||||
# While activating devices, I/O to devices being (re)configured is
|
||||
# suspended, and as a precaution against deadlocks, LVM2 needs to pin
|
||||
# any memory it is using so it is not paged out. Groups of pages that
|
||||
# are known not to be accessed during activation need not be pinned
|
||||
# into memory. Each string listed in this setting is compared against
|
||||
# each line in /proc/self/maps, and the pages corresponding to any
|
||||
# lines that match are not pinned. On some systems locale-archive was
|
||||
# found to make up over 80% of the memory used by the process.
|
||||
# mlock_filter = [ "locale/locale-archive", "gconv/gconv-modules.cache" ]
|
||||
|
||||
# Set to 1 to revert to the default behaviour prior to version 2.02.62
|
||||
# which used mlockall() to pin the whole process's memory while activating
|
||||
# devices.
|
||||
use_mlockall = 0
|
||||
|
||||
# Monitoring is enabled by default when activating logical volumes.
|
||||
# Set to 0 to disable monitoring or use the --ignoremonitoring option.
|
||||
monitoring = 1
|
||||
|
||||
# When pvmove or lvconvert must wait for the kernel to finish
|
||||
# synchronising or merging data, they check and report progress
|
||||
# at intervals of this number of seconds. The default is 15 seconds.
|
||||
# If this is set to 0 and there is only one thing to wait for, there
|
||||
# are no progress reports, but the process is awoken immediately the
|
||||
# operation is complete.
|
||||
polling_interval = 15
|
||||
}
|
||||
|
||||
|
||||
####################
|
||||
# Advanced section #
|
||||
####################
|
||||
|
||||
# Metadata settings
|
||||
#
|
||||
# metadata {
|
||||
# Default number of copies of metadata to hold on each PV. 0, 1 or 2.
|
||||
# You might want to override it from the command line with 0
|
||||
# when running pvcreate on new PVs which are to be added to large VGs.
|
||||
|
||||
# pvmetadatacopies = 1
|
||||
|
||||
# Default number of copies of metadata to maintain for each VG.
|
||||
# If set to a non-zero value, LVM automatically chooses which of
|
||||
# the available metadata areas to use to achieve the requested
|
||||
# number of copies of the VG metadata. If you set a value larger
|
||||
# than the the total number of metadata areas available then
|
||||
# metadata is stored in them all.
|
||||
# The default value of 0 ("unmanaged") disables this automatic
|
||||
# management and allows you to control which metadata areas
|
||||
# are used at the individual PV level using 'pvchange
|
||||
# --metadataignore y/n'.
|
||||
|
||||
# vgmetadatacopies = 0
|
||||
|
||||
# Approximate default size of on-disk metadata areas in sectors.
|
||||
# You should increase this if you have large volume groups or
|
||||
# you want to retain a large on-disk history of your metadata changes.
|
||||
|
||||
# pvmetadatasize = 255
|
||||
|
||||
# List of directories holding live copies of text format metadata.
|
||||
# These directories must not be on logical volumes!
|
||||
# It's possible to use LVM2 with a couple of directories here,
|
||||
# preferably on different (non-LV) filesystems, and with no other
|
||||
# on-disk metadata (pvmetadatacopies = 0). Or this can be in
|
||||
# addition to on-disk metadata areas.
|
||||
# The feature was originally added to simplify testing and is not
|
||||
# supported under low memory situations - the machine could lock up.
|
||||
#
|
||||
# Never edit any files in these directories by hand unless you
|
||||
# you are absolutely sure you know what you are doing! Use
|
||||
# the supplied toolset to make changes (e.g. vgcfgrestore).
|
||||
|
||||
# dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
|
||||
#}
|
||||
|
||||
# Event daemon
|
||||
#
|
||||
dmeventd {
|
||||
# mirror_library is the library used when monitoring a mirror device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2mirror.so" attempts to recover from
|
||||
# failures. It removes failed devices from a volume group and
|
||||
# reconfigures a mirror as necessary. If no mirror library is
|
||||
# provided, mirrors are not monitored through dmeventd.
|
||||
|
||||
mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||
|
||||
# snapshot_library is the library used when monitoring a snapshot device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2snapshot.so" monitors the filling of
|
||||
# snapshots and emits a warning through syslog when the use of
|
||||
# the snapshot exceeds 80%. The warning is repeated when 85%, 90% and
|
||||
# 95% of the snapshot is filled.
|
||||
|
||||
snapshot_library = "libdevmapper-event-lvm2snapshot.so"
|
||||
|
||||
# thin_library is the library used when monitoring a thin device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2thin.so" monitors the filling of
|
||||
# pool and emits a warning through syslog when the use of
|
||||
# the pool exceeds 80%. The warning is repeated when 85%, 90% and
|
||||
# 95% of the pool is filled.
|
||||
|
||||
thin_library = "libdevmapper-event-lvm2thin.so"
|
||||
|
||||
# Full path of the dmeventd binary.
|
||||
#
|
||||
# executable = "@DMEVENTD_PATH@"
|
||||
}
|
||||
49
doc/example_cmdlib.c
Normal file
49
doc/example_cmdlib.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* All output gets passed to this function line-by-line */
|
||||
void test_log_fn(int level, const char *file, int line,
|
||||
int dm_errno, const char *format)
|
||||
{
|
||||
/* Extract and process output here rather than printing it */
|
||||
|
||||
if (level != 4)
|
||||
return;
|
||||
|
||||
printf("%s\n", format);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *handle;
|
||||
int r;
|
||||
|
||||
lvm2_log_fn(test_log_fn);
|
||||
|
||||
handle = lvm2_init();
|
||||
|
||||
lvm2_log_level(handle, 1);
|
||||
r = lvm2_run(handle, "vgs --noheadings vg1");
|
||||
|
||||
/* More commands here */
|
||||
|
||||
lvm2_exit(handle);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
77
doc/kernel/cache-policies.txt
Normal file
77
doc/kernel/cache-policies.txt
Normal file
@@ -0,0 +1,77 @@
|
||||
Guidance for writing policies
|
||||
=============================
|
||||
|
||||
Try to keep transactionality out of it. The core is careful to
|
||||
avoid asking about anything that is migrating. This is a pain, but
|
||||
makes it easier to write the policies.
|
||||
|
||||
Mappings are loaded into the policy at construction time.
|
||||
|
||||
Every bio that is mapped by the target is referred to the policy.
|
||||
The policy can return a simple HIT or MISS or issue a migration.
|
||||
|
||||
Currently there's no way for the policy to issue background work,
|
||||
e.g. to start writing back dirty blocks that are going to be evicte
|
||||
soon.
|
||||
|
||||
Because we map bios, rather than requests it's easy for the policy
|
||||
to get fooled by many small bios. For this reason the core target
|
||||
issues periodic ticks to the policy. It's suggested that the policy
|
||||
doesn't update states (eg, hit counts) for a block more than once
|
||||
for each tick. The core ticks by watching bios complete, and so
|
||||
trying to see when the io scheduler has let the ios run.
|
||||
|
||||
|
||||
Overview of supplied cache replacement policies
|
||||
===============================================
|
||||
|
||||
multiqueue
|
||||
----------
|
||||
|
||||
This policy is the default.
|
||||
|
||||
The multiqueue policy has two sets of 16 queues: one set for entries
|
||||
waiting for the cache and another one for those in the cache.
|
||||
Cache entries in the queues are aged based on logical time. Entry into
|
||||
the cache is based on variable thresholds and queue selection is based
|
||||
on hit count on entry. The policy aims to take different cache miss
|
||||
costs into account and to adjust to varying load patterns automatically.
|
||||
|
||||
Message and constructor argument pairs are:
|
||||
'sequential_threshold <#nr_sequential_ios>' and
|
||||
'random_threshold <#nr_random_ios>'.
|
||||
|
||||
The sequential threshold indicates the number of contiguous I/Os
|
||||
required before a stream is treated as sequential. The random threshold
|
||||
is the number of intervening non-contiguous I/Os that must be seen
|
||||
before the stream is treated as random again.
|
||||
|
||||
The sequential and random thresholds default to 512 and 4 respectively.
|
||||
|
||||
Large, sequential ios are probably better left on the origin device
|
||||
since spindles tend to have good bandwidth. The io_tracker counts
|
||||
contiguous I/Os to try to spot when the io is in one of these sequential
|
||||
modes.
|
||||
|
||||
cleaner
|
||||
-------
|
||||
|
||||
The cleaner writes back all dirty blocks in a cache to decommission it.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
The syntax for a table is:
|
||||
cache <metadata dev> <cache dev> <origin dev> <block size>
|
||||
<#feature_args> [<feature arg>]*
|
||||
<policy> <#policy_args> [<policy arg>]*
|
||||
|
||||
The syntax to send a message using the dmsetup command is:
|
||||
dmsetup message <mapped device> 0 sequential_threshold 1024
|
||||
dmsetup message <mapped device> 0 random_threshold 8
|
||||
|
||||
Using dmsetup:
|
||||
dmsetup create blah --table "0 268435456 cache /dev/sdb /dev/sdc \
|
||||
/dev/sdd 512 0 mq 4 sequential_threshold 1024 random_threshold 8"
|
||||
creates a 128GB large mapped device named 'blah' with the
|
||||
sequential threshold set to 1024 and the random_threshold set to 8.
|
||||
243
doc/kernel/cache.txt
Normal file
243
doc/kernel/cache.txt
Normal file
@@ -0,0 +1,243 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
dm-cache is a device mapper target written by Joe Thornber, Heinz
|
||||
Mauelshagen, and Mike Snitzer.
|
||||
|
||||
It aims to improve performance of a block device (eg, a spindle) by
|
||||
dynamically migrating some of its data to a faster, smaller device
|
||||
(eg, an SSD).
|
||||
|
||||
This device-mapper solution allows us to insert this caching at
|
||||
different levels of the dm stack, for instance above the data device for
|
||||
a thin-provisioning pool. Caching solutions that are integrated more
|
||||
closely with the virtual memory system should give better performance.
|
||||
|
||||
The target reuses the metadata library used in the thin-provisioning
|
||||
library.
|
||||
|
||||
The decision as to what data to migrate and when is left to a plug-in
|
||||
policy module. Several of these have been written as we experiment,
|
||||
and we hope other people will contribute others for specific io
|
||||
scenarios (eg. a vm image server).
|
||||
|
||||
Glossary
|
||||
========
|
||||
|
||||
Migration - Movement of the primary copy of a logical block from one
|
||||
device to the other.
|
||||
Promotion - Migration from slow device to fast device.
|
||||
Demotion - Migration from fast device to slow device.
|
||||
|
||||
The origin device always contains a copy of the logical block, which
|
||||
may be out of date or kept in sync with the copy on the cache device
|
||||
(depending on policy).
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
Sub-devices
|
||||
-----------
|
||||
|
||||
The target is constructed by passing three devices to it (along with
|
||||
other parameters detailed later):
|
||||
|
||||
1. An origin device - the big, slow one.
|
||||
|
||||
2. A cache device - the small, fast one.
|
||||
|
||||
3. A small metadata device - records which blocks are in the cache,
|
||||
which are dirty, and extra hints for use by the policy object.
|
||||
This information could be put on the cache device, but having it
|
||||
separate allows the volume manager to configure it differently,
|
||||
e.g. as a mirror for extra robustness.
|
||||
|
||||
Fixed block size
|
||||
----------------
|
||||
|
||||
The origin is divided up into blocks of a fixed size. This block size
|
||||
is configurable when you first create the cache. Typically we've been
|
||||
using block sizes of 256k - 1024k.
|
||||
|
||||
Having a fixed block size simplifies the target a lot. But it is
|
||||
something of a compromise. For instance, a small part of a block may be
|
||||
getting hit a lot, yet the whole block will be promoted to the cache.
|
||||
So large block sizes are bad because they waste cache space. And small
|
||||
block sizes are bad because they increase the amount of metadata (both
|
||||
in core and on disk).
|
||||
|
||||
Writeback/writethrough
|
||||
----------------------
|
||||
|
||||
The cache has two modes, writeback and writethrough.
|
||||
|
||||
If writeback, the default, is selected then a write to a block that is
|
||||
cached will go only to the cache and the block will be marked dirty in
|
||||
the metadata.
|
||||
|
||||
If writethrough is selected then a write to a cached block will not
|
||||
complete until it has hit both the origin and cache devices. Clean
|
||||
blocks should remain clean.
|
||||
|
||||
A simple cleaner policy is provided, which will clean (write back) all
|
||||
dirty blocks in a cache. Useful for decommissioning a cache.
|
||||
|
||||
Migration throttling
|
||||
--------------------
|
||||
|
||||
Migrating data between the origin and cache device uses bandwidth.
|
||||
The user can set a throttle to prevent more than a certain amount of
|
||||
migration occuring at any one time. Currently we're not taking any
|
||||
account of normal io traffic going to the devices. More work needs
|
||||
doing here to avoid migrating during those peak io moments.
|
||||
|
||||
For the time being, a message "migration_threshold <#sectors>"
|
||||
can be used to set the maximum number of sectors being migrated,
|
||||
the default being 204800 sectors (or 100MB).
|
||||
|
||||
Updating on-disk metadata
|
||||
-------------------------
|
||||
|
||||
On-disk metadata is committed every time a REQ_SYNC or REQ_FUA bio is
|
||||
written. If no such requests are made then commits will occur every
|
||||
second. This means the cache behaves like a physical disk that has a
|
||||
write cache (the same is true of the thin-provisioning target). If
|
||||
power is lost you may lose some recent writes. The metadata should
|
||||
always be consistent in spite of any crash.
|
||||
|
||||
The 'dirty' state for a cache block changes far too frequently for us
|
||||
to keep updating it on the fly. So we treat it as a hint. In normal
|
||||
operation it will be written when the dm device is suspended. If the
|
||||
system crashes all cache blocks will be assumed dirty when restarted.
|
||||
|
||||
Per-block policy hints
|
||||
----------------------
|
||||
|
||||
Policy plug-ins can store a chunk of data per cache block. It's up to
|
||||
the policy how big this chunk is, but it should be kept small. Like the
|
||||
dirty flags this data is lost if there's a crash so a safe fallback
|
||||
value should always be possible.
|
||||
|
||||
For instance, the 'mq' policy, which is currently the default policy,
|
||||
uses this facility to store the hit count of the cache blocks. If
|
||||
there's a crash this information will be lost, which means the cache
|
||||
may be less efficient until those hit counts are regenerated.
|
||||
|
||||
Policy hints affect performance, not correctness.
|
||||
|
||||
Policy messaging
|
||||
----------------
|
||||
|
||||
Policies will have different tunables, specific to each one, so we
|
||||
need a generic way of getting and setting these. Device-mapper
|
||||
messages are used. Refer to cache-policies.txt.
|
||||
|
||||
Discard bitset resolution
|
||||
-------------------------
|
||||
|
||||
We can avoid copying data during migration if we know the block has
|
||||
been discarded. A prime example of this is when mkfs discards the
|
||||
whole block device. We store a bitset tracking the discard state of
|
||||
blocks. However, we allow this bitset to have a different block size
|
||||
from the cache blocks. This is because we need to track the discard
|
||||
state for all of the origin device (compare with the dirty bitset
|
||||
which is just for the smaller cache device).
|
||||
|
||||
Target interface
|
||||
================
|
||||
|
||||
Constructor
|
||||
-----------
|
||||
|
||||
cache <metadata dev> <cache dev> <origin dev> <block size>
|
||||
<#feature args> [<feature arg>]*
|
||||
<policy> <#policy args> [policy args]*
|
||||
|
||||
metadata dev : fast device holding the persistent metadata
|
||||
cache dev : fast device holding cached data blocks
|
||||
origin dev : slow device holding original data blocks
|
||||
block size : cache unit size in sectors
|
||||
|
||||
#feature args : number of feature arguments passed
|
||||
feature args : writethrough. (The default is writeback.)
|
||||
|
||||
policy : the replacement policy to use
|
||||
#policy args : an even number of arguments corresponding to
|
||||
key/value pairs passed to the policy
|
||||
policy args : key/value pairs passed to the policy
|
||||
E.g. 'sequential_threshold 1024'
|
||||
See cache-policies.txt for details.
|
||||
|
||||
Optional feature arguments are:
|
||||
writethrough : write through caching that prohibits cache block
|
||||
content from being different from origin block content.
|
||||
Without this argument, the default behaviour is to write
|
||||
back cache block contents later for performance reasons,
|
||||
so they may differ from the corresponding origin blocks.
|
||||
|
||||
A policy called 'default' is always registered. This is an alias for
|
||||
the policy we currently think is giving best all round performance.
|
||||
|
||||
As the default policy could vary between kernels, if you are relying on
|
||||
the characteristics of a specific policy, always request it by name.
|
||||
|
||||
Status
|
||||
------
|
||||
|
||||
<#used metadata blocks>/<#total metadata blocks> <#read hits> <#read misses>
|
||||
<#write hits> <#write misses> <#demotions> <#promotions> <#blocks in cache>
|
||||
<#dirty> <#features> <features>* <#core args> <core args>* <#policy args>
|
||||
<policy args>*
|
||||
|
||||
#used metadata blocks : Number of metadata blocks used
|
||||
#total metadata blocks : Total number of metadata blocks
|
||||
#read hits : Number of times a READ bio has been mapped
|
||||
to the cache
|
||||
#read misses : Number of times a READ bio has been mapped
|
||||
to the origin
|
||||
#write hits : Number of times a WRITE bio has been mapped
|
||||
to the cache
|
||||
#write misses : Number of times a WRITE bio has been
|
||||
mapped to the origin
|
||||
#demotions : Number of times a block has been removed
|
||||
from the cache
|
||||
#promotions : Number of times a block has been moved to
|
||||
the cache
|
||||
#blocks in cache : Number of blocks resident in the cache
|
||||
#dirty : Number of blocks in the cache that differ
|
||||
from the origin
|
||||
#feature args : Number of feature args to follow
|
||||
feature args : 'writethrough' (optional)
|
||||
#core args : Number of core arguments (must be even)
|
||||
core args : Key/value pairs for tuning the core
|
||||
e.g. migration_threshold
|
||||
#policy args : Number of policy arguments to follow (must be even)
|
||||
policy args : Key/value pairs
|
||||
e.g. 'sequential_threshold 1024
|
||||
|
||||
Messages
|
||||
--------
|
||||
|
||||
Policies will have different tunables, specific to each one, so we
|
||||
need a generic way of getting and setting these. Device-mapper
|
||||
messages are used. (A sysfs interface would also be possible.)
|
||||
|
||||
The message format is:
|
||||
|
||||
<key> <value>
|
||||
|
||||
E.g.
|
||||
dmsetup message my_cache 0 sequential_threshold 1024
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
The test suite can be found here:
|
||||
|
||||
https://github.com/jthornber/thinp-test-suite
|
||||
|
||||
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
|
||||
/dev/mapper/ssd /dev/mapper/origin 512 1 writeback default 0'
|
||||
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
|
||||
/dev/mapper/ssd /dev/mapper/origin 1024 1 writeback \
|
||||
mq 4 sequential_threshold 1024 random_threshold 8'
|
||||
76
doc/kernel/crypt.txt
Normal file
76
doc/kernel/crypt.txt
Normal file
@@ -0,0 +1,76 @@
|
||||
dm-crypt
|
||||
=========
|
||||
|
||||
Device-Mapper's "crypt" target provides transparent encryption of block devices
|
||||
using the kernel crypto API.
|
||||
|
||||
Parameters: <cipher> <key> <iv_offset> <device path> \
|
||||
<offset> [<#opt_params> <opt_params>]
|
||||
|
||||
<cipher>
|
||||
Encryption cipher and an optional IV generation mode.
|
||||
(In format cipher[:keycount]-chainmode-ivopts:ivmode).
|
||||
Examples:
|
||||
des
|
||||
aes-cbc-essiv:sha256
|
||||
twofish-ecb
|
||||
|
||||
/proc/crypto contains supported crypto modes
|
||||
|
||||
<key>
|
||||
Key used for encryption. It is encoded as a hexadecimal number.
|
||||
You can only use key sizes that are valid for the selected cipher.
|
||||
|
||||
<keycount>
|
||||
Multi-key compatibility mode. You can define <keycount> keys and
|
||||
then sectors are encrypted according to their offsets (sector 0 uses key0;
|
||||
sector 1 uses key1 etc.). <keycount> must be a power of two.
|
||||
|
||||
<iv_offset>
|
||||
The IV offset is a sector count that is added to the sector number
|
||||
before creating the IV.
|
||||
|
||||
<device path>
|
||||
This is the device that is going to be used as backend and contains the
|
||||
encrypted data. You can specify it as a path like /dev/xxx or a device
|
||||
number <major>:<minor>.
|
||||
|
||||
<offset>
|
||||
Starting sector within the device where the encrypted data begins.
|
||||
|
||||
<#opt_params>
|
||||
Number of optional parameters. If there are no optional parameters,
|
||||
the optional paramaters section can be skipped or #opt_params can be zero.
|
||||
Otherwise #opt_params is the number of following arguments.
|
||||
|
||||
Example of optional parameters section:
|
||||
1 allow_discards
|
||||
|
||||
allow_discards
|
||||
Block discard requests (a.k.a. TRIM) are passed through the crypt device.
|
||||
The default is to ignore discard requests.
|
||||
|
||||
WARNING: Assess the specific security risks carefully before enabling this
|
||||
option. For example, allowing discards on encrypted devices may lead to
|
||||
the leak of information about the ciphertext device (filesystem type,
|
||||
used space etc.) if the discarded blocks can be located easily on the
|
||||
device later.
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
|
||||
encryption with dm-crypt using the 'cryptsetup' utility, see
|
||||
http://code.google.com/p/cryptsetup/
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create a crypt device using dmsetup
|
||||
dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
|
||||
]]
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create a crypt device using cryptsetup and LUKS header with default cipher
|
||||
cryptsetup luksFormat $1
|
||||
cryptsetup luksOpen $1 crypt1
|
||||
]]
|
||||
26
doc/kernel/delay.txt
Normal file
26
doc/kernel/delay.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
dm-delay
|
||||
========
|
||||
|
||||
Device-Mapper's "delay" target delays reads and/or writes
|
||||
and maps them to different devices.
|
||||
|
||||
Parameters:
|
||||
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
|
||||
|
||||
With separate write parameters, the first set is only used for reads.
|
||||
Delays are specified in milliseconds.
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create device delaying rw operation for 500ms
|
||||
echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed
|
||||
]]
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create device delaying only write operation for 500ms and
|
||||
# splitting reads and writes to different devices $1 $2
|
||||
echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
|
||||
]]
|
||||
53
doc/kernel/flakey.txt
Normal file
53
doc/kernel/flakey.txt
Normal file
@@ -0,0 +1,53 @@
|
||||
dm-flakey
|
||||
=========
|
||||
|
||||
This target is the same as the linear target except that it exhibits
|
||||
unreliable behaviour periodically. It's been found useful in simulating
|
||||
failing devices for testing purposes.
|
||||
|
||||
Starting from the time the table is loaded, the device is available for
|
||||
<up interval> seconds, then exhibits unreliable behaviour for <down
|
||||
interval> seconds, and then this cycle repeats.
|
||||
|
||||
Also, consider using this in combination with the dm-delay target too,
|
||||
which can delay reads and writes and/or send them to different
|
||||
underlying devices.
|
||||
|
||||
Table parameters
|
||||
----------------
|
||||
<dev path> <offset> <up interval> <down interval> \
|
||||
[<num_features> [<feature arguments>]]
|
||||
|
||||
Mandatory parameters:
|
||||
<dev path>: Full pathname to the underlying block-device, or a
|
||||
"major:minor" device-number.
|
||||
<offset>: Starting sector within the device.
|
||||
<up interval>: Number of seconds device is available.
|
||||
<down interval>: Number of seconds device returns errors.
|
||||
|
||||
Optional feature parameters:
|
||||
If no feature parameters are present, during the periods of
|
||||
unreliability, all I/O returns errors.
|
||||
|
||||
drop_writes:
|
||||
All write I/O is silently ignored.
|
||||
Read I/O is handled correctly.
|
||||
|
||||
corrupt_bio_byte <Nth_byte> <direction> <value> <flags>:
|
||||
During <down interval>, replace <Nth_byte> of the data of
|
||||
each matching bio with <value>.
|
||||
|
||||
<Nth_byte>: The offset of the byte to replace.
|
||||
Counting starts at 1, to replace the first byte.
|
||||
<direction>: Either 'r' to corrupt reads or 'w' to corrupt writes.
|
||||
'w' is incompatible with drop_writes.
|
||||
<value>: The value (from 0-255) to write.
|
||||
<flags>: Perform the replacement only if bio->bi_rw has all the
|
||||
selected flags set.
|
||||
|
||||
Examples:
|
||||
corrupt_bio_byte 32 r 1 0
|
||||
- replaces the 32nd byte of READ bios with the value 1
|
||||
|
||||
corrupt_bio_byte 224 w 0 32
|
||||
- replaces the 224th byte of REQ_META (=32) bios with the value 0
|
||||
75
doc/kernel/io.txt
Normal file
75
doc/kernel/io.txt
Normal file
@@ -0,0 +1,75 @@
|
||||
dm-io
|
||||
=====
|
||||
|
||||
Dm-io provides synchronous and asynchronous I/O services. There are three
|
||||
types of I/O services available, and each type has a sync and an async
|
||||
version.
|
||||
|
||||
The user must set up an io_region structure to describe the desired location
|
||||
of the I/O. Each io_region indicates a block-device along with the starting
|
||||
sector and size of the region.
|
||||
|
||||
struct io_region {
|
||||
struct block_device *bdev;
|
||||
sector_t sector;
|
||||
sector_t count;
|
||||
};
|
||||
|
||||
Dm-io can read from one io_region or write to one or more io_regions. Writes
|
||||
to multiple regions are specified by an array of io_region structures.
|
||||
|
||||
The first I/O service type takes a list of memory pages as the data buffer for
|
||||
the I/O, along with an offset into the first page.
|
||||
|
||||
struct page_list {
|
||||
struct page_list *next;
|
||||
struct page *page;
|
||||
};
|
||||
|
||||
int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
|
||||
struct page_list *pl, unsigned int offset,
|
||||
unsigned long *error_bits);
|
||||
int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
|
||||
struct page_list *pl, unsigned int offset,
|
||||
io_notify_fn fn, void *context);
|
||||
|
||||
The second I/O service type takes an array of bio vectors as the data buffer
|
||||
for the I/O. This service can be handy if the caller has a pre-assembled bio,
|
||||
but wants to direct different portions of the bio to different devices.
|
||||
|
||||
int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where,
|
||||
int rw, struct bio_vec *bvec,
|
||||
unsigned long *error_bits);
|
||||
int dm_io_async_bvec(unsigned int num_regions, struct io_region *where,
|
||||
int rw, struct bio_vec *bvec,
|
||||
io_notify_fn fn, void *context);
|
||||
|
||||
The third I/O service type takes a pointer to a vmalloc'd memory buffer as the
|
||||
data buffer for the I/O. This service can be handy if the caller needs to do
|
||||
I/O to a large region but doesn't want to allocate a large number of individual
|
||||
memory pages.
|
||||
|
||||
int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
|
||||
void *data, unsigned long *error_bits);
|
||||
int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
|
||||
void *data, io_notify_fn fn, void *context);
|
||||
|
||||
Callers of the asynchronous I/O services must include the name of a completion
|
||||
callback routine and a pointer to some context data for the I/O.
|
||||
|
||||
typedef void (*io_notify_fn)(unsigned long error, void *context);
|
||||
|
||||
The "error" parameter in this callback, as well as the "*error" parameter in
|
||||
all of the synchronous versions, is a bitset (instead of a simple error value).
|
||||
In the case of an write-I/O to multiple regions, this bitset allows dm-io to
|
||||
indicate success or failure on each individual region.
|
||||
|
||||
Before using any of the dm-io services, the user should call dm_io_get()
|
||||
and specify the number of pages they expect to perform I/O on concurrently.
|
||||
Dm-io will attempt to resize its mempool to make sure enough pages are
|
||||
always available in order to avoid unnecessary waiting while performing I/O.
|
||||
|
||||
When the user is finished using the dm-io services, they should call
|
||||
dm_io_put() and specify the same number of pages that were given on the
|
||||
dm_io_get() call.
|
||||
|
||||
47
doc/kernel/kcopyd.txt
Normal file
47
doc/kernel/kcopyd.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
kcopyd
|
||||
======
|
||||
|
||||
Kcopyd provides the ability to copy a range of sectors from one block-device
|
||||
to one or more other block-devices, with an asynchronous completion
|
||||
notification. It is used by dm-snapshot and dm-mirror.
|
||||
|
||||
Users of kcopyd must first create a client and indicate how many memory pages
|
||||
to set aside for their copy jobs. This is done with a call to
|
||||
kcopyd_client_create().
|
||||
|
||||
int kcopyd_client_create(unsigned int num_pages,
|
||||
struct kcopyd_client **result);
|
||||
|
||||
To start a copy job, the user must set up io_region structures to describe
|
||||
the source and destinations of the copy. Each io_region indicates a
|
||||
block-device along with the starting sector and size of the region. The source
|
||||
of the copy is given as one io_region structure, and the destinations of the
|
||||
copy are given as an array of io_region structures.
|
||||
|
||||
struct io_region {
|
||||
struct block_device *bdev;
|
||||
sector_t sector;
|
||||
sector_t count;
|
||||
};
|
||||
|
||||
To start the copy, the user calls kcopyd_copy(), passing in the client
|
||||
pointer, pointers to the source and destination io_regions, the name of a
|
||||
completion callback routine, and a pointer to some context data for the copy.
|
||||
|
||||
int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
|
||||
unsigned int num_dests, struct io_region *dests,
|
||||
unsigned int flags, kcopyd_notify_fn fn, void *context);
|
||||
|
||||
typedef void (*kcopyd_notify_fn)(int read_err, unsigned int write_err,
|
||||
void *context);
|
||||
|
||||
When the copy completes, kcopyd will call the user's completion routine,
|
||||
passing back the user's context pointer. It will also indicate if a read or
|
||||
write error occurred during the copy.
|
||||
|
||||
When a user is done with all their copy jobs, they should call
|
||||
kcopyd_client_destroy() to delete the kcopyd client, which will release the
|
||||
associated memory pages.
|
||||
|
||||
void kcopyd_client_destroy(struct kcopyd_client *kc);
|
||||
|
||||
61
doc/kernel/linear.txt
Normal file
61
doc/kernel/linear.txt
Normal file
@@ -0,0 +1,61 @@
|
||||
dm-linear
|
||||
=========
|
||||
|
||||
Device-Mapper's "linear" target maps a linear range of the Device-Mapper
|
||||
device onto a linear range of another device. This is the basic building
|
||||
block of logical volume managers.
|
||||
|
||||
Parameters: <dev path> <offset>
|
||||
<dev path>: Full pathname to the underlying block-device, or a
|
||||
"major:minor" device-number.
|
||||
<offset>: Starting sector within the device.
|
||||
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Create an identity mapping for a device
|
||||
echo "0 `blockdev --getsize $1` linear $1 0" | dmsetup create identity
|
||||
]]
|
||||
|
||||
|
||||
[[
|
||||
#!/bin/sh
|
||||
# Join 2 devices together
|
||||
size1=`blockdev --getsize $1`
|
||||
size2=`blockdev --getsize $2`
|
||||
echo "0 $size1 linear $1 0
|
||||
$size1 $size2 linear $2 0" | dmsetup create joined
|
||||
]]
|
||||
|
||||
|
||||
[[
|
||||
#!/usr/bin/perl -w
|
||||
# Split a device into 4M chunks and then join them together in reverse order.
|
||||
|
||||
my $name = "reverse";
|
||||
my $extent_size = 4 * 1024 * 2;
|
||||
my $dev = $ARGV[0];
|
||||
my $table = "";
|
||||
my $count = 0;
|
||||
|
||||
if (!defined($dev)) {
|
||||
die("Please specify a device.\n");
|
||||
}
|
||||
|
||||
my $dev_size = `blockdev --getsize $dev`;
|
||||
my $extents = int($dev_size / $extent_size) -
|
||||
(($dev_size % $extent_size) ? 1 : 0);
|
||||
|
||||
while ($extents > 0) {
|
||||
my $this_start = $count * $extent_size;
|
||||
$extents--;
|
||||
$count++;
|
||||
my $this_offset = $extents * $extent_size;
|
||||
|
||||
$table .= "$this_start $extent_size linear $dev $this_offset\n";
|
||||
}
|
||||
|
||||
`echo \"$table\" | dmsetup create $name`;
|
||||
]]
|
||||
54
doc/kernel/log.txt
Normal file
54
doc/kernel/log.txt
Normal file
@@ -0,0 +1,54 @@
|
||||
Device-Mapper Logging
|
||||
=====================
|
||||
The device-mapper logging code is used by some of the device-mapper
|
||||
RAID targets to track regions of the disk that are not consistent.
|
||||
A region (or portion of the address space) of the disk may be
|
||||
inconsistent because a RAID stripe is currently being operated on or
|
||||
a machine died while the region was being altered. In the case of
|
||||
mirrors, a region would be considered dirty/inconsistent while you
|
||||
are writing to it because the writes need to be replicated for all
|
||||
the legs of the mirror and may not reach the legs at the same time.
|
||||
Once all writes are complete, the region is considered clean again.
|
||||
|
||||
There is a generic logging interface that the device-mapper RAID
|
||||
implementations use to perform logging operations (see
|
||||
dm_dirty_log_type in include/linux/dm-dirty-log.h). Various different
|
||||
logging implementations are available and provide different
|
||||
capabilities. The list includes:
|
||||
|
||||
Type Files
|
||||
==== =====
|
||||
disk drivers/md/dm-log.c
|
||||
core drivers/md/dm-log.c
|
||||
userspace drivers/md/dm-log-userspace* include/linux/dm-log-userspace.h
|
||||
|
||||
The "disk" log type
|
||||
-------------------
|
||||
This log implementation commits the log state to disk. This way, the
|
||||
logging state survives reboots/crashes.
|
||||
|
||||
The "core" log type
|
||||
-------------------
|
||||
This log implementation keeps the log state in memory. The log state
|
||||
will not survive a reboot or crash, but there may be a small boost in
|
||||
performance. This method can also be used if no storage device is
|
||||
available for storing log state.
|
||||
|
||||
The "userspace" log type
|
||||
------------------------
|
||||
This log type simply provides a way to export the log API to userspace,
|
||||
so log implementations can be done there. This is done by forwarding most
|
||||
logging requests to userspace, where a daemon receives and processes the
|
||||
request.
|
||||
|
||||
The structure used for communication between kernel and userspace are
|
||||
located in include/linux/dm-log-userspace.h. Due to the frequency,
|
||||
diversity, and 2-way communication nature of the exchanges between
|
||||
kernel and userspace, 'connector' is used as the interface for
|
||||
communication.
|
||||
|
||||
There are currently two userspace log implementations that leverage this
|
||||
framework - "clustered-disk" and "clustered-core". These implementations
|
||||
provide a cluster-coherent log for shared-storage. Device-mapper mirroring
|
||||
can be used in a shared-storage environment when the cluster log implementations
|
||||
are employed.
|
||||
84
doc/kernel/persistent-data.txt
Normal file
84
doc/kernel/persistent-data.txt
Normal file
@@ -0,0 +1,84 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
The more-sophisticated device-mapper targets require complex metadata
|
||||
that is managed in kernel. In late 2010 we were seeing that various
|
||||
different targets were rolling their own data structures, for example:
|
||||
|
||||
- Mikulas Patocka's multisnap implementation
|
||||
- Heinz Mauelshagen's thin provisioning target
|
||||
- Another btree-based caching target posted to dm-devel
|
||||
- Another multi-snapshot target based on a design of Daniel Phillips
|
||||
|
||||
Maintaining these data structures takes a lot of work, so if possible
|
||||
we'd like to reduce the number.
|
||||
|
||||
The persistent-data library is an attempt to provide a re-usable
|
||||
framework for people who want to store metadata in device-mapper
|
||||
targets. It's currently used by the thin-provisioning target and an
|
||||
upcoming hierarchical storage target.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The main documentation is in the header files which can all be found
|
||||
under drivers/md/persistent-data.
|
||||
|
||||
The block manager
|
||||
-----------------
|
||||
|
||||
dm-block-manager.[hc]
|
||||
|
||||
This provides access to the data on disk in fixed sized-blocks. There
|
||||
is a read/write locking interface to prevent concurrent accesses, and
|
||||
keep data that is being used in the cache.
|
||||
|
||||
Clients of persistent-data are unlikely to use this directly.
|
||||
|
||||
The transaction manager
|
||||
-----------------------
|
||||
|
||||
dm-transaction-manager.[hc]
|
||||
|
||||
This restricts access to blocks and enforces copy-on-write semantics.
|
||||
The only way you can get hold of a writable block through the
|
||||
transaction manager is by shadowing an existing block (ie. doing
|
||||
copy-on-write) or allocating a fresh one. Shadowing is elided within
|
||||
the same transaction so performance is reasonable. The commit method
|
||||
ensures that all data is flushed before it writes the superblock.
|
||||
On power failure your metadata will be as it was when last committed.
|
||||
|
||||
The Space Maps
|
||||
--------------
|
||||
|
||||
dm-space-map.h
|
||||
dm-space-map-metadata.[hc]
|
||||
dm-space-map-disk.[hc]
|
||||
|
||||
On-disk data structures that keep track of reference counts of blocks.
|
||||
Also acts as the allocator of new blocks. Currently two
|
||||
implementations: a simpler one for managing blocks on a different
|
||||
device (eg. thinly-provisioned data blocks); and one for managing
|
||||
the metadata space. The latter is complicated by the need to store
|
||||
its own data within the space it's managing.
|
||||
|
||||
The data structures
|
||||
-------------------
|
||||
|
||||
dm-btree.[hc]
|
||||
dm-btree-remove.c
|
||||
dm-btree-spine.c
|
||||
dm-btree-internal.h
|
||||
|
||||
Currently there is only one data structure, a hierarchical btree.
|
||||
There are plans to add more. For example, something with an
|
||||
array-like interface would see a lot of use.
|
||||
|
||||
The btree is 'hierarchical' in that you can define it to be composed
|
||||
of nested btrees, and take multiple keys. For example, the
|
||||
thin-provisioning target uses a btree with two levels of nesting.
|
||||
The first maps a device id to a mapping tree, and that in turn maps a
|
||||
virtual block to a physical block.
|
||||
|
||||
Values stored in the btrees can have arbitrary size. Keys are always
|
||||
64bits, although nesting allows you to use multiple keys.
|
||||
39
doc/kernel/queue-length.txt
Normal file
39
doc/kernel/queue-length.txt
Normal file
@@ -0,0 +1,39 @@
|
||||
dm-queue-length
|
||||
===============
|
||||
|
||||
dm-queue-length is a path selector module for device-mapper targets,
|
||||
which selects a path with the least number of in-flight I/Os.
|
||||
The path selector name is 'queue-length'.
|
||||
|
||||
Table parameters for each path: [<repeat_count>]
|
||||
<repeat_count>: The number of I/Os to dispatch using the selected
|
||||
path before switching to the next path.
|
||||
If not given, internal default is used. To check
|
||||
the default value, see the activated table.
|
||||
|
||||
Status for each path: <status> <fail-count> <in-flight>
|
||||
<status>: 'A' if the path is active, 'F' if the path is failed.
|
||||
<fail-count>: The number of path failures.
|
||||
<in-flight>: The number of in-flight I/Os on the path.
|
||||
|
||||
|
||||
Algorithm
|
||||
=========
|
||||
|
||||
dm-queue-length increments/decrements 'in-flight' when an I/O is
|
||||
dispatched/completed respectively.
|
||||
dm-queue-length selects a path with the minimum 'in-flight'.
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
In case that 2 paths (sda and sdb) are used with repeat_count == 128.
|
||||
|
||||
# echo "0 10 multipath 0 0 1 1 queue-length 0 2 1 8:0 128 8:16 128" \
|
||||
dmsetup create test
|
||||
#
|
||||
# dmsetup table
|
||||
test: 0 10 multipath 0 0 1 1 queue-length 0 2 1 8:0 128 8:16 128
|
||||
#
|
||||
# dmsetup status
|
||||
test: 0 10 multipath 2 0 0 0 1 1 E 0 2 1 8:0 A 0 0 8:16 A 0 0
|
||||
224
doc/kernel/raid.txt
Normal file
224
doc/kernel/raid.txt
Normal file
@@ -0,0 +1,224 @@
|
||||
dm-raid
|
||||
=======
|
||||
|
||||
The device-mapper RAID (dm-raid) target provides a bridge from DM to MD.
|
||||
It allows the MD RAID drivers to be accessed using a device-mapper
|
||||
interface.
|
||||
|
||||
|
||||
Mapping Table Interface
|
||||
-----------------------
|
||||
The target is named "raid" and it accepts the following parameters:
|
||||
|
||||
<raid_type> <#raid_params> <raid_params> \
|
||||
<#raid_devs> <metadata_dev0> <dev0> [.. <metadata_devN> <devN>]
|
||||
|
||||
<raid_type>:
|
||||
raid1 RAID1 mirroring
|
||||
raid4 RAID4 dedicated parity disk
|
||||
raid5_la RAID5 left asymmetric
|
||||
- rotating parity 0 with data continuation
|
||||
raid5_ra RAID5 right asymmetric
|
||||
- rotating parity N with data continuation
|
||||
raid5_ls RAID5 left symmetric
|
||||
- rotating parity 0 with data restart
|
||||
raid5_rs RAID5 right symmetric
|
||||
- rotating parity N with data restart
|
||||
raid6_zr RAID6 zero restart
|
||||
- rotating parity zero (left-to-right) with data restart
|
||||
raid6_nr RAID6 N restart
|
||||
- rotating parity N (right-to-left) with data restart
|
||||
raid6_nc RAID6 N continue
|
||||
- rotating parity N (right-to-left) with data continuation
|
||||
raid10 Various RAID10 inspired algorithms chosen by additional params
|
||||
- RAID10: Striped Mirrors (aka 'Striping on top of mirrors')
|
||||
- RAID1E: Integrated Adjacent Stripe Mirroring
|
||||
- RAID1E: Integrated Offset Stripe Mirroring
|
||||
- and other similar RAID10 variants
|
||||
|
||||
Reference: Chapter 4 of
|
||||
http://www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf
|
||||
|
||||
<#raid_params>: The number of parameters that follow.
|
||||
|
||||
<raid_params> consists of
|
||||
Mandatory parameters:
|
||||
<chunk_size>: Chunk size in sectors. This parameter is often known as
|
||||
"stripe size". It is the only mandatory parameter and
|
||||
is placed first.
|
||||
|
||||
followed by optional parameters (in any order):
|
||||
[sync|nosync] Force or prevent RAID initialization.
|
||||
|
||||
[rebuild <idx>] Rebuild drive number 'idx' (first drive is 0).
|
||||
|
||||
[daemon_sleep <ms>]
|
||||
Interval between runs of the bitmap daemon that
|
||||
clear bits. A longer interval means less bitmap I/O but
|
||||
resyncing after a failure is likely to take longer.
|
||||
|
||||
[min_recovery_rate <kB/sec/disk>] Throttle RAID initialization
|
||||
[max_recovery_rate <kB/sec/disk>] Throttle RAID initialization
|
||||
[write_mostly <idx>] Mark drive index 'idx' write-mostly.
|
||||
[max_write_behind <sectors>] See '--write-behind=' (man mdadm)
|
||||
[stripe_cache <sectors>] Stripe cache size (RAID 4/5/6 only)
|
||||
[region_size <sectors>]
|
||||
The region_size multiplied by the number of regions is the
|
||||
logical size of the array. The bitmap records the device
|
||||
synchronisation state for each region.
|
||||
|
||||
[raid10_copies <# copies>]
|
||||
[raid10_format <near|far|offset>]
|
||||
These two options are used to alter the default layout of
|
||||
a RAID10 configuration. The number of copies is can be
|
||||
specified, but the default is 2. There are also three
|
||||
variations to how the copies are laid down - the default
|
||||
is "near". Near copies are what most people think of with
|
||||
respect to mirroring. If these options are left unspecified,
|
||||
or 'raid10_copies 2' and/or 'raid10_format near' are given,
|
||||
then the layouts for 2, 3 and 4 devices are:
|
||||
2 drives 3 drives 4 drives
|
||||
-------- ---------- --------------
|
||||
A1 A1 A1 A1 A2 A1 A1 A2 A2
|
||||
A2 A2 A2 A3 A3 A3 A3 A4 A4
|
||||
A3 A3 A4 A4 A5 A5 A5 A6 A6
|
||||
A4 A4 A5 A6 A6 A7 A7 A8 A8
|
||||
.. .. .. .. .. .. .. .. ..
|
||||
The 2-device layout is equivalent 2-way RAID1. The 4-device
|
||||
layout is what a traditional RAID10 would look like. The
|
||||
3-device layout is what might be called a 'RAID1E - Integrated
|
||||
Adjacent Stripe Mirroring'.
|
||||
|
||||
If 'raid10_copies 2' and 'raid10_format far', then the layouts
|
||||
for 2, 3 and 4 devices are:
|
||||
2 drives 3 drives 4 drives
|
||||
-------- -------------- --------------------
|
||||
A1 A2 A1 A2 A3 A1 A2 A3 A4
|
||||
A3 A4 A4 A5 A6 A5 A6 A7 A8
|
||||
A5 A6 A7 A8 A9 A9 A10 A11 A12
|
||||
.. .. .. .. .. .. .. .. ..
|
||||
A2 A1 A3 A1 A2 A2 A1 A4 A3
|
||||
A4 A3 A6 A4 A5 A6 A5 A8 A7
|
||||
A6 A5 A9 A7 A8 A10 A9 A12 A11
|
||||
.. .. .. .. .. .. .. .. ..
|
||||
|
||||
If 'raid10_copies 2' and 'raid10_format offset', then the
|
||||
layouts for 2, 3 and 4 devices are:
|
||||
2 drives 3 drives 4 drives
|
||||
-------- ------------ -----------------
|
||||
A1 A2 A1 A2 A3 A1 A2 A3 A4
|
||||
A2 A1 A3 A1 A2 A2 A1 A4 A3
|
||||
A3 A4 A4 A5 A6 A5 A6 A7 A8
|
||||
A4 A3 A6 A4 A5 A6 A5 A8 A7
|
||||
A5 A6 A7 A8 A9 A9 A10 A11 A12
|
||||
A6 A5 A9 A7 A8 A10 A9 A12 A11
|
||||
.. .. .. .. .. .. .. .. ..
|
||||
Here we see layouts closely akin to 'RAID1E - Integrated
|
||||
Offset Stripe Mirroring'.
|
||||
|
||||
<#raid_devs>: The number of devices composing the array.
|
||||
Each device consists of two entries. The first is the device
|
||||
containing the metadata (if any); the second is the one containing the
|
||||
data.
|
||||
|
||||
If a drive has failed or is missing at creation time, a '-' can be
|
||||
given for both the metadata and data drives for a given position.
|
||||
|
||||
|
||||
Example Tables
|
||||
--------------
|
||||
# RAID4 - 4 data drives, 1 parity (no metadata devices)
|
||||
# No metadata devices specified to hold superblock/bitmap info
|
||||
# Chunk size of 1MiB
|
||||
# (Lines separated for easy reading)
|
||||
|
||||
0 1960893648 raid \
|
||||
raid4 1 2048 \
|
||||
5 - 8:17 - 8:33 - 8:49 - 8:65 - 8:81
|
||||
|
||||
# RAID4 - 4 data drives, 1 parity (with metadata devices)
|
||||
# Chunk size of 1MiB, force RAID initialization,
|
||||
# min recovery rate at 20 kiB/sec/disk
|
||||
|
||||
0 1960893648 raid \
|
||||
raid4 4 2048 sync min_recovery_rate 20 \
|
||||
5 8:17 8:18 8:33 8:34 8:49 8:50 8:65 8:66 8:81 8:82
|
||||
|
||||
|
||||
Status Output
|
||||
-------------
|
||||
'dmsetup table' displays the table used to construct the mapping.
|
||||
The optional parameters are always printed in the order listed
|
||||
above with "sync" or "nosync" always output ahead of the other
|
||||
arguments, regardless of the order used when originally loading the table.
|
||||
Arguments that can be repeated are ordered by value.
|
||||
|
||||
|
||||
'dmsetup status' yields information on the state and health of the array.
|
||||
The output is as follows (normally a single line, but expanded here for
|
||||
clarity):
|
||||
1: <s> <l> raid \
|
||||
2: <raid_type> <#devices> <health_chars> \
|
||||
3: <sync_ratio> <sync_action> <mismatch_cnt>
|
||||
|
||||
Line 1 is the standard output produced by device-mapper.
|
||||
Line 2 & 3 are produced by the raid target and are best explained by example:
|
||||
0 1960893648 raid raid4 5 AAAAA 2/490221568 init 0
|
||||
Here we can see the RAID type is raid4, there are 5 devices - all of
|
||||
which are 'A'live, and the array is 2/490221568 complete with its initial
|
||||
recovery. Here is a fuller description of the individual fields:
|
||||
<raid_type> Same as the <raid_type> used to create the array.
|
||||
<health_chars> One char for each device, indicating: 'A' = alive and
|
||||
in-sync, 'a' = alive but not in-sync, 'D' = dead/failed.
|
||||
<sync_ratio> The ratio indicating how much of the array has undergone
|
||||
the process described by 'sync_action'. If the
|
||||
'sync_action' is "check" or "repair", then the process
|
||||
of "resync" or "recover" can be considered complete.
|
||||
<sync_action> One of the following possible states:
|
||||
idle - No synchronization action is being performed.
|
||||
frozen - The current action has been halted.
|
||||
resync - Array is undergoing its initial synchronization
|
||||
or is resynchronizing after an unclean shutdown
|
||||
(possibly aided by a bitmap).
|
||||
recover - A device in the array is being rebuilt or
|
||||
replaced.
|
||||
check - A user-initiated full check of the array is
|
||||
being performed. All blocks are read and
|
||||
checked for consistency. The number of
|
||||
discrepancies found are recorded in
|
||||
<mismatch_cnt>. No changes are made to the
|
||||
array by this action.
|
||||
repair - The same as "check", but discrepancies are
|
||||
corrected.
|
||||
reshape - The array is undergoing a reshape.
|
||||
<mismatch_cnt> The number of discrepancies found between mirror copies
|
||||
in RAID1/10 or wrong parity values found in RAID4/5/6.
|
||||
This value is valid only after a "check" of the array
|
||||
is performed. A healthy array has a 'mismatch_cnt' of 0.
|
||||
|
||||
Message Interface
|
||||
-----------------
|
||||
The dm-raid target will accept certain actions through the 'message' interface.
|
||||
('man dmsetup' for more information on the message interface.) These actions
|
||||
include:
|
||||
"idle" - Halt the current sync action.
|
||||
"frozen" - Freeze the current sync action.
|
||||
"resync" - Initiate/continue a resync.
|
||||
"recover"- Initiate/continue a recover process.
|
||||
"check" - Initiate a check (i.e. a "scrub") of the array.
|
||||
"repair" - Initiate a repair of the array.
|
||||
"reshape"- Currently unsupported (-EINVAL).
|
||||
|
||||
Version History
|
||||
---------------
|
||||
1.0.0 Initial version. Support for RAID 4/5/6
|
||||
1.1.0 Added support for RAID 1
|
||||
1.2.0 Handle creation of arrays that contain failed devices.
|
||||
1.3.0 Added support for RAID 10
|
||||
1.3.1 Allow device replacement/rebuild for RAID 10
|
||||
1.3.2 Fix/improve redundancy checking for RAID10
|
||||
1.4.0 Non-functional change. Removes arg from mapping function.
|
||||
1.4.1 RAID10 fix redundancy validation checks (commit 55ebbb5).
|
||||
1.4.2 Add RAID10 "far" and "offset" algorithm support.
|
||||
1.5.0 Add message interface to allow manipulation of the sync_action.
|
||||
New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt.
|
||||
91
doc/kernel/service-time.txt
Normal file
91
doc/kernel/service-time.txt
Normal file
@@ -0,0 +1,91 @@
|
||||
dm-service-time
|
||||
===============
|
||||
|
||||
dm-service-time is a path selector module for device-mapper targets,
|
||||
which selects a path with the shortest estimated service time for
|
||||
the incoming I/O.
|
||||
|
||||
The service time for each path is estimated by dividing the total size
|
||||
of in-flight I/Os on a path with the performance value of the path.
|
||||
The performance value is a relative throughput value among all paths
|
||||
in a path-group, and it can be specified as a table argument.
|
||||
|
||||
The path selector name is 'service-time'.
|
||||
|
||||
Table parameters for each path: [<repeat_count> [<relative_throughput>]]
|
||||
<repeat_count>: The number of I/Os to dispatch using the selected
|
||||
path before switching to the next path.
|
||||
If not given, internal default is used. To check
|
||||
the default value, see the activated table.
|
||||
<relative_throughput>: The relative throughput value of the path
|
||||
among all paths in the path-group.
|
||||
The valid range is 0-100.
|
||||
If not given, minimum value '1' is used.
|
||||
If '0' is given, the path isn't selected while
|
||||
other paths having a positive value are available.
|
||||
|
||||
Status for each path: <status> <fail-count> <in-flight-size> \
|
||||
<relative_throughput>
|
||||
<status>: 'A' if the path is active, 'F' if the path is failed.
|
||||
<fail-count>: The number of path failures.
|
||||
<in-flight-size>: The size of in-flight I/Os on the path.
|
||||
<relative_throughput>: The relative throughput value of the path
|
||||
among all paths in the path-group.
|
||||
|
||||
|
||||
Algorithm
|
||||
=========
|
||||
|
||||
dm-service-time adds the I/O size to 'in-flight-size' when the I/O is
|
||||
dispatched and subtracts when completed.
|
||||
Basically, dm-service-time selects a path having minimum service time
|
||||
which is calculated by:
|
||||
|
||||
('in-flight-size' + 'size-of-incoming-io') / 'relative_throughput'
|
||||
|
||||
However, some optimizations below are used to reduce the calculation
|
||||
as much as possible.
|
||||
|
||||
1. If the paths have the same 'relative_throughput', skip
|
||||
the division and just compare the 'in-flight-size'.
|
||||
|
||||
2. If the paths have the same 'in-flight-size', skip the division
|
||||
and just compare the 'relative_throughput'.
|
||||
|
||||
3. If some paths have non-zero 'relative_throughput' and others
|
||||
have zero 'relative_throughput', ignore those paths with zero
|
||||
'relative_throughput'.
|
||||
|
||||
If such optimizations can't be applied, calculate service time, and
|
||||
compare service time.
|
||||
If calculated service time is equal, the path having maximum
|
||||
'relative_throughput' may be better. So compare 'relative_throughput'
|
||||
then.
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
In case that 2 paths (sda and sdb) are used with repeat_count == 128
|
||||
and sda has an average throughput 1GB/s and sdb has 4GB/s,
|
||||
'relative_throughput' value may be '1' for sda and '4' for sdb.
|
||||
|
||||
# echo "0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 1 8:16 128 4" \
|
||||
dmsetup create test
|
||||
#
|
||||
# dmsetup table
|
||||
test: 0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 1 8:16 128 4
|
||||
#
|
||||
# dmsetup status
|
||||
test: 0 10 multipath 2 0 0 0 1 1 E 0 2 2 8:0 A 0 0 1 8:16 A 0 0 4
|
||||
|
||||
|
||||
Or '2' for sda and '8' for sdb would be also true.
|
||||
|
||||
# echo "0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 2 8:16 128 8" \
|
||||
dmsetup create test
|
||||
#
|
||||
# dmsetup table
|
||||
test: 0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 2 8:16 128 8
|
||||
#
|
||||
# dmsetup status
|
||||
test: 0 10 multipath 2 0 0 0 1 1 E 0 2 2 8:0 A 0 0 2 8:16 A 0 0 8
|
||||
168
doc/kernel/snapshot.txt
Normal file
168
doc/kernel/snapshot.txt
Normal file
@@ -0,0 +1,168 @@
|
||||
Device-mapper snapshot support
|
||||
==============================
|
||||
|
||||
Device-mapper allows you, without massive data copying:
|
||||
|
||||
*) To create snapshots of any block device i.e. mountable, saved states of
|
||||
the block device which are also writable without interfering with the
|
||||
original content;
|
||||
*) To create device "forks", i.e. multiple different versions of the
|
||||
same data stream.
|
||||
*) To merge a snapshot of a block device back into the snapshot's origin
|
||||
device.
|
||||
|
||||
In the first two cases, dm copies only the chunks of data that get
|
||||
changed and uses a separate copy-on-write (COW) block device for
|
||||
storage.
|
||||
|
||||
For snapshot merge the contents of the COW storage are merged back into
|
||||
the origin device.
|
||||
|
||||
|
||||
There are three dm targets available:
|
||||
snapshot, snapshot-origin, and snapshot-merge.
|
||||
|
||||
*) snapshot-origin <origin>
|
||||
|
||||
which will normally have one or more snapshots based on it.
|
||||
Reads will be mapped directly to the backing device. For each write, the
|
||||
original data will be saved in the <COW device> of each snapshot to keep
|
||||
its visible content unchanged, at least until the <COW device> fills up.
|
||||
|
||||
|
||||
*) snapshot <origin> <COW device> <persistent?> <chunksize>
|
||||
|
||||
A snapshot of the <origin> block device is created. Changed chunks of
|
||||
<chunksize> sectors will be stored on the <COW device>. Writes will
|
||||
only go to the <COW device>. Reads will come from the <COW device> or
|
||||
from <origin> for unchanged data. <COW device> will often be
|
||||
smaller than the origin and if it fills up the snapshot will become
|
||||
useless and be disabled, returning errors. So it is important to monitor
|
||||
the amount of free space and expand the <COW device> before it fills up.
|
||||
|
||||
<persistent?> is P (Persistent) or N (Not persistent - will not survive
|
||||
after reboot).
|
||||
The difference is that for transient snapshots less metadata must be
|
||||
saved on disk - they can be kept in memory by the kernel.
|
||||
|
||||
|
||||
* snapshot-merge <origin> <COW device> <persistent> <chunksize>
|
||||
|
||||
takes the same table arguments as the snapshot target except it only
|
||||
works with persistent snapshots. This target assumes the role of the
|
||||
"snapshot-origin" target and must not be loaded if the "snapshot-origin"
|
||||
is still present for <origin>.
|
||||
|
||||
Creates a merging snapshot that takes control of the changed chunks
|
||||
stored in the <COW device> of an existing snapshot, through a handover
|
||||
procedure, and merges these chunks back into the <origin>. Once merging
|
||||
has started (in the background) the <origin> may be opened and the merge
|
||||
will continue while I/O is flowing to it. Changes to the <origin> are
|
||||
deferred until the merging snapshot's corresponding chunk(s) have been
|
||||
merged. Once merging has started the snapshot device, associated with
|
||||
the "snapshot" target, will return -EIO when accessed.
|
||||
|
||||
|
||||
How snapshot is used by LVM2
|
||||
============================
|
||||
When you create the first LVM2 snapshot of a volume, four dm devices are used:
|
||||
|
||||
1) a device containing the original mapping table of the source volume;
|
||||
2) a device used as the <COW device>;
|
||||
3) a "snapshot" device, combining #1 and #2, which is the visible snapshot
|
||||
volume;
|
||||
4) the "original" volume (which uses the device number used by the original
|
||||
source volume), whose table is replaced by a "snapshot-origin" mapping
|
||||
from device #1.
|
||||
|
||||
A fixed naming scheme is used, so with the following commands:
|
||||
|
||||
lvcreate -L 1G -n base volumeGroup
|
||||
lvcreate -L 100M --snapshot -n snap volumeGroup/base
|
||||
|
||||
we'll have this situation (with volumes in above order):
|
||||
|
||||
# dmsetup table|grep volumeGroup
|
||||
|
||||
volumeGroup-base-real: 0 2097152 linear 8:19 384
|
||||
volumeGroup-snap-cow: 0 204800 linear 8:19 2097536
|
||||
volumeGroup-snap: 0 2097152 snapshot 254:11 254:12 P 16
|
||||
volumeGroup-base: 0 2097152 snapshot-origin 254:11
|
||||
|
||||
# ls -lL /dev/mapper/volumeGroup-*
|
||||
brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
|
||||
brw------- 1 root root 254, 12 29 ago 18:15 /dev/mapper/volumeGroup-snap-cow
|
||||
brw------- 1 root root 254, 13 29 ago 18:15 /dev/mapper/volumeGroup-snap
|
||||
brw------- 1 root root 254, 10 29 ago 18:14 /dev/mapper/volumeGroup-base
|
||||
|
||||
|
||||
How snapshot-merge is used by LVM2
|
||||
==================================
|
||||
A merging snapshot assumes the role of the "snapshot-origin" while
|
||||
merging. As such the "snapshot-origin" is replaced with
|
||||
"snapshot-merge". The "-real" device is not changed and the "-cow"
|
||||
device is renamed to <origin name>-cow to aid LVM2's cleanup of the
|
||||
merging snapshot after it completes. The "snapshot" that hands over its
|
||||
COW device to the "snapshot-merge" is deactivated (unless using lvchange
|
||||
--refresh); but if it is left active it will simply return I/O errors.
|
||||
|
||||
A snapshot will merge into its origin with the following command:
|
||||
|
||||
lvconvert --merge volumeGroup/snap
|
||||
|
||||
we'll now have this situation:
|
||||
|
||||
# dmsetup table|grep volumeGroup
|
||||
|
||||
volumeGroup-base-real: 0 2097152 linear 8:19 384
|
||||
volumeGroup-base-cow: 0 204800 linear 8:19 2097536
|
||||
volumeGroup-base: 0 2097152 snapshot-merge 254:11 254:12 P 16
|
||||
|
||||
# ls -lL /dev/mapper/volumeGroup-*
|
||||
brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
|
||||
brw------- 1 root root 254, 12 29 ago 18:16 /dev/mapper/volumeGroup-base-cow
|
||||
brw------- 1 root root 254, 10 29 ago 18:16 /dev/mapper/volumeGroup-base
|
||||
|
||||
|
||||
How to determine when a merging is complete
|
||||
===========================================
|
||||
The snapshot-merge and snapshot status lines end with:
|
||||
<sectors_allocated>/<total_sectors> <metadata_sectors>
|
||||
|
||||
Both <sectors_allocated> and <total_sectors> include both data and metadata.
|
||||
During merging, the number of sectors allocated gets smaller and
|
||||
smaller. Merging has finished when the number of sectors holding data
|
||||
is zero, in other words <sectors_allocated> == <metadata_sectors>.
|
||||
|
||||
Here is a practical example (using a hybrid of lvm and dmsetup commands):
|
||||
|
||||
# lvs
|
||||
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
|
||||
base volumeGroup owi-a- 4.00g
|
||||
snap volumeGroup swi-a- 1.00g base 18.97
|
||||
|
||||
# dmsetup status volumeGroup-snap
|
||||
0 8388608 snapshot 397896/2097152 1560
|
||||
^^^^ metadata sectors
|
||||
|
||||
# lvconvert --merge -b volumeGroup/snap
|
||||
Merging of volume snap started.
|
||||
|
||||
# lvs volumeGroup/snap
|
||||
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
|
||||
base volumeGroup Owi-a- 4.00g 17.23
|
||||
|
||||
# dmsetup status volumeGroup-base
|
||||
0 8388608 snapshot-merge 281688/2097152 1104
|
||||
|
||||
# dmsetup status volumeGroup-base
|
||||
0 8388608 snapshot-merge 180480/2097152 712
|
||||
|
||||
# dmsetup status volumeGroup-base
|
||||
0 8388608 snapshot-merge 16/2097152 16
|
||||
|
||||
Merging has finished.
|
||||
|
||||
# lvs
|
||||
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
|
||||
base volumeGroup owi-a- 4.00g
|
||||
57
doc/kernel/striped.txt
Normal file
57
doc/kernel/striped.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
dm-stripe
|
||||
=========
|
||||
|
||||
Device-Mapper's "striped" target is used to create a striped (i.e. RAID-0)
|
||||
device across one or more underlying devices. Data is written in "chunks",
|
||||
with consecutive chunks rotating among the underlying devices. This can
|
||||
potentially provide improved I/O throughput by utilizing several physical
|
||||
devices in parallel.
|
||||
|
||||
Parameters: <num devs> <chunk size> [<dev path> <offset>]+
|
||||
<num devs>: Number of underlying devices.
|
||||
<chunk size>: Size of each chunk of data. Must be at least as
|
||||
large as the system's PAGE_SIZE.
|
||||
<dev path>: Full pathname to the underlying block-device, or a
|
||||
"major:minor" device-number.
|
||||
<offset>: Starting sector within the device.
|
||||
|
||||
One or more underlying devices can be specified. The striped device size must
|
||||
be a multiple of the chunk size multiplied by the number of underlying devices.
|
||||
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
|
||||
[[
|
||||
#!/usr/bin/perl -w
|
||||
# Create a striped device across any number of underlying devices. The device
|
||||
# will be called "stripe_dev" and have a chunk-size of 128k.
|
||||
|
||||
my $chunk_size = 128 * 2;
|
||||
my $dev_name = "stripe_dev";
|
||||
my $num_devs = @ARGV;
|
||||
my @devs = @ARGV;
|
||||
my ($min_dev_size, $stripe_dev_size, $i);
|
||||
|
||||
if (!$num_devs) {
|
||||
die("Specify at least one device\n");
|
||||
}
|
||||
|
||||
$min_dev_size = `blockdev --getsize $devs[0]`;
|
||||
for ($i = 1; $i < $num_devs; $i++) {
|
||||
my $this_size = `blockdev --getsize $devs[$i]`;
|
||||
$min_dev_size = ($min_dev_size < $this_size) ?
|
||||
$min_dev_size : $this_size;
|
||||
}
|
||||
|
||||
$stripe_dev_size = $min_dev_size * $num_devs;
|
||||
$stripe_dev_size -= $stripe_dev_size % ($chunk_size * $num_devs);
|
||||
|
||||
$table = "0 $stripe_dev_size striped $num_devs $chunk_size";
|
||||
for ($i = 0; $i < $num_devs; $i++) {
|
||||
$table .= " $devs[$i] 0";
|
||||
}
|
||||
|
||||
`echo $table | dmsetup create $dev_name`;
|
||||
]]
|
||||
|
||||
353
doc/kernel/thin-provisioning.txt
Normal file
353
doc/kernel/thin-provisioning.txt
Normal file
@@ -0,0 +1,353 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document describes a collection of device-mapper targets that
|
||||
between them implement thin-provisioning and snapshots.
|
||||
|
||||
The main highlight of this implementation, compared to the previous
|
||||
implementation of snapshots, is that it allows many virtual devices to
|
||||
be stored on the same data volume. This simplifies administration and
|
||||
allows the sharing of data between volumes, thus reducing disk usage.
|
||||
|
||||
Another significant feature is support for an arbitrary depth of
|
||||
recursive snapshots (snapshots of snapshots of snapshots ...). The
|
||||
previous implementation of snapshots did this by chaining together
|
||||
lookup tables, and so performance was O(depth). This new
|
||||
implementation uses a single data structure to avoid this degradation
|
||||
with depth. Fragmentation may still be an issue, however, in some
|
||||
scenarios.
|
||||
|
||||
Metadata is stored on a separate device from data, giving the
|
||||
administrator some freedom, for example to:
|
||||
|
||||
- Improve metadata resilience by storing metadata on a mirrored volume
|
||||
but data on a non-mirrored one.
|
||||
|
||||
- Improve performance by storing the metadata on SSD.
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
These targets are very much still in the EXPERIMENTAL state. Please
|
||||
do not yet rely on them in production. But do experiment and offer us
|
||||
feedback. Different use cases will have different performance
|
||||
characteristics, for example due to fragmentation of the data volume.
|
||||
|
||||
If you find this software is not performing as expected please mail
|
||||
dm-devel@redhat.com with details and we'll try our best to improve
|
||||
things for you.
|
||||
|
||||
Userspace tools for checking and repairing the metadata are under
|
||||
development.
|
||||
|
||||
Cookbook
|
||||
========
|
||||
|
||||
This section describes some quick recipes for using thin provisioning.
|
||||
They use the dmsetup program to control the device-mapper driver
|
||||
directly. End users will be advised to use a higher-level volume
|
||||
manager such as LVM2 once support has been added.
|
||||
|
||||
Pool device
|
||||
-----------
|
||||
|
||||
The pool device ties together the metadata volume and the data volume.
|
||||
It maps I/O linearly to the data volume and updates the metadata via
|
||||
two mechanisms:
|
||||
|
||||
- Function calls from the thin targets
|
||||
|
||||
- Device-mapper 'messages' from userspace which control the creation of new
|
||||
virtual devices amongst other things.
|
||||
|
||||
Setting up a fresh pool device
|
||||
------------------------------
|
||||
|
||||
Setting up a pool device requires a valid metadata device, and a
|
||||
data device. If you do not have an existing metadata device you can
|
||||
make one by zeroing the first 4k to indicate empty metadata.
|
||||
|
||||
dd if=/dev/zero of=$metadata_dev bs=4096 count=1
|
||||
|
||||
The amount of metadata you need will vary according to how many blocks
|
||||
are shared between thin devices (i.e. through snapshots). If you have
|
||||
less sharing than average you'll need a larger-than-average metadata device.
|
||||
|
||||
As a guide, we suggest you calculate the number of bytes to use in the
|
||||
metadata device as 48 * $data_dev_size / $data_block_size but round it up
|
||||
to 2MB if the answer is smaller. If you're creating large numbers of
|
||||
snapshots which are recording large amounts of change, you may find you
|
||||
need to increase this.
|
||||
|
||||
The largest size supported is 16GB: If the device is larger,
|
||||
a warning will be issued and the excess space will not be used.
|
||||
|
||||
Reloading a pool table
|
||||
----------------------
|
||||
|
||||
You may reload a pool's table, indeed this is how the pool is resized
|
||||
if it runs out of space. (N.B. While specifying a different metadata
|
||||
device when reloading is not forbidden at the moment, things will go
|
||||
wrong if it does not route I/O to exactly the same on-disk location as
|
||||
previously.)
|
||||
|
||||
Using an existing pool device
|
||||
-----------------------------
|
||||
|
||||
dmsetup create pool \
|
||||
--table "0 20971520 thin-pool $metadata_dev $data_dev \
|
||||
$data_block_size $low_water_mark"
|
||||
|
||||
$data_block_size gives the smallest unit of disk space that can be
|
||||
allocated at a time expressed in units of 512-byte sectors. People
|
||||
primarily interested in thin provisioning may want to use a value such
|
||||
as 1024 (512KB). People doing lots of snapshotting may want a smaller value
|
||||
such as 128 (64KB). If you are not zeroing newly-allocated data,
|
||||
a larger $data_block_size in the region of 256000 (128MB) is suggested.
|
||||
$data_block_size must be the same for the lifetime of the
|
||||
metadata device.
|
||||
|
||||
$low_water_mark is expressed in blocks of size $data_block_size. If
|
||||
free space on the data device drops below this level then a dm event
|
||||
will be triggered which a userspace daemon should catch allowing it to
|
||||
extend the pool device. Only one such event will be sent.
|
||||
Resuming a device with a new table itself triggers an event so the
|
||||
userspace daemon can use this to detect a situation where a new table
|
||||
already exceeds the threshold.
|
||||
|
||||
Thin provisioning
|
||||
-----------------
|
||||
|
||||
i) Creating a new thinly-provisioned volume.
|
||||
|
||||
To create a new thinly- provisioned volume you must send a message to an
|
||||
active pool device, /dev/mapper/pool in this example.
|
||||
|
||||
dmsetup message /dev/mapper/pool 0 "create_thin 0"
|
||||
|
||||
Here '0' is an identifier for the volume, a 24-bit number. It's up
|
||||
to the caller to allocate and manage these identifiers. If the
|
||||
identifier is already in use, the message will fail with -EEXIST.
|
||||
|
||||
ii) Using a thinly-provisioned volume.
|
||||
|
||||
Thinly-provisioned volumes are activated using the 'thin' target:
|
||||
|
||||
dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"
|
||||
|
||||
The last parameter is the identifier for the thinp device.
|
||||
|
||||
Internal snapshots
|
||||
------------------
|
||||
|
||||
i) Creating an internal snapshot.
|
||||
|
||||
Snapshots are created with another message to the pool.
|
||||
|
||||
N.B. If the origin device that you wish to snapshot is active, you
|
||||
must suspend it before creating the snapshot to avoid corruption.
|
||||
This is NOT enforced at the moment, so please be careful!
|
||||
|
||||
dmsetup suspend /dev/mapper/thin
|
||||
dmsetup message /dev/mapper/pool 0 "create_snap 1 0"
|
||||
dmsetup resume /dev/mapper/thin
|
||||
|
||||
Here '1' is the identifier for the volume, a 24-bit number. '0' is the
|
||||
identifier for the origin device.
|
||||
|
||||
ii) Using an internal snapshot.
|
||||
|
||||
Once created, the user doesn't have to worry about any connection
|
||||
between the origin and the snapshot. Indeed the snapshot is no
|
||||
different from any other thinly-provisioned device and can be
|
||||
snapshotted itself via the same method. It's perfectly legal to
|
||||
have only one of them active, and there's no ordering requirement on
|
||||
activating or removing them both. (This differs from conventional
|
||||
device-mapper snapshots.)
|
||||
|
||||
Activate it exactly the same way as any other thinly-provisioned volume:
|
||||
|
||||
dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
|
||||
|
||||
External snapshots
|
||||
------------------
|
||||
|
||||
You can use an external _read only_ device as an origin for a
|
||||
thinly-provisioned volume. Any read to an unprovisioned area of the
|
||||
thin device will be passed through to the origin. Writes trigger
|
||||
the allocation of new blocks as usual.
|
||||
|
||||
One use case for this is VM hosts that want to run guests on
|
||||
thinly-provisioned volumes but have the base image on another device
|
||||
(possibly shared between many VMs).
|
||||
|
||||
You must not write to the origin device if you use this technique!
|
||||
Of course, you may write to the thin device and take internal snapshots
|
||||
of the thin volume.
|
||||
|
||||
i) Creating a snapshot of an external device
|
||||
|
||||
This is the same as creating a thin device.
|
||||
You don't mention the origin at this stage.
|
||||
|
||||
dmsetup message /dev/mapper/pool 0 "create_thin 0"
|
||||
|
||||
ii) Using a snapshot of an external device.
|
||||
|
||||
Append an extra parameter to the thin target specifying the origin:
|
||||
|
||||
dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 0 /dev/image"
|
||||
|
||||
N.B. All descendants (internal snapshots) of this snapshot require the
|
||||
same extra origin parameter.
|
||||
|
||||
Deactivation
|
||||
------------
|
||||
|
||||
All devices using a pool must be deactivated before the pool itself
|
||||
can be.
|
||||
|
||||
dmsetup remove thin
|
||||
dmsetup remove snap
|
||||
dmsetup remove pool
|
||||
|
||||
Reference
|
||||
=========
|
||||
|
||||
'thin-pool' target
|
||||
------------------
|
||||
|
||||
i) Constructor
|
||||
|
||||
thin-pool <metadata dev> <data dev> <data block size (sectors)> \
|
||||
<low water mark (blocks)> [<number of feature args> [<arg>]*]
|
||||
|
||||
Optional feature arguments:
|
||||
|
||||
skip_block_zeroing: Skip the zeroing of newly-provisioned blocks.
|
||||
|
||||
ignore_discard: Disable discard support.
|
||||
|
||||
no_discard_passdown: Don't pass discards down to the underlying
|
||||
data device, but just remove the mapping.
|
||||
|
||||
read_only: Don't allow any changes to be made to the pool
|
||||
metadata.
|
||||
|
||||
Data block size must be between 64KB (128 sectors) and 1GB
|
||||
(2097152 sectors) inclusive.
|
||||
|
||||
|
||||
ii) Status
|
||||
|
||||
<transaction id> <used metadata blocks>/<total metadata blocks>
|
||||
<used data blocks>/<total data blocks> <held metadata root>
|
||||
[no_]discard_passdown ro|rw
|
||||
|
||||
transaction id:
|
||||
A 64-bit number used by userspace to help synchronise with metadata
|
||||
from volume managers.
|
||||
|
||||
used data blocks / total data blocks
|
||||
If the number of free blocks drops below the pool's low water mark a
|
||||
dm event will be sent to userspace. This event is edge-triggered and
|
||||
it will occur only once after each resume so volume manager writers
|
||||
should register for the event and then check the target's status.
|
||||
|
||||
held metadata root:
|
||||
The location, in sectors, of the metadata root that has been
|
||||
'held' for userspace read access. '-' indicates there is no
|
||||
held root. This feature is not yet implemented so '-' is
|
||||
always returned.
|
||||
|
||||
discard_passdown|no_discard_passdown
|
||||
Whether or not discards are actually being passed down to the
|
||||
underlying device. When this is enabled when loading the table,
|
||||
it can get disabled if the underlying device doesn't support it.
|
||||
|
||||
ro|rw
|
||||
If the pool encounters certain types of device failures it will
|
||||
drop into a read-only metadata mode in which no changes to
|
||||
the pool metadata (like allocating new blocks) are permitted.
|
||||
|
||||
In serious cases where even a read-only mode is deemed unsafe
|
||||
no further I/O will be permitted and the status will just
|
||||
contain the string 'Fail'. The userspace recovery tools
|
||||
should then be used.
|
||||
|
||||
iii) Messages
|
||||
|
||||
create_thin <dev id>
|
||||
|
||||
Create a new thinly-provisioned device.
|
||||
<dev id> is an arbitrary unique 24-bit identifier chosen by
|
||||
the caller.
|
||||
|
||||
create_snap <dev id> <origin id>
|
||||
|
||||
Create a new snapshot of another thinly-provisioned device.
|
||||
<dev id> is an arbitrary unique 24-bit identifier chosen by
|
||||
the caller.
|
||||
<origin id> is the identifier of the thinly-provisioned device
|
||||
of which the new device will be a snapshot.
|
||||
|
||||
delete <dev id>
|
||||
|
||||
Deletes a thin device. Irreversible.
|
||||
|
||||
set_transaction_id <current id> <new id>
|
||||
|
||||
Userland volume managers, such as LVM, need a way to
|
||||
synchronise their external metadata with the internal metadata of the
|
||||
pool target. The thin-pool target offers to store an
|
||||
arbitrary 64-bit transaction id and return it on the target's
|
||||
status line. To avoid races you must provide what you think
|
||||
the current transaction id is when you change it with this
|
||||
compare-and-swap message.
|
||||
|
||||
reserve_metadata_snap
|
||||
|
||||
Reserve a copy of the data mapping btree for use by userland.
|
||||
This allows userland to inspect the mappings as they were when
|
||||
this message was executed. Use the pool's status command to
|
||||
get the root block associated with the metadata snapshot.
|
||||
|
||||
release_metadata_snap
|
||||
|
||||
Release a previously reserved copy of the data mapping btree.
|
||||
|
||||
'thin' target
|
||||
-------------
|
||||
|
||||
i) Constructor
|
||||
|
||||
thin <pool dev> <dev id> [<external origin dev>]
|
||||
|
||||
pool dev:
|
||||
the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
|
||||
|
||||
dev id:
|
||||
the internal device identifier of the device to be
|
||||
activated.
|
||||
|
||||
external origin dev:
|
||||
an optional block device outside the pool to be treated as a
|
||||
read-only snapshot origin: reads to unprovisioned areas of the
|
||||
thin target will be mapped to this device.
|
||||
|
||||
The pool doesn't store any size against the thin devices. If you
|
||||
load a thin target that is smaller than you've been using previously,
|
||||
then you'll have no access to blocks mapped beyond the end. If you
|
||||
load a target that is bigger than before, then extra blocks will be
|
||||
provisioned as and when needed.
|
||||
|
||||
If you wish to reduce the size of your thin device and potentially
|
||||
regain some space then send the 'trim' message to the pool.
|
||||
|
||||
ii) Status
|
||||
|
||||
<nr mapped sectors> <highest mapped sector>
|
||||
|
||||
If the pool has encountered device errors and failed, the status
|
||||
will just contain the string 'Fail'. The userspace recovery
|
||||
tools should then be used.
|
||||
97
doc/kernel/uevent.txt
Normal file
97
doc/kernel/uevent.txt
Normal file
@@ -0,0 +1,97 @@
|
||||
The device-mapper uevent code adds the capability to device-mapper to create
|
||||
and send kobject uevents (uevents). Previously device-mapper events were only
|
||||
available through the ioctl interface. The advantage of the uevents interface
|
||||
is the event contains environment attributes providing increased context for
|
||||
the event avoiding the need to query the state of the device-mapper device after
|
||||
the event is received.
|
||||
|
||||
There are two functions currently for device-mapper events. The first function
|
||||
listed creates the event and the second function sends the event(s).
|
||||
|
||||
void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
|
||||
const char *path, unsigned nr_valid_paths)
|
||||
|
||||
void dm_send_uevents(struct list_head *events, struct kobject *kobj)
|
||||
|
||||
|
||||
The variables added to the uevent environment are:
|
||||
|
||||
Variable Name: DM_TARGET
|
||||
Uevent Action(s): KOBJ_CHANGE
|
||||
Type: string
|
||||
Description:
|
||||
Value: Name of device-mapper target that generated the event.
|
||||
|
||||
Variable Name: DM_ACTION
|
||||
Uevent Action(s): KOBJ_CHANGE
|
||||
Type: string
|
||||
Description:
|
||||
Value: Device-mapper specific action that caused the uevent action.
|
||||
PATH_FAILED - A path has failed.
|
||||
PATH_REINSTATED - A path has been reinstated.
|
||||
|
||||
Variable Name: DM_SEQNUM
|
||||
Uevent Action(s): KOBJ_CHANGE
|
||||
Type: unsigned integer
|
||||
Description: A sequence number for this specific device-mapper device.
|
||||
Value: Valid unsigned integer range.
|
||||
|
||||
Variable Name: DM_PATH
|
||||
Uevent Action(s): KOBJ_CHANGE
|
||||
Type: string
|
||||
Description: Major and minor number of the path device pertaining to this
|
||||
event.
|
||||
Value: Path name in the form of "Major:Minor"
|
||||
|
||||
Variable Name: DM_NR_VALID_PATHS
|
||||
Uevent Action(s): KOBJ_CHANGE
|
||||
Type: unsigned integer
|
||||
Description:
|
||||
Value: Valid unsigned integer range.
|
||||
|
||||
Variable Name: DM_NAME
|
||||
Uevent Action(s): KOBJ_CHANGE
|
||||
Type: string
|
||||
Description: Name of the device-mapper device.
|
||||
Value: Name
|
||||
|
||||
Variable Name: DM_UUID
|
||||
Uevent Action(s): KOBJ_CHANGE
|
||||
Type: string
|
||||
Description: UUID of the device-mapper device.
|
||||
Value: UUID. (Empty string if there isn't one.)
|
||||
|
||||
An example of the uevents generated as captured by udevmonitor is shown
|
||||
below.
|
||||
|
||||
1.) Path failure.
|
||||
UEVENT[1192521009.711215] change@/block/dm-3
|
||||
ACTION=change
|
||||
DEVPATH=/block/dm-3
|
||||
SUBSYSTEM=block
|
||||
DM_TARGET=multipath
|
||||
DM_ACTION=PATH_FAILED
|
||||
DM_SEQNUM=1
|
||||
DM_PATH=8:32
|
||||
DM_NR_VALID_PATHS=0
|
||||
DM_NAME=mpath2
|
||||
DM_UUID=mpath-35333333000002328
|
||||
MINOR=3
|
||||
MAJOR=253
|
||||
SEQNUM=1130
|
||||
|
||||
2.) Path reinstate.
|
||||
UEVENT[1192521132.989927] change@/block/dm-3
|
||||
ACTION=change
|
||||
DEVPATH=/block/dm-3
|
||||
SUBSYSTEM=block
|
||||
DM_TARGET=multipath
|
||||
DM_ACTION=PATH_REINSTATED
|
||||
DM_SEQNUM=2
|
||||
DM_PATH=8:32
|
||||
DM_NR_VALID_PATHS=1
|
||||
DM_NAME=mpath2
|
||||
DM_UUID=mpath-35333333000002328
|
||||
MINOR=3
|
||||
MAJOR=253
|
||||
SEQNUM=1131
|
||||
155
doc/kernel/verity.txt
Normal file
155
doc/kernel/verity.txt
Normal file
@@ -0,0 +1,155 @@
|
||||
dm-verity
|
||||
==========
|
||||
|
||||
Device-Mapper's "verity" target provides transparent integrity checking of
|
||||
block devices using a cryptographic digest provided by the kernel crypto API.
|
||||
This target is read-only.
|
||||
|
||||
Construction Parameters
|
||||
=======================
|
||||
<version> <dev> <hash_dev>
|
||||
<data_block_size> <hash_block_size>
|
||||
<num_data_blocks> <hash_start_block>
|
||||
<algorithm> <digest> <salt>
|
||||
|
||||
<version>
|
||||
This is the type of the on-disk hash format.
|
||||
|
||||
0 is the original format used in the Chromium OS.
|
||||
The salt is appended when hashing, digests are stored continuously and
|
||||
the rest of the block is padded with zeros.
|
||||
|
||||
1 is the current format that should be used for new devices.
|
||||
The salt is prepended when hashing and each digest is
|
||||
padded with zeros to the power of two.
|
||||
|
||||
<dev>
|
||||
This is the device containing data, the integrity of which needs to be
|
||||
checked. It may be specified as a path, like /dev/sdaX, or a device number,
|
||||
<major>:<minor>.
|
||||
|
||||
<hash_dev>
|
||||
This is the device that supplies the hash tree data. It may be
|
||||
specified similarly to the device path and may be the same device. If the
|
||||
same device is used, the hash_start should be outside the configured
|
||||
dm-verity device.
|
||||
|
||||
<data_block_size>
|
||||
The block size on a data device in bytes.
|
||||
Each block corresponds to one digest on the hash device.
|
||||
|
||||
<hash_block_size>
|
||||
The size of a hash block in bytes.
|
||||
|
||||
<num_data_blocks>
|
||||
The number of data blocks on the data device. Additional blocks are
|
||||
inaccessible. You can place hashes to the same partition as data, in this
|
||||
case hashes are placed after <num_data_blocks>.
|
||||
|
||||
<hash_start_block>
|
||||
This is the offset, in <hash_block_size>-blocks, from the start of hash_dev
|
||||
to the root block of the hash tree.
|
||||
|
||||
<algorithm>
|
||||
The cryptographic hash algorithm used for this device. This should
|
||||
be the name of the algorithm, like "sha1".
|
||||
|
||||
<digest>
|
||||
The hexadecimal encoding of the cryptographic hash of the root hash block
|
||||
and the salt. This hash should be trusted as there is no other authenticity
|
||||
beyond this point.
|
||||
|
||||
<salt>
|
||||
The hexadecimal encoding of the salt value.
|
||||
|
||||
Theory of operation
|
||||
===================
|
||||
|
||||
dm-verity is meant to be set up as part of a verified boot path. This
|
||||
may be anything ranging from a boot using tboot or trustedgrub to just
|
||||
booting from a known-good device (like a USB drive or CD).
|
||||
|
||||
When a dm-verity device is configured, it is expected that the caller
|
||||
has been authenticated in some way (cryptographic signatures, etc).
|
||||
After instantiation, all hashes will be verified on-demand during
|
||||
disk access. If they cannot be verified up to the root node of the
|
||||
tree, the root hash, then the I/O will fail. This should detect
|
||||
tampering with any data on the device and the hash data.
|
||||
|
||||
Cryptographic hashes are used to assert the integrity of the device on a
|
||||
per-block basis. This allows for a lightweight hash computation on first read
|
||||
into the page cache. Block hashes are stored linearly, aligned to the nearest
|
||||
block size.
|
||||
|
||||
Hash Tree
|
||||
---------
|
||||
|
||||
Each node in the tree is a cryptographic hash. If it is a leaf node, the hash
|
||||
of some data block on disk is calculated. If it is an intermediary node,
|
||||
the hash of a number of child nodes is calculated.
|
||||
|
||||
Each entry in the tree is a collection of neighboring nodes that fit in one
|
||||
block. The number is determined based on block_size and the size of the
|
||||
selected cryptographic digest algorithm. The hashes are linearly-ordered in
|
||||
this entry and any unaligned trailing space is ignored but included when
|
||||
calculating the parent node.
|
||||
|
||||
The tree looks something like:
|
||||
|
||||
alg = sha256, num_blocks = 32768, block_size = 4096
|
||||
|
||||
[ root ]
|
||||
/ . . . \
|
||||
[entry_0] [entry_1]
|
||||
/ . . . \ . . . \
|
||||
[entry_0_0] . . . [entry_0_127] . . . . [entry_1_127]
|
||||
/ ... \ / . . . \ / \
|
||||
blk_0 ... blk_127 blk_16256 blk_16383 blk_32640 . . . blk_32767
|
||||
|
||||
|
||||
On-disk format
|
||||
==============
|
||||
|
||||
The verity kernel code does not read the verity metadata on-disk header.
|
||||
It only reads the hash blocks which directly follow the header.
|
||||
It is expected that a user-space tool will verify the integrity of the
|
||||
verity header.
|
||||
|
||||
Alternatively, the header can be omitted and the dmsetup parameters can
|
||||
be passed via the kernel command-line in a rooted chain of trust where
|
||||
the command-line is verified.
|
||||
|
||||
Directly following the header (and with sector number padded to the next hash
|
||||
block boundary) are the hash blocks which are stored a depth at a time
|
||||
(starting from the root), sorted in order of increasing index.
|
||||
|
||||
The full specification of kernel parameters and on-disk metadata format
|
||||
is available at the cryptsetup project's wiki page
|
||||
http://code.google.com/p/cryptsetup/wiki/DMVerity
|
||||
|
||||
Status
|
||||
======
|
||||
V (for Valid) is returned if every check performed so far was valid.
|
||||
If any check failed, C (for Corruption) is returned.
|
||||
|
||||
Example
|
||||
=======
|
||||
Set up a device:
|
||||
# dmsetup create vroot --readonly --table \
|
||||
"0 2097152 verity 1 /dev/sda1 /dev/sda2 4096 4096 262144 1 sha256 "\
|
||||
"4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 "\
|
||||
"1234000000000000000000000000000000000000000000000000000000000000"
|
||||
|
||||
A command line tool veritysetup is available to compute or verify
|
||||
the hash tree or activate the kernel device. This is available from
|
||||
the cryptsetup upstream repository http://code.google.com/p/cryptsetup/
|
||||
(as a libcryptsetup extension).
|
||||
|
||||
Create hash on the device:
|
||||
# veritysetup format /dev/sda1 /dev/sda2
|
||||
...
|
||||
Root hash: 4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076
|
||||
|
||||
Activate the device:
|
||||
# veritysetup create vroot /dev/sda1 /dev/sda2 \
|
||||
4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076
|
||||
37
doc/kernel/zero.txt
Normal file
37
doc/kernel/zero.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
dm-zero
|
||||
=======
|
||||
|
||||
Device-Mapper's "zero" target provides a block-device that always returns
|
||||
zero'd data on reads and silently drops writes. This is similar behavior to
|
||||
/dev/zero, but as a block-device instead of a character-device.
|
||||
|
||||
Dm-zero has no target-specific parameters.
|
||||
|
||||
One very interesting use of dm-zero is for creating "sparse" devices in
|
||||
conjunction with dm-snapshot. A sparse device reports a device-size larger
|
||||
than the amount of actual storage space available for that device. A user can
|
||||
write data anywhere within the sparse device and read it back like a normal
|
||||
device. Reads to previously unwritten areas will return a zero'd buffer. When
|
||||
enough data has been written to fill up the actual storage space, the sparse
|
||||
device is deactivated. This can be very useful for testing device and
|
||||
filesystem limitations.
|
||||
|
||||
To create a sparse device, start by creating a dm-zero device that's the
|
||||
desired size of the sparse device. For this example, we'll assume a 10TB
|
||||
sparse device.
|
||||
|
||||
TEN_TERABYTES=`expr 10 \* 1024 \* 1024 \* 1024 \* 2` # 10 TB in sectors
|
||||
echo "0 $TEN_TERABYTES zero" | dmsetup create zero1
|
||||
|
||||
Then create a snapshot of the zero device, using any available block-device as
|
||||
the COW device. The size of the COW device will determine the amount of real
|
||||
space available to the sparse device. For this example, we'll assume /dev/sdb1
|
||||
is an available 10GB partition.
|
||||
|
||||
echo "0 $TEN_TERABYTES snapshot /dev/mapper/zero1 /dev/sdb1 p 128" | \
|
||||
dmsetup create sparse1
|
||||
|
||||
This will create a 10TB sparse device called /dev/mapper/sparse1 that has
|
||||
10GB of actual storage space available. If more than 10GB of data is written
|
||||
to this device, it will start returning I/O errors.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user