mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-09 04:23:47 +03:00
Compare commits
1610 Commits
2018-06-01
...
dev-dct-wr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6e67d688e | ||
|
|
05d23b2dd8 | ||
|
|
5a94126e7a | ||
|
|
c96645781c | ||
|
|
020d1edaa0 | ||
|
|
830c20d33c | ||
|
|
2c31939827 | ||
|
|
7bafae48bb | ||
|
|
e793f34eb7 | ||
|
|
b033384135 | ||
|
|
2183af62e5 | ||
|
|
edb55b767a | ||
|
|
413c88116d | ||
|
|
9740e98cbd | ||
|
|
be94410446 | ||
|
|
8c2779ba34 | ||
|
|
51a532719c | ||
|
|
73ef86ae3f | ||
|
|
6226512ad2 | ||
|
|
f3b723cd8d | ||
|
|
a7f195b7e8 | ||
|
|
677f829e54 | ||
|
|
c7311d4722 | ||
|
|
b3cdf0d881 | ||
|
|
2c9bb67604 | ||
|
|
c74ccd5201 | ||
|
|
c601ec0d6e | ||
|
|
83d0818523 | ||
|
|
6be29e1179 | ||
|
|
fdec4cd3e6 | ||
|
|
bd272e3bce | ||
|
|
756066a2e8 | ||
|
|
3e06061d82 | ||
|
|
a17ec7e0ba | ||
|
|
b75c2dfe1b | ||
|
|
b2a326b511 | ||
|
|
4b0565b82f | ||
|
|
4c1caa7e26 | ||
|
|
58976ccc34 | ||
|
|
d2bdad28d1 | ||
|
|
b50134dc14 | ||
|
|
616e5b854c | ||
|
|
53db14171c | ||
|
|
ee43ec5782 | ||
|
|
99b6173f10 | ||
|
|
5e26a2b74d | ||
|
|
8d9b4c624f | ||
|
|
73a3a0d347 | ||
|
|
117fc64e6e | ||
|
|
1b8c6f09bc | ||
|
|
e1af80c81c | ||
|
|
dd8212365d | ||
|
|
e7fff97b8d | ||
|
|
c65d3a6b8a | ||
|
|
7396f1cfee | ||
|
|
b44db5d1a7 | ||
|
|
b3c7a2b3f0 | ||
|
|
0fe58fc54f | ||
|
|
41f9e372c0 | ||
|
|
9885c9b43a | ||
|
|
2df7ef58a5 | ||
|
|
ae96a43f05 | ||
|
|
91f869e43c | ||
|
|
0143c7aebe | ||
|
|
74ed6e8a99 | ||
|
|
450f272b31 | ||
|
|
ff3945777b | ||
|
|
c32d7fed4f | ||
|
|
d1b7438c9f | ||
|
|
46e5908759 | ||
|
|
2272a32e6f | ||
|
|
82e270c18a | ||
|
|
af8044da3a | ||
|
|
6728788bf5 | ||
|
|
0c89c5a40f | ||
|
|
bd0d4de4e2 | ||
|
|
4cd356b26b | ||
|
|
18c74666ee | ||
|
|
4de6f58085 | ||
|
|
92c0e8c17f | ||
|
|
08e838f488 | ||
|
|
af5f29c7e2 | ||
|
|
3ed11170da | ||
|
|
655342427d | ||
|
|
168e2ffbcd | ||
|
|
fb96e9ab21 | ||
|
|
df6f16c081 | ||
|
|
da14cf68cb | ||
|
|
890c7ef451 | ||
|
|
8952dcbff0 | ||
|
|
bbc164991a | ||
|
|
a89ac3bf6f | ||
|
|
ccb58c109f | ||
|
|
3e003320a7 | ||
|
|
e2577c037d | ||
|
|
e414ebef6e | ||
|
|
2bfa868f91 | ||
|
|
8b22e38087 | ||
|
|
ef59c83f2d | ||
|
|
e2eb1dc501 | ||
|
|
fc9e732811 | ||
|
|
502b895bb4 | ||
|
|
39cdc1469d | ||
|
|
cfc4dd4c7c | ||
|
|
90c50c1b53 | ||
|
|
50a37948b5 | ||
|
|
7c19186271 | ||
|
|
3869c9c4f6 | ||
|
|
e280f56dd3 | ||
|
|
adead83dc2 | ||
|
|
cbed63eeb9 | ||
|
|
3a3307c0d8 | ||
|
|
f38b7afd62 | ||
|
|
642ef54399 | ||
|
|
e08a0421a3 | ||
|
|
5bc66532c7 | ||
|
|
bc9bb534ff | ||
|
|
f507a2564c | ||
|
|
f2878a801c | ||
|
|
531a475afc | ||
|
|
a1074da20d | ||
|
|
e556c7b7c6 | ||
|
|
6c769eb460 | ||
|
|
6b168afcad | ||
|
|
f63aac5309 | ||
|
|
f7c58c636d | ||
|
|
8e3e2c74ed | ||
|
|
530fc17b38 | ||
|
|
1404e5ee61 | ||
|
|
1570e76233 | ||
|
|
4b07ae55f1 | ||
|
|
9fbcba1c40 | ||
|
|
9448476202 | ||
|
|
206620018e | ||
|
|
048e04e417 | ||
|
|
b77595ac8b | ||
|
|
a4137412bf | ||
|
|
8d40859e29 | ||
|
|
a5e867139d | ||
|
|
7f019f2580 | ||
|
|
72b931d664 | ||
|
|
46f43589d0 | ||
|
|
491eb25832 | ||
|
|
37bcd7ce84 | ||
|
|
52d3c4de6e | ||
|
|
49292bccc3 | ||
|
|
2c6bd480b2 | ||
|
|
cf4fed3761 | ||
|
|
d0ccb2521b | ||
|
|
2b36542f41 | ||
|
|
d588de77aa | ||
|
|
ec4e8b5c0e | ||
|
|
7bcc994776 | ||
|
|
7b08133844 | ||
|
|
6d344b4ac0 | ||
|
|
187cc8d344 | ||
|
|
39198eb2ce | ||
|
|
18a60c6340 | ||
|
|
9c0d11ecc9 | ||
|
|
1005fd7b06 | ||
|
|
57e1e037b6 | ||
|
|
64c8827cf3 | ||
|
|
b2978efbff | ||
|
|
c285bf2f37 | ||
|
|
27383a4b3d | ||
|
|
2101e324f9 | ||
|
|
fe77d1a710 | ||
|
|
3008e1be08 | ||
|
|
17dbb24f7c | ||
|
|
7bd015861d | ||
|
|
a940979ff7 | ||
|
|
740d5bf6cd | ||
|
|
a5d45b237d | ||
|
|
a9cb96f146 | ||
|
|
463a61e62e | ||
|
|
93e252c4a3 | ||
|
|
f84a7266bc | ||
|
|
c9b40083fc | ||
|
|
f233d9a909 | ||
|
|
77fdc17d70 | ||
|
|
7db124774a | ||
|
|
223b75ee91 | ||
|
|
d71199920f | ||
|
|
c38c4d9d36 | ||
|
|
9f78acfee9 | ||
|
|
b798554a20 | ||
|
|
3f2e9e3546 | ||
|
|
49d2b27a68 | ||
|
|
3dcd61d3d7 | ||
|
|
678951f635 | ||
|
|
e7bd3ba22d | ||
|
|
bc09803628 | ||
|
|
e7f5acdfa6 | ||
|
|
6d392776b0 | ||
|
|
1f54129c4e | ||
|
|
0210c7076d | ||
|
|
763342016c | ||
|
|
af33a00847 | ||
|
|
a8ea1817ab | ||
|
|
bb62af5b3d | ||
|
|
676ce47754 | ||
|
|
8dea63d30f | ||
|
|
ce5ea07411 | ||
|
|
3388e19489 | ||
|
|
3e6bb77228 | ||
|
|
8d6f1f9768 | ||
|
|
dddf63ebc3 | ||
|
|
10fc3610c4 | ||
|
|
76b1f43e81 | ||
|
|
d8bb85d963 | ||
|
|
f5a669f314 | ||
|
|
8b9028bbe7 | ||
|
|
d1019a6434 | ||
|
|
9a7b81fb72 | ||
|
|
739827ef1c | ||
|
|
ed249a2c53 | ||
|
|
47b5fb138c | ||
|
|
f2c1de783c | ||
|
|
9a06700017 | ||
|
|
fa1290f40e | ||
|
|
38d460ed6e | ||
|
|
ada5728c72 | ||
|
|
bc13c7d246 | ||
|
|
672d5ad98b | ||
|
|
11f08dacc9 | ||
|
|
66803586ef | ||
|
|
1ff1e86deb | ||
|
|
4baedfc578 | ||
|
|
a375657092 | ||
|
|
dbb19f6ace | ||
|
|
56c41b7522 | ||
|
|
a481f42630 | ||
|
|
85e2c7e14d | ||
|
|
1705b439b1 | ||
|
|
de837c15a5 | ||
|
|
534760398c | ||
|
|
fd96f1014b | ||
|
|
cc2218b401 | ||
|
|
0f377a04e5 | ||
|
|
2fbc578cfa | ||
|
|
ef389603dd | ||
|
|
f0614e7cf0 | ||
|
|
b722ce2f10 | ||
|
|
19e9c88faf | ||
|
|
ee0cb17608 | ||
|
|
b918afb693 | ||
|
|
7880896f0d | ||
|
|
fd8d926fc5 | ||
|
|
ce202c3b1c | ||
|
|
ff4827ffb1 | ||
|
|
93c9055591 | ||
|
|
03f9cd95b4 | ||
|
|
fb7a3fe8d6 | ||
|
|
ca54afd701 | ||
|
|
e3e04b99f2 | ||
|
|
9a88a9c4ce | ||
|
|
1d0dc74f91 | ||
|
|
46d15b5e4d | ||
|
|
3e9664baca | ||
|
|
7b41ea61b2 | ||
|
|
135d16fbb8 | ||
|
|
231cdd0efb | ||
|
|
4d9f0606be | ||
|
|
c1d136fea3 | ||
|
|
9f8c331760 | ||
|
|
4f44841045 | ||
|
|
d4d060acd5 | ||
|
|
8f1068c02d | ||
|
|
e12bdd591a | ||
|
|
7a507583d9 | ||
|
|
085760992d | ||
|
|
3c9177fdc0 | ||
|
|
119d594788 | ||
|
|
4667c4b35b | ||
|
|
8f421bdd7a | ||
|
|
00c9a788cc | ||
|
|
23774f997e | ||
|
|
286a793c12 | ||
|
|
d0faad0db3 | ||
|
|
9b9bf8786f | ||
|
|
b7f3667ce2 | ||
|
|
fe78cd4082 | ||
|
|
40266faaab | ||
|
|
ad773511c5 | ||
|
|
3f32f9811e | ||
|
|
094d6f80dd | ||
|
|
88b92d4225 | ||
|
|
b7885dbb73 | ||
|
|
cca2a652d1 | ||
|
|
eb06832b37 | ||
|
|
dccaab3d79 | ||
|
|
bc39d5bec6 | ||
|
|
edbc5a62b2 | ||
|
|
6eb9eba59b | ||
|
|
04bba5ea42 | ||
|
|
2cf0f90780 | ||
|
|
3bd9d81b29 | ||
|
|
ae5634a8be | ||
|
|
2aed2a41f7 | ||
|
|
21b37964eb | ||
|
|
950d2d59c1 | ||
|
|
48872b0369 | ||
|
|
a014c4f341 | ||
|
|
8e2938c963 | ||
|
|
9f38e95a2f | ||
|
|
f32e85ae51 | ||
|
|
b528a9ce90 | ||
|
|
9fbad5bb0f | ||
|
|
6ea3654868 | ||
|
|
ba27b9ee2a | ||
|
|
38eaa1035b | ||
|
|
712c9efbf6 | ||
|
|
48c1a295a2 | ||
|
|
a7b2fc8f57 | ||
|
|
d15c466f95 | ||
|
|
1ee42f1391 | ||
|
|
ce772bfab9 | ||
|
|
240062a183 | ||
|
|
8806f2d5ed | ||
|
|
fa9eb76a5d | ||
|
|
b59127a838 | ||
|
|
d14a8040d4 | ||
|
|
ae029fcced | ||
|
|
7b04ed07ba | ||
|
|
5410dd5441 | ||
|
|
be61bd6ff5 | ||
|
|
74a211cfd3 | ||
|
|
bb41ca86fa | ||
|
|
53803821de | ||
|
|
b5811b7c9c | ||
|
|
70a45c44e8 | ||
|
|
d3b515cea5 | ||
|
|
deb5160181 | ||
|
|
16da6651a1 | ||
|
|
cf74123830 | ||
|
|
ce8277b47e | ||
|
|
33fdeaf3f1 | ||
|
|
2a304d7a75 | ||
|
|
5c095400de | ||
|
|
2f29765e7f | ||
|
|
2d1fe38d84 | ||
|
|
33265467f9 | ||
|
|
5263551a2d | ||
|
|
d945b53ff7 | ||
|
|
4047a32128 | ||
|
|
a509776588 | ||
|
|
d79afd4084 | ||
|
|
cc4051eec0 | ||
|
|
3854931aea | ||
|
|
2aa36209eb | ||
|
|
211eaa284c | ||
|
|
d9e8895a96 | ||
|
|
b6b4ad8e28 | ||
|
|
0dd905c959 | ||
|
|
e10f20bc23 | ||
|
|
3dd11d9ea8 | ||
|
|
98e33ee3fb | ||
|
|
06cbe3cfc6 | ||
|
|
e1c2b41265 | ||
|
|
caff31df19 | ||
|
|
e6b93dc24e | ||
|
|
fc32787c1b | ||
|
|
957904933b | ||
|
|
fbdcc45255 | ||
|
|
dd0fdd846d | ||
|
|
a5b1b52903 | ||
|
|
c9526e859e | ||
|
|
f439716b75 | ||
|
|
b3fa71fbd8 | ||
|
|
212cf8efbd | ||
|
|
caecbcbeac | ||
|
|
4b5bfa779a | ||
|
|
f6667f94cb | ||
|
|
1b711b955d | ||
|
|
f140620043 | ||
|
|
c6746181a3 | ||
|
|
1b79673845 | ||
|
|
b19b7b6111 | ||
|
|
f50e7ce76c | ||
|
|
c392ccaa47 | ||
|
|
9532bb577a | ||
|
|
d02d7bc560 | ||
|
|
84eab461c8 | ||
|
|
81d0333067 | ||
|
|
2284f845b0 | ||
|
|
8153c5f1e6 | ||
|
|
4829f27b76 | ||
|
|
db1d66859f | ||
|
|
cba06012ac | ||
|
|
892a182975 | ||
|
|
25b97e522d | ||
|
|
b9752d719c | ||
|
|
3716aa848e | ||
|
|
8f794f2095 | ||
|
|
744b75f881 | ||
|
|
b756cb3e49 | ||
|
|
96985b1373 | ||
|
|
ffea7daec3 | ||
|
|
2a6078f961 | ||
|
|
9255c7148a | ||
|
|
aa7642a444 | ||
|
|
336361b2f2 | ||
|
|
67f627c8fb | ||
|
|
409362c127 | ||
|
|
e6a3c09017 | ||
|
|
4791d0f035 | ||
|
|
91d16fc049 | ||
|
|
d01f27f411 | ||
|
|
bcfe4993e5 | ||
|
|
555d6d4e62 | ||
|
|
d6ac039b65 | ||
|
|
de43527f94 | ||
|
|
c5e5ae4c95 | ||
|
|
1bde35e596 | ||
|
|
ac38b576f9 | ||
|
|
62ad12d0d0 | ||
|
|
c0de37ab18 | ||
|
|
c1ee6f0eef | ||
|
|
379a7e1288 | ||
|
|
adbb0a8d5b | ||
|
|
64a82a1c79 | ||
|
|
bddbbcb98c | ||
|
|
2444e830a9 | ||
|
|
8810c11bc9 | ||
|
|
7404216241 | ||
|
|
bab3b70e3a | ||
|
|
ecb77e9db3 | ||
|
|
cf844941d4 | ||
|
|
d7bf7091c3 | ||
|
|
7078dd01e8 | ||
|
|
d53bfae273 | ||
|
|
2f6d0a6408 | ||
|
|
151bf52649 | ||
|
|
30f4d0fcd4 | ||
|
|
5ccf3e6f30 | ||
|
|
7737ffb11c | ||
|
|
dad2660a38 | ||
|
|
c496ba6505 | ||
|
|
c3ef41f620 | ||
|
|
87e88078c9 | ||
|
|
a2a993d995 | ||
|
|
2173bdb821 | ||
|
|
2da6f01c15 | ||
|
|
4a52855899 | ||
|
|
611d4107a4 | ||
|
|
3b6defcf1f | ||
|
|
8ab1d489f3 | ||
|
|
89d839e541 | ||
|
|
abc0a8faba | ||
|
|
5555765cfc | ||
|
|
cff16b062b | ||
|
|
e70d5d470c | ||
|
|
4353823306 | ||
|
|
df0bc5081c | ||
|
|
338f4df54b | ||
|
|
3f381784f2 | ||
|
|
ec71df6fec | ||
|
|
91f91b80f1 | ||
|
|
3d7f755674 | ||
|
|
0a7495e680 | ||
|
|
5a88b2ce7f | ||
|
|
3145a85583 | ||
|
|
2e0f273008 | ||
|
|
d051e899a5 | ||
|
|
9cf08836ef | ||
|
|
53126ceada | ||
|
|
94076245df | ||
|
|
74ad2cd76f | ||
|
|
13c629fb78 | ||
|
|
39bd9b111b | ||
|
|
4485b8edca | ||
|
|
657d42e879 | ||
|
|
595aa1d452 | ||
|
|
98a8099da9 | ||
|
|
b400353c71 | ||
|
|
a61272a6f0 | ||
|
|
0c1316cda8 | ||
|
|
56a295f78c | ||
|
|
29db9c6325 | ||
|
|
2037476008 | ||
|
|
1c9b36618e | ||
|
|
bbd8badaef | ||
|
|
b690258518 | ||
|
|
4757ce4c2a | ||
|
|
1e669ab315 | ||
|
|
7474440d3b | ||
|
|
f88f7c0fdc | ||
|
|
496c368528 | ||
|
|
dccc50f6f6 | ||
|
|
7ea71a9eb9 | ||
|
|
31a862a6be | ||
|
|
91df257b53 | ||
|
|
e92d3bd1f7 | ||
|
|
14e01d6316 | ||
|
|
1760b96368 | ||
|
|
9af1d63b4d | ||
|
|
33c1d2e921 | ||
|
|
ad0343d8cb | ||
|
|
9ee3af7efc | ||
|
|
cbabdf2fca | ||
|
|
1da5fd8226 | ||
|
|
61a483a654 | ||
|
|
c38be06531 | ||
|
|
1349a52626 | ||
|
|
219fe72359 | ||
|
|
d4d82dbb70 | ||
|
|
70fb31b5d6 | ||
|
|
1f4968289c | ||
|
|
d67ce9e140 | ||
|
|
0bad3977df | ||
|
|
153e55c20e | ||
|
|
44bf9c9a6a | ||
|
|
82e6b820b8 | ||
|
|
43f149526d | ||
|
|
33c8e4de33 | ||
|
|
13c254fc05 | ||
|
|
9cad26be32 | ||
|
|
38617213f0 | ||
|
|
08f36dd093 | ||
|
|
3b05fd4d07 | ||
|
|
ba313ac84a | ||
|
|
1cc1333599 | ||
|
|
cc865749ae | ||
|
|
43db8f8d5d | ||
|
|
30a23a1941 | ||
|
|
8679d45917 | ||
|
|
e184f77109 | ||
|
|
8263e62b00 | ||
|
|
c67a03727b | ||
|
|
dbaa4cdcdf | ||
|
|
5f064e2221 | ||
|
|
c935f8a327 | ||
|
|
d1c5b3ae74 | ||
|
|
569e328cc0 | ||
|
|
cca5aec0ef | ||
|
|
50b50039d9 | ||
|
|
8689b4ed82 | ||
|
|
3d9fc7d6f3 | ||
|
|
c21440536d | ||
|
|
ab315e7a81 | ||
|
|
80b2de9e6a | ||
|
|
8b3cf53e24 | ||
|
|
508d1808b0 | ||
|
|
f91df163e2 | ||
|
|
f961311436 | ||
|
|
1bbf977577 | ||
|
|
4dcb36aba4 | ||
|
|
f56b21ae2c | ||
|
|
9e15c83673 | ||
|
|
b7aab9ba59 | ||
|
|
89373761c8 | ||
|
|
ed7e365ae5 | ||
|
|
5971da2c72 | ||
|
|
455498f206 | ||
|
|
c786636afb | ||
|
|
e1d3a6c552 | ||
|
|
df2292020b | ||
|
|
5b224d58f7 | ||
|
|
6204955347 | ||
|
|
9d2ef05c5d | ||
|
|
ceb808d26f | ||
|
|
c5f4f2efb6 | ||
|
|
69d4847975 | ||
|
|
293f6d2795 | ||
|
|
a4666f63ad | ||
|
|
b8d4969117 | ||
|
|
22a22a735f | ||
|
|
62136c056a | ||
|
|
12c47e0c98 | ||
|
|
75628a5f4c | ||
|
|
bafe5d15b1 | ||
|
|
b7c64fe8e2 | ||
|
|
b0286fa127 | ||
|
|
1839702cb4 | ||
|
|
df38eb49ab | ||
|
|
25e7bf021a | ||
|
|
7e8296f478 | ||
|
|
2b3c39e402 | ||
|
|
5fdebf9bbf | ||
|
|
6b0d969b2a | ||
|
|
2938b4dcca | ||
|
|
6163b733e1 | ||
|
|
e88fd2edfd | ||
|
|
0e5f39a5ac | ||
|
|
855b16ce14 | ||
|
|
9968be55ed | ||
|
|
6a8bd0c509 | ||
|
|
221edf4030 | ||
|
|
0ba260e397 | ||
|
|
c8b01f33a6 | ||
|
|
b9391b1b9f | ||
|
|
23cc7ddc50 | ||
|
|
3e3c78a6b0 | ||
|
|
5706764885 | ||
|
|
80ae7206a8 | ||
|
|
b4e87e638e | ||
|
|
3e01ff2783 | ||
|
|
65efacd0e0 | ||
|
|
a7563dc6a1 | ||
|
|
967e2decd2 | ||
|
|
c08704cee7 | ||
|
|
018cf39316 | ||
|
|
0c01a4c2a6 | ||
|
|
644186e920 | ||
|
|
f61d828c86 | ||
|
|
a0e40bad1d | ||
|
|
dd7629ea09 | ||
|
|
23f660cf98 | ||
|
|
a5f8e7a96c | ||
|
|
766dedb628 | ||
|
|
2266a1863f | ||
|
|
5714c8c9cc | ||
|
|
4f860f79ff | ||
|
|
f07e5c1fe4 | ||
|
|
ec85dfe0f8 | ||
|
|
5938cde11b | ||
|
|
9969361b51 | ||
|
|
a255385e3a | ||
|
|
dab4a2c893 | ||
|
|
f63e20ebcc | ||
|
|
af8cfa90d9 | ||
|
|
2a08d6d1d4 | ||
|
|
55bf692bff | ||
|
|
998e7b1075 | ||
|
|
81fe045714 | ||
|
|
0443d00ff1 | ||
|
|
91ee025d5b | ||
|
|
6666c39346 | ||
|
|
c70bab7531 | ||
|
|
1cd308d640 | ||
|
|
201ffbd04a | ||
|
|
2825ad9dd2 | ||
|
|
a454a1b4ea | ||
|
|
8d8047883e | ||
|
|
77deadd3af | ||
|
|
8a8e6ebba2 | ||
|
|
f6d171ffe3 | ||
|
|
615e18f5b2 | ||
|
|
6ee83f699b | ||
|
|
bc35ccd174 | ||
|
|
36944e1009 | ||
|
|
ddaf2002c9 | ||
|
|
e6691aa04b | ||
|
|
76a9a86fd3 | ||
|
|
bd21736e8b | ||
|
|
d6ffc99052 | ||
|
|
fe16d296b0 | ||
|
|
df26b73b8e | ||
|
|
53b97b146d | ||
|
|
b6240c9188 | ||
|
|
a22729a557 | ||
|
|
414f903cdc | ||
|
|
ca70dc4540 | ||
|
|
862aa06e5e | ||
|
|
7ca9be034f | ||
|
|
cf8aee096f | ||
|
|
c756f76802 | ||
|
|
9d8a028e8c | ||
|
|
aad91330fe | ||
|
|
98419e0667 | ||
|
|
6a9a4b4534 | ||
|
|
cb5f0bdba9 | ||
|
|
667b33dd3b | ||
|
|
ebc9274be0 | ||
|
|
a68258339d | ||
|
|
b20b23dfc6 | ||
|
|
d693041149 | ||
|
|
c2ff8876f9 | ||
|
|
b138a87f43 | ||
|
|
242e2dccc3 | ||
|
|
c4aba47dd0 | ||
|
|
7368cf8e7d | ||
|
|
1bfae5bf8e | ||
|
|
f836fe3836 | ||
|
|
4910a31f6d | ||
|
|
f3084ee2e5 | ||
|
|
0c23d3fc84 | ||
|
|
3a8e41a67b | ||
|
|
fcfabb26a5 | ||
|
|
8f02f8dcd7 | ||
|
|
5c0264d689 | ||
|
|
a98b77c164 | ||
|
|
c813db8fc2 | ||
|
|
fd5b8b72da | ||
|
|
9680fd6d78 | ||
|
|
0673d13518 | ||
|
|
90fe4b106b | ||
|
|
dc3f0e067d | ||
|
|
9a8e6ad014 | ||
|
|
26596ce7fa | ||
|
|
76dd9b2b51 | ||
|
|
56aadd7fe2 | ||
|
|
3b36de573e | ||
|
|
f27625f005 | ||
|
|
4464004362 | ||
|
|
e35cf0f623 | ||
|
|
4fe4c30e7a | ||
|
|
a353bfdd9f | ||
|
|
5191057d9d | ||
|
|
338a60bb41 | ||
|
|
27c3c1d7c8 | ||
|
|
6f7d7089b4 | ||
|
|
6f355c6736 | ||
|
|
6fc46af8ec | ||
|
|
8d8b5e4f75 | ||
|
|
5d3bced5ea | ||
|
|
b46dce0bad | ||
|
|
515e37b6dd | ||
|
|
d2c065789c | ||
|
|
3ce0dc59f2 | ||
|
|
38a3da532f | ||
|
|
6612d8dd5e | ||
|
|
66f69e766e | ||
|
|
693215716b | ||
|
|
ee6b9b78ec | ||
|
|
7612c21f55 | ||
|
|
13fb57bbb1 | ||
|
|
6e1cf248d4 | ||
|
|
51c105702f | ||
|
|
df36a8eadf | ||
|
|
196a9ed59f | ||
|
|
39a0de68bd | ||
|
|
585db87274 | ||
|
|
82b887a4cf | ||
|
|
1fe04f89ef | ||
|
|
772dbb1e39 | ||
|
|
447ba5f1c2 | ||
|
|
31b6a04e4c | ||
|
|
69b7c00a77 | ||
|
|
715d2c778f | ||
|
|
3e5e7fd6c9 | ||
|
|
aae2e872b4 | ||
|
|
acb8050a30 | ||
|
|
fcbffbdbc0 | ||
|
|
25b58310e3 | ||
|
|
98d420200e | ||
|
|
7cfbf3a394 | ||
|
|
5b3fbccab9 | ||
|
|
12707adac8 | ||
|
|
dcbed38b33 | ||
|
|
32a8865a27 | ||
|
|
b2885b7103 | ||
|
|
aefd177b04 | ||
|
|
55f1d8a269 | ||
|
|
a50c127904 | ||
|
|
4b1dcc2eeb | ||
|
|
c98e34e4d0 | ||
|
|
af0b84ccc8 | ||
|
|
7833c45fbe | ||
|
|
a18f562913 | ||
|
|
30a98e4d67 | ||
|
|
0bdd6d6240 | ||
|
|
0451225c19 | ||
|
|
a53c157db0 | ||
|
|
4a3e707402 | ||
|
|
9b63f59016 | ||
|
|
0534cd9cd4 | ||
|
|
61fce72a11 | ||
|
|
987f2733c7 | ||
|
|
83261b79b5 | ||
|
|
e01fddc578 | ||
|
|
ee4a32e992 | ||
|
|
96dfad5022 | ||
|
|
677833ce6f | ||
|
|
65bcd16be2 | ||
|
|
ad560a286a | ||
|
|
125f27ac37 | ||
|
|
e653f43732 | ||
|
|
05c7e09e71 | ||
|
|
505c1d56e8 | ||
|
|
1e553159d5 | ||
|
|
d3903d94e9 | ||
|
|
3596210e02 | ||
|
|
08396b4bce | ||
|
|
728435e7d6 | ||
|
|
cc4a92b13c | ||
|
|
46f1d17c74 | ||
|
|
2f5ea9e61a | ||
|
|
f2489d9dda | ||
|
|
3fcb4697f6 | ||
|
|
ecefcc9ca8 | ||
|
|
eb6aa5fefe | ||
|
|
09bc2d0fd1 | ||
|
|
bec3088f85 | ||
|
|
29eee32ac2 | ||
|
|
682b6216df | ||
|
|
3a0d493d91 | ||
|
|
cd8a0133fa | ||
|
|
0404539edb | ||
|
|
c1996c78c1 | ||
|
|
e3ba8561fa | ||
|
|
7f347698e3 | ||
|
|
dd19fa9ff3 | ||
|
|
aa58f9bd9b | ||
|
|
bbca70a0b7 | ||
|
|
c22ad12bab | ||
|
|
7657313740 | ||
|
|
7230aa891c | ||
|
|
4eb0e65693 | ||
|
|
4567c6a2b2 | ||
|
|
b16abb3816 | ||
|
|
f17353e3e6 | ||
|
|
d2b88f2715 | ||
|
|
1b63a219f4 | ||
|
|
fef8e50689 | ||
|
|
f938545687 | ||
|
|
ba9d152aa5 | ||
|
|
09f29570f2 | ||
|
|
9ba45d824a | ||
|
|
b4402bd821 | ||
|
|
d16142f90f | ||
|
|
8fecd9c14e | ||
|
|
82b137ef2f | ||
|
|
556dcd2c6b | ||
|
|
7c697c1058 | ||
|
|
1d1741b23a | ||
|
|
60bd9e8406 | ||
|
|
b4ff865b44 | ||
|
|
9f5e46965b | ||
|
|
a4dbbefaff | ||
|
|
208a09745d | ||
|
|
7eaa3adedf | ||
|
|
4bb7d3da0e | ||
|
|
0f350ba890 | ||
|
|
c9203a6106 | ||
|
|
e225bf59ff | ||
|
|
b7850faba7 | ||
|
|
49b8846567 | ||
|
|
550536474f | ||
|
|
5036244ce8 | ||
|
|
a07cc8dbef | ||
|
|
36cbc6db24 | ||
|
|
4c020b4d4a | ||
|
|
dbc5543cbb | ||
|
|
f1b4aeba66 | ||
|
|
d7c1168c6a | ||
|
|
878741502a | ||
|
|
4fa1638301 | ||
|
|
9156640b60 | ||
|
|
d3636ff832 | ||
|
|
a3a676e0e7 | ||
|
|
ba7ff96faf | ||
|
|
015b906069 | ||
|
|
5dd32680b0 | ||
|
|
47effdc025 | ||
|
|
de3d3b11f4 | ||
|
|
89914a541f | ||
|
|
ab61a6d85d | ||
|
|
45b164f62c | ||
|
|
027e0e92e6 | ||
|
|
86d831b916 | ||
|
|
889b5d3183 | ||
|
|
b2447e3538 | ||
|
|
0b18c25d93 | ||
|
|
650524b955 | ||
|
|
aeafdc1f45 | ||
|
|
db98a6e362 | ||
|
|
a2c309a5c5 | ||
|
|
07d41de74c | ||
|
|
24bd35b4ce | ||
|
|
4d11bf8d50 | ||
|
|
cb6277aa8a | ||
|
|
2bcd43c683 | ||
|
|
c315112a3b | ||
|
|
2b241eb1f6 | ||
|
|
356ea897cc | ||
|
|
bada89a224 | ||
|
|
4d9f41b119 | ||
|
|
ddd68fbead | ||
|
|
e3c4ab0cc7 | ||
|
|
d18e491f68 | ||
|
|
669a834981 | ||
|
|
a9907bef99 | ||
|
|
eebb5e9fff | ||
|
|
e055b89d28 | ||
|
|
645dd27604 | ||
|
|
ef2d61fea8 | ||
|
|
52586b1039 | ||
|
|
1022b88a66 | ||
|
|
6169c0a51b | ||
|
|
2036608423 | ||
|
|
78afe75b08 | ||
|
|
cf3f463929 | ||
|
|
99ca06ca46 | ||
|
|
dc1e12dcd4 | ||
|
|
60bf9c9f33 | ||
|
|
6422b9ddc5 | ||
|
|
19ef399ea7 | ||
|
|
0c26aa13ca | ||
|
|
85dbcda150 | ||
|
|
1f7c9da554 | ||
|
|
4ff472b907 | ||
|
|
9f561f2206 | ||
|
|
3405ead1e0 | ||
|
|
6ff1583c1b | ||
|
|
1e9e21a171 | ||
|
|
6078585381 | ||
|
|
ac627fd1ce | ||
|
|
8c56e31134 | ||
|
|
d60d59a5f3 | ||
|
|
7a5ea681fb | ||
|
|
a520b3002c | ||
|
|
3c70ae1803 | ||
|
|
99de816a1b | ||
|
|
81735b46d9 | ||
|
|
0046c4e7a7 | ||
|
|
adfb9bf20c | ||
|
|
90b94ead12 | ||
|
|
d7054cd28a | ||
|
|
366c1ac15b | ||
|
|
6d0f09f478 | ||
|
|
c3e385c108 | ||
|
|
a519be8d4b | ||
|
|
8c87dda195 | ||
|
|
ccd1386070 | ||
|
|
8fbaa6d9a5 | ||
|
|
44cfa55843 | ||
|
|
116bd314cb | ||
|
|
aa75b31db5 | ||
|
|
41ba2b568b | ||
|
|
d0b869e46a | ||
|
|
0cc80ccfd5 | ||
|
|
25f231cf06 | ||
|
|
0cab341e1d | ||
|
|
344a9e9afd | ||
|
|
7836e7aa1c | ||
|
|
6f18186bfd | ||
|
|
48e9f116ae | ||
|
|
f58a70c168 | ||
|
|
0ba316f102 | ||
|
|
6b89c0d4b7 | ||
|
|
417724efe2 | ||
|
|
6f408f68d2 | ||
|
|
c33770c02d | ||
|
|
50800e33d5 | ||
|
|
5d6fe796bd | ||
|
|
fcec6691f0 | ||
|
|
e27d027155 | ||
|
|
7c3de2fd93 | ||
|
|
bca0a4df9a | ||
|
|
2f471f0184 | ||
|
|
27cfeb1d39 | ||
|
|
86b96ede2a | ||
|
|
85e68a8333 | ||
|
|
d369de8399 | ||
|
|
9b4926aaff | ||
|
|
7f757ab616 | ||
|
|
5139e5f1b3 | ||
|
|
1117f1d46f | ||
|
|
597113646d | ||
|
|
4411fe2ba8 | ||
|
|
677aa84be3 | ||
|
|
0db22c5f81 | ||
|
|
ac31bfd6fd | ||
|
|
030c39073e | ||
|
|
1cc690e911 | ||
|
|
74b5f22838 | ||
|
|
dc6dea4033 | ||
|
|
1eeb2fa3f6 | ||
|
|
da31541bd8 | ||
|
|
d84134c75b | ||
|
|
9b2b0fef9c | ||
|
|
98b7a3a42d | ||
|
|
4e20ebd6a1 | ||
|
|
a0c848d4e4 | ||
|
|
07483cc165 | ||
|
|
7edbf8a441 | ||
|
|
3584e0c0d5 | ||
|
|
dd8d083795 | ||
|
|
3ed9256985 | ||
|
|
fb83719d7f | ||
|
|
ce79b62bc2 | ||
|
|
a9eaab6beb | ||
|
|
c8fc18e8bf | ||
|
|
90149c303e | ||
|
|
74460f70ef | ||
|
|
9aea6ae956 | ||
|
|
ccfbd505fe | ||
|
|
eff33684f7 | ||
|
|
74a388cca1 | ||
|
|
f0089472e7 | ||
|
|
71a302effe | ||
|
|
fedeab28c3 | ||
|
|
7be6791e70 | ||
|
|
0aa51a2f61 | ||
|
|
3ebce8dbd2 | ||
|
|
d19e372795 | ||
|
|
5cf8888976 | ||
|
|
d04520c321 | ||
|
|
cb90606c83 | ||
|
|
59b87cf7d6 | ||
|
|
87864f09f6 | ||
|
|
b64021ee5f | ||
|
|
ab1fd0cb37 | ||
|
|
78dd9d820d | ||
|
|
58ad831c72 | ||
|
|
cbf62b9262 | ||
|
|
30ad845f3d | ||
|
|
2a45ef0300 | ||
|
|
2264399b0d | ||
|
|
105a8edea1 | ||
|
|
e689bfb5d5 | ||
|
|
fc02343eff | ||
|
|
f3c52a515b | ||
|
|
3d367f3348 | ||
|
|
cbadf3d370 | ||
|
|
246b0c444b | ||
|
|
2cac4bfc15 | ||
|
|
01cbdc4e67 | ||
|
|
a16d914d34 | ||
|
|
08cabe9b83 | ||
|
|
bd6709cec6 | ||
|
|
f1ad4b0679 | ||
|
|
ca72d19691 | ||
|
|
ab031d673d | ||
|
|
022ebb0cfe | ||
|
|
74ae1c5bc1 | ||
|
|
30a3dda9d6 | ||
|
|
9a0535e354 | ||
|
|
21742c3f3d | ||
|
|
e8ea3c9a61 | ||
|
|
28f3125aaa | ||
|
|
f87dd7b127 | ||
|
|
0d142f6514 | ||
|
|
f43b7bb461 | ||
|
|
b4c3382990 | ||
|
|
1ed4b3f23b | ||
|
|
4c1fd82774 | ||
|
|
b6d26245fb | ||
|
|
5f102b3421 | ||
|
|
facd520931 | ||
|
|
ebaaff3590 | ||
|
|
e158835a05 | ||
|
|
7b5abc3fb1 | ||
|
|
3cf7668e34 | ||
|
|
6620dc9475 | ||
|
|
81b3b71dae | ||
|
|
c0c202e606 | ||
|
|
54a569be40 | ||
|
|
61e378c4e7 | ||
|
|
fdd612b824 | ||
|
|
6298eaeca5 | ||
|
|
bc40391b7d | ||
|
|
938b6b8253 | ||
|
|
89c61f2018 | ||
|
|
ee9d623d38 | ||
|
|
6d8356d208 | ||
|
|
1dee4b4ffc | ||
|
|
88faf5a53b | ||
|
|
44aeb6d6b8 | ||
|
|
fc479b2b07 | ||
|
|
83c6f7e7e6 | ||
|
|
1fc5d8c428 | ||
|
|
26ead4bf45 | ||
|
|
9dfb1a11b7 | ||
|
|
a355aeb17a | ||
|
|
8db2527c6e | ||
|
|
e2c017fdac | ||
|
|
2724a09e58 | ||
|
|
095c9791ca | ||
|
|
82f66834ef | ||
|
|
a13fa75d8e | ||
|
|
65cb8efd16 | ||
|
|
fb85d5d024 | ||
|
|
9830aa207c | ||
|
|
3750b0cff5 | ||
|
|
0161ebe484 | ||
|
|
a4577c427a | ||
|
|
a3fe619552 | ||
|
|
71af650760 | ||
|
|
7832d35668 | ||
|
|
98924e4703 | ||
|
|
18aa541ca2 | ||
|
|
a7034fa420 | ||
|
|
5bdcafff47 | ||
|
|
ab1f1a306b | ||
|
|
3320ab8334 | ||
|
|
9785e40b8d | ||
|
|
f05104af76 | ||
|
|
b068f21f6a | ||
|
|
93c7bca08f | ||
|
|
88153c7c0a | ||
|
|
e0c2d374ae | ||
|
|
07fc4866f0 | ||
|
|
e82303fd6a | ||
|
|
1f1d36f6a2 | ||
|
|
2076dda0b8 | ||
|
|
5db56b36f1 | ||
|
|
94237354dd | ||
|
|
0dc7abe013 | ||
|
|
b5366b1d8d | ||
|
|
143c8dcd7f | ||
|
|
a665206453 | ||
|
|
f619cac598 | ||
|
|
a63015442e | ||
|
|
d76b4afb8e | ||
|
|
a8cdd9e16a | ||
|
|
701ecff0ff | ||
|
|
8bf445b2de | ||
|
|
035a7b9a4b | ||
|
|
c666e8d25e | ||
|
|
f514e37978 | ||
|
|
2e01af0f78 | ||
|
|
a6cba2d0a0 | ||
|
|
51f08efaa7 | ||
|
|
f1684bf8e8 | ||
|
|
859feb81e5 | ||
|
|
db6d9e04af | ||
|
|
cc5cfb88d7 | ||
|
|
73bef5e3dd | ||
|
|
4801919b01 | ||
|
|
454024f957 | ||
|
|
0f5bdd4d31 | ||
|
|
63b0f0dab8 | ||
|
|
0b19387dae | ||
|
|
3c37764333 | ||
|
|
46a8d2e898 | ||
|
|
627f0e2bd8 | ||
|
|
dd5716ddf2 | ||
|
|
b2d1facd96 | ||
|
|
edb72cb70c | ||
|
|
a4b8377488 | ||
|
|
21784e94d6 | ||
|
|
92b0d014aa | ||
|
|
73687b7b75 | ||
|
|
752b1e95f4 | ||
|
|
3d2fd95af7 | ||
|
|
89c11a2b49 | ||
|
|
c1b2de936c | ||
|
|
a063d2d123 | ||
|
|
5a5e3bcf15 | ||
|
|
d8ad73e937 | ||
|
|
0d61a17152 | ||
|
|
1aac59f82a | ||
|
|
250e05a965 | ||
|
|
a1e5b8832b | ||
|
|
38c7ba315d | ||
|
|
65eb29503b | ||
|
|
93dfb5dd3e | ||
|
|
c61c4271a4 | ||
|
|
6a4a6a7cd7 | ||
|
|
c0c318e4f2 | ||
|
|
8b87ffaa8a | ||
|
|
7fb280ceac | ||
|
|
46f946145c | ||
|
|
41afe8c5cc | ||
|
|
e940293c33 | ||
|
|
7da75f41ed | ||
|
|
217d647a46 | ||
|
|
5f87ba68d4 | ||
|
|
74731a5277 | ||
|
|
e3a22cdc31 | ||
|
|
fc482406ec | ||
|
|
4ddd756d6f | ||
|
|
98c21e98b2 | ||
|
|
f54ead831f | ||
|
|
ceb2f0ad3b | ||
|
|
483ed8f767 | ||
|
|
8bb5dd5430 | ||
|
|
cb04b84c79 | ||
|
|
cd0fb0846d | ||
|
|
ea9b2c2122 | ||
|
|
d8284beb23 | ||
|
|
904e1e3d26 | ||
|
|
2d1152103f | ||
|
|
4b5d6de86b | ||
|
|
229e63b638 | ||
|
|
9deb134014 | ||
|
|
7e721ca048 | ||
|
|
ca66d52032 | ||
|
|
b1e9fe9505 | ||
|
|
cb15373ad7 | ||
|
|
b968c73d21 | ||
|
|
b2261b5d81 | ||
|
|
54de0d829b | ||
|
|
a53024cafc | ||
|
|
6d2609a232 | ||
|
|
0747a6d0de | ||
|
|
f7adcb5f6d | ||
|
|
14f24c2175 | ||
|
|
4021e88a31 | ||
|
|
188bedf8de | ||
|
|
ea001426af | ||
|
|
2d89192935 | ||
|
|
a23ed35f6c | ||
|
|
97a95f9648 | ||
|
|
fd8001a9fc | ||
|
|
83d9ea7348 | ||
|
|
55a8d6c86b | ||
|
|
43f8da7699 | ||
|
|
1ae5bf2b83 | ||
|
|
10e191fd12 | ||
|
|
d44bfe90f1 | ||
|
|
df2fa88e63 | ||
|
|
16fed9ef0c | ||
|
|
e6be10ffd2 | ||
|
|
3ca8ed66a7 | ||
|
|
814cff0c20 | ||
|
|
819b469880 | ||
|
|
cbee4d3d88 | ||
|
|
1c0b02e367 | ||
|
|
8aec65c054 | ||
|
|
c203ce7f86 | ||
|
|
970f49dcab | ||
|
|
517332e78d | ||
|
|
836dc9876b | ||
|
|
38770db19b | ||
|
|
2f02e8d33a | ||
|
|
73132bc254 | ||
|
|
025332edc2 | ||
|
|
8794fb71db | ||
|
|
e1e33e75e7 | ||
|
|
8c5fbd5fac | ||
|
|
d4de3cfa4d | ||
|
|
f86f01a3a1 | ||
|
|
3a557dcfbf | ||
|
|
6cee8f1b06 | ||
|
|
c1703845c3 | ||
|
|
1dc5603f73 | ||
|
|
3ae5569570 | ||
|
|
cac4a9743a | ||
|
|
8c9d9a7446 | ||
|
|
e548e7c29d | ||
|
|
a686391eca | ||
|
|
23948e99b3 | ||
|
|
3e547fa952 | ||
|
|
5ee1727f80 | ||
|
|
7541e002b2 | ||
|
|
85b4b2f924 | ||
|
|
e26dacf30a | ||
|
|
f3f3d6066b | ||
|
|
8d7075528f | ||
|
|
a427a93549 | ||
|
|
ad0268e239 | ||
|
|
a1b1b3dbb6 | ||
|
|
9a6f0e64f9 | ||
|
|
9d9979963f | ||
|
|
aa8b2d6a0f | ||
|
|
d3ebb18f40 | ||
|
|
70e3d0a613 | ||
|
|
a91ac41b93 | ||
|
|
9238b972c5 | ||
|
|
0d934e730e | ||
|
|
813347cf84 | ||
|
|
c7789daec0 | ||
|
|
bc1976011a | ||
|
|
79879bd201 | ||
|
|
6235861e64 | ||
|
|
1951e0db0f | ||
|
|
5d747f724e | ||
|
|
e7a56d5cd3 | ||
|
|
f6a54a50a0 | ||
|
|
7a170873aa | ||
|
|
0b01e3f5d7 | ||
|
|
925aaf0b87 | ||
|
|
19f2105b87 | ||
|
|
420af27f08 | ||
|
|
913c28917e | ||
|
|
1e40e734e6 | ||
|
|
aecf542126 | ||
|
|
8df2dd66ce | ||
|
|
16ae968d24 | ||
|
|
fc35a9169e | ||
|
|
7498f83833 | ||
|
|
9e1ee07d69 | ||
|
|
015231b11f | ||
|
|
32f1afbe36 | ||
|
|
69bebfd958 | ||
|
|
f1ac72c848 | ||
|
|
4db228b907 | ||
|
|
c15ac326cc | ||
|
|
05b5774827 | ||
|
|
6179cab877 | ||
|
|
2217d6396a | ||
|
|
06a4a356db | ||
|
|
fdd76da33d | ||
|
|
c4f39decc8 | ||
|
|
43e4bfe428 | ||
|
|
84f00f5058 | ||
|
|
b57e73a0f1 | ||
|
|
70950bbd97 | ||
|
|
f1ac130dc1 | ||
|
|
668c9d0762 | ||
|
|
b1ff52ca14 | ||
|
|
2513661467 | ||
|
|
cbbdace006 | ||
|
|
253989ecd9 | ||
|
|
13c49033ed | ||
|
|
a7298810d1 | ||
|
|
eb566e034f | ||
|
|
9b71212262 | ||
|
|
30b1b57506 | ||
|
|
eed8715e1d | ||
|
|
20971f7034 | ||
|
|
77aa055e8a | ||
|
|
2ab784440a | ||
|
|
9b85ecb85b | ||
|
|
3222924c3d | ||
|
|
fbfbbf6d6a | ||
|
|
1bb30a8c27 | ||
|
|
5811fa33bb | ||
|
|
954b885a08 | ||
|
|
48768cc5be | ||
|
|
6462e8dffc | ||
|
|
9ed869cce1 | ||
|
|
f8462cff92 | ||
|
|
37366ec3b0 | ||
|
|
6e12a33292 | ||
|
|
5c36ad06a1 | ||
|
|
194eccf925 | ||
|
|
11d4e63888 | ||
|
|
a49f494c4d | ||
|
|
6be1efd13d | ||
|
|
91c7e66f2b | ||
|
|
09131e3922 | ||
|
|
30c94b0324 | ||
|
|
8424655af9 | ||
|
|
bda4f3a7ae | ||
|
|
ba6d8a3195 | ||
|
|
bb17302084 | ||
|
|
ebd2d7773f | ||
|
|
0ac7913c6a | ||
|
|
abe2210c26 | ||
|
|
945d13541e | ||
|
|
41ef146dc3 | ||
|
|
fdb6ef8a85 | ||
|
|
0c00af776a | ||
|
|
ccb08dfa1d | ||
|
|
19a59cc53c | ||
|
|
e9b6cdd6e6 | ||
|
|
81ca0cb161 | ||
|
|
297f6d5122 | ||
|
|
1365f0d4c8 | ||
|
|
0aeca60aaa | ||
|
|
17bd91e33e | ||
|
|
5fb15b1934 | ||
|
|
3832329a6b | ||
|
|
df67b1da4d | ||
|
|
d0ff078e77 | ||
|
|
3255e384db | ||
|
|
4d964133e2 | ||
|
|
07d2794a16 | ||
|
|
b070c14a8b | ||
|
|
3bcc6c7e60 | ||
|
|
989626926c | ||
|
|
e2e30a64ab | ||
|
|
22a1304368 | ||
|
|
61600f8fa7 | ||
|
|
fa0a04236c | ||
|
|
bfcecbbce1 | ||
|
|
a0f6f18841 | ||
|
|
03ed2aae3a | ||
|
|
3d5c4847b6 | ||
|
|
cb17ef221b | ||
|
|
fade9ca3b6 | ||
|
|
3c966e637f | ||
|
|
e83c4f07ca | ||
|
|
10ede2cc0f | ||
|
|
4578411633 | ||
|
|
8b05f1f230 | ||
|
|
54668feaab | ||
|
|
d131024255 | ||
|
|
acab591378 | ||
|
|
c34291e3bf | ||
|
|
9adae653e9 | ||
|
|
763219611c | ||
|
|
aa464aa2f6 | ||
|
|
9cd05d1f1e | ||
|
|
7f49d463d6 | ||
|
|
a004bb07f1 | ||
|
|
8b0729af0f | ||
|
|
2f43f0393e | ||
|
|
706606627f | ||
|
|
5ff18f51b9 | ||
|
|
279f3bfdc0 | ||
|
|
97506a7e2a | ||
|
|
7709b70f97 | ||
|
|
86c3940537 | ||
|
|
bf4be80669 | ||
|
|
2214dc12c3 | ||
|
|
778ce8d808 | ||
|
|
8a66c81b9b | ||
|
|
63ec42f428 | ||
|
|
117160b27e | ||
|
|
edf3f86184 | ||
|
|
06439a2562 | ||
|
|
db741e75a2 | ||
|
|
c47655f231 | ||
|
|
faa126882a | ||
|
|
12213445b5 | ||
|
|
7b8aa4af57 | ||
|
|
6206bd0e79 | ||
|
|
c58733ca15 | ||
|
|
6945bbdbc6 | ||
|
|
96e9929f2f | ||
|
|
a821b88a43 | ||
|
|
44c99a8822 | ||
|
|
5807993bbf | ||
|
|
4f708e8709 | ||
|
|
493ffe7a0f | ||
|
|
00990ed53e | ||
|
|
0dafd159a8 | ||
|
|
aa63dfbe39 | ||
|
|
aff69ecf39 | ||
|
|
4b7a57c9ed | ||
|
|
a8f84f7801 | ||
|
|
c66a960149 | ||
|
|
d8a41f22e9 | ||
|
|
0d9a4c6989 | ||
|
|
4a90b0c4c9 | ||
|
|
2e05f6018b | ||
|
|
80e6097ea6 | ||
|
|
b98846998b | ||
|
|
5f3eff8eae | ||
|
|
9b6b4f14d8 | ||
|
|
4a64bb9573 | ||
|
|
5cf0923e18 | ||
|
|
e9d1f676b3 | ||
|
|
333eb8667e | ||
|
|
6d1c983122 | ||
|
|
a55d4b6051 | ||
|
|
c8b4f9414c | ||
|
|
b697aa9646 | ||
|
|
c96400b6c7 | ||
|
|
c1a6b10d09 | ||
|
|
d56e400d44 | ||
|
|
f2b856c994 | ||
|
|
2bb9627d01 | ||
|
|
ed3428b7ed | ||
|
|
0bae9a1bff | ||
|
|
b55d30956d | ||
|
|
52b07672f8 | ||
|
|
29b9ccd261 | ||
|
|
f96fd9961d | ||
|
|
163a30d784 | ||
|
|
a14f21bf1d | ||
|
|
4194fc9bbd | ||
|
|
739a213d2e | ||
|
|
a1c81c009a | ||
|
|
19b92ae3f3 | ||
|
|
cea88a9e4e | ||
|
|
357e9f9572 | ||
|
|
9c0d92d957 | ||
|
|
8949903fbb | ||
|
|
6b3a4aac09 | ||
|
|
106ee05ba0 | ||
|
|
6c84a36b53 | ||
|
|
8215e3503d | ||
|
|
fa58fc3257 | ||
|
|
c728d88e11 | ||
|
|
086f1ef4a0 | ||
|
|
254e5c5d11 | ||
|
|
18528180d9 | ||
|
|
72e2e92f4c | ||
|
|
dd7ebec120 | ||
|
|
15826214f9 | ||
|
|
e166d2b14c | ||
|
|
40c1f7889f | ||
|
|
c8cfbfa605 | ||
|
|
20b9746c5d | ||
|
|
42f7caf1c2 | ||
|
|
f85a010a6b | ||
|
|
565df4e732 | ||
|
|
428514a07f | ||
|
|
ccab4a1994 | ||
|
|
328303d4d4 | ||
|
|
54f61e7dcc | ||
|
|
3fd75d1bcd | ||
|
|
8eab37593e | ||
|
|
27c647d6ce | ||
|
|
2a7f2a3a24 | ||
|
|
7d8bd97187 | ||
|
|
9d2b9e5bc6 | ||
|
|
52e7270e23 | ||
|
|
faf3cc8f71 | ||
|
|
b2cb8f846a | ||
|
|
b1729dbcdd | ||
|
|
f4abbafde7 | ||
|
|
b58160a191 | ||
|
|
a35098b110 | ||
|
|
218c57410c | ||
|
|
752c39d91d | ||
|
|
33703995ae | ||
|
|
f38a54227d | ||
|
|
70b159d145 | ||
|
|
3eff3aa4f8 | ||
|
|
5b515db71b | ||
|
|
52ab3c1584 | ||
|
|
a457566e91 | ||
|
|
c6be409609 | ||
|
|
327f62a255 | ||
|
|
b5f444d447 | ||
|
|
e84e9cd115 | ||
|
|
fededfbbbc | ||
|
|
0524829af6 | ||
|
|
e53cfc6a88 | ||
|
|
9b79f0244a | ||
|
|
fa00fce97c | ||
|
|
a163d5341a | ||
|
|
d067263f51 | ||
|
|
5fca75877d | ||
|
|
22c5467add | ||
|
|
17f5572bc9 | ||
|
|
9df6f601e0 | ||
|
|
885e57cb27 | ||
|
|
7824bb710d | ||
|
|
be3af7f93e | ||
|
|
981a3ba98e | ||
|
|
9a8c36b891 | ||
|
|
c4153a8dfc | ||
|
|
3b6b7f8f9b | ||
|
|
1c79cf9830 | ||
|
|
77d5caae90 | ||
|
|
75fed05d3e | ||
|
|
e82b70e739 | ||
|
|
9c7ee1e1c4 | ||
|
|
5c2f7f083c | ||
|
|
2a307ce33c | ||
|
|
b48e10d9e6 | ||
|
|
ebd147ff24 | ||
|
|
4ce9579099 | ||
|
|
1c59140f5f | ||
|
|
a8759dc7a6 | ||
|
|
5e672df6ae | ||
|
|
8266b7e951 | ||
|
|
ae961a192a | ||
|
|
669b1295ae | ||
|
|
dbc3e62cc0 | ||
|
|
73b7e6fde7 | ||
|
|
7c4b19c335 | ||
|
|
0ac89fb860 | ||
|
|
61e67e51e1 | ||
|
|
962a3eb3fa | ||
|
|
d5da55ed85 | ||
|
|
0e2a358da9 | ||
|
|
59dc9b445d | ||
|
|
f20e828ec2 | ||
|
|
bb7c064b23 | ||
|
|
c93e0932e8 | ||
|
|
8b111f28b0 | ||
|
|
bc8c8d2f87 | ||
|
|
5cb4b2a424 | ||
|
|
1f5f8382ae | ||
|
|
fb171edd45 | ||
|
|
0c62ae3f89 | ||
|
|
c78239d860 | ||
|
|
286c1ba336 | ||
|
|
88ae928ca3 | ||
|
|
9573ff3a3b | ||
|
|
b67ef90438 | ||
|
|
cc87f55e25 | ||
|
|
0d22b58172 | ||
|
|
e6bb780d24 | ||
|
|
c7c7017f0c | ||
|
|
60db97ae1d | ||
|
|
00befc04d0 | ||
|
|
6e6ef95ba6 | ||
|
|
e966752b86 | ||
|
|
229582c97c | ||
|
|
da30b4a786 | ||
|
|
616eeba6f2 | ||
|
|
e7aa51c70f | ||
|
|
18259d5559 | ||
|
|
e4d9099e19 | ||
|
|
d154dd6638 | ||
|
|
1539e51721 | ||
|
|
bd8c6cf862 | ||
|
|
f2ff06d675 | ||
|
|
55521be2cb | ||
|
|
802382e21f | ||
|
|
b7da704566 | ||
|
|
58a9254252 | ||
|
|
d2d8dd7f7f | ||
|
|
c157c43f7c | ||
|
|
eb60029245 | ||
|
|
3c657adc0a | ||
|
|
c67bd8b47b | ||
|
|
74460cd009 | ||
|
|
3e781ea446 | ||
|
|
11384637fb | ||
|
|
3810fd8d0d | ||
|
|
bd7cdd0b09 | ||
|
|
de66704253 | ||
|
|
2eda683a20 | ||
|
|
232918fb86 | ||
|
|
29abba3785 | ||
|
|
66b10275c5 | ||
|
|
f6eeb218b2 | ||
|
|
891f8dc19d | ||
|
|
1140d70893 | ||
|
|
eebf070d32 | ||
|
|
21a5be2364 | ||
|
|
6a1f458bb7 | ||
|
|
4d19321fd3 | ||
|
|
02c4901d89 | ||
|
|
7b5b1a9b6f | ||
|
|
0625c7f372 | ||
|
|
09177b53dd | ||
|
|
b6f0f20da2 | ||
|
|
c4497ee9e8 | ||
|
|
15a8142f6d | ||
|
|
dbba1e9b93 | ||
|
|
cb379c86c4 | ||
|
|
d4d39d0f90 | ||
|
|
7635df8cce | ||
|
|
272ec3fa73 | ||
|
|
89fdc0b588 | ||
|
|
ccc35e2647 | ||
|
|
7f97c7ea9a | ||
|
|
02b99be57e |
15
.gitignore
vendored
15
.gitignore
vendored
@@ -25,17 +25,29 @@ make.tmpl
|
|||||||
|
|
||||||
/autom4te.cache/
|
/autom4te.cache/
|
||||||
/autoscan.log
|
/autoscan.log
|
||||||
|
/build/
|
||||||
|
/config.cache
|
||||||
/config.log
|
/config.log
|
||||||
/config.status
|
/config.status
|
||||||
/configure.scan
|
/configure.scan
|
||||||
/cscope.out
|
/cscope.*
|
||||||
|
/html/
|
||||||
|
/reports/
|
||||||
/tags
|
/tags
|
||||||
/tmp/
|
/tmp/
|
||||||
|
|
||||||
|
coverity/coverity_model.xml
|
||||||
|
|
||||||
|
# gcov files:
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
|
|
||||||
tools/man-generator
|
tools/man-generator
|
||||||
tools/man-generator.c
|
tools/man-generator.c
|
||||||
|
|
||||||
|
test/.lib-dir-stamp
|
||||||
|
test/.tests-stamp
|
||||||
|
test/lib/dmsecuretest
|
||||||
test/lib/lvchange
|
test/lib/lvchange
|
||||||
test/lib/lvconvert
|
test/lib/lvconvert
|
||||||
test/lib/lvcreate
|
test/lib/lvcreate
|
||||||
@@ -60,6 +72,7 @@ test/lib/pvremove
|
|||||||
test/lib/pvresize
|
test/lib/pvresize
|
||||||
test/lib/pvs
|
test/lib/pvs
|
||||||
test/lib/pvscan
|
test/lib/pvscan
|
||||||
|
test/lib/securetest
|
||||||
test/lib/vgcfgbackup
|
test/lib/vgcfgbackup
|
||||||
test/lib/vgcfgrestore
|
test/lib/vgcfgrestore
|
||||||
test/lib/vgchange
|
test/lib/vgchange
|
||||||
|
|||||||
78
Makefile.in
78
Makefile.in
@@ -18,7 +18,7 @@ top_builddir = @top_builddir@
|
|||||||
abs_top_builddir = @abs_top_builddir@
|
abs_top_builddir = @abs_top_builddir@
|
||||||
abs_top_srcdir = @abs_top_srcdir@
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
|
||||||
SUBDIRS = conf daemons include lib libdaemon libdm man scripts device_mapper tools
|
SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
|
||||||
|
|
||||||
ifeq ("@UDEV_RULES@", "yes")
|
ifeq ("@UDEV_RULES@", "yes")
|
||||||
SUBDIRS += udev
|
SUBDIRS += udev
|
||||||
@@ -28,14 +28,6 @@ ifeq ("@INTL@", "yes")
|
|||||||
SUBDIRS += po
|
SUBDIRS += po
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ("@APPLIB@", "yes")
|
|
||||||
SUBDIRS += liblvm
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ("@PYTHON_BINDINGS@", "yes")
|
|
||||||
SUBDIRS += python
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(MAKECMDGOALS),clean)
|
ifeq ($(MAKECMDGOALS),clean)
|
||||||
SUBDIRS += test
|
SUBDIRS += test
|
||||||
endif
|
endif
|
||||||
@@ -43,7 +35,7 @@ endif
|
|||||||
ifeq ($(MAKECMDGOALS),distclean)
|
ifeq ($(MAKECMDGOALS),distclean)
|
||||||
SUBDIRS = conf include man test scripts \
|
SUBDIRS = conf include man test scripts \
|
||||||
libdaemon lib tools daemons libdm \
|
libdaemon lib tools daemons libdm \
|
||||||
udev po liblvm python device_mapper
|
udev po
|
||||||
tools.distclean: test.distclean
|
tools.distclean: test.distclean
|
||||||
endif
|
endif
|
||||||
DISTCLEAN_DIRS += lcov_reports*
|
DISTCLEAN_DIRS += lcov_reports*
|
||||||
@@ -51,23 +43,25 @@ DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
|
|||||||
|
|
||||||
include make.tmpl
|
include make.tmpl
|
||||||
|
|
||||||
|
include $(top_srcdir)/base/Makefile
|
||||||
|
include $(top_srcdir)/device_mapper/Makefile
|
||||||
|
include $(top_srcdir)/test/unit/Makefile
|
||||||
|
|
||||||
libdm: include
|
libdm: include
|
||||||
libdaemon: include
|
libdaemon: include
|
||||||
lib: libdm libdaemon
|
lib: libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET)
|
||||||
liblvm: lib
|
|
||||||
daemons: lib libdaemon tools
|
daemons: lib libdaemon tools
|
||||||
tools: lib libdaemon device-mapper
|
scripts: lib
|
||||||
|
tools: lib libdaemon
|
||||||
po: tools daemons
|
po: tools daemons
|
||||||
man: tools
|
man: tools
|
||||||
all_man: tools
|
all_man: tools
|
||||||
scripts: liblvm libdm
|
scripts: libdm
|
||||||
test: tools daemons
|
test: tools daemons
|
||||||
unit-test: lib
|
unit-test run-unit-test: test
|
||||||
run-unit-test: unit-test
|
|
||||||
|
|
||||||
lib.device-mapper: include.device-mapper
|
lib.device-mapper: include.device-mapper
|
||||||
libdm.device-mapper: include.device-mapper
|
libdm.device-mapper: include.device-mapper
|
||||||
liblvm.device-mapper: include.device-mapper
|
|
||||||
daemons.device-mapper: libdm.device-mapper
|
daemons.device-mapper: libdm.device-mapper
|
||||||
tools.device-mapper: libdm.device-mapper
|
tools.device-mapper: libdm.device-mapper
|
||||||
scripts.device-mapper: include.device-mapper
|
scripts.device-mapper: include.device-mapper
|
||||||
@@ -81,10 +75,6 @@ po.pofile: tools.pofile daemons.pofile
|
|||||||
pofile: po.pofile
|
pofile: po.pofile
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ("@PYTHON_BINDINGS@", "yes")
|
|
||||||
python: liblvm
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ("$(CFLOW_CMD)", "")
|
ifneq ("$(CFLOW_CMD)", "")
|
||||||
tools.cflow: libdm.cflow lib.cflow
|
tools.cflow: libdm.cflow lib.cflow
|
||||||
daemons.cflow: tools.cflow
|
daemons.cflow: tools.cflow
|
||||||
@@ -99,7 +89,7 @@ endif
|
|||||||
DISTCLEAN_TARGETS += cscope.out
|
DISTCLEAN_TARGETS += cscope.out
|
||||||
CLEAN_DIRS += autom4te.cache
|
CLEAN_DIRS += autom4te.cache
|
||||||
|
|
||||||
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit-test run-unit-test: test
|
check check_system check_cluster check_local check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock: test
|
||||||
$(MAKE) -C test $(@)
|
$(MAKE) -C test $(@)
|
||||||
|
|
||||||
conf.generate man.generate: tools
|
conf.generate man.generate: tools
|
||||||
@@ -161,27 +151,11 @@ install_systemd_units:
|
|||||||
install_all_man:
|
install_all_man:
|
||||||
$(MAKE) -C man install_all_man
|
$(MAKE) -C man install_all_man
|
||||||
|
|
||||||
ifeq ("@PYTHON_BINDINGS@", "yes")
|
|
||||||
install_python_bindings:
|
|
||||||
$(MAKE) -C liblvm/python install_python_bindings
|
|
||||||
endif
|
|
||||||
|
|
||||||
install_tmpfiles_configuration:
|
install_tmpfiles_configuration:
|
||||||
$(MAKE) -C scripts install_tmpfiles_configuration
|
$(MAKE) -C scripts install_tmpfiles_configuration
|
||||||
|
|
||||||
LCOV_TRACES = libdm.info lib.info liblvm.info tools.info \
|
|
||||||
libdaemon/client.info libdaemon/server.info \
|
|
||||||
test/unit.info \
|
|
||||||
daemons/clvmd.info \
|
|
||||||
daemons/dmeventd.info \
|
|
||||||
daemons/lvmetad.info \
|
|
||||||
daemons/lvmlockd.info \
|
|
||||||
daemons/lvmpolld.info
|
|
||||||
|
|
||||||
CLEAN_TARGETS += $(LCOV_TRACES)
|
|
||||||
|
|
||||||
ifneq ("$(LCOV)", "")
|
ifneq ("$(LCOV)", "")
|
||||||
.PHONY: lcov-reset lcov lcov-dated $(LCOV_TRACES)
|
.PHONY: lcov-reset lcov lcov-dated
|
||||||
|
|
||||||
ifeq ($(MAKECMDGOALS),lcov-dated)
|
ifeq ($(MAKECMDGOALS),lcov-dated)
|
||||||
LCOV_REPORTS_DIR := lcov_reports-$(shell date +%Y%m%d%k%M%S)
|
LCOV_REPORTS_DIR := lcov_reports-$(shell date +%Y%m%d%k%M%S)
|
||||||
@@ -191,30 +165,22 @@ LCOV_REPORTS_DIR := lcov_reports
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
lcov-reset:
|
lcov-reset:
|
||||||
$(LCOV) --zerocounters $(addprefix -d , $(basename $(LCOV_TRACES)))
|
$(LCOV) --zerocounters --directory $(top_builddir)
|
||||||
|
|
||||||
# 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)", "")
|
ifneq ("$(GENHTML)", "")
|
||||||
lcov: $(LCOV_TRACES)
|
lcov:
|
||||||
$(RM) -r $(LCOV_REPORTS_DIR)
|
$(RM) -rf $(LCOV_REPORTS_DIR)
|
||||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||||
for i in $(LCOV_TRACES); do \
|
$(LCOV) --capture --directory $(top_builddir) --ignore-errors source \
|
||||||
test -s $$i -a $$(wc -w <$$i) -ge 100 && lc="$$lc $$i"; \
|
--output-file $(LCOV_REPORTS_DIR)/out.info
|
||||||
done; \
|
-test ! -s $(LCOV_REPORTS_DIR)/out.info || \
|
||||||
test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
|
$(GENHTML) -o $(LCOV_REPORTS_DIR) --ignore-errors source \
|
||||||
-o $(LCOV_REPORTS_DIR) $$lc
|
$(LCOV_REPORTS_DIR)/out.info
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(shell which ctags),)
|
ifneq ($(shell which ctags 2>/dev/null),)
|
||||||
.PHONY: tags
|
.PHONY: tags
|
||||||
tags:
|
tags:
|
||||||
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
|
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
|
||||||
|
|||||||
10
README
10
README
@@ -1,5 +1,7 @@
|
|||||||
This tree contains the LVM2 and device-mapper tools and libraries.
|
This tree contains the LVM2 and device-mapper tools and libraries.
|
||||||
|
|
||||||
|
This is development branch, for stable 2.02 release see stable-2.02 branch.
|
||||||
|
|
||||||
For more information about LVM2 read the changelog in the WHATS_NEW file.
|
For more information about LVM2 read the changelog in the WHATS_NEW file.
|
||||||
Installation instructions are in INSTALL.
|
Installation instructions are in INSTALL.
|
||||||
|
|
||||||
@@ -7,7 +9,6 @@ There is no warranty - see COPYING and COPYING.LIB.
|
|||||||
|
|
||||||
Tarballs are available from:
|
Tarballs are available from:
|
||||||
ftp://sourceware.org/pub/lvm2/
|
ftp://sourceware.org/pub/lvm2/
|
||||||
ftp://sources.redhat.com/pub/lvm2/
|
|
||||||
https://github.com/lvmteam/lvm2/releases
|
https://github.com/lvmteam/lvm2/releases
|
||||||
|
|
||||||
The source code is stored in git:
|
The source code is stored in git:
|
||||||
@@ -42,6 +43,9 @@ Report upstream bugs at:
|
|||||||
or open issues at:
|
or open issues at:
|
||||||
https://github.com/lvmteam/lvm2/issues
|
https://github.com/lvmteam/lvm2/issues
|
||||||
|
|
||||||
The source code repository used until 7th June 2012 is accessible here:
|
The source code repository used until 7th June 2012 is accessible using CVS:
|
||||||
http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2.
|
|
||||||
|
|
||||||
|
cvs -d :pserver:cvs@sourceware.org:/cvs/lvm2 login cvs
|
||||||
|
cvs -d :pserver:cvs@sourceware.org:/cvs/lvm2 checkout LVM2
|
||||||
|
|
||||||
|
The password is cvs.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1.02.156-git (2018-12-07)
|
1.02.175-git (2020-08-09)
|
||||||
|
|||||||
225
WHATS_NEW
225
WHATS_NEW
@@ -1,70 +1,199 @@
|
|||||||
Version 2.02.184 -
|
Version 2.03.11 -
|
||||||
=====================================
|
==================================
|
||||||
Fix missing proper initialization of pv_list struct when adding pv.
|
Enhance error handling for fsadm and hanled correct fsck result.
|
||||||
|
Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values.
|
||||||
|
Support using BLKZEROOUT for clearing devices.
|
||||||
|
Support interruption when wipping LVs.
|
||||||
|
Support interruption for bcache waiting.
|
||||||
|
Fix bcache when device has too many failing writes.
|
||||||
|
Fix bcache waiting for IO completion with failing disks.
|
||||||
|
Configure use own python path name order to prefer using python3.
|
||||||
|
Add configure --enable-editline support as an alternative to readline.
|
||||||
|
Enhance reporting and error handling when creating thin volumes.
|
||||||
|
Enable vgsplit for VDO volumes.
|
||||||
|
Lvextend of vdo pool volumes ensure at least 1 new VDO slab is added.
|
||||||
|
Use revert_lv() on reload error path after vg_revert().
|
||||||
|
Configure --with-integrity enabled.
|
||||||
|
Restore lost signal blocking while VG lock is held.
|
||||||
|
Improve estimation of needed extents when creating thin-pool.
|
||||||
|
Use extra 1% when resizing thin-pool metadata LV with --use-policy.
|
||||||
|
Enhance --use-policy percentage rounding.
|
||||||
|
Configure --with-vdo and --with-writecache as internal segments.
|
||||||
|
Improving VDO man page examples.
|
||||||
|
Switch code base to use flexible array syntax.
|
||||||
|
Fix 64bit math when calculation cachevol size.
|
||||||
|
Preserve uint32_t for seqno handling.
|
||||||
|
Switch from mmap to plain read when loading regular files.
|
||||||
|
Update lvmvdo man page and better explain DISCARD usage.
|
||||||
|
|
||||||
Version 2.02.183 - 07th December 2018
|
Version 2.03.10 - 09th August 2020
|
||||||
=====================================
|
==================================
|
||||||
Avoid disabling lvmetad when repair does nothing.
|
Add writecache and integrity support to lvmdbusd.
|
||||||
Fix component detection for md version 0.90.
|
Generate unique cachevol name when default required from lvcreate.
|
||||||
Use sync io if async io_setup fails, or use_aio=0 is set in config.
|
Converting RAID1 volume to one with same number of legs now succeeds with a
|
||||||
Avoid opening devices to get block size by using existing open fd.
|
warning.
|
||||||
|
Fix conversion to raid from striped lagging type.
|
||||||
|
Fix conversion to 'mirrored' mirror log with larger regionsize.
|
||||||
|
Zero pool metadata on allocation (disable with allocation/zero_metadata=0).
|
||||||
|
Failure in zeroing or wiping will fail command (bypass with -Zn, -Wn).
|
||||||
|
Add lvcreate of new cache or writecache lv with single command.
|
||||||
|
Fix running out of free buffers for async writing for larger writes.
|
||||||
|
Add integrity with raid capability.
|
||||||
|
Fix support for lvconvert --repair used by foreign apps (i.e. Docker).
|
||||||
|
|
||||||
Version 2.02.182 - 30th October 2018
|
Version 2.03.09 - 26th March 2020
|
||||||
|
=================================
|
||||||
|
Fix formating of vdopool (vdo_slab_size_mb was smaller by 2 bits).
|
||||||
|
Fix showing of a dm kernel error when uncaching a volume with cachevol.
|
||||||
|
|
||||||
|
Version 2.03.08 - 11th February 2020
|
||||||
====================================
|
====================================
|
||||||
Fix possible write race between last metadata block and the first extent.
|
Prevent problematic snapshots of writecache volumes.
|
||||||
Fix filtering of md 1.0 devices so they are not seen as duplicate PVs.
|
Add error handling for failing allocation in _reserve_area().
|
||||||
|
Fix memleak in syncing of internal cache.
|
||||||
|
Fix pvck dump_current_text memleak.
|
||||||
|
Fix lvmlockd result code on error path for _query_lock_lv().
|
||||||
|
Update pvck man page and help output.
|
||||||
|
Reject invalid writecache high/low_watermark setting.
|
||||||
|
Report writecache status.
|
||||||
|
Accept more output lines from vdo_format.
|
||||||
|
Prohibit reshaping of stacked raid LVs.
|
||||||
|
Avoid running cache input arg validation when creating vdo pool.
|
||||||
|
Prevent raid reshaping of stacked volumes.
|
||||||
|
Added VDO lvmdbusd methods for enable/disable compression & dedupe.
|
||||||
|
Added VDO lvmdbusd method for converting LV to VDO pool.
|
||||||
|
|
||||||
|
Version 2.03.07 - 30th November 2019
|
||||||
|
====================================
|
||||||
|
Subcommand in vgck for repairing headers and metadata.
|
||||||
|
Ensure minimum required region size on striped RaidLV creation.
|
||||||
|
Fix resize of thin-pool with data and metadata of different segtype.
|
||||||
|
Improve mirror type leg splitting.
|
||||||
|
Improve error path handling in daemons on shutdown.
|
||||||
|
Fix activation order when removing merged snapshot.
|
||||||
|
Experimental VDO support for lvmdbusd.
|
||||||
|
|
||||||
|
Version 2.03.06 - 23rd October 2019
|
||||||
|
===================================
|
||||||
|
Add _cpool suffix to cache-pool LV name when used by caching LV.
|
||||||
|
No longer store extra UUID for cmeta and cdata cachevol layer.
|
||||||
|
Enhance activation of cache devices with cachevols.
|
||||||
|
Add _cvol in list of protected suffixes and start use it with DM UUID.
|
||||||
|
Rename LV converted to cachevol to use _cvol suffix.
|
||||||
|
Use normal LVs for wiping of cachevols.
|
||||||
|
Reload cleanered cache DM only with cleaner policy.
|
||||||
|
Fix cmd return when zeroing of cachevol fails.
|
||||||
|
Extend lvs to show all VDO properties.
|
||||||
|
Preserve VDO write policy with vdopool.
|
||||||
|
Increase default vdo bio threads to 4.
|
||||||
|
Continue report when cache_status fails.
|
||||||
|
Add support for DM_DEVICE_GET_TARGET_VERSION into device_mapper.
|
||||||
|
Fix cmirrord usage of header files from device_mapper subdir.
|
||||||
|
Allow standalone activation of VDO pool just like for thin-pools.
|
||||||
|
Activate thin-pool layered volume as 'read-only' device.
|
||||||
|
Ignore crypto devices with UUID signature CRYPT-SUBDEV.
|
||||||
|
Enhance validation for thin and cache pool conversion and swapping.
|
||||||
|
Improve internal removal of cached devices.
|
||||||
|
Synchronize with udev when dropping snapshot.
|
||||||
|
Add missing device synchronization point before removing pvmove node.
|
||||||
|
Correctly set read_ahead for LVs when pvmove is finished.
|
||||||
|
Remove unsupported OPTIONS+="event_timeout" udev rule from 11-dm-lvm.rules.
|
||||||
|
Prevent creating VGs with PVs with different logical block sizes.
|
||||||
|
Fix metadata writes from corrupting with large physical block size.
|
||||||
|
|
||||||
|
Version 2.03.05 - 15th June 2019
|
||||||
|
================================
|
||||||
|
Fix command definition for pvchange -a.
|
||||||
|
Add vgck --updatemetadata command that will repair metadata problems.
|
||||||
|
Improve VG reading to work if one good copy of metadata is found.
|
||||||
|
Report/display/scan commands that read VGs will no longer write/repair.
|
||||||
|
Move metadata repairs from VG reading to VG writing.
|
||||||
|
Add config setting md_component_checks to control MD component checks.
|
||||||
|
Add end of device MD component checks when dev has no udev info.
|
||||||
|
|
||||||
|
Version 2.03.04 - 10th June 2019
|
||||||
|
================================
|
||||||
|
Remove unused_duplicate_devs from cmd causing segfault in dmeventd.
|
||||||
|
|
||||||
|
Version 2.03.03 - 07th June 2019
|
||||||
|
================================
|
||||||
|
Report no_discard_passdown for cache LVs with lvs -o+kernel_discards.
|
||||||
|
Add pvck --dump option to extract metadata.
|
||||||
|
Fix signal delivery checking race in libdaemon (lvmetad).
|
||||||
|
Add missing Before=shutdown.target to LVM2 services to fix shutdown ordering.
|
||||||
|
Skip autoactivation for a PV when PV size does not match device size.
|
||||||
|
Remove first-pvscan-initialization which should no longer be needed.
|
||||||
|
Add remote refresh through lvmlockd/dlm for shared LVs after lvextend.
|
||||||
|
Ignore foreign and shared PVs for pvscan online files.
|
||||||
|
Add config setting to control fields in debug file and verbose output.
|
||||||
|
Add command[pid] and timestamp to debug file and verbose output.
|
||||||
|
Fix missing growth of _pmsmare volume when extending _tmeta volume.
|
||||||
|
Automatically grow thin metadata, when thin data gets too big.
|
||||||
|
Add synchronization with udev before removing cached devices.
|
||||||
|
Add support for caching VDO LVs and VDOPOOL LVs.
|
||||||
|
Add support for vgsplit with cached devices.
|
||||||
|
Query mpath device only once per command for its state.
|
||||||
|
Use device INFO instead of STATUS when checking for mpath device uuid.
|
||||||
|
Change default io_memory_size from 4 to 8 MiB.
|
||||||
|
Add config setting io_memory_size to set bcache size.
|
||||||
|
Fix pvscan autoactivation for concurrent pvscans.
|
||||||
|
Change scan_lvs default to 0 so LVs are not scanned for PVs.
|
||||||
|
Thin-pool selects power-of-2 chunk size by default.
|
||||||
|
Cache selects power-of-2 chunk size by default.
|
||||||
|
Support reszing for VDOPoolLV and VDOLV.
|
||||||
|
Improve -lXXX%VG modifier which improves cache segment estimation.
|
||||||
|
Ensure migration_threshold for cache is at least 8 chunks.
|
||||||
|
Restore missing man info lvcreate --zero for thin-pools.
|
||||||
|
Drop misleadning comment for metadata minimum_io_size for VDO segment.
|
||||||
|
Add device hints to reduce scanning.
|
||||||
|
Introduce LVM_SUPPRESS_SYSLOG to suppress syslog usage by generator.
|
||||||
|
Fix generator quering lvmconfig unpresent config option.
|
||||||
|
Fix memleak on bcache error path code.
|
||||||
|
Fix missing unlock on lvm2 dmeventd plugin error path initialization.
|
||||||
|
Improve Makefile dependency tracking.
|
||||||
|
Move VDO support towards V2 target (6.2) support.
|
||||||
|
|
||||||
|
Version 2.03.02 - 18th December 2018
|
||||||
|
====================================
|
||||||
|
Fix missing proper initialization of pv_list struct when adding pv.
|
||||||
|
Fix (de)activation of RaidLVs with visible SubLVs.
|
||||||
|
Prohibit mirrored 'mirror' log via lvcreate and lvconvert.
|
||||||
|
Use sync io if async io_setup fails, or use_aio=0 is set in config.
|
||||||
|
Fix more issues reported by coverity scan.
|
||||||
|
|
||||||
|
Version 2.03.01 - 31st October 2018
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Version 2.03.00 - 10th October 2018
|
||||||
|
===================================
|
||||||
|
Add hot fix to avoiding locking collision when monitoring thin-pools.
|
||||||
|
Allow raid4 -> linear conversion request.
|
||||||
Fix lvconvert striped/raid0/raid0_meta -> raid6 regression.
|
Fix lvconvert striped/raid0/raid0_meta -> raid6 regression.
|
||||||
|
Add 'lvm2-activation-generator:' prefix for kmsg messages logged by generator.
|
||||||
Add After=rbdmap.service to {lvm2-activation-net,blk-availability}.service.
|
Add After=rbdmap.service to {lvm2-activation-net,blk-availability}.service.
|
||||||
Fix pvs with lvmetad to avoid too many open files from filter reads.
|
|
||||||
Fix pvscan --cache to avoid too many open files from filter reads.
|
|
||||||
Reduce max concurrent aios to avoid EMFILE with many devices.
|
Reduce max concurrent aios to avoid EMFILE with many devices.
|
||||||
Fix lvconvert conversion attempts to linear.
|
Fix lvconvert conversion attempts to linear.
|
||||||
Fix lvconvert raid0/raid0_meta -> striped regression.
|
Fix lvconvert raid0/raid0_meta -> striped regression.
|
||||||
Fix lvconvert --splitmirror for mirror type (2.02.178).
|
Fix lvconvert --splitmirror for mirror type (2.02.178).
|
||||||
Do not pair cache policy and cache metadata format.
|
Do not pair cache policy and cache metadata format.
|
||||||
Fix mirrors honoring read_only_volume_list.
|
lvconvert: reject conversions on raid1 LVs with split tracked SubLVs
|
||||||
|
lvconvert: reject conversions on raid1 split tracked SubLVs
|
||||||
Version 2.02.181 - 01 August 2018
|
Add basic creation support for VDO target.
|
||||||
=================================
|
|
||||||
Reject conversions on raid1 LVs with split tracked SubLVs.
|
|
||||||
Reject conversions on raid1 split tracked SubLVs.
|
|
||||||
Fix dmstats list failing when no regions exist.
|
|
||||||
Reject conversions of LVs under snapshot.
|
|
||||||
Limit suggested options on incorrect option for lvconvert subcommand.
|
|
||||||
|
|
||||||
Version 2.02.180 - 19th July 2018
|
|
||||||
=================================
|
|
||||||
Never send any discard ioctl with test mode.
|
Never send any discard ioctl with test mode.
|
||||||
Fix thin-pool alloc which needs same PV for data and metadata.
|
Fix thin-pool alloc which needs same PV for data and metadata.
|
||||||
Extend list of non-memlocked areas with newly linked libs.
|
Extend list of non-memlocked areas with newly linked libs.
|
||||||
Enhance vgcfgrestore to check for active LVs in restored VG.
|
Enhance vgcfgrestore to check for active LVs in restored VG.
|
||||||
lvconvert: provide possible layouts between linear and striped/raid
|
Configure supports --disable-silent-rules for verbose builds.
|
||||||
Fix unmonitoring of merging snapshots.
|
Fix unmonitoring of merging snapshots.
|
||||||
Add missing -l description in fsadm man page.
|
|
||||||
Cache can uses metadata format 2 with cleaner policy.
|
Cache can uses metadata format 2 with cleaner policy.
|
||||||
Avoid showing internal error in lvs output or pvmoved LVs.
|
|
||||||
Fix check if resized PV can also fit metadata area.
|
Fix check if resized PV can also fit metadata area.
|
||||||
Reopen devices RDWR only before writing to avoid udev issues.
|
Avoid showing internal error in lvs output or pvmoved LVs.
|
||||||
Change pvresize output confusing when no resize took place.
|
Remove clvmd
|
||||||
Fix lvmetad hanging on shutdown.
|
Remove lvmlib (api)
|
||||||
Fix mem leak in clvmd and more coverity issues.
|
Remove lvmetad
|
||||||
|
lvconvert: provide possible layouts between linear and striped/raid
|
||||||
Version 2.02.179 - 18th June 2018
|
|
||||||
=================================
|
|
||||||
Allow forced vgchange to lock type none on clustered VG.
|
|
||||||
Add the report field "shared".
|
|
||||||
Enable automatic metadata consistency repair on a shared VG.
|
|
||||||
Fix pvremove force on a PV with a shared VG.
|
|
||||||
Fixed vgimportclone of a PV with a shared VG.
|
|
||||||
Enable previously disallowed thin/cache commands in shared VGs.
|
|
||||||
Enable metadata-related changes on LVs active with shared lock.
|
|
||||||
Do not continue trying to use a device that cannot be opened.
|
|
||||||
Fix problems opening a device that fails and returns.
|
|
||||||
Use versionsort to fix archive file expiry beyond 100000 files.
|
Use versionsort to fix archive file expiry beyond 100000 files.
|
||||||
|
|
||||||
Version 2.02.178 - 13th June 2018
|
|
||||||
=================================
|
|
||||||
|
|
||||||
Version 2.02.178-rc1 - 24th May 2018
|
Version 2.02.178-rc1 - 24th May 2018
|
||||||
====================================
|
====================================
|
||||||
Add libaio dependency for build.
|
Add libaio dependency for build.
|
||||||
|
|||||||
46
WHATS_NEW_DM
46
WHATS_NEW_DM
@@ -1,12 +1,52 @@
|
|||||||
Version 1.02.156 -
|
Version 1.02.175 -
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Version 1.02.173 - 09th August 2020
|
||||||
|
===================================
|
||||||
|
Add support for VDO in blkdeactivate script.
|
||||||
|
|
||||||
|
Version 1.02.171 - 26th March 2020
|
||||||
|
==================================
|
||||||
|
Try to remove all created devices on dm preload tree error path.
|
||||||
|
Fix dm_list interators with gcc 10 optimization (-ftree-pta).
|
||||||
|
Dmeventd handles timer without looping on short intervals.
|
||||||
|
|
||||||
|
Version 1.02.169 - 11th February 2020
|
||||||
|
=====================================
|
||||||
|
Enhance error messages for device creation.
|
||||||
|
|
||||||
|
Version 1.02.167 - 30th November 2019
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
Version 1.02.154 - 07th December 2018
|
Version 1.02.165 - 23rd October 2019
|
||||||
|
====================================
|
||||||
|
Add support for DM_DEVICE_GET_TARGET_VERSION.
|
||||||
|
Add debug of dmsetup udevcomplete with hexa print DM_COOKIE_COMPLETED.
|
||||||
|
Fix versioning of dm_stats_create_region and dm_stats_create_region.
|
||||||
|
|
||||||
|
Version 1.02.163 - 15th June 2019
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Version 1.02.161 - 10th June 2019
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Version 1.02.159 - 07th June 2019
|
||||||
|
=================================
|
||||||
|
Parsing of cache status understand no_discard_passdown.
|
||||||
|
Ensure migration_threshold for cache is at least 8 chunks.
|
||||||
|
|
||||||
|
Version 1.02.155 - 18th December 2018
|
||||||
=====================================
|
=====================================
|
||||||
|
Include correct internal header inside libdm list.c.
|
||||||
|
Enhance ioctl flattening and add parameters only when needed.
|
||||||
|
Add DM_DEVICE_ARM_POLL for API completness matching kernel.
|
||||||
Do not add parameters for RESUME with DM_DEVICE_CREATE dm task.
|
Do not add parameters for RESUME with DM_DEVICE_CREATE dm task.
|
||||||
Fix dmstats report printing no output.
|
Fix dmstats report printing no output.
|
||||||
|
|
||||||
Version 1.02.152 - 30th October 2018
|
Version 1.02.153 - 31st October 2018
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Version 1.02.151 - 10th October 2018
|
||||||
====================================
|
====================================
|
||||||
Add hot fix to avoiding locking collision when monitoring thin-pools.
|
Add hot fix to avoiding locking collision when monitoring thin-pools.
|
||||||
|
|
||||||
|
|||||||
95
aclocal.m4
vendored
95
aclocal.m4
vendored
@@ -1,6 +1,6 @@
|
|||||||
# generated automatically by aclocal 1.15 -*- Autoconf -*-
|
# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
|
||||||
|
|
||||||
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
# This file is free software; the Free Software Foundation
|
# This file is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
|
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_python_module.html
|
# https://www.gnu.org/software/autoconf-archive/ax_python_module.html
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
@@ -37,7 +37,7 @@ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun
|
|||||||
# and this notice are preserved. This file is offered as-is, without any
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
# warranty.
|
# warranty.
|
||||||
|
|
||||||
#serial 8
|
#serial 9
|
||||||
|
|
||||||
AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE])
|
AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE])
|
||||||
AC_DEFUN([AX_PYTHON_MODULE],[
|
AC_DEFUN([AX_PYTHON_MODULE],[
|
||||||
@@ -69,9 +69,9 @@ AC_DEFUN([AX_PYTHON_MODULE],[
|
|||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||||
dnl serial 11 (pkg-config-0.29)
|
# serial 11 (pkg-config-0.29.1)
|
||||||
dnl
|
|
||||||
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||||
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||||
dnl
|
dnl
|
||||||
@@ -112,7 +112,7 @@ dnl
|
|||||||
dnl See the "Since" comment for each macro you use to see what version
|
dnl See the "Since" comment for each macro you use to see what version
|
||||||
dnl of the macros you require.
|
dnl of the macros you require.
|
||||||
m4_defun([PKG_PREREQ],
|
m4_defun([PKG_PREREQ],
|
||||||
[m4_define([PKG_MACROS_VERSION], [0.29])
|
[m4_define([PKG_MACROS_VERSION], [0.29.1])
|
||||||
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
|
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
|
||||||
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
|
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
|
||||||
])dnl PKG_PREREQ
|
])dnl PKG_PREREQ
|
||||||
@@ -345,7 +345,75 @@ AS_VAR_COPY([$1], [pkg_cv_][$1])
|
|||||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||||
])dnl PKG_CHECK_VAR
|
])dnl PKG_CHECK_VAR
|
||||||
|
|
||||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||||
|
dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
|
||||||
|
dnl [DESCRIPTION], [DEFAULT])
|
||||||
|
dnl ------------------------------------------
|
||||||
|
dnl
|
||||||
|
dnl Prepare a "--with-" configure option using the lowercase
|
||||||
|
dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
|
||||||
|
dnl PKG_CHECK_MODULES in a single macro.
|
||||||
|
AC_DEFUN([PKG_WITH_MODULES],
|
||||||
|
[
|
||||||
|
m4_pushdef([with_arg], m4_tolower([$1]))
|
||||||
|
|
||||||
|
m4_pushdef([description],
|
||||||
|
[m4_default([$5], [build with ]with_arg[ support])])
|
||||||
|
|
||||||
|
m4_pushdef([def_arg], [m4_default([$6], [auto])])
|
||||||
|
m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
|
||||||
|
m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
|
||||||
|
|
||||||
|
m4_case(def_arg,
|
||||||
|
[yes],[m4_pushdef([with_without], [--without-]with_arg)],
|
||||||
|
[m4_pushdef([with_without],[--with-]with_arg)])
|
||||||
|
|
||||||
|
AC_ARG_WITH(with_arg,
|
||||||
|
AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
|
||||||
|
[AS_TR_SH([with_]with_arg)=def_arg])
|
||||||
|
|
||||||
|
AS_CASE([$AS_TR_SH([with_]with_arg)],
|
||||||
|
[yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
|
||||||
|
[auto],[PKG_CHECK_MODULES([$1],[$2],
|
||||||
|
[m4_n([def_action_if_found]) $3],
|
||||||
|
[m4_n([def_action_if_not_found]) $4])])
|
||||||
|
|
||||||
|
m4_popdef([with_arg])
|
||||||
|
m4_popdef([description])
|
||||||
|
m4_popdef([def_arg])
|
||||||
|
|
||||||
|
])dnl PKG_WITH_MODULES
|
||||||
|
|
||||||
|
dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||||
|
dnl [DESCRIPTION], [DEFAULT])
|
||||||
|
dnl -----------------------------------------------
|
||||||
|
dnl
|
||||||
|
dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
|
||||||
|
dnl check._[VARIABLE-PREFIX] is exported as make variable.
|
||||||
|
AC_DEFUN([PKG_HAVE_WITH_MODULES],
|
||||||
|
[
|
||||||
|
PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([HAVE_][$1],
|
||||||
|
[test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
|
||||||
|
])dnl PKG_HAVE_WITH_MODULES
|
||||||
|
|
||||||
|
dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||||
|
dnl [DESCRIPTION], [DEFAULT])
|
||||||
|
dnl ------------------------------------------------------
|
||||||
|
dnl
|
||||||
|
dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
|
||||||
|
dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
|
||||||
|
dnl and preprocessor variable.
|
||||||
|
AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
|
||||||
|
[
|
||||||
|
PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
|
||||||
|
|
||||||
|
AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
|
||||||
|
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
|
||||||
|
])dnl PKG_HAVE_DEFINE_WITH_MODULES
|
||||||
|
|
||||||
|
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
|
||||||
#
|
#
|
||||||
# This file is free software; the Free Software Foundation
|
# This file is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
@@ -379,8 +447,11 @@ AC_DEFUN([AM_PATH_PYTHON],
|
|||||||
dnl Find a Python interpreter. Python versions prior to 2.0 are not
|
dnl Find a Python interpreter. Python versions prior to 2.0 are not
|
||||||
dnl supported. (2.0 was released on October 16, 2000).
|
dnl supported. (2.0 was released on October 16, 2000).
|
||||||
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
|
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
|
||||||
[python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl
|
[python python2 python3 dnl
|
||||||
python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0])
|
python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl
|
||||||
|
python3.2 python3.1 python3.0 dnl
|
||||||
|
python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl
|
||||||
|
python2.0])
|
||||||
|
|
||||||
AC_ARG_VAR([PYTHON], [the Python interpreter])
|
AC_ARG_VAR([PYTHON], [the Python interpreter])
|
||||||
|
|
||||||
@@ -580,7 +651,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
|
|||||||
sys.exit(sys.hexversion < minverhex)"
|
sys.exit(sys.hexversion < minverhex)"
|
||||||
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
|
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
|
||||||
|
|
||||||
# Copyright (C) 2001-2014 Free Software Foundation, Inc.
|
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
|
||||||
#
|
#
|
||||||
# This file is free software; the Free Software Foundation
|
# This file is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
|||||||
40
base/Makefile
Normal file
40
base/Makefile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Copyright (C) 2018 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This file is part of the device-mapper userspace tools.
|
||||||
|
#
|
||||||
|
# This copyrighted material is made available to anyone wishing to use,
|
||||||
|
# modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
# of the GNU Lesser General Public License v.2.1.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
# Uncomment this to build the simple radix tree. You'll need to make clean too.
|
||||||
|
# Comment to build the advanced radix tree.
|
||||||
|
#base/data-struct/radix-tree.o: CFLAGS += -DSIMPLE_RADIX_TREE
|
||||||
|
|
||||||
|
# NOTE: this Makefile only works as 'include' for toplevel Makefile
|
||||||
|
# which defined all top_* variables
|
||||||
|
|
||||||
|
BASE_SOURCE=\
|
||||||
|
base/data-struct/hash.c \
|
||||||
|
base/data-struct/list.c \
|
||||||
|
base/data-struct/radix-tree.c
|
||||||
|
|
||||||
|
BASE_TARGET = base/libbase.a
|
||||||
|
BASE_DEPENDS = $(BASE_SOURCE:%.c=%.d)
|
||||||
|
BASE_OBJECTS = $(BASE_SOURCE:%.c=%.o)
|
||||||
|
CLEAN_TARGETS += $(BASE_DEPENDS) $(BASE_OBJECTS) \
|
||||||
|
$(BASE_SOURCE:%.c=%.gcda) \
|
||||||
|
$(BASE_SOURCE:%.c=%.gcno) \
|
||||||
|
$(BASE_TARGET)
|
||||||
|
|
||||||
|
$(BASE_TARGET): $(BASE_OBJECTS)
|
||||||
|
@echo " [AR] $@"
|
||||||
|
$(Q) $(RM) $@
|
||||||
|
$(Q) $(AR) rsv $@ $(BASE_OBJECTS) > /dev/null
|
||||||
|
|
||||||
|
ifeq ("$(DEPENDS)","yes")
|
||||||
|
-include $(BASE_DEPENDS)
|
||||||
|
endif
|
||||||
395
base/data-struct/hash.c
Normal file
395
base/data-struct/hash.c
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* 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 device-mapper userspace tools.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU Lesser General Public License v.2.1.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "device_mapper/misc/dmlib.h"
|
||||||
|
#include "base/memory/zalloc.h"
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
struct dm_hash_node {
|
||||||
|
struct dm_hash_node *next;
|
||||||
|
void *data;
|
||||||
|
unsigned data_len;
|
||||||
|
unsigned keylen;
|
||||||
|
char key[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dm_hash_table {
|
||||||
|
unsigned num_nodes;
|
||||||
|
unsigned num_slots;
|
||||||
|
struct dm_hash_node **slots;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Permutation of the Integers 0 through 255 */
|
||||||
|
static unsigned char _nums[] = {
|
||||||
|
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
|
||||||
|
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
|
||||||
|
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
|
||||||
|
12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172,
|
||||||
|
144,
|
||||||
|
176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
|
||||||
|
178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54,
|
||||||
|
221,
|
||||||
|
102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
|
||||||
|
166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
|
||||||
|
121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185,
|
||||||
|
194,
|
||||||
|
193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232,
|
||||||
|
139,
|
||||||
|
6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
|
||||||
|
84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196,
|
||||||
|
43,
|
||||||
|
249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231,
|
||||||
|
71,
|
||||||
|
230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47,
|
||||||
|
109,
|
||||||
|
44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
|
||||||
|
163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
|
||||||
|
209
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dm_hash_node *_create_node(const void *key, unsigned len)
|
||||||
|
{
|
||||||
|
struct dm_hash_node *n = malloc(sizeof(*n) + len);
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
memcpy(n->key, key, len);
|
||||||
|
n->keylen = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long _hash(const void *key, unsigned len)
|
||||||
|
{
|
||||||
|
const unsigned char *str = key;
|
||||||
|
unsigned long h = 0, g;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
h <<= 4;
|
||||||
|
h += _nums[*str++];
|
||||||
|
g = h & ((unsigned long) 0xf << 16u);
|
||||||
|
if (g) {
|
||||||
|
h ^= g >> 16u;
|
||||||
|
h ^= g >> 5u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dm_hash_table *dm_hash_create(unsigned size_hint)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
unsigned new_size = 16u;
|
||||||
|
struct dm_hash_table *hc = zalloc(sizeof(*hc));
|
||||||
|
|
||||||
|
if (!hc)
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
/* round size hint up to a power of two */
|
||||||
|
while (new_size < size_hint)
|
||||||
|
new_size = new_size << 1;
|
||||||
|
|
||||||
|
hc->num_slots = new_size;
|
||||||
|
len = sizeof(*(hc->slots)) * new_size;
|
||||||
|
if (!(hc->slots = zalloc(len)))
|
||||||
|
goto_bad;
|
||||||
|
|
||||||
|
return hc;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
free(hc->slots);
|
||||||
|
free(hc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _free_nodes(struct dm_hash_table *t)
|
||||||
|
{
|
||||||
|
struct dm_hash_node *c, *n;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < t->num_slots; i++)
|
||||||
|
for (c = t->slots[i]; c; c = n) {
|
||||||
|
n = c->next;
|
||||||
|
free(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_hash_destroy(struct dm_hash_table *t)
|
||||||
|
{
|
||||||
|
_free_nodes(t);
|
||||||
|
free(t->slots);
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dm_hash_node **_find(struct dm_hash_table *t, const void *key,
|
||||||
|
uint32_t len)
|
||||||
|
{
|
||||||
|
unsigned h = _hash(key, len) & (t->num_slots - 1);
|
||||||
|
struct dm_hash_node **c;
|
||||||
|
|
||||||
|
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
|
||||||
|
if ((*c)->keylen != len)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!memcmp(key, (*c)->key, len))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key,
|
||||||
|
uint32_t len)
|
||||||
|
{
|
||||||
|
struct dm_hash_node **c = _find(t, key, len);
|
||||||
|
|
||||||
|
return *c ? (*c)->data : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_hash_insert_binary(struct dm_hash_table *t, const void *key,
|
||||||
|
uint32_t len, void *data)
|
||||||
|
{
|
||||||
|
struct dm_hash_node **c = _find(t, key, len);
|
||||||
|
|
||||||
|
if (*c)
|
||||||
|
(*c)->data = data;
|
||||||
|
else {
|
||||||
|
struct dm_hash_node *n = _create_node(key, len);
|
||||||
|
|
||||||
|
if (!n)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
n->data = data;
|
||||||
|
n->next = 0;
|
||||||
|
*c = n;
|
||||||
|
t->num_nodes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_hash_remove_binary(struct dm_hash_table *t, const void *key,
|
||||||
|
uint32_t len)
|
||||||
|
{
|
||||||
|
struct dm_hash_node **c = _find(t, key, len);
|
||||||
|
|
||||||
|
if (*c) {
|
||||||
|
struct dm_hash_node *old = *c;
|
||||||
|
*c = (*c)->next;
|
||||||
|
free(old);
|
||||||
|
t->num_nodes--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dm_hash_lookup(struct dm_hash_table *t, const char *key)
|
||||||
|
{
|
||||||
|
return dm_hash_lookup_binary(t, key, strlen(key) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data)
|
||||||
|
{
|
||||||
|
return dm_hash_insert_binary(t, key, strlen(key) + 1, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_hash_remove(struct dm_hash_table *t, const char *key)
|
||||||
|
{
|
||||||
|
dm_hash_remove_binary(t, key, strlen(key) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dm_hash_node **_find_str_with_val(struct dm_hash_table *t,
|
||||||
|
const void *key, const void *val,
|
||||||
|
uint32_t len, uint32_t val_len)
|
||||||
|
{
|
||||||
|
struct dm_hash_node **c;
|
||||||
|
unsigned h;
|
||||||
|
|
||||||
|
h = _hash(key, len) & (t->num_slots - 1);
|
||||||
|
|
||||||
|
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
|
||||||
|
if ((*c)->keylen != len)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!memcmp(key, (*c)->key, len) && (*c)->data) {
|
||||||
|
if (((*c)->data_len == val_len) &&
|
||||||
|
!memcmp(val, (*c)->data, val_len))
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
|
||||||
|
const void *val, uint32_t val_len)
|
||||||
|
{
|
||||||
|
struct dm_hash_node *n;
|
||||||
|
struct dm_hash_node *first;
|
||||||
|
int len = strlen(key) + 1;
|
||||||
|
unsigned h;
|
||||||
|
|
||||||
|
n = _create_node(key, len);
|
||||||
|
if (!n)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
n->data = (void *)val;
|
||||||
|
n->data_len = val_len;
|
||||||
|
|
||||||
|
h = _hash(key, len) & (t->num_slots - 1);
|
||||||
|
|
||||||
|
first = t->slots[h];
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
n->next = first;
|
||||||
|
else
|
||||||
|
n->next = 0;
|
||||||
|
t->slots[h] = n;
|
||||||
|
|
||||||
|
t->num_nodes++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look through multiple entries with the same key for one that has a
|
||||||
|
* matching val and return that. If none have maching val, return NULL.
|
||||||
|
*/
|
||||||
|
void *dm_hash_lookup_with_val(struct dm_hash_table *t, const char *key,
|
||||||
|
const void *val, uint32_t val_len)
|
||||||
|
{
|
||||||
|
struct dm_hash_node **c;
|
||||||
|
|
||||||
|
c = _find_str_with_val(t, key, val, strlen(key) + 1, val_len);
|
||||||
|
|
||||||
|
return (c && *c) ? (*c)->data : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look through multiple entries with the same key for one that has a
|
||||||
|
* matching val and remove that.
|
||||||
|
*/
|
||||||
|
void dm_hash_remove_with_val(struct dm_hash_table *t, const char *key,
|
||||||
|
const void *val, uint32_t val_len)
|
||||||
|
{
|
||||||
|
struct dm_hash_node **c;
|
||||||
|
|
||||||
|
c = _find_str_with_val(t, key, val, strlen(key) + 1, val_len);
|
||||||
|
|
||||||
|
if (c && *c) {
|
||||||
|
struct dm_hash_node *old = *c;
|
||||||
|
*c = (*c)->next;
|
||||||
|
free(old);
|
||||||
|
t->num_nodes--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the value for a key and count how many
|
||||||
|
* entries have the same key.
|
||||||
|
*
|
||||||
|
* If no entries have key, return NULL and set count to 0.
|
||||||
|
*
|
||||||
|
* If one entry has the key, the function returns the val,
|
||||||
|
* and sets count to 1.
|
||||||
|
*
|
||||||
|
* If N entries have the key, the function returns the val
|
||||||
|
* from the first entry, and sets count to N.
|
||||||
|
*/
|
||||||
|
void *dm_hash_lookup_with_count(struct dm_hash_table *t, const char *key, int *count)
|
||||||
|
{
|
||||||
|
struct dm_hash_node **c;
|
||||||
|
struct dm_hash_node **c1 = NULL;
|
||||||
|
uint32_t len = strlen(key) + 1;
|
||||||
|
unsigned h;
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
h = _hash(key, len) & (t->num_slots - 1);
|
||||||
|
|
||||||
|
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
|
||||||
|
if ((*c)->keylen != len)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!memcmp(key, (*c)->key, len)) {
|
||||||
|
(*count)++;
|
||||||
|
if (!c1)
|
||||||
|
c1 = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c1)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return *c1 ? (*c1)->data : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned dm_hash_get_num_entries(struct dm_hash_table *t)
|
||||||
|
{
|
||||||
|
return t->num_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
|
||||||
|
{
|
||||||
|
struct dm_hash_node *c, *n;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < t->num_slots; i++)
|
||||||
|
for (c = t->slots[i]; c; c = n) {
|
||||||
|
n = c->next;
|
||||||
|
f(c->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_hash_wipe(struct dm_hash_table *t)
|
||||||
|
{
|
||||||
|
_free_nodes(t);
|
||||||
|
memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots);
|
||||||
|
t->num_nodes = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dm_hash_get_key(struct dm_hash_table *t __attribute__((unused)),
|
||||||
|
struct dm_hash_node *n)
|
||||||
|
{
|
||||||
|
return n->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dm_hash_get_data(struct dm_hash_table *t __attribute__((unused)),
|
||||||
|
struct dm_hash_node *n)
|
||||||
|
{
|
||||||
|
return n->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s)
|
||||||
|
{
|
||||||
|
struct dm_hash_node *c = NULL;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = s; i < t->num_slots && !c; i++)
|
||||||
|
c = t->slots[i];
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)
|
||||||
|
{
|
||||||
|
return _next_slot(t, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n)
|
||||||
|
{
|
||||||
|
unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
|
||||||
|
|
||||||
|
return n->next ? n->next : _next_slot(t, h + 1);
|
||||||
|
}
|
||||||
94
base/data-struct/hash.h
Normal file
94
base/data-struct/hash.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#ifndef BASE_DATA_STRUCT_HASH_H
|
||||||
|
#define BASE_DATA_STRUCT_HASH_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
struct dm_hash_table;
|
||||||
|
struct dm_hash_node;
|
||||||
|
|
||||||
|
typedef void (*dm_hash_iterate_fn) (void *data);
|
||||||
|
|
||||||
|
struct dm_hash_table *dm_hash_create(unsigned size_hint)
|
||||||
|
__attribute__((__warn_unused_result__));
|
||||||
|
void dm_hash_destroy(struct dm_hash_table *t);
|
||||||
|
void dm_hash_wipe(struct dm_hash_table *t);
|
||||||
|
|
||||||
|
void *dm_hash_lookup(struct dm_hash_table *t, const char *key);
|
||||||
|
int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data);
|
||||||
|
void dm_hash_remove(struct dm_hash_table *t, const char *key);
|
||||||
|
|
||||||
|
void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key, uint32_t len);
|
||||||
|
int dm_hash_insert_binary(struct dm_hash_table *t, const void *key, uint32_t len,
|
||||||
|
void *data);
|
||||||
|
void dm_hash_remove_binary(struct dm_hash_table *t, const void *key, uint32_t len);
|
||||||
|
|
||||||
|
unsigned dm_hash_get_num_entries(struct dm_hash_table *t);
|
||||||
|
void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f);
|
||||||
|
|
||||||
|
char *dm_hash_get_key(struct dm_hash_table *t, struct dm_hash_node *n);
|
||||||
|
void *dm_hash_get_data(struct dm_hash_table *t, struct dm_hash_node *n);
|
||||||
|
struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t);
|
||||||
|
struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dm_hash_insert() replaces the value of an existing
|
||||||
|
* entry with a matching key if one exists. Otherwise
|
||||||
|
* it adds a new entry.
|
||||||
|
*
|
||||||
|
* dm_hash_insert_with_val() inserts a new entry if
|
||||||
|
* another entry with the same key already exists.
|
||||||
|
* val_len is the size of the data being inserted.
|
||||||
|
*
|
||||||
|
* If two entries with the same key exist,
|
||||||
|
* (added using dm_hash_insert_allow_multiple), then:
|
||||||
|
* . dm_hash_lookup() returns the first one it finds, and
|
||||||
|
* dm_hash_lookup_with_val() returns the one with a matching
|
||||||
|
* val_len/val.
|
||||||
|
* . dm_hash_remove() removes the first one it finds, and
|
||||||
|
* dm_hash_remove_with_val() removes the one with a matching
|
||||||
|
* val_len/val.
|
||||||
|
*
|
||||||
|
* If a single entry with a given key exists, and it has
|
||||||
|
* zero val_len, then:
|
||||||
|
* . dm_hash_lookup() returns it
|
||||||
|
* . dm_hash_lookup_with_val(val_len=0) returns it
|
||||||
|
* . dm_hash_remove() removes it
|
||||||
|
* . dm_hash_remove_with_val(val_len=0) removes it
|
||||||
|
*
|
||||||
|
* dm_hash_lookup_with_count() is a single call that will
|
||||||
|
* both lookup a key's value and check if there is more
|
||||||
|
* than one entry with the given key.
|
||||||
|
*
|
||||||
|
* (It is not meant to retrieve all the entries with the
|
||||||
|
* given key. In the common case where a single entry exists
|
||||||
|
* for the key, it is useful to have a single call that will
|
||||||
|
* both look up the value and indicate if multiple values
|
||||||
|
* exist for the key.)
|
||||||
|
*
|
||||||
|
* dm_hash_lookup_with_count:
|
||||||
|
* . If no entries exist, the function returns NULL, and
|
||||||
|
* the count is set to 0.
|
||||||
|
* . If only one entry exists, the value of that entry is
|
||||||
|
* returned and count is set to 1.
|
||||||
|
* . If N entries exists, the value of the first entry is
|
||||||
|
* returned and count is set to N.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *dm_hash_lookup_with_val(struct dm_hash_table *t, const char *key,
|
||||||
|
const void *val, uint32_t val_len);
|
||||||
|
void dm_hash_remove_with_val(struct dm_hash_table *t, const char *key,
|
||||||
|
const void *val, uint32_t val_len);
|
||||||
|
int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
|
||||||
|
const void *val, uint32_t val_len);
|
||||||
|
void *dm_hash_lookup_with_count(struct dm_hash_table *t, const char *key, int *count);
|
||||||
|
|
||||||
|
|
||||||
|
#define dm_hash_iterate(v, h) \
|
||||||
|
for (v = dm_hash_get_first((h)); v; \
|
||||||
|
v = dm_hash_get_next((h), v))
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
||||||
170
base/data-struct/list.c
Normal file
170
base/data-struct/list.c
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* 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 Lesser General Public License v.2.1.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise a list before use.
|
||||||
|
* The list head's next and previous pointers point back to itself.
|
||||||
|
*/
|
||||||
|
void dm_list_init(struct dm_list *head)
|
||||||
|
{
|
||||||
|
head->n = head->p = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert an element before 'head'.
|
||||||
|
* If 'head' is the list head, this adds an element to the end of the list.
|
||||||
|
*/
|
||||||
|
void dm_list_add(struct dm_list *head, struct dm_list *elem)
|
||||||
|
{
|
||||||
|
assert(head->n);
|
||||||
|
|
||||||
|
elem->n = head;
|
||||||
|
elem->p = head->p;
|
||||||
|
|
||||||
|
head->p->n = elem;
|
||||||
|
head->p = elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert an element after 'head'.
|
||||||
|
* If 'head' is the list head, this adds an element to the front of the list.
|
||||||
|
*/
|
||||||
|
void dm_list_add_h(struct dm_list *head, struct dm_list *elem)
|
||||||
|
{
|
||||||
|
assert(head->n);
|
||||||
|
|
||||||
|
elem->n = head->n;
|
||||||
|
elem->p = head;
|
||||||
|
|
||||||
|
head->n->p = elem;
|
||||||
|
head->n = elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete an element from its list.
|
||||||
|
* Note that this doesn't change the element itself - it may still be safe
|
||||||
|
* to follow its pointers.
|
||||||
|
*/
|
||||||
|
void dm_list_del(struct dm_list *elem)
|
||||||
|
{
|
||||||
|
elem->n->p = elem->p;
|
||||||
|
elem->p->n = elem->n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove an element from existing list and insert before 'head'.
|
||||||
|
*/
|
||||||
|
void dm_list_move(struct dm_list *head, struct dm_list *elem)
|
||||||
|
{
|
||||||
|
dm_list_del(elem);
|
||||||
|
dm_list_add(head, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the list empty?
|
||||||
|
*/
|
||||||
|
int dm_list_empty(const struct dm_list *head)
|
||||||
|
{
|
||||||
|
return head->n == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the first element of the list?
|
||||||
|
*/
|
||||||
|
int dm_list_start(const struct dm_list *head, const struct dm_list *elem)
|
||||||
|
{
|
||||||
|
return elem->p == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the last element of the list?
|
||||||
|
*/
|
||||||
|
int dm_list_end(const struct dm_list *head, const struct dm_list *elem)
|
||||||
|
{
|
||||||
|
return elem->n == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return first element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
struct dm_list *dm_list_first(const struct dm_list *head)
|
||||||
|
{
|
||||||
|
return (dm_list_empty(head) ? NULL : head->n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return last element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
struct dm_list *dm_list_last(const struct dm_list *head)
|
||||||
|
{
|
||||||
|
return (dm_list_empty(head) ? NULL : head->p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the previous element of the list, or NULL if we've reached the start.
|
||||||
|
*/
|
||||||
|
struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem)
|
||||||
|
{
|
||||||
|
return (dm_list_start(head, elem) ? NULL : elem->p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the next element of the list, or NULL if we've reached the end.
|
||||||
|
*/
|
||||||
|
struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem)
|
||||||
|
{
|
||||||
|
return (dm_list_end(head, elem) ? NULL : elem->n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the number of elements in a list by walking it.
|
||||||
|
*/
|
||||||
|
unsigned int dm_list_size(const struct dm_list *head)
|
||||||
|
{
|
||||||
|
unsigned int s = 0;
|
||||||
|
const struct dm_list *v;
|
||||||
|
|
||||||
|
dm_list_iterate(v, head)
|
||||||
|
s++;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Join two lists together.
|
||||||
|
* This moves all the elements of the list 'head1' to the end of the list
|
||||||
|
* 'head', leaving 'head1' empty.
|
||||||
|
*/
|
||||||
|
void dm_list_splice(struct dm_list *head, struct dm_list *head1)
|
||||||
|
{
|
||||||
|
assert(head->n);
|
||||||
|
assert(head1->n);
|
||||||
|
|
||||||
|
if (dm_list_empty(head1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
head1->p->n = head;
|
||||||
|
head1->n->p = head->p;
|
||||||
|
|
||||||
|
head->p->n = head1->n;
|
||||||
|
head->p = head1->p;
|
||||||
|
|
||||||
|
dm_list_init(head1);
|
||||||
|
}
|
||||||
211
base/data-struct/list.h
Normal file
211
base/data-struct/list.h
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
#ifndef BASE_DATA_STRUCT_LIST_H
|
||||||
|
#define BASE_DATA_STRUCT_LIST_H
|
||||||
|
|
||||||
|
#include "base/memory/container_of.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A list consists of a list head plus elements.
|
||||||
|
* Each element has 'next' and 'previous' pointers.
|
||||||
|
* The list head's pointers point to the first and the last element.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct dm_list {
|
||||||
|
struct dm_list *n, *p;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* String list.
|
||||||
|
*/
|
||||||
|
struct dm_str_list {
|
||||||
|
struct dm_list list;
|
||||||
|
const char *str;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise a list before use.
|
||||||
|
* The list head's next and previous pointers point back to itself.
|
||||||
|
*/
|
||||||
|
#define DM_LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||||
|
#define DM_LIST_INIT(name) struct dm_list name = DM_LIST_HEAD_INIT(name)
|
||||||
|
void dm_list_init(struct dm_list *head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert an element before 'head'.
|
||||||
|
* If 'head' is the list head, this adds an element to the end of the list.
|
||||||
|
*/
|
||||||
|
void dm_list_add(struct dm_list *head, struct dm_list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert an element after 'head'.
|
||||||
|
* If 'head' is the list head, this adds an element to the front of the list.
|
||||||
|
*/
|
||||||
|
void dm_list_add_h(struct dm_list *head, struct dm_list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete an element from its list.
|
||||||
|
* Note that this doesn't change the element itself - it may still be safe
|
||||||
|
* to follow its pointers.
|
||||||
|
*/
|
||||||
|
void dm_list_del(struct dm_list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove an element from existing list and insert before 'head'.
|
||||||
|
*/
|
||||||
|
void dm_list_move(struct dm_list *head, struct dm_list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Join 'head1' to the end of 'head'.
|
||||||
|
*/
|
||||||
|
void dm_list_splice(struct dm_list *head, struct dm_list *head1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the list empty?
|
||||||
|
*/
|
||||||
|
int dm_list_empty(const struct dm_list *head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the first element of the list?
|
||||||
|
*/
|
||||||
|
int dm_list_start(const struct dm_list *head, const struct dm_list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the last element of the list?
|
||||||
|
*/
|
||||||
|
int dm_list_end(const struct dm_list *head, const struct dm_list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return first element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
struct dm_list *dm_list_first(const struct dm_list *head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return last element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
struct dm_list *dm_list_last(const struct dm_list *head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the previous element of the list, or NULL if we've reached the start.
|
||||||
|
*/
|
||||||
|
struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the next element of the list, or NULL if we've reached the end.
|
||||||
|
*/
|
||||||
|
struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the address v of an instance of 'struct dm_list' called 'head'
|
||||||
|
* contained in a structure of type t, return the containing structure.
|
||||||
|
*/
|
||||||
|
#define dm_list_struct_base(v, t, head) \
|
||||||
|
container_of(v, t, head)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the address v of an instance of 'struct dm_list list' contained in
|
||||||
|
* a structure of type t, return the containing structure.
|
||||||
|
*/
|
||||||
|
#define dm_list_item(v, t) dm_list_struct_base((v), t, list)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the address v of one known element e in a known structure of type t,
|
||||||
|
* return another element f.
|
||||||
|
*/
|
||||||
|
#define dm_struct_field(v, t, e, f) \
|
||||||
|
(((t *)((uintptr_t)(v) - offsetof(t, e)))->f)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the address v of a known element e in a known structure of type t,
|
||||||
|
* return the list head 'list'
|
||||||
|
*/
|
||||||
|
#define dm_list_head(v, t, e) dm_struct_field(v, t, e, list)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set v to each element of a list in turn.
|
||||||
|
*/
|
||||||
|
#define dm_list_iterate(v, head) \
|
||||||
|
for (v = (head)->n; v != head; v = v->n)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set v to each element in a list in turn, starting from the element
|
||||||
|
* in front of 'start'.
|
||||||
|
* You can use this to 'unwind' a list_iterate and back out actions on
|
||||||
|
* already-processed elements.
|
||||||
|
* If 'start' is 'head' it walks the list backwards.
|
||||||
|
*/
|
||||||
|
#define dm_list_uniterate(v, head, start) \
|
||||||
|
for (v = (start)->p; v != head; v = v->p)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A safe way to walk a list and delete and free some elements along
|
||||||
|
* the way.
|
||||||
|
* t must be defined as a temporary variable of the same type as v.
|
||||||
|
*/
|
||||||
|
#define dm_list_iterate_safe(v, t, head) \
|
||||||
|
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||||
|
* The containing structure should be the same type as 'v'.
|
||||||
|
* The 'struct dm_list' variable within the containing structure is 'field'.
|
||||||
|
*/
|
||||||
|
#define dm_list_iterate_items_gen(v, head, field) \
|
||||||
|
for (v = dm_list_struct_base((head)->n, __typeof__(*v), field); \
|
||||||
|
&v->field != (head); \
|
||||||
|
v = dm_list_struct_base(v->field.n, __typeof__(*v), field))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||||
|
* The containing structure should be the same type as 'v'.
|
||||||
|
* The list should be 'struct dm_list list' within the containing structure.
|
||||||
|
*/
|
||||||
|
#define dm_list_iterate_items(v, head) dm_list_iterate_items_gen(v, (head), list)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||||
|
* The containing structure should be the same type as 'v'.
|
||||||
|
* The 'struct dm_list' variable within the containing structure is 'field'.
|
||||||
|
* t must be defined as a temporary variable of the same type as v.
|
||||||
|
*/
|
||||||
|
#define dm_list_iterate_items_gen_safe(v, t, head, field) \
|
||||||
|
for (v = dm_list_struct_base((head)->n, __typeof__(*v), field), \
|
||||||
|
t = dm_list_struct_base(v->field.n, __typeof__(*v), field); \
|
||||||
|
&v->field != (head); \
|
||||||
|
v = t, t = dm_list_struct_base(v->field.n, __typeof__(*v), field))
|
||||||
|
/*
|
||||||
|
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||||
|
* The containing structure should be the same type as 'v'.
|
||||||
|
* The list should be 'struct dm_list list' within the containing structure.
|
||||||
|
* t must be defined as a temporary variable of the same type as v.
|
||||||
|
*/
|
||||||
|
#define dm_list_iterate_items_safe(v, t, head) \
|
||||||
|
dm_list_iterate_items_gen_safe(v, t, (head), list)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk a list backwards, setting 'v' in turn to the containing structure
|
||||||
|
* of each item.
|
||||||
|
* The containing structure should be the same type as 'v'.
|
||||||
|
* The 'struct dm_list' variable within the containing structure is 'field'.
|
||||||
|
*/
|
||||||
|
#define dm_list_iterate_back_items_gen(v, head, field) \
|
||||||
|
for (v = dm_list_struct_base((head)->p, __typeof__(*v), field); \
|
||||||
|
&v->field != (head); \
|
||||||
|
v = dm_list_struct_base(v->field.p, __typeof__(*v), field))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk a list backwards, setting 'v' in turn to the containing structure
|
||||||
|
* of each item.
|
||||||
|
* The containing structure should be the same type as 'v'.
|
||||||
|
* The list should be 'struct dm_list list' within the containing structure.
|
||||||
|
*/
|
||||||
|
#define dm_list_iterate_back_items(v, head) dm_list_iterate_back_items_gen(v, (head), list)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the number of elements in a list by walking it.
|
||||||
|
*/
|
||||||
|
unsigned int dm_list_size(const struct dm_list *head);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
||||||
1297
base/data-struct/radix-tree-adaptive.c
Normal file
1297
base/data-struct/radix-tree-adaptive.c
Normal file
File diff suppressed because it is too large
Load Diff
256
base/data-struct/radix-tree-simple.c
Normal file
256
base/data-struct/radix-tree-simple.c
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of LVM2.
|
||||||
|
//
|
||||||
|
// This copyrighted material is made available to anyone wishing to use,
|
||||||
|
// modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
// of the GNU Lesser General Public License v.2.1.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
#include "radix-tree.h"
|
||||||
|
|
||||||
|
#include "base/memory/container_of.h"
|
||||||
|
#include "base/memory/zalloc.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// This implementation is based around nested binary trees. Very
|
||||||
|
// simple (and hopefully correct).
|
||||||
|
|
||||||
|
struct node {
|
||||||
|
struct node *left;
|
||||||
|
struct node *right;
|
||||||
|
|
||||||
|
uint8_t key;
|
||||||
|
struct node *center;
|
||||||
|
|
||||||
|
bool has_value;
|
||||||
|
union radix_value value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct radix_tree {
|
||||||
|
radix_value_dtr dtr;
|
||||||
|
void *dtr_context;
|
||||||
|
|
||||||
|
struct node *root;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct radix_tree *
|
||||||
|
radix_tree_create(radix_value_dtr dtr, void *dtr_context)
|
||||||
|
{
|
||||||
|
struct radix_tree *rt = zalloc(sizeof(*rt));
|
||||||
|
|
||||||
|
if (rt) {
|
||||||
|
rt->dtr = dtr;
|
||||||
|
rt->dtr_context = dtr_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the number of entries in the tree
|
||||||
|
static unsigned _destroy_tree(struct node *n, radix_value_dtr dtr, void *context)
|
||||||
|
{
|
||||||
|
unsigned r;
|
||||||
|
|
||||||
|
if (!n)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = _destroy_tree(n->left, dtr, context);
|
||||||
|
r += _destroy_tree(n->right, dtr, context);
|
||||||
|
r += _destroy_tree(n->center, dtr, context);
|
||||||
|
|
||||||
|
if (n->has_value) {
|
||||||
|
if (dtr)
|
||||||
|
dtr(context, n->value);
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(n);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void radix_tree_destroy(struct radix_tree *rt)
|
||||||
|
{
|
||||||
|
_destroy_tree(rt->root, rt->dtr, rt->dtr_context);
|
||||||
|
free(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned _count(struct node *n)
|
||||||
|
{
|
||||||
|
unsigned r;
|
||||||
|
|
||||||
|
if (!n)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = _count(n->left);
|
||||||
|
r += _count(n->right);
|
||||||
|
r += _count(n->center);
|
||||||
|
|
||||||
|
if (n->has_value)
|
||||||
|
r++;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned radix_tree_size(struct radix_tree *rt)
|
||||||
|
{
|
||||||
|
return _count(rt->root);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct node **_lookup(struct node **pn, uint8_t *kb, uint8_t *ke)
|
||||||
|
{
|
||||||
|
struct node *n = *pn;
|
||||||
|
|
||||||
|
if (!n || (kb == ke))
|
||||||
|
return pn;
|
||||||
|
|
||||||
|
if (*kb < n->key)
|
||||||
|
return _lookup(&n->left, kb, ke);
|
||||||
|
|
||||||
|
else if (*kb > n->key)
|
||||||
|
return _lookup(&n->right, kb, ke);
|
||||||
|
|
||||||
|
else
|
||||||
|
return _lookup(&n->center, kb + 1, ke);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _insert(struct node **pn, uint8_t *kb, uint8_t *ke, union radix_value v)
|
||||||
|
{
|
||||||
|
struct node *n = *pn;
|
||||||
|
|
||||||
|
if (!n) {
|
||||||
|
n = zalloc(sizeof(*n));
|
||||||
|
if (!n)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
n->key = *kb;
|
||||||
|
*pn = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kb == ke) {
|
||||||
|
n->has_value = true;
|
||||||
|
n->value = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*kb < n->key)
|
||||||
|
return _insert(&n->left, kb, ke, v);
|
||||||
|
|
||||||
|
else if (*kb > n->key)
|
||||||
|
return _insert(&n->right, kb, ke, v);
|
||||||
|
|
||||||
|
else
|
||||||
|
return _insert(&n->center, kb + 1, ke, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v)
|
||||||
|
{
|
||||||
|
return _insert(&rt->root, kb, ke, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
|
||||||
|
{
|
||||||
|
struct node **pn = _lookup(&rt->root, kb, ke);
|
||||||
|
struct node *n = *pn;
|
||||||
|
|
||||||
|
if (!n || !n->has_value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
else {
|
||||||
|
if (rt->dtr)
|
||||||
|
rt->dtr(rt->dtr_context, n->value);
|
||||||
|
|
||||||
|
if (n->left || n->center || n->right) {
|
||||||
|
n->has_value = false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// FIXME: delete parent if this was the last entry
|
||||||
|
free(n);
|
||||||
|
*pn = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
|
||||||
|
{
|
||||||
|
struct node **pn;
|
||||||
|
unsigned count;
|
||||||
|
|
||||||
|
pn = _lookup(&rt->root, kb, ke);
|
||||||
|
|
||||||
|
if (*pn) {
|
||||||
|
count = _destroy_tree(*pn, rt->dtr, rt->dtr_context);
|
||||||
|
*pn = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
radix_tree_lookup(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value *result)
|
||||||
|
{
|
||||||
|
struct node **pn = _lookup(&rt->root, kb, ke);
|
||||||
|
struct node *n = *pn;
|
||||||
|
|
||||||
|
if (n && n->has_value) {
|
||||||
|
*result = n->value;
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _iterate(struct node *n, struct radix_tree_iterator *it)
|
||||||
|
{
|
||||||
|
if (!n)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_iterate(n->left, it);
|
||||||
|
|
||||||
|
if (n->has_value)
|
||||||
|
// FIXME: fill out the key
|
||||||
|
it->visit(it, NULL, NULL, n->value);
|
||||||
|
|
||||||
|
_iterate(n->center, it);
|
||||||
|
_iterate(n->right, it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
|
||||||
|
struct radix_tree_iterator *it)
|
||||||
|
{
|
||||||
|
if (kb == ke)
|
||||||
|
_iterate(rt->root, it);
|
||||||
|
|
||||||
|
else {
|
||||||
|
struct node **pn = _lookup(&rt->root, kb, ke);
|
||||||
|
struct node *n = *pn;
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
if (n->has_value)
|
||||||
|
it->visit(it, NULL, NULL, n->value);
|
||||||
|
_iterate(n->center, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool radix_tree_is_well_formed(struct radix_tree *rt)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void radix_tree_dump(struct radix_tree *rt, FILE *out)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
@@ -10,853 +10,12 @@
|
|||||||
// along with this program; if not, write to the Free Software Foundation,
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "radix-tree.h"
|
|
||||||
|
|
||||||
#include "base/memory/container_of.h"
|
|
||||||
#include "base/memory/zalloc.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
enum node_type {
|
#ifdef SIMPLE_RADIX_TREE
|
||||||
UNSET = 0,
|
#include "base/data-struct/radix-tree-simple.c"
|
||||||
VALUE,
|
#else
|
||||||
VALUE_CHAIN,
|
#include "base/data-struct/radix-tree-adaptive.c"
|
||||||
PREFIX_CHAIN,
|
#endif
|
||||||
NODE4,
|
|
||||||
NODE16,
|
|
||||||
NODE48,
|
|
||||||
NODE256
|
|
||||||
};
|
|
||||||
|
|
||||||
struct value {
|
|
||||||
enum node_type type;
|
|
||||||
union radix_value value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is used for entries that have a key which is a prefix of another key.
|
|
||||||
struct value_chain {
|
|
||||||
union radix_value value;
|
|
||||||
struct value child;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prefix_chain {
|
|
||||||
struct value child;
|
|
||||||
unsigned len;
|
|
||||||
uint8_t prefix[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct node4 {
|
|
||||||
uint32_t nr_entries;
|
|
||||||
uint8_t keys[4];
|
|
||||||
struct value values[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct node16 {
|
|
||||||
uint32_t nr_entries;
|
|
||||||
uint8_t keys[16];
|
|
||||||
struct value values[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct node48 {
|
|
||||||
uint32_t nr_entries;
|
|
||||||
uint8_t keys[256];
|
|
||||||
struct value values[48];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct node256 {
|
|
||||||
uint32_t nr_entries;
|
|
||||||
struct value values[256];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct radix_tree {
|
|
||||||
unsigned nr_entries;
|
|
||||||
struct value root;
|
|
||||||
radix_value_dtr dtr;
|
|
||||||
void *dtr_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
|
||||||
|
|
||||||
struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
|
|
||||||
{
|
|
||||||
struct radix_tree *rt = malloc(sizeof(*rt));
|
|
||||||
|
|
||||||
if (rt) {
|
|
||||||
rt->nr_entries = 0;
|
|
||||||
rt->root.type = UNSET;
|
|
||||||
rt->dtr = dtr;
|
|
||||||
rt->dtr_context = dtr_context;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void _dtr(struct radix_tree *rt, union radix_value v)
|
|
||||||
{
|
|
||||||
if (rt->dtr)
|
|
||||||
rt->dtr(rt->dtr_context, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the number of values removed
|
|
||||||
static unsigned _free_node(struct radix_tree *rt, struct value v)
|
|
||||||
{
|
|
||||||
unsigned i, nr = 0;
|
|
||||||
struct value_chain *vc;
|
|
||||||
struct prefix_chain *pc;
|
|
||||||
struct node4 *n4;
|
|
||||||
struct node16 *n16;
|
|
||||||
struct node48 *n48;
|
|
||||||
struct node256 *n256;
|
|
||||||
|
|
||||||
switch (v.type) {
|
|
||||||
case UNSET:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE:
|
|
||||||
_dtr(rt, v.value);
|
|
||||||
nr = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_CHAIN:
|
|
||||||
vc = v.value.ptr;
|
|
||||||
_dtr(rt, vc->value);
|
|
||||||
nr = 1 + _free_node(rt, vc->child);
|
|
||||||
free(vc);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PREFIX_CHAIN:
|
|
||||||
pc = v.value.ptr;
|
|
||||||
nr = _free_node(rt, pc->child);
|
|
||||||
free(pc);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NODE4:
|
|
||||||
n4 = (struct node4 *) v.value.ptr;
|
|
||||||
for (i = 0; i < n4->nr_entries; i++)
|
|
||||||
nr += _free_node(rt, n4->values[i]);
|
|
||||||
free(n4);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NODE16:
|
|
||||||
n16 = (struct node16 *) v.value.ptr;
|
|
||||||
for (i = 0; i < n16->nr_entries; i++)
|
|
||||||
nr += _free_node(rt, n16->values[i]);
|
|
||||||
free(n16);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NODE48:
|
|
||||||
n48 = (struct node48 *) v.value.ptr;
|
|
||||||
for (i = 0; i < n48->nr_entries; i++)
|
|
||||||
nr += _free_node(rt, n48->values[i]);
|
|
||||||
free(n48);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NODE256:
|
|
||||||
n256 = (struct node256 *) v.value.ptr;
|
|
||||||
for (i = 0; i < 256; i++)
|
|
||||||
nr += _free_node(rt, n256->values[i]);
|
|
||||||
free(n256);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void radix_tree_destroy(struct radix_tree *rt)
|
|
||||||
{
|
|
||||||
_free_node(rt, rt->root);
|
|
||||||
free(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned radix_tree_size(struct radix_tree *rt)
|
|
||||||
{
|
|
||||||
return rt->nr_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv);
|
|
||||||
|
|
||||||
static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
unsigned len = ke - kb;
|
|
||||||
|
|
||||||
if (!len) {
|
|
||||||
// value
|
|
||||||
v->type = VALUE;
|
|
||||||
v->value = rv;
|
|
||||||
rt->nr_entries++;
|
|
||||||
} else {
|
|
||||||
// prefix -> value
|
|
||||||
struct prefix_chain *pc = zalloc(sizeof(*pc) + len);
|
|
||||||
if (!pc)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
pc->child.type = VALUE;
|
|
||||||
pc->child.value = rv;
|
|
||||||
pc->len = len;
|
|
||||||
memcpy(pc->prefix, kb, len);
|
|
||||||
v->type = PREFIX_CHAIN;
|
|
||||||
v->value.ptr = pc;
|
|
||||||
rt->nr_entries++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
unsigned len = ke - kb;
|
|
||||||
|
|
||||||
if (!len)
|
|
||||||
// overwrite
|
|
||||||
v->value = rv;
|
|
||||||
|
|
||||||
else {
|
|
||||||
// value_chain -> value
|
|
||||||
struct value_chain *vc = zalloc(sizeof(*vc));
|
|
||||||
if (!vc)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vc->value = v->value;
|
|
||||||
if (!_insert(rt, &vc->child, kb, ke, rv)) {
|
|
||||||
free(vc);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
v->type = VALUE_CHAIN;
|
|
||||||
v->value.ptr = vc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
struct value_chain *vc = v->value.ptr;
|
|
||||||
return _insert(rt, &vc->child, kb, ke, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned min(unsigned lhs, unsigned rhs)
|
|
||||||
{
|
|
||||||
if (lhs <= rhs)
|
|
||||||
return lhs;
|
|
||||||
else
|
|
||||||
return rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
struct prefix_chain *pc = v->value.ptr;
|
|
||||||
|
|
||||||
if (*kb == pc->prefix[0]) {
|
|
||||||
// There's a common prefix let's split the chain into two and
|
|
||||||
// recurse.
|
|
||||||
struct prefix_chain *pc2;
|
|
||||||
unsigned i, len = min(pc->len, ke - kb);
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
if (kb[i] != pc->prefix[i])
|
|
||||||
break;
|
|
||||||
|
|
||||||
pc2 = zalloc(sizeof(*pc2) + pc->len - i);
|
|
||||||
pc2->len = pc->len - i;
|
|
||||||
memmove(pc2->prefix, pc->prefix + i, pc2->len);
|
|
||||||
pc2->child = pc->child;
|
|
||||||
|
|
||||||
// FIXME: this trashes pc so we can't back out
|
|
||||||
pc->child.type = PREFIX_CHAIN;
|
|
||||||
pc->child.value.ptr = pc2;
|
|
||||||
pc->len = i;
|
|
||||||
|
|
||||||
if (!_insert(rt, &pc->child, kb + i, ke, rv)) {
|
|
||||||
free(pc2);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Stick an n4 in front.
|
|
||||||
struct node4 *n4 = zalloc(sizeof(*n4));
|
|
||||||
if (!n4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n4->keys[0] = *kb;
|
|
||||||
if (!_insert(rt, n4->values, kb + 1, ke, rv)) {
|
|
||||||
free(n4);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pc->len) {
|
|
||||||
n4->keys[1] = pc->prefix[0];
|
|
||||||
if (pc->len == 1) {
|
|
||||||
n4->values[1] = pc->child;
|
|
||||||
free(pc);
|
|
||||||
} else {
|
|
||||||
memmove(pc->prefix, pc->prefix + 1, pc->len - 1);
|
|
||||||
pc->len--;
|
|
||||||
n4->values[1] = *v;
|
|
||||||
}
|
|
||||||
n4->nr_entries = 2;
|
|
||||||
} else
|
|
||||||
n4->nr_entries = 1;
|
|
||||||
|
|
||||||
v->type = NODE4;
|
|
||||||
v->value.ptr = n4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
struct node4 *n4 = v->value.ptr;
|
|
||||||
if (n4->nr_entries == 4) {
|
|
||||||
struct node16 *n16 = zalloc(sizeof(*n16));
|
|
||||||
if (!n16)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n16->nr_entries = 5;
|
|
||||||
memcpy(n16->keys, n4->keys, sizeof(n4->keys));
|
|
||||||
memcpy(n16->values, n4->values, sizeof(n4->values));
|
|
||||||
|
|
||||||
n16->keys[4] = *kb;
|
|
||||||
if (!_insert(rt, n16->values + 4, kb + 1, ke, rv)) {
|
|
||||||
free(n16);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free(n4);
|
|
||||||
v->type = NODE16;
|
|
||||||
v->value.ptr = n16;
|
|
||||||
} else {
|
|
||||||
n4 = v->value.ptr;
|
|
||||||
if (!_insert(rt, n4->values + n4->nr_entries, kb + 1, ke, rv))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n4->keys[n4->nr_entries] = *kb;
|
|
||||||
n4->nr_entries++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
struct node16 *n16 = v->value.ptr;
|
|
||||||
|
|
||||||
if (n16->nr_entries == 16) {
|
|
||||||
unsigned i;
|
|
||||||
struct node48 *n48 = zalloc(sizeof(*n48));
|
|
||||||
|
|
||||||
if (!n48)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n48->nr_entries = 17;
|
|
||||||
memset(n48->keys, 48, sizeof(n48->keys));
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
n48->keys[n16->keys[i]] = i;
|
|
||||||
n48->values[i] = n16->values[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
n48->keys[*kb] = 16;
|
|
||||||
if (!_insert(rt, n48->values + 16, kb + 1, ke, rv)) {
|
|
||||||
free(n48);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(n16);
|
|
||||||
v->type = NODE48;
|
|
||||||
v->value.ptr = n48;
|
|
||||||
} else {
|
|
||||||
if (!_insert(rt, n16->values + n16->nr_entries, kb + 1, ke, rv))
|
|
||||||
return false;
|
|
||||||
n16->keys[n16->nr_entries] = *kb;
|
|
||||||
n16->nr_entries++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
struct node48 *n48 = v->value.ptr;
|
|
||||||
if (n48->nr_entries == 48) {
|
|
||||||
unsigned i;
|
|
||||||
struct node256 *n256 = zalloc(sizeof(*n256));
|
|
||||||
if (!n256)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
if (n48->keys[i] >= 48)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
n256->values[i] = n48->values[n48->keys[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_insert(rt, n256->values + *kb, kb + 1, ke, rv)) {
|
|
||||||
free(n256);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(n48);
|
|
||||||
v->type = NODE256;
|
|
||||||
v->value.ptr = n256;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (!_insert(rt, n48->values + n48->nr_entries, kb + 1, ke, rv))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n48->keys[*kb] = n48->nr_entries;
|
|
||||||
n48->nr_entries++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _insert_node256(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
struct node256 *n256 = v->value.ptr;
|
|
||||||
bool was_unset = n256->values[*kb].type == UNSET;
|
|
||||||
|
|
||||||
if (!_insert(rt, n256->values + *kb, kb + 1, ke, rv))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (was_unset)
|
|
||||||
n256->nr_entries++;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: the tree should not be touched if insert fails (eg, OOM)
|
|
||||||
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
if (kb == ke) {
|
|
||||||
if (v->type == UNSET) {
|
|
||||||
v->type = VALUE;
|
|
||||||
v->value = rv;
|
|
||||||
rt->nr_entries++;
|
|
||||||
|
|
||||||
} else if (v->type == VALUE) {
|
|
||||||
v->value = rv;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
struct value_chain *vc = zalloc(sizeof(*vc));
|
|
||||||
if (!vc)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vc->value = rv;
|
|
||||||
vc->child = *v;
|
|
||||||
v->type = VALUE_CHAIN;
|
|
||||||
v->value.ptr = vc;
|
|
||||||
rt->nr_entries++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (v->type) {
|
|
||||||
case UNSET:
|
|
||||||
return _insert_unset(rt, v, kb, ke, rv);
|
|
||||||
|
|
||||||
case VALUE:
|
|
||||||
return _insert_value(rt, v, kb, ke, rv);
|
|
||||||
|
|
||||||
case VALUE_CHAIN:
|
|
||||||
return _insert_value_chain(rt, v, kb, ke, rv);
|
|
||||||
|
|
||||||
case PREFIX_CHAIN:
|
|
||||||
return _insert_prefix_chain(rt, v, kb, ke, rv);
|
|
||||||
|
|
||||||
case NODE4:
|
|
||||||
return _insert_node4(rt, v, kb, ke, rv);
|
|
||||||
|
|
||||||
case NODE16:
|
|
||||||
return _insert_node16(rt, v, kb, ke, rv);
|
|
||||||
|
|
||||||
case NODE48:
|
|
||||||
return _insert_node48(rt, v, kb, ke, rv);
|
|
||||||
|
|
||||||
case NODE256:
|
|
||||||
return _insert_node256(rt, v, kb, ke, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't get here
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct lookup_result {
|
|
||||||
struct value *v;
|
|
||||||
uint8_t *kb;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t *ke)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
struct value_chain *vc;
|
|
||||||
struct prefix_chain *pc;
|
|
||||||
struct node4 *n4;
|
|
||||||
struct node16 *n16;
|
|
||||||
struct node48 *n48;
|
|
||||||
struct node256 *n256;
|
|
||||||
|
|
||||||
if (kb == ke)
|
|
||||||
return (struct lookup_result) {.v = v, .kb = kb};
|
|
||||||
|
|
||||||
switch (v->type) {
|
|
||||||
case UNSET:
|
|
||||||
case VALUE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_CHAIN:
|
|
||||||
vc = v->value.ptr;
|
|
||||||
return _lookup_prefix(&vc->child, kb, ke);
|
|
||||||
|
|
||||||
case PREFIX_CHAIN:
|
|
||||||
pc = v->value.ptr;
|
|
||||||
if (ke - kb < pc->len)
|
|
||||||
return (struct lookup_result) {.v = v, .kb = kb};
|
|
||||||
|
|
||||||
for (i = 0; i < pc->len; i++)
|
|
||||||
if (kb[i] != pc->prefix[i])
|
|
||||||
return (struct lookup_result) {.v = v, .kb = kb};
|
|
||||||
|
|
||||||
return _lookup_prefix(&pc->child, kb + pc->len, ke);
|
|
||||||
|
|
||||||
case NODE4:
|
|
||||||
n4 = v->value.ptr;
|
|
||||||
for (i = 0; i < n4->nr_entries; i++)
|
|
||||||
if (n4->keys[i] == *kb)
|
|
||||||
return _lookup_prefix(n4->values + i, kb + 1, ke);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NODE16:
|
|
||||||
// FIXME: use binary search or simd?
|
|
||||||
n16 = v->value.ptr;
|
|
||||||
for (i = 0; i < n16->nr_entries; i++)
|
|
||||||
if (n16->keys[i] == *kb)
|
|
||||||
return _lookup_prefix(n16->values + i, kb + 1, ke);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NODE48:
|
|
||||||
n48 = v->value.ptr;
|
|
||||||
i = n48->keys[*kb];
|
|
||||||
if (i < 48)
|
|
||||||
return _lookup_prefix(n48->values + i, kb + 1, ke);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NODE256:
|
|
||||||
n256 = v->value.ptr;
|
|
||||||
return _lookup_prefix(n256->values + *kb, kb + 1, ke);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (struct lookup_result) {.v = v, .kb = kb};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
|
||||||
{
|
|
||||||
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
|
|
||||||
return _insert(rt, lr.v, lr.kb, ke, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note the degrade functions also free the original node.
|
|
||||||
static void _degrade_to_n4(struct node16 *n16, struct value *result)
|
|
||||||
{
|
|
||||||
struct node4 *n4 = zalloc(sizeof(*n4));
|
|
||||||
|
|
||||||
n4->nr_entries = n16->nr_entries;
|
|
||||||
memcpy(n4->keys, n16->keys, n16->nr_entries * sizeof(*n4->keys));
|
|
||||||
memcpy(n4->values, n16->values, n16->nr_entries * sizeof(*n4->values));
|
|
||||||
free(n16);
|
|
||||||
|
|
||||||
result->type = NODE4;
|
|
||||||
result->value.ptr = n4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _degrade_to_n16(struct node48 *n48, struct value *result)
|
|
||||||
{
|
|
||||||
struct node4 *n16 = zalloc(sizeof(*n16));
|
|
||||||
|
|
||||||
n16->nr_entries = n48->nr_entries;
|
|
||||||
memcpy(n16->keys, n48->keys, n48->nr_entries * sizeof(*n16->keys));
|
|
||||||
memcpy(n16->values, n48->values, n48->nr_entries * sizeof(*n16->values));
|
|
||||||
free(n48);
|
|
||||||
|
|
||||||
result->type = NODE16;
|
|
||||||
result->value.ptr = n16;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _degrade_to_n48(struct node256 *n256, struct value *result)
|
|
||||||
{
|
|
||||||
unsigned i, count = 0;
|
|
||||||
struct node4 *n48 = zalloc(sizeof(*n48));
|
|
||||||
|
|
||||||
n48->nr_entries = n256->nr_entries;
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
if (n256->values[i].type == UNSET)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
n48->keys[count] = i;
|
|
||||||
n48->values[count] = n256->values[i];
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
free(n256);
|
|
||||||
|
|
||||||
result->type = NODE48;
|
|
||||||
result->value.ptr = n48;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke)
|
|
||||||
{
|
|
||||||
bool r;
|
|
||||||
unsigned i;
|
|
||||||
struct value_chain *vc;
|
|
||||||
struct prefix_chain *pc;
|
|
||||||
struct node4 *n4;
|
|
||||||
struct node16 *n16;
|
|
||||||
struct node48 *n48;
|
|
||||||
struct node256 *n256;
|
|
||||||
|
|
||||||
if (kb == ke) {
|
|
||||||
if (root->type == VALUE) {
|
|
||||||
root->type = UNSET;
|
|
||||||
_dtr(rt, root->value);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (root->type == VALUE_CHAIN) {
|
|
||||||
vc = root->value.ptr;
|
|
||||||
_dtr(rt, vc->value);
|
|
||||||
memcpy(root, &vc->child, sizeof(*root));
|
|
||||||
free(vc);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (root->type) {
|
|
||||||
case UNSET:
|
|
||||||
case VALUE:
|
|
||||||
// this is a value for a prefix of the key
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case VALUE_CHAIN:
|
|
||||||
vc = root->value.ptr;
|
|
||||||
r = _remove(rt, &vc->child, kb, ke);
|
|
||||||
if (r && (vc->child.type == UNSET)) {
|
|
||||||
memcpy(root, &vc->child, sizeof(*root));
|
|
||||||
free(vc);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
|
|
||||||
case PREFIX_CHAIN:
|
|
||||||
pc = root->value.ptr;
|
|
||||||
if (ke - kb < pc->len)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (i = 0; i < pc->len; i++)
|
|
||||||
if (kb[i] != pc->prefix[i])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return _remove(rt, &pc->child, kb + pc->len, ke);
|
|
||||||
|
|
||||||
case NODE4:
|
|
||||||
n4 = root->value.ptr;
|
|
||||||
for (i = 0; i < n4->nr_entries; i++) {
|
|
||||||
if (n4->keys[i] == *kb) {
|
|
||||||
r = _remove(rt, n4->values + i, kb + 1, ke);
|
|
||||||
if (r && n4->values[i].type == UNSET) {
|
|
||||||
n4->nr_entries--;
|
|
||||||
if (i < n4->nr_entries)
|
|
||||||
// slide the entries down
|
|
||||||
memmove(n4->keys + i, n4->keys + i + 1,
|
|
||||||
sizeof(*n4->keys) * (n4->nr_entries - i));
|
|
||||||
if (!n4->nr_entries)
|
|
||||||
root->type = UNSET;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case NODE16:
|
|
||||||
n16 = root->value.ptr;
|
|
||||||
for (i = 0; i < n16->nr_entries; i++) {
|
|
||||||
if (n16->keys[i] == *kb) {
|
|
||||||
r = _remove(rt, n16->values + i, kb + 1, ke);
|
|
||||||
if (r && n16->values[i].type == UNSET) {
|
|
||||||
n16->nr_entries--;
|
|
||||||
if (i < n16->nr_entries)
|
|
||||||
// slide the entries down
|
|
||||||
memmove(n16->keys + i, n16->keys + i + 1,
|
|
||||||
sizeof(*n16->keys) * (n16->nr_entries - i));
|
|
||||||
if (n16->nr_entries <= 4)
|
|
||||||
_degrade_to_n4(n16, root);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case NODE48:
|
|
||||||
n48 = root->value.ptr;
|
|
||||||
i = n48->keys[*kb];
|
|
||||||
if (i < 48) {
|
|
||||||
r = _remove(rt, n48->values + i, kb + 1, ke);
|
|
||||||
if (r && n48->values[i].type == UNSET) {
|
|
||||||
n48->keys[*kb] = 48;
|
|
||||||
n48->nr_entries--;
|
|
||||||
if (n48->nr_entries <= 16)
|
|
||||||
_degrade_to_n16(n48, root);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case NODE256:
|
|
||||||
n256 = root->value.ptr;
|
|
||||||
r = _remove(rt, n256->values + (*kb), kb + 1, ke);
|
|
||||||
if (r && n256->values[*kb].type == UNSET) {
|
|
||||||
n256->nr_entries--;
|
|
||||||
if (n256->nr_entries <= 48)
|
|
||||||
_degrade_to_n48(n256, root);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_end)
|
|
||||||
{
|
|
||||||
if (_remove(rt, &rt->root, key_begin, key_end)) {
|
|
||||||
rt->nr_entries--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _prefix_chain_matches(struct lookup_result *lr, uint8_t *ke)
|
|
||||||
{
|
|
||||||
// It's possible the top node is a prefix chain, and
|
|
||||||
// the remaining key matches part of it.
|
|
||||||
if (lr->v->type == PREFIX_CHAIN) {
|
|
||||||
unsigned i, rlen = ke - lr->kb;
|
|
||||||
struct prefix_chain *pc = lr->v->value.ptr;
|
|
||||||
if (rlen < pc->len) {
|
|
||||||
for (i = 0; i < rlen; i++)
|
|
||||||
if (pc->prefix[i] != lr->kb[i])
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
|
|
||||||
{
|
|
||||||
unsigned count = 0;
|
|
||||||
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
|
|
||||||
if (lr.kb == ke || _prefix_chain_matches(&lr, ke)) {
|
|
||||||
count = _free_node(rt, *lr.v);
|
|
||||||
lr.v->type = UNSET;
|
|
||||||
}
|
|
||||||
|
|
||||||
rt->nr_entries -= count;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool radix_tree_lookup(struct radix_tree *rt,
|
|
||||||
uint8_t *kb, uint8_t *ke, union radix_value *result)
|
|
||||||
{
|
|
||||||
struct value_chain *vc;
|
|
||||||
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
|
|
||||||
if (lr.kb == ke) {
|
|
||||||
switch (lr.v->type) {
|
|
||||||
case VALUE:
|
|
||||||
*result = lr.v->value;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case VALUE_CHAIN:
|
|
||||||
vc = lr.v->value.ptr;
|
|
||||||
*result = vc->value;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: build up the keys too
|
|
||||||
static bool _iterate(struct value *v, struct radix_tree_iterator *it)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
struct value_chain *vc;
|
|
||||||
struct prefix_chain *pc;
|
|
||||||
struct node4 *n4;
|
|
||||||
struct node16 *n16;
|
|
||||||
struct node48 *n48;
|
|
||||||
struct node256 *n256;
|
|
||||||
|
|
||||||
switch (v->type) {
|
|
||||||
case UNSET:
|
|
||||||
// can't happen
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE:
|
|
||||||
return it->visit(it, NULL, NULL, v->value);
|
|
||||||
|
|
||||||
case VALUE_CHAIN:
|
|
||||||
vc = v->value.ptr;
|
|
||||||
return it->visit(it, NULL, NULL, vc->value) && _iterate(&vc->child, it);
|
|
||||||
|
|
||||||
case PREFIX_CHAIN:
|
|
||||||
pc = v->value.ptr;
|
|
||||||
return _iterate(&pc->child, it);
|
|
||||||
|
|
||||||
case NODE4:
|
|
||||||
n4 = (struct node4 *) v->value.ptr;
|
|
||||||
for (i = 0; i < n4->nr_entries; i++)
|
|
||||||
if (!_iterate(n4->values + i, it))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case NODE16:
|
|
||||||
n16 = (struct node16 *) v->value.ptr;
|
|
||||||
for (i = 0; i < n16->nr_entries; i++)
|
|
||||||
if (!_iterate(n16->values + i, it))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case NODE48:
|
|
||||||
n48 = (struct node48 *) v->value.ptr;
|
|
||||||
for (i = 0; i < n48->nr_entries; i++)
|
|
||||||
if (!_iterate(n48->values + i, it))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case NODE256:
|
|
||||||
n256 = (struct node256 *) v->value.ptr;
|
|
||||||
for (i = 0; i < 256; i++)
|
|
||||||
if (n256->values[i].type != UNSET && !_iterate(n256->values + i, it))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't get here
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
|
|
||||||
struct radix_tree_iterator *it)
|
|
||||||
{
|
|
||||||
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
|
|
||||||
if (lr.kb == ke || _prefix_chain_matches(&lr, ke))
|
|
||||||
_iterate(lr.v, it);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
@@ -53,6 +54,11 @@ struct radix_tree_iterator {
|
|||||||
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
|
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
|
||||||
struct radix_tree_iterator *it);
|
struct radix_tree_iterator *it);
|
||||||
|
|
||||||
|
// Checks that some constraints on the shape of the tree are
|
||||||
|
// being held. For debug only.
|
||||||
|
bool radix_tree_is_well_formed(struct radix_tree *rt);
|
||||||
|
void radix_tree_dump(struct radix_tree *rt, FILE *out);
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
|
// Copyright (C) 2018 - 2020 Red Hat, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
// This file is part of LVM2.
|
// This file is part of LVM2.
|
||||||
//
|
//
|
||||||
@@ -13,10 +13,12 @@
|
|||||||
#ifndef BASE_MEMORY_CONTAINER_OF_H
|
#ifndef BASE_MEMORY_CONTAINER_OF_H
|
||||||
#define BASE_MEMORY_CONTAINER_OF_H
|
#define BASE_MEMORY_CONTAINER_OF_H
|
||||||
|
|
||||||
|
#include <stddef.h> // offsetof
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
#define container_of(v, t, head) \
|
#define container_of(v, t, head) \
|
||||||
((t *)((const char *)(v) - (const char *)&((t *) 0)->head))
|
((t *)((char *)(v) - offsetof(t, head)))
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -14,16 +14,12 @@
|
|||||||
#define BASE_MEMORY_ZALLOC_H
|
#define BASE_MEMORY_ZALLOC_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
static inline void *zalloc(size_t len)
|
static inline void *zalloc(size_t len)
|
||||||
{
|
{
|
||||||
void *ptr = malloc(len);
|
return calloc(1, len);
|
||||||
if (ptr)
|
|
||||||
memset(ptr, 0, len);
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of LVM2.
|
# This file is part of LVM2.
|
||||||
#
|
#
|
||||||
@@ -25,6 +25,7 @@ PROFILES=$(PROFILE_TEMPLATES) \
|
|||||||
$(srcdir)/cache-smq.profile \
|
$(srcdir)/cache-smq.profile \
|
||||||
$(srcdir)/thin-generic.profile \
|
$(srcdir)/thin-generic.profile \
|
||||||
$(srcdir)/thin-performance.profile \
|
$(srcdir)/thin-performance.profile \
|
||||||
|
$(srcdir)/vdo-small.profile \
|
||||||
$(srcdir)/lvmdbusd.profile
|
$(srcdir)/lvmdbusd.profile
|
||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
@@ -32,8 +33,8 @@ include $(top_builddir)/make.tmpl
|
|||||||
.PHONY: install_conf install_localconf install_profiles
|
.PHONY: install_conf install_localconf install_profiles
|
||||||
|
|
||||||
generate:
|
generate:
|
||||||
LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withgeneralpreamble --withcomments --ignorelocal --withspaces > example.conf.in
|
$(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withgeneralpreamble --withcomments --ignorelocal --withspaces > example.conf.in
|
||||||
LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withlocalpreamble --withcomments --withspaces local > lvmlocal.conf.in
|
$(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withlocalpreamble --withcomments --withspaces local > lvmlocal.conf.in
|
||||||
|
|
||||||
install_conf: $(CONFSRC)
|
install_conf: $(CONFSRC)
|
||||||
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||||
@@ -48,8 +49,9 @@ install_localconf: $(CONFLOCAL)
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
install_profiles: $(PROFILES)
|
install_profiles: $(PROFILES)
|
||||||
$(INSTALL_DIR) $(profiledir)
|
@echo " [INSTALL] $<"
|
||||||
$(INSTALL_DATA) $(PROFILES) $(profiledir)/
|
$(Q) $(INSTALL_DIR) $(profiledir)
|
||||||
|
$(Q) $(INSTALL_DATA) $(PROFILES) $(profiledir)/
|
||||||
|
|
||||||
install_lvm2: install_conf install_localconf install_profiles
|
install_lvm2: install_conf install_localconf install_profiles
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,22 @@ devices {
|
|||||||
#
|
#
|
||||||
external_device_info_source = "none"
|
external_device_info_source = "none"
|
||||||
|
|
||||||
|
# Configuration option devices/hints.
|
||||||
|
# Use a local file to remember which devices have PVs on them.
|
||||||
|
# Some commands will use this as an optimization to reduce device
|
||||||
|
# scanning, and will only scan the listed PVs. Removing the hint file
|
||||||
|
# will cause lvm to generate a new one. Disable hints if PVs will
|
||||||
|
# be copied onto devices using non-lvm commands, like dd.
|
||||||
|
#
|
||||||
|
# Accepted values:
|
||||||
|
# all
|
||||||
|
# Use all hints.
|
||||||
|
# none
|
||||||
|
# Use no hints.
|
||||||
|
#
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# hints = "all"
|
||||||
|
|
||||||
# Configuration option devices/preferred_names.
|
# Configuration option devices/preferred_names.
|
||||||
# Select which path name to display for a block device.
|
# Select which path name to display for a block device.
|
||||||
# If multiple path names exist for a block device, and LVM needs to
|
# If multiple path names exist for a block device, and LVM needs to
|
||||||
@@ -123,11 +139,10 @@ devices {
|
|||||||
# then the device is accepted. Be careful mixing 'a' and 'r' patterns,
|
# then the device is accepted. Be careful mixing 'a' and 'r' patterns,
|
||||||
# as the combination might produce unexpected results (test changes.)
|
# as the combination might produce unexpected results (test changes.)
|
||||||
# Run vgscan after changing the filter to regenerate the cache.
|
# Run vgscan after changing the filter to regenerate the cache.
|
||||||
# See the use_lvmetad comment for a special case regarding filters.
|
|
||||||
#
|
#
|
||||||
# Example
|
# Example
|
||||||
# Accept every block device:
|
# Accept every block device:
|
||||||
# filter = [ "a|.*/|" ]
|
# filter = [ "a|.*|" ]
|
||||||
# Reject the cdrom drive:
|
# Reject the cdrom drive:
|
||||||
# filter = [ "r|/dev/cdrom|" ]
|
# filter = [ "r|/dev/cdrom|" ]
|
||||||
# Work with just loopback devices, e.g. for testing:
|
# Work with just loopback devices, e.g. for testing:
|
||||||
@@ -135,38 +150,20 @@ devices {
|
|||||||
# Accept all loop devices and ide drives except hdc:
|
# Accept all loop devices and ide drives except hdc:
|
||||||
# filter = [ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
|
# filter = [ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
|
||||||
# Use anchors to be very specific:
|
# Use anchors to be very specific:
|
||||||
# filter = [ "a|^/dev/hda8$|", "r|.*/|" ]
|
# filter = [ "a|^/dev/hda8$|", "r|.*|" ]
|
||||||
#
|
#
|
||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# filter = [ "a|.*/|" ]
|
# filter = [ "a|.*|" ]
|
||||||
|
|
||||||
# Configuration option devices/global_filter.
|
# Configuration option devices/global_filter.
|
||||||
# Limit the block devices that are used by LVM system components.
|
# Limit the block devices that are used by LVM system components.
|
||||||
# Because devices/filter may be overridden from the command line, it is
|
# Because devices/filter may be overridden from the command line, it is
|
||||||
# not suitable for system-wide device filtering, e.g. udev and lvmetad.
|
# not suitable for system-wide device filtering, e.g. udev.
|
||||||
# Use global_filter to hide devices from these LVM system components.
|
# Use global_filter to hide devices from these LVM system components.
|
||||||
# The syntax is the same as devices/filter. Devices rejected by
|
# The syntax is the same as devices/filter. Devices rejected by
|
||||||
# global_filter are not opened by LVM.
|
# global_filter are not opened by LVM.
|
||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# global_filter = [ "a|.*/|" ]
|
# global_filter = [ "a|.*|" ]
|
||||||
|
|
||||||
# Configuration option devices/cache_dir.
|
|
||||||
# Directory in which to store the device cache file.
|
|
||||||
# The results of filtering are cached on disk to avoid rescanning dud
|
|
||||||
# devices (which can take a very long time). By default this cache is
|
|
||||||
# stored in a file named .cache. It is safe to delete this file; the
|
|
||||||
# tools regenerate it. If obtain_device_list_from_udev is enabled, the
|
|
||||||
# list of devices is obtained from udev and any existing .cache file
|
|
||||||
# is removed.
|
|
||||||
cache_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@"
|
|
||||||
|
|
||||||
# Configuration option devices/cache_file_prefix.
|
|
||||||
# A prefix used before the .cache file name. See devices/cache_dir.
|
|
||||||
cache_file_prefix = ""
|
|
||||||
|
|
||||||
# Configuration option devices/write_cache_state.
|
|
||||||
# Enable/disable writing the cache file. See devices/cache_dir.
|
|
||||||
write_cache_state = 1
|
|
||||||
|
|
||||||
# Configuration option devices/types.
|
# Configuration option devices/types.
|
||||||
# List of additional acceptable block device types.
|
# List of additional acceptable block device types.
|
||||||
@@ -185,14 +182,53 @@ devices {
|
|||||||
# present on the system. sysfs must be part of the kernel and mounted.)
|
# present on the system. sysfs must be part of the kernel and mounted.)
|
||||||
sysfs_scan = 1
|
sysfs_scan = 1
|
||||||
|
|
||||||
|
# Configuration option devices/scan_lvs.
|
||||||
|
# Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.
|
||||||
|
# When 1, LVM will detect PVs layered on LVs, and caution must be
|
||||||
|
# taken to avoid a host accessing a layered VG that may not belong
|
||||||
|
# to it, e.g. from a guest image. This generally requires excluding
|
||||||
|
# the LVs with device filters. Also, when this setting is enabled,
|
||||||
|
# every LVM command will scan every active LV on the system (unless
|
||||||
|
# filtered), which can cause performance problems on systems with
|
||||||
|
# many active LVs. When this setting is 0, LVM will not detect or
|
||||||
|
# use PVs that exist on LVs, and will not allow a PV to be created on
|
||||||
|
# an LV. The LVs are ignored using a built in device filter that
|
||||||
|
# identifies and excludes LVs.
|
||||||
|
scan_lvs = 0
|
||||||
|
|
||||||
# Configuration option devices/multipath_component_detection.
|
# Configuration option devices/multipath_component_detection.
|
||||||
# Ignore devices that are components of DM multipath devices.
|
# Ignore devices that are components of DM multipath devices.
|
||||||
multipath_component_detection = 1
|
multipath_component_detection = 1
|
||||||
|
|
||||||
# Configuration option devices/md_component_detection.
|
# Configuration option devices/md_component_detection.
|
||||||
# Ignore devices that are components of software RAID (md) devices.
|
# Enable detection and exclusion of MD component devices.
|
||||||
|
# An MD component device is a block device that MD uses as part
|
||||||
|
# of a software RAID virtual device. When an LVM PV is created
|
||||||
|
# on an MD device, LVM must only use the top level MD device as
|
||||||
|
# the PV, and should ignore the underlying component devices.
|
||||||
|
# In cases where the MD superblock is located at the end of the
|
||||||
|
# component devices, it is more difficult for LVM to consistently
|
||||||
|
# identify an MD component, see the md_component_checks setting.
|
||||||
md_component_detection = 1
|
md_component_detection = 1
|
||||||
|
|
||||||
|
# Configuration option devices/md_component_checks.
|
||||||
|
# The checks LVM should use to detect MD component devices.
|
||||||
|
# MD component devices are block devices used by MD software RAID.
|
||||||
|
#
|
||||||
|
# Accepted values:
|
||||||
|
# auto
|
||||||
|
# LVM will skip scanning the end of devices when it has other
|
||||||
|
# indications that the device is not an MD component.
|
||||||
|
# start
|
||||||
|
# LVM will only scan the start of devices for MD superblocks.
|
||||||
|
# This does not incur extra I/O by LVM.
|
||||||
|
# full
|
||||||
|
# LVM will scan the start and end of devices for MD superblocks.
|
||||||
|
# This requires an extra read at the end of devices.
|
||||||
|
#
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# md_component_checks = "auto"
|
||||||
|
|
||||||
# Configuration option devices/fw_raid_component_detection.
|
# Configuration option devices/fw_raid_component_detection.
|
||||||
# Ignore devices that are components of firmware RAID devices.
|
# Ignore devices that are components of firmware RAID devices.
|
||||||
# LVM must use an external_device_info_source other than none for this
|
# LVM must use an external_device_info_source other than none for this
|
||||||
@@ -200,19 +236,24 @@ devices {
|
|||||||
fw_raid_component_detection = 0
|
fw_raid_component_detection = 0
|
||||||
|
|
||||||
# Configuration option devices/md_chunk_alignment.
|
# Configuration option devices/md_chunk_alignment.
|
||||||
# Align PV data blocks with md device's stripe-width.
|
# Align the start of a PV data area with md device's stripe-width.
|
||||||
# This applies if a PV is placed directly on an md device.
|
# This applies if a PV is placed directly on an md device.
|
||||||
|
# default_data_alignment will be overriden if it is not aligned
|
||||||
|
# with the value detected for this setting.
|
||||||
|
# This setting is overriden by data_alignment_detection,
|
||||||
|
# data_alignment, and the --dataalignment option.
|
||||||
md_chunk_alignment = 1
|
md_chunk_alignment = 1
|
||||||
|
|
||||||
# Configuration option devices/default_data_alignment.
|
# Configuration option devices/default_data_alignment.
|
||||||
# Default alignment of the start of a PV data area in MB.
|
# Align the start of a PV data area with this number of MiB.
|
||||||
# If set to 0, a value of 64KiB will be used.
|
# Set to 1 for 1MiB, 2 for 2MiB, etc. Set to 0 to disable.
|
||||||
# Set to 1 for 1MiB, 2 for 2MiB, etc.
|
# This setting is overriden by data_alignment and the --dataalignment
|
||||||
|
# option.
|
||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# default_data_alignment = 1
|
# default_data_alignment = 1
|
||||||
|
|
||||||
# Configuration option devices/data_alignment_detection.
|
# Configuration option devices/data_alignment_detection.
|
||||||
# Detect PV data alignment based on sysfs device information.
|
# Align the start of a PV data area with sysfs io properties.
|
||||||
# The start of a PV data area will be a multiple of minimum_io_size or
|
# The start of a PV data area will be a multiple of minimum_io_size or
|
||||||
# optimal_io_size exposed in sysfs. minimum_io_size is the smallest
|
# optimal_io_size exposed in sysfs. minimum_io_size is the smallest
|
||||||
# request the device can perform without incurring a read-modify-write
|
# request the device can perform without incurring a read-modify-write
|
||||||
@@ -220,27 +261,29 @@ devices {
|
|||||||
# preferred unit of receiving I/O, e.g. MD stripe width.
|
# preferred unit of receiving I/O, e.g. MD stripe width.
|
||||||
# minimum_io_size is used if optimal_io_size is undefined (0).
|
# minimum_io_size is used if optimal_io_size is undefined (0).
|
||||||
# If md_chunk_alignment is enabled, that detects the optimal_io_size.
|
# If md_chunk_alignment is enabled, that detects the optimal_io_size.
|
||||||
# This setting takes precedence over md_chunk_alignment.
|
# default_data_alignment and md_chunk_alignment will be overriden
|
||||||
|
# if they are not aligned with the value detected for this setting.
|
||||||
|
# This setting is overriden by data_alignment and the --dataalignment
|
||||||
|
# option.
|
||||||
data_alignment_detection = 1
|
data_alignment_detection = 1
|
||||||
|
|
||||||
# Configuration option devices/data_alignment.
|
# Configuration option devices/data_alignment.
|
||||||
# Alignment of the start of a PV data area in KiB.
|
# Align the start of a PV data area with this number of KiB.
|
||||||
# If a PV is placed directly on an md device and md_chunk_alignment or
|
# When non-zero, this setting overrides default_data_alignment.
|
||||||
# data_alignment_detection are enabled, then this setting is ignored.
|
# Set to 0 to disable, in which case default_data_alignment
|
||||||
# Otherwise, md_chunk_alignment and data_alignment_detection are
|
# is used to align the first PE in units of MiB.
|
||||||
# disabled if this is set. Set to 0 to use the default alignment or the
|
# This setting is overriden by the --dataalignment option.
|
||||||
# page size, if larger.
|
|
||||||
data_alignment = 0
|
data_alignment = 0
|
||||||
|
|
||||||
# Configuration option devices/data_alignment_offset_detection.
|
# Configuration option devices/data_alignment_offset_detection.
|
||||||
# Detect PV data alignment offset based on sysfs device information.
|
# Shift the start of an aligned PV data area based on sysfs information.
|
||||||
# The start of a PV aligned data area will be shifted by the
|
# After a PV data area is aligned, it will be shifted by the
|
||||||
# alignment_offset exposed in sysfs. This offset is often 0, but may
|
# alignment_offset exposed in sysfs. This offset is often 0, but may
|
||||||
# be non-zero. Certain 4KiB sector drives that compensate for windows
|
# be non-zero. Certain 4KiB sector drives that compensate for windows
|
||||||
# partitioning will have an alignment_offset of 3584 bytes (sector 7
|
# partitioning will have an alignment_offset of 3584 bytes (sector 7
|
||||||
# is the lowest aligned logical block, the 4KiB sectors start at
|
# is the lowest aligned logical block, the 4KiB sectors start at
|
||||||
# LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).
|
# LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).
|
||||||
# pvcreate --dataalignmentoffset will skip this detection.
|
# This setting is overriden by the --dataalignmentoffset option.
|
||||||
data_alignment_offset_detection = 1
|
data_alignment_offset_detection = 1
|
||||||
|
|
||||||
# Configuration option devices/ignore_suspended_devices.
|
# Configuration option devices/ignore_suspended_devices.
|
||||||
@@ -268,14 +311,6 @@ devices {
|
|||||||
# different way, making them a better choice for VG stacking.
|
# different way, making them a better choice for VG stacking.
|
||||||
ignore_lvm_mirrors = 1
|
ignore_lvm_mirrors = 1
|
||||||
|
|
||||||
# Configuration option devices/disable_after_error_count.
|
|
||||||
# Number of I/O errors after which a device is skipped.
|
|
||||||
# During each LVM operation, errors received from each device are
|
|
||||||
# counted. If the counter of a device exceeds the limit set here,
|
|
||||||
# no further I/O is sent to that device for the remainder of the
|
|
||||||
# operation. Setting this to 0 disables the counters altogether.
|
|
||||||
disable_after_error_count = 0
|
|
||||||
|
|
||||||
# Configuration option devices/require_restorefile_with_uuid.
|
# Configuration option devices/require_restorefile_with_uuid.
|
||||||
# Allow use of pvcreate --uuid without requiring --restorefile.
|
# Allow use of pvcreate --uuid without requiring --restorefile.
|
||||||
require_restorefile_with_uuid = 1
|
require_restorefile_with_uuid = 1
|
||||||
@@ -312,6 +347,12 @@ devices {
|
|||||||
# Enabling this setting allows the VG to be used as usual even with
|
# Enabling this setting allows the VG to be used as usual even with
|
||||||
# uncertain devices.
|
# uncertain devices.
|
||||||
allow_changes_with_duplicate_pvs = 0
|
allow_changes_with_duplicate_pvs = 0
|
||||||
|
|
||||||
|
# Configuration option devices/allow_mixed_block_sizes.
|
||||||
|
# Allow PVs in the same VG with different logical block sizes.
|
||||||
|
# When allowed, the user is responsible to ensure that an LV is
|
||||||
|
# using PVs with matching block sizes when necessary.
|
||||||
|
allow_mixed_block_sizes = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration section allocation.
|
# Configuration section allocation.
|
||||||
@@ -346,7 +387,7 @@ allocation {
|
|||||||
maximise_cling = 1
|
maximise_cling = 1
|
||||||
|
|
||||||
# Configuration option allocation/use_blkid_wiping.
|
# Configuration option allocation/use_blkid_wiping.
|
||||||
# Use blkid to detect existing signatures on new PVs and LVs.
|
# Use blkid to detect and erase existing signatures on new PVs and LVs.
|
||||||
# The blkid library can detect more signatures than the native LVM
|
# The blkid library can detect more signatures than the native LVM
|
||||||
# detection code, but may take longer. LVM needs to be compiled with
|
# detection code, but may take longer. LVM needs to be compiled with
|
||||||
# blkid wiping support for this setting to apply. LVM native detection
|
# blkid wiping support for this setting to apply. LVM native detection
|
||||||
@@ -388,7 +429,8 @@ allocation {
|
|||||||
|
|
||||||
# Configuration option allocation/cache_pool_metadata_require_separate_pvs.
|
# Configuration option allocation/cache_pool_metadata_require_separate_pvs.
|
||||||
# Cache pool metadata and data will always use different PVs.
|
# Cache pool metadata and data will always use different PVs.
|
||||||
cache_pool_metadata_require_separate_pvs = 0
|
# This configuration option has an automatic default value.
|
||||||
|
# cache_pool_metadata_require_separate_pvs = 0
|
||||||
|
|
||||||
# Configuration option allocation/cache_metadata_format.
|
# Configuration option allocation/cache_metadata_format.
|
||||||
# Sets default metadata format for new cache.
|
# Sets default metadata format for new cache.
|
||||||
@@ -447,8 +489,9 @@ allocation {
|
|||||||
# This configuration option does not have a default value defined.
|
# This configuration option does not have a default value defined.
|
||||||
|
|
||||||
# Configuration option allocation/thin_pool_metadata_require_separate_pvs.
|
# Configuration option allocation/thin_pool_metadata_require_separate_pvs.
|
||||||
# Thin pool metdata and data will always use different PVs.
|
# Thin pool metadata and data will always use different PVs.
|
||||||
thin_pool_metadata_require_separate_pvs = 0
|
# This configuration option has an automatic default value.
|
||||||
|
# thin_pool_metadata_require_separate_pvs = 0
|
||||||
|
|
||||||
# Configuration option allocation/thin_pool_zero.
|
# Configuration option allocation/thin_pool_zero.
|
||||||
# Thin pool data chunks are zeroed before they are first used.
|
# Thin pool data chunks are zeroed before they are first used.
|
||||||
@@ -485,6 +528,11 @@ allocation {
|
|||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# thin_pool_chunk_size_policy = "generic"
|
# thin_pool_chunk_size_policy = "generic"
|
||||||
|
|
||||||
|
# Configuration option allocation/zero_metadata.
|
||||||
|
# Zero whole metadata area before use with thin or cache pool.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# zero_metadata = 1
|
||||||
|
|
||||||
# Configuration option allocation/thin_pool_chunk_size.
|
# Configuration option allocation/thin_pool_chunk_size.
|
||||||
# The minimal chunk size in KiB for thin pool volumes.
|
# The minimal chunk size in KiB for thin pool volumes.
|
||||||
# Larger chunk sizes may improve performance for plain thin volumes,
|
# Larger chunk sizes may improve performance for plain thin volumes,
|
||||||
@@ -498,6 +546,154 @@ allocation {
|
|||||||
# Default physical extent size in KiB to use for new VGs.
|
# Default physical extent size in KiB to use for new VGs.
|
||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# physical_extent_size = 4096
|
# physical_extent_size = 4096
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_use_compression.
|
||||||
|
# Enables or disables compression when creating a VDO volume.
|
||||||
|
# Compression may be disabled if necessary to maximize performance
|
||||||
|
# or to speed processing of data that is unlikely to compress.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_use_compression = 1
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_use_deduplication.
|
||||||
|
# Enables or disables deduplication when creating a VDO volume.
|
||||||
|
# Deduplication may be disabled in instances where data is not expected
|
||||||
|
# to have good deduplication rates but compression is still desired.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_use_deduplication = 1
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_use_metadata_hints.
|
||||||
|
# Enables or disables whether VDO volume should tag its latency-critical
|
||||||
|
# writes with the REQ_SYNC flag. Some device mapper targets such as dm-raid5
|
||||||
|
# process writes with this flag at a higher priority.
|
||||||
|
# Default is enabled.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_use_metadata_hints = 1
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_minimum_io_size.
|
||||||
|
# The minimum IO size for VDO volume to accept, in bytes.
|
||||||
|
# Valid values are 512 or 4096. The recommended and default value is 4096.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_minimum_io_size = 4096
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_block_map_cache_size_mb.
|
||||||
|
# Specifies the amount of memory in MiB allocated for caching block map
|
||||||
|
# pages for VDO volume. The value must be a multiple of 4096 and must be
|
||||||
|
# at least 128MiB and less than 16TiB. The cache must be at least 16MiB
|
||||||
|
# per logical thread. Note that there is a memory overhead of 15%.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_block_map_cache_size_mb = 128
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_block_map_period.
|
||||||
|
# The speed with which the block map cache writes out modified block map pages.
|
||||||
|
# A smaller era length is likely to reduce the amount time spent rebuilding,
|
||||||
|
# at the cost of increased block map writes during normal operation.
|
||||||
|
# The maximum and recommended value is 16380; the minimum value is 1.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_block_map_period = 16380
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_check_point_frequency.
|
||||||
|
# The default check point frequency for VDO volume.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_check_point_frequency = 0
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_use_sparse_index.
|
||||||
|
# Enables sparse indexing for VDO volume.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_use_sparse_index = 0
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_index_memory_size_mb.
|
||||||
|
# Specifies the amount of index memory in MiB for VDO volume.
|
||||||
|
# The value must be at least 256MiB and at most 1TiB.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_index_memory_size_mb = 256
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_slab_size_mb.
|
||||||
|
# Specifies the size in MiB of the increment by which a VDO is grown.
|
||||||
|
# Using a smaller size constrains the total maximum physical size
|
||||||
|
# that can be accommodated. Must be a power of two between 128MiB and 32GiB.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_slab_size_mb = 2048
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_ack_threads.
|
||||||
|
# Specifies the number of threads to use for acknowledging
|
||||||
|
# completion of requested VDO I/O operations.
|
||||||
|
# The value must be at in range [0..100].
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_ack_threads = 1
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_bio_threads.
|
||||||
|
# Specifies the number of threads to use for submitting I/O
|
||||||
|
# operations to the storage device of VDO volume.
|
||||||
|
# The value must be in range [1..100]
|
||||||
|
# Each additional thread after the first will use an additional 18MiB of RAM,
|
||||||
|
# plus 1.12 MiB of RAM per megabyte of configured read cache size.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_bio_threads = 4
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_bio_rotation.
|
||||||
|
# Specifies the number of I/O operations to enqueue for each bio-submission
|
||||||
|
# thread before directing work to the next. The value must be in range [1..1024].
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_bio_rotation = 64
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_cpu_threads.
|
||||||
|
# Specifies the number of threads to use for CPU-intensive work such as
|
||||||
|
# hashing or compression for VDO volume. The value must be in range [1..100]
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_cpu_threads = 2
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_hash_zone_threads.
|
||||||
|
# Specifies the number of threads across which to subdivide parts of the VDO
|
||||||
|
# processing based on the hash value computed from the block data.
|
||||||
|
# The value must be at in range [0..100].
|
||||||
|
# vdo_hash_zone_threads, vdo_logical_threads and vdo_physical_threads must be
|
||||||
|
# either all zero or all non-zero.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_hash_zone_threads = 1
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_logical_threads.
|
||||||
|
# Specifies the number of threads across which to subdivide parts of the VDO
|
||||||
|
# processing based on the hash value computed from the block data.
|
||||||
|
# A logical thread count of 9 or more will require explicitly specifying
|
||||||
|
# a sufficiently large block map cache size, as well.
|
||||||
|
# The value must be in range [0..100].
|
||||||
|
# vdo_hash_zone_threads, vdo_logical_threads and vdo_physical_threads must be
|
||||||
|
# either all zero or all non-zero.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_logical_threads = 1
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_physical_threads.
|
||||||
|
# Specifies the number of threads across which to subdivide parts of the VDO
|
||||||
|
# processing based on physical block addresses.
|
||||||
|
# Each additional thread after the first will use an additional 10MiB of RAM.
|
||||||
|
# The value must be in range [0..16].
|
||||||
|
# vdo_hash_zone_threads, vdo_logical_threads and vdo_physical_threads must be
|
||||||
|
# either all zero or all non-zero.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_physical_threads = 1
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_write_policy.
|
||||||
|
# Specifies the write policy:
|
||||||
|
# auto - VDO will check the storage device and determine whether it supports flushes.
|
||||||
|
# If it does, VDO will run in async mode, otherwise it will run in sync mode.
|
||||||
|
# sync - Writes are acknowledged only after data is stably written.
|
||||||
|
# This policy is not supported if the underlying storage is not also synchronous.
|
||||||
|
# async - Writes are acknowledged after data has been cached for writing to stable storage.
|
||||||
|
# Data which has not been flushed is not guaranteed to persist in this mode.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_write_policy = "auto"
|
||||||
|
|
||||||
|
# Configuration option allocation/vdo_max_discard.
|
||||||
|
# Specified te maximum size of discard bio accepted, in 4096 byte blocks.
|
||||||
|
# I/O requests to a VDO volume are normally split into 4096-byte blocks,
|
||||||
|
# and processed up to 2048 at a time. However, discard requests to a VDO volume
|
||||||
|
# can be automatically split to a larger size, up to <max discard> 4096-byte blocks
|
||||||
|
# in a single bio, and are limited to 1500 at a time.
|
||||||
|
# Increasing this value may provide better overall performance, at the cost of
|
||||||
|
# increased latency for the individual discard requests.
|
||||||
|
# The default and minimum is 1. The maximum is UINT_MAX / 4096.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_max_discard = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration section log.
|
# Configuration section log.
|
||||||
@@ -588,7 +784,8 @@ log {
|
|||||||
|
|
||||||
# Configuration option log/indent.
|
# Configuration option log/indent.
|
||||||
# Indent messages according to their severity.
|
# Indent messages according to their severity.
|
||||||
indent = 1
|
# This configuration option has an automatic default value.
|
||||||
|
# indent = 0
|
||||||
|
|
||||||
# Configuration option log/command_names.
|
# Configuration option log/command_names.
|
||||||
# Display the command name on each line of output.
|
# Display the command name on each line of output.
|
||||||
@@ -611,9 +808,23 @@ log {
|
|||||||
# Select log messages by class.
|
# Select log messages by class.
|
||||||
# Some debugging messages are assigned to a class and only appear in
|
# Some debugging messages are assigned to a class and only appear in
|
||||||
# debug output if the class is listed here. Classes currently
|
# debug output if the class is listed here. Classes currently
|
||||||
# available: memory, devices, io, activation, allocation, lvmetad,
|
# available: memory, devices, io, activation, allocation,
|
||||||
# metadata, cache, locking, lvmpolld. Use "all" to see everything.
|
# metadata, cache, locking, lvmpolld. Use "all" to see everything.
|
||||||
debug_classes = [ "memory", "devices", "io", "activation", "allocation", "lvmetad", "metadata", "cache", "locking", "lvmpolld", "dbus" ]
|
debug_classes = [ "memory", "devices", "io", "activation", "allocation", "metadata", "cache", "locking", "lvmpolld", "dbus" ]
|
||||||
|
|
||||||
|
# Configuration option log/debug_file_fields.
|
||||||
|
# The fields included in debug output written to log file.
|
||||||
|
# Use "all" to include everything (the default).
|
||||||
|
# This configuration option is advanced.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# debug_file_fields = [ "time", "command", "fileline", "message" ]
|
||||||
|
|
||||||
|
# Configuration option log/debug_output_fields.
|
||||||
|
# The fields included in debug output written to stderr.
|
||||||
|
# Use "all" to include everything (the default).
|
||||||
|
# This configuration option is advanced.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# debug_output_fields = [ "time", "command", "fileline", "message" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration section backup.
|
# Configuration section backup.
|
||||||
@@ -701,23 +912,6 @@ global {
|
|||||||
# the error messages.
|
# the error messages.
|
||||||
activation = 1
|
activation = 1
|
||||||
|
|
||||||
# Configuration option global/fallback_to_lvm1.
|
|
||||||
# This setting is no longer used.
|
|
||||||
# This configuration option has an automatic default value.
|
|
||||||
# fallback_to_lvm1 = 0
|
|
||||||
|
|
||||||
# Configuration option global/format.
|
|
||||||
# This setting is no longer used.
|
|
||||||
# This configuration option has an automatic default value.
|
|
||||||
# format = "lvm2"
|
|
||||||
|
|
||||||
# Configuration option global/format_libraries.
|
|
||||||
# This setting is no longer used.
|
|
||||||
# This configuration option does not have a default value defined.
|
|
||||||
|
|
||||||
# Configuration option global/segment_libraries.
|
|
||||||
# This configuration option does not have a default value defined.
|
|
||||||
|
|
||||||
# Configuration option global/proc.
|
# Configuration option global/proc.
|
||||||
# Location of proc filesystem.
|
# Location of proc filesystem.
|
||||||
# This configuration option is advanced.
|
# This configuration option is advanced.
|
||||||
@@ -727,57 +921,10 @@ global {
|
|||||||
# Location of /etc system configuration directory.
|
# Location of /etc system configuration directory.
|
||||||
etc = "@CONFDIR@"
|
etc = "@CONFDIR@"
|
||||||
|
|
||||||
# Configuration option global/locking_type.
|
|
||||||
# Type of locking to use.
|
|
||||||
#
|
|
||||||
# Accepted values:
|
|
||||||
# 0
|
|
||||||
# Turns off locking. Warning: this risks metadata corruption if
|
|
||||||
# commands run concurrently.
|
|
||||||
# 1
|
|
||||||
# LVM uses local file-based locking, the standard mode.
|
|
||||||
# 2
|
|
||||||
# LVM uses the external shared library locking_library.
|
|
||||||
# 3
|
|
||||||
# LVM uses built-in clustered locking with clvmd.
|
|
||||||
# This is incompatible with lvmetad. If use_lvmetad is enabled,
|
|
||||||
# LVM prints a warning and disables lvmetad use.
|
|
||||||
# 4
|
|
||||||
# LVM uses read-only locking which forbids any operations that
|
|
||||||
# might change metadata.
|
|
||||||
# 5
|
|
||||||
# Offers dummy locking for tools that do not need any locks.
|
|
||||||
# You should not need to set this directly; the tools will select
|
|
||||||
# when to use it instead of the configured locking_type.
|
|
||||||
# Do not use lvmetad or the kernel device-mapper driver with this
|
|
||||||
# locking type. It is used by the --readonly option that offers
|
|
||||||
# read-only access to Volume Group metadata that cannot be locked
|
|
||||||
# safely because it belongs to an inaccessible domain and might be
|
|
||||||
# in use, for example a virtual machine image or a disk that is
|
|
||||||
# shared by a clustered machine.
|
|
||||||
#
|
|
||||||
locking_type = 1
|
|
||||||
|
|
||||||
# Configuration option global/wait_for_locks.
|
# Configuration option global/wait_for_locks.
|
||||||
# When disabled, fail if a lock request would block.
|
# When disabled, fail if a lock request would block.
|
||||||
wait_for_locks = 1
|
wait_for_locks = 1
|
||||||
|
|
||||||
# Configuration option global/fallback_to_clustered_locking.
|
|
||||||
# Attempt to use built-in cluster locking if locking_type 2 fails.
|
|
||||||
# If using external locking (type 2) and initialisation fails, with
|
|
||||||
# this enabled, an attempt will be made to use the built-in clustered
|
|
||||||
# locking. Disable this if using a customised locking_library.
|
|
||||||
fallback_to_clustered_locking = 1
|
|
||||||
|
|
||||||
# Configuration option global/fallback_to_local_locking.
|
|
||||||
# Use locking_type 1 (local) if locking_type 2 or 3 fail.
|
|
||||||
# If an attempt to initialise type 2 or type 3 locking failed, perhaps
|
|
||||||
# because cluster components such as clvmd are not running, with this
|
|
||||||
# enabled, an attempt will be made to use local file-based locking
|
|
||||||
# (type 1). If this succeeds, only commands against local VGs will
|
|
||||||
# proceed. VGs marked as clustered will be ignored.
|
|
||||||
fallback_to_local_locking = 1
|
|
||||||
|
|
||||||
# Configuration option global/locking_dir.
|
# Configuration option global/locking_dir.
|
||||||
# Directory to use for LVM command file locks.
|
# Directory to use for LVM command file locks.
|
||||||
# Local non-LV directory that holds file-based locks while commands are
|
# Local non-LV directory that holds file-based locks while commands are
|
||||||
@@ -798,11 +945,6 @@ global {
|
|||||||
# Search this directory first for shared libraries.
|
# Search this directory first for shared libraries.
|
||||||
# This configuration option does not have a default value defined.
|
# This configuration option does not have a default value defined.
|
||||||
|
|
||||||
# Configuration option global/locking_library.
|
|
||||||
# The external locking library to use for locking_type 2.
|
|
||||||
# This configuration option has an automatic default value.
|
|
||||||
# locking_library = "liblvm2clusterlock.so"
|
|
||||||
|
|
||||||
# Configuration option global/abort_on_internal_errors.
|
# Configuration option global/abort_on_internal_errors.
|
||||||
# Abort a command that encounters an internal error.
|
# Abort a command that encounters an internal error.
|
||||||
# Treat any internal errors as fatal errors, aborting the process that
|
# Treat any internal errors as fatal errors, aborting the process that
|
||||||
@@ -843,6 +985,17 @@ global {
|
|||||||
#
|
#
|
||||||
mirror_segtype_default = "@DEFAULT_MIRROR_SEGTYPE@"
|
mirror_segtype_default = "@DEFAULT_MIRROR_SEGTYPE@"
|
||||||
|
|
||||||
|
# Configuration option global/support_mirrored_mirror_log.
|
||||||
|
# Enable mirrored 'mirror' log type for testing.
|
||||||
|
#
|
||||||
|
# This type is deprecated to create or convert to but can
|
||||||
|
# be enabled to test that activation of existing mirrored
|
||||||
|
# logs and conversion to disk/core works.
|
||||||
|
#
|
||||||
|
# Not supported for regular operation!
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# support_mirrored_mirror_log = 0
|
||||||
|
|
||||||
# Configuration option global/raid10_segtype_default.
|
# Configuration option global/raid10_segtype_default.
|
||||||
# The segment type used by the -i -m combination.
|
# The segment type used by the -i -m combination.
|
||||||
# The --type raid10|mirror option overrides this setting.
|
# The --type raid10|mirror option overrides this setting.
|
||||||
@@ -891,47 +1044,22 @@ global {
|
|||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# lvdisplay_shows_full_device_path = 0
|
# lvdisplay_shows_full_device_path = 0
|
||||||
|
|
||||||
|
# Configuration option global/event_activation.
|
||||||
|
# Activate LVs based on system-generated device events.
|
||||||
|
# When a device appears on the system, a system-generated event runs
|
||||||
|
# the pvscan command to activate LVs if the new PV completes the VG.
|
||||||
|
# Use auto_activation_volume_list to select which LVs should be
|
||||||
|
# activated from these events (the default is all.)
|
||||||
|
# When event_activation is disabled, the system will generally run
|
||||||
|
# a direct activation command to activate LVs in complete VGs.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# event_activation = 1
|
||||||
|
|
||||||
# Configuration option global/use_aio.
|
# Configuration option global/use_aio.
|
||||||
# Use async I/O when reading and writing devices.
|
# Use async I/O when reading and writing devices.
|
||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# use_aio = 1
|
# use_aio = 1
|
||||||
|
|
||||||
# Configuration option global/use_lvmetad.
|
|
||||||
# Use lvmetad to cache metadata and reduce disk scanning.
|
|
||||||
# When enabled (and running), lvmetad provides LVM commands with VG
|
|
||||||
# metadata and PV state. LVM commands then avoid reading this
|
|
||||||
# information from disks which can be slow. When disabled (or not
|
|
||||||
# running), LVM commands fall back to scanning disks to obtain VG
|
|
||||||
# metadata. lvmetad is kept updated via udev rules which must be set
|
|
||||||
# up for LVM to work correctly. (The udev rules should be installed
|
|
||||||
# by default.) Without a proper udev setup, changes in the system's
|
|
||||||
# block device configuration will be unknown to LVM, and ignored
|
|
||||||
# until a manual 'pvscan --cache' is run. If lvmetad was running
|
|
||||||
# while use_lvmetad was disabled, it must be stopped, use_lvmetad
|
|
||||||
# enabled, and then started. When using lvmetad, LV activation is
|
|
||||||
# switched to an automatic, event-based mode. In this mode, LVs are
|
|
||||||
# activated based on incoming udev events that inform lvmetad when
|
|
||||||
# PVs appear on the system. When a VG is complete (all PVs present),
|
|
||||||
# it is auto-activated. The auto_activation_volume_list setting
|
|
||||||
# controls which LVs are auto-activated (all by default.)
|
|
||||||
# When lvmetad is updated (automatically by udev events, or directly
|
|
||||||
# by pvscan --cache), devices/filter is ignored and all devices are
|
|
||||||
# scanned by default. lvmetad always keeps unfiltered information
|
|
||||||
# which is provided to LVM commands. Each LVM command then filters
|
|
||||||
# based on devices/filter. This does not apply to other, non-regexp,
|
|
||||||
# filtering settings: component filters such as multipath and MD
|
|
||||||
# are checked during pvscan --cache. To filter a device and prevent
|
|
||||||
# scanning from the LVM system entirely, including lvmetad, use
|
|
||||||
# devices/global_filter.
|
|
||||||
use_lvmetad = @DEFAULT_USE_LVMETAD@
|
|
||||||
|
|
||||||
# Configuration option global/lvmetad_update_wait_time.
|
|
||||||
# Number of seconds a command will wait for lvmetad update to finish.
|
|
||||||
# After waiting for this period, a command will not use lvmetad, and
|
|
||||||
# will revert to disk scanning.
|
|
||||||
# This configuration option has an automatic default value.
|
|
||||||
# lvmetad_update_wait_time = 10
|
|
||||||
|
|
||||||
# Configuration option global/use_lvmlockd.
|
# Configuration option global/use_lvmlockd.
|
||||||
# Use lvmlockd for locking among hosts using LVM on shared storage.
|
# Use lvmlockd for locking among hosts using LVM on shared storage.
|
||||||
# Applicable only if LVM is compiled with lockd support in which
|
# Applicable only if LVM is compiled with lockd support in which
|
||||||
@@ -1056,6 +1184,17 @@ global {
|
|||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# cache_repair_options = [ "" ]
|
# cache_repair_options = [ "" ]
|
||||||
|
|
||||||
|
# Configuration option global/vdo_format_executable.
|
||||||
|
# The full path to the vdoformat command.
|
||||||
|
# LVM uses this command to initial data volume for VDO type logical volume
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_format_executable = "@VDO_FORMAT_CMD@"
|
||||||
|
|
||||||
|
# Configuration option global/vdo_format_options.
|
||||||
|
# List of options passed added to standard vdoformat command.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_format_options = [ "" ]
|
||||||
|
|
||||||
# Configuration option global/fsadm_executable.
|
# Configuration option global/fsadm_executable.
|
||||||
# The full path to the fsadm command.
|
# The full path to the fsadm command.
|
||||||
# LVM uses this command to help with lvresize -r operations.
|
# LVM uses this command to help with lvresize -r operations.
|
||||||
@@ -1113,6 +1252,16 @@ global {
|
|||||||
# When enabled, an LVM command that changes PVs, changes VG metadata,
|
# When enabled, an LVM command that changes PVs, changes VG metadata,
|
||||||
# or changes the activation state of an LV will send a notification.
|
# or changes the activation state of an LV will send a notification.
|
||||||
notify_dbus = 1
|
notify_dbus = 1
|
||||||
|
|
||||||
|
# Configuration option global/io_memory_size.
|
||||||
|
# The amount of memory in KiB that LVM allocates to perform disk io.
|
||||||
|
# LVM performance may benefit from more io memory when there are many
|
||||||
|
# disks or VG metadata is large. Increasing this size may be necessary
|
||||||
|
# when a single copy of VG metadata is larger than the current setting.
|
||||||
|
# This value should usually not be decreased from the default; setting
|
||||||
|
# it too low can result in lvm failing to read VGs.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# io_memory_size = 8192
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration section activation.
|
# Configuration section activation.
|
||||||
@@ -1148,7 +1297,8 @@ activation {
|
|||||||
# This enables additional checks (and if necessary, repairs) on entries
|
# This enables additional checks (and if necessary, repairs) on entries
|
||||||
# in the device directory after udev has completed processing its
|
# in the device directory after udev has completed processing its
|
||||||
# events. Useful for diagnosing problems with LVM/udev interactions.
|
# events. Useful for diagnosing problems with LVM/udev interactions.
|
||||||
verify_udev_operations = 0
|
# This configuration option has an automatic default value.
|
||||||
|
# verify_udev_operations = 0
|
||||||
|
|
||||||
# Configuration option activation/retry_deactivation.
|
# Configuration option activation/retry_deactivation.
|
||||||
# Retry failed LV deactivation.
|
# Retry failed LV deactivation.
|
||||||
@@ -1173,23 +1323,27 @@ activation {
|
|||||||
# When disabled, the striped target is used. The linear target is an
|
# When disabled, the striped target is used. The linear target is an
|
||||||
# optimised version of the striped target that only handles a single
|
# optimised version of the striped target that only handles a single
|
||||||
# stripe.
|
# stripe.
|
||||||
use_linear_target = 1
|
# This configuration option has an automatic default value.
|
||||||
|
# use_linear_target = 1
|
||||||
|
|
||||||
# Configuration option activation/reserved_stack.
|
# Configuration option activation/reserved_stack.
|
||||||
# Stack size in KiB to reserve for use while devices are suspended.
|
# Stack size in KiB to reserve for use while devices are suspended.
|
||||||
# Insufficent reserve risks I/O deadlock during device suspension.
|
# Insufficent reserve risks I/O deadlock during device suspension.
|
||||||
reserved_stack = 64
|
# This configuration option has an automatic default value.
|
||||||
|
# reserved_stack = 64
|
||||||
|
|
||||||
# Configuration option activation/reserved_memory.
|
# Configuration option activation/reserved_memory.
|
||||||
# Memory size in KiB to reserve for use while devices are suspended.
|
# Memory size in KiB to reserve for use while devices are suspended.
|
||||||
# Insufficent reserve risks I/O deadlock during device suspension.
|
# Insufficent reserve risks I/O deadlock during device suspension.
|
||||||
reserved_memory = 8192
|
# This configuration option has an automatic default value.
|
||||||
|
# reserved_memory = 8192
|
||||||
|
|
||||||
# Configuration option activation/process_priority.
|
# Configuration option activation/process_priority.
|
||||||
# Nice value used while devices are suspended.
|
# Nice value used while devices are suspended.
|
||||||
# Use a high priority so that LVs are suspended
|
# Use a high priority so that LVs are suspended
|
||||||
# for the shortest possible time.
|
# for the shortest possible time.
|
||||||
process_priority = -18
|
# This configuration option has an automatic default value.
|
||||||
|
# process_priority = -18
|
||||||
|
|
||||||
# Configuration option activation/volume_list.
|
# Configuration option activation/volume_list.
|
||||||
# Only LVs selected by this list are activated.
|
# Only LVs selected by this list are activated.
|
||||||
@@ -1306,7 +1460,8 @@ activation {
|
|||||||
# auto
|
# auto
|
||||||
# Use default value chosen by kernel.
|
# Use default value chosen by kernel.
|
||||||
#
|
#
|
||||||
readahead = "auto"
|
# This configuration option has an automatic default value.
|
||||||
|
# readahead = "auto"
|
||||||
|
|
||||||
# Configuration option activation/raid_fault_policy.
|
# Configuration option activation/raid_fault_policy.
|
||||||
# Defines how a device failure in a RAID LV is handled.
|
# Defines how a device failure in a RAID LV is handled.
|
||||||
@@ -1429,6 +1584,34 @@ activation {
|
|||||||
#
|
#
|
||||||
thin_pool_autoextend_percent = 20
|
thin_pool_autoextend_percent = 20
|
||||||
|
|
||||||
|
# Configuration option activation/vdo_pool_autoextend_threshold.
|
||||||
|
# Auto-extend a VDO pool when its usage exceeds this percent.
|
||||||
|
# Setting this to 100 disables automatic extension.
|
||||||
|
# The minimum value is 50 (a smaller value is treated as 50.)
|
||||||
|
# Also see vdo_pool_autoextend_percent.
|
||||||
|
# Automatic extension requires dmeventd to be monitoring the LV.
|
||||||
|
#
|
||||||
|
# Example
|
||||||
|
# Using 70% autoextend threshold and 20% autoextend size, when a 10G
|
||||||
|
# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds
|
||||||
|
# 8.4G, it is extended to 14.4G:
|
||||||
|
# vdo_pool_autoextend_threshold = 70
|
||||||
|
#
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_pool_autoextend_threshold = 100
|
||||||
|
|
||||||
|
# Configuration option activation/vdo_pool_autoextend_percent.
|
||||||
|
# Auto-extending a VDO pool adds this percent extra space.
|
||||||
|
# The amount of additional space added to a VDO pool is this
|
||||||
|
# percent of its current size.
|
||||||
|
#
|
||||||
|
# Example
|
||||||
|
# Using 70% autoextend threshold and 20% autoextend size, when a 10G
|
||||||
|
# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds
|
||||||
|
# 8.4G, it is extended to 14.4G:
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_pool_autoextend_percent = 20
|
||||||
|
|
||||||
# Configuration option activation/mlock_filter.
|
# Configuration option activation/mlock_filter.
|
||||||
# Do not mlock these memory areas.
|
# Do not mlock these memory areas.
|
||||||
# While activating devices, I/O to devices being (re)configured is
|
# While activating devices, I/O to devices being (re)configured is
|
||||||
@@ -1451,7 +1634,8 @@ activation {
|
|||||||
# Use the old behavior of mlockall to pin all memory.
|
# Use the old behavior of mlockall to pin all memory.
|
||||||
# Prior to version 2.02.62, LVM used mlockall() to pin the whole
|
# Prior to version 2.02.62, LVM used mlockall() to pin the whole
|
||||||
# process's memory while activating devices.
|
# process's memory while activating devices.
|
||||||
use_mlockall = 0
|
# This configuration option has an automatic default value.
|
||||||
|
# use_mlockall = 0
|
||||||
|
|
||||||
# Configuration option activation/monitoring.
|
# Configuration option activation/monitoring.
|
||||||
# Monitor LVs that are activated.
|
# Monitor LVs that are activated.
|
||||||
@@ -1466,7 +1650,8 @@ activation {
|
|||||||
# intervals of this number of seconds. If this is set to 0 and there
|
# intervals of this number of seconds. If this is set to 0 and there
|
||||||
# is only one thing to wait for, there are no progress reports, but
|
# is only one thing to wait for, there are no progress reports, but
|
||||||
# the process is awoken immediately once the operation is complete.
|
# the process is awoken immediately once the operation is complete.
|
||||||
polling_interval = 15
|
# This configuration option has an automatic default value.
|
||||||
|
# polling_interval = 15
|
||||||
|
|
||||||
# Configuration option activation/auto_set_activation_skip.
|
# Configuration option activation/auto_set_activation_skip.
|
||||||
# Set the activation skip flag on new thin snapshot LVs.
|
# Set the activation skip flag on new thin snapshot LVs.
|
||||||
@@ -1574,13 +1759,19 @@ activation {
|
|||||||
# vgmetadatacopies = 0
|
# vgmetadatacopies = 0
|
||||||
|
|
||||||
# Configuration option metadata/pvmetadatasize.
|
# Configuration option metadata/pvmetadatasize.
|
||||||
# Approximate number of sectors to use for each metadata copy.
|
# The default size of the metadata area in units of 512 byte sectors.
|
||||||
# VGs with large numbers of PVs or LVs, or VGs containing complex LV
|
# The metadata area begins at an offset of the page size from the start
|
||||||
# structures, may need additional space for VG metadata. The metadata
|
# of the device. The first PE is by default at 1 MiB from the start of
|
||||||
# areas are treated as circular buffers, so unused space becomes filled
|
# the device. The space between these is the default metadata area size.
|
||||||
# with an archive of the most recent previous versions of the metadata.
|
# The actual size of the metadata area may be larger than what is set
|
||||||
# This configuration option has an automatic default value.
|
# here due to default_data_alignment making the first PE a MiB multiple.
|
||||||
# pvmetadatasize = 255
|
# The metadata area begins with a 512 byte header and is followed by a
|
||||||
|
# circular buffer used for VG metadata text. The maximum size of the VG
|
||||||
|
# metadata is about half the size of the metadata buffer. VGs with large
|
||||||
|
# numbers of PVs or LVs, or VGs containing complex LV structures, may need
|
||||||
|
# additional space for VG metadata. The --metadatasize option overrides
|
||||||
|
# this setting.
|
||||||
|
# This configuration option does not have a default value defined.
|
||||||
|
|
||||||
# Configuration option metadata/pvmetadataignore.
|
# Configuration option metadata/pvmetadataignore.
|
||||||
# Ignore metadata areas on a new PV.
|
# Ignore metadata areas on a new PV.
|
||||||
@@ -1595,24 +1786,6 @@ activation {
|
|||||||
# This configuration option is advanced.
|
# This configuration option is advanced.
|
||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# stripesize = 64
|
# stripesize = 64
|
||||||
|
|
||||||
# Configuration option metadata/dirs.
|
|
||||||
# Directories holding live copies of text format metadata.
|
|
||||||
# These directories must not be on logical volumes!
|
|
||||||
# It's possible to use LVM 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 are absolutely sure you know what you are doing!
|
|
||||||
# Use the supplied toolset to make changes (e.g. vgcfgrestore).
|
|
||||||
#
|
|
||||||
# Example
|
|
||||||
# dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
|
|
||||||
#
|
|
||||||
# This configuration option is advanced.
|
|
||||||
# This configuration option does not have a default value defined.
|
|
||||||
# }
|
# }
|
||||||
|
|
||||||
# Configuration section report.
|
# Configuration section report.
|
||||||
@@ -2034,7 +2207,8 @@ dmeventd {
|
|||||||
# failures. It removes failed devices from a volume group and
|
# failures. It removes failed devices from a volume group and
|
||||||
# reconfigures a mirror as necessary. If no mirror library is
|
# reconfigures a mirror as necessary. If no mirror library is
|
||||||
# provided, mirrors are not monitored through dmeventd.
|
# provided, mirrors are not monitored through dmeventd.
|
||||||
mirror_library = "libdevmapper-event-lvm2mirror.so"
|
# This configuration option has an automatic default value.
|
||||||
|
# mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||||
|
|
||||||
# Configuration option dmeventd/raid_library.
|
# Configuration option dmeventd/raid_library.
|
||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
@@ -2045,14 +2219,16 @@ dmeventd {
|
|||||||
# libdevmapper-event-lvm2snapshot.so monitors the filling of snapshots
|
# libdevmapper-event-lvm2snapshot.so monitors the filling of snapshots
|
||||||
# and emits a warning through syslog when the usage exceeds 80%. The
|
# and emits a warning through syslog when the usage exceeds 80%. The
|
||||||
# warning is repeated when 85%, 90% and 95% of the snapshot is filled.
|
# warning is repeated when 85%, 90% and 95% of the snapshot is filled.
|
||||||
snapshot_library = "libdevmapper-event-lvm2snapshot.so"
|
# This configuration option has an automatic default value.
|
||||||
|
# snapshot_library = "libdevmapper-event-lvm2snapshot.so"
|
||||||
|
|
||||||
# Configuration option dmeventd/thin_library.
|
# Configuration option dmeventd/thin_library.
|
||||||
# The library dmeventd uses when monitoring a thin device.
|
# The library dmeventd uses when monitoring a thin device.
|
||||||
# libdevmapper-event-lvm2thin.so monitors the filling of a pool
|
# libdevmapper-event-lvm2thin.so monitors the filling of a pool
|
||||||
# and emits a warning through syslog when the usage exceeds 80%. The
|
# and emits a warning through syslog when the usage exceeds 80%. The
|
||||||
# warning is repeated when 85%, 90% and 95% of the pool is filled.
|
# warning is repeated when 85%, 90% and 95% of the pool is filled.
|
||||||
thin_library = "libdevmapper-event-lvm2thin.so"
|
# This configuration option has an automatic default value.
|
||||||
|
# thin_library = "libdevmapper-event-lvm2thin.so"
|
||||||
|
|
||||||
# Configuration option dmeventd/thin_command.
|
# Configuration option dmeventd/thin_command.
|
||||||
# The plugin runs command with each 5% increment when thin-pool data volume
|
# The plugin runs command with each 5% increment when thin-pool data volume
|
||||||
@@ -2063,6 +2239,23 @@ dmeventd {
|
|||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
# thin_command = "lvm lvextend --use-policies"
|
# thin_command = "lvm lvextend --use-policies"
|
||||||
|
|
||||||
|
# Configuration option dmeventd/vdo_library.
|
||||||
|
# The library dmeventd uses when monitoring a VDO pool device.
|
||||||
|
# libdevmapper-event-lvm2vdo.so monitors the filling of a pool
|
||||||
|
# and emits a warning through syslog when the usage exceeds 80%. The
|
||||||
|
# warning is repeated when 85%, 90% and 95% of the pool is filled.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_library = "libdevmapper-event-lvm2vdo.so"
|
||||||
|
|
||||||
|
# Configuration option dmeventd/vdo_command.
|
||||||
|
# The plugin runs command with each 5% increment when VDO pool volume
|
||||||
|
# gets above 50%.
|
||||||
|
# Command which starts with 'lvm ' prefix is internal lvm command.
|
||||||
|
# You can write your own handler to customise behaviour in more details.
|
||||||
|
# User handler is specified with the full path starting with '/'.
|
||||||
|
# This configuration option has an automatic default value.
|
||||||
|
# vdo_command = "lvm lvextend --use-policies"
|
||||||
|
|
||||||
# Configuration option dmeventd/executable.
|
# Configuration option dmeventd/executable.
|
||||||
# The full path to the dmeventd binary.
|
# The full path to the dmeventd binary.
|
||||||
# This configuration option has an automatic default value.
|
# This configuration option has an automatic default value.
|
||||||
|
|||||||
24
conf/vdo-small.profile
Normal file
24
conf/vdo-small.profile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Demo configuration for 'VDO' using less memory.
|
||||||
|
# ~lvmconfig --type full | grep vdo
|
||||||
|
|
||||||
|
allocation {
|
||||||
|
vdo_use_compression=1
|
||||||
|
vdo_use_deduplication=1
|
||||||
|
vdo_use_metadata_hints=1
|
||||||
|
vdo_minimum_io_size=4096
|
||||||
|
vdo_block_map_cache_size_mb=128
|
||||||
|
vdo_block_map_period=16380
|
||||||
|
vdo_check_point_frequency=0
|
||||||
|
vdo_use_sparse_index=0
|
||||||
|
vdo_index_memory_size_mb=256
|
||||||
|
vdo_slab_size_mb=2048
|
||||||
|
vdo_ack_threads=1
|
||||||
|
vdo_bio_threads=1
|
||||||
|
vdo_bio_rotation=64
|
||||||
|
vdo_cpu_threads=2
|
||||||
|
vdo_hash_zone_threads=1
|
||||||
|
vdo_logical_threads=1
|
||||||
|
vdo_physical_threads=1
|
||||||
|
vdo_write_policy="auto"
|
||||||
|
vdo_max_discard=1
|
||||||
|
}
|
||||||
624
configure.ac
624
configure.ac
@@ -30,7 +30,7 @@ AC_CANONICAL_TARGET([])
|
|||||||
AS_IF([test -z "$CFLAGS"], [COPTIMISE_FLAG="-O2"])
|
AS_IF([test -z "$CFLAGS"], [COPTIMISE_FLAG="-O2"])
|
||||||
case "$host_os" in
|
case "$host_os" in
|
||||||
linux*)
|
linux*)
|
||||||
CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
|
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
|
||||||
# equivalent to -rdynamic
|
# equivalent to -rdynamic
|
||||||
ELDFLAGS="-Wl,--export-dynamic"
|
ELDFLAGS="-Wl,--export-dynamic"
|
||||||
# FIXME Generate list and use --dynamic-list=.dlopen.sym
|
# FIXME Generate list and use --dynamic-list=.dlopen.sym
|
||||||
@@ -39,20 +39,19 @@ case "$host_os" in
|
|||||||
LDDEPS="$LDDEPS .export.sym"
|
LDDEPS="$LDDEPS .export.sym"
|
||||||
LIB_SUFFIX=so
|
LIB_SUFFIX=so
|
||||||
DEVMAPPER=yes
|
DEVMAPPER=yes
|
||||||
BUILD_LVMETAD=no
|
|
||||||
BUILD_LVMPOLLD=no
|
BUILD_LVMPOLLD=no
|
||||||
LOCKDSANLOCK=no
|
LOCKDSANLOCK=no
|
||||||
LOCKDDLM=no
|
LOCKDDLM=no
|
||||||
|
LOCKDDLM_CONTROL=no
|
||||||
ODIRECT=yes
|
ODIRECT=yes
|
||||||
DM_IOCTLS=yes
|
DM_IOCTLS=yes
|
||||||
SELINUX=yes
|
SELINUX=yes
|
||||||
CLUSTER=internal
|
|
||||||
FSADM=yes
|
FSADM=yes
|
||||||
BLKDEACTIVATE=yes
|
BLKDEACTIVATE=yes
|
||||||
;;
|
;;
|
||||||
darwin*)
|
darwin*)
|
||||||
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
||||||
CLDFLAGS="$CLDFLAGS"
|
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"
|
||||||
ELDFLAGS=
|
ELDFLAGS=
|
||||||
CLDWHOLEARCHIVE="-all_load"
|
CLDWHOLEARCHIVE="-all_load"
|
||||||
CLDNOWHOLEARCHIVE=
|
CLDNOWHOLEARCHIVE=
|
||||||
@@ -61,10 +60,12 @@ case "$host_os" in
|
|||||||
ODIRECT=no
|
ODIRECT=no
|
||||||
DM_IOCTLS=no
|
DM_IOCTLS=no
|
||||||
SELINUX=no
|
SELINUX=no
|
||||||
CLUSTER=none
|
|
||||||
FSADM=no
|
FSADM=no
|
||||||
BLKDEACTIVATE=no
|
BLKDEACTIVATE=no
|
||||||
;;
|
;;
|
||||||
|
*)
|
||||||
|
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
@@ -142,13 +143,20 @@ AC_TYPE_UINT16_T
|
|||||||
AC_TYPE_UINT32_T
|
AC_TYPE_UINT32_T
|
||||||
AC_TYPE_UINT64_T
|
AC_TYPE_UINT64_T
|
||||||
AX_GCC_BUILTIN([__builtin_clz])
|
AX_GCC_BUILTIN([__builtin_clz])
|
||||||
|
AX_GCC_BUILTIN([__builtin_clzll])
|
||||||
|
|
||||||
|
|
||||||
|
AC_DEFINE([_GNU_SOURCE], 1, [Define to get access to GNU/Linux extension])
|
||||||
|
AC_DEFINE([_REENTRANT], 1, [Define to use re-entrant thread safe versions])
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Check for functions
|
dnl -- Check for functions
|
||||||
AC_CHECK_FUNCS([ftruncate gethostname getpagesize gettimeofday localtime_r \
|
AC_CHECK_FUNCS([ftruncate gethostname getpagesize gettimeofday localtime_r \
|
||||||
memchr memset mkdir mkfifo munmap nl_langinfo realpath rmdir setenv \
|
memchr memset mkdir mkfifo munmap nl_langinfo pselect realpath rmdir setenv \
|
||||||
setlocale strcasecmp strchr strcspn strdup strerror strncasecmp strndup \
|
setlocale strcasecmp strchr strcspn strdup strerror strncasecmp strndup \
|
||||||
strrchr strspn strstr strtol strtoul uname], , [AC_MSG_ERROR(bailing out)])
|
strrchr strspn strstr strtol strtoul uname], , [AC_MSG_ERROR(bailing out)])
|
||||||
|
AC_CHECK_FUNCS([prlimit])
|
||||||
AC_FUNC_ALLOCA
|
AC_FUNC_ALLOCA
|
||||||
AC_FUNC_CLOSEDIR_VOID
|
AC_FUNC_CLOSEDIR_VOID
|
||||||
AC_FUNC_CHOWN
|
AC_FUNC_CHOWN
|
||||||
@@ -172,6 +180,15 @@ AC_ARG_ENABLE(dependency-tracking,
|
|||||||
USE_TRACKING=$enableval, USE_TRACKING=yes)
|
USE_TRACKING=$enableval, USE_TRACKING=yes)
|
||||||
AC_MSG_RESULT($USE_TRACKING)
|
AC_MSG_RESULT($USE_TRACKING)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Disable silence rules
|
||||||
|
AC_MSG_CHECKING(whether to build silently)
|
||||||
|
AC_ARG_ENABLE(silent-rules,
|
||||||
|
AC_HELP_STRING([--disable-silent-rules], [disable silent building]),
|
||||||
|
SILENT_RULES=$enableval, SILENT_RULES=yes)
|
||||||
|
AC_MSG_RESULT($SILENT_RULES)
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Enables statically-linked tools
|
dnl -- Enables statically-linked tools
|
||||||
AC_MSG_CHECKING(whether to use static linking)
|
AC_MSG_CHECKING(whether to use static linking)
|
||||||
@@ -282,22 +299,6 @@ esac
|
|||||||
AC_MSG_RESULT($MANGLING)
|
AC_MSG_RESULT($MANGLING)
|
||||||
AC_DEFINE_UNQUOTED([DEFAULT_DM_NAME_MANGLING], $mangling, [Define default name mangling behaviour])
|
AC_DEFINE_UNQUOTED([DEFAULT_DM_NAME_MANGLING], $mangling, [Define default name mangling behaviour])
|
||||||
|
|
||||||
################################################################################
|
|
||||||
dnl -- cluster_locking inclusion type
|
|
||||||
AC_MSG_CHECKING(whether to include support for cluster locking)
|
|
||||||
AC_ARG_WITH(cluster,
|
|
||||||
AC_HELP_STRING([--with-cluster=TYPE],
|
|
||||||
[cluster LVM locking support: internal/shared/none [internal]]),
|
|
||||||
CLUSTER=$withval)
|
|
||||||
AC_MSG_RESULT($CLUSTER)
|
|
||||||
|
|
||||||
case "$CLUSTER" in
|
|
||||||
none|shared) ;;
|
|
||||||
internal) AC_DEFINE([CLUSTER_LOCKING_INTERNAL], 1,
|
|
||||||
[Define to 1 to include built-in support for clustered LVM locking.]) ;;
|
|
||||||
*) AC_MSG_ERROR([--with-cluster parameter invalid]) ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- snapshots inclusion type
|
dnl -- snapshots inclusion type
|
||||||
AC_MSG_CHECKING(whether to include snapshots)
|
AC_MSG_CHECKING(whether to include snapshots)
|
||||||
@@ -600,6 +601,89 @@ AC_DEFINE_UNQUOTED([CACHE_REPAIR_CMD], ["$CACHE_REPAIR_CMD"],
|
|||||||
AC_DEFINE_UNQUOTED([CACHE_RESTORE_CMD], ["$CACHE_RESTORE_CMD"],
|
AC_DEFINE_UNQUOTED([CACHE_RESTORE_CMD], ["$CACHE_RESTORE_CMD"],
|
||||||
[The path to 'cache_restore', if available.])
|
[The path to 'cache_restore', if available.])
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- cache inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include vdo)
|
||||||
|
AC_ARG_WITH(vdo,
|
||||||
|
AC_HELP_STRING([--with-vdo=TYPE],
|
||||||
|
[vdo support: internal/none [internal]]),
|
||||||
|
VDO=$withval, VDO="internal")
|
||||||
|
|
||||||
|
AC_MSG_RESULT($VDO)
|
||||||
|
|
||||||
|
AC_ARG_WITH(vdo-format,
|
||||||
|
AC_HELP_STRING([--with-vdo-format=PATH],
|
||||||
|
[vdoformat tool: [autodetect]]),
|
||||||
|
VDO_FORMAT_CMD=$withval, VDO_FORMAT_CMD="autodetect")
|
||||||
|
case "$VDO" in
|
||||||
|
none) ;;
|
||||||
|
internal)
|
||||||
|
AC_DEFINE([VDO_INTERNAL], 1, [Define to 1 to include built-in support for vdo.])
|
||||||
|
if test "$VDO_FORMAT_CMD" = "autodetect"; then
|
||||||
|
AC_PATH_TOOL(VDO_FORMAT_CMD, vdoformat, [], [$PATH])
|
||||||
|
if test -z "$VDO_FORMAT_CMD"; then
|
||||||
|
AC_MSG_WARN([vdoformat not found in path $PATH])
|
||||||
|
VDO_FORMAT_CMD=/usr/bin/vdoformat
|
||||||
|
VDO_CONFIGURE_WARN=y
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*) AC_MSG_ERROR([--with-vdo parameter invalid]) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED([VDO_FORMAT_CMD], ["$VDO_FORMAT_CMD"],
|
||||||
|
[The path to 'vdoformat', if available.])
|
||||||
|
#
|
||||||
|
# Do we need to use the API??
|
||||||
|
# Do we want to link lvm2 with a big library for vdoformating ?
|
||||||
|
#
|
||||||
|
#AC_ARG_WITH(vdo-include,
|
||||||
|
# AC_HELP_STRING([--with-vdo-include=PATH],
|
||||||
|
# [vdo support: Path to utils headers: [/usr/include/vdo/utils]]),
|
||||||
|
# VDO_INCLUDE=$withval, VDO_INCLUDE="/usr/include/vdo/utils")
|
||||||
|
#AC_MSG_RESULT($VDO_INCLUDE)
|
||||||
|
#
|
||||||
|
#AC_ARG_WITH(vdo-lib,
|
||||||
|
# AC_HELP_STRING([--with-vdo-lib=PATH],
|
||||||
|
# [vdo support: Path to utils lib: [/usr/lib]]),
|
||||||
|
# VDO_LIB=$withval, VDO_LIB="/usr/lib")
|
||||||
|
#AC_MSG_RESULT($VDO_LIB)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- writecache inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include writecache)
|
||||||
|
AC_ARG_WITH(writecache,
|
||||||
|
AC_HELP_STRING([--with-writecache=TYPE],
|
||||||
|
[writecache support: internal/none [internal]]),
|
||||||
|
WRITECACHE=$withval, WRITECACHE="internal")
|
||||||
|
|
||||||
|
AC_MSG_RESULT($WRITECACHE)
|
||||||
|
|
||||||
|
case "$WRITECACHE" in
|
||||||
|
none) ;;
|
||||||
|
internal)
|
||||||
|
AC_DEFINE([WRITECACHE_INTERNAL], 1, [Define to 1 to include built-in support for writecache.])
|
||||||
|
;;
|
||||||
|
*) AC_MSG_ERROR([--with-writecache parameter invalid]) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- integrity inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include integrity)
|
||||||
|
AC_ARG_WITH(integrity,
|
||||||
|
AC_HELP_STRING([--with-integrity=TYPE],
|
||||||
|
[integrity support: internal/none [internal]]),
|
||||||
|
INTEGRITY=$withval, INTEGRITY="internal")
|
||||||
|
|
||||||
|
AC_MSG_RESULT($INTEGRITY)
|
||||||
|
|
||||||
|
case "$INTEGRITY" in
|
||||||
|
none) ;;
|
||||||
|
internal)
|
||||||
|
AC_DEFINE([INTEGRITY_INTERNAL], 1, [Define to 1 to include built-in support for integrity.])
|
||||||
|
;;
|
||||||
|
*) AC_MSG_ERROR([--with-integrity parameter invalid]) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Disable readline
|
dnl -- Disable readline
|
||||||
@@ -607,6 +691,12 @@ AC_ARG_ENABLE([readline],
|
|||||||
AC_HELP_STRING([--disable-readline], [disable readline support]),
|
AC_HELP_STRING([--disable-readline], [disable readline support]),
|
||||||
READLINE=$enableval, READLINE=maybe)
|
READLINE=$enableval, READLINE=maybe)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Disable editline
|
||||||
|
AC_ARG_ENABLE([editline],
|
||||||
|
AC_HELP_STRING([--enable-editline], [enable editline support]),
|
||||||
|
EDITLINE=$enableval, EDITLINE=no)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Disable realtime clock support
|
dnl -- Disable realtime clock support
|
||||||
AC_MSG_CHECKING(whether to enable realtime support)
|
AC_MSG_CHECKING(whether to enable realtime support)
|
||||||
@@ -650,7 +740,7 @@ dnl -- Set up pidfile and run directory
|
|||||||
AH_TEMPLATE(DEFAULT_PID_DIR)
|
AH_TEMPLATE(DEFAULT_PID_DIR)
|
||||||
AC_ARG_WITH(default-pid-dir,
|
AC_ARG_WITH(default-pid-dir,
|
||||||
AC_HELP_STRING([--with-default-pid-dir=PID_DIR],
|
AC_HELP_STRING([--with-default-pid-dir=PID_DIR],
|
||||||
[Default directory to keep PID files in. [autodetect]]),
|
[default directory to keep PID files in [autodetect]]),
|
||||||
DEFAULT_PID_DIR="$withval", DEFAULT_PID_DIR=$RUN_DIR)
|
DEFAULT_PID_DIR="$withval", DEFAULT_PID_DIR=$RUN_DIR)
|
||||||
AC_DEFINE_UNQUOTED(DEFAULT_PID_DIR, ["$DEFAULT_PID_DIR"],
|
AC_DEFINE_UNQUOTED(DEFAULT_PID_DIR, ["$DEFAULT_PID_DIR"],
|
||||||
[Default directory to keep PID files in.])
|
[Default directory to keep PID files in.])
|
||||||
@@ -658,7 +748,7 @@ AC_DEFINE_UNQUOTED(DEFAULT_PID_DIR, ["$DEFAULT_PID_DIR"],
|
|||||||
AH_TEMPLATE(DEFAULT_DM_RUN_DIR, [Name of default DM run directory.])
|
AH_TEMPLATE(DEFAULT_DM_RUN_DIR, [Name of default DM run directory.])
|
||||||
AC_ARG_WITH(default-dm-run-dir,
|
AC_ARG_WITH(default-dm-run-dir,
|
||||||
AC_HELP_STRING([--with-default-dm-run-dir=DM_RUN_DIR],
|
AC_HELP_STRING([--with-default-dm-run-dir=DM_RUN_DIR],
|
||||||
[ Default DM run directory. [autodetect]]),
|
[default DM run directory [autodetect]]),
|
||||||
DEFAULT_DM_RUN_DIR="$withval", DEFAULT_DM_RUN_DIR=$RUN_DIR)
|
DEFAULT_DM_RUN_DIR="$withval", DEFAULT_DM_RUN_DIR=$RUN_DIR)
|
||||||
AC_DEFINE_UNQUOTED(DEFAULT_DM_RUN_DIR, ["$DEFAULT_DM_RUN_DIR"],
|
AC_DEFINE_UNQUOTED(DEFAULT_DM_RUN_DIR, ["$DEFAULT_DM_RUN_DIR"],
|
||||||
[Default DM run directory.])
|
[Default DM run directory.])
|
||||||
@@ -666,246 +756,11 @@ AC_DEFINE_UNQUOTED(DEFAULT_DM_RUN_DIR, ["$DEFAULT_DM_RUN_DIR"],
|
|||||||
AH_TEMPLATE(DEFAULT_RUN_DIR, [Name of default LVM run directory.])
|
AH_TEMPLATE(DEFAULT_RUN_DIR, [Name of default LVM run directory.])
|
||||||
AC_ARG_WITH(default-run-dir,
|
AC_ARG_WITH(default-run-dir,
|
||||||
AC_HELP_STRING([--with-default-run-dir=RUN_DIR],
|
AC_HELP_STRING([--with-default-run-dir=RUN_DIR],
|
||||||
[Default LVM run directory. [autodetect_run_dir/lvm]]),
|
[default LVM run directory [autodetect_run_dir/lvm]]),
|
||||||
DEFAULT_RUN_DIR="$withval", DEFAULT_RUN_DIR="$RUN_DIR/lvm")
|
DEFAULT_RUN_DIR="$withval", DEFAULT_RUN_DIR="$RUN_DIR/lvm")
|
||||||
AC_DEFINE_UNQUOTED(DEFAULT_RUN_DIR, ["$DEFAULT_RUN_DIR"],
|
AC_DEFINE_UNQUOTED(DEFAULT_RUN_DIR, ["$DEFAULT_RUN_DIR"],
|
||||||
[Default LVM run directory.])
|
[Default LVM run directory.])
|
||||||
|
|
||||||
################################################################################
|
|
||||||
dnl -- Build cluster LVM daemon
|
|
||||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
|
|
||||||
AC_ARG_WITH(clvmd,
|
|
||||||
[ --with-clvmd=TYPE build cluster LVM Daemon
|
|
||||||
The following cluster manager combinations are valid:
|
|
||||||
* cman (RHEL5 or equivalent)
|
|
||||||
* cman,corosync,openais (or selection of them)
|
|
||||||
* singlenode (localhost only)
|
|
||||||
* all (autodetect)
|
|
||||||
* none (disable build)
|
|
||||||
[[none]]],
|
|
||||||
CLVMD=$withval, CLVMD=none)
|
|
||||||
test "$CLVMD" = yes && CLVMD=all
|
|
||||||
AC_MSG_RESULT($CLVMD)
|
|
||||||
|
|
||||||
dnl -- If clvmd enabled without cluster locking, automagically include it
|
|
||||||
test "$CLVMD" != none -a "$CLUSTER" = none && CLUSTER=internal
|
|
||||||
|
|
||||||
dnl -- init pkgconfig if required
|
|
||||||
test "$CLVMD" != none && pkg_config_init
|
|
||||||
|
|
||||||
dnl -- Express clvmd init script Required-Start / Required-Stop
|
|
||||||
CLVMD_CMANAGERS=""
|
|
||||||
dnl -- On RHEL4/RHEL5, qdiskd is started from a separate init script.
|
|
||||||
dnl -- Enable if we are build for cman.
|
|
||||||
CLVMD_NEEDS_QDISKD=no
|
|
||||||
|
|
||||||
dnl -- define build types
|
|
||||||
if [[ `expr x"$CLVMD" : '.*gulm.*'` != 0 ]]; then
|
|
||||||
AC_MSG_ERROR([Since version 2.02.87 GULM locking is no longer supported.]);
|
|
||||||
fi
|
|
||||||
if [[ `expr x"$CLVMD" : '.*cman.*'` != 0 ]]; then
|
|
||||||
BUILDCMAN=yes
|
|
||||||
CLVMD_CMANAGERS="$CLVMD_CMANAGERS cman"
|
|
||||||
CLVMD_NEEDS_QDISKD=yes
|
|
||||||
fi
|
|
||||||
if [[ `expr x"$CLVMD" : '.*corosync.*'` != 0 ]]; then
|
|
||||||
BUILDCOROSYNC=yes
|
|
||||||
CLVMD_CMANAGERS="$CLVMD_CMANAGERS corosync"
|
|
||||||
fi
|
|
||||||
if [[ `expr x"$CLVMD" : '.*openais.*'` != 0 ]]; then
|
|
||||||
BUILDOPENAIS=yes
|
|
||||||
CLVMD_CMANAGERS="$CLVMD_CMANAGERS openais"
|
|
||||||
fi
|
|
||||||
test "$CLVMD_NEEDS_QDISKD" != no && CLVMD_CMANAGERS="$CLVMD_CMANAGERS qdiskd"
|
|
||||||
|
|
||||||
dnl -- define a soft bailout if we are autodetecting
|
|
||||||
soft_bailout() {
|
|
||||||
NOTFOUND=1
|
|
||||||
}
|
|
||||||
|
|
||||||
hard_bailout() {
|
|
||||||
AC_MSG_ERROR([bailing out])
|
|
||||||
}
|
|
||||||
|
|
||||||
dnl -- if clvmd=all then set soft_bailout (we do not want to error)
|
|
||||||
dnl -- and set all builds to yes. We need to do this here
|
|
||||||
dnl -- to skip the openais|corosync sanity check above.
|
|
||||||
if test "$CLVMD" = all; then
|
|
||||||
bailout=soft_bailout
|
|
||||||
BUILDCMAN=yes
|
|
||||||
BUILDCOROSYNC=yes
|
|
||||||
BUILDOPENAIS=yes
|
|
||||||
else
|
|
||||||
bailout=hard_bailout
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- helper macro to check libs without adding them to LIBS
|
|
||||||
check_lib_no_libs() {
|
|
||||||
lib_no_libs_arg1=$1
|
|
||||||
shift
|
|
||||||
lib_no_libs_arg2=$1
|
|
||||||
shift
|
|
||||||
lib_no_libs_args=$@
|
|
||||||
AC_CHECK_LIB([$lib_no_libs_arg1],
|
|
||||||
[$lib_no_libs_arg2],,
|
|
||||||
[$bailout],
|
|
||||||
[$lib_no_libs_args])
|
|
||||||
LIBS=$ac_check_lib_save_LIBS
|
|
||||||
}
|
|
||||||
|
|
||||||
dnl -- Look for cman libraries if required.
|
|
||||||
if test "$BUILDCMAN" = yes; then
|
|
||||||
PKG_CHECK_MODULES(CMAN, libcman, [HAVE_CMAN=yes],
|
|
||||||
[NOTFOUND=0
|
|
||||||
AC_CHECK_HEADERS(libcman.h,,$bailout)
|
|
||||||
check_lib_no_libs cman cman_init
|
|
||||||
if test $NOTFOUND = 0; then
|
|
||||||
AC_MSG_RESULT([no pkg for libcman, using -lcman])
|
|
||||||
CMAN_LIBS="-lcman"
|
|
||||||
HAVE_CMAN=yes
|
|
||||||
fi])
|
|
||||||
CHECKCONFDB=yes
|
|
||||||
CHECKDLM=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- Look for corosync that is required also for openais build
|
|
||||||
dnl -- only enough recent version of corosync ship pkg-config files.
|
|
||||||
dnl -- We can safely rely on that to detect the correct bits.
|
|
||||||
if test "$BUILDCOROSYNC" = yes -o "$BUILDOPENAIS" = yes; then
|
|
||||||
PKG_CHECK_MODULES(COROSYNC, corosync, [HAVE_COROSYNC=yes], $bailout)
|
|
||||||
CHECKCONFDB=yes
|
|
||||||
CHECKCMAP=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- Look for corosync libraries if required.
|
|
||||||
if test "$BUILDCOROSYNC" = yes; then
|
|
||||||
PKG_CHECK_MODULES(QUORUM, libquorum, [HAVE_QUORUM=yes], $bailout)
|
|
||||||
CHECKCPG=yes
|
|
||||||
CHECKDLM=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- Look for openais libraries if required.
|
|
||||||
if test "$BUILDOPENAIS" = yes; then
|
|
||||||
PKG_CHECK_MODULES(SALCK, libSaLck, [HAVE_SALCK=yes], $bailout)
|
|
||||||
CHECKCPG=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- Below are checks for libraries common to more than one build.
|
|
||||||
|
|
||||||
dnl -- Check confdb library.
|
|
||||||
dnl -- mandatory for corosync < 2.0 build.
|
|
||||||
dnl -- optional for openais/cman build.
|
|
||||||
|
|
||||||
if test "$CHECKCONFDB" = yes; then
|
|
||||||
PKG_CHECK_MODULES(CONFDB, libconfdb,
|
|
||||||
[HAVE_CONFDB=yes], [HAVE_CONFDB=no])
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS([corosync/confdb.h],
|
|
||||||
[HAVE_CONFDB_H=yes], [HAVE_CONFDB_H=no])
|
|
||||||
|
|
||||||
if test "$HAVE_CONFDB" != yes -a "$HAVE_CONFDB_H" = yes; then
|
|
||||||
check_lib_no_libs confdb confdb_initialize
|
|
||||||
AC_MSG_RESULT([no pkg for confdb, using -lconfdb])
|
|
||||||
CONFDB_LIBS="-lconfdb"
|
|
||||||
HAVE_CONFDB=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- Check cmap library
|
|
||||||
dnl -- mandatory for corosync >= 2.0 build.
|
|
||||||
|
|
||||||
if test "$CHECKCMAP" = yes; then
|
|
||||||
PKG_CHECK_MODULES(CMAP, libcmap,
|
|
||||||
[HAVE_CMAP=yes], [HAVE_CMAP=no])
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS([corosync/cmap.h],
|
|
||||||
[HAVE_CMAP_H=yes], [HAVE_CMAP_H=no])
|
|
||||||
|
|
||||||
if test "$HAVE_CMAP" != yes -a "$HAVE_CMAP_H" = yes; then
|
|
||||||
check_lib_no_libs cmap cmap_initialize
|
|
||||||
AC_MSG_RESULT([no pkg for cmap, using -lcmap])
|
|
||||||
CMAP_LIBS="-lcmap"
|
|
||||||
HAVE_CMAP=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$BUILDCOROSYNC" = yes -a \
|
|
||||||
"$HAVE_CMAP" != yes -a "$HAVE_CONFDB" != yes -a "$CLVMD" != all; then
|
|
||||||
AC_MSG_ERROR([bailing out... cmap (corosync >= 2.0) or confdb (corosync < 2.0) library is required])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- Check cpg library.
|
|
||||||
if test "$CHECKCPG" = yes; then
|
|
||||||
PKG_CHECK_MODULES(CPG, libcpg, [HAVE_CPG=yes], [$bailout])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- Check dlm library.
|
|
||||||
if test "$CHECKDLM" = yes; then
|
|
||||||
PKG_CHECK_MODULES(DLM, libdlm, [HAVE_DLM=yes],
|
|
||||||
[NOTFOUND=0
|
|
||||||
AC_CHECK_HEADERS(libdlm.h,,[$bailout])
|
|
||||||
check_lib_no_libs dlm dlm_lock -lpthread
|
|
||||||
if test $NOTFOUND = 0; then
|
|
||||||
AC_MSG_RESULT([no pkg for libdlm, using -ldlm])
|
|
||||||
DLM_LIBS="-ldlm -lpthread"
|
|
||||||
HAVE_DLM=yes
|
|
||||||
fi])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- If we are autodetecting, we need to re-create
|
|
||||||
dnl -- the depedencies checks and set a proper CLVMD,
|
|
||||||
dnl -- together with init script Required-Start/Stop entries.
|
|
||||||
if test "$CLVMD" = all; then
|
|
||||||
CLVMD=none
|
|
||||||
CLVMD_CMANAGERS=""
|
|
||||||
CLVMD_NEEDS_QDISKD=no
|
|
||||||
if test "$HAVE_CMAN" = yes -a \
|
|
||||||
"$HAVE_DLM" = yes; then
|
|
||||||
AC_MSG_RESULT([Enabling clvmd cman cluster manager])
|
|
||||||
CLVMD="$CLVMD,cman"
|
|
||||||
CLVMD_CMANAGERS="$CLVMD_CMANAGERS cman"
|
|
||||||
CLVMD_NEEDS_QDISKD=yes
|
|
||||||
fi
|
|
||||||
if test "$HAVE_COROSYNC" = yes -a \
|
|
||||||
"$HAVE_QUORUM" = yes -a \
|
|
||||||
"$HAVE_CPG" = yes -a \
|
|
||||||
"$HAVE_DLM" = yes; then
|
|
||||||
if test "$HAVE_CONFDB" = yes -o "$HAVE_CMAP" = yes; then
|
|
||||||
AC_MSG_RESULT([Enabling clvmd corosync cluster manager])
|
|
||||||
CLVMD="$CLVMD,corosync"
|
|
||||||
CLVMD_CMANAGERS="$CLVMD_CMANAGERS corosync"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test "$HAVE_COROSYNC" = yes -a \
|
|
||||||
"$HAVE_CPG" = yes -a \
|
|
||||||
"$HAVE_SALCK" = yes; then
|
|
||||||
AC_MSG_RESULT([Enabling clvmd openais cluster manager])
|
|
||||||
CLVMD="$CLVMD,openais"
|
|
||||||
CLVMD_CMANAGERS="$CLVMD_CMANAGERS openais"
|
|
||||||
fi
|
|
||||||
test "$CLVMD_NEEDS_QDISKD" != no && CLVMD_CMANAGERS="$CLVMD_CMANAGERS qdiskd"
|
|
||||||
test "$CLVMD" = none && AC_MSG_RESULT([Disabling clvmd build. No cluster manager detected.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -- Fixup CLVMD_CMANAGERS with new corosync
|
|
||||||
dnl -- clvmd built with corosync >= 2.0 needs dlm (either init or systemd service)
|
|
||||||
dnl -- to be started.
|
|
||||||
if [[ `expr x"$CLVMD" : '.*corosync.*'` != 0 ]]; then
|
|
||||||
test "$HAVE_CMAP" = yes && CLVMD_CMANAGERS="$CLVMD_CMANAGERS dlm"
|
|
||||||
fi
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
dnl -- clvmd pidfile
|
|
||||||
if test "$CLVMD" != none; then
|
|
||||||
AC_ARG_WITH(clvmd-pidfile,
|
|
||||||
AC_HELP_STRING([--with-clvmd-pidfile=PATH],
|
|
||||||
[clvmd pidfile [PID_DIR/clvmd.pid]]),
|
|
||||||
CLVMD_PIDFILE=$withval,
|
|
||||||
CLVMD_PIDFILE="$DEFAULT_PID_DIR/clvmd.pid")
|
|
||||||
AC_DEFINE_UNQUOTED(CLVMD_PIDFILE, ["$CLVMD_PIDFILE"],
|
|
||||||
[Path to clvmd pidfile.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Build cluster mirror log daemon
|
dnl -- Build cluster mirror log daemon
|
||||||
AC_MSG_CHECKING(whether to build cluster mirror log daemon)
|
AC_MSG_CHECKING(whether to build cluster mirror log daemon)
|
||||||
@@ -934,11 +789,6 @@ dnl -- Look for corosync libraries if required.
|
|||||||
if [[ "$BUILD_CMIRRORD" = yes ]]; then
|
if [[ "$BUILD_CMIRRORD" = yes ]]; then
|
||||||
pkg_config_init
|
pkg_config_init
|
||||||
|
|
||||||
AC_DEFINE([CMIRROR_HAS_CHECKPOINT], 1, [Define to 1 to include libSaCkpt.])
|
|
||||||
PKG_CHECK_MODULES(SACKPT, libSaCkpt, [HAVE_SACKPT=yes],
|
|
||||||
[AC_MSG_RESULT([no libSaCkpt, compiling without it])
|
|
||||||
AC_DEFINE([CMIRROR_HAS_CHECKPOINT], 0, [Define to 0 to exclude libSaCkpt.])])
|
|
||||||
|
|
||||||
if test "$HAVE_CPG" != yes; then
|
if test "$HAVE_CPG" != yes; then
|
||||||
PKG_CHECK_MODULES(CPG, libcpg)
|
PKG_CHECK_MODULES(CPG, libcpg)
|
||||||
fi
|
fi
|
||||||
@@ -1044,16 +894,6 @@ if test "$DEVMAPPER" = yes; then
|
|||||||
AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable LVM2 device-mapper interaction.])
|
AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable LVM2 device-mapper interaction.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
################################################################################
|
|
||||||
dnl -- Build lvmetad
|
|
||||||
AC_MSG_CHECKING(whether to build LVMetaD)
|
|
||||||
AC_ARG_ENABLE(lvmetad,
|
|
||||||
AC_HELP_STRING([--enable-lvmetad],
|
|
||||||
[enable the LVM Metadata Daemon]),
|
|
||||||
LVMETAD=$enableval)
|
|
||||||
test -n "$LVMETAD" && BUILD_LVMETAD=$LVMETAD
|
|
||||||
AC_MSG_RESULT($BUILD_LVMETAD)
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Build lvmpolld
|
dnl -- Build lvmpolld
|
||||||
AC_MSG_CHECKING(whether to build lvmpolld)
|
AC_MSG_CHECKING(whether to build lvmpolld)
|
||||||
@@ -1102,6 +942,24 @@ if test "$BUILD_LOCKDDLM" = yes; then
|
|||||||
BUILD_LVMLOCKD=yes
|
BUILD_LVMLOCKD=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Build lvmlockddlmcontrol
|
||||||
|
AC_MSG_CHECKING(whether to build lvmlockddlmcontrol)
|
||||||
|
AC_ARG_ENABLE(lvmlockd-dlmcontrol,
|
||||||
|
AC_HELP_STRING([--enable-lvmlockd-dlmcontrol],
|
||||||
|
[enable lvmlockd remote refresh using libdlmcontrol]),
|
||||||
|
LOCKDDLM_CONTROL=$enableval)
|
||||||
|
AC_MSG_RESULT($LOCKDDLM_CONTROL)
|
||||||
|
|
||||||
|
BUILD_LOCKDDLM_CONTROL=$LOCKDDLM_CONTROL
|
||||||
|
|
||||||
|
dnl -- Look for libdlmcontrol libraries
|
||||||
|
if test "$BUILD_LOCKDDLM_CONTROL" = yes; then
|
||||||
|
PKG_CHECK_MODULES(LOCKD_DLM_CONTROL, libdlmcontrol >= 3.2, [HAVE_LOCKD_DLM_CONTROL=yes], $bailout)
|
||||||
|
AC_DEFINE([LOCKDDLM_CONTROL_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd dlm control option.])
|
||||||
|
BUILD_LVMLOCKD=yes
|
||||||
|
fi
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Build lvmlockd
|
dnl -- Build lvmlockd
|
||||||
AC_MSG_CHECKING(whether to build lvmlockd)
|
AC_MSG_CHECKING(whether to build lvmlockd)
|
||||||
@@ -1109,9 +967,7 @@ AC_MSG_RESULT($BUILD_LVMLOCKD)
|
|||||||
|
|
||||||
if test "$BUILD_LVMLOCKD" = yes; then
|
if test "$BUILD_LVMLOCKD" = yes; then
|
||||||
AS_IF([test "$LVMPOLLD" = no], [AC_MSG_ERROR([cannot build lvmlockd with --disable-lvmpolld.])])
|
AS_IF([test "$LVMPOLLD" = no], [AC_MSG_ERROR([cannot build lvmlockd with --disable-lvmpolld.])])
|
||||||
AS_IF([test "$LVMETAD" = no], [AC_MSG_ERROR([cannot build lvmlockd with --disable-lvmetad.])])
|
|
||||||
AS_IF([test "$BUILD_LVMPOLLD" = no], [BUILD_LVMPOLLD=yes; AC_MSG_WARN([Enabling lvmpolld - required by lvmlockd.])])
|
AS_IF([test "$BUILD_LVMPOLLD" = no], [BUILD_LVMPOLLD=yes; AC_MSG_WARN([Enabling lvmpolld - required by lvmlockd.])])
|
||||||
AS_IF([test "$BUILD_LVMETAD" = no], [BUILD_LVMETAD=yes; AC_MSG_WARN([Enabling lvmetad - required by lvmlockd.])])
|
|
||||||
AC_MSG_CHECKING([defaults for use_lvmlockd])
|
AC_MSG_CHECKING([defaults for use_lvmlockd])
|
||||||
AC_ARG_ENABLE(use_lvmlockd,
|
AC_ARG_ENABLE(use_lvmlockd,
|
||||||
AC_HELP_STRING([--disable-use-lvmlockd],
|
AC_HELP_STRING([--disable-use-lvmlockd],
|
||||||
@@ -1136,33 +992,6 @@ fi
|
|||||||
AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMLOCKD, [$DEFAULT_USE_LVMLOCKD],
|
AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMLOCKD, [$DEFAULT_USE_LVMLOCKD],
|
||||||
[Use lvmlockd by default.])
|
[Use lvmlockd by default.])
|
||||||
|
|
||||||
################################################################################
|
|
||||||
dnl -- Check lvmetad
|
|
||||||
if test "$BUILD_LVMETAD" = yes; then
|
|
||||||
AC_MSG_CHECKING([defaults for use_lvmetad])
|
|
||||||
AC_ARG_ENABLE(use_lvmetad,
|
|
||||||
AC_HELP_STRING([--disable-use-lvmetad],
|
|
||||||
[disable usage of LVM Metadata Daemon]),
|
|
||||||
[case ${enableval} in
|
|
||||||
yes) DEFAULT_USE_LVMETAD=1 ;;
|
|
||||||
*) DEFAULT_USE_LVMETAD=0 ;;
|
|
||||||
esac], DEFAULT_USE_LVMETAD=1)
|
|
||||||
AC_MSG_RESULT($DEFAULT_USE_LVMETAD)
|
|
||||||
AC_DEFINE([LVMETAD_SUPPORT], 1, [Define to 1 to include code that uses lvmetad.])
|
|
||||||
|
|
||||||
AC_ARG_WITH(lvmetad-pidfile,
|
|
||||||
AC_HELP_STRING([--with-lvmetad-pidfile=PATH],
|
|
||||||
[lvmetad pidfile [PID_DIR/lvmetad.pid]]),
|
|
||||||
LVMETAD_PIDFILE=$withval,
|
|
||||||
LVMETAD_PIDFILE="$DEFAULT_PID_DIR/lvmetad.pid")
|
|
||||||
AC_DEFINE_UNQUOTED(LVMETAD_PIDFILE, ["$LVMETAD_PIDFILE"],
|
|
||||||
[Path to lvmetad pidfile.])
|
|
||||||
else
|
|
||||||
DEFAULT_USE_LVMETAD=0
|
|
||||||
fi
|
|
||||||
AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMETAD, [$DEFAULT_USE_LVMETAD],
|
|
||||||
[Use lvmetad by default.])
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Check lvmpolld
|
dnl -- Check lvmpolld
|
||||||
if test "$BUILD_LVMPOLLD" = yes; then
|
if test "$BUILD_LVMPOLLD" = yes; then
|
||||||
@@ -1366,20 +1195,6 @@ if test "$ODIRECT" = yes; then
|
|||||||
AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
|
AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
################################################################################
|
|
||||||
dnl -- Enable liblvm2app.so
|
|
||||||
AC_MSG_CHECKING(whether to build liblvm2app.so application library)
|
|
||||||
AC_ARG_ENABLE(applib,
|
|
||||||
AC_HELP_STRING([--enable-applib], [build application library]),
|
|
||||||
APPLIB=$enableval, APPLIB=no)
|
|
||||||
AC_MSG_RESULT($APPLIB)
|
|
||||||
AC_SUBST([LVM2APP_LIB])
|
|
||||||
test "$APPLIB" = yes \
|
|
||||||
&& LVM2APP_LIB=-llvm2app \
|
|
||||||
|| LVM2APP_LIB=
|
|
||||||
AS_IF([test "$APPLIB"],
|
|
||||||
[AC_MSG_WARN([liblvm2app is deprecated. Use D-Bus API])])
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Enable cmdlib
|
dnl -- Enable cmdlib
|
||||||
AC_MSG_CHECKING(whether to compile liblvm2cmd.so)
|
AC_MSG_CHECKING(whether to compile liblvm2cmd.so)
|
||||||
@@ -1403,48 +1218,15 @@ AS_IF([test "$NOTIFYDBUS_SUPPORT" = yes && test "BUILD_LVMDBUSD" = yes],
|
|||||||
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications.])])
|
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications.])])
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Enable Python liblvm2app bindings
|
dnl -- Enable Python dbus library
|
||||||
AC_MSG_CHECKING(whether to build Python wrapper for liblvm2app.so)
|
|
||||||
AC_ARG_ENABLE(python_bindings,
|
|
||||||
AC_HELP_STRING([--enable-python_bindings], [build default Python applib bindings]),
|
|
||||||
PYTHON_BINDINGS=$enableval, PYTHON_BINDINGS=no)
|
|
||||||
AC_MSG_RESULT($PYTHON_BINDINGS)
|
|
||||||
|
|
||||||
AC_MSG_CHECKING(whether to build Python2 wrapper for liblvm2app.so)
|
if test "$BUILD_LVMDBUSD" = yes; then
|
||||||
AC_ARG_ENABLE(python2_bindings,
|
|
||||||
AC_HELP_STRING([--enable-python2_bindings], [build Python2 applib bindings]),
|
|
||||||
PYTHON2_BINDINGS=$enableval, PYTHON2_BINDINGS=no)
|
|
||||||
AC_MSG_RESULT($PYTHON2_BINDINGS)
|
|
||||||
|
|
||||||
|
|
||||||
AC_MSG_CHECKING(whether to build Python3 wrapper for liblvm2app.so)
|
|
||||||
AC_ARG_ENABLE(python3_bindings,
|
|
||||||
AC_HELP_STRING([--enable-python3_bindings], [build Python3 applib bindings]),
|
|
||||||
PYTHON3_BINDINGS=$enableval, PYTHON3_BINDINGS=no)
|
|
||||||
AC_MSG_RESULT($PYTHON3_BINDINGS)
|
|
||||||
|
|
||||||
if test "$PYTHON_BINDINGS" = yes; then
|
|
||||||
AC_MSG_ERROR([--enable-python-bindings is replaced by --enable-python2-bindings and --enable-python3-bindings])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$PYTHON2_BINDINGS" = yes; then
|
|
||||||
AM_PATH_PYTHON([2])
|
|
||||||
AC_PATH_TOOL(PYTHON2, python2)
|
|
||||||
test -z "$PYTHON2" && AC_MSG_ERROR([python2 is required for --enable-python2_bindings but cannot be found])
|
|
||||||
AC_PATH_TOOL(PYTHON2_CONFIG, python2-config)
|
|
||||||
test -z "$PYTHON2_CONFIG" && AC_PATH_TOOL(PYTHON2_CONFIG, python-config)
|
|
||||||
test -z "$PYTHON2_CONFIG" && AC_MSG_ERROR([python headers are required for --enable-python2_bindings but cannot be found])
|
|
||||||
PYTHON2_INCDIRS=`"$PYTHON2_CONFIG" --includes`
|
|
||||||
PYTHON2_LIBDIRS=`"$PYTHON2_CONFIG" --libs`
|
|
||||||
PYTHON2DIR=$pythondir
|
|
||||||
PYTHON_BINDINGS=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$PYTHON3_BINDINGS" = yes -o "$BUILD_LVMDBUSD" = yes; then
|
|
||||||
unset PYTHON PYTHON_CONFIG
|
|
||||||
unset am_cv_pathless_PYTHON ac_cv_path_PYTHON am_cv_python_platform
|
unset am_cv_pathless_PYTHON ac_cv_path_PYTHON am_cv_python_platform
|
||||||
unset am_cv_python_pythondir am_cv_python_version am_cv_python_pyexecdir
|
unset am_cv_python_pythondir am_cv_python_version am_cv_python_pyexecdir
|
||||||
unset ac_cv_path_PYTHON_CONFIG ac_cv_path_ac_pt_PYTHON_CONFIG
|
unset ac_cv_path_PYTHON_CONFIG ac_cv_path_ac_pt_PYTHON_CONFIG
|
||||||
|
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],[ python3 python2 python dnl
|
||||||
|
python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 dnl
|
||||||
|
python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 ])
|
||||||
AM_PATH_PYTHON([3])
|
AM_PATH_PYTHON([3])
|
||||||
PYTHON3=$PYTHON
|
PYTHON3=$PYTHON
|
||||||
test -z "$PYTHON3" && AC_MSG_ERROR([python3 is required for --enable-python3_bindings or --enable-dbus-service but cannot be found])
|
test -z "$PYTHON3" && AC_MSG_ERROR([python3 is required for --enable-python3_bindings or --enable-dbus-service but cannot be found])
|
||||||
@@ -1454,19 +1236,12 @@ if test "$PYTHON3_BINDINGS" = yes -o "$BUILD_LVMDBUSD" = yes; then
|
|||||||
PYTHON3_LIBDIRS=`"$PYTHON3_CONFIG" --libs`
|
PYTHON3_LIBDIRS=`"$PYTHON3_CONFIG" --libs`
|
||||||
PYTHON3DIR=$pythondir
|
PYTHON3DIR=$pythondir
|
||||||
test "$PYTHON3_BINDINGS" = yes && PYTHON_BINDINGS=yes
|
test "$PYTHON3_BINDINGS" = yes && PYTHON_BINDINGS=yes
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$BUILD_LVMDBUSD" = yes; then
|
|
||||||
# To get this macro, install autoconf-archive package then run autoreconf
|
# To get this macro, install autoconf-archive package then run autoreconf
|
||||||
AC_PYTHON_MODULE([pyudev], [Required], python3)
|
AC_PYTHON_MODULE([pyudev], [Required], python3)
|
||||||
AC_PYTHON_MODULE([dbus], [Required], python3)
|
AC_PYTHON_MODULE([dbus], [Required], python3)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$PYTHON_BINDINGS" = yes -o "$PYTHON2_BINDINGS" = yes -o "$PYTHON3_BINDINGS" = yes; then
|
|
||||||
AC_MSG_WARN([Python bindings are deprecated. Use D-Bus API])
|
|
||||||
test "$APPLIB" != yes && AC_MSG_ERROR([Python_bindings require --enable-applib])
|
|
||||||
fi
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Enable pkg-config
|
dnl -- Enable pkg-config
|
||||||
AC_ARG_ENABLE(pkgconfig,
|
AC_ARG_ENABLE(pkgconfig,
|
||||||
@@ -1538,7 +1313,7 @@ AC_CHECK_LIB(dl, dlopen,
|
|||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Check for shared/static conflicts
|
dnl -- Check for shared/static conflicts
|
||||||
if [[ \( "$LVM1" = shared -o "$POOL" = shared -o "$CLUSTER" = shared \
|
if [[ \( "$LVM1" = shared -o "$POOL" = shared \
|
||||||
\) -a "$STATIC_LINK" = yes ]]; then
|
\) -a "$STATIC_LINK" = yes ]]; then
|
||||||
AC_MSG_ERROR([Features cannot be 'shared' when building statically])
|
AC_MSG_ERROR([Features cannot be 'shared' when building statically])
|
||||||
fi
|
fi
|
||||||
@@ -1579,6 +1354,33 @@ if test "$SELINUX" = yes; then
|
|||||||
HAVE_SELINUX=no ])
|
HAVE_SELINUX=no ])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check BLKZEROOUT support
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([for BLKZEROOUT in sys/ioctl.h.],
|
||||||
|
[ac_cv_have_blkzeroout],
|
||||||
|
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||||
|
[#include <sys/ioctl.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
int bar(void) { return ioctl(0, BLKZEROOUT, 0); }]
|
||||||
|
)], [ac_cv_have_blkzeroout=yes], [ac_cv_have_blkzeroout=no])])
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(blkzeroout,
|
||||||
|
AC_HELP_STRING([--disable-blkzeroout],
|
||||||
|
[do not use BLKZEROOUT for device zeroing]),
|
||||||
|
BLKZEROOUT=$enableval, BLKZEROOUT=yes)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(whether to use BLKZEROOUT for device zeroing)
|
||||||
|
if test "$BLKZEROOUT" = yes; then
|
||||||
|
AC_IF_YES(ac_cv_have_blkzeroout,
|
||||||
|
AC_DEFINE(HAVE_BLKZEROOUT, 1,
|
||||||
|
[Define if ioctl BLKZEROOUT can be used for device zeroing.]),
|
||||||
|
BLKZEROOUT=no)
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT($BLKZEROOUT)
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Check for realtime clock support
|
dnl -- Check for realtime clock support
|
||||||
RT_LIBS=
|
RT_LIBS=
|
||||||
@@ -1612,6 +1414,16 @@ AC_IF_YES(ac_cv_stat_st_ctim,
|
|||||||
dnl -- Check for getopt
|
dnl -- Check for getopt
|
||||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getopt_long is available.]))
|
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getopt_long is available.]))
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for editline
|
||||||
|
if test "$EDITLINE" == yes; then
|
||||||
|
PKG_CHECK_MODULES([EDITLINE], [libedit], [
|
||||||
|
AC_DEFINE([EDITLINE_SUPPORT], 1,
|
||||||
|
[Define to 1 to include the LVM editline shell.])], AC_MSG_ERROR(
|
||||||
|
[libedit could not be found which is required for the --enable-readline option.])
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
|
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
|
||||||
if test "$READLINE" != no; then
|
if test "$READLINE" != no; then
|
||||||
@@ -1744,6 +1556,12 @@ fi
|
|||||||
AC_MSG_CHECKING(whether to enable readline)
|
AC_MSG_CHECKING(whether to enable readline)
|
||||||
AC_MSG_RESULT($READLINE)
|
AC_MSG_RESULT($READLINE)
|
||||||
|
|
||||||
|
if test "$EDITLINE" = yes; then
|
||||||
|
AC_CHECK_HEADERS(editline/readline.h editline/history.h,,hard_bailout)
|
||||||
|
fi
|
||||||
|
AC_MSG_CHECKING(whether to enable editline)
|
||||||
|
AC_MSG_RESULT($EDITLINE)
|
||||||
|
|
||||||
if test "$BUILD_CMIRRORD" = yes; then
|
if test "$BUILD_CMIRRORD" = yes; then
|
||||||
AC_CHECK_FUNCS(atexit,,hard_bailout)
|
AC_CHECK_FUNCS(atexit,,hard_bailout)
|
||||||
fi
|
fi
|
||||||
@@ -1758,18 +1576,6 @@ if test "$BUILD_LVMPOLLD" = yes; then
|
|||||||
AC_FUNC_STRERROR_R
|
AC_FUNC_STRERROR_R
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$CLVMD" != none; then
|
|
||||||
AC_CHECK_HEADERS(mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h,,AC_MSG_ERROR(bailing out))
|
|
||||||
AC_CHECK_FUNCS(dup2 getmntent memmove select socket,,hard_bailout)
|
|
||||||
AC_FUNC_GETMNTENT
|
|
||||||
AC_FUNC_SELECT_ARGTYPES
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$CLUSTER" != none; then
|
|
||||||
AC_CHECK_HEADERS(sys/socket.h sys/un.h,,hard_bailout)
|
|
||||||
AC_CHECK_FUNCS(socket,,hard_bailout)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$BUILD_DMEVENTD" = yes; then
|
if test "$BUILD_DMEVENTD" = yes; then
|
||||||
AC_CHECK_HEADERS(arpa/inet.h,,hard_bailout)
|
AC_CHECK_HEADERS(arpa/inet.h,,hard_bailout)
|
||||||
fi
|
fi
|
||||||
@@ -1803,9 +1609,10 @@ SBINDIR="$(eval echo $(eval echo $sbindir))"
|
|||||||
LVM_PATH="$SBINDIR/lvm"
|
LVM_PATH="$SBINDIR/lvm"
|
||||||
AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
|
AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
|
||||||
|
|
||||||
|
LVMCONFIG_PATH="$SBINDIR/lvmconfig"
|
||||||
|
AC_DEFINE_UNQUOTED(LVMCONFIG_PATH, ["$LVMCONFIG_PATH"], [Path to lvmconfig binary.])
|
||||||
|
|
||||||
USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
|
USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
|
||||||
CLVMD_PATH="$USRSBINDIR/clvmd"
|
|
||||||
AC_DEFINE_UNQUOTED(CLVMD_PATH, ["$CLVMD_PATH"], [Path to clvmd binary.])
|
|
||||||
|
|
||||||
FSADM_PATH="$SBINDIR/fsadm"
|
FSADM_PATH="$SBINDIR/fsadm"
|
||||||
AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
|
AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
|
||||||
@@ -1885,15 +1692,6 @@ AC_ARG_WITH(default-locking-dir,
|
|||||||
AC_DEFINE_UNQUOTED(DEFAULT_LOCK_DIR, ["$DEFAULT_LOCK_DIR"],
|
AC_DEFINE_UNQUOTED(DEFAULT_LOCK_DIR, ["$DEFAULT_LOCK_DIR"],
|
||||||
[Name of default locking directory.])
|
[Name of default locking directory.])
|
||||||
|
|
||||||
################################################################################
|
|
||||||
dnl -- Setup default data alignment
|
|
||||||
AC_ARG_WITH(default-data-alignment,
|
|
||||||
AC_HELP_STRING([--with-default-data-alignment=NUM],
|
|
||||||
[set the default data alignment in MiB [1]]),
|
|
||||||
DEFAULT_DATA_ALIGNMENT=$withval, DEFAULT_DATA_ALIGNMENT=1)
|
|
||||||
AC_DEFINE_UNQUOTED(DEFAULT_DATA_ALIGNMENT, [$DEFAULT_DATA_ALIGNMENT],
|
|
||||||
[Default data alignment.])
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
dnl -- which kernel interface to use (ioctl only)
|
dnl -- which kernel interface to use (ioctl only)
|
||||||
AC_MSG_CHECKING(for kernel interface choice)
|
AC_MSG_CHECKING(for kernel interface choice)
|
||||||
@@ -1925,17 +1723,16 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[[()]]' '{print $2}'`
|
|||||||
AC_DEFINE_UNQUOTED(LVM_CONFIGURE_LINE, "$CONFIGURE_LINE", [configure command line used])
|
AC_DEFINE_UNQUOTED(LVM_CONFIGURE_LINE, "$CONFIGURE_LINE", [configure command line used])
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
AC_SUBST(APPLIB)
|
|
||||||
AC_SUBST(AWK)
|
AC_SUBST(AWK)
|
||||||
AC_SUBST(BLKID_PC)
|
AC_SUBST(BLKID_PC)
|
||||||
AC_SUBST(BUILD_CMIRRORD)
|
AC_SUBST(BUILD_CMIRRORD)
|
||||||
AC_SUBST(BUILD_DMEVENTD)
|
AC_SUBST(BUILD_DMEVENTD)
|
||||||
AC_SUBST(BUILD_LVMDBUSD)
|
AC_SUBST(BUILD_LVMDBUSD)
|
||||||
AC_SUBST(BUILD_LVMETAD)
|
|
||||||
AC_SUBST(BUILD_LVMPOLLD)
|
AC_SUBST(BUILD_LVMPOLLD)
|
||||||
AC_SUBST(BUILD_LVMLOCKD)
|
AC_SUBST(BUILD_LVMLOCKD)
|
||||||
AC_SUBST(BUILD_LOCKDSANLOCK)
|
AC_SUBST(BUILD_LOCKDSANLOCK)
|
||||||
AC_SUBST(BUILD_LOCKDDLM)
|
AC_SUBST(BUILD_LOCKDDLM)
|
||||||
|
AC_SUBST(BUILD_LOCKDDLM_CONTROL)
|
||||||
AC_SUBST(BUILD_DMFILEMAPD)
|
AC_SUBST(BUILD_DMFILEMAPD)
|
||||||
AC_SUBST(CACHE)
|
AC_SUBST(CACHE)
|
||||||
AC_SUBST(CFLAGS)
|
AC_SUBST(CFLAGS)
|
||||||
@@ -1944,14 +1741,6 @@ AC_SUBST(CHMOD)
|
|||||||
AC_SUBST(CLDFLAGS)
|
AC_SUBST(CLDFLAGS)
|
||||||
AC_SUBST(CLDNOWHOLEARCHIVE)
|
AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||||
AC_SUBST(CLDWHOLEARCHIVE)
|
AC_SUBST(CLDWHOLEARCHIVE)
|
||||||
AC_SUBST(CLUSTER)
|
|
||||||
AC_SUBST(CLVMD)
|
|
||||||
AC_SUBST(CLVMD_CMANAGERS)
|
|
||||||
AC_SUBST(CLVMD_PATH)
|
|
||||||
AC_SUBST(CMAN_CFLAGS)
|
|
||||||
AC_SUBST(CMAN_LIBS)
|
|
||||||
AC_SUBST(CMAP_CFLAGS)
|
|
||||||
AC_SUBST(CMAP_LIBS)
|
|
||||||
AC_SUBST(CMDLIB)
|
AC_SUBST(CMDLIB)
|
||||||
AC_SUBST(CONFDB_CFLAGS)
|
AC_SUBST(CONFDB_CFLAGS)
|
||||||
AC_SUBST(CONFDB_LIBS)
|
AC_SUBST(CONFDB_LIBS)
|
||||||
@@ -1964,7 +1753,6 @@ AC_SUBST(DEBUG)
|
|||||||
AC_SUBST(DEFAULT_ARCHIVE_SUBDIR)
|
AC_SUBST(DEFAULT_ARCHIVE_SUBDIR)
|
||||||
AC_SUBST(DEFAULT_BACKUP_SUBDIR)
|
AC_SUBST(DEFAULT_BACKUP_SUBDIR)
|
||||||
AC_SUBST(DEFAULT_CACHE_SUBDIR)
|
AC_SUBST(DEFAULT_CACHE_SUBDIR)
|
||||||
AC_SUBST(DEFAULT_DATA_ALIGNMENT)
|
|
||||||
AC_SUBST(DEFAULT_DM_RUN_DIR)
|
AC_SUBST(DEFAULT_DM_RUN_DIR)
|
||||||
AC_SUBST(DEFAULT_LOCK_DIR)
|
AC_SUBST(DEFAULT_LOCK_DIR)
|
||||||
AC_SUBST(DEFAULT_MIRROR_SEGTYPE)
|
AC_SUBST(DEFAULT_MIRROR_SEGTYPE)
|
||||||
@@ -1976,7 +1764,6 @@ AC_SUBST(DEFAULT_SPARSE_SEGTYPE)
|
|||||||
AC_SUBST(DEFAULT_SYS_DIR)
|
AC_SUBST(DEFAULT_SYS_DIR)
|
||||||
AC_SUBST(DEFAULT_SYS_LOCK_DIR)
|
AC_SUBST(DEFAULT_SYS_LOCK_DIR)
|
||||||
AC_SUBST(DEFAULT_USE_BLKID_WIPING)
|
AC_SUBST(DEFAULT_USE_BLKID_WIPING)
|
||||||
AC_SUBST(DEFAULT_USE_LVMETAD)
|
|
||||||
AC_SUBST(DEFAULT_USE_LVMPOLLD)
|
AC_SUBST(DEFAULT_USE_LVMPOLLD)
|
||||||
AC_SUBST(DEFAULT_USE_LVMLOCKD)
|
AC_SUBST(DEFAULT_USE_LVMLOCKD)
|
||||||
AC_SUBST(DEVMAPPER)
|
AC_SUBST(DEVMAPPER)
|
||||||
@@ -2030,6 +1817,7 @@ AC_SUBST(QUORUM_CFLAGS)
|
|||||||
AC_SUBST(QUORUM_LIBS)
|
AC_SUBST(QUORUM_LIBS)
|
||||||
AC_SUBST(RT_LIBS)
|
AC_SUBST(RT_LIBS)
|
||||||
AC_SUBST(READLINE_LIBS)
|
AC_SUBST(READLINE_LIBS)
|
||||||
|
AC_SUBST(EDITLINE_LIBS)
|
||||||
AC_SUBST(REPLICATORS)
|
AC_SUBST(REPLICATORS)
|
||||||
AC_SUBST(SACKPT_CFLAGS)
|
AC_SUBST(SACKPT_CFLAGS)
|
||||||
AC_SUBST(SACKPT_LIBS)
|
AC_SUBST(SACKPT_LIBS)
|
||||||
@@ -2060,14 +1848,17 @@ AC_SUBST(UDEV_SYSTEMD_BACKGROUND_JOBS)
|
|||||||
AC_SUBST(UDEV_RULE_EXEC_DETECTION)
|
AC_SUBST(UDEV_RULE_EXEC_DETECTION)
|
||||||
AC_SUBST(UDEV_HAS_BUILTIN_BLKID)
|
AC_SUBST(UDEV_HAS_BUILTIN_BLKID)
|
||||||
AC_SUBST(USE_TRACKING)
|
AC_SUBST(USE_TRACKING)
|
||||||
|
AC_SUBST(SILENT_RULES)
|
||||||
AC_SUBST(USRSBINDIR)
|
AC_SUBST(USRSBINDIR)
|
||||||
AC_SUBST(VALGRIND_POOL)
|
AC_SUBST(VALGRIND_POOL)
|
||||||
|
AC_SUBST(VDO)
|
||||||
|
AC_SUBST(VDO_FORMAT_CMD)
|
||||||
|
AC_SUBST(VDO_INCLUDE)
|
||||||
|
AC_SUBST(VDO_LIB)
|
||||||
AC_SUBST(WRITE_INSTALL)
|
AC_SUBST(WRITE_INSTALL)
|
||||||
AC_SUBST(DMEVENTD_PIDFILE)
|
AC_SUBST(DMEVENTD_PIDFILE)
|
||||||
AC_SUBST(LVMETAD_PIDFILE)
|
|
||||||
AC_SUBST(LVMPOLLD_PIDFILE)
|
AC_SUBST(LVMPOLLD_PIDFILE)
|
||||||
AC_SUBST(LVMLOCKD_PIDFILE)
|
AC_SUBST(LVMLOCKD_PIDFILE)
|
||||||
AC_SUBST(CLVMD_PIDFILE)
|
|
||||||
AC_SUBST(CMIRRORD_PIDFILE)
|
AC_SUBST(CMIRRORD_PIDFILE)
|
||||||
AC_SUBST(interface)
|
AC_SUBST(interface)
|
||||||
AC_SUBST(kerneldir)
|
AC_SUBST(kerneldir)
|
||||||
@@ -2088,8 +1879,8 @@ dnl -- keep utility scripts running properly
|
|||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
make.tmpl
|
make.tmpl
|
||||||
|
libdm/make.tmpl
|
||||||
daemons/Makefile
|
daemons/Makefile
|
||||||
daemons/clvmd/Makefile
|
|
||||||
daemons/cmirrord/Makefile
|
daemons/cmirrord/Makefile
|
||||||
daemons/dmeventd/Makefile
|
daemons/dmeventd/Makefile
|
||||||
daemons/dmeventd/libdevmapper-event.pc
|
daemons/dmeventd/libdevmapper-event.pc
|
||||||
@@ -2100,68 +1891,50 @@ daemons/dmeventd/plugins/mirror/Makefile
|
|||||||
daemons/dmeventd/plugins/snapshot/Makefile
|
daemons/dmeventd/plugins/snapshot/Makefile
|
||||||
daemons/dmeventd/plugins/thin/Makefile
|
daemons/dmeventd/plugins/thin/Makefile
|
||||||
daemons/dmeventd/plugins/vdo/Makefile
|
daemons/dmeventd/plugins/vdo/Makefile
|
||||||
daemons/dmfilemapd/Makefile
|
|
||||||
daemons/lvmdbusd/Makefile
|
daemons/lvmdbusd/Makefile
|
||||||
daemons/lvmdbusd/lvmdbusd
|
daemons/lvmdbusd/lvmdbusd
|
||||||
daemons/lvmdbusd/lvmdb.py
|
daemons/lvmdbusd/lvmdb.py
|
||||||
daemons/lvmdbusd/lvm_shell_proxy.py
|
daemons/lvmdbusd/lvm_shell_proxy.py
|
||||||
daemons/lvmdbusd/path.py
|
daemons/lvmdbusd/path.py
|
||||||
daemons/lvmetad/Makefile
|
|
||||||
daemons/lvmpolld/Makefile
|
daemons/lvmpolld/Makefile
|
||||||
daemons/lvmlockd/Makefile
|
daemons/lvmlockd/Makefile
|
||||||
device_mapper/Makefile
|
|
||||||
conf/Makefile
|
conf/Makefile
|
||||||
conf/example.conf
|
conf/example.conf
|
||||||
conf/lvmlocal.conf
|
conf/lvmlocal.conf
|
||||||
conf/command_profile_template.profile
|
conf/command_profile_template.profile
|
||||||
conf/metadata_profile_template.profile
|
conf/metadata_profile_template.profile
|
||||||
include/.symlinks
|
|
||||||
include/Makefile
|
include/Makefile
|
||||||
lib/Makefile
|
lib/Makefile
|
||||||
lib/locking/Makefile
|
|
||||||
include/lvm-version.h
|
include/lvm-version.h
|
||||||
libdaemon/Makefile
|
libdaemon/Makefile
|
||||||
libdaemon/client/Makefile
|
libdaemon/client/Makefile
|
||||||
libdaemon/server/Makefile
|
libdaemon/server/Makefile
|
||||||
libdm/Makefile
|
libdm/Makefile
|
||||||
|
libdm/dm-tools/Makefile
|
||||||
libdm/libdevmapper.pc
|
libdm/libdevmapper.pc
|
||||||
liblvm/Makefile
|
|
||||||
liblvm/liblvm2app.pc
|
|
||||||
man/Makefile
|
man/Makefile
|
||||||
po/Makefile
|
po/Makefile
|
||||||
python/Makefile
|
scripts/lvm2-pvscan.service
|
||||||
python/setup.py
|
|
||||||
scripts/blkdeactivate.sh
|
scripts/blkdeactivate.sh
|
||||||
scripts/blk_availability_init_red_hat
|
scripts/blk_availability_init_red_hat
|
||||||
scripts/blk_availability_systemd_red_hat.service
|
scripts/blk_availability_systemd_red_hat.service
|
||||||
scripts/clvmd_init_red_hat
|
|
||||||
scripts/cmirrord_init_red_hat
|
scripts/cmirrord_init_red_hat
|
||||||
scripts/com.redhat.lvmdbus1.service
|
scripts/com.redhat.lvmdbus1.service
|
||||||
scripts/dm_event_systemd_red_hat.service
|
scripts/dm_event_systemd_red_hat.service
|
||||||
scripts/dm_event_systemd_red_hat.socket
|
scripts/dm_event_systemd_red_hat.socket
|
||||||
scripts/lvm2_cluster_activation_red_hat.sh
|
|
||||||
scripts/lvm2_cluster_activation_systemd_red_hat.service
|
|
||||||
scripts/lvm2_clvmd_systemd_red_hat.service
|
|
||||||
scripts/lvm2_cmirrord_systemd_red_hat.service
|
scripts/lvm2_cmirrord_systemd_red_hat.service
|
||||||
scripts/lvm2_lvmdbusd_systemd_red_hat.service
|
scripts/lvm2_lvmdbusd_systemd_red_hat.service
|
||||||
scripts/lvm2_lvmetad_init_red_hat
|
|
||||||
scripts/lvm2_lvmetad_systemd_red_hat.service
|
|
||||||
scripts/lvm2_lvmetad_systemd_red_hat.socket
|
|
||||||
scripts/lvm2_lvmpolld_init_red_hat
|
scripts/lvm2_lvmpolld_init_red_hat
|
||||||
scripts/lvm2_lvmpolld_systemd_red_hat.service
|
scripts/lvm2_lvmpolld_systemd_red_hat.service
|
||||||
scripts/lvm2_lvmpolld_systemd_red_hat.socket
|
scripts/lvm2_lvmpolld_systemd_red_hat.socket
|
||||||
scripts/lvm2_lvmlockd_systemd_red_hat.service
|
scripts/lvmlockd.service
|
||||||
scripts/lvm2_lvmlocking_systemd_red_hat.service
|
scripts/lvmlocks.service
|
||||||
scripts/lvm2_monitoring_init_red_hat
|
scripts/lvm2_monitoring_init_red_hat
|
||||||
scripts/lvm2_monitoring_systemd_red_hat.service
|
scripts/lvm2_monitoring_systemd_red_hat.service
|
||||||
scripts/lvm2_pvscan_systemd_red_hat@.service
|
|
||||||
scripts/lvm2_tmpfiles_red_hat.conf
|
scripts/lvm2_tmpfiles_red_hat.conf
|
||||||
scripts/lvmdump.sh
|
scripts/lvmdump.sh
|
||||||
scripts/Makefile
|
scripts/Makefile
|
||||||
test/Makefile
|
test/Makefile
|
||||||
test/api/Makefile
|
|
||||||
test/api/python_lvm_unit.py
|
|
||||||
test/unit/Makefile
|
|
||||||
tools/Makefile
|
tools/Makefile
|
||||||
udev/Makefile
|
udev/Makefile
|
||||||
])
|
])
|
||||||
@@ -2179,6 +1952,9 @@ AS_IF([test -n "$CACHE_CONFIGURE_WARN"],
|
|||||||
AS_IF([test -n "$CACHE_CHECK_VERSION_WARN"],
|
AS_IF([test -n "$CACHE_CHECK_VERSION_WARN"],
|
||||||
[AC_MSG_WARN([You should install latest cache_check vsn 0.7.0 to use lvm2 cache metadata format 2])])
|
[AC_MSG_WARN([You should install latest cache_check vsn 0.7.0 to use lvm2 cache metadata format 2])])
|
||||||
|
|
||||||
|
AS_IF([test -n "$VDO_CONFIGURE_WARN"],
|
||||||
|
[AC_MSG_WARN([Unrecognized 'vdoformat' tool is REQUIRED for VDO logical volume creation!])])
|
||||||
|
|
||||||
|
|
||||||
AS_IF([test "$ODIRECT" != yes],
|
AS_IF([test "$ODIRECT" != yes],
|
||||||
[AC_MSG_WARN([O_DIRECT disabled: low-memory pvmove may lock up])])
|
[AC_MSG_WARN([O_DIRECT disabled: low-memory pvmove may lock up])])
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile
|
|||||||
return "STRING";
|
return "STRING";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
if (lv)
|
if (lv)
|
||||||
@@ -53,6 +54,7 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
|||||||
|
|
||||||
__coverity_panic__();
|
__coverity_panic__();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* simple_memccpy() from glibc */
|
/* simple_memccpy() from glibc */
|
||||||
void *memccpy(void *dest, const void *src, int c, size_t n)
|
void *memccpy(void *dest, const void *src, int c, size_t n)
|
||||||
|
|||||||
@@ -15,11 +15,7 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
.PHONY: dmeventd clvmd cmirrord lvmetad lvmpolld lvmlockd
|
.PHONY: dmeventd cmirrord lvmpolld lvmlockd
|
||||||
|
|
||||||
ifneq ("@CLVMD@", "none")
|
|
||||||
SUBDIRS += clvmd
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ("@BUILD_CMIRRORD@", "yes")
|
ifeq ("@BUILD_CMIRRORD@", "yes")
|
||||||
SUBDIRS += cmirrord
|
SUBDIRS += cmirrord
|
||||||
@@ -32,10 +28,6 @@ daemons.cflow: dmeventd.cflow
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ("@BUILD_LVMETAD@", "yes")
|
|
||||||
SUBDIRS += lvmetad
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ("@BUILD_LVMPOLLD@", "yes")
|
ifeq ("@BUILD_LVMPOLLD@", "yes")
|
||||||
SUBDIRS += lvmpolld
|
SUBDIRS += lvmpolld
|
||||||
endif
|
endif
|
||||||
@@ -48,12 +40,8 @@ ifeq ("@BUILD_LVMDBUSD@", "yes")
|
|||||||
SUBDIRS += lvmdbusd
|
SUBDIRS += lvmdbusd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ("@BUILD_DMFILEMAPD@", "yes")
|
|
||||||
SUBDIRS += dmfilemapd
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(MAKECMDGOALS),distclean)
|
ifeq ($(MAKECMDGOALS),distclean)
|
||||||
SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd dmfilemapd
|
SUBDIRS = cmirrord dmeventd lvmpolld lvmlockd lvmdbusd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|||||||
1
daemons/clvmd/.gitignore
vendored
1
daemons/clvmd/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
clvmd
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
#
|
|
||||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
|
||||||
|
|
||||||
LIBS += $(LVMINTERNAL_LIBS) -ldevmapper $(PTHREAD_LIBS) -laio
|
|
||||||
CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
|
|
||||||
|
|
||||||
INSTALL_TARGETS = \
|
|
||||||
install_clvmd
|
|
||||||
|
|
||||||
clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) \
|
|
||||||
-o clvmd $(OBJECTS) $(LMLIBS) $(LIBS)
|
|
||||||
|
|
||||||
.PHONY: install_clvmd
|
|
||||||
|
|
||||||
install_clvmd: $(TARGETS)
|
|
||||||
$(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd
|
|
||||||
|
|
||||||
install: $(INSTALL_TARGETS)
|
|
||||||
|
|
||||||
install_cluster: $(INSTALL_TARGETS)
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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"
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
struct clvm_header {
|
|
||||||
uint8_t cmd; /* See below */
|
|
||||||
uint8_t flags; /* See below */
|
|
||||||
uint16_t xid; /* Transaction ID */
|
|
||||||
uint32_t clientid; /* Only used in Daemon->Daemon comms */
|
|
||||||
int32_t status; /* For replies, whether request succeeded */
|
|
||||||
uint32_t arglen; /* Length of argument below.
|
|
||||||
If >1500 then it will be passed
|
|
||||||
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 */
|
|
||||||
#define 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.*/
|
|
||||||
#ifndef NODE_ALL
|
|
||||||
# define NODE_ALL "*"
|
|
||||||
# define NODE_LOCAL "."
|
|
||||||
# define NODE_REMOTE "^"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,505 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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(void)
|
|
||||||
{
|
|
||||||
return cman_get_fd(c_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _get_num_nodes(void)
|
|
||||||
{
|
|
||||||
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(void)
|
|
||||||
{
|
|
||||||
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(void)
|
|
||||||
{
|
|
||||||
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(void)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,415 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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;
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
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];
|
|
||||||
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) {
|
|
||||||
if (*buf)
|
|
||||||
*retlen = dm_snprintf(*buf, buflen, "%s", strerror(status)) + 1;
|
|
||||||
else
|
|
||||||
*retlen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lock_vg(struct local_client *client)
|
|
||||||
{
|
|
||||||
struct dm_hash_table *lock_hash;
|
|
||||||
struct clvm_header *header =
|
|
||||||
(struct clvm_header *) client->bits.localsock.cmd;
|
|
||||||
unsigned char lock_cmd;
|
|
||||||
int lock_mode;
|
|
||||||
char *args = header->node + strlen(header->node) + 1;
|
|
||||||
int lkid;
|
|
||||||
int status;
|
|
||||||
char *lockname;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Keep a track of VG locks in our own hash table. In current
|
|
||||||
* practice there should only ever be more than two VGs locked
|
|
||||||
* if a user tries to merge lots of them at once
|
|
||||||
*/
|
|
||||||
if (!client->bits.localsock.private) {
|
|
||||||
if (!(lock_hash = dm_hash_create(3)))
|
|
||||||
return ENOMEM;
|
|
||||||
client->bits.localsock.private = (void *) lock_hash;
|
|
||||||
} else
|
|
||||||
lock_hash = (struct dm_hash_table *) client->bits.localsock.private;
|
|
||||||
|
|
||||||
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("(%p) doing PRE command LOCK_VG '%s' at %x\n", client, lockname, lock_cmd);
|
|
||||||
|
|
||||||
if (lock_mode == LCK_UNLOCK) {
|
|
||||||
if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname)))
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
if ((status = sync_unlock(lockname, lkid)))
|
|
||||||
status = errno;
|
|
||||||
else
|
|
||||||
dm_hash_remove(lock_hash, lockname);
|
|
||||||
} else {
|
|
||||||
/* Read locks need to be PR; other modes get passed through */
|
|
||||||
if (lock_mode == LCK_READ)
|
|
||||||
lock_mode = LCK_PREAD;
|
|
||||||
|
|
||||||
if ((status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid)))
|
|
||||||
status = errno;
|
|
||||||
else if (!dm_hash_insert(lock_hash, lockname, (void *) (long) lkid))
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
switch (header->cmd) {
|
|
||||||
case CLVMD_CMD_TEST:
|
|
||||||
status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
|
|
||||||
client->bits.localsock.private = (void *)(long)lockid;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CLVMD_CMD_LOCK_VG:
|
|
||||||
lockname = &args[2];
|
|
||||||
/* We take out a real lock unless LCK_CACHE was set */
|
|
||||||
if (!strncmp(lockname, "V_", 2) ||
|
|
||||||
!strncmp(lockname, "P_#", 3))
|
|
||||||
status = lock_vg(client);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CLVMD_CMD_LOCK_LV:
|
|
||||||
lock_cmd = args[0];
|
|
||||||
lock_flags = args[1];
|
|
||||||
lockname = &args[2];
|
|
||||||
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CLVMD_CMD_REFRESH:
|
|
||||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
|
||||||
case CLVMD_CMD_SET_DEBUG:
|
|
||||||
case CLVMD_CMD_VG_BACKUP:
|
|
||||||
case CLVMD_CMD_SYNC_NAMES:
|
|
||||||
case CLVMD_CMD_LOCK_QUERY:
|
|
||||||
case CLVMD_CMD_RESTART:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log_error("Unknown command %d received\n", header->cmd);
|
|
||||||
status = EINVAL;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that the post-command routine is called even if the pre-command or the real command
|
|
||||||
failed */
|
|
||||||
int do_post_command(struct local_client *client)
|
|
||||||
{
|
|
||||||
struct clvm_header *header =
|
|
||||||
(struct clvm_header *) client->bits.localsock.cmd;
|
|
||||||
int status = 0;
|
|
||||||
unsigned char lock_cmd;
|
|
||||||
unsigned char lock_flags;
|
|
||||||
char *args = header->node + strlen(header->node) + 1;
|
|
||||||
char *lockname;
|
|
||||||
|
|
||||||
switch (header->cmd) {
|
|
||||||
case CLVMD_CMD_TEST:
|
|
||||||
status = sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
|
||||||
client->bits.localsock.private = NULL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CLVMD_CMD_LOCK_LV:
|
|
||||||
lock_cmd = args[0];
|
|
||||||
lock_flags = args[1];
|
|
||||||
lockname = &args[2];
|
|
||||||
status = post_lock_lv(lock_cmd, lock_flags, lockname);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* Nothing to do here */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Called when the client is about to be deleted */
|
|
||||||
void cmd_client_cleanup(struct local_client *client)
|
|
||||||
{
|
|
||||||
struct dm_hash_node *v;
|
|
||||||
struct dm_hash_table *lock_hash;
|
|
||||||
int lkid;
|
|
||||||
char *lockname;
|
|
||||||
|
|
||||||
DEBUGLOG("(%p) Client thread cleanup\n", client);
|
|
||||||
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("(%p) Cleanup: Unlocking lock %s %x\n", client, lockname, lkid);
|
|
||||||
(void) sync_unlock(lockname, lkid);
|
|
||||||
}
|
|
||||||
|
|
||||||
dm_hash_destroy(lock_hash);
|
|
||||||
client->bits.localsock.private = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int restart_clvmd(void)
|
|
||||||
{
|
|
||||||
const char **argv;
|
|
||||||
char *lv_name;
|
|
||||||
int argc = 0, max_locks = 0;
|
|
||||||
struct dm_hash_node *hn = NULL;
|
|
||||||
char debug_arg[16];
|
|
||||||
const char *clvmd = getenv("LVM_CLVMD_BINARY") ? : CLVMD_PATH;
|
|
||||||
|
|
||||||
DEBUGLOG("clvmd restart requested\n");
|
|
||||||
|
|
||||||
/* Count exclusively-open LVs */
|
|
||||||
do {
|
|
||||||
hn = get_next_excl_lock(hn, &lv_name);
|
|
||||||
if (lv_name) {
|
|
||||||
max_locks++;
|
|
||||||
if (!*lv_name)
|
|
||||||
break; /* FIXME: Is this error ? */
|
|
||||||
}
|
|
||||||
} while (hn);
|
|
||||||
|
|
||||||
/* clvmd + locks (-E uuid) + debug (-d X) + NULL */
|
|
||||||
if (!(argv = malloc((max_locks * 2 + 6) * sizeof(*argv))))
|
|
||||||
goto_out;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Build the command-line
|
|
||||||
*/
|
|
||||||
argv[argc++] = "clvmd";
|
|
||||||
|
|
||||||
/* Propagate debug options */
|
|
||||||
if (clvmd_get_debug()) {
|
|
||||||
if (dm_snprintf(debug_arg, sizeof(debug_arg), "-d%u", clvmd_get_debug()) < 0)
|
|
||||||
goto_out;
|
|
||||||
argv[argc++] = debug_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Propagate foreground options */
|
|
||||||
if (clvmd_get_foreground())
|
|
||||||
argv[argc++] = "-f";
|
|
||||||
|
|
||||||
argv[argc++] = "-I";
|
|
||||||
argv[argc++] = clops->name;
|
|
||||||
|
|
||||||
/* Now add the exclusively-open LVs */
|
|
||||||
hn = NULL;
|
|
||||||
do {
|
|
||||||
hn = get_next_excl_lock(hn, &lv_name);
|
|
||||||
if (lv_name) {
|
|
||||||
if (!*lv_name)
|
|
||||||
break; /* FIXME: Is this error ? */
|
|
||||||
argv[argc++] = "-E";
|
|
||||||
argv[argc++] = lv_name;
|
|
||||||
DEBUGLOG("excl lock: %s\n", lv_name);
|
|
||||||
}
|
|
||||||
} while (hn);
|
|
||||||
argv[argc] = NULL;
|
|
||||||
|
|
||||||
/* Exec new clvmd */
|
|
||||||
DEBUGLOG("--- Restarting %s ---\n", clvmd);
|
|
||||||
for (argc = 1; argv[argc]; argc++) DEBUGLOG("--- %d: %s\n", argc, argv[argc]);
|
|
||||||
|
|
||||||
/* NOTE: This will fail when downgrading! */
|
|
||||||
execvp(clvmd, (char **)argv);
|
|
||||||
out:
|
|
||||||
/* We failed */
|
|
||||||
DEBUGLOG("Restart of clvmd failed.\n");
|
|
||||||
|
|
||||||
free(argv);
|
|
||||||
|
|
||||||
return EIO;
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
|
|
||||||
@@ -1,662 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2009-2012 Red Hat, Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* This file is part of LVM2.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU Lesser General Public License v.2.1.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This provides the interface between clvmd and corosync/DLM as the cluster
|
|
||||||
* and lock manager.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "clvmd-common.h"
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "clvm.h"
|
|
||||||
#include "clvmd-comms.h"
|
|
||||||
#include "clvmd.h"
|
|
||||||
#include "lvm-functions.h"
|
|
||||||
|
|
||||||
#include "locking.h"
|
|
||||||
|
|
||||||
#include <corosync/cpg.h>
|
|
||||||
#include <corosync/quorum.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_COROSYNC_CONFDB_H
|
|
||||||
# include <corosync/confdb.h>
|
|
||||||
#elif defined HAVE_COROSYNC_CMAP_H
|
|
||||||
# include <corosync/cmap.h>
|
|
||||||
#else
|
|
||||||
# error "Either HAVE_COROSYNC_CONFDB_H or HAVE_COROSYNC_CMAP_H must be defined."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <libdlm.h>
|
|
||||||
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
/* Timeout value for several corosync calls */
|
|
||||||
#define LOCKSPACE_NAME "clvmd"
|
|
||||||
|
|
||||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
|
|
||||||
const struct cpg_name *groupName,
|
|
||||||
uint32_t nodeid,
|
|
||||||
uint32_t pid,
|
|
||||||
void *msg,
|
|
||||||
size_t msg_len);
|
|
||||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
|
||||||
const struct cpg_name *groupName,
|
|
||||||
const struct cpg_address *member_list, size_t member_list_entries,
|
|
||||||
const struct cpg_address *left_list, size_t left_list_entries,
|
|
||||||
const struct cpg_address *joined_list, size_t joined_list_entries);
|
|
||||||
static void _cluster_closedown(void);
|
|
||||||
|
|
||||||
/* Hash list of nodes in the cluster */
|
|
||||||
static struct dm_hash_table *node_hash;
|
|
||||||
|
|
||||||
/* Number of active nodes */
|
|
||||||
static int num_nodes;
|
|
||||||
static unsigned int our_nodeid;
|
|
||||||
|
|
||||||
static struct local_client *cluster_client;
|
|
||||||
|
|
||||||
/* Corosync handles */
|
|
||||||
static cpg_handle_t cpg_handle;
|
|
||||||
static quorum_handle_t quorum_handle;
|
|
||||||
|
|
||||||
/* DLM Handle */
|
|
||||||
static dlm_lshandle_t *lockspace;
|
|
||||||
|
|
||||||
static struct cpg_name cpg_group_name;
|
|
||||||
|
|
||||||
/* Corosync callback structs */
|
|
||||||
cpg_callbacks_t corosync_cpg_callbacks = {
|
|
||||||
.cpg_deliver_fn = corosync_cpg_deliver_callback,
|
|
||||||
.cpg_confchg_fn = corosync_cpg_confchg_callback,
|
|
||||||
};
|
|
||||||
|
|
||||||
quorum_callbacks_t quorum_callbacks = {
|
|
||||||
.quorum_notify_fn = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct node_info
|
|
||||||
{
|
|
||||||
enum {NODE_DOWN, NODE_CLVMD} state;
|
|
||||||
int nodeid;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Set errno to something approximating the right value and return 0 or -1 */
|
|
||||||
static int cs_to_errno(cs_error_t err)
|
|
||||||
{
|
|
||||||
switch(err)
|
|
||||||
{
|
|
||||||
case CS_OK:
|
|
||||||
return 0;
|
|
||||||
case CS_ERR_LIBRARY:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_VERSION:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_INIT:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_TIMEOUT:
|
|
||||||
errno = ETIME;
|
|
||||||
break;
|
|
||||||
case CS_ERR_TRY_AGAIN:
|
|
||||||
errno = EAGAIN;
|
|
||||||
break;
|
|
||||||
case CS_ERR_INVALID_PARAM:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_NO_MEMORY:
|
|
||||||
errno = ENOMEM;
|
|
||||||
break;
|
|
||||||
case CS_ERR_BAD_HANDLE:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_BUSY:
|
|
||||||
errno = EBUSY;
|
|
||||||
break;
|
|
||||||
case CS_ERR_ACCESS:
|
|
||||||
errno = EPERM;
|
|
||||||
break;
|
|
||||||
case CS_ERR_NOT_EXIST:
|
|
||||||
errno = ENOENT;
|
|
||||||
break;
|
|
||||||
case CS_ERR_NAME_TOO_LONG:
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
break;
|
|
||||||
case CS_ERR_EXIST:
|
|
||||||
errno = EEXIST;
|
|
||||||
break;
|
|
||||||
case CS_ERR_NO_SPACE:
|
|
||||||
errno = ENOSPC;
|
|
||||||
break;
|
|
||||||
case CS_ERR_INTERRUPT:
|
|
||||||
errno = EINTR;
|
|
||||||
break;
|
|
||||||
case CS_ERR_NAME_NOT_FOUND:
|
|
||||||
errno = ENOENT;
|
|
||||||
break;
|
|
||||||
case CS_ERR_NO_RESOURCES:
|
|
||||||
errno = ENOMEM;
|
|
||||||
break;
|
|
||||||
case CS_ERR_NOT_SUPPORTED:
|
|
||||||
errno = EOPNOTSUPP;
|
|
||||||
break;
|
|
||||||
case CS_ERR_BAD_OPERATION:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_FAILED_OPERATION:
|
|
||||||
errno = EIO;
|
|
||||||
break;
|
|
||||||
case CS_ERR_MESSAGE_ERROR:
|
|
||||||
errno = EIO;
|
|
||||||
break;
|
|
||||||
case CS_ERR_QUEUE_FULL:
|
|
||||||
errno = EXFULL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_QUEUE_NOT_AVAILABLE:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_BAD_FLAGS:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case CS_ERR_TOO_BIG:
|
|
||||||
errno = E2BIG;
|
|
||||||
break;
|
|
||||||
case CS_ERR_NO_SECTIONS:
|
|
||||||
errno = ENOMEM;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *print_corosync_csid(const char *csid)
|
|
||||||
{
|
|
||||||
static char buf[128];
|
|
||||||
int id;
|
|
||||||
|
|
||||||
memcpy(&id, csid, sizeof(int));
|
|
||||||
sprintf(buf, "%d", id);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
|
|
||||||
const struct cpg_name *groupName,
|
|
||||||
uint32_t nodeid,
|
|
||||||
uint32_t pid,
|
|
||||||
void *msg,
|
|
||||||
size_t msg_len)
|
|
||||||
{
|
|
||||||
int target_nodeid;
|
|
||||||
|
|
||||||
memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
|
|
||||||
|
|
||||||
DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
|
|
||||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
|
||||||
|
|
||||||
if (nodeid != our_nodeid)
|
|
||||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
|
||||||
process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
|
|
||||||
msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
|
||||||
const struct cpg_name *groupName,
|
|
||||||
const struct cpg_address *member_list, size_t member_list_entries,
|
|
||||||
const struct cpg_address *left_list, size_t left_list_entries,
|
|
||||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n",
|
|
||||||
joined_list_entries, left_list_entries, member_list_entries);
|
|
||||||
|
|
||||||
for (i=0; i<joined_list_entries; i++) {
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash,
|
|
||||||
(char *)&joined_list[i].nodeid,
|
|
||||||
COROSYNC_CSID_LEN);
|
|
||||||
if (!ninfo) {
|
|
||||||
ninfo = malloc(sizeof(struct node_info));
|
|
||||||
if (!ninfo) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ninfo->nodeid = joined_list[i].nodeid;
|
|
||||||
dm_hash_insert_binary(node_hash,
|
|
||||||
(char *)&ninfo->nodeid,
|
|
||||||
COROSYNC_CSID_LEN, ninfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ninfo->state = NODE_CLVMD;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<left_list_entries; i++) {
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash,
|
|
||||||
(char *)&left_list[i].nodeid,
|
|
||||||
COROSYNC_CSID_LEN);
|
|
||||||
if (ninfo)
|
|
||||||
ninfo->state = NODE_DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
num_nodes = member_list_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _init_cluster(void)
|
|
||||||
{
|
|
||||||
cs_error_t err;
|
|
||||||
|
|
||||||
#ifdef QUORUM_SET /* corosync/quorum.h */
|
|
||||||
uint32_t quorum_type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
node_hash = dm_hash_create(100);
|
|
||||||
|
|
||||||
err = cpg_initialize(&cpg_handle,
|
|
||||||
&corosync_cpg_callbacks);
|
|
||||||
if (err != CS_OK) {
|
|
||||||
syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
|
|
||||||
err);
|
|
||||||
DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
|
|
||||||
return cs_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef QUORUM_SET
|
|
||||||
err = quorum_initialize(&quorum_handle,
|
|
||||||
&quorum_callbacks,
|
|
||||||
&quorum_type);
|
|
||||||
|
|
||||||
if (quorum_type != QUORUM_SET) {
|
|
||||||
syslog(LOG_ERR, "Corosync quorum service is not configured");
|
|
||||||
DEBUGLOG("Corosync quorum service is not configured");
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
err = quorum_initialize(&quorum_handle,
|
|
||||||
&quorum_callbacks);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (err != CS_OK) {
|
|
||||||
syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
|
|
||||||
err);
|
|
||||||
DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
|
|
||||||
return cs_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a lockspace for LV & VG locks to live in */
|
|
||||||
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
|
|
||||||
if (!lockspace) {
|
|
||||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
|
||||||
if (!lockspace) {
|
|
||||||
syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
DEBUGLOG("Created DLM lockspace for CLVMD.\n");
|
|
||||||
} else
|
|
||||||
DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
|
|
||||||
|
|
||||||
dlm_ls_pthread_init(lockspace);
|
|
||||||
DEBUGLOG("DLM initialisation complete\n");
|
|
||||||
|
|
||||||
/* Connect to the clvmd group */
|
|
||||||
strcpy((char *)cpg_group_name.value, "clvmd");
|
|
||||||
cpg_group_name.length = strlen((char *)cpg_group_name.value);
|
|
||||||
err = cpg_join(cpg_handle, &cpg_group_name);
|
|
||||||
if (err != CS_OK) {
|
|
||||||
cpg_finalize(cpg_handle);
|
|
||||||
quorum_finalize(quorum_handle);
|
|
||||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
|
||||||
syslog(LOG_ERR, "Cannot join clvmd process group");
|
|
||||||
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
|
|
||||||
return cs_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cpg_local_get(cpg_handle,
|
|
||||||
&our_nodeid);
|
|
||||||
if (err != CS_OK) {
|
|
||||||
cpg_finalize(cpg_handle);
|
|
||||||
quorum_finalize(quorum_handle);
|
|
||||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
|
||||||
syslog(LOG_ERR, "Cannot get local node id\n");
|
|
||||||
return cs_to_errno(err);
|
|
||||||
}
|
|
||||||
DEBUGLOG("Our local node id is %d\n", our_nodeid);
|
|
||||||
|
|
||||||
DEBUGLOG("Connected to Corosync\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cluster_closedown(void)
|
|
||||||
{
|
|
||||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
|
||||||
cpg_finalize(cpg_handle);
|
|
||||||
quorum_finalize(quorum_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _get_our_csid(char *csid)
|
|
||||||
{
|
|
||||||
memcpy(csid, &our_nodeid, sizeof(int));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Corosync doesn't really have nmode names so we
|
|
||||||
just use the node ID in hex instead */
|
|
||||||
static int _csid_from_name(char *csid, const char *name)
|
|
||||||
{
|
|
||||||
int nodeid;
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
if (sscanf(name, "%x", &nodeid) == 1) {
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
|
||||||
if (ninfo)
|
|
||||||
return nodeid;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _name_from_csid(const char *csid, char *name)
|
|
||||||
{
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
|
||||||
if (!ninfo)
|
|
||||||
{
|
|
||||||
sprintf(name, "UNKNOWN %s", print_corosync_csid(csid));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(name, "%x", ninfo->nodeid);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _get_num_nodes(void)
|
|
||||||
{
|
|
||||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
|
||||||
return num_nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Node is now known to be running a clvmd */
|
|
||||||
static void _add_up_node(const char *csid)
|
|
||||||
{
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
|
||||||
if (!ninfo) {
|
|
||||||
DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
|
|
||||||
print_corosync_csid(csid));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGLOG("corosync_add_up_node %d\n", ninfo->nodeid);
|
|
||||||
|
|
||||||
ninfo->state = NODE_CLVMD;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
|
||||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
|
||||||
void (*callback)(struct local_client *,
|
|
||||||
const char *csid, int node_up))
|
|
||||||
{
|
|
||||||
struct dm_hash_node *hn;
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
dm_hash_iterate(hn, node_hash)
|
|
||||||
{
|
|
||||||
char csid[COROSYNC_CSID_LEN];
|
|
||||||
|
|
||||||
ninfo = dm_hash_get_data(node_hash, hn);
|
|
||||||
memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN);
|
|
||||||
|
|
||||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
|
||||||
ninfo->state);
|
|
||||||
|
|
||||||
if (ninfo->state == NODE_CLVMD)
|
|
||||||
callback(master_client, csid, 1);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Real locking */
|
|
||||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
|
||||||
{
|
|
||||||
struct dlm_lksb lksb;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
|
||||||
|
|
||||||
if (flags & LKF_CONVERT)
|
|
||||||
lksb.sb_lkid = *lockid;
|
|
||||||
|
|
||||||
err = dlm_ls_lock_wait(lockspace,
|
|
||||||
mode,
|
|
||||||
&lksb,
|
|
||||||
flags,
|
|
||||||
resource,
|
|
||||||
strlen(resource),
|
|
||||||
0,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (err != 0)
|
|
||||||
{
|
|
||||||
DEBUGLOG("dlm_ls_lock returned %d\n", errno);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if (lksb.sb_status != 0)
|
|
||||||
{
|
|
||||||
DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
|
|
||||||
errno = lksb.sb_status;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
|
|
||||||
|
|
||||||
*lockid = lksb.sb_lkid;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int _unlock_resource(const char *resource, int lockid)
|
|
||||||
{
|
|
||||||
struct dlm_lksb lksb;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
|
|
||||||
lksb.sb_lkid = lockid;
|
|
||||||
|
|
||||||
err = dlm_ls_unlock_wait(lockspace,
|
|
||||||
lockid,
|
|
||||||
0,
|
|
||||||
&lksb);
|
|
||||||
if (err != 0)
|
|
||||||
{
|
|
||||||
DEBUGLOG("Unlock returned %d\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if (lksb.sb_status != EUNLOCK)
|
|
||||||
{
|
|
||||||
DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
|
|
||||||
errno = lksb.sb_status;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _is_quorate(void)
|
|
||||||
{
|
|
||||||
int quorate;
|
|
||||||
if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
|
|
||||||
return quorate;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _get_main_cluster_fd(void)
|
|
||||||
{
|
|
||||||
int select_fd;
|
|
||||||
|
|
||||||
cpg_fd_get(cpg_handle, &select_fd);
|
|
||||||
return select_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
|
||||||
const char *csid,
|
|
||||||
struct local_client **new_client)
|
|
||||||
{
|
|
||||||
cluster_client = fd;
|
|
||||||
*new_client = NULL;
|
|
||||||
cpg_dispatch(cpg_handle, CS_DISPATCH_ONE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
|
||||||
const char *errtext)
|
|
||||||
{
|
|
||||||
static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
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;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&_mutex);
|
|
||||||
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
|
|
||||||
pthread_mutex_unlock(&_mutex);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,687 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* This file is part of LVM2.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU Lesser General Public License v.2.1.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This provides the interface between clvmd and OpenAIS as the cluster
|
|
||||||
* and lock manager.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "clvmd-common.h"
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include <openais/saAis.h>
|
|
||||||
#include <openais/saLck.h>
|
|
||||||
|
|
||||||
#include <corosync/corotypes.h>
|
|
||||||
#include <corosync/cpg.h>
|
|
||||||
|
|
||||||
#include "locking.h"
|
|
||||||
#include "clvm.h"
|
|
||||||
#include "clvmd-comms.h"
|
|
||||||
#include "lvm-functions.h"
|
|
||||||
#include "clvmd.h"
|
|
||||||
|
|
||||||
/* Timeout value for several openais calls */
|
|
||||||
#define TIMEOUT 10
|
|
||||||
|
|
||||||
static void openais_cpg_deliver_callback (cpg_handle_t handle,
|
|
||||||
const struct cpg_name *groupName,
|
|
||||||
uint32_t nodeid,
|
|
||||||
uint32_t pid,
|
|
||||||
void *msg,
|
|
||||||
size_t msg_len);
|
|
||||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
|
|
||||||
const struct cpg_name *groupName,
|
|
||||||
const struct cpg_address *member_list, size_t member_list_entries,
|
|
||||||
const struct cpg_address *left_list, size_t left_list_entries,
|
|
||||||
const struct cpg_address *joined_list, size_t joined_list_entries);
|
|
||||||
|
|
||||||
static void _cluster_closedown(void);
|
|
||||||
|
|
||||||
/* Hash list of nodes in the cluster */
|
|
||||||
static struct dm_hash_table *node_hash;
|
|
||||||
|
|
||||||
/* For associating lock IDs & resource handles */
|
|
||||||
static struct dm_hash_table *lock_hash;
|
|
||||||
|
|
||||||
/* Number of active nodes */
|
|
||||||
static int num_nodes;
|
|
||||||
static unsigned int our_nodeid;
|
|
||||||
|
|
||||||
static struct local_client *cluster_client;
|
|
||||||
|
|
||||||
/* OpenAIS handles */
|
|
||||||
static cpg_handle_t cpg_handle;
|
|
||||||
static SaLckHandleT lck_handle;
|
|
||||||
|
|
||||||
static struct cpg_name cpg_group_name;
|
|
||||||
|
|
||||||
/* Openais callback structs */
|
|
||||||
cpg_callbacks_t openais_cpg_callbacks = {
|
|
||||||
.cpg_deliver_fn = openais_cpg_deliver_callback,
|
|
||||||
.cpg_confchg_fn = openais_cpg_confchg_callback,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct node_info
|
|
||||||
{
|
|
||||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
|
||||||
int nodeid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lock_info
|
|
||||||
{
|
|
||||||
SaLckResourceHandleT res_handle;
|
|
||||||
SaLckLockIdT lock_id;
|
|
||||||
SaNameT lock_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Set errno to something approximating the right value and return 0 or -1 */
|
|
||||||
static int ais_to_errno(SaAisErrorT err)
|
|
||||||
{
|
|
||||||
switch(err)
|
|
||||||
{
|
|
||||||
case SA_AIS_OK:
|
|
||||||
return 0;
|
|
||||||
case SA_AIS_ERR_LIBRARY:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_VERSION:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_INIT:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_TIMEOUT:
|
|
||||||
errno = ETIME;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_TRY_AGAIN:
|
|
||||||
errno = EAGAIN;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_INVALID_PARAM:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_NO_MEMORY:
|
|
||||||
errno = ENOMEM;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_BAD_HANDLE:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_BUSY:
|
|
||||||
errno = EBUSY;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_ACCESS:
|
|
||||||
errno = EPERM;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_NOT_EXIST:
|
|
||||||
errno = ENOENT;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_NAME_TOO_LONG:
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_EXIST:
|
|
||||||
errno = EEXIST;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_NO_SPACE:
|
|
||||||
errno = ENOSPC;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_INTERRUPT:
|
|
||||||
errno = EINTR;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_NAME_NOT_FOUND:
|
|
||||||
errno = ENOENT;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_NO_RESOURCES:
|
|
||||||
errno = ENOMEM;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_NOT_SUPPORTED:
|
|
||||||
errno = EOPNOTSUPP;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_BAD_OPERATION:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_FAILED_OPERATION:
|
|
||||||
errno = EIO;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_MESSAGE_ERROR:
|
|
||||||
errno = EIO;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_QUEUE_FULL:
|
|
||||||
errno = EXFULL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_BAD_FLAGS:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_TOO_BIG:
|
|
||||||
errno = E2BIG;
|
|
||||||
break;
|
|
||||||
case SA_AIS_ERR_NO_SECTIONS:
|
|
||||||
errno = ENOMEM;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *print_openais_csid(const char *csid)
|
|
||||||
{
|
|
||||||
static char buf[128];
|
|
||||||
int id;
|
|
||||||
|
|
||||||
memcpy(&id, csid, sizeof(int));
|
|
||||||
sprintf(buf, "%d", id);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int add_internal_client(int fd, fd_callback_t callback)
|
|
||||||
{
|
|
||||||
struct local_client *client;
|
|
||||||
|
|
||||||
DEBUGLOG("Add_internal_client, fd = %d\n", fd);
|
|
||||||
|
|
||||||
if (!(client = dm_zalloc(sizeof(*client)))) {
|
|
||||||
DEBUGLOG("malloc failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
client->fd = fd;
|
|
||||||
client->type = CLUSTER_INTERNAL;
|
|
||||||
client->callback = callback;
|
|
||||||
add_client(client);
|
|
||||||
|
|
||||||
/* Set Close-on-exec */
|
|
||||||
fcntl(fd, F_SETFD, 1);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void openais_cpg_deliver_callback (cpg_handle_t handle,
|
|
||||||
const struct cpg_name *groupName,
|
|
||||||
uint32_t nodeid,
|
|
||||||
uint32_t pid,
|
|
||||||
void *msg,
|
|
||||||
size_t msg_len)
|
|
||||||
{
|
|
||||||
int target_nodeid;
|
|
||||||
|
|
||||||
memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
|
|
||||||
|
|
||||||
DEBUGLOG("%u got message from nodeid %d for %d. len %" PRIsize_t "\n",
|
|
||||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
|
||||||
|
|
||||||
if (nodeid != our_nodeid)
|
|
||||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
|
||||||
process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
|
|
||||||
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
|
|
||||||
const struct cpg_name *groupName,
|
|
||||||
const struct cpg_address *member_list, size_t member_list_entries,
|
|
||||||
const struct cpg_address *left_list, size_t left_list_entries,
|
|
||||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
DEBUGLOG("confchg callback. %" PRIsize_t " joined, "
|
|
||||||
FMTsize_t " left, %" PRIsize_t " members\n",
|
|
||||||
joined_list_entries, left_list_entries, member_list_entries);
|
|
||||||
|
|
||||||
for (i=0; i<joined_list_entries; i++) {
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash,
|
|
||||||
(char *)&joined_list[i].nodeid,
|
|
||||||
OPENAIS_CSID_LEN);
|
|
||||||
if (!ninfo) {
|
|
||||||
ninfo = malloc(sizeof(struct node_info));
|
|
||||||
if (!ninfo) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ninfo->nodeid = joined_list[i].nodeid;
|
|
||||||
dm_hash_insert_binary(node_hash,
|
|
||||||
(char *)&ninfo->nodeid,
|
|
||||||
OPENAIS_CSID_LEN, ninfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ninfo->state = NODE_CLVMD;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<left_list_entries; i++) {
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash,
|
|
||||||
(char *)&left_list[i].nodeid,
|
|
||||||
OPENAIS_CSID_LEN);
|
|
||||||
if (ninfo)
|
|
||||||
ninfo->state = NODE_DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<member_list_entries; i++) {
|
|
||||||
if (member_list[i].nodeid == 0) continue;
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash,
|
|
||||||
(char *)&member_list[i].nodeid,
|
|
||||||
OPENAIS_CSID_LEN);
|
|
||||||
if (!ninfo) {
|
|
||||||
ninfo = malloc(sizeof(struct node_info));
|
|
||||||
if (!ninfo) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ninfo->nodeid = member_list[i].nodeid;
|
|
||||||
dm_hash_insert_binary(node_hash,
|
|
||||||
(char *)&ninfo->nodeid,
|
|
||||||
OPENAIS_CSID_LEN, ninfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ninfo->state = NODE_CLVMD;
|
|
||||||
}
|
|
||||||
|
|
||||||
num_nodes = member_list_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lck_dispatch(struct local_client *client, char *buf, int len,
|
|
||||||
const char *csid, struct local_client **new_client)
|
|
||||||
{
|
|
||||||
*new_client = NULL;
|
|
||||||
saLckDispatch(lck_handle, SA_DISPATCH_ONE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _init_cluster(void)
|
|
||||||
{
|
|
||||||
SaAisErrorT err;
|
|
||||||
SaVersionT ver = { 'B', 1, 1 };
|
|
||||||
int select_fd;
|
|
||||||
|
|
||||||
node_hash = dm_hash_create(100);
|
|
||||||
lock_hash = dm_hash_create(10);
|
|
||||||
|
|
||||||
err = cpg_initialize(&cpg_handle,
|
|
||||||
&openais_cpg_callbacks);
|
|
||||||
if (err != SA_AIS_OK) {
|
|
||||||
syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
|
|
||||||
err);
|
|
||||||
DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = saLckInitialize(&lck_handle,
|
|
||||||
NULL,
|
|
||||||
&ver);
|
|
||||||
if (err != SA_AIS_OK) {
|
|
||||||
cpg_initialize(&cpg_handle, &openais_cpg_callbacks);
|
|
||||||
syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
|
|
||||||
err);
|
|
||||||
DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connect to the clvmd group */
|
|
||||||
strcpy((char *)cpg_group_name.value, "clvmd");
|
|
||||||
cpg_group_name.length = strlen((char *)cpg_group_name.value);
|
|
||||||
err = cpg_join(cpg_handle, &cpg_group_name);
|
|
||||||
if (err != SA_AIS_OK) {
|
|
||||||
cpg_finalize(cpg_handle);
|
|
||||||
saLckFinalize(lck_handle);
|
|
||||||
syslog(LOG_ERR, "Cannot join clvmd process group");
|
|
||||||
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cpg_local_get(cpg_handle,
|
|
||||||
&our_nodeid);
|
|
||||||
if (err != SA_AIS_OK) {
|
|
||||||
cpg_finalize(cpg_handle);
|
|
||||||
saLckFinalize(lck_handle);
|
|
||||||
syslog(LOG_ERR, "Cannot get local node id\n");
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
DEBUGLOG("Our local node id is %d\n", our_nodeid);
|
|
||||||
|
|
||||||
saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
|
|
||||||
add_internal_client(select_fd, lck_dispatch);
|
|
||||||
|
|
||||||
DEBUGLOG("Connected to OpenAIS\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cluster_closedown(void)
|
|
||||||
{
|
|
||||||
saLckFinalize(lck_handle);
|
|
||||||
cpg_finalize(cpg_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _get_our_csid(char *csid)
|
|
||||||
{
|
|
||||||
memcpy(csid, &our_nodeid, sizeof(int));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OpenAIS doesn't really have nmode names so we
|
|
||||||
just use the node ID in hex instead */
|
|
||||||
static int _csid_from_name(char *csid, const char *name)
|
|
||||||
{
|
|
||||||
int nodeid;
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
if (sscanf(name, "%x", &nodeid) == 1) {
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
|
||||||
if (ninfo)
|
|
||||||
return nodeid;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _name_from_csid(const char *csid, char *name)
|
|
||||||
{
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
|
||||||
if (!ninfo)
|
|
||||||
{
|
|
||||||
sprintf(name, "UNKNOWN %s", print_openais_csid(csid));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(name, "%x", ninfo->nodeid);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _get_num_nodes()
|
|
||||||
{
|
|
||||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
|
||||||
return num_nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Node is now known to be running a clvmd */
|
|
||||||
static void _add_up_node(const char *csid)
|
|
||||||
{
|
|
||||||
struct node_info *ninfo;
|
|
||||||
|
|
||||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
|
||||||
if (!ninfo) {
|
|
||||||
DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
|
|
||||||
print_openais_csid(csid));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
|
|
||||||
|
|
||||||
ninfo->state = NODE_CLVMD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
|
||||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
|
||||||
void (*callback)(struct local_client *,
|
|
||||||
const char *csid, int node_up))
|
|
||||||
{
|
|
||||||
struct dm_hash_node *hn;
|
|
||||||
struct node_info *ninfo;
|
|
||||||
int somedown = 0;
|
|
||||||
|
|
||||||
dm_hash_iterate(hn, node_hash)
|
|
||||||
{
|
|
||||||
char csid[OPENAIS_CSID_LEN];
|
|
||||||
|
|
||||||
ninfo = dm_hash_get_data(node_hash, hn);
|
|
||||||
memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
|
|
||||||
|
|
||||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
|
||||||
ninfo->state);
|
|
||||||
|
|
||||||
if (ninfo->state != NODE_DOWN)
|
|
||||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
|
||||||
if (ninfo->state != NODE_CLVMD)
|
|
||||||
somedown = -1;
|
|
||||||
}
|
|
||||||
return somedown;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Real locking */
|
|
||||||
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
|
||||||
{
|
|
||||||
struct lock_info *linfo;
|
|
||||||
SaLckResourceHandleT res_handle;
|
|
||||||
SaAisErrorT err;
|
|
||||||
SaLckLockIdT lock_id;
|
|
||||||
SaLckLockStatusT lockStatus;
|
|
||||||
|
|
||||||
/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
|
|
||||||
if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
|
|
||||||
|
|
||||||
linfo = malloc(sizeof(struct lock_info));
|
|
||||||
if (!linfo)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
|
||||||
|
|
||||||
linfo->lock_name.length = strlen(resource)+1;
|
|
||||||
strcpy((char *)linfo->lock_name.value, resource);
|
|
||||||
|
|
||||||
err = saLckResourceOpen(lck_handle, &linfo->lock_name,
|
|
||||||
SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
|
|
||||||
if (err != SA_AIS_OK)
|
|
||||||
{
|
|
||||||
DEBUGLOG("ResourceOpen returned %d\n", err);
|
|
||||||
free(linfo);
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = saLckResourceLock(
|
|
||||||
res_handle,
|
|
||||||
&lock_id,
|
|
||||||
mode,
|
|
||||||
flags,
|
|
||||||
0,
|
|
||||||
SA_TIME_END,
|
|
||||||
&lockStatus);
|
|
||||||
if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
|
|
||||||
{
|
|
||||||
free(linfo);
|
|
||||||
saLckResourceClose(res_handle);
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for it to complete */
|
|
||||||
|
|
||||||
DEBUGLOG("lock_resource returning %d, lock_id=%" PRIx64 "\n",
|
|
||||||
err, lock_id);
|
|
||||||
|
|
||||||
linfo->lock_id = lock_id;
|
|
||||||
linfo->res_handle = res_handle;
|
|
||||||
|
|
||||||
dm_hash_insert(lock_hash, resource, linfo);
|
|
||||||
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int _unlock_resource(char *resource, int lockid)
|
|
||||||
{
|
|
||||||
SaAisErrorT err;
|
|
||||||
struct lock_info *linfo;
|
|
||||||
|
|
||||||
DEBUGLOG("unlock_resource %s\n", resource);
|
|
||||||
linfo = dm_hash_lookup(lock_hash, resource);
|
|
||||||
if (!linfo)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
DEBUGLOG("unlock_resource: lockid: %" PRIx64 "\n", linfo->lock_id);
|
|
||||||
err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
|
|
||||||
if (err != SA_AIS_OK)
|
|
||||||
{
|
|
||||||
DEBUGLOG("Unlock returned %d\n", err);
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release the resource */
|
|
||||||
dm_hash_remove(lock_hash, resource);
|
|
||||||
saLckResourceClose(linfo->res_handle);
|
|
||||||
free(linfo);
|
|
||||||
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
char lock1[strlen(resource)+3];
|
|
||||||
char lock2[strlen(resource)+3];
|
|
||||||
|
|
||||||
snprintf(lock1, sizeof(lock1), "%s-1", resource);
|
|
||||||
snprintf(lock2, sizeof(lock2), "%s-2", resource);
|
|
||||||
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case LCK_EXCL:
|
|
||||||
status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
|
|
||||||
if (status)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* If we can't get this lock too then bail out */
|
|
||||||
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
|
|
||||||
lockid);
|
|
||||||
if (status == SA_LCK_LOCK_NOT_QUEUED)
|
|
||||||
{
|
|
||||||
_unlock_resource(lock1, *lockid);
|
|
||||||
status = -1;
|
|
||||||
errno = EAGAIN;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LCK_PREAD:
|
|
||||||
case LCK_READ:
|
|
||||||
status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
|
|
||||||
if (status)
|
|
||||||
goto out;
|
|
||||||
_unlock_resource(lock2, *lockid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LCK_WRITE:
|
|
||||||
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
|
|
||||||
if (status)
|
|
||||||
goto out;
|
|
||||||
_unlock_resource(lock1, *lockid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
status = -1;
|
|
||||||
errno = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
*lockid = mode;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _sync_unlock(const char *resource, int lockid)
|
|
||||||
{
|
|
||||||
int status = 0;
|
|
||||||
char lock1[strlen(resource)+3];
|
|
||||||
char lock2[strlen(resource)+3];
|
|
||||||
|
|
||||||
snprintf(lock1, sizeof(lock1), "%s-1", resource);
|
|
||||||
snprintf(lock2, sizeof(lock2), "%s-2", resource);
|
|
||||||
|
|
||||||
_unlock_resource(lock1, lockid);
|
|
||||||
_unlock_resource(lock2, lockid);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We are always quorate ! */
|
|
||||||
static int _is_quorate()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _get_main_cluster_fd(void)
|
|
||||||
{
|
|
||||||
int select_fd;
|
|
||||||
|
|
||||||
cpg_fd_get(cpg_handle, &select_fd);
|
|
||||||
return select_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
|
||||||
const char *csid,
|
|
||||||
struct local_client **new_client)
|
|
||||||
{
|
|
||||||
cluster_client = fd;
|
|
||||||
*new_client = NULL;
|
|
||||||
cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
|
||||||
const char *errtext)
|
|
||||||
{
|
|
||||||
struct iovec iov[2];
|
|
||||||
SaAisErrorT err;
|
|
||||||
int target_node;
|
|
||||||
|
|
||||||
if (csid)
|
|
||||||
memcpy(&target_node, csid, OPENAIS_CSID_LEN);
|
|
||||||
else
|
|
||||||
target_node = 0;
|
|
||||||
|
|
||||||
iov[0].iov_base = &target_node;
|
|
||||||
iov[0].iov_len = sizeof(int);
|
|
||||||
iov[1].iov_base = (char *)buf;
|
|
||||||
iov[1].iov_len = msglen;
|
|
||||||
|
|
||||||
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
|
|
||||||
return ais_to_errno(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't have a cluster name to report here */
|
|
||||||
static int _get_cluster_name(char *buf, int buflen)
|
|
||||||
{
|
|
||||||
strncpy(buf, "OpenAIS", buflen);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct cluster_ops _cluster_openais_ops = {
|
|
||||||
.name = "openais",
|
|
||||||
.cluster_init_completed = NULL,
|
|
||||||
.cluster_send_message = _cluster_send_message,
|
|
||||||
.name_from_csid = _name_from_csid,
|
|
||||||
.csid_from_name = _csid_from_name,
|
|
||||||
.get_num_nodes = _get_num_nodes,
|
|
||||||
.cluster_fd_callback = _cluster_fd_callback,
|
|
||||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
|
||||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
|
||||||
.is_quorate = _is_quorate,
|
|
||||||
.get_our_csid = _get_our_csid,
|
|
||||||
.add_up_node = _add_up_node,
|
|
||||||
.reread_config = NULL,
|
|
||||||
.cluster_closedown = _cluster_closedown,
|
|
||||||
.get_cluster_name = _get_cluster_name,
|
|
||||||
.sync_lock = _sync_lock,
|
|
||||||
.sync_unlock = _sync_unlock,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cluster_ops *init_openais_cluster(void)
|
|
||||||
{
|
|
||||||
if (!_init_cluster())
|
|
||||||
return &_cluster_openais_ops;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
@@ -1,382 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2009-2013 Red Hat, Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* This file is part of LVM2.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU Lesser General Public License v.2.1.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "clvmd-common.h"
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "locking.h"
|
|
||||||
#include "clvm.h"
|
|
||||||
#include "clvmd-comms.h"
|
|
||||||
#include "clvmd.h"
|
|
||||||
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock";
|
|
||||||
static int listen_fd = -1;
|
|
||||||
|
|
||||||
static struct dm_hash_table *_locks;
|
|
||||||
static int _lockid;
|
|
||||||
|
|
||||||
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
/* Using one common condition for all locks for simplicity */
|
|
||||||
static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
|
|
||||||
|
|
||||||
struct lock {
|
|
||||||
struct dm_list list;
|
|
||||||
int lockid;
|
|
||||||
int mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void close_comms(void)
|
|
||||||
{
|
|
||||||
if (listen_fd != -1 && close(listen_fd))
|
|
||||||
stack;
|
|
||||||
(void)unlink(SINGLENODE_CLVMD_SOCKNAME);
|
|
||||||
listen_fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int init_comms(void)
|
|
||||||
{
|
|
||||||
mode_t old_mask;
|
|
||||||
struct sockaddr_un addr = { .sun_family = AF_UNIX };
|
|
||||||
|
|
||||||
if (!dm_strncpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
|
|
||||||
sizeof(addr.sun_path))) {
|
|
||||||
DEBUGLOG("%s: singlenode socket name too long.",
|
|
||||||
SINGLENODE_CLVMD_SOCKNAME);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
close_comms();
|
|
||||||
|
|
||||||
(void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK);
|
|
||||||
old_mask = umask(0077);
|
|
||||||
|
|
||||||
listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (listen_fd < 0) {
|
|
||||||
DEBUGLOG("Can't create local socket: %s\n", strerror(errno));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
/* Set Close-on-exec */
|
|
||||||
if (fcntl(listen_fd, F_SETFD, 1)) {
|
|
||||||
DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
DEBUGLOG("Can't bind local socket: %s\n", strerror(errno));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (listen(listen_fd, 10) < 0) {
|
|
||||||
DEBUGLOG("Can't listen local socket: %s\n", strerror(errno));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
umask(old_mask);
|
|
||||||
(void) dm_prepare_selinux_context(NULL, 0);
|
|
||||||
return 0;
|
|
||||||
error:
|
|
||||||
umask(old_mask);
|
|
||||||
(void) dm_prepare_selinux_context(NULL, 0);
|
|
||||||
close_comms();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _init_cluster(void)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (!(_locks = dm_hash_create(128))) {
|
|
||||||
DEBUGLOG("Failed to allocate single-node hash table.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = init_comms();
|
|
||||||
if (r) {
|
|
||||||
dm_hash_destroy(_locks);
|
|
||||||
_locks = NULL;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGLOG("Single-node cluster initialised.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _cluster_closedown(void)
|
|
||||||
{
|
|
||||||
close_comms();
|
|
||||||
|
|
||||||
/* If there is any awaited resource, kill it softly */
|
|
||||||
pthread_mutex_lock(&_lock_mutex);
|
|
||||||
dm_hash_destroy(_locks);
|
|
||||||
_locks = NULL;
|
|
||||||
_lockid = 0;
|
|
||||||
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
|
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _get_our_csid(char *csid)
|
|
||||||
{
|
|
||||||
int nodeid = 1;
|
|
||||||
memcpy(csid, &nodeid, sizeof(int));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _csid_from_name(char *csid, const char *name)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _name_from_csid(const char *csid, char *name)
|
|
||||||
{
|
|
||||||
strcpy(name, "SINGLENODE");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _get_num_nodes(void)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Node is now known to be running a clvmd */
|
|
||||||
static void _add_up_node(const char *csid)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
|
||||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
|
||||||
void (*callback)(struct local_client *,
|
|
||||||
const char *csid, int node_up))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _lock_file(const char *file, uint32_t flags);
|
|
||||||
|
|
||||||
static const char *_get_mode(int mode)
|
|
||||||
{
|
|
||||||
switch (mode) {
|
|
||||||
case LCK_NULL: return "NULL";
|
|
||||||
case LCK_READ: return "READ";
|
|
||||||
case LCK_PREAD: return "PREAD";
|
|
||||||
case LCK_WRITE: return "WRITE";
|
|
||||||
case LCK_EXCL: return "EXCLUSIVE";
|
|
||||||
case LCK_UNLOCK: return "UNLOCK";
|
|
||||||
default: return "????";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Real locking */
|
|
||||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
|
||||||
{
|
|
||||||
/* DLM table of allowed transition states */
|
|
||||||
static const int _dlm_table[6][6] = {
|
|
||||||
/* Mode NL CR CW PR PW EX */
|
|
||||||
/* NL */ { 1, 1, 1, 1, 1, 1},
|
|
||||||
/* CR */ { 1, 1, 1, 1, 1, 0},
|
|
||||||
/* CW */ { 1, 1, 1, 0, 0, 0},
|
|
||||||
/* PR */ { 1, 1, 0, 1, 0, 0},
|
|
||||||
/* PW */ { 1, 1, 0, 0, 0, 0},
|
|
||||||
/* EX */ { 1, 0, 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lock *lck = NULL, *lckt;
|
|
||||||
struct dm_list *head;
|
|
||||||
|
|
||||||
DEBUGLOG("Locking resource %s, flags=0x%02x (%s%s%s), mode=%s (%d)\n",
|
|
||||||
resource, flags,
|
|
||||||
(flags & LCKF_NOQUEUE) ? "NOQUEUE" : "",
|
|
||||||
((flags & (LCKF_NOQUEUE | LCKF_CONVERT)) ==
|
|
||||||
(LCKF_NOQUEUE | LCKF_CONVERT)) ? "|" : "",
|
|
||||||
(flags & LCKF_CONVERT) ? "CONVERT" : "",
|
|
||||||
_get_mode(mode), mode);
|
|
||||||
|
|
||||||
mode &= LCK_TYPE_MASK;
|
|
||||||
pthread_mutex_lock(&_lock_mutex);
|
|
||||||
|
|
||||||
retry:
|
|
||||||
if (!(head = dm_hash_lookup(_locks, resource))) {
|
|
||||||
if (flags & LCKF_CONVERT) {
|
|
||||||
/* In real DLM, lock is identified only by lockid, resource is not used */
|
|
||||||
DEBUGLOG("Unlocked resource %s cannot be converted\n", resource);
|
|
||||||
goto_bad;
|
|
||||||
}
|
|
||||||
/* Add new locked resource */
|
|
||||||
if (!(head = dm_malloc(sizeof(struct dm_list))) ||
|
|
||||||
!dm_hash_insert(_locks, resource, head)) {
|
|
||||||
dm_free(head);
|
|
||||||
goto_bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
dm_list_init(head);
|
|
||||||
} else /* Update/convert locked resource */
|
|
||||||
dm_list_iterate_items(lck, head) {
|
|
||||||
/* Check is all locks are compatible with requested lock */
|
|
||||||
if (flags & LCKF_CONVERT) {
|
|
||||||
if (lck->lockid != *lockid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DEBUGLOG("Converting resource %s lockid=%d mode:%s -> %s...\n",
|
|
||||||
resource, lck->lockid, _get_mode(lck->mode), _get_mode(mode));
|
|
||||||
dm_list_iterate_items(lckt, head) {
|
|
||||||
if ((lckt->lockid != *lockid) &&
|
|
||||||
!_dlm_table[mode][lckt->mode]) {
|
|
||||||
if (!(flags & LCKF_NOQUEUE) &&
|
|
||||||
/* TODO: Real dlm uses here conversion queues */
|
|
||||||
!pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
|
|
||||||
_locks) /* End of the game? */
|
|
||||||
goto retry;
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lck->mode = mode; /* Lock is now converted */
|
|
||||||
goto out;
|
|
||||||
} else if (!_dlm_table[mode][lck->mode]) {
|
|
||||||
DEBUGLOG("Resource %s already locked lockid=%d, mode:%s\n",
|
|
||||||
resource, lck->lockid, _get_mode(lck->mode));
|
|
||||||
if (!(flags & LCKF_NOQUEUE) &&
|
|
||||||
!pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
|
|
||||||
_locks) { /* End of the game? */
|
|
||||||
DEBUGLOG("Resource %s retrying lock in mode:%s...\n",
|
|
||||||
resource, _get_mode(mode));
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(flags & LCKF_CONVERT)) {
|
|
||||||
if (!(lck = dm_malloc(sizeof(struct lock))))
|
|
||||||
goto_bad;
|
|
||||||
|
|
||||||
*lockid = lck->lockid = ++_lockid;
|
|
||||||
lck->mode = mode;
|
|
||||||
dm_list_add(head, &lck->list);
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
|
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
|
||||||
DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n",
|
|
||||||
resource, lck->lockid, _get_mode(lck->mode));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
bad:
|
|
||||||
pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
|
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
|
||||||
DEBUGLOG("Failed to lock resource %s\n", resource);
|
|
||||||
|
|
||||||
return 1; /* fail */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _unlock_resource(const char *resource, int lockid)
|
|
||||||
{
|
|
||||||
struct lock *lck;
|
|
||||||
struct dm_list *head;
|
|
||||||
int r = 1;
|
|
||||||
|
|
||||||
if (lockid < 0) {
|
|
||||||
DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
|
|
||||||
resource, lockid);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
|
|
||||||
pthread_mutex_lock(&_lock_mutex);
|
|
||||||
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
|
|
||||||
|
|
||||||
if (!(head = dm_hash_lookup(_locks, resource))) {
|
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
|
||||||
DEBUGLOG("Resource %s is not locked.\n", resource);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dm_list_iterate_items(lck, head)
|
|
||||||
if (lck->lockid == lockid) {
|
|
||||||
dm_list_del(&lck->list);
|
|
||||||
dm_free(lck);
|
|
||||||
r = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGLOG("Resource %s has wrong lockid %d.\n", resource, lockid);
|
|
||||||
out:
|
|
||||||
if (dm_list_empty(head)) {
|
|
||||||
//DEBUGLOG("Resource %s is no longer hashed (lockid=%d).\n", resource, lockid);
|
|
||||||
dm_hash_remove(_locks, resource);
|
|
||||||
dm_free(head);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _is_quorate(void)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _get_main_cluster_fd(void)
|
|
||||||
{
|
|
||||||
return listen_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
|
||||||
const char *csid,
|
|
||||||
struct local_client **new_client)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cluster_send_message(const void *buf, int msglen,
|
|
||||||
const char *csid,
|
|
||||||
const char *errtext)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _get_cluster_name(char *buf, int buflen)
|
|
||||||
{
|
|
||||||
return dm_strncpy(buf, "localcluster", buflen) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct cluster_ops _cluster_singlenode_ops = {
|
|
||||||
.name = "singlenode",
|
|
||||||
.cluster_init_completed = NULL,
|
|
||||||
.cluster_send_message = _cluster_send_message,
|
|
||||||
.name_from_csid = _name_from_csid,
|
|
||||||
.csid_from_name = _csid_from_name,
|
|
||||||
.get_num_nodes = _get_num_nodes,
|
|
||||||
.cluster_fd_callback = _cluster_fd_callback,
|
|
||||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
|
||||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
|
||||||
.is_quorate = _is_quorate,
|
|
||||||
.get_our_csid = _get_our_csid,
|
|
||||||
.add_up_node = _add_up_node,
|
|
||||||
.reread_config = NULL,
|
|
||||||
.cluster_closedown = _cluster_closedown,
|
|
||||||
.get_cluster_name = _get_cluster_name,
|
|
||||||
.sync_lock = _lock_resource,
|
|
||||||
.sync_unlock = _unlock_resource,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cluster_ops *init_singlenode_cluster(void)
|
|
||||||
{
|
|
||||||
if (!_init_cluster())
|
|
||||||
return &_cluster_singlenode_ops;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 */
|
|
||||||
int cleanup_needed; /* helper for cleanup_zombie */
|
|
||||||
struct local_client *pipe_client;
|
|
||||||
pthread_t threadid;
|
|
||||||
enum { PRE_COMMAND, POST_COMMAND } state;
|
|
||||||
pthread_mutex_t mutex; /* Main thread and worker synchronisation */
|
|
||||||
pthread_cond_t cond;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
@@ -1,927 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "clvmd-common.h"
|
|
||||||
|
|
||||||
#include <pthread.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%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_MODE ? "CONVERT|" : "",
|
|
||||||
flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "",
|
|
||||||
flags & LCK_REVERT_MODE ? "REVERT|" : "");
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
int num_open;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&lv_hash_lock);
|
|
||||||
dm_hash_remove(lv_hash, resource);
|
|
||||||
|
|
||||||
/* When last lock is remove, validate there are not left opened devices */
|
|
||||||
if (!dm_hash_get_first(lv_hash)) {
|
|
||||||
if (critical_section())
|
|
||||||
log_error(INTERNAL_ERROR "No volumes are locked however clvmd is in activation mode critical section.");
|
|
||||||
if ((num_open = dev_cache_check_for_open_devices()))
|
|
||||||
log_error(INTERNAL_ERROR "No volumes are locked however %d devices are still open.", num_open);
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
dm_free(lvi);
|
|
||||||
}
|
|
||||||
|
|
||||||
dm_hash_destroy(lv_hash);
|
|
||||||
lv_hash = NULL;
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&lv_hash_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Gets a real lock and keeps the info in the hash table */
|
|
||||||
static int hold_lock(char *resource, int mode, int flags)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
int saved_errno;
|
|
||||||
struct lv_info *lvi;
|
|
||||||
|
|
||||||
/* Mask off invalid options */
|
|
||||||
flags &= LCKF_NOQUEUE | LCKF_CONVERT;
|
|
||||||
|
|
||||||
lvi = lookup_info(resource);
|
|
||||||
|
|
||||||
if (lvi) {
|
|
||||||
if (lvi->lock_mode == mode) {
|
|
||||||
DEBUGLOG("hold_lock, lock mode %d already held\n",
|
|
||||||
mode);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
|
|
||||||
DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
|
|
||||||
"ignoring LCK_WRITE request\n");
|
|
||||||
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;
|
|
||||||
else
|
|
||||||
DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
|
|
||||||
strerror(errno));
|
|
||||||
errno = saved_errno;
|
|
||||||
} else {
|
|
||||||
if (!(lvi = dm_malloc(sizeof(struct lv_info)))) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lvi->lock_mode = mode;
|
|
||||||
lvi->lock_id = 0;
|
|
||||||
status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
|
|
||||||
saved_errno = errno;
|
|
||||||
if (status) {
|
|
||||||
dm_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 (!(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);
|
|
||||||
dm_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, NULL))
|
|
||||||
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 (!test_mode() && command & LCK_CLUSTER_VG) {
|
|
||||||
status = hold_lock(resource, mode, LCKF_NOQUEUE | ((lock_flags & LCK_CONVERT_MODE) ? 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, NULL)) {
|
|
||||||
critical_section_dec(cmd, "resumed");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now activate it */
|
|
||||||
if (!lv_activate(cmd, resource, exclusive, 0, 0, NULL))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (!test_mode() && (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, NULL))
|
|
||||||
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, NULL, NULL))
|
|
||||||
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, NULL))
|
|
||||||
return EIO;
|
|
||||||
|
|
||||||
if (!test_mode() && 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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
default: type = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
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->initialized.config || 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);
|
|
||||||
init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
|
|
||||||
|
|
||||||
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);
|
|
||||||
init_test(0);
|
|
||||||
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 (!(lock_flags & LCK_TEST_MODE) &&
|
|
||||||
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 (!(lock_flags & LCK_TEST_MODE)) {
|
|
||||||
if (lvi.exists) {
|
|
||||||
if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
|
|
||||||
return errno;
|
|
||||||
} else if (hold_unlock(resource))
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_ignore_suspended_devices(1);
|
|
||||||
lvmcache_label_scan(cmd);
|
|
||||||
label_scan_destroy(cmd); /* destroys bcache (to close devs), keeps lvmcache */
|
|
||||||
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);
|
|
||||||
init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
init_test(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[65], vg[65], flags[26], vg_flags[26]; /* with space for '\0' */
|
|
||||||
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;
|
|
||||||
|
|
||||||
(void) dm_strncpy(last_error, message, sizeof(last_error));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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, NULL);
|
|
||||||
|
|
||||||
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, NULL);
|
|
||||||
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*/, 0, 0, WARN_PV_READ, &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 (!udev_init_library_context())
|
|
||||||
stack;
|
|
||||||
|
|
||||||
if (!(cmd = create_toolcontext(1, NULL, 0, 1, 1, 1))) {
|
|
||||||
log_error("Failed to allocate command context");
|
|
||||||
udev_fin_library_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);
|
|
||||||
udev_fin_library_context();
|
|
||||||
cmd = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
|
||||||
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* This file is part of LVM2.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU General Public License v.2.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 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_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
|
|
||||||
@@ -1,382 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
|
||||||
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
|
||||||
*
|
|
||||||
* This file is part of LVM2.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU General Public License v.2.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* FIXME Remove duplicated functions from this file. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send a command to a running clvmd from the command-line
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "clvmd-common.h"
|
|
||||||
|
|
||||||
#include "clvm.h"
|
|
||||||
#include "refresh_clvmd.h"
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
|
|
||||||
typedef struct lvm_response {
|
|
||||||
char node[255];
|
|
||||||
char *response;
|
|
||||||
int status;
|
|
||||||
int len;
|
|
||||||
} lvm_response_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This gets stuck at the start of memory we allocate so we
|
|
||||||
* can sanity-check it at deallocation time
|
|
||||||
*/
|
|
||||||
#define LVM_SIGNATURE 0x434C564D
|
|
||||||
|
|
||||||
static int _clvmd_sock = -1;
|
|
||||||
|
|
||||||
/* Open connection to the clvm daemon */
|
|
||||||
static int _open_local_sock(void)
|
|
||||||
{
|
|
||||||
int local_socket;
|
|
||||||
struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
|
|
||||||
|
|
||||||
if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
|
|
||||||
fprintf(stderr, "%s: clvmd socket name too long.", CLVMD_SOCKNAME);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open local socket */
|
|
||||||
if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
||||||
fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connect(local_socket,(struct sockaddr *) &sockaddr,
|
|
||||||
sizeof(sockaddr))) {
|
|
||||||
int saved_errno = errno;
|
|
||||||
|
|
||||||
fprintf(stderr, "connect() failed on local socket: %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
if (close(local_socket))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
errno = saved_errno;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return local_socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a request and return the status */
|
|
||||||
static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response)
|
|
||||||
{
|
|
||||||
char outbuf[PIPE_BUF];
|
|
||||||
struct clvm_header *outheader = (struct clvm_header *) outbuf;
|
|
||||||
int len;
|
|
||||||
unsigned off;
|
|
||||||
int buflen;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* Send it to CLVMD */
|
|
||||||
rewrite:
|
|
||||||
if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
|
|
||||||
if (err == -1 && errno == EINTR)
|
|
||||||
goto rewrite;
|
|
||||||
fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (no_response)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Get the response */
|
|
||||||
reread:
|
|
||||||
if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto reread;
|
|
||||||
fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == 0) {
|
|
||||||
fprintf(stderr, "EOF reading CLVMD");
|
|
||||||
errno = ENOTCONN;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate buffer */
|
|
||||||
buflen = len + outheader->arglen;
|
|
||||||
*retbuf = dm_malloc(buflen);
|
|
||||||
if (!*retbuf) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the header */
|
|
||||||
memcpy(*retbuf, outbuf, len);
|
|
||||||
outheader = (struct clvm_header *) *retbuf;
|
|
||||||
|
|
||||||
/* Read the returned values */
|
|
||||||
off = 1; /* we've already read the first byte */
|
|
||||||
while (off <= outheader->arglen && len > 0) {
|
|
||||||
len = read(_clvmd_sock, outheader->args + off,
|
|
||||||
buflen - off - offsetof(struct clvm_header, args));
|
|
||||||
if (len > 0)
|
|
||||||
off += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Was it an error ? */
|
|
||||||
if (outheader->status != 0) {
|
|
||||||
errno = outheader->status;
|
|
||||||
|
|
||||||
/* Only return an error here if there are no node-specific
|
|
||||||
errors present in the message that might have more detail */
|
|
||||||
if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
|
|
||||||
fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build the structure header and parse-out wildcard node names */
|
|
||||||
static void _build_header(struct clvm_header *head, int cmd, const char *node,
|
|
||||||
unsigned int len)
|
|
||||||
{
|
|
||||||
head->cmd = cmd;
|
|
||||||
head->status = 0;
|
|
||||||
head->flags = 0;
|
|
||||||
head->xid = 0;
|
|
||||||
head->clientid = 0;
|
|
||||||
if (len)
|
|
||||||
/* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */
|
|
||||||
head->arglen = len - 1;
|
|
||||||
else {
|
|
||||||
head->arglen = 0;
|
|
||||||
*head->args = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Translate special node names.
|
|
||||||
*/
|
|
||||||
if (!node || !strcmp(node, NODE_ALL))
|
|
||||||
head->node[0] = '\0';
|
|
||||||
else if (!strcmp(node, NODE_LOCAL)) {
|
|
||||||
head->node[0] = '\0';
|
|
||||||
head->flags = CLVMD_FLAG_LOCAL;
|
|
||||||
} else
|
|
||||||
strcpy(head->node, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send a message to a(or all) node(s) in the cluster and wait for replies
|
|
||||||
*/
|
|
||||||
static int _cluster_request(char cmd, const char *node, void *data, int len,
|
|
||||||
lvm_response_t ** response, int *num, int no_response)
|
|
||||||
{
|
|
||||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
|
||||||
char *inptr;
|
|
||||||
char *retbuf = NULL;
|
|
||||||
int status;
|
|
||||||
int i;
|
|
||||||
int num_responses = 0;
|
|
||||||
struct clvm_header *head = (struct clvm_header *) outbuf;
|
|
||||||
lvm_response_t *rarray;
|
|
||||||
|
|
||||||
*num = 0;
|
|
||||||
|
|
||||||
if (_clvmd_sock == -1)
|
|
||||||
_clvmd_sock = _open_local_sock();
|
|
||||||
|
|
||||||
if (_clvmd_sock == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
_build_header(head, cmd, node, len);
|
|
||||||
if (len)
|
|
||||||
memcpy(head->node + strlen(head->node) + 1, data, len);
|
|
||||||
|
|
||||||
status = _send_request(outbuf, sizeof(struct clvm_header) +
|
|
||||||
strlen(head->node) + len, &retbuf, no_response);
|
|
||||||
if (!status || no_response)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Count the number of responses we got */
|
|
||||||
head = (struct clvm_header *) retbuf;
|
|
||||||
inptr = head->args;
|
|
||||||
while (inptr[0]) {
|
|
||||||
num_responses++;
|
|
||||||
inptr += strlen(inptr) + 1;
|
|
||||||
inptr += sizeof(int);
|
|
||||||
inptr += strlen(inptr) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate response array.
|
|
||||||
* With an extra pair of INTs on the front to sanity
|
|
||||||
* check the pointer when we are given it back to free
|
|
||||||
*/
|
|
||||||
*response = NULL;
|
|
||||||
if (!(rarray = dm_malloc(sizeof(lvm_response_t) * num_responses +
|
|
||||||
sizeof(int) * 2))) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
status = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unpack the response into an lvm_response_t array */
|
|
||||||
inptr = head->args;
|
|
||||||
i = 0;
|
|
||||||
while (inptr[0]) {
|
|
||||||
strcpy(rarray[i].node, inptr);
|
|
||||||
inptr += strlen(inptr) + 1;
|
|
||||||
|
|
||||||
memcpy(&rarray[i].status, inptr, sizeof(int));
|
|
||||||
inptr += sizeof(int);
|
|
||||||
|
|
||||||
rarray[i].response = dm_malloc(strlen(inptr) + 1);
|
|
||||||
if (rarray[i].response == NULL) {
|
|
||||||
/* Free up everything else and return error */
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < i; j++)
|
|
||||||
dm_free(rarray[i].response);
|
|
||||||
dm_free(rarray);
|
|
||||||
errno = ENOMEM;
|
|
||||||
status = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(rarray[i].response, inptr);
|
|
||||||
rarray[i].len = strlen(inptr);
|
|
||||||
inptr += strlen(inptr) + 1;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
*num = num_responses;
|
|
||||||
*response = rarray;
|
|
||||||
|
|
||||||
out:
|
|
||||||
dm_free(retbuf);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free reply array */
|
|
||||||
static int _cluster_free_request(lvm_response_t * response, int num)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
|
||||||
dm_free(response[i].response);
|
|
||||||
}
|
|
||||||
|
|
||||||
dm_free(response);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int refresh_clvmd(int all_nodes)
|
|
||||||
{
|
|
||||||
int num_responses;
|
|
||||||
char args[1]; // No args really.
|
|
||||||
lvm_response_t *response = NULL;
|
|
||||||
int saved_errno;
|
|
||||||
int status;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes ? NODE_ALL : NODE_LOCAL, args, 0, &response, &num_responses, 0);
|
|
||||||
|
|
||||||
/* If any nodes were down then display them and return an error */
|
|
||||||
for (i = 0; i < num_responses; i++) {
|
|
||||||
if (response[i].status == EHOSTDOWN) {
|
|
||||||
fprintf(stderr, "clvmd not running on node %s",
|
|
||||||
response[i].node);
|
|
||||||
status = 0;
|
|
||||||
errno = response[i].status;
|
|
||||||
} else if (response[i].status) {
|
|
||||||
fprintf(stderr, "Error resetting node %s: %s",
|
|
||||||
response[i].node,
|
|
||||||
response[i].response[0] ?
|
|
||||||
response[i].response :
|
|
||||||
strerror(response[i].status));
|
|
||||||
status = 0;
|
|
||||||
errno = response[i].status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
saved_errno = errno;
|
|
||||||
_cluster_free_request(response, num_responses);
|
|
||||||
errno = saved_errno;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int restart_clvmd(int all_nodes)
|
|
||||||
{
|
|
||||||
int dummy, status;
|
|
||||||
|
|
||||||
status = _cluster_request(CLVMD_CMD_RESTART, all_nodes ? NODE_ALL : NODE_LOCAL, NULL, 0, NULL, &dummy, 1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: we cannot receive response, clvmd re-exec before it.
|
|
||||||
* but also should not close socket too early (the whole rq is dropped then).
|
|
||||||
* FIXME: This should be handled this way:
|
|
||||||
* - client waits for RESTART ack (and socket close)
|
|
||||||
* - server restarts
|
|
||||||
* - client checks that server is ready again (VERSION command?)
|
|
||||||
*/
|
|
||||||
usleep(500000);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int debug_clvmd(int level, int clusterwide)
|
|
||||||
{
|
|
||||||
int num_responses;
|
|
||||||
char args[1];
|
|
||||||
const char *nodes;
|
|
||||||
lvm_response_t *response = NULL;
|
|
||||||
int saved_errno;
|
|
||||||
int status;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
args[0] = level;
|
|
||||||
if (clusterwide)
|
|
||||||
nodes = NODE_ALL;
|
|
||||||
else
|
|
||||||
nodes = NODE_LOCAL;
|
|
||||||
|
|
||||||
status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0);
|
|
||||||
|
|
||||||
/* If any nodes were down then display them and return an error */
|
|
||||||
for (i = 0; i < num_responses; i++) {
|
|
||||||
if (response[i].status == EHOSTDOWN) {
|
|
||||||
fprintf(stderr, "clvmd not running on node %s",
|
|
||||||
response[i].node);
|
|
||||||
status = 0;
|
|
||||||
errno = response[i].status;
|
|
||||||
} else if (response[i].status) {
|
|
||||||
fprintf(stderr, "Error setting debug on node %s: %s",
|
|
||||||
response[i].node,
|
|
||||||
response[i].response[0] ?
|
|
||||||
response[i].response :
|
|
||||||
strerror(response[i].status));
|
|
||||||
status = 0;
|
|
||||||
errno = response[i].status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
saved_errno = errno;
|
|
||||||
_cluster_free_request(response, num_responses);
|
|
||||||
errno = saved_errno;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
int refresh_clvmd(int all_nodes);
|
|
||||||
int restart_clvmd(int all_nodes);
|
|
||||||
int debug_clvmd(int level, int clusterwide);
|
|
||||||
|
|
||||||
@@ -17,8 +17,6 @@ top_builddir = @top_builddir@
|
|||||||
|
|
||||||
CPG_LIBS = @CPG_LIBS@
|
CPG_LIBS = @CPG_LIBS@
|
||||||
CPG_CFLAGS = @CPG_CFLAGS@
|
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
|
SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
|
||||||
|
|
||||||
@@ -26,14 +24,15 @@ TARGETS = cmirrord
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += -ldevmapper
|
LMLIBS += $(CPG_LIBS)
|
||||||
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
|
CFLAGS += $(CPG_CFLAGS) $(EXTRA_EXEC_CFLAGS)
|
||||||
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS) $(EXTRA_EXEC_CFLAGS)
|
|
||||||
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||||
|
|
||||||
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
cmirrord: $(OBJECTS)
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
@echo " [CC] $@"
|
||||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
||||||
|
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
|
||||||
|
|
||||||
install: $(TARGETS)
|
install: $(TARGETS)
|
||||||
$(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
|
||||||
|
|||||||
@@ -16,7 +16,11 @@
|
|||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
#include "link_mon.h"
|
#include "link_mon.h"
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
#include "xlate.h"
|
#include "lib/mm/xlate.h"
|
||||||
|
#include "base/memory/zalloc.h"
|
||||||
|
|
||||||
|
/* FIXME: remove this and the code */
|
||||||
|
#define CMIRROR_HAS_CHECKPOINT 0
|
||||||
|
|
||||||
#include <corosync/cpg.h>
|
#include <corosync/cpg.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -399,13 +403,12 @@ static struct checkpoint_data *prepare_checkpoint(struct clog_cpg *entry,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = malloc(sizeof(*new));
|
new = zalloc(sizeof(*new));
|
||||||
if (!new) {
|
if (!new) {
|
||||||
LOG_ERROR("Unable to create checkpoint data for %u",
|
LOG_ERROR("Unable to create checkpoint data for %u",
|
||||||
cp_requester);
|
cp_requester);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(new, 0, sizeof(*new));
|
|
||||||
new->requester = cp_requester;
|
new->requester = cp_requester;
|
||||||
strncpy(new->uuid, entry->name.value, entry->name.length);
|
strncpy(new->uuid, entry->name.value, entry->name.length);
|
||||||
|
|
||||||
@@ -640,13 +643,12 @@ static int export_checkpoint(struct checkpoint_data *cp)
|
|||||||
rq_size += RECOVERING_REGION_SECTION_SIZE;
|
rq_size += RECOVERING_REGION_SECTION_SIZE;
|
||||||
rq_size += cp->bitmap_size * 2; /* clean|sync_bits */
|
rq_size += cp->bitmap_size * 2; /* clean|sync_bits */
|
||||||
|
|
||||||
rq = malloc(rq_size);
|
rq = zalloc(rq_size);
|
||||||
if (!rq) {
|
if (!rq) {
|
||||||
LOG_ERROR("export_checkpoint: "
|
LOG_ERROR("export_checkpoint: "
|
||||||
"Unable to allocate transfer structs");
|
"Unable to allocate transfer structs");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
memset(rq, 0, rq_size);
|
|
||||||
|
|
||||||
dm_list_init(&rq->u.list);
|
dm_list_init(&rq->u.list);
|
||||||
rq->u_rq.request_type = DM_ULOG_CHECKPOINT_READY;
|
rq->u_rq.request_type = DM_ULOG_CHECKPOINT_READY;
|
||||||
@@ -1618,12 +1620,11 @@ int create_cluster_cpg(char *uuid, uint64_t luid)
|
|||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = malloc(sizeof(*new));
|
new = zalloc(sizeof(*new));
|
||||||
if (!new) {
|
if (!new) {
|
||||||
LOG_ERROR("Unable to allocate memory for clog_cpg");
|
LOG_ERROR("Unable to allocate memory for clog_cpg");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
memset(new, 0, sizeof(*new));
|
|
||||||
dm_list_init(&new->list);
|
dm_list_init(&new->list);
|
||||||
new->lowest_id = 0xDEAD;
|
new->lowest_id = 0xDEAD;
|
||||||
dm_list_init(&new->startup_list);
|
dm_list_init(&new->startup_list);
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
#ifndef _LVM_CLOG_CLUSTER_H
|
#ifndef _LVM_CLOG_CLUSTER_H
|
||||||
#define _LVM_CLOG_CLUSTER_H
|
#define _LVM_CLOG_CLUSTER_H
|
||||||
|
|
||||||
#include "dm-log-userspace.h"
|
#include "libdm/libdevmapper.h"
|
||||||
#include "libdevmapper.h"
|
#include "libdm/misc/dm-log-userspace.h"
|
||||||
|
|
||||||
#define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */
|
#define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */
|
||||||
#define DM_ULOG_CHECKPOINT_READY 21
|
#define DM_ULOG_CHECKPOINT_READY 21
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "cluster.h"
|
#include "cluster.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "xlate.h"
|
#include "lib/mm/xlate.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
|
#include "base/memory/zalloc.h"
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
@@ -435,7 +436,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
|
|||||||
block_on_error = 1;
|
block_on_error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lc = dm_zalloc(sizeof(*lc));
|
lc = zalloc(sizeof(*lc));
|
||||||
if (!lc) {
|
if (!lc) {
|
||||||
LOG_ERROR("Unable to allocate cluster log context");
|
LOG_ERROR("Unable to allocate cluster log context");
|
||||||
r = -ENOMEM;
|
r = -ENOMEM;
|
||||||
@@ -532,9 +533,9 @@ fail:
|
|||||||
LOG_ERROR("Close device error, %s: %s",
|
LOG_ERROR("Close device error, %s: %s",
|
||||||
disk_path, strerror(errno));
|
disk_path, strerror(errno));
|
||||||
free(lc->disk_buffer);
|
free(lc->disk_buffer);
|
||||||
dm_free(lc->sync_bits);
|
free(lc->sync_bits);
|
||||||
dm_free(lc->clean_bits);
|
free(lc->clean_bits);
|
||||||
dm_free(lc);
|
free(lc);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -659,9 +660,9 @@ static int clog_dtr(struct dm_ulog_request *rq)
|
|||||||
strerror(errno));
|
strerror(errno));
|
||||||
if (lc->disk_buffer)
|
if (lc->disk_buffer)
|
||||||
free(lc->disk_buffer);
|
free(lc->disk_buffer);
|
||||||
dm_free(lc->clean_bits);
|
free(lc->clean_bits);
|
||||||
dm_free(lc->sync_bits);
|
free(lc->sync_bits);
|
||||||
dm_free(lc);
|
free(lc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
#ifndef _LVM_CLOG_FUNCTIONS_H
|
#ifndef _LVM_CLOG_FUNCTIONS_H
|
||||||
#define _LVM_CLOG_FUNCTIONS_H
|
#define _LVM_CLOG_FUNCTIONS_H
|
||||||
|
|
||||||
#include "dm-log-userspace.h"
|
#include "libdm/libdevmapper.h"
|
||||||
|
#include "libdm/misc/dm-log-userspace.h"
|
||||||
#include "cluster.h"
|
#include "cluster.h"
|
||||||
|
|
||||||
#define LOG_RESUMED 1
|
#define LOG_RESUMED 1
|
||||||
|
|||||||
@@ -13,9 +13,6 @@
|
|||||||
#ifndef _LVM_CLOG_LOGGING_H
|
#ifndef _LVM_CLOG_LOGGING_H
|
||||||
#define _LVM_CLOG_LOGGING_H
|
#define _LVM_CLOG_LOGGING_H
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
#include "configure.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|||||||
@@ -57,14 +57,16 @@ all: device-mapper
|
|||||||
device-mapper: $(TARGETS)
|
device-mapper: $(TARGETS)
|
||||||
|
|
||||||
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
|
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
|
||||||
LIBS += -ldevmapper $(PTHREAD_LIBS)
|
LIBS += $(PTHREAD_LIBS) -L$(top_builddir)/libdm -ldevmapper
|
||||||
|
|
||||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||||
$(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
|
@echo " [CC] $@"
|
||||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS)
|
$(Q) $(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
|
||||||
|
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) -lm
|
||||||
|
|
||||||
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
|
dmeventd.static: $(LIB_STATIC) dmeventd.o
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
|
@echo " [CC] $@"
|
||||||
|
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
|
||||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
|
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
|
||||||
|
|
||||||
ifeq ("@PKGCONFIG@", "yes")
|
ifeq ("@PKGCONFIG@", "yes")
|
||||||
@@ -73,7 +75,6 @@ endif
|
|||||||
|
|
||||||
ifneq ("$(CFLOW_CMD)", "")
|
ifneq ("$(CFLOW_CMD)", "")
|
||||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||||
-include $(top_builddir)/libdm/libdevmapper.cflow
|
|
||||||
-include $(top_builddir)/lib/liblvm-internal.cflow
|
-include $(top_builddir)/lib/liblvm-internal.cflow
|
||||||
-include $(top_builddir)/lib/liblvm2cmd.cflow
|
-include $(top_builddir)/lib/liblvm2cmd.cflow
|
||||||
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
|
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
|
||||||
@@ -81,23 +82,28 @@ CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
install_include: $(srcdir)/libdevmapper-event.h
|
install_include: $(srcdir)/libdevmapper-event.h
|
||||||
$(INSTALL_DATA) -D $< $(includedir)/$(<F)
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
|
||||||
|
|
||||||
install_pkgconfig: libdevmapper-event.pc
|
install_pkgconfig: libdevmapper-event.pc
|
||||||
$(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
|
||||||
|
|
||||||
install_lib_dynamic: install_lib_shared
|
install_lib_dynamic: install_lib_shared
|
||||||
|
|
||||||
install_lib_static: $(LIB_STATIC)
|
install_lib_static: $(LIB_STATIC)
|
||||||
$(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
|
||||||
|
|
||||||
install_lib: $(INSTALL_LIB_TARGETS)
|
install_lib: $(INSTALL_LIB_TARGETS)
|
||||||
|
|
||||||
install_dmeventd_dynamic: dmeventd
|
install_dmeventd_dynamic: dmeventd
|
||||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||||
|
|
||||||
install_dmeventd_static: dmeventd.static
|
install_dmeventd_static: dmeventd.static
|
||||||
$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
|
||||||
|
|
||||||
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
|
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,12 @@
|
|||||||
* dmeventd - dm event daemon to monitor active mapped devices
|
* dmeventd - dm event daemon to monitor active mapped devices
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dm-logging.h"
|
|
||||||
|
|
||||||
#include "libdevmapper-event.h"
|
#include "libdevmapper-event.h"
|
||||||
#include "dmeventd.h"
|
#include "dmeventd.h"
|
||||||
|
|
||||||
#include "tool.h"
|
#include "libdm/misc/dm-logging.h"
|
||||||
|
#include "base/memory/zalloc.h"
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <arpa/inet.h> /* for htonl, ntohl */
|
#include <arpa/inet.h> /* for htonl, ntohl */
|
||||||
#include <fcntl.h> /* for musl libc */
|
#include <fcntl.h> /* for musl libc */
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
/*
|
/*
|
||||||
@@ -60,8 +62,6 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#define DM_SIGNALED_EXIT 1
|
#define DM_SIGNALED_EXIT 1
|
||||||
#define DM_SCHEDULED_EXIT 2
|
#define DM_SCHEDULED_EXIT 2
|
||||||
static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */
|
static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */
|
||||||
@@ -264,19 +264,19 @@ static pthread_cond_t _timeout_cond = PTHREAD_COND_INITIALIZER;
|
|||||||
/* DSO data allocate/free. */
|
/* DSO data allocate/free. */
|
||||||
static void _free_dso_data(struct dso_data *data)
|
static void _free_dso_data(struct dso_data *data)
|
||||||
{
|
{
|
||||||
dm_free(data->dso_name);
|
free(data->dso_name);
|
||||||
dm_free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dso_data *_alloc_dso_data(struct message_data *data)
|
static struct dso_data *_alloc_dso_data(struct message_data *data)
|
||||||
{
|
{
|
||||||
struct dso_data *ret = (typeof(ret)) dm_zalloc(sizeof(*ret));
|
struct dso_data *ret = (typeof(ret)) zalloc(sizeof(*ret));
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
if (!(ret->dso_name = dm_strdup(data->dso_name))) {
|
if (!(ret->dso_name = strdup(data->dso_name))) {
|
||||||
dm_free(ret);
|
free(ret);
|
||||||
return_NULL;
|
return_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,9 +397,9 @@ static void _free_thread_status(struct thread_status *thread)
|
|||||||
_lib_put(thread->dso_data);
|
_lib_put(thread->dso_data);
|
||||||
if (thread->wait_task)
|
if (thread->wait_task)
|
||||||
dm_task_destroy(thread->wait_task);
|
dm_task_destroy(thread->wait_task);
|
||||||
dm_free(thread->device.uuid);
|
free(thread->device.uuid);
|
||||||
dm_free(thread->device.name);
|
free(thread->device.name);
|
||||||
dm_free(thread);
|
free(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: events_field must not be 0, ensured by caller */
|
/* Note: events_field must not be 0, ensured by caller */
|
||||||
@@ -408,7 +408,7 @@ static struct thread_status *_alloc_thread_status(const struct message_data *dat
|
|||||||
{
|
{
|
||||||
struct thread_status *thread;
|
struct thread_status *thread;
|
||||||
|
|
||||||
if (!(thread = dm_zalloc(sizeof(*thread)))) {
|
if (!(thread = zalloc(sizeof(*thread)))) {
|
||||||
log_error("Cannot create new thread, out of memory.");
|
log_error("Cannot create new thread, out of memory.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -422,11 +422,11 @@ static struct thread_status *_alloc_thread_status(const struct message_data *dat
|
|||||||
if (!dm_task_set_uuid(thread->wait_task, data->device_uuid))
|
if (!dm_task_set_uuid(thread->wait_task, data->device_uuid))
|
||||||
goto_out;
|
goto_out;
|
||||||
|
|
||||||
if (!(thread->device.uuid = dm_strdup(data->device_uuid)))
|
if (!(thread->device.uuid = strdup(data->device_uuid)))
|
||||||
goto_out;
|
goto_out;
|
||||||
|
|
||||||
/* Until real name resolved, use UUID */
|
/* Until real name resolved, use UUID */
|
||||||
if (!(thread->device.name = dm_strdup(data->device_uuid)))
|
if (!(thread->device.name = strdup(data->device_uuid)))
|
||||||
goto_out;
|
goto_out;
|
||||||
|
|
||||||
/* runs ioctl and may register lvm2 pluging */
|
/* runs ioctl and may register lvm2 pluging */
|
||||||
@@ -515,7 +515,7 @@ static int _fetch_string(char **ptr, char **src, const int delimiter)
|
|||||||
if ((p = strchr(*src, delimiter))) {
|
if ((p = strchr(*src, delimiter))) {
|
||||||
if (*src < p) {
|
if (*src < p) {
|
||||||
*p = 0; /* Temporary exit with \0 */
|
*p = 0; /* Temporary exit with \0 */
|
||||||
if (!(*ptr = dm_strdup(*src))) {
|
if (!(*ptr = strdup(*src))) {
|
||||||
log_error("Failed to fetch item %s.", *src);
|
log_error("Failed to fetch item %s.", *src);
|
||||||
ret = 0; /* Allocation fail */
|
ret = 0; /* Allocation fail */
|
||||||
}
|
}
|
||||||
@@ -525,7 +525,7 @@ static int _fetch_string(char **ptr, char **src, const int delimiter)
|
|||||||
(*src)++; /* Skip delmiter, next field */
|
(*src)++; /* Skip delmiter, next field */
|
||||||
} else if ((len = strlen(*src))) {
|
} else if ((len = strlen(*src))) {
|
||||||
/* No delimiter, item ends with '\0' */
|
/* No delimiter, item ends with '\0' */
|
||||||
if (!(*ptr = dm_strdup(*src))) {
|
if (!(*ptr = strdup(*src))) {
|
||||||
log_error("Failed to fetch last item %s.", *src);
|
log_error("Failed to fetch last item %s.", *src);
|
||||||
ret = 0; /* Fail */
|
ret = 0; /* Fail */
|
||||||
}
|
}
|
||||||
@@ -538,11 +538,11 @@ out:
|
|||||||
/* Free message memory. */
|
/* Free message memory. */
|
||||||
static void _free_message(struct message_data *message_data)
|
static void _free_message(struct message_data *message_data)
|
||||||
{
|
{
|
||||||
dm_free(message_data->id);
|
free(message_data->id);
|
||||||
dm_free(message_data->dso_name);
|
free(message_data->dso_name);
|
||||||
dm_free(message_data->device_uuid);
|
free(message_data->device_uuid);
|
||||||
dm_free(message_data->events_str);
|
free(message_data->events_str);
|
||||||
dm_free(message_data->timeout_str);
|
free(message_data->timeout_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a register message from the client. */
|
/* Parse a register message from the client. */
|
||||||
@@ -574,7 +574,7 @@ static int _parse_message(struct message_data *message_data)
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_free(msg->data);
|
free(msg->data);
|
||||||
msg->data = NULL;
|
msg->data = NULL;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -608,8 +608,8 @@ static int _fill_device_data(struct thread_status *ts)
|
|||||||
if (!dm_task_run(dmt))
|
if (!dm_task_run(dmt))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
dm_free(ts->device.name);
|
free(ts->device.name);
|
||||||
if (!(ts->device.name = dm_strdup(dm_task_get_name(dmt))))
|
if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (!dm_task_get_info(dmt, &dmi))
|
if (!dm_task_get_info(dmt, &dmi))
|
||||||
@@ -696,8 +696,8 @@ static int _get_status(struct message_data *message_data)
|
|||||||
|
|
||||||
len = strlen(message_data->id);
|
len = strlen(message_data->id);
|
||||||
msg->size = size + len + 1;
|
msg->size = size + len + 1;
|
||||||
dm_free(msg->data);
|
free(msg->data);
|
||||||
if (!(msg->data = dm_malloc(msg->size)))
|
if (!(msg->data = malloc(msg->size)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
memcpy(msg->data, message_data->id, len);
|
memcpy(msg->data, message_data->id, len);
|
||||||
@@ -712,7 +712,7 @@ static int _get_status(struct message_data *message_data)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
for (j = 0; j < i; ++j)
|
for (j = 0; j < i; ++j)
|
||||||
dm_free(buffers[j]);
|
free(buffers[j]);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -721,7 +721,7 @@ static int _get_parameters(struct message_data *message_data) {
|
|||||||
struct dm_event_daemon_message *msg = message_data->msg;
|
struct dm_event_daemon_message *msg = message_data->msg;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
dm_free(msg->data);
|
free(msg->data);
|
||||||
if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s",
|
if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s",
|
||||||
message_data->id, getpid(),
|
message_data->id, getpid(),
|
||||||
_foreground ? "no" : "yes",
|
_foreground ? "no" : "yes",
|
||||||
@@ -752,7 +752,7 @@ static void _exit_timeout(void *unused __attribute__((unused)))
|
|||||||
static void *_timeout_thread(void *unused __attribute__((unused)))
|
static void *_timeout_thread(void *unused __attribute__((unused)))
|
||||||
{
|
{
|
||||||
struct thread_status *thread;
|
struct thread_status *thread;
|
||||||
struct timespec timeout;
|
struct timespec timeout, real_time;
|
||||||
time_t curr_time;
|
time_t curr_time;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -763,7 +763,16 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
|
|||||||
while (!dm_list_empty(&_timeout_registry)) {
|
while (!dm_list_empty(&_timeout_registry)) {
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
timeout.tv_nsec = 0;
|
timeout.tv_nsec = 0;
|
||||||
|
#ifndef HAVE_REALTIME
|
||||||
curr_time = time(NULL);
|
curr_time = time(NULL);
|
||||||
|
#else
|
||||||
|
if (clock_gettime(CLOCK_REALTIME, &real_time)) {
|
||||||
|
log_error("Failed to read clock_gettime().");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* 10ms back to the future */
|
||||||
|
curr_time = real_time.tv_sec + ((real_time.tv_nsec > (1000000000 - 10000000)) ? 1 : 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
|
dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
|
||||||
if (thread->next_time <= curr_time) {
|
if (thread->next_time <= curr_time) {
|
||||||
@@ -1225,7 +1234,7 @@ static int _registered_device(struct message_data *message_data,
|
|||||||
int r;
|
int r;
|
||||||
struct dm_event_daemon_message *msg = message_data->msg;
|
struct dm_event_daemon_message *msg = message_data->msg;
|
||||||
|
|
||||||
dm_free(msg->data);
|
free(msg->data);
|
||||||
|
|
||||||
if ((r = dm_asprintf(&(msg->data), "%s %s %s %u",
|
if ((r = dm_asprintf(&(msg->data), "%s %s %s %u",
|
||||||
message_data->id,
|
message_data->id,
|
||||||
@@ -1365,7 +1374,7 @@ static int _get_timeout(struct message_data *message_data)
|
|||||||
if (!thread)
|
if (!thread)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
dm_free(msg->data);
|
free(msg->data);
|
||||||
msg->size = dm_asprintf(&(msg->data), "%s %" PRIu32,
|
msg->size = dm_asprintf(&(msg->data), "%s %" PRIu32,
|
||||||
message_data->id, thread->timeout);
|
message_data->id, thread->timeout);
|
||||||
|
|
||||||
@@ -1485,37 +1494,34 @@ static int _client_read(struct dm_event_fifos *fifos,
|
|||||||
t.tv_usec = 0;
|
t.tv_usec = 0;
|
||||||
ret = select(fifos->client + 1, &fds, NULL, NULL, &t);
|
ret = select(fifos->client + 1, &fds, NULL, NULL, &t);
|
||||||
|
|
||||||
if (!ret && !bytes) /* nothing to read */
|
if (!ret && bytes)
|
||||||
return 0;
|
continue; /* trying to finish read */
|
||||||
|
|
||||||
if (!ret) /* trying to finish read */
|
if (ret <= 0) /* nothing to read */
|
||||||
continue;
|
goto bad;
|
||||||
|
|
||||||
if (ret < 0) /* error */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = read(fifos->client, buf + bytes, size - bytes);
|
ret = read(fifos->client, buf + bytes, size - bytes);
|
||||||
bytes += ret > 0 ? ret : 0;
|
bytes += ret > 0 ? ret : 0;
|
||||||
if (header && (bytes == 2 * sizeof(uint32_t))) {
|
if (!msg->data && (bytes == 2 * sizeof(uint32_t))) {
|
||||||
msg->cmd = ntohl(header[0]);
|
msg->cmd = ntohl(header[0]);
|
||||||
size = msg->size = ntohl(header[1]);
|
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
if (!size)
|
|
||||||
break; /* No data -> error */
|
if (!(size = msg->size = ntohl(header[1])))
|
||||||
buf = msg->data = dm_malloc(msg->size);
|
break;
|
||||||
if (!buf)
|
|
||||||
break; /* No mem -> error */
|
if (!(buf = msg->data = malloc(msg->size)))
|
||||||
header = 0;
|
goto bad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes != size) {
|
if (bytes == size)
|
||||||
dm_free(msg->data);
|
return 1;
|
||||||
msg->data = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
bad:
|
||||||
|
free(msg->data);
|
||||||
|
msg->data = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1530,7 +1536,7 @@ static int _client_write(struct dm_event_fifos *fifos,
|
|||||||
fd_set fds;
|
fd_set fds;
|
||||||
|
|
||||||
size_t size = 2 * sizeof(uint32_t) + ((msg->data) ? msg->size : 0);
|
size_t size = 2 * sizeof(uint32_t) + ((msg->data) ? msg->size : 0);
|
||||||
uint32_t *header = dm_malloc(size);
|
uint32_t *header = malloc(size);
|
||||||
char *buf = (char *)header;
|
char *buf = (char *)header;
|
||||||
|
|
||||||
if (!header) {
|
if (!header) {
|
||||||
@@ -1560,7 +1566,7 @@ static int _client_write(struct dm_event_fifos *fifos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (header != temp)
|
if (header != temp)
|
||||||
dm_free(header);
|
free(header);
|
||||||
|
|
||||||
return (bytes == size);
|
return (bytes == size);
|
||||||
}
|
}
|
||||||
@@ -1622,7 +1628,7 @@ static int _do_process_request(struct dm_event_daemon_message *msg)
|
|||||||
msg->size = dm_asprintf(&(msg->data), "%s %s %d", answer,
|
msg->size = dm_asprintf(&(msg->data), "%s %s %d", answer,
|
||||||
(msg->cmd == DM_EVENT_CMD_DIE) ? "DYING" : "HELLO",
|
(msg->cmd == DM_EVENT_CMD_DIE) ? "DYING" : "HELLO",
|
||||||
DM_EVENT_PROTOCOL_VERSION);
|
DM_EVENT_PROTOCOL_VERSION);
|
||||||
dm_free(answer);
|
free(answer);
|
||||||
}
|
}
|
||||||
} else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
|
} else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
|
||||||
stack;
|
stack;
|
||||||
@@ -1664,7 +1670,7 @@ static void _process_request(struct dm_event_fifos *fifos)
|
|||||||
|
|
||||||
DEBUGLOG("<<< CMD:%s (0x%x) completed (result %d).", decode_cmd(cmd), cmd, msg.cmd);
|
DEBUGLOG("<<< CMD:%s (0x%x) completed (result %d).", decode_cmd(cmd), cmd, msg.cmd);
|
||||||
|
|
||||||
dm_free(msg.data);
|
free(msg.data);
|
||||||
|
|
||||||
if (cmd == DM_EVENT_CMD_DIE) {
|
if (cmd == DM_EVENT_CMD_DIE) {
|
||||||
if (unlink(DMEVENTD_PIDFILE))
|
if (unlink(DMEVENTD_PIDFILE))
|
||||||
@@ -1745,7 +1751,8 @@ static void _init_thread_signals(void)
|
|||||||
sigdelset(&my_sigset, SIGHUP);
|
sigdelset(&my_sigset, SIGHUP);
|
||||||
sigdelset(&my_sigset, SIGQUIT);
|
sigdelset(&my_sigset, SIGQUIT);
|
||||||
|
|
||||||
pthread_sigmask(SIG_BLOCK, &my_sigset, NULL);
|
if (pthread_sigmask(SIG_BLOCK, &my_sigset, NULL))
|
||||||
|
log_sys_error("pthread_sigmask", "SIG_BLOCK");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1975,7 +1982,7 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos)
|
|||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
ret = daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
ret = daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
||||||
dm_free(msg.data);
|
free(msg.data);
|
||||||
msg.data = NULL;
|
msg.data = NULL;
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -2021,8 +2028,8 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos)
|
|||||||
static void _restart_dmeventd(void)
|
static void _restart_dmeventd(void)
|
||||||
{
|
{
|
||||||
struct dm_event_fifos fifos = {
|
struct dm_event_fifos fifos = {
|
||||||
.server = -1,
|
|
||||||
.client = -1,
|
.client = -1,
|
||||||
|
.server = -1,
|
||||||
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||||
.client_path = DM_EVENT_FIFO_CLIENT,
|
.client_path = DM_EVENT_FIFO_CLIENT,
|
||||||
.server_path = DM_EVENT_FIFO_SERVER
|
.server_path = DM_EVENT_FIFO_SERVER
|
||||||
@@ -2061,13 +2068,13 @@ static void _restart_dmeventd(void)
|
|||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(_initial_registrations = dm_malloc(sizeof(char*) * (count + 1)))) {
|
if (!(_initial_registrations = malloc(sizeof(char*) * (count + 1)))) {
|
||||||
fprintf(stderr, "Memory allocation registration failed.\n");
|
fprintf(stderr, "Memory allocation registration failed.\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; ++i) {
|
for (i = 0; i < count; ++i) {
|
||||||
if (!(_initial_registrations[i] = dm_strdup(message))) {
|
if (!(_initial_registrations[i] = strdup(message))) {
|
||||||
fprintf(stderr, "Memory allocation for message failed.\n");
|
fprintf(stderr, "Memory allocation for message failed.\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -2236,7 +2243,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
_init_thread_signals();
|
_init_thread_signals();
|
||||||
|
|
||||||
pthread_mutex_init(&_global_mutex, NULL);
|
if (pthread_mutex_init(&_global_mutex, NULL))
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (!_systemd_activation && !_open_fifos(&fifos))
|
if (!_systemd_activation && !_open_fifos(&fifos))
|
||||||
exit(EXIT_FIFO_FAILURE);
|
exit(EXIT_FIFO_FAILURE);
|
||||||
|
|||||||
@@ -12,10 +12,12 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dm-logging.h"
|
|
||||||
#include "dmlib.h"
|
|
||||||
#include "libdevmapper-event.h"
|
#include "libdevmapper-event.h"
|
||||||
#include "dmeventd.h"
|
#include "dmeventd.h"
|
||||||
|
#include "libdm/misc/dm-logging.h"
|
||||||
|
#include "base/memory/zalloc.h"
|
||||||
|
|
||||||
|
#include "lib/misc/intl.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
@@ -25,6 +27,7 @@
|
|||||||
#include <arpa/inet.h> /* for htonl, ntohl */
|
#include <arpa/inet.h> /* for htonl, ntohl */
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
static int _debug_level = 0;
|
static int _debug_level = 0;
|
||||||
static int _use_syslog = 0;
|
static int _use_syslog = 0;
|
||||||
@@ -47,8 +50,8 @@ struct dm_event_handler {
|
|||||||
|
|
||||||
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
|
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
|
||||||
{
|
{
|
||||||
dm_free(dmevh->dev_name);
|
free(dmevh->dev_name);
|
||||||
dm_free(dmevh->uuid);
|
free(dmevh->uuid);
|
||||||
dmevh->dev_name = dmevh->uuid = NULL;
|
dmevh->dev_name = dmevh->uuid = NULL;
|
||||||
dmevh->major = dmevh->minor = 0;
|
dmevh->major = dmevh->minor = 0;
|
||||||
}
|
}
|
||||||
@@ -57,7 +60,7 @@ struct dm_event_handler *dm_event_handler_create(void)
|
|||||||
{
|
{
|
||||||
struct dm_event_handler *dmevh;
|
struct dm_event_handler *dmevh;
|
||||||
|
|
||||||
if (!(dmevh = dm_zalloc(sizeof(*dmevh)))) {
|
if (!(dmevh = zalloc(sizeof(*dmevh)))) {
|
||||||
log_error("Failed to allocate event handler.");
|
log_error("Failed to allocate event handler.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -68,9 +71,9 @@ struct dm_event_handler *dm_event_handler_create(void)
|
|||||||
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
|
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
|
||||||
{
|
{
|
||||||
_dm_event_handler_clear_dev_info(dmevh);
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
dm_free(dmevh->dso);
|
free(dmevh->dso);
|
||||||
dm_free(dmevh->dmeventd_path);
|
free(dmevh->dmeventd_path);
|
||||||
dm_free(dmevh);
|
free(dmevh);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
|
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
|
||||||
@@ -78,9 +81,9 @@ int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const cha
|
|||||||
if (!dmeventd_path) /* noop */
|
if (!dmeventd_path) /* noop */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dm_free(dmevh->dmeventd_path);
|
free(dmevh->dmeventd_path);
|
||||||
|
|
||||||
if (!(dmevh->dmeventd_path = dm_strdup(dmeventd_path)))
|
if (!(dmevh->dmeventd_path = strdup(dmeventd_path)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -91,9 +94,9 @@ int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
|
|||||||
if (!path) /* noop */
|
if (!path) /* noop */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dm_free(dmevh->dso);
|
free(dmevh->dso);
|
||||||
|
|
||||||
if (!(dmevh->dso = dm_strdup(path)))
|
if (!(dmevh->dso = strdup(path)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -106,7 +109,7 @@ int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *de
|
|||||||
|
|
||||||
_dm_event_handler_clear_dev_info(dmevh);
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
|
||||||
if (!(dmevh->dev_name = dm_strdup(dev_name)))
|
if (!(dmevh->dev_name = strdup(dev_name)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -119,7 +122,7 @@ int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
|
|||||||
|
|
||||||
_dm_event_handler_clear_dev_info(dmevh);
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
|
||||||
if (!(dmevh->uuid = dm_strdup(uuid)))
|
if (!(dmevh->uuid = strdup(uuid)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -234,16 +237,16 @@ static int _daemon_read(struct dm_event_fifos *fifos,
|
|||||||
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
|
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
|
||||||
if (ret < 0 && errno != EINTR) {
|
if (ret < 0 && errno != EINTR) {
|
||||||
log_error("Unable to read from event server.");
|
log_error("Unable to read from event server.");
|
||||||
return 0;
|
goto bad;
|
||||||
}
|
}
|
||||||
if ((ret == 0) && (i > 4) && !bytes) {
|
if ((ret == 0) && (i > 4) && !bytes) {
|
||||||
log_error("No input from event server.");
|
log_error("No input from event server.");
|
||||||
return 0;
|
goto bad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret < 1) {
|
if (ret < 1) {
|
||||||
log_error("Unable to read from event server.");
|
log_error("Unable to read from event server.");
|
||||||
return 0;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = read(fifos->server, buf + bytes, size);
|
ret = read(fifos->server, buf + bytes, size);
|
||||||
@@ -252,25 +255,32 @@ static int _daemon_read(struct dm_event_fifos *fifos,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
log_error("Unable to read from event server.");
|
log_error("Unable to read from event server.");
|
||||||
return 0;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes += ret;
|
bytes += ret;
|
||||||
if (header && (bytes == 2 * sizeof(uint32_t))) {
|
if (!msg->data && (bytes == 2 * sizeof(uint32_t))) {
|
||||||
msg->cmd = ntohl(header[0]);
|
msg->cmd = ntohl(header[0]);
|
||||||
msg->size = ntohl(header[1]);
|
|
||||||
buf = msg->data = dm_malloc(msg->size);
|
|
||||||
size = msg->size;
|
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
header = 0;
|
|
||||||
|
if (!(size = msg->size = ntohl(header[1])))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(buf = msg->data = malloc(msg->size))) {
|
||||||
|
log_error("Unable to allocate message data.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes != size) {
|
if (bytes == size)
|
||||||
dm_free(msg->data);
|
return 1;
|
||||||
msg->data = NULL;
|
|
||||||
}
|
bad:
|
||||||
return bytes == size;
|
free(msg->data);
|
||||||
|
msg->data = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write message to daemon. */
|
/* Write message to daemon. */
|
||||||
@@ -370,13 +380,13 @@ int daemon_talk(struct dm_event_fifos *fifos,
|
|||||||
*/
|
*/
|
||||||
if (!_daemon_write(fifos, msg)) {
|
if (!_daemon_write(fifos, msg)) {
|
||||||
stack;
|
stack;
|
||||||
dm_free(msg->data);
|
free(msg->data);
|
||||||
msg->data = NULL;
|
msg->data = NULL;
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
dm_free(msg->data);
|
free(msg->data);
|
||||||
msg->data = NULL;
|
msg->data = NULL;
|
||||||
|
|
||||||
if (!_daemon_read(fifos, msg)) {
|
if (!_daemon_read(fifos, msg)) {
|
||||||
@@ -605,8 +615,8 @@ static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_messag
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct dm_event_fifos fifos = {
|
struct dm_event_fifos fifos = {
|
||||||
.server = -1,
|
|
||||||
.client = -1,
|
.client = -1,
|
||||||
|
.server = -1,
|
||||||
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||||
.client_path = DM_EVENT_FIFO_CLIENT,
|
.client_path = DM_EVENT_FIFO_CLIENT,
|
||||||
.server_path = DM_EVENT_FIFO_SERVER
|
.server_path = DM_EVENT_FIFO_SERVER
|
||||||
@@ -619,7 +629,7 @@ static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_messag
|
|||||||
|
|
||||||
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
||||||
|
|
||||||
dm_free(msg->data);
|
free(msg->data);
|
||||||
msg->data = 0;
|
msg->data = 0;
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
@@ -660,7 +670,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_free(msg.data);
|
free(msg.data);
|
||||||
|
|
||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
@@ -687,7 +697,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_free(msg.data);
|
free(msg.data);
|
||||||
|
|
||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
@@ -703,7 +713,7 @@ static char *_fetch_string(char **src, const int delimiter)
|
|||||||
if ((p = strchr(*src, delimiter)))
|
if ((p = strchr(*src, delimiter)))
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
if ((ret = dm_strdup(*src)))
|
if ((ret = strdup(*src)))
|
||||||
*src += strlen(ret) + 1;
|
*src += strlen(ret) + 1;
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
@@ -723,11 +733,11 @@ static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
|
|||||||
(*dso_name = _fetch_string(&p, ' ')) &&
|
(*dso_name = _fetch_string(&p, ' ')) &&
|
||||||
(*uuid = _fetch_string(&p, ' '))) {
|
(*uuid = _fetch_string(&p, ' '))) {
|
||||||
*evmask = atoi(p);
|
*evmask = atoi(p);
|
||||||
dm_free(id);
|
free(id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_free(id);
|
free(id);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,7 +779,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
|||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
dmt = NULL;
|
dmt = NULL;
|
||||||
|
|
||||||
dm_free(msg.data);
|
free(msg.data);
|
||||||
msg.data = NULL;
|
msg.data = NULL;
|
||||||
|
|
||||||
_dm_event_handler_clear_dev_info(dmevh);
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
@@ -778,7 +788,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dmevh->uuid = dm_strdup(reply_uuid))) {
|
if (!(dmevh->uuid = strdup(reply_uuid))) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -791,13 +801,13 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
|||||||
dm_event_handler_set_dso(dmevh, reply_dso);
|
dm_event_handler_set_dso(dmevh, reply_dso);
|
||||||
dm_event_handler_set_event_mask(dmevh, reply_mask);
|
dm_event_handler_set_event_mask(dmevh, reply_mask);
|
||||||
|
|
||||||
dm_free(reply_dso);
|
free(reply_dso);
|
||||||
reply_dso = NULL;
|
reply_dso = NULL;
|
||||||
|
|
||||||
dm_free(reply_uuid);
|
free(reply_uuid);
|
||||||
reply_uuid = NULL;
|
reply_uuid = NULL;
|
||||||
|
|
||||||
if (!(dmevh->dev_name = dm_strdup(dm_task_get_name(dmt)))) {
|
if (!(dmevh->dev_name = strdup(dm_task_get_name(dmt)))) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -815,9 +825,9 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
dm_free(msg.data);
|
free(msg.data);
|
||||||
dm_free(reply_dso);
|
free(reply_dso);
|
||||||
dm_free(reply_uuid);
|
free(reply_uuid);
|
||||||
_dm_event_handler_clear_dev_info(dmevh);
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
if (dmt)
|
if (dmt)
|
||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
@@ -982,12 +992,12 @@ int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
|
|||||||
if (!p) {
|
if (!p) {
|
||||||
log_error("Malformed reply from dmeventd '%s'.",
|
log_error("Malformed reply from dmeventd '%s'.",
|
||||||
msg.data);
|
msg.data);
|
||||||
dm_free(msg.data);
|
free(msg.data);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
*timeout = atoi(p);
|
*timeout = atoi(p);
|
||||||
}
|
}
|
||||||
dm_free(msg.data);
|
free(msg.data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#ifndef LIB_DMEVENT_H
|
#ifndef LIB_DMEVENT_H
|
||||||
#define LIB_DMEVENT_H
|
#define LIB_DMEVENT_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -8,4 +8,3 @@ Description: device-mapper event library
|
|||||||
Version: @DM_LIB_PATCHLEVEL@
|
Version: @DM_LIB_PATCHLEVEL@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
Libs: -L${libdir} -ldevmapper-event
|
Libs: -L${libdir} -ldevmapper-event
|
||||||
Requires.private: devmapper
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ top_srcdir = @top_srcdir@
|
|||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
CLDFLAGS += -L$(top_builddir)/tools
|
CLDFLAGS += -L$(top_builddir)/tools
|
||||||
|
LIBS += $(DMEVENT_LIBS) $(PTHREAD_LIBS) @LVM2CMD_LIB@
|
||||||
|
|
||||||
SOURCES = dmeventd_lvm.c
|
SOURCES = dmeventd_lvm.c
|
||||||
|
|
||||||
@@ -24,8 +25,6 @@ LIB_VERSION = $(LIB_VERSION_LVM)
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS)
|
|
||||||
|
|
||||||
install_lvm2: install_lib_shared
|
install_lvm2: install_lib_shared
|
||||||
|
|
||||||
install: install_lvm2
|
install: install_lvm2
|
||||||
|
|||||||
@@ -12,10 +12,10 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib/misc/lib.h"
|
||||||
#include "dmeventd_lvm.h"
|
#include "dmeventd_lvm.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "daemons/dmeventd/libdevmapper-event.h"
|
||||||
#include "lvm2cmd.h"
|
#include "tools/lvm2cmd.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ int dmeventd_lvm2_init(void)
|
|||||||
if (!_lvm_handle) {
|
if (!_lvm_handle) {
|
||||||
lvm2_log_fn(_lvm2_print_log);
|
lvm2_log_fn(_lvm2_print_log);
|
||||||
|
|
||||||
if (!(_lvm_handle = lvm2_init()))
|
if (!(_lvm_handle = lvm2_init_threaded()))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -159,6 +159,7 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
|
|||||||
dmeventd_lvm2_lock();
|
dmeventd_lvm2_lock();
|
||||||
if (!dmeventd_lvm2_run(cmd) ||
|
if (!dmeventd_lvm2_run(cmd) ||
|
||||||
!(env = getenv(cmd))) {
|
!(env = getenv(cmd))) {
|
||||||
|
dmeventd_lvm2_unlock();
|
||||||
log_error("Unable to find configured command.");
|
log_error("Unable to find configured command.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
LIBS += -ldevmapper-event-lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_mirror.c
|
SOURCES = dmeventd_mirror.c
|
||||||
|
|
||||||
@@ -30,8 +30,6 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
|
||||||
|
|
||||||
install_lvm2: install_dm_plugin
|
install_lvm2: install_dm_plugin
|
||||||
|
|
||||||
install: install_lvm2
|
install: install_lvm2
|
||||||
|
|||||||
@@ -12,10 +12,10 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib/misc/lib.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
|
||||||
#include "dmeventd_lvm.h"
|
#include "daemons/dmeventd/libdevmapper-event.h"
|
||||||
#include "activate.h" /* For TARGET_NAME* */
|
#include "lib/activate/activate.h"
|
||||||
|
|
||||||
/* FIXME Reformat to 80 char lines. */
|
/* FIXME Reformat to 80 char lines. */
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
LIBS += -ldevmapper-event-lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_raid.c
|
SOURCES = dmeventd_raid.c
|
||||||
|
|
||||||
@@ -29,8 +29,6 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
|
||||||
|
|
||||||
install_lvm2: install_dm_plugin
|
install_lvm2: install_dm_plugin
|
||||||
|
|
||||||
install: install_lvm2
|
install: install_lvm2
|
||||||
|
|||||||
@@ -12,10 +12,10 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib/misc/lib.h"
|
||||||
#include "defaults.h"
|
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
|
||||||
#include "dmeventd_lvm.h"
|
#include "daemons/dmeventd/libdevmapper-event.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "lib/config/defaults.h"
|
||||||
|
|
||||||
/* Hold enough elements for the mximum number of RAID images */
|
/* Hold enough elements for the mximum number of RAID images */
|
||||||
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
|
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
|
||||||
@@ -76,14 +76,17 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dead) {
|
if (dead) {
|
||||||
if (status->insync_regions < status->total_regions) {
|
/*
|
||||||
if (!state->warned) {
|
* Use the first event to run a repair ignoring any additonal ones.
|
||||||
state->warned = 1;
|
*
|
||||||
log_warn("WARNING: waiting for resynchronization to finish "
|
* We presume lvconvert to do pre-repair
|
||||||
"before initiating repair on RAID device %s.", device);
|
* checks to avoid bloat in this plugin.
|
||||||
}
|
*/
|
||||||
|
if (!state->warned && status->insync_regions < status->total_regions) {
|
||||||
goto out; /* Not yet done syncing with accessible devices */
|
state->warned = 1;
|
||||||
|
log_warn("WARNING: waiting for resynchronization to finish "
|
||||||
|
"before initiating repair on RAID device %s.", device);
|
||||||
|
/* Fall through to allow lvconvert to run. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->failed)
|
if (state->failed)
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
LIBS += -ldevmapper-event-lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_snapshot.c
|
SOURCES = dmeventd_snapshot.c
|
||||||
|
|
||||||
@@ -26,8 +26,6 @@ LIB_VERSION = $(LIB_VERSION_LVM)
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
|
||||||
|
|
||||||
install_lvm2: install_dm_plugin
|
install_lvm2: install_dm_plugin
|
||||||
|
|
||||||
install: install_lvm2
|
install: install_lvm2
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib/misc/lib.h"
|
||||||
#include "dmeventd_lvm.h"
|
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "daemons/dmeventd/libdevmapper-event.h"
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
@@ -175,6 +175,7 @@ void process_event(struct dm_task *dmt,
|
|||||||
const char *device = dm_task_get_name(dmt);
|
const char *device = dm_task_get_name(dmt);
|
||||||
int percent;
|
int percent;
|
||||||
struct dm_info info;
|
struct dm_info info;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* No longer monitoring, waiting for remove */
|
/* No longer monitoring, waiting for remove */
|
||||||
if (!state->percent_check)
|
if (!state->percent_check)
|
||||||
@@ -205,7 +206,8 @@ void process_event(struct dm_task *dmt,
|
|||||||
/* Maybe configurable ? */
|
/* Maybe configurable ? */
|
||||||
_remove(dm_task_get_uuid(dmt));
|
_remove(dm_task_get_uuid(dmt));
|
||||||
#endif
|
#endif
|
||||||
pthread_kill(pthread_self(), SIGALRM);
|
if ((ret = pthread_kill(pthread_self(), SIGALRM)) && (ret != ESRCH))
|
||||||
|
log_sys_error("pthread_kill", "self");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +215,8 @@ void process_event(struct dm_task *dmt,
|
|||||||
/* TODO eventually recognize earlier when room is enough */
|
/* TODO eventually recognize earlier when room is enough */
|
||||||
log_info("Dropping monitoring of fully provisioned snapshot %s.",
|
log_info("Dropping monitoring of fully provisioned snapshot %s.",
|
||||||
device);
|
device);
|
||||||
pthread_kill(pthread_self(), SIGALRM);
|
if ((ret = pthread_kill(pthread_self(), SIGALRM)) && (ret != ESRCH))
|
||||||
|
log_sys_error("pthread_kill", "self");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
LIBS += -ldevmapper-event-lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_thin.c
|
SOURCES = dmeventd_thin.c
|
||||||
|
|
||||||
@@ -29,8 +29,6 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
|
||||||
|
|
||||||
install_lvm2: install_dm_plugin
|
install_lvm2: install_dm_plugin
|
||||||
|
|
||||||
install: install_lvm2
|
install: install_lvm2
|
||||||
|
|||||||
@@ -12,16 +12,16 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h" /* using here lvm log */
|
#include "lib/misc/lib.h"
|
||||||
#include "dmeventd_lvm.h"
|
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "daemons/dmeventd/libdevmapper-event.h"
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
/* TODO - move this mountinfo code into library to be reusable */
|
/* TODO - move this mountinfo code into library to be reusable */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# include "kdev_t.h"
|
# include "libdm/misc/kdev_t.h"
|
||||||
#else
|
#else
|
||||||
# define MAJOR(x) major((x))
|
# define MAJOR(x) major((x))
|
||||||
# define MINOR(x) minor((x))
|
# define MINOR(x) minor((x))
|
||||||
@@ -286,7 +286,7 @@ void process_event(struct dm_task *dmt,
|
|||||||
if (state->fails++ <= state->max_fails) {
|
if (state->fails++ <= state->max_fails) {
|
||||||
log_debug("Postponing frequently failing policy (%u <= %u).",
|
log_debug("Postponing frequently failing policy (%u <= %u).",
|
||||||
state->fails - 1, state->max_fails);
|
state->fails - 1, state->max_fails);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
if (state->max_fails < MAX_FAILS)
|
if (state->max_fails < MAX_FAILS)
|
||||||
state->max_fails <<= 1;
|
state->max_fails <<= 1;
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
LIBS += -ldevmapper-event-lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_vdo.c
|
SOURCES = dmeventd_vdo.c
|
||||||
|
|
||||||
@@ -29,8 +29,6 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += -ldevmapper-event-lvm2 $(INTERNAL_LIBS)
|
|
||||||
|
|
||||||
install_lvm2: install_dm_plugin
|
install_lvm2: install_dm_plugin
|
||||||
|
|
||||||
install: install_lvm2
|
install: install_lvm2
|
||||||
|
|||||||
@@ -12,9 +12,17 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib/misc/lib.h"
|
||||||
#include "dmeventd_lvm.h"
|
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "daemons/dmeventd/libdevmapper-event.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use parser from new device_mapper library.
|
||||||
|
* Although during compilation we can see dm_vdo_status_parse()
|
||||||
|
* in runtime we are linked agains systems libdm 'older' library
|
||||||
|
* which does not provide this symbol and plugin fails to load
|
||||||
|
*/
|
||||||
|
#include "device_mapper/vdo/status.c"
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -45,23 +53,6 @@ struct dso_state {
|
|||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vdo_status {
|
|
||||||
uint64_t used_blocks;
|
|
||||||
uint64_t total_blocks;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int _vdo_status_parse(const char *params, struct vdo_status *status)
|
|
||||||
{
|
|
||||||
if (sscanf(params, "%*s %*s %*s %*s %*s %" PRIu64 " %" PRIu64,
|
|
||||||
&status->used_blocks,
|
|
||||||
&status->total_blocks) < 2) {
|
|
||||||
log_error("Failed to parse vdo params: %s.", params);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DM_EVENT_LOG_FN("vdo")
|
DM_EVENT_LOG_FN("vdo")
|
||||||
|
|
||||||
static int _run_command(struct dso_state *state)
|
static int _run_command(struct dso_state *state)
|
||||||
@@ -165,7 +156,7 @@ void process_event(struct dm_task *dmt,
|
|||||||
char *params;
|
char *params;
|
||||||
int needs_policy = 0;
|
int needs_policy = 0;
|
||||||
struct dm_task *new_dmt = NULL;
|
struct dm_task *new_dmt = NULL;
|
||||||
struct vdo_status status;
|
struct dm_vdo_status_parse_result vdop = { .status = NULL };
|
||||||
|
|
||||||
#if VDO_DEBUG
|
#if VDO_DEBUG
|
||||||
log_debug("Watch for VDO %s:%.2f%%.", state->name,
|
log_debug("Watch for VDO %s:%.2f%%.", state->name,
|
||||||
@@ -211,24 +202,24 @@ void process_event(struct dm_task *dmt,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_vdo_status_parse(params, &status)) {
|
if (!dm_vdo_status_parse(state->mem, params, &vdop)) {
|
||||||
log_error("Failed to parse status.");
|
log_error("Failed to parse status.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->percent = dm_make_percent(status.used_blocks,
|
state->percent = dm_make_percent(vdop.status->used_blocks,
|
||||||
status.total_blocks);
|
vdop.status->total_blocks);
|
||||||
|
|
||||||
#if VDO_DEBUG
|
#if VDO_DEBUG
|
||||||
log_debug("VDO %s status %.2f%% " FMTu64 "/" FMTu64 ".",
|
log_debug("VDO %s status %.2f%% " FMTu64 "/" FMTu64 ".",
|
||||||
state->name, dm_percent_to_round_float(state->percent, 2),
|
state->name, dm_percent_to_round_float(state->percent, 2),
|
||||||
status.used_blocks, status.total_blocks);
|
vdop.status->used_blocks, vdop.status->total_blocks);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* VDO pool size had changed. Clear the threshold. */
|
/* VDO pool size had changed. Clear the threshold. */
|
||||||
if (state->known_data_size != status.total_blocks) {
|
if (state->known_data_size != vdop.status->total_blocks) {
|
||||||
state->percent_check = CHECK_MINIMUM;
|
state->percent_check = CHECK_MINIMUM;
|
||||||
state->known_data_size = status.total_blocks;
|
state->known_data_size = vdop.status->total_blocks;
|
||||||
state->fails = 0;
|
state->fails = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +252,7 @@ void process_event(struct dm_task *dmt,
|
|||||||
if (state->fails++ <= state->max_fails) {
|
if (state->fails++ <= state->max_fails) {
|
||||||
log_debug("Postponing frequently failing policy (%u <= %u).",
|
log_debug("Postponing frequently failing policy (%u <= %u).",
|
||||||
state->fails - 1, state->max_fails);
|
state->fails - 1, state->max_fails);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
if (state->max_fails < MAX_FAILS)
|
if (state->max_fails < MAX_FAILS)
|
||||||
state->max_fails <<= 1;
|
state->max_fails <<= 1;
|
||||||
@@ -269,10 +260,12 @@ void process_event(struct dm_task *dmt,
|
|||||||
} else
|
} else
|
||||||
state->max_fails = 1; /* Reset on success */
|
state->max_fails = 1; /* Reset on success */
|
||||||
|
|
||||||
/* FIXME: ATM nothing can be done, drop 0, once it becomes useful */
|
if (needs_policy)
|
||||||
if (0 && needs_policy)
|
|
||||||
_use_policy(dmt, state);
|
_use_policy(dmt, state);
|
||||||
out:
|
out:
|
||||||
|
if (vdop.status)
|
||||||
|
dm_pool_free(state->mem, vdop.status);
|
||||||
|
|
||||||
if (new_dmt)
|
if (new_dmt)
|
||||||
dm_task_destroy(new_dmt);
|
dm_task_destroy(new_dmt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
|
|
||||||
#
|
|
||||||
# This file is part of the device-mapper userspace tools.
|
|
||||||
#
|
|
||||||
# This copyrighted material is made available to anyone wishing to use,
|
|
||||||
# modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
# of the GNU Lesser General Public License v.2.1.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
srcdir = @srcdir@
|
|
||||||
top_srcdir = @top_srcdir@
|
|
||||||
top_builddir = @top_builddir@
|
|
||||||
|
|
||||||
SOURCES = dmfilemapd.c
|
|
||||||
|
|
||||||
TARGETS = dmfilemapd
|
|
||||||
|
|
||||||
.PHONY: install_dmfilemapd install_dmfilemapd_static
|
|
||||||
|
|
||||||
INSTALL_DMFILEMAPD_TARGETS = install_dmfilemapd_dynamic
|
|
||||||
|
|
||||||
CLEAN_TARGETS = dmfilemapd.static
|
|
||||||
|
|
||||||
CFLOW_LIST = $(SOURCES)
|
|
||||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
|
||||||
CFLOW_TARGET = dmfilemapd
|
|
||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
|
||||||
|
|
||||||
all: device-mapper
|
|
||||||
device-mapper: $(TARGETS)
|
|
||||||
|
|
||||||
CFLAGS_dmfilemapd.o += $(EXTRA_EXEC_CFLAGS)
|
|
||||||
LIBS += -ldevmapper
|
|
||||||
|
|
||||||
dmfilemapd: $(LIB_SHARED) dmfilemapd.o
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) \
|
|
||||||
-o $@ dmfilemapd.o $(DL_LIBS) $(LIBS)
|
|
||||||
|
|
||||||
dmfilemapd.static: $(LIB_STATIC) dmfilemapd.o $(interfacebuilddir)/libdevmapper.a
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L$(interfacebuilddir) \
|
|
||||||
-o $@ dmfilemapd.o $(DL_LIBS) $(LIBS) $(STATIC_LIBS)
|
|
||||||
|
|
||||||
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/dmfilemapd/$(LIB_NAME).cflow
|
|
||||||
endif
|
|
||||||
|
|
||||||
install_dmfilemapd_dynamic: dmfilemapd
|
|
||||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
|
||||||
|
|
||||||
install_dmfilemapd_static: dmfilemapd.static
|
|
||||||
$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
|
|
||||||
|
|
||||||
install_dmfilemapd: $(INSTALL_DMFILEMAPD_TARGETS)
|
|
||||||
|
|
||||||
install: install_dmfilemapd
|
|
||||||
|
|
||||||
install_device-mapper: install_dmfilemapd
|
|
||||||
@@ -23,11 +23,10 @@ LVMDBUS_SRCDIR_FILES = \
|
|||||||
cfg.py \
|
cfg.py \
|
||||||
cmdhandler.py \
|
cmdhandler.py \
|
||||||
fetch.py \
|
fetch.py \
|
||||||
__init__.py \
|
|
||||||
job.py \
|
job.py \
|
||||||
loader.py \
|
loader.py \
|
||||||
main.py \
|
|
||||||
lv.py \
|
lv.py \
|
||||||
|
main.py \
|
||||||
manager.py \
|
manager.py \
|
||||||
objectmanager.py \
|
objectmanager.py \
|
||||||
pv.py \
|
pv.py \
|
||||||
@@ -35,7 +34,8 @@ LVMDBUS_SRCDIR_FILES = \
|
|||||||
state.py \
|
state.py \
|
||||||
udevwatch.py \
|
udevwatch.py \
|
||||||
utils.py \
|
utils.py \
|
||||||
vg.py
|
vg.py \
|
||||||
|
__init__.py
|
||||||
|
|
||||||
LVMDBUS_BUILDDIR_FILES = \
|
LVMDBUS_BUILDDIR_FILES = \
|
||||||
lvmdb.py \
|
lvmdb.py \
|
||||||
@@ -51,17 +51,18 @@ include $(top_builddir)/make.tmpl
|
|||||||
.PHONY: install_lvmdbusd
|
.PHONY: install_lvmdbusd
|
||||||
|
|
||||||
all:
|
all:
|
||||||
test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
|
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
|
||||||
|
|
||||||
install_lvmdbusd:
|
install_lvmdbusd:
|
||||||
$(INSTALL_DIR) $(sbindir)
|
@echo " [INSTALL] $<"
|
||||||
$(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
|
$(Q) $(INSTALL_DIR) $(sbindir)
|
||||||
$(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
|
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
|
||||||
(cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
|
$(Q) $(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
|
||||||
$(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
|
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
|
||||||
PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
|
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
|
||||||
$(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
|
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
|
||||||
$(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
|
$(Q) $(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
|
||||||
|
$(Q) $(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
|
||||||
|
|
||||||
install_lvm2: install_lvmdbusd
|
install_lvm2: install_lvmdbusd
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class AutomatedProperties(dbus.service.Object):
|
|||||||
# through all dbus objects as some don't have a search method, like
|
# through all dbus objects as some don't have a search method, like
|
||||||
# 'Manager' object.
|
# 'Manager' object.
|
||||||
if not self._ap_search_method:
|
if not self._ap_search_method:
|
||||||
return
|
return 0
|
||||||
|
|
||||||
search = self.lvm_id
|
search = self.lvm_id
|
||||||
if search_key:
|
if search_key:
|
||||||
|
|||||||
@@ -47,9 +47,11 @@ BUS_NAME = os.getenv('LVM_DBUS_NAME', 'com.redhat.lvmdbus1')
|
|||||||
BASE_INTERFACE = 'com.redhat.lvmdbus1'
|
BASE_INTERFACE = 'com.redhat.lvmdbus1'
|
||||||
PV_INTERFACE = BASE_INTERFACE + '.Pv'
|
PV_INTERFACE = BASE_INTERFACE + '.Pv'
|
||||||
VG_INTERFACE = BASE_INTERFACE + '.Vg'
|
VG_INTERFACE = BASE_INTERFACE + '.Vg'
|
||||||
|
VG_VDO_INTERFACE = BASE_INTERFACE + '.VgVdo'
|
||||||
LV_INTERFACE = BASE_INTERFACE + '.Lv'
|
LV_INTERFACE = BASE_INTERFACE + '.Lv'
|
||||||
LV_COMMON_INTERFACE = BASE_INTERFACE + '.LvCommon'
|
LV_COMMON_INTERFACE = BASE_INTERFACE + '.LvCommon'
|
||||||
THIN_POOL_INTERFACE = BASE_INTERFACE + '.ThinPool'
|
THIN_POOL_INTERFACE = BASE_INTERFACE + '.ThinPool'
|
||||||
|
VDO_POOL_INTERFACE = BASE_INTERFACE + '.VdoPool'
|
||||||
CACHE_POOL_INTERFACE = BASE_INTERFACE + '.CachePool'
|
CACHE_POOL_INTERFACE = BASE_INTERFACE + '.CachePool'
|
||||||
LV_CACHED = BASE_INTERFACE + '.CachedLv'
|
LV_CACHED = BASE_INTERFACE + '.CachedLv'
|
||||||
SNAPSHOT_INTERFACE = BASE_INTERFACE + '.Snapshot'
|
SNAPSHOT_INTERFACE = BASE_INTERFACE + '.Snapshot'
|
||||||
@@ -61,6 +63,7 @@ PV_OBJ_PATH = BASE_OBJ_PATH + '/Pv'
|
|||||||
VG_OBJ_PATH = BASE_OBJ_PATH + '/Vg'
|
VG_OBJ_PATH = BASE_OBJ_PATH + '/Vg'
|
||||||
LV_OBJ_PATH = BASE_OBJ_PATH + '/Lv'
|
LV_OBJ_PATH = BASE_OBJ_PATH + '/Lv'
|
||||||
THIN_POOL_PATH = BASE_OBJ_PATH + "/ThinPool"
|
THIN_POOL_PATH = BASE_OBJ_PATH + "/ThinPool"
|
||||||
|
VDO_POOL_PATH = BASE_OBJ_PATH + "/VdoPool"
|
||||||
CACHE_POOL_PATH = BASE_OBJ_PATH + "/CachePool"
|
CACHE_POOL_PATH = BASE_OBJ_PATH + "/CachePool"
|
||||||
HIDDEN_LV_PATH = BASE_OBJ_PATH + "/HiddenLv"
|
HIDDEN_LV_PATH = BASE_OBJ_PATH + "/HiddenLv"
|
||||||
MANAGER_OBJ_PATH = BASE_OBJ_PATH + '/Manager'
|
MANAGER_OBJ_PATH = BASE_OBJ_PATH + '/Manager'
|
||||||
@@ -71,6 +74,7 @@ pv_id = itertools.count()
|
|||||||
vg_id = itertools.count()
|
vg_id = itertools.count()
|
||||||
lv_id = itertools.count()
|
lv_id = itertools.count()
|
||||||
thin_id = itertools.count()
|
thin_id = itertools.count()
|
||||||
|
vdo_id = itertools.count()
|
||||||
cache_pool_id = itertools.count()
|
cache_pool_id = itertools.count()
|
||||||
job_id = itertools.count()
|
job_id = itertools.count()
|
||||||
hidden_lv = itertools.count()
|
hidden_lv = itertools.count()
|
||||||
@@ -79,6 +83,9 @@ hidden_lv = itertools.count()
|
|||||||
load = None
|
load = None
|
||||||
event = None
|
event = None
|
||||||
|
|
||||||
|
# Boolean to denote if lvm supports VDO integration
|
||||||
|
vdo_support = False
|
||||||
|
|
||||||
# Global cached state
|
# Global cached state
|
||||||
db = None
|
db = None
|
||||||
|
|
||||||
@@ -87,3 +94,13 @@ blackbox = None
|
|||||||
|
|
||||||
# RequestEntry ctor
|
# RequestEntry ctor
|
||||||
create_request_entry = None
|
create_request_entry = None
|
||||||
|
|
||||||
|
|
||||||
|
def exit_daemon():
|
||||||
|
"""
|
||||||
|
Exit the daemon cleanly
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if run and loop:
|
||||||
|
run.value = 0
|
||||||
|
loop.quit()
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class LvmFlightRecorder(object):
|
|||||||
with cmd_lock:
|
with cmd_lock:
|
||||||
if len(self.queue):
|
if len(self.queue):
|
||||||
log_error("LVM dbus flight recorder START")
|
log_error("LVM dbus flight recorder START")
|
||||||
for c in self.queue:
|
for c in reversed(self.queue):
|
||||||
log_error(str(c))
|
log_error(str(c))
|
||||||
log_error("LVM dbus flight recorder END")
|
log_error("LVM dbus flight recorder END")
|
||||||
|
|
||||||
@@ -217,7 +217,10 @@ def options_to_cli_args(options):
|
|||||||
else:
|
else:
|
||||||
rc.append("--%s" % k)
|
rc.append("--%s" % k)
|
||||||
if v != "":
|
if v != "":
|
||||||
rc.append(str(v))
|
if isinstance(v, int):
|
||||||
|
rc.append(str(int(v)))
|
||||||
|
else:
|
||||||
|
rc.append(str(v))
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
|
|
||||||
@@ -263,10 +266,10 @@ def lv_tag(lv_name, add, rm, tag_options):
|
|||||||
return _tag('lvchange', lv_name, add, rm, tag_options)
|
return _tag('lvchange', lv_name, add, rm, tag_options)
|
||||||
|
|
||||||
|
|
||||||
def vg_rename(vg, new_name, rename_options):
|
def vg_rename(vg_uuid, new_name, rename_options):
|
||||||
cmd = ['vgrename']
|
cmd = ['vgrename']
|
||||||
cmd.extend(options_to_cli_args(rename_options))
|
cmd.extend(options_to_cli_args(rename_options))
|
||||||
cmd.extend([vg, new_name])
|
cmd.extend([vg_uuid, new_name])
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
@@ -280,7 +283,7 @@ def vg_remove(vg_name, remove_options):
|
|||||||
def vg_lv_create(vg_name, create_options, name, size_bytes, pv_dests):
|
def vg_lv_create(vg_name, create_options, name, size_bytes, pv_dests):
|
||||||
cmd = ['lvcreate']
|
cmd = ['lvcreate']
|
||||||
cmd.extend(options_to_cli_args(create_options))
|
cmd.extend(options_to_cli_args(create_options))
|
||||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
cmd.extend(['--size', '%dB' % size_bytes])
|
||||||
cmd.extend(['--name', name, vg_name, '--yes'])
|
cmd.extend(['--name', name, vg_name, '--yes'])
|
||||||
pv_dest_ranges(cmd, pv_dests)
|
pv_dest_ranges(cmd, pv_dests)
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
@@ -292,7 +295,7 @@ def vg_lv_snapshot(vg_name, snapshot_options, name, size_bytes):
|
|||||||
cmd.extend(["-s"])
|
cmd.extend(["-s"])
|
||||||
|
|
||||||
if size_bytes != 0:
|
if size_bytes != 0:
|
||||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
cmd.extend(['--size', '%dB' % size_bytes])
|
||||||
|
|
||||||
cmd.extend(['--name', name, vg_name])
|
cmd.extend(['--name', name, vg_name])
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
@@ -303,9 +306,9 @@ def _vg_lv_create_common_cmd(create_options, size_bytes, thin_pool):
|
|||||||
cmd.extend(options_to_cli_args(create_options))
|
cmd.extend(options_to_cli_args(create_options))
|
||||||
|
|
||||||
if not thin_pool:
|
if not thin_pool:
|
||||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
cmd.extend(['--size', '%dB' % size_bytes])
|
||||||
else:
|
else:
|
||||||
cmd.extend(['--thin', '--size', str(size_bytes) + 'B'])
|
cmd.extend(['--thin', '--size', '%dB' % size_bytes])
|
||||||
|
|
||||||
cmd.extend(['--yes'])
|
cmd.extend(['--yes'])
|
||||||
return cmd
|
return cmd
|
||||||
@@ -320,10 +323,10 @@ def vg_lv_create_linear(vg_name, create_options, name, size_bytes, thin_pool):
|
|||||||
def vg_lv_create_striped(vg_name, create_options, name, size_bytes,
|
def vg_lv_create_striped(vg_name, create_options, name, size_bytes,
|
||||||
num_stripes, stripe_size_kb, thin_pool):
|
num_stripes, stripe_size_kb, thin_pool):
|
||||||
cmd = _vg_lv_create_common_cmd(create_options, size_bytes, thin_pool)
|
cmd = _vg_lv_create_common_cmd(create_options, size_bytes, thin_pool)
|
||||||
cmd.extend(['--stripes', str(num_stripes)])
|
cmd.extend(['--stripes', str(int(num_stripes))])
|
||||||
|
|
||||||
if stripe_size_kb != 0:
|
if stripe_size_kb != 0:
|
||||||
cmd.extend(['--stripesize', str(stripe_size_kb)])
|
cmd.extend(['--stripesize', str(int(stripe_size_kb))])
|
||||||
|
|
||||||
cmd.extend(['--name', name, vg_name])
|
cmd.extend(['--name', name, vg_name])
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
@@ -336,13 +339,13 @@ def _vg_lv_create_raid(vg_name, create_options, name, raid_type, size_bytes,
|
|||||||
cmd.extend(options_to_cli_args(create_options))
|
cmd.extend(options_to_cli_args(create_options))
|
||||||
|
|
||||||
cmd.extend(['--type', raid_type])
|
cmd.extend(['--type', raid_type])
|
||||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
cmd.extend(['--size', '%dB' % size_bytes])
|
||||||
|
|
||||||
if num_stripes != 0:
|
if num_stripes != 0:
|
||||||
cmd.extend(['--stripes', str(num_stripes)])
|
cmd.extend(['--stripes', str(int(num_stripes))])
|
||||||
|
|
||||||
if stripe_size_kb != 0:
|
if stripe_size_kb != 0:
|
||||||
cmd.extend(['--stripesize', str(stripe_size_kb)])
|
cmd.extend(['--stripesize', str(int(stripe_size_kb))])
|
||||||
|
|
||||||
cmd.extend(['--name', name, vg_name, '--yes'])
|
cmd.extend(['--name', name, vg_name, '--yes'])
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
@@ -363,8 +366,8 @@ def vg_lv_create_mirror(
|
|||||||
cmd.extend(options_to_cli_args(create_options))
|
cmd.extend(options_to_cli_args(create_options))
|
||||||
|
|
||||||
cmd.extend(['--type', 'mirror'])
|
cmd.extend(['--type', 'mirror'])
|
||||||
cmd.extend(['--mirrors', str(num_copies)])
|
cmd.extend(['--mirrors', str(int(num_copies))])
|
||||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
cmd.extend(['--size', '%dB' % size_bytes])
|
||||||
cmd.extend(['--name', name, vg_name, '--yes'])
|
cmd.extend(['--name', name, vg_name, '--yes'])
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
|
|
||||||
@@ -385,6 +388,24 @@ def vg_create_thin_pool(md_full_name, data_full_name, create_options):
|
|||||||
return call(cmd)
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def vg_create_vdo_pool_lv_and_lv(vg_name, pool_name, lv_name, data_size,
|
||||||
|
virtual_size, create_options):
|
||||||
|
cmd = ['lvcreate']
|
||||||
|
cmd.extend(options_to_cli_args(create_options))
|
||||||
|
cmd.extend(['-y', '--type', 'vdo', '-n', lv_name,
|
||||||
|
'-L', '%dB' % data_size, '-V', '%dB' % virtual_size,
|
||||||
|
"%s/%s" % (vg_name, pool_name)])
|
||||||
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def vg_create_vdo_pool(pool_full_name, lv_name, virtual_size, create_options):
|
||||||
|
cmd = ['lvconvert']
|
||||||
|
cmd.extend(options_to_cli_args(create_options))
|
||||||
|
cmd.extend(['--type', 'vdo-pool', '-n', lv_name, '--force', '-y',
|
||||||
|
'-V', '%dB' % virtual_size, pool_full_name])
|
||||||
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
def lv_remove(lv_path, remove_options):
|
def lv_remove(lv_path, remove_options):
|
||||||
cmd = ['lvremove']
|
cmd = ['lvremove']
|
||||||
cmd.extend(options_to_cli_args(remove_options))
|
cmd.extend(options_to_cli_args(remove_options))
|
||||||
@@ -418,7 +439,7 @@ def lv_resize(lv_full_name, size_change, pv_dests,
|
|||||||
def lv_lv_create(lv_full_name, create_options, name, size_bytes):
|
def lv_lv_create(lv_full_name, create_options, name, size_bytes):
|
||||||
cmd = ['lvcreate']
|
cmd = ['lvcreate']
|
||||||
cmd.extend(options_to_cli_args(create_options))
|
cmd.extend(options_to_cli_args(create_options))
|
||||||
cmd.extend(['--virtualsize', str(size_bytes) + 'B', '-T'])
|
cmd.extend(['--virtualsize', '%dB' % size_bytes, '-T'])
|
||||||
cmd.extend(['--name', name, lv_full_name, '--yes'])
|
cmd.extend(['--name', name, lv_full_name, '--yes'])
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
|
|
||||||
@@ -432,6 +453,15 @@ def lv_cache_lv(cache_pool_full_name, lv_full_name, cache_options):
|
|||||||
return call(cmd)
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def lv_writecache_lv(cache_lv_full_name, lv_full_name, cache_options):
|
||||||
|
# lvconvert --type writecache --cachevol VG/CacheLV VG/OriginLV
|
||||||
|
cmd = ['lvconvert']
|
||||||
|
cmd.extend(options_to_cli_args(cache_options))
|
||||||
|
cmd.extend(['-y', '--type', 'writecache', '--cachevol',
|
||||||
|
cache_lv_full_name, lv_full_name])
|
||||||
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
def lv_detach_cache(lv_full_name, detach_options, destroy_cache):
|
def lv_detach_cache(lv_full_name, detach_options, destroy_cache):
|
||||||
cmd = ['lvconvert']
|
cmd = ['lvconvert']
|
||||||
if destroy_cache:
|
if destroy_cache:
|
||||||
@@ -447,6 +477,28 @@ def lv_detach_cache(lv_full_name, detach_options, destroy_cache):
|
|||||||
return call(cmd)
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def lv_vdo_compression(lv_path, enable, comp_options):
|
||||||
|
cmd = ['lvchange', '--compression']
|
||||||
|
if enable:
|
||||||
|
cmd.append('y')
|
||||||
|
else:
|
||||||
|
cmd.append('n')
|
||||||
|
cmd.extend(options_to_cli_args(comp_options))
|
||||||
|
cmd.append(lv_path)
|
||||||
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def lv_vdo_deduplication(lv_path, enable, dedup_options):
|
||||||
|
cmd = ['lvchange', '--deduplication']
|
||||||
|
if enable:
|
||||||
|
cmd.append('y')
|
||||||
|
else:
|
||||||
|
cmd.append('n')
|
||||||
|
cmd.extend(options_to_cli_args(dedup_options))
|
||||||
|
cmd.append(lv_path)
|
||||||
|
return call(cmd)
|
||||||
|
|
||||||
|
|
||||||
def supports_json():
|
def supports_json():
|
||||||
cmd = ['help']
|
cmd = ['help']
|
||||||
rc, out, err = call(cmd)
|
rc, out, err = call(cmd)
|
||||||
@@ -459,6 +511,16 @@ def supports_json():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def supports_vdo():
|
||||||
|
cmd = ['segtypes']
|
||||||
|
rc, out, err = call(cmd)
|
||||||
|
if rc == 0:
|
||||||
|
if "vdo" in out:
|
||||||
|
log_debug("We have VDO support")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def lvm_full_report_json():
|
def lvm_full_report_json():
|
||||||
pv_columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
|
pv_columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
|
||||||
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
|
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
|
||||||
@@ -486,6 +548,22 @@ def lvm_full_report_json():
|
|||||||
|
|
||||||
lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid']
|
lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid']
|
||||||
|
|
||||||
|
if cfg.vdo_support:
|
||||||
|
lv_columns.extend(
|
||||||
|
['vdo_operating_mode', 'vdo_compression_state', 'vdo_index_state',
|
||||||
|
'vdo_used_size', 'vdo_saving_percent']
|
||||||
|
)
|
||||||
|
|
||||||
|
lv_seg_columns.extend(
|
||||||
|
['vdo_compression', 'vdo_deduplication',
|
||||||
|
'vdo_use_metadata_hints', 'vdo_minimum_io_size',
|
||||||
|
'vdo_block_map_cache_size', 'vdo_block_map_era_length',
|
||||||
|
'vdo_use_sparse_index', 'vdo_index_memory_size',
|
||||||
|
'vdo_slab_size', 'vdo_ack_threads', 'vdo_bio_threads',
|
||||||
|
'vdo_bio_rotation', 'vdo_cpu_threads', 'vdo_hash_zone_threads',
|
||||||
|
'vdo_logical_threads', 'vdo_physical_threads',
|
||||||
|
'vdo_max_discard', 'vdo_write_policy', 'vdo_header_size'])
|
||||||
|
|
||||||
cmd = _dc('fullreport', [
|
cmd = _dc('fullreport', [
|
||||||
'-a', # Need hidden too
|
'-a', # Need hidden too
|
||||||
'--configreport', 'pv', '-o', ','.join(pv_columns),
|
'--configreport', 'pv', '-o', ','.join(pv_columns),
|
||||||
@@ -497,7 +575,8 @@ def lvm_full_report_json():
|
|||||||
])
|
])
|
||||||
|
|
||||||
rc, out, err = call(cmd)
|
rc, out, err = call(cmd)
|
||||||
if rc == 0:
|
# When we have an exported vg the exit code of lvs or fullreport will be 5
|
||||||
|
if rc == 0 or rc == 5:
|
||||||
# With the current implementation, if we are using the shell then we
|
# With the current implementation, if we are using the shell then we
|
||||||
# are using JSON and JSON is returned back to us as it was parsed to
|
# are using JSON and JSON is returned back to us as it was parsed to
|
||||||
# figure out if we completed OK or not
|
# figure out if we completed OK or not
|
||||||
@@ -555,7 +634,7 @@ def pv_resize(device, size_bytes, create_options):
|
|||||||
cmd.extend(options_to_cli_args(create_options))
|
cmd.extend(options_to_cli_args(create_options))
|
||||||
|
|
||||||
if size_bytes != 0:
|
if size_bytes != 0:
|
||||||
cmd.extend(['--yes', '--setphysicalvolumesize', str(size_bytes) + 'B'])
|
cmd.extend(['--yes', '--setphysicalvolumesize', '%dB' % size_bytes])
|
||||||
|
|
||||||
cmd.extend([device])
|
cmd.extend([device])
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
@@ -651,12 +730,12 @@ def vg_allocation_policy(vg_name, policy, policy_options):
|
|||||||
|
|
||||||
|
|
||||||
def vg_max_pv(vg_name, number, max_options):
|
def vg_max_pv(vg_name, number, max_options):
|
||||||
return _vg_value_set(vg_name, ['--maxphysicalvolumes', str(number)],
|
return _vg_value_set(vg_name, ['--maxphysicalvolumes', str(int(number))],
|
||||||
max_options)
|
max_options)
|
||||||
|
|
||||||
|
|
||||||
def vg_max_lv(vg_name, number, max_options):
|
def vg_max_lv(vg_name, number, max_options):
|
||||||
return _vg_value_set(vg_name, ['-l', str(number)], max_options)
|
return _vg_value_set(vg_name, ['-l', str(int(number))], max_options)
|
||||||
|
|
||||||
|
|
||||||
def vg_uuid_gen(vg_name, ignore, options):
|
def vg_uuid_gen(vg_name, ignore, options):
|
||||||
@@ -698,6 +777,7 @@ def activate_deactivate(op, name, activate, control_flags, options):
|
|||||||
op += 'n'
|
op += 'n'
|
||||||
|
|
||||||
cmd.append(op)
|
cmd.append(op)
|
||||||
|
cmd.append("-y")
|
||||||
cmd.append(name)
|
cmd.append(name)
|
||||||
return call(cmd)
|
return call(cmd)
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ from . import cfg
|
|||||||
from .utils import MThreadRunner, log_debug, log_error
|
from .utils import MThreadRunner, log_debug, log_error
|
||||||
import threading
|
import threading
|
||||||
import queue
|
import queue
|
||||||
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
@@ -28,11 +29,26 @@ def _main_thread_load(refresh=True, emit_signal=True):
|
|||||||
refresh=refresh,
|
refresh=refresh,
|
||||||
emit_signal=emit_signal,
|
emit_signal=emit_signal,
|
||||||
cache_refresh=False)[1]
|
cache_refresh=False)[1]
|
||||||
num_total_changes += load_lvs(
|
|
||||||
|
lv_changes = load_lvs(
|
||||||
refresh=refresh,
|
refresh=refresh,
|
||||||
emit_signal=emit_signal,
|
emit_signal=emit_signal,
|
||||||
cache_refresh=False)[1]
|
cache_refresh=False)[1]
|
||||||
|
|
||||||
|
num_total_changes += lv_changes
|
||||||
|
|
||||||
|
# When the LVs change it can cause another change in the VGs which is
|
||||||
|
# missed if we don't scan through the VGs again. We could achieve this
|
||||||
|
# the other way and re-scan the LVs, but in general there are more LVs than
|
||||||
|
# VGs, thus this should be more efficient. This happens when a LV interface
|
||||||
|
# changes causing the dbus object representing it to be removed and
|
||||||
|
# recreated.
|
||||||
|
if refresh and lv_changes > 0:
|
||||||
|
num_total_changes += load_vgs(
|
||||||
|
refresh=refresh,
|
||||||
|
emit_signal=emit_signal,
|
||||||
|
cache_refresh=False)[1]
|
||||||
|
|
||||||
return num_total_changes
|
return num_total_changes
|
||||||
|
|
||||||
|
|
||||||
@@ -82,6 +98,8 @@ class StateUpdate(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_thread(obj):
|
def update_thread(obj):
|
||||||
|
exception_count = 0
|
||||||
|
|
||||||
queued_requests = []
|
queued_requests = []
|
||||||
while cfg.run.value != 0:
|
while cfg.run.value != 0:
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
@@ -136,12 +154,26 @@ class StateUpdate(object):
|
|||||||
# wake up if we get an exception
|
# wake up if we get an exception
|
||||||
queued_requests = []
|
queued_requests = []
|
||||||
|
|
||||||
|
# We retrieved OK, clear exception count
|
||||||
|
exception_count = 0
|
||||||
|
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
except Exception:
|
except Exception as e:
|
||||||
st = traceback.format_exc()
|
st = traceback.format_exc()
|
||||||
log_error("update_thread exception: \n%s" % st)
|
log_error("update_thread exception: \n%s" % st)
|
||||||
cfg.blackbox.dump()
|
cfg.blackbox.dump()
|
||||||
|
exception_count += 1
|
||||||
|
if exception_count >= 5:
|
||||||
|
for i in queued_requests:
|
||||||
|
i.set_result(e)
|
||||||
|
|
||||||
|
log_error("Too many errors in update_thread, exiting daemon")
|
||||||
|
cfg.exit_daemon()
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Slow things down when encountering errors
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.lock = threading.RLock()
|
self.lock = threading.RLock()
|
||||||
|
|||||||
@@ -10,20 +10,22 @@
|
|||||||
from .automatedproperties import AutomatedProperties
|
from .automatedproperties import AutomatedProperties
|
||||||
|
|
||||||
from . import utils
|
from . import utils
|
||||||
from .utils import vg_obj_path_generate
|
from .utils import vg_obj_path_generate, log_error, _handle_execute
|
||||||
import dbus
|
import dbus
|
||||||
from . import cmdhandler
|
from . import cmdhandler
|
||||||
from . import cfg
|
from . import cfg
|
||||||
from .cfg import LV_INTERFACE, THIN_POOL_INTERFACE, SNAPSHOT_INTERFACE, \
|
from .cfg import LV_INTERFACE, THIN_POOL_INTERFACE, SNAPSHOT_INTERFACE, \
|
||||||
LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED
|
LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED, VDO_POOL_INTERFACE
|
||||||
from .request import RequestEntry
|
from .request import RequestEntry
|
||||||
from .utils import n, n32
|
from .utils import n, n32, d
|
||||||
from .loader import common
|
from .loader import common
|
||||||
from .state import State
|
from .state import State
|
||||||
from . import background
|
from . import background
|
||||||
from .utils import round_size, mt_remove_dbus_objects
|
from .utils import round_size, mt_remove_dbus_objects
|
||||||
from .job import JobState
|
from .job import JobState
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
# Try and build a key for a LV, so that we sort the LVs with least dependencies
|
# Try and build a key for a LV, so that we sort the LVs with least dependencies
|
||||||
# first. This may be error prone because of the flexibility LVM
|
# first. This may be error prone because of the flexibility LVM
|
||||||
@@ -72,23 +74,66 @@ def lvs_state_retrieve(selection, cache_refresh=True):
|
|||||||
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
|
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
|
||||||
|
|
||||||
for l in lvs:
|
for l in lvs:
|
||||||
rc.append(LvState(
|
if cfg.vdo_support:
|
||||||
l['lv_uuid'], l['lv_name'],
|
rc.append(LvStateVdo(
|
||||||
l['lv_path'], n(l['lv_size']),
|
l['lv_uuid'], l['lv_name'],
|
||||||
l['vg_name'],
|
l['lv_path'], n(l['lv_size']),
|
||||||
l['vg_uuid'], l['pool_lv_uuid'],
|
l['vg_name'],
|
||||||
l['pool_lv'], l['origin_uuid'], l['origin'],
|
l['vg_uuid'], l['pool_lv_uuid'],
|
||||||
n32(l['data_percent']), l['lv_attr'],
|
l['pool_lv'], l['origin_uuid'], l['origin'],
|
||||||
l['lv_tags'], l['lv_active'], l['data_lv'],
|
n32(l['data_percent']), l['lv_attr'],
|
||||||
l['metadata_lv'], l['segtype'], l['lv_role'],
|
l['lv_tags'], l['lv_active'], l['data_lv'],
|
||||||
l['lv_layout'],
|
l['metadata_lv'], l['segtype'], l['lv_role'],
|
||||||
n32(l['snap_percent']),
|
l['lv_layout'],
|
||||||
n32(l['metadata_percent']),
|
n32(l['snap_percent']),
|
||||||
n32(l['copy_percent']),
|
n32(l['metadata_percent']),
|
||||||
n32(l['sync_percent']),
|
n32(l['copy_percent']),
|
||||||
n(l['lv_metadata_size']),
|
n32(l['sync_percent']),
|
||||||
l['move_pv'],
|
n(l['lv_metadata_size']),
|
||||||
l['move_pv_uuid']))
|
l['move_pv'],
|
||||||
|
l['move_pv_uuid'],
|
||||||
|
l['vdo_operating_mode'],
|
||||||
|
l['vdo_compression_state'],
|
||||||
|
l['vdo_index_state'],
|
||||||
|
n(l['vdo_used_size']),
|
||||||
|
d(l['vdo_saving_percent']),
|
||||||
|
l['vdo_compression'],
|
||||||
|
l['vdo_deduplication'],
|
||||||
|
l['vdo_use_metadata_hints'],
|
||||||
|
n32(l['vdo_minimum_io_size']),
|
||||||
|
n(l['vdo_block_map_cache_size']),
|
||||||
|
n32(l['vdo_block_map_era_length']),
|
||||||
|
l['vdo_use_sparse_index'],
|
||||||
|
n(l['vdo_index_memory_size']),
|
||||||
|
n(l['vdo_slab_size']),
|
||||||
|
n32(l['vdo_ack_threads']),
|
||||||
|
n32(l['vdo_bio_threads']),
|
||||||
|
n32(l['vdo_bio_rotation']),
|
||||||
|
n32(l['vdo_cpu_threads']),
|
||||||
|
n32(l['vdo_hash_zone_threads']),
|
||||||
|
n32(l['vdo_logical_threads']),
|
||||||
|
n32(l['vdo_physical_threads']),
|
||||||
|
n32(l['vdo_max_discard']),
|
||||||
|
l['vdo_write_policy'],
|
||||||
|
n32(l['vdo_header_size'])))
|
||||||
|
else:
|
||||||
|
rc.append(LvState(
|
||||||
|
l['lv_uuid'], l['lv_name'],
|
||||||
|
l['lv_path'], n(l['lv_size']),
|
||||||
|
l['vg_name'],
|
||||||
|
l['vg_uuid'], l['pool_lv_uuid'],
|
||||||
|
l['pool_lv'], l['origin_uuid'], l['origin'],
|
||||||
|
n32(l['data_percent']), l['lv_attr'],
|
||||||
|
l['lv_tags'], l['lv_active'], l['data_lv'],
|
||||||
|
l['metadata_lv'], l['segtype'], l['lv_role'],
|
||||||
|
l['lv_layout'],
|
||||||
|
n32(l['snap_percent']),
|
||||||
|
n32(l['metadata_percent']),
|
||||||
|
n32(l['copy_percent']),
|
||||||
|
n32(l['sync_percent']),
|
||||||
|
n(l['lv_metadata_size']),
|
||||||
|
l['move_pv'],
|
||||||
|
l['move_pv_uuid']))
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
|
|
||||||
@@ -192,6 +237,8 @@ class LvState(State):
|
|||||||
def _object_type_create(self):
|
def _object_type_create(self):
|
||||||
if self.Attr[0] == 't':
|
if self.Attr[0] == 't':
|
||||||
return LvThinPool
|
return LvThinPool
|
||||||
|
elif self.Attr[0] == 'd':
|
||||||
|
return LvVdoPool
|
||||||
elif self.Attr[0] == 'C':
|
elif self.Attr[0] == 'C':
|
||||||
if 'pool' in self.layout:
|
if 'pool' in self.layout:
|
||||||
return LvCachePool
|
return LvCachePool
|
||||||
@@ -218,6 +265,34 @@ class LvState(State):
|
|||||||
return (klass, path_method)
|
return (klass, path_method)
|
||||||
|
|
||||||
|
|
||||||
|
class LvStateVdo(LvState):
|
||||||
|
|
||||||
|
def __init__(self, Uuid, Name, Path, SizeBytes,
|
||||||
|
vg_name, vg_uuid, pool_lv_uuid, PoolLv,
|
||||||
|
origin_uuid, OriginLv, DataPercent, Attr, Tags, active,
|
||||||
|
data_lv, metadata_lv, segtypes, role, layout, SnapPercent,
|
||||||
|
MetaDataPercent, CopyPercent, SyncPercent,
|
||||||
|
MetaDataSizeBytes, move_pv, move_pv_uuid,
|
||||||
|
vdo_operating_mode, vdo_compression_state, vdo_index_state,
|
||||||
|
vdo_used_size,vdo_saving_percent,vdo_compression,
|
||||||
|
vdo_deduplication,vdo_use_metadata_hints,
|
||||||
|
vdo_minimum_io_size,vdo_block_map_cache_size,
|
||||||
|
vdo_block_map_era_length,vdo_use_sparse_index,
|
||||||
|
vdo_index_memory_size,vdo_slab_size,vdo_ack_threads,
|
||||||
|
vdo_bio_threads,vdo_bio_rotation,vdo_cpu_threads,
|
||||||
|
vdo_hash_zone_threads,vdo_logical_threads,
|
||||||
|
vdo_physical_threads,vdo_max_discard,
|
||||||
|
vdo_write_policy,vdo_header_size):
|
||||||
|
super(LvStateVdo, self).__init__(Uuid, Name, Path, SizeBytes,
|
||||||
|
vg_name, vg_uuid, pool_lv_uuid, PoolLv,
|
||||||
|
origin_uuid, OriginLv, DataPercent, Attr, Tags, active,
|
||||||
|
data_lv, metadata_lv, segtypes, role, layout, SnapPercent,
|
||||||
|
MetaDataPercent, CopyPercent, SyncPercent,
|
||||||
|
MetaDataSizeBytes, move_pv, move_pv_uuid)
|
||||||
|
|
||||||
|
utils.init_class_from_arguments(self, "vdo_", snake_to_pascal=True)
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Uuid', 's')
|
@utils.dbus_property(LV_COMMON_INTERFACE, 'Uuid', 's')
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's')
|
@utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's')
|
||||||
@@ -273,13 +348,7 @@ class LvCommon(AutomatedProperties):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_execute(rc, out, err):
|
def handle_execute(rc, out, err):
|
||||||
if rc == 0:
|
_handle_execute(rc, out, err, LV_INTERFACE)
|
||||||
cfg.load()
|
|
||||||
else:
|
|
||||||
# Need to work on error handling, need consistent
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_dbus_object(lv_uuid, lv_name):
|
def validate_dbus_object(lv_uuid, lv_name):
|
||||||
@@ -291,6 +360,22 @@ class LvCommon(AutomatedProperties):
|
|||||||
(lv_uuid, lv_name))
|
(lv_uuid, lv_name))
|
||||||
return dbo
|
return dbo
|
||||||
|
|
||||||
|
def attr_struct(self, index, type_map, default='undisclosed'):
|
||||||
|
try:
|
||||||
|
if self.state.Attr[index] not in type_map:
|
||||||
|
log_error("LV %s %s with lv_attr %s, lv_attr[%d] = "
|
||||||
|
"'%s' is not known" %
|
||||||
|
(self.Uuid, self.Name, self.Attr, index,
|
||||||
|
self.state.Attr[index]))
|
||||||
|
|
||||||
|
return dbus.Struct((self.state.Attr[index],
|
||||||
|
type_map.get(self.state.Attr[index], default)),
|
||||||
|
signature="(ss)")
|
||||||
|
except BaseException:
|
||||||
|
st = traceback.format_exc()
|
||||||
|
log_error("attr_struct: \n%s" % st)
|
||||||
|
return dbus.Struct(('?', 'Unavailable'), signature="(ss)")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def VolumeType(self):
|
def VolumeType(self):
|
||||||
type_map = {'C': 'Cache', 'm': 'mirrored',
|
type_map = {'C': 'Cache', 'm': 'mirrored',
|
||||||
@@ -303,17 +388,16 @@ class LvCommon(AutomatedProperties):
|
|||||||
'l': 'mirror log device', 'c': 'under conversion',
|
'l': 'mirror log device', 'c': 'under conversion',
|
||||||
'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
|
'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
|
||||||
'e': 'raid or pool metadata or pool metadata spare',
|
'e': 'raid or pool metadata or pool metadata spare',
|
||||||
|
'd': 'vdo pool', 'D': 'vdo pool data', 'g': 'integrity',
|
||||||
'-': 'Unspecified'}
|
'-': 'Unspecified'}
|
||||||
return dbus.Struct((self.state.Attr[0], type_map[self.state.Attr[0]]),
|
return self.attr_struct(0, type_map)
|
||||||
signature="as")
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def Permissions(self):
|
def Permissions(self):
|
||||||
type_map = {'w': 'writable', 'r': 'read-only',
|
type_map = {'w': 'writable', 'r': 'read-only',
|
||||||
'R': 'Read-only activation of non-read-only volume',
|
'R': 'Read-only activation of non-read-only volume',
|
||||||
'-': 'Unspecified'}
|
'-': 'Unspecified'}
|
||||||
return dbus.Struct((self.state.Attr[1], type_map[self.state.Attr[1]]),
|
return self.attr_struct(1, type_map)
|
||||||
signature="(ss)")
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def AllocationPolicy(self):
|
def AllocationPolicy(self):
|
||||||
@@ -322,8 +406,7 @@ class LvCommon(AutomatedProperties):
|
|||||||
'i': 'inherited', 'I': 'inherited locked',
|
'i': 'inherited', 'I': 'inherited locked',
|
||||||
'l': 'cling', 'L': 'cling locked',
|
'l': 'cling', 'L': 'cling locked',
|
||||||
'n': 'normal', 'N': 'normal locked', '-': 'Unspecified'}
|
'n': 'normal', 'N': 'normal locked', '-': 'Unspecified'}
|
||||||
return dbus.Struct((self.state.Attr[2], type_map[self.state.Attr[2]]),
|
return self.attr_struct(2, type_map)
|
||||||
signature="(ss)")
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def FixedMinor(self):
|
def FixedMinor(self):
|
||||||
@@ -331,15 +414,20 @@ class LvCommon(AutomatedProperties):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def State(self):
|
def State(self):
|
||||||
type_map = {'a': 'active', 's': 'suspended', 'I': 'Invalid snapshot',
|
type_map = {'a': 'active',
|
||||||
|
's': 'suspended',
|
||||||
|
'I': 'Invalid snapshot',
|
||||||
'S': 'invalid Suspended snapshot',
|
'S': 'invalid Suspended snapshot',
|
||||||
'm': 'snapshot merge failed',
|
'm': 'snapshot merge failed',
|
||||||
'M': 'suspended snapshot (M)erge failed',
|
'M': 'suspended snapshot (M)erge failed',
|
||||||
'd': 'mapped device present without tables',
|
'd': 'mapped device present without tables',
|
||||||
'i': 'mapped device present with inactive table',
|
'i': 'mapped device present with inactive table',
|
||||||
'X': 'unknown', '-': 'Unspecified'}
|
'h': 'historical',
|
||||||
return dbus.Struct((self.state.Attr[4], type_map[self.state.Attr[4]]),
|
'c': 'check needed suspended thin-pool',
|
||||||
signature="(ss)")
|
'C': 'check needed',
|
||||||
|
'X': 'unknown',
|
||||||
|
'-': 'Unspecified'}
|
||||||
|
return self.attr_struct(4, type_map)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def TargetType(self):
|
def TargetType(self):
|
||||||
@@ -355,11 +443,18 @@ class LvCommon(AutomatedProperties):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def Health(self):
|
def Health(self):
|
||||||
type_map = {'p': 'partial', 'r': 'refresh',
|
type_map = {'p': 'partial',
|
||||||
'm': 'mismatches', 'w': 'writemostly',
|
'r': 'refresh needed',
|
||||||
'X': 'X unknown', '-': 'Unspecified'}
|
'm': 'mismatches',
|
||||||
return dbus.Struct((self.state.Attr[8], type_map[self.state.Attr[8]]),
|
'w': 'writemostly',
|
||||||
signature="(ss)")
|
'X': 'unknown',
|
||||||
|
'-': 'unspecified',
|
||||||
|
's': 'reshaping',
|
||||||
|
'F': 'failed',
|
||||||
|
'D': 'Data space',
|
||||||
|
'R': 'Remove',
|
||||||
|
'M': 'Metadata'}
|
||||||
|
return self.attr_struct(8, type_map)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def SkipActivation(self):
|
def SkipActivation(self):
|
||||||
@@ -429,8 +524,7 @@ class Lv(LvCommon):
|
|||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
||||||
# Remove the LV, if successful then remove from the model
|
# Remove the LV, if successful then remove from the model
|
||||||
rc, out, err = cmdhandler.lv_remove(lv_name, remove_options)
|
LvCommon.handle_execute(*cmdhandler.lv_remove(lv_name, remove_options))
|
||||||
LvCommon.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -450,9 +544,8 @@ class Lv(LvCommon):
|
|||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
||||||
# Rename the logical volume
|
# Rename the logical volume
|
||||||
rc, out, err = cmdhandler.lv_rename(lv_name, new_name,
|
LvCommon.handle_execute(*cmdhandler.lv_rename(lv_name, new_name,
|
||||||
rename_options)
|
rename_options))
|
||||||
LvCommon.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -501,13 +594,11 @@ class Lv(LvCommon):
|
|||||||
remainder = space % 512
|
remainder = space % 512
|
||||||
optional_size = space + 512 - remainder
|
optional_size = space + 512 - remainder
|
||||||
|
|
||||||
rc, out, err = cmdhandler.vg_lv_snapshot(
|
LvCommon.handle_execute(*cmdhandler.vg_lv_snapshot(
|
||||||
lv_name, snapshot_options, name, optional_size)
|
lv_name, snapshot_options,name, optional_size))
|
||||||
LvCommon.handle_execute(rc, out, err)
|
|
||||||
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
|
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
|
||||||
return cfg.om.get_object_path_by_lvm_id(full_name)
|
return cfg.om.get_object_path_by_lvm_id(full_name)
|
||||||
|
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
dbus_interface=LV_INTERFACE,
|
dbus_interface=LV_INTERFACE,
|
||||||
in_signature='stia{sv}',
|
in_signature='stia{sv}',
|
||||||
@@ -543,9 +634,8 @@ class Lv(LvCommon):
|
|||||||
pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
|
pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
|
||||||
|
|
||||||
size_change = new_size_bytes - dbo.SizeBytes
|
size_change = new_size_bytes - dbo.SizeBytes
|
||||||
rc, out, err = cmdhandler.lv_resize(dbo.lvm_id, size_change,
|
LvCommon.handle_execute(*cmdhandler.lv_resize(
|
||||||
pv_dests, resize_options)
|
dbo.lvm_id, size_change,pv_dests, resize_options))
|
||||||
LvCommon.handle_execute(rc, out, err)
|
|
||||||
return "/"
|
return "/"
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -580,9 +670,8 @@ class Lv(LvCommon):
|
|||||||
options):
|
options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
LvCommon.validate_dbus_object(uuid, lv_name)
|
LvCommon.validate_dbus_object(uuid, lv_name)
|
||||||
rc, out, err = cmdhandler.activate_deactivate(
|
LvCommon.handle_execute(*cmdhandler.activate_deactivate(
|
||||||
'lvchange', lv_name, activate, control_flags, options)
|
'lvchange', lv_name, activate, control_flags, options))
|
||||||
LvCommon.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -616,9 +705,8 @@ class Lv(LvCommon):
|
|||||||
def _add_rm_tags(uuid, lv_name, tags_add, tags_del, tag_options):
|
def _add_rm_tags(uuid, lv_name, tags_add, tags_del, tag_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
LvCommon.validate_dbus_object(uuid, lv_name)
|
LvCommon.validate_dbus_object(uuid, lv_name)
|
||||||
rc, out, err = cmdhandler.lv_tag(
|
LvCommon.handle_execute(*cmdhandler.lv_tag(
|
||||||
lv_name, tags_add, tags_del, tag_options)
|
lv_name, tags_add, tags_del, tag_options))
|
||||||
LvCommon.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -655,6 +743,152 @@ class Lv(LvCommon):
|
|||||||
cb, cbe, return_tuple=False)
|
cb, cbe, return_tuple=False)
|
||||||
cfg.worker_q.put(r)
|
cfg.worker_q.put(r)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _writecache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
|
||||||
|
# Make sure we have a dbus object representing it
|
||||||
|
dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
||||||
|
|
||||||
|
# Make sure we have dbus object representing lv to cache
|
||||||
|
lv_to_cache = cfg.om.get_object_by_path(lv_object_path)
|
||||||
|
|
||||||
|
if lv_to_cache:
|
||||||
|
fcn = lv_to_cache.lv_full_name()
|
||||||
|
rc, out, err = cmdhandler.lv_writecache_lv(
|
||||||
|
dbo.lv_full_name(), fcn, cache_options)
|
||||||
|
if rc == 0:
|
||||||
|
# When we cache an LV, the cache pool and the lv that is getting
|
||||||
|
# cached need to be removed from the object manager and
|
||||||
|
# re-created as their interfaces have changed!
|
||||||
|
mt_remove_dbus_objects((dbo, lv_to_cache))
|
||||||
|
cfg.load()
|
||||||
|
|
||||||
|
lv_converted = cfg.om.get_object_path_by_lvm_id(fcn)
|
||||||
|
else:
|
||||||
|
raise dbus.exceptions.DBusException(
|
||||||
|
LV_INTERFACE,
|
||||||
|
'Exit code %s, stderr = %s' % (str(rc), err))
|
||||||
|
else:
|
||||||
|
raise dbus.exceptions.DBusException(
|
||||||
|
LV_INTERFACE, 'LV to cache with object path %s not present!' %
|
||||||
|
lv_object_path)
|
||||||
|
return lv_converted
|
||||||
|
|
||||||
|
@dbus.service.method(
|
||||||
|
dbus_interface=LV_INTERFACE,
|
||||||
|
in_signature='oia{sv}',
|
||||||
|
out_signature='(oo)',
|
||||||
|
async_callbacks=('cb', 'cbe'))
|
||||||
|
def WriteCacheLv(self, lv_object, tmo, cache_options, cb, cbe):
|
||||||
|
r = RequestEntry(
|
||||||
|
tmo, Lv._writecache_lv,
|
||||||
|
(self.Uuid, self.lvm_id, lv_object,
|
||||||
|
cache_options), cb, cbe)
|
||||||
|
cfg.worker_q.put(r)
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyPep8Naming
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'OperatingMode', 's')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'CompressionState', 's')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'IndexState', 's')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'UsedSize', 't')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'SavingPercent', 'd')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'Compression', 's')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'Deduplication', 's')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'UseMetadataHints', 's')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'MinimumIoSize', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'BlockMapCacheSize', "t")
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'BlockMapEraLength', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'UseSparseIndex', 's')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'IndexMemorySize', 't')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'SlabSize', 't')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'AckThreads', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'BioThreads', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'BioRotation', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'CpuThreads', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'HashZoneThreads', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'LogicalThreads', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'PhysicalThreads', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'MaxDiscard', 'u')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'WritePolicy', 's')
|
||||||
|
@utils.dbus_property(VDO_POOL_INTERFACE, 'HeaderSize', 'u')
|
||||||
|
class LvVdoPool(Lv):
|
||||||
|
_DataLv_meta = ("o", VDO_POOL_INTERFACE)
|
||||||
|
|
||||||
|
def __init__(self, object_path, object_state):
|
||||||
|
super(LvVdoPool, self).__init__(object_path, object_state)
|
||||||
|
self.set_interface(VDO_POOL_INTERFACE)
|
||||||
|
self._data_lv, _ = self._get_data_meta()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def DataLv(self):
|
||||||
|
return dbus.ObjectPath(self._data_lv)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _enable_disable_compression(pool_uuid, pool_name, enable, comp_options):
|
||||||
|
# Make sure we have a dbus object representing it
|
||||||
|
LvCommon.validate_dbus_object(pool_uuid, pool_name)
|
||||||
|
# Rename the logical volume
|
||||||
|
LvCommon.handle_execute(*cmdhandler.lv_vdo_compression(
|
||||||
|
pool_name, enable, comp_options))
|
||||||
|
return '/'
|
||||||
|
|
||||||
|
@dbus.service.method(
|
||||||
|
dbus_interface=VDO_POOL_INTERFACE,
|
||||||
|
in_signature='ia{sv}',
|
||||||
|
out_signature='o',
|
||||||
|
async_callbacks=('cb', 'cbe'))
|
||||||
|
def EnableCompression(self, tmo, comp_options, cb, cbe):
|
||||||
|
r = RequestEntry(
|
||||||
|
tmo, LvVdoPool._enable_disable_compression,
|
||||||
|
(self.Uuid, self.lvm_id, True, comp_options),
|
||||||
|
cb, cbe, False)
|
||||||
|
cfg.worker_q.put(r)
|
||||||
|
|
||||||
|
@dbus.service.method(
|
||||||
|
dbus_interface=VDO_POOL_INTERFACE,
|
||||||
|
in_signature='ia{sv}',
|
||||||
|
out_signature='o',
|
||||||
|
async_callbacks=('cb', 'cbe'))
|
||||||
|
def DisableCompression(self, tmo, comp_options, cb, cbe):
|
||||||
|
r = RequestEntry(
|
||||||
|
tmo, LvVdoPool._enable_disable_compression,
|
||||||
|
(self.Uuid, self.lvm_id, False, comp_options),
|
||||||
|
cb, cbe, False)
|
||||||
|
cfg.worker_q.put(r)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _enable_disable_deduplication(pool_uuid, pool_name, enable, dedup_options):
|
||||||
|
# Make sure we have a dbus object representing it
|
||||||
|
LvCommon.validate_dbus_object(pool_uuid, pool_name)
|
||||||
|
# Rename the logical volume
|
||||||
|
LvCommon.handle_execute(*cmdhandler.lv_vdo_deduplication(
|
||||||
|
pool_name, enable, dedup_options))
|
||||||
|
return '/'
|
||||||
|
|
||||||
|
@dbus.service.method(
|
||||||
|
dbus_interface=VDO_POOL_INTERFACE,
|
||||||
|
in_signature='ia{sv}',
|
||||||
|
out_signature='o',
|
||||||
|
async_callbacks=('cb', 'cbe'))
|
||||||
|
def EnableDeduplication(self, tmo, dedup_options, cb, cbe):
|
||||||
|
r = RequestEntry(
|
||||||
|
tmo, LvVdoPool._enable_disable_deduplication,
|
||||||
|
(self.Uuid, self.lvm_id, True, dedup_options),
|
||||||
|
cb, cbe, False)
|
||||||
|
cfg.worker_q.put(r)
|
||||||
|
|
||||||
|
@dbus.service.method(
|
||||||
|
dbus_interface=VDO_POOL_INTERFACE,
|
||||||
|
in_signature='ia{sv}',
|
||||||
|
out_signature='o',
|
||||||
|
async_callbacks=('cb', 'cbe'))
|
||||||
|
def DisableDeduplication(self, tmo, dedup_options, cb, cbe):
|
||||||
|
r = RequestEntry(
|
||||||
|
tmo, LvVdoPool._enable_disable_deduplication,
|
||||||
|
(self.Uuid, self.lvm_id, False, dedup_options),
|
||||||
|
cb, cbe, False)
|
||||||
|
cfg.worker_q.put(r)
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
class LvThinPool(Lv):
|
class LvThinPool(Lv):
|
||||||
@@ -678,10 +912,8 @@ class LvThinPool(Lv):
|
|||||||
def _lv_create(lv_uuid, lv_name, name, size_bytes, create_options):
|
def _lv_create(lv_uuid, lv_name, name, size_bytes, create_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
||||||
|
LvCommon.handle_execute(*cmdhandler.lv_lv_create(
|
||||||
rc, out, err = cmdhandler.lv_lv_create(
|
lv_name, create_options, name, size_bytes))
|
||||||
lv_name, create_options, name, size_bytes)
|
|
||||||
LvCommon.handle_execute(rc, out, err)
|
|
||||||
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
|
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
|
||||||
return cfg.om.get_object_path_by_lvm_id(full_name)
|
return cfg.om.get_object_path_by_lvm_id(full_name)
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,10 @@ class LVMShellProxy(object):
|
|||||||
|
|
||||||
# Parse the report to see what happened
|
# Parse the report to see what happened
|
||||||
if 'log' in report_json:
|
if 'log' in report_json:
|
||||||
if report_json['log'][-1:][0]['log_ret_code'] == '1':
|
ret_code = int(report_json['log'][-1:][0]['log_ret_code'])
|
||||||
|
# If we have an exported vg we get a log_ret_code == 5 when
|
||||||
|
# we do a 'fullreport'
|
||||||
|
if (ret_code == 1) or (ret_code == 5 and argv[0] == 'fullreport'):
|
||||||
rc = 0
|
rc = 0
|
||||||
else:
|
else:
|
||||||
error_msg = self.get_error_msg()
|
error_msg = self.get_error_msg()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from lvmdbusd.utils import log_debug, log_error
|
|||||||
|
|
||||||
|
|
||||||
class DataStore(object):
|
class DataStore(object):
|
||||||
def __init__(self, usejson=True):
|
def __init__(self, usejson=True, vdo_support=False):
|
||||||
self.pvs = {}
|
self.pvs = {}
|
||||||
self.vgs = {}
|
self.vgs = {}
|
||||||
self.lvs = {}
|
self.lvs = {}
|
||||||
@@ -43,6 +43,8 @@ class DataStore(object):
|
|||||||
else:
|
else:
|
||||||
self.json = usejson
|
self.json = usejson
|
||||||
|
|
||||||
|
self.vdo_support = vdo_support
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _insert_record(table, key, record, allowed_multiple):
|
def _insert_record(table, key, record, allowed_multiple):
|
||||||
if key in table:
|
if key in table:
|
||||||
@@ -141,13 +143,22 @@ class DataStore(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_vgs(_vgs):
|
def _parse_vgs(_vgs):
|
||||||
vgs = sorted(_vgs, key=lambda vk: vk['vg_name'])
|
vgs = sorted(_vgs, key=lambda vk: vk['vg_uuid'])
|
||||||
|
|
||||||
c_vgs = OrderedDict()
|
c_vgs = OrderedDict()
|
||||||
c_lookup = {}
|
c_lookup = {}
|
||||||
|
|
||||||
for i in vgs:
|
for i in vgs:
|
||||||
c_lookup[i['vg_name']] = i['vg_uuid']
|
vg_name = i['vg_name']
|
||||||
|
|
||||||
|
# Lvm allows duplicate vg names. When this occurs, each subsequent
|
||||||
|
# matching VG name will be called vg_name:vg_uuid. Note: ':' is an
|
||||||
|
# invalid character for lvm VG names
|
||||||
|
if vg_name in c_lookup:
|
||||||
|
vg_name = "%s:%s" % (vg_name, i['vg_uuid'])
|
||||||
|
i['vg_name'] = vg_name
|
||||||
|
|
||||||
|
c_lookup[vg_name] = i['vg_uuid']
|
||||||
DataStore._insert_record(c_vgs, i['vg_uuid'], i, [])
|
DataStore._insert_record(c_vgs, i['vg_uuid'], i, [])
|
||||||
|
|
||||||
return c_vgs, c_lookup
|
return c_vgs, c_lookup
|
||||||
@@ -162,13 +173,22 @@ class DataStore(object):
|
|||||||
tmp_vg.extend(r['vg'])
|
tmp_vg.extend(r['vg'])
|
||||||
|
|
||||||
# Sort for consistent output, however this is optional
|
# Sort for consistent output, however this is optional
|
||||||
vgs = sorted(tmp_vg, key=lambda vk: vk['vg_name'])
|
vgs = sorted(tmp_vg, key=lambda vk: vk['vg_uuid'])
|
||||||
|
|
||||||
c_vgs = OrderedDict()
|
c_vgs = OrderedDict()
|
||||||
c_lookup = {}
|
c_lookup = {}
|
||||||
|
|
||||||
for i in vgs:
|
for i in vgs:
|
||||||
c_lookup[i['vg_name']] = i['vg_uuid']
|
vg_name = i['vg_name']
|
||||||
|
|
||||||
|
# Lvm allows duplicate vg names. When this occurs, each subsequent
|
||||||
|
# matching VG name will be called vg_name:vg_uuid. Note: ':' is an
|
||||||
|
# invalid character for lvm VG names
|
||||||
|
if vg_name in c_lookup:
|
||||||
|
vg_name = "%s:%s" % (vg_name, i['vg_uuid'])
|
||||||
|
i['vg_name'] = vg_name
|
||||||
|
|
||||||
|
c_lookup[vg_name] = i['vg_uuid']
|
||||||
c_vgs[i['vg_uuid']] = i
|
c_vgs[i['vg_uuid']] = i
|
||||||
|
|
||||||
return c_vgs, c_lookup
|
return c_vgs, c_lookup
|
||||||
@@ -223,8 +243,7 @@ class DataStore(object):
|
|||||||
|
|
||||||
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
||||||
|
|
||||||
@staticmethod
|
def _parse_lvs_json(self, _all):
|
||||||
def _parse_lvs_json(_all):
|
|
||||||
|
|
||||||
c_lvs = OrderedDict()
|
c_lvs = OrderedDict()
|
||||||
c_lv_full_lookup = {}
|
c_lv_full_lookup = {}
|
||||||
@@ -244,8 +263,13 @@ class DataStore(object):
|
|||||||
if 'seg' in r:
|
if 'seg' in r:
|
||||||
for s in r['seg']:
|
for s in r['seg']:
|
||||||
r = c_lvs[s['lv_uuid']]
|
r = c_lvs[s['lv_uuid']]
|
||||||
r.setdefault('seg_pe_ranges', []).append(s['seg_pe_ranges'])
|
r.setdefault('seg_pe_ranges', []).\
|
||||||
|
append(s['seg_pe_ranges'])
|
||||||
r.setdefault('segtype', []).append(s['segtype'])
|
r.setdefault('segtype', []).append(s['segtype'])
|
||||||
|
if self.vdo_support:
|
||||||
|
for seg_key, seg_val in s.items():
|
||||||
|
if seg_key.startswith("vdo_"):
|
||||||
|
r[seg_key] = seg_val
|
||||||
|
|
||||||
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
||||||
|
|
||||||
@@ -521,6 +545,10 @@ if __name__ == "__main__":
|
|||||||
for v in ds.vgs.values():
|
for v in ds.vgs.values():
|
||||||
pp.pprint(v)
|
pp.pprint(v)
|
||||||
|
|
||||||
|
print("VG name to UUID")
|
||||||
|
for k, v in ds.vg_name_to_uuid.items():
|
||||||
|
print("%s: %s" % (k, v))
|
||||||
|
|
||||||
print("LVS")
|
print("LVS")
|
||||||
for v in ds.lvs.values():
|
for v in ds.lvs.values():
|
||||||
pp.pprint(v)
|
pp.pprint(v)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ from .utils import log_debug, log_error
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from .cmdhandler import LvmFlightRecorder
|
from .cmdhandler import LvmFlightRecorder, supports_vdo
|
||||||
from .request import RequestEntry
|
from .request import RequestEntry
|
||||||
|
|
||||||
|
|
||||||
@@ -44,10 +44,10 @@ def process_request():
|
|||||||
try:
|
try:
|
||||||
req = cfg.worker_q.get(True, 5)
|
req = cfg.worker_q.get(True, 5)
|
||||||
log_debug(
|
log_debug(
|
||||||
"Running method: %s with args %s" %
|
"Method start: %s with args %s (callback = %s)" %
|
||||||
(str(req.method), str(req.arguments)))
|
(str(req.method), str(req.arguments), str(req.cb)))
|
||||||
req.run_cmd()
|
req.run_cmd()
|
||||||
log_debug("Method complete ")
|
log_debug("Method complete: %s" % str(req.method))
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -127,6 +127,14 @@ def main():
|
|||||||
log_error("You cannot specify --lvmshell and --nojson")
|
log_error("You cannot specify --lvmshell and --nojson")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# We will dynamically add interfaces which support vdo if it
|
||||||
|
# exists.
|
||||||
|
cfg.vdo_support = supports_vdo()
|
||||||
|
|
||||||
|
if cfg.vdo_support and not cfg.args.use_json:
|
||||||
|
log_error("You cannot specify --nojson when lvm has VDO support")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# List of threads that we start up
|
# List of threads that we start up
|
||||||
thread_list = []
|
thread_list = []
|
||||||
|
|
||||||
@@ -147,12 +155,12 @@ def main():
|
|||||||
cfg.om = Lvm(BASE_OBJ_PATH)
|
cfg.om = Lvm(BASE_OBJ_PATH)
|
||||||
cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
|
cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
|
||||||
|
|
||||||
cfg.db = lvmdb.DataStore(cfg.args.use_json)
|
cfg.db = lvmdb.DataStore(cfg.args.use_json, cfg.vdo_support)
|
||||||
|
|
||||||
# Using a thread to process requests, we cannot hang the dbus library
|
# Using a thread to process requests, we cannot hang the dbus library
|
||||||
# thread that is handling the dbus interface
|
# thread that is handling the dbus interface
|
||||||
thread_list.append(threading.Thread(target=process_request,
|
thread_list.append(
|
||||||
name='process_request'))
|
threading.Thread(target=process_request, name='process_request'))
|
||||||
|
|
||||||
# Have a single thread handling updating lvm and the dbus model so we
|
# Have a single thread handling updating lvm and the dbus model so we
|
||||||
# don't have multiple threads doing this as the same time
|
# don't have multiple threads doing this as the same time
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class Manager(AutomatedProperties):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def Version(self):
|
def Version(self):
|
||||||
return dbus.String('1.0.0')
|
return dbus.String('1.1.0')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_execute(rc, out, err):
|
def handle_execute(rc, out, err):
|
||||||
@@ -107,10 +107,10 @@ class Manager(AutomatedProperties):
|
|||||||
rc = cfg.load(log=False)
|
rc = cfg.load(log=False)
|
||||||
|
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
utils.log_debug('Manager.Refresh - exit %d' % (rc),
|
utils.log_debug('Manager.Refresh - exit %d %d' % (rc, lc),
|
||||||
'bg_black', 'fg_light_red')
|
'bg_black', 'fg_light_red')
|
||||||
else:
|
else:
|
||||||
utils.log_debug('Manager.Refresh - exit %d' % (rc))
|
utils.log_debug('Manager.Refresh - exit %d %d' % (rc, lc))
|
||||||
return rc + lc
|
return rc + lc
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -164,6 +164,8 @@ class Manager(AutomatedProperties):
|
|||||||
return the object path in O(1) time.
|
return the object path in O(1) time.
|
||||||
|
|
||||||
:param key: The lookup value
|
:param key: The lookup value
|
||||||
|
:param cb: dbus python call back parameter, not client visible
|
||||||
|
:param cbe: dbus python error call back parameter, not client visible
|
||||||
:return: Return the object path. If object not found you will get '/'
|
:return: Return the object path. If object not found you will get '/'
|
||||||
"""
|
"""
|
||||||
r = RequestEntry(-1, Manager._lookup_by_lvm_id, (key,), cb, cbe, False)
|
r = RequestEntry(-1, Manager._lookup_by_lvm_id, (key,), cb, cbe, False)
|
||||||
|
|||||||
@@ -189,8 +189,8 @@ class ObjectManager(AutomatedProperties):
|
|||||||
path = dbus_object.dbus_object_path()
|
path = dbus_object.dbus_object_path()
|
||||||
interfaces = dbus_object.interface()
|
interfaces = dbus_object.interface()
|
||||||
|
|
||||||
# print 'UN-Registering object path %s for %s' % \
|
# print('UN-Registering object path %s for %s' %
|
||||||
# (path, dbus_object.lvm_id)
|
# (path, dbus_object.lvm_id))
|
||||||
|
|
||||||
self._lookup_remove(path)
|
self._lookup_remove(path)
|
||||||
|
|
||||||
@@ -240,39 +240,19 @@ class ObjectManager(AutomatedProperties):
|
|||||||
return lookup_rc
|
return lookup_rc
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
def _uuid_verify(self, path, uuid, lvm_id):
|
def _id_verify(self, path, uuid, lvm_id):
|
||||||
"""
|
"""
|
||||||
Ensure uuid is present for a successful lvm_id lookup
|
Ensure our lookups are correct
|
||||||
NOTE: Internal call, assumes under object manager lock
|
NOTE: Internal call, assumes under object manager lock
|
||||||
:param path: Path to object we looked up
|
:param path: Path to object we looked up
|
||||||
:param uuid: lvm uuid to verify
|
:param uuid: uuid lookup
|
||||||
:param lvm_id: lvm_id used to find object
|
:param lvm_id: lvm_id lookup
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
# This gets called when we found an object based on lvm_id, ensure
|
# There is no durable non-changeable name in lvm
|
||||||
# uuid is correct too, as they can change. There is no durable
|
|
||||||
# non-changeable name in lvm
|
|
||||||
if lvm_id != uuid:
|
if lvm_id != uuid:
|
||||||
if uuid and uuid not in self._id_to_object_path:
|
obj = self.get_object_by_path(path)
|
||||||
obj = self.get_object_by_path(path)
|
self._lookup_add(obj, path, lvm_id, uuid)
|
||||||
self._lookup_add(obj, path, lvm_id, uuid)
|
|
||||||
|
|
||||||
def _lvm_id_verify(self, path, uuid, lvm_id):
|
|
||||||
"""
|
|
||||||
Ensure lvm_id is present for a successful uuid lookup
|
|
||||||
NOTE: Internal call, assumes under object manager lock
|
|
||||||
:param path: Path to object we looked up
|
|
||||||
:param uuid: uuid used to find object
|
|
||||||
:param lvm_id: lvm_id to verify
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
# This gets called when we found an object based on uuid, ensure
|
|
||||||
# lvm_id is correct too, as they can change. There is no durable
|
|
||||||
# non-changeable name in lvm
|
|
||||||
if lvm_id != uuid:
|
|
||||||
if lvm_id and lvm_id not in self._id_to_object_path:
|
|
||||||
obj = self.get_object_by_path(path)
|
|
||||||
self._lookup_add(obj, path, lvm_id, uuid)
|
|
||||||
|
|
||||||
def _id_lookup(self, the_id):
|
def _id_lookup(self, the_id):
|
||||||
path = None
|
path = None
|
||||||
@@ -339,22 +319,22 @@ class ObjectManager(AutomatedProperties):
|
|||||||
# Lets check for the uuid first
|
# Lets check for the uuid first
|
||||||
path = self._id_lookup(uuid)
|
path = self._id_lookup(uuid)
|
||||||
if path:
|
if path:
|
||||||
# Verify the lvm_id is sane
|
# Ensure table lookups are correct
|
||||||
self._lvm_id_verify(path, uuid, lvm_id)
|
self._id_verify(path, uuid, lvm_id)
|
||||||
else:
|
else:
|
||||||
# Unable to find by UUID, lets lookup by lvm_id
|
# Unable to find by UUID, lets lookup by lvm_id
|
||||||
path = self._id_lookup(lvm_id)
|
path = self._id_lookup(lvm_id)
|
||||||
if path:
|
if path:
|
||||||
# Verify the uuid is sane
|
# Ensure table lookups are correct
|
||||||
self._uuid_verify(path, uuid, lvm_id)
|
self._id_verify(path, uuid, lvm_id)
|
||||||
else:
|
else:
|
||||||
# We have exhausted all lookups, let's create if we can
|
# We have exhausted all lookups, let's create if we can
|
||||||
if path_create:
|
if path_create:
|
||||||
path = path_create()
|
path = path_create()
|
||||||
self._lookup_add(None, path, lvm_id, uuid)
|
self._lookup_add(None, path, lvm_id, uuid)
|
||||||
|
|
||||||
# print('get_object_path_by_lvm_id(%s, %s, %s, %s: return %s' %
|
# print('get_object_path_by_lvm_id(%s, %s, %s): return %s' %
|
||||||
# (uuid, lvm_id, str(path_create), str(gen_new), path))
|
# (uuid, lvm_id, str(path_create), path))
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import dbus
|
|||||||
from .cfg import PV_INTERFACE
|
from .cfg import PV_INTERFACE
|
||||||
from . import cmdhandler
|
from . import cmdhandler
|
||||||
from .utils import vg_obj_path_generate, n, pv_obj_path_generate, \
|
from .utils import vg_obj_path_generate, n, pv_obj_path_generate, \
|
||||||
lv_object_path_method
|
lv_object_path_method, _handle_execute
|
||||||
from .loader import common
|
from .loader import common
|
||||||
from .request import RequestEntry
|
from .request import RequestEntry
|
||||||
from .state import State
|
from .state import State
|
||||||
@@ -138,19 +138,12 @@ class Pv(AutomatedProperties):
|
|||||||
# Remove the PV, if successful then remove from the model
|
# Remove the PV, if successful then remove from the model
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Pv.validate_dbus_object(pv_uuid, pv_name)
|
Pv.validate_dbus_object(pv_uuid, pv_name)
|
||||||
rc, out, err = cmdhandler.pv_remove(pv_name, remove_options)
|
Pv.handle_execute(*cmdhandler.pv_remove(pv_name, remove_options))
|
||||||
Pv.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_execute(rc, out, err):
|
def handle_execute(rc, out, err):
|
||||||
if rc == 0:
|
return _handle_execute(rc, out, err, PV_INTERFACE)
|
||||||
cfg.load()
|
|
||||||
else:
|
|
||||||
# Need to work on error handling, need consistent
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
PV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_dbus_object(pv_uuid, pv_name):
|
def validate_dbus_object(pv_uuid, pv_name):
|
||||||
@@ -178,10 +171,8 @@ class Pv(AutomatedProperties):
|
|||||||
def _resize(pv_uuid, pv_name, new_size_bytes, resize_options):
|
def _resize(pv_uuid, pv_name, new_size_bytes, resize_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Pv.validate_dbus_object(pv_uuid, pv_name)
|
Pv.validate_dbus_object(pv_uuid, pv_name)
|
||||||
|
Pv.handle_execute(*cmdhandler.pv_resize(pv_name, new_size_bytes,
|
||||||
rc, out, err = cmdhandler.pv_resize(pv_name, new_size_bytes,
|
resize_options))
|
||||||
resize_options)
|
|
||||||
Pv.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -200,9 +191,8 @@ class Pv(AutomatedProperties):
|
|||||||
def _allocation_enabled(pv_uuid, pv_name, yes_no, allocation_options):
|
def _allocation_enabled(pv_uuid, pv_name, yes_no, allocation_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Pv.validate_dbus_object(pv_uuid, pv_name)
|
Pv.validate_dbus_object(pv_uuid, pv_name)
|
||||||
rc, out, err = cmdhandler.pv_allocatable(
|
Pv.handle_execute(*cmdhandler.pv_allocatable(pv_name, yes_no,
|
||||||
pv_name, yes_no, allocation_options)
|
allocation_options))
|
||||||
Pv.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
|
|||||||
@@ -26,6 +26,15 @@ import signal
|
|||||||
STDOUT_TTY = os.isatty(sys.stdout.fileno())
|
STDOUT_TTY = os.isatty(sys.stdout.fileno())
|
||||||
|
|
||||||
|
|
||||||
|
def _handle_execute(rc, out, err, interface):
|
||||||
|
if rc == 0:
|
||||||
|
cfg.load()
|
||||||
|
else:
|
||||||
|
# Need to work on error handling, need consistent
|
||||||
|
raise dbus.exceptions.DBusException(
|
||||||
|
interface, 'Exit code %s, stderr = %s' % (str(rc), err))
|
||||||
|
|
||||||
|
|
||||||
def rtype(dbus_type):
|
def rtype(dbus_type):
|
||||||
"""
|
"""
|
||||||
Decorator making sure that the decorated function returns a value of
|
Decorator making sure that the decorated function returns a value of
|
||||||
@@ -57,8 +66,20 @@ def n32(v):
|
|||||||
return int(float(v))
|
return int(float(v))
|
||||||
|
|
||||||
|
|
||||||
|
@rtype(dbus.Double)
|
||||||
|
def d(v):
|
||||||
|
if not v:
|
||||||
|
return 0.0
|
||||||
|
return float(v)
|
||||||
|
|
||||||
|
|
||||||
|
def _snake_to_pascal(s):
|
||||||
|
return ''.join(x.title() for x in s.split('_'))
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyProtectedMember
|
# noinspection PyProtectedMember
|
||||||
def init_class_from_arguments(obj_instance):
|
def init_class_from_arguments(
|
||||||
|
obj_instance, begin_suffix=None, snake_to_pascal=False):
|
||||||
for k, v in list(sys._getframe(1).f_locals.items()):
|
for k, v in list(sys._getframe(1).f_locals.items()):
|
||||||
if k != 'self':
|
if k != 'self':
|
||||||
nt = k
|
nt = k
|
||||||
@@ -69,8 +90,17 @@ def init_class_from_arguments(obj_instance):
|
|||||||
cur = getattr(obj_instance, nt, v)
|
cur = getattr(obj_instance, nt, v)
|
||||||
|
|
||||||
# print 'Init class %s = %s' % (nt, str(v))
|
# print 'Init class %s = %s' % (nt, str(v))
|
||||||
if not (cur and len(str(cur)) and (v is None or len(str(v))) == 0):
|
if not (cur and len(str(cur)) and (v is None or len(str(v))) == 0)\
|
||||||
setattr(obj_instance, nt, v)
|
and (begin_suffix is None or nt.startswith(begin_suffix)):
|
||||||
|
|
||||||
|
if begin_suffix and nt.startswith(begin_suffix):
|
||||||
|
name = nt[len(begin_suffix):]
|
||||||
|
if snake_to_pascal:
|
||||||
|
name = _snake_to_pascal(name)
|
||||||
|
|
||||||
|
setattr(obj_instance, name, v)
|
||||||
|
else:
|
||||||
|
setattr(obj_instance, nt, v)
|
||||||
|
|
||||||
|
|
||||||
def get_properties(f):
|
def get_properties(f):
|
||||||
@@ -338,6 +368,8 @@ def lv_object_path_method(name, meta):
|
|||||||
return _hidden_lv_obj_path_generate
|
return _hidden_lv_obj_path_generate
|
||||||
elif meta[0][0] == 't':
|
elif meta[0][0] == 't':
|
||||||
return _thin_pool_obj_path_generate
|
return _thin_pool_obj_path_generate
|
||||||
|
elif meta[0][0] == 'd':
|
||||||
|
return _vdo_pool_object_path_generate
|
||||||
elif meta[0][0] == 'C' and 'pool' in meta[1]:
|
elif meta[0][0] == 'C' and 'pool' in meta[1]:
|
||||||
return _cache_pool_obj_path_generate
|
return _cache_pool_obj_path_generate
|
||||||
|
|
||||||
@@ -355,6 +387,10 @@ def _thin_pool_obj_path_generate():
|
|||||||
return cfg.THIN_POOL_PATH + "/%d" % next(cfg.thin_id)
|
return cfg.THIN_POOL_PATH + "/%d" % next(cfg.thin_id)
|
||||||
|
|
||||||
|
|
||||||
|
def _vdo_pool_object_path_generate():
|
||||||
|
return cfg.VDO_POOL_PATH + "/%d" % next(cfg.vdo_id)
|
||||||
|
|
||||||
|
|
||||||
def _cache_pool_obj_path_generate():
|
def _cache_pool_obj_path_generate():
|
||||||
return cfg.CACHE_POOL_PATH + "/%d" % next(cfg.cache_pool_id)
|
return cfg.CACHE_POOL_PATH + "/%d" % next(cfg.cache_pool_id)
|
||||||
|
|
||||||
@@ -446,7 +482,7 @@ _ALLOWABLE_CH_SET = set(_ALLOWABLE_CH)
|
|||||||
_ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+'
|
_ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+'
|
||||||
_ALLOWABLE_VG_LV_CH_SET = set(_ALLOWABLE_VG_LV_CH)
|
_ALLOWABLE_VG_LV_CH_SET = set(_ALLOWABLE_VG_LV_CH)
|
||||||
_LV_NAME_RESERVED = ("_cdata", "_cmeta", "_corig", "_mimage", "_mlog",
|
_LV_NAME_RESERVED = ("_cdata", "_cmeta", "_corig", "_mimage", "_mlog",
|
||||||
"_pmspare", "_rimage", "_rmeta", "_tdata", "_tmeta", "_vorigin")
|
"_pmspare", "_rimage", "_rmeta", "_tdata", "_tmeta", "_vorigin", "_vdata")
|
||||||
|
|
||||||
# Tags can have the characters, based on the code
|
# Tags can have the characters, based on the code
|
||||||
# a-zA-Z0-9._-+/=!:&#
|
# a-zA-Z0-9._-+/=!:&#
|
||||||
|
|||||||
@@ -10,10 +10,11 @@
|
|||||||
from .automatedproperties import AutomatedProperties
|
from .automatedproperties import AutomatedProperties
|
||||||
|
|
||||||
from . import utils
|
from . import utils
|
||||||
from .utils import pv_obj_path_generate, vg_obj_path_generate, n
|
from .utils import pv_obj_path_generate, vg_obj_path_generate, n, \
|
||||||
|
_handle_execute
|
||||||
import dbus
|
import dbus
|
||||||
from . import cfg
|
from . import cfg
|
||||||
from .cfg import VG_INTERFACE
|
from .cfg import VG_INTERFACE, VG_VDO_INTERFACE
|
||||||
from . import cmdhandler
|
from . import cmdhandler
|
||||||
from .request import RequestEntry
|
from .request import RequestEntry
|
||||||
from .loader import common
|
from .loader import common
|
||||||
@@ -46,24 +47,29 @@ def vgs_state_retrieve(selection, cache_refresh=True):
|
|||||||
|
|
||||||
def load_vgs(vg_specific=None, object_path=None, refresh=False,
|
def load_vgs(vg_specific=None, object_path=None, refresh=False,
|
||||||
emit_signal=False, cache_refresh=True):
|
emit_signal=False, cache_refresh=True):
|
||||||
return common(vgs_state_retrieve, (Vg,), vg_specific, object_path, refresh,
|
return common(vgs_state_retrieve, (Vg, VgVdo, ), vg_specific, object_path, refresh,
|
||||||
emit_signal, cache_refresh)
|
emit_signal, cache_refresh)
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming,PyUnresolvedReferences,PyUnusedLocal
|
# noinspection PyPep8Naming,PyUnresolvedReferences,PyUnusedLocal
|
||||||
class VgState(State):
|
class VgState(State):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lvm_id(self):
|
def internal_name(self):
|
||||||
return self.Name
|
return self.Name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lvm_id(self):
|
||||||
|
return self.internal_name
|
||||||
|
|
||||||
def identifiers(self):
|
def identifiers(self):
|
||||||
return (self.Uuid, self.Name)
|
return (self.Uuid, self.internal_name)
|
||||||
|
|
||||||
def _lv_paths_build(self):
|
def _lv_paths_build(self):
|
||||||
rc = []
|
rc = []
|
||||||
for lv in cfg.db.lvs_in_vg(self.Uuid):
|
for lv in cfg.db.lvs_in_vg(self.Uuid):
|
||||||
(lv_name, meta, lv_uuid) = lv
|
(lv_name, meta, lv_uuid) = lv
|
||||||
full_name = "%s/%s" % (self.Name, lv_name)
|
full_name = "%s/%s" % (self.internal_name, lv_name)
|
||||||
|
|
||||||
gen = utils.lv_object_path_method(lv_name, meta)
|
gen = utils.lv_object_path_method(lv_name, meta)
|
||||||
|
|
||||||
@@ -92,8 +98,12 @@ class VgState(State):
|
|||||||
def create_dbus_object(self, path):
|
def create_dbus_object(self, path):
|
||||||
if not path:
|
if not path:
|
||||||
path = cfg.om.get_object_path_by_uuid_lvm_id(
|
path = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||||
self.Uuid, self.Name, vg_obj_path_generate)
|
self.Uuid, self.internal_name, vg_obj_path_generate)
|
||||||
return Vg(path, self)
|
|
||||||
|
if cfg.vdo_support:
|
||||||
|
return VgVdo(path, self)
|
||||||
|
else:
|
||||||
|
return Vg(path, self)
|
||||||
|
|
||||||
# noinspection PyMethodMayBeStatic
|
# noinspection PyMethodMayBeStatic
|
||||||
def creation_signature(self):
|
def creation_signature(self):
|
||||||
@@ -102,7 +112,6 @@ class VgState(State):
|
|||||||
|
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
@utils.dbus_property(VG_INTERFACE, 'Uuid', 's')
|
@utils.dbus_property(VG_INTERFACE, 'Uuid', 's')
|
||||||
@utils.dbus_property(VG_INTERFACE, 'Name', 's')
|
|
||||||
@utils.dbus_property(VG_INTERFACE, 'Fmt', 's')
|
@utils.dbus_property(VG_INTERFACE, 'Fmt', 's')
|
||||||
@utils.dbus_property(VG_INTERFACE, 'SizeBytes', 't', 0)
|
@utils.dbus_property(VG_INTERFACE, 'SizeBytes', 't', 0)
|
||||||
@utils.dbus_property(VG_INTERFACE, 'FreeBytes', 't', 0)
|
@utils.dbus_property(VG_INTERFACE, 'FreeBytes', 't', 0)
|
||||||
@@ -135,6 +144,7 @@ class Vg(AutomatedProperties):
|
|||||||
_AllocNormal_meta = ('b', VG_INTERFACE)
|
_AllocNormal_meta = ('b', VG_INTERFACE)
|
||||||
_AllocAnywhere_meta = ('b', VG_INTERFACE)
|
_AllocAnywhere_meta = ('b', VG_INTERFACE)
|
||||||
_Clustered_meta = ('b', VG_INTERFACE)
|
_Clustered_meta = ('b', VG_INTERFACE)
|
||||||
|
_Name_meta = ('s', VG_INTERFACE)
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyPep8Naming
|
# noinspection PyUnusedLocal,PyPep8Naming
|
||||||
def __init__(self, object_path, object_state):
|
def __init__(self, object_path, object_state):
|
||||||
@@ -149,13 +159,7 @@ class Vg(AutomatedProperties):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_execute(rc, out, err):
|
def handle_execute(rc, out, err):
|
||||||
if rc == 0:
|
return _handle_execute(rc, out, err, VG_INTERFACE)
|
||||||
cfg.load()
|
|
||||||
else:
|
|
||||||
# Need to work on error handling, need consistent
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
VG_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_dbus_object(vg_uuid, vg_name):
|
def validate_dbus_object(vg_uuid, vg_name):
|
||||||
@@ -171,9 +175,8 @@ class Vg(AutomatedProperties):
|
|||||||
def _rename(uuid, vg_name, new_name, rename_options):
|
def _rename(uuid, vg_name, new_name, rename_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
rc, out, err = cmdhandler.vg_rename(
|
Vg.handle_execute(*cmdhandler.vg_rename(
|
||||||
vg_name, new_name, rename_options)
|
uuid, new_name, rename_options))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -192,8 +195,7 @@ class Vg(AutomatedProperties):
|
|||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
# Remove the VG, if successful then remove from the model
|
# Remove the VG, if successful then remove from the model
|
||||||
rc, out, err = cmdhandler.vg_remove(vg_name, remove_options)
|
Vg.handle_execute(*cmdhandler.vg_remove(vg_name, remove_options))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -209,14 +211,13 @@ class Vg(AutomatedProperties):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _change(uuid, vg_name, change_options):
|
def _change(uuid, vg_name, change_options):
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
rc, out, err = cmdhandler.vg_change(change_options, vg_name)
|
Vg.handle_execute(*cmdhandler.vg_change(change_options, vg_name))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
# TODO: This should be broken into a number of different methods
|
# TODO: This should be broken into a number of different methods
|
||||||
# instead of having one method that takes a hash for parameters. Some of
|
# instead of having one method that takes a hash for parameters. Some of
|
||||||
# the changes that vgchange does works on entire system, not just a
|
# the changes that vgchange does works on entire system, not just a
|
||||||
# specfic vg, thus that should be in the Manager interface.
|
# specific vg, thus that should be in the Manager interface.
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
dbus_interface=VG_INTERFACE,
|
dbus_interface=VG_INTERFACE,
|
||||||
in_signature='ia{sv}',
|
in_signature='ia{sv}',
|
||||||
@@ -246,9 +247,8 @@ class Vg(AutomatedProperties):
|
|||||||
VG_INTERFACE,
|
VG_INTERFACE,
|
||||||
'PV Object path not found = %s!' % pv_op)
|
'PV Object path not found = %s!' % pv_op)
|
||||||
|
|
||||||
rc, out, err = cmdhandler.vg_reduce(vg_name, missing, pv_devices,
|
Vg.handle_execute(*cmdhandler.vg_reduce(
|
||||||
reduce_options)
|
vg_name, missing, pv_devices, reduce_options))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -278,9 +278,8 @@ class Vg(AutomatedProperties):
|
|||||||
VG_INTERFACE, 'PV Object path not found = %s!' % i)
|
VG_INTERFACE, 'PV Object path not found = %s!' % i)
|
||||||
|
|
||||||
if len(extend_devices):
|
if len(extend_devices):
|
||||||
rc, out, err = cmdhandler.vg_extend(vg_name, extend_devices,
|
Vg.handle_execute(*cmdhandler.vg_extend(
|
||||||
extend_options)
|
vg_name, extend_devices, extend_options))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
else:
|
else:
|
||||||
raise dbus.exceptions.DBusException(
|
raise dbus.exceptions.DBusException(
|
||||||
VG_INTERFACE, 'No pv_object_paths provided!')
|
VG_INTERFACE, 'No pv_object_paths provided!')
|
||||||
@@ -334,10 +333,8 @@ class Vg(AutomatedProperties):
|
|||||||
|
|
||||||
pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
|
pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
|
||||||
|
|
||||||
rc, out, err = cmdhandler.vg_lv_create(
|
Vg.handle_execute(*cmdhandler.vg_lv_create(
|
||||||
vg_name, create_options, name, size_bytes, pv_dests)
|
vg_name, create_options, name, size_bytes, pv_dests))
|
||||||
|
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return Vg.fetch_new_lv(vg_name, name)
|
return Vg.fetch_new_lv(vg_name, name)
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -375,11 +372,8 @@ class Vg(AutomatedProperties):
|
|||||||
thin_pool, create_options):
|
thin_pool, create_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
|
Vg.handle_execute(*cmdhandler.vg_lv_create_linear(
|
||||||
rc, out, err = cmdhandler.vg_lv_create_linear(
|
vg_name, create_options, name, size_bytes, thin_pool))
|
||||||
vg_name, create_options, name, size_bytes, thin_pool)
|
|
||||||
|
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return Vg.fetch_new_lv(vg_name, name)
|
return Vg.fetch_new_lv(vg_name, name)
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -401,10 +395,9 @@ class Vg(AutomatedProperties):
|
|||||||
stripe_size_kb, thin_pool, create_options):
|
stripe_size_kb, thin_pool, create_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
rc, out, err = cmdhandler.vg_lv_create_striped(
|
Vg.handle_execute(*cmdhandler.vg_lv_create_striped(
|
||||||
vg_name, create_options, name, size_bytes,
|
vg_name, create_options, name, size_bytes,
|
||||||
num_stripes, stripe_size_kb, thin_pool)
|
num_stripes, stripe_size_kb, thin_pool))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return Vg.fetch_new_lv(vg_name, name)
|
return Vg.fetch_new_lv(vg_name, name)
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -429,9 +422,8 @@ class Vg(AutomatedProperties):
|
|||||||
num_copies, create_options):
|
num_copies, create_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
rc, out, err = cmdhandler.vg_lv_create_mirror(
|
Vg.handle_execute(*cmdhandler.vg_lv_create_mirror(
|
||||||
vg_name, create_options, name, size_bytes, num_copies)
|
vg_name, create_options, name, size_bytes, num_copies))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return Vg.fetch_new_lv(vg_name, name)
|
return Vg.fetch_new_lv(vg_name, name)
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -454,10 +446,9 @@ class Vg(AutomatedProperties):
|
|||||||
num_stripes, stripe_size_kb, create_options):
|
num_stripes, stripe_size_kb, create_options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
rc, out, err = cmdhandler.vg_lv_create_raid(
|
Vg.handle_execute(*cmdhandler.vg_lv_create_raid(
|
||||||
vg_name, create_options, name, raid_type, size_bytes,
|
vg_name, create_options, name, raid_type, size_bytes,
|
||||||
num_stripes, stripe_size_kb)
|
num_stripes, stripe_size_kb))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return Vg.fetch_new_lv(vg_name, name)
|
return Vg.fetch_new_lv(vg_name, name)
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -555,9 +546,8 @@ class Vg(AutomatedProperties):
|
|||||||
raise dbus.exceptions.DBusException(
|
raise dbus.exceptions.DBusException(
|
||||||
VG_INTERFACE, 'PV object path = %s not found' % p)
|
VG_INTERFACE, 'PV object path = %s not found' % p)
|
||||||
|
|
||||||
rc, out, err = cmdhandler.pv_tag(
|
Vg.handle_execute(*cmdhandler.pv_tag(
|
||||||
pv_devices, tags_add, tags_del, tag_options)
|
pv_devices, tags_add, tags_del, tag_options))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -598,9 +588,8 @@ class Vg(AutomatedProperties):
|
|||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
|
|
||||||
rc, out, err = cmdhandler.vg_tag(
|
Vg.handle_execute(*cmdhandler.vg_tag(
|
||||||
vg_name, tags_add, tags_del, tag_options)
|
vg_name, tags_add, tags_del, tag_options))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -639,8 +628,7 @@ class Vg(AutomatedProperties):
|
|||||||
def _vg_change_set(uuid, vg_name, method, value, options):
|
def _vg_change_set(uuid, vg_name, method, value, options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
rc, out, err = method(vg_name, value, options)
|
Vg.handle_execute(*method(vg_name, value, options))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -700,9 +688,8 @@ class Vg(AutomatedProperties):
|
|||||||
options):
|
options):
|
||||||
# Make sure we have a dbus object representing it
|
# Make sure we have a dbus object representing it
|
||||||
Vg.validate_dbus_object(uuid, vg_name)
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
rc, out, err = cmdhandler.activate_deactivate(
|
Vg.handle_execute(*cmdhandler.activate_deactivate(
|
||||||
'vgchange', vg_name, activate, control_flags, options)
|
'vgchange', vg_name, activate, control_flags, options))
|
||||||
Vg.handle_execute(rc, out, err)
|
|
||||||
return '/'
|
return '/'
|
||||||
|
|
||||||
@dbus.service.method(
|
@dbus.service.method(
|
||||||
@@ -729,6 +716,12 @@ class Vg(AutomatedProperties):
|
|||||||
cb, cbe, return_tuple=False)
|
cb, cbe, return_tuple=False)
|
||||||
cfg.worker_q.put(r)
|
cfg.worker_q.put(r)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def Name(self):
|
||||||
|
if ':' in self.state.Name:
|
||||||
|
return self.state.Name.split(':')[0]
|
||||||
|
return self.state.Name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def Tags(self):
|
def Tags(self):
|
||||||
return utils.parse_tags(self.state.tags)
|
return utils.parse_tags(self.state.tags)
|
||||||
@@ -784,3 +777,71 @@ class Vg(AutomatedProperties):
|
|||||||
@property
|
@property
|
||||||
def Clustered(self):
|
def Clustered(self):
|
||||||
return self._attribute(5, 'c')
|
return self._attribute(5, 'c')
|
||||||
|
|
||||||
|
|
||||||
|
class VgVdo(Vg):
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal,PyPep8Naming
|
||||||
|
def __init__(self, object_path, object_state):
|
||||||
|
super(VgVdo, self).__init__(object_path, vgs_state_retrieve)
|
||||||
|
self.set_interface(VG_VDO_INTERFACE)
|
||||||
|
self._object_path = object_path
|
||||||
|
self.state = object_state
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _lv_vdo_pool_create_with_lv(uuid, vg_name, pool_name, lv_name,
|
||||||
|
data_size, virtual_size, create_options):
|
||||||
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
|
Vg.handle_execute(*cmdhandler.vg_create_vdo_pool_lv_and_lv(
|
||||||
|
vg_name, pool_name, lv_name, data_size, virtual_size,
|
||||||
|
create_options))
|
||||||
|
return Vg.fetch_new_lv(vg_name, pool_name)
|
||||||
|
|
||||||
|
@dbus.service.method(
|
||||||
|
dbus_interface=VG_VDO_INTERFACE,
|
||||||
|
in_signature='ssttia{sv}',
|
||||||
|
out_signature='(oo)',
|
||||||
|
async_callbacks=('cb', 'cbe'))
|
||||||
|
def CreateVdoPoolandLv(self, pool_name, lv_name, data_size, virtual_size,
|
||||||
|
tmo, create_options, cb, cbe):
|
||||||
|
utils.validate_lv_name(VG_VDO_INTERFACE, self.Name, pool_name)
|
||||||
|
utils.validate_lv_name(VG_VDO_INTERFACE, self.Name, lv_name)
|
||||||
|
|
||||||
|
r = RequestEntry(tmo, VgVdo._lv_vdo_pool_create_with_lv,
|
||||||
|
(self.state.Uuid, self.state.lvm_id,
|
||||||
|
pool_name, lv_name, round_size(data_size),
|
||||||
|
round_size(virtual_size),
|
||||||
|
create_options), cb, cbe)
|
||||||
|
cfg.worker_q.put(r)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _vdo_pool_create(uuid, vg_name, pool_lv, name, virtual_size, create_options):
|
||||||
|
Vg.validate_dbus_object(uuid, vg_name)
|
||||||
|
|
||||||
|
# Retrieve the full name of the pool lv
|
||||||
|
pool = cfg.om.get_object_by_path(pool_lv)
|
||||||
|
if not pool:
|
||||||
|
msg = 'LV with object path %s not present!' % \
|
||||||
|
(pool_lv)
|
||||||
|
raise dbus.exceptions.DBusException(VG_VDO_INTERFACE, msg)
|
||||||
|
|
||||||
|
Vg.handle_execute(*cmdhandler.vg_create_vdo_pool(
|
||||||
|
pool.lv_full_name(), name, virtual_size,
|
||||||
|
create_options))
|
||||||
|
return Vg.fetch_new_lv(vg_name, pool.Name)
|
||||||
|
|
||||||
|
@dbus.service.method(
|
||||||
|
dbus_interface=VG_VDO_INTERFACE,
|
||||||
|
in_signature='ostia{sv}',
|
||||||
|
out_signature='(oo)',
|
||||||
|
async_callbacks=('cb', 'cbe'))
|
||||||
|
def CreateVdoPool(self, pool_lv, name, virtual_size,
|
||||||
|
tmo, create_options, cb, cbe):
|
||||||
|
utils.validate_lv_name(VG_VDO_INTERFACE, self.Name, name)
|
||||||
|
|
||||||
|
r = RequestEntry(tmo, VgVdo._vdo_pool_create,
|
||||||
|
(self.state.Uuid, self.state.lvm_id,
|
||||||
|
pool_lv, name,
|
||||||
|
round_size(virtual_size),
|
||||||
|
create_options), cb, cbe)
|
||||||
|
cfg.worker_q.put(r)
|
||||||
|
|||||||
2
daemons/lvmetad/.gitignore
vendored
2
daemons/lvmetad/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
lvmetad
|
|
||||||
lvmetactl
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2011-2012 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# This file is part of LVM2.
|
|
||||||
#
|
|
||||||
# This copyrighted material is made available to anyone wishing to use,
|
|
||||||
# modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
# of the GNU Lesser General Public License v.2.1.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
srcdir = @srcdir@
|
|
||||||
top_srcdir = @top_srcdir@
|
|
||||||
top_builddir = @top_builddir@
|
|
||||||
|
|
||||||
SOURCES = lvmetad-core.c
|
|
||||||
SOURCES2 = lvmetactl.c
|
|
||||||
|
|
||||||
TARGETS = lvmetad lvmetactl
|
|
||||||
|
|
||||||
.PHONY: install_lvmetad
|
|
||||||
|
|
||||||
CFLOW_LIST = $(SOURCES)
|
|
||||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
|
||||||
CFLOW_TARGET = lvmetad
|
|
||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
|
||||||
|
|
||||||
CFLAGS_lvmetactl.o += $(EXTRA_EXEC_CFLAGS)
|
|
||||||
CFLAGS_lvmetad-core.o += $(EXTRA_EXEC_CFLAGS)
|
|
||||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
|
||||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
|
||||||
LIBS += $(RT_LIBS) $(DAEMON_LIBS) -ldevmapper $(PTHREAD_LIBS)
|
|
||||||
|
|
||||||
lvmetad: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
|
||||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) -ldaemonserver $(LIBS)
|
|
||||||
|
|
||||||
lvmetactl: lvmetactl.o $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
|
||||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmetactl.o $(LIBS)
|
|
||||||
|
|
||||||
CLEAN_TARGETS += lvmetactl.o
|
|
||||||
|
|
||||||
# TODO: No idea. No idea how to test either.
|
|
||||||
#ifneq ("$(CFLOW_CMD)", "")
|
|
||||||
#CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
|
||||||
#-include $(top_builddir)/libdm/libdevmapper.cflow
|
|
||||||
#-include $(top_builddir)/lib/liblvm-internal.cflow
|
|
||||||
#-include $(top_builddir)/lib/liblvm2cmd.cflow
|
|
||||||
#-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
|
|
||||||
#-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
|
|
||||||
#endif
|
|
||||||
|
|
||||||
install_lvmetad: lvmetad
|
|
||||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
|
||||||
|
|
||||||
install_lvm2: install_lvmetad
|
|
||||||
|
|
||||||
install: install_lvm2
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2014 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tool.h"
|
|
||||||
|
|
||||||
#include "lvmetad-client.h"
|
|
||||||
|
|
||||||
daemon_handle h;
|
|
||||||
|
|
||||||
static void print_reply(daemon_reply reply)
|
|
||||||
{
|
|
||||||
const char *a = daemon_reply_str(reply, "response", NULL);
|
|
||||||
const char *b = daemon_reply_str(reply, "status", NULL);
|
|
||||||
const char *c = daemon_reply_str(reply, "reason", NULL);
|
|
||||||
|
|
||||||
printf("response \"%s\" status \"%s\" reason \"%s\"\n",
|
|
||||||
a ? a : "", b ? b : "", c ? c : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
daemon_reply reply;
|
|
||||||
char *cmd;
|
|
||||||
char *uuid;
|
|
||||||
char *name;
|
|
||||||
int val;
|
|
||||||
int ver;
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
printf("lvmetactl dump\n");
|
|
||||||
printf("lvmetactl pv_list\n");
|
|
||||||
printf("lvmetactl vg_list\n");
|
|
||||||
printf("lvmetactl get_global_info\n");
|
|
||||||
printf("lvmetactl vg_lookup_name <name>\n");
|
|
||||||
printf("lvmetactl vg_lookup_uuid <uuid>\n");
|
|
||||||
printf("lvmetactl pv_lookup_uuid <uuid>\n");
|
|
||||||
printf("lvmetactl set_global_invalid 0|1\n");
|
|
||||||
printf("lvmetactl set_global_disable 0|1\n");
|
|
||||||
printf("lvmetactl set_vg_version <uuid> <name> <version>\n");
|
|
||||||
printf("lvmetactl vg_lock_type <uuid>\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = argv[1];
|
|
||||||
|
|
||||||
h = lvmetad_open(NULL);
|
|
||||||
|
|
||||||
if (!strcmp(cmd, "dump")) {
|
|
||||||
reply = daemon_send_simple(h, "dump",
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
printf("%s\n", reply.buffer.mem);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "pv_list")) {
|
|
||||||
reply = daemon_send_simple(h, "pv_list",
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
printf("%s\n", reply.buffer.mem);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "vg_list")) {
|
|
||||||
reply = daemon_send_simple(h, "vg_list",
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
printf("%s\n", reply.buffer.mem);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "get_global_info")) {
|
|
||||||
reply = daemon_send_simple(h, "get_global_info",
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
printf("%s\n", reply.buffer.mem);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "set_global_invalid")) {
|
|
||||||
if (argc < 3) {
|
|
||||||
printf("set_global_invalid 0|1\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
val = atoi(argv[2]);
|
|
||||||
|
|
||||||
reply = daemon_send_simple(h, "set_global_info",
|
|
||||||
"global_invalid = " FMTd64, (int64_t) val,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
print_reply(reply);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "set_global_disable")) {
|
|
||||||
if (argc < 3) {
|
|
||||||
printf("set_global_disable 0|1\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
val = atoi(argv[2]);
|
|
||||||
|
|
||||||
reply = daemon_send_simple(h, "set_global_info",
|
|
||||||
"global_disable = " FMTd64, (int64_t) val,
|
|
||||||
"disable_reason = %s", LVMETAD_DISABLE_REASON_DIRECT,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
print_reply(reply);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "set_vg_version")) {
|
|
||||||
if (argc < 5) {
|
|
||||||
printf("set_vg_version <uuid> <name> <ver>\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uuid = argv[2];
|
|
||||||
name = argv[3];
|
|
||||||
ver = atoi(argv[4]);
|
|
||||||
|
|
||||||
if ((strlen(uuid) == 1) && (uuid[0] == '-'))
|
|
||||||
uuid = NULL;
|
|
||||||
if ((strlen(name) == 1) && (name[0] == '-'))
|
|
||||||
name = NULL;
|
|
||||||
|
|
||||||
if (uuid && name) {
|
|
||||||
reply = daemon_send_simple(h, "set_vg_info",
|
|
||||||
"uuid = %s", uuid,
|
|
||||||
"name = %s", name,
|
|
||||||
"version = " FMTd64, (int64_t) ver,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
} else if (uuid) {
|
|
||||||
reply = daemon_send_simple(h, "set_vg_info",
|
|
||||||
"uuid = %s", uuid,
|
|
||||||
"version = " FMTd64, (int64_t) ver,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
} else if (name) {
|
|
||||||
reply = daemon_send_simple(h, "set_vg_info",
|
|
||||||
"name = %s", name,
|
|
||||||
"version = " FMTd64, (int64_t) ver,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
} else {
|
|
||||||
printf("name or uuid required\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_reply(reply);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "vg_lookup_name")) {
|
|
||||||
if (argc < 3) {
|
|
||||||
printf("vg_lookup_name <name>\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
name = argv[2];
|
|
||||||
|
|
||||||
reply = daemon_send_simple(h, "vg_lookup",
|
|
||||||
"name = %s", name,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
printf("%s\n", reply.buffer.mem);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "vg_lookup_uuid")) {
|
|
||||||
if (argc < 3) {
|
|
||||||
printf("vg_lookup_uuid <uuid>\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uuid = argv[2];
|
|
||||||
|
|
||||||
reply = daemon_send_simple(h, "vg_lookup",
|
|
||||||
"uuid = %s", uuid,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
printf("%s\n", reply.buffer.mem);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "vg_lock_type")) {
|
|
||||||
struct dm_config_node *metadata;
|
|
||||||
const char *lock_type;
|
|
||||||
|
|
||||||
if (argc < 3) {
|
|
||||||
printf("vg_lock_type <uuid>\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uuid = argv[2];
|
|
||||||
|
|
||||||
reply = daemon_send_simple(h, "vg_lookup",
|
|
||||||
"uuid = %s", uuid,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
/* printf("%s\n", reply.buffer.mem); */
|
|
||||||
|
|
||||||
metadata = dm_config_find_node(reply.cft->root, "metadata");
|
|
||||||
if (!metadata) {
|
|
||||||
printf("no metadata\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock_type = dm_config_find_str(metadata, "metadata/lock_type", NULL);
|
|
||||||
if (!lock_type) {
|
|
||||||
printf("no lock_type\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
printf("lock_type %s\n", lock_type);
|
|
||||||
|
|
||||||
} else if (!strcmp(cmd, "pv_lookup_uuid")) {
|
|
||||||
if (argc < 3) {
|
|
||||||
printf("pv_lookup_uuid <uuid>\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uuid = argv[2];
|
|
||||||
|
|
||||||
reply = daemon_send_simple(h, "pv_lookup",
|
|
||||||
"uuid = %s", uuid,
|
|
||||||
"token = %s", "skip",
|
|
||||||
"pid = " FMTd64, (int64_t)getpid(),
|
|
||||||
"cmd = %s", "lvmetactl",
|
|
||||||
NULL);
|
|
||||||
printf("%s\n", reply.buffer.mem);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
printf("unknown command\n");
|
|
||||||
goto out_close;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
daemon_reply_destroy(reply);
|
|
||||||
out_close:
|
|
||||||
daemon_close(h);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2011-2012 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of LVM2.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU Lesser General Public License v.2.1.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LVM_LVMETAD_CLIENT_H
|
|
||||||
#define _LVM_LVMETAD_CLIENT_H
|
|
||||||
|
|
||||||
#include "daemon-client.h"
|
|
||||||
|
|
||||||
#define LVMETAD_SOCKET DEFAULT_RUN_DIR "/lvmetad.socket"
|
|
||||||
|
|
||||||
#define LVMETAD_TOKEN_UPDATE_IN_PROGRESS "update in progress"
|
|
||||||
|
|
||||||
#define LVMETAD_DISABLE_REASON_DIRECT "DIRECT"
|
|
||||||
#define LVMETAD_DISABLE_REASON_DUPLICATES "DUPLICATES"
|
|
||||||
#define LVMETAD_DISABLE_REASON_VGRESTORE "VGRESTORE"
|
|
||||||
#define LVMETAD_DISABLE_REASON_REPAIR "REPAIR"
|
|
||||||
|
|
||||||
struct volume_group;
|
|
||||||
|
|
||||||
/* Different types of replies we may get from lvmetad. */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
daemon_reply r;
|
|
||||||
const char **uuids; /* NULL terminated array */
|
|
||||||
} lvmetad_uuidlist;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
daemon_reply r;
|
|
||||||
struct dm_config_tree *cft;
|
|
||||||
} lvmetad_vg;
|
|
||||||
|
|
||||||
/* Get a list of VG UUIDs that match a given VG name. */
|
|
||||||
lvmetad_uuidlist lvmetad_lookup_vgname(daemon_handle h, const char *name);
|
|
||||||
|
|
||||||
/* Get the metadata of a single VG, identified by UUID. */
|
|
||||||
lvmetad_vg lvmetad_get_vg(daemon_handle h, const char *uuid);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add and remove PVs on demand. Udev-driven systems will use this interface
|
|
||||||
* instead of scanning.
|
|
||||||
*/
|
|
||||||
daemon_reply lvmetad_add_pv(daemon_handle h, const char *pv_uuid, const char *mda_content);
|
|
||||||
daemon_reply lvmetad_remove_pv(daemon_handle h, const char *pv_uuid);
|
|
||||||
|
|
||||||
/* Trigger a full disk scan, throwing away all caches. XXX do we eventually want
|
|
||||||
* this? Probably not yet, anyway.
|
|
||||||
* daemon_reply lvmetad_rescan(daemon_handle h);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update the version of metadata of a volume group. The VG has to be locked for
|
|
||||||
* writing for this, and the VG metadata here has to match whatever has been
|
|
||||||
* written to the disk (under this lock). This initially avoids the requirement
|
|
||||||
* for lvmetad to write to disk (in later revisions, lvmetad_supersede_vg may
|
|
||||||
* also do the writing, or we probably add another function to do that).
|
|
||||||
*/
|
|
||||||
daemon_reply lvmetad_supersede_vg(daemon_handle h, struct volume_group *vg);
|
|
||||||
|
|
||||||
/* Wrappers to open/close connection */
|
|
||||||
|
|
||||||
static inline daemon_handle lvmetad_open(const char *socket)
|
|
||||||
{
|
|
||||||
daemon_info lvmetad_info = {
|
|
||||||
.path = "lvmetad",
|
|
||||||
.socket = socket ?: LVMETAD_SOCKET,
|
|
||||||
.protocol = "lvmetad",
|
|
||||||
.protocol_version = 1,
|
|
||||||
.autostart = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
return daemon_open(lvmetad_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void lvmetad_close(daemon_handle h)
|
|
||||||
{
|
|
||||||
return daemon_close(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
|
|
||||||
test -n "$2" && {
|
|
||||||
rm -f /var/run/lvmetad.{socket,pid}
|
|
||||||
chmod +rx lvmetad
|
|
||||||
valgrind ./lvmetad -f &
|
|
||||||
PID=$!
|
|
||||||
sleep 1
|
|
||||||
./testclient
|
|
||||||
kill $PID
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
sudo ./test.sh "$1" .
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2011-2014 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 General Public License v.2.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#include "tool.h"
|
|
||||||
|
|
||||||
#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];
|
|
||||||
if (!id_write_format(dev->pvid, uuid, 64)) {
|
|
||||||
fprintf(stderr, "[C] Failed to format PV UUID for %s", dev_name(dev));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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();
|
|
||||||
/* FIXME Missing error path */
|
|
||||||
|
|
||||||
if (argc > 1) {
|
|
||||||
int i;
|
|
||||||
struct cmd_context *cmd = create_toolcontext(0, NULL, 0, 0, 1, 1);
|
|
||||||
for (i = 1; i < argc; ++i) {
|
|
||||||
const char *uuid = NULL;
|
|
||||||
scan(h, argv[i]);
|
|
||||||
}
|
|
||||||
destroy_toolcontext(cmd);
|
|
||||||
/* FIXME Missing lvmetad_close() */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_pv_add(h, uuid1, NULL);
|
|
||||||
_pv_add(h, uuid2, metadata2);
|
|
||||||
_dump_vg(h, vgid);
|
|
||||||
_pv_add(h, uuid3, NULL);
|
|
||||||
|
|
||||||
daemon_close(h); /* FIXME lvmetad_close? */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,8 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
|
USE_SD_NOTIFY=yes
|
||||||
|
|
||||||
SOURCES = lvmlockd-core.c
|
SOURCES = lvmlockd-core.c
|
||||||
|
|
||||||
ifeq ("@BUILD_LOCKDSANLOCK@", "yes")
|
ifeq ("@BUILD_LOCKDSANLOCK@", "yes")
|
||||||
@@ -25,6 +27,7 @@ endif
|
|||||||
ifeq ("@BUILD_LOCKDDLM@", "yes")
|
ifeq ("@BUILD_LOCKDDLM@", "yes")
|
||||||
SOURCES += lvmlockd-dlm.c
|
SOURCES += lvmlockd-dlm.c
|
||||||
LOCK_LIBS += -ldlm_lt
|
LOCK_LIBS += -ldlm_lt
|
||||||
|
LOCK_LIBS += -ldlmcontrol
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SOURCES2 = lvmlockctl.c
|
SOURCES2 = lvmlockctl.c
|
||||||
@@ -38,20 +41,30 @@ include $(top_builddir)/make.tmpl
|
|||||||
CFLAGS += $(EXTRA_EXEC_CFLAGS)
|
CFLAGS += $(EXTRA_EXEC_CFLAGS)
|
||||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||||
LIBS += $(RT_LIBS) $(DAEMON_LIBS) -ldevmapper $(PTHREAD_LIBS)
|
LIBS += $(RT_LIBS) $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(USE_SD_NOTIFY),yes)
|
||||||
|
CFLAGS += $(shell pkg-config --cflags libsystemd) -DUSE_SD_NOTIFY
|
||||||
|
LIBS += $(shell pkg-config --libs libsystemd)
|
||||||
|
endif
|
||||||
|
|
||||||
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
||||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LOCK_LIBS) -ldaemonserver $(LIBS)
|
@echo " [CC] $@"
|
||||||
|
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LOCK_LIBS) -ldaemonserver $(INTERNAL_LIBS) $(LIBS)
|
||||||
|
|
||||||
lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a
|
lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(LIBS)
|
@echo " [CC] $@"
|
||||||
|
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(INTERNAL_LIBS) $(LIBS)
|
||||||
|
|
||||||
install_lvmlockd: lvmlockd
|
install_lvmlockd: lvmlockd
|
||||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||||
|
|
||||||
install_lvmlockctl: lvmlockctl
|
install_lvmlockctl: lvmlockctl
|
||||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||||
|
|
||||||
install_lvm2: install_lvmlockd install_lvmlockctl
|
install_lvm2: install_lvmlockd install_lvmlockctl
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
* of the GNU Lesser General Public License v.2.1.
|
* of the GNU Lesser General Public License v.2.1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tool.h"
|
#include "tools/tool.h"
|
||||||
|
|
||||||
#include "lvmlockd-client.h"
|
#include "daemons/lvmlockd/lvmlockd-client.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
static int quit = 0;
|
static int quit = 0;
|
||||||
static int info = 0;
|
static int info = 0;
|
||||||
static int dump = 0;
|
static int dump = 0;
|
||||||
static int wait_opt = 0;
|
static int wait_opt = 1;
|
||||||
static int force_opt = 0;
|
static int force_opt = 0;
|
||||||
static int kill_vg = 0;
|
static int kill_vg = 0;
|
||||||
static int drop_vg = 0;
|
static int drop_vg = 0;
|
||||||
@@ -280,13 +280,12 @@ static void format_info_line(char *line, char *r_name, char *r_type)
|
|||||||
|
|
||||||
static void format_info(void)
|
static void format_info(void)
|
||||||
{
|
{
|
||||||
char line[MAX_LINE];
|
char line[MAX_LINE] = { 0 };
|
||||||
char r_name[MAX_NAME+1];
|
char r_name[MAX_NAME+1] = { 0 };
|
||||||
char r_type[MAX_NAME+1];
|
char r_type[MAX_NAME+1] = { 0 };
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
memset(line, 0, sizeof(line));
|
|
||||||
|
|
||||||
for (i = 0; i < dump_len; i++) {
|
for (i = 0; i < dump_len; i++) {
|
||||||
line[j++] = dump_buf[i];
|
line[j++] = dump_buf[i];
|
||||||
@@ -326,6 +325,8 @@ static int _lvmlockd_result(daemon_reply reply, int *result)
|
|||||||
{
|
{
|
||||||
int reply_result;
|
int reply_result;
|
||||||
|
|
||||||
|
*result = NO_LOCKD_RESULT;
|
||||||
|
|
||||||
if (reply.error) {
|
if (reply.error) {
|
||||||
log_error("lvmlockd_result reply error %d", reply.error);
|
log_error("lvmlockd_result reply error %d", reply.error);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -337,7 +338,7 @@ static int _lvmlockd_result(daemon_reply reply, int *result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reply_result = daemon_reply_int(reply, "op_result", NO_LOCKD_RESULT);
|
reply_result = daemon_reply_int(reply, "op_result", NO_LOCKD_RESULT);
|
||||||
if (reply_result == -1000) {
|
if (reply_result == NO_LOCKD_RESULT) {
|
||||||
log_error("lvmlockd_result no op_result");
|
log_error("lvmlockd_result no op_result");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,10 @@
|
|||||||
#ifndef _LVM_LVMLOCKD_CLIENT_H
|
#ifndef _LVM_LVMLOCKD_CLIENT_H
|
||||||
#define _LVM_LVMLOCKD_CLIENT_H
|
#define _LVM_LVMLOCKD_CLIENT_H
|
||||||
|
|
||||||
#include "daemon-client.h"
|
#include "libdaemon/client/daemon-client.h"
|
||||||
|
|
||||||
#define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket"
|
#define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket"
|
||||||
|
#define LVMLOCKD_ADOPT_FILE DEFAULT_RUN_DIR "/lvmlockd.adopt"
|
||||||
|
|
||||||
/* Wrappers to open/close connection */
|
/* Wrappers to open/close connection */
|
||||||
|
|
||||||
@@ -22,9 +23,9 @@ static inline daemon_handle lvmlockd_open(const char *sock)
|
|||||||
daemon_info lvmlockd_info = {
|
daemon_info lvmlockd_info = {
|
||||||
.path = "lvmlockd",
|
.path = "lvmlockd",
|
||||||
.socket = sock ?: LVMLOCKD_SOCKET,
|
.socket = sock ?: LVMLOCKD_SOCKET,
|
||||||
|
.autostart = 0,
|
||||||
.protocol = "lvmlockd",
|
.protocol = "lvmlockd",
|
||||||
.protocol_version = 1,
|
.protocol_version = 1,
|
||||||
.autostart = 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return daemon_open(lvmlockd_info);
|
return daemon_open(lvmlockd_info);
|
||||||
@@ -32,7 +33,7 @@ static inline daemon_handle lvmlockd_open(const char *sock)
|
|||||||
|
|
||||||
static inline void lvmlockd_close(daemon_handle h)
|
static inline void lvmlockd_close(daemon_handle h)
|
||||||
{
|
{
|
||||||
return daemon_close(h);
|
daemon_close(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -8,18 +8,13 @@
|
|||||||
* of the GNU Lesser General Public License v.2.1.
|
* of the GNU Lesser General Public License v.2.1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _XOPEN_SOURCE 500 /* pthread */
|
#include "tools/tool.h"
|
||||||
#define _ISOC99_SOURCE
|
|
||||||
#define _REENTRANT
|
|
||||||
|
|
||||||
#include "tool.h"
|
#include "libdaemon/client/daemon-io.h"
|
||||||
|
|
||||||
#include "daemon-io.h"
|
|
||||||
#include "daemon-server.h"
|
#include "daemon-server.h"
|
||||||
#include "lvm-version.h"
|
#include "lvm-version.h"
|
||||||
#include "lvmetad-client.h"
|
#include "daemons/lvmlockd/lvmlockd-client.h"
|
||||||
#include "lvmlockd-client.h"
|
#include "device_mapper/misc/dm-ioctl.h"
|
||||||
#include "dm-ioctl.h" /* for DM_UUID_LEN */
|
|
||||||
|
|
||||||
/* #include <assert.h> */
|
/* #include <assert.h> */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -36,9 +31,15 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#ifdef USE_SD_NOTIFY
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define EXTERN
|
#define EXTERN
|
||||||
#include "lvmlockd-internal.h"
|
#include "lvmlockd-internal.h"
|
||||||
|
|
||||||
|
static int str_to_mode(const char *str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Basic operation of lvmlockd
|
* Basic operation of lvmlockd
|
||||||
*
|
*
|
||||||
@@ -143,10 +144,8 @@ static const char *lvmlockd_protocol = "lvmlockd";
|
|||||||
static const int lvmlockd_protocol_version = 1;
|
static const int lvmlockd_protocol_version = 1;
|
||||||
static int daemon_quit;
|
static int daemon_quit;
|
||||||
static int adopt_opt;
|
static int adopt_opt;
|
||||||
|
static uint32_t adopt_update_count;
|
||||||
static daemon_handle lvmetad_handle;
|
static const char *adopt_file;
|
||||||
static pthread_mutex_t lvmetad_mutex;
|
|
||||||
static int lvmetad_connected;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use a separate socket for dumping daemon info.
|
* We use a separate socket for dumping daemon info.
|
||||||
@@ -410,12 +409,11 @@ struct lockspace *alloc_lockspace(void)
|
|||||||
{
|
{
|
||||||
struct lockspace *ls;
|
struct lockspace *ls;
|
||||||
|
|
||||||
if (!(ls = malloc(sizeof(struct lockspace)))) {
|
if (!(ls = zalloc(sizeof(struct lockspace)))) {
|
||||||
log_error("out of memory for lockspace");
|
log_error("out of memory for lockspace");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(ls, 0, sizeof(struct lockspace));
|
|
||||||
INIT_LIST_HEAD(&ls->actions);
|
INIT_LIST_HEAD(&ls->actions);
|
||||||
INIT_LIST_HEAD(&ls->resources);
|
INIT_LIST_HEAD(&ls->resources);
|
||||||
pthread_mutex_init(&ls->mutex, NULL);
|
pthread_mutex_init(&ls->mutex, NULL);
|
||||||
@@ -508,6 +506,10 @@ static struct lock *alloc_lock(void)
|
|||||||
|
|
||||||
static void free_action(struct action *act)
|
static void free_action(struct action *act)
|
||||||
{
|
{
|
||||||
|
if (act->path) {
|
||||||
|
free(act->path);
|
||||||
|
act->path = NULL;
|
||||||
|
}
|
||||||
pthread_mutex_lock(&unused_struct_mutex);
|
pthread_mutex_lock(&unused_struct_mutex);
|
||||||
if (unused_action_count >= MAX_UNUSED_ACTION) {
|
if (unused_action_count >= MAX_UNUSED_ACTION) {
|
||||||
free(act);
|
free(act);
|
||||||
@@ -731,6 +733,8 @@ static const char *op_str(int x)
|
|||||||
return "rename_final";
|
return "rename_final";
|
||||||
case LD_OP_RUNNING_LM:
|
case LD_OP_RUNNING_LM:
|
||||||
return "running_lm";
|
return "running_lm";
|
||||||
|
case LD_OP_QUERY_LOCK:
|
||||||
|
return "query_lock";
|
||||||
case LD_OP_FIND_FREE_LOCK:
|
case LD_OP_FIND_FREE_LOCK:
|
||||||
return "find_free_lock";
|
return "find_free_lock";
|
||||||
case LD_OP_KILL_VG:
|
case LD_OP_KILL_VG:
|
||||||
@@ -743,6 +747,8 @@ static const char *op_str(int x)
|
|||||||
return "dump_info";
|
return "dump_info";
|
||||||
case LD_OP_BUSY:
|
case LD_OP_BUSY:
|
||||||
return "busy";
|
return "busy";
|
||||||
|
case LD_OP_REFRESH_LV:
|
||||||
|
return "refresh_lv";
|
||||||
default:
|
default:
|
||||||
return "op_unknown";
|
return "op_unknown";
|
||||||
};
|
};
|
||||||
@@ -809,6 +815,144 @@ int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsi
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write new info when a command exits if that command has acquired a new LV
|
||||||
|
* lock. If the command has released an LV lock we don't bother updating the
|
||||||
|
* info. When adopting, we eliminate any LV lock adoptions if there is no dm
|
||||||
|
* device for that LV. If lvmlockd is terminated after acquiring but before
|
||||||
|
* writing this file, those LV locks would not be adopted on restart.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ADOPT_VERSION_MAJOR 1
|
||||||
|
#define ADOPT_VERSION_MINOR 0
|
||||||
|
|
||||||
|
static void write_adopt_file(void)
|
||||||
|
{
|
||||||
|
struct lockspace *ls;
|
||||||
|
struct resource *r;
|
||||||
|
struct lock *lk;
|
||||||
|
time_t t;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (!(fp = fopen(adopt_file, "w")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
adopt_update_count++;
|
||||||
|
|
||||||
|
t = time(NULL);
|
||||||
|
fprintf(fp, "lvmlockd adopt_version %u.%u pid %d updates %u %s",
|
||||||
|
ADOPT_VERSION_MAJOR, ADOPT_VERSION_MINOR, getpid(), adopt_update_count, ctime(&t));
|
||||||
|
|
||||||
|
pthread_mutex_lock(&lockspaces_mutex);
|
||||||
|
list_for_each_entry(ls, &lockspaces, list) {
|
||||||
|
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
|
||||||
|
continue;
|
||||||
|
fprintf(fp, "VG: %38s %s %s %s\n",
|
||||||
|
ls->vg_uuid, ls->vg_name, lm_str(ls->lm_type), ls->vg_args);
|
||||||
|
list_for_each_entry(r, &ls->resources, list) {
|
||||||
|
if (r->type != LD_RT_LV)
|
||||||
|
continue;
|
||||||
|
if ((r->mode != LD_LK_EX) && (r->mode != LD_LK_SH))
|
||||||
|
continue;
|
||||||
|
list_for_each_entry(lk, &r->locks, list) {
|
||||||
|
fprintf(fp, "LV: %38s %s %s %s %u\n",
|
||||||
|
ls->vg_uuid, r->name, r->lv_args, mode_str(r->mode), r->version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lockspaces_mutex);
|
||||||
|
|
||||||
|
fflush(fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_adopt_file(struct list_head *vg_lockd)
|
||||||
|
{
|
||||||
|
char adopt_line[512];
|
||||||
|
char vg_uuid[72];
|
||||||
|
char lm_type_str[16];
|
||||||
|
char mode[8];
|
||||||
|
struct lockspace *ls, *ls2;
|
||||||
|
struct resource *r;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (MAX_ARGS != 64 || MAX_NAME != 64)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!(fp = fopen(adopt_file, "r")))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (fgets(adopt_line, sizeof(adopt_line), fp)) {
|
||||||
|
if (adopt_line[0] == '#')
|
||||||
|
continue;
|
||||||
|
else if (!strncmp(adopt_line, "lvmlockd", 8)) {
|
||||||
|
unsigned int v_major = 0, v_minor = 0;
|
||||||
|
if ((sscanf(adopt_line, "lvmlockd adopt_version %u.%u", &v_major, &v_minor) != 2) ||
|
||||||
|
(v_major != ADOPT_VERSION_MAJOR))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
} else if (!strncmp(adopt_line, "VG:", 3)) {
|
||||||
|
if (!(ls = alloc_lockspace()))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
memset(vg_uuid, 0, sizeof(vg_uuid));
|
||||||
|
|
||||||
|
if (sscanf(adopt_line, "VG: %63s %64s %16s %64s",
|
||||||
|
vg_uuid, ls->vg_name, lm_type_str, ls->vg_args) != 4) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ls->vg_uuid, vg_uuid, 64);
|
||||||
|
|
||||||
|
if ((ls->lm_type = str_to_lm(lm_type_str)) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
list_add(&ls->list, vg_lockd);
|
||||||
|
|
||||||
|
} else if (!strncmp(adopt_line, "LV:", 3)) {
|
||||||
|
if (!(r = alloc_resource()))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
r->type = LD_RT_LV;
|
||||||
|
|
||||||
|
memset(vg_uuid, 0, sizeof(vg_uuid));
|
||||||
|
|
||||||
|
if (sscanf(adopt_line, "LV: %64s %64s %s %8s %u",
|
||||||
|
vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((r->adopt_mode = str_to_mode(mode)) == LD_LK_IV)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (ls && !memcmp(ls->vg_uuid, vg_uuid, 64)) {
|
||||||
|
list_add(&r->list, &ls->resources);
|
||||||
|
r = NULL;
|
||||||
|
} else {
|
||||||
|
list_for_each_entry(ls2, vg_lockd, list) {
|
||||||
|
if (memcmp(ls2->vg_uuid, vg_uuid, 64))
|
||||||
|
continue;
|
||||||
|
list_add(&r->list, &ls2->resources);
|
||||||
|
r = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
log_error("No lockspace found for resource %s vg_uuid %s", r->name, vg_uuid);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are few enough that arrays of function pointers can
|
* These are few enough that arrays of function pointers can
|
||||||
* be avoided.
|
* be avoided.
|
||||||
@@ -930,12 +1074,12 @@ static void lm_rem_resource(struct lockspace *ls, struct resource *r)
|
|||||||
lm_rem_resource_sanlock(ls, r);
|
lm_rem_resource_sanlock(ls, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset)
|
static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
|
||||||
{
|
{
|
||||||
if (ls->lm_type == LD_LM_DLM)
|
if (ls->lm_type == LD_LM_DLM)
|
||||||
return 0;
|
return 0;
|
||||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||||
return lm_find_free_lock_sanlock(ls, free_offset);
|
return lm_find_free_lock_sanlock(ls, free_offset, sector_size, align_size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,54 +1153,6 @@ static void add_work_action(struct action *act)
|
|||||||
pthread_mutex_unlock(&worker_mutex);
|
pthread_mutex_unlock(&worker_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ERR_LVMETAD_NOT_RUNNING -200
|
|
||||||
|
|
||||||
static daemon_reply send_lvmetad(const char *id, ...)
|
|
||||||
{
|
|
||||||
daemon_reply reply;
|
|
||||||
va_list ap;
|
|
||||||
int retries = 0;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
va_start(ap, id);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* mutex is used because all threads share a single
|
|
||||||
* lvmetad connection/handle.
|
|
||||||
*/
|
|
||||||
pthread_mutex_lock(&lvmetad_mutex);
|
|
||||||
retry:
|
|
||||||
if (!lvmetad_connected) {
|
|
||||||
lvmetad_handle = lvmetad_open(NULL);
|
|
||||||
if (lvmetad_handle.error || lvmetad_handle.socket_fd < 0) {
|
|
||||||
err = lvmetad_handle.error ?: lvmetad_handle.socket_fd;
|
|
||||||
pthread_mutex_unlock(&lvmetad_mutex);
|
|
||||||
log_debug("lvmetad_open reconnect error %d", err);
|
|
||||||
memset(&reply, 0, sizeof(reply));
|
|
||||||
reply.error = ERR_LVMETAD_NOT_RUNNING;
|
|
||||||
va_end(ap);
|
|
||||||
return reply;
|
|
||||||
} else {
|
|
||||||
log_debug("lvmetad reconnected");
|
|
||||||
lvmetad_connected = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reply = daemon_send_simple_v(lvmetad_handle, id, ap);
|
|
||||||
|
|
||||||
/* lvmetad may have been restarted */
|
|
||||||
if ((reply.error == ECONNRESET) && (retries < 2)) {
|
|
||||||
daemon_close(lvmetad_handle);
|
|
||||||
lvmetad_connected = 0;
|
|
||||||
retries++;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&lvmetad_mutex);
|
|
||||||
|
|
||||||
va_end(ap);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int res_lock(struct lockspace *ls, struct resource *r, struct action *act, int *retry)
|
static int res_lock(struct lockspace *ls, struct resource *r, struct action *act, int *retry)
|
||||||
{
|
{
|
||||||
struct lock *lk;
|
struct lock *lk;
|
||||||
@@ -1252,6 +1348,18 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
|
|||||||
rv = -EREMOVED;
|
rv = -EREMOVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lvmetad is no longer used, but the infrastructure for
|
||||||
|
* distributed cache validation remains. The points
|
||||||
|
* where vg or global cache state would be invalidated
|
||||||
|
* remain below and log_debug messages point out where
|
||||||
|
* they would occur.
|
||||||
|
*
|
||||||
|
* The comments related to "lvmetad" remain because they
|
||||||
|
* describe how some other local cache like lvmetad would
|
||||||
|
* be invalidated here.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* r is vglk: tell lvmetad to set the vg invalid
|
* r is vglk: tell lvmetad to set the vg invalid
|
||||||
* flag, and provide the new r_version. If lvmetad finds
|
* flag, and provide the new r_version. If lvmetad finds
|
||||||
@@ -1277,47 +1385,12 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (inval_meta && (r->type == LD_RT_VG)) {
|
if (inval_meta && (r->type == LD_RT_VG)) {
|
||||||
daemon_reply reply;
|
log_debug("S %s R %s res_lock invalidate vg state version %u",
|
||||||
char *uuid;
|
|
||||||
|
|
||||||
log_debug("S %s R %s res_lock set lvmetad vg version %u",
|
|
||||||
ls->name, r->name, new_version);
|
ls->name, r->name, new_version);
|
||||||
|
|
||||||
if (!ls->vg_uuid[0] || !strcmp(ls->vg_uuid, "none"))
|
|
||||||
uuid = (char *)"none";
|
|
||||||
else
|
|
||||||
uuid = ls->vg_uuid;
|
|
||||||
|
|
||||||
reply = send_lvmetad("set_vg_info",
|
|
||||||
"token = %s", "skip",
|
|
||||||
"uuid = %s", uuid,
|
|
||||||
"name = %s", ls->vg_name,
|
|
||||||
"version = " FMTd64, (int64_t)new_version,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
|
|
||||||
if (reply.error != ERR_LVMETAD_NOT_RUNNING)
|
|
||||||
log_error("set_vg_info in lvmetad failed %d", reply.error);
|
|
||||||
}
|
|
||||||
daemon_reply_destroy(reply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inval_meta && (r->type == LD_RT_GL)) {
|
if (inval_meta && (r->type == LD_RT_GL)) {
|
||||||
daemon_reply reply;
|
log_debug("S %s R %s res_lock invalidate global state", ls->name, r->name);
|
||||||
|
|
||||||
log_debug("S %s R %s res_lock set lvmetad global invalid",
|
|
||||||
ls->name, r->name);
|
|
||||||
|
|
||||||
reply = send_lvmetad("set_global_info",
|
|
||||||
"token = %s", "skip",
|
|
||||||
"global_invalid = " FMTd64, INT64_C(1),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
|
|
||||||
if (reply.error != ERR_LVMETAD_NOT_RUNNING)
|
|
||||||
log_error("set_global_info in lvmetad failed %d", reply.error);
|
|
||||||
}
|
|
||||||
daemon_reply_destroy(reply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1891,9 +1964,9 @@ static void res_process(struct lockspace *ls, struct resource *r,
|
|||||||
add_client_result(act);
|
add_client_result(act);
|
||||||
} else {
|
} else {
|
||||||
/* persistent lock is sh, transient request is ex */
|
/* persistent lock is sh, transient request is ex */
|
||||||
/* FIXME: can we remove this case? do a convert here? */
|
|
||||||
log_debug("res_process %s existing persistent lock new transient", r->name);
|
log_debug("res_process %s existing persistent lock new transient", r->name);
|
||||||
r->last_client_id = act->client_id;
|
r->last_client_id = act->client_id;
|
||||||
|
act->flags |= LD_AF_SH_EXISTS;
|
||||||
act->result = -EEXIST;
|
act->result = -EEXIST;
|
||||||
list_del(&act->list);
|
list_del(&act->list);
|
||||||
add_client_result(act);
|
add_client_result(act);
|
||||||
@@ -2273,6 +2346,7 @@ static int process_op_during_kill(struct action *act)
|
|||||||
case LD_OP_UPDATE:
|
case LD_OP_UPDATE:
|
||||||
case LD_OP_RENAME_BEFORE:
|
case LD_OP_RENAME_BEFORE:
|
||||||
case LD_OP_RENAME_FINAL:
|
case LD_OP_RENAME_FINAL:
|
||||||
|
case LD_OP_QUERY_LOCK:
|
||||||
case LD_OP_FIND_FREE_LOCK:
|
case LD_OP_FIND_FREE_LOCK:
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
@@ -2298,7 +2372,7 @@ static void *lockspace_thread_main(void *arg_in)
|
|||||||
struct action *act_op_free = NULL;
|
struct action *act_op_free = NULL;
|
||||||
struct list_head tmp_act;
|
struct list_head tmp_act;
|
||||||
struct list_head act_close;
|
struct list_head act_close;
|
||||||
char tmp_name[MAX_NAME+1];
|
char tmp_name[MAX_NAME+5];
|
||||||
int free_vg = 0;
|
int free_vg = 0;
|
||||||
int drop_vg = 0;
|
int drop_vg = 0;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
@@ -2497,13 +2571,31 @@ static void *lockspace_thread_main(void *arg_in)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (act->op == LD_OP_QUERY_LOCK) {
|
||||||
|
r = find_resource_act(ls, act, 0);
|
||||||
|
if (!r)
|
||||||
|
act->result = -ENOENT;
|
||||||
|
else {
|
||||||
|
act->result = 0;
|
||||||
|
act->mode = r->mode;
|
||||||
|
}
|
||||||
|
list_del(&act->list);
|
||||||
|
add_client_result(act);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (act->op == LD_OP_FIND_FREE_LOCK && act->rt == LD_RT_VG) {
|
if (act->op == LD_OP_FIND_FREE_LOCK && act->rt == LD_RT_VG) {
|
||||||
uint64_t free_offset = 0;
|
uint64_t free_offset = 0;
|
||||||
|
int sector_size = 0;
|
||||||
|
int align_size = 0;
|
||||||
|
|
||||||
log_debug("S %s find free lock", ls->name);
|
log_debug("S %s find free lock", ls->name);
|
||||||
rv = lm_find_free_lock(ls, &free_offset);
|
rv = lm_find_free_lock(ls, &free_offset, §or_size, &align_size);
|
||||||
log_debug("S %s find free lock %d offset %llu",
|
log_debug("S %s find free lock %d offset %llu sector_size %d align_size %d",
|
||||||
ls->name, rv, (unsigned long long)free_offset);
|
ls->name, rv, (unsigned long long)free_offset, sector_size, align_size);
|
||||||
ls->free_lock_offset = free_offset;
|
ls->free_lock_offset = free_offset;
|
||||||
|
ls->free_lock_sector_size = sector_size;
|
||||||
|
ls->free_lock_align_size = align_size;
|
||||||
list_del(&act->list);
|
list_del(&act->list);
|
||||||
act->result = rv;
|
act->result = rv;
|
||||||
add_client_result(act);
|
add_client_result(act);
|
||||||
@@ -2674,8 +2766,10 @@ out_act:
|
|||||||
* blank or fill it with garbage, but instead set it to REM:<name>
|
* blank or fill it with garbage, but instead set it to REM:<name>
|
||||||
* to make it easier to follow progress of freeing is via log_debug.
|
* to make it easier to follow progress of freeing is via log_debug.
|
||||||
*/
|
*/
|
||||||
dm_strncpy(tmp_name, ls->name, sizeof(tmp_name));
|
memset(tmp_name, 0, sizeof(tmp_name));
|
||||||
snprintf(ls->name, sizeof(ls->name), "REM:%s", tmp_name);
|
memcpy(tmp_name, "REM:", 4);
|
||||||
|
strncpy(tmp_name+4, ls->name, sizeof(tmp_name)-4);
|
||||||
|
memcpy(ls->name, tmp_name, sizeof(ls->name));
|
||||||
pthread_mutex_unlock(&lockspaces_mutex);
|
pthread_mutex_unlock(&lockspaces_mutex);
|
||||||
|
|
||||||
/* worker_thread will join this thread, and free the ls */
|
/* worker_thread will join this thread, and free the ls */
|
||||||
@@ -3312,6 +3406,8 @@ static int work_init_lv(struct action *act)
|
|||||||
char vg_args[MAX_ARGS+1];
|
char vg_args[MAX_ARGS+1];
|
||||||
char lv_args[MAX_ARGS+1];
|
char lv_args[MAX_ARGS+1];
|
||||||
uint64_t free_offset = 0;
|
uint64_t free_offset = 0;
|
||||||
|
int sector_size = 0;
|
||||||
|
int align_size = 0;
|
||||||
int lm_type = 0;
|
int lm_type = 0;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
@@ -3327,6 +3423,8 @@ static int work_init_lv(struct action *act)
|
|||||||
lm_type = ls->lm_type;
|
lm_type = ls->lm_type;
|
||||||
memcpy(vg_args, ls->vg_args, MAX_ARGS);
|
memcpy(vg_args, ls->vg_args, MAX_ARGS);
|
||||||
free_offset = ls->free_lock_offset;
|
free_offset = ls->free_lock_offset;
|
||||||
|
sector_size = ls->free_lock_sector_size;
|
||||||
|
align_size = ls->free_lock_align_size;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&lockspaces_mutex);
|
pthread_mutex_unlock(&lockspaces_mutex);
|
||||||
|
|
||||||
@@ -3343,7 +3441,7 @@ static int work_init_lv(struct action *act)
|
|||||||
|
|
||||||
if (lm_type == LD_LM_SANLOCK) {
|
if (lm_type == LD_LM_SANLOCK) {
|
||||||
rv = lm_init_lv_sanlock(ls_name, act->vg_name, act->lv_uuid,
|
rv = lm_init_lv_sanlock(ls_name, act->vg_name, act->lv_uuid,
|
||||||
vg_args, lv_args, free_offset);
|
vg_args, lv_args, sector_size, align_size, free_offset);
|
||||||
|
|
||||||
memcpy(act->lv_args, lv_args, MAX_ARGS);
|
memcpy(act->lv_args, lv_args, MAX_ARGS);
|
||||||
return rv;
|
return rv;
|
||||||
@@ -3473,6 +3571,15 @@ static void *worker_thread_main(void *arg_in)
|
|||||||
else
|
else
|
||||||
list_add(&act->list, &delayed_list);
|
list_add(&act->list, &delayed_list);
|
||||||
|
|
||||||
|
} else if (act->op == LD_OP_REFRESH_LV) {
|
||||||
|
log_debug("work refresh_lv %s %s", act->lv_uuid, act->path);
|
||||||
|
rv = lm_refresh_lv_start_dlm(act);
|
||||||
|
if (rv < 0) {
|
||||||
|
act->result = rv;
|
||||||
|
add_client_result(act);
|
||||||
|
} else
|
||||||
|
list_add(&act->list, &delayed_list);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log_error("work unknown op %d", act->op);
|
log_error("work unknown op %d", act->op);
|
||||||
act->result = -EINVAL;
|
act->result = -EINVAL;
|
||||||
@@ -3508,6 +3615,19 @@ static void *worker_thread_main(void *arg_in)
|
|||||||
act->result = 0;
|
act->result = 0;
|
||||||
add_client_result(act);
|
add_client_result(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (act->op == LD_OP_REFRESH_LV) {
|
||||||
|
log_debug("work delayed refresh_lv");
|
||||||
|
rv = lm_refresh_lv_check_dlm(act);
|
||||||
|
if (!rv) {
|
||||||
|
list_del(&act->list);
|
||||||
|
act->result = 0;
|
||||||
|
add_client_result(act);
|
||||||
|
} else if ((rv < 0) && (rv != -EAGAIN)) {
|
||||||
|
list_del(&act->list);
|
||||||
|
act->result = rv;
|
||||||
|
add_client_result(act);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3713,6 +3833,9 @@ static int client_send_result(struct client *cl, struct action *act)
|
|||||||
if ((act->flags & LD_AF_WARN_GL_REMOVED) || gl_vg_removed)
|
if ((act->flags & LD_AF_WARN_GL_REMOVED) || gl_vg_removed)
|
||||||
strcat(result_flags, "WARN_GL_REMOVED,");
|
strcat(result_flags, "WARN_GL_REMOVED,");
|
||||||
|
|
||||||
|
if (act->flags & LD_AF_SH_EXISTS)
|
||||||
|
strcat(result_flags, "SH_EXISTS,");
|
||||||
|
|
||||||
if (act->op == LD_OP_INIT) {
|
if (act->op == LD_OP_INIT) {
|
||||||
/*
|
/*
|
||||||
* init is a special case where lock args need
|
* init is a special case where lock args need
|
||||||
@@ -3741,6 +3864,20 @@ static int client_send_result(struct client *cl, struct action *act)
|
|||||||
"result_flags = %s", result_flags[0] ? result_flags : "none",
|
"result_flags = %s", result_flags[0] ? result_flags : "none",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
} else if (act->op == LD_OP_QUERY_LOCK) {
|
||||||
|
|
||||||
|
log_debug("send %s[%d] cl %u %s %s rv %d mode %d",
|
||||||
|
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
|
||||||
|
op_str(act->op), rt_str(act->rt),
|
||||||
|
act->result, act->mode);
|
||||||
|
|
||||||
|
res = daemon_reply_simple("OK",
|
||||||
|
"op = " FMTd64, (int64_t)act->op,
|
||||||
|
"op_result = " FMTd64, (int64_t) act->result,
|
||||||
|
"lock_type = %s", lm_str(act->lm_type),
|
||||||
|
"mode = %s", mode_str(act->mode),
|
||||||
|
NULL);
|
||||||
|
|
||||||
} else if (act->op == LD_OP_DUMP_LOG || act->op == LD_OP_DUMP_INFO) {
|
} else if (act->op == LD_OP_DUMP_LOG || act->op == LD_OP_DUMP_INFO) {
|
||||||
/*
|
/*
|
||||||
* lvmlockctl creates the unix socket then asks us to write to it.
|
* lvmlockctl creates the unix socket then asks us to write to it.
|
||||||
@@ -4071,6 +4208,16 @@ static int str_to_op_rt(const char *req_name, int *op, int *rt)
|
|||||||
*rt = 0;
|
*rt = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(req_name, "query_lock_vg")) {
|
||||||
|
*op = LD_OP_QUERY_LOCK;
|
||||||
|
*rt = LD_RT_VG;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!strcmp(req_name, "query_lock_lv")) {
|
||||||
|
*op = LD_OP_QUERY_LOCK;
|
||||||
|
*rt = LD_RT_LV;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!strcmp(req_name, "find_free_lock")) {
|
if (!strcmp(req_name, "find_free_lock")) {
|
||||||
*op = LD_OP_FIND_FREE_LOCK;
|
*op = LD_OP_FIND_FREE_LOCK;
|
||||||
*rt = LD_RT_VG;
|
*rt = LD_RT_VG;
|
||||||
@@ -4086,6 +4233,11 @@ static int str_to_op_rt(const char *req_name, int *op, int *rt)
|
|||||||
*rt = LD_RT_VG;
|
*rt = LD_RT_VG;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(req_name, "refresh_lv")) {
|
||||||
|
*op = LD_OP_REFRESH_LV;
|
||||||
|
*rt = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -4447,6 +4599,7 @@ static void client_recv_action(struct client *cl)
|
|||||||
const char *vg_name;
|
const char *vg_name;
|
||||||
const char *vg_uuid;
|
const char *vg_uuid;
|
||||||
const char *vg_sysid;
|
const char *vg_sysid;
|
||||||
|
const char *path;
|
||||||
const char *str;
|
const char *str;
|
||||||
int64_t val;
|
int64_t val;
|
||||||
uint32_t opts = 0;
|
uint32_t opts = 0;
|
||||||
@@ -4533,6 +4686,7 @@ static void client_recv_action(struct client *cl)
|
|||||||
opts = str_to_opts(str);
|
opts = str_to_opts(str);
|
||||||
str = daemon_request_str(req, "vg_lock_type", NULL);
|
str = daemon_request_str(req, "vg_lock_type", NULL);
|
||||||
lm = str_to_lm(str);
|
lm = str_to_lm(str);
|
||||||
|
path = daemon_request_str(req, "path", NULL);
|
||||||
|
|
||||||
if (cl_pid && cl_pid != cl->pid)
|
if (cl_pid && cl_pid != cl->pid)
|
||||||
log_error("client recv bad message pid %d client %d", cl_pid, cl->pid);
|
log_error("client recv bad message pid %d client %d", cl_pid, cl->pid);
|
||||||
@@ -4565,6 +4719,9 @@ static void client_recv_action(struct client *cl)
|
|||||||
act->flags = opts;
|
act->flags = opts;
|
||||||
act->lm_type = lm;
|
act->lm_type = lm;
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
act->path = strdup(path);
|
||||||
|
|
||||||
if (vg_name && strcmp(vg_name, "none"))
|
if (vg_name && strcmp(vg_name, "none"))
|
||||||
strncpy(act->vg_name, vg_name, MAX_NAME);
|
strncpy(act->vg_name, vg_name, MAX_NAME);
|
||||||
|
|
||||||
@@ -4641,6 +4798,7 @@ static void client_recv_action(struct client *cl)
|
|||||||
case LD_OP_STOP_ALL:
|
case LD_OP_STOP_ALL:
|
||||||
case LD_OP_RENAME_FINAL:
|
case LD_OP_RENAME_FINAL:
|
||||||
case LD_OP_RUNNING_LM:
|
case LD_OP_RUNNING_LM:
|
||||||
|
case LD_OP_REFRESH_LV:
|
||||||
add_work_action(act);
|
add_work_action(act);
|
||||||
rv = 0;
|
rv = 0;
|
||||||
break;
|
break;
|
||||||
@@ -4650,6 +4808,7 @@ static void client_recv_action(struct client *cl)
|
|||||||
case LD_OP_DISABLE:
|
case LD_OP_DISABLE:
|
||||||
case LD_OP_FREE:
|
case LD_OP_FREE:
|
||||||
case LD_OP_RENAME_BEFORE:
|
case LD_OP_RENAME_BEFORE:
|
||||||
|
case LD_OP_QUERY_LOCK:
|
||||||
case LD_OP_FIND_FREE_LOCK:
|
case LD_OP_FIND_FREE_LOCK:
|
||||||
case LD_OP_KILL_VG:
|
case LD_OP_KILL_VG:
|
||||||
case LD_OP_DROP_VG:
|
case LD_OP_DROP_VG:
|
||||||
@@ -4672,6 +4831,7 @@ static void *client_thread_main(void *arg_in)
|
|||||||
struct client *cl;
|
struct client *cl;
|
||||||
struct action *act;
|
struct action *act;
|
||||||
struct action *act_un;
|
struct action *act_un;
|
||||||
|
uint32_t lock_acquire_count = 0, lock_acquire_written = 0;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -4703,6 +4863,9 @@ static void *client_thread_main(void *arg_in)
|
|||||||
rv = -1;
|
rv = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (act->flags & LD_AF_LV_LOCK)
|
||||||
|
lock_acquire_count++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The client failed after we acquired an LV lock for
|
* The client failed after we acquired an LV lock for
|
||||||
* it, but before getting this reply saying it's done.
|
* it, but before getting this reply saying it's done.
|
||||||
@@ -4724,6 +4887,11 @@ static void *client_thread_main(void *arg_in)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adopt_opt && (lock_acquire_count > lock_acquire_written)) {
|
||||||
|
lock_acquire_written = lock_acquire_count;
|
||||||
|
write_adopt_file();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Queue incoming actions for lockspace threads
|
* Queue incoming actions for lockspace threads
|
||||||
*/
|
*/
|
||||||
@@ -4797,6 +4965,8 @@ static void *client_thread_main(void *arg_in)
|
|||||||
pthread_mutex_unlock(&client_mutex);
|
pthread_mutex_unlock(&client_mutex);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
if (adopt_opt && lock_acquire_written)
|
||||||
|
unlink(adopt_file);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4829,176 +4999,6 @@ static void close_client_thread(void)
|
|||||||
log_error("pthread_join client_thread error %d", perrno);
|
log_error("pthread_join client_thread error %d", perrno);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Get a list of all VGs with a lockd type (sanlock|dlm) from lvmetad.
|
|
||||||
* We'll match this list against a list of existing lockspaces that are
|
|
||||||
* found in the lock manager.
|
|
||||||
*
|
|
||||||
* For each of these VGs, also create a struct resource on ls->resources to
|
|
||||||
* represent each LV in the VG that uses a lock. For each of these LVs
|
|
||||||
* that are active, we'll attempt to adopt a lock.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int get_lockd_vgs(struct list_head *vg_lockd)
|
|
||||||
{
|
|
||||||
struct list_head update_vgs;
|
|
||||||
daemon_reply reply;
|
|
||||||
struct dm_config_node *cn;
|
|
||||||
struct dm_config_node *metadata;
|
|
||||||
struct dm_config_node *md_cn;
|
|
||||||
struct dm_config_node *lv_cn;
|
|
||||||
struct lockspace *ls, *safe;
|
|
||||||
struct resource *r;
|
|
||||||
const char *vg_name;
|
|
||||||
const char *vg_uuid;
|
|
||||||
const char *lv_uuid;
|
|
||||||
const char *lock_type;
|
|
||||||
const char *lock_args;
|
|
||||||
char find_str_path[PATH_MAX];
|
|
||||||
int rv = 0;
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&update_vgs);
|
|
||||||
|
|
||||||
reply = send_lvmetad("vg_list", "token = %s", "skip", NULL);
|
|
||||||
|
|
||||||
if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
|
|
||||||
log_error("vg_list from lvmetad failed %d", reply.error);
|
|
||||||
rv = -EINVAL;
|
|
||||||
goto destroy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(cn = dm_config_find_node(reply.cft->root, "volume_groups"))) {
|
|
||||||
log_error("get_lockd_vgs no vgs");
|
|
||||||
rv = -EINVAL;
|
|
||||||
goto destroy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create an update_vgs list of all vg uuids */
|
|
||||||
|
|
||||||
for (cn = cn->child; cn; cn = cn->sib) {
|
|
||||||
vg_uuid = cn->key;
|
|
||||||
|
|
||||||
if (!(ls = alloc_lockspace())) {
|
|
||||||
rv = -ENOMEM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(ls->vg_uuid, vg_uuid, 64);
|
|
||||||
list_add_tail(&ls->list, &update_vgs);
|
|
||||||
log_debug("get_lockd_vgs %s", vg_uuid);
|
|
||||||
}
|
|
||||||
destroy:
|
|
||||||
daemon_reply_destroy(reply);
|
|
||||||
|
|
||||||
if (rv < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* get vg_name and lock_type for each vg uuid entry in update_vgs */
|
|
||||||
|
|
||||||
list_for_each_entry(ls, &update_vgs, list) {
|
|
||||||
reply = send_lvmetad("vg_lookup",
|
|
||||||
"token = %s", "skip",
|
|
||||||
"uuid = %s", ls->vg_uuid,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
|
|
||||||
log_error("vg_lookup from lvmetad failed %d", reply.error);
|
|
||||||
rv = -EINVAL;
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
vg_name = daemon_reply_str(reply, "name", NULL);
|
|
||||||
if (!vg_name) {
|
|
||||||
log_error("get_lockd_vgs %s no name", ls->vg_uuid);
|
|
||||||
rv = -EINVAL;
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(ls->vg_name, vg_name, MAX_NAME);
|
|
||||||
|
|
||||||
metadata = dm_config_find_node(reply.cft->root, "metadata");
|
|
||||||
if (!metadata) {
|
|
||||||
log_error("get_lockd_vgs %s name %s no metadata",
|
|
||||||
ls->vg_uuid, ls->vg_name);
|
|
||||||
rv = -EINVAL;
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock_type = dm_config_find_str(metadata, "metadata/lock_type", NULL);
|
|
||||||
ls->lm_type = str_to_lm(lock_type);
|
|
||||||
|
|
||||||
if ((ls->lm_type != LD_LM_SANLOCK) && (ls->lm_type != LD_LM_DLM)) {
|
|
||||||
log_debug("get_lockd_vgs %s not lockd type", ls->vg_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock_args = dm_config_find_str(metadata, "metadata/lock_args", NULL);
|
|
||||||
if (lock_args)
|
|
||||||
strncpy(ls->vg_args, lock_args, MAX_ARGS);
|
|
||||||
|
|
||||||
log_debug("get_lockd_vgs %s lock_type %s lock_args %s",
|
|
||||||
ls->vg_name, lock_type, lock_args ?: "none");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make a record (struct resource) of each lv that uses a lock.
|
|
||||||
* For any lv that uses a lock, we'll check if the lv is active
|
|
||||||
* and if so try to adopt a lock for it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (md_cn = metadata->child; md_cn; md_cn = md_cn->sib) {
|
|
||||||
if (strcmp(md_cn->key, "logical_volumes"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (lv_cn = md_cn->child; lv_cn; lv_cn = lv_cn->sib) {
|
|
||||||
snprintf(find_str_path, PATH_MAX, "%s/lock_args", lv_cn->key);
|
|
||||||
lock_args = dm_config_find_str(lv_cn, find_str_path, NULL);
|
|
||||||
if (!lock_args)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
snprintf(find_str_path, PATH_MAX, "%s/id", lv_cn->key);
|
|
||||||
lv_uuid = dm_config_find_str(lv_cn, find_str_path, NULL);
|
|
||||||
|
|
||||||
if (!lv_uuid) {
|
|
||||||
log_error("get_lock_vgs no lv id for name %s", lv_cn->key);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(r = alloc_resource())) {
|
|
||||||
rv = -ENOMEM;
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->use_vb = 0;
|
|
||||||
r->type = LD_RT_LV;
|
|
||||||
strncpy(r->name, lv_uuid, MAX_NAME);
|
|
||||||
if (lock_args)
|
|
||||||
strncpy(r->lv_args, lock_args, MAX_ARGS);
|
|
||||||
list_add_tail(&r->list, &ls->resources);
|
|
||||||
log_debug("get_lockd_vgs %s lv %s %s (name %s)",
|
|
||||||
ls->vg_name, r->name, lock_args ? lock_args : "", lv_cn->key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next:
|
|
||||||
daemon_reply_destroy(reply);
|
|
||||||
|
|
||||||
if (rv < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
/* Return lockd VG's on the vg_lockd list. */
|
|
||||||
|
|
||||||
list_for_each_entry_safe(ls, safe, &update_vgs, list) {
|
|
||||||
list_del(&ls->list);
|
|
||||||
|
|
||||||
if ((ls->lm_type == LD_LM_SANLOCK) || (ls->lm_type == LD_LM_DLM))
|
|
||||||
list_add_tail(&ls->list, vg_lockd);
|
|
||||||
else
|
|
||||||
free(ls);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char _dm_uuid[DM_UUID_LEN];
|
static char _dm_uuid[DM_UUID_LEN];
|
||||||
|
|
||||||
static char *get_dm_uuid(char *dm_name)
|
static char *get_dm_uuid(char *dm_name)
|
||||||
@@ -5215,9 +5215,9 @@ static void adopt_locks(void)
|
|||||||
INIT_LIST_HEAD(&to_unlock);
|
INIT_LIST_HEAD(&to_unlock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get list of lockspaces from lock managers.
|
* Get list of lockspaces from currently running lock managers.
|
||||||
* Get list of VGs from lvmetad with a lockd type.
|
* Get list of shared VGs from file written by prior lvmlockd.
|
||||||
* Get list of active lockd type LVs from /dev.
|
* Get list of active LVs (in the shared VGs) from the file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (lm_support_dlm() && lm_is_running_dlm()) {
|
if (lm_support_dlm() && lm_is_running_dlm()) {
|
||||||
@@ -5241,12 +5241,17 @@ static void adopt_locks(void)
|
|||||||
* Adds a struct lockspace to vg_lockd for each lockd VG.
|
* Adds a struct lockspace to vg_lockd for each lockd VG.
|
||||||
* Adds a struct resource to ls->resources for each LV.
|
* Adds a struct resource to ls->resources for each LV.
|
||||||
*/
|
*/
|
||||||
rv = get_lockd_vgs(&vg_lockd);
|
rv = read_adopt_file(&vg_lockd);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
log_error("adopt_locks get_lockd_vgs failed");
|
log_error("adopt_locks read_adopt_file failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (list_empty(&vg_lockd)) {
|
||||||
|
log_debug("No lockspaces in adopt file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For each resource on each lockspace, check if the
|
* For each resource on each lockspace, check if the
|
||||||
* corresponding LV is active. If so, leave the
|
* corresponding LV is active. If so, leave the
|
||||||
@@ -5271,7 +5276,7 @@ static void adopt_locks(void)
|
|||||||
gl_use_sanlock = 1;
|
gl_use_sanlock = 1;
|
||||||
|
|
||||||
list_for_each_entry(ls, &vg_lockd, list) {
|
list_for_each_entry(ls, &vg_lockd, list) {
|
||||||
log_debug("adopt lvmetad vg %s lock_type %s lock_args %s",
|
log_debug("adopt vg %s lock_type %s lock_args %s",
|
||||||
ls->vg_name, lm_str(ls->lm_type), ls->vg_args);
|
ls->vg_name, lm_str(ls->lm_type), ls->vg_args);
|
||||||
|
|
||||||
list_for_each_entry(r, &ls->resources, list)
|
list_for_each_entry(r, &ls->resources, list)
|
||||||
@@ -5336,7 +5341,7 @@ static void adopt_locks(void)
|
|||||||
/*
|
/*
|
||||||
* LS in ls_found, not in vg_lockd.
|
* LS in ls_found, not in vg_lockd.
|
||||||
* An lvm lockspace found in the lock manager has no
|
* An lvm lockspace found in the lock manager has no
|
||||||
* corresponding VG in lvmetad. This shouldn't usually
|
* corresponding VG. This shouldn't usually
|
||||||
* happen, but it's possible the VG could have been removed
|
* happen, but it's possible the VG could have been removed
|
||||||
* while the orphaned lockspace from it was still around.
|
* while the orphaned lockspace from it was still around.
|
||||||
* Report an error and leave the ls in the lm alone.
|
* Report an error and leave the ls in the lm alone.
|
||||||
@@ -5351,7 +5356,7 @@ static void adopt_locks(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* LS in vg_lockd, not in ls_found.
|
* LS in vg_lockd, not in ls_found.
|
||||||
* lockd vgs from lvmetad that do not have an existing lockspace.
|
* lockd vgs that do not have an existing lockspace.
|
||||||
* This wouldn't be unusual; we just skip the vg.
|
* This wouldn't be unusual; we just skip the vg.
|
||||||
* But, if the vg has active lvs, then it should have had locks
|
* But, if the vg has active lvs, then it should have had locks
|
||||||
* and a lockspace. Should we attempt to join the lockspace and
|
* and a lockspace. Should we attempt to join the lockspace and
|
||||||
@@ -5403,8 +5408,6 @@ static void adopt_locks(void)
|
|||||||
memcpy(act->vg_args, ls->vg_args, MAX_ARGS);
|
memcpy(act->vg_args, ls->vg_args, MAX_ARGS);
|
||||||
act->host_id = ls->host_id;
|
act->host_id = ls->host_id;
|
||||||
|
|
||||||
/* set act->version from lvmetad data? */
|
|
||||||
|
|
||||||
log_debug("adopt add %s vg lockspace %s", lm_str(act->lm_type), act->vg_name);
|
log_debug("adopt add %s vg lockspace %s", lm_str(act->lm_type), act->vg_name);
|
||||||
|
|
||||||
rv = add_lockspace_thread(ls->name, act->vg_name, act->vg_uuid,
|
rv = add_lockspace_thread(ls->name, act->vg_name, act->vg_uuid,
|
||||||
@@ -5487,7 +5490,7 @@ static void adopt_locks(void)
|
|||||||
goto fail;
|
goto fail;
|
||||||
act->op = LD_OP_LOCK;
|
act->op = LD_OP_LOCK;
|
||||||
act->rt = LD_RT_LV;
|
act->rt = LD_RT_LV;
|
||||||
act->mode = LD_LK_EX;
|
act->mode = r->adopt_mode;
|
||||||
act->flags = (LD_AF_ADOPT | LD_AF_PERSISTENT);
|
act->flags = (LD_AF_ADOPT | LD_AF_PERSISTENT);
|
||||||
act->client_id = INTERNAL_CLIENT_ID;
|
act->client_id = INTERNAL_CLIENT_ID;
|
||||||
act->lm_type = ls->lm_type;
|
act->lm_type = ls->lm_type;
|
||||||
@@ -5585,8 +5588,9 @@ static void adopt_locks(void)
|
|||||||
* Adopt failed because the orphan has a different mode
|
* Adopt failed because the orphan has a different mode
|
||||||
* than initially requested. Repeat the lock-adopt operation
|
* than initially requested. Repeat the lock-adopt operation
|
||||||
* with the other mode. N.B. this logic depends on first
|
* with the other mode. N.B. this logic depends on first
|
||||||
* trying sh then ex for GL/VG locks, and ex then sh for
|
* trying sh then ex for GL/VG locks; for LV locks the mode
|
||||||
* LV locks.
|
* from the adopt file is tried first, the alternate
|
||||||
|
* (if the mode in adopt file was wrong somehow.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((act->rt != LD_RT_LV) && (act->mode == LD_LK_SH)) {
|
if ((act->rt != LD_RT_LV) && (act->mode == LD_LK_SH)) {
|
||||||
@@ -5594,9 +5598,12 @@ static void adopt_locks(void)
|
|||||||
act->mode = LD_LK_EX;
|
act->mode = LD_LK_EX;
|
||||||
rv = add_lock_action(act);
|
rv = add_lock_action(act);
|
||||||
|
|
||||||
} else if ((act->rt == LD_RT_LV) && (act->mode == LD_LK_EX)) {
|
} else if (act->rt == LD_RT_LV) {
|
||||||
/* LV locks: attempt to adopt sh after ex failed. */
|
/* LV locks: attempt to adopt the other mode. */
|
||||||
act->mode = LD_LK_SH;
|
if (act->mode == LD_LK_EX)
|
||||||
|
act->mode = LD_LK_SH;
|
||||||
|
else if (act->mode == LD_LK_SH)
|
||||||
|
act->mode = LD_LK_EX;
|
||||||
rv = add_lock_action(act);
|
rv = add_lock_action(act);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -5731,10 +5738,13 @@ static void adopt_locks(void)
|
|||||||
if (count_start_fail || count_adopt_fail)
|
if (count_start_fail || count_adopt_fail)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
unlink(adopt_file);
|
||||||
|
write_adopt_file();
|
||||||
log_debug("adopt_locks done");
|
log_debug("adopt_locks done");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
unlink(adopt_file);
|
||||||
log_error("adopt_locks failed, reset host");
|
log_error("adopt_locks failed, reset host");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5863,24 +5873,16 @@ static int main_loop(daemon_state *ds_arg)
|
|||||||
setup_worker_thread();
|
setup_worker_thread();
|
||||||
setup_restart();
|
setup_restart();
|
||||||
|
|
||||||
pthread_mutex_init(&lvmetad_mutex, NULL);
|
#ifdef USE_SD_NOTIFY
|
||||||
lvmetad_handle = lvmetad_open(NULL);
|
sd_notify(0, "READY=1");
|
||||||
if (lvmetad_handle.error || lvmetad_handle.socket_fd < 0)
|
#endif
|
||||||
log_debug("lvmetad_open error %d", lvmetad_handle.error);
|
|
||||||
else
|
|
||||||
lvmetad_connected = 1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to rejoin lockspaces and adopt locks from a previous
|
* Attempt to rejoin lockspaces and adopt locks from a previous
|
||||||
* instance of lvmlockd that left behind lockspaces/locks.
|
* instance of lvmlockd that left behind lockspaces/locks.
|
||||||
*/
|
*/
|
||||||
if (adopt_opt) {
|
if (adopt_opt)
|
||||||
/* FIXME: implement this without lvmetad */
|
adopt_locks();
|
||||||
if (!lvmetad_connected)
|
|
||||||
log_error("Cannot adopt locks without lvmetad running.");
|
|
||||||
else
|
|
||||||
adopt_locks();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
rv = poll(pollfd, pollfd_maxi + 1, -1);
|
rv = poll(pollfd, pollfd_maxi + 1, -1);
|
||||||
@@ -5996,7 +5998,6 @@ static int main_loop(daemon_state *ds_arg)
|
|||||||
close_worker_thread();
|
close_worker_thread();
|
||||||
close_client_thread();
|
close_client_thread();
|
||||||
closelog();
|
closelog();
|
||||||
daemon_close(lvmetad_handle);
|
|
||||||
return 1; /* libdaemon uses 1 for success */
|
return 1; /* libdaemon uses 1 for success */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6018,6 +6019,8 @@ static void usage(char *prog, FILE *file)
|
|||||||
fprintf(file, " Set path to the pid file. [%s]\n", LVMLOCKD_PIDFILE);
|
fprintf(file, " Set path to the pid file. [%s]\n", LVMLOCKD_PIDFILE);
|
||||||
fprintf(file, " --socket-path | -s <path>\n");
|
fprintf(file, " --socket-path | -s <path>\n");
|
||||||
fprintf(file, " Set path to the socket to listen on. [%s]\n", LVMLOCKD_SOCKET);
|
fprintf(file, " Set path to the socket to listen on. [%s]\n", LVMLOCKD_SOCKET);
|
||||||
|
fprintf(file, " --adopt-file <path>\n");
|
||||||
|
fprintf(file, " Set path to the adopt file. [%s]\n", LVMLOCKD_ADOPT_FILE);
|
||||||
fprintf(file, " --syslog-priority | -S err|warning|debug\n");
|
fprintf(file, " --syslog-priority | -S err|warning|debug\n");
|
||||||
fprintf(file, " Write log messages from this level up to syslog. [%s]\n", _syslog_num_to_name(LOG_SYSLOG_PRIO));
|
fprintf(file, " Write log messages from this level up to syslog. [%s]\n", _syslog_num_to_name(LOG_SYSLOG_PRIO));
|
||||||
fprintf(file, " --gl-type | -g <str>\n");
|
fprintf(file, " --gl-type | -g <str>\n");
|
||||||
@@ -6035,14 +6038,14 @@ static void usage(char *prog, FILE *file)
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
daemon_state ds = {
|
daemon_state ds = {
|
||||||
.daemon_main = main_loop,
|
.name = "lvmlockd",
|
||||||
.daemon_init = NULL,
|
|
||||||
.daemon_fini = NULL,
|
|
||||||
.pidfile = getenv("LVM_LVMLOCKD_PIDFILE"),
|
.pidfile = getenv("LVM_LVMLOCKD_PIDFILE"),
|
||||||
.socket_path = getenv("LVM_LVMLOCKD_SOCKET"),
|
.socket_path = getenv("LVM_LVMLOCKD_SOCKET"),
|
||||||
.protocol = lvmlockd_protocol,
|
.protocol = lvmlockd_protocol,
|
||||||
.protocol_version = lvmlockd_protocol_version,
|
.protocol_version = lvmlockd_protocol_version,
|
||||||
.name = "lvmlockd",
|
.daemon_init = NULL,
|
||||||
|
.daemon_fini = NULL,
|
||||||
|
.daemon_main = main_loop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
@@ -6053,6 +6056,7 @@ int main(int argc, char *argv[])
|
|||||||
{"daemon-debug", no_argument, 0, 'D' },
|
{"daemon-debug", no_argument, 0, 'D' },
|
||||||
{"pid-file", required_argument, 0, 'p' },
|
{"pid-file", required_argument, 0, 'p' },
|
||||||
{"socket-path", required_argument, 0, 's' },
|
{"socket-path", required_argument, 0, 's' },
|
||||||
|
{"adopt-file", required_argument, 0, 128 },
|
||||||
{"gl-type", required_argument, 0, 'g' },
|
{"gl-type", required_argument, 0, 'g' },
|
||||||
{"host-id", required_argument, 0, 'i' },
|
{"host-id", required_argument, 0, 'i' },
|
||||||
{"host-id-file", required_argument, 0, 'F' },
|
{"host-id-file", required_argument, 0, 'F' },
|
||||||
@@ -6075,6 +6079,9 @@ int main(int argc, char *argv[])
|
|||||||
switch (c) {
|
switch (c) {
|
||||||
case '0':
|
case '0':
|
||||||
break;
|
break;
|
||||||
|
case 128:
|
||||||
|
adopt_file = strdup(optarg);
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(argv[0], stdout);
|
usage(argv[0], stdout);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
@@ -6136,6 +6143,9 @@ int main(int argc, char *argv[])
|
|||||||
if (!ds.socket_path)
|
if (!ds.socket_path)
|
||||||
ds.socket_path = LVMLOCKD_SOCKET;
|
ds.socket_path = LVMLOCKD_SOCKET;
|
||||||
|
|
||||||
|
if (!adopt_file)
|
||||||
|
adopt_file = LVMLOCKD_ADOPT_FILE;
|
||||||
|
|
||||||
/* runs daemon_main/main_loop */
|
/* runs daemon_main/main_loop */
|
||||||
daemon_start(ds);
|
daemon_start(ds);
|
||||||
|
|
||||||
|
|||||||
@@ -11,19 +11,20 @@
|
|||||||
#define _XOPEN_SOURCE 500 /* pthread */
|
#define _XOPEN_SOURCE 500 /* pthread */
|
||||||
#define _ISOC99_SOURCE
|
#define _ISOC99_SOURCE
|
||||||
|
|
||||||
#include "tool.h"
|
#include "tools/tool.h"
|
||||||
|
|
||||||
#include "daemon-server.h"
|
#include "daemon-server.h"
|
||||||
#include "xlate.h"
|
#include "lib/mm/xlate.h"
|
||||||
|
|
||||||
#include "lvmlockd-internal.h"
|
#include "lvmlockd-internal.h"
|
||||||
#include "lvmlockd-client.h"
|
#include "daemons/lvmlockd/lvmlockd-client.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Using synchronous _wait dlm apis so do not define _REENTRANT and
|
* Using synchronous _wait dlm apis so do not define _REENTRANT and
|
||||||
* link with non-threaded version of library, libdlm_lt.
|
* link with non-threaded version of library, libdlm_lt.
|
||||||
*/
|
*/
|
||||||
#include "libdlm.h"
|
#include "libdlm.h"
|
||||||
|
#include "libdlmcontrol.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
@@ -127,16 +128,18 @@ static int read_cluster_name(char *clustername)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_VERSION 16
|
||||||
|
|
||||||
int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
||||||
{
|
{
|
||||||
char clustername[MAX_ARGS+1];
|
char clustername[MAX_ARGS+1];
|
||||||
char lock_args_version[MAX_ARGS+1];
|
char lock_args_version[MAX_VERSION+1];
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
memset(clustername, 0, sizeof(clustername));
|
memset(clustername, 0, sizeof(clustername));
|
||||||
memset(lock_args_version, 0, sizeof(lock_args_version));
|
memset(lock_args_version, 0, sizeof(lock_args_version));
|
||||||
|
|
||||||
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
|
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
|
||||||
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
|
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
|
||||||
|
|
||||||
rv = read_cluster_name(clustername);
|
rv = read_cluster_name(clustername);
|
||||||
@@ -148,7 +151,9 @@ int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
|||||||
return -EARGS;
|
return -EARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, clustername);
|
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, clustername);
|
||||||
|
if (rv >= MAX_ARGS)
|
||||||
|
log_debug("init_vg_dlm vg_args may be too long %d %s", rv, vg_args);
|
||||||
rv = 0;
|
rv = 0;
|
||||||
|
|
||||||
log_debug("init_vg_dlm done %s vg_args %s", ls_name, vg_args);
|
log_debug("init_vg_dlm done %s vg_args %s", ls_name, vg_args);
|
||||||
@@ -272,10 +277,9 @@ static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int wit
|
|||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
|
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
|
||||||
buf = malloc(sizeof(struct val_blk) + DLM_LVB_LEN);
|
buf = zalloc(sizeof(struct val_blk) + DLM_LVB_LEN);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
memset(buf, 0, sizeof(struct val_blk) + DLM_LVB_LEN);
|
|
||||||
|
|
||||||
rdd->vb = (struct val_blk *)buf;
|
rdd->vb = (struct val_blk *)buf;
|
||||||
rdd->lksb.sb_lvbptr = buf + sizeof(struct val_blk);
|
rdd->lksb.sb_lvbptr = buf + sizeof(struct val_blk);
|
||||||
@@ -394,12 +398,18 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
|||||||
(void *)1, (void *)1, (void *)1,
|
(void *)1, (void *)1, (void *)1,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
if (rv == -1 && errno == -EAGAIN) {
|
if (rv == -1 && (errno == EAGAIN)) {
|
||||||
log_debug("S %s R %s adopt_dlm adopt mode %d try other mode",
|
log_debug("S %s R %s adopt_dlm adopt mode %d try other mode",
|
||||||
ls->name, r->name, ld_mode);
|
ls->name, r->name, ld_mode);
|
||||||
rv = -EUCLEAN;
|
rv = -EUCLEAN;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (rv == -1 && (errno == ENOENT)) {
|
||||||
|
log_debug("S %s R %s adopt_dlm adopt mode %d no lock",
|
||||||
|
ls->name, r->name, ld_mode);
|
||||||
|
rv = -ENOENT;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d",
|
log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d",
|
||||||
ls->name, r->name, mode, flags, rv, errno);
|
ls->name, r->name, mode, flags, rv, errno);
|
||||||
@@ -777,3 +787,107 @@ int lm_is_running_dlm(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LOCKDDLM_CONTROL_SUPPORT
|
||||||
|
|
||||||
|
int lm_refresh_lv_start_dlm(struct action *act)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char command[DLMC_RUN_COMMAND_LEN];
|
||||||
|
char run_uuid[DLMC_RUN_UUID_LEN];
|
||||||
|
char *p, *vgname, *lvname;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* split /dev/vgname/lvname into vgname and lvname strings */
|
||||||
|
strncpy(path, act->path, strlen(act->path));
|
||||||
|
|
||||||
|
/* skip past dev */
|
||||||
|
p = strchr(path + 1, '/');
|
||||||
|
|
||||||
|
/* skip past slashes */
|
||||||
|
while (*p == '/')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
/* start of vgname */
|
||||||
|
vgname = p;
|
||||||
|
|
||||||
|
/* skip past vgname */
|
||||||
|
while (*p != '/')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
/* terminate vgname */
|
||||||
|
*p = '\0';
|
||||||
|
p++;
|
||||||
|
|
||||||
|
/* skip past slashes */
|
||||||
|
while (*p == '/')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
lvname = p;
|
||||||
|
|
||||||
|
memset(command, 0, sizeof(command));
|
||||||
|
memset(run_uuid, 0, sizeof(run_uuid));
|
||||||
|
|
||||||
|
/* todo: add --readonly */
|
||||||
|
|
||||||
|
snprintf(command, DLMC_RUN_COMMAND_LEN,
|
||||||
|
"lvm lvchange --refresh --partial --nolocking %s/%s",
|
||||||
|
vgname, lvname);
|
||||||
|
|
||||||
|
rv = dlmc_run_start(command, strlen(command), 0,
|
||||||
|
DLMC_FLAG_RUN_START_NODE_NONE,
|
||||||
|
run_uuid);
|
||||||
|
if (rv < 0) {
|
||||||
|
log_debug("refresh_lv run_start error %d", rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("refresh_lv run_start %s", run_uuid);
|
||||||
|
|
||||||
|
/* Bit of a hack here, we don't need path once started,
|
||||||
|
but we do need to save the run_uuid somewhere, so just
|
||||||
|
replace the path with the uuid. */
|
||||||
|
|
||||||
|
free(act->path);
|
||||||
|
act->path = strdup(run_uuid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lm_refresh_lv_check_dlm(struct action *act)
|
||||||
|
{
|
||||||
|
uint32_t check_status = 0;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* NB act->path was replaced with run_uuid */
|
||||||
|
|
||||||
|
rv = dlmc_run_check(act->path, strlen(act->path), 0,
|
||||||
|
DLMC_FLAG_RUN_CHECK_CLEAR,
|
||||||
|
&check_status);
|
||||||
|
if (rv < 0) {
|
||||||
|
log_debug("refresh_lv check error %d", rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("refresh_lv check %s status %x", act->path, check_status);
|
||||||
|
|
||||||
|
if (!(check_status & DLMC_RUN_STATUS_DONE))
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
if (check_status & DLMC_RUN_STATUS_FAILED)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* LOCKDDLM_CONTROL_SUPPORT */
|
||||||
|
|
||||||
|
int lm_refresh_lv_start_dlm(struct action *act)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lm_refresh_lv_check_dlm(struct action *act)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LOCKDDLM_CONTROL_SUPPORT */
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#ifndef _LVM_LVMLOCKD_INTERNAL_H
|
#ifndef _LVM_LVMLOCKD_INTERNAL_H
|
||||||
#define _LVM_LVMLOCKD_INTERNAL_H
|
#define _LVM_LVMLOCKD_INTERNAL_H
|
||||||
|
|
||||||
|
#include "base/memory/container_of.h"
|
||||||
|
|
||||||
#define MAX_NAME 64
|
#define MAX_NAME 64
|
||||||
#define MAX_ARGS 64
|
#define MAX_ARGS 64
|
||||||
|
|
||||||
@@ -53,6 +55,8 @@ enum {
|
|||||||
LD_OP_KILL_VG,
|
LD_OP_KILL_VG,
|
||||||
LD_OP_DROP_VG,
|
LD_OP_DROP_VG,
|
||||||
LD_OP_BUSY,
|
LD_OP_BUSY,
|
||||||
|
LD_OP_QUERY_LOCK,
|
||||||
|
LD_OP_REFRESH_LV,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* resource types */
|
/* resource types */
|
||||||
@@ -105,6 +109,7 @@ struct client {
|
|||||||
#define LD_AF_WARN_GL_REMOVED 0x00020000
|
#define LD_AF_WARN_GL_REMOVED 0x00020000
|
||||||
#define LD_AF_LV_LOCK 0x00040000
|
#define LD_AF_LV_LOCK 0x00040000
|
||||||
#define LD_AF_LV_UNLOCK 0x00080000
|
#define LD_AF_LV_UNLOCK 0x00080000
|
||||||
|
#define LD_AF_SH_EXISTS 0x00100000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of times to repeat a lock request after
|
* Number of times to repeat a lock request after
|
||||||
@@ -127,6 +132,7 @@ struct action {
|
|||||||
int max_retries;
|
int max_retries;
|
||||||
int result;
|
int result;
|
||||||
int lm_rv; /* return value from lm_ function */
|
int lm_rv; /* return value from lm_ function */
|
||||||
|
char *path;
|
||||||
char vg_uuid[64];
|
char vg_uuid[64];
|
||||||
char vg_name[MAX_NAME+1];
|
char vg_name[MAX_NAME+1];
|
||||||
char lv_name[MAX_NAME+1];
|
char lv_name[MAX_NAME+1];
|
||||||
@@ -141,6 +147,7 @@ struct resource {
|
|||||||
char name[MAX_NAME+1]; /* vg name or lv name */
|
char name[MAX_NAME+1]; /* vg name or lv name */
|
||||||
int8_t type; /* resource type LD_RT_ */
|
int8_t type; /* resource type LD_RT_ */
|
||||||
int8_t mode;
|
int8_t mode;
|
||||||
|
int8_t adopt_mode;
|
||||||
unsigned int sh_count; /* number of sh locks on locks list */
|
unsigned int sh_count; /* number of sh locks on locks list */
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uint32_t last_client_id; /* last client_id to lock or unlock resource */
|
uint32_t last_client_id; /* last client_id to lock or unlock resource */
|
||||||
@@ -151,7 +158,7 @@ struct resource {
|
|||||||
struct list_head locks;
|
struct list_head locks;
|
||||||
struct list_head actions;
|
struct list_head actions;
|
||||||
char lv_args[MAX_ARGS+1];
|
char lv_args[MAX_ARGS+1];
|
||||||
char lm_data[0]; /* lock manager specific data */
|
char lm_data[]; /* lock manager specific data */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LD_LF_PERSISTENT 0x00000001
|
#define LD_LF_PERSISTENT 0x00000001
|
||||||
@@ -174,7 +181,9 @@ struct lockspace {
|
|||||||
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
|
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
|
||||||
void *lm_data;
|
void *lm_data;
|
||||||
uint64_t host_id;
|
uint64_t host_id;
|
||||||
uint64_t free_lock_offset; /* start search for free lock here */
|
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
|
||||||
|
int free_lock_sector_size; /* for sanlock */
|
||||||
|
int free_lock_align_size; /* for sanlock */
|
||||||
|
|
||||||
uint32_t start_client_id; /* client_id that started the lockspace */
|
uint32_t start_client_id; /* client_id that started the lockspace */
|
||||||
pthread_t thread; /* makes synchronous lock requests */
|
pthread_t thread; /* makes synchronous lock requests */
|
||||||
@@ -210,10 +219,6 @@ struct val_blk {
|
|||||||
/* lm_unlock flags */
|
/* lm_unlock flags */
|
||||||
#define LMUF_FREE_VG 0x00000001
|
#define LMUF_FREE_VG 0x00000001
|
||||||
|
|
||||||
#define container_of(ptr, type, member) ({ \
|
|
||||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
|
||||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
|
||||||
|
|
||||||
static inline void INIT_LIST_HEAD(struct list_head *list)
|
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||||
{
|
{
|
||||||
list->next = list;
|
list->next = list;
|
||||||
@@ -387,6 +392,8 @@ int lm_get_lockspaces_dlm(struct list_head *ls_rejoin);
|
|||||||
int lm_data_size_dlm(void);
|
int lm_data_size_dlm(void);
|
||||||
int lm_is_running_dlm(void);
|
int lm_is_running_dlm(void);
|
||||||
int lm_hosts_dlm(struct lockspace *ls, int notify);
|
int lm_hosts_dlm(struct lockspace *ls, int notify);
|
||||||
|
int lm_refresh_lv_start_dlm(struct action *act);
|
||||||
|
int lm_refresh_lv_check_dlm(struct action *act);
|
||||||
|
|
||||||
static inline int lm_support_dlm(void)
|
static inline int lm_support_dlm(void)
|
||||||
{
|
{
|
||||||
@@ -463,12 +470,22 @@ static inline int lm_hosts_dlm(struct lockspace *ls, int notify)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int lm_refresh_lv_start_dlm(struct action *act)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int lm_refresh_lv_check_dlm(struct action *act)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* dlm support */
|
#endif /* dlm support */
|
||||||
|
|
||||||
#ifdef LOCKDSANLOCK_SUPPORT
|
#ifdef LOCKDSANLOCK_SUPPORT
|
||||||
|
|
||||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
||||||
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, uint64_t free_offset);
|
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset);
|
||||||
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
|
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
|
||||||
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
||||||
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
|
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
|
||||||
@@ -488,7 +505,7 @@ int lm_gl_is_enabled(struct lockspace *ls);
|
|||||||
int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
|
int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
|
||||||
int lm_data_size_sanlock(void);
|
int lm_data_size_sanlock(void);
|
||||||
int lm_is_running_sanlock(void);
|
int lm_is_running_sanlock(void);
|
||||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset);
|
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size);
|
||||||
|
|
||||||
static inline int lm_support_sanlock(void)
|
static inline int lm_support_sanlock(void)
|
||||||
{
|
{
|
||||||
@@ -502,7 +519,7 @@ static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flag
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, uint64_t free_offset)
|
static inline int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -590,7 +607,7 @@ static inline int lm_is_running_sanlock(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
|
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,23 +11,42 @@
|
|||||||
#define _XOPEN_SOURCE 500 /* pthread */
|
#define _XOPEN_SOURCE 500 /* pthread */
|
||||||
#define _ISOC99_SOURCE
|
#define _ISOC99_SOURCE
|
||||||
|
|
||||||
#include "tool.h"
|
#include "tools/tool.h"
|
||||||
|
|
||||||
#include "daemon-server.h"
|
#include "daemon-server.h"
|
||||||
#include "xlate.h"
|
#include "lib/mm/xlate.h"
|
||||||
|
|
||||||
#include "lvmlockd-internal.h"
|
#include "lvmlockd-internal.h"
|
||||||
#include "lvmlockd-client.h"
|
#include "daemons/lvmlockd/lvmlockd-client.h"
|
||||||
|
|
||||||
#include "sanlock.h"
|
#include "sanlock.h"
|
||||||
#include "sanlock_rv.h"
|
#include "sanlock_rv.h"
|
||||||
#include "sanlock_admin.h"
|
#include "sanlock_admin.h"
|
||||||
#include "sanlock_resource.h"
|
#include "sanlock_resource.h"
|
||||||
|
|
||||||
|
/* FIXME: these are copied from sanlock.h only until
|
||||||
|
an updated version of sanlock is available with them. */
|
||||||
|
#define SANLK_RES_ALIGN1M 0x00000010
|
||||||
|
#define SANLK_RES_ALIGN2M 0x00000020
|
||||||
|
#define SANLK_RES_ALIGN4M 0x00000040
|
||||||
|
#define SANLK_RES_ALIGN8M 0x00000080
|
||||||
|
#define SANLK_RES_SECTOR512 0x00000100
|
||||||
|
#define SANLK_RES_SECTOR4K 0x00000200
|
||||||
|
#define SANLK_LSF_ALIGN1M 0x00000010
|
||||||
|
#define SANLK_LSF_ALIGN2M 0x00000020
|
||||||
|
#define SANLK_LSF_ALIGN4M 0x00000040
|
||||||
|
#define SANLK_LSF_ALIGN8M 0x00000080
|
||||||
|
#define SANLK_LSF_SECTOR512 0x00000100
|
||||||
|
#define SANLK_LSF_SECTOR4K 0x00000200
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <blkid/blkid.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
#define ONE_MB 1048576
|
||||||
|
|
||||||
/*
|
/*
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@@ -139,6 +158,7 @@ release all the leases for the VG.
|
|||||||
|
|
||||||
struct lm_sanlock {
|
struct lm_sanlock {
|
||||||
struct sanlk_lockspace ss;
|
struct sanlk_lockspace ss;
|
||||||
|
int sector_size;
|
||||||
int align_size;
|
int align_size;
|
||||||
int sock; /* sanlock daemon connection */
|
int sock; /* sanlock daemon connection */
|
||||||
};
|
};
|
||||||
@@ -201,7 +221,6 @@ int lm_data_size_sanlock(void)
|
|||||||
* ...
|
* ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LS_BEGIN 0
|
|
||||||
#define GL_LOCK_BEGIN UINT64_C(65)
|
#define GL_LOCK_BEGIN UINT64_C(65)
|
||||||
#define VG_LOCK_BEGIN UINT64_C(66)
|
#define VG_LOCK_BEGIN UINT64_C(66)
|
||||||
#define LV_LOCK_BEGIN UINT64_C(67)
|
#define LV_LOCK_BEGIN UINT64_C(67)
|
||||||
@@ -288,7 +307,8 @@ static int read_host_id_file(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fclose(file))
|
if (fclose(file))
|
||||||
log_error("failed to close host id file %s", daemon_host_id_file);
|
log_debug("Failed to fclose host id file %s (%s).",
|
||||||
|
daemon_host_id_file, strerror(errno));
|
||||||
out:
|
out:
|
||||||
log_debug("host_id %d from %s", host_id, daemon_host_id_file);
|
log_debug("host_id %d from %s", host_id, daemon_host_id_file);
|
||||||
return host_id;
|
return host_id;
|
||||||
@@ -324,6 +344,154 @@ fail:
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _read_sysfs_size(dev_t devno, const char *name, unsigned int *val)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char buf[32];
|
||||||
|
FILE *fp;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/queue/%s",
|
||||||
|
(int)major(devno), (int)minor(devno), name);
|
||||||
|
|
||||||
|
if (!(fp = fopen(path, "r")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!fgets(buf, sizeof(buf), fp))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if ((len = strlen(buf)) && buf[len - 1] == '\n')
|
||||||
|
buf[--len] = '\0';
|
||||||
|
|
||||||
|
if (strlen(buf))
|
||||||
|
*val = atoi(buf);
|
||||||
|
out:
|
||||||
|
if (fclose(fp))
|
||||||
|
log_debug("Failed to fclose host id file %s (%s).", path, strerror(errno));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select sector/align size for a new VG based on what the device reports for
|
||||||
|
sector size of the lvmlock LV. */
|
||||||
|
|
||||||
|
static int get_sizes_device(char *path, int *sector_size, int *align_size)
|
||||||
|
{
|
||||||
|
unsigned int physical_block_size = 0;
|
||||||
|
unsigned int logical_block_size = 0;
|
||||||
|
struct stat st;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = stat(path, &st);
|
||||||
|
if (rv < 0) {
|
||||||
|
log_error("Failed to stat device to get block size %s %d", path, errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_read_sysfs_size(st.st_rdev, "physical_block_size", &physical_block_size);
|
||||||
|
_read_sysfs_size(st.st_rdev, "logical_block_size", &logical_block_size);
|
||||||
|
|
||||||
|
if ((physical_block_size == 512) && (logical_block_size == 512)) {
|
||||||
|
*sector_size = 512;
|
||||||
|
*align_size = ONE_MB;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((physical_block_size == 4096) && (logical_block_size == 4096)) {
|
||||||
|
*sector_size = 4096;
|
||||||
|
*align_size = 8 * ONE_MB;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (physical_block_size && (physical_block_size != 512) && (physical_block_size != 4096)) {
|
||||||
|
log_warn("WARNING: invalid block sizes physical %u logical %u for %s",
|
||||||
|
physical_block_size, logical_block_size, path);
|
||||||
|
physical_block_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logical_block_size && (logical_block_size != 512) && (logical_block_size != 4096)) {
|
||||||
|
log_warn("WARNING: invalid block sizes physical %u logical %u for %s",
|
||||||
|
physical_block_size, logical_block_size, path);
|
||||||
|
logical_block_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!physical_block_size && !logical_block_size) {
|
||||||
|
log_error("Failed to get a block size for %s", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!physical_block_size || !logical_block_size) {
|
||||||
|
log_warn("WARNING: incomplete block size information physical %u logical %u for %s",
|
||||||
|
physical_block_size, logical_block_size, path);
|
||||||
|
if (!physical_block_size)
|
||||||
|
physical_block_size = logical_block_size;
|
||||||
|
if (!logical_block_size)
|
||||||
|
logical_block_size = physical_block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((logical_block_size == 4096) && (physical_block_size == 512)) {
|
||||||
|
log_warn("WARNING: mixed block sizes physical %u logical %u (using 4096) for %s",
|
||||||
|
physical_block_size, logical_block_size, path);
|
||||||
|
*sector_size = 4096;
|
||||||
|
*align_size = 8 * ONE_MB;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((physical_block_size == 4096) && (logical_block_size == 512)) {
|
||||||
|
log_warn("WARNING: mixed block sizes physical %u logical %u (using 4096) for %s",
|
||||||
|
physical_block_size, logical_block_size, path);
|
||||||
|
*sector_size = 4096;
|
||||||
|
*align_size = 8 * ONE_MB;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (physical_block_size == 512) {
|
||||||
|
*sector_size = 512;
|
||||||
|
*align_size = ONE_MB;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (physical_block_size == 4096) {
|
||||||
|
*sector_size = 4096;
|
||||||
|
*align_size = 8 * ONE_MB;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error("Failed to get a block size for %s", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the sector/align sizes that were used to create an existing VG.
|
||||||
|
sanlock encoded this in the lockspace/resource structs on disk. */
|
||||||
|
|
||||||
|
static int get_sizes_lockspace(char *path, int *sector_size, int *align_size)
|
||||||
|
{
|
||||||
|
struct sanlk_lockspace ss;
|
||||||
|
uint32_t io_timeout = 0;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
memset(&ss, 0, sizeof(ss));
|
||||||
|
memcpy(ss.host_id_disk.path, path, SANLK_PATH_LEN);
|
||||||
|
ss.host_id_disk.offset = 0;
|
||||||
|
|
||||||
|
rv = sanlock_read_lockspace(&ss, 0, &io_timeout);
|
||||||
|
if (rv < 0) {
|
||||||
|
log_error("get_sizes_lockspace %s error %d", path, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN8M)) {
|
||||||
|
*sector_size = 4096;
|
||||||
|
*align_size = 8 * ONE_MB;
|
||||||
|
} else if ((ss.flags & SANLK_LSF_SECTOR512) && (ss.flags & SANLK_LSF_ALIGN1M)) {
|
||||||
|
*sector_size = 512;
|
||||||
|
*align_size = ONE_MB;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("get_sizes_lockspace found %d %d", *sector_size, *align_size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vgcreate
|
* vgcreate
|
||||||
*
|
*
|
||||||
@@ -332,18 +500,21 @@ fail:
|
|||||||
* version and lv name, and returns the real lock_args in vg_args.
|
* version and lv name, and returns the real lock_args in vg_args.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define MAX_VERSION 16
|
||||||
|
|
||||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
||||||
{
|
{
|
||||||
struct sanlk_lockspace ss;
|
struct sanlk_lockspace ss;
|
||||||
struct sanlk_resourced rd;
|
struct sanlk_resourced rd;
|
||||||
struct sanlk_disk disk;
|
struct sanlk_disk disk;
|
||||||
char lock_lv_name[MAX_ARGS+1];
|
char lock_lv_name[MAX_ARGS+1];
|
||||||
char lock_args_version[MAX_ARGS+1];
|
char lock_args_version[MAX_VERSION+1];
|
||||||
const char *gl_name = NULL;
|
const char *gl_name = NULL;
|
||||||
uint32_t daemon_version;
|
uint32_t daemon_version;
|
||||||
uint32_t daemon_proto;
|
uint32_t daemon_proto;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
int align_size;
|
int sector_size = 0;
|
||||||
|
int align_size = 0;
|
||||||
int i, rv;
|
int i, rv;
|
||||||
|
|
||||||
memset(&ss, 0, sizeof(ss));
|
memset(&ss, 0, sizeof(ss));
|
||||||
@@ -357,7 +528,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
|||||||
return -EARGS;
|
return -EARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
|
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
|
||||||
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
|
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
|
||||||
|
|
||||||
/* see comment above about input vg_args being only lock_lv_name */
|
/* see comment above about input vg_args being only lock_lv_name */
|
||||||
@@ -374,7 +545,9 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
|||||||
if (daemon_test) {
|
if (daemon_test) {
|
||||||
if (!gl_lsname_sanlock[0])
|
if (!gl_lsname_sanlock[0])
|
||||||
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
|
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
|
||||||
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
|
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
|
||||||
|
if (rv >= MAX_ARGS)
|
||||||
|
log_debug("init_vg_san vg_args may be too long %d %s", rv, vg_args);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,23 +560,25 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
|||||||
log_debug("sanlock daemon version %08x proto %08x",
|
log_debug("sanlock daemon version %08x proto %08x",
|
||||||
daemon_version, daemon_proto);
|
daemon_version, daemon_proto);
|
||||||
|
|
||||||
rv = sanlock_align(&disk);
|
/* Nothing formatted on disk yet, use what the device reports. */
|
||||||
if (rv <= 0) {
|
rv = get_sizes_device(disk.path, §or_size, &align_size);
|
||||||
|
if (rv < 0) {
|
||||||
if (rv == -EACCES) {
|
if (rv == -EACCES) {
|
||||||
log_error("S %s init_vg_san sanlock error -EACCES: no permission to access %s",
|
log_error("S %s init_vg_san sanlock error -EACCES: no permission to access %s",
|
||||||
ls_name, disk.path);
|
ls_name, disk.path);
|
||||||
return -EDEVOPEN;
|
return -EDEVOPEN;
|
||||||
} else {
|
} else {
|
||||||
log_error("S %s init_vg_san sanlock error %d trying to get align size of %s",
|
log_error("S %s init_vg_san sanlock error %d trying to get sector/align size of %s",
|
||||||
ls_name, rv, disk.path);
|
ls_name, rv, disk.path);
|
||||||
return -EARGS;
|
return -EARGS;
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
align_size = rv;
|
|
||||||
|
|
||||||
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
|
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
|
||||||
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
|
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
|
||||||
ss.host_id_disk.offset = LS_BEGIN * align_size;
|
ss.host_id_disk.offset = 0;
|
||||||
|
ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
|
||||||
|
(SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M);
|
||||||
|
|
||||||
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
|
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
@@ -436,6 +611,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
|||||||
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
|
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
|
||||||
rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
|
rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
|
||||||
rd.rs.num_disks = 1;
|
rd.rs.num_disks = 1;
|
||||||
|
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
|
||||||
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
|
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
@@ -449,6 +626,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
|||||||
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
|
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
|
||||||
rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
|
rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
|
||||||
rd.rs.num_disks = 1;
|
rd.rs.num_disks = 1;
|
||||||
|
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
|
||||||
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
|
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
@@ -460,7 +639,9 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
|||||||
if (!strcmp(gl_name, R_NAME_GL))
|
if (!strcmp(gl_name, R_NAME_GL))
|
||||||
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
|
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
|
||||||
|
|
||||||
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
|
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
|
||||||
|
if (rv >= MAX_ARGS)
|
||||||
|
log_debug("init_vg_san vg_args may be too long %d %s", rv, vg_args);
|
||||||
|
|
||||||
log_debug("S %s init_vg_san done vg_args %s", ls_name, vg_args);
|
log_debug("S %s init_vg_san done vg_args %s", ls_name, vg_args);
|
||||||
|
|
||||||
@@ -472,6 +653,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
|||||||
|
|
||||||
memset(&rd, 0, sizeof(rd));
|
memset(&rd, 0, sizeof(rd));
|
||||||
rd.rs.num_disks = 1;
|
rd.rs.num_disks = 1;
|
||||||
|
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
|
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
|
||||||
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
|
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
|
||||||
strcpy(rd.rs.name, "#unused");
|
strcpy(rd.rs.name, "#unused");
|
||||||
@@ -510,13 +693,13 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
|
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
|
||||||
char *vg_args, char *lv_args, uint64_t free_offset)
|
char *vg_args, char *lv_args,
|
||||||
|
int sector_size, int align_size, uint64_t free_offset)
|
||||||
{
|
{
|
||||||
struct sanlk_resourced rd;
|
struct sanlk_resourced rd;
|
||||||
char lock_lv_name[MAX_ARGS+1];
|
char lock_lv_name[MAX_ARGS+1];
|
||||||
char lock_args_version[MAX_ARGS+1];
|
char lock_args_version[MAX_VERSION+1];
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
int align_size;
|
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
memset(&rd, 0, sizeof(rd));
|
memset(&rd, 0, sizeof(rd));
|
||||||
@@ -530,11 +713,11 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
|
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
|
||||||
LV_LOCK_ARGS_MAJOR, LV_LOCK_ARGS_MINOR, LV_LOCK_ARGS_PATCH);
|
LV_LOCK_ARGS_MAJOR, LV_LOCK_ARGS_MINOR, LV_LOCK_ARGS_PATCH);
|
||||||
|
|
||||||
if (daemon_test) {
|
if (daemon_test) {
|
||||||
align_size = 1048576;
|
align_size = ONE_MB;
|
||||||
snprintf(lv_args, MAX_ARGS, "%s:%llu",
|
snprintf(lv_args, MAX_ARGS, "%s:%llu",
|
||||||
lock_args_version,
|
lock_args_version,
|
||||||
(unsigned long long)((align_size * LV_LOCK_BEGIN) + (align_size * daemon_test_lv_count)));
|
(unsigned long long)((align_size * LV_LOCK_BEGIN) + (align_size * daemon_test_lv_count)));
|
||||||
@@ -547,12 +730,35 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
|
|||||||
if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
|
if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
align_size = sanlock_align(&rd.rs.disks[0]);
|
/*
|
||||||
if (align_size <= 0) {
|
* These should not usually be zero, maybe only the first time this function is called?
|
||||||
log_error("S %s init_lv_san align error %d", ls_name, align_size);
|
* We need to use the same sector/align sizes that are already being used.
|
||||||
return -EINVAL;
|
*/
|
||||||
|
if (!sector_size || !align_size) {
|
||||||
|
rv = get_sizes_lockspace(rd.rs.disks[0].path, §or_size, &align_size);
|
||||||
|
if (rv < 0) {
|
||||||
|
log_error("S %s init_lv_san read_lockspace error %d %s",
|
||||||
|
ls_name, rv, rd.rs.disks[0].path);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sector_size)
|
||||||
|
log_debug("S %s init_lv_san found ls sector_size %d align_size %d", ls_name, sector_size, align_size);
|
||||||
|
else {
|
||||||
|
/* use the old method */
|
||||||
|
align_size = sanlock_align(&rd.rs.disks[0]);
|
||||||
|
if (align_size <= 0) {
|
||||||
|
log_error("S %s init_lv_san align error %d", ls_name, align_size);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
sector_size = (align_size == ONE_MB) ? 512 : 4096;
|
||||||
|
log_debug("S %s init_lv_san found old sector_size %d align_size %d", ls_name, sector_size, align_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
|
||||||
if (free_offset)
|
if (free_offset)
|
||||||
offset = free_offset;
|
offset = free_offset;
|
||||||
else
|
else
|
||||||
@@ -595,6 +801,8 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
|
|||||||
ls_name, lv_name, (unsigned long long)offset);
|
ls_name, lv_name, (unsigned long long)offset);
|
||||||
|
|
||||||
strncpy(rd.rs.name, lv_name, SANLK_NAME_LEN);
|
strncpy(rd.rs.name, lv_name, SANLK_NAME_LEN);
|
||||||
|
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
|
||||||
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
|
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
|
||||||
if (!rv) {
|
if (!rv) {
|
||||||
@@ -626,7 +834,8 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
|
|||||||
char lock_lv_name[MAX_ARGS+1];
|
char lock_lv_name[MAX_ARGS+1];
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint32_t io_timeout;
|
uint32_t io_timeout;
|
||||||
int align_size;
|
int sector_size = 0;
|
||||||
|
int align_size = 0;
|
||||||
int i, rv;
|
int i, rv;
|
||||||
|
|
||||||
memset(&disk, 0, sizeof(disk));
|
memset(&disk, 0, sizeof(disk));
|
||||||
@@ -655,20 +864,13 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
|
|||||||
/* FIXME: device is not always ready for us here */
|
/* FIXME: device is not always ready for us here */
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
align_size = sanlock_align(&disk);
|
|
||||||
if (align_size <= 0) {
|
|
||||||
log_error("S %s rename_vg_san bad align size %d %s",
|
|
||||||
ls_name, align_size, disk.path);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lockspace
|
* Lockspace
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memset(&ss, 0, sizeof(ss));
|
memset(&ss, 0, sizeof(ss));
|
||||||
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
|
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
|
||||||
ss.host_id_disk.offset = LS_BEGIN * align_size;
|
ss.host_id_disk.offset = 0;
|
||||||
|
|
||||||
rv = sanlock_read_lockspace(&ss, 0, &io_timeout);
|
rv = sanlock_read_lockspace(&ss, 0, &io_timeout);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
@@ -677,6 +879,26 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN8M)) {
|
||||||
|
sector_size = 4096;
|
||||||
|
align_size = 8 * ONE_MB;
|
||||||
|
} else if ((ss.flags & SANLK_LSF_SECTOR512) && (ss.flags & SANLK_LSF_ALIGN1M)) {
|
||||||
|
sector_size = 512;
|
||||||
|
align_size = ONE_MB;
|
||||||
|
} else {
|
||||||
|
/* use the old method */
|
||||||
|
align_size = sanlock_align(&ss.host_id_disk);
|
||||||
|
if (align_size <= 0) {
|
||||||
|
log_error("S %s rename_vg_san unknown sector/align size for %s",
|
||||||
|
ls_name, ss.host_id_disk.path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sector_size = (align_size == ONE_MB) ? 512 : 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sector_size || !align_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
|
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
|
||||||
|
|
||||||
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
|
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
|
||||||
@@ -830,6 +1052,11 @@ int lm_ex_disable_gl_sanlock(struct lockspace *ls)
|
|||||||
rd1.rs.num_disks = 1;
|
rd1.rs.num_disks = 1;
|
||||||
strncpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
|
strncpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
|
||||||
rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
|
rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
|
||||||
|
|
||||||
|
rd1.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
rd2.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
|
||||||
rv = sanlock_acquire(lms->sock, -1, 0, 1, &rs1, NULL);
|
rv = sanlock_acquire(lms->sock, -1, 0, 1, &rs1, NULL);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
@@ -891,6 +1118,8 @@ int lm_able_gl_sanlock(struct lockspace *ls, int enable)
|
|||||||
rd.rs.num_disks = 1;
|
rd.rs.num_disks = 1;
|
||||||
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
|
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
|
||||||
rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
|
rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
|
||||||
|
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
|
||||||
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
|
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
@@ -936,7 +1165,8 @@ static int gl_is_enabled(struct lockspace *ls, struct lm_sanlock *lms)
|
|||||||
|
|
||||||
rv = sanlock_read_resource(&rd.rs, 0);
|
rv = sanlock_read_resource(&rd.rs, 0);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
log_error("gl_is_enabled read_resource error %d", rv);
|
log_error("gl_is_enabled read_resource align_size %d offset %llu error %d",
|
||||||
|
lms->align_size, (unsigned long long)offset, rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -973,7 +1203,7 @@ int lm_gl_is_enabled(struct lockspace *ls)
|
|||||||
* been disabled.)
|
* been disabled.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
|
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
|
||||||
{
|
{
|
||||||
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
|
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
|
||||||
struct sanlk_resourced rd;
|
struct sanlk_resourced rd;
|
||||||
@@ -983,15 +1213,22 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
|
|||||||
int round = 0;
|
int round = 0;
|
||||||
|
|
||||||
if (daemon_test) {
|
if (daemon_test) {
|
||||||
*free_offset = (1048576 * LV_LOCK_BEGIN) + (1048576 * (daemon_test_lv_count + 1));
|
*free_offset = (ONE_MB * LV_LOCK_BEGIN) + (ONE_MB * (daemon_test_lv_count + 1));
|
||||||
|
*sector_size = 512;
|
||||||
|
*align_size = ONE_MB;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*sector_size = lms->sector_size;
|
||||||
|
*align_size = lms->align_size;
|
||||||
|
|
||||||
memset(&rd, 0, sizeof(rd));
|
memset(&rd, 0, sizeof(rd));
|
||||||
|
|
||||||
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
|
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
|
||||||
rd.rs.num_disks = 1;
|
rd.rs.num_disks = 1;
|
||||||
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
|
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
|
||||||
|
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
|
||||||
|
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
|
||||||
if (ls->free_lock_offset)
|
if (ls->free_lock_offset)
|
||||||
offset = ls->free_lock_offset;
|
offset = ls->free_lock_offset;
|
||||||
@@ -1091,6 +1328,8 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
|
|||||||
char disk_path[SANLK_PATH_LEN];
|
char disk_path[SANLK_PATH_LEN];
|
||||||
char killpath[SANLK_PATH_LEN];
|
char killpath[SANLK_PATH_LEN];
|
||||||
char killargs[SANLK_PATH_LEN];
|
char killargs[SANLK_PATH_LEN];
|
||||||
|
int sector_size = 0;
|
||||||
|
int align_size = 0;
|
||||||
int gl_found;
|
int gl_found;
|
||||||
int ret, rv;
|
int ret, rv;
|
||||||
|
|
||||||
@@ -1160,7 +1399,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
lms = malloc(sizeof(struct lm_sanlock));
|
lms = zalloc(sizeof(struct lm_sanlock));
|
||||||
if (!lms) {
|
if (!lms) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -1169,7 +1408,6 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
|
|||||||
memset(lsname, 0, sizeof(lsname));
|
memset(lsname, 0, sizeof(lsname));
|
||||||
strncpy(lsname, ls->name, SANLK_NAME_LEN);
|
strncpy(lsname, ls->name, SANLK_NAME_LEN);
|
||||||
|
|
||||||
memset(lms, 0, sizeof(struct lm_sanlock));
|
|
||||||
memcpy(lms->ss.name, lsname, SANLK_NAME_LEN);
|
memcpy(lms->ss.name, lsname, SANLK_NAME_LEN);
|
||||||
lms->ss.host_id_disk.offset = 0;
|
lms->ss.host_id_disk.offset = 0;
|
||||||
lms->ss.host_id = ls->host_id;
|
lms->ss.host_id = ls->host_id;
|
||||||
@@ -1207,13 +1445,34 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
lms->align_size = sanlock_align(&lms->ss.host_id_disk);
|
rv = get_sizes_lockspace(disk_path, §or_size, &align_size);
|
||||||
if (lms->align_size <= 0) {
|
if (rv < 0) {
|
||||||
log_error("S %s prepare_lockspace_san align error %d", lsname, lms->align_size);
|
log_error("S %s prepare_lockspace_san cannot get sector/align sizes %d", lsname, rv);
|
||||||
ret = -EMANAGER;
|
ret = -EMANAGER;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sector_size) {
|
||||||
|
log_debug("S %s prepare_lockspace_san using old size method", lsname);
|
||||||
|
/* use the old method */
|
||||||
|
align_size = sanlock_align(&lms->ss.host_id_disk);
|
||||||
|
if (align_size <= 0) {
|
||||||
|
log_error("S %s prepare_lockspace_san align error %d", lsname, align_size);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
sector_size = (align_size == ONE_MB) ? 512 : 4096;
|
||||||
|
log_debug("S %s prepare_lockspace_san found old sector_size %d align_size %d", lsname, sector_size, align_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("S %s prepare_lockspace_san sizes %d %d", lsname, sector_size, align_size);
|
||||||
|
|
||||||
|
lms->align_size = align_size;
|
||||||
|
lms->sector_size = sector_size;
|
||||||
|
|
||||||
|
lms->ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
|
||||||
|
(SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M);
|
||||||
|
|
||||||
gl_found = gl_is_enabled(ls, lms);
|
gl_found = gl_is_enabled(ls, lms);
|
||||||
if (gl_found < 0) {
|
if (gl_found < 0) {
|
||||||
log_error("S %s prepare_lockspace_san gl_enabled error %d", lsname, gl_found);
|
log_error("S %s prepare_lockspace_san gl_enabled error %d", lsname, gl_found);
|
||||||
@@ -1351,6 +1610,7 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
|
|||||||
strncpy(rds->rs.name, r->name, SANLK_NAME_LEN);
|
strncpy(rds->rs.name, r->name, SANLK_NAME_LEN);
|
||||||
rds->rs.num_disks = 1;
|
rds->rs.num_disks = 1;
|
||||||
memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN);
|
memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN);
|
||||||
|
rds->rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
|
||||||
|
|
||||||
if (r->type == LD_RT_GL)
|
if (r->type == LD_RT_GL)
|
||||||
rds->rs.disks[0].offset = GL_LOCK_BEGIN * lms->align_size;
|
rds->rs.disks[0].offset = GL_LOCK_BEGIN * lms->align_size;
|
||||||
@@ -1360,10 +1620,9 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
|
|||||||
/* LD_RT_LV offset is set in each lm_lock call from lv_args. */
|
/* LD_RT_LV offset is set in each lm_lock call from lv_args. */
|
||||||
|
|
||||||
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
|
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
|
||||||
rds->vb = malloc(sizeof(struct val_blk));
|
rds->vb = zalloc(sizeof(struct val_blk));
|
||||||
if (!rds->vb)
|
if (!rds->vb)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
memset(rds->vb, 0, sizeof(struct val_blk));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1860,12 +2119,20 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
|
|||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
log_error("S %s R %s unlock_san release error %d", ls->name, r->name, rv);
|
log_error("S %s R %s unlock_san release error %d", ls->name, r->name, rv);
|
||||||
|
|
||||||
if (rv == -EIO)
|
/*
|
||||||
rv = -ELOCKIO;
|
* sanlock may return an error here if it fails to release the lease on
|
||||||
else if (rv < 0)
|
* disk because of an io timeout. But, sanlock will continue trying to
|
||||||
rv = -ELMERR;
|
* release the lease after this call returns. We shouldn't return an
|
||||||
|
* error here which would result in lvmlockd-core keeping the lock
|
||||||
|
* around. By releasing the lock in lvmlockd-core at this point,
|
||||||
|
* lvmlockd may send another acquire request to lvmlockd. If sanlock
|
||||||
|
* has not been able to release the previous instance of the lock yet,
|
||||||
|
* then it will return an error for the new request. But, acquiring a
|
||||||
|
* new lock is able o fail gracefully, until sanlock is finally able to
|
||||||
|
* release the old lock.
|
||||||
|
*/
|
||||||
|
|
||||||
return rv;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lm_hosts_sanlock(struct lockspace *ls, int notify)
|
int lm_hosts_sanlock(struct lockspace *ls, int notify)
|
||||||
|
|||||||
@@ -29,15 +29,16 @@ include $(top_builddir)/make.tmpl
|
|||||||
|
|
||||||
CFLAGS += $(EXTRA_EXEC_CFLAGS)
|
CFLAGS += $(EXTRA_EXEC_CFLAGS)
|
||||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||||
LIBS += $(DAEMON_LIBS) -ldaemonserver -ldevmapper $(PTHREAD_LIBS)
|
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||||
|
|
||||||
lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
|
||||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
@echo " [CC] $@"
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)
|
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
|
||||||
|
|
||||||
install_lvmpolld: lvmpolld
|
install_lvmpolld: lvmpolld
|
||||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
@echo " [INSTALL] $<"
|
||||||
|
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||||
|
|
||||||
install_lvm2: install_lvmpolld
|
install_lvm2: install_lvmpolld
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *ind)
|
|||||||
const char **newargv;
|
const char **newargv;
|
||||||
|
|
||||||
if (*ind && !(*ind % MIN_ARGV_SIZE)) {
|
if (*ind && !(*ind % MIN_ARGV_SIZE)) {
|
||||||
newargv = dm_realloc(*cmdargv, (*ind / MIN_ARGV_SIZE + 1) * MIN_ARGV_SIZE * sizeof(char *));
|
newargv = realloc(*cmdargv, (*ind / MIN_ARGV_SIZE + 1) * MIN_ARGV_SIZE * sizeof(char *));
|
||||||
if (!newargv)
|
if (!newargv)
|
||||||
return 0;
|
return 0;
|
||||||
*cmdargv = newargv;
|
*cmdargv = newargv;
|
||||||
@@ -50,7 +50,7 @@ static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *ind)
|
|||||||
const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary, unsigned abort_polling, unsigned handle_missing_pvs)
|
const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary, unsigned abort_polling, unsigned handle_missing_pvs)
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
const char **cmd_argv = dm_malloc(MIN_ARGV_SIZE * sizeof(char *));
|
const char **cmd_argv = malloc(MIN_ARGV_SIZE * sizeof(char *));
|
||||||
|
|
||||||
if (!cmd_argv)
|
if (!cmd_argv)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -98,7 +98,7 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary,
|
|||||||
|
|
||||||
return cmd_argv;
|
return cmd_argv;
|
||||||
err:
|
err:
|
||||||
dm_free(cmd_argv);
|
free(cmd_argv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ static int copy_env(const char ***cmd_envp, unsigned *i, const char *exclude)
|
|||||||
const char **cmdenvp_ctr(const struct lvmpolld_lv *pdlv)
|
const char **cmdenvp_ctr(const struct lvmpolld_lv *pdlv)
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
const char **cmd_envp = dm_malloc(MIN_ARGV_SIZE * sizeof(char *));
|
const char **cmd_envp = malloc(MIN_ARGV_SIZE * sizeof(char *));
|
||||||
|
|
||||||
if (!cmd_envp)
|
if (!cmd_envp)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -141,6 +141,6 @@ const char **cmdenvp_ctr(const struct lvmpolld_lv *pdlv)
|
|||||||
|
|
||||||
return cmd_envp;
|
return cmd_envp;
|
||||||
err:
|
err:
|
||||||
dm_free(cmd_envp);
|
free(cmd_envp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,10 @@
|
|||||||
#ifndef _LVM_LVMPOLLD_COMMON_H
|
#ifndef _LVM_LVMPOLLD_COMMON_H
|
||||||
#define _LVM_LVMPOLLD_COMMON_H
|
#define _LVM_LVMPOLLD_COMMON_H
|
||||||
|
|
||||||
#define _REENTRANT
|
#include "tools/tool.h"
|
||||||
|
|
||||||
#include "tool.h"
|
|
||||||
|
|
||||||
#include "lvmpolld-cmd-utils.h"
|
#include "lvmpolld-cmd-utils.h"
|
||||||
#include "lvmpolld-protocol.h"
|
#include "daemons/lvmpolld/lvmpolld-protocol.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|||||||
@@ -530,7 +530,7 @@ static response progress_info(client_handle h, struct lvmpolld_state *ls, reques
|
|||||||
|
|
||||||
pdst_unlock(pdst);
|
pdst_unlock(pdst);
|
||||||
|
|
||||||
dm_free(id);
|
free(id);
|
||||||
|
|
||||||
if (pdlv) {
|
if (pdlv) {
|
||||||
if (st.error)
|
if (st.error)
|
||||||
@@ -673,7 +673,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
|
|||||||
PD_LOG_PREFIX, "poll operation type mismatch on LV identified by",
|
PD_LOG_PREFIX, "poll operation type mismatch on LV identified by",
|
||||||
id,
|
id,
|
||||||
polling_op(pdlv_get_type(pdlv)), polling_op(type));
|
polling_op(pdlv_get_type(pdlv)), polling_op(type));
|
||||||
dm_free(id);
|
free(id);
|
||||||
return reply(LVMPD_RESP_EINVAL,
|
return reply(LVMPD_RESP_EINVAL,
|
||||||
REASON_DIFFERENT_OPERATION_IN_PROGRESS);
|
REASON_DIFFERENT_OPERATION_IN_PROGRESS);
|
||||||
}
|
}
|
||||||
@@ -683,14 +683,14 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
|
|||||||
lvname, sysdir, type, abort_polling, 2 * uinterval);
|
lvname, sysdir, type, abort_polling, 2 * uinterval);
|
||||||
if (!pdlv) {
|
if (!pdlv) {
|
||||||
pdst_unlock(pdst);
|
pdst_unlock(pdst);
|
||||||
dm_free(id);
|
free(id);
|
||||||
return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
|
return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
|
||||||
}
|
}
|
||||||
if (!pdst_locked_insert(pdst, id, pdlv)) {
|
if (!pdst_locked_insert(pdst, id, pdlv)) {
|
||||||
pdlv_destroy(pdlv);
|
pdlv_destroy(pdlv);
|
||||||
pdst_unlock(pdst);
|
pdst_unlock(pdst);
|
||||||
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "couldn't store internal LV data structure");
|
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "couldn't store internal LV data structure");
|
||||||
dm_free(id);
|
free(id);
|
||||||
return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
|
return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
|
||||||
}
|
}
|
||||||
if (!spawn_detached_thread(pdlv)) {
|
if (!spawn_detached_thread(pdlv)) {
|
||||||
@@ -698,7 +698,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
|
|||||||
pdst_locked_remove(pdst, id);
|
pdst_locked_remove(pdst, id);
|
||||||
pdlv_destroy(pdlv);
|
pdlv_destroy(pdlv);
|
||||||
pdst_unlock(pdst);
|
pdst_unlock(pdst);
|
||||||
dm_free(id);
|
free(id);
|
||||||
return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
|
return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,7 +709,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
|
|||||||
|
|
||||||
pdst_unlock(pdst);
|
pdst_unlock(pdst);
|
||||||
|
|
||||||
dm_free(id);
|
free(id);
|
||||||
|
|
||||||
return daemon_reply_simple(LVMPD_RESP_OK, NULL);
|
return daemon_reply_simple(LVMPD_RESP_OK, NULL);
|
||||||
}
|
}
|
||||||
@@ -806,7 +806,7 @@ static int printout_raw_response(const char *prefix, const char *msg)
|
|||||||
char *buf;
|
char *buf;
|
||||||
char *pos;
|
char *pos;
|
||||||
|
|
||||||
buf = dm_strdup(msg);
|
buf = strdup(msg);
|
||||||
pos = buf;
|
pos = buf;
|
||||||
|
|
||||||
if (!buf)
|
if (!buf)
|
||||||
@@ -819,7 +819,7 @@ static int printout_raw_response(const char *prefix, const char *msg)
|
|||||||
_log_line(pos, &b);
|
_log_line(pos, &b);
|
||||||
pos = next ? next + 1 : 0;
|
pos = next ? next + 1 : 0;
|
||||||
}
|
}
|
||||||
dm_free(buf);
|
free(buf);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -915,7 +915,7 @@ int main(int argc, char *argv[])
|
|||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
int client = 0, server = 0;
|
int client = 0, server = 0;
|
||||||
unsigned action = ACTION_MAX;
|
unsigned action = ACTION_MAX;
|
||||||
struct timeval timeout;
|
struct timespec timeout;
|
||||||
daemon_idle di = { .ptimeout = &timeout };
|
daemon_idle di = { .ptimeout = &timeout };
|
||||||
struct lvmpolld_state ls = { .log_config = "" };
|
struct lvmpolld_state ls = { .log_config = "" };
|
||||||
daemon_state s = {
|
daemon_state s = {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include "lvmpolld-common.h"
|
#include "lvmpolld-common.h"
|
||||||
|
|
||||||
#include "config-util.h"
|
#include "libdaemon/client/config-util.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -27,12 +27,12 @@ static char *_construct_full_lvname(const char *vgname, const char *lvname)
|
|||||||
size_t l;
|
size_t l;
|
||||||
|
|
||||||
l = strlen(vgname) + strlen(lvname) + 2; /* vg/lv and \0 */
|
l = strlen(vgname) + strlen(lvname) + 2; /* vg/lv and \0 */
|
||||||
name = (char *) dm_malloc(l * sizeof(char));
|
name = (char *) malloc(l * sizeof(char));
|
||||||
if (!name)
|
if (!name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (dm_snprintf(name, l, "%s/%s", vgname, lvname) < 0) {
|
if (dm_snprintf(name, l, "%s/%s", vgname, lvname) < 0) {
|
||||||
dm_free(name);
|
free(name);
|
||||||
name = NULL;
|
name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ static char *_construct_lvm_system_dir_env(const char *sysdir)
|
|||||||
* just single char to store NULL byte
|
* just single char to store NULL byte
|
||||||
*/
|
*/
|
||||||
size_t l = sysdir ? strlen(sysdir) + 16 : 1;
|
size_t l = sysdir ? strlen(sysdir) + 16 : 1;
|
||||||
char *env = (char *) dm_malloc(l * sizeof(char));
|
char *env = (char *) malloc(l * sizeof(char));
|
||||||
|
|
||||||
if (!env)
|
if (!env)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -55,7 +55,7 @@ static char *_construct_lvm_system_dir_env(const char *sysdir)
|
|||||||
*env = '\0';
|
*env = '\0';
|
||||||
|
|
||||||
if (sysdir && dm_snprintf(env, l, "%s%s", LVM_SYSTEM_DIR, sysdir) < 0) {
|
if (sysdir && dm_snprintf(env, l, "%s%s", LVM_SYSTEM_DIR, sysdir) < 0) {
|
||||||
dm_free(env);
|
free(env);
|
||||||
env = NULL;
|
env = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ char *construct_id(const char *sysdir, const char *uuid)
|
|||||||
size_t l;
|
size_t l;
|
||||||
|
|
||||||
l = strlen(uuid) + (sysdir ? strlen(sysdir) : 0) + 1;
|
l = strlen(uuid) + (sysdir ? strlen(sysdir) : 0) + 1;
|
||||||
id = (char *) dm_malloc(l * sizeof(char));
|
id = (char *) malloc(l * sizeof(char));
|
||||||
if (!id)
|
if (!id)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ char *construct_id(const char *sysdir, const char *uuid)
|
|||||||
dm_snprintf(id, l, "%s", uuid);
|
dm_snprintf(id, l, "%s", uuid);
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
dm_free(id);
|
free(id);
|
||||||
id = NULL;
|
id = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
|||||||
const char *sinterval, unsigned pdtimeout,
|
const char *sinterval, unsigned pdtimeout,
|
||||||
struct lvmpolld_store *pdst)
|
struct lvmpolld_store *pdst)
|
||||||
{
|
{
|
||||||
char *lvmpolld_id = dm_strdup(id), /* copy */
|
char *lvmpolld_id = strdup(id), /* copy */
|
||||||
*full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
|
*full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
|
||||||
*lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
|
*lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
|
||||||
|
|
||||||
@@ -106,12 +106,12 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
|||||||
.lvid = _get_lvid(lvmpolld_id, sysdir),
|
.lvid = _get_lvid(lvmpolld_id, sysdir),
|
||||||
.lvname = full_lvname,
|
.lvname = full_lvname,
|
||||||
.lvm_system_dir_env = lvm_system_dir_env,
|
.lvm_system_dir_env = lvm_system_dir_env,
|
||||||
.sinterval = dm_strdup(sinterval), /* copy */
|
.sinterval = strdup(sinterval), /* copy */
|
||||||
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
|
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
|
||||||
.cmd_state = { .retcode = -1, .signal = 0 },
|
.cmd_state = { .retcode = -1, .signal = 0 },
|
||||||
.pdst = pdst,
|
.pdst = pdst,
|
||||||
.init_rq_count = 1
|
.init_rq_count = 1
|
||||||
}, *pdlv = (struct lvmpolld_lv *) dm_malloc(sizeof(struct lvmpolld_lv));
|
}, *pdlv = (struct lvmpolld_lv *) malloc(sizeof(struct lvmpolld_lv));
|
||||||
|
|
||||||
if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
|
if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -124,27 +124,27 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
|||||||
return pdlv;
|
return pdlv;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
dm_free((void *)full_lvname);
|
free((void *)full_lvname);
|
||||||
dm_free((void *)lvmpolld_id);
|
free((void *)lvmpolld_id);
|
||||||
dm_free((void *)lvm_system_dir_env);
|
free((void *)lvm_system_dir_env);
|
||||||
dm_free((void *)tmp.sinterval);
|
free((void *)tmp.sinterval);
|
||||||
dm_free((void *)pdlv);
|
free((void *)pdlv);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdlv_destroy(struct lvmpolld_lv *pdlv)
|
void pdlv_destroy(struct lvmpolld_lv *pdlv)
|
||||||
{
|
{
|
||||||
dm_free((void *)pdlv->lvmpolld_id);
|
free((void *)pdlv->lvmpolld_id);
|
||||||
dm_free((void *)pdlv->lvname);
|
free((void *)pdlv->lvname);
|
||||||
dm_free((void *)pdlv->sinterval);
|
free((void *)pdlv->sinterval);
|
||||||
dm_free((void *)pdlv->lvm_system_dir_env);
|
free((void *)pdlv->lvm_system_dir_env);
|
||||||
dm_free((void *)pdlv->cmdargv);
|
free((void *)pdlv->cmdargv);
|
||||||
dm_free((void *)pdlv->cmdenvp);
|
free((void *)pdlv->cmdenvp);
|
||||||
|
|
||||||
pthread_mutex_destroy(&pdlv->lock);
|
pthread_mutex_destroy(&pdlv->lock);
|
||||||
|
|
||||||
dm_free((void *)pdlv);
|
free((void *)pdlv);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv)
|
unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv)
|
||||||
@@ -194,7 +194,7 @@ void pdlv_set_polling_finished(struct lvmpolld_lv *pdlv, unsigned finished)
|
|||||||
|
|
||||||
struct lvmpolld_store *pdst_init(const char *name)
|
struct lvmpolld_store *pdst_init(const char *name)
|
||||||
{
|
{
|
||||||
struct lvmpolld_store *pdst = (struct lvmpolld_store *) dm_malloc(sizeof(struct lvmpolld_store));
|
struct lvmpolld_store *pdst = (struct lvmpolld_store *) malloc(sizeof(struct lvmpolld_store));
|
||||||
if (!pdst)
|
if (!pdst)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ struct lvmpolld_store *pdst_init(const char *name)
|
|||||||
err_mutex:
|
err_mutex:
|
||||||
dm_hash_destroy(pdst->store);
|
dm_hash_destroy(pdst->store);
|
||||||
err_hash:
|
err_hash:
|
||||||
dm_free(pdst);
|
free(pdst);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ void pdst_destroy(struct lvmpolld_store *pdst)
|
|||||||
|
|
||||||
dm_hash_destroy(pdst->store);
|
dm_hash_destroy(pdst->store);
|
||||||
pthread_mutex_destroy(&pdst->lock);
|
pthread_mutex_destroy(&pdst->lock);
|
||||||
dm_free(pdst);
|
free(pdst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdst_locked_lock_all_pdlvs(const struct lvmpolld_store *pdst)
|
void pdst_locked_lock_all_pdlvs(const struct lvmpolld_store *pdst)
|
||||||
@@ -321,7 +321,7 @@ void pdst_locked_destroy_all_pdlvs(const struct lvmpolld_store *pdst)
|
|||||||
|
|
||||||
struct lvmpolld_thread_data *lvmpolld_thread_data_constructor(struct lvmpolld_lv *pdlv)
|
struct lvmpolld_thread_data *lvmpolld_thread_data_constructor(struct lvmpolld_lv *pdlv)
|
||||||
{
|
{
|
||||||
struct lvmpolld_thread_data *data = (struct lvmpolld_thread_data *) dm_malloc(sizeof(struct lvmpolld_thread_data));
|
struct lvmpolld_thread_data *data = (struct lvmpolld_thread_data *) malloc(sizeof(struct lvmpolld_thread_data));
|
||||||
if (!data)
|
if (!data)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@ void lvmpolld_thread_data_destroy(void *thread_private)
|
|||||||
pdst_unlock(data->pdlv->pdst);
|
pdst_unlock(data->pdlv->pdst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* may get reallocated in getline(). dm_free must not be used */
|
/* may get reallocated in getline(). free must not be used */
|
||||||
free(data->line);
|
free(data->line);
|
||||||
|
|
||||||
if (data->fout && !fclose(data->fout))
|
if (data->fout && !fclose(data->fout))
|
||||||
@@ -389,5 +389,5 @@ void lvmpolld_thread_data_destroy(void *thread_private)
|
|||||||
if (data->errpipe[1] >= 0)
|
if (data->errpipe[1] >= 0)
|
||||||
(void) close(data->errpipe[1]);
|
(void) close(data->errpipe[1]);
|
||||||
|
|
||||||
dm_free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#ifndef _LVM_LVMPOLLD_PROTOCOL_H
|
#ifndef _LVM_LVMPOLLD_PROTOCOL_H
|
||||||
#define _LVM_LVMPOLLD_PROTOCOL_H
|
#define _LVM_LVMPOLLD_PROTOCOL_H
|
||||||
|
|
||||||
#include "polling_ops.h"
|
#include "daemons/lvmpolld/polling_ops.h"
|
||||||
|
|
||||||
#define LVMPOLLD_PROTOCOL "lvmpolld"
|
#define LVMPOLLD_PROTOCOL "lvmpolld"
|
||||||
#define LVMPOLLD_PROTOCOL_VERSION 1
|
#define LVMPOLLD_PROTOCOL_VERSION 1
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user