mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-29 13:44:18 +03:00
Compare commits
826 Commits
dev-dct-dm
...
dev-dct-se
Author | SHA1 | Date | |
---|---|---|---|
|
60270a4288 | ||
|
813d333e0c | ||
|
5e6ff6f446 | ||
|
38c1124a47 | ||
|
f83ad85b16 | ||
|
cf2b027d47 | ||
|
ba16339bc4 | ||
|
6db8e63996 | ||
|
5b410e589c | ||
|
a93729b004 | ||
|
ce5d7d11b3 | ||
|
cb72f6217e | ||
|
59fb9f5d3a | ||
|
be3224b3f5 | ||
|
5f8b2e0e53 | ||
|
ed8d913c78 | ||
|
b2cd886a12 | ||
|
279d3feaae | ||
|
ee32cabd0f | ||
|
ca6fe99162 | ||
|
d89869f17e | ||
|
16d3195a69 | ||
|
63250dfe8d | ||
|
47118a45bd | ||
|
7086da4335 | ||
|
4d8819218e | ||
|
8dcdcc54b4 | ||
|
436778f6df | ||
|
881df5e071 | ||
|
e61aab7049 | ||
|
b2bc06caf8 | ||
|
95e7e48d86 | ||
|
4380986053 | ||
|
bada07d267 | ||
|
ae75b70e5b | ||
|
e04e784575 | ||
|
b1462ea09b | ||
|
6d8585c249 | ||
|
9b95252a94 | ||
|
01fda7092a | ||
|
8a8660107e | ||
|
d75361f445 | ||
|
3fe57cc892 | ||
|
77f1809ddf | ||
|
b32b830f95 | ||
|
3dc5c3fc9e | ||
|
e50e59ae42 | ||
|
5fe7d1150d | ||
|
1854556593 | ||
|
36a0b26054 | ||
|
d9063048cb | ||
|
c74ea97121 | ||
|
e7d6df8600 | ||
|
06c87e4f8a | ||
|
f6abf8abe2 | ||
|
a79085612d | ||
|
bfae3beef0 | ||
|
2ecbfe0246 | ||
|
aab17a04b4 | ||
|
c868c1bbd8 | ||
|
4671f99bdc | ||
|
9636d15473 | ||
|
9ba6eaf702 | ||
|
6a31246bdd | ||
|
c705eda4ad | ||
|
8486aef090 | ||
|
f4398897a8 | ||
|
220f855e8a | ||
|
fa2ec32c4e | ||
|
175a80157a | ||
|
6c6fc6d507 | ||
|
e30289c855 | ||
|
af42fa8553 | ||
|
d5abc55fcf | ||
|
80144223e7 | ||
|
222445f2dc | ||
|
986ff7b9cd | ||
|
1cd2f35655 | ||
|
03e3b27ba0 | ||
|
5da3676ff3 | ||
|
ff7f9ee113 | ||
|
457603e3f1 | ||
|
ce71153788 | ||
|
8fd6300642 | ||
|
f530425f56 | ||
|
612a22ac08 | ||
|
501efc7f3f | ||
|
550a84414b | ||
|
35a4eeebf0 | ||
|
6fa5510b65 | ||
|
bc2e280e8e | ||
|
0b8716e25c | ||
|
ee62860b62 | ||
|
9c599292aa | ||
|
2877232e24 | ||
|
eeaa3b2df3 | ||
|
15c73e044e | ||
|
dedaa201a8 | ||
|
65a997b985 | ||
|
7b383df03e | ||
|
31cea1bbdc | ||
|
e4ef309d62 | ||
|
4cf9077899 | ||
|
2539aadb50 | ||
|
584d6aff95 | ||
|
04d75d7a63 | ||
|
6cb61996b6 | ||
|
527b54cb17 | ||
|
cbd1918dce | ||
|
c53c895612 | ||
|
07bc54f333 | ||
|
eb13823985 | ||
|
312b29ecfe | ||
|
c5084b4ba5 | ||
|
e76eba860f | ||
|
d2a66d4343 | ||
|
bdfdc52093 | ||
|
296fcd4c79 | ||
|
cfeeee9b3d | ||
|
a23ef8e26f | ||
|
ca844f7715 | ||
|
61159f127a | ||
|
274e09755c | ||
|
c6b924c843 | ||
|
8be572d4f4 | ||
|
3e811e5f85 | ||
|
e1e35840f3 | ||
|
0695846dcc | ||
|
ed63b90441 | ||
|
96b0f1a178 | ||
|
1593a6e47c | ||
|
5d16b1d734 | ||
|
adb8ca503b | ||
|
a68cfa5691 | ||
|
7c79abc33f | ||
|
0b7b6ccd79 | ||
|
f82c46e673 | ||
|
b86b1da80a | ||
|
bd26e768ef | ||
|
8e2cdcc006 | ||
|
a2c9e252a0 | ||
|
95c77bc922 | ||
|
3358e0339a | ||
|
f35f074afd | ||
|
78e087f54c | ||
|
e16439b8aa | ||
|
fcca60fda6 | ||
|
592cd62de3 | ||
|
1eaada302b | ||
|
03a343dc9e | ||
|
c03631ed67 | ||
|
a60f958707 | ||
|
ed13916859 | ||
|
c901528053 | ||
|
4bc52d2dc5 | ||
|
69d7beba91 | ||
|
8a7c026451 | ||
|
3541b483d7 | ||
|
0be635934c | ||
|
29dd3800e4 | ||
|
9fcc66316c | ||
|
bf580fcc2f | ||
|
483da854a3 | ||
|
2c5489dd13 | ||
|
ae407d2f3c | ||
|
49e8ecc2dd | ||
|
f1f94d987d | ||
|
29a799961c | ||
|
a53352b4aa | ||
|
ce8dc67c47 | ||
|
543a87e12a | ||
|
5c42822eab | ||
|
5fbdd7014a | ||
|
ad016ea4e3 | ||
|
39a45f212d | ||
|
c45ad22806 | ||
|
c0c47ead98 | ||
|
8873599b66 | ||
|
5f73db83bc | ||
|
2a2ad7317f | ||
|
11154dfab2 | ||
|
50abb2c2c9 | ||
|
e5f0d312b3 | ||
|
2dec6f5493 | ||
|
879fb36f0a | ||
|
bc417b2e25 | ||
|
1fba3b876b | ||
|
460033c3d4 | ||
|
a9ffaeb6c0 | ||
|
c2cca24ff0 | ||
|
8e630ebf2c | ||
|
83debc25a3 | ||
|
6e0fa754be | ||
|
9039295c5e | ||
|
70e8ef249b | ||
|
5f0ddd0fd8 | ||
|
fb250d23f2 | ||
|
2d5ef4a4ef | ||
|
b6878873db | ||
|
6ccc8f801e | ||
|
e3871db279 | ||
|
e97ce575f4 | ||
|
c3e69d89bf | ||
|
0e01a5d3ae | ||
|
6f86a9ad2a | ||
|
a8941ec608 | ||
|
6708b2f5d2 | ||
|
97449a611b | ||
|
4ee806d391 | ||
|
7417698823 | ||
|
63c6a2629a | ||
|
c117dde67a | ||
|
26154af9e4 | ||
|
6b61dea9bb | ||
|
95585bc2fa | ||
|
97768cf302 | ||
|
86f2d0668d | ||
|
f88565316c | ||
|
9aa346a0c6 | ||
|
4ef8acb018 | ||
|
cbf4a7c53b | ||
|
f024936924 | ||
|
0a665d0c17 | ||
|
f110b32239 | ||
|
37b28216fd | ||
|
80b1ccd2f3 | ||
|
46a6d0d2bd | ||
|
93013c09be | ||
|
9edb10b5f4 | ||
|
7c65c16a66 | ||
|
7c9a3ba381 | ||
|
239f4be1f0 | ||
|
759d1bfe11 | ||
|
22364ce9b6 | ||
|
88910c200f | ||
|
53752ef851 | ||
|
dbac36adf0 | ||
|
5d7f862b9b | ||
|
1e7a614c34 | ||
|
0cafb18978 | ||
|
0a8f560c75 | ||
|
03d8661657 | ||
|
b66cc11b78 | ||
|
54f3656b7e | ||
|
a1b27f0656 | ||
|
47a48fd0b6 | ||
|
a494f07aec | ||
|
bd363a4284 | ||
|
9b51b3d3f1 | ||
|
0217887fcd | ||
|
086b0ee6e4 | ||
|
8817523c56 | ||
|
338bb7e68b | ||
|
8acb84f5bd | ||
|
480bf01936 | ||
|
c1bfc8737f | ||
|
fe14628818 | ||
|
df45871754 | ||
|
9b985f3519 | ||
|
dcfa77c345 | ||
|
11b64b0c0c | ||
|
6838881956 | ||
|
5d16beee57 | ||
|
26e86f9da9 | ||
|
b8b0fcfa10 | ||
|
6679438437 | ||
|
1bf3961bbe | ||
|
dcf37af2ca | ||
|
ebbdaccd9c | ||
|
fafc0f76c5 | ||
|
491c6652ae | ||
|
ea73594f07 | ||
|
9ed7528d1f | ||
|
7becd29494 | ||
|
3687f7fee3 | ||
|
74c178f7bf | ||
|
82789f6134 | ||
|
30fdd6b9b4 | ||
|
63088e1f82 | ||
|
579054452b | ||
|
253ef42362 | ||
|
54831ecabd | ||
|
a4951801fa | ||
|
d0c9bcf6d7 | ||
|
43a755d568 | ||
|
12419e3b67 | ||
|
0d17105292 | ||
|
1d94dd075d | ||
|
872e085030 | ||
|
959f775985 | ||
|
0c970d8ec7 | ||
|
8d41afbc1f | ||
|
b4ebf69739 | ||
|
8c696e463f | ||
|
91c29c318f | ||
|
d556d77363 | ||
|
649d17d221 | ||
|
b4a9897bd8 | ||
|
523d796b15 | ||
|
d9832565ec | ||
|
6565ce22b7 | ||
|
53ccbdab1b | ||
|
c065b407cb | ||
|
22b628924f | ||
|
06baec439e | ||
|
92493361f3 | ||
|
5efa388206 | ||
|
fe1cf7174f | ||
|
6e5e7b3193 | ||
|
a6264f6a44 | ||
|
b2f8e744de | ||
|
01e4764c40 | ||
|
c9ee8d8a06 | ||
|
154befd4b8 | ||
|
951fd6358b | ||
|
8efbffe086 | ||
|
cff93e4d5c | ||
|
227d3ca507 | ||
|
cc843151b4 | ||
|
7dd2f101c7 | ||
|
381b45b5a9 | ||
|
8273a6e2e1 | ||
|
c59a8e2d56 | ||
|
a1e449dea2 | ||
|
3a6e221c56 | ||
|
d80d346f4e | ||
|
54ade3a6bb | ||
|
1dcd9fbe08 | ||
|
a853649565 | ||
|
a512bf3c62 | ||
|
9197880050 | ||
|
16bc80c389 | ||
|
4fa6c76181 | ||
|
b4c9f29eb3 | ||
|
8d855ff23a | ||
|
ba9c4368f4 | ||
|
1f728f370f | ||
|
80ee9e45cb | ||
|
297808c269 | ||
|
dfb4ed13f6 | ||
|
be25429ea7 | ||
|
36bdffb6a4 | ||
|
6f9e247285 | ||
|
be0b2ea01a | ||
|
d5ac344465 | ||
|
4789abbcd2 | ||
|
a29d0c014a | ||
|
7d0acdbcb0 | ||
|
5430eec2b9 | ||
|
d83f40d25a | ||
|
c40bd459df | ||
|
d016158ff9 | ||
|
874a8ab4d0 | ||
|
0fe1613c9b | ||
|
56398a2180 | ||
|
bb458e9528 | ||
|
2fae69cc4b | ||
|
0d4418fe6c | ||
|
bb66753a14 | ||
|
c1bc0c9726 | ||
|
685e704373 | ||
|
4be1c7b6ca | ||
|
36be0778f8 | ||
|
6ad474385b | ||
|
b02e6cd4a9 | ||
|
bb0bbc6d74 | ||
|
8417a6a578 | ||
|
79c022133b | ||
|
e3f0af8f1f | ||
|
5359737c29 | ||
|
b13b55884a | ||
|
da19ef49b1 | ||
|
03b78fa666 | ||
|
a87cc133e2 | ||
|
07f23d4b81 | ||
|
8bdc234348 | ||
|
05f1e78f3e | ||
|
9f425a62fc | ||
|
1e91c16112 | ||
|
12efeb6d51 | ||
|
5fd50ae192 | ||
|
5a6d318b29 | ||
|
924221765e | ||
|
a6b2ce6299 | ||
|
464c30e6c3 | ||
|
5e127fb8e9 | ||
|
f66c76e5ea | ||
|
3a700dd2f2 | ||
|
bacd9f394d | ||
|
cb0c43898a | ||
|
ff1f1188c3 | ||
|
9cc6b15dd9 | ||
|
e737c54d8a | ||
|
1d13b391f8 | ||
|
15b3cf1104 | ||
|
4ff8c706db | ||
|
0c3c08b95f | ||
|
063984afde | ||
|
623e98e16c | ||
|
f0a707f6b4 | ||
|
bea43e4faa | ||
|
c326796a89 | ||
|
fd341c818d | ||
|
00a3664a5c | ||
|
625a38c855 | ||
|
04cacff3b9 | ||
|
852f3c20bb | ||
|
8a67936e7e | ||
|
13fcb7e428 | ||
|
736db4247c | ||
|
0bb06eb99b | ||
|
5b92ce741f | ||
|
c0b725d6e6 | ||
|
75a39003b0 | ||
|
e9640e5178 | ||
|
e410715154 | ||
|
d6934ea31d | ||
|
a1017024f1 | ||
|
e7ae3fbd10 | ||
|
8425c1b468 | ||
|
7f12b5d0dc | ||
|
550ce921fa | ||
|
d913d776d1 | ||
|
a9fcc3ab0c | ||
|
a187f02ed5 | ||
|
74a2325261 | ||
|
be1b83a76f | ||
|
87a4e7bb68 | ||
|
7858c25427 | ||
|
425ae9aaf0 | ||
|
2a34723511 | ||
|
ed9468153e | ||
|
09e508cd43 | ||
|
a6408163dd | ||
|
c68af364e7 | ||
|
d5cc65f683 | ||
|
082d475ea9 | ||
|
29bb84f17b | ||
|
48d7511808 | ||
|
ffeee23537 | ||
|
46a48f1320 | ||
|
2c63b12bd3 | ||
|
36ae51c3cb | ||
|
1e21b0a6f2 | ||
|
12f1472972 | ||
|
1719f1169f | ||
|
d32ee0b7ab | ||
|
42a43c37de | ||
|
583e5f952e | ||
|
fd91edfd15 | ||
|
51030c57a1 | ||
|
1e21a93ead | ||
|
cae445443e | ||
|
f582c7be1d | ||
|
09d896810b | ||
|
07b595d0f3 | ||
|
9fe73c8d95 | ||
|
27f0ca79cc | ||
|
5f71cebcbe | ||
|
e907c3cf9a | ||
|
b32c0bb9c5 | ||
|
dd09127608 | ||
|
76b1776367 | ||
|
ebb90fd2c6 | ||
|
7d7b5db230 | ||
|
c2cf9a4cae | ||
|
84aa248f07 | ||
|
6c2debf917 | ||
|
6de7c51dce | ||
|
9f81fccd65 | ||
|
ffbf3a8ca2 | ||
|
8247752ce1 | ||
|
8cbd417e7a | ||
|
a4bf6667f8 | ||
|
b47612cd8b | ||
|
9ad2980996 | ||
|
ecf2cbec7f | ||
|
e95bc8f8c9 | ||
|
970463fc46 | ||
|
d582ee591e | ||
|
14673b2746 | ||
|
8fb58826c0 | ||
|
d7ffd98257 | ||
|
86574ce07a | ||
|
f392dab286 | ||
|
9414dcae3a | ||
|
0d3b87d19f | ||
|
4ef211a187 | ||
|
1576273273 | ||
|
e86a75b4fe | ||
|
036e88eb85 | ||
|
5f53ecda36 | ||
|
5ef958704c | ||
|
e1117164a4 | ||
|
8a9bc6eed8 | ||
|
3e641578d8 | ||
|
6326d00937 | ||
|
928b8e9c6e | ||
|
cb87e184bc | ||
|
d952358636 | ||
|
736d23ad26 | ||
|
32ab91e528 | ||
|
85014fcd6d | ||
|
32cfcfd151 | ||
|
3c365e6c5c | ||
|
4a18f89736 | ||
|
2b82e882ed | ||
|
d8726b07c3 | ||
|
ee97c5c633 | ||
|
f08d1caf47 | ||
|
acd7cfbc08 | ||
|
6c5e8ee18b | ||
|
017c668fd0 | ||
|
ccde015712 | ||
|
9beea2db69 | ||
|
275c9666b6 | ||
|
d791f160a8 | ||
|
75907f0e80 | ||
|
45344262cc | ||
|
c695c7a252 | ||
|
94da2c9792 | ||
|
ce8e6c8c63 | ||
|
60cd279f96 | ||
|
25638f6a87 | ||
|
47c4f737c9 | ||
|
a6e918cd48 | ||
|
c77f2697ee | ||
|
9259892627 | ||
|
2c06950888 | ||
|
5893ca17da | ||
|
e8e4324d68 | ||
|
502543ffed | ||
|
03a3863804 | ||
|
ebadd3ccc6 | ||
|
c4d4bddfce | ||
|
efe5af819a | ||
|
ca5d258376 | ||
|
4c31e6d56a | ||
|
51a684ef0f | ||
|
dfc132a514 | ||
|
473e93fbff | ||
|
270f9306bc | ||
|
7b9bdcb4d4 | ||
|
c2f41c1a59 | ||
|
cbfc31ee2b | ||
|
dcac774f09 | ||
|
e4b5f8a485 | ||
|
c3ed3f28a2 | ||
|
158d3243b6 | ||
|
44a04b71f8 | ||
|
a2ca20dad9 | ||
|
1d8a4c4817 | ||
|
b5249fa3c2 | ||
|
a210e9d768 | ||
|
0fc7266353 | ||
|
2a1a7a863d | ||
|
f7df63748a | ||
|
987256aaa8 | ||
|
d53c71a4f2 | ||
|
dfa74465e9 | ||
|
cf6cbfb7f7 | ||
|
352b1b1817 | ||
|
03782806eb | ||
|
e42ceccc6d | ||
|
f87a6ad6d6 | ||
|
8ada61dbed | ||
|
0aa585a29f | ||
|
fc2e4a7b70 | ||
|
057314ff8d | ||
|
88a085c485 | ||
|
4eb66fd20c | ||
|
354ca52e8c | ||
|
c2afa7a116 | ||
|
db0f1b799f | ||
|
0e5beb92c5 | ||
|
7bf404db3b | ||
|
ae8ba49142 | ||
|
6ebcb0015e | ||
|
699696b0a6 | ||
|
8095a6c14c | ||
|
9e8bd57e15 | ||
|
b66b72b115 | ||
|
30adf7e91c | ||
|
e2a5715a60 | ||
|
0e64d49642 | ||
|
608418e4f2 | ||
|
16241b2dc7 | ||
|
e2b00dd162 | ||
|
b05e0df4e1 | ||
|
86dc72c28c | ||
|
a934231623 | ||
|
708435d187 | ||
|
034b6a262c | ||
|
143545a08c | ||
|
c8a8c7286f | ||
|
5a293968ec | ||
|
43ce78e5c6 | ||
|
aa0200c3ff | ||
|
40010e3eb8 | ||
|
ebc5c0cb1d | ||
|
0fbcb3b308 | ||
|
5ec8f744d0 | ||
|
ea4daeb28e | ||
|
1363a5ffb2 | ||
|
5a3375f958 | ||
|
edfa4955d8 | ||
|
a5e3f0e6dd | ||
|
f61572eef2 | ||
|
87f68f443c | ||
|
7d48c1f6e3 | ||
|
188dd3c357 | ||
|
875012fb5d | ||
|
77332669d0 | ||
|
639fb633d3 | ||
|
9295de7cea | ||
|
2c5bf25187 | ||
|
b88cbc7f17 | ||
|
c27d6695c1 | ||
|
73c7dac1a8 | ||
|
21517c2bd5 | ||
|
1825e782cc | ||
|
956b2c568f | ||
|
c681d4e61a | ||
|
73f24443e5 | ||
|
eb4b307d0c | ||
|
dee8bc9ae4 | ||
|
d62170d646 | ||
|
668c185949 | ||
|
0852c3171d | ||
|
5b1ebed3fc | ||
|
dd856edaab | ||
|
2916a8a1f3 | ||
|
1f0530919e | ||
|
ea39c58127 | ||
|
056ad4a8f4 | ||
|
e0421ee7bf | ||
|
4929c55bc5 | ||
|
7156b4930d | ||
|
96cea466a5 | ||
|
0f793fcbca | ||
|
5666728b27 | ||
|
d121707ffa | ||
|
c19dfe11a5 | ||
|
ccd693d065 | ||
|
34b5d7f8bd | ||
|
5827c9e337 | ||
|
5d2d3c53a4 | ||
|
4dc0ee8e56 | ||
|
7c5cca600c | ||
|
fa11ef6846 | ||
|
1755ceb17c | ||
|
8fcfac7c89 | ||
|
b4156bb4de | ||
|
0179f00e0c | ||
|
89da9ae251 | ||
|
9c9953dc3e | ||
|
fd9f7d10ca | ||
|
f59fa69507 | ||
|
d8996a2a12 | ||
|
c29e3410c9 | ||
|
92158a24a5 | ||
|
2f022f5cbb | ||
|
b185578321 | ||
|
f55c949410 | ||
|
d07e273aff | ||
|
e96d6b7442 | ||
|
6ab2a22fcf | ||
|
8e3db44036 | ||
|
317fae4024 | ||
|
e2e6b08518 | ||
|
207990a877 | ||
|
ec965dde39 | ||
|
b77f7acac8 | ||
|
ca02546649 | ||
|
493d8908fb | ||
|
9d6a3ee547 | ||
|
bd5ca83c43 | ||
|
5096335277 | ||
|
e009becd73 | ||
|
4524778b23 | ||
|
d5d2c98980 | ||
|
84cabd068b | ||
|
4708a354f6 | ||
|
28e7be9f39 | ||
|
0e1e220c3d | ||
|
7f29afdb06 | ||
|
6816366ff1 | ||
|
7447634c26 | ||
|
0862e2b150 | ||
|
74f607952d | ||
|
cb781b3e1d | ||
|
964012fdb9 | ||
|
7e2bb2a35e | ||
|
e9413fb211 | ||
|
9d7c19c2ce | ||
|
d7a028aaad | ||
|
1c3d7dfb07 | ||
|
86a9db05cf | ||
|
f42aef4706 | ||
|
1b68841605 | ||
|
e8383073a9 | ||
|
1e48599193 | ||
|
f7f08ba881 | ||
|
de196f4b60 | ||
|
80d7483322 | ||
|
b7fef5b133 | ||
|
418fb5a3b4 | ||
|
915689f566 | ||
|
a4fa14c73b | ||
|
460ff472f9 | ||
|
0e52e215a8 | ||
|
26a6c69a87 | ||
|
e3a2f7b8ee | ||
|
7d816c6a4a | ||
|
39b7d1ba8f | ||
|
7da47cea35 | ||
|
643bc26595 | ||
|
6a8ba51d82 | ||
|
1c9e619fef | ||
|
bfd5464002 | ||
|
625c55fd6c | ||
|
b8a4fda0f7 | ||
|
a8696ee72a | ||
|
f301f6acbc | ||
|
7a20ac4f61 | ||
|
4313e3896c | ||
|
30e25d0db9 | ||
|
83ae675f8d | ||
|
c65d379769 | ||
|
8e9d7ace7b | ||
|
6de3937ac5 | ||
|
7825d914e3 | ||
|
e2f6af68c2 | ||
|
efbea49971 | ||
|
038760da4f | ||
|
ff2cadbf18 | ||
|
7dbb362c0f | ||
|
07b6174f7c | ||
|
9df8dd97c3 | ||
|
b53a2ae2a4 | ||
|
1ced65b6b4 | ||
|
9472e9c5a0 | ||
|
4efed9ee99 | ||
|
845a65a755 | ||
|
5c6120186d | ||
|
75f9b0c25a | ||
|
bec1860531 | ||
|
012854b3c2 | ||
|
90a845a708 | ||
|
9036862357 | ||
|
2dc6c3d236 | ||
|
b4af2571db | ||
|
a06a49b549 | ||
|
aa75e1f0bf | ||
|
e150931fc4 | ||
|
d1c6da2f66 | ||
|
22672be97d | ||
|
76936f2832 | ||
|
426c3c7b88 | ||
|
78d14a805c | ||
|
07576f7e51 | ||
|
ae8d5113f4 | ||
|
7fdba39b3f | ||
|
0e8c429e30 | ||
|
14dbf6ca7b | ||
|
3eecdcbd64 | ||
|
8281f7c111 | ||
|
be229b0cd1 | ||
|
557b2850ce | ||
|
c288ddd6c8 | ||
|
60fbbd5f5f | ||
|
0eef5ab6e1 | ||
|
f8aa073a8d | ||
|
39e65c8f59 | ||
|
5bf4efbab5 | ||
|
77be3250d9 | ||
|
57e9083c90 | ||
|
76bd678ce3 | ||
|
92fd2cb498 | ||
|
82d145a372 | ||
|
ad1d688734 | ||
|
8b4701d7c4 | ||
|
5551e4a1e9 | ||
|
5f26c05bf2 | ||
|
2f8550a388 | ||
|
3ced86217c | ||
|
200b05cec0 | ||
|
b8869e2d4e | ||
|
24943fe9d3 | ||
|
990f4f7c4f | ||
|
680f7bd676 | ||
|
54a8562804 | ||
|
f1d88007b0 | ||
|
d85ceff9c5 | ||
|
f32fd1fcb9 | ||
|
943e979079 | ||
|
9ea5ff3db5 | ||
|
4d8fb10af2 | ||
|
bada03cd48 | ||
|
e777ef720c | ||
|
5e1d64a991 | ||
|
039be7d5b9 | ||
|
55687b6656 | ||
|
58e75f6178 | ||
|
4dc009c872 | ||
|
bf60cb4da2 | ||
|
1b9bf5007b | ||
|
ab93e1c38d | ||
|
82ea579ba2 | ||
|
21b215ee63 | ||
|
336cb32884 | ||
|
57e6e94a83 | ||
|
88fb07b669 | ||
|
cc344c3e69 | ||
|
e0537559c6 | ||
|
4b126fd953 | ||
|
ed440367b9 | ||
|
e30bc9b179 | ||
|
14f782c5a7 | ||
|
b1d80a0ffd | ||
|
64ccbc4b52 | ||
|
a98beb8ee3 | ||
|
f8907b8f3c | ||
|
d01e5ec126 | ||
|
cc6ddf978a | ||
|
2468b66b30 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -45,6 +45,12 @@ make.tmpl
|
||||
|
||||
coverity/coverity_model.xml
|
||||
|
||||
/.cache/
|
||||
/compile_commands.json
|
||||
|
||||
/doc/.ikiwiki
|
||||
/public
|
||||
|
||||
/libdm/.symver_check
|
||||
|
||||
daemons/clvmd
|
||||
|
@@ -134,6 +134,7 @@ install_system_dirs:
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
|
||||
$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)/var/lib/lvm
|
||||
|
||||
install_initscripts:
|
||||
$(MAKE) -C scripts install_initscripts
|
||||
@@ -172,7 +173,7 @@ help:
|
||||
@echo " lcov-dated Generate lcov with timedate suffix."
|
||||
@echo " lcov-reset Reset lcov counters"
|
||||
@echo " man Build man pages."
|
||||
@echo " print-VARIABLE Resolve make variable."
|
||||
@echo " print-VARIABLE Resolve make variable."
|
||||
@echo " rpm Build rpm."
|
||||
@echo " run-unit-test Run unit tests."
|
||||
@echo " tags Generate c/etags."
|
||||
@@ -194,7 +195,8 @@ ifneq ("$(GENHTML)", "")
|
||||
lcov:
|
||||
$(RM) -rf $(LCOV_REPORTS_DIR)
|
||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||
$(LCOV) --capture --directory $(top_builddir) --ignore-errors source \
|
||||
-find . -name '*.gc[dn][ao]' ! -newer make.tmpl -delete
|
||||
-$(LCOV) --capture --directory $(top_builddir) --ignore-errors source,negative,gcov \
|
||||
--output-file $(LCOV_REPORTS_DIR)/out.info
|
||||
-test ! -s $(LCOV_REPORTS_DIR)/out.info || \
|
||||
$(GENHTML) -o $(LCOV_REPORTS_DIR) --ignore-errors source \
|
||||
|
@@ -1 +1 @@
|
||||
1.02.199-git (2024-05-16)
|
||||
1.02.210-git (2025-09-09)
|
||||
|
292
WHATS_NEW
292
WHATS_NEW
@@ -1,19 +1,152 @@
|
||||
Version 2.03.25 -
|
||||
Version 2.03.36 -
|
||||
==================
|
||||
|
||||
Version 2.03.35 - 09th September 2025
|
||||
=====================================
|
||||
Fix unlocking devices file only after all PVs are processed.
|
||||
Avoid creating system.devices when deleting entries.
|
||||
Fix existing issues with persistent reservations.
|
||||
Fix possible report output format inconsistencies while processing PVs.
|
||||
Allow report options for pv/vg/lvdisplay only if used with -C|--columns.
|
||||
Fix vgsplit failing to split a VG with RAID+integrity or cache with cachevol.
|
||||
Fix --lockopt handling in lvmlockd when --nolocking is used.
|
||||
Optimize dmeventd when remonitoring active devices.
|
||||
|
||||
Version 2.03.34 - 30th July 2025
|
||||
================================
|
||||
Support dmeventd restart when there are no monitored devices.
|
||||
Dmeventd no longer calls 'action commands' on removed devices.
|
||||
Fix reader of VDO metadata on 32bit architecture.
|
||||
Fix lvmdevices --deldev/--delpvid to error out if devices file not writeable.
|
||||
Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
|
||||
Enhanced lvresize -r support for btrfs.
|
||||
Use glibc standard functions htoX, Xtoh functions for endian conversion.
|
||||
Fix structure copying within sanlock's release_rename().
|
||||
Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
|
||||
Add lvmlockd --lockopt repair to reinitialize corrupted sanlock leases.
|
||||
Fix support for lvcreate -T --setautoactivation.
|
||||
Add lvm.conf global/lvresize_fs_helper_executable.
|
||||
Enable lvm to use persistent reservations on a VG.
|
||||
|
||||
Version 2.03.33 - 27th June 2025
|
||||
================================
|
||||
Various spelling, grammar, formatting, test, and build script improvements.
|
||||
Override LC_NUMERIC locale if unsuitable for json_std report format.
|
||||
Repair raid arrays with transiently lost devices.
|
||||
|
||||
Version 2.03.32 - 05th May 2025
|
||||
===============================
|
||||
Lvconvert vdopool conversion properly validates acceptable LVs.
|
||||
Accept thin pool data LV as cacheable LV.
|
||||
Allow using zram block devices (likely for testing).
|
||||
Fix lvresize when resizing COW snapshots already covering origin.
|
||||
Fix lvmdbusd read of executed lvm commands output.
|
||||
Fix construction of DM UUID for cachevol _cdata and _cmeta devices.
|
||||
Ignore PV claims from old metadata when then PV belongs to a new VG.
|
||||
Fix integrity metadata rounding.
|
||||
Accept --autobackup option in pvresize.
|
||||
|
||||
Version 2.03.31 - 27th February 2025
|
||||
====================================
|
||||
Reduce 'mandoc -T lint' reported issues for man pages.
|
||||
Restore support for LVM_SUPPRESS_FD_WARNINGS (2.03.24).
|
||||
Fix uncache and split cache restoring original state of volume.
|
||||
Extend use of lockopt skip to more scenarios.
|
||||
Enhance error path resolving in polling code.
|
||||
Disallow shared activation of LV with CoW snapshot.
|
||||
Fix lvmlockd use in lvremove of CoW snapshot, VDO pool, and uncache.
|
||||
Improve mirror split with opened temporary volumes.
|
||||
Improve pvmove finish with opened temporary volumes.
|
||||
Fix backup limit for devices file, handle over 10,000 files.
|
||||
Ignore reported optimal_io_size not divisible by 4096.
|
||||
Fix busy-loop in config reading when read returned 0.
|
||||
Fix DM cache preserving logic (2.03.28).
|
||||
Improve use of lvmlockd for usecases involving thin volumes and pools.
|
||||
|
||||
Version 2.03.30 - 14th January 2025
|
||||
===================================
|
||||
Lvresize reports origin vdo volume cannot be resized.
|
||||
Support setting reserved_memory|stack of --config cmdline.
|
||||
Fix support for disabling memory locking (2.03.27).
|
||||
Do not extend an LV if FS resize unsupported and '--fs resize' used.
|
||||
Prevent leftover temporary device when converting in use volume to a pool.
|
||||
lvconvert detects early volume in use when converting it to a pool.
|
||||
Handle NVMe with quirk changed WWID not matching WWID in devices file.
|
||||
|
||||
Version 2.03.29 - 09th December 2024
|
||||
====================================
|
||||
Configure --enable/disable-sd-notify to control lvmlockd build with sd-notify.
|
||||
Allow test mode when lvmlockd is built without dlm support.
|
||||
Add a note about RAID + integrity synchronization to lvmraid(7) man page.
|
||||
Add a function for running lvconvert --repair on RAID LVs to lvmdbusd.
|
||||
Improve option section of man pages for listing commands ({pv,lv,vg}{s,display}).
|
||||
Fix renaming of raid sub LVs when converting a volume to raid (2.03.28).
|
||||
Fix segfault/VG write error for raid LV lvextend -i|--stripes -I|--stripesize.
|
||||
Revert ignore -i|--stripes, -I|--stripesize for lvextend on raid0 LV (2.03.27).
|
||||
|
||||
Version 2.03.28 - 04th November 2024
|
||||
====================================
|
||||
Use radix_tree to lookup for UUID within committed metadata.
|
||||
Use radix_tree to lookup LV list entry within VG struct.
|
||||
Introduce setting config/validate_metadata = full | none.
|
||||
Restore fs resize call for lvresize -r on the same size LV (2.03.17).
|
||||
Correct off-by-one devicesfile backup counting.
|
||||
Replace use of dm_hash with radix_tree for lv names and uuids.
|
||||
Refactor vg_validate with uniq_insert and better use of CPU caches.
|
||||
Add radix_tree_uniq_insert.
|
||||
Update DM cache when taking next VG lock instead of dropping it.
|
||||
Generate json string id only for json reporting.
|
||||
For vgsummary use new API call dm_config_parse_only_section().
|
||||
Use radix_tree for PV names mapping.
|
||||
Split check_lv_segment into separate _in/complete_vg variant.
|
||||
Use find_lv instead of find_lv_in_vg when possible.
|
||||
Do a mirror fixup only when mirrors with logs are imported.
|
||||
Add faster crc32 calculation from zlib code for x86_64.
|
||||
Fall back to direct zeroing if BLKZEROOUT fails during new LV initialization.
|
||||
|
||||
Version 2.03.27 - 02nd October 2024
|
||||
===================================
|
||||
Fix swap device size detection using blkid for lvresize/lvreduce/lvextend.
|
||||
Detect GPT partition table and pass partition filter if no partitions defined.
|
||||
Add global/sanlock_align_size option to configure sanlock lease size.
|
||||
Disable mem locking when activation/reserved_stack or reserved_memory is 0.
|
||||
Fix locking issues in lvmlockd leaving thin pool locked.
|
||||
Deprecate vdo settings vdo_write_policy and vdo_write_policy.
|
||||
Lots of typo fixes across lvm2 code base (codespell).
|
||||
Corrected integrity parameter interleave_sectors for DM table line.
|
||||
Ignore -i|--stripes, -I|--stripesize for lvextend on raid0 LV, like raid10.
|
||||
Do not accept duplicate device names for pvcreate.
|
||||
|
||||
Version 2.03.26 - 23rd August 2024
|
||||
==================================
|
||||
Fix internal error reported by pvmove on a VG with single PV.
|
||||
Also accept --mknodes --refresh for vgscan.
|
||||
Fix vgmknodes --refresh to wait for udev before checking /dev content.
|
||||
Use log/report_command_log=1 config setting by default for JSON output format.
|
||||
Fix unreleased memory pools on RAID lvextend.
|
||||
Add --integritysettings option to manipulate dm-integrity settings.
|
||||
|
||||
Version 2.03.25 - 12nd July 2024
|
||||
================================
|
||||
Utilize more radix_tree instead of dm_hash and btree.
|
||||
Refactor DM uuid caching from device_mapper directory.
|
||||
Enhance checking for DM uuid device.
|
||||
Fix lvm shell command completion on tab key (2.03.24).
|
||||
Avoid lockd_vg call to lvmlockd for local VGs.
|
||||
Allow forced change of locktype from none.
|
||||
Handle OPTIONS defined in /etc/sysconfig/lvmlockd.
|
||||
|
||||
Version 2.03.24 - 16th May 2024
|
||||
===============================
|
||||
Lvconvert supports VDO options for thin-pool with vdo conversion.
|
||||
Improve placement to .data.rel.ro and .rodata sections.
|
||||
Fix support for -y and -W when creating thinpool with vdo.
|
||||
Bettter support for runtime valgrind detection.
|
||||
Better support for runtime valgrind detection.
|
||||
Allow command interruption when communicating with dmeventd.
|
||||
Fix resize of VDO volume used for thin pool data volume.
|
||||
Use -Wl,-z,now and -Wl,--as-needed for compilation by default.
|
||||
Require 3.7 as minimal version for sanlock.
|
||||
Share code for closing opened desriptors on program startup.
|
||||
Share code for closing opened descriptors on program startup.
|
||||
Fix memleak in lvmcache.
|
||||
Add configure --with-default-event-activation=ON setting.
|
||||
Fix return value from reporter function when hitting internal error.
|
||||
@@ -57,7 +190,7 @@ Version 2.03.23 - 21st November 2023
|
||||
Support PV lists with thin lvconvert.
|
||||
Fix support for lvm_import_vdo with SCSI VDO volumes.
|
||||
Fix locking issue leading to hanging concurrent vgchange --refresh.
|
||||
Recognize lvm.conf report/headings=2 for full column names in report headings.
|
||||
Recognise lvm.conf report/headings=2 for full column names in report headings.
|
||||
Add --headings none|abbrev|full cmd line option to set report headings type.
|
||||
Fix conversion to thin pool using lvmlockd.
|
||||
Fix conversion from thick into thin volume using lvmlockd.
|
||||
@@ -127,6 +260,7 @@ Version 2.03.17 - 10th November 2022
|
||||
Switch to use mallinfo2 and use it only with glibc.
|
||||
Error out in lvm shell if using a cmd argument not supported in the shell.
|
||||
Fix lvm shell's lastlog command to report previous pre-command failures.
|
||||
Keep libaio locked in memory in critical section.
|
||||
Extend VDO and VDOPOOL without flushing and locking fs.
|
||||
Add --valuesonly option to lvmconfig to print only values without keys.
|
||||
Updates configure with recent autoconf tooling.
|
||||
@@ -146,7 +280,7 @@ Version 2.03.16 - 18th May 2022
|
||||
--deldev.
|
||||
Display writecache block size with lvs -o writecache_block_size.
|
||||
Improve cachesettings description in man lvmcache.
|
||||
Fix lossing of delete message on thin-pool extension.
|
||||
Fix losing of delete message on thin-pool extension.
|
||||
|
||||
Version 2.03.15 - 07th February 2022
|
||||
====================================
|
||||
@@ -233,7 +367,7 @@ Version 2.03.12 - 07th May 2021
|
||||
Fix problem with unbound variable usage within fsadm.
|
||||
Fix IMSM MD RAID detection on 4k devices.
|
||||
Check for presence of VDO target before starting any conversion.
|
||||
Support metatadata profiles with volume VDO pool conversions.
|
||||
Support metadata profiles with volume VDO pool conversions.
|
||||
Support -Zn for conversion of already formatted VDO pools.
|
||||
Avoid removing LVs on error path of lvconvert during creation volumes.
|
||||
Fix crashing lvdisplay when thin volume was waiting for merge.
|
||||
@@ -264,7 +398,7 @@ Version 2.03.11 - 08th January 2021
|
||||
Enhance error handling for fsadm and handle 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 when wiping LVs.
|
||||
Support interruption for bcache waiting.
|
||||
Fix bcache when device has too many failing writes.
|
||||
Fix bcache waiting for IO completion with failing disks.
|
||||
@@ -391,7 +525,7 @@ Version 2.03.03 - 07th June 2019
|
||||
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.
|
||||
Fix missing growth of _pmspare 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.
|
||||
@@ -404,14 +538,14 @@ Version 2.03.03 - 07th June 2019
|
||||
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.
|
||||
Support resizing 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.
|
||||
Drop misleading 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 generator querying 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.
|
||||
@@ -473,7 +607,7 @@ Version 2.02.178-rc1 - 24th May 2018
|
||||
--with-cache switch for ./configure has been removed.
|
||||
Include new unit-test framework and unit tests.
|
||||
Extend validation of region_size for mirror segment.
|
||||
Reload whole device stack when reinitilizing mirror log.
|
||||
Reload whole device stack when reinitializing mirror log.
|
||||
Mirrors without monitoring are WARNING and not blocking on error.
|
||||
Detect too big region_size with clustered mirrors.
|
||||
Fix evaluation of maximal region size for mirror log.
|
||||
@@ -518,7 +652,7 @@ Version 2.02.178-rc1 - 24th May 2018
|
||||
Restore pvmove support for wide-clustered active volumes (2.02.177).
|
||||
Avoid non-exclusive activation of exclusive segment types.
|
||||
Fix trimming sibling PVs when doing a pvmove of raid subLVs.
|
||||
Preserve exclusive activation during thin snaphost merge.
|
||||
Preserve exclusive activation during thin snapshot merge.
|
||||
Avoid exceeding array bounds in allocation tag processing.
|
||||
Add --lockopt to common options and add option to skip selected locks.
|
||||
|
||||
@@ -534,7 +668,7 @@ Version 2.02.177 - 18th December 2017
|
||||
Fix lvmlockd to use pool lock when accessing _tmeta volume.
|
||||
Report expected sanlock_convert errors only when retries fail.
|
||||
Avoid blocking in sanlock_convert on SH to EX lock conversion.
|
||||
Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on decativation.
|
||||
Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on deactivation.
|
||||
Skip read-modify-write when entire block is replaced.
|
||||
Categorise I/O with reason annotations in debug messages.
|
||||
Allow extending of raid LVs created with --nosync after a failed repair.
|
||||
@@ -556,7 +690,7 @@ Version 2.02.177 - 18th December 2017
|
||||
Check raid reshape flags in vg_validate().
|
||||
Add support for pvmove of cache and snapshot origins.
|
||||
Avoid using precommitted metadata for suspending pvmove tree.
|
||||
Ehnance pvmove locking.
|
||||
Enhance pvmove locking.
|
||||
Deactivate activated LVs on error path when pvmove activation fails.
|
||||
Add "io" to log/debug_classes for logging low-level I/O.
|
||||
Eliminate redundant nested VG metadata in VG struct.
|
||||
@@ -646,13 +780,13 @@ Version 2.02.173 - 20th July 2017
|
||||
|
||||
Version 2.02.172 - 28th June 2017
|
||||
=================================
|
||||
Add missing NULL to argv array when spliting cmdline arguments.
|
||||
Add missing NULL to argv array when splitting cmdline arguments.
|
||||
Add display_percent helper function for printing percent values.
|
||||
lvconvert --repair handles failing raid legs (present but marked 'D'ead).
|
||||
Do not lvdisplay --maps unset settings of cache pool.
|
||||
Fix lvdisplay --maps for cache pool without policy settings.
|
||||
Support aborting of flushing cache LV.
|
||||
Reenable conversion of data and metadata thin-pool volumes to raid.
|
||||
Re-enable conversion of data and metadata thin-pool volumes to raid.
|
||||
Improve raid status reporting with lvs.
|
||||
No longer necessary to '--force' a repair for RAID1.
|
||||
Linear to RAID1 upconverts now use "recover" sync action, not "resync".
|
||||
@@ -720,7 +854,7 @@ Version 2.02.169 - 28th March 2017
|
||||
Support cache segment with configurable metadata format.
|
||||
Add allocation/cache_metadata_format profilable settings.
|
||||
Use function cache_set_params() for both lvcreate and lvconvert.
|
||||
Skip rounding on cache chunk size boudary when create cache LV.
|
||||
Skip rounding on cache chunk size boundary when create cache LV.
|
||||
Improve cache_set_params support for chunk_size selection.
|
||||
Fix metadata profile allocation/cache_[mode|policy] setting.
|
||||
Fix missing support for using allocation/cache_pool_chunk_size setting.
|
||||
@@ -770,8 +904,8 @@ Version 2.02.169 - 28th March 2017
|
||||
Extend metadata validation of external origin LV use count.
|
||||
Fix dm table when the last user of active external origin is removed.
|
||||
Improve reported lvs status for active external origin volume.
|
||||
Fix table load for splitted RAID LV and require explicit activation.
|
||||
Always active splitted RAID LV exclusively locally.
|
||||
Fix table load for split RAID LV and require explicit activation.
|
||||
Always active split RAID LV exclusively locally.
|
||||
Do not use LV RAID status bit for segment status.
|
||||
Check segtype directly instead of checking RAID in segment status.
|
||||
Reusing exiting code for raid image removal.
|
||||
@@ -834,7 +968,7 @@ Version 2.02.166 - 26th September 2016
|
||||
Use --alloc normal for mirror logs even if the mimages were stricter.
|
||||
Use O_DIRECT to gather metadata in lvmdump.
|
||||
Ignore creation_time when checking for matching metadata for lvmetad.
|
||||
Fix possible NULL pointer derefence when checking for monitoring.
|
||||
Fix possible NULL pointer dereference when checking for monitoring.
|
||||
Add lvmreport(7) man page.
|
||||
Don't install lvmraid(7) man page when raid excluded. (2.02.165)
|
||||
Report 0% as dirty (copy%) for cache without any used block.
|
||||
@@ -874,7 +1008,7 @@ Version 2.02.164 - 15th August 2016
|
||||
Version 2.02.163 - 10th August 2016
|
||||
===================================
|
||||
Add profile for lvmdbusd which uses lvm shell json report output.
|
||||
Restrict in-command modification of some parms in lvm shell.
|
||||
Restrict in-command modification of some params in lvm shell.
|
||||
Apply LVM_COMMAND_PROFILE early for lvm shell.
|
||||
Refactor reporting so lvm shell log report collects whole of cmd execution.
|
||||
Support LVM_*_FD envvars to redirect output to file descriptors.
|
||||
@@ -1027,11 +1161,11 @@ Version 2.02.152 - 30th April 2016
|
||||
==================================
|
||||
Use any inherited tags when wiping metadata sub LVs to ensure activation.
|
||||
Add str_list_wipe.
|
||||
Improve support for interrupting procesing of volumes during lvchange.
|
||||
Improve support for interrupting processing of volumes during lvchange.
|
||||
Use failed command return code when lvchanging read-only volume.
|
||||
Show creation transaction_id and zeroing state of pool with thin volume.
|
||||
Stop checking for dm_cache_mq policy with cache target 1.9 (alias to smq).
|
||||
Check first /sys/module/dm_* dir existance before using modprobe.
|
||||
Check first /sys/module/dm_* dir existence before using modprobe.
|
||||
Remove mpath from 10-dm.rules, superseded by 11-dm-mpath.rules (mpath>=0.6.0).
|
||||
|
||||
Version 2.02.151 - 23rd April 2016
|
||||
@@ -1056,7 +1190,7 @@ Version 2.02.150 - 9th April 2016
|
||||
=================================
|
||||
Avoid using flushing dm status ioctl when checking for usable DM device.
|
||||
Check for devices without LVM- uuid prefix only with kernels < 3.X.
|
||||
Reuse %FREE size aproximation with lvcreate -l%PVS thin-pool.
|
||||
Reuse %FREE size approximation with lvcreate -l%PVS thin-pool.
|
||||
Allow the lvmdump directory to exist already provided it is empty.
|
||||
Show lvconverted percentage with 2 decimal digits.
|
||||
Fix regression in suspend when repairing --type mirror (2.02.133).
|
||||
@@ -1133,7 +1267,7 @@ Version 2.02.143 - 21st February 2016
|
||||
Fix error path when sending thin-pool message fails in update_pool_lv().
|
||||
Support reporting CheckNeeded and Fail state for thin-pool and thin LV.
|
||||
For failing thin-pool and thin volume correctly report percentage as INVALID.
|
||||
Report -1, not 'unkown' for lv_{snapshot_invalid,merge_failed} with --binary.
|
||||
Report -1, not 'unknown' for lv_{snapshot_invalid,merge_failed} with --binary.
|
||||
Add configure --enable-dbus-service for an LVM D-Bus service.
|
||||
Replace configure --enable-python_bindings with python2 and python3 versions.
|
||||
If PV belongs to some VG and metadata missing, skip it if system ID is used.
|
||||
@@ -1162,7 +1296,7 @@ Version 2.02.141 - 25th January 2016
|
||||
Restore support for command breaking in process_each_lv_in_vg() (2.02.118).
|
||||
Use correct mempool when process_each_lv_in_vg() (2.02.118).
|
||||
Fix lvm.8 man to show again prohibited suffixes.
|
||||
Fix configure to set proper use_blkid_wiping if autodetected as disabled.
|
||||
Fix configure to set proper use_blkid_wiping if autodetection as disabled.
|
||||
Initialise udev in clvmd for use in device scanning. (2.02.116)
|
||||
Add seg_le_ranges report field for common format when displaying seg devices.
|
||||
Honour report/list_item_separator for seg_metadata_le_ranges report field.
|
||||
@@ -1312,7 +1446,7 @@ Version 2.02.129 - 26th August 2015
|
||||
Fix shared library generation to stop exporting internal functions.(2.02.120)
|
||||
Accept --cachemode with lvconvert.
|
||||
Fix and improve reporting properties of cache-pool.
|
||||
Enable usage of --cachepolicy and --cachesetting with lvconvert.
|
||||
Enable usage of --cachepolicy and --cachesettings with lvconvert.
|
||||
Don't allow to reduce size of thin-pool metadata.
|
||||
Fix debug buffer overflows in cmirrord logging.
|
||||
Add --foreground and --help to cmirrord.
|
||||
@@ -1469,7 +1603,7 @@ Version 2.02.119 - 2nd May 2015
|
||||
Add --enable-halvm and --disable-halvm options to lvmconf script.
|
||||
Add --services, --mirrorservice and --startstopservices option to lvmconf.
|
||||
Use proper default value of global/use_lvmetad when processing lvmconf script.
|
||||
Respect allocation/cling_tag_list during intial contiguous allocation.
|
||||
Respect allocation/cling_tag_list during initial contiguous allocation.
|
||||
Add A_PARTITION_BY_TAGS set when allocated areas should not share tags.
|
||||
Make changes persist with python addTag/removeTag.
|
||||
Set correct vgid when updating cache when writing PV metadata.
|
||||
@@ -1547,7 +1681,7 @@ Version 2.02.116 - 30th January 2015
|
||||
Scan pools in for_each_sub_lv() and add for_each_sub_lv_except_pools().
|
||||
Fix lvm2app lvm_lv_get_property return value for fields with info/status ioctl.
|
||||
Fix lvm2app regression in lvm_lv_get_attr causing unknown values (2.02.115).
|
||||
Set default cache_mode to writehrough when missing in metadata.
|
||||
Set default cache_mode to writethrough when missing in metadata.
|
||||
Preserve chunk size with repair and metadata swap of a thin pool.
|
||||
Fix raid --splitmirror 1 functionality (2.02.112).
|
||||
Fix tree preload to handle splitting raid images.
|
||||
@@ -1613,13 +1747,13 @@ Version 2.02.112 - 11th November 2014
|
||||
Properly report error when taking snapshot of any cache type LV.
|
||||
Add basic thread debugging messages to dmeventd.
|
||||
Include threads being shutdown in dmeventd device registration responses.
|
||||
Inital support for external users of thin pools based on transaction_id.
|
||||
Initial support for external users of thin pools based on transaction_id.
|
||||
Report some basic percentage info for cache pools.
|
||||
Introduce size_mb_arg_with_percent() for advanced size arg reading.
|
||||
Add extra support for '.' as decimal point in size args.
|
||||
Add configure parameters for default segment type choices.
|
||||
Add global/sparse_segtype_default setting to use thin for --type sparse.
|
||||
Update and correct lvcreate and lvcovert man pages.
|
||||
Update and correct lvcreate and lvconvert man pages.
|
||||
Mark pools and snapshots as unzeroable volumes.
|
||||
Check for zeroing of volume after segment type is fully detected.
|
||||
Better support for persistent major and minor options with lvcreate.
|
||||
@@ -1672,7 +1806,7 @@ Version 2.02.112 - 11th November 2014
|
||||
Support DEBUG_MEMLOCK to trap unsupported mmap usage.
|
||||
Enable cache segment type by default.
|
||||
Ensure only supported volume types are used with cache segments.
|
||||
Fix inablility to specify cachemode when 'lvconvert'ing to cache-pool.
|
||||
Fix inability to specify cachemode when 'lvconvert'ing to cache-pool.
|
||||
Grab cluster lock for active LVs when setting clustered attribute.
|
||||
Use va_copy to properly pass va_list through functions.
|
||||
Add function to detect rotational devices.
|
||||
@@ -1740,7 +1874,7 @@ Version 2.02.108 - 23rd July 2014
|
||||
Enhance lvconvert thin, thinpool, cache and cachepool command line support.
|
||||
Display 'C' only for cache and cache-pool target types in lvs.
|
||||
Prompt for confirmation before change LV into a snapshot exception store.
|
||||
Return proper error codes for some failing lvconvert funtions.
|
||||
Return proper error codes for some failing lvconvert functions.
|
||||
Add initial code to use cache tools (cache_check|dump|repair|restore).
|
||||
Support lvdisplay --maps for raid.
|
||||
Add --activationmode degraded to activate degraded raid volumes by default.
|
||||
@@ -1759,7 +1893,7 @@ Version 2.02.108 - 23rd July 2014
|
||||
Support lvremove -ff to remove thin volumes from broken thin pools.
|
||||
Require --yes to skip raid repair prompt.
|
||||
Change makefile %.d generation to handle filename changes without make clean.
|
||||
Fix use of buildir in make pofile.
|
||||
Fix use of builddir in make pofile.
|
||||
Enhance private volumes UUIDs with suffixed for easier detection.
|
||||
Do not use reserved _[tc]meta volumes for temporary LVs.
|
||||
Leave backup pool metadata with _meta%d suffix instead of reserved _tmeta%d.
|
||||
@@ -1864,7 +1998,7 @@ Version 2.02.106 - 10th April 2014
|
||||
Include 'lvm dumpconfig --type missing' and '--type diff' output to lvmdump.
|
||||
Return failure when specifying negative size for pvresize.
|
||||
Fix memory corruption in cmd context refresh if clvmd leaks opened device.
|
||||
Reinitialise lvmcache properly on fork to fix premature polldaemon exit.
|
||||
Reinitialize lvmcache properly on fork to fix premature polldaemon exit.
|
||||
Add 'lvm dumpconfig --type diff' to show differences from defaults.
|
||||
Fix swap signature detection for devices smaller then 2MB.
|
||||
Use dm_malloc function in clvmd.c.
|
||||
@@ -1891,7 +2025,7 @@ Version 2.02.106 - 10th April 2014
|
||||
Don't print an error and accept empty value for global/thin_disabled_features.
|
||||
Update API for internal function build_dm_uuid().
|
||||
Do not try to check empty pool with scheduled messages.
|
||||
Fix return value in pool_has_message() when quering for any message.
|
||||
Fix return value in pool_has_message() when querying for any message.
|
||||
Cleanup all client resources on clvmd exit.
|
||||
Use dm_zalloc to clear members of clvmd client struct.
|
||||
Use BLKID_CFLAGS when compiling with blkid support.
|
||||
@@ -1933,7 +2067,7 @@ Version 2.02.106 - 10th April 2014
|
||||
Fix test when checking target version for available thin features.
|
||||
Detect thin feature external_origin_extend and limit extend when missing.
|
||||
Rename internal pool_can_resize_metadata() to thin_pool_feature_supported().
|
||||
Issue error if libbblkid detects signature and fails to return offset/length.
|
||||
Issue error if libblkid detects signature and fails to return offset/length.
|
||||
Update autoconf config.guess/sub to 2014-01-01.
|
||||
Online thin pool metadata resize requires 1.10 kernel thin pool target.
|
||||
|
||||
@@ -2006,7 +2140,7 @@ Version 2.02.104 - 13th November 2013
|
||||
=====================================
|
||||
Workaround VG refresh race during autoactivation by retrying the refresh.
|
||||
Handle failures in temporary mirror used when adding images to mirrors.
|
||||
Fix and improve logic for implicitely exclusive activations.
|
||||
Fix and improve logic for implicitly exclusive activations.
|
||||
Return success when LV cannot be activated because of volume_list filter.
|
||||
Return proper error state for remote exclusive activation.
|
||||
Fix missing lvmetad scan for PVs found on MD partitions.
|
||||
@@ -2169,11 +2303,11 @@ Version 2.02.99 - 24th July 2013
|
||||
Add support for persistent flagging of LVs to be skipped during activation.
|
||||
Add --type profilable to lvm dumpconfig to show profilable config settings.
|
||||
Add --mergedconfig to lvm dumpconfig for merged --config/--profile/lvm.conf.
|
||||
Relase memory and unblock signals in lock_vol error path.
|
||||
Release memory and unblock signals in lock_vol error path.
|
||||
Define LVM2_* command errors in lvm2cmd.h and use in dmeventd plugins.
|
||||
Move errors.h to tools dir.
|
||||
Add man page entries for profile configuration and related options.
|
||||
Improve error loging when user tries to interrupt commands.
|
||||
Improve error logging when user tries to interrupt commands.
|
||||
Rename _swap_lv to _swap_lv_identifiers and move to allow an additional user.
|
||||
Rename snapshot segment returning methods from find_*_cow to find_*_snapshot.
|
||||
liblvm/python API: Additions: PV create/removal/resize/listing
|
||||
@@ -2374,7 +2508,7 @@ Version 2.02.98 - 15th October 2012
|
||||
Do not start dmeventd for lvchange --resync when monitoring is off.
|
||||
Remove pvscan --cache from lvm2-lvmetad init script.
|
||||
Remove ExecStartPost with pvscan --cache from lvm2-lvmetad.service.
|
||||
Report invalid percentage for property snap_percent of non-snaphot LVs.
|
||||
Report invalid percentage for property snap_percent of non-snapshot LVs.
|
||||
Disallow conversion of thin LVs to mirrors.
|
||||
Fix lvm2api data_percent reporting for thin volumes.
|
||||
Do not allow RAID LVs in a clustered volume group.
|
||||
@@ -2424,7 +2558,7 @@ Version 2.02.98 - 15th October 2012
|
||||
|
||||
Version 2.02.97 - 7th August 2012
|
||||
=================================
|
||||
Improve documention of allocation policies in lvm.8.
|
||||
Improve documentation of allocation policies in lvm.8.
|
||||
Increase limit for major:minor to 4095:1048575 when using -My option.
|
||||
Add make install_systemd_generators.
|
||||
Add generator for lvm2 activation systemd units.
|
||||
@@ -2508,7 +2642,7 @@ Version 2.02.96 - 8th June 2012
|
||||
Check for buffer overwrite in get_cluster_type() in clvmd.
|
||||
Fix global/detect_internal_vg_cache_corruption config check.
|
||||
Update lcov Makefile target to support all dmeventd plugins.
|
||||
Fix initializiation of thin monitoring. (2.02.92)
|
||||
Fix initialization of thin monitoring. (2.02.92)
|
||||
Cope with improperly formatted device numbers in /proc/devices. (2.02.91)
|
||||
Exit if LISTEN_PID environment variable incorrect in lvmetad systemd handover.
|
||||
Use pvscan --cache instead of vgscan in lvmetad scripts.
|
||||
@@ -2521,7 +2655,7 @@ Version 2.02.96 - 8th June 2012
|
||||
Add --with-thin-check configure option for path to thin_check.
|
||||
Fix error message when pvmove LV activation fails with name already in use.
|
||||
Better structure layout for device_info in dev_subsystem_name().
|
||||
Change message severity for creation of VG over uninitialised devices.
|
||||
Change message severity for creation of VG over uninitialized devices.
|
||||
Fix error path for failed toolcontext creation.
|
||||
Detect lvm binary path in lvmetad udev rules.
|
||||
Don't unlink socket on lvmetad shutdown if instantiated from systemd.
|
||||
@@ -2556,7 +2690,7 @@ Version 2.02.94 - 3rd March 2012
|
||||
Add some close() and dev_close() error path backtraces.
|
||||
Set stdin/stdout/stderr to /dev/null for polldaemon.
|
||||
Limit the max size of processed clvmd message to ~8KB.
|
||||
Do not send uninitialised bytes in cluster error reply messages.
|
||||
Do not send uninitialized bytes in cluster error reply messages.
|
||||
Use unsigned type for bitmask instead of enum type for lvm properties.
|
||||
Add missing cleanup of excl_uuid hash on some exit paths of clvmd.
|
||||
Check for existence of vg_name in _format1/_pool_vg_read().
|
||||
@@ -2629,7 +2763,7 @@ Version 2.02.91 - 12th February 2012
|
||||
|
||||
Version 2.02.90 - 1st February 2012
|
||||
===================================
|
||||
sync_local_dev_names before (re)activating mirror log for initialisation.
|
||||
sync_local_dev_names before (re)activating mirror log for initialization.
|
||||
Disable partial activation for thin LVs and LVs with all missing segments.
|
||||
Do not print warning for pv_min_size between 512KB and 2MB.
|
||||
Clean up systemd unit ordering and requirements.
|
||||
@@ -2648,7 +2782,7 @@ Version 2.02.89 - 26th January 2012
|
||||
Add data_percent and metadata_percent for thin pools to lvs -v.
|
||||
Add data_lv & metadata_lv fields to lvs for thin pools.
|
||||
Add data_percent & pool_lv fields to lvs for thin volumes.
|
||||
Rename origin_only parm to use_layer for lv_info and use with thin LVs.
|
||||
Rename origin_only param to use_layer for lv_info and use with thin LVs.
|
||||
Add lv_thin_pool_transaction_id to read the transaction_id value.
|
||||
Use {suspend,resume}_origin_only when up-converting RAID, as mirrors do.
|
||||
Always add RAID metadata LVs to deptree (even when origin_only is set).
|
||||
@@ -2678,7 +2812,7 @@ Version 2.02.89 - 26th January 2012
|
||||
Add _dev_init to initialize common struct device members.
|
||||
Always zalloc struct device during initialization.
|
||||
Fix missing thread list manipulation protection in dmeventd.
|
||||
Do not derefence lv pointer in _percent_run() function before NULL check.
|
||||
Do not dereference lv pointer in _percent_run() function before NULL check.
|
||||
Allow empty strings for description and creation_host config fields.
|
||||
Issue deprecation warning when removing last lvm1-format snapshot.
|
||||
Reinstate support for snapshot removal with lvm1 format. (2.02.86)
|
||||
@@ -2749,11 +2883,11 @@ Version 2.02.89 - 26th January 2012
|
||||
Change vg_revert to void and remove superfluous calls after failed vg_commit.
|
||||
Use execvp for CLVMD restart to preserve environment settings.
|
||||
Restart CLVMD with same cluster manager.
|
||||
Fix log_error() usage in raid and unknown segtype initialisation.
|
||||
Fix log_error() usage in raid and unknown segtype initialization.
|
||||
Improve testing Makefile.
|
||||
Fix install_ocf make target when srcdir != builddir. (2.02.80)
|
||||
Support env vars LVM_CLVMD_BINARY and LVM_BINARY in clvmd.
|
||||
Fix restart of clvmd (preserve exlusive locks). (2.02.64)
|
||||
Fix restart of clvmd (preserve exclusive locks). (2.02.64)
|
||||
Add 'Volume Type' lv_attr characters for RAID and RAID_IMAGE.
|
||||
Add activation/retry_deactivation to lvm.conf to retry deactivation of an LV.
|
||||
Replace open_count check with holders/mounted_fs check on lvremove path.
|
||||
@@ -2819,13 +2953,13 @@ Version 2.02.87 - 12th August 2011
|
||||
Cache and share generated VG structs.
|
||||
Fix possible format instance memory leaks and premature releases in _vg_read.
|
||||
Suppress locking error messages in monitoring init scripts.
|
||||
If pipe in clvmd fails return busy instead of using uninitialised descriptors.
|
||||
If pipe in clvmd fails return busy instead of using uninitialized descriptors.
|
||||
Add ability to reduce the number of mirrors in raid1 arrays to lvconvert.
|
||||
Add dmeventd plugin for raid.
|
||||
Replace free_vg with release_vg and move it to vg.c.
|
||||
Remove INCONSISTENT_VG flag from the code.
|
||||
Remove lock from cache in _lock_vol even if unlock fails.
|
||||
Initialise clvmd locks before lvm context to avoid open descriptor leaks.
|
||||
Initialize clvmd locks before lvm context to avoid open descriptor leaks.
|
||||
Remove obsolete gulm clvmd cluster locking support.
|
||||
Suppress low-level locking errors and warnings while using --sysinit.
|
||||
Remove unused inconsistent_seqno variable in _vg_read().
|
||||
@@ -2898,7 +3032,7 @@ Version 2.02.85 - 29th April 2011
|
||||
Issue discards on lvremove and lvreduce etc. if enabled and supported.
|
||||
Add seg_pe_ranges and devices fields to liblvm.
|
||||
Fix incorrect tests for dm_snprintf() failure.
|
||||
Fix some unmatching sign comparation gcc warnings in the code.
|
||||
Fix some unmatching sign comparison gcc warnings in the code.
|
||||
Support lv_extend() on empty LVs.
|
||||
Avoid regenerating cache content when exported VG buffer is unchanged.
|
||||
Extend the set of memory regions that are not locked to memory.
|
||||
@@ -2924,7 +3058,7 @@ Version 2.02.85 - 29th April 2011
|
||||
Use only vg_set_fid and new pv_set_fid fn to assign the format instance.
|
||||
Make create_text_context fn static and move it inside create_instance fn.
|
||||
Add mem and ref_count fields to struct format_instance for own mempool use.
|
||||
Use new alloc_fid fn for common format instance initialisation.
|
||||
Use new alloc_fid fn for common format instance initialization.
|
||||
Optimise _get_token() and _eat_space().
|
||||
Add _lv_postorder_vg() to improve efficiency for all LVs in VG.
|
||||
Add gdbinit script for debugging.
|
||||
@@ -2933,10 +3067,10 @@ Version 2.02.85 - 29th April 2011
|
||||
Avoid possible endless loop in _free_vginfo when 4 or more VGs have same name.
|
||||
Use empty string instead of /dev// for LV path when there's no VG.
|
||||
Don't allocate unused VG mempool in _pvsegs_sub_single.
|
||||
Do not send uninitialised bytes in local clvmd messages.
|
||||
Do not send uninitialized bytes in local clvmd messages.
|
||||
Support --help option for clvmd and return error for unknown option.
|
||||
Avoid reading freed memory when printing LV segment type.
|
||||
Fix syslog initialisation in clvmd to respect lvm.conf setting.
|
||||
Fix syslog initialization in clvmd to respect lvm.conf setting.
|
||||
Fix possible overflow in maximum stripe size and physical extent size.
|
||||
Improve pvremove error message when PV belongs to a VG.
|
||||
Extend normal policy to allow mirror logs on same PVs as images if necessary.
|
||||
@@ -2950,7 +3084,7 @@ Version 2.02.85 - 29th April 2011
|
||||
Restructure existing pv_setup and pv_write and add pv_initialise.
|
||||
Add internal interface to support adding and removing metadata areas.
|
||||
Allow internal indexing of metadata areas (PV id + mda order).
|
||||
Generalise internal format_instance infrastrusture for PV and VG use.
|
||||
Generalise internal format_instance infrastructure for PV and VG use.
|
||||
Handle decimal digits with --units instead of ignoring them silently.
|
||||
Fix remaining warnings and compile with -Wpointer-arith.
|
||||
Fix gcc warnings for unused variables and const casts.
|
||||
@@ -2964,7 +3098,7 @@ Version 2.02.85 - 29th April 2011
|
||||
Make pv_min_size configurable and increase to 2048KB to exclude floppy drives.
|
||||
Add find_config_tree_int64 to read 64-bit ints from config.
|
||||
Ensure resuming exclusive cluster mirror continues to use local mirror target.
|
||||
Clear temporary postorder LV status flags to allow re-use with same LV struct.
|
||||
Clear temporary postorder LV status flags to allow reuse with same LV struct.
|
||||
Remove invalid snapshot umount mesg which floods syslog from dmeventd plugin.
|
||||
Add extended examples to pvmove man page.
|
||||
Support LVM_TEST_DEVDIR env var for private /dev during testing.
|
||||
@@ -3019,7 +3153,7 @@ Version 2.02.80 - 10th January 2011
|
||||
Speed up command processing by caching resolved config tree.
|
||||
Pass config_tree to renamed function import_vg_from_config_tree().
|
||||
Detect NULL handle in get_property().
|
||||
Fix superfluous /usr in ocf_scriptdir instalation path.
|
||||
Fix superfluous /usr in ocf_scriptdir installation path.
|
||||
Add --with-ocfdir configurable option.
|
||||
Add aclocal.m4 (for pkgconfig).
|
||||
Fix memory leak in persistent filter creation error path.
|
||||
@@ -3051,7 +3185,7 @@ Version 2.02.79 - 20th December 2010
|
||||
Add copy_percent and snap_percent to liblvm.
|
||||
Enhance vg_validate to ensure integrity of LV and PV structs referenced.
|
||||
Enhance vg_validate to check composition of pvmove LVs.
|
||||
Create /var/run/lvm directory during clvmd initialisation if missing.
|
||||
Create /var/run/lvm directory during clvmd initialization if missing.
|
||||
Use new dm_prepare_selinux_context instead of dm_set_selinux_context.
|
||||
Avoid revalidating the label cache immediately after scanning.
|
||||
Support scanning for a single VG in independent mdas.
|
||||
@@ -3348,7 +3482,7 @@ Version 2.02.67 - 4th June 2010
|
||||
Avoid selecting names under /dev/block if there is an alternative.
|
||||
Update clustered log kernel module name to log-userspace for 2.6.31 onwards.
|
||||
Add replicators' LVs to dtree for activation.
|
||||
Supress activation message if there is a missing replicator VG.
|
||||
Suppress activation message if there is a missing replicator VG.
|
||||
Fix scripts/relpath.awk to work in mawk
|
||||
Extend lock_vol to check for missing replicator VGs first.
|
||||
Update _process_one_vg and process_each_lv_in_vg to populate cmd_vg.
|
||||
@@ -3399,7 +3533,7 @@ Version 2.02.65 - 17th May 2010
|
||||
|
||||
Version 2.02.64 - 30th April 2010
|
||||
=================================
|
||||
Avoid pointless initialisation when the 'version' command is run directly.
|
||||
Avoid pointless initialization when the 'version' command is run directly.
|
||||
Fix memory leak for invalid regex pattern input.
|
||||
Display invalid regex pattern for filter configuration in case of error.
|
||||
Remove no-longer-used arg_ptr_value.
|
||||
@@ -3558,7 +3692,7 @@ Version 2.02.60 - 23rd January 2010
|
||||
Disable memory debugging if dmeventd is configured. (Not thread-safe.)
|
||||
Fix first log message prefix in syslog for dmeventd plugins.
|
||||
Fix exported symbols names for dmeventd lvm2 wrapper plugin.
|
||||
Make failed locking initialisation messages more descriptive.
|
||||
Make failed locking initialization messages more descriptive.
|
||||
|
||||
Version 2.02.59 - 21st January 2010
|
||||
===================================
|
||||
@@ -3574,7 +3708,7 @@ Version 2.02.59 - 21st January 2010
|
||||
Fix detection of completed snapshot merge.
|
||||
Add Red Hat cmirror initscript (unfinished).
|
||||
Add cmirrord man page (incomplete).
|
||||
Make cluster log communication structures architecture independant.
|
||||
Make cluster log communication structures architecture independent.
|
||||
Fix cluster log in-memory bitmap handling.
|
||||
Improve snapshot merge metadata import validation.
|
||||
Improve target type compatibility checking in _percent_run().
|
||||
@@ -3650,7 +3784,7 @@ Version 2.02.57 - 12th January 2010
|
||||
Impose limit of 8 mirror images to match the in-kernel kcopyd restriction.
|
||||
Use locking_type 3 (compiled in) for lvmconf --enable-cluster.
|
||||
Remove list.c and list.h with no-longer-used dm_list macros and functions.
|
||||
Log failure type and recognise type 'F' (flush) in dmeventd mirror plugin.
|
||||
Log failure type and recognize type 'F' (flush) in dmeventd mirror plugin.
|
||||
Extend internal PV/VG/LV/segment status variables from 32-bit to 64-bit.
|
||||
|
||||
Version 2.02.56 - 24th November 2009
|
||||
@@ -3688,14 +3822,14 @@ Version 2.02.54 - 26th October 2009
|
||||
Fix clvmd segfault when refresh_toolcontext fails.
|
||||
Remember to clear 'global lock held during cache refresh' state after use.
|
||||
Use udev flags support in LVM and apply various fixes to udev rules.
|
||||
Delay announcing mirror monitoring to syslog until initialisation succeeded.
|
||||
Delay announcing mirror monitoring to syslog until initialization succeeded.
|
||||
Handle metadata with unknown segment types more gracefully.
|
||||
Set default owner and group to null.
|
||||
Add dmeventd.static to the build.
|
||||
Disable realtime support code by default.
|
||||
Make clvmd return 0 on success rather than 1.
|
||||
Add --pvmetadatacopies for pvcreate, vgcreate, vgextend, vgconvert.
|
||||
Add implict pvcreate support to vgcreate and vgextend.
|
||||
Add implicit pvcreate support to vgcreate and vgextend.
|
||||
Correct example.conf to indicate that lvm2 not lvm1 is the default format.
|
||||
Remove an unused stray LVM1_SUPPORT ifdef.
|
||||
Only include selinux libs in libdevmapper.pc when selinux build enabled.
|
||||
@@ -3875,7 +4009,7 @@ Version 2.02.48 - 30th June 2009
|
||||
Reinstate partial activation support in clustered mode. (2.02.40)
|
||||
Allow metadata correction even when PVs are missing.
|
||||
Use 'lvm lvresize' instead of 'lvresize' in fsadm.
|
||||
Do not use '-n' realine option in fsadm for busybox compatiblity.
|
||||
Do not use '-n' realine option in fsadm for busybox compatibility.
|
||||
Add vg_lock_newname() library function for vgrename, vgsplit and vgcreate.
|
||||
Round up requested readahead to at least one page and print warning.
|
||||
Try to repair vg before actual vgremove when force flag provided.
|
||||
@@ -3936,7 +4070,7 @@ Version 2.02.46 - 21st May 2009
|
||||
Fix first_seg() call for empty segment list.
|
||||
Add install_lvm2 makefile target to install only the LVM2 components.
|
||||
Reject missing PVs from allocation in toollib.
|
||||
Fix PV datalignment for values starting prior to MDA area. (2.02.45)
|
||||
Fix PV dataalignment for values starting prior to MDA area. (2.02.45)
|
||||
Add sparse devices: lvcreate -s --virtualoriginsize (hidden zero origin).
|
||||
Fix minimum width of devices column in reports.
|
||||
Add lvs origin_size field.
|
||||
@@ -4009,7 +4143,7 @@ Version 2.02.45 - 3rd March 2009
|
||||
Separate PV label attributes which do not need parse metadata when reporting.
|
||||
Remove external dependency on the 'cut' command from fsadm.
|
||||
Fix pvs segfault when pv mda attributes requested for not available PV.
|
||||
Add fsadm support for reszing ext4 filesysystems.
|
||||
Add fsadm support for resizing ext4 filesystems.
|
||||
Move locking_type reading inside init_locking().
|
||||
Rename get_vgs() to get_vgnames() and clarify related error messages.
|
||||
Allow clvmd to be built with all cluster managers & select one on cmdline.
|
||||
@@ -4186,7 +4320,7 @@ Version 2.02.37 - 6th June 2008
|
||||
Refactor some vginfo manipulation code.
|
||||
Add assertions to trap deprecated P_ and V_ lock usage.
|
||||
Add missing mutex around clvmd lvmcache_drop_metadata library call.
|
||||
Fix uninitialised mutex in clvmd if all daemons are not running at startup.
|
||||
Fix uninitialized mutex in clvmd if all daemons are not running at startup.
|
||||
Avoid using DLM locks with LCK_CACHE type P_ lock requests.
|
||||
When asked to drop cached committed VG metadata, invalidate cached PV labels.
|
||||
Drop metadata cache before writing precommitted metadata instead of after.
|
||||
@@ -4233,7 +4367,7 @@ Version 2.02.34 - 10th April 2008
|
||||
Mention default --clustered setting in vgcreate man page.
|
||||
Add config file overrides to clvmd when it reads the active LVs list.
|
||||
Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
|
||||
Add (empty) orphan VGs to lvmcache during initialisation.
|
||||
Add (empty) orphan VGs to lvmcache during initialization.
|
||||
Fix orphan VG name used for format_pool.
|
||||
Create a fid for internal orphan VGs.
|
||||
Update lvmcache VG lock state for all locking types now.
|
||||
@@ -4251,7 +4385,7 @@ Version 2.02.34 - 10th April 2008
|
||||
Fix redundant lvresize message if vg doesn't exist.
|
||||
Fix another allocation bug with clvmd and large node IDs.
|
||||
Add find_lv_in_lv_list() and find_pv_in_pv_list().
|
||||
Fix uninitialised variable in clvmd that could cause odd hangs.
|
||||
Fix uninitialized variable in clvmd that could cause odd hangs.
|
||||
Add vgmerge tests.
|
||||
Add pvseg_is_allocated() for identifying a PV segment allocated to a LV.
|
||||
Add list_move() for moving elements from one list to another.
|
||||
@@ -4259,7 +4393,7 @@ Version 2.02.34 - 10th April 2008
|
||||
Correct command name in lvmdiskscan man page.
|
||||
clvmd no longer crashes if it sees nodeids over 50.
|
||||
Fix potential deadlock in clvmd thread handling.
|
||||
Refactor text format initialisation into _init_text_import.
|
||||
Refactor text format initialization into _init_text_import.
|
||||
Escape double quotes and backslashes in external metadata and config data.
|
||||
Add functions for escaping double quotes in strings.
|
||||
Rename count_chars_len to count_chars.
|
||||
@@ -4309,7 +4443,7 @@ Version 2.02.31 - 19th January 2008
|
||||
|
||||
Version 2.02.30 - 17th January 2008
|
||||
===================================
|
||||
Set default readahead to twice maximium stripe size.
|
||||
Set default readahead to twice maximum stripe size.
|
||||
Reinstate VG extent size and stripe size defaults (halved). (2.02.29)
|
||||
Add lists of stacked LV segments using each LV to the internal metadata.
|
||||
Change vgsplit -l (for unimplemented --list) into --maxlogicalvolumes.
|
||||
@@ -4681,7 +4815,7 @@ Version 2.02.11 - 12th October 2006
|
||||
Capture error messages in clvmd and pass them back to the user.
|
||||
Remove unused #defines from filter-md.c.
|
||||
Make clvmd restart init script wait until clvmd has died before starting it.
|
||||
Add -R to clvmd which tells running clvmds to reload their device cache.
|
||||
Add -R to clvmd which tells running clvmd to reload their device cache.
|
||||
Add LV column to reports listing kernel modules needed for activation.
|
||||
Show available fields if report given invalid field. (e.g. lvs -o list)
|
||||
Add timestamp functions with --disable-realtime configure option.
|
||||
@@ -5008,7 +5142,7 @@ Version 2.01.08 - 22nd March 2005
|
||||
Improve detection of external changes affecting internal cache.
|
||||
Add 'already in device cache' debug message.
|
||||
Add -a to pvdisplay -C.
|
||||
Avoid rmdir opendir error messsages when dir was already removed.
|
||||
Avoid rmdir opendir error messages when dir was already removed.
|
||||
Tighten signal handlers.
|
||||
Avoid some compiler warnings.
|
||||
Additional rename failure error message.
|
||||
@@ -5239,7 +5373,7 @@ Version 2.00.17 - 20 June 2004
|
||||
fsadm support for fsck and resizing - needs testing.
|
||||
Add read-only GFS pool support.
|
||||
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
|
||||
Fix rounding of large diplayed sizes.
|
||||
Fix rounding of large displayed sizes.
|
||||
Suppress decimal point when using units of sectors/bytes.
|
||||
Additional kernel target checks before pvmove & snapshot creation.
|
||||
Add i2o_block.
|
||||
|
85
WHATS_NEW_DM
85
WHATS_NEW_DM
@@ -1,6 +1,51 @@
|
||||
Version 1.02.199 -
|
||||
Version 1.02.210 -
|
||||
===================
|
||||
|
||||
Version 1.02.209 - 09th September 2025
|
||||
======================================
|
||||
|
||||
Version 1.02.208 - 30th July 2025
|
||||
=================================
|
||||
|
||||
Version 1.02.207 - 27th June 2025
|
||||
=================================
|
||||
Escape the escape character itself on JSON report format output.
|
||||
Fail dm_report_group_create if radix char from locale unsuitable for JSON_STD.
|
||||
|
||||
Version 1.02.206 - 05th May 2025
|
||||
================================
|
||||
Add support for using regex in selection criteria for string lists.
|
||||
Fix string list selection when using [<item> || <item> ...].
|
||||
|
||||
Version 1.02.205 - 27th February 2025
|
||||
=====================================
|
||||
Restore missing symbol dm_tree_node_size_changed@Base (1.02.175).
|
||||
Restore missing symbol dm_bitset_parse_list@@DM_1_02_138 (1.02.175).
|
||||
|
||||
Version 1.02.204 - 14th January 2025
|
||||
====================================
|
||||
Create /dev/disk/by-diskseq/<DISKSEQ> symlink for public DM devices.
|
||||
|
||||
Version 1.02.203 - 09th December 2024
|
||||
=====================================
|
||||
|
||||
Version 1.02.202 - 04th November 2024
|
||||
=====================================
|
||||
Introduce dm_config_parse_only_section to stop parsing after section.
|
||||
For shorter string use on stack buffers when generating sections.
|
||||
Enhance dm_config tokenizer.
|
||||
|
||||
Version 1.02.201 - 02nd October 2024
|
||||
====================================
|
||||
Cleanup udev sync semaphore if dm_{udev_create,task_set}_cookie fails.
|
||||
Improve error messages on failed udev cookie create/inc/dec operation.
|
||||
|
||||
Version 1.02.200 - 23rd August 2024
|
||||
===================================
|
||||
|
||||
Version 1.02.199 - 12nd July 2024
|
||||
=================================
|
||||
|
||||
Version 1.02.198 - 16th May 2024
|
||||
================================
|
||||
Fix static only compilation of libdevmapper.a and dmsetup tool.
|
||||
@@ -85,7 +130,7 @@ Version 1.02.173 - 09th August 2020
|
||||
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).
|
||||
Fix dm_list iterators with gcc 10 optimization (-ftree-pta).
|
||||
Dmeventd handles timer without looping on short intervals.
|
||||
|
||||
Version 1.02.169 - 11th February 2020
|
||||
@@ -116,7 +161,7 @@ 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.
|
||||
Add DM_DEVICE_ARM_POLL for API completeness matching kernel.
|
||||
Do not add parameters for RESUME with DM_DEVICE_CREATE dm task.
|
||||
Fix dmstats report printing no output.
|
||||
|
||||
@@ -145,7 +190,7 @@ Version 1.02.147-rc1 - 24th May 2018
|
||||
Reuse uname() result for mirror target.
|
||||
Recognize also mounted btrfs through dm_device_has_mounted_fs().
|
||||
Add missing log_error() into dm_stats_populate() returning 0.
|
||||
Avoid calling dm_stats_populat() for DM devices without any stats regions.
|
||||
Avoid calling dm_stats_populate() for DM devices without any stats regions.
|
||||
Support DM_DEBUG_WITH_LINE_NUMBERS envvar for debug msg with source:line.
|
||||
Configured command for thin pool threshold handling gets whole environment.
|
||||
Fix tests for failing dm_snprintf() in stats code.
|
||||
@@ -194,7 +239,7 @@ Version 1.02.141 - 28th June 2017
|
||||
Add dm_percent_to_round_float for adjusted percentage rounding.
|
||||
Reset array with dead rimage devices once raid gets in sync.
|
||||
Drop unneeded --config option from raid dmeventd plugin.
|
||||
dm_get_status_raid() handle better some incosistent md statuses.
|
||||
dm_get_status_raid() handle better some inconsistent md statuses.
|
||||
Accept truncated files in calls to dm_stats_update_regions_from_fd().
|
||||
Restore Warning by 5% increment when thin-pool is over 80% (1.02.138).
|
||||
|
||||
@@ -249,7 +294,7 @@ Version 1.02.136 - 5th November 2016
|
||||
Still produce output when dmsetup dependency tree building finds dev missing.
|
||||
Check and report pthread_sigmask() failure in dmeventd.
|
||||
Check mem alloc fail in _canonicalize_field_ids().
|
||||
Use unsigned math when checking more then 31 legs of raid.
|
||||
Use unsigned math when checking more than 31 legs of raid.
|
||||
Fix 'dmstats delete' with dmsetup older than v1.02.129
|
||||
Fix stats walk segfault with dmsetup older than v1.02.129
|
||||
|
||||
@@ -389,7 +434,7 @@ Version 1.02.112 - 28th November 2015
|
||||
=====================================
|
||||
Show error message when trying to create unsupported raid type.
|
||||
Improve preloading sequence of an active thin-pool target.
|
||||
Drop extra space from cache target line to fix unneded table reloads.
|
||||
Drop extra space from cache target line to fix unneeded table reloads.
|
||||
|
||||
Version 1.02.111 - 23rd November 2015
|
||||
=====================================
|
||||
@@ -404,7 +449,7 @@ Version 1.02.110 - 30th October 2015
|
||||
Disable thin monitoring plugin when it fails too often (>10 times).
|
||||
Fix/restore parsing of empty field '-' when processing dmeventd event.
|
||||
Enhance dm_tree_node_size_changed() to recognize size reduction.
|
||||
Support exit on idle for dmenventd (1 hour).
|
||||
Support exit on idle for dmeventd (1 hour).
|
||||
Add support to allow unmonitor device from plugin itself.
|
||||
New design for thread co-operation in dmeventd.
|
||||
Dmeventd read device status with 'noflush'.
|
||||
@@ -577,7 +622,7 @@ Version 1.02.93 - 21st January 2015
|
||||
Version 1.02.92 - 24th November 2014
|
||||
====================================
|
||||
Fix memory corruption with sorting empty string lists (1.02.86).
|
||||
Fix man dmsetup.8 syntax warning of Groff
|
||||
Fix man dmsetup.8 syntax warning of Groff.
|
||||
Accept unquoted strings and / in place of {} when parsing configs.
|
||||
|
||||
Version 1.02.91 - 11th November 2014
|
||||
@@ -596,7 +641,7 @@ Version 1.02.90 - 1st September 2014
|
||||
Version 1.02.89 - 26th August 2014
|
||||
==================================
|
||||
Improve libdevmapper-event select() error handling.
|
||||
Add extra check for matching transation_id after message submitting.
|
||||
Add extra check for matching transaction_id after message submitting.
|
||||
Add dm_report_field_string_list_unsorted for str. list report without sorting.
|
||||
Support --deferred with dmsetup remove to defer removal of open devices.
|
||||
Update dm-ioctl.h to include DM_DEFERRED_REMOVE flag.
|
||||
@@ -683,7 +728,7 @@ Version 1.02.82 - 4th October 2013
|
||||
|
||||
Version 1.02.81 - 23rd September 2013
|
||||
=====================================
|
||||
Tidy dmeventd fifo initialisation.
|
||||
Tidy dmeventd fifo initialization.
|
||||
|
||||
Version 1.02.80 - 20th September 2013
|
||||
=====================================
|
||||
@@ -708,7 +753,7 @@ Version 1.02.78 - 24th July 2013
|
||||
Always return success on dmeventd -V command call.
|
||||
Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
|
||||
Add dm_get_status_snapshot() for parsing snapshot status.
|
||||
Detecte mounted fs also via reading /proc/self/mountinfo.
|
||||
Detect mounted fs also via reading /proc/self/mountinfo.
|
||||
Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
|
||||
Report error for nonexisting devices in dmeventd communication.
|
||||
Prevent double free error after dmeventd call of _fill_device_data().
|
||||
@@ -805,7 +850,7 @@ Version 1.02.71 - 20th February 2012
|
||||
Add "watch" rule to 13-dm-disk.rules.
|
||||
Detect failing fifo and skip 20s retry communication period.
|
||||
Add DM_DEFAULT_NAME_MANGLING_MODE environment variable as an override.
|
||||
Add dm_lib_init to automatically initialise device-mapper library on load.
|
||||
Add dm_lib_init to automatically initialize device-mapper library on load.
|
||||
Replace any '\' char with '\\' in dm table specification on input.
|
||||
Add mangle command to dmsetup to provide renaming to correct mangled form.
|
||||
Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o.
|
||||
@@ -899,7 +944,7 @@ Version 1.02.66 - 12th August 2011
|
||||
Fix memory leak in dmsetup _message() memory allocation error path.
|
||||
Use new oom killer adjustment interface (oom_score_adj) when available.
|
||||
Add systemd unit files for dmeventd.
|
||||
Fix read-only identical table reload supression.
|
||||
Fix read-only identical table reload suppression.
|
||||
|
||||
Version 1.02.65 - 8th July 2011
|
||||
===============================
|
||||
@@ -914,7 +959,7 @@ Version 1.02.65 - 8th July 2011
|
||||
Add dm_get_suspended_counter() for number of devs in suspended state by lib.
|
||||
Fix "all" report field prefix matching to include label fields with pv_all.
|
||||
Delay resuming new preloaded mirror devices with core logs in deptree code.
|
||||
Accept new kernel version 3 uname formats in initialisation.
|
||||
Accept new kernel version 3 uname formats in initialization.
|
||||
|
||||
Version 1.02.64 - 29th April 2011
|
||||
==================================
|
||||
@@ -928,7 +973,7 @@ Version 1.02.64 - 29th April 2011
|
||||
Improve stack debug reporting in dm_task_create().
|
||||
Fallback to control node creation only if node doesn't exist yet.
|
||||
Change dm_hash binary functions to take void *key instead of char *.
|
||||
Fix uninitialised memory use with empty params in _reload_with_suppression_v4.
|
||||
Fix uninitialized memory use with empty params in _reload_with_suppression_v4.
|
||||
Lower severity of selabel_lookup and matchpathcon failure to log_debug.
|
||||
Add test for failed allocation from dm_task_set_uuid() in dmeventd.
|
||||
Add dm_event_get_version to dmeventd for use with -R.
|
||||
@@ -1097,7 +1142,7 @@ Version 1.02.44 - 15th February 2010
|
||||
|
||||
Version 1.02.43 - 21st January 2010
|
||||
===================================
|
||||
Remove bitset, hash and pool headers superceded by libdevmapper.h.
|
||||
Remove bitset, hash and pool headers superseded by libdevmapper.h.
|
||||
Fix off-by-one error causing bad cluster mirror table construction.
|
||||
|
||||
Version 1.02.42 - 14th January 2010
|
||||
@@ -1221,7 +1266,7 @@ Version 1.02.27 - 25th June 2008
|
||||
|
||||
Version 1.02.26 - 6th June 2008
|
||||
===============================
|
||||
Initialise params buffer to empty string in _emit_segment.
|
||||
Initialize params buffer to empty string in _emit_segment.
|
||||
Skip add_dev_node when ioctls disabled.
|
||||
Make dm_hash_iter safe against deletion.
|
||||
Accept a NULL pointer to dm_free silently.
|
||||
@@ -1277,7 +1322,7 @@ Version 1.02.20 - 15th June 2007
|
||||
|
||||
Version 1.02.19 - 27th April 2007
|
||||
=================================
|
||||
Standardise protective include file #defines.
|
||||
Standardize protective include file #defines.
|
||||
Add regex functions to library.
|
||||
Avoid trailing separator in reports when there are hidden sort fields.
|
||||
Fix segfault in 'dmsetup status' without --showkeys against crypt target.
|
||||
@@ -1308,7 +1353,7 @@ Version 1.02.16 - 25th January 2007
|
||||
Streamline dm_report_field_* interface.
|
||||
Add cmdline debug & version options to dmeventd.
|
||||
Add DM_LIB_VERSION definition to configure.h.
|
||||
Suppress 'Unrecognised field' error if report field is 'help'.
|
||||
Suppress 'Unrecognized field' error if report field is 'help'.
|
||||
Add --separator and --sort to dmsetup (unused).
|
||||
Make alignment flag optional when specifying report fields.
|
||||
|
||||
|
61
aclocal.m4
vendored
61
aclocal.m4
vendored
@@ -1,6 +1,6 @@
|
||||
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.18.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2025 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -117,8 +117,8 @@ 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])])
|
||||
])dnl PKG_PREREQ
|
||||
|
||||
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
dnl ----------------------------------
|
||||
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION], [ACTION-IF-NOT-FOUND])
|
||||
dnl ---------------------------------------------------------
|
||||
dnl Since: 0.16
|
||||
dnl
|
||||
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
|
||||
@@ -126,6 +126,12 @@ dnl first found in the path. Checks that the version of pkg-config found
|
||||
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
|
||||
dnl used since that's the first version where most current features of
|
||||
dnl pkg-config existed.
|
||||
dnl
|
||||
dnl If pkg-config is not found or older than specified, it will result
|
||||
dnl in an empty PKG_CONFIG variable. To avoid widespread issues with
|
||||
dnl scripts not checking it, ACTION-IF-NOT-FOUND defaults to aborting.
|
||||
dnl You can specify [PKG_CONFIG=false] as an action instead, which would
|
||||
dnl result in pkg-config tests failing, but no bogus error messages.
|
||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
||||
@@ -146,6 +152,9 @@ if test -n "$PKG_CONFIG"; then
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi
|
||||
if test -z "$PKG_CONFIG"; then
|
||||
m4_default([$2], [AC_MSG_ERROR([pkg-config not found])])
|
||||
fi[]dnl
|
||||
])dnl PKG_PROG_PKG_CONFIG
|
||||
|
||||
@@ -413,7 +422,7 @@ 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-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1999-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -447,9 +456,12 @@ AC_DEFUN([AM_PATH_PYTHON],
|
||||
dnl Find a Python interpreter. Python versions prior to 2.0 are not
|
||||
dnl supported. (2.0 was released on October 16, 2000).
|
||||
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
|
||||
[python python2 python3 dnl
|
||||
[python python3 dnl
|
||||
python3.20 python3.19 python3.18 python3.17 python3.16 dnl
|
||||
python3.15 python3.14 python3.13 python3.12 python3.11 python3.10 dnl
|
||||
python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl
|
||||
python3.2 python3.1 python3.0 dnl
|
||||
python2 dnl
|
||||
python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl
|
||||
python2.0])
|
||||
|
||||
@@ -644,15 +656,29 @@ try:
|
||||
if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
|
||||
can_use_sysconfig = 0
|
||||
except ImportError:
|
||||
pass"
|
||||
pass" # end of am_python_setup_sysconfig
|
||||
|
||||
# More repeated code, for figuring out the installation scheme to use.
|
||||
am_python_setup_scheme="if hasattr(sysconfig, 'get_default_scheme'):
|
||||
scheme = sysconfig.get_default_scheme()
|
||||
else:
|
||||
scheme = sysconfig._get_default_scheme()
|
||||
if scheme == 'posix_local':
|
||||
if '$am_py_prefix' == '/usr':
|
||||
scheme = 'deb_system' # should only happen during Debian package builds
|
||||
else:
|
||||
# Debian's default scheme installs to /usr/local/ but we want to
|
||||
# follow the prefix, as we always have.
|
||||
# See bugs#54412, #64837, et al.
|
||||
scheme = 'posix_prefix'" # end of am_python_setup_scheme
|
||||
|
||||
dnl emacs-page Set up 4 directories:
|
||||
|
||||
dnl 1. pythondir: where to install python scripts. This is the
|
||||
dnl site-packages directory, not the python standard library
|
||||
dnl directory like in previous automake betas. This behavior
|
||||
dnl directory as in early automake betas. This behavior
|
||||
dnl is more consistent with lispdir.m4 for example.
|
||||
dnl Query distutils for this directory.
|
||||
dnl Query sysconfig or distutils (per above) for this directory.
|
||||
dnl
|
||||
AC_CACHE_CHECK([for $am_display_PYTHON script directory (pythondir)],
|
||||
[am_cv_python_pythondir],
|
||||
@@ -664,7 +690,11 @@ except ImportError:
|
||||
am_cv_python_pythondir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
|
||||
try:
|
||||
$am_python_setup_scheme
|
||||
sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'})
|
||||
except:
|
||||
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
|
||||
else:
|
||||
from distutils import sysconfig
|
||||
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
|
||||
@@ -694,7 +724,8 @@ sys.stdout.write(sitedir)"`
|
||||
|
||||
dnl 3. pyexecdir: directory for installing python extension modules
|
||||
dnl (shared libraries).
|
||||
dnl Query distutils for this directory.
|
||||
dnl Query sysconfig or distutils for this directory.
|
||||
dnl Much of this is the same as for prefix setup above.
|
||||
dnl
|
||||
AC_CACHE_CHECK([for $am_display_PYTHON extension module directory (pyexecdir)],
|
||||
[am_cv_python_pyexecdir],
|
||||
@@ -706,7 +737,11 @@ sys.stdout.write(sitedir)"`
|
||||
am_cv_python_pyexecdir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
|
||||
try:
|
||||
$am_python_setup_scheme
|
||||
sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'})
|
||||
except:
|
||||
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
|
||||
else:
|
||||
from distutils import sysconfig
|
||||
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix')
|
||||
@@ -757,7 +792,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
|
||||
sys.exit(sys.hexversion < minverhex)"
|
||||
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
|
||||
|
||||
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@@ -30,10 +30,10 @@ struct dm_hash_table {
|
||||
unsigned num_nodes;
|
||||
unsigned num_hint;
|
||||
unsigned mask_slots; /* (slots - 1) -> used as hash mask */
|
||||
unsigned collisions; /* Collissions of hash keys */
|
||||
unsigned collisions; /* Collisions of hash keys */
|
||||
unsigned search; /* How many keys were searched */
|
||||
unsigned found; /* How many nodes were found */
|
||||
unsigned same_hash; /* Was there a colision with same masked hash and len ? */
|
||||
unsigned same_hash; /* Was there a collision with same masked hash and len ? */
|
||||
struct dm_hash_node **slots;
|
||||
};
|
||||
|
||||
@@ -348,7 +348,7 @@ int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* matching val and return that. If none have matching val, return NULL.
|
||||
*/
|
||||
void *dm_hash_lookup_with_val(struct dm_hash_table *t, const char *key,
|
||||
const void *val, uint32_t val_len)
|
||||
|
@@ -279,7 +279,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const u
|
||||
pc->len = i;
|
||||
|
||||
if (!_insert(rt, &pc->child, kb + i, ke, rv)) {
|
||||
free(pc2);
|
||||
free(pc->child.value.ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -293,6 +293,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const u
|
||||
if (pc->len == 1) {
|
||||
n4->values[0] = pc->child;
|
||||
free(pc);
|
||||
v->value.ptr = NULL;
|
||||
} else {
|
||||
memmove(pc->prefix, pc->prefix + 1, pc->len - 1);
|
||||
pc->len--;
|
||||
@@ -564,6 +565,13 @@ bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, un
|
||||
return _insert(rt, lr.v, lr.kb, ke, rv);
|
||||
}
|
||||
|
||||
int radix_tree_uniq_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value rv)
|
||||
{
|
||||
unsigned entries = rt->nr_entries;
|
||||
return radix_tree_insert(rt, key, keylen, rv) ?
|
||||
((entries != rt->nr_entries) ? 1 : -1) : 0;
|
||||
}
|
||||
|
||||
// Note the degrade functions also free the original node.
|
||||
static void _degrade_to_n4(struct node16 *n16, struct value *result)
|
||||
{
|
||||
|
@@ -193,12 +193,12 @@ bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
const uint8_t *kb = prefix;
|
||||
const uint8_t *ke = kb + prefix_len;
|
||||
struct node **pn;
|
||||
unsigned count;
|
||||
unsigned count = 0;
|
||||
|
||||
pn = _lookup(&rt->root, kb, ke);
|
||||
|
||||
@@ -280,7 +280,7 @@ static void _dump(FILE *out, struct node *n, unsigned indent)
|
||||
fprintf(out, " ");
|
||||
|
||||
if (n->has_value) {
|
||||
fprintf(out, "value: %llu\n", n->value.n);
|
||||
fprintf(out, "value: %lu\n", (unsigned long) n->value.n);
|
||||
} else {
|
||||
fprintf(out, "key: '%c' [0x%02x] %u\n",
|
||||
isprint(n->key) ? n->key : ' ', n->key, indent);
|
||||
|
@@ -35,6 +35,10 @@ void radix_tree_destroy(struct radix_tree *rt);
|
||||
unsigned radix_tree_size(struct radix_tree *rt);
|
||||
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value v);
|
||||
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen);
|
||||
// Returns: 1 success
|
||||
// 0 failure during insert
|
||||
// -1 key had already existing value (that was updated)
|
||||
int radix_tree_uniq_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value v);
|
||||
|
||||
// Returns the number of values removed
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len);
|
||||
@@ -78,6 +82,12 @@ static inline bool radix_tree_insert_ptr(struct radix_tree *rt, const void *key,
|
||||
union radix_value v = { .ptr = ptr };
|
||||
return radix_tree_insert(rt, key, keylen, v);
|
||||
}
|
||||
|
||||
static inline int radix_tree_uniq_insert_ptr(struct radix_tree *rt, const void *key, size_t keylen, void *ptr)
|
||||
{
|
||||
union radix_value v = { .ptr = ptr };
|
||||
return radix_tree_uniq_insert(rt, key, keylen, v);
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
|
@@ -36,6 +36,19 @@ config {
|
||||
# This configuration option has an automatic default value.
|
||||
# checks = 1
|
||||
|
||||
# Configuration option config/validate_metadata.
|
||||
# Allows to select the level of validation after metadata transformation.
|
||||
# Validation takes extra CPU time to verify internal consistency.
|
||||
# Accepted values:
|
||||
# full
|
||||
# Do a full metadata validation before disk write.
|
||||
# none
|
||||
# Skip any checks (unrecommended, slightly faster).
|
||||
#
|
||||
# This configuration option is advanced.
|
||||
# This configuration option has an automatic default value.
|
||||
# validate_metadata = "full"
|
||||
|
||||
# Configuration option config/abort_on_errors.
|
||||
# Abort the LVM process if a configuration mismatch is found.
|
||||
# This configuration option has an automatic default value.
|
||||
@@ -122,7 +135,7 @@ devices {
|
||||
# Configuration option devices/use_devicesfile.
|
||||
# Enable or disable the use of a devices file.
|
||||
# When enabled, lvm will only use devices that
|
||||
# are lised in the devices file. A devices file will
|
||||
# are listed in the devices file. A devices file will
|
||||
# be used, regardless of this setting, when the --devicesfile
|
||||
# option is set to a specific file name.
|
||||
# This configuration option has an automatic default value.
|
||||
@@ -562,7 +575,7 @@ allocation {
|
||||
|
||||
# Configuration option allocation/cache_pool_max_chunks.
|
||||
# The maximum number of chunks in a cache pool.
|
||||
# For cache target v1.9 the recommended maximumm is 1000000 chunks.
|
||||
# For cache target v1.9 the recommended maximum is 1000000 chunks.
|
||||
# Using cache pool with more chunks may degrade cache performance.
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
@@ -573,7 +586,7 @@ allocation {
|
||||
|
||||
# Configuration option allocation/thin_pool_crop_metadata.
|
||||
# Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
|
||||
# This is slightly less then the actual maximum 15.88 GiB.
|
||||
# This is slightly less than the actual maximum 15.88 GiB.
|
||||
# For compatibility with older version and use of cropped size set to 1.
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_pool_crop_metadata = 0
|
||||
@@ -646,13 +659,6 @@ allocation {
|
||||
# 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.
|
||||
# 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 value is 4096.
|
||||
@@ -751,19 +757,6 @@ allocation {
|
||||
# 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.
|
||||
# async-unsafe - Writes are handled like 'async' but there is no guarantee of the atomicity async provides.
|
||||
# This mode should only be used for better performance when atomicity is not required.
|
||||
# This configuration option has an automatic default value.
|
||||
# vdo_write_policy = "auto"
|
||||
|
||||
# Configuration option allocation/vdo_max_discard.
|
||||
# Specified the maximum size of discard bio accepted, in 4096 byte blocks.
|
||||
# I/O requests to a VDO volume are normally split into 4096-byte blocks,
|
||||
@@ -801,6 +794,9 @@ log {
|
||||
# to define fields to display and sort fields for the log report.
|
||||
# You can also use log/command_log_selection to define selection
|
||||
# criteria used each time the log is reported.
|
||||
# Note that if report/output_format (or --reportformat command line
|
||||
# option) is set to json or json_std, then log/report_command_log=1
|
||||
# is default.
|
||||
# This configuration option has an automatic default value.
|
||||
# report_command_log = 0
|
||||
|
||||
@@ -830,8 +826,9 @@ log {
|
||||
# define selection criteria for log report on command line directly
|
||||
# using <lvm command> --configreport log -S <selection criteria>
|
||||
# which has precedence over log/command_log_selection setting.
|
||||
# For more information about selection criteria in general, see
|
||||
# lvm(8) man page.
|
||||
# To make all the command log lines visible, use "all" value
|
||||
# for the command log selection. For more information about selection
|
||||
# criteria in general, see lvmreport(7) man page.
|
||||
# This configuration option has an automatic default value.
|
||||
# command_log_selection = "!(log_type=status && message=success)"
|
||||
|
||||
@@ -1208,6 +1205,16 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# sanlock_lv_extend = 256
|
||||
|
||||
# Configuration option global/sanlock_align_size.
|
||||
# The sanlock lease size in MiB to use on disks with a 4K sector size.
|
||||
# Possible values are 1,2,4,8. The default is 8, which supports up to
|
||||
# 2000 hosts (and max host_id 2000.) Smaller values support smaller
|
||||
# numbers of max hosts (and max host_ids): 250, 500, 1000, 2000 for
|
||||
# lease sizes 1,2,4,8. Disks with 512 byte sectors always use 1MiB
|
||||
# leases and support 2000 hosts, and are not affected by this setting.
|
||||
# This configuration option has an automatic default value.
|
||||
# sanlock_align_size = 8
|
||||
|
||||
# Configuration option global/lvmlockctl_kill_command.
|
||||
# The command that lvmlockctl --kill should use to force LVs offline.
|
||||
# The lvmlockctl --kill command is run when a shared VG has lost
|
||||
@@ -1372,6 +1379,12 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# fsadm_executable = "@FSADM_PATH@"
|
||||
|
||||
# Configuration option global/lvresize_fs_helper_executable.
|
||||
# The full path to the lvresize_fs_helper command.
|
||||
# LVM uses this command to help with filesystem operations during lvresize.
|
||||
# This configuration option has an automatic default value.
|
||||
# lvresize_fs_helper_executable = "@LVRESIZE_FS_HELPER_PATH@"
|
||||
|
||||
# Configuration option global/system_id_source.
|
||||
# The method LVM uses to set the local system ID.
|
||||
# Volume Groups can also be given a system ID (by vgcreate, vgchange,
|
||||
@@ -1511,12 +1524,14 @@ activation {
|
||||
# Configuration option activation/reserved_stack.
|
||||
# Stack size in KiB to reserve for use while devices are suspended.
|
||||
# Insufficient reserve risks I/O deadlock during device suspension.
|
||||
# Value 0 disables memory locking.
|
||||
# This configuration option has an automatic default value.
|
||||
# reserved_stack = 64
|
||||
|
||||
# Configuration option activation/reserved_memory.
|
||||
# Memory size in KiB to reserve for use while devices are suspended.
|
||||
# Insufficient reserve risks I/O deadlock during device suspension.
|
||||
# Value 0 disables memory locking.
|
||||
# This configuration option has an automatic default value.
|
||||
# reserved_memory = 8192
|
||||
|
||||
@@ -1865,7 +1880,7 @@ activation {
|
||||
# uses are present. Other PVs in the Volume Group may be missing.
|
||||
# degraded
|
||||
# Like complete, but additionally RAID LVs of segment type raid1,
|
||||
# raid4, raid5, radid6 and raid10 will be activated if there is no
|
||||
# raid4, raid5, raid6 and raid10 will be activated if there is no
|
||||
# data loss, i.e. they have sufficient redundancy to present the
|
||||
# entire addressable range of the Logical Volume.
|
||||
# partial
|
||||
@@ -1989,7 +2004,7 @@ report {
|
||||
# If there is more than one report per command, then the format
|
||||
# is applied for all reports. You can also change output format
|
||||
# directly on command line using --reportformat option which
|
||||
# has precedence over log/output_format setting.
|
||||
# has precedence over report/output_format setting.
|
||||
# Accepted values:
|
||||
# basic
|
||||
# Original format with columns and rows. If there is more than
|
||||
@@ -2003,6 +2018,7 @@ report {
|
||||
# - it does not use double quotes around numeric values,
|
||||
# - it uses 'null' for undefined numeric values,
|
||||
# - it prints string list as proper JSON array of strings instead of a single string.
|
||||
# Note that if json or json_std output format is used, then log/command_log_report=1 is default.
|
||||
# This configuration option has an automatic default value.
|
||||
# output_format = "basic"
|
||||
|
||||
@@ -2125,7 +2141,7 @@ report {
|
||||
# %F
|
||||
# Equivalent to %Y-%m-%d (the ISO 8601 date format).
|
||||
# %G
|
||||
# The ISO 8601 week-based year with century as adecimal number.
|
||||
# The ISO 8601 week-based year with century as a decimal number.
|
||||
# The 4-digit year corresponding to the ISO week number (see %V).
|
||||
# This has the same format and value as %Y, except that if the
|
||||
# ISO week number belongs to the previous or next year, that year
|
||||
|
@@ -38,6 +38,14 @@ local {
|
||||
# This configuration option has an automatic default value.
|
||||
# system_id = ""
|
||||
|
||||
# Configuration option local/pr_key.
|
||||
# The local persistent reservation key in hexidecimal.
|
||||
# The value must be unique among all hosts using the same VG.
|
||||
# The max length is 16 hex characters (8 bytes), plus an optional
|
||||
# 0x prefix. If pr_key is not set, host_id will be used to create a key.
|
||||
# This configuration option has an automatic default value.
|
||||
# pr_key = ""
|
||||
|
||||
# Configuration option local/extra_system_ids.
|
||||
# A list of extra VG system IDs the local host can access.
|
||||
# VGs with the system IDs listed here (in addition to the host's own
|
||||
@@ -49,9 +57,12 @@ local {
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option local/host_id.
|
||||
# The lvmlockd sanlock host_id.
|
||||
# This must be unique among all hosts, and must be between 1 and 2000.
|
||||
# Applicable only if LVM is compiled with lockd support
|
||||
# The sanlock host_id used by lvmlockd. This must be unique among all the hosts
|
||||
# using shared VGs with sanlock. Accepted values are 1-2000, except when sanlock_align_size
|
||||
# is configured to 1, 2 or 4, which correspond to max host_id values of 250, 500, or 1000.
|
||||
# When using persistent reservations, lvm will generate a PR key from the host_id
|
||||
# if pr_key is not defined. All hosts using a sanlock shared VG with PR must use
|
||||
# the same approach for configuring their PR key (pr_key or host_id.)
|
||||
# This configuration option has an automatic default value.
|
||||
# host_id = 0
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@
|
||||
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
|
||||
@@ -18,6 +17,5 @@ allocation {
|
||||
vdo_hash_zone_threads=1
|
||||
vdo_logical_threads=1
|
||||
vdo_physical_threads=1
|
||||
vdo_write_policy="auto"
|
||||
vdo_max_discard=1
|
||||
}
|
||||
|
327
configure
vendored
327
configure
vendored
@@ -678,6 +678,7 @@ SILENT_RULES
|
||||
SHARED_LINK
|
||||
SELINUX_STATIC_LIBS
|
||||
SELINUX_PC
|
||||
SD_NOTIFY_SUPPORT
|
||||
SBINDIR
|
||||
RT_LIBS
|
||||
PYTHON3DIR
|
||||
@@ -787,6 +788,8 @@ LIBSYSTEMD_LIBS
|
||||
LIBSYSTEMD_CFLAGS
|
||||
UDEV_LIBS
|
||||
UDEV_CFLAGS
|
||||
LIBNVME_LIBS
|
||||
LIBNVME_CFLAGS
|
||||
BLKID_LIBS
|
||||
BLKID_CFLAGS
|
||||
SYSTEMD_RUN_CMD
|
||||
@@ -912,6 +915,7 @@ enable_silent_rules
|
||||
enable_static_link
|
||||
enable_shared
|
||||
with_blkid
|
||||
with_libnvme
|
||||
with_systemd
|
||||
with_udev
|
||||
with_user
|
||||
@@ -971,8 +975,10 @@ enable_use_lvmpolld
|
||||
with_lvmpolld_pidfile
|
||||
enable_systemd_journal
|
||||
enable_app_machineid
|
||||
enable_sd_notify
|
||||
with_systemd_run
|
||||
enable_blkid_wiping
|
||||
enable_nvme_wwid
|
||||
enable_udev_sync
|
||||
enable_udev_rules
|
||||
enable_udev_rule_exec_detection
|
||||
@@ -1045,6 +1051,8 @@ LIBSEAGATEILM_CFLAGS
|
||||
LIBSEAGATEILM_LIBS
|
||||
BLKID_CFLAGS
|
||||
BLKID_LIBS
|
||||
LIBNVME_CFLAGS
|
||||
LIBNVME_LIBS
|
||||
UDEV_CFLAGS
|
||||
UDEV_LIBS
|
||||
LIBSYSTEMD_CFLAGS
|
||||
@@ -1713,8 +1721,10 @@ Optional Features:
|
||||
--disable-systemd-journal
|
||||
disable LVM systemd journaling
|
||||
--disable-app-machineid disable LVM system ID using app-specific machine-id
|
||||
--disable-sd-notify disable LVM sd_notify
|
||||
--disable-blkid_wiping disable libblkid detection of signatures when wiping
|
||||
and use native code instead
|
||||
--disable-nvme-wwid do not use libnvme to detect alternate WWIDs
|
||||
--enable-udev_sync enable synchronization with udev processing
|
||||
--enable-udev_rules install rule files needed for udev synchronization
|
||||
--enable-udev-rule-exec-detection
|
||||
@@ -1741,6 +1751,7 @@ Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
||||
--without-blkid do not build with blkid library
|
||||
--without-libnvme do not build with libnvme library
|
||||
--without-systemd do not build with systemd library
|
||||
--without-udev do not build with udev library
|
||||
--with-user=USER set the owner of installed files [USER=]
|
||||
@@ -1880,6 +1891,10 @@ Some influential environment variables:
|
||||
BLKID_CFLAGS
|
||||
C compiler flags for BLKID, overriding pkg-config
|
||||
BLKID_LIBS linker flags for BLKID, overriding pkg-config
|
||||
LIBNVME_CFLAGS
|
||||
C compiler flags for LIBNVME, overriding pkg-config
|
||||
LIBNVME_LIBS
|
||||
linker flags for LIBNVME, overriding pkg-config
|
||||
UDEV_CFLAGS C compiler flags for UDEV, overriding pkg-config
|
||||
UDEV_LIBS linker flags for UDEV, overriding pkg-config
|
||||
LIBSYSTEMD_CFLAGS
|
||||
@@ -9128,6 +9143,16 @@ esac
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-libnvme was given.
|
||||
if test ${with_libnvme+y}
|
||||
then :
|
||||
withval=$with_libnvme;
|
||||
else case e in #(
|
||||
e) with_libnvme="yes" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-systemd was given.
|
||||
if test ${with_systemd+y}
|
||||
then :
|
||||
@@ -10929,7 +10954,7 @@ printf "%s\n" "#define VDO_FORMAT_CMD \"$VDO_FORMAT_CMD\"" >>confdefs.h
|
||||
|
||||
#
|
||||
# Do we need to use the API??
|
||||
# Do we want to link lvm2 with a big library for vdoformatting ?
|
||||
# Do we want to link lvm2 with a big library for VDO formatting ?
|
||||
#
|
||||
#AC_ARG_WITH(vdo-include,
|
||||
# AS_HELP_STRING([--with-vdo-include=PATH],
|
||||
@@ -11286,6 +11311,9 @@ printf "%s\n" "no" >&6; }
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi
|
||||
if test -z "$PKG_CONFIG"; then
|
||||
as_fn_error $? "pkg-config not found" "$LINENO" 5
|
||||
fi
|
||||
if test "$BUILD_CMIRRORD" = "yes" && test "$HAVE_CPG" != "yes"
|
||||
then :
|
||||
|
||||
@@ -12146,6 +12174,23 @@ printf "%s\n" "$BUILD_LOCKDSANLOCK" >&6; }
|
||||
if test "$BUILD_LOCKDSANLOCK" = "yes"
|
||||
then :
|
||||
|
||||
LOCKDSANLOCK_SUPPORT=370
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.0.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.0.0") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
LOCKDSANLOCK_SUPPORT=400
|
||||
fi
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.1.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.1.0") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
LOCKDSANLOCK_SUPPORT=410
|
||||
fi
|
||||
|
||||
pkg_failed=no
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsanlock_client >= 3.7.0" >&5
|
||||
@@ -12238,7 +12283,7 @@ printf "%s\n" "yes" >&6; }
|
||||
BUILD_LVMLOCKD="yes"
|
||||
fi
|
||||
|
||||
printf "%s\n" "#define LOCKDSANLOCK_SUPPORT 1" >>confdefs.h
|
||||
printf "%s\n" "#define LOCKDSANLOCK_SUPPORT $LOCKDSANLOCK_SUPPORT" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
@@ -12721,9 +12766,18 @@ SYSTEMD_MIN_VERSION=0
|
||||
NOTIFYDBUS_SUPPORT="no"
|
||||
SYSTEMD_JOURNAL_SUPPORT="no"
|
||||
APP_MACHINEID_SUPPORT="no"
|
||||
SD_NOTIFY_SUPPORT="no"
|
||||
if test "$with_systemd" = "yes"
|
||||
then :
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 218\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "systemd >= 218") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
SYSTEMD_MIN_VERSION=218 SD_NOTIFY_SUPPORT="maybe"
|
||||
fi
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 221\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "systemd >= 221") 2>&5
|
||||
ac_status=$?
|
||||
@@ -12811,6 +12865,41 @@ printf "%s\n" "#define APP_MACHINEID_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test "$SD_NOTIFY_SUPPORT" != "no"
|
||||
then :
|
||||
ac_fn_c_check_header_compile "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes
|
||||
then :
|
||||
SD_NOTIFY_SUPPORT="yes"
|
||||
else case e in #(
|
||||
e) SD_NOTIFY_SUPPORT="no" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
fi
|
||||
# Check whether --enable-sd-notify was given.
|
||||
if test ${enable_sd_notify+y}
|
||||
then :
|
||||
enableval=$enable_sd_notify; if test "$enableval" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"
|
||||
then :
|
||||
as_fn_error $? "--enable-sd-notify requires systemd/sd-daemon.h. (--with-systemd=$with_systemd)" "$LINENO" 5
|
||||
fi
|
||||
SD_NOTIFY_SUPPORT=$enableval
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable to sd_notify" >&5
|
||||
printf %s "checking whether to enable to sd_notify... " >&6; }
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SD_NOTIFY_SUPPORT" >&5
|
||||
printf "%s\n" "$SD_NOTIFY_SUPPORT" >&6; }
|
||||
|
||||
if test "$SD_NOTIFY_SUPPORT" = "yes"
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define SD_NOTIFY_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
|
||||
# Check whether --with-systemd-run was given.
|
||||
@@ -13126,6 +13215,181 @@ printf "%s\n" "$BLKID_WIPING" >&6; }
|
||||
printf "%s\n" "#define DEFAULT_USE_BLKID_WIPING $DEFAULT_USE_BLKID_WIPING" >>confdefs.h
|
||||
|
||||
|
||||
################################################################################
|
||||
# Check whether --enable-nvme-wwid was given.
|
||||
if test ${enable_nvme_wwid+y}
|
||||
then :
|
||||
enableval=$enable_nvme_wwid; NVME_WWID=$enableval
|
||||
else case e in #(
|
||||
e) if test "$with_libnvme" = "yes"
|
||||
then :
|
||||
NVME_WWID="maybe"
|
||||
else case e in #(
|
||||
e) NVME_WWID="no" ;;
|
||||
esac
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
# ATM NVME_WWID is the only user of libnvme, so skip checking for libnvme when disabled
|
||||
if test "$NVME_WWID" = "no"
|
||||
then :
|
||||
with_libnvme="no"
|
||||
fi
|
||||
|
||||
if test "$with_libnvme" = "yes"
|
||||
then :
|
||||
|
||||
|
||||
pkg_failed=no
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libnvme >= 1.4" >&5
|
||||
printf %s "checking for libnvme >= 1.4... " >&6; }
|
||||
|
||||
if test -n "$LIBNVME_CFLAGS"; then
|
||||
pkg_cv_LIBNVME_CFLAGS="$LIBNVME_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnvme >= 1.4\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libnvme >= 1.4") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LIBNVME_CFLAGS=`$PKG_CONFIG --cflags "libnvme >= 1.4" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$LIBNVME_LIBS"; then
|
||||
pkg_cv_LIBNVME_LIBS="$LIBNVME_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnvme >= 1.4\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libnvme >= 1.4") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LIBNVME_LIBS=`$PKG_CONFIG --libs "libnvme >= 1.4" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
LIBNVME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnvme >= 1.4" 2>&1`
|
||||
else
|
||||
LIBNVME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnvme >= 1.4" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$LIBNVME_PKG_ERRORS" >&5
|
||||
|
||||
if test "$NVME_WWID" = "yes"
|
||||
then :
|
||||
NVME_WWID="error"
|
||||
else case e in #(
|
||||
e) NVME_WWID="no" ;;
|
||||
esac
|
||||
fi
|
||||
elif test $pkg_failed = untried; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
if test "$NVME_WWID" = "yes"
|
||||
then :
|
||||
NVME_WWID="error"
|
||||
else case e in #(
|
||||
e) NVME_WWID="no" ;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
LIBNVME_CFLAGS=$pkg_cv_LIBNVME_CFLAGS
|
||||
LIBNVME_LIBS=$pkg_cv_LIBNVME_LIBS
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for NVME_NIDT_CSI in libnvme.h" >&5
|
||||
printf %s "checking for NVME_NIDT_CSI in libnvme.h... " >&6; }
|
||||
if test ${ac_cv_have_libnvme_csi+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else case e in #(
|
||||
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <libnvme.h>
|
||||
const int a = NVME_NIDT_CSI;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"
|
||||
then :
|
||||
ac_cv_have_libnvme_csi="yes"
|
||||
else case e in #(
|
||||
e) ac_cv_have_libnvme_csi="no" ;;
|
||||
esac
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
|
||||
esac
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_libnvme_csi" >&5
|
||||
printf "%s\n" "$ac_cv_have_libnvme_csi" >&6; }
|
||||
|
||||
if test "$NVME_WWID" != "no"
|
||||
then :
|
||||
|
||||
if test $ac_cv_have_libnvme_csi = yes
|
||||
then :
|
||||
NVME_WWID="yes"
|
||||
|
||||
printf "%s\n" "#define NVME_SUPPORT 1" >>confdefs.h
|
||||
|
||||
else case e in #(
|
||||
e) NVME_WWID="error" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
else case e in #(
|
||||
e) if test "$NVME_WWID" = "yes"
|
||||
then :
|
||||
NVME_WWID="error"
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test "$NVME_WWID" = "error"
|
||||
then :
|
||||
as_fn_error $? "--enable-nvme-wwid requires libnvme library >= 1.1. (--with-libnvme=$with_libnvme)" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use libnvme for alternate WWIDs" >&5
|
||||
printf %s "checking whether to use libnvme for alternate WWIDs... " >&6; }
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NVME_WWID" >&5
|
||||
printf "%s\n" "$NVME_WWID" >&6; }
|
||||
|
||||
################################################################################
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable synchronization with udev processing" >&5
|
||||
printf %s "checking whether to enable synchronization with udev processing... " >&6; }
|
||||
@@ -13424,7 +13688,11 @@ printf "%s\n" "$BUILD_LVMDBUSD" >&6; }
|
||||
# Check whether --enable-notify-dbus was given.
|
||||
if test ${enable_notify_dbus+y}
|
||||
then :
|
||||
enableval=$enable_notify_dbus; NOTIFYDBUS_SUPPORT=$enableval
|
||||
enableval=$enable_notify_dbus; if test "enableval" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"
|
||||
then :
|
||||
as_fn_error $? "--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)" "$LINENO" 5
|
||||
fi
|
||||
NOTIFYDBUS_SUPPORT=$enableval
|
||||
fi
|
||||
|
||||
|
||||
@@ -13441,10 +13709,6 @@ fi
|
||||
|
||||
if test "$NOTIFYDBUS_SUPPORT" = "yes"
|
||||
then :
|
||||
if test "$SYSTEMD_MIN_VERSION" -lt 221
|
||||
then :
|
||||
as_fn_error $? "--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)" "$LINENO" 5
|
||||
fi
|
||||
|
||||
printf "%s\n" "#define NOTIFYDBUS_SUPPORT 1" >>confdefs.h
|
||||
|
||||
@@ -13456,10 +13720,10 @@ printf %s "checking whether to build notifydbus... " >&6; }
|
||||
printf "%s\n" "$NOTIFYDBUS_SUPPORT" >&6; }
|
||||
|
||||
################################################################################
|
||||
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"
|
||||
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" ||
|
||||
test "$APP_MACHINEID_SUPPORT" = "yes" || test "$SD_NOTIFY_SUPPORT" = "yes"
|
||||
then :
|
||||
|
||||
|
||||
pkg_failed=no
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5
|
||||
printf %s "checking for libsystemd... " >&6; }
|
||||
@@ -13550,7 +13814,6 @@ else
|
||||
printf "%s\n" "yes" >&6; }
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -13877,7 +14140,21 @@ try:
|
||||
if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
|
||||
can_use_sysconfig = 0
|
||||
except ImportError:
|
||||
pass"
|
||||
pass" # end of am_python_setup_sysconfig
|
||||
|
||||
# More repeated code, for figuring out the installation scheme to use.
|
||||
am_python_setup_scheme="if hasattr(sysconfig, 'get_default_scheme'):
|
||||
scheme = sysconfig.get_default_scheme()
|
||||
else:
|
||||
scheme = sysconfig._get_default_scheme()
|
||||
if scheme == 'posix_local':
|
||||
if '$am_py_prefix' == '/usr':
|
||||
scheme = 'deb_system' # should only happen during Debian package builds
|
||||
else:
|
||||
# Debian's default scheme installs to /usr/local/ but we want to
|
||||
# follow the prefix, as we always have.
|
||||
# See bugs#54412, #64837, et al.
|
||||
scheme = 'posix_prefix'" # end of am_python_setup_scheme
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory (pythondir)" >&5
|
||||
@@ -13894,7 +14171,11 @@ else case e in #(
|
||||
am_cv_python_pythondir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
|
||||
try:
|
||||
$am_python_setup_scheme
|
||||
sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'})
|
||||
except:
|
||||
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
|
||||
else:
|
||||
from distutils import sysconfig
|
||||
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
|
||||
@@ -13924,7 +14205,7 @@ printf "%s\n" "$am_cv_python_pythondir" >&6; }
|
||||
pkgpythondir=\${pythondir}/$PACKAGE
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory (pyexecdir)" >&5
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory (pyexecdir)" >&5
|
||||
printf %s "checking for $am_display_PYTHON extension module directory (pyexecdir)... " >&6; }
|
||||
if test ${am_cv_python_pyexecdir+y}
|
||||
then :
|
||||
@@ -13938,7 +14219,11 @@ else case e in #(
|
||||
am_cv_python_pyexecdir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
|
||||
try:
|
||||
$am_python_setup_scheme
|
||||
sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'})
|
||||
except:
|
||||
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
|
||||
else:
|
||||
from distutils import sysconfig
|
||||
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix')
|
||||
@@ -14287,7 +14572,7 @@ printf %s "checking whether to compile liblvm2cmd.so... " >&6; }
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CMDLIB" >&5
|
||||
printf "%s\n" "$CMDLIB" >&6; }
|
||||
|
||||
if test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"
|
||||
if test "$CMDLIB" = "yes" && test "$SHARED_LINK" = "no"
|
||||
then :
|
||||
as_fn_error $? "--enable-cmdlib requires dynamic linking." "$LINENO" 5
|
||||
fi
|
||||
@@ -16218,6 +16503,11 @@ LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
|
||||
printf "%s\n" "#define LVRESIZE_FS_HELPER_PATH \"$LVRESIZE_FS_HELPER_PATH\"" >>confdefs.h
|
||||
|
||||
|
||||
LVMPERSIST_PATH="$SBINDIR/lvmpersist"
|
||||
|
||||
printf "%s\n" "#define LVMPERSIST_PATH \"$LVMPERSIST_PATH\"" >>confdefs.h
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
# Check whether --with-dmeventd-pidfile was given.
|
||||
@@ -16561,6 +16851,7 @@ AIO_LIBS=${AIO_LIBS:--laio}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -17958,3 +18249,9 @@ then :
|
||||
printf "%s\n" "$as_me: WARNING: Building D-Bus support without D-Bus notifications!" >&2;}
|
||||
fi
|
||||
|
||||
if test "$BUILD_LVMLOCKD" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"
|
||||
then :
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Building lvmlockd without sd-notify support may block!" >&5
|
||||
printf "%s\n" "$as_me: WARNING: Building lvmlockd without sd-notify support may block!" >&2;}
|
||||
fi
|
||||
|
||||
|
90
configure.ac
90
configure.ac
@@ -1,4 +1,3 @@
|
||||
###############################################################################
|
||||
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
|
||||
## Copyright (C) 2004-2023 Red Hat, Inc. All rights reserved.
|
||||
##
|
||||
@@ -20,7 +19,7 @@ AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
|
||||
AC_CONFIG_HEADERS([include/configure.h])
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup the directory where autoconf has auxilary files
|
||||
dnl -- Setup the directory where autoconf has auxiliary files
|
||||
AC_CONFIG_AUX_DIR(autoconf)
|
||||
|
||||
################################################################################
|
||||
@@ -217,6 +216,8 @@ test "$exec_prefix" = "NONE" && exec_prefix='${prefix}'
|
||||
|
||||
AC_ARG_WITH(blkid, [AS_HELP_STRING([--without-blkid], [do not build with blkid library])],
|
||||
[], with_blkid="yes")
|
||||
AC_ARG_WITH(libnvme, [AS_HELP_STRING([--without-libnvme], [do not build with libnvme library])],
|
||||
[], with_libnvme="yes")
|
||||
AC_ARG_WITH(systemd, [AS_HELP_STRING([--without-systemd], [do not build with systemd library])],
|
||||
[], with_systemd="yes")
|
||||
AC_ARG_WITH(udev, [AS_HELP_STRING([--without-udev], [do not build with udev library])],
|
||||
@@ -656,7 +657,7 @@ 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 vdoformatting ?
|
||||
# Do we want to link lvm2 with a big library for VDO formatting ?
|
||||
#
|
||||
#AC_ARG_WITH(vdo-include,
|
||||
# AS_HELP_STRING([--with-vdo-include=PATH],
|
||||
@@ -933,8 +934,11 @@ AC_MSG_RESULT([$BUILD_LOCKDSANLOCK])
|
||||
|
||||
dnl -- Look for sanlock libraries
|
||||
AS_IF([test "$BUILD_LOCKDSANLOCK" = "yes"], [
|
||||
LOCKDSANLOCK_SUPPORT=410
|
||||
PKG_CHECK_EXISTS(libsanlock_client >= 4.0.0, [LOCKDSANLOCK_SUPPORT=400])
|
||||
PKG_CHECK_EXISTS(libsanlock_client >= 4.1.0, [LOCKDSANLOCK_SUPPORT=410])
|
||||
PKG_CHECK_MODULES(LIBSANLOCKCLIENT, libsanlock_client >= 3.7.0, [BUILD_LVMLOCKD="yes"])
|
||||
AC_DEFINE([LOCKDSANLOCK_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd sanlock option.])
|
||||
AC_DEFINE_UNQUOTED([LOCKDSANLOCK_SUPPORT], [$LOCKDSANLOCK_SUPPORT], [Define version of sanlock.])
|
||||
])
|
||||
|
||||
################################################################################
|
||||
@@ -952,7 +956,7 @@ AS_IF([test "$BUILD_LOCKDDLM" = "yes"], [
|
||||
AC_DEFINE([LOCKDDLM_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd dlm option.])
|
||||
AS_CASE(["$LIBDLM_LIBS"],
|
||||
[*lpthread*], [
|
||||
dnl -- pkg-congig for libdlm_lt may give us libdlm with libpthread
|
||||
dnl -- pkg-config for libdlm_lt may give us libdlm with libpthread
|
||||
AC_MSG_RESULT([replacing pkg-config --libs libdlm_lt "$LIBDLM_LIBS" with... -ldlm_lt])
|
||||
LIBDLM_LIBS="${LIBDLM_LIBS%%ldlm*}ldlm_lt"])
|
||||
])
|
||||
@@ -1046,7 +1050,9 @@ SYSTEMD_MIN_VERSION=0
|
||||
NOTIFYDBUS_SUPPORT="no"
|
||||
SYSTEMD_JOURNAL_SUPPORT="no"
|
||||
APP_MACHINEID_SUPPORT="no"
|
||||
SD_NOTIFY_SUPPORT="no"
|
||||
AS_IF([test "$with_systemd" = "yes"],
|
||||
PKG_CHECK_EXISTS(systemd >= 218, [SYSTEMD_MIN_VERSION=218 SD_NOTIFY_SUPPORT="maybe"])
|
||||
PKG_CHECK_EXISTS(systemd >= 221, [SYSTEMD_MIN_VERSION=221 NOTIFYDBUS_SUPPORT="maybe" SYSTEMD_JOURNAL_SUPPORT="maybe"])
|
||||
PKG_CHECK_EXISTS(systemd >= 234, [SYSTEMD_MIN_VERSION=234 APP_MACHINEID_SUPPORT="maybe"]))
|
||||
|
||||
@@ -1082,6 +1088,22 @@ AC_MSG_RESULT([$APP_MACHINEID_SUPPORT])
|
||||
AS_IF([test "$APP_MACHINEID_SUPPORT" = "yes"],
|
||||
AC_DEFINE([APP_MACHINEID_SUPPORT], 1, [Define to 1 to include code that uses libsystemd machine-id apis.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Build with sd_notify when the header file sd-daemon.h is present
|
||||
AS_IF([test "$SD_NOTIFY_SUPPORT" != "no"],
|
||||
AC_CHECK_HEADER([systemd/sd-daemon.h], [SD_NOTIFY_SUPPORT="yes"], [SD_NOTIFY_SUPPORT="no"]))
|
||||
AC_ARG_ENABLE(sd-notify,
|
||||
AS_HELP_STRING([--disable-sd-notify],
|
||||
[disable LVM sd_notify]),
|
||||
AS_IF([test "$enableval" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"],
|
||||
AC_MSG_ERROR([--enable-sd-notify requires systemd/sd-daemon.h. (--with-systemd=$with_systemd)]))
|
||||
SD_NOTIFY_SUPPORT=$enableval, [])
|
||||
AC_MSG_CHECKING([whether to enable to sd_notify])
|
||||
AC_MSG_RESULT([$SD_NOTIFY_SUPPORT])
|
||||
|
||||
AS_IF([test "$SD_NOTIFY_SUPPORT" = "yes"],
|
||||
AC_DEFINE([SD_NOTIFY_SUPPORT], 1, [Define to 1 to include code that uses sd_notify.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Support override for systemd-run path if they need to (NixOS builds)
|
||||
AC_ARG_WITH(systemd-run,
|
||||
@@ -1139,6 +1161,38 @@ AC_MSG_RESULT([$BLKID_WIPING])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_USE_BLKID_WIPING, [$DEFAULT_USE_BLKID_WIPING],
|
||||
[Use blkid wiping by default.])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable nvme alternate WWID via libnvme
|
||||
AC_ARG_ENABLE(nvme-wwid,
|
||||
AS_HELP_STRING([--disable-nvme-wwid],
|
||||
[do not use libnvme to detect alternate WWIDs]),
|
||||
NVME_WWID=$enableval,
|
||||
[AS_IF([test "$with_libnvme" = "yes"], [NVME_WWID="maybe"], [NVME_WWID="no"])])
|
||||
|
||||
# ATM NVME_WWID is the only user of libnvme, so skip checking for libnvme when disabled
|
||||
AS_IF([test "$NVME_WWID" = "no"], [with_libnvme="no"])
|
||||
|
||||
AS_IF([test "$with_libnvme" = "yes"], [
|
||||
PKG_CHECK_MODULES([LIBNVME], [libnvme >= 1.4], [
|
||||
AC_CACHE_CHECK([for NVME_NIDT_CSI in libnvme.h],
|
||||
[ac_cv_have_libnvme_csi],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <libnvme.h>
|
||||
const int a = NVME_NIDT_CSI;
|
||||
])], [ac_cv_have_libnvme_csi="yes"], [ac_cv_have_libnvme_csi="no"])])
|
||||
|
||||
AS_IF([test "$NVME_WWID" != "no"], [
|
||||
AC_IF_YES(ac_cv_have_libnvme_csi, [NVME_WWID="yes"
|
||||
AC_DEFINE(NVME_SUPPORT, 1, [Use libnvme for WWID.])],
|
||||
[NVME_WWID="error"])])
|
||||
], [AS_IF([test "$NVME_WWID" = "yes"], [NVME_WWID="error"], [NVME_WWID="no"])])
|
||||
], [AS_IF([test "$NVME_WWID" = "yes"], [NVME_WWID="error"])])
|
||||
|
||||
AS_IF([test "$NVME_WWID" = "error"],
|
||||
[AC_MSG_ERROR([--enable-nvme-wwid requires libnvme library >= 1.1. (--with-libnvme=$with_libnvme)])])
|
||||
|
||||
AC_MSG_CHECKING([whether to use libnvme for alternate WWIDs])
|
||||
AC_MSG_RESULT([$NVME_WWID])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable udev synchronization
|
||||
AC_MSG_CHECKING([whether to enable synchronization with udev processing])
|
||||
@@ -1231,24 +1285,25 @@ AC_MSG_RESULT([$BUILD_LVMDBUSD])
|
||||
dnl -- Build notifydbus
|
||||
AC_ARG_ENABLE(notify-dbus,
|
||||
[AS_HELP_STRING([--enable-notify-dbus], [enable LVM notification using dbus])],
|
||||
[NOTIFYDBUS_SUPPORT=$enableval])
|
||||
[AS_IF([test "enableval" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
|
||||
[AC_MSG_ERROR([--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)])])
|
||||
NOTIFYDBUS_SUPPORT=$enableval])
|
||||
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "maybe"],
|
||||
[AS_IF([test "$BUILD_LVMDBUSD" = "yes"], [NOTIFYDBUS_SUPPORT="yes"], [NOTIFYDBUS_SUPPORT="no"])])
|
||||
[AS_IF([test "$BUILD_LVMDBUSD" = "yes"],
|
||||
[NOTIFYDBUS_SUPPORT="yes"], [NOTIFYDBUS_SUPPORT="no"])])
|
||||
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes"],
|
||||
[AS_IF([test "$SYSTEMD_MIN_VERSION" -lt 221],
|
||||
[AC_MSG_ERROR([--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)])])
|
||||
AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])])
|
||||
[AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])])
|
||||
|
||||
AC_MSG_CHECKING([whether to build notifydbus])
|
||||
AC_MSG_RESULT([$NOTIFYDBUS_SUPPORT])
|
||||
|
||||
################################################################################
|
||||
dnl -- Look for libsystemd libraries if needed
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"], [
|
||||
PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])
|
||||
])
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" ||
|
||||
test "$APP_MACHINEID_SUPPORT" = "yes" || test "$SD_NOTIFY_SUPPORT" = "yes"],
|
||||
[PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable Python dbus library
|
||||
@@ -1341,7 +1396,7 @@ AS_IF([test "$CMDLIB" != "yes"], [CMDLIB="no" LVM2CMD_LIB=], [LVM2CMD_LIB="-llvm
|
||||
AC_MSG_CHECKING([whether to compile liblvm2cmd.so])
|
||||
AC_MSG_RESULT([$CMDLIB])
|
||||
|
||||
AS_IF([test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"],
|
||||
AS_IF([test "$CMDLIB" = "yes" && test "$SHARED_LINK" = "no"],
|
||||
[AC_MSG_ERROR([--enable-cmdlib requires dynamic linking.])])
|
||||
|
||||
|
||||
@@ -1717,6 +1772,9 @@ LIBEXECDIR="$(eval echo $(eval echo $libexecdir))"
|
||||
LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
|
||||
AC_DEFINE_UNQUOTED(LVRESIZE_FS_HELPER_PATH, ["$LVRESIZE_FS_HELPER_PATH"], [Path to lvresize_fs_helper script.])
|
||||
|
||||
LVMPERSIST_PATH="$SBINDIR/lvmpersist"
|
||||
AC_DEFINE_UNQUOTED(LVMPERSIST_PATH, ["$LVMPERSIST_PATH"], [Path to lvmpersist script.])
|
||||
|
||||
################################################################################
|
||||
dnl -- dmeventd pidfile and executable path
|
||||
AC_ARG_WITH(dmeventd-pidfile,
|
||||
@@ -1938,6 +1996,7 @@ AC_SUBST(PYTHON3)
|
||||
AC_SUBST(PYTHON3DIR)
|
||||
AC_SUBST(RT_LIBS)
|
||||
AC_SUBST(SBINDIR)
|
||||
AC_SUBST(SD_NOTIFY_SUPPORT)
|
||||
AC_SUBST(SELINUX_LIBS)
|
||||
AC_SUBST(SELINUX_PC)
|
||||
AC_SUBST(SELINUX_STATIC_LIBS)
|
||||
@@ -2075,3 +2134,6 @@ AS_IF([test "$ODIRECT" != "yes"],
|
||||
|
||||
AS_IF([test "$BUILD_LVMDBUSD" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
|
||||
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications!])])
|
||||
|
||||
AS_IF([test "$BUILD_LVMLOCKD" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"],
|
||||
[AC_MSG_WARN([Building lvmlockd without sd-notify support may block!])])
|
||||
|
@@ -21,7 +21,7 @@
|
||||
* compile (using outdir 'cov'):
|
||||
* cov-build --dir=cov make CC=gcc
|
||||
*
|
||||
* analyze (agressively, using 'cov')
|
||||
* analyze (aggressively, using 'cov')
|
||||
* cov-analyze --dir cov --wait-for-license --hfa --concurrency --enable-fnptr --enable-constraint-fpp --security --all --aggressiveness-level=high --field-offset-escape --user-model-file=coverity/coverity_model.xml
|
||||
*
|
||||
* generate html output (to 'html' from 'cov'):
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
struct lv_segment;
|
||||
struct logical_volume;
|
||||
struct cmd_context;
|
||||
struct profile;
|
||||
|
||||
struct lv_segment *first_seg(const struct logical_volume *lv)
|
||||
{
|
||||
@@ -57,7 +59,7 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
||||
*/
|
||||
|
||||
/* 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, unsigned long n)
|
||||
{
|
||||
const char *s = src;
|
||||
char *d = dest;
|
||||
@@ -70,7 +72,7 @@ void *memccpy(void *dest, const void *src, int c, size_t n)
|
||||
}
|
||||
|
||||
/*
|
||||
* 2 lines bellow needs to be placed in coverity/config/user_nodefs.h
|
||||
* 2 lines below needs to be placed in coverity/config/user_nodefs.h
|
||||
* Not sure about any other way.
|
||||
* Without them, coverity shows warning since x86 system header files
|
||||
* are using inline assembly to reset fdset
|
||||
@@ -90,9 +92,14 @@ void model_FD_ZERO(void *fdset)
|
||||
/* Resent Coverity reports quite weird errors... */
|
||||
int *__errno_location(void)
|
||||
{
|
||||
static int _i = 0;
|
||||
return &_i;
|
||||
}
|
||||
|
||||
const unsigned short **__ctype_b_loc (void)
|
||||
{
|
||||
static const unsigned short *_a[1] = { 0 };
|
||||
return _a;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -197,7 +197,7 @@ int cluster_send(struct clog_request *rq)
|
||||
iov.iov_base = rq;
|
||||
iov.iov_len = sizeof(struct clog_request) + rq->u_rq.data_size;
|
||||
|
||||
rq->u.version[0] = xlate64(CLOG_TFR_VERSION);
|
||||
rq->u.version[0] = htole64(CLOG_TFR_VERSION);
|
||||
rq->u.version[1] = CLOG_TFR_VERSION;
|
||||
|
||||
r = clog_request_to_network(rq);
|
||||
@@ -279,7 +279,7 @@ static int handle_cluster_request(struct clog_cpg *entry __attribute__((unused))
|
||||
* With resumes, we only handle our own.
|
||||
* Resume is a special case that requires
|
||||
* local action (to set up CPG), followed by
|
||||
* a cluster action to co-ordinate reading
|
||||
* a cluster action to coordinate reading
|
||||
* the disk and checkpointing
|
||||
*/
|
||||
if (tmp->u_rq.request_type == DM_ULOG_RESUME) {
|
||||
|
@@ -52,19 +52,19 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
*pu64 = xlate64(*pu64);
|
||||
*pu64 = htole64(*pu64);
|
||||
break;
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
pi64 = (int64_t *)rq->u_rq.data;
|
||||
*pi64 = xlate64(*pi64);
|
||||
*pi64 = htole64(*pi64);
|
||||
break;
|
||||
case DM_ULOG_GET_RESYNC_WORK:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
pi64 = (int64_t *)rq->u_rq.data;
|
||||
pu64 = ((uint64_t *)rq->u_rq.data) + 1;
|
||||
*pi64 = xlate64(*pi64);
|
||||
*pu64 = xlate64(*pu64);
|
||||
*pi64 = htole64(*pi64);
|
||||
*pu64 = htole64(*pu64);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown request type, %u", rq_type);
|
||||
@@ -94,7 +94,7 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
|
||||
case DM_ULOG_IN_SYNC:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
*pu64 = xlate64(*pu64);
|
||||
*pu64 = htole64(*pu64);
|
||||
break;
|
||||
case DM_ULOG_MARK_REGION:
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
@@ -102,13 +102,13 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
|
||||
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
for (i = 0; i < end; i++)
|
||||
pu64[i] = xlate64(pu64[i]);
|
||||
pu64[i] = htole64(pu64[i]);
|
||||
break;
|
||||
case DM_ULOG_SET_REGION_SYNC:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
pi64 = ((int64_t *)rq->u_rq.data) + 1;
|
||||
*pu64 = xlate64(*pu64);
|
||||
*pi64 = xlate64(*pi64);
|
||||
*pu64 = htole64(*pu64);
|
||||
*pi64 = htole64(*pi64);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown request type, %u", rq_type);
|
||||
@@ -124,15 +124,15 @@ static int v5_endian_to_network(struct clog_request *rq)
|
||||
|
||||
size = sizeof(*rq) + u_rq->data_size;
|
||||
|
||||
u_rq->error = xlate32(u_rq->error);
|
||||
u_rq->seq = xlate32(u_rq->seq);
|
||||
u_rq->error = htole32(u_rq->error);
|
||||
u_rq->seq = htole32(u_rq->seq);
|
||||
|
||||
rq->originator = xlate32(rq->originator);
|
||||
rq->originator = htole32(rq->originator);
|
||||
|
||||
v5_data_endian_switch(rq, 1);
|
||||
|
||||
u_rq->request_type = xlate32(u_rq->request_type);
|
||||
u_rq->data_size = xlate32(u_rq->data_size);
|
||||
u_rq->request_type = htole32(u_rq->request_type);
|
||||
u_rq->data_size = htole32(u_rq->data_size);
|
||||
|
||||
return size;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ int clog_request_to_network(struct clog_request *rq)
|
||||
int r;
|
||||
|
||||
/* FIXME: Remove this safety check */
|
||||
if (rq->u.version[0] != xlate64(rq->u.version[1])) {
|
||||
if (rq->u.version[0] != htole64(rq->u.version[1])) {
|
||||
LOG_ERROR("Programmer error: version[0] must be LE");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -165,12 +165,12 @@ static int v5_endian_from_network(struct clog_request *rq)
|
||||
int size;
|
||||
struct dm_ulog_request *u_rq = &rq->u_rq;
|
||||
|
||||
u_rq->error = xlate32(u_rq->error);
|
||||
u_rq->seq = xlate32(u_rq->seq);
|
||||
u_rq->request_type = xlate32(u_rq->request_type);
|
||||
u_rq->data_size = xlate32(u_rq->data_size);
|
||||
u_rq->error = htole32(u_rq->error);
|
||||
u_rq->seq = htole32(u_rq->seq);
|
||||
u_rq->request_type = htole32(u_rq->request_type);
|
||||
u_rq->data_size = htole32(u_rq->data_size);
|
||||
|
||||
rq->originator = xlate32(rq->originator);
|
||||
rq->originator = htole32(rq->originator);
|
||||
|
||||
size = sizeof(*rq) + u_rq->data_size;
|
||||
|
||||
@@ -182,7 +182,7 @@ static int v5_endian_from_network(struct clog_request *rq)
|
||||
int clog_request_from_network(void *data, size_t data_len)
|
||||
{
|
||||
uint64_t *vp = data;
|
||||
uint64_t version = xlate64(vp[0]);
|
||||
uint64_t version = htole64(vp[0]);
|
||||
struct clog_request *rq = data;
|
||||
|
||||
switch (version) {
|
||||
|
@@ -8,6 +8,8 @@
|
||||
#ifndef _LVM_CLOG_COMPAT_H
|
||||
#define _LVM_CLOG_COMPAT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* The intermachine communication structure version are:
|
||||
* 0: Unused
|
||||
@@ -19,6 +21,8 @@
|
||||
*/
|
||||
#define CLOG_TFR_VERSION 5
|
||||
|
||||
struct clog_request;
|
||||
|
||||
int clog_request_to_network(struct clog_request *rq);
|
||||
int clog_request_from_network(void *data, size_t data_len);
|
||||
|
||||
|
@@ -254,7 +254,7 @@ static int read_log(struct log_c *lc)
|
||||
bitset_size = lc->region_count / 8;
|
||||
bitset_size += (lc->region_count % 8) ? 1 : 0;
|
||||
|
||||
/* 'lc->clean_bits + 1' becasue dm_bitset_t leads with a uint32_t */
|
||||
/* 'lc->clean_bits + 1' because dm_bitset_t leads with a uint32_t */
|
||||
memcpy(lc->clean_bits + 1, (char *)lc->disk_buffer + 1024, bitset_size);
|
||||
|
||||
return 0;
|
||||
@@ -281,7 +281,7 @@ static int write_log(struct log_c *lc)
|
||||
bitset_size = lc->region_count / 8;
|
||||
bitset_size += (lc->region_count % 8) ? 1 : 0;
|
||||
|
||||
/* 'lc->clean_bits + 1' becasue dm_bitset_t leads with a uint32_t */
|
||||
/* 'lc->clean_bits + 1' because dm_bitset_t leads with a uint32_t */
|
||||
memcpy((char *)lc->disk_buffer + 1024, lc->clean_bits + 1, bitset_size);
|
||||
|
||||
if (rw_log(lc, 1)) {
|
||||
@@ -380,8 +380,8 @@ static int _clog_ctr(char *uuid, uint64_t luid,
|
||||
int disk_log;
|
||||
char disk_path[PATH_MAX] = { 0 };
|
||||
int unlink_path = 0;
|
||||
long page_size;
|
||||
int pages;
|
||||
long ps;
|
||||
size_t pages, page_size;
|
||||
|
||||
/* If core log request, then argv[0] will be region_size */
|
||||
if (!strtoll(argv[0], &p, 0) || *p) {
|
||||
@@ -488,14 +488,15 @@ static int _clog_ctr(char *uuid, uint64_t luid,
|
||||
lc->sync_count = (log_sync == NOSYNC) ? region_count : 0;
|
||||
|
||||
if (disk_log) {
|
||||
if ((page_size = sysconf(_SC_PAGESIZE)) < 0) {
|
||||
if (((ps = sysconf(_SC_PAGESIZE)) <= 0) ||
|
||||
(ps > (1 << 24))) {
|
||||
LOG_ERROR("Unable to read pagesize: %s",
|
||||
strerror(errno));
|
||||
r = errno;
|
||||
goto fail;
|
||||
}
|
||||
pages = *(lc->clean_bits) / page_size;
|
||||
pages += *(lc->clean_bits) % page_size ? 1 : 0;
|
||||
page_size = (size_t)ps;
|
||||
pages = (*(lc->clean_bits) + page_size - 1) / page_size;
|
||||
pages += 1; /* for header */
|
||||
|
||||
r = open(disk_path, O_RDWR | O_DIRECT);
|
||||
@@ -927,7 +928,7 @@ int local_resume(struct dm_ulog_request *rq)
|
||||
*
|
||||
* Since this value doesn't change, the kernel
|
||||
* should not need to talk to server to get this
|
||||
* The function is here for completness
|
||||
* The function is here for completeness
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
@@ -1018,7 +1019,7 @@ static int clog_in_sync(struct dm_ulog_request *rq)
|
||||
* happen for reads is that additional read attempts may be
|
||||
* taken.
|
||||
*
|
||||
* Futher investigation may be required to determine if there are
|
||||
* Further investigation may be required to determine if there are
|
||||
* similar possible outcomes when the mirror is in the process of
|
||||
* recovering. In that case, lc->in_sync would not have been set
|
||||
* yet.
|
||||
|
@@ -326,10 +326,11 @@ static int do_local_work(void *data __attribute__((unused)))
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
int kernel_send(struct dm_ulog_request *u_rq)
|
||||
int kernel_send(void *data)
|
||||
{
|
||||
int r;
|
||||
uint16_t size;
|
||||
struct dm_ulog_request *u_rq = data;
|
||||
|
||||
if (!u_rq)
|
||||
return -EINVAL;
|
||||
@@ -353,7 +354,7 @@ int kernel_send(struct dm_ulog_request *u_rq)
|
||||
size = sizeof(struct dm_ulog_request);
|
||||
}
|
||||
|
||||
r = kernel_send_helper(u_rq, size);
|
||||
r = kernel_send_helper(data, size);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to send msg to kernel.");
|
||||
|
||||
|
@@ -12,9 +12,11 @@
|
||||
#ifndef _LVM_CLOG_LOCAL_H
|
||||
#define _LVM_CLOG_LOCAL_H
|
||||
|
||||
struct dm_ulog_request;
|
||||
|
||||
int init_local(void);
|
||||
void cleanup_local(void);
|
||||
|
||||
int kernel_send(struct dm_ulog_request *rq);
|
||||
int kernel_send(void *data);
|
||||
|
||||
#endif /* _LVM_CLOG_LOCAL_H */
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include <fcntl.h> /* for musl libc */
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#ifdef __linux__
|
||||
/*
|
||||
@@ -92,6 +93,10 @@ static const size_t THREAD_STACK_SIZE = 300 * 1024;
|
||||
/* Default idle exit timeout 1 hour (in seconds) */
|
||||
static const time_t DMEVENTD_IDLE_EXIT_TIMEOUT = 60 * 60;
|
||||
|
||||
/* Default grace period for thread cleanup 10 seconds */
|
||||
#define DMEVENTD_DEFAULT_GRACE_PERIOD 10
|
||||
static int _grace_period = DMEVENTD_DEFAULT_GRACE_PERIOD;
|
||||
|
||||
static int _systemd_activation = 0;
|
||||
static int _foreground = 0;
|
||||
static time_t _idle_since = 0;
|
||||
@@ -209,7 +214,8 @@ struct message_data {
|
||||
/* There are three states a thread can attain. */
|
||||
enum {
|
||||
DM_THREAD_REGISTERING, /* Registering, transitions to RUNNING */
|
||||
DM_THREAD_RUNNING, /* Working on events, transitions to DONE */
|
||||
DM_THREAD_RUNNING, /* Working on events, transitions to GRACE or DONE */
|
||||
DM_THREAD_GRACE_PERIOD, /* Thread awaits reuse for a grace period */
|
||||
DM_THREAD_DONE /* Terminated and cleanup is pending */
|
||||
};
|
||||
|
||||
@@ -233,12 +239,15 @@ struct thread_status {
|
||||
} device;
|
||||
int processing; /* Set when event is being processed */
|
||||
|
||||
int status; /* See DM_THREAD_{REGISTERING,RUNNING,DONE} */
|
||||
int status; /* See DM_THREAD_{REGISTERING,RUNNING,GRACE_PERIOD,DONE} */
|
||||
|
||||
int events; /* bitfield for event filter. */
|
||||
int current_events; /* bitfield for occured events. */
|
||||
int current_events; /* bitfield for occurred events. */
|
||||
struct dm_task *wait_task;
|
||||
int pending; /* Set when event filter change is pending */
|
||||
int used; /* Count thread reusage (for debugging) */
|
||||
pthread_cond_t grace_cond; /* Condition variable for grace period wait */
|
||||
uint64_t inode; /* Device path inode of monitored volume */
|
||||
time_t next_time;
|
||||
uint32_t timeout;
|
||||
struct dm_list timeout_list;
|
||||
@@ -268,7 +277,7 @@ static void _free_dso_data(struct dso_data *data)
|
||||
|
||||
static struct dso_data *_alloc_dso_data(struct message_data *data)
|
||||
{
|
||||
struct dso_data *ret = (typeof(ret)) zalloc(sizeof(*ret));
|
||||
struct dso_data *ret = (__typeof__(ret)) zalloc(sizeof(*ret));
|
||||
|
||||
if (!ret)
|
||||
return_NULL;
|
||||
@@ -395,11 +404,17 @@ static void _free_thread_status(struct thread_status *thread)
|
||||
_lib_put(thread->dso_data);
|
||||
if (thread->wait_task)
|
||||
dm_task_destroy(thread->wait_task);
|
||||
|
||||
/* Clean up grace period condition variable */
|
||||
pthread_cond_destroy(&thread->grace_cond);
|
||||
|
||||
free(thread->device.uuid);
|
||||
free(thread->device.name);
|
||||
free(thread);
|
||||
}
|
||||
|
||||
static int _lock_mutex(void);
|
||||
static int _unlock_mutex(void);
|
||||
/* Note: events_field must not be 0, ensured by caller */
|
||||
static struct thread_status *_alloc_thread_status(const struct message_data *data,
|
||||
struct dso_data *dso_data)
|
||||
@@ -427,7 +442,13 @@ static struct thread_status *_alloc_thread_status(const struct message_data *dat
|
||||
if (!(thread->device.name = strdup(data->device_uuid)))
|
||||
goto_out;
|
||||
|
||||
/* runs ioctl and may register lvm2 pluging */
|
||||
/* Initialize grace period condition variable */
|
||||
if (pthread_cond_init(&thread->grace_cond, NULL)) {
|
||||
log_error("Failed to initialize grace period condition variable.");
|
||||
goto_out;
|
||||
}
|
||||
|
||||
/* runs ioctl and may register lvm2 plugin */
|
||||
thread->processing = 1;
|
||||
thread->status = DM_THREAD_REGISTERING;
|
||||
|
||||
@@ -520,7 +541,7 @@ static int _fetch_string(char **ptr, char **src, const int delimiter)
|
||||
*p = delimiter;
|
||||
*src = p;
|
||||
}
|
||||
(*src)++; /* Skip delmiter, next field */
|
||||
(*src)++; /* Skip delimiter, next field */
|
||||
} else if ((len = strlen(*src))) {
|
||||
/* No delimiter, item ends with '\0' */
|
||||
if (!(*ptr = strdup(*src))) {
|
||||
@@ -606,11 +627,14 @@ static int _fill_device_data(struct thread_status *ts)
|
||||
if (!dm_task_run(dmt))
|
||||
goto fail;
|
||||
|
||||
free(ts->device.name);
|
||||
if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
|
||||
if (!dm_task_get_info(dmt, &dmi))
|
||||
goto fail;
|
||||
|
||||
if (!dm_task_get_info(dmt, &dmi))
|
||||
if (!dmi.exists)
|
||||
goto fail;
|
||||
|
||||
free(ts->device.name);
|
||||
if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
|
||||
goto fail;
|
||||
|
||||
ts->device.major = dmi.major;
|
||||
@@ -626,9 +650,9 @@ fail:
|
||||
|
||||
static struct dm_task *_get_device_status(struct thread_status *ts)
|
||||
{
|
||||
struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS);
|
||||
struct dm_task *dmt;
|
||||
|
||||
if (!dmt)
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
|
||||
return_NULL;
|
||||
|
||||
if (!dm_task_set_uuid(dmt, ts->device.uuid)) {
|
||||
@@ -648,6 +672,60 @@ static struct dm_task *_get_device_status(struct thread_status *ts)
|
||||
return dmt;
|
||||
}
|
||||
|
||||
static uint64_t _get_device_inode(struct thread_status *ts)
|
||||
{
|
||||
static int _kernel_major = -1;
|
||||
struct utsname uts;
|
||||
struct stat buf;
|
||||
char path[PATH_MAX];
|
||||
|
||||
/* Get kernel version to determine path format */
|
||||
if (_kernel_major < 0) {
|
||||
_kernel_major = 0;
|
||||
if (uname(&uts))
|
||||
log_sys_debug("uname", "");
|
||||
else if (sscanf(uts.release, "%d", &_kernel_major) != 1)
|
||||
log_debug("Cannot parse kernel version from %s.", uts.release);
|
||||
}
|
||||
|
||||
if (_kernel_major >= 3) {
|
||||
/* Use sysfs path with major:minor format for modern kernels */
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
|
||||
dm_sysfs_dir(), ts->device.major, ts->device.minor) < 0)
|
||||
return_0;
|
||||
} else {
|
||||
/* Use /dev/mapper/name device path for kernel version <3.
|
||||
* Older kernels do not change inode numbers for devices!
|
||||
* Relies on correct files in /dev/mapper directory.
|
||||
*/
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s",
|
||||
dm_dir(), ts->device.name) < 0)
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (stat(path, &buf) < 0) {
|
||||
log_sys_debug("stat", path);
|
||||
if (_kernel_major >= 3)
|
||||
return 0;
|
||||
|
||||
/* Since monitoring is not synchronized with udev
|
||||
* symlink may not exists, so also try /dev/dm-X */
|
||||
if (dm_snprintf(path, sizeof(path), "%s/../dm-%d",
|
||||
dm_dir(), ts->device.minor) < 0)
|
||||
return_0;
|
||||
|
||||
if (stat(path, &buf) < 0) {
|
||||
log_sys_debug("stat", path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("Device %s with inode %" PRIu64 " (kernel %d).",
|
||||
path, (uint64_t) buf.st_ino, _kernel_major);
|
||||
|
||||
return (uint64_t) buf.st_ino;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an existing thread for a device.
|
||||
*
|
||||
@@ -664,6 +742,22 @@ static struct thread_status *_lookup_thread_status(struct message_data *data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct thread_status *_lookup_grace_thread_status(struct message_data *data)
|
||||
{
|
||||
struct thread_status *thread;
|
||||
|
||||
dm_list_iterate_items(thread, &_thread_registry_unused)
|
||||
if ((thread->status == DM_THREAD_GRACE_PERIOD) &&
|
||||
!strcmp(data->device_uuid, thread->device.uuid) &&
|
||||
!strcmp(data->dso_name, thread->dso_data->dso_name) &&
|
||||
(thread->inode == _get_device_inode(thread))) {
|
||||
DEBUGLOG("Found reusable thread %x in grace period.",(int)thread->thread);
|
||||
return thread;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _get_status(struct message_data *message_data)
|
||||
{
|
||||
struct dm_event_daemon_message *msg = message_data->msg;
|
||||
@@ -680,9 +774,15 @@ static int _get_status(struct message_data *message_data)
|
||||
return -EINVAL;
|
||||
|
||||
_lock_mutex();
|
||||
count = dm_list_size(&_thread_registry);
|
||||
if (!(count = dm_list_size(&_thread_registry))) {
|
||||
_unlock_mutex();
|
||||
ret = 0; /* no monitored devices */
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffers = alloca(sizeof(char*) * count);
|
||||
dm_list_iterate_items(thread, &_thread_registry) {
|
||||
/* coverity[overflow_sink] - only positive 'current' is used */
|
||||
if ((current = dm_asprintf(buffers + i, "0:%d %s %s %u %" PRIu32 ";",
|
||||
i, thread->dso_data->dso_name,
|
||||
thread->device.uuid, thread->events,
|
||||
@@ -691,6 +791,7 @@ static int _get_status(struct message_data *message_data)
|
||||
goto out;
|
||||
}
|
||||
++i;
|
||||
/* coverity[overflow] - only positive 'current' is used */
|
||||
size += current; /* count with trailing '\0' */
|
||||
}
|
||||
_unlock_mutex();
|
||||
@@ -785,7 +886,11 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
|
||||
if (thread->next_time <= curr_time) {
|
||||
thread->next_time = curr_time + thread->timeout;
|
||||
_lock_mutex();
|
||||
if (thread->processing) {
|
||||
if (thread->status != DM_THREAD_RUNNING) {
|
||||
/* Skip wake up of non running thread (i.e. in grace period) */
|
||||
log_debug("Skipping SIGALRM to non running Thr %x for timeout.",
|
||||
(int) thread->thread);
|
||||
} else if (thread->processing) {
|
||||
/* Cannot signal processing monitoring thread */
|
||||
log_debug("Skipping SIGALRM to processing Thr %x for timeout.",
|
||||
(int) thread->thread);
|
||||
@@ -804,8 +909,8 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
|
||||
timeout.tv_sec = thread->next_time;
|
||||
}
|
||||
|
||||
pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
|
||||
&timeout);
|
||||
(void) pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
|
||||
&timeout);
|
||||
}
|
||||
|
||||
DEBUGLOG("Timeout thread finished.");
|
||||
@@ -872,6 +977,43 @@ enum {
|
||||
DM_WAIT_FATAL
|
||||
};
|
||||
|
||||
/* Reset pending signal for a task/thread */
|
||||
static int _reset_pending_signal(int signal)
|
||||
{
|
||||
sigset_t prev_mask, mask;
|
||||
struct sigaction prev_act, act = { .sa_handler = SIG_IGN };
|
||||
|
||||
sigemptyset(&act.sa_mask);
|
||||
|
||||
sigemptyset(&prev_mask);
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, signal);
|
||||
|
||||
if (pthread_sigmask(SIG_SETMASK, &mask, &prev_mask) != 0) {
|
||||
log_sys_error("pthread_sigmask", "ignore signal");
|
||||
return 0; /* What better */
|
||||
}
|
||||
|
||||
if (sigaction(signal, &act, &prev_act) < 0) {
|
||||
log_sys_error("sigaction", "ignore signal");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sigaction(signal, &prev_act, NULL) < 0) {
|
||||
log_sys_error("sigaction", "restore signal");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* And also restore the process's original sigmask */
|
||||
if (pthread_sigmask(SIG_SETMASK, &prev_mask, NULL) < 0) {
|
||||
log_sys_error("pthread_sigmask", "restore signal");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Wait on a device until an event occurs. */
|
||||
static int _event_wait(struct thread_status *thread)
|
||||
{
|
||||
@@ -894,6 +1036,9 @@ static int _event_wait(struct thread_status *thread)
|
||||
}
|
||||
|
||||
if (dm_task_run(thread->wait_task)) {
|
||||
/* Recheck device info whether is still exists */
|
||||
if (!_fill_device_data(thread))
|
||||
goto disappeared; /* device is gone... */
|
||||
thread->current_events |= DM_EVENT_DEVICE_ERROR;
|
||||
ret = DM_WAIT_INTR;
|
||||
/* Update event_nr */
|
||||
@@ -902,6 +1047,7 @@ static int _event_wait(struct thread_status *thread)
|
||||
} else {
|
||||
switch (dm_task_get_errno(thread->wait_task)) {
|
||||
case ENXIO:
|
||||
disappeared:
|
||||
log_error("%s disappeared, detaching.",
|
||||
thread->device.name);
|
||||
ret = DM_WAIT_FATAL;
|
||||
@@ -958,7 +1104,8 @@ static void _do_process_event(struct thread_status *thread)
|
||||
if (!task)
|
||||
log_error("Lost event in Thr %x.", (int)thread->thread);
|
||||
else {
|
||||
thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private));
|
||||
thread->dso_data->process_event(task, (enum dm_event_mask) thread->current_events,
|
||||
&(thread->dso_private));
|
||||
if (task != thread->wait_task)
|
||||
dm_task_destroy(task);
|
||||
}
|
||||
@@ -970,6 +1117,12 @@ static void _thread_unused(struct thread_status *thread)
|
||||
LINK(thread, &_thread_registry_unused);
|
||||
}
|
||||
|
||||
static void _thread_used(struct thread_status *thread)
|
||||
{
|
||||
UNLINK_THREAD(thread);
|
||||
LINK_THREAD(thread);
|
||||
}
|
||||
|
||||
/* Thread cleanup handler to unregister device. */
|
||||
static void _monitor_unregister(void *arg)
|
||||
{
|
||||
@@ -1006,32 +1159,11 @@ static void _monitor_unregister(void *arg)
|
||||
kill(getpid(), SIGINT);
|
||||
}
|
||||
|
||||
/* Device monitoring thread. */
|
||||
static void *_monitor_thread(void *arg)
|
||||
static int _monitor_events(struct thread_status *thread)
|
||||
{
|
||||
struct thread_status *thread = arg;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
sigset_t pendmask;
|
||||
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
||||
pthread_cleanup_push(_monitor_unregister, thread);
|
||||
|
||||
if (!_fill_device_data(thread)) {
|
||||
log_error("Failed to fill device data for %s.", thread->device.uuid);
|
||||
_lock_mutex();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_do_register_device(thread)) {
|
||||
log_error("Failed to register device %s.", thread->device.name);
|
||||
_lock_mutex();
|
||||
goto out;
|
||||
}
|
||||
|
||||
_lock_mutex();
|
||||
thread->status = DM_THREAD_RUNNING;
|
||||
thread->processing = 0;
|
||||
|
||||
/* Loop awaiting/analyzing device events. */
|
||||
while (thread->events) {
|
||||
|
||||
@@ -1077,6 +1209,96 @@ static void *_monitor_thread(void *arg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Thread awaits condition wake up for a grace period */
|
||||
static void _monitor_grace_period_wait(struct thread_status *thread)
|
||||
{
|
||||
struct timespec grace_timeout = { .tv_sec = time(NULL) + _grace_period };
|
||||
|
||||
DEBUGLOG("Thread %x entering grace period for %d seconds.",
|
||||
(int)thread->thread, _grace_period);
|
||||
|
||||
/* Wait on per-thread condition variable with global mutex */
|
||||
while (!_exit_now && !thread->events &&
|
||||
(ETIMEDOUT != pthread_cond_timedwait(&thread->grace_cond,
|
||||
&_global_mutex, &grace_timeout)))
|
||||
/* Waiting */;
|
||||
|
||||
DEBUGLOG("Thread %x wakeup grace period.", (int)thread->thread);
|
||||
}
|
||||
|
||||
/* Device monitoring thread. */
|
||||
static void *_monitor_thread(void *arg)
|
||||
{
|
||||
struct thread_status *thread = arg;
|
||||
int ret;
|
||||
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
||||
pthread_cleanup_push(_monitor_unregister, thread);
|
||||
|
||||
if (!_fill_device_data(thread)) {
|
||||
log_error("Failed to fill device data for %s.", thread->device.uuid);
|
||||
_lock_mutex();
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Now with resolved major:minor store also device inode */
|
||||
thread->inode = _get_device_inode(thread);
|
||||
|
||||
if (!_do_register_device(thread)) {
|
||||
log_error("Failed to register device %s.", thread->device.name);
|
||||
_lock_mutex();
|
||||
goto out;
|
||||
}
|
||||
|
||||
_lock_mutex();
|
||||
|
||||
/* Main monitoring loop with grace period support */
|
||||
while (thread->events) {
|
||||
DEBUGLOG("Monitoring %s with Thr %x (events: %x, used: %d).",
|
||||
thread->device.name, (int)thread->thread,
|
||||
thread->events, thread->used);
|
||||
|
||||
thread->status = DM_THREAD_RUNNING;
|
||||
thread->processing = 0;
|
||||
thread->used++;
|
||||
|
||||
ret = _monitor_events(thread);
|
||||
|
||||
/* No grace period when set to 0
|
||||
* or there were left some processing events which is an error state
|
||||
* or there is on going exit
|
||||
* or there was fatal error while waiting for some event */
|
||||
if (!_grace_period || thread->events || _exit_now || (ret == DM_WAIT_FATAL))
|
||||
break;
|
||||
|
||||
/* Before restarting event loop reset any pending SIGALRM signal */
|
||||
if (!_reset_pending_signal(SIGALRM)) {
|
||||
stack;
|
||||
break; /* Something is wrong... */
|
||||
}
|
||||
|
||||
thread->current_events = 0;
|
||||
thread->status = DM_THREAD_GRACE_PERIOD; /* No events - enter grace period */
|
||||
_thread_unused(thread);
|
||||
|
||||
DEBUGLOG("Gracing %s with Thr %x (events: %x, used: %d).",
|
||||
thread->device.name, (int)thread->thread,
|
||||
thread->events, thread->used);
|
||||
|
||||
_monitor_grace_period_wait(thread);
|
||||
_unlock_mutex();
|
||||
|
||||
pthread_mutex_lock(&_timeout_mutex);
|
||||
thread->next_time = time(NULL) + thread->timeout;
|
||||
pthread_mutex_unlock(&_timeout_mutex);
|
||||
|
||||
_lock_mutex();
|
||||
_thread_used(thread);
|
||||
}
|
||||
out:
|
||||
/* ';' fixes gcc compilation problem with older pthread macros
|
||||
* "label at end of compound statement" */
|
||||
@@ -1105,6 +1327,15 @@ static int _update_events(struct thread_status *thread, int events)
|
||||
thread->events = events;
|
||||
thread->pending = DM_EVENT_REGISTRATION_PENDING;
|
||||
|
||||
/* If needed, wake up thread waiting in grace period */
|
||||
if ((events || _exit_now) && (thread->status == DM_THREAD_GRACE_PERIOD)) {
|
||||
DEBUGLOG("Waking up thread %x waiting in grace period (events=%x).",
|
||||
(int)thread->thread, events);
|
||||
/* Signal per-thread condition variable while holding global mutex */
|
||||
pthread_cond_signal(&thread->grace_cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only non-processing threads can be notified */
|
||||
if (!thread->processing) {
|
||||
DEBUGLOG("Sending SIGALRM to wakeup Thr %x.", (int)thread->thread);
|
||||
@@ -1119,9 +1350,7 @@ static int _update_events(struct thread_status *thread, int events)
|
||||
}
|
||||
}
|
||||
|
||||
/* Threads with no events has to be moved to unused */
|
||||
if (!thread->events)
|
||||
_thread_unused(thread);
|
||||
/* Threads with no events will enter grace period in their main loop */
|
||||
|
||||
return -ret;
|
||||
}
|
||||
@@ -1223,7 +1452,8 @@ static int _register_for_event(struct message_data *message_data)
|
||||
|
||||
_lock_mutex();
|
||||
|
||||
if ((thread = _lookup_thread_status(message_data))) {
|
||||
if ((thread = _lookup_thread_status(message_data)) ||
|
||||
(thread = _lookup_grace_thread_status(message_data))) {
|
||||
/* OR event # into events bitfield. */
|
||||
ret = _update_events(thread, (thread->events | message_data->events_field));
|
||||
} else {
|
||||
@@ -1337,11 +1567,13 @@ static int _get_registered_dev(struct message_data *message_data, int next)
|
||||
|
||||
/*
|
||||
* If we didn't get a match, try the threads waiting to be deleted.
|
||||
* Threads in grace period are skipped.
|
||||
* FIXME Do something similar if 'next' is set.
|
||||
*/
|
||||
if (!hit && !next)
|
||||
dm_list_iterate_items(thread, &_thread_registry_unused)
|
||||
if (_want_registered_device(message_data->dso_name,
|
||||
if ((thread->status != DM_THREAD_GRACE_PERIOD) &&
|
||||
_want_registered_device(message_data->dso_name,
|
||||
message_data->device_uuid, thread)) {
|
||||
hit = thread;
|
||||
goto reg;
|
||||
@@ -1426,8 +1658,8 @@ static int _open_fifo(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
int fd = -1;
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* FIXME Explicitly verify the code's requirement that path is secure:
|
||||
* - All parent directories owned by root without group/other write access unless sticky.
|
||||
*/
|
||||
@@ -1716,8 +1948,8 @@ static void _process_request(struct dm_event_fifos *fifos)
|
||||
free(msg.data);
|
||||
|
||||
if (cmd == DM_EVENT_CMD_DIE) {
|
||||
_exit_now = DM_SCHEDULED_EXIT; /* No grace period */
|
||||
_unregister_all_threads();
|
||||
_exit_now = DM_SCHEDULED_EXIT;
|
||||
log_info("dmeventd exiting for restart.");
|
||||
}
|
||||
}
|
||||
@@ -2250,16 +2482,18 @@ bad:
|
||||
static void _usage(char *prog, FILE *file)
|
||||
{
|
||||
fprintf(file, "Usage:\n"
|
||||
"%s [-d [-d [-d]]] [-e path] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
|
||||
"%s [-d [-d [-d]]] [-e path] [-g seconds] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
|
||||
" -d Log debug messages to syslog (-d, -dd, -ddd)\n"
|
||||
" -e Select a file path checked on exit\n"
|
||||
" -g Grace period for thread cleanup (0-300 seconds, default: %d)\n"
|
||||
" -f Don't fork, run in the foreground\n"
|
||||
" -h Show this help information\n"
|
||||
" -i Query running instance of dmeventd for info\n"
|
||||
" -l Log to stdout,stderr instead of syslog\n"
|
||||
" -? Show this help information on stderr\n"
|
||||
" -R Restart dmeventd\n"
|
||||
" -V Show version of dmeventd\n\n", prog);
|
||||
" -V Show version of dmeventd\n\n", prog,
|
||||
_grace_period);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -2279,7 +2513,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
optopt = optind = opterr = 0;
|
||||
optarg = (char*) "";
|
||||
while ((opt = getopt(argc, argv, ":?e:fhiVdlR")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, ":?e:g:fhiVdlR")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
_usage(argv[0], stdout);
|
||||
@@ -2300,6 +2534,13 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
_exit_on=optarg;
|
||||
break;
|
||||
case 'g':
|
||||
_grace_period = atoi(optarg);
|
||||
if (_grace_period < 0 || _grace_period > 300) {
|
||||
fprintf(stderr, "dmeventd: grace period must be between 0 and 300 seconds.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
_foreground++;
|
||||
break;
|
||||
|
@@ -15,6 +15,8 @@
|
||||
#ifndef __DMEVENTD_DOT_H__
|
||||
#define __DMEVENTD_DOT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* FIXME This stuff must be configurable. */
|
||||
|
||||
#define DM_EVENT_FIFO_CLIENT DEFAULT_DM_RUN_DIR "/dmeventd-client"
|
||||
|
@@ -404,7 +404,7 @@ int daemon_talk(struct dm_event_fifos *fifos,
|
||||
/*
|
||||
* Check for usable client fifo file
|
||||
*
|
||||
* Returns: 2 cliant path does not exists, dmeventd should be restarted
|
||||
* Returns: 2 client path does not exists, dmeventd should be restarted
|
||||
* 1 on success, 0 otherwise
|
||||
*/
|
||||
static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
@@ -446,6 +446,7 @@ static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *f
|
||||
log_error("%s is no longer a secure root-owned fifo with mode 0600.", fifos->client_path);
|
||||
if (close(fifos->client))
|
||||
log_sys_debug("close", fifos->client_path);
|
||||
fifos->client = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -828,7 +829,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
||||
}
|
||||
|
||||
dm_event_handler_set_dso(dmevh, reply_dso);
|
||||
dm_event_handler_set_event_mask(dmevh, reply_mask);
|
||||
dm_event_handler_set_event_mask(dmevh, (enum dm_event_mask) reply_mask);
|
||||
|
||||
free(reply_dso);
|
||||
reply_dso = NULL;
|
||||
@@ -987,7 +988,7 @@ void dm_event_log(const char *subsys, int level, const char *file,
|
||||
fprintf(stream, "%28s:%4d %s", file, line, indent);
|
||||
vfprintf(stream, _(format), ap);
|
||||
fputc('\n', stream);
|
||||
fflush(stream);
|
||||
(void) fflush(stream);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_log_mutex);
|
||||
@@ -1006,7 +1007,7 @@ void dm_event_log(const char *subsys, int level, const char *file,
|
||||
|
||||
static char *_skip_string(char *src, const int delimiter)
|
||||
{
|
||||
src = srtchr(src, delimiter);
|
||||
src = strchr(src, delimiter);
|
||||
if (src && *(src + 1))
|
||||
return src + 1;
|
||||
return NULL;
|
||||
|
@@ -29,19 +29,22 @@
|
||||
*/
|
||||
|
||||
enum dm_event_mask {
|
||||
DM_EVENT_SETTINGS_MASK = 0x0000FF,
|
||||
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
|
||||
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
|
||||
DM_EVENT_SETTINGS_MASK = 0x0000FF,
|
||||
|
||||
DM_EVENT_ERROR_MASK = 0x00FF00,
|
||||
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
|
||||
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
|
||||
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
|
||||
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
|
||||
DM_EVENT_ERROR_MASK = 0x00FF00,
|
||||
|
||||
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
|
||||
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occurred */
|
||||
|
||||
DM_EVENT_ERROR_AND_TIMEOUT_MASK = 0x02FF00,
|
||||
|
||||
DM_EVENT_STATUS_MASK = 0xFF0000,
|
||||
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
|
||||
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
|
||||
|
||||
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
|
||||
};
|
||||
@@ -70,10 +73,10 @@ int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
|
||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path);
|
||||
|
||||
/*
|
||||
* Identify the device to monitor by exactly one of device_name, uuid or
|
||||
* Identify the device to monitor by exactly one of dev_name, uuid or
|
||||
* device number. String arguments are duplicated, see above.
|
||||
*/
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name);
|
||||
|
||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
|
||||
|
||||
@@ -109,7 +112,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
|
||||
/* Set debug level for logging, and whether to log on stdout/stderr or syslog */
|
||||
void dm_event_log_set(int debug_log_level, int use_syslog);
|
||||
|
||||
/* Log messages acroding to current debug level */
|
||||
/* Log messages according to current debug level */
|
||||
__attribute__((format(printf, 6, 0)))
|
||||
void dm_event_log(const char *subsys, int level, const char *file,
|
||||
int line, int dm_errno_or_class,
|
||||
|
@@ -87,7 +87,7 @@ int dmeventd_lvm2_init(void)
|
||||
lvm2_disable_dmeventd_monitoring(_lvm_handle);
|
||||
/* FIXME Temporary: move to dmeventd core */
|
||||
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||
log_debug("lvm plugin initilized.");
|
||||
log_debug("lvm plugin initialized.");
|
||||
}
|
||||
|
||||
_register_count++;
|
||||
@@ -103,7 +103,7 @@ void dmeventd_lvm2_exit(void)
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
if (!--_register_count) {
|
||||
log_debug("lvm plugin shuting down.");
|
||||
log_debug("lvm plugin shutting down.");
|
||||
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||
dm_pool_destroy(_mem_pool);
|
||||
_mem_pool = NULL;
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#ifndef _DMEVENTD_LVMWRAP_H
|
||||
#define _DMEVENTD_LVMWRAP_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct dm_pool;
|
||||
|
||||
int dmeventd_lvm2_init(void);
|
||||
|
@@ -38,7 +38,7 @@ static void _process_status_code(dm_status_mirror_health_t health,
|
||||
* A => Alive - No failures
|
||||
* D => Dead - A write failure occurred leaving mirror out-of-sync
|
||||
* F => Flush failed.
|
||||
* S => Sync - A sychronization failure occurred, mirror out-of-sync
|
||||
* S => Sync - A synchronization failure occurred, mirror out-of-sync
|
||||
* R => Read - A read failure occurred, mirror data unaffected
|
||||
* U => Unclassified failure (bug)
|
||||
*/
|
||||
@@ -112,7 +112,7 @@ static int _remove_failed_devices(const char *cmd_lvconvert, const char *device)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
struct dso_state *state = *user;
|
||||
|
@@ -17,7 +17,7 @@
|
||||
#include "daemons/dmeventd/libdevmapper-event.h"
|
||||
#include "lib/config/defaults.h"
|
||||
|
||||
/* Hold enough elements for the mximum number of RAID images */
|
||||
/* Hold enough elements for the maximum number of RAID images */
|
||||
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
|
||||
|
||||
struct dso_state {
|
||||
@@ -84,7 +84,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
*/
|
||||
if (!state->warned && status->insync_regions < status->total_regions) {
|
||||
state->warned = 1;
|
||||
log_warn("WARNING: waiting for resynchronization to finish "
|
||||
log_warn("WARNING: Waiting for resynchronization to finish "
|
||||
"before initiating repair on RAID device %s.", device);
|
||||
/* Fall through to allow lvconvert to run. */
|
||||
}
|
||||
@@ -114,7 +114,7 @@ out:
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
struct dso_state *state = *user;
|
||||
|
@@ -163,7 +163,7 @@ static void _umount(const char *device, int major, int minor)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
struct dso_state *state = *user;
|
||||
|
@@ -45,10 +45,10 @@
|
||||
|
||||
struct dso_state {
|
||||
struct dm_pool *mem;
|
||||
int metadata_percent_check;
|
||||
int metadata_percent;
|
||||
int data_percent_check;
|
||||
int data_percent;
|
||||
dm_percent_t metadata_percent_check;
|
||||
dm_percent_t metadata_percent;
|
||||
dm_percent_t data_percent_check;
|
||||
dm_percent_t data_percent;
|
||||
uint64_t known_metadata_size;
|
||||
uint64_t known_data_size;
|
||||
unsigned fails;
|
||||
@@ -87,7 +87,7 @@ static int _run_command(struct dso_state *state)
|
||||
log_verbose("Executing command: %s", state->cmd_str);
|
||||
|
||||
/* TODO:
|
||||
* Support parallel run of 'task' and it's waitpid maintainence
|
||||
* Support parallel run of 'task' and it's waitpid maintenance
|
||||
* ATM we can't handle signaling of SIGALRM
|
||||
* as signalling is not allowed while 'process_event()' is running
|
||||
*/
|
||||
@@ -155,7 +155,7 @@ static int _wait_for_pid(struct dso_state *state)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask,
|
||||
void **user)
|
||||
{
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
@@ -179,7 +179,7 @@ void process_event(struct dm_task *dmt,
|
||||
return;
|
||||
}
|
||||
|
||||
if (event & DM_EVENT_DEVICE_ERROR) {
|
||||
if (evmask & DM_EVENT_DEVICE_ERROR) {
|
||||
/* Error -> no need to check and do instant resize */
|
||||
state->data_percent = state->metadata_percent = 0;
|
||||
if (_use_policy(dmt, state))
|
||||
@@ -223,10 +223,12 @@ void process_event(struct dm_task *dmt,
|
||||
}
|
||||
|
||||
#if THIN_DEBUG
|
||||
log_debug("Thin pool status " FMTu64 "/" FMTu64 " "
|
||||
FMTu64 "/" FMTu64 ".",
|
||||
log_debug("Thin pool status " FMTu64 "/" FMTu64 " (" FMTu64 ") "
|
||||
FMTu64 "/" FMTu64 " (" FMTu64").",
|
||||
tps->used_data_blocks, tps->total_data_blocks,
|
||||
state->known_data_size,
|
||||
tps->used_metadata_blocks, tps->total_metadata_blocks,
|
||||
tps->used_data_blocks, tps->total_data_blocks);
|
||||
state->known_metadata_size);
|
||||
#endif
|
||||
|
||||
/* Thin pool size had changed. Clear the threshold. */
|
||||
@@ -245,7 +247,7 @@ void process_event(struct dm_task *dmt,
|
||||
/*
|
||||
* Trigger action when threshold boundary is exceeded.
|
||||
* Report 80% threshold warning when it's used above 80%.
|
||||
* Only 100% is exception as it cannot be surpased so policy
|
||||
* Only 100% is exception as it cannot be surpassed so policy
|
||||
* action is called for: >50%, >55% ... >95%, 100%
|
||||
*/
|
||||
state->metadata_percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
|
||||
@@ -379,14 +381,13 @@ int register_device(const char *device,
|
||||
|
||||
state->argv[1] = str + 1; /* 1 argument - vg/lv */
|
||||
_init_thread_signals(state);
|
||||
} else /* Unuspported command format */
|
||||
} else /* Unsupported command format */
|
||||
goto inval;
|
||||
|
||||
state->max_fails = 1;
|
||||
state->pid = -1;
|
||||
*user = state;
|
||||
|
||||
log_info("Monitoring thin pool %s.", device);
|
||||
|
||||
return 1;
|
||||
inval:
|
||||
log_error("Invalid command for monitoring: %s.", cmd_str);
|
||||
@@ -430,7 +431,6 @@ int unregister_device(const char *device,
|
||||
_restore_thread_signals(state);
|
||||
|
||||
dmeventd_lvm2_exit_with_pool(state);
|
||||
log_info("No longer monitoring thin pool %s.", device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
/*
|
||||
* 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
|
||||
* in runtime we are linked against systems libdm 'older' library
|
||||
* which does not provide this symbol and plugin fails to load
|
||||
*/
|
||||
/* coverity[unnecessary_header] used for parsing */
|
||||
@@ -78,7 +78,7 @@ static int _run_command(struct dso_state *state)
|
||||
log_verbose("Executing command: %s", state->cmd_str);
|
||||
|
||||
/* TODO:
|
||||
* Support parallel run of 'task' and it's waitpid maintainence
|
||||
* Support parallel run of 'task' and it's waitpid maintenance
|
||||
* ATM we can't handle signaling of SIGALRM
|
||||
* as signalling is not allowed while 'process_event()' is running
|
||||
*/
|
||||
@@ -146,7 +146,7 @@ static int _wait_for_pid(struct dso_state *state)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
@@ -169,7 +169,7 @@ void process_event(struct dm_task *dmt,
|
||||
return;
|
||||
}
|
||||
|
||||
if (event & DM_EVENT_DEVICE_ERROR) {
|
||||
if (evmask & DM_EVENT_DEVICE_ERROR) {
|
||||
#if VDO_DEBUG
|
||||
log_debug("VDO event error.");
|
||||
#endif
|
||||
@@ -227,7 +227,7 @@ void process_event(struct dm_task *dmt,
|
||||
/*
|
||||
* Trigger action when threshold boundary is exceeded.
|
||||
* Report 80% threshold warning when it's used above 80%.
|
||||
* Only 100% is exception as it cannot be surpased so policy
|
||||
* Only 100% is exception as it cannot be surpassed so policy
|
||||
* action is called for: >50%, >55% ... >95%, 100%
|
||||
*/
|
||||
if ((state->percent > WARNING_THRESH) &&
|
||||
@@ -354,7 +354,7 @@ int register_device(const char *device,
|
||||
_init_thread_signals(state);
|
||||
} else if (cmd[0] == 0) {
|
||||
state->name = "volume"; /* What to use with 'others?' */
|
||||
} else/* Unuspported command format */
|
||||
} else/* Unsupported command format */
|
||||
goto inval;
|
||||
|
||||
state->pid = -1;
|
||||
|
@@ -160,6 +160,8 @@ def call_lvm(command, debug=False, line_cb=None,
|
||||
|
||||
# Check to see if process has terminated, None when running
|
||||
if process.poll() is not None:
|
||||
stdout_text += read_decoded(process.stdout)
|
||||
stderr_text += read_decoded(process.stderr)
|
||||
break
|
||||
except IOError as ioe:
|
||||
log_debug("call_lvm:" + str(ioe))
|
||||
@@ -552,6 +554,14 @@ def lv_vdo_deduplication(lv_path, enable, dedup_options):
|
||||
return call(cmd)
|
||||
|
||||
|
||||
def lv_raid_repair(lv_path, new_pvs, repair_options):
|
||||
cmd = ['lvconvert', '-y', '--repair']
|
||||
cmd.append(lv_path)
|
||||
cmd.extend(new_pvs)
|
||||
cmd.extend(options_to_cli_args(repair_options))
|
||||
return call(cmd)
|
||||
|
||||
|
||||
def supports_json():
|
||||
cmd = ['help']
|
||||
rc, out, err = call(cmd)
|
||||
|
@@ -67,7 +67,7 @@ def lvs_state_retrieve(selection, cache_refresh=True):
|
||||
|
||||
try:
|
||||
# When building up the model, it's best to process LVs with the least
|
||||
# dependencies to those that are dependant upon other LVs. Otherwise, when
|
||||
# dependencies to those that are dependent upon other LVs. Otherwise, when
|
||||
# we are trying to gather information we could be in a position where we
|
||||
# don't have information available yet.
|
||||
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
|
||||
@@ -795,6 +795,39 @@ class Lv(LvCommon):
|
||||
cache_options), cb, cbe)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
@staticmethod
|
||||
def _repair_raid_lv(lv_uuid, lv_name, new_pvs, repair_options):
|
||||
# Make sure we have a dbus object representing it
|
||||
pv_dests = []
|
||||
dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
||||
|
||||
# If we have PVs, verify them
|
||||
if len(new_pvs):
|
||||
for pv in new_pvs:
|
||||
pv_dbus_obj = cfg.om.get_object_by_path(pv)
|
||||
if not pv_dbus_obj:
|
||||
raise dbus.exceptions.DBusException(
|
||||
LV_INTERFACE,
|
||||
'PV Destination (%s) not found' % pv)
|
||||
|
||||
pv_dests.append(pv_dbus_obj.lvm_id)
|
||||
|
||||
LvCommon.handle_execute(*cmdhandler.lv_raid_repair(
|
||||
dbo.lvm_id, pv_dests, repair_options))
|
||||
return "/"
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=LV_INTERFACE,
|
||||
in_signature='aoia{sv}',
|
||||
out_signature='o',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
def RepairRaidLv(self, new_pvs, tmo, repair_options, cb, cbe):
|
||||
r = RequestEntry(
|
||||
tmo, Lv._repair_raid_lv,
|
||||
(self.Uuid, self.lvm_id, new_pvs,
|
||||
repair_options), cb, cbe, return_tuple=False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@utils.dbus_property(VDO_POOL_INTERFACE, 'OperatingMode', 's')
|
||||
|
@@ -351,7 +351,7 @@ class DataStore(object):
|
||||
else:
|
||||
rc = []
|
||||
for s in pv_name:
|
||||
# Ths user could be using a symlink instead of the actual
|
||||
# The user could be using a symlink instead of the actual
|
||||
# block device, make sure we are using actual block device file
|
||||
# if the pv name isn't in the lookup
|
||||
if s not in self.pv_path_to_uuid:
|
||||
|
@@ -133,7 +133,7 @@ def process_args():
|
||||
|
||||
def running_under_systemd():
|
||||
""""
|
||||
Checks to see if we are running under systemd, by checking damon fd 0, 1
|
||||
Checks to see if we are running under systemd, by checking daemon fd 0, 1
|
||||
systemd sets stdin to /dev/null and 1 & 2 are a socket
|
||||
"""
|
||||
base = "/proc/self/fd"
|
||||
@@ -214,7 +214,7 @@ def main():
|
||||
cfg.loop = GLib.MainLoop()
|
||||
|
||||
for thread in thread_list:
|
||||
thread.damon = True
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
# In all cases we are going to monitor for udev until we get an
|
||||
|
@@ -160,7 +160,7 @@ class ObjectManager(AutomatedProperties):
|
||||
# (path, dbus_object.lvm_id))
|
||||
|
||||
# We want fast access to the object by a number of different ways,
|
||||
# so we use multiple hashs with different keys
|
||||
# so we use multiple hashes with different keys
|
||||
self._lookup_add(dbus_object, path, dbus_object.lvm_id,
|
||||
dbus_object.Uuid)
|
||||
|
||||
@@ -272,7 +272,7 @@ class ObjectManager(AutomatedProperties):
|
||||
For a given lvm asset return the dbus object path registered for it.
|
||||
This method first looks up by uuid and then by lvm_id. You
|
||||
can search by just one by setting uuid == lvm_id (uuid or lvm_id).
|
||||
If the object is not found and path_create is a not None, the
|
||||
If the object is not found and path_create is not None, the
|
||||
path_create function will be called to create a new object path and
|
||||
register it with the object manager for the specified uuid & lvm_id.
|
||||
Note: If path create is not None, uuid and lvm_id cannot be equal
|
||||
@@ -295,7 +295,7 @@ class ObjectManager(AutomatedProperties):
|
||||
if uuid == lvm_id:
|
||||
path = self._id_lookup(lvm_id)
|
||||
else:
|
||||
# We have an uuid and a lvm_id we can do sanity checks to ensure
|
||||
# We have a uuid and an lvm_id we can do sanity checks to ensure
|
||||
# that they are consistent
|
||||
|
||||
# If a PV is missing its device path is '[unknown]' or some
|
||||
|
@@ -15,7 +15,7 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SOURCES = lvmlockd-core.c
|
||||
SOURCES = lvmlockd-core.c lvmlockd-helper.c
|
||||
SOURCES2 = lvmlockctl.c
|
||||
|
||||
TARGETS = lvmlockd lvmlockctl
|
||||
@@ -50,8 +50,7 @@ INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||
|
||||
ifneq (,$(firstword $(LIBSYSTEMD_LIBS)))
|
||||
DEFS += -DUSE_SD_NOTIFY
|
||||
ifeq ("@SD_NOTIFY_SUPPORT@", "yes")
|
||||
CFLAGS += $(LIBSYSTEMD_CFLAGS)
|
||||
LIBS += $(LIBSYSTEMD_LIBS)
|
||||
endif
|
||||
|
@@ -38,7 +38,7 @@ static int stop_lockspaces = 0;
|
||||
static char *arg_vg_name = NULL;
|
||||
|
||||
#define DUMP_SOCKET_NAME "lvmlockd-dump.sock"
|
||||
#define DUMP_BUF_SIZE (1024 * 1024)
|
||||
#define DUMP_BUF_SIZE (4 * 1024 * 1024)
|
||||
static char dump_buf[DUMP_BUF_SIZE+1];
|
||||
static int dump_len;
|
||||
static struct sockaddr_un dump_addr;
|
||||
@@ -67,6 +67,160 @@ do { \
|
||||
syslog(LOG_WARNING, fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Like sscanf, but requires buffer size to be specified
|
||||
* for storing scanned strings, e.g.
|
||||
*
|
||||
* szscanf("%s", sizeof(buf), buf);
|
||||
*
|
||||
* Up to size-1 input bytes will be copied into buf.
|
||||
* A null byte will be written to buf following the
|
||||
* last copied byte. When nothing is copied to buf,
|
||||
* no terminating null byte is written.
|
||||
*
|
||||
* If an input string matching %s is too long for the
|
||||
* specified buffer size, the characters that would have
|
||||
* been copied are ignored.
|
||||
*
|
||||
* Only recognizes: %d, %u, %s.
|
||||
*/
|
||||
static int szscanf(const char *input, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
const char *fm;
|
||||
const char *in;
|
||||
int matched = 0;
|
||||
int n;
|
||||
|
||||
va_start(args, format);
|
||||
fm = format;
|
||||
in = input;
|
||||
|
||||
while (*fm != '\0') {
|
||||
|
||||
/*
|
||||
* format is a string containing:
|
||||
* 1. %d matching int from input
|
||||
* %u matching unsigned int from input
|
||||
* %s matching non-whitespace characters from input
|
||||
* 2. whitespace chars matching zero or more whitespace
|
||||
* characters from input
|
||||
* 3. non-whitespace chars matching the same input chars
|
||||
*/
|
||||
|
||||
if (*fm == '%') {
|
||||
/*
|
||||
* case 1: %u, %d, or %s
|
||||
*/
|
||||
|
||||
/* advance past '%' character, to look for 'u', 'd' or 's' */
|
||||
fm++;
|
||||
|
||||
if (*fm == 'd') {
|
||||
/*
|
||||
* read an int (%d)
|
||||
*/
|
||||
int *dest = va_arg(args, int *);
|
||||
|
||||
if (sscanf(in, "%d%n", dest, &n) == 1) {
|
||||
in += n;
|
||||
matched++;
|
||||
} else {
|
||||
/* matching failure: no input int */
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (*fm == 'u') {
|
||||
/*
|
||||
* read an unsigned int (%u)
|
||||
*/
|
||||
unsigned int *dest = va_arg(args, unsigned int *);
|
||||
|
||||
if (sscanf(in, "%u%n", dest, &n) == 1) {
|
||||
in += n;
|
||||
matched++;
|
||||
} else {
|
||||
/* matching failure: no input unsigned int */
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (*fm == 's') {
|
||||
/*
|
||||
* read a string (%s) into dest buffer with dest_size
|
||||
* copy up to dest_size-1 characters into dest buffer
|
||||
* write null byte into dest buffer following the last
|
||||
* character copied. When dest_size-1 bytes are copied,
|
||||
* the null byte is written into the final byte of the
|
||||
* dest buffer. input bytes that would have been copied
|
||||
* but did not fit in the dest buffer are skipped.
|
||||
*/
|
||||
size_t dest_size = va_arg(args, size_t);
|
||||
char *dest = va_arg(args, char *);
|
||||
char *out = dest;
|
||||
|
||||
/* don't copy leading input whitespace to dest */
|
||||
while (isspace((unsigned char)*in))
|
||||
in++;
|
||||
|
||||
/* copy non-whitespace characters from input to dest */
|
||||
n = 0;
|
||||
while (*in != '\0' && !isspace((unsigned char)*in) && (n < (int)dest_size-1)) {
|
||||
*out = *in;
|
||||
out++;
|
||||
in++;
|
||||
n++;
|
||||
}
|
||||
if (n) {
|
||||
dest[n] = '\0';
|
||||
matched++;
|
||||
} else {
|
||||
/* matching failure: no input string chars */
|
||||
break;
|
||||
}
|
||||
|
||||
/* ignore input bytes that would have been copied but didn't fit */
|
||||
while (*in != '\0' && !isspace((unsigned char)*in))
|
||||
in++;
|
||||
|
||||
} else {
|
||||
/* unsupported format specifier */
|
||||
matched = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* advance past 'd', 'u', or 's' character */
|
||||
fm++;
|
||||
|
||||
} else if (isspace((unsigned char)*fm)) {
|
||||
/*
|
||||
* case 2: format whitespace skips zero or more input
|
||||
* whitespace characters
|
||||
*/
|
||||
while (isspace((unsigned char)*in))
|
||||
in++;
|
||||
|
||||
/* advance past whitespace character */
|
||||
fm++;
|
||||
|
||||
} else if (*fm == *in) {
|
||||
/*
|
||||
* case 3: literal character match between format and input
|
||||
*/
|
||||
fm++;
|
||||
in++;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* matching failure: format and input don't match
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return matched;
|
||||
}
|
||||
|
||||
#define MAX_LINE 512
|
||||
|
||||
/* copied from lvmlockd-internal.h */
|
||||
@@ -97,8 +251,11 @@ static void save_client_info(char *line)
|
||||
uint32_t client_id = 0;
|
||||
char name[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
|
||||
&pid, &fd, &pi, &client_id, name);
|
||||
/* info=client pid=%u fd=%d pi=%d id=%u name=%s */
|
||||
|
||||
if (szscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
|
||||
&pid, &fd, &pi, &client_id, sizeof(name), name) < 0)
|
||||
return;
|
||||
|
||||
clients[num_clients].client_id = client_id;
|
||||
clients[num_clients].pid = pid;
|
||||
@@ -126,20 +283,26 @@ static void format_info_ls(char *line)
|
||||
char ls_name[MAX_NAME+1] = { 0 };
|
||||
char vg_name[MAX_NAME+1] = { 0 };
|
||||
char vg_uuid[MAX_NAME+1] = { 0 };
|
||||
char vg_sysid[MAX_NAME+1] = { 0 };
|
||||
char lock_args[MAX_ARGS+1] = { 0 };
|
||||
char lock_type[MAX_NAME+1] = { 0 };
|
||||
char vg_args[MAX_ARGS+1] = { 0 };
|
||||
char lm_type[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_sysid=%s vg_args=%s lm_type=%s",
|
||||
ls_name, vg_name, vg_uuid, vg_sysid, lock_args, lock_type);
|
||||
/* info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s */
|
||||
|
||||
if (szscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s",
|
||||
sizeof(ls_name), ls_name,
|
||||
sizeof(vg_name), vg_name,
|
||||
sizeof(vg_uuid), vg_uuid,
|
||||
sizeof(vg_args), vg_args,
|
||||
sizeof(lm_type), lm_type) < 0)
|
||||
return;
|
||||
|
||||
if (!first_ls)
|
||||
printf("\n");
|
||||
first_ls = 0;
|
||||
|
||||
printf("VG %s lock_type=%s %s\n", vg_name, lock_type, vg_uuid);
|
||||
printf("VG %s lock_type=%s %s\n", vg_name, lm_type, vg_uuid);
|
||||
|
||||
printf("LS %s %s\n", lock_type, ls_name);
|
||||
printf("LS %s %s\n", lm_type, ls_name);
|
||||
}
|
||||
|
||||
static void format_info_ls_action(char *line)
|
||||
@@ -151,8 +314,14 @@ static void format_info_ls_action(char *line)
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=ls_action client_id=%u %s %s op=%s",
|
||||
&client_id, flags, version, op);
|
||||
/* info=ls_action client_id=%u flags=%s version=%u op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d */
|
||||
|
||||
if (szscanf(line, "info=ls_action client_id=%u flags=%s version=%s op=%s",
|
||||
&client_id,
|
||||
sizeof(flags), flags,
|
||||
sizeof(version), version,
|
||||
sizeof(op), op) < 0)
|
||||
return;
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
@@ -164,11 +333,18 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
|
||||
char r_name[MAX_NAME+1] = { 0 };
|
||||
char r_type[4] = { 0 };
|
||||
char mode[4] = { 0 };
|
||||
char sh_count[MAX_NAME+1] = { 0 };
|
||||
uint32_t ver = 0;
|
||||
int sh_count = 0;
|
||||
unsigned int ver = 0;
|
||||
|
||||
(void) sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
|
||||
r_name, r_type, mode, sh_count, &ver);
|
||||
/* info=r name=%s type=%s mode=%s sh_count=%d version=%s */
|
||||
|
||||
if (szscanf(line, "info=r name=%s type=%s mode=%s sh_count=%d version=%u",
|
||||
sizeof(r_name), r_name,
|
||||
sizeof(r_type), r_type,
|
||||
sizeof(mode), mode,
|
||||
&sh_count,
|
||||
&ver) < 0)
|
||||
return;
|
||||
|
||||
strcpy(r_name_out, r_name);
|
||||
strcpy(r_type_out, r_type);
|
||||
@@ -193,8 +369,8 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
|
||||
static void format_info_lk(char *line, char *r_name, char *r_type)
|
||||
{
|
||||
char mode[4] = { 0 };
|
||||
uint32_t ver = 0;
|
||||
char flags[MAX_NAME+1] = { 0 };
|
||||
uint32_t ver = 0;
|
||||
uint32_t client_id = 0;
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
@@ -205,8 +381,14 @@ static void format_info_lk(char *line, char *r_name, char *r_type)
|
||||
return;
|
||||
}
|
||||
|
||||
(void) sscanf(line, "info=lk mode=%s version=%u %s client_id=%u",
|
||||
mode, &ver, flags, &client_id);
|
||||
/* info=lk mode=%s version=%s flags=%s client_id=%u */
|
||||
|
||||
if (szscanf(line, "info=lk mode=%s version=%u flags=%s client_id=%u",
|
||||
sizeof(mode), mode,
|
||||
&ver,
|
||||
sizeof(flags), flags,
|
||||
&client_id) < 0)
|
||||
return;
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
@@ -229,9 +411,9 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
char op[MAX_NAME+1] = { 0 };
|
||||
char rt[4] = { 0 };
|
||||
char mode[4] = { 0 };
|
||||
char lm[MAX_NAME+1] = { 0 };
|
||||
char result[MAX_NAME+1] = { 0 };
|
||||
char lm_rv[MAX_NAME+1] = { 0 };
|
||||
char lm_type[MAX_NAME+1] = { 0 };
|
||||
int result = 0;
|
||||
int lm_rv = 0;
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
|
||||
@@ -241,8 +423,19 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
return;
|
||||
}
|
||||
|
||||
(void) sscanf(line, "info=r_action client_id=%u %s %s op=%s rt=%s mode=%s %s %s %s",
|
||||
&client_id, flags, version, op, rt, mode, lm, result, lm_rv);
|
||||
/* info=r_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d */
|
||||
|
||||
if (szscanf(line, "info=r_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d",
|
||||
&client_id,
|
||||
sizeof(flags), flags,
|
||||
sizeof(version), version,
|
||||
sizeof(op), op,
|
||||
sizeof(rt), rt,
|
||||
sizeof(mode), mode,
|
||||
sizeof(lm_type), lm_type,
|
||||
&result,
|
||||
&lm_rv) < 0)
|
||||
return;
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket"
|
||||
#define LVMLOCKD_ADOPT_FILE DEFAULT_RUN_DIR "/lvmlockd.adopt"
|
||||
|
||||
#define LVMLOCKD_USE_SANLOCK_LVB 0
|
||||
|
||||
/* Wrappers to open/close connection */
|
||||
|
||||
static inline __attribute__((always_inline))
|
||||
@@ -52,5 +54,17 @@ static inline void lvmlockd_close(daemon_handle h)
|
||||
#define EREMOVED 219
|
||||
#define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */
|
||||
#define ELMERR 221
|
||||
#define EORPHAN 222
|
||||
#define EADOPT_NONE 223
|
||||
#define EADOPT_RETRY 224
|
||||
#define EIOTIMEOUT 225
|
||||
#define ELOCKREPAIR 226
|
||||
|
||||
#define LOCKARGS_VERSION 0x00000001 /* meta only */
|
||||
#define LOCKARGS_LVMLOCK 0x00000002 /* meta only */
|
||||
#define LOCKARGS_TIMEOUT 0x00000004 /* user only */
|
||||
#define LOCKARGS_NOTIMEOUT 0x00000008 /* meta or user */
|
||||
#define LOCKARGS_PERSIST 0x00000010 /* meta or user */
|
||||
#define LOCKARGS_NOPERSIST 0x00000020 /* user only */
|
||||
|
||||
#endif /* _LVM_LVMLOCKD_CLIENT_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "daemon-server.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <errno.h>
|
||||
#include <endian.h>
|
||||
#include <fcntl.h>
|
||||
#include <byteswap.h>
|
||||
#include <syslog.h>
|
||||
#include <dirent.h>
|
||||
|
||||
@@ -77,7 +76,7 @@ static int check_args_version(char *vg_args)
|
||||
unsigned int major = 0;
|
||||
int rv;
|
||||
|
||||
rv = version_from_args(vg_args, &major, NULL, NULL);
|
||||
rv = lockd_lockargs_get_version(vg_args, &major, NULL, NULL);
|
||||
if (rv < 0) {
|
||||
log_error("check_args_version %s error %d", vg_args, rv);
|
||||
return rv;
|
||||
@@ -169,8 +168,10 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls)
|
||||
struct lm_dlm *lmd;
|
||||
int rv;
|
||||
|
||||
if (daemon_test)
|
||||
if (daemon_test) {
|
||||
log_debug("lm_prepare_lockspace_dlm test");
|
||||
goto skip_args;
|
||||
}
|
||||
|
||||
memset(sys_clustername, 0, sizeof(sys_clustername));
|
||||
memset(arg_clustername, 0, sizeof(arg_clustername));
|
||||
@@ -305,20 +306,27 @@ fail:
|
||||
return rv;
|
||||
}
|
||||
|
||||
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
|
||||
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
|
||||
{
|
||||
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
|
||||
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
|
||||
if (adopt)
|
||||
if (adopt_only || adopt_ok) {
|
||||
lmd->dh = dlm_open_lockspace(ls->name);
|
||||
else
|
||||
if (!lmd->dh && adopt_ok)
|
||||
lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
|
||||
if (!lmd->dh)
|
||||
log_error("add_lockspace_dlm adopt_only %d adopt_ok %d %s error",
|
||||
adopt_only, adopt_ok, ls->name);
|
||||
} else {
|
||||
lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
|
||||
if (!lmd->dh)
|
||||
log_error("add_lockspace_dlm %s error", ls->name);
|
||||
}
|
||||
|
||||
if (!lmd->dh) {
|
||||
log_error("add_lockspace_dlm %s adopt %d error", ls->name, adopt);
|
||||
free(lmd);
|
||||
ls->lm_data = NULL;
|
||||
return -1;
|
||||
@@ -354,7 +362,7 @@ int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
|
||||
int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
|
||||
{
|
||||
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
|
||||
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
|
||||
@@ -386,7 +394,7 @@ static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int wit
|
||||
r->name, strlen(r->name),
|
||||
0, NULL, NULL, NULL);
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s add_resource_dlm lock error %d", ls->name, r->name, rv);
|
||||
log_error("%s:%s add_resource_dlm lock error %d", ls->name, r->name, rv);
|
||||
return rv;
|
||||
}
|
||||
out:
|
||||
@@ -410,7 +418,7 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
|
||||
|
||||
rv = dlm_ls_unlock_wait(lmd->dh, lksb->sb_lkid, 0, lksb);
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
|
||||
log_error("%s:%s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
|
||||
}
|
||||
out:
|
||||
free(rdd->vb);
|
||||
@@ -465,7 +473,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
log_debug("S %s R %s adopt_dlm", ls->name, r->name);
|
||||
log_debug("%s:%s adopt_dlm", ls->name, r->name);
|
||||
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
@@ -484,19 +492,19 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
NULL, NULL);
|
||||
|
||||
if (rv == -1 && (errno == EAGAIN)) {
|
||||
log_debug("S %s R %s adopt_dlm adopt mode %d try other mode",
|
||||
log_debug("%s:%s adopt_dlm adopt mode %d try other mode",
|
||||
ls->name, r->name, ld_mode);
|
||||
rv = -EUCLEAN;
|
||||
rv = -EADOPT_RETRY;
|
||||
goto fail;
|
||||
}
|
||||
if (rv == -1 && (errno == ENOENT)) {
|
||||
log_debug("S %s R %s adopt_dlm adopt mode %d no lock",
|
||||
log_debug("%s:%s adopt_dlm adopt mode %d no lock",
|
||||
ls->name, r->name, ld_mode);
|
||||
rv = -ENOENT;
|
||||
rv = -EADOPT_NONE;
|
||||
goto fail;
|
||||
}
|
||||
if (rv < 0) {
|
||||
log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d",
|
||||
log_debug("%s:%s adopt_dlm mode %d flags %x error %d errno %d",
|
||||
ls->name, r->name, mode, flags, rv, errno);
|
||||
goto fail;
|
||||
}
|
||||
@@ -526,7 +534,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
*/
|
||||
|
||||
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int adopt)
|
||||
struct val_blk *vb_out, int adopt_only, int adopt_ok)
|
||||
{
|
||||
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
|
||||
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
|
||||
@@ -536,7 +544,13 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
int mode;
|
||||
int rv;
|
||||
|
||||
if (adopt) {
|
||||
if (adopt_ok) {
|
||||
log_debug("%s:%s lock_dlm adopt_ok not supported", ls->name, r->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adopt_only) {
|
||||
log_debug("%s:%s lock_dlm adopt_only", ls->name, r->name);
|
||||
/* When adopting, we don't follow the normal method
|
||||
of acquiring a NL lock then converting it to the
|
||||
desired mode. */
|
||||
@@ -565,13 +579,13 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log_debug("S %s R %s lock_dlm", ls->name, r->name);
|
||||
log_debug("%s:%s lock_dlm", ls->name, r->name);
|
||||
|
||||
if (daemon_test) {
|
||||
if (rdd->vb) {
|
||||
vb_out->version = le16_to_cpu(rdd->vb->version);
|
||||
vb_out->flags = le16_to_cpu(rdd->vb->flags);
|
||||
vb_out->r_version = le32_to_cpu(rdd->vb->r_version);
|
||||
vb_out->version = le16toh(rdd->vb->version);
|
||||
vb_out->flags = le16toh(rdd->vb->flags);
|
||||
vb_out->r_version = le32toh(rdd->vb->r_version);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -585,7 +599,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
r->name, strlen(r->name),
|
||||
0, NULL, NULL, NULL);
|
||||
if (rv == -1) {
|
||||
log_debug("S %s R %s lock_dlm acquire mode PR for %d rv %d",
|
||||
log_debug("%s:%s lock_dlm acquire mode PR for %d rv %d",
|
||||
ls->name, r->name, mode, rv);
|
||||
goto lockrv;
|
||||
}
|
||||
@@ -598,17 +612,17 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
0, NULL, NULL, NULL);
|
||||
lockrv:
|
||||
if (rv == -1 && errno == EAGAIN) {
|
||||
log_debug("S %s R %s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
|
||||
log_debug("%s:%s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
|
||||
log_error("%s:%s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
|
||||
return -ELMERR;
|
||||
}
|
||||
|
||||
if (rdd->vb) {
|
||||
if (lksb->sb_flags & DLM_SBF_VALNOTVALID) {
|
||||
log_debug("S %s R %s lock_dlm VALNOTVALID", ls->name, r->name);
|
||||
log_debug("%s:%s lock_dlm VALNOTVALID", ls->name, r->name);
|
||||
memset(rdd->vb, 0, sizeof(struct val_blk));
|
||||
memset(vb_out, 0, sizeof(struct val_blk));
|
||||
goto out;
|
||||
@@ -623,9 +637,9 @@ lockrv:
|
||||
memcpy(&vb, lksb->sb_lvbptr, sizeof(struct val_blk));
|
||||
memcpy(rdd->vb, &vb, sizeof(vb));
|
||||
|
||||
vb_out->version = le16_to_cpu(vb.version);
|
||||
vb_out->flags = le16_to_cpu(vb.flags);
|
||||
vb_out->r_version = le32_to_cpu(vb.r_version);
|
||||
vb_out->version = le16toh(vb.version);
|
||||
vb_out->flags = le16toh(vb.flags);
|
||||
vb_out->r_version = le32toh(vb.r_version);
|
||||
}
|
||||
out:
|
||||
return 0;
|
||||
@@ -641,7 +655,7 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
uint32_t flags = 0;
|
||||
int rv;
|
||||
|
||||
log_debug("S %s R %s convert_dlm", ls->name, r->name);
|
||||
log_debug("%s:%s convert_dlm", ls->name, r->name);
|
||||
|
||||
flags |= LKF_CONVERT;
|
||||
flags |= LKF_NOQUEUE;
|
||||
@@ -650,12 +664,12 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
if (rdd->vb && r_version && (r->mode == LD_LK_EX)) {
|
||||
if (!rdd->vb->version) {
|
||||
/* first time vb has been written */
|
||||
rdd->vb->version = cpu_to_le16(VAL_BLK_VERSION);
|
||||
rdd->vb->version = htole16(VAL_BLK_VERSION);
|
||||
}
|
||||
rdd->vb->r_version = cpu_to_le32(r_version);
|
||||
rdd->vb->r_version = htole32(r_version);
|
||||
memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk));
|
||||
|
||||
log_debug("S %s R %s convert_dlm set r_version %u",
|
||||
log_debug("%s:%s convert_dlm set r_version %u",
|
||||
ls->name, r->name, r_version);
|
||||
|
||||
flags |= LKF_VALBLK;
|
||||
@@ -673,11 +687,11 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
0, NULL, NULL, NULL);
|
||||
if (rv == -1 && errno == EAGAIN) {
|
||||
/* FIXME: When does this happen? Should something different be done? */
|
||||
log_error("S %s R %s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
|
||||
log_error("%s:%s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s convert_dlm error %d", ls->name, r->name, rv);
|
||||
log_error("%s:%s convert_dlm error %d", ls->name, r->name, rv);
|
||||
rv = -ELMERR;
|
||||
}
|
||||
return rv;
|
||||
@@ -709,17 +723,17 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
memcpy(&vb_next, rdd->vb, sizeof(struct val_blk));
|
||||
|
||||
if (!vb_prev.version) {
|
||||
vb_next.version = cpu_to_le16(VAL_BLK_VERSION);
|
||||
vb_next.version = htole16(VAL_BLK_VERSION);
|
||||
new_vb = 1;
|
||||
}
|
||||
|
||||
if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) {
|
||||
vb_next.flags = cpu_to_le16(VBF_REMOVED);
|
||||
vb_next.flags = htole16(VBF_REMOVED);
|
||||
new_vb = 1;
|
||||
}
|
||||
|
||||
if (r_version) {
|
||||
vb_next.r_version = cpu_to_le32(r_version);
|
||||
vb_next.r_version = htole32(r_version);
|
||||
new_vb = 1;
|
||||
}
|
||||
|
||||
@@ -727,21 +741,21 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
memcpy(rdd->vb, &vb_next, sizeof(struct val_blk));
|
||||
memcpy(lksb->sb_lvbptr, &vb_next, sizeof(struct val_blk));
|
||||
|
||||
log_debug("S %s R %s unlock_dlm vb old %x %x %u new %x %x %u",
|
||||
log_debug("%s:%s unlock_dlm vb old %x %x %u new %x %x %u",
|
||||
ls->name, r->name,
|
||||
le16_to_cpu(vb_prev.version),
|
||||
le16_to_cpu(vb_prev.flags),
|
||||
le32_to_cpu(vb_prev.r_version),
|
||||
le16_to_cpu(vb_next.version),
|
||||
le16_to_cpu(vb_next.flags),
|
||||
le32_to_cpu(vb_next.r_version));
|
||||
le16toh(vb_prev.version),
|
||||
le16toh(vb_prev.flags),
|
||||
le32toh(vb_prev.r_version),
|
||||
le16toh(vb_next.version),
|
||||
le16toh(vb_next.flags),
|
||||
le32toh(vb_next.r_version));
|
||||
} else {
|
||||
log_debug("S %s R %s unlock_dlm vb unchanged", ls->name, r->name);
|
||||
log_debug("%s:%s unlock_dlm vb unchanged", ls->name, r->name);
|
||||
}
|
||||
|
||||
flags |= LKF_VALBLK;
|
||||
} else {
|
||||
log_debug("S %s R %s unlock_dlm", ls->name, r->name);
|
||||
log_debug("%s:%s unlock_dlm", ls->name, r->name);
|
||||
}
|
||||
|
||||
if (daemon_test)
|
||||
@@ -751,7 +765,7 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
r->name, strlen(r->name),
|
||||
0, NULL, NULL, NULL);
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s unlock_dlm error %d", ls->name, r->name, rv);
|
||||
log_error("%s:%s unlock_dlm error %d", ls->name, r->name, rv);
|
||||
rv = -ELMERR;
|
||||
}
|
||||
|
||||
@@ -784,6 +798,14 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
* the stale lockspaces on the others eventually.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* On error, returns < 0
|
||||
*
|
||||
* On success:
|
||||
* If other hosts are found, returns the number.
|
||||
* If no other hosts are found (only ourself), returns 0.
|
||||
*/
|
||||
|
||||
int lm_hosts_dlm(struct lockspace *ls, int notify)
|
||||
{
|
||||
char ls_nodes_path[PATH_MAX];
|
||||
|
264
daemons/lvmlockd/lvmlockd-helper.c
Normal file
264
daemons/lvmlockd/lvmlockd-helper.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright 2025 Red Hat, Inc.
|
||||
*
|
||||
* 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 v2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <grp.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
|
||||
struct list_head commands; /* helper_msg_list entries */
|
||||
|
||||
static int _log_stderr;
|
||||
|
||||
#define log_helper(fmt, args...) \
|
||||
do { \
|
||||
if (_log_stderr) \
|
||||
fprintf(stderr, fmt "\n", ##args); \
|
||||
} while (0)
|
||||
|
||||
static void _save_command(struct helper_msg *msg)
|
||||
{
|
||||
struct helper_msg_list *ml;
|
||||
|
||||
ml = malloc(sizeof(struct helper_msg_list));
|
||||
if (!ml)
|
||||
return;
|
||||
|
||||
memcpy(&ml->msg, msg, sizeof(struct helper_msg));
|
||||
list_add_tail(&ml->list, &commands);
|
||||
}
|
||||
|
||||
static struct helper_msg_list *_get_command(int pid)
|
||||
{
|
||||
struct helper_msg_list *ml;
|
||||
|
||||
list_for_each_entry(ml, &commands, list) {
|
||||
if (ml->msg.pid == pid)
|
||||
return ml;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int read_msg(int fd, struct helper_msg *msg)
|
||||
{
|
||||
int rv;
|
||||
retry:
|
||||
rv = read(fd, msg, sizeof(struct helper_msg));
|
||||
if (rv == -1 && errno == EINTR)
|
||||
goto retry;
|
||||
|
||||
if (rv != sizeof(struct helper_msg))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exec_command(char *cmd_str)
|
||||
{
|
||||
char arg[ONE_ARG_LEN];
|
||||
char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
|
||||
int av_count = 0;
|
||||
int i, arg_len, cmd_len;
|
||||
|
||||
for (i = 0; i < MAX_AV_COUNT + 1; i++)
|
||||
av[i] = NULL;
|
||||
|
||||
if (!cmd_str[0])
|
||||
return;
|
||||
|
||||
/* this should already be done, but make sure */
|
||||
cmd_str[RUN_COMMAND_LEN - 1] = '\0';
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg_len = 0;
|
||||
cmd_len = strlen(cmd_str);
|
||||
|
||||
for (i = 0; i < cmd_len; i++) {
|
||||
if (!cmd_str[i])
|
||||
break;
|
||||
|
||||
if (av_count == MAX_AV_COUNT)
|
||||
break;
|
||||
|
||||
if (cmd_str[i] == '\\') {
|
||||
if (i == (cmd_len - 1))
|
||||
break;
|
||||
i++;
|
||||
|
||||
if (cmd_str[i] == '\\') {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
continue;
|
||||
}
|
||||
if (isspace(cmd_str[i])) {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
} else if (isspace(cmd_str[i])) {
|
||||
if (arg_len)
|
||||
av[av_count++] = strdup(arg);
|
||||
|
||||
memset(arg, 0, sizeof(arg));
|
||||
arg_len = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((av_count < MAX_AV_COUNT) && arg_len) {
|
||||
av[av_count++] = strdup(arg);
|
||||
}
|
||||
|
||||
execvp(av[0], av);
|
||||
}
|
||||
|
||||
static int send_result(struct helper_msg *msg, int fd)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = write(fd, msg, sizeof(struct helper_msg));
|
||||
|
||||
if (rv == sizeof(struct helper_msg))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define IDLE_TIMEOUT_MS (30 * 1000)
|
||||
#define ACTIVE_TIMEOUT_MS 500
|
||||
|
||||
__attribute__((noreturn)) void helper_main(int in_fd, int out_fd, int log_stderr)
|
||||
{
|
||||
struct pollfd pollfd;
|
||||
struct helper_msg msg;
|
||||
struct helper_msg_list *ml;
|
||||
siginfo_t info;
|
||||
unsigned int fork_count = 0;
|
||||
unsigned int done_count = 0;
|
||||
int timeout = IDLE_TIMEOUT_MS;
|
||||
int rv, pid;
|
||||
|
||||
INIT_LIST_HEAD(&commands);
|
||||
|
||||
_log_stderr = log_stderr;
|
||||
|
||||
rv = setgroups(0, NULL);
|
||||
if (rv < 0)
|
||||
log_helper("error clearing helper groups errno %i", errno);
|
||||
|
||||
memset(&pollfd, 0, sizeof(pollfd));
|
||||
pollfd.fd = in_fd;
|
||||
pollfd.events = POLLIN;
|
||||
|
||||
openlog("lvmlockd-helper", LOG_CONS | LOG_PID, LOG_LOCAL4);
|
||||
|
||||
while (1) {
|
||||
rv = poll(&pollfd, 1, timeout);
|
||||
if (rv == -1 && errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (rv < 0)
|
||||
exit(0);
|
||||
|
||||
if (pollfd.revents & POLLIN) {
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
rv = read_msg(in_fd, &msg);
|
||||
if (rv)
|
||||
continue;
|
||||
|
||||
if (msg.type == HELPER_COMMAND) {
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
exec_command(msg.command);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
msg.pid = pid;
|
||||
|
||||
_save_command(&msg);
|
||||
|
||||
fork_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL))
|
||||
exit(0);
|
||||
|
||||
/* collect child exits until no more children exist (ECHILD)
|
||||
or none are ready (WNOHANG) */
|
||||
|
||||
while (1) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
rv = waitid(P_ALL, 0, &info, WEXITED | WNOHANG);
|
||||
|
||||
if ((rv < 0) && (errno == ECHILD)) {
|
||||
/*
|
||||
log_helper("helper no children exist fork_count %d done_count %d", fork_count, done_count);
|
||||
*/
|
||||
timeout = IDLE_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
else if (!rv && !info.si_pid) {
|
||||
log_helper("helper no children ready fork_count %d done_count %d", fork_count, done_count);
|
||||
timeout = ACTIVE_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
else if (!rv && info.si_pid) {
|
||||
done_count++;
|
||||
|
||||
if (!(ml = _get_command(info.si_pid))) {
|
||||
log_helper("command for pid %d result %d not found",
|
||||
info.si_pid, info.si_status);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_helper("command for pid %d result %d done", info.si_pid, info.si_status);
|
||||
|
||||
ml->msg.type = HELPER_COMMAND_RESULT;
|
||||
ml->msg.result = info.si_status;
|
||||
|
||||
send_result(&ml->msg, out_fd);
|
||||
|
||||
list_del(&ml->list);
|
||||
free(ml);
|
||||
continue;
|
||||
}
|
||||
|
||||
else {
|
||||
log_helper("helper waitid rv %d errno %d fork_count %d done_count %d",
|
||||
rv, errno, fork_count, done_count);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "daemon-server.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
@@ -136,7 +136,7 @@ static int lm_idm_scsi_directory_select(const struct dirent *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm_idm_scsi_find_block_dirctory(const char *block_path)
|
||||
static int lm_idm_scsi_find_block_directory(const char *block_path)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
@@ -252,7 +252,7 @@ static char *lm_idm_scsi_get_block_device_node(const char *scsi_path)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = lm_idm_scsi_find_block_dirctory(blk_path);
|
||||
ret = lm_idm_scsi_find_block_directory(blk_path);
|
||||
if (ret < 0) {
|
||||
log_error("Fail to find block path %s", blk_path);
|
||||
goto fail;
|
||||
@@ -364,7 +364,7 @@ static void lm_idm_update_vb_timestamp(uint64_t *vb_timestamp)
|
||||
|
||||
/*
|
||||
* It's possible that the multiple nodes have no clock
|
||||
* synchronization with microsecond prcision and the time
|
||||
* synchronization with microsecond precision and the time
|
||||
* is going backward. For this case, simply increment the
|
||||
* existing timestamp and write out to drive.
|
||||
*/
|
||||
@@ -391,7 +391,7 @@ int lm_prepare_lockspace_idm(struct lockspace *ls)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
|
||||
int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok)
|
||||
{
|
||||
char killpath[IDM_FAILURE_PATH_LEN];
|
||||
char killargs[IDM_FAILURE_ARGS_LEN];
|
||||
@@ -490,7 +490,7 @@ out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
|
||||
@@ -530,7 +530,7 @@ static int to_idm_mode(int ld_mode)
|
||||
|
||||
int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
|
||||
int adopt)
|
||||
int adopt_only, int adopt_ok)
|
||||
{
|
||||
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
@@ -556,9 +556,9 @@ int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
|
||||
if (daemon_test) {
|
||||
if (rdi->vb) {
|
||||
vb_out->version = le16_to_cpu(rdi->vb->version);
|
||||
vb_out->flags = le16_to_cpu(rdi->vb->flags);
|
||||
vb_out->r_version = le32_to_cpu(rdi->vb->r_version);
|
||||
vb_out->version = le16toh(rdi->vb->version);
|
||||
vb_out->flags = le16toh(rdi->vb->flags);
|
||||
vb_out->r_version = le32toh(rdi->vb->r_version);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@@ -13,6 +13,9 @@
|
||||
|
||||
#include "base/memory/container_of.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_NAME 64
|
||||
#define MAX_ARGS 64
|
||||
|
||||
@@ -59,6 +62,11 @@ enum {
|
||||
LD_OP_BUSY,
|
||||
LD_OP_QUERY_LOCK,
|
||||
LD_OP_REFRESH_LV,
|
||||
LD_OP_VG_STATUS,
|
||||
LD_OP_FENCE,
|
||||
LD_OP_FENCE_RESULT,
|
||||
LD_OP_SETLOCKARGS_BEFORE,
|
||||
LD_OP_SETLOCKARGS_FINAL,
|
||||
};
|
||||
|
||||
/* resource types */
|
||||
@@ -107,11 +115,15 @@ struct client {
|
||||
#define LD_AF_SEARCH_LS 0x00000200
|
||||
#define LD_AF_WAIT_STARTING 0x00001000
|
||||
#define LD_AF_DUP_GL_LS 0x00002000
|
||||
#define LD_AF_ADOPT 0x00010000
|
||||
#define LD_AF_ADOPT 0x00010000 /* adopt ok but not required */
|
||||
#define LD_AF_WARN_GL_REMOVED 0x00020000
|
||||
#define LD_AF_LV_LOCK 0x00040000
|
||||
#define LD_AF_LV_UNLOCK 0x00080000
|
||||
#define LD_AF_SH_EXISTS 0x00100000
|
||||
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
|
||||
#define LD_AF_NODELAY 0x00400000
|
||||
#define LD_AF_REPAIR 0x00800000
|
||||
#define LD_AF_NO_TIMEOUT 0x01000000
|
||||
|
||||
/*
|
||||
* Number of times to repeat a lock request after
|
||||
@@ -125,12 +137,53 @@ struct pvs {
|
||||
int num;
|
||||
};
|
||||
|
||||
#define RUN_COMMAND_LEN 1024
|
||||
#define MAX_AV_COUNT 32
|
||||
#define ONE_ARG_LEN 256
|
||||
|
||||
/* helper_msg types */
|
||||
#define HELPER_COMMAND 0x1
|
||||
#define HELPER_COMMAND_RESULT 0x2
|
||||
|
||||
struct helper_msg {
|
||||
uint8_t type;
|
||||
uint8_t act;
|
||||
uint16_t unused1;
|
||||
uint32_t msg_id;
|
||||
int pid;
|
||||
int result;
|
||||
char ls_name[MAX_NAME+1];
|
||||
uint8_t unused2;
|
||||
uint16_t unused3;
|
||||
char command[RUN_COMMAND_LEN];
|
||||
};
|
||||
|
||||
struct helper_msg_list {
|
||||
struct helper_msg msg;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define OWNER_NAME_SIZE 64
|
||||
#define OWNER_STATE_SIZE 32
|
||||
|
||||
struct owner {
|
||||
uint32_t host_id;
|
||||
uint32_t generation;
|
||||
uint32_t timestamp;
|
||||
char state[OWNER_STATE_SIZE];
|
||||
char name[OWNER_NAME_SIZE];
|
||||
};
|
||||
|
||||
struct action {
|
||||
struct list_head list;
|
||||
uint32_t client_id;
|
||||
uint32_t flags; /* LD_AF_ */
|
||||
uint32_t msg_id;
|
||||
uint32_t version;
|
||||
uint64_t host_id;
|
||||
uint32_t host_id;
|
||||
uint64_t ourkey;
|
||||
uint64_t remkey;
|
||||
uint64_t lv_size_bytes;
|
||||
int8_t op; /* operation type LD_OP_ */
|
||||
int8_t rt; /* resource type LD_RT_ */
|
||||
int8_t mode; /* lock mode LD_LK_ */
|
||||
@@ -139,6 +192,7 @@ struct action {
|
||||
int max_retries;
|
||||
int result;
|
||||
int lm_rv; /* return value from lm_ function */
|
||||
int align_mb;
|
||||
char *path;
|
||||
char vg_uuid[64];
|
||||
char vg_name[MAX_NAME+1];
|
||||
@@ -146,7 +200,8 @@ struct action {
|
||||
char lv_uuid[MAX_NAME+1];
|
||||
char vg_args[MAX_ARGS+1];
|
||||
char lv_args[MAX_ARGS+1];
|
||||
char vg_sysid[MAX_NAME+1];
|
||||
char other_args[MAX_ARGS+1];
|
||||
struct owner owner;
|
||||
struct pvs pvs; /* PV list for idm */
|
||||
};
|
||||
|
||||
@@ -159,12 +214,14 @@ struct resource {
|
||||
unsigned int sh_count; /* number of sh locks on locks list */
|
||||
uint32_t version;
|
||||
uint32_t last_client_id; /* last client_id to lock or unlock resource */
|
||||
uint32_t dispose_client_id; /* client_id disposing of resource struct */
|
||||
unsigned int lm_init : 1; /* lm_data is initialized */
|
||||
unsigned int adopt : 1; /* temp flag in remove_inactive_lvs */
|
||||
unsigned int version_zero_valid : 1;
|
||||
unsigned int use_vb : 1;
|
||||
struct list_head locks;
|
||||
struct list_head actions;
|
||||
struct list_head fence_wait_actions;
|
||||
char lv_args[MAX_ARGS+1];
|
||||
char lm_data[]; /* lock manager specific data */
|
||||
};
|
||||
@@ -185,13 +242,13 @@ struct lockspace {
|
||||
char vg_name[MAX_NAME+1];
|
||||
char vg_uuid[64];
|
||||
char vg_args[MAX_ARGS+1]; /* lock manager specific args */
|
||||
char vg_sysid[MAX_NAME+1];
|
||||
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
|
||||
void *lm_data;
|
||||
uint64_t host_id;
|
||||
uint32_t lock_args_flags;
|
||||
uint32_t host_id;
|
||||
uint64_t generation;
|
||||
uint64_t ourkey;
|
||||
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 */
|
||||
struct pvs pvs; /* for idm: PV list */
|
||||
|
||||
uint32_t start_client_id; /* client_id that started the lockspace */
|
||||
@@ -205,12 +262,14 @@ struct lockspace {
|
||||
unsigned int thread_done : 1;
|
||||
unsigned int sanlock_gl_enabled: 1;
|
||||
unsigned int sanlock_gl_dup: 1;
|
||||
unsigned int free_vg: 1;
|
||||
unsigned int kill_vg: 1;
|
||||
unsigned int drop_vg: 1;
|
||||
unsigned int fence_pr: 1;
|
||||
unsigned int no_timeout: 1;
|
||||
|
||||
struct list_head actions; /* new client actions */
|
||||
struct list_head resources; /* resource/lock state for gl/vg/lv */
|
||||
struct list_head dispose; /* resources to free */
|
||||
struct list_head fence_history; /* internally created actions for fencing */
|
||||
};
|
||||
|
||||
/* val_blk version */
|
||||
@@ -277,15 +336,15 @@ static inline int list_empty(const struct list_head *head)
|
||||
list_entry((ptr)->next, type, member)
|
||||
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
for (pos = list_entry((head)->next, __typeof__(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
pos = list_entry(pos->member.next, __typeof__(*pos), member))
|
||||
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
for (pos = list_entry((head)->next, __typeof__(*pos), member), \
|
||||
n = list_entry(pos->member.next, __typeof__(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
pos = n, n = list_entry(n->member.next, __typeof__(*n), member))
|
||||
|
||||
|
||||
/* to improve readability */
|
||||
@@ -369,7 +428,9 @@ void log_level(int level, const char *fmt, ...) __attribute__((format(printf, 2
|
||||
struct lockspace *alloc_lockspace(void);
|
||||
int lockspaces_empty(void);
|
||||
int last_string_from_args(char *args_in, char *last);
|
||||
int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsigned int *patch);
|
||||
void helper_main(int in_fd, int out_fd, int log_stderr);
|
||||
int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags);
|
||||
int lockd_lockargs_get_version(char *str, unsigned int *major, unsigned int *minor, unsigned int *patch);
|
||||
|
||||
static inline const char *mode_str(int x)
|
||||
{
|
||||
@@ -393,11 +454,12 @@ static inline const char *mode_str(int x)
|
||||
|
||||
int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
||||
int lm_prepare_lockspace_dlm(struct lockspace *ls);
|
||||
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt);
|
||||
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok);
|
||||
int lm_purge_locks_dlm(struct lockspace *ls);
|
||||
int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg);
|
||||
int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl);
|
||||
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int adopt);
|
||||
struct val_blk *vb_out, int adopt_only, int adopt_ok);
|
||||
int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version);
|
||||
int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
@@ -419,69 +481,102 @@ static inline int lm_support_dlm(void)
|
||||
|
||||
static inline int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_prepare_lockspace_dlm(struct lockspace *ls)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
|
||||
static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_purge_locks_dlm(struct lockspace *ls)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int adopt)
|
||||
struct val_blk *vb_out, int adopt_only, int adopt_ok)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
uint32_t r_version, uint32_t lmu_flags)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_data_size_dlm(void)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_is_running_dlm(void)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lm_support_dlm(void)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -504,15 +599,17 @@ static inline int lm_refresh_lv_check_dlm(struct action *act)
|
||||
|
||||
#ifdef LOCKDSANLOCK_SUPPORT
|
||||
|
||||
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, int sector_size, int align_size, uint64_t free_offset);
|
||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args);
|
||||
int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_args);
|
||||
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_prepare_lockspace_sanlock(struct lockspace *ls);
|
||||
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt);
|
||||
int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair);
|
||||
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay);
|
||||
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
|
||||
int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r);
|
||||
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int *retry, int adopt);
|
||||
struct val_blk *vb_out, int *retry, struct owner *owner,
|
||||
int adopt_only, int adopt_ok, int repair);
|
||||
int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version);
|
||||
int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
|
||||
@@ -525,7 +622,11 @@ int lm_gl_is_enabled(struct lockspace *ls);
|
||||
int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
|
||||
int lm_data_size_sanlock(void);
|
||||
int lm_is_running_sanlock(void);
|
||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size);
|
||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
|
||||
int lm_vg_status_sanlock(struct lockspace *ls, struct action *act);
|
||||
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner);
|
||||
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act);
|
||||
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act);
|
||||
|
||||
static inline int lm_support_sanlock(void)
|
||||
{
|
||||
@@ -534,12 +635,12 @@ static inline int lm_support_sanlock(void)
|
||||
|
||||
#else
|
||||
|
||||
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
||||
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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)
|
||||
static inline int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_args)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -554,12 +655,12 @@ static inline int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t fl
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
|
||||
static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt)
|
||||
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -569,8 +670,14 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int *retry, int adopt)
|
||||
struct val_blk *vb_out, int *retry, struct owner *owner,
|
||||
int adopt_only, int adopt_ok, int repair)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -627,7 +734,12 @@ static inline int lm_is_running_sanlock(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
|
||||
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_vg_status_sanlock(struct lockspace *ls, struct action *act)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -637,6 +749,20 @@ static inline int lm_support_sanlock(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
|
||||
{
|
||||
}
|
||||
|
||||
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* sanlock support */
|
||||
|
||||
#ifdef LOCKDIDM_SUPPORT
|
||||
@@ -644,11 +770,12 @@ static inline int lm_support_sanlock(void)
|
||||
int lm_data_size_idm(void);
|
||||
int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
||||
int lm_prepare_lockspace_idm(struct lockspace *ls);
|
||||
int lm_add_lockspace_idm(struct lockspace *ls, int adopt);
|
||||
int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok);
|
||||
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg);
|
||||
int lm_add_resource_idm(struct lockspace *ls, struct resource *r);
|
||||
int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
|
||||
int adopt);
|
||||
int adopt_only, int adopt_ok);
|
||||
int lm_convert_idm(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version);
|
||||
int lm_unlock_idm(struct lockspace *ls, struct resource *r,
|
||||
@@ -681,7 +808,7 @@ static inline int lm_prepare_lockspace_idm(struct lockspace *ls)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
|
||||
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -691,9 +818,14 @@ static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
|
||||
int adopt)
|
||||
int adopt_only, int adopt_ok)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@
|
||||
#include "lvmpolld-common.h"
|
||||
|
||||
#include "lvm-version.h"
|
||||
#include "daemon-server.h"
|
||||
#include "daemon-log.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "libdaemon/server/daemon-log.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
@@ -75,7 +75,7 @@ static void _usage(const char *prog, FILE *file)
|
||||
" -p|--pidfile Set path to the pidfile\n"
|
||||
" -s|--socket Set path to the communication socket\n"
|
||||
" -B|--binary Path to lvm2 binary\n"
|
||||
" -t|--timeout Time to wait in seconds before shutdown on idle (missing or 0 = inifinite)\n\n", prog, prog);
|
||||
" -t|--timeout Time to wait in seconds before shutdown on idle (missing or 0 = infinite)\n\n", prog, prog);
|
||||
}
|
||||
|
||||
static int _init(struct daemon_state *s)
|
||||
@@ -390,6 +390,11 @@ static void *fork_and_poll(void *args)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!pdlv->cmdargv || !*(pdlv->cmdargv)) {
|
||||
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "Missing command");
|
||||
goto err;
|
||||
}
|
||||
|
||||
DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "cmd line arguments:");
|
||||
debug_print(ls, pdlv->cmdargv);
|
||||
DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "---end---");
|
||||
|
@@ -46,7 +46,7 @@ static char *_construct_lvm_system_dir_env(const char *sysdir)
|
||||
* - or -
|
||||
* just single char to store NULL byte
|
||||
*/
|
||||
size_t l = sysdir ? strlen(sysdir) + 16 : 1;
|
||||
size_t l = sysdir ? strlen(sysdir) + sizeof(LVM_SYSTEM_DIR): 1;
|
||||
char *env = (char *) malloc(l * sizeof(char));
|
||||
|
||||
if (!env)
|
||||
@@ -89,6 +89,17 @@ char *construct_id(const char *sysdir, const char *uuid)
|
||||
return id;
|
||||
}
|
||||
|
||||
static void _free_lvmpolld_lv(struct lvmpolld_lv *p)
|
||||
{
|
||||
free((void *)p->devicesfile);
|
||||
free((void *)p->lvm_system_dir_env);
|
||||
free((void *)p->lvmpolld_id);
|
||||
free((void *)p->lvname);
|
||||
free((void *)p->sinterval);
|
||||
free((void *)p->cmdargv);
|
||||
free((void *)p->cmdenvp);
|
||||
}
|
||||
|
||||
struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
const char *vgname, const char *lvname,
|
||||
const char *sysdir, enum poll_type type,
|
||||
@@ -96,30 +107,26 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
struct lvmpolld_store *pdst,
|
||||
const char *devicesfile)
|
||||
{
|
||||
char *lvmpolld_id = strdup(id), /* copy */
|
||||
*full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
|
||||
*lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
|
||||
char *devicesfile_dup = devicesfile ? strdup(devicesfile) : NULL;
|
||||
|
||||
struct lvmpolld_lv tmp = {
|
||||
.ls = ls,
|
||||
.type = type,
|
||||
.lvmpolld_id = lvmpolld_id,
|
||||
.lvid = _get_lvid(lvmpolld_id, sysdir),
|
||||
.lvname = full_lvname,
|
||||
.devicesfile = devicesfile_dup,
|
||||
.lvm_system_dir_env = lvm_system_dir_env,
|
||||
.sinterval = strdup(sinterval), /* copy */
|
||||
.lvmpolld_id = strdup(id),
|
||||
.lvname = _construct_full_lvname(vgname, lvname),
|
||||
.devicesfile = devicesfile ? strdup(devicesfile) : NULL,
|
||||
.lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir),
|
||||
.sinterval = strdup(sinterval),
|
||||
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
|
||||
.cmd_state = { .retcode = -1, .signal = 0 },
|
||||
.pdst = pdst,
|
||||
.init_rq_count = 1
|
||||
}, *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.lvmpolld_id || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
|
||||
goto err;
|
||||
|
||||
memcpy(pdlv, &tmp, sizeof(*pdlv));
|
||||
tmp.lvid = _get_lvid(tmp.lvmpolld_id, sysdir),
|
||||
|
||||
*pdlv = tmp;
|
||||
|
||||
if (pthread_mutex_init(&pdlv->lock, NULL))
|
||||
goto err;
|
||||
@@ -127,29 +134,20 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
return pdlv;
|
||||
|
||||
err:
|
||||
free((void *)devicesfile_dup);
|
||||
free((void *)full_lvname);
|
||||
free((void *)lvmpolld_id);
|
||||
free((void *)lvm_system_dir_env);
|
||||
free((void *)tmp.sinterval);
|
||||
free((void *)pdlv);
|
||||
_free_lvmpolld_lv(&tmp);
|
||||
|
||||
free(pdlv);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pdlv_destroy(struct lvmpolld_lv *pdlv)
|
||||
{
|
||||
free((void *)pdlv->lvmpolld_id);
|
||||
free((void *)pdlv->devicesfile);
|
||||
free((void *)pdlv->lvname);
|
||||
free((void *)pdlv->sinterval);
|
||||
free((void *)pdlv->lvm_system_dir_env);
|
||||
free((void *)pdlv->cmdargv);
|
||||
free((void *)pdlv->cmdenvp);
|
||||
_free_lvmpolld_lv(pdlv);
|
||||
|
||||
pthread_mutex_destroy(&pdlv->lock);
|
||||
|
||||
free((void *)pdlv);
|
||||
free(pdlv);
|
||||
}
|
||||
|
||||
unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv)
|
||||
@@ -273,12 +271,12 @@ static void _pdlv_locked_dump(struct buffer *buff, const struct lvmpolld_lv *pdl
|
||||
buffer_append(buff, tmp);
|
||||
if (dm_snprintf(tmp, sizeof(tmp), "\t\tpolling_finished=%d\n", pdlv->polling_finished) > 0)
|
||||
buffer_append(buff, tmp);
|
||||
if (dm_snprintf(tmp, sizeof(tmp), "\t\terror_occured=%d\n", pdlv->error) > 0)
|
||||
if (dm_snprintf(tmp, sizeof(tmp), "\t\terror_occurred=%d\n", pdlv->error) > 0)
|
||||
buffer_append(buff, tmp);
|
||||
if (dm_snprintf(tmp, sizeof(tmp), "\t\tinit_requests_count=%d\n", pdlv->init_rq_count) > 0)
|
||||
buffer_append(buff, tmp);
|
||||
|
||||
/* lvm_commmand-section { */
|
||||
/* lvm_command-section { */
|
||||
buffer_append(buff, "\t\tlvm_command {\n");
|
||||
if (cmd_state->retcode == -1 && !cmd_state->signal)
|
||||
buffer_append(buff, "\t\t\tstate=\"" LVMPD_RESP_IN_PROGRESS "\"\n");
|
||||
@@ -290,7 +288,7 @@ static void _pdlv_locked_dump(struct buffer *buff, const struct lvmpolld_lv *pdl
|
||||
buffer_append(buff, tmp);
|
||||
}
|
||||
buffer_append(buff, "\t\t}\n");
|
||||
/* } lvm_commmand-section */
|
||||
/* } lvm_command-section */
|
||||
|
||||
buffer_append(buff, "\t}\n");
|
||||
/* } pdlv-section */
|
||||
|
@@ -15,7 +15,10 @@
|
||||
#ifndef _LVM_LVMPOLLD_DATA_UTILS_H
|
||||
#define _LVM_LVMPOLLD_DATA_UTILS_H
|
||||
|
||||
#include "base/data-struct/hash.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct buffer;
|
||||
struct lvmpolld_state;
|
||||
@@ -68,7 +71,7 @@ struct lvmpolld_lv {
|
||||
struct lvmpolld_cmd_stat cmd_state;
|
||||
unsigned init_rq_count; /* for debugging purposes only */
|
||||
unsigned polling_finished:1; /* no more updates */
|
||||
unsigned error:1; /* unrecoverable error occured in lvmpolld */
|
||||
unsigned error:1; /* unrecoverable error occurred in lvmpolld */
|
||||
};
|
||||
|
||||
typedef void (*lvmpolld_parse_output_fn_t) (struct lvmpolld_lv *pdlv, const char *line);
|
||||
@@ -93,7 +96,7 @@ struct lvmpolld_thread_data {
|
||||
struct lvmpolld_lv *pdlv;
|
||||
};
|
||||
|
||||
char *construct_id(const char *sysdir, const char *lvid);
|
||||
char *construct_id(const char *sysdir, const char *uuid);
|
||||
|
||||
/* LVMPOLLD_LV_T section */
|
||||
|
||||
|
@@ -45,7 +45,7 @@
|
||||
#define LVMPD_RESP_OK "OK"
|
||||
|
||||
#define LVMPD_REAS_RETCODE "retcode" /* lvm cmd ret code */
|
||||
#define LVMPD_REAS_SIGNAL "signal" /* lvm cmd terminating singal */
|
||||
#define LVMPD_REAS_SIGNAL "signal" /* lvm cmd terminating signal */
|
||||
|
||||
#define LVMPD_RET_DUP_FAILED 100
|
||||
#define LVMPD_RET_EXC_FAILED 101
|
||||
|
@@ -25,6 +25,7 @@ DEVICE_MAPPER_SOURCE=\
|
||||
device_mapper/libdm-targets.c \
|
||||
device_mapper/libdm-timestamp.c \
|
||||
device_mapper/mm/pool.c \
|
||||
device_mapper/raid/raid_parser.c \
|
||||
device_mapper/regex/matcher.c \
|
||||
device_mapper/regex/parse_rx.c \
|
||||
device_mapper/regex/ttree.c \
|
||||
|
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "base/data-struct/list.h"
|
||||
#include "base/data-struct/hash.h"
|
||||
#include "raid/target.h"
|
||||
#include "vdo/target.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
@@ -175,12 +176,11 @@ struct dm_names {
|
||||
|
||||
struct dm_active_device {
|
||||
struct dm_list list;
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
char *name; /* device name */
|
||||
dev_t devno;
|
||||
const char *name; /* device name */
|
||||
|
||||
uint32_t event_nr; /* valid when DM_DEVICE_LIST_HAS_EVENT_NR is set */
|
||||
char *uuid; /* valid uuid when DM_DEVICE_LIST_HAS_UUID is set */
|
||||
const char *uuid; /* valid uuid when DM_DEVICE_LIST_HAS_UUID is set */
|
||||
};
|
||||
|
||||
struct dm_versions {
|
||||
@@ -192,7 +192,7 @@ struct dm_versions {
|
||||
|
||||
int dm_get_library_version(char *version, size_t size);
|
||||
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
|
||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
|
||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info);
|
||||
|
||||
/*
|
||||
* This function returns dm device's UUID based on the value
|
||||
@@ -230,16 +230,6 @@ struct dm_names *dm_task_get_names(struct dm_task *dmt);
|
||||
#define DM_DEVICE_LIST_HAS_UUID 2
|
||||
int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
|
||||
unsigned *devs_features);
|
||||
/*
|
||||
* -1: no idea about uuid (not provided by DM_DEVICE_LIST ioctl)
|
||||
* 0: uuid not present
|
||||
* 1: listed and dm_active_device will be set for not NULL pointer
|
||||
*/
|
||||
int dm_device_list_find_by_uuid(const struct dm_list *devs_list, const char *uuid,
|
||||
const struct dm_active_device **dev);
|
||||
int dm_device_list_find_by_dev(const struct dm_list *devs_list,
|
||||
uint32_t major, uint32_t minor,
|
||||
const char **name, const char **uuid);
|
||||
/* Release all associated memory with list of active DM devices */
|
||||
void dm_device_list_destroy(struct dm_list **devs_list);
|
||||
|
||||
@@ -315,15 +305,15 @@ int dm_task_add_target(struct dm_task *dmt,
|
||||
#define DM_FORMAT_DEV_BUFSIZE 13 /* Minimum bufsize to handle worst case. */
|
||||
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor);
|
||||
|
||||
/* Use this to retrive target information returned from a STATUS call */
|
||||
/* Use this to retrieve target information returned from a STATUS call */
|
||||
void *dm_get_next_target(struct dm_task *dmt,
|
||||
void *next, uint64_t *start, uint64_t *length,
|
||||
char **target_type, char **params);
|
||||
|
||||
/*
|
||||
* Following dm_get_status_* functions will allocate approriate status structure
|
||||
* Following dm_get_status_* functions will allocate appropriate status structure
|
||||
* from passed mempool together with the necessary character arrays.
|
||||
* Destroying the mempool will release all asociated allocation.
|
||||
* Destroying the mempool will release all associated allocation.
|
||||
*/
|
||||
|
||||
/* Parse params from STATUS call for mirror target */
|
||||
@@ -552,7 +542,7 @@ const char *dm_sysfs_dir(void);
|
||||
|
||||
/*
|
||||
* Configure default UUID prefix string.
|
||||
* Conventionally this is a short capitalised prefix indicating the subsystem
|
||||
* Conventionally this is a short capitalized prefix indicating the subsystem
|
||||
* that is managing the devices, e.g. "LVM-" or "MPATH-".
|
||||
* To support stacks of devices from different subsystems, recursive functions
|
||||
* stop recursing if they reach a device with a different prefix.
|
||||
@@ -595,7 +585,7 @@ int dm_device_has_mounted_fs(uint32_t major, uint32_t minor);
|
||||
|
||||
|
||||
/*
|
||||
* Callback is invoked for individal mountinfo lines,
|
||||
* Callback is invoked for individual mountinfo lines,
|
||||
* minor, major and mount target are parsed and unmangled.
|
||||
*/
|
||||
typedef int (*dm_mountinfo_line_callback_fn) (char *line, unsigned maj, unsigned min,
|
||||
@@ -709,7 +699,7 @@ void *dm_tree_node_get_context(const struct dm_tree_node *node);
|
||||
/*
|
||||
* Returns 0 when node size and its children is unchanged.
|
||||
* Returns 1 when node or any of its children has increased size.
|
||||
* Rerurns -1 when node or any of its children has reduced size.
|
||||
* Returns -1 when node or any of its children has reduced size.
|
||||
*/
|
||||
int dm_tree_node_size_changed(const struct dm_tree_node *dnode);
|
||||
|
||||
@@ -896,7 +886,7 @@ struct dm_tree_node_raid_params {
|
||||
};
|
||||
|
||||
/*
|
||||
* Version 2 of above node raid params struct to keeep API compatibility.
|
||||
* Version 2 of above node raid params struct to keep API compatibility.
|
||||
*
|
||||
* Extended for more than 64 legs (max 253 in the MD kernel runtime!),
|
||||
* delta_disks for disk add/remove reshaping,
|
||||
@@ -919,7 +909,7 @@ struct dm_tree_node_raid_params_v2 {
|
||||
* 'rebuilds' and 'writemostly' are bitfields that signify
|
||||
* which devices in the array are to be rebuilt or marked
|
||||
* writemostly. The kernel supports up to 253 legs.
|
||||
* We limit ourselvs by choosing a lower value
|
||||
* We limit ourselves by choosing a lower value
|
||||
* for DEFAULT_RAID_MAX_IMAGES.
|
||||
*/
|
||||
uint64_t rebuilds[RAID_BITMAP_SIZE];
|
||||
@@ -956,7 +946,7 @@ struct dm_config_node;
|
||||
*
|
||||
* policy_settings {
|
||||
* migration_threshold=2048
|
||||
* sequention_threashold=100
|
||||
* sequential_threshold=100
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
@@ -1034,6 +1024,7 @@ struct integrity_settings {
|
||||
uint32_t commit_time;
|
||||
uint32_t bitmap_flush_interval;
|
||||
uint64_t sectors_per_bit;
|
||||
uint32_t allow_discards;
|
||||
|
||||
unsigned journal_sectors_set:1;
|
||||
unsigned interleave_sectors_set:1;
|
||||
@@ -1042,6 +1033,7 @@ struct integrity_settings {
|
||||
unsigned commit_time_set:1;
|
||||
unsigned bitmap_flush_interval_set:1;
|
||||
unsigned sectors_per_bit_set:1;
|
||||
unsigned allow_discards_set:1;
|
||||
};
|
||||
|
||||
int dm_tree_node_add_integrity_target(struct dm_tree_node *node,
|
||||
@@ -1060,7 +1052,7 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
|
||||
const char *vdo_pool_name,
|
||||
const char *data_uuid,
|
||||
uint64_t data_size,
|
||||
const struct dm_vdo_target_params *param);
|
||||
const struct dm_vdo_target_params *vtp);
|
||||
|
||||
/*
|
||||
* FIXME Add individual cache policy pairs <key> = value, like:
|
||||
@@ -1103,7 +1095,7 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
|
||||
/* End of Replicator API */
|
||||
|
||||
/*
|
||||
* FIXME: Defines bellow are based on kernel's dm-thin.c defines
|
||||
* FIXME: Defines below are based on kernel's dm-thin.c defines
|
||||
* DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
|
||||
* DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
|
||||
*/
|
||||
@@ -1169,7 +1161,7 @@ int dm_tree_node_set_thin_pool_error_if_no_space(struct dm_tree_node *node,
|
||||
int dm_tree_node_set_thin_pool_read_only(struct dm_tree_node *node,
|
||||
unsigned read_only);
|
||||
/*
|
||||
* FIXME: Defines bellow are based on kernel's dm-thin.c defines
|
||||
* FIXME: Defines below are based on kernel's dm-thin.c defines
|
||||
* MAX_DEV_ID ((1 << 24) - 1)
|
||||
*/
|
||||
#define DM_THIN_MAX_DEVICE_ID (UINT32_C((1 << 24) - 1))
|
||||
@@ -1187,9 +1179,9 @@ void dm_tree_node_set_presuspend_node(struct dm_tree_node *node,
|
||||
struct dm_tree_node *presuspend_node);
|
||||
|
||||
int dm_tree_node_add_target_area(struct dm_tree_node *node,
|
||||
const char *dev_name,
|
||||
const char *dlid,
|
||||
uint64_t offset);
|
||||
const char *dev_name,
|
||||
const char *uuid,
|
||||
uint64_t offset);
|
||||
|
||||
/*
|
||||
* Only for temporarily-missing raid devices where changes are tracked.
|
||||
@@ -1599,9 +1591,9 @@ int dm_fclose(FILE *stream);
|
||||
* Pointer to the buffer is stored in *buf.
|
||||
* Returns -1 on failure leaving buf undefined.
|
||||
*/
|
||||
int dm_asprintf(char **buf, const char *format, ...)
|
||||
int dm_asprintf(char **result, const char *format, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
int dm_vasprintf(char **buf, const char *format, va_list ap)
|
||||
int dm_vasprintf(char **result, const char *format, va_list aq)
|
||||
__attribute__ ((format(printf, 2, 0)));
|
||||
|
||||
/*
|
||||
@@ -1950,7 +1942,7 @@ void dm_report_free(struct dm_report *rh);
|
||||
* Prefix added to each field name with DM_REPORT_OUTPUT_FIELD_NAME_PREFIX
|
||||
*/
|
||||
int dm_report_set_output_field_name_prefix(struct dm_report *rh,
|
||||
const char *report_prefix);
|
||||
const char *output_field_name_prefix);
|
||||
|
||||
int dm_report_set_selection(struct dm_report *rh, const char *selection);
|
||||
|
||||
@@ -2043,6 +2035,7 @@ struct dm_config_tree *dm_config_create(void);
|
||||
struct dm_config_tree *dm_config_from_string(const char *config_settings);
|
||||
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end);
|
||||
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end);
|
||||
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section);
|
||||
|
||||
void *dm_config_get_custom(struct dm_config_tree *cft);
|
||||
void dm_config_set_custom(struct dm_config_tree *cft, void *custom);
|
||||
@@ -2067,7 +2060,7 @@ void dm_config_destroy(struct dm_config_tree *cft);
|
||||
|
||||
/* Simple output line by line. */
|
||||
typedef int (*dm_putline_fn)(const char *line, void *baton);
|
||||
/* More advaced output with config node reference. */
|
||||
/* More advanced output with config node reference. */
|
||||
typedef int (*dm_config_node_out_fn)(const struct dm_config_node *cn, const char *line, void *baton);
|
||||
|
||||
/*
|
||||
@@ -2089,7 +2082,7 @@ int dm_config_write_one_node_out(const struct dm_config_node *cn, const struct d
|
||||
|
||||
struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path);
|
||||
int dm_config_has_node(const struct dm_config_node *cn, const char *path);
|
||||
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *remove);
|
||||
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *rem_node);
|
||||
const char *dm_config_find_str(const struct dm_config_node *cn, const char *path, const char *fail);
|
||||
const char *dm_config_find_str_allow_empty(const struct dm_config_node *cn, const char *path, const char *fail);
|
||||
int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail);
|
||||
@@ -2121,7 +2114,7 @@ unsigned dm_config_maybe_section(const char *str, unsigned len);
|
||||
|
||||
const char *dm_config_parent_name(const struct dm_config_node *n);
|
||||
|
||||
struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *node, int siblings);
|
||||
struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *cn, int siblings);
|
||||
struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key);
|
||||
struct dm_config_value *dm_config_create_value(struct dm_config_tree *cft);
|
||||
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *cn, int siblings);
|
||||
@@ -2130,7 +2123,7 @@ struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const st
|
||||
* Common formatting flags applicable to all config node types (lower 16 bits).
|
||||
*/
|
||||
#define DM_CONFIG_VALUE_FMT_COMMON_ARRAY 0x00000001 /* value is array */
|
||||
#define DM_CONFIG_VALUE_FMT_COMMON_EXTRA_SPACES 0x00000002 /* add spaces in "key = value" pairs in constrast to "key=value" for better readability */
|
||||
#define DM_CONFIG_VALUE_FMT_COMMON_EXTRA_SPACES 0x00000002 /* add spaces in "key = value" pairs in contrast to "key=value" for better readability */
|
||||
|
||||
/*
|
||||
* Type-related config node formatting flags (higher 16 bits).
|
||||
@@ -2176,7 +2169,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
|
||||
*/
|
||||
#define DM_UDEV_DISABLE_DM_RULES_FLAG 0x0001
|
||||
/*
|
||||
* DM_UDEV_DISABLE_SUBSYTEM_RULES_FLAG is set in case we need to disable
|
||||
* DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG is set in case we need to disable
|
||||
* subsystem udev rules, but still we need the general DM udev rules to
|
||||
* be applied (to create the nodes and symlinks under /dev and /dev/disk).
|
||||
*/
|
||||
|
@@ -70,6 +70,7 @@ static unsigned _dm_version_minor = 0;
|
||||
static unsigned _dm_version_patchlevel = 0;
|
||||
static int _log_suppress = 0;
|
||||
static struct dm_timestamp *_dm_ioctl_timestamp = NULL;
|
||||
static int _dm_warn_inactive_suppress = 0;
|
||||
|
||||
/*
|
||||
* If the kernel dm driver only supports one major number
|
||||
@@ -485,7 +486,7 @@ static void _dm_zfree_string(char *string)
|
||||
{
|
||||
if (string) {
|
||||
memset(string, 0, strlen(string));
|
||||
asm volatile ("" ::: "memory"); /* Compiler barrier. */
|
||||
__asm__ volatile ("" ::: "memory"); /* Compiler barrier. */
|
||||
free(string);
|
||||
}
|
||||
}
|
||||
@@ -494,7 +495,7 @@ static void _dm_zfree_dmi(struct dm_ioctl *dmi)
|
||||
{
|
||||
if (dmi) {
|
||||
memset(dmi, 0, dmi->data_size);
|
||||
asm volatile ("" ::: "memory"); /* Compiler barrier. */
|
||||
__asm__ volatile ("" ::: "memory"); /* Compiler barrier. */
|
||||
free(dmi);
|
||||
}
|
||||
}
|
||||
@@ -659,7 +660,7 @@ void *dm_get_next_target(struct dm_task *dmt, void *next,
|
||||
return t->next;
|
||||
}
|
||||
|
||||
/* Unmarshall the target info returned from a status call */
|
||||
/* Unmarshal the target info returned from a status call */
|
||||
static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
|
||||
{
|
||||
char *outbuf = (char *) dmi + dmi->data_start;
|
||||
@@ -769,7 +770,7 @@ static size_t _align_val(size_t val)
|
||||
}
|
||||
static void *_align_ptr(void *ptr)
|
||||
{
|
||||
return (void *)_align_val((size_t)ptr);
|
||||
return (void *)(uintptr_t)_align_val((size_t)ptr);
|
||||
}
|
||||
|
||||
static int _check_has_event_nr(void) {
|
||||
@@ -782,46 +783,17 @@ static int _check_has_event_nr(void) {
|
||||
return _has_event_nr;
|
||||
}
|
||||
|
||||
struct dm_device_list {
|
||||
struct dm_list list;
|
||||
unsigned count;
|
||||
unsigned features;
|
||||
struct dm_hash_table *uuids;
|
||||
/* As last element (sized according to count), pointers to individual dm_devs */
|
||||
struct dm_active_device *sorted[]; /* For bsearch() devs sorted by device node */
|
||||
};
|
||||
|
||||
/*
|
||||
* Comparing 2 dev nodes by its minor.
|
||||
*
|
||||
* TODO: enhance if DM would ever use multiple major:minor...
|
||||
*/
|
||||
static int _dm_dev_compare(const void *p1, const void *p2)
|
||||
{
|
||||
int m1 = (*(struct dm_active_device **)p1)->minor;
|
||||
int m2 = (*(struct dm_active_device **)p2)->minor;
|
||||
|
||||
if (m1 > m2)
|
||||
return 1;
|
||||
|
||||
if (m1 < m2)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
|
||||
unsigned *devs_features)
|
||||
{
|
||||
struct dm_names *names, *names1;
|
||||
struct dm_active_device *dm_dev, *dm_new_dev;
|
||||
struct dm_device_list *devs;
|
||||
struct dm_list *devs;
|
||||
unsigned next = 0;
|
||||
uint32_t *event_nr;
|
||||
char *uuid_ptr;
|
||||
size_t len;
|
||||
int cnt = 0;
|
||||
unsigned index = 0;
|
||||
|
||||
*devs_list = 0;
|
||||
*devs_features = 0;
|
||||
@@ -839,12 +811,10 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
|
||||
|
||||
/* buffer for devs + sorted ptrs + dm_devs + aligned strings */
|
||||
if (!(devs = malloc(sizeof(*devs) + cnt * (2 * sizeof(void*) + sizeof(*dm_dev)) +
|
||||
(!cnt ? 0 : (char*)names1 - (char*)names + 256))))
|
||||
(cnt ? (char*)names1 - (char*)names + 256 : 0))))
|
||||
return_0;
|
||||
|
||||
dm_list_init(&devs->list);
|
||||
devs->count = cnt;
|
||||
devs->uuids = NULL;
|
||||
dm_list_init(devs);
|
||||
|
||||
if (!cnt) {
|
||||
/* nothing in the list -> mark all features present */
|
||||
@@ -858,23 +828,16 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
|
||||
do {
|
||||
names = (struct dm_names *)((char *) names + next);
|
||||
|
||||
devs->sorted[index++] = dm_dev;
|
||||
dm_dev->major = MAJOR(names->dev);
|
||||
dm_dev->minor = MINOR(names->dev);
|
||||
dm_dev->name = (char*)(dm_dev + 1);
|
||||
dm_dev->devno = (dev_t) names->dev;
|
||||
dm_dev->name = (const char *)(dm_dev + 1);
|
||||
dm_dev->event_nr = 0;
|
||||
dm_dev->uuid = NULL;
|
||||
dm_dev->uuid = "";
|
||||
|
||||
len = strlen(names->name) + 1;
|
||||
memcpy(dm_dev->name, names->name, len);
|
||||
memcpy((char*)dm_dev->name, names->name, len);
|
||||
|
||||
dm_new_dev = _align_ptr((char*)(dm_dev + 1) + len);
|
||||
if (_check_has_event_nr()) {
|
||||
/* Hash for UUIDs with some more bits to reduce colision count */
|
||||
if (!devs->uuids && !(devs->uuids = dm_hash_create(cnt * 8))) {
|
||||
free(devs);
|
||||
return_0;
|
||||
}
|
||||
|
||||
*devs_features |= DM_DEVICE_LIST_HAS_EVENT_NR;
|
||||
event_nr = _align_ptr(names->name + len);
|
||||
@@ -883,101 +846,29 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
|
||||
if ((event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) {
|
||||
*devs_features |= DM_DEVICE_LIST_HAS_UUID;
|
||||
uuid_ptr = _align_ptr(event_nr + 2);
|
||||
dm_dev->uuid = (char*) dm_new_dev;
|
||||
len = strlen(uuid_ptr) + 1;
|
||||
memcpy(dm_new_dev, uuid_ptr, len);
|
||||
dm_dev->uuid = (const char *) dm_new_dev;
|
||||
dm_new_dev = _align_ptr((char*)dm_new_dev + len);
|
||||
memcpy(dm_dev->uuid, uuid_ptr, len);
|
||||
if (!dm_hash_insert(devs->uuids, dm_dev->uuid, dm_dev))
|
||||
return_0; // FIXME
|
||||
#if 0
|
||||
log_debug("Active %s (%s) %u:%u event:%u",
|
||||
dm_dev->name, dm_dev->uuid,
|
||||
dm_dev->major, dm_dev->minor, dm_dev->event_nr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
dm_list_add(&devs->list, &dm_dev->list);
|
||||
dm_list_add(devs, &dm_dev->list);
|
||||
dm_dev = dm_new_dev;
|
||||
next = names->next;
|
||||
} while (next);
|
||||
|
||||
out:
|
||||
*devs_list = (struct dm_list *)devs;
|
||||
|
||||
/* sort by minors */
|
||||
qsort(devs->sorted, devs->count, sizeof(void*), _dm_dev_compare);
|
||||
#if 0
|
||||
for (int i = 0; i < index; ++i) /* check order */
|
||||
log_debug("DM devices: minor=%d name=%s uuid=%s",
|
||||
devs->sorted[i]->minor, devs->sorted[i]->name,
|
||||
devs->sorted[i]->uuid);
|
||||
#endif
|
||||
*devs_list = devs;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_device_list_find_by_uuid(const struct dm_list *devs_list, const char *uuid,
|
||||
const struct dm_active_device **dev)
|
||||
{
|
||||
const struct dm_device_list *devs = (const struct dm_device_list *) devs_list;
|
||||
const struct dm_active_device *dm_dev;
|
||||
|
||||
if (devs->uuids &&
|
||||
(dm_dev = dm_hash_lookup(devs->uuids, uuid))) {
|
||||
if (dev)
|
||||
*dev = dm_dev;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find DM device in devs array for given major:minor.
|
||||
* ATM assuming all DM devices use the single known major.
|
||||
*
|
||||
* NOTE:
|
||||
* When major:minor is found, the 'name' and 'uuid' pointers
|
||||
* are return as const string pointing to devs structure.
|
||||
* Once the dm_device_list structure is destroyed
|
||||
* those pointers become invalid!
|
||||
*/
|
||||
int dm_device_list_find_by_dev(const struct dm_list *devs_list,
|
||||
uint32_t major, uint32_t minor,
|
||||
const char **name, const char **uuid)
|
||||
{
|
||||
const struct dm_device_list *devs = (const struct dm_device_list *) devs_list;
|
||||
const struct dm_active_device search = { .major = major, .minor = minor };
|
||||
const struct dm_active_device *findme[] = { &search };
|
||||
const struct dm_active_device **dm_dev_found;
|
||||
const char *fname = NULL, *fuuid = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* Prefer bsearch O(logN) over linear list scanning O(N) */
|
||||
if ((dm_dev_found = bsearch(findme, devs->sorted, devs->count, sizeof(void*),
|
||||
_dm_dev_compare))) {
|
||||
fname = (*dm_dev_found)->name;
|
||||
fuuid = (*dm_dev_found)->uuid ? : ""; /* Device without UUID */
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (name)
|
||||
*name = fname;
|
||||
if (uuid)
|
||||
*uuid = fuuid;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dm_device_list_destroy(struct dm_list **devs_list)
|
||||
{
|
||||
struct dm_device_list *devs = (struct dm_device_list *) *devs_list;
|
||||
|
||||
if (devs) {
|
||||
if (devs->uuids)
|
||||
dm_hash_destroy(devs->uuids);
|
||||
|
||||
free(devs);
|
||||
*devs_list = NULL;
|
||||
}
|
||||
@@ -1522,22 +1413,23 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
}
|
||||
if (dmt->query_inactive_table) {
|
||||
if (!_dm_inactive_supported())
|
||||
log_warn("WARNING: Inactive table query unsupported "
|
||||
"by kernel. It will use live table.");
|
||||
log_warn_suppress(_dm_warn_inactive_suppress++,
|
||||
"WARNING: Inactive table query unsupported by kernel. "
|
||||
"It will use live table.");
|
||||
dmi->flags |= DM_QUERY_INACTIVE_TABLE_FLAG;
|
||||
}
|
||||
if (dmt->new_uuid) {
|
||||
if (_dm_version_minor < 19) {
|
||||
log_error("WARNING: Setting UUID unsupported by "
|
||||
"kernel. Aborting operation.");
|
||||
log_error("Setting UUID unsupported by kernel. "
|
||||
"Aborting operation.");
|
||||
goto bad;
|
||||
}
|
||||
dmi->flags |= DM_UUID_FLAG;
|
||||
}
|
||||
if (dmt->ima_measurement) {
|
||||
if (_dm_version_minor < 45) {
|
||||
log_error("WARNING: IMA measurement unsupported by "
|
||||
"kernel. Aborting operation.");
|
||||
log_error("IMA measurement unsupported by kernel. "
|
||||
"Aborting operation.");
|
||||
goto bad;
|
||||
}
|
||||
dmi->flags |= DM_IMA_MEASUREMENT_FLAG;
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#ifndef LIB_DMTARGETS_H
|
||||
#define LIB_DMTARGETS_H
|
||||
|
||||
#include "device_mapper/all.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
@@ -511,7 +511,7 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
|
||||
char *buf, size_t buf_len, dm_string_mangling_t mode)
|
||||
{
|
||||
int strict = mode != DM_STRING_MANGLING_NONE;
|
||||
char str_rest[DM_NAME_LEN];
|
||||
char str_rest[DM_NAME_LEN + 1];
|
||||
size_t i, j;
|
||||
unsigned int code;
|
||||
int r = 0;
|
||||
@@ -1796,7 +1796,7 @@ static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min,
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to operate on individal mountinfo line,
|
||||
* Function to operate on individual mountinfo line,
|
||||
* minor, major and mount target are parsed and unmangled
|
||||
*/
|
||||
int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
|
||||
@@ -1832,32 +1832,27 @@ int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
|
||||
|
||||
static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
|
||||
{
|
||||
char *sysfs_path, *temp_buf = NULL;
|
||||
char sysfs_path[PATH_MAX], temp_buf[2 * DM_NAME_LEN];
|
||||
FILE *fp = NULL;
|
||||
int r = 0;
|
||||
size_t len;
|
||||
|
||||
if (!(sysfs_path = malloc(PATH_MAX)) ||
|
||||
!(temp_buf = malloc(PATH_MAX))) {
|
||||
log_error("_sysfs_get_dm_name: failed to allocate temporary buffers");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32
|
||||
if (dm_snprintf(sysfs_path, sizeof(sysfs_path),
|
||||
"%sdev/block/%" PRIu32 ":%" PRIu32
|
||||
"/dm/name", _sysfs_dir, major, minor) < 0) {
|
||||
log_error("_sysfs_get_dm_name: dm_snprintf failed");
|
||||
log_error("_sysfs_get_dm_name: dm_snprintf failed.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(fp = fopen(sysfs_path, "r"))) {
|
||||
if (errno != ENOENT)
|
||||
log_sys_error("fopen", sysfs_path);
|
||||
else
|
||||
if (errno == ENOENT)
|
||||
log_sys_debug("fopen", sysfs_path);
|
||||
else
|
||||
log_sys_error("fopen", sysfs_path);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!fgets(temp_buf, PATH_MAX, fp)) {
|
||||
if (!fgets(temp_buf, sizeof(temp_buf), fp)) {
|
||||
log_sys_error("fgets", sysfs_path);
|
||||
goto bad;
|
||||
}
|
||||
@@ -1865,20 +1860,21 @@ static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t
|
||||
len = strlen(temp_buf);
|
||||
|
||||
if (len > buf_size) {
|
||||
log_error("_sysfs_get_dm_name: supplied buffer too small");
|
||||
log_error("_sysfs_get_dm_name: supplied buffer too small.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
temp_buf[len ? len - 1 : 0] = '\0'; /* \n */
|
||||
strcpy(buf, temp_buf);
|
||||
if (len)
|
||||
--len; /* strip \n */
|
||||
|
||||
memcpy(buf, temp_buf, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
r = 1;
|
||||
bad:
|
||||
if (fp && fclose(fp))
|
||||
log_sys_error("fclose", sysfs_path);
|
||||
|
||||
free(temp_buf);
|
||||
free(sysfs_path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1961,7 +1957,7 @@ static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, si
|
||||
!strcmp(name_dev, "holders") ||
|
||||
!strcmp(name_dev, "integrity") ||
|
||||
!strcmp(name_dev, "loop") ||
|
||||
!strcmp(name_dev, "queueu") ||
|
||||
!strcmp(name_dev, "queue") ||
|
||||
!strcmp(name_dev, "md") ||
|
||||
!strcmp(name_dev, "mq") ||
|
||||
!strcmp(name_dev, "power") ||
|
||||
@@ -2416,7 +2412,7 @@ static int _get_cookie_sem(uint32_t cookie, int *semid)
|
||||
break;
|
||||
case EACCES:
|
||||
log_error("No permission to access "
|
||||
"notificaton semaphore identified "
|
||||
"notification semaphore identified "
|
||||
"by cookie value %" PRIu32 " (0x%x)",
|
||||
cookie, cookie);
|
||||
break;
|
||||
@@ -2437,20 +2433,20 @@ static int _udev_notify_sem_inc(uint32_t cookie, int semid)
|
||||
int val;
|
||||
|
||||
if (semop(semid, &sb, 1) < 0) {
|
||||
log_error("semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
|
||||
log_error("cookie inc: semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
|
||||
semid, cookie, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((val = semctl(semid, 0, GETVAL)) < 0) {
|
||||
log_error("semid %d: sem_ctl GETVAL failed for "
|
||||
log_warn("cookie inc: semid %d: sem_ctl GETVAL failed for "
|
||||
"cookie 0x%" PRIx32 ": %s",
|
||||
semid, cookie, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
|
||||
cookie, semid, val);
|
||||
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented.",
|
||||
cookie, semid);
|
||||
} else
|
||||
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
|
||||
cookie, semid, val);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2460,23 +2456,21 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
|
||||
struct sembuf sb = {0, -1, IPC_NOWAIT};
|
||||
int val;
|
||||
|
||||
if ((val = semctl(semid, 0, GETVAL)) < 0) {
|
||||
log_error("semid %d: sem_ctl GETVAL failed for "
|
||||
"cookie 0x%" PRIx32 ": %s",
|
||||
semid, cookie, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if ((val = semctl(semid, 0, GETVAL)) < 0)
|
||||
log_warn("cookie dec: semid %d: sem_ctl GETVAL failed for "
|
||||
"cookie 0x%" PRIx32 ": %s",
|
||||
semid, cookie, strerror(errno));
|
||||
|
||||
if (semop(semid, &sb, 1) < 0) {
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
log_error("semid %d: semop failed for cookie "
|
||||
log_error("cookie dec: semid %d: semop failed for cookie "
|
||||
"0x%" PRIx32 ": "
|
||||
"incorrect semaphore state",
|
||||
semid, cookie);
|
||||
break;
|
||||
default:
|
||||
log_error("semid %d: semop failed for cookie "
|
||||
log_error("cookie dec: semid %d: semop failed for cookie "
|
||||
"0x%" PRIx32 ": %s",
|
||||
semid, cookie, strerror(errno));
|
||||
break;
|
||||
@@ -2484,9 +2478,12 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
|
||||
cookie, semid, val - 1);
|
||||
|
||||
if (val < 0)
|
||||
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented.",
|
||||
cookie, semid);
|
||||
else
|
||||
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
|
||||
cookie, semid, val - 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2563,7 +2560,7 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
|
||||
sem_arg.val = 1;
|
||||
|
||||
if (semctl(gen_semid, 0, SETVAL, sem_arg) < 0) {
|
||||
log_error("semid %d: semctl failed: %s", gen_semid, strerror(errno));
|
||||
log_error("cookie create: semid %d: semctl failed: %s", gen_semid, strerror(errno));
|
||||
/* We have to destroy just created semaphore
|
||||
* so it won't stay in the system. */
|
||||
(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
|
||||
@@ -2571,9 +2568,10 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
|
||||
}
|
||||
|
||||
if ((val = semctl(gen_semid, 0, GETVAL)) < 0) {
|
||||
log_error("semid %d: sem_ctl GETVAL failed for "
|
||||
log_error("cookie create: semid %d: sem_ctl GETVAL failed for "
|
||||
"cookie 0x%" PRIx32 ": %s",
|
||||
gen_semid, gen_cookie, strerror(errno));
|
||||
(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,7 @@ struct target *create_target(uint64_t start,
|
||||
uint64_t len,
|
||||
const char *type, const char *params);
|
||||
|
||||
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major,
|
||||
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
uid_t uid, gid_t gid, mode_t mode, int check_udev, unsigned rely_on_udev);
|
||||
int rm_dev_node(const char *dev_name, int check_udev, unsigned rely_on_udev);
|
||||
int rename_dev_node(const char *old_name, const char *new_name,
|
||||
|
@@ -53,6 +53,8 @@ struct parser {
|
||||
int no_dup_node_check; /* whether to disable dup node checking */
|
||||
const char *key; /* last obtained key */
|
||||
unsigned ignored_creation_time;
|
||||
unsigned section_indent;
|
||||
const char *stop_after_section;
|
||||
};
|
||||
|
||||
struct config_output {
|
||||
@@ -70,7 +72,8 @@ static struct dm_config_value *_value(struct parser *p);
|
||||
static struct dm_config_value *_type(struct parser *p);
|
||||
static int _match_aux(struct parser *p, int t);
|
||||
static struct dm_config_value *_create_value(struct dm_pool *mem);
|
||||
static struct dm_config_node *_create_node(struct dm_pool *mem);
|
||||
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len);
|
||||
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len);
|
||||
static char *_dup_tok(struct parser *p);
|
||||
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
|
||||
|
||||
@@ -84,20 +87,24 @@ static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* match token */
|
||||
static int _tok_match(const char *str, const char *b, const char *e)
|
||||
{
|
||||
while (*str && (b != e)) {
|
||||
if (*str++ != *b++)
|
||||
while (b < e) {
|
||||
if (!*str ||
|
||||
(*str != *b))
|
||||
return 0;
|
||||
++str;
|
||||
++b;
|
||||
}
|
||||
|
||||
return !(*str || (b != e));
|
||||
return !*str; /* token is matching for \0 end */
|
||||
}
|
||||
|
||||
struct dm_config_tree *dm_config_create(void)
|
||||
{
|
||||
struct dm_config_tree *cft;
|
||||
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
|
||||
struct dm_pool *mem = dm_pool_create("config", 63 * 1024);
|
||||
|
||||
if (!mem) {
|
||||
log_error("Failed to allocate config pool.");
|
||||
@@ -171,7 +178,8 @@ static struct dm_config_node *_config_reverse(struct dm_config_node *head)
|
||||
return middle;
|
||||
}
|
||||
|
||||
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end, int no_dup_node_check)
|
||||
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end,
|
||||
int no_dup_node_check, const char *section)
|
||||
{
|
||||
/* TODO? if (start == end) return 1; */
|
||||
|
||||
@@ -182,6 +190,7 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
|
||||
.fb = start,
|
||||
.fe = end,
|
||||
.line = 1,
|
||||
.stop_after_section = section,
|
||||
.no_dup_node_check = no_dup_node_check
|
||||
};
|
||||
|
||||
@@ -196,12 +205,23 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
|
||||
|
||||
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end)
|
||||
{
|
||||
return _do_dm_config_parse(cft, start, end, 0);
|
||||
return _do_dm_config_parse(cft, start, end, 0, NULL);
|
||||
}
|
||||
|
||||
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end)
|
||||
{
|
||||
return _do_dm_config_parse(cft, start, end, 1);
|
||||
return _do_dm_config_parse(cft, start, end, 1, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop parsing more sections after given section is parsed.
|
||||
* Only non-section config nodes are then still parsed.
|
||||
* It can be useful, when parsing i.e. lvm2 metadata and only physical_volumes config node is needed.
|
||||
* This function is automatically running without_dup_node_check.
|
||||
*/
|
||||
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section)
|
||||
{
|
||||
return _do_dm_config_parse(cft, start, end, 1, section);
|
||||
}
|
||||
|
||||
struct dm_config_tree *dm_config_from_string(const char *config_settings)
|
||||
@@ -467,23 +487,33 @@ int dm_config_write_node_out(const struct dm_config_node *cn,
|
||||
/*
|
||||
* parser
|
||||
*/
|
||||
static char *_dup_string_tok(struct parser *p)
|
||||
static const char *_string_tok(struct parser *p, size_t *len)
|
||||
{
|
||||
char *str;
|
||||
ptrdiff_t d = p->te - p->tb;
|
||||
|
||||
p->tb++, p->te--; /* strip "'s */
|
||||
|
||||
if (p->te < p->tb) {
|
||||
if (d < 2) {
|
||||
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): "
|
||||
"expected a string token.",
|
||||
p->tb - p->fb + 1, p->line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(str = _dup_tok(p)))
|
||||
*len = (size_t)(d - 2); /* strip "'s */
|
||||
|
||||
return p->tb + 1;
|
||||
}
|
||||
|
||||
static char *_dup_string_tok(struct parser *p)
|
||||
{
|
||||
const char *tok;
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
if (!(tok = _string_tok(p, &len)))
|
||||
return_NULL;
|
||||
|
||||
p->te++;
|
||||
if (!(str = _dup_token(p->mem, tok, tok + len)))
|
||||
return_NULL;
|
||||
|
||||
return str;
|
||||
}
|
||||
@@ -505,10 +535,9 @@ static struct dm_config_node *_make_node(struct dm_pool *mem,
|
||||
{
|
||||
struct dm_config_node *n;
|
||||
|
||||
if (!(n = _create_node(mem)))
|
||||
if (!(n = _create_node(mem, key_b, key_e - key_b)))
|
||||
return_NULL;
|
||||
|
||||
n->key = _dup_token(mem, key_b, key_e);
|
||||
if (parent) {
|
||||
n->parent = parent;
|
||||
n->sib = parent->child;
|
||||
@@ -578,6 +607,8 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
|
||||
struct dm_config_node *root;
|
||||
struct dm_config_value *value;
|
||||
char *str;
|
||||
size_t len;
|
||||
char buf[8192];
|
||||
|
||||
if (p->t == TOK_STRING_ESCAPED) {
|
||||
if (!(str = _dup_string_tok(p)))
|
||||
@@ -591,9 +622,16 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
|
||||
|
||||
match(TOK_STRING);
|
||||
} else {
|
||||
if (!(str = _dup_tok(p)))
|
||||
return_NULL;
|
||||
|
||||
len = p->te - p->tb;
|
||||
if (len < (sizeof(buf) - 1)) {
|
||||
/* Use stack for smaller string */
|
||||
str = buf;
|
||||
memcpy(str, p->tb, len);
|
||||
str[len] = '\0';
|
||||
} else {
|
||||
if (!(str = _dup_tok(p)))
|
||||
return_NULL;
|
||||
}
|
||||
match(TOK_IDENTIFIER);
|
||||
}
|
||||
|
||||
@@ -607,12 +645,28 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
|
||||
return_NULL;
|
||||
|
||||
if (p->t == TOK_SECTION_B) {
|
||||
if (p->stop_after_section)
|
||||
++p->section_indent;
|
||||
match(TOK_SECTION_B);
|
||||
while (p->t != TOK_SECTION_E) {
|
||||
if (!(_section(p, root)))
|
||||
return_NULL;
|
||||
}
|
||||
match(TOK_SECTION_E);
|
||||
if (p->stop_after_section && (--p->section_indent == 1)) {
|
||||
if (!strcmp(str, p->stop_after_section)) {
|
||||
/* Found stopping section name -> parsing is finished.
|
||||
* Now try to find the sequence "\n}\n" from end of b
|
||||
* parsed buffer to continue filling remaining nodes */
|
||||
for (p->te = p->fe - 1; p->te > p->tb; --p->te)
|
||||
if ((p->te[-2] == '\n') &&
|
||||
(p->te[-1] == '}') &&
|
||||
(p->te[ 0] == '\n')) {
|
||||
p->t = TOK_SECTION_E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match(TOK_EQ);
|
||||
p->key = root->key;
|
||||
@@ -669,16 +723,14 @@ static struct dm_config_value *_value(struct parser *p)
|
||||
static struct dm_config_value *_type(struct parser *p)
|
||||
{
|
||||
/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
|
||||
struct dm_config_value *v = _create_value(p->mem);
|
||||
char *str;
|
||||
|
||||
if (!v) {
|
||||
log_error("Failed to allocate type value");
|
||||
return NULL;
|
||||
}
|
||||
struct dm_config_value *v;
|
||||
const char *str;
|
||||
size_t len;
|
||||
|
||||
switch (p->t) {
|
||||
case TOK_INT:
|
||||
if (!(v = _create_value(p->mem)))
|
||||
break;
|
||||
v->type = DM_CFG_INT;
|
||||
errno = 0;
|
||||
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
|
||||
@@ -699,6 +751,8 @@ static struct dm_config_value *_type(struct parser *p)
|
||||
break;
|
||||
|
||||
case TOK_FLOAT:
|
||||
if (!(v = _create_value(p->mem)))
|
||||
break;
|
||||
v->type = DM_CFG_FLOAT;
|
||||
errno = 0;
|
||||
v->v.f = strtod(p->tb, NULL); /* FIXME: check error */
|
||||
@@ -710,31 +764,31 @@ static struct dm_config_value *_type(struct parser *p)
|
||||
break;
|
||||
|
||||
case TOK_STRING:
|
||||
v->type = DM_CFG_STRING;
|
||||
|
||||
if (!(v->v.str = _dup_string_tok(p)))
|
||||
if (!(str = _string_tok(p, &len)))
|
||||
return_NULL;
|
||||
|
||||
match(TOK_STRING);
|
||||
if ((v = _create_str_value(p->mem, str, len))) {
|
||||
v->type = DM_CFG_STRING;
|
||||
match(TOK_STRING);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK_STRING_BARE:
|
||||
v->type = DM_CFG_STRING;
|
||||
|
||||
if (!(v->v.str = _dup_tok(p)))
|
||||
return_NULL;
|
||||
|
||||
match(TOK_STRING_BARE);
|
||||
if ((v = _create_str_value(p->mem, p->tb, p->te - p->tb))) {
|
||||
v->type = DM_CFG_STRING;
|
||||
match(TOK_STRING_BARE);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK_STRING_ESCAPED:
|
||||
v->type = DM_CFG_STRING;
|
||||
|
||||
if (!(str = _dup_string_tok(p)))
|
||||
if (!(str = _string_tok(p, &len)))
|
||||
return_NULL;
|
||||
dm_unescape_double_quotes(str);
|
||||
v->v.str = str;
|
||||
match(TOK_STRING_ESCAPED);
|
||||
|
||||
if ((v = _create_str_value(p->mem, str, len))) {
|
||||
v->type = DM_CFG_STRING;
|
||||
dm_unescape_double_quotes((char*)v->v.str);
|
||||
match(TOK_STRING_ESCAPED);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -742,6 +796,12 @@ static struct dm_config_value *_type(struct parser *p)
|
||||
p->tb - p->fb + 1, p->line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!v) {
|
||||
log_error("Failed to allocate type value.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -759,60 +819,52 @@ static int _match_aux(struct parser *p, int t)
|
||||
*/
|
||||
static void _get_token(struct parser *p, int tok_prev)
|
||||
{
|
||||
int values_allowed = 0;
|
||||
|
||||
/* Should next token be interpreted as value instead of identifier? */
|
||||
const int values_allowed = (tok_prev == TOK_EQ ||
|
||||
tok_prev == TOK_ARRAY_B ||
|
||||
tok_prev == TOK_COMMA);
|
||||
const char *te;
|
||||
char c;
|
||||
|
||||
p->tb = p->te;
|
||||
_eat_space(p);
|
||||
if (p->tb == p->fe || !*p->tb) {
|
||||
if (p->tb == p->fe ||
|
||||
!((c = *p->tb))) {
|
||||
p->t = TOK_EOF;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Should next token be interpreted as value instead of identifier? */
|
||||
if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
|
||||
tok_prev == TOK_COMMA)
|
||||
values_allowed = 1;
|
||||
|
||||
p->t = TOK_INT; /* fudge so the fall through for
|
||||
floats works */
|
||||
te = p->te + 1; /* next character */
|
||||
|
||||
te = p->te;
|
||||
switch (*te) {
|
||||
switch (c) {
|
||||
case SECTION_B_CHAR:
|
||||
p->t = TOK_SECTION_B;
|
||||
te++;
|
||||
break;
|
||||
|
||||
case SECTION_E_CHAR:
|
||||
p->t = TOK_SECTION_E;
|
||||
te++;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
p->t = TOK_ARRAY_B;
|
||||
te++;
|
||||
break;
|
||||
|
||||
case ']':
|
||||
p->t = TOK_ARRAY_E;
|
||||
te++;
|
||||
break;
|
||||
|
||||
case ',':
|
||||
p->t = TOK_COMMA;
|
||||
te++;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
p->t = TOK_EQ;
|
||||
te++;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
p->t = TOK_STRING_ESCAPED;
|
||||
te++;
|
||||
while ((te != p->fe) && (*te) && (*te != '"')) {
|
||||
if ((*te == '\\') && (te + 1 != p->fe) &&
|
||||
*(te + 1))
|
||||
@@ -826,7 +878,6 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
|
||||
case '\'':
|
||||
p->t = TOK_STRING;
|
||||
te++;
|
||||
while ((te != p->fe) && (*te) && (*te != '\''))
|
||||
te++;
|
||||
|
||||
@@ -850,7 +901,7 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
case '+':
|
||||
case '-':
|
||||
if (values_allowed) {
|
||||
while (++te != p->fe) {
|
||||
for (; te != p->fe; ++te) {
|
||||
if (!isdigit((int) *te)) {
|
||||
if (*te == '.') {
|
||||
if (p->t != TOK_FLOAT) {
|
||||
@@ -867,10 +918,10 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
|
||||
default:
|
||||
p->t = TOK_IDENTIFIER;
|
||||
while ((te != p->fe) && (*te) && !isspace(*te) &&
|
||||
(*te != '#') && (*te != '=') &&
|
||||
(*te != SECTION_B_CHAR) &&
|
||||
(*te != SECTION_E_CHAR))
|
||||
while ((te != p->fe) && ((c = *te)) && !isspace(c) &&
|
||||
(c != '#') && (c != '=') &&
|
||||
(c != SECTION_B_CHAR) &&
|
||||
(c != SECTION_E_CHAR))
|
||||
te++;
|
||||
if (values_allowed)
|
||||
p->t = TOK_STRING_BARE;
|
||||
@@ -883,16 +934,19 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
static void _eat_space(struct parser *p)
|
||||
{
|
||||
while (p->tb != p->fe) {
|
||||
if (*p->te == '#')
|
||||
if (!isspace(*p->te)) {
|
||||
if (*p->te != '#')
|
||||
break;
|
||||
|
||||
while ((p->te != p->fe) && (*p->te != '\n') && (*p->te))
|
||||
++p->te;
|
||||
}
|
||||
|
||||
else if (!isspace(*p->te))
|
||||
break;
|
||||
|
||||
while ((p->te != p->fe) && isspace(*p->te)) {
|
||||
while (p->te != p->fe) {
|
||||
if (*p->te == '\n')
|
||||
++p->line;
|
||||
else if (!isspace(*p->te))
|
||||
break;
|
||||
++p->te;
|
||||
}
|
||||
|
||||
@@ -908,9 +962,44 @@ static struct dm_config_value *_create_value(struct dm_pool *mem)
|
||||
return dm_pool_zalloc(mem, sizeof(struct dm_config_value));
|
||||
}
|
||||
|
||||
static struct dm_config_node *_create_node(struct dm_pool *mem)
|
||||
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len)
|
||||
{
|
||||
return dm_pool_zalloc(mem, sizeof(struct dm_config_node));
|
||||
struct dm_config_value *cv;
|
||||
char *str_buf;
|
||||
|
||||
if (!(cv = dm_pool_alloc(mem, sizeof(struct dm_config_value) + str_len + 1)))
|
||||
return_NULL;
|
||||
|
||||
memset(cv, 0, sizeof(*cv));
|
||||
|
||||
if (str) {
|
||||
str_buf = (char *)(cv + 1);
|
||||
memcpy(str_buf, str, str_len);
|
||||
str_buf[str_len] = '\0';
|
||||
cv->v.str = str_buf;
|
||||
}
|
||||
|
||||
return cv;
|
||||
}
|
||||
|
||||
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len)
|
||||
{
|
||||
struct dm_config_node *cn;
|
||||
char *key_buf;
|
||||
|
||||
if (!(cn = dm_pool_alloc(mem, sizeof(struct dm_config_node) + key_len + 1)))
|
||||
return_NULL;
|
||||
|
||||
memset(cn, 0, sizeof(*cn));
|
||||
|
||||
if (key) {
|
||||
key_buf = (char *)(cn + 1);
|
||||
memcpy(key_buf, key, key_len);
|
||||
key_buf[key_len] = '\0';
|
||||
cn->key = key_buf;
|
||||
}
|
||||
|
||||
return cn;
|
||||
}
|
||||
|
||||
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e)
|
||||
@@ -1327,19 +1416,20 @@ static struct dm_config_value *_clone_config_value(struct dm_pool *mem,
|
||||
{
|
||||
struct dm_config_value *new_cv;
|
||||
|
||||
if (!(new_cv = _create_value(mem))) {
|
||||
log_error("Failed to clone config value.");
|
||||
return NULL;
|
||||
if (v->type == DM_CFG_STRING) {
|
||||
if (!(new_cv = _create_str_value(mem, v->v.str, strlen(v->v.str)))) {
|
||||
log_error("Failed to clone string config value.");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (!(new_cv = _create_value(mem))) {
|
||||
log_error("Failed to clone config value.");
|
||||
return NULL;
|
||||
}
|
||||
new_cv->v = v->v;
|
||||
}
|
||||
|
||||
new_cv->type = v->type;
|
||||
if (v->type == DM_CFG_STRING) {
|
||||
if (!(new_cv->v.str = dm_pool_strdup(mem, v->v.str))) {
|
||||
log_error("Failed to clone config string value.");
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
new_cv->v = v->v;
|
||||
|
||||
if (v->next && !(new_cv->next = _clone_config_value(mem, v->next)))
|
||||
return_NULL;
|
||||
@@ -1356,16 +1446,11 @@ struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(new_cn = _create_node(mem))) {
|
||||
if (!(new_cn = _create_node(mem, cn->key, cn->key ? strlen(cn->key) : 0))) {
|
||||
log_error("Failed to clone config node.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((cn->key && !(new_cn->key = dm_pool_strdup(mem, cn->key)))) {
|
||||
log_error("Failed to clone config node key.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_cn->id = cn->id;
|
||||
|
||||
if ((cn->v && !(new_cn->v = _clone_config_value(mem, cn->v))) ||
|
||||
@@ -1376,23 +1461,20 @@ struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const
|
||||
return new_cn;
|
||||
}
|
||||
|
||||
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *node, int sib)
|
||||
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *cn, int sib)
|
||||
{
|
||||
return dm_config_clone_node_with_mem(cft->mem, node, sib);
|
||||
return dm_config_clone_node_with_mem(cft->mem, cn, sib);
|
||||
}
|
||||
|
||||
struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key)
|
||||
{
|
||||
struct dm_config_node *cn;
|
||||
|
||||
if (!(cn = _create_node(cft->mem))) {
|
||||
if (!(cn = _create_node(cft->mem, key, strlen(key)))) {
|
||||
log_error("Failed to create config node.");
|
||||
return NULL;
|
||||
}
|
||||
if (!(cn->key = dm_pool_strdup(cft->mem, key))) {
|
||||
log_error("Failed to create config node's key.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cn->parent = NULL;
|
||||
cn->v = NULL;
|
||||
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#include "misc/dm-ioctl.h"
|
||||
#include "vdo/target.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
@@ -152,15 +151,17 @@ struct thin_message {
|
||||
struct load_segment {
|
||||
struct dm_list list;
|
||||
|
||||
unsigned type;
|
||||
|
||||
uint64_t size;
|
||||
|
||||
unsigned type;
|
||||
|
||||
unsigned area_count; /* Linear + Striped + Mirrored + Crypt */
|
||||
struct dm_list areas; /* Linear + Striped + Mirrored + Crypt */
|
||||
|
||||
uint32_t stripe_size; /* Striped + raid */
|
||||
|
||||
uint32_t region_size; /* Mirror + raid */
|
||||
|
||||
int persistent; /* Snapshot */
|
||||
uint32_t chunk_size; /* Snapshot */
|
||||
struct dm_tree_node *cow; /* Snapshot */
|
||||
@@ -168,7 +169,6 @@ struct load_segment {
|
||||
struct dm_tree_node *merge; /* Snapshot */
|
||||
|
||||
struct dm_tree_node *log; /* Mirror */
|
||||
uint32_t region_size; /* Mirror + raid */
|
||||
unsigned clustered; /* Mirror */
|
||||
unsigned mirror_area_count; /* Mirror */
|
||||
uint64_t flags; /* Mirror + Raid + Cache */
|
||||
@@ -265,7 +265,7 @@ struct load_properties {
|
||||
/*
|
||||
* Preload tree normally only loads and not resume, but there is
|
||||
* automatic resume when target is extended, as it's believed
|
||||
* there can be no i/o flying to this 'new' extedend space
|
||||
* there can be no i/o flying to this 'new' extended space
|
||||
* from any device above. Reason is that preloaded target above
|
||||
* may actually need to see its bigger subdevice before it
|
||||
* gets suspended. As long as devices are simple linears
|
||||
@@ -277,7 +277,7 @@ struct load_properties {
|
||||
|
||||
/*
|
||||
* When comparing table lines to decide if a reload is
|
||||
* needed, ignore any differences betwen the lvm device
|
||||
* needed, ignore any differences between the lvm device
|
||||
* params and the kernel-reported device params.
|
||||
* dm-integrity reports many internal parameters on the
|
||||
* table line when lvm does not explicitly set them,
|
||||
@@ -288,8 +288,8 @@ struct load_properties {
|
||||
/*
|
||||
* Call node_send_messages(), set to 2 if there are messages
|
||||
* When != 0, it validates matching transaction id, thus thin-pools
|
||||
* where transation_id is passed as 0 are never validated, this
|
||||
* allows external managment of thin-pool TID.
|
||||
* where transaction_id is passed as 0 are never validated, this
|
||||
* allows external management of thin-pool TID.
|
||||
*/
|
||||
unsigned send_messages;
|
||||
/* Skip suspending node's children, used when sending messages to thin-pool */
|
||||
@@ -540,7 +540,8 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
|
||||
struct dm_tree_node *node;
|
||||
dev_t dev;
|
||||
|
||||
if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
|
||||
if (!dtree || !dtree->mem ||
|
||||
!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
|
||||
!(node->name = dm_pool_strdup(dtree->mem, name)) ||
|
||||
!(node->uuid = dm_pool_strdup(dtree->mem, uuid))) {
|
||||
log_error("_create_dm_tree_node alloc failed.");
|
||||
@@ -968,7 +969,7 @@ static int _check_device_not_in_use(const char *name, struct dm_info *info)
|
||||
} else if (dm_device_has_holders(info->major, info->minor))
|
||||
reason = "is used by another device";
|
||||
else if (dm_device_has_mounted_fs(info->major, info->minor))
|
||||
reason = "constains a filesystem in use";
|
||||
reason = "contains a filesystem in use";
|
||||
else
|
||||
return 1;
|
||||
|
||||
@@ -1816,7 +1817,7 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
|
||||
|
||||
if (info.open_count) {
|
||||
/* Skip internal non-toplevel opened nodes */
|
||||
/* On some old udev systems without corrrect udev rules
|
||||
/* On some old udev systems without correct udev rules
|
||||
* this hack avoids 'leaking' active _mimageX legs after
|
||||
* deactivation of mirror LV. Other suffixes are not added
|
||||
* since it's expected newer systems with wider range of
|
||||
@@ -2182,7 +2183,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
|
||||
/*
|
||||
* FIXME: Implement delayed error reporting
|
||||
* activation should be stopped only in the case,
|
||||
* the submission of transation_id message fails,
|
||||
* the submission of transaction_id message fails,
|
||||
* resume should continue further, just whole command
|
||||
* has to report failure.
|
||||
*/
|
||||
@@ -2274,7 +2275,7 @@ static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* simplify string emiting code */
|
||||
/* simplify string emitting code */
|
||||
#define EMIT_PARAMS(p, str...)\
|
||||
do {\
|
||||
int w;\
|
||||
@@ -2868,6 +2869,8 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
|
||||
count++;
|
||||
if (set->sectors_per_bit_set)
|
||||
count++;
|
||||
if (set->allow_discards_set && set->allow_discards)
|
||||
count++;
|
||||
|
||||
EMIT_PARAMS(pos, "%s 0 %u %s %d fix_padding block_size:%u internal_hash:%s",
|
||||
origin_dev,
|
||||
@@ -2887,7 +2890,7 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
|
||||
EMIT_PARAMS(pos, " journal_sectors:%u", set->journal_sectors);
|
||||
|
||||
if (set->interleave_sectors_set)
|
||||
EMIT_PARAMS(pos, " ineterleave_sectors:%u", set->interleave_sectors);
|
||||
EMIT_PARAMS(pos, " interleave_sectors:%u", set->interleave_sectors);
|
||||
|
||||
if (set->buffer_sectors_set)
|
||||
EMIT_PARAMS(pos, " buffer_sectors:%u", set->buffer_sectors);
|
||||
@@ -2904,6 +2907,9 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
|
||||
if (set->sectors_per_bit_set)
|
||||
EMIT_PARAMS(pos, " sectors_per_bit:%llu", (unsigned long long)set->sectors_per_bit);
|
||||
|
||||
if (set->allow_discards_set && set->allow_discards)
|
||||
EMIT_PARAMS(pos, " allow_discards");
|
||||
|
||||
if (!dm_task_secure_data(dmt))
|
||||
stack;
|
||||
|
||||
@@ -2965,7 +2971,7 @@ static int _vdo_emit_segment_line(struct dm_task *dmt, uint32_t major, uint32_t
|
||||
* If there is already running VDO target, read 'existing' virtual size out of table line
|
||||
* and avoid reading it them from VDO metadata device
|
||||
*
|
||||
* NOTE: ATM VDO virtual size can be ONLY extended thus it's simple to recongnize 'right' size.
|
||||
* NOTE: ATM VDO virtual size can be ONLY extended thus it's simple to recognize 'right' size.
|
||||
* However if there would be supported also reduction, this check would need to check range.
|
||||
*/
|
||||
if ((vdo_dmt = dm_task_create(DM_DEVICE_TABLE))) {
|
||||
@@ -3377,7 +3383,7 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
|
||||
if (!child->info.exists && !(node_created = _create_node(child, dnode)))
|
||||
return_0;
|
||||
|
||||
/* Propagate delayed resume from exteded child node */
|
||||
/* Propagate delayed resume from extended child node */
|
||||
if (child->props.delay_resume_if_extended)
|
||||
dnode->props.delay_resume_if_extended = 1;
|
||||
|
||||
@@ -3813,7 +3819,7 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
|
||||
* - maximum 253 legs in a raid set (MD kernel limitation)
|
||||
* - delta_disks for disk add/remove reshaping
|
||||
* - data_offset for out-of-place reshaping
|
||||
* - data_copies to cope witth odd numbers of raid10 disks
|
||||
* - data_copies to cope with odd numbers of raid10 disks
|
||||
*/
|
||||
int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
@@ -4077,7 +4083,7 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
|
||||
uint32_t slog_flags,
|
||||
uint32_t slog_region_size)
|
||||
{
|
||||
log_error("Replicator targer is unsupported.");
|
||||
log_error("Replicator target is unsupported.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "base/memory/zalloc.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <langinfo.h>
|
||||
#include <math.h> /* fabs() */
|
||||
#include <float.h> /* DBL_EPSILON */
|
||||
#include <time.h>
|
||||
@@ -31,6 +32,7 @@
|
||||
|
||||
struct selection {
|
||||
struct dm_pool *mem;
|
||||
struct dm_pool *regex_mem;
|
||||
struct selection_node *selection_root;
|
||||
int add_new_fields;
|
||||
};
|
||||
@@ -204,7 +206,9 @@ static const struct op_def _op_log[] = {
|
||||
|
||||
struct selection_str_list {
|
||||
struct dm_str_list str_list;
|
||||
unsigned type; /* either SEL_AND or SEL_OR */
|
||||
struct dm_regex *regex;
|
||||
size_t regex_num_patterns;
|
||||
unsigned type; /* either SEL_LIST_LS or SEL_LIST_SUBSET_LS with either SEL_AND or SEL_OR */
|
||||
};
|
||||
|
||||
struct field_selection_value {
|
||||
@@ -459,7 +463,7 @@ static int _report_field_string_list(struct dm_report *rh,
|
||||
*
|
||||
* The very first item in the array of 'struct pos_len' is always
|
||||
* a pair denoting '[list_size,strlen(field->report_string)]'. The
|
||||
* rest of items denote start and lenght of each item in the list.
|
||||
* rest of items denote start and length of each item in the list.
|
||||
*
|
||||
*
|
||||
* For example, if we have a list with "abc", "xy", "defgh"
|
||||
@@ -547,7 +551,7 @@ static int _report_field_string_list(struct dm_report *rh,
|
||||
}
|
||||
|
||||
/* more than one item - allocate temporary array for string list items for further processing */
|
||||
if (!(arr = malloc(list_size * sizeof(struct str_pos_len)))) {
|
||||
if (!(arr = zalloc(list_size * sizeof(struct str_pos_len)))) {
|
||||
log_error("%s failed to allocate temporary array for processing", _error_msg_prefix);
|
||||
goto out;
|
||||
}
|
||||
@@ -589,7 +593,8 @@ static int _report_field_string_list(struct dm_report *rh,
|
||||
for (i = 0, pos = 0; i < list_size; i++) {
|
||||
arr[i].item.pos = pos;
|
||||
|
||||
memcpy(repstr + pos, arr[i].str, arr[i].item.len);
|
||||
if (arr[i].str)
|
||||
memcpy(repstr + pos, arr[i].str, arr[i].item.len);
|
||||
memcpy(repstr_extra + i + 1, &arr[i].item, sizeof(struct pos_len));
|
||||
|
||||
pos += arr[i].item.len;
|
||||
@@ -1396,7 +1401,7 @@ struct dm_report *dm_report_init(uint32_t *report_types,
|
||||
}
|
||||
|
||||
/*
|
||||
* Return updated types value for further compatility check by caller.
|
||||
* Return updated types value for further compatibility check by caller.
|
||||
*/
|
||||
_dm_report_init_update_types(rh, report_types);
|
||||
|
||||
@@ -1411,8 +1416,11 @@ struct dm_report *dm_report_init(uint32_t *report_types,
|
||||
|
||||
void dm_report_free(struct dm_report *rh)
|
||||
{
|
||||
if (rh->selection)
|
||||
if (rh->selection) {
|
||||
dm_pool_destroy(rh->selection->mem);
|
||||
if (rh->selection->regex_mem)
|
||||
dm_pool_destroy(rh->selection->regex_mem);
|
||||
}
|
||||
if (rh->value_cache)
|
||||
dm_hash_destroy(rh->value_cache);
|
||||
dm_pool_destroy(rh->mem);
|
||||
@@ -1751,8 +1759,74 @@ static int _cmp_field_time(struct dm_report *rh,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _str_list_item_match_regex(const struct str_list_sort_value *val, unsigned int i, struct dm_regex *regex)
|
||||
{
|
||||
struct pos_len *item = val->items + i;
|
||||
char *s = (char *) (val->value + item->pos);
|
||||
char c = s[item->len];
|
||||
int r;
|
||||
|
||||
/*
|
||||
* The val->items contains the whole string list in the form of a single string,
|
||||
* where each item is delimited by a delimiter.
|
||||
*
|
||||
* The item->pos + item->len pair then points to the exact item within the val->items.
|
||||
*
|
||||
* The dm_regex_match accepts a string, not the pos + len pair, so we need to adapt here:
|
||||
* replace the delimiter with '\0' temporarily so the item is a proper string.
|
||||
*/
|
||||
s[item->len] = '\0';
|
||||
r = dm_regex_match(regex, s);
|
||||
s[item->len] = c;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static size_t _bitset_count_set(dm_bitset_t bs)
|
||||
{
|
||||
size_t i, size = bs[0]/DM_BITS_PER_INT + 1;
|
||||
size_t count = 0;
|
||||
|
||||
for (i = 1; i <= size; i++)
|
||||
count += hweight32(bs[i]);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match list value strictly 1:1. */
|
||||
static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *val,
|
||||
static int _cmp_field_string_list_strict_regex_all(const struct dm_report *rh,
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int i;
|
||||
dm_bitset_t bs;
|
||||
int r;
|
||||
|
||||
if (!val->items)
|
||||
return (sel->regex_num_patterns == 1) && dm_regex_match(sel->regex, "") >= 0;
|
||||
|
||||
if (!(bs = dm_bitset_create(rh->selection->mem, sel->regex_num_patterns))) {
|
||||
log_error("Failed to create bitset for regex match counter.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
if ((r = _str_list_item_match_regex(val, i, sel->regex)) < 0) {
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
dm_bit_set(bs, r);
|
||||
}
|
||||
|
||||
r = _bitset_count_set(bs) == sel->regex_num_patterns;
|
||||
out:
|
||||
dm_pool_free(rh->selection->mem, bs);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match list value strictly 1:1. */
|
||||
static int _cmp_field_string_list_strict_all(const struct dm_report *rh,
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int sel_list_size = dm_list_size(&sel->str_list.list);
|
||||
@@ -1784,7 +1858,36 @@ static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *v
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match a subset of list value. */
|
||||
static int _cmp_field_string_list_subset_all(const struct str_list_sort_value *val,
|
||||
static int _cmp_field_string_list_subset_regex_all(const struct dm_report *rh,
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
dm_bitset_t bs;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
if (!val->items)
|
||||
return (sel->regex_num_patterns == 1) && dm_regex_match(sel->regex, "") >= 0;
|
||||
|
||||
if (!(bs = dm_bitset_create(rh->selection->mem, sel->regex_num_patterns))) {
|
||||
log_error("Failed to create bitset for regex match counter.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
if ((r = _str_list_item_match_regex(val, i, sel->regex)) < 0)
|
||||
continue;
|
||||
dm_bit_set(bs, r);
|
||||
}
|
||||
|
||||
r = _bitset_count_set(bs) == sel->regex_num_patterns;
|
||||
dm_pool_free(rh->selection->mem, bs);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match a subset of list value. */
|
||||
static int _cmp_field_string_list_subset_all(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int sel_list_size = dm_list_size(&sel->str_list.list);
|
||||
@@ -1819,8 +1922,26 @@ static int _cmp_field_string_list_subset_all(const struct str_list_sort_value *v
|
||||
}
|
||||
|
||||
/* Matches if any item from selection string list matches list value. */
|
||||
static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
static int _cmp_field_string_list_subset_regex_any(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!val->items)
|
||||
return dm_regex_match(sel->regex, "") >= 0;
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
if (_str_list_item_match_regex(val, i, sel->regex) >= 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Matches if any item from selection string list matches list value. */
|
||||
static int _cmp_field_string_list_subset_any(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
struct dm_str_list *sel_item;
|
||||
unsigned int i;
|
||||
@@ -1849,7 +1970,59 @@ static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _cmp_field_string_list(struct dm_report *rh __attribute__((unused)),
|
||||
/* Matches if all items from list value can be matched by any item from selection list. */
|
||||
static int _cmp_field_string_list_strict_regex_any(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!val->items)
|
||||
return dm_regex_match(sel->regex, "") >= 0;
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
if (_str_list_item_match_regex(val, i, sel->regex) < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Matches if all items from list value can be matched by any item from selection list. */
|
||||
static int _cmp_field_string_list_strict_any(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
struct dm_str_list *sel_item;
|
||||
unsigned int i;
|
||||
int match;
|
||||
|
||||
/* match blank string list with selection that contains blank string */
|
||||
if (!val->items) {
|
||||
dm_list_iterate_items(sel_item, &sel->str_list.list) {
|
||||
if (!strcmp(sel_item->str, ""))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
match = 0;
|
||||
dm_list_iterate_items(sel_item, &sel->str_list.list) {
|
||||
if ((strlen(sel_item->str) == val->items[i].len) &&
|
||||
!strncmp(sel_item->str, val->value + val->items[i].pos, val->items[i].len)) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cmp_field_string_list(struct dm_report *rh,
|
||||
uint32_t field_num, const char *field_id,
|
||||
const struct str_list_sort_value *val,
|
||||
struct field_selection *fs)
|
||||
@@ -1871,11 +2044,16 @@ static int _cmp_field_string_list(struct dm_report *rh __attribute__((unused)),
|
||||
|
||||
switch (sel->type & SEL_MASK) {
|
||||
case SEL_AND:
|
||||
r = subset ? _cmp_field_string_list_subset_all(val, sel)
|
||||
: _cmp_field_string_list_strict_all(val, sel);
|
||||
r = subset ? sel->regex ? _cmp_field_string_list_subset_regex_all(rh, val, sel)
|
||||
: _cmp_field_string_list_subset_all(rh, val, sel)
|
||||
: sel->regex ? _cmp_field_string_list_strict_regex_all(rh, val, sel)
|
||||
: _cmp_field_string_list_strict_all(rh, val, sel);
|
||||
break;
|
||||
case SEL_OR:
|
||||
r = _cmp_field_string_list_any(val, sel);
|
||||
r = subset ? sel->regex ? _cmp_field_string_list_subset_regex_any(rh, val, sel)
|
||||
: _cmp_field_string_list_subset_any(rh, val, sel)
|
||||
: sel->regex ? _cmp_field_string_list_strict_regex_any(rh, val, sel)
|
||||
: _cmp_field_string_list_strict_any(rh, val, sel);
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_cmp_field_string_list: unsupported string "
|
||||
@@ -1909,7 +2087,17 @@ static int _compare_selection_field(struct dm_report *rh,
|
||||
}
|
||||
|
||||
if (fs->flags & FLD_CMP_REGEX)
|
||||
r = _cmp_field_regex((const char *) f->sort_value, fs);
|
||||
switch (f->props->flags & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
case DM_REPORT_FIELD_TYPE_STRING:
|
||||
r = _cmp_field_regex((const char *) f->sort_value, fs);
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_STRING_LIST:
|
||||
r = _cmp_field_string_list(rh, f->props->field_num, field_id, (const struct str_list_sort_value *) f->sort_value, fs);
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_compare_selection_field: regex: incorrect type %" PRIu32 " for field %s",
|
||||
f->props->flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
}
|
||||
else {
|
||||
switch(f->props->flags & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
case DM_REPORT_FIELD_TYPE_PERCENT:
|
||||
@@ -1936,7 +2124,8 @@ static int _compare_selection_field(struct dm_report *rh,
|
||||
r = _cmp_field_time(rh, f->props->field_num, field_id, *(const time_t *) f->sort_value, fs);
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_compare_selection_field: unknown field type for field %s", field_id);
|
||||
log_error(INTERNAL_ERROR "_compare_selection_field: incorrect type %" PRIu32 " for field %s",
|
||||
f->props->flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2430,7 +2619,7 @@ static const char *_reserved_name(struct dm_report *rh,
|
||||
(reserved->type & DM_REPORT_FIELD_TYPE_MASK) ? "type-specific" : "field-specific",
|
||||
rh->fields[field_num].id);
|
||||
else
|
||||
log_error("Error occured while processing %s reserved value handler for field %s",
|
||||
log_error("Error occurred while processing %s reserved value handler for field %s",
|
||||
(reserved->type & DM_REPORT_FIELD_TYPE_MASK) ? "type-specific" : "field-specific",
|
||||
rh->fields[field_num].id);
|
||||
}
|
||||
@@ -2628,11 +2817,9 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
|
||||
static const char *_tok_value_regex(struct dm_report *rh,
|
||||
const struct dm_report_field_type *ft,
|
||||
const char *s, const char **begin,
|
||||
const char **end, uint32_t *flags,
|
||||
struct reserved_value_wrapper *rvw)
|
||||
const char **end, uint32_t *flags)
|
||||
{
|
||||
char c;
|
||||
rvw->reserved = NULL;
|
||||
|
||||
s = _skip_space(s);
|
||||
|
||||
@@ -2695,7 +2882,8 @@ static int _add_item_to_string_list(struct dm_pool *mem, const char *begin,
|
||||
static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
struct dm_pool *mem, const char *s,
|
||||
const char **begin, const char **end,
|
||||
struct selection_str_list **sel_str_list)
|
||||
struct selection_str_list **sel_str_list,
|
||||
uint32_t *flags)
|
||||
{
|
||||
static const char _str_list_item_parsing_failed[] = "Failed to parse string list value "
|
||||
"for selection field %s.";
|
||||
@@ -2709,12 +2897,11 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
int list_end = 0;
|
||||
char c;
|
||||
|
||||
if (!(ssl = dm_pool_alloc(mem, sizeof(*ssl)))) {
|
||||
log_error("_tok_value_string_list: memory allocation failed for selection list");
|
||||
if (!(ssl = dm_pool_zalloc(mem, sizeof(*ssl)))) {
|
||||
log_error("_tok_value_string_list: memory allocation failed for selection list.");
|
||||
goto bad;
|
||||
}
|
||||
dm_list_init(&ssl->str_list.list);
|
||||
ssl->type = 0;
|
||||
*begin = s;
|
||||
|
||||
if (!(op_flags = _tok_op_log(s, &tmp, SEL_LIST_LS | SEL_LIST_SUBSET_LS))) {
|
||||
@@ -2726,7 +2913,7 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
}
|
||||
if (!_add_item_to_string_list(mem, begin_item, end_item, &ssl->str_list.list))
|
||||
goto_bad;
|
||||
ssl->type = SEL_OR | SEL_LIST_LS;
|
||||
ssl->type = SEL_OR | SEL_LIST_SUBSET_LS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2801,12 +2988,17 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
else
|
||||
ssl->type |= SEL_LIST_SUBSET_LS;
|
||||
|
||||
/* Sort the list. */
|
||||
if (!(list_size = dm_list_size(&ssl->str_list.list))) {
|
||||
log_error(INTERNAL_ERROR "_tok_value_string_list: list has no items");
|
||||
goto bad;
|
||||
} else if (list_size == 1)
|
||||
goto out;
|
||||
|
||||
if (*flags & FLD_CMP_REGEX)
|
||||
/* No need to sort the list for regex. */
|
||||
goto out;
|
||||
|
||||
/* Sort the list. */
|
||||
if (!(arr = malloc(sizeof(item) * list_size))) {
|
||||
log_error("_tok_value_string_list: memory allocation failed for sort array");
|
||||
goto bad;
|
||||
@@ -3135,7 +3327,9 @@ static int _local_tz_offset(time_t t_local)
|
||||
time_t t_gmt;
|
||||
|
||||
gmtime_r(&t_local, &tm_gmt);
|
||||
t_gmt = mktime(&tm_gmt);
|
||||
|
||||
if ((t_gmt = mktime(&tm_gmt)) < 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* gmtime returns time that is adjusted
|
||||
@@ -3146,7 +3340,7 @@ static int _local_tz_offset(time_t t_local)
|
||||
if (tm_gmt.tm_isdst)
|
||||
t_gmt -= 3600;
|
||||
|
||||
return t_local - t_gmt;
|
||||
return (int)(t_local - t_gmt);
|
||||
}
|
||||
|
||||
static void _get_final_time(time_range_t range, struct tm *tm,
|
||||
@@ -3322,7 +3516,10 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
|
||||
s = _skip_space(s);
|
||||
|
||||
s = _get_reserved(rh, expected_type, field_num, implicit, s, begin, end, rvw);
|
||||
/* recognize possible reserved value (but not in a regex) */
|
||||
if (!(*flags & FLD_CMP_REGEX))
|
||||
s = _get_reserved(rh, expected_type, field_num, implicit, s, begin, end, rvw);
|
||||
|
||||
if (rvw->reserved) {
|
||||
/*
|
||||
* FLD_CMP_NUMBER shares operators with FLD_CMP_TIME,
|
||||
@@ -3333,17 +3530,24 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
else if (expected_type == DM_REPORT_FIELD_TYPE_NUMBER)
|
||||
*flags &= ~FLD_CMP_TIME;
|
||||
*flags |= expected_type;
|
||||
|
||||
/* if we matched a reserved value, skip further processing of this token */
|
||||
return s;
|
||||
}
|
||||
|
||||
switch (expected_type) {
|
||||
|
||||
case DM_REPORT_FIELD_TYPE_STRING:
|
||||
c = _get_and_skip_quote_char(&s);
|
||||
if (!(s = _tok_value_string(s, begin, end, c, SEL_AND | SEL_OR | SEL_PRECEDENCE_PE, NULL))) {
|
||||
log_error("Failed to parse string value "
|
||||
"for selection field %s.", ft->id);
|
||||
return NULL;
|
||||
if (*flags & FLD_CMP_REGEX) {
|
||||
if (!(s = _tok_value_regex(rh, ft, s, begin, end, flags)))
|
||||
return NULL;
|
||||
} else {
|
||||
c = _get_and_skip_quote_char(&s);
|
||||
if (!(s = _tok_value_string(s, begin, end, c, SEL_AND | SEL_OR | SEL_PRECEDENCE_PE, NULL))) {
|
||||
log_error("Failed to parse string value "
|
||||
"for selection field %s.", ft->id);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*flags |= DM_REPORT_FIELD_TYPE_STRING;
|
||||
break;
|
||||
@@ -3352,7 +3556,7 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
if (!(str_list = (struct selection_str_list **) custom))
|
||||
goto_bad;
|
||||
|
||||
s = _tok_value_string_list(ft, mem, s, begin, end, str_list);
|
||||
s = _tok_value_string_list(ft, mem, s, begin, end, str_list, flags);
|
||||
if (!(*str_list)) {
|
||||
log_error("Failed to parse string list value "
|
||||
"for selection field %s.", ft->id);
|
||||
@@ -3436,7 +3640,7 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
|
||||
return s;
|
||||
bad:
|
||||
log_error(INTERNAL_ERROR "Forbidden NULL custom detected.");
|
||||
log_error(INTERNAL_ERROR "_tok_value: Forbidden NULL custom parameter detected.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -3496,7 +3700,7 @@ static int _get_reserved_value(struct dm_report *rh, uint32_t field_num,
|
||||
(rvw->reserved->type) & DM_REPORT_FIELD_TYPE_MASK ? "type-specific" : "field-specific",
|
||||
rh->fields[field_num].id);
|
||||
else
|
||||
log_error("Error occured while processing %s reserved value handler for field %s",
|
||||
log_error("Error occurred while processing %s reserved value handler for field %s",
|
||||
(rvw->reserved->type) & DM_REPORT_FIELD_TYPE_MASK ? "type-specific" : "field-specific",
|
||||
rh->fields[field_num].id);
|
||||
return 0;
|
||||
@@ -3507,6 +3711,19 @@ static int _get_reserved_value(struct dm_report *rh, uint32_t field_num,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct dm_regex *_selection_regex_create(struct selection *selection, const char * const *patterns,
|
||||
unsigned num_patterns)
|
||||
{
|
||||
if (!selection->regex_mem) {
|
||||
if (!(selection->regex_mem = dm_pool_create("report selection regex", 32 * 1024))) {
|
||||
log_error("Failed to create report selection regex memory pool.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return dm_regex_create(selection->regex_mem, patterns, num_patterns);
|
||||
}
|
||||
|
||||
static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
uint32_t field_num,
|
||||
int implicit,
|
||||
@@ -3524,6 +3741,11 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
struct time_value *tval;
|
||||
uint64_t factor;
|
||||
char *s;
|
||||
const char *s_arr_single[2] = { 0 };
|
||||
const char **s_arr;
|
||||
size_t s_arr_size;
|
||||
struct dm_str_list *sl;
|
||||
size_t i;
|
||||
|
||||
dm_list_iterate_items(fp, &rh->field_props) {
|
||||
if ((fp->implicit == implicit) && (fp->field_num == field_num)) {
|
||||
@@ -3588,20 +3810,55 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
/* store comparison operand */
|
||||
if (flags & FLD_CMP_REGEX) {
|
||||
/* REGEX */
|
||||
if (!(s = malloc(len + 1))) {
|
||||
log_error("dm_report: malloc failed to store "
|
||||
"regex value for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
memcpy(s, v, len);
|
||||
s[len] = '\0';
|
||||
switch (flags & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
case DM_REPORT_FIELD_TYPE_STRING:
|
||||
if (!(s = malloc(len + 1))) {
|
||||
log_error("dm_report: malloc failed to store "
|
||||
"regex value for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
memcpy(s, v, len);
|
||||
s[len] = '\0';
|
||||
s_arr_single[0] = s;
|
||||
|
||||
fs->value->v.r = dm_regex_create(rh->selection->mem, (const char * const *) &s, 1);
|
||||
free(s);
|
||||
if (!fs->value->v.r) {
|
||||
log_error("dm_report: failed to create regex "
|
||||
"matcher for selection field %s", field_id);
|
||||
goto error;
|
||||
fs->value->v.r = _selection_regex_create(rh->selection, s_arr_single, 1);
|
||||
free(s);
|
||||
if (!fs->value->v.r) {
|
||||
log_error("dm_report: failed to create regex "
|
||||
"matcher for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_STRING_LIST:
|
||||
if (!custom)
|
||||
goto bad;
|
||||
fs->value->v.l = *((struct selection_str_list **) custom);
|
||||
|
||||
if (!(s_arr_size = dm_list_size(&fs->value->v.l->str_list.list)))
|
||||
break;
|
||||
|
||||
if (!(s_arr = calloc(s_arr_size, sizeof(char *)))) {
|
||||
log_error("dm_report: malloc failed for regex array "
|
||||
"for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
i = 0;
|
||||
dm_list_iterate_items(sl, &fs->value->v.l->str_list.list)
|
||||
s_arr[i++] = sl->str;
|
||||
|
||||
fs->value->v.l->regex = _selection_regex_create(rh->selection, s_arr, s_arr_size);
|
||||
fs->value->v.l->regex_num_patterns = s_arr_size;
|
||||
free(s_arr);
|
||||
if (!fs->value->v.l->regex) {
|
||||
log_error("dm_report: failed to create regex "
|
||||
"matcher for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: regex: incorrect type %" PRIu32 " for field %s",
|
||||
flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
/* STRING, NUMBER, SIZE, PERCENT, STRING_LIST, TIME */
|
||||
@@ -3715,8 +3972,8 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: "
|
||||
"unknown type of selection field %s", field_id);
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: incorrect type %" PRIu32 " for field %s",
|
||||
flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -3727,7 +3984,7 @@ error_field_id:
|
||||
field_id);
|
||||
goto error;
|
||||
bad:
|
||||
log_error(INTERNAL_ERROR "Forbiden NULL custom detected.");
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: Forbidden NULL custom detected.");
|
||||
error:
|
||||
dm_pool_free(rh->selection->mem, fs);
|
||||
|
||||
@@ -3821,8 +4078,11 @@ out_reserved_values:
|
||||
log_warn(" ");
|
||||
}
|
||||
|
||||
static const char _sel_syntax_error_at_msg[] = "Selection syntax error at '%s'.";
|
||||
static const char _sel_help_ref_msg[] = "Use \'help\' for selection to get more help.";
|
||||
static void _parse_syntax_error(const char *s)
|
||||
{
|
||||
log_error("Selection syntax error at '%s'.", s);
|
||||
log_error("Use \'help\' for selection to get more help.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Selection parser
|
||||
@@ -3863,7 +4123,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
char *tmp;
|
||||
char c;
|
||||
|
||||
/* field name */
|
||||
/* get field name */
|
||||
if (!(last = _tok_field_name(s, &ws, &we))) {
|
||||
log_error("Expecting field name");
|
||||
goto bad;
|
||||
@@ -3896,7 +4156,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
} else
|
||||
ft = &rh->fields[field_num];
|
||||
|
||||
/* comparison operator */
|
||||
/* get comparison operator */
|
||||
if (!(flags = _tok_op_cmp(we, &last))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Unrecognised comparison operator: %s", we);
|
||||
@@ -3908,50 +4168,49 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* comparison value */
|
||||
/* check we can use the operator with the field */
|
||||
if (flags & FLD_CMP_REGEX) {
|
||||
/*
|
||||
* REGEX value
|
||||
*/
|
||||
if (!(last = _tok_value_regex(rh, ft, last, &vs, &ve, &flags, &rvw)))
|
||||
goto_bad;
|
||||
} else {
|
||||
/*
|
||||
* STRING, NUMBER, SIZE, PERCENT, STRING_LIST, TIME value
|
||||
*/
|
||||
if (flags & FLD_CMP_NUMBER) {
|
||||
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_NUMBER |
|
||||
DM_REPORT_FIELD_TYPE_SIZE |
|
||||
DM_REPORT_FIELD_TYPE_PERCENT |
|
||||
DM_REPORT_FIELD_TYPE_TIME))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with number, size, time or percent fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
} else if (flags & FLD_CMP_TIME) {
|
||||
if (!(ft->flags & DM_REPORT_FIELD_TYPE_TIME)) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with time fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_STRING |
|
||||
DM_REPORT_FIELD_TYPE_STRING_LIST))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with string or string list fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
} else if (flags & FLD_CMP_NUMBER) {
|
||||
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_NUMBER |
|
||||
DM_REPORT_FIELD_TYPE_SIZE |
|
||||
DM_REPORT_FIELD_TYPE_PERCENT |
|
||||
DM_REPORT_FIELD_TYPE_TIME))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with number, size, time or percent fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
} else if (flags & FLD_CMP_TIME) {
|
||||
if (!(ft->flags & DM_REPORT_FIELD_TYPE_TIME)) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with time fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (ft->flags == DM_REPORT_FIELD_TYPE_SIZE ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_NUMBER ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_PERCENT)
|
||||
custom = &factor;
|
||||
else if (ft->flags & DM_REPORT_FIELD_TYPE_TIME)
|
||||
custom = &tval;
|
||||
else if (ft->flags == DM_REPORT_FIELD_TYPE_STRING_LIST)
|
||||
custom = &str_list;
|
||||
else
|
||||
custom = NULL;
|
||||
if (!(last = _tok_value(rh, ft, field_num, implicit,
|
||||
last, &vs, &ve, &flags,
|
||||
&rvw, rh->selection->mem, custom)))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
/* assign custom structures to hold extra information for specific value types */
|
||||
if (ft->flags == DM_REPORT_FIELD_TYPE_SIZE ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_NUMBER ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_PERCENT)
|
||||
custom = &factor;
|
||||
else if (ft->flags & DM_REPORT_FIELD_TYPE_TIME)
|
||||
custom = &tval;
|
||||
else if (ft->flags == DM_REPORT_FIELD_TYPE_STRING_LIST)
|
||||
custom = &str_list;
|
||||
else
|
||||
custom = NULL;
|
||||
|
||||
/* get value to compare with */
|
||||
if (!(last = _tok_value(rh, ft, field_num, implicit,
|
||||
last, &vs, &ve, &flags,
|
||||
&rvw, rh->selection->mem, custom)))
|
||||
goto_bad;
|
||||
|
||||
*next = _skip_space(last);
|
||||
|
||||
/* create selection */
|
||||
@@ -3967,8 +4226,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
|
||||
return sn;
|
||||
bad:
|
||||
log_error(_sel_syntax_error_at_msg, s);
|
||||
log_error(_sel_help_ref_msg);
|
||||
_parse_syntax_error(s);
|
||||
*next = s;
|
||||
return NULL;
|
||||
}
|
||||
@@ -4025,7 +4283,7 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* AND_EXPRESSION := EX (AND_OP AND_EXPRSSION) */
|
||||
/* AND_EXPRESSION := EX (AND_OP AND_EXPRESSION) */
|
||||
static struct selection_node *_parse_and_ex(struct dm_report *rh,
|
||||
const char *s,
|
||||
const char **next,
|
||||
@@ -4092,7 +4350,7 @@ error:
|
||||
static int _alloc_rh_selection(struct dm_report *rh)
|
||||
{
|
||||
if (!(rh->selection = dm_pool_zalloc(rh->mem, sizeof(struct selection))) ||
|
||||
!(rh->selection->mem = dm_pool_create("report selection", 10 * 1024))) {
|
||||
!(rh->selection->mem = dm_pool_create("report selection", 1024))) {
|
||||
log_error("Failed to allocate report selection structure.");
|
||||
if (rh->selection)
|
||||
dm_pool_free(rh->mem, rh->selection);
|
||||
@@ -4133,8 +4391,7 @@ static int _report_set_selection(struct dm_report *rh, const char *selection, in
|
||||
next = _skip_space(fin);
|
||||
if (*next) {
|
||||
log_error("Expecting logical operator");
|
||||
log_error(_sel_syntax_error_at_msg, next);
|
||||
log_error(_sel_help_ref_msg);
|
||||
_parse_syntax_error(next);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@@ -4371,9 +4628,10 @@ static int _row_compare(const void *a, const void *b)
|
||||
for (cnt = 0; cnt < rowa->rh->keys_count; cnt++) {
|
||||
sfa = (*rowa->sort_fields)[cnt];
|
||||
sfb = (*rowb->sort_fields)[cnt];
|
||||
if ((sfa->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ||
|
||||
(sfa->props->flags & DM_REPORT_FIELD_TYPE_SIZE) ||
|
||||
(sfa->props->flags & DM_REPORT_FIELD_TYPE_TIME)) {
|
||||
if (sfa->props->flags &
|
||||
((DM_REPORT_FIELD_TYPE_NUMBER) |
|
||||
(DM_REPORT_FIELD_TYPE_SIZE) |
|
||||
(DM_REPORT_FIELD_TYPE_TIME))) {
|
||||
const uint64_t numa =
|
||||
*(const uint64_t *) sfa->sort_value;
|
||||
const uint64_t numb =
|
||||
@@ -4413,9 +4671,12 @@ static int _sort_rows(struct dm_report *rh)
|
||||
struct row *(*rows)[];
|
||||
uint32_t count = 0;
|
||||
struct row *row;
|
||||
size_t cnt_rows;
|
||||
|
||||
if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) *
|
||||
dm_list_size(&rh->rows)))) {
|
||||
if (!(cnt_rows = dm_list_size(&rh->rows)))
|
||||
return 1; /* nothing to sort */
|
||||
|
||||
if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) * cnt_rows))) {
|
||||
log_error("dm_report: sort array allocation failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -4484,6 +4745,7 @@ static const char *_get_field_id(struct dm_report *rh, struct dm_report_field *f
|
||||
|
||||
static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field *field)
|
||||
{
|
||||
char buf_local[8192];
|
||||
char *field_id;
|
||||
int32_t width;
|
||||
uint32_t align;
|
||||
@@ -4491,25 +4753,26 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
|
||||
size_t buf_size = 0;
|
||||
|
||||
if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) {
|
||||
if (!(field_id = strdup(_get_field_id(rh, field)))) {
|
||||
log_error("dm_report: Failed to copy field name");
|
||||
buf_size = strlen(_get_field_id(rh, field)) + 1;
|
||||
if (buf_size >= sizeof(buf_local)) {
|
||||
/* for field names our buf_local should be enough */
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
field_id = buf_local;
|
||||
memcpy(field_id, _get_field_id(rh, field), buf_size);
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
free(field_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
free(field_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(field_id);
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, STANDARD_PAIR, 1)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
@@ -4532,7 +4795,10 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
|
||||
|
||||
/* Including trailing '\0'! */
|
||||
buf_size = width + 1;
|
||||
if (!(buf = malloc(buf_size))) {
|
||||
if (buf_size < sizeof(buf_local))
|
||||
/* Use local buffer on stack for smaller strings */
|
||||
buf = buf_local;
|
||||
else if (!(buf = malloc(buf_size))) {
|
||||
log_error("dm_report: Could not allocate memory for output line buffer.");
|
||||
return 0;
|
||||
}
|
||||
@@ -4574,40 +4840,50 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
if (buf != buf_local)
|
||||
free(buf);
|
||||
return 1;
|
||||
bad:
|
||||
free(buf);
|
||||
if (buf != buf_local)
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _safe_repstr_output(struct dm_report *rh, const char *repstr, size_t len)
|
||||
{
|
||||
const char *p_repstr;
|
||||
const char *repstr_next_write = repstr;
|
||||
const char *repstr_current = repstr;
|
||||
const char *repstr_end = len ? repstr + len : repstr + strlen(repstr);
|
||||
|
||||
/* Escape any JSON_QUOTE that may appear in reported string. */
|
||||
while (1) {
|
||||
if (!(p_repstr = memchr(repstr, JSON_QUOTE[0], repstr_end - repstr)))
|
||||
break;
|
||||
/* Escape any JSON_ESCAPE_CHAR and JSON_QUOTE that may appear in reported string. */
|
||||
while (repstr_current < repstr_end) {
|
||||
if (repstr_current[0] == JSON_ESCAPE_CHAR[0] || repstr_current[0] == JSON_QUOTE[0]) {
|
||||
// Write out all "sanitized" chars so far
|
||||
if (repstr_next_write < repstr_current) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr_next_write, repstr_current - repstr_next_write)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (p_repstr > repstr) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr, p_repstr - repstr)) {
|
||||
repstr_next_write = repstr_current;
|
||||
}
|
||||
|
||||
// Add an escape
|
||||
if (!dm_pool_grow_object(rh->mem, JSON_ESCAPE_CHAR, 1)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, JSON_ESCAPE_CHAR, 1) ||
|
||||
!dm_pool_grow_object(rh->mem, JSON_QUOTE, 1)) {
|
||||
|
||||
++repstr_current;
|
||||
}
|
||||
|
||||
// Write out all remaining "sanitized" chars
|
||||
if (repstr_next_write < repstr_end) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr_next_write, repstr_end - repstr_next_write)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
repstr = p_repstr + 1;
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, repstr, repstr_end - repstr)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -4757,6 +5033,8 @@ static int _output_as_rows(struct dm_report *rh)
|
||||
dm_list_iterate_items(fp, &rh->field_props) {
|
||||
if (fp->flags & FLD_HIDDEN) {
|
||||
dm_list_iterate_items(row, &rh->rows) {
|
||||
if (dm_list_empty(&row->fields))
|
||||
continue;
|
||||
field = dm_list_item(dm_list_first(&row->fields), struct dm_report_field);
|
||||
dm_list_del(&field->list);
|
||||
}
|
||||
@@ -4845,6 +5123,7 @@ static int _output_as_columns(struct dm_report *rh)
|
||||
struct dm_report_field *field;
|
||||
struct dm_list *last_rowh;
|
||||
int do_field_delim;
|
||||
int is_json_report = _is_json_report(rh);
|
||||
char *line;
|
||||
|
||||
/* If headings not printed yet, calculate field widths and print them */
|
||||
@@ -4864,7 +5143,7 @@ static int _output_as_columns(struct dm_report *rh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_is_json_report(rh)) {
|
||||
if (is_json_report) {
|
||||
if (!dm_pool_grow_object(rh->mem, JSON_OBJECT_START, 0)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
@@ -4879,7 +5158,7 @@ static int _output_as_columns(struct dm_report *rh)
|
||||
continue;
|
||||
|
||||
if (do_field_delim) {
|
||||
if (_is_json_report(rh)) {
|
||||
if (is_json_report) {
|
||||
if (!dm_pool_grow_object(rh->mem, JSON_SEPARATOR, 0) ||
|
||||
!dm_pool_grow_object(rh->mem, JSON_SPACE, 0)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
@@ -4901,7 +5180,7 @@ static int _output_as_columns(struct dm_report *rh)
|
||||
dm_list_del(&field->list);
|
||||
}
|
||||
|
||||
if (_is_json_report(rh)) {
|
||||
if (is_json_report) {
|
||||
if (!dm_pool_grow_object(rh->mem, JSON_OBJECT_END, 0)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
@@ -5088,6 +5367,15 @@ struct dm_report_group *dm_report_group_create(dm_report_group_type_t type, void
|
||||
struct dm_pool *mem;
|
||||
struct report_group_item *item;
|
||||
|
||||
if (type == DM_REPORT_GROUP_JSON_STD) {
|
||||
const char * radixchar = nl_langinfo(RADIXCHAR);
|
||||
if (radixchar && strcmp(radixchar, ".")) {
|
||||
log_error("dm_report: incompatible locale used for DM_REPORT_GROUP_JSON_STD, "
|
||||
"radix character is '%s', expected '.'", radixchar);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mem = dm_pool_create("report_group", 1024))) {
|
||||
log_error("dm_report: dm_report_init_group: failed to allocate mem pool");
|
||||
return NULL;
|
||||
@@ -5103,7 +5391,7 @@ struct dm_report_group *dm_report_group_create(dm_report_group_type_t type, void
|
||||
dm_list_init(&group->items);
|
||||
|
||||
if (!(item = dm_pool_zalloc(mem, sizeof(*item)))) {
|
||||
log_error("dm_report: faile to allocate root report group item");
|
||||
log_error("dm_report: failed to allocate root report group item");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@@ -169,7 +169,7 @@ int dm_vasprintf(char **result, const char *format, va_list aq)
|
||||
}
|
||||
|
||||
if (i > 1) {
|
||||
/* Reallocating more then once? */
|
||||
/* Reallocating more than once? */
|
||||
if (!(*result = strdup(buf))) {
|
||||
free(buf);
|
||||
return -1;
|
||||
@@ -471,10 +471,10 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
double d;
|
||||
uint64_t byte = UINT64_C(0);
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
char *size_buf;
|
||||
char new_unit_type = '\0', unit_type_buf[2];
|
||||
const char *prefix = "";
|
||||
const char * const size_str[][3] = {
|
||||
static const char _size_str[][3][12] = {
|
||||
/* BASE_UNKNOWN */
|
||||
{" ", " ", " "}, /* [0] */
|
||||
|
||||
@@ -519,14 +519,14 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
/* Case-independent match */
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (toupper((int) unit_type) ==
|
||||
*size_str[BASE_SHARED + s][2]) {
|
||||
*_size_str[BASE_SHARED + s][2]) {
|
||||
base = BASE_SHARED;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Case-dependent match for powers of 1000 */
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (unit_type == *size_str[BASE_1000 + s][2]) {
|
||||
if (unit_type == *_size_str[BASE_1000 + s][2]) {
|
||||
base = BASE_1000;
|
||||
break;
|
||||
}
|
||||
@@ -534,7 +534,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
/* Case-dependent match for powers of 1024 */
|
||||
if (base == BASE_UNKNOWN)
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (unit_type == *size_str[BASE_1024 + s][2]) {
|
||||
if (unit_type == *_size_str[BASE_1024 + s][2]) {
|
||||
base = BASE_1024;
|
||||
break;
|
||||
}
|
||||
@@ -544,7 +544,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
/* Check for special units - s, b or u */
|
||||
for (s = 0; s < NUM_SPECIAL; s++)
|
||||
if (toupper((int) unit_type) ==
|
||||
*size_str[BASE_SPECIAL + s][2]) {
|
||||
*_size_str[BASE_SPECIAL + s][2]) {
|
||||
base = BASE_SPECIAL;
|
||||
break;
|
||||
}
|
||||
@@ -552,7 +552,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
if (size == UINT64_C(0)) {
|
||||
if (base == BASE_UNKNOWN)
|
||||
s = 0;
|
||||
snprintf(size_buf, SIZE_BUF, "0%s", include_suffix ? size_str[base + s][suffix_type] : "");
|
||||
snprintf(size_buf, SIZE_BUF, "0%s", include_suffix ? _size_str[base + s][suffix_type] : "");
|
||||
return size_buf;
|
||||
}
|
||||
|
||||
@@ -591,7 +591,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
if ((s < NUM_UNIT_PREFIXES) &&
|
||||
((unit_type == 'R') || (unit_type == 'r'))) {
|
||||
/* When the rounding would cause difference, add '<' prefix
|
||||
* i.e. 2043M is more then 1.9949G prints <2.00G
|
||||
* i.e. 2043M is more than 1.9949G prints <2.00G
|
||||
* This version is for 2 digits fixed precision */
|
||||
d = 100. * (double) size / byte;
|
||||
if (!_close_enough(floorl(d), nearbyintl(d)))
|
||||
@@ -602,7 +602,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
}
|
||||
|
||||
/* FIXME Make precision configurable */
|
||||
switch (toupper(*size_str[base + s][DM_SIZE_UNIT])) {
|
||||
switch (toupper(*_size_str[base + s][DM_SIZE_UNIT])) {
|
||||
case 'B':
|
||||
case 'S':
|
||||
precision = 0;
|
||||
@@ -612,7 +612,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
}
|
||||
|
||||
snprintf(size_buf, SIZE_BUF, "%s%.*f%s", prefix, precision,
|
||||
(double) size / byte, include_suffix ? size_str[base + s][suffix_type] : "");
|
||||
(double) size / byte, include_suffix ? _size_str[base + s][suffix_type] : "");
|
||||
|
||||
return size_buf;
|
||||
}
|
||||
|
@@ -120,7 +120,7 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
if (!(pp = _skip_fields(p, 1)))
|
||||
goto_bad;
|
||||
|
||||
/* Raid target can actually report more then real number of legs in a case
|
||||
/* Raid target can actually report more than real number of legs in a case
|
||||
* raid legs have been removed during initial raid array resynchronization */
|
||||
if (i > (pp - p - 1))
|
||||
i = pp - p - 1;
|
||||
@@ -335,11 +335,19 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
|
||||
|
||||
/* Read in policy args */
|
||||
pp = p;
|
||||
if (!(p = _skip_fields(p, 1)) ||
|
||||
!(s->policy_name = dm_pool_zalloc(mem, (p - pp))))
|
||||
goto bad;
|
||||
if (sscanf(pp, "%s %d", s->policy_name, &s->policy_argc) != 2)
|
||||
if (!(p = _skip_fields(p, 1)))
|
||||
goto_bad;
|
||||
|
||||
i = p - pp;
|
||||
if ((i < 1) ||
|
||||
!(s->policy_name = dm_pool_zalloc(mem, i)))
|
||||
goto_bad;
|
||||
|
||||
dm_strncpy(s->policy_name, pp, i);
|
||||
|
||||
if (sscanf(p, "%d", &s->policy_argc) != 1)
|
||||
goto bad;
|
||||
|
||||
if (s->policy_argc &&
|
||||
(!(s->policy_argv = dm_pool_zalloc(mem, sizeof(char *) * s->policy_argc)) ||
|
||||
!(p = _skip_fields(p, 1)) ||
|
||||
@@ -401,12 +409,12 @@ int dm_get_status_integrity(struct dm_pool *mem, const char *params,
|
||||
struct dm_status_integrity **status)
|
||||
{
|
||||
struct dm_status_integrity *s;
|
||||
char recalc_str[16] = "\0";
|
||||
char recalc_str[16] = { 0 };
|
||||
|
||||
if (!(s = dm_pool_zalloc(mem, sizeof(*s))))
|
||||
return_0;
|
||||
|
||||
if (sscanf(params, "%llu %llu %s",
|
||||
if (sscanf(params, "%llu %llu %15s",
|
||||
(unsigned long long *)&s->number_of_mismatches,
|
||||
(unsigned long long *)&s->provided_data_sectors,
|
||||
recalc_str) != 3) {
|
||||
@@ -571,7 +579,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
|
||||
pos += used;
|
||||
|
||||
if (num_devs > DM_MIRROR_MAX_IMAGES) {
|
||||
log_error(INTERNAL_ERROR "More then " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
|
||||
log_error(INTERNAL_ERROR "More than " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
|
||||
" reported in mirror status.");
|
||||
goto out;
|
||||
}
|
||||
|
@@ -13,6 +13,8 @@
|
||||
# include <linux/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define DM_DIR "mapper" /* Slashes not supported */
|
||||
#define DM_CONTROL_NODE "control"
|
||||
#define DM_MAX_TYPE_NAME 16
|
||||
@@ -209,7 +211,7 @@ struct dm_name_list {
|
||||
};
|
||||
|
||||
#define DM_NAME_LIST_FLAG_HAS_UUID 1
|
||||
#define DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID 2
|
||||
#define DM_NAME_LIST_FLAG_DOES_NOT_HAVE_UUID 2
|
||||
|
||||
/*
|
||||
* Used to retrieve the target versions
|
||||
|
@@ -62,7 +62,7 @@
|
||||
*
|
||||
* The UUID contained in the dm_ulog_request structure is the reference that
|
||||
* will be used by all request types to a specific log. The constructor must
|
||||
* record this assotiation with the instance created.
|
||||
* record this association with the instance created.
|
||||
*
|
||||
* When the request has been processed, user-space must return the
|
||||
* dm_ulog_request to the kernel - setting the 'error' field, filling the
|
||||
|
@@ -13,7 +13,8 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "dmlib.h"
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include <assert.h>
|
||||
|
||||
struct block {
|
||||
|
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#ifdef VALGRIND_POOL
|
||||
#include "memcheck.h"
|
||||
#include <memcheck.h>
|
||||
#endif
|
||||
|
||||
#include "base/memory/zalloc.h"
|
||||
|
@@ -129,7 +129,7 @@ int dm_pool_locked(struct dm_pool *p)
|
||||
* Bool specifies whether to store the pool crc/hash checksum.
|
||||
*
|
||||
* \return
|
||||
* 1 (success) when the pool was preperly locked, 0 otherwise.
|
||||
* 1 (success) when the pool was properly locked, 0 otherwise.
|
||||
*/
|
||||
int dm_pool_lock(struct dm_pool *p, int crc)
|
||||
{
|
||||
|
165
device_mapper/raid/raid_parser.c
Normal file
165
device_mapper/raid/raid_parser.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support counting number of failed device bits in dm-raid superblock bit arrays or clear them out.
|
||||
*/
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "device_mapper/all.h"
|
||||
#include "device_mapper/raid/target.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Copied/derived from kernel's drivers/md/dm-raid.c so this is prone to out-of-sync (factor out to header file?). */
|
||||
#define MAX_RAID_DEVICES 253 /* md-raid kernel limit? */
|
||||
#define UINT64_BITS (sizeof(uint64_t) * 8)
|
||||
#define DISKS_ARRAY_ELEMS ((MAX_RAID_DEVICES + (UINT64_BITS - 1)) / UINT64_BITS)
|
||||
#define DM_RAID_SB_MAGIC 0x446D5264 /* "DmRd" */
|
||||
#define FEATURE_FLAG_SUPPORTS_V190 0x1 /* Supports extended superblock */
|
||||
|
||||
/* RAID superblock at beginning of rmeta SubLVs trimmed down to mandatory members. */
|
||||
struct dm_raid_superblock {
|
||||
__le32 magic; /* "DmRd" */
|
||||
__le32 compat_features; /* Used to indicate compatible features (like 1.9.0 ondisk metadata extension) */
|
||||
__le32 dummy[4];
|
||||
__le64 failed_devices; /* Pre 1.9.0 part of bit field of devices to */
|
||||
/* indicate device failures (see extension below) */
|
||||
__le32 dummy1[7];
|
||||
|
||||
/********************************************************************
|
||||
* BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
|
||||
*
|
||||
* FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
|
||||
*/
|
||||
__le32 flags; /* Flags defining array states for reshaping */
|
||||
__le32 dummy2[14];
|
||||
__le64 extended_failed_devices[DISKS_ARRAY_ELEMS - 1];
|
||||
|
||||
__le32 dummy3;
|
||||
/* Always set rest up to logical block size to 0 when writing ... */
|
||||
} __packed;
|
||||
/* END: Copied from ... */
|
||||
|
||||
/* Superblock I/O buffer size to be able to Cope with 4K native devices... */
|
||||
#define SB_BUFSZ 4096
|
||||
|
||||
static size_t _get_sb_size(const struct dm_raid_superblock *sb)
|
||||
{
|
||||
return (FEATURE_FLAG_SUPPORTS_V190 & le32toh(sb->compat_features)) ?
|
||||
sizeof(*sb) : ((char *) &sb->flags - (char *) sb);
|
||||
}
|
||||
|
||||
static uint32_t _hweight64(__le64 v)
|
||||
{
|
||||
uint32_t r = 0;
|
||||
|
||||
while (v) {
|
||||
r += v & 1;
|
||||
v >>= 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint32_t _hweight_failed(struct dm_raid_superblock *sb)
|
||||
{
|
||||
uint32_t r = _hweight64(sb->failed_devices);
|
||||
|
||||
if (_get_sb_size(sb) == sizeof(*sb)) {
|
||||
int i = (int)DM_ARRAY_SIZE(sb->extended_failed_devices);
|
||||
|
||||
while (i--)
|
||||
r = max(r, _hweight64(sb->extended_failed_devices[i]));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void _clear_failed_devices(struct dm_raid_superblock *sb)
|
||||
{
|
||||
|
||||
sb->failed_devices = 0;
|
||||
|
||||
if (_get_sb_size(sb) == sizeof(*sb))
|
||||
memset(sb->extended_failed_devices, 0, sizeof(sb->extended_failed_devices));
|
||||
}
|
||||
|
||||
static int _count_or_clear_failed_devices(const char *dev_path, bool clear, uint32_t *nr_failed)
|
||||
{
|
||||
struct dm_raid_superblock *sb = NULL;
|
||||
size_t sz;
|
||||
int fd, r = 0;
|
||||
|
||||
if (posix_memalign((void *) &sb, SB_BUFSZ, SB_BUFSZ)) {
|
||||
log_sys_error("Failed to allocate RAID superblock buffer", dev_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open(dev_path, O_EXCL | ((clear) ? O_RDWR : O_RDONLY) | O_DIRECT);
|
||||
if (fd < 0) {
|
||||
log_sys_error("Failed to open RAID metadata volume", dev_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (read(fd, sb, SB_BUFSZ) != SB_BUFSZ) {
|
||||
log_sys_error("Failed to read RAID metadata volume", dev_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* FIXME: big endian??? */
|
||||
if (sb->magic != htobe32(DM_RAID_SB_MAGIC)) {
|
||||
log_error("No RAID signature on %s.", dev_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nr_failed)
|
||||
*nr_failed = _hweight_failed(sb);
|
||||
|
||||
if (clear) {
|
||||
if (lseek(fd, 0, SEEK_SET) < 0) {
|
||||
log_sys_error("Failed to seek RAID metadata volume", dev_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sz = _get_sb_size(sb);
|
||||
memset((void *)((char *) sb + sz), 0, SB_BUFSZ - sz);
|
||||
_clear_failed_devices(sb);
|
||||
if (write(fd, sb, SB_BUFSZ) != SB_BUFSZ) {
|
||||
log_sys_error("Failed to clear RAID metadata volume", dev_path);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
if ((fd >= 0) && close(fd))
|
||||
log_sys_debug("close", dev_path);
|
||||
|
||||
free(sb);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_raid_count_failed_devices(const char *dev_path, uint32_t *nr_failed)
|
||||
{
|
||||
return _count_or_clear_failed_devices(dev_path, false, nr_failed);
|
||||
}
|
||||
|
||||
int dm_raid_clear_failed_devices(const char *dev_path, uint32_t *nr_failed)
|
||||
{
|
||||
return _count_or_clear_failed_devices(dev_path, true, nr_failed);
|
||||
}
|
23
device_mapper/raid/target.h
Normal file
23
device_mapper/raid/target.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef DEVICE_MAPPER_RAID_TARGET_H
|
||||
#define DEVICE_MAPPER_RAID_TARGET_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int dm_raid_count_failed_devices(const char *dev_path, uint32_t *nr_failed);
|
||||
int dm_raid_clear_failed_devices(const char *dev_path, uint32_t *nr_failed);
|
||||
|
||||
#endif
|
@@ -356,7 +356,7 @@ struct dm_regex *dm_regex_create(struct dm_pool *mem, const char * const *patter
|
||||
|
||||
for (i = 0; i < num_patterns; i++) {
|
||||
ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS);
|
||||
if (i < (num_patterns - 1))
|
||||
if ((i + 1) < num_patterns)
|
||||
*ptr++ = '|';
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,6 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "parse_rx.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#ifndef _DM_PARSE_REGEX_H
|
||||
#define _DM_PARSE_REGEX_H
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
|
||||
enum {
|
||||
CAT,
|
||||
STAR,
|
||||
|
@@ -13,7 +13,6 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "ttree.h"
|
||||
|
||||
struct node {
|
||||
@@ -84,9 +83,7 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
|
||||
} while (*c && count);
|
||||
|
||||
if (!*c) {
|
||||
count++;
|
||||
|
||||
while (count--) {
|
||||
do {
|
||||
if (!(*c = _tree_node(tt->mem, k)))
|
||||
return_0;
|
||||
|
||||
@@ -94,7 +91,7 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
|
||||
k = *key++;
|
||||
c = &((*c)->m);
|
||||
}
|
||||
}
|
||||
} while (count--);
|
||||
}
|
||||
(*c)->data = data;
|
||||
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#ifndef _DM_TTREE_H
|
||||
#define _DM_TTREE_H
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
|
||||
struct ttree;
|
||||
|
||||
struct ttree *ttree_create(struct dm_pool *mem, unsigned int klen);
|
||||
|
@@ -28,11 +28,6 @@
|
||||
#include "target.h"
|
||||
|
||||
#include "lib/mm/xlate.h"
|
||||
//#include "linux/byteorder/big_endian.h"
|
||||
//#include "linux/byteorder/little_endian.h"
|
||||
//#define le32_to_cpu __le32_to_cpu
|
||||
//#define le64_to_cpu __le64_to_cpu
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -72,7 +67,7 @@ enum {
|
||||
struct vdo_header {
|
||||
uint32_t id; /* The component this is a header for */
|
||||
struct vdo_version_number version; /* The version of the data format */
|
||||
size_t size; /* The size of the data following this header */
|
||||
uint64_t size; /* The size of the data following this header */
|
||||
} __packed;
|
||||
|
||||
struct vdo_geometry_block {
|
||||
@@ -136,40 +131,40 @@ struct vdo_volume_geometry_4 {
|
||||
struct vdo_index_config index_config;
|
||||
} __packed;
|
||||
|
||||
/* Decoding mostly only some used stucture members */
|
||||
/* Decoding mostly only some used structure members */
|
||||
|
||||
static void _vdo_decode_version(struct vdo_version_number *v)
|
||||
{
|
||||
v->major_version = le32_to_cpu(v->major_version);
|
||||
v->minor_version = le32_to_cpu(v->minor_version);
|
||||
v->major_version = le32toh(v->major_version);
|
||||
v->minor_version = le32toh(v->minor_version);
|
||||
}
|
||||
|
||||
static void _vdo_decode_header(struct vdo_header *h)
|
||||
{
|
||||
h->id = le32_to_cpu(h->id);
|
||||
h->id = le32toh(h->id);
|
||||
_vdo_decode_version(&h->version);
|
||||
h->size = le64_to_cpu(h->size);
|
||||
h->size = le64toh(h->size);
|
||||
}
|
||||
|
||||
static void _vdo_decode_geometry_region(struct vdo_volume_region *vr)
|
||||
{
|
||||
vr->id = le32_to_cpu(vr->id);
|
||||
vr->start_block = le64_to_cpu(vr->start_block);
|
||||
vr->id = (enum vdo_volume_region_id) le32toh(vr->id);
|
||||
vr->start_block = le64toh(vr->start_block);
|
||||
}
|
||||
|
||||
static void _vdo_decode_volume_geometry(struct vdo_volume_geometry *vg)
|
||||
{
|
||||
vg->release_version = le32_to_cpu(vg->release_version);
|
||||
vg->nonce = le64_to_cpu(vg->nonce);
|
||||
vg->bio_offset = le64_to_cpu(vg->bio_offset);
|
||||
vg->release_version = le32toh(vg->release_version);
|
||||
vg->nonce = le64toh(vg->nonce);
|
||||
vg->bio_offset = le64toh(vg->bio_offset);
|
||||
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
|
||||
}
|
||||
|
||||
static void _vdo_decode_volume_geometry_4(struct vdo_volume_geometry *vg,
|
||||
struct vdo_volume_geometry_4 *vg_4)
|
||||
{
|
||||
vg->release_version = le32_to_cpu(vg_4->release_version);
|
||||
vg->nonce = le64_to_cpu(vg_4->nonce);
|
||||
vg->release_version = le32toh(vg_4->release_version);
|
||||
vg->nonce = le64toh(vg_4->nonce);
|
||||
vg->bio_offset = 0;
|
||||
vg->regions[VDO_DATA_REGION] = vg_4->regions[VDO_DATA_REGION];
|
||||
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
|
||||
@@ -177,17 +172,17 @@ static void _vdo_decode_volume_geometry_4(struct vdo_volume_geometry *vg,
|
||||
|
||||
static void _vdo_decode_config(struct vdo_config *vc)
|
||||
{
|
||||
vc->logical_blocks = le64_to_cpu(vc->logical_blocks);
|
||||
vc->physical_blocks = le64_to_cpu(vc->physical_blocks);
|
||||
vc->slab_size = le64_to_cpu(vc->slab_size);
|
||||
vc->recovery_journal_size = le64_to_cpu(vc->recovery_journal_size);
|
||||
vc->slab_journal_blocks = le64_to_cpu(vc->slab_journal_blocks);
|
||||
vc->logical_blocks = le64toh(vc->logical_blocks);
|
||||
vc->physical_blocks = le64toh(vc->physical_blocks);
|
||||
vc->slab_size = le64toh(vc->slab_size);
|
||||
vc->recovery_journal_size = le64toh(vc->recovery_journal_size);
|
||||
vc->slab_journal_blocks = le64toh(vc->slab_journal_blocks);
|
||||
}
|
||||
|
||||
static void _vdo_decode_pvc(struct vdo_component_41_0 *pvc)
|
||||
{
|
||||
_vdo_decode_config(&pvc->config);
|
||||
pvc->nonce = le64_to_cpu(pvc->nonce);
|
||||
pvc->nonce = le64toh(pvc->nonce);
|
||||
}
|
||||
|
||||
bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
@@ -226,7 +221,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
size = st.st_size;
|
||||
}
|
||||
|
||||
if (read(fh, buffer, sizeof(buffer)) < 0) {
|
||||
if (read(fh, buffer, sizeof(buffer)) < (int)(MAGIC_NUMBER_SIZE + sizeof(h))) {
|
||||
log_sys_debug("read", vdo_path);
|
||||
goto err;
|
||||
}
|
||||
@@ -270,7 +265,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (read(fh, buffer, sizeof(buffer)) < 0) {
|
||||
if (read(fh, buffer, sizeof(buffer)) < (int)(sizeof(struct vdo_geometry_block) + sizeof(vn))) {
|
||||
log_sys_debug("read", vdo_path);
|
||||
goto err;
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
|
||||
if ((vtp->minimum_io_size != (512 >> SECTOR_SHIFT)) &&
|
||||
(vtp->minimum_io_size != (4096 >> SECTOR_SHIFT))) {
|
||||
log_error("VDO minimum io size %u is unsupported [512, 4096].",
|
||||
vtp->minimum_io_size);
|
||||
(vtp->minimum_io_size << SECTOR_SHIFT));
|
||||
valid = false;
|
||||
}
|
||||
|
||||
|
@@ -35,7 +35,7 @@ To use LVM2 you need 3 things:
|
||||
|
||||
## Getting LVM
|
||||
|
||||
Most of linux ditribution offer packaged LVM tools.
|
||||
Most of linux distribution offer packaged LVM tools.
|
||||
Depending on your distribution use
|
||||
|
||||
# RPM based distributions (Fedora):
|
||||
@@ -49,7 +49,7 @@ List of official [mirror sites](https://sourceware.org/mirrors.html) (including
|
||||
|
||||
### LVM Releases
|
||||
|
||||
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
|
||||
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit="2" show="2" rootpage="release-notes"]]
|
||||
|
||||
[[More releases|release-notes/index]]
|
||||
|
||||
@@ -64,7 +64,7 @@ tool with low level access and one may seriously harm their data when used
|
||||
incorrectly!
|
||||
|
||||
|
||||
* Physical Volume (PV) is underlaying disk, local or remote, encrypted or even
|
||||
* Physical Volume (PV) is underlying disk, local or remote, encrypted or even
|
||||
a mdadm RAID volume. PV is divided into so called Physical Extents (PE) which
|
||||
are a basic allocation unit.
|
||||
List PVs using [pvs(8)](https://man7.org/linux/man-pages/man8/pvs.8.html) or
|
||||
@@ -72,7 +72,7 @@ incorrectly!
|
||||
|
||||
Make one by running `pvcreate /dev/sdX`.
|
||||
See [pvcreate(8)](https://man7.org/linux/man-pages/man8/pvcreate.8.html). This step is optional.
|
||||
* Volume Group (VG) consisting for one or more PVs is used as a pool from which LVs are allocated.
|
||||
* Volume Group (VG) consisting of one or more PVs is used as a pool from which LVs are allocated.
|
||||
List VGs using [vgs(8)](https://man7.org/linux/man-pages/man8/vgs.8.html) or
|
||||
[vgdisplay(8)](https://man7.org/linux/man-pages/man8/vgdisplay.8.html).
|
||||
|
||||
|
@@ -13,7 +13,7 @@ different targets were rolling their own data structures, for example:
|
||||
Maintaining these data structures takes a lot of work, so if possible
|
||||
we'd like to reduce the number.
|
||||
|
||||
The persistent-data library is an attempt to provide a re-usable
|
||||
The persistent-data library is an attempt to provide a reusable
|
||||
framework for people who want to store metadata in device-mapper
|
||||
targets. It's currently used by the thin-provisioning target and an
|
||||
upcoming hierarchical storage target.
|
||||
|
@@ -41,7 +41,7 @@ metadata.
|
||||
The zones of the device are separated into 2 types:
|
||||
|
||||
1) Metadata zones: these are conventional zones used to store metadata.
|
||||
Metadata zones are not reported as useable capacity to the user.
|
||||
Metadata zones are not reported as usable capacity to the user.
|
||||
|
||||
2) Data zones: all remaining zones, the vast majority of which will be
|
||||
sequential zones used exclusively to store user data. The conventional
|
||||
|
@@ -86,7 +86,7 @@ are as follows:
|
||||
the policies outlined in the LVM configuration file - usually,
|
||||
/etc/lvm/lvm.conf. Once this operation is complete, the logical volumes
|
||||
will be consistent. However, the volume group will still be inconsistent -
|
||||
due to the refernced-but-missing device/PV - and operations will still be
|
||||
due to the referenced-but-missing device/PV - and operations will still be
|
||||
restricted to the aforementioned actions until either the device is
|
||||
restored or 'vgreduce --removemissing' is run.
|
||||
|
||||
|
@@ -108,7 +108,7 @@ really an orphan and enable its usage for creating or extending VGs. In
|
||||
practice, the decision might be governed by a timeout or assumed immediately --
|
||||
the former case is a little safer, the latter is probably more transparent. I
|
||||
am not very keen on using timeouts and we can probably assume that the admin
|
||||
won't blindly try to re-use devices in a way that would trip up LVM in this
|
||||
won't blindly try to reuse devices in a way that would trip up LVM in this
|
||||
respect. I would be in favour of just assuming that metadata-less VGs with no
|
||||
known referencing VGs are orphans -- after all, this is the same approach as we
|
||||
use today. The metadata balancing support may stress this a bit more than the
|
||||
@@ -153,7 +153,7 @@ Protocol & co.
|
||||
|
||||
I expect a simple text-based protocol executed on top of an Unix Domain Socket
|
||||
to be the communication interface for lvmetad. Ideally, the requests and
|
||||
replies will be well-formed "config file" style strings, so we can re-use
|
||||
replies will be well-formed "config file" style strings, so we can reuse
|
||||
existing parsing infrastructure.
|
||||
|
||||
Since we already have two daemons, I would probably look into factoring some
|
||||
|
@@ -56,7 +56,7 @@ Device mapper
|
||||
-------------
|
||||
|
||||
As well as the low level dm-ioctl driving code we need to have all our dm 'best
|
||||
practise' stuff in here. For instance this is the code that decides to use the
|
||||
practice' stuff in here. For instance this is the code that decides to use the
|
||||
mirror target to move some data around; that knows to suspend a thin volume
|
||||
before taking a snapshot of it. This module is going to have a lot more code
|
||||
in it than the current libdevmapper.
|
||||
@@ -150,7 +150,7 @@ interface to get round.
|
||||
'lib' is where the bulk of our code currently is. Dependency-wise the code is
|
||||
a bit like a ball of string. So splitting it up is going to take time. We can
|
||||
probably pull code pretty quickly into the 'metadata model' dir. But factoring
|
||||
out the dm best practises stuff is going to require splitting at least
|
||||
out the dm best practices stuff is going to require splitting at least
|
||||
files, and probably functions. Certainly not something that can be done in one
|
||||
go. System should just be a question of cherry picking functions.
|
||||
|
||||
|
@@ -22,7 +22,7 @@ Features
|
||||
|
||||
* **IMPORTANT:** When `devices/scan_lvs` is enabled found LVs are no longer auto
|
||||
activated, must enable `LVM_PVSCAN_ON_LVS` in udev rules (*69-dm-lvm.rules*.)
|
||||
* NOTE: It is not recomended to use LVs for PVs. If you have an use case for
|
||||
* NOTE: It is not recommended to use LVs for PVs. If you have an use case for
|
||||
this talk to us, please.
|
||||
* Changes to devices file are now backed up in */etc/lvm/devices/backup/*.
|
||||
Controlled by `devices/devicesfile_backup_limit` configuration option.
|
||||
@@ -73,4 +73,4 @@ Also few more minor improvements:
|
||||
"""]]
|
||||
|
||||
[[!tag]]
|
||||
[[meta date="Thu May 16 12:12:06 2024 +0200"]]
|
||||
[[!meta date="Thu May 16 12:12:06 2024 +0200"]]
|
||||
|
19
doc/release-notes/2.03.25.mdwn
Normal file
19
doc/release-notes/2.03.25.mdwn
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.25 - Feature and Bug Fix Release"]]
|
||||
|
||||
Version 2.03.25
|
||||
===============
|
||||
|
||||
* Add `vgimportdevices --rootvg [--auto]` adding devices from root VG to devices file.
|
||||
* Add `lvm-devices-import.{path,service}` service using the above to initialize devices file.
|
||||
* Handle pruning ids from devices file when lvremove is called and a PV is on top of the LV.
|
||||
* Change device cache data structures and caching to speed up operations with many LVs.
|
||||
* Fix infinite loop in lvm shell completion causing out of memory issue (2.03.24).
|
||||
* Allow forced change of locktype from none.
|
||||
* Handle OPTIONS defined in /etc/sysconfig/lvmlockd.
|
||||
* And as usually some clean up, static analysis fixes, etc.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
[[!meta date="Fri Jul 12 12:49:07 2024 +0200"]]
|
||||
|
18
doc/release-notes/2.03.26.mdwn
Normal file
18
doc/release-notes/2.03.26.mdwn
Normal file
@@ -0,0 +1,18 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.26 - Feature and Bug Fix Release"]]
|
||||
|
||||
Version 2.03.26
|
||||
===============
|
||||
|
||||
* Add `--integritysettings` option to manipulate dm-integrity settings.
|
||||
* Add `--refresh` with `vgscan --mknodes`.
|
||||
* Improve documentation for `--refresh` option.
|
||||
* Use `log/report_command_log=1` config setting by default for JSON output format.
|
||||
* Fix `vgmknodes --refresh` to wait for udev before checking `/dev` content.
|
||||
* Fix internal error reported by pvmove on a VG with single PV.
|
||||
* Fix unreleased memory pools on RAID lvextend.
|
||||
* And as usually some clean up, static analysis fixes, etc.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
[[!meta date="Fri Aug 23 16:02:00 2024 +0200"]]
|
26
doc/release-notes/2.03.27.mdwn
Normal file
26
doc/release-notes/2.03.27.mdwn
Normal file
@@ -0,0 +1,26 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.27 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.27
|
||||
===============
|
||||
|
||||
* Deprecate vdo settings `vdo_write_policy` and `vdo_write_policy`.
|
||||
* Do not accept duplicate device names for pvcreate.
|
||||
* Fix swap device size detection using blkid for lvresize/lvreduce/lvextend.
|
||||
* Detect GPT partition table and pass partition filter if no partitions defined.
|
||||
* Add `global/sanlock_align_size` option to configure sanlock lease size.
|
||||
* Disable mem locking when `activation/reserved_stack` or `reserved_memory` is `0`.
|
||||
* Fix locking issues in lvmlockd leaving thin pool inactive but locked.
|
||||
* Corrected integrity parameter `interleave_sectors` for DM table line.
|
||||
* Ignore `-i|--stripes`, `-I|--stripesize` for lvextend on raid0 LV, like on raid10.
|
||||
* Fix lot of typos across lvm2 code base (codespell).
|
||||
* Cleanup udev sync semaphore if `dm_{udev_create,task_set}_cookie` fails.
|
||||
* Improve error messages on failed udev cookie create/inc/dec operation.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Wed Oct 2 14:19:23 2024 +0200"]]
|
||||
-->
|
||||
|
20
doc/release-notes/2.03.28.mdwn
Normal file
20
doc/release-notes/2.03.28.mdwn
Normal file
@@ -0,0 +1,20 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.28 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.28
|
||||
===============
|
||||
|
||||
Few bugfixes and a lot of speed improvements mainly for many LVs.
|
||||
|
||||
* Introduce setting config/validate_metadata = full | none.
|
||||
* Restore fs resize call for lvresize -r on the same size LV (2.03.17).
|
||||
* Correct off-by-one devicesfile backup counting.
|
||||
* Fall back to direct zeroing if BLKZEROOUT fails during new LV initialization.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Mon Nov 4 16:42:12 2024 +0100"]]
|
||||
-->
|
||||
|
23
doc/release-notes/2.03.29.mdwn
Normal file
23
doc/release-notes/2.03.29.mdwn
Normal file
@@ -0,0 +1,23 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.29 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.29
|
||||
===============
|
||||
|
||||
Mostly bugfix release, few interesting changes:
|
||||
|
||||
* **Fix renaming of raid sub LVs when converting a volume to raid (2.03.28)**.
|
||||
* **Fix segfault/VG write error for raid LV `lvextend -i|--stripes -I|--stripesize`**.
|
||||
* Add configure --enable/disable-sd-notify to control lvmlockd build with sd-notify.
|
||||
* Allow test mode when lvmlockd is built without dlm support.
|
||||
* Add a note about RAID + integrity synchronization to lvmraid(7) man page.
|
||||
* Add a function for running lvconvert --repair on RAID LVs to lvmdbusd.
|
||||
* Improve option section of man pages for listing commands ({pv,lv,vg}{s,display}).
|
||||
* And some cleanup mostly in test code.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Mon Dec 09 12:57:57 2024 +0100"]]
|
||||
-->
|
24
doc/release-notes/2.03.30.mdwn
Normal file
24
doc/release-notes/2.03.30.mdwn
Normal file
@@ -0,0 +1,24 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.30 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.30
|
||||
===============
|
||||
|
||||
Small bugfix release:
|
||||
|
||||
* **NEW** Create `/dev/disk/by-diskseq/<DISKSEQ>` symlink for public DM devices.
|
||||
* Lvresize reports origin vdo volume cannot be resized.
|
||||
* Support setting `reserved_memory|stack` using `--config` on cmdline.
|
||||
* Fix support for disabling memory locking (2.03.27).
|
||||
* Do not extend an LV if FS resize unsupported and `--fs resize` used.
|
||||
* Prevent leftover temporary device when converting in use volume to a pool.
|
||||
* lvconvert detects volume in use early when converting it to a pool.
|
||||
* Handle NVMe with quirk changed WWID not matching WWID in devices file.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Tue Jan 14 20:55:33 2025 +0100"]]
|
||||
-->
|
||||
|
33
doc/release-notes/2.03.31.mdwn
Normal file
33
doc/release-notes/2.03.31.mdwn
Normal file
@@ -0,0 +1,33 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.31 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.31
|
||||
===============
|
||||
|
||||
Bugfix release:
|
||||
|
||||
* Disallow shared activation of LV with CoW snapshot.
|
||||
* Ignore reported `optimal_io_size` not divisible by 4096.
|
||||
* Restore support for `LVM_SUPPRESS_FD_WARNINGS` (2.03.24).
|
||||
* Fix DM cache preserving logic (2.03.28).
|
||||
* Restore missing symbol `dm_tree_node_size_changed@Base` (1.02.175).
|
||||
* Restore missing symbol `dm_bitset_parse_list@@DM_1_02_138` (1.02.175).
|
||||
* Fix uncache and split cache restoring original state of volume.
|
||||
* Extend use of lockopt skip to more scenarios.
|
||||
* Reduce `mandoc -T lint` reported issues for man pages.
|
||||
* Enhance error path resolving in polling code.
|
||||
* Fix lvmlockd use in lvremove of CoW snapshot, VDO pool, and uncache.
|
||||
* Improve mirror split with opened temporary volumes.
|
||||
* Improve pvmove finish with opened temporary volumes.
|
||||
* Fix backup limit for devices file, handle over 10,000 files.
|
||||
* Fix busy-loop in config reading when read returned 0.
|
||||
* Improve use of lvmlockd for usecases involving thin volumes and pools.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Thu Feb 27 16:51:29 2025 +0100"]]
|
||||
-->
|
||||
|
||||
|
26
doc/release-notes/2.03.32.mdwn
Normal file
26
doc/release-notes/2.03.32.mdwn
Normal file
@@ -0,0 +1,26 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.32 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.32
|
||||
===============
|
||||
|
||||
Mostly bugfix release:
|
||||
|
||||
* Add support for using regex in selection criteria for string lists.
|
||||
* Accept thin pool data LV as cachable LV.
|
||||
* Accept `--autobackup` option in pvresize.
|
||||
* Allow using zram block devices (likely for testing).
|
||||
* Lvconvert vdopool conversion propperly validates acceptable LVs.
|
||||
* Fix lvresize when resizing COW snapshots already covering origin.
|
||||
* Fix lvmdbusd read of executed lvm commands output.
|
||||
* Fix construction of DM UUID for cachevol `_cdata` and `_cmeta` devices.
|
||||
* Ignore PV claims from old metadata when then PV belongs to a new VG.
|
||||
* Fix integrity metadata rounding.
|
||||
* Fix string list selection when using `[<item> || <item> ...]`.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Mon May 05 17:02:00 2025 +0200"]]
|
||||
-->
|
19
doc/release-notes/2.03.33.mdwn
Normal file
19
doc/release-notes/2.03.33.mdwn
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.33 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.33
|
||||
===============
|
||||
|
||||
Mostly bugfix release:
|
||||
|
||||
* Use `lvconvert --repair` to repair raid arrays with transiently lost devices.
|
||||
* Override `LC_NUMERIC` locale if unsuitable for `json_std` report format.
|
||||
* Fail `dm_report_group_create` if radix char from locale unsuitable for `json_std`.
|
||||
* Escape the escape character itself on JSON report format output.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Fri Jun 27 10:14:00 2025 +0200"]]
|
||||
-->
|
30
doc/release-notes/2.03.34.mdwn
Normal file
30
doc/release-notes/2.03.34.mdwn
Normal file
@@ -0,0 +1,30 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.34 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.34
|
||||
===============
|
||||
|
||||
Add *Persisten Reservations* and many mostly small fixes.
|
||||
|
||||
* **NEW** Add support for **persistent reservations** controlling access to shared PVs.
|
||||
* See [lvmpersist(8)](https://man7.org/linux/man-pages/man8/lvmpersist.8.html) for more details.
|
||||
* Add `lvmlockd --lockopt repair` to reinitialize corrupted sanlock leases.
|
||||
* Add *lvm.conf* `global/lvresize_fs_helper_executable`.
|
||||
* Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
|
||||
* Support dmeventd restart when there are no monitored devices.
|
||||
* Dmeventd no longer calls 'action commands' on removed devices.
|
||||
* Enhanced `lvresize -r` support for btrfs.
|
||||
* Fix reader of VDO metadata on 32bit architecture.
|
||||
* Fix `lvmdevices --deldev/--delpvid` to error out if devices file not writeable.
|
||||
* Use glibc standard functions htoX, Xtoh functions for endian conversion.
|
||||
* Fix structure copying within sanlock's `release_rename()`.
|
||||
* Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
|
||||
* Fix support for `lvcreate -T --setautoactivation`.
|
||||
* Fix many issues found by coverity static analysis, gcc warnings, typos, tests, and other clean ups.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Wed Jul 30 15:35:00 2025 +0200"]]
|
||||
-->
|
53
doc/release-notes/2.03.35.mdwn
Normal file
53
doc/release-notes/2.03.35.mdwn
Normal file
@@ -0,0 +1,53 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.35 - Feature and Bug Fix Release"]]
|
||||
|
||||
Version 2.03.35
|
||||
===============
|
||||
|
||||
* Optimize dmeventd when remonitoring active devices.
|
||||
* Allow report options for `(pv|vg|lv)display` only if used with `-C|--columns`.
|
||||
* And [[!toggle text="more"]]
|
||||
|
||||
[[!toggleable text="""
|
||||
Features
|
||||
-----------------------
|
||||
|
||||
### Optimize dmeventd when remonitoring active devices.
|
||||
|
||||
Add grace period (controlled by `-g SECONDS` option) to [dmeventd(8)](https://man7.org/linux/man-pages/man8/dmeventd.8.html) to reuse threads.
|
||||
|
||||
This change help to reduce overhead and unnecessary `lvextend` calls.
|
||||
|
||||
|
||||
<!--
|
||||
TODO: It would be nice if we could use a real session output, so we could test the examples
|
||||
- During tests, save some outputs
|
||||
-->
|
||||
|
||||
Changes in command line
|
||||
-----------------------
|
||||
|
||||
* Report options (`--select STRING`, `--configreport CONFIG_REPORT`, `--logonly`)
|
||||
are allowed only with `(pv|vg|lv)display -C|--columns`.
|
||||
These **no longer work** without `-C|--columns` and were removed as they were not working properly anyway.
|
||||
|
||||
Other Changes
|
||||
-------------
|
||||
|
||||
* Fix unlocking devices file only after all PVs are processed.
|
||||
* Avoid creating system.devices when deleting entries.
|
||||
* Fix existing issues with persistent reservations.
|
||||
* Fix possible report output format inconsistencies while processing PVs.
|
||||
* Allow report options for pv/vg/lvdisplay only if used with -C|--columns.
|
||||
* Fix vgsplit failing to split a VG with RAID+integrity or cache with cachevol.
|
||||
* Fix --lockopt handling in lvmlockd when --nolocking is used.
|
||||
* Optimize dmeventd when remonitoring active devices.
|
||||
|
||||
"""]]
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Tue Sep 09 14:19:37 2025 +0200"]]
|
||||
-->
|
@@ -4,5 +4,5 @@ This list is incomplete, only releases with a release-note are included.
|
||||
|
||||
For releases of stable branch 2.03 see [[index]].
|
||||
|
||||
[[!inline pages="release-notes/2.02.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
|
||||
[[!inline pages="release-notes/2.02.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" rootpage="release-notes"]]
|
||||
|
||||
|
@@ -25,7 +25,7 @@ TODO: It would be nice if we could use a real session output, so we could test t
|
||||
Changes in command line
|
||||
-----------------------
|
||||
|
||||
Describe important changes in command line tools, especially any chnages of behavior, which user must be aware of:
|
||||
Describe important changes in command line tools, especially any changes of behavior, which user must be aware of:
|
||||
|
||||
* New options
|
||||
* Removed options
|
||||
|
@@ -29,7 +29,7 @@ LVM2 that is running the LV's on my development box.
|
||||
variable LVM_SYSTEM_DIR to point to your config directory
|
||||
(/etc/lvm_loops in my case).
|
||||
|
||||
5) It's a good idea to do a vgscan to initialise the filters:
|
||||
5) It's a good idea to do a vgscan to initialize the filters:
|
||||
|
||||
export LVM_SYSTEM_DIR=/etc/lvm_loops
|
||||
./lvm vgscan
|
||||
|
@@ -579,7 +579,7 @@
|
||||
/* Define to 1 to include code that uses lvmlockd IDM option. */
|
||||
#undef LOCKDIDM_SUPPORT
|
||||
|
||||
/* Define to 1 to include code that uses lvmlockd sanlock option. */
|
||||
/* Define version of sanlock. */
|
||||
#undef LOCKDSANLOCK_SUPPORT
|
||||
|
||||
/* Define to 1 if 'lstat' dereferences a symlink specified with a trailing
|
||||
@@ -598,6 +598,9 @@
|
||||
/* Define to 1 to include code that uses lvmlockd. */
|
||||
#undef LVMLOCKD_SUPPORT
|
||||
|
||||
/* Path to lvmpersist script. */
|
||||
#undef LVMPERSIST_PATH
|
||||
|
||||
/* Path to lvmpolld pidfile. */
|
||||
#undef LVMPOLLD_PIDFILE
|
||||
|
||||
@@ -633,6 +636,9 @@
|
||||
/* Define to 1 to include code that uses dbus notification. */
|
||||
#undef NOTIFYDBUS_SUPPORT
|
||||
|
||||
/* Use libnvme for WWID. */
|
||||
#undef NVME_SUPPORT
|
||||
|
||||
/* Define to 1 to enable O_DIRECT support. */
|
||||
#undef O_DIRECT_SUPPORT
|
||||
|
||||
@@ -660,6 +666,9 @@
|
||||
/* Define to 1 to include the LVM readline shell. */
|
||||
#undef READLINE_SUPPORT
|
||||
|
||||
/* Define to 1 to include code that uses sd_notify. */
|
||||
#undef SD_NOTIFY_SUPPORT
|
||||
|
||||
/* Define to 1 to include built-in support for snapshots. */
|
||||
#undef SNAPSHOT_INTERNAL
|
||||
|
||||
|
@@ -43,6 +43,8 @@ SOURCES =\
|
||||
device/filesystem.c \
|
||||
device/online.c \
|
||||
device/parse_vpd.c \
|
||||
device/persist.c \
|
||||
device/nvme.c \
|
||||
device/dev_util.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
@@ -142,7 +144,7 @@ LIB_STATIC = $(LIB_NAME).a
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
PROGS_CFLAGS = $(BLKID_CFLAGS) $(UDEV_CFLAGS)
|
||||
PROGS_CFLAGS = $(BLKID_CFLAGS) $(LIBNVME_CFLAGS) $(UDEV_CFLAGS)
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user